reel-deal 0.1.0-dev.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/defaults.ts","../src/utils/math.ts","../src/normalize.ts","../src/utils/dom.ts","../src/ReelDeal.ts"],"sourcesContent":["import type {\n ReelDealIdleBob,\n ReelDealSpinBlur,\n ReelDealSpinConfig,\n ReelDealWebGLShading,\n} from './types';\n\nexport const defaultSpinConfig: ReelDealSpinConfig = {\n minSpins: 2,\n durationMs: 4000,\n speedPxS: 4000,\n staggerMs: 300,\n};\n\nexport const defaultWebGLShading: ReelDealWebGLShading = {\n warpAngleDeg: 90,\n edgePower: 0.5,\n};\n\nexport const defaultSpinBlur: ReelDealSpinBlur = {\n maxPx: 4,\n speedAtMax: 2200,\n};\n\nexport const defaultIdleBob: ReelDealIdleBob = {\n amplitudePx: 8,\n speedHz: 0.25,\n phaseOffsetRad: 0.9,\n delayMs: 500,\n rampMs: 800,\n};\n","const SPIN_ACCEL_END = 0.1;\nconst SPIN_DECEL_START = 0.6;\n\nexport const clampInt = (value: number, min: number, max: number): number =>\n Math.max(min, Math.min(max, Math.floor(value)));\n\nexport const mod = (n: number, m: number): number => ((n % m) + m) % m;\n\nexport const clamp01 = (t: number): number => Math.max(0, Math.min(1, t));\n\nexport const rampHermite = (u: number): number => {\n const x = clamp01(u);\n\n return x ** 2 * (2 - x);\n};\n\nexport const brakeHermite = (u: number): number => {\n const x = clamp01(u);\n\n return x + x ** 2 - x ** 3;\n};\n\nexport const reelProgress = (t: number): number => {\n const tt = clamp01(t);\n\n if (tt <= SPIN_ACCEL_END) {\n const u = tt / SPIN_ACCEL_END;\n\n return rampHermite(u) * SPIN_ACCEL_END;\n }\n\n if (tt < SPIN_DECEL_START) {\n return tt;\n }\n\n const u = (tt - SPIN_DECEL_START) / (1 - SPIN_DECEL_START);\n\n return SPIN_DECEL_START + brakeHermite(u) * (1 - SPIN_DECEL_START);\n};\n\nexport const finiteOr = (value: number | undefined, fallback: number): number =>\n typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n\nexport const nonNegative = (value: number | undefined, fallback: number): number =>\n Math.max(0, finiteOr(value, fallback));\n\nexport const nonNegativeInt = (value: number | undefined, fallback: number): number =>\n Math.max(0, Math.floor(finiteOr(value, fallback)));\n","import {\n defaultIdleBob,\n defaultSpinBlur,\n defaultSpinConfig,\n defaultWebGLShading,\n} from './defaults';\nimport type {\n ReelDealIdleBob,\n ReelDealSpinBlur,\n ReelDealSpinConfig,\n ReelDealWebGLShading,\n} from './types';\nimport { finiteOr, nonNegative, nonNegativeInt } from './utils/math';\n\nconst DEFAULT_MAX_DPR = 2;\n\nexport type NormalizedSpinConfig = Required<ReelDealSpinConfig>;\n\nexport const normalizeSpinConfig = (\n overrides?: Partial<ReelDealSpinConfig>,\n): NormalizedSpinConfig => {\n const base = { ...defaultSpinConfig, ...(overrides ?? {}) };\n\n return {\n minSpins: nonNegativeInt(base.minSpins, defaultSpinConfig.minSpins),\n durationMs: nonNegativeInt(base.durationMs, defaultSpinConfig.durationMs ?? 0),\n speedPxS: nonNegativeInt(base.speedPxS, defaultSpinConfig.speedPxS ?? 0),\n staggerMs: nonNegativeInt(base.staggerMs, defaultSpinConfig.staggerMs ?? 0),\n };\n};\n\nexport const normalizeSpinBlur = (overrides?: Partial<ReelDealSpinBlur>): ReelDealSpinBlur => {\n const base = { ...defaultSpinBlur, ...(overrides ?? {}) };\n\n return {\n maxPx: nonNegative(base.maxPx, defaultSpinBlur.maxPx),\n speedAtMax: nonNegative(base.speedAtMax, defaultSpinBlur.speedAtMax),\n };\n};\n\nexport const normalizeWebGLShading = (\n overrides?: Partial<ReelDealWebGLShading>,\n): ReelDealWebGLShading => {\n const base = { ...defaultWebGLShading, ...(overrides ?? {}) };\n\n return {\n warpAngleDeg: nonNegative(base.warpAngleDeg, defaultWebGLShading.warpAngleDeg),\n edgePower: nonNegative(base.edgePower, defaultWebGLShading.edgePower),\n };\n};\n\nexport const normalizeIdleBob = (\n overrides?: Partial<ReelDealIdleBob> | false,\n): ReelDealIdleBob | null => {\n if (overrides === false) return null;\n\n const base = { ...defaultIdleBob, ...(overrides ?? {}) };\n\n return {\n amplitudePx: nonNegative(base.amplitudePx, defaultIdleBob.amplitudePx),\n speedHz: nonNegative(base.speedHz, defaultIdleBob.speedHz),\n phaseOffsetRad: finiteOr(base.phaseOffsetRad, defaultIdleBob.phaseOffsetRad),\n delayMs: nonNegativeInt(base.delayMs, defaultIdleBob.delayMs),\n rampMs: nonNegativeInt(base.rampMs, defaultIdleBob.rampMs),\n };\n};\n\nexport const normalizeMaxDpr = (value?: number): number =>\n Math.max(1, finiteOr(value, DEFAULT_MAX_DPR));\n","export const resolveElementById = <T extends HTMLElement>(id: string, kind: string): T => {\n const el = document.getElementById(id);\n\n if (!el) {\n throw new Error(`${kind} not found: ${id}`);\n }\n\n return el as T;\n};\n\nexport const resolveElement = <T extends HTMLElement>(elOrId: T | string, kind: string): T => {\n if (typeof elOrId === 'string') return resolveElementById<T>(elOrId, kind);\n\n return elOrId;\n};\n","import {\n type NormalizedSpinConfig,\n normalizeIdleBob,\n normalizeMaxDpr,\n normalizeSpinBlur,\n normalizeSpinConfig,\n normalizeWebGLShading,\n} from './normalize';\nimport type {\n ReelDealIdleBob,\n ReelDealOptions,\n ReelDealSpinBlur,\n ReelDealSpinConfig,\n ReelDealSpinState,\n ReelDealWebGLShading,\n} from './types';\nimport { resolveElement } from './utils/dom';\nimport { clamp01, clampInt, mod, rampHermite, reelProgress } from './utils/math';\n\nconst MAX_REELS = 5;\nconst SPIN_TICK_START = 0.72;\nconst SPIN_TICK_RANGE = 0.28;\nconst SPIN_TICK_MAX_PX = 7;\nconst VELOCITY_DECAY = 0.85;\nconst VELOCITY_GAIN = 1 - VELOCITY_DECAY;\n\ntype SpinAnimation = {\n startTime: number;\n startOffsets: number[];\n deltas: number[];\n durationMs: number[];\n};\n\nexport class ReelDeal {\n private readonly canvas: HTMLCanvasElement;\n private readonly container: HTMLElement;\n\n private readonly opts: ReelDealOptions;\n private readonly visibleSlots = 3;\n private readonly heightScale = 2 / 3;\n private readonly centerIndex = 1;\n private readonly reels: number;\n private readonly spinConfig: NormalizedSpinConfig;\n private readonly spinBlur: ReelDealSpinBlur;\n private readonly webglShading: ReelDealWebGLShading;\n private readonly idleBob: ReelDealIdleBob | null;\n private readonly maxDpr: number;\n\n private spriteImg: HTMLImageElement | null = null;\n private spriteWidth = 0;\n private spriteHeight = 0;\n private frameHeight = 0;\n\n private width = 0;\n private height = 0;\n private dpr = 1;\n\n private offsets: number[];\n private velocities: number[];\n private lastVelT: number | null = null;\n private lastVelOffsets: number[];\n private idleStartTime: number | null = null;\n private idleBaseOffsets: number[];\n\n private gl: WebGLRenderingContext | WebGL2RenderingContext | null = null;\n private glProgram: WebGLProgram | null = null;\n private glBuffer: WebGLBuffer | null = null;\n private glTexture: WebGLTexture | null = null;\n private glAttribs: { pos: number; uv: number } | null = null;\n private webglInitError: string | null = null;\n private glUniforms: {\n texture: WebGLUniformLocation | null;\n reelX: WebGLUniformLocation | null;\n reelW: WebGLUniformLocation | null;\n offsetPx: WebGLUniformLocation | null;\n frameHeight: WebGLUniformLocation | null;\n spriteHeight: WebGLUniformLocation | null;\n visibleSlots: WebGLUniformLocation | null;\n heightScale: WebGLUniformLocation | null;\n edgePower: WebGLUniformLocation | null;\n warpAngle: WebGLUniformLocation | null;\n blurPx: WebGLUniformLocation | null;\n } | null = null;\n\n private anim: SpinAnimation | null = null;\n private rafId: number | null = null;\n private pendingSpinResolvers: Array<() => void> = [];\n\n private resizeObserver: ResizeObserver | null = null;\n private resizeQueued = false;\n\n private button: HTMLButtonElement | null = null;\n private buttonHandlerAttached = false;\n private spinning = false;\n private queuedSpins: ReelDealSpinState[] | null = null;\n\n constructor(options: ReelDealOptions) {\n this.opts = options;\n this.reels = clampInt(options.reels ?? 1, 1, MAX_REELS);\n this.spinConfig = normalizeSpinConfig(options.spinConfig);\n this.spinBlur = normalizeSpinBlur(options.spinBlur);\n this.webglShading = normalizeWebGLShading(options.webglShading);\n this.idleBob = normalizeIdleBob(options.idleBob);\n this.maxDpr = normalizeMaxDpr(options.maxDpr);\n\n this.canvas = resolveElement<HTMLCanvasElement>(options.canvas, 'Canvas');\n this.container = resolveElement<HTMLElement>(options.container, 'Container');\n\n this.offsets = new Array(this.reels).fill(0);\n this.velocities = new Array(this.reels).fill(0);\n this.lastVelOffsets = new Array(this.reels).fill(0);\n this.idleBaseOffsets = new Array(this.reels).fill(0);\n }\n\n async init(): Promise<void> {\n await this.loadSprite();\n\n this.tryInitWebGL();\n\n if (!this.gl) {\n throw new Error(\n `WebGL is not supported or failed to initialize. ${this.webglInitError ?? ''}`.trim(),\n );\n }\n\n this.syncContainerLayoutVars();\n this.ensureCanvasCoversContainer();\n this.setupResizeWatcher();\n this.resizeToContainer();\n\n this.setSegments(this.opts.initialSegments);\n\n this.button = this.resolveButton();\n this.queuedSpins = this.resolveSpinQueue();\n this.attachButtonHandler();\n\n this.render();\n this.startLoop();\n }\n\n destroy(): void {\n this.stop();\n\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n if (this.button && this.buttonHandlerAttached) {\n this.button.removeEventListener('click', this.handleButtonClick);\n this.buttonHandlerAttached = false;\n }\n\n this.releaseWebGLResources();\n }\n\n private ensureCanvasCoversContainer(): void {\n if (this.canvas === this.container) return;\n if (!this.container.contains(this.canvas)) return;\n\n if (!this.canvas.style.width) this.canvas.style.width = '100%';\n if (!this.canvas.style.height) this.canvas.style.height = '100%';\n if (!this.canvas.style.display) this.canvas.style.display = 'block';\n }\n\n private syncContainerLayoutVars(): void {\n const target = this.canvas === this.container ? this.canvas : this.container;\n\n target.style.setProperty('--reels', String(this.reels));\n target.style.setProperty('--visible-slots', String(this.visibleSlots));\n target.style.aspectRatio = `${this.reels} / ${this.visibleSlots * this.heightScale}`;\n\n if (this.canvas !== this.container) {\n this.container.style.overflow = 'hidden';\n }\n }\n\n setSegments(initialSegments?: number[]): void {\n this.ensureReady();\n\n const segments = initialSegments ?? [];\n\n for (let r = 0; r < this.reels; r += 1) {\n const segIndex = segments[r] ?? 0;\n const idx = clampInt(segIndex, 0, this.opts.slotCount - 1);\n\n this.offsets[r] = idx * this.frameHeight - this.centerIndex * this.frameHeight;\n this.lastVelOffsets[r] = this.offsets[r];\n this.velocities[r] = 0;\n this.idleBaseOffsets[r] = this.offsets[r];\n }\n\n this.lastVelT = null;\n this.idleStartTime = null;\n this.anim = null;\n\n this.stop();\n this.render();\n this.startLoop();\n }\n\n setSegment(segmentIndex: number): void {\n this.setSegments(new Array(this.reels).fill(segmentIndex));\n }\n\n spinOnce(stopAtSegments: number[], config?: Partial<ReelDealSpinConfig>): Promise<void> {\n this.ensureReady();\n\n const { minSpins, staggerMs, speedPxS, durationMs } = this.getSpinConfig(config);\n const useSpeed = speedPxS > 0;\n\n const startOffsets = new Array(this.reels);\n const deltas = new Array(this.reels);\n const durations = new Array(this.reels);\n\n for (let r = 0; r < this.reels; r += 1) {\n const idx = clampInt(stopAtSegments[r] ?? 0, 0, this.opts.slotCount - 1);\n const desiredTop = idx * this.frameHeight - this.centerIndex * this.frameHeight;\n const desired = mod(desiredTop, this.spriteHeight);\n const current = mod(this.offsets[r], this.spriteHeight);\n\n const alignDelta = mod(current - desired, this.spriteHeight);\n\n let delta = -(minSpins * this.spriteHeight + alignDelta);\n\n if (useSpeed && durationMs > 0) {\n const desiredDistance = (speedPxS * durationMs) / 1000;\n const loops = Math.max(\n minSpins,\n Math.ceil(Math.max(0, desiredDistance - alignDelta) / this.spriteHeight),\n );\n\n delta = -(alignDelta + loops * this.spriteHeight);\n }\n\n if (staggerMs > 0 && useSpeed) {\n const extraDelta = (speedPxS * staggerMs * r) / 1000;\n const extraLoops = Math.ceil(extraDelta / this.spriteHeight);\n\n delta -= extraLoops * this.spriteHeight;\n }\n\n startOffsets[r] = this.offsets[r];\n deltas[r] = delta;\n\n if (useSpeed) {\n durations[r] = Math.max(0, Math.round((Math.abs(delta) / speedPxS) * 1000));\n } else {\n durations[r] = Math.max(0, durationMs + staggerMs * r);\n }\n }\n\n const totalDelta = deltas.reduce((acc, v) => acc + Math.abs(v), 0);\n\n if (totalDelta === 0 || durations.every((entry) => entry <= 0)) {\n for (let r = 0; r < this.reels; r += 1) {\n this.offsets[r] = this.offsets[r] + deltas[r];\n }\n\n this.anim = null;\n this.resolvePendingSpins();\n this.render();\n\n return Promise.resolve();\n }\n\n const startTime = performance.now();\n\n this.anim = { startTime, startOffsets, deltas, durationMs: durations };\n this.idleStartTime = null;\n this.startLoop();\n\n return new Promise((resolve) => {\n this.pendingSpinResolvers.push(resolve);\n });\n }\n\n private getSpinConfig(overrides?: Partial<ReelDealSpinConfig>): NormalizedSpinConfig {\n if (!overrides) return this.spinConfig;\n\n return normalizeSpinConfig({ ...this.spinConfig, ...overrides });\n }\n\n async spinQueue(spins: ReelDealSpinState[]): Promise<void> {\n for (let i = 0; i < spins.length; i += 1) {\n const spin = spins[i];\n\n await this.spinOnce(spin.stopAtSegments);\n\n spin.callback?.(i, spin.stopAtSegments);\n }\n }\n\n stop(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n\n this.rafId = null;\n this.anim = null;\n this.resolvePendingSpins();\n this.lastVelT = null;\n\n for (let r = 0; r < this.reels; r += 1) {\n this.velocities[r] = 0;\n }\n }\n\n private resolvePendingSpins(): void {\n if (this.pendingSpinResolvers.length === 0) return;\n\n const resolvers = this.pendingSpinResolvers;\n\n this.pendingSpinResolvers = [];\n\n for (const resolve of resolvers) {\n resolve();\n }\n }\n\n requestResize(): void {\n this.queueResize();\n }\n\n private ensureReady(): void {\n if (\n !this.spriteImg ||\n this.spriteWidth <= 0 ||\n this.spriteHeight <= 0 ||\n this.frameHeight <= 0\n ) {\n throw new Error('Sprite is not ready. Call init() and await it first.');\n }\n }\n\n private attachButtonHandler(): void {\n if (!this.button || this.buttonHandlerAttached) return;\n\n this.button.addEventListener('click', this.handleButtonClick, { passive: true });\n this.buttonHandlerAttached = true;\n }\n\n private handleButtonClick = async (): Promise<void> => {\n if (this.spinning) return;\n\n const spin = this.consumeNextSpin() ?? {\n stopAtSegments: this.buildRandomSegments(),\n };\n\n this.spinning = true;\n this.setButtonDisabled(true);\n\n try {\n await this.spinOnce(spin.stopAtSegments);\n } finally {\n if (this.queuedSpins && this.queuedSpins.length === 0) {\n this.setButtonDisabled(true);\n } else {\n this.setButtonDisabled(false);\n }\n\n this.spinning = false;\n }\n };\n\n private resolveButton(): HTMLButtonElement | null {\n if (!this.opts.button) return null;\n\n return resolveElement<HTMLButtonElement>(this.opts.button, 'Button');\n }\n\n private resolveSpinQueue(): ReelDealSpinState[] | null {\n return this.opts.queuedSpinStates ?? null;\n }\n\n private consumeNextSpin(): ReelDealSpinState | null {\n if (!this.queuedSpins) {\n this.queuedSpins = this.resolveSpinQueue();\n }\n\n if (!this.queuedSpins || this.queuedSpins.length === 0) return null;\n\n return this.queuedSpins.shift() ?? null;\n }\n\n private buildRandomSegments(): number[] {\n const max = Math.max(1, Math.floor(this.opts.slotCount));\n const segments: number[] = [];\n\n for (let r = 0; r < this.reels; r += 1) {\n segments.push(Math.floor(Math.random() * max));\n }\n\n return segments;\n }\n\n private setButtonDisabled(disabled: boolean): void {\n if (!this.button) return;\n\n this.button.disabled = disabled;\n\n if (disabled) this.button.setAttribute('aria-busy', 'true');\n else this.button.removeAttribute('aria-busy');\n }\n\n private shouldAnimate(): boolean {\n return this.anim !== null || this.idleBob !== null;\n }\n\n private startLoop(): void {\n if (this.rafId !== null) return;\n if (!this.shouldAnimate()) return;\n\n this.rafId = requestAnimationFrame(this.loop);\n }\n\n private loop = (now: number): void => {\n if (this.anim) {\n const { startTime, durationMs, startOffsets, deltas } = this.anim;\n\n let allDone = true;\n\n for (let r = 0; r < this.reels; r += 1) {\n const duration = durationMs[r] ?? 0;\n const t = duration <= 0 ? 1 : Math.min(1, (now - startTime) / duration);\n const eased = reelProgress(t);\n\n if (t < 1) allDone = false;\n\n const baseOffset = startOffsets[r] + deltas[r] * eased;\n\n let tick = 0;\n\n if (t > SPIN_TICK_START && this.frameHeight > 0) {\n const u = clamp01((t - SPIN_TICK_START) / SPIN_TICK_RANGE);\n const env = (1 - u) ** 2;\n const phase = (baseOffset / this.frameHeight) * Math.PI * 2;\n const amp = Math.min(SPIN_TICK_MAX_PX, this.frameHeight * 0.06);\n\n tick = Math.sin(phase) * env * amp;\n }\n\n this.offsets[r] = baseOffset + tick;\n }\n\n this.updateVelocity(now);\n this.render();\n\n if (allDone) {\n for (let r = 0; r < this.reels; r += 1) {\n this.offsets[r] = this.anim.startOffsets[r] + this.anim.deltas[r];\n this.idleBaseOffsets[r] = this.offsets[r];\n }\n\n this.updateVelocity(now);\n\n for (let r = 0; r < this.reels; r += 1) {\n this.velocities[r] = 0;\n }\n\n this.anim = null;\n this.idleStartTime = null;\n\n this.render();\n this.resolvePendingSpins();\n }\n } else if (this.idleBob) {\n this.updateIdle(now);\n this.render();\n }\n\n if (!this.shouldAnimate()) {\n this.rafId = null;\n\n return;\n }\n\n if (this.rafId === null) return;\n\n this.rafId = requestAnimationFrame(this.loop);\n };\n\n private render(): void {\n if (!this.spriteImg) return;\n if (this.width <= 0 || this.height <= 0) return;\n if (!this.gl) return;\n\n this.renderWebGL();\n }\n\n private getSpinBlurPxForReel(reel: number): number {\n if (!this.anim) return 0;\n\n const speed = Math.abs(this.velocities[reel] ?? 0);\n const speedAtMax = Math.max(1, this.spinBlur.speedAtMax);\n const t = clamp01(speed / speedAtMax);\n\n return t * Math.max(0, this.spinBlur.maxPx);\n }\n\n private renderWebGL(): void {\n if (\n !this.gl ||\n !this.glProgram ||\n !this.glAttribs ||\n !this.glUniforms ||\n !this.glTexture ||\n !this.glBuffer\n ) {\n return;\n }\n\n if (!this.spriteImg) return;\n\n const gl = this.gl;\n\n gl.useProgram(this.glProgram);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);\n\n gl.enableVertexAttribArray(this.glAttribs.pos);\n gl.vertexAttribPointer(this.glAttribs.pos, 2, gl.FLOAT, false, 16, 0);\n gl.enableVertexAttribArray(this.glAttribs.uv);\n gl.vertexAttribPointer(this.glAttribs.uv, 2, gl.FLOAT, false, 16, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.glTexture);\n gl.uniform1i(this.glUniforms.texture, 0);\n\n gl.uniform1f(this.glUniforms.frameHeight, this.frameHeight);\n gl.uniform1f(this.glUniforms.spriteHeight, this.spriteHeight);\n gl.uniform1f(this.glUniforms.visibleSlots, this.visibleSlots);\n gl.uniform1f(this.glUniforms.heightScale, this.heightScale);\n gl.uniform1f(this.glUniforms.edgePower, Math.max(0.5, this.webglShading.edgePower));\n\n const shading = this.webglShading;\n const warpAngle = (Math.max(0, shading.warpAngleDeg) * Math.PI) / 180;\n\n gl.uniform1f(this.glUniforms.warpAngle, warpAngle);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n const reelW = 1 / this.reels;\n\n for (let r = 0; r < this.reels; r += 1) {\n gl.uniform1f(this.glUniforms.reelX, r * reelW);\n gl.uniform1f(this.glUniforms.reelW, reelW);\n\n const offsetPx = mod(this.offsets[r], this.spriteHeight);\n\n gl.uniform1f(this.glUniforms.offsetPx, offsetPx);\n gl.uniform1f(this.glUniforms.blurPx, this.getSpinBlurPxForReel(r));\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n }\n\n private updateVelocity(now: number): void {\n if (this.lastVelT === null) {\n this.lastVelT = now;\n\n for (let r = 0; r < this.reels; r += 1) {\n this.lastVelOffsets[r] = this.offsets[r];\n this.velocities[r] = 0;\n }\n\n return;\n }\n\n const dt = (now - this.lastVelT) / 1000;\n\n if (dt <= 0) return;\n\n for (let r = 0; r < this.reels; r += 1) {\n const v = (this.offsets[r] - this.lastVelOffsets[r]) / dt;\n\n this.velocities[r] = this.velocities[r] * VELOCITY_DECAY + v * VELOCITY_GAIN;\n this.lastVelOffsets[r] = this.offsets[r];\n }\n\n this.lastVelT = now;\n }\n\n private updateIdle(now: number): void {\n if (!this.idleBob) return;\n if (this.idleStartTime === null) this.idleStartTime = now;\n\n const { amplitudePx, speedHz, phaseOffsetRad, delayMs, rampMs } = this.idleBob;\n const elapsedMs = now - this.idleStartTime;\n\n if (elapsedMs < Math.max(0, delayMs)) {\n for (let r = 0; r < this.reels; r += 1) {\n this.offsets[r] = this.idleBaseOffsets[r];\n this.velocities[r] = 0;\n }\n\n return;\n }\n\n const tSec = (elapsedMs - Math.max(0, delayMs)) / 1000;\n const rampT = Math.max(\n 0,\n Math.min(1, (elapsedMs - Math.max(0, delayMs)) / Math.max(1, rampMs)),\n );\n const ramp = rampHermite(rampT);\n const omega = speedHz * Math.PI * 2;\n\n for (let r = 0; r < this.reels; r += 1) {\n const phase = tSec * omega + r * phaseOffsetRad;\n\n this.offsets[r] = this.idleBaseOffsets[r] + Math.sin(phase) * (amplitudePx * ramp);\n this.velocities[r] = 0;\n }\n }\n\n private async loadSprite(): Promise<void> {\n const { sprite } = this.opts;\n const img = typeof sprite === 'string' ? new Image() : sprite;\n\n if (typeof sprite === 'string') {\n img.src = sprite;\n }\n\n if (!img.complete || img.naturalWidth <= 0) {\n await new Promise<void>((resolve, reject) => {\n const onLoad = () => resolve();\n const onError = () => reject(new Error('Failed to load sprite image'));\n\n img.addEventListener('load', onLoad, { once: true });\n img.addEventListener('error', onError, { once: true });\n });\n }\n\n const slotCount = Math.max(1, Math.floor(this.opts.slotCount));\n const spriteWidth = img.naturalWidth;\n const frameHeight = spriteWidth;\n const expectedSpriteHeight = frameHeight * slotCount;\n\n const naturalHeight = img.naturalHeight;\n const diff = Math.abs(naturalHeight - expectedSpriteHeight);\n\n if (diff > 2) {\n throw new Error(\n `Sprite size mismatch. Expected height ~${Math.round(expectedSpriteHeight)}px (slotCount=${slotCount}, slot aspect 1/1), got ${naturalHeight}px.`,\n );\n }\n\n this.spriteImg = img;\n this.spriteWidth = spriteWidth;\n this.frameHeight = Math.max(1, Math.round(frameHeight));\n this.spriteHeight = Math.max(1, Math.round(this.frameHeight * slotCount));\n }\n\n private setupResizeWatcher(): void {\n if (typeof ResizeObserver === 'undefined') return;\n if (this.resizeObserver) return;\n\n this.resizeObserver = new ResizeObserver(() => this.queueResize());\n this.resizeObserver.observe(this.container);\n }\n\n private queueResize = (): void => {\n if (this.resizeQueued) return;\n\n this.resizeQueued = true;\n\n requestAnimationFrame(() => {\n this.resizeQueued = false;\n this.resizeToContainer();\n });\n };\n\n private resizeToContainer(): void {\n const cssWidth = this.container.clientWidth;\n const cssHeight = this.container.clientHeight;\n const slotsViewport = this.visibleSlots * this.heightScale;\n\n if (cssWidth <= 0 || cssHeight <= 0) {\n this.applyResize(1, 1);\n\n return;\n }\n\n const slots = slotsViewport;\n const reels = this.reels;\n const fitByWidthH = (cssWidth / reels) * slots;\n\n let w = cssWidth;\n let h = fitByWidthH;\n\n if (h > cssHeight) {\n h = cssHeight;\n w = (cssHeight / slots) * reels;\n }\n\n const viewportWidth = Math.max(1, Math.floor(w));\n const viewportHeight = Math.max(1, Math.floor(h));\n\n this.applyResize(viewportWidth, viewportHeight);\n this.render();\n }\n\n private applyViewportCrop(): void {\n this.canvas.style.width = '100%';\n this.canvas.style.height = '100%';\n this.canvas.style.transform = '';\n }\n\n private applyResize(width: number, height: number): void {\n const normalizedWidth = Math.max(1, Math.floor(width));\n const normalizedHeight = Math.max(1, Math.floor(height));\n\n const dpr = this.getTargetDpr();\n\n this.width = normalizedWidth;\n this.height = normalizedHeight;\n this.dpr = dpr;\n\n this.canvas.width = Math.floor(this.width * this.dpr);\n this.canvas.height = Math.floor(this.height * this.dpr);\n\n if (this.gl) {\n this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n }\n\n this.applyViewportCrop();\n }\n\n private getTargetDpr(): number {\n const rawDpr = window.devicePixelRatio || 1;\n const base = Math.max(1, rawDpr);\n\n return Math.min(this.maxDpr, base);\n }\n\n private tryInitWebGL(): void {\n if (!this.spriteImg) return;\n\n this.releaseWebGLResources();\n this.webglInitError = null;\n\n const gl =\n (this.canvas.getContext('webgl2', {\n antialias: true,\n alpha: true,\n }) as WebGL2RenderingContext | null) ??\n (this.canvas.getContext('webgl', {\n antialias: true,\n alpha: true,\n }) as WebGLRenderingContext | null) ??\n (this.canvas.getContext('experimental-webgl', {\n antialias: true,\n alpha: true,\n }) as WebGLRenderingContext | null);\n\n if (!gl) {\n const fallback = document.createElement('canvas');\n const canWebGL = typeof WebGLRenderingContext !== 'undefined';\n const fallbackGl =\n (fallback.getContext('webgl2') as WebGL2RenderingContext | null) ??\n (fallback.getContext('webgl') as WebGLRenderingContext | null);\n\n this.webglInitError = `context is null (browser WebGL=${canWebGL ? 'yes' : 'no'}, fallback canvas=${fallbackGl ? 'yes' : 'no'})`;\n\n console.warn('ReelDeal WebGL:', this.webglInitError);\n\n return;\n }\n\n const vsSource = `\n attribute vec2 a_pos;\n attribute vec2 a_uv;\n varying vec2 v_uv;\n void main() {\n v_uv = a_uv;\n gl_Position = vec4(a_pos, 0.0, 1.0);\n }\n `;\n\n const fsSource = `\n #ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n #else\n precision mediump float;\n #endif\n\n varying vec2 v_uv;\n uniform sampler2D u_tex;\n uniform float u_reelX;\n uniform float u_reelW;\n uniform float u_offsetPx;\n uniform float u_frameHeight;\n uniform float u_spriteHeight;\n uniform float u_visibleSlots;\n uniform float u_heightScale;\n uniform float u_edgePower;\n uniform float u_warpAngle;\n uniform float u_blurPx;\n\n float saturate(float x) { return clamp(x, 0.0, 1.0); }\n\n void main() {\n if (v_uv.x < u_reelX || v_uv.x > (u_reelX + u_reelW)) {\n discard;\n }\n\n float localX = (v_uv.x - u_reelX) / u_reelW;\n // v_uv.y is authored as 0 at TOP, 1 at BOTTOM (Canvas-like).\n float localY = v_uv.y;\n float hs = max(0.0001, u_heightScale);\n float fullY = localY * hs + (1.0 - hs) * 0.5;\n\n float warp = max(0.0, u_warpAngle);\n float warpStrength = saturate(warp / 1.2);\n float center = 0.5;\n float centerBand = 1.0 / 3.0;\n float halfBand = centerBand * 0.5;\n float dist = abs(fullY - center);\n // Smoother transition: avoid a hard boundary at halfBand.\n float edgeWeight = smoothstep(halfBand, 0.5, dist);\n float edgePow = max(0.5, u_edgePower);\n edgeWeight = pow(edgeWeight, edgePow) * warpStrength;\n float tEase = smoothstep(0.0, 1.0, fullY);\n float warpedY = mix(fullY, tEase, edgeWeight);\n float y = (warpedY - 0.5) * 2.0;\n float theta = y * warp;\n float edgeWarp = edgeWeight;\n\n float yPx = u_offsetPx + warpedY * (u_frameHeight * u_visibleSlots);\n // With UNPACK_FLIP_Y_WEBGL=0 and Canvas-like UVs (v=0 at TOP),\n // v=0 samples the TOP of the original image, so pixel Y-from-top maps directly to v.\n // Normalize early to improve precision on mobile GPUs.\n float v = fract((u_offsetPx / u_spriteHeight) +\n warpedY * ((u_frameHeight * u_visibleSlots) / u_spriteHeight));\n\n vec4 base = texture2D(u_tex, vec2(localX, v));\n\n if (u_blurPx > 0.0) {\n // Clamp blur step to reduce banding on mobile GPUs.\n // Scale max step with speed proxy (u_blurPx).\n float maxStepPx = 1.0 + 3.0 * saturate(u_blurPx / 4.0);\n float blurPx = min(u_blurPx, maxStepPx);\n float blurStep = blurPx / max(1.0, u_spriteHeight);\n // 9-tap gaussian-ish blur to reduce banding on mobile.\n vec4 sum = base * 0.227027;\n sum += texture2D(u_tex, vec2(localX, fract(v + blurStep))) * 0.1945946;\n sum += texture2D(u_tex, vec2(localX, fract(v - blurStep))) * 0.1945946;\n sum += texture2D(u_tex, vec2(localX, fract(v + 2.0 * blurStep))) * 0.1216216;\n sum += texture2D(u_tex, vec2(localX, fract(v - 2.0 * blurStep))) * 0.1216216;\n sum += texture2D(u_tex, vec2(localX, fract(v + 3.0 * blurStep))) * 0.054054;\n sum += texture2D(u_tex, vec2(localX, fract(v - 3.0 * blurStep))) * 0.054054;\n sum += texture2D(u_tex, vec2(localX, fract(v + 4.0 * blurStep))) * 0.016216;\n sum += texture2D(u_tex, vec2(localX, fract(v - 4.0 * blurStep))) * 0.016216;\n base = sum;\n }\n\n gl_FragColor = base;\n }\n `;\n\n const program = this.createWebGLProgram(gl, vsSource, fsSource);\n\n if (!program) {\n this.webglInitError = 'shader program failed to compile/link (see console)';\n\n console.warn('ReelDeal WebGL:', this.webglInitError);\n\n return;\n }\n\n const buffer = gl.createBuffer();\n\n if (!buffer) {\n this.webglInitError = 'failed to create vertex buffer';\n\n console.warn('ReelDeal WebGL:', this.webglInitError);\n\n gl.deleteProgram(program);\n\n return;\n }\n\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n\n const quad = new Float32Array([-1, -1, 0, 1, 1, -1, 1, 1, -1, 1, 0, 0, 1, 1, 1, 0]);\n\n gl.bufferData(gl.ARRAY_BUFFER, quad, gl.STATIC_DRAW);\n\n const texture = gl.createTexture();\n\n if (!texture) {\n this.webglInitError = 'failed to create texture';\n\n console.warn('ReelDeal WebGL:', this.webglInitError);\n\n gl.deleteBuffer(buffer);\n gl.deleteProgram(program);\n\n return;\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.spriteImg);\n\n const isPowerOfTwo = (n: number): boolean => n > 0 && (n & (n - 1)) === 0;\n const pot = isPowerOfTwo(this.spriteWidth) && isPowerOfTwo(this.spriteHeight);\n\n if (pot) {\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);\n gl.generateMipmap(gl.TEXTURE_2D);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n } else {\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n }\n\n gl.useProgram(program);\n gl.clearColor(0, 0, 0, 0);\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n this.gl = gl;\n this.glProgram = program;\n this.glBuffer = buffer;\n this.glTexture = texture;\n this.glAttribs = {\n pos: gl.getAttribLocation(program, 'a_pos'),\n uv: gl.getAttribLocation(program, 'a_uv'),\n };\n this.glUniforms = {\n texture: gl.getUniformLocation(program, 'u_tex'),\n reelX: gl.getUniformLocation(program, 'u_reelX'),\n reelW: gl.getUniformLocation(program, 'u_reelW'),\n offsetPx: gl.getUniformLocation(program, 'u_offsetPx'),\n frameHeight: gl.getUniformLocation(program, 'u_frameHeight'),\n spriteHeight: gl.getUniformLocation(program, 'u_spriteHeight'),\n visibleSlots: gl.getUniformLocation(program, 'u_visibleSlots'),\n heightScale: gl.getUniformLocation(program, 'u_heightScale'),\n edgePower: gl.getUniformLocation(program, 'u_edgePower'),\n warpAngle: gl.getUniformLocation(program, 'u_warpAngle'),\n blurPx: gl.getUniformLocation(program, 'u_blurPx'),\n };\n }\n\n private createWebGLProgram(\n gl: WebGLRenderingContext | WebGL2RenderingContext,\n vsSource: string,\n fsSource: string,\n ): WebGLProgram | null {\n const vs = this.createWebGLShader(gl, gl.VERTEX_SHADER, vsSource);\n const fs = this.createWebGLShader(gl, gl.FRAGMENT_SHADER, fsSource);\n\n if (!vs || !fs) {\n if (vs) gl.deleteShader(vs);\n if (fs) gl.deleteShader(fs);\n\n return null;\n }\n\n const program = gl.createProgram();\n\n if (!program) return null;\n\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(program) ?? 'unknown link error';\n\n this.webglInitError = `program link failed: ${info}`;\n\n console.warn('ReelDeal WebGL: program link failed', info);\n\n gl.deleteProgram(program);\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return null;\n }\n\n gl.detachShader(program, vs);\n gl.detachShader(program, fs);\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return program;\n }\n\n private createWebGLShader(\n gl: WebGLRenderingContext | WebGL2RenderingContext,\n type: number,\n source: string,\n ): WebGLShader | null {\n const shader = gl.createShader(type);\n\n if (!shader) return null;\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader) ?? 'unknown compile error';\n\n this.webglInitError = `shader compile failed: ${info}`;\n\n console.warn('ReelDeal WebGL: shader compile failed', info);\n\n gl.deleteShader(shader);\n\n return null;\n }\n\n return shader;\n }\n\n private releaseWebGLResources(): void {\n if (!this.gl) return;\n if (this.glTexture) this.gl.deleteTexture(this.glTexture);\n if (this.glBuffer) this.gl.deleteBuffer(this.glBuffer);\n if (this.glProgram) this.gl.deleteProgram(this.glProgram);\n\n this.glTexture = null;\n this.glBuffer = null;\n this.glProgram = null;\n this.glAttribs = null;\n this.glUniforms = null;\n this.gl = null;\n }\n}\n"],"names":["defaultSpinConfig","defaultWebGLShading","defaultSpinBlur","defaultIdleBob","SPIN_ACCEL_END","SPIN_DECEL_START","clampInt","value","min","max","mod","n","m","clamp01","t","rampHermite","u","x","brakeHermite","reelProgress","tt","finiteOr","fallback","nonNegative","nonNegativeInt","DEFAULT_MAX_DPR","normalizeSpinConfig","overrides","base","normalizeSpinBlur","normalizeWebGLShading","normalizeIdleBob","normalizeMaxDpr","resolveElementById","id","kind","el","resolveElement","elOrId","MAX_REELS","SPIN_TICK_START","SPIN_TICK_RANGE","SPIN_TICK_MAX_PX","VELOCITY_DECAY","VELOCITY_GAIN","ReelDeal","options","target","initialSegments","segments","r","segIndex","idx","segmentIndex","stopAtSegments","config","minSpins","staggerMs","speedPxS","durationMs","useSpeed","startOffsets","deltas","durations","desiredTop","desired","current","alignDelta","delta","desiredDistance","loops","extraDelta","extraLoops","acc","v","entry","startTime","resolve","spins","spin","resolvers","disabled","now","allDone","duration","eased","baseOffset","tick","env","phase","amp","reel","speed","speedAtMax","gl","shading","warpAngle","reelW","offsetPx","dt","amplitudePx","speedHz","phaseOffsetRad","delayMs","rampMs","elapsedMs","tSec","rampT","ramp","omega","sprite","img","reject","onLoad","onError","slotCount","spriteWidth","frameHeight","expectedSpriteHeight","naturalHeight","cssWidth","cssHeight","slotsViewport","slots","reels","fitByWidthH","w","h","viewportWidth","viewportHeight","width","height","normalizedWidth","normalizedHeight","dpr","rawDpr","canWebGL","fallbackGl","program","buffer","quad","texture","isPowerOfTwo","vsSource","fsSource","vs","fs","info","type","source","shader"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/defaults.ts","../src/utils/math.ts","../src/normalize.ts","../src/utils/dom.ts","../src/ReelDeal.ts"],"sourcesContent":["import type { ReelDealIdleBob, ReelDealSpinBlur, ReelDealSpinConfig } from './types';\n\nexport const defaultSpinConfig: ReelDealSpinConfig = {\n minSpins: 2,\n durationMs: 4000,\n speedPxS: 4000,\n staggerMs: 300,\n};\n\nexport const defaultSpinBlur: ReelDealSpinBlur = {\n maxPx: 4,\n speedAtMax: 2200,\n};\n\nexport const defaultIdleBob: ReelDealIdleBob = {\n amplitudePx: 9,\n speedHz: 0.25,\n phaseOffsetRad: 0.9,\n rampMs: 800,\n};\n","const SPIN_ACCEL_END = 0.1;\nconst SPIN_DECEL_START = 0.6;\n\nexport const clampInt = (value: number, min: number, max: number): number =>\n Math.max(min, Math.min(max, Math.floor(value)));\n\nexport const mod = (n: number, m: number): number => ((n % m) + m) % m;\n\nexport const clamp01 = (t: number): number => Math.max(0, Math.min(1, t));\n\nexport const rampHermite = (u: number): number => {\n const x = clamp01(u);\n\n return x ** 2 * (2 - x);\n};\n\nexport const brakeHermite = (u: number): number => {\n const x = clamp01(u);\n\n return x + x ** 2 - x ** 3;\n};\n\nexport const reelProgress = (t: number): number => {\n const tt = clamp01(t);\n\n if (tt <= SPIN_ACCEL_END) {\n const u = tt / SPIN_ACCEL_END;\n\n return rampHermite(u) * SPIN_ACCEL_END;\n }\n\n if (tt < SPIN_DECEL_START) {\n return tt;\n }\n\n const u = (tt - SPIN_DECEL_START) / (1 - SPIN_DECEL_START);\n\n return SPIN_DECEL_START + brakeHermite(u) * (1 - SPIN_DECEL_START);\n};\n\nexport const finiteOr = (value: number | undefined, fallback: number): number =>\n typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n\nexport const nonNegative = (value: number | undefined, fallback: number): number =>\n Math.max(0, finiteOr(value, fallback));\n\nexport const nonNegativeInt = (value: number | undefined, fallback: number): number =>\n Math.max(0, Math.floor(finiteOr(value, fallback)));\n","import { defaultIdleBob, defaultSpinBlur, defaultSpinConfig } from './defaults';\nimport type { ReelDealIdleBob, ReelDealSpinBlur, ReelDealSpinConfig } from './types';\nimport { finiteOr, nonNegative, nonNegativeInt } from './utils/math';\n\nconst DEFAULT_MAX_DPR = 2;\n\nexport type NormalizedSpinConfig = Required<ReelDealSpinConfig>;\n\nexport const normalizeSpinConfig = (\n overrides?: Partial<ReelDealSpinConfig>,\n): NormalizedSpinConfig => {\n const base = { ...defaultSpinConfig, ...(overrides ?? {}) };\n\n return {\n minSpins: nonNegativeInt(base.minSpins, defaultSpinConfig.minSpins),\n durationMs: nonNegativeInt(base.durationMs, defaultSpinConfig.durationMs ?? 0),\n speedPxS: nonNegativeInt(base.speedPxS, defaultSpinConfig.speedPxS ?? 0),\n staggerMs: nonNegativeInt(base.staggerMs, defaultSpinConfig.staggerMs ?? 0),\n };\n};\n\nexport const normalizeSpinBlur = (overrides?: Partial<ReelDealSpinBlur>): ReelDealSpinBlur => {\n const base = { ...defaultSpinBlur, ...(overrides ?? {}) };\n\n return {\n maxPx: nonNegative(base.maxPx, defaultSpinBlur.maxPx),\n speedAtMax: nonNegative(base.speedAtMax, defaultSpinBlur.speedAtMax),\n };\n};\n\nexport const normalizeIdleBob = (\n overrides?: Partial<ReelDealIdleBob> | false,\n): ReelDealIdleBob | null => {\n if (overrides === false) return null;\n\n const base = { ...defaultIdleBob, ...(overrides ?? {}) };\n\n return {\n amplitudePx: nonNegative(base.amplitudePx, defaultIdleBob.amplitudePx),\n speedHz: nonNegative(base.speedHz, defaultIdleBob.speedHz),\n phaseOffsetRad: finiteOr(base.phaseOffsetRad, defaultIdleBob.phaseOffsetRad),\n rampMs: nonNegativeInt(base.rampMs, defaultIdleBob.rampMs),\n };\n};\n\nexport const normalizeMaxDpr = (value?: number): number =>\n Math.max(1, finiteOr(value, DEFAULT_MAX_DPR));\n","export const resolveElementById = <T extends HTMLElement>(id: string, kind: string): T => {\n const el = document.getElementById(id);\n\n if (!el) {\n throw new Error(`${kind} not found: ${id}`);\n }\n\n return el as T;\n};\n\nexport const resolveElement = <T extends HTMLElement>(elOrId: T | string, kind: string): T => {\n if (typeof elOrId === 'string') return resolveElementById<T>(elOrId, kind);\n\n return elOrId;\n};\n","import {\n type NormalizedSpinConfig,\n normalizeIdleBob,\n normalizeMaxDpr,\n normalizeSpinBlur,\n normalizeSpinConfig,\n} from './normalize';\nimport type {\n ReelDealIdleBob,\n ReelDealOptions,\n ReelDealSpinBlur,\n ReelDealSpinConfig,\n ReelDealSpinState,\n} from './types';\nimport { resolveElement } from './utils/dom';\nimport { clamp01, clampInt, mod, nonNegative, rampHermite, reelProgress } from './utils/math';\n\nconst MAX_REELS = 5;\nconst SPIN_TICK_START = 0.72;\nconst SPIN_TICK_RANGE = 0.28;\nconst SPIN_TICK_MAX_PX = 7;\nconst VELOCITY_DECAY = 0.85;\nconst VELOCITY_GAIN = 1 - VELOCITY_DECAY;\nconst STOP_SPRING_OVERSHOOT_PX = 30;\nconst STOP_SPRING_SETTLE_MS = 500;\nconst STOP_SPRING_OSCILLATIONS = 1.25;\nconst STOP_SPRING_DAMPING = 4;\nconst STOP_SPRING_MAX_RATIO = 0.25;\n\ntype WebGLShadingConfig = {\n warpAngleDeg: number;\n edgePower: number;\n};\n\nconst DEFAULT_WEBGL_SHADING: WebGLShadingConfig = {\n warpAngleDeg: 360,\n edgePower: 0.5,\n};\n\nconst normalizeWebGLShading = (overrides?: Partial<WebGLShadingConfig>): WebGLShadingConfig => ({\n warpAngleDeg: nonNegative(overrides?.warpAngleDeg, DEFAULT_WEBGL_SHADING.warpAngleDeg),\n edgePower: nonNegative(overrides?.edgePower, DEFAULT_WEBGL_SHADING.edgePower),\n});\n\ntype SpinAnimation = {\n startTime: number;\n startOffsets: number[];\n deltas: number[];\n durationMs: number[];\n settleDurationMs: number[];\n targets: number[];\n};\n\nexport class ReelDeal {\n private readonly canvas: HTMLCanvasElement;\n private readonly container: HTMLElement;\n\n private readonly opts: ReelDealOptions;\n private readonly visibleSlots = 3;\n private readonly heightScale = 2 / 3;\n private readonly centerIndex = 1;\n private readonly reels: number;\n private readonly spinConfig: NormalizedSpinConfig;\n private readonly spinBlur: ReelDealSpinBlur;\n private readonly webglShading: WebGLShadingConfig;\n private readonly idleBob: ReelDealIdleBob | null;\n private readonly maxDpr: number;\n\n private spriteImg: HTMLImageElement | null = null;\n private spriteWidth = 0;\n private spriteHeight = 0;\n private frameHeight = 0;\n\n private width = 0;\n private height = 0;\n private dpr = 1;\n\n private offsets: number[];\n private velocities: number[];\n private lastVelT: number | null = null;\n private lastVelOffsets: number[];\n private idleStartTime: number | null = null;\n private idleBaseOffsets: number[];\n\n private gl: WebGLRenderingContext | WebGL2RenderingContext | null = null;\n private glProgram: WebGLProgram | null = null;\n private glBuffer: WebGLBuffer | null = null;\n private glTexture: WebGLTexture | null = null;\n private glAttribs: { pos: number; uv: number } | null = null;\n private webglInitError: string | null = null;\n private glUniforms: {\n texture: WebGLUniformLocation | null;\n reelX: WebGLUniformLocation | null;\n reelW: WebGLUniformLocation | null;\n offsetPx: WebGLUniformLocation | null;\n frameHeight: WebGLUniformLocation | null;\n spriteHeight: WebGLUniformLocation | null;\n visibleSlots: WebGLUniformLocation | null;\n heightScale: WebGLUniformLocation | null;\n edgePower: WebGLUniformLocation | null;\n warpAngle: WebGLUniformLocation | null;\n blurPx: WebGLUniformLocation | null;\n } | null = null;\n\n private anim: SpinAnimation | null = null;\n private rafId: number | null = null;\n private pendingSpinResolvers: Array<() => void> = [];\n\n private resizeObserver: ResizeObserver | null = null;\n private resizeQueued = false;\n\n private button: HTMLButtonElement | null = null;\n private buttonHandlerAttached = false;\n private spinning = false;\n private queuedSpins: ReelDealSpinState[] | null = null;\n\n constructor(options: ReelDealOptions) {\n this.opts = options;\n this.reels = clampInt(options.reels ?? 1, 1, MAX_REELS);\n this.spinConfig = normalizeSpinConfig(options.spinConfig);\n this.spinBlur = normalizeSpinBlur(options.spinBlur);\n this.webglShading = normalizeWebGLShading(\n (options as { webglShading?: Partial<WebGLShadingConfig> }).webglShading,\n );\n this.idleBob = normalizeIdleBob(options.idleBob);\n this.maxDpr = normalizeMaxDpr(options.maxDpr);\n\n this.canvas = resolveElement<HTMLCanvasElement>(options.canvas, 'Canvas');\n this.container = resolveElement<HTMLElement>(options.container, 'Container');\n\n this.offsets = new Array(this.reels).fill(0);\n this.velocities = new Array(this.reels).fill(0);\n this.lastVelOffsets = new Array(this.reels).fill(0);\n this.idleBaseOffsets = new Array(this.reels).fill(0);\n }\n\n async init(): Promise<void> {\n await this.loadSprite();\n\n this.tryInitWebGL();\n\n if (!this.gl) {\n throw new Error(\n `WebGL is not supported or failed to initialize. ${this.webglInitError ?? ''}`.trim(),\n );\n }\n\n this.syncContainerLayoutVars();\n this.ensureCanvasCoversContainer();\n this.setupResizeWatcher();\n this.resizeToContainer();\n\n this.setSegments(this.opts.initialSegments);\n\n this.button = this.resolveButton();\n this.queuedSpins = this.resolveSpinQueue();\n this.attachButtonHandler();\n\n this.render();\n this.startLoop();\n }\n\n destroy(): void {\n this.stop();\n\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n if (this.button && this.buttonHandlerAttached) {\n this.button.removeEventListener('click', this.handleButtonClick);\n this.buttonHandlerAttached = false;\n }\n\n this.releaseWebGLResources();\n }\n\n private ensureCanvasCoversContainer(): void {\n if (this.canvas === this.container) return;\n if (!this.container.contains(this.canvas)) return;\n\n if (!this.canvas.style.width) this.canvas.style.width = '100%';\n if (!this.canvas.style.height) this.canvas.style.height = '100%';\n if (!this.canvas.style.display) this.canvas.style.display = 'block';\n }\n\n private syncContainerLayoutVars(): void {\n const target = this.canvas === this.container ? this.canvas : this.container;\n\n target.style.setProperty('--reels', String(this.reels));\n target.style.setProperty('--visible-slots', String(this.visibleSlots));\n target.style.aspectRatio = `${this.reels} / ${this.visibleSlots * this.heightScale}`;\n\n if (this.canvas !== this.container) {\n this.container.style.overflow = 'hidden';\n }\n }\n\n setSegments(initialSegments?: number[]): void {\n this.ensureReady();\n\n const segments = initialSegments ?? [];\n\n for (let r = 0; r < this.reels; r += 1) {\n const segIndex = segments[r] ?? 0;\n const idx = clampInt(segIndex, 0, this.opts.slotCount - 1);\n\n this.offsets[r] = idx * this.frameHeight - this.centerIndex * this.frameHeight;\n this.lastVelOffsets[r] = this.offsets[r];\n this.velocities[r] = 0;\n this.idleBaseOffsets[r] = this.offsets[r];\n }\n\n this.lastVelT = null;\n this.idleStartTime = null;\n this.anim = null;\n\n this.stop();\n this.render();\n this.startLoop();\n }\n\n setSegment(segmentIndex: number): void {\n this.setSegments(new Array(this.reels).fill(segmentIndex));\n }\n\n spinOnce(stopAtSegments: number[], config?: Partial<ReelDealSpinConfig>): Promise<void> {\n this.ensureReady();\n\n const { minSpins, staggerMs, speedPxS, durationMs } = this.getSpinConfig(config);\n const useSpeed = speedPxS > 0;\n const stopSpringOvershootPx = this.getStopSpringOvershootPx();\n const stopSpringSettleMs = Math.max(0, STOP_SPRING_SETTLE_MS);\n const stopSpringEnabled = stopSpringSettleMs > 0 && stopSpringOvershootPx > 0;\n\n const startOffsets = new Array(this.reels);\n const deltas = new Array(this.reels);\n const durations = new Array(this.reels);\n const settleDurationMs = new Array(this.reels);\n const targets = new Array(this.reels);\n\n for (let r = 0; r < this.reels; r += 1) {\n const idx = clampInt(stopAtSegments[r] ?? 0, 0, this.opts.slotCount - 1);\n const desiredTop = idx * this.frameHeight - this.centerIndex * this.frameHeight;\n const desired = mod(desiredTop, this.spriteHeight);\n const current = mod(this.offsets[r], this.spriteHeight);\n\n const alignDelta = mod(current - desired, this.spriteHeight);\n\n let delta = -(minSpins * this.spriteHeight + alignDelta);\n\n if (useSpeed && durationMs > 0) {\n const desiredDistance = (speedPxS * durationMs) / 1000;\n const loops = Math.max(\n minSpins,\n Math.ceil(Math.max(0, desiredDistance - alignDelta) / this.spriteHeight),\n );\n\n delta = -(alignDelta + loops * this.spriteHeight);\n }\n\n if (staggerMs > 0 && useSpeed) {\n const extraDelta = (speedPxS * staggerMs * r) / 1000;\n const extraLoops = Math.ceil(extraDelta / this.spriteHeight);\n\n delta -= extraLoops * this.spriteHeight;\n }\n\n startOffsets[r] = this.offsets[r];\n targets[r] = this.offsets[r] + delta;\n\n let finalDelta = delta;\n let settleDuration = 0;\n\n if (stopSpringEnabled && delta !== 0 && stopSpringOvershootPx > 0) {\n const direction = Math.sign(delta);\n const overshoot = direction * stopSpringOvershootPx;\n\n finalDelta += overshoot;\n settleDuration = stopSpringSettleMs;\n }\n\n deltas[r] = finalDelta;\n settleDurationMs[r] = settleDuration;\n\n if (useSpeed) {\n durations[r] = Math.max(0, Math.round((Math.abs(finalDelta) / speedPxS) * 1000));\n } else {\n durations[r] = Math.max(0, durationMs + staggerMs * r);\n }\n }\n\n const totalDelta = deltas.reduce((acc, v) => acc + Math.abs(v), 0);\n const allSpinZero = durations.every((entry) => entry <= 0);\n const allSettleZero = settleDurationMs.every((entry) => entry <= 0);\n\n if (totalDelta === 0 || (allSpinZero && allSettleZero)) {\n for (let r = 0; r < this.reels; r += 1) {\n this.offsets[r] = targets[r];\n }\n\n this.anim = null;\n this.resolvePendingSpins();\n this.render();\n\n return Promise.resolve();\n }\n\n const startTime = performance.now();\n\n this.anim = {\n startTime,\n startOffsets,\n deltas,\n durationMs: durations,\n settleDurationMs,\n targets,\n };\n this.idleStartTime = null;\n this.startLoop();\n\n return new Promise((resolve) => {\n this.pendingSpinResolvers.push(resolve);\n });\n }\n\n private getSpinConfig(overrides?: Partial<ReelDealSpinConfig>): NormalizedSpinConfig {\n if (!overrides) return this.spinConfig;\n\n return normalizeSpinConfig({ ...this.spinConfig, ...overrides });\n }\n\n private getStopSpringOvershootPx(): number {\n const cap = this.frameHeight * STOP_SPRING_MAX_RATIO;\n const overshoot = Math.max(0, STOP_SPRING_OVERSHOOT_PX);\n\n return Math.min(overshoot, cap);\n }\n\n private getStopSpringOffset(overshoot: number, t: number): number {\n if (overshoot === 0) return 0;\n\n const decay = Math.exp(-STOP_SPRING_DAMPING * t);\n const angle = Math.PI * 2 * STOP_SPRING_OSCILLATIONS * t;\n\n return overshoot * decay * Math.cos(angle);\n }\n\n async spinQueue(spins: ReelDealSpinState[]): Promise<void> {\n for (let i = 0; i < spins.length; i += 1) {\n const spin = spins[i];\n\n await this.spinOnce(spin.stopAtSegments);\n\n spin.callback?.(i, spin.stopAtSegments);\n }\n }\n\n stop(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n\n this.rafId = null;\n this.anim = null;\n this.resolvePendingSpins();\n this.lastVelT = null;\n\n for (let r = 0; r < this.reels; r += 1) {\n this.velocities[r] = 0;\n }\n }\n\n private resolvePendingSpins(): void {\n if (this.pendingSpinResolvers.length === 0) return;\n\n const resolvers = this.pendingSpinResolvers;\n\n this.pendingSpinResolvers = [];\n\n for (const resolve of resolvers) {\n resolve();\n }\n }\n\n requestResize(): void {\n this.queueResize();\n }\n\n private ensureReady(): void {\n if (\n !this.spriteImg ||\n this.spriteWidth <= 0 ||\n this.spriteHeight <= 0 ||\n this.frameHeight <= 0\n ) {\n throw new Error('Sprite is not ready. Call init() and await it first.');\n }\n }\n\n private attachButtonHandler(): void {\n if (!this.button || this.buttonHandlerAttached) return;\n\n this.button.addEventListener('click', this.handleButtonClick, { passive: true });\n this.buttonHandlerAttached = true;\n }\n\n private handleButtonClick = async (): Promise<void> => {\n if (this.spinning) return;\n\n const spin = this.consumeNextSpin() ?? {\n stopAtSegments: this.buildRandomSegments(),\n };\n\n this.spinning = true;\n this.setButtonDisabled(true);\n\n try {\n await this.spinOnce(spin.stopAtSegments);\n } finally {\n if (this.queuedSpins && this.queuedSpins.length === 0) {\n this.setButtonDisabled(true);\n } else {\n this.setButtonDisabled(false);\n }\n\n this.spinning = false;\n }\n };\n\n private resolveButton(): HTMLButtonElement | null {\n if (!this.opts.button) return null;\n\n return resolveElement<HTMLButtonElement>(this.opts.button, 'Button');\n }\n\n private resolveSpinQueue(): ReelDealSpinState[] | null {\n return this.opts.queuedSpinStates ?? null;\n }\n\n private consumeNextSpin(): ReelDealSpinState | null {\n if (!this.queuedSpins) {\n this.queuedSpins = this.resolveSpinQueue();\n }\n\n if (!this.queuedSpins || this.queuedSpins.length === 0) return null;\n\n return this.queuedSpins.shift() ?? null;\n }\n\n private buildRandomSegments(): number[] {\n const max = Math.max(1, Math.floor(this.opts.slotCount));\n const segments: number[] = [];\n\n for (let r = 0; r < this.reels; r += 1) {\n segments.push(Math.floor(Math.random() * max));\n }\n\n return segments;\n }\n\n private setButtonDisabled(disabled: boolean): void {\n if (!this.button) return;\n\n this.button.disabled = disabled;\n\n if (disabled) this.button.setAttribute('aria-busy', 'true');\n else this.button.removeAttribute('aria-busy');\n }\n\n private shouldAnimate(): boolean {\n return this.anim !== null || this.idleBob !== null;\n }\n\n private startLoop(): void {\n if (this.rafId !== null) return;\n if (!this.shouldAnimate()) return;\n\n this.rafId = requestAnimationFrame(this.loop);\n }\n\n private loop = (now: number): void => {\n if (this.anim) {\n const { startTime, durationMs, startOffsets, deltas, settleDurationMs, targets } = this.anim;\n const elapsed = now - startTime;\n\n let allDone = true;\n\n for (let r = 0; r < this.reels; r += 1) {\n const duration = durationMs[r] ?? 0;\n const settleDuration = settleDurationMs[r] ?? 0;\n const targetOffset = targets[r] ?? startOffsets[r] + deltas[r];\n\n if (duration > 0 && elapsed < duration) {\n const t = Math.min(1, elapsed / duration);\n const eased = reelProgress(t);\n\n if (t < 1) allDone = false;\n\n const baseOffset = startOffsets[r] + deltas[r] * eased;\n\n let tick = 0;\n\n if (t > SPIN_TICK_START && this.frameHeight > 0) {\n const u = clamp01((t - SPIN_TICK_START) / SPIN_TICK_RANGE);\n const env = (1 - u) ** 2;\n const phase = (baseOffset / this.frameHeight) * Math.PI * 2;\n const amp = Math.min(SPIN_TICK_MAX_PX, this.frameHeight * 0.06);\n\n tick = Math.sin(phase) * env * amp;\n }\n\n this.offsets[r] = baseOffset + tick;\n } else if (settleDuration > 0) {\n const t =\n duration <= 0 ? elapsed / settleDuration : (elapsed - duration) / settleDuration;\n const u = clamp01(t);\n const overshoot = startOffsets[r] + deltas[r] - targetOffset;\n const spring = this.getStopSpringOffset(overshoot, u);\n\n if (u < 1) allDone = false;\n\n this.offsets[r] = targetOffset + spring;\n } else {\n this.offsets[r] = targetOffset;\n }\n }\n\n this.updateVelocity(now);\n this.render();\n\n if (allDone) {\n for (let r = 0; r < this.reels; r += 1) {\n const targetOffset =\n this.anim.targets[r] ?? this.anim.startOffsets[r] + this.anim.deltas[r];\n\n this.offsets[r] = targetOffset;\n this.idleBaseOffsets[r] = this.offsets[r];\n }\n\n this.updateVelocity(now);\n\n for (let r = 0; r < this.reels; r += 1) {\n this.velocities[r] = 0;\n }\n\n this.anim = null;\n this.idleStartTime = null;\n\n this.render();\n this.resolvePendingSpins();\n }\n } else if (this.idleBob) {\n this.updateIdle(now);\n this.render();\n }\n\n if (!this.shouldAnimate()) {\n this.rafId = null;\n\n return;\n }\n\n if (this.rafId === null) return;\n\n this.rafId = requestAnimationFrame(this.loop);\n };\n\n private render(): void {\n if (!this.spriteImg) return;\n if (this.width <= 0 || this.height <= 0) return;\n if (!this.gl) return;\n\n this.renderWebGL();\n }\n\n private getSpinBlurPxForReel(reel: number): number {\n if (!this.anim) return 0;\n\n const speed = Math.abs(this.velocities[reel] ?? 0);\n const speedAtMax = Math.max(1, this.spinBlur.speedAtMax);\n const t = clamp01(speed / speedAtMax);\n\n return t * Math.max(0, this.spinBlur.maxPx);\n }\n\n private renderWebGL(): void {\n if (\n !this.gl ||\n !this.glProgram ||\n !this.glAttribs ||\n !this.glUniforms ||\n !this.glTexture ||\n !this.glBuffer\n ) {\n return;\n }\n\n if (!this.spriteImg) return;\n\n const gl = this.gl;\n\n gl.useProgram(this.glProgram);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);\n\n gl.enableVertexAttribArray(this.glAttribs.pos);\n gl.vertexAttribPointer(this.glAttribs.pos, 2, gl.FLOAT, false, 16, 0);\n gl.enableVertexAttribArray(this.glAttribs.uv);\n gl.vertexAttribPointer(this.glAttribs.uv, 2, gl.FLOAT, false, 16, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.glTexture);\n gl.uniform1i(this.glUniforms.texture, 0);\n\n gl.uniform1f(this.glUniforms.frameHeight, this.frameHeight);\n gl.uniform1f(this.glUniforms.spriteHeight, this.spriteHeight);\n gl.uniform1f(this.glUniforms.visibleSlots, this.visibleSlots);\n gl.uniform1f(this.glUniforms.heightScale, this.heightScale);\n gl.uniform1f(this.glUniforms.edgePower, Math.max(0.5, this.webglShading.edgePower));\n\n const shading = this.webglShading;\n const warpAngle = (Math.max(0, shading.warpAngleDeg) * Math.PI) / 180;\n\n gl.uniform1f(this.glUniforms.warpAngle, warpAngle);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n const reelW = 1 / this.reels;\n\n for (let r = 0; r < this.reels; r += 1) {\n gl.uniform1f(this.glUniforms.reelX, r * reelW);\n gl.uniform1f(this.glUniforms.reelW, reelW);\n\n const offsetPx = mod(this.offsets[r], this.spriteHeight);\n\n gl.uniform1f(this.glUniforms.offsetPx, offsetPx);\n gl.uniform1f(this.glUniforms.blurPx, this.getSpinBlurPxForReel(r));\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n }\n\n private updateVelocity(now: number): void {\n if (this.lastVelT === null) {\n this.lastVelT = now;\n\n for (let r = 0; r < this.reels; r += 1) {\n this.lastVelOffsets[r] = this.offsets[r];\n this.velocities[r] = 0;\n }\n\n return;\n }\n\n const dt = (now - this.lastVelT) / 1000;\n\n if (dt <= 0) return;\n\n for (let r = 0; r < this.reels; r += 1) {\n const v = (this.offsets[r] - this.lastVelOffsets[r]) / dt;\n\n this.velocities[r] = this.velocities[r] * VELOCITY_DECAY + v * VELOCITY_GAIN;\n this.lastVelOffsets[r] = this.offsets[r];\n }\n\n this.lastVelT = now;\n }\n\n private updateIdle(now: number): void {\n if (!this.idleBob) return;\n if (this.idleStartTime === null) this.idleStartTime = now;\n\n const { amplitudePx, speedHz, phaseOffsetRad, rampMs } = this.idleBob;\n const elapsedMs = now - this.idleStartTime;\n\n const tSec = elapsedMs / 1000;\n const rampT = Math.max(0, Math.min(1, elapsedMs / Math.max(1, rampMs)));\n const ramp = rampHermite(rampT);\n const omega = speedHz * Math.PI * 2;\n\n for (let r = 0; r < this.reels; r += 1) {\n const phase = tSec * omega + r * phaseOffsetRad;\n\n this.offsets[r] = this.idleBaseOffsets[r] + Math.sin(phase) * (amplitudePx * ramp);\n this.velocities[r] = 0;\n }\n }\n\n private async loadSprite(): Promise<void> {\n const { sprite } = this.opts;\n const img = typeof sprite === 'string' ? new Image() : sprite;\n\n if (typeof sprite === 'string') {\n img.src = sprite;\n }\n\n if (!img.complete || img.naturalWidth <= 0) {\n await new Promise<void>((resolve, reject) => {\n const onLoad = () => resolve();\n const onError = () => reject(new Error('Failed to load sprite image'));\n\n img.addEventListener('load', onLoad, { once: true });\n img.addEventListener('error', onError, { once: true });\n });\n }\n\n const slotCount = Math.max(1, Math.floor(this.opts.slotCount));\n const spriteWidth = img.naturalWidth;\n const frameHeight = spriteWidth;\n const expectedSpriteHeight = frameHeight * slotCount;\n\n const naturalHeight = img.naturalHeight;\n const diff = Math.abs(naturalHeight - expectedSpriteHeight);\n\n if (diff > 2) {\n throw new Error(\n `Sprite size mismatch. Expected height ~${Math.round(expectedSpriteHeight)}px (slotCount=${slotCount}, slot aspect 1/1), got ${naturalHeight}px.`,\n );\n }\n\n this.spriteImg = img;\n this.spriteWidth = spriteWidth;\n this.frameHeight = Math.max(1, Math.round(frameHeight));\n this.spriteHeight = Math.max(1, Math.round(this.frameHeight * slotCount));\n }\n\n private setupResizeWatcher(): void {\n if (typeof ResizeObserver === 'undefined') return;\n if (this.resizeObserver) return;\n\n this.resizeObserver = new ResizeObserver(() => this.queueResize());\n this.resizeObserver.observe(this.container);\n }\n\n private queueResize = (): void => {\n if (this.resizeQueued) return;\n\n this.resizeQueued = true;\n\n requestAnimationFrame(() => {\n this.resizeQueued = false;\n this.resizeToContainer();\n });\n };\n\n private resizeToContainer(): void {\n const cssWidth = this.container.clientWidth;\n const cssHeight = this.container.clientHeight;\n const slotsViewport = this.visibleSlots * this.heightScale;\n\n if (cssWidth <= 0 || cssHeight <= 0) {\n this.applyResize(1, 1);\n\n return;\n }\n\n const slots = slotsViewport;\n const reels = this.reels;\n const fitByWidthH = (cssWidth / reels) * slots;\n\n let w = cssWidth;\n let h = fitByWidthH;\n\n if (h > cssHeight) {\n h = cssHeight;\n w = (cssHeight / slots) * reels;\n }\n\n const viewportWidth = Math.max(1, Math.floor(w));\n const viewportHeight = Math.max(1, Math.floor(h));\n\n this.applyResize(viewportWidth, viewportHeight);\n this.render();\n }\n\n private applyViewportCrop(): void {\n this.canvas.style.width = '100%';\n this.canvas.style.height = '100%';\n this.canvas.style.transform = '';\n }\n\n private applyResize(width: number, height: number): void {\n const normalizedWidth = Math.max(1, Math.floor(width));\n const normalizedHeight = Math.max(1, Math.floor(height));\n\n const dpr = this.getTargetDpr();\n\n this.width = normalizedWidth;\n this.height = normalizedHeight;\n this.dpr = dpr;\n\n this.canvas.width = Math.floor(this.width * this.dpr);\n this.canvas.height = Math.floor(this.height * this.dpr);\n\n if (this.gl) {\n this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n }\n\n this.applyViewportCrop();\n }\n\n private getTargetDpr(): number {\n const rawDpr = window.devicePixelRatio || 1;\n const base = Math.max(1, rawDpr);\n\n return Math.min(this.maxDpr, base);\n }\n\n private tryInitWebGL(): void {\n if (!this.spriteImg) return;\n\n this.releaseWebGLResources();\n this.webglInitError = null;\n\n const gl =\n (this.canvas.getContext('webgl2', {\n antialias: true,\n alpha: true,\n }) as WebGL2RenderingContext | null) ??\n (this.canvas.getContext('webgl', {\n antialias: true,\n alpha: true,\n }) as WebGLRenderingContext | null) ??\n (this.canvas.getContext('experimental-webgl', {\n antialias: true,\n alpha: true,\n }) as WebGLRenderingContext | null);\n\n if (!gl) {\n const fallback = document.createElement('canvas');\n const canWebGL = typeof WebGLRenderingContext !== 'undefined';\n const fallbackGl =\n (fallback.getContext('webgl2') as WebGL2RenderingContext | null) ??\n (fallback.getContext('webgl') as WebGLRenderingContext | null);\n\n this.webglInitError = `context is null (browser WebGL=${canWebGL ? 'yes' : 'no'}, fallback canvas=${fallbackGl ? 'yes' : 'no'})`;\n\n console.warn('ReelDeal WebGL:', this.webglInitError);\n\n return;\n }\n\n const vsSource = `\n attribute vec2 a_pos;\n attribute vec2 a_uv;\n varying vec2 v_uv;\n void main() {\n v_uv = a_uv;\n gl_Position = vec4(a_pos, 0.0, 1.0);\n }\n `;\n\n const fsSource = `\n #ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n #else\n precision mediump float;\n #endif\n\n varying vec2 v_uv;\n uniform sampler2D u_tex;\n uniform float u_reelX;\n uniform float u_reelW;\n uniform float u_offsetPx;\n uniform float u_frameHeight;\n uniform float u_spriteHeight;\n uniform float u_visibleSlots;\n uniform float u_heightScale;\n uniform float u_edgePower;\n uniform float u_warpAngle;\n uniform float u_blurPx;\n\n const float HALF_PI = 1.5707963;\n\n float saturate(float x) { return clamp(x, 0.0, 1.0); }\n\n void main() {\n if (v_uv.x < u_reelX || v_uv.x > (u_reelX + u_reelW)) {\n discard;\n }\n\n float localX = (v_uv.x - u_reelX) / u_reelW;\n float localY = v_uv.y;\n float hs = max(0.0001, u_heightScale);\n float fullY = localY * hs + (1.0 - hs) * 0.5;\n\n float warp = max(0.0, u_warpAngle);\n float warpStrength = saturate(warp / 1.2);\n float center = 0.5;\n float centerBand = 1.0 / 3.0;\n float halfBand = centerBand * 0.5;\n float dist = abs(fullY - center);\n float edgeWeight = smoothstep(halfBand, 0.5, dist);\n float edgePow = max(0.5, u_edgePower);\n edgeWeight = pow(edgeWeight, edgePow) * warpStrength;\n float yCentered = (fullY - 0.5) * 2.0;\n float sinY = 0.5 + 0.5 * sin(yCentered * HALF_PI);\n float warpedY = mix(fullY, sinY, edgeWeight);\n\n float yPx = u_offsetPx + warpedY * (u_frameHeight * u_visibleSlots);\n float v = fract((u_offsetPx / u_spriteHeight) +\n warpedY * ((u_frameHeight * u_visibleSlots) / u_spriteHeight));\n\n vec4 base = texture2D(u_tex, vec2(localX, v));\n\n if (u_blurPx > 0.0) {\n float maxStepPx = 1.0 + 3.0 * saturate(u_blurPx / 4.0);\n float blurPx = min(u_blurPx, maxStepPx);\n float blurStep = blurPx / max(1.0, u_spriteHeight);\n vec4 sum = base * 0.227027;\n sum += texture2D(u_tex, vec2(localX, fract(v + blurStep))) * 0.1945946;\n sum += texture2D(u_tex, vec2(localX, fract(v - blurStep))) * 0.1945946;\n sum += texture2D(u_tex, vec2(localX, fract(v + 2.0 * blurStep))) * 0.1216216;\n sum += texture2D(u_tex, vec2(localX, fract(v - 2.0 * blurStep))) * 0.1216216;\n sum += texture2D(u_tex, vec2(localX, fract(v + 3.0 * blurStep))) * 0.054054;\n sum += texture2D(u_tex, vec2(localX, fract(v - 3.0 * blurStep))) * 0.054054;\n sum += texture2D(u_tex, vec2(localX, fract(v + 4.0 * blurStep))) * 0.016216;\n sum += texture2D(u_tex, vec2(localX, fract(v - 4.0 * blurStep))) * 0.016216;\n base = sum;\n }\n\n gl_FragColor = base;\n }\n `;\n\n const program = this.createWebGLProgram(gl, vsSource, fsSource);\n\n if (!program) {\n this.webglInitError = 'shader program failed to compile/link (see console)';\n\n console.warn('ReelDeal WebGL:', this.webglInitError);\n\n return;\n }\n\n const buffer = gl.createBuffer();\n\n if (!buffer) {\n this.webglInitError = 'failed to create vertex buffer';\n\n console.warn('ReelDeal WebGL:', this.webglInitError);\n\n gl.deleteProgram(program);\n\n return;\n }\n\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n\n const quad = new Float32Array([-1, -1, 0, 1, 1, -1, 1, 1, -1, 1, 0, 0, 1, 1, 1, 0]);\n\n gl.bufferData(gl.ARRAY_BUFFER, quad, gl.STATIC_DRAW);\n\n const texture = gl.createTexture();\n\n if (!texture) {\n this.webglInitError = 'failed to create texture';\n\n console.warn('ReelDeal WebGL:', this.webglInitError);\n\n gl.deleteBuffer(buffer);\n gl.deleteProgram(program);\n\n return;\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.spriteImg);\n\n const isPowerOfTwo = (n: number): boolean => n > 0 && (n & (n - 1)) === 0;\n const pot = isPowerOfTwo(this.spriteWidth) && isPowerOfTwo(this.spriteHeight);\n\n if (pot) {\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);\n gl.generateMipmap(gl.TEXTURE_2D);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n } else {\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n }\n\n gl.useProgram(program);\n gl.clearColor(0, 0, 0, 0);\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n this.gl = gl;\n this.glProgram = program;\n this.glBuffer = buffer;\n this.glTexture = texture;\n this.glAttribs = {\n pos: gl.getAttribLocation(program, 'a_pos'),\n uv: gl.getAttribLocation(program, 'a_uv'),\n };\n this.glUniforms = {\n texture: gl.getUniformLocation(program, 'u_tex'),\n reelX: gl.getUniformLocation(program, 'u_reelX'),\n reelW: gl.getUniformLocation(program, 'u_reelW'),\n offsetPx: gl.getUniformLocation(program, 'u_offsetPx'),\n frameHeight: gl.getUniformLocation(program, 'u_frameHeight'),\n spriteHeight: gl.getUniformLocation(program, 'u_spriteHeight'),\n visibleSlots: gl.getUniformLocation(program, 'u_visibleSlots'),\n heightScale: gl.getUniformLocation(program, 'u_heightScale'),\n edgePower: gl.getUniformLocation(program, 'u_edgePower'),\n warpAngle: gl.getUniformLocation(program, 'u_warpAngle'),\n blurPx: gl.getUniformLocation(program, 'u_blurPx'),\n };\n }\n\n private createWebGLProgram(\n gl: WebGLRenderingContext | WebGL2RenderingContext,\n vsSource: string,\n fsSource: string,\n ): WebGLProgram | null {\n const vs = this.createWebGLShader(gl, gl.VERTEX_SHADER, vsSource);\n const fs = this.createWebGLShader(gl, gl.FRAGMENT_SHADER, fsSource);\n\n if (!vs || !fs) {\n if (vs) gl.deleteShader(vs);\n if (fs) gl.deleteShader(fs);\n\n return null;\n }\n\n const program = gl.createProgram();\n\n if (!program) return null;\n\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(program) ?? 'unknown link error';\n\n this.webglInitError = `program link failed: ${info}`;\n\n console.warn('ReelDeal WebGL: program link failed', info);\n\n gl.deleteProgram(program);\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return null;\n }\n\n gl.detachShader(program, vs);\n gl.detachShader(program, fs);\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return program;\n }\n\n private createWebGLShader(\n gl: WebGLRenderingContext | WebGL2RenderingContext,\n type: number,\n source: string,\n ): WebGLShader | null {\n const shader = gl.createShader(type);\n\n if (!shader) return null;\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader) ?? 'unknown compile error';\n\n this.webglInitError = `shader compile failed: ${info}`;\n\n console.warn('ReelDeal WebGL: shader compile failed', info);\n\n gl.deleteShader(shader);\n\n return null;\n }\n\n return shader;\n }\n\n private releaseWebGLResources(): void {\n if (!this.gl) return;\n if (this.glTexture) this.gl.deleteTexture(this.glTexture);\n if (this.glBuffer) this.gl.deleteBuffer(this.glBuffer);\n if (this.glProgram) this.gl.deleteProgram(this.glProgram);\n\n this.glTexture = null;\n this.glBuffer = null;\n this.glProgram = null;\n this.glAttribs = null;\n this.glUniforms = null;\n this.gl = null;\n }\n}\n"],"names":["defaultSpinConfig","defaultSpinBlur","defaultIdleBob","SPIN_ACCEL_END","SPIN_DECEL_START","clampInt","value","min","max","mod","n","m","clamp01","t","rampHermite","u","x","brakeHermite","reelProgress","tt","finiteOr","fallback","nonNegative","nonNegativeInt","DEFAULT_MAX_DPR","normalizeSpinConfig","overrides","base","normalizeSpinBlur","normalizeIdleBob","normalizeMaxDpr","resolveElementById","id","kind","el","resolveElement","elOrId","MAX_REELS","SPIN_TICK_START","SPIN_TICK_RANGE","SPIN_TICK_MAX_PX","VELOCITY_DECAY","VELOCITY_GAIN","STOP_SPRING_OVERSHOOT_PX","STOP_SPRING_SETTLE_MS","STOP_SPRING_OSCILLATIONS","STOP_SPRING_MAX_RATIO","DEFAULT_WEBGL_SHADING","normalizeWebGLShading","ReelDeal","options","target","initialSegments","segments","r","segIndex","idx","segmentIndex","stopAtSegments","config","minSpins","staggerMs","speedPxS","durationMs","useSpeed","stopSpringOvershootPx","stopSpringSettleMs","stopSpringEnabled","startOffsets","deltas","durations","settleDurationMs","targets","desiredTop","desired","current","alignDelta","delta","desiredDistance","loops","extraDelta","extraLoops","finalDelta","settleDuration","overshoot","totalDelta","acc","v","allSpinZero","entry","allSettleZero","startTime","resolve","cap","decay","angle","spins","i","spin","resolvers","disabled","now","elapsed","allDone","duration","targetOffset","eased","baseOffset","tick","env","phase","amp","spring","reel","speed","speedAtMax","gl","shading","warpAngle","reelW","offsetPx","dt","amplitudePx","speedHz","phaseOffsetRad","rampMs","elapsedMs","tSec","rampT","ramp","omega","sprite","img","reject","onLoad","onError","slotCount","spriteWidth","frameHeight","expectedSpriteHeight","naturalHeight","cssWidth","cssHeight","slotsViewport","slots","reels","fitByWidthH","w","h","viewportWidth","viewportHeight","width","height","normalizedWidth","normalizedHeight","dpr","rawDpr","canWebGL","fallbackGl","program","buffer","quad","texture","isPowerOfTwo","vsSource","fsSource","vs","fs","info","type","source","shader"],"mappings":"iOAEO,MAAMA,EAAwC,CACnD,SAAU,EACV,WAAY,IACZ,SAAU,IACV,UAAW,GACb,EAEaC,EAAoC,CAC/C,MAAO,EACP,WAAY,IACd,EAEaC,EAAkC,CAC7C,YAAa,EACb,QAAS,IACT,eAAgB,GAChB,OAAQ,GACV,ECnBMC,EAAiB,GACjBC,EAAmB,GAEZC,EAAW,CAACC,EAAeC,EAAaC,IACnD,KAAK,IAAID,EAAK,KAAK,IAAIC,EAAK,KAAK,MAAMF,CAAK,CAAC,CAAC,EAEnCG,EAAM,CAACC,EAAWC,KAAwBD,EAAIC,EAAKA,GAAKA,EAExDC,EAAWC,GAAsB,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGA,CAAC,CAAC,EAE3DC,EAAeC,GAAsB,CAChD,MAAMC,EAAIJ,EAAQG,CAAC,EAEnB,OAAOC,GAAK,GAAK,EAAIA,EACvB,EAEaC,EAAgBF,GAAsB,CACjD,MAAMC,EAAIJ,EAAQG,CAAC,EAEnB,OAAOC,EAAIA,GAAK,EAAIA,GAAK,CAC3B,EAEaE,EAAgBL,GAAsB,CACjD,MAAMM,EAAKP,EAAQC,CAAC,EAEpB,GAAIM,GAAMhB,EAAgB,CACxB,MAAMY,EAAII,EAAKhB,EAEf,OAAOW,EAAYC,CAAC,EAAIZ,CAC1B,CAEA,GAAIgB,EAAKf,EACP,OAAOe,EAGT,MAAMJ,GAAKI,EAAKf,IAAqB,EAAIA,GAEzC,OAAOA,EAAmBa,EAAaF,CAAC,GAAK,EAAIX,EACnD,EAEagB,EAAW,CAACd,EAA2Be,IAClD,OAAOf,GAAU,UAAY,OAAO,SAASA,CAAK,EAAIA,EAAQe,EAEnDC,EAAc,CAAChB,EAA2Be,IACrD,KAAK,IAAI,EAAGD,EAASd,EAAOe,CAAQ,CAAC,EAE1BE,EAAiB,CAACjB,EAA2Be,IACxD,KAAK,IAAI,EAAG,KAAK,MAAMD,EAASd,EAAOe,CAAQ,CAAC,CAAC,EC3C7CG,EAAkB,EAIXC,EACXC,GACyB,CACzB,MAAMC,EAAO,CAAE,GAAG3B,EAAmB,GAAI0B,GAAa,CAAA,CAAC,EAEvD,MAAO,CACL,SAAUH,EAAeI,EAAK,SAAU3B,EAAkB,QAAQ,EAClE,WAAYuB,EAAeI,EAAK,WAAY3B,EAAkB,YAAc,CAAC,EAC7E,SAAUuB,EAAeI,EAAK,SAAU3B,EAAkB,UAAY,CAAC,EACvE,UAAWuB,EAAeI,EAAK,UAAW3B,EAAkB,WAAa,CAAC,CAAA,CAE9E,EAEa4B,EAAqBF,GAA4D,CAC5F,MAAMC,EAAO,CAAE,GAAG1B,EAAiB,GAAIyB,GAAa,CAAA,CAAC,EAErD,MAAO,CACL,MAAOJ,EAAYK,EAAK,MAAO1B,EAAgB,KAAK,EACpD,WAAYqB,EAAYK,EAAK,WAAY1B,EAAgB,UAAU,CAAA,CAEvE,EAEa4B,EACXH,GAC2B,CAC3B,GAAIA,IAAc,GAAO,OAAO,KAEhC,MAAMC,EAAO,CAAE,GAAGzB,EAAgB,GAAIwB,GAAa,CAAA,CAAC,EAEpD,MAAO,CACL,YAAaJ,EAAYK,EAAK,YAAazB,EAAe,WAAW,EACrE,QAASoB,EAAYK,EAAK,QAASzB,EAAe,OAAO,EACzD,eAAgBkB,EAASO,EAAK,eAAgBzB,EAAe,cAAc,EAC3E,OAAQqB,EAAeI,EAAK,OAAQzB,EAAe,MAAM,CAAA,CAE7D,EAEa4B,EAAmBxB,GAC9B,KAAK,IAAI,EAAGc,EAASd,EAAOkB,CAAe,CAAC,EC9CjCO,EAAqB,CAAwBC,EAAYC,IAAoB,CACxF,MAAMC,EAAK,SAAS,eAAeF,CAAE,EAErC,GAAI,CAACE,EACH,MAAM,IAAI,MAAM,GAAGD,CAAI,eAAeD,CAAE,EAAE,EAG5C,OAAOE,CACT,EAEaC,EAAiB,CAAwBC,EAAoBH,IACpE,OAAOG,GAAW,SAAiBL,EAAsBK,EAAQH,CAAI,EAElEG,ECIHC,EAAY,EACZC,EAAkB,IAClBC,GAAkB,IAClBC,GAAmB,EACnBC,EAAiB,IACjBC,GAAgB,EAAID,EACpBE,GAA2B,GAC3BC,GAAwB,IACxBC,GAA2B,KAE3BC,GAAwB,IAOxBC,EAA4C,CAChD,aAAc,IACd,UAAW,EACb,EAEMC,GAAyBtB,IAAiE,CAC9F,aAAcJ,EAAYI,GAAW,aAAcqB,EAAsB,YAAY,EACrF,UAAWzB,EAAYI,GAAW,UAAWqB,EAAsB,SAAS,CAC9E,GAWO,MAAME,EAAS,CACH,OACA,UAEA,KACA,aAAe,EACf,YAAc,EAAI,EAClB,YAAc,EACd,MACA,WACA,SACA,aACA,QACA,OAET,UAAqC,KACrC,YAAc,EACd,aAAe,EACf,YAAc,EAEd,MAAQ,EACR,OAAS,EACT,IAAM,EAEN,QACA,WACA,SAA0B,KAC1B,eACA,cAA+B,KAC/B,gBAEA,GAA4D,KAC5D,UAAiC,KACjC,SAA+B,KAC/B,UAAiC,KACjC,UAAgD,KAChD,eAAgC,KAChC,WAYG,KAEH,KAA6B,KAC7B,MAAuB,KACvB,qBAA0C,CAAA,EAE1C,eAAwC,KACxC,aAAe,GAEf,OAAmC,KACnC,sBAAwB,GACxB,SAAW,GACX,YAA0C,KAElD,YAAYC,EAA0B,CACpC,KAAK,KAAOA,EACZ,KAAK,MAAQ7C,EAAS6C,EAAQ,OAAS,EAAG,EAAGb,CAAS,EACtD,KAAK,WAAaZ,EAAoByB,EAAQ,UAAU,EACxD,KAAK,SAAWtB,EAAkBsB,EAAQ,QAAQ,EAClD,KAAK,aAAeF,GACjBE,EAA2D,YAAA,EAE9D,KAAK,QAAUrB,EAAiBqB,EAAQ,OAAO,EAC/C,KAAK,OAASpB,EAAgBoB,EAAQ,MAAM,EAE5C,KAAK,OAASf,EAAkCe,EAAQ,OAAQ,QAAQ,EACxE,KAAK,UAAYf,EAA4Be,EAAQ,UAAW,WAAW,EAE3E,KAAK,QAAU,IAAI,MAAM,KAAK,KAAK,EAAE,KAAK,CAAC,EAC3C,KAAK,WAAa,IAAI,MAAM,KAAK,KAAK,EAAE,KAAK,CAAC,EAC9C,KAAK,eAAiB,IAAI,MAAM,KAAK,KAAK,EAAE,KAAK,CAAC,EAClD,KAAK,gBAAkB,IAAI,MAAM,KAAK,KAAK,EAAE,KAAK,CAAC,CACrD,CAEA,MAAM,MAAsB,CAK1B,GAJA,MAAM,KAAK,WAAA,EAEX,KAAK,aAAA,EAED,CAAC,KAAK,GACR,MAAM,IAAI,MACR,mDAAmD,KAAK,gBAAkB,EAAE,GAAG,KAAA,CAAK,EAIxF,KAAK,wBAAA,EACL,KAAK,4BAAA,EACL,KAAK,mBAAA,EACL,KAAK,kBAAA,EAEL,KAAK,YAAY,KAAK,KAAK,eAAe,EAE1C,KAAK,OAAS,KAAK,cAAA,EACnB,KAAK,YAAc,KAAK,iBAAA,EACxB,KAAK,oBAAA,EAEL,KAAK,OAAA,EACL,KAAK,UAAA,CACP,CAEA,SAAgB,CACd,KAAK,KAAA,EAED,KAAK,iBACP,KAAK,eAAe,WAAA,EACpB,KAAK,eAAiB,MAGpB,KAAK,QAAU,KAAK,wBACtB,KAAK,OAAO,oBAAoB,QAAS,KAAK,iBAAiB,EAC/D,KAAK,sBAAwB,IAG/B,KAAK,sBAAA,CACP,CAEQ,6BAAoC,CACtC,KAAK,SAAW,KAAK,WACpB,KAAK,UAAU,SAAS,KAAK,MAAM,IAEnC,KAAK,OAAO,MAAM,QAAO,KAAK,OAAO,MAAM,MAAQ,QACnD,KAAK,OAAO,MAAM,SAAQ,KAAK,OAAO,MAAM,OAAS,QACrD,KAAK,OAAO,MAAM,UAAS,KAAK,OAAO,MAAM,QAAU,SAC9D,CAEQ,yBAAgC,CACtC,MAAMC,EAAS,KAAK,SAAW,KAAK,UAAY,KAAK,OAAS,KAAK,UAEnEA,EAAO,MAAM,YAAY,UAAW,OAAO,KAAK,KAAK,CAAC,EACtDA,EAAO,MAAM,YAAY,kBAAmB,OAAO,KAAK,YAAY,CAAC,EACrEA,EAAO,MAAM,YAAc,GAAG,KAAK,KAAK,MAAM,KAAK,aAAe,KAAK,WAAW,GAE9E,KAAK,SAAW,KAAK,YACvB,KAAK,UAAU,MAAM,SAAW,SAEpC,CAEA,YAAYC,EAAkC,CAC5C,KAAK,YAAA,EAEL,MAAMC,EAAWD,GAAmB,CAAA,EAEpC,QAASE,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EAAG,CACtC,MAAMC,EAAWF,EAASC,CAAC,GAAK,EAC1BE,EAAMnD,EAASkD,EAAU,EAAG,KAAK,KAAK,UAAY,CAAC,EAEzD,KAAK,QAAQD,CAAC,EAAIE,EAAM,KAAK,YAAc,KAAK,YAAc,KAAK,YACnE,KAAK,eAAeF,CAAC,EAAI,KAAK,QAAQA,CAAC,EACvC,KAAK,WAAWA,CAAC,EAAI,EACrB,KAAK,gBAAgBA,CAAC,EAAI,KAAK,QAAQA,CAAC,CAC1C,CAEA,KAAK,SAAW,KAChB,KAAK,cAAgB,KACrB,KAAK,KAAO,KAEZ,KAAK,KAAA,EACL,KAAK,OAAA,EACL,KAAK,UAAA,CACP,CAEA,WAAWG,EAA4B,CACrC,KAAK,YAAY,IAAI,MAAM,KAAK,KAAK,EAAE,KAAKA,CAAY,CAAC,CAC3D,CAEA,SAASC,EAA0BC,EAAqD,CACtF,KAAK,YAAA,EAEL,KAAM,CAAE,SAAAC,EAAU,UAAAC,EAAW,SAAAC,EAAU,WAAAC,GAAe,KAAK,cAAcJ,CAAM,EACzEK,EAAWF,EAAW,EACtBG,EAAwB,KAAK,yBAAA,EAC7BC,EAAqB,KAAK,IAAI,EAAGtB,EAAqB,EACtDuB,EAAoBD,EAAqB,GAAKD,EAAwB,EAEtEG,EAAe,IAAI,MAAM,KAAK,KAAK,EACnCC,EAAS,IAAI,MAAM,KAAK,KAAK,EAC7BC,EAAY,IAAI,MAAM,KAAK,KAAK,EAChCC,EAAmB,IAAI,MAAM,KAAK,KAAK,EACvCC,EAAU,IAAI,MAAM,KAAK,KAAK,EAEpC,QAASlB,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EAAG,CAEtC,MAAMmB,GADMpE,EAASqD,EAAeJ,CAAC,GAAK,EAAG,EAAG,KAAK,KAAK,UAAY,CAAC,EAC9C,KAAK,YAAc,KAAK,YAAc,KAAK,YAC9DoB,GAAUjE,EAAIgE,GAAY,KAAK,YAAY,EAC3CE,GAAUlE,EAAI,KAAK,QAAQ6C,CAAC,EAAG,KAAK,YAAY,EAEhDsB,EAAanE,EAAIkE,GAAUD,GAAS,KAAK,YAAY,EAE3D,IAAIG,EAAQ,EAAEjB,EAAW,KAAK,aAAegB,GAE7C,GAAIZ,GAAYD,EAAa,EAAG,CAC9B,MAAMe,EAAmBhB,EAAWC,EAAc,IAC5CgB,EAAQ,KAAK,IACjBnB,EACA,KAAK,KAAK,KAAK,IAAI,EAAGkB,EAAkBF,CAAU,EAAI,KAAK,YAAY,CAAA,EAGzEC,EAAQ,EAAED,EAAaG,EAAQ,KAAK,aACtC,CAEA,GAAIlB,EAAY,GAAKG,EAAU,CAC7B,MAAMgB,EAAclB,EAAWD,EAAYP,EAAK,IAC1C2B,EAAa,KAAK,KAAKD,EAAa,KAAK,YAAY,EAE3DH,GAASI,EAAa,KAAK,YAC7B,CAEAb,EAAad,CAAC,EAAI,KAAK,QAAQA,CAAC,EAChCkB,EAAQlB,CAAC,EAAI,KAAK,QAAQA,CAAC,EAAIuB,EAE/B,IAAIK,EAAaL,EACbM,EAAiB,EAErB,GAAIhB,GAAqBU,IAAU,GAAKZ,EAAwB,EAAG,CAEjE,MAAMmB,EADY,KAAK,KAAKP,CAAK,EACHZ,EAE9BiB,GAAcE,EACdD,EAAiBjB,CACnB,CAEAG,EAAOf,CAAC,EAAI4B,EACZX,EAAiBjB,CAAC,EAAI6B,EAElBnB,EACFM,EAAUhB,CAAC,EAAI,KAAK,IAAI,EAAG,KAAK,MAAO,KAAK,IAAI4B,CAAU,EAAIpB,EAAY,GAAI,CAAC,EAE/EQ,EAAUhB,CAAC,EAAI,KAAK,IAAI,EAAGS,EAAaF,EAAYP,CAAC,CAEzD,CAEA,MAAM+B,EAAahB,EAAO,OAAO,CAACiB,EAAKC,IAAMD,EAAM,KAAK,IAAIC,CAAC,EAAG,CAAC,EAC3DC,EAAclB,EAAU,MAAOmB,GAAUA,GAAS,CAAC,EACnDC,EAAgBnB,EAAiB,MAAOkB,GAAUA,GAAS,CAAC,EAElE,GAAIJ,IAAe,GAAMG,GAAeE,EAAgB,CACtD,QAASpC,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EACnC,KAAK,QAAQA,CAAC,EAAIkB,EAAQlB,CAAC,EAG7B,YAAK,KAAO,KACZ,KAAK,oBAAA,EACL,KAAK,OAAA,EAEE,QAAQ,QAAA,CACjB,CAEA,MAAMqC,EAAY,YAAY,IAAA,EAE9B,YAAK,KAAO,CACV,UAAAA,EACA,aAAAvB,EACA,OAAAC,EACA,WAAYC,EACZ,iBAAAC,EACA,QAAAC,CAAA,EAEF,KAAK,cAAgB,KACrB,KAAK,UAAA,EAEE,IAAI,QAASoB,GAAY,CAC9B,KAAK,qBAAqB,KAAKA,CAAO,CACxC,CAAC,CACH,CAEQ,cAAclE,EAA+D,CACnF,OAAKA,EAEED,EAAoB,CAAE,GAAG,KAAK,WAAY,GAAGC,EAAW,EAFxC,KAAK,UAG9B,CAEQ,0BAAmC,CACzC,MAAMmE,EAAM,KAAK,YAAc/C,GACzBsC,EAAY,KAAK,IAAI,EAAGzC,EAAwB,EAEtD,OAAO,KAAK,IAAIyC,EAAWS,CAAG,CAChC,CAEQ,oBAAoBT,EAAmBvE,EAAmB,CAChE,GAAIuE,IAAc,EAAG,MAAO,GAE5B,MAAMU,EAAQ,KAAK,IAAI,GAAuBjF,CAAC,EACzCkF,EAAQ,KAAK,GAAK,EAAIlD,GAA2BhC,EAEvD,OAAOuE,EAAYU,EAAQ,KAAK,IAAIC,CAAK,CAC3C,CAEA,MAAM,UAAUC,EAA2C,CACzD,QAASC,EAAI,EAAGA,EAAID,EAAM,OAAQC,GAAK,EAAG,CACxC,MAAMC,EAAOF,EAAMC,CAAC,EAEpB,MAAM,KAAK,SAASC,EAAK,cAAc,EAEvCA,EAAK,WAAWD,EAAGC,EAAK,cAAc,CACxC,CACF,CAEA,MAAa,CACP,KAAK,QAAU,MAAM,qBAAqB,KAAK,KAAK,EAExD,KAAK,MAAQ,KACb,KAAK,KAAO,KACZ,KAAK,oBAAA,EACL,KAAK,SAAW,KAEhB,QAAS5C,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EACnC,KAAK,WAAWA,CAAC,EAAI,CAEzB,CAEQ,qBAA4B,CAClC,GAAI,KAAK,qBAAqB,SAAW,EAAG,OAE5C,MAAM6C,EAAY,KAAK,qBAEvB,KAAK,qBAAuB,CAAA,EAE5B,UAAWP,KAAWO,EACpBP,EAAA,CAEJ,CAEA,eAAsB,CACpB,KAAK,YAAA,CACP,CAEQ,aAAoB,CAC1B,GACE,CAAC,KAAK,WACN,KAAK,aAAe,GACpB,KAAK,cAAgB,GACrB,KAAK,aAAe,EAEpB,MAAM,IAAI,MAAM,sDAAsD,CAE1E,CAEQ,qBAA4B,CAC9B,CAAC,KAAK,QAAU,KAAK,wBAEzB,KAAK,OAAO,iBAAiB,QAAS,KAAK,kBAAmB,CAAE,QAAS,GAAM,EAC/E,KAAK,sBAAwB,GAC/B,CAEQ,kBAAoB,SAA2B,CACrD,GAAI,KAAK,SAAU,OAEnB,MAAMM,EAAO,KAAK,mBAAqB,CACrC,eAAgB,KAAK,oBAAA,CAAoB,EAG3C,KAAK,SAAW,GAChB,KAAK,kBAAkB,EAAI,EAE3B,GAAI,CACF,MAAM,KAAK,SAASA,EAAK,cAAc,CACzC,QAAA,CACM,KAAK,aAAe,KAAK,YAAY,SAAW,EAClD,KAAK,kBAAkB,EAAI,EAE3B,KAAK,kBAAkB,EAAK,EAG9B,KAAK,SAAW,EAClB,CACF,EAEQ,eAA0C,CAChD,OAAK,KAAK,KAAK,OAER/D,EAAkC,KAAK,KAAK,OAAQ,QAAQ,EAFrC,IAGhC,CAEQ,kBAA+C,CACrD,OAAO,KAAK,KAAK,kBAAoB,IACvC,CAEQ,iBAA4C,CAKlD,OAJK,KAAK,cACR,KAAK,YAAc,KAAK,iBAAA,GAGtB,CAAC,KAAK,aAAe,KAAK,YAAY,SAAW,EAAU,KAExD,KAAK,YAAY,MAAA,GAAW,IACrC,CAEQ,qBAAgC,CACtC,MAAM3B,EAAM,KAAK,IAAI,EAAG,KAAK,MAAM,KAAK,KAAK,SAAS,CAAC,EACjD6C,EAAqB,CAAA,EAE3B,QAASC,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EACnCD,EAAS,KAAK,KAAK,MAAM,KAAK,OAAA,EAAW7C,CAAG,CAAC,EAG/C,OAAO6C,CACT,CAEQ,kBAAkB+C,EAAyB,CAC5C,KAAK,SAEV,KAAK,OAAO,SAAWA,EAEnBA,EAAU,KAAK,OAAO,aAAa,YAAa,MAAM,EACrD,KAAK,OAAO,gBAAgB,WAAW,EAC9C,CAEQ,eAAyB,CAC/B,OAAO,KAAK,OAAS,MAAQ,KAAK,UAAY,IAChD,CAEQ,WAAkB,CACpB,KAAK,QAAU,MACd,KAAK,kBAEV,KAAK,MAAQ,sBAAsB,KAAK,IAAI,EAC9C,CAEQ,KAAQC,GAAsB,CACpC,GAAI,KAAK,KAAM,CACb,KAAM,CAAE,UAAAV,EAAW,WAAA5B,EAAY,aAAAK,EAAc,OAAAC,EAAQ,iBAAAE,EAAkB,QAAAC,GAAY,KAAK,KAClF8B,EAAUD,EAAMV,EAEtB,IAAIY,EAAU,GAEd,QAASjD,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EAAG,CACtC,MAAMkD,EAAWzC,EAAWT,CAAC,GAAK,EAC5B6B,EAAiBZ,EAAiBjB,CAAC,GAAK,EACxCmD,EAAejC,EAAQlB,CAAC,GAAKc,EAAad,CAAC,EAAIe,EAAOf,CAAC,EAE7D,GAAIkD,EAAW,GAAKF,EAAUE,EAAU,CACtC,MAAM3F,EAAI,KAAK,IAAI,EAAGyF,EAAUE,CAAQ,EAClCE,EAAQxF,EAAaL,CAAC,EAExBA,EAAI,IAAG0F,EAAU,IAErB,MAAMI,EAAavC,EAAad,CAAC,EAAIe,EAAOf,CAAC,EAAIoD,EAEjD,IAAIE,EAAO,EAEX,GAAI/F,EAAIyB,GAAmB,KAAK,YAAc,EAAG,CAE/C,MAAMuE,GAAO,EADHjG,GAASC,EAAIyB,GAAmBC,EAAe,IAClC,EACjBuE,EAASH,EAAa,KAAK,YAAe,KAAK,GAAK,EACpDI,EAAM,KAAK,IAAIvE,GAAkB,KAAK,YAAc,GAAI,EAE9DoE,EAAO,KAAK,IAAIE,CAAK,EAAID,EAAME,CACjC,CAEA,KAAK,QAAQzD,CAAC,EAAIqD,EAAaC,CACjC,SAAWzB,EAAiB,EAAG,CAC7B,MAAMtE,EACJ2F,GAAY,EAAIF,EAAUnB,GAAkBmB,EAAUE,GAAYrB,EAC9DpE,EAAIH,EAAQC,CAAC,EACbuE,EAAYhB,EAAad,CAAC,EAAIe,EAAOf,CAAC,EAAImD,EAC1CO,EAAS,KAAK,oBAAoB5B,EAAWrE,CAAC,EAEhDA,EAAI,IAAGwF,EAAU,IAErB,KAAK,QAAQjD,CAAC,EAAImD,EAAeO,CACnC,MACE,KAAK,QAAQ1D,CAAC,EAAImD,CAEtB,CAKA,GAHA,KAAK,eAAeJ,CAAG,EACvB,KAAK,OAAA,EAEDE,EAAS,CACX,QAASjD,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EAAG,CACtC,MAAMmD,EACJ,KAAK,KAAK,QAAQnD,CAAC,GAAK,KAAK,KAAK,aAAaA,CAAC,EAAI,KAAK,KAAK,OAAOA,CAAC,EAExE,KAAK,QAAQA,CAAC,EAAImD,EAClB,KAAK,gBAAgBnD,CAAC,EAAI,KAAK,QAAQA,CAAC,CAC1C,CAEA,KAAK,eAAe+C,CAAG,EAEvB,QAAS/C,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EACnC,KAAK,WAAWA,CAAC,EAAI,EAGvB,KAAK,KAAO,KACZ,KAAK,cAAgB,KAErB,KAAK,OAAA,EACL,KAAK,oBAAA,CACP,CACF,MAAW,KAAK,UACd,KAAK,WAAW+C,CAAG,EACnB,KAAK,OAAA,GAGP,GAAI,CAAC,KAAK,gBAAiB,CACzB,KAAK,MAAQ,KAEb,MACF,CAEI,KAAK,QAAU,OAEnB,KAAK,MAAQ,sBAAsB,KAAK,IAAI,EAC9C,EAEQ,QAAe,CAChB,KAAK,YACN,KAAK,OAAS,GAAK,KAAK,QAAU,GACjC,KAAK,IAEV,KAAK,YAAA,EACP,CAEQ,qBAAqBY,EAAsB,CACjD,GAAI,CAAC,KAAK,KAAM,MAAO,GAEvB,MAAMC,EAAQ,KAAK,IAAI,KAAK,WAAWD,CAAI,GAAK,CAAC,EAC3CE,EAAa,KAAK,IAAI,EAAG,KAAK,SAAS,UAAU,EAGvD,OAFUvG,EAAQsG,EAAQC,CAAU,EAEzB,KAAK,IAAI,EAAG,KAAK,SAAS,KAAK,CAC5C,CAEQ,aAAoB,CAY1B,GAVE,CAAC,KAAK,IACN,CAAC,KAAK,WACN,CAAC,KAAK,WACN,CAAC,KAAK,YACN,CAAC,KAAK,WACN,CAAC,KAAK,UAKJ,CAAC,KAAK,UAAW,OAErB,MAAMC,EAAK,KAAK,GAEhBA,EAAG,WAAW,KAAK,SAAS,EAC5BA,EAAG,WAAWA,EAAG,aAAc,KAAK,QAAQ,EAE5CA,EAAG,wBAAwB,KAAK,UAAU,GAAG,EAC7CA,EAAG,oBAAoB,KAAK,UAAU,IAAK,EAAGA,EAAG,MAAO,GAAO,GAAI,CAAC,EACpEA,EAAG,wBAAwB,KAAK,UAAU,EAAE,EAC5CA,EAAG,oBAAoB,KAAK,UAAU,GAAI,EAAGA,EAAG,MAAO,GAAO,GAAI,CAAC,EAEnEA,EAAG,cAAcA,EAAG,QAAQ,EAC5BA,EAAG,YAAYA,EAAG,WAAY,KAAK,SAAS,EAC5CA,EAAG,UAAU,KAAK,WAAW,QAAS,CAAC,EAEvCA,EAAG,UAAU,KAAK,WAAW,YAAa,KAAK,WAAW,EAC1DA,EAAG,UAAU,KAAK,WAAW,aAAc,KAAK,YAAY,EAC5DA,EAAG,UAAU,KAAK,WAAW,aAAc,KAAK,YAAY,EAC5DA,EAAG,UAAU,KAAK,WAAW,YAAa,KAAK,WAAW,EAC1DA,EAAG,UAAU,KAAK,WAAW,UAAW,KAAK,IAAI,GAAK,KAAK,aAAa,SAAS,CAAC,EAElF,MAAMC,EAAU,KAAK,aACfC,EAAa,KAAK,IAAI,EAAGD,EAAQ,YAAY,EAAI,KAAK,GAAM,IAElED,EAAG,UAAU,KAAK,WAAW,UAAWE,CAAS,EACjDF,EAAG,MAAMA,EAAG,gBAAgB,EAE5B,MAAMG,EAAQ,EAAI,KAAK,MAEvB,QAAS,EAAI,EAAG,EAAI,KAAK,MAAO,GAAK,EAAG,CACtCH,EAAG,UAAU,KAAK,WAAW,MAAO,EAAIG,CAAK,EAC7CH,EAAG,UAAU,KAAK,WAAW,MAAOG,CAAK,EAEzC,MAAMC,EAAW/G,EAAI,KAAK,QAAQ,CAAC,EAAG,KAAK,YAAY,EAEvD2G,EAAG,UAAU,KAAK,WAAW,SAAUI,CAAQ,EAC/CJ,EAAG,UAAU,KAAK,WAAW,OAAQ,KAAK,qBAAqB,CAAC,CAAC,EACjEA,EAAG,WAAWA,EAAG,eAAgB,EAAG,CAAC,CACvC,CACF,CAEQ,eAAef,EAAmB,CACxC,GAAI,KAAK,WAAa,KAAM,CAC1B,KAAK,SAAWA,EAEhB,QAAS/C,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EACnC,KAAK,eAAeA,CAAC,EAAI,KAAK,QAAQA,CAAC,EACvC,KAAK,WAAWA,CAAC,EAAI,EAGvB,MACF,CAEA,MAAMmE,GAAMpB,EAAM,KAAK,UAAY,IAEnC,GAAI,EAAAoB,GAAM,GAEV,SAASnE,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EAAG,CACtC,MAAMiC,GAAK,KAAK,QAAQjC,CAAC,EAAI,KAAK,eAAeA,CAAC,GAAKmE,EAEvD,KAAK,WAAWnE,CAAC,EAAI,KAAK,WAAWA,CAAC,EAAIb,EAAiB8C,EAAI7C,GAC/D,KAAK,eAAeY,CAAC,EAAI,KAAK,QAAQA,CAAC,CACzC,CAEA,KAAK,SAAW+C,EAClB,CAEQ,WAAWA,EAAmB,CACpC,GAAI,CAAC,KAAK,QAAS,OACf,KAAK,gBAAkB,OAAM,KAAK,cAAgBA,GAEtD,KAAM,CAAE,YAAAqB,EAAa,QAAAC,EAAS,eAAAC,EAAgB,OAAAC,CAAA,EAAW,KAAK,QACxDC,EAAYzB,EAAM,KAAK,cAEvB0B,EAAOD,EAAY,IACnBE,EAAQ,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGF,EAAY,KAAK,IAAI,EAAGD,CAAM,CAAC,CAAC,EAChEI,EAAOnH,EAAYkH,CAAK,EACxBE,EAAQP,EAAU,KAAK,GAAK,EAElC,QAASrE,EAAI,EAAGA,EAAI,KAAK,MAAOA,GAAK,EAAG,CACtC,MAAMwD,EAAQiB,EAAOG,EAAQ5E,EAAIsE,EAEjC,KAAK,QAAQtE,CAAC,EAAI,KAAK,gBAAgBA,CAAC,EAAI,KAAK,IAAIwD,CAAK,GAAKY,EAAcO,GAC7E,KAAK,WAAW3E,CAAC,EAAI,CACvB,CACF,CAEA,MAAc,YAA4B,CACxC,KAAM,CAAE,OAAA6E,GAAW,KAAK,KAClBC,EAAM,OAAOD,GAAW,SAAW,IAAI,MAAUA,EAEnD,OAAOA,GAAW,WACpBC,EAAI,IAAMD,IAGR,CAACC,EAAI,UAAYA,EAAI,cAAgB,IACvC,MAAM,IAAI,QAAc,CAACxC,EAASyC,IAAW,CAC3C,MAAMC,EAAS,IAAM1C,EAAA,EACf2C,EAAU,IAAMF,EAAO,IAAI,MAAM,6BAA6B,CAAC,EAErED,EAAI,iBAAiB,OAAQE,EAAQ,CAAE,KAAM,GAAM,EACnDF,EAAI,iBAAiB,QAASG,EAAS,CAAE,KAAM,GAAM,CACvD,CAAC,EAGH,MAAMC,EAAY,KAAK,IAAI,EAAG,KAAK,MAAM,KAAK,KAAK,SAAS,CAAC,EACvDC,EAAcL,EAAI,aAClBM,EAAcD,EACdE,EAAuBD,EAAcF,EAErCI,EAAgBR,EAAI,cAG1B,GAFa,KAAK,IAAIQ,EAAgBD,CAAoB,EAE/C,EACT,MAAM,IAAI,MACR,0CAA0C,KAAK,MAAMA,CAAoB,CAAC,iBAAiBH,CAAS,2BAA2BI,CAAa,KAAA,EAIhJ,KAAK,UAAYR,EACjB,KAAK,YAAcK,EACnB,KAAK,YAAc,KAAK,IAAI,EAAG,KAAK,MAAMC,CAAW,CAAC,EACtD,KAAK,aAAe,KAAK,IAAI,EAAG,KAAK,MAAM,KAAK,YAAcF,CAAS,CAAC,CAC1E,CAEQ,oBAA2B,CAC7B,OAAO,eAAmB,KAC1B,KAAK,iBAET,KAAK,eAAiB,IAAI,eAAe,IAAM,KAAK,aAAa,EACjE,KAAK,eAAe,QAAQ,KAAK,SAAS,EAC5C,CAEQ,YAAc,IAAY,CAC5B,KAAK,eAET,KAAK,aAAe,GAEpB,sBAAsB,IAAM,CAC1B,KAAK,aAAe,GACpB,KAAK,kBAAA,CACP,CAAC,EACH,EAEQ,mBAA0B,CAChC,MAAMK,EAAW,KAAK,UAAU,YAC1BC,EAAY,KAAK,UAAU,aAC3BC,EAAgB,KAAK,aAAe,KAAK,YAE/C,GAAIF,GAAY,GAAKC,GAAa,EAAG,CACnC,KAAK,YAAY,EAAG,CAAC,EAErB,MACF,CAEA,MAAME,EAAQD,EACRE,EAAQ,KAAK,MACbC,EAAeL,EAAWI,EAASD,EAEzC,IAAIG,EAAIN,EACJO,EAAIF,EAEJE,EAAIN,IACNM,EAAIN,EACJK,EAAKL,EAAYE,EAASC,GAG5B,MAAMI,EAAgB,KAAK,IAAI,EAAG,KAAK,MAAMF,CAAC,CAAC,EACzCG,EAAiB,KAAK,IAAI,EAAG,KAAK,MAAMF,CAAC,CAAC,EAEhD,KAAK,YAAYC,EAAeC,CAAc,EAC9C,KAAK,OAAA,CACP,CAEQ,mBAA0B,CAChC,KAAK,OAAO,MAAM,MAAQ,OAC1B,KAAK,OAAO,MAAM,OAAS,OAC3B,KAAK,OAAO,MAAM,UAAY,EAChC,CAEQ,YAAYC,EAAeC,EAAsB,CACvD,MAAMC,EAAkB,KAAK,IAAI,EAAG,KAAK,MAAMF,CAAK,CAAC,EAC/CG,EAAmB,KAAK,IAAI,EAAG,KAAK,MAAMF,CAAM,CAAC,EAEjDG,EAAM,KAAK,aAAA,EAEjB,KAAK,MAAQF,EACb,KAAK,OAASC,EACd,KAAK,IAAMC,EAEX,KAAK,OAAO,MAAQ,KAAK,MAAM,KAAK,MAAQ,KAAK,GAAG,EACpD,KAAK,OAAO,OAAS,KAAK,MAAM,KAAK,OAAS,KAAK,GAAG,EAElD,KAAK,IACP,KAAK,GAAG,SAAS,EAAG,EAAG,KAAK,OAAO,MAAO,KAAK,OAAO,MAAM,EAG9D,KAAK,kBAAA,CACP,CAEQ,cAAuB,CAC7B,MAAMC,EAAS,OAAO,kBAAoB,EACpCjI,EAAO,KAAK,IAAI,EAAGiI,CAAM,EAE/B,OAAO,KAAK,IAAI,KAAK,OAAQjI,CAAI,CACnC,CAEQ,cAAqB,CAC3B,GAAI,CAAC,KAAK,UAAW,OAErB,KAAK,sBAAA,EACL,KAAK,eAAiB,KAEtB,MAAMyF,EACH,KAAK,OAAO,WAAW,SAAU,CAChC,UAAW,GACX,MAAO,EAAA,CACR,GACA,KAAK,OAAO,WAAW,QAAS,CAC/B,UAAW,GACX,MAAO,EAAA,CACR,GACA,KAAK,OAAO,WAAW,qBAAsB,CAC5C,UAAW,GACX,MAAO,EAAA,CACR,EAEH,GAAI,CAACA,EAAI,CACP,MAAM/F,EAAW,SAAS,cAAc,QAAQ,EAC1CwI,EAAW,OAAO,sBAA0B,IAC5CC,EACHzI,EAAS,WAAW,QAAQ,GAC5BA,EAAS,WAAW,OAAO,EAE9B,KAAK,eAAiB,kCAAkCwI,EAAW,MAAQ,IAAI,qBAAqBC,EAAa,MAAQ,IAAI,IAE7H,QAAQ,KAAK,kBAAmB,KAAK,cAAc,EAEnD,MACF,CAqFA,MAAMC,EAAU,KAAK,mBAAmB3C,EAnFvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAyE6C,EAE9D,GAAI,CAAC2C,EAAS,CACZ,KAAK,eAAiB,sDAEtB,QAAQ,KAAK,kBAAmB,KAAK,cAAc,EAEnD,MACF,CAEA,MAAMC,EAAS5C,EAAG,aAAA,EAElB,GAAI,CAAC4C,EAAQ,CACX,KAAK,eAAiB,iCAEtB,QAAQ,KAAK,kBAAmB,KAAK,cAAc,EAEnD5C,EAAG,cAAc2C,CAAO,EAExB,MACF,CAEA3C,EAAG,WAAWA,EAAG,aAAc4C,CAAM,EAErC,MAAMC,EAAO,IAAI,aAAa,CAAC,GAAI,GAAI,EAAG,EAAG,EAAG,GAAI,EAAG,EAAG,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,CAAC,EAElF7C,EAAG,WAAWA,EAAG,aAAc6C,EAAM7C,EAAG,WAAW,EAEnD,MAAM8C,EAAU9C,EAAG,cAAA,EAEnB,GAAI,CAAC8C,EAAS,CACZ,KAAK,eAAiB,2BAEtB,QAAQ,KAAK,kBAAmB,KAAK,cAAc,EAEnD9C,EAAG,aAAa4C,CAAM,EACtB5C,EAAG,cAAc2C,CAAO,EAExB,MACF,CAEA3C,EAAG,YAAYA,EAAG,WAAY8C,CAAO,EACrC9C,EAAG,YAAYA,EAAG,oBAAqB,CAAC,EACxCA,EAAG,WAAWA,EAAG,WAAY,EAAGA,EAAG,KAAMA,EAAG,KAAMA,EAAG,cAAe,KAAK,SAAS,EAElF,MAAM+C,EAAgB,GAAuB,EAAI,IAAM,EAAK,EAAI,KAAQ,EAC5DA,EAAa,KAAK,WAAW,GAAKA,EAAa,KAAK,YAAY,GAG1E/C,EAAG,cAAcA,EAAG,WAAYA,EAAG,eAAgBA,EAAG,MAAM,EAC5DA,EAAG,cAAcA,EAAG,WAAYA,EAAG,eAAgBA,EAAG,MAAM,EAC5DA,EAAG,eAAeA,EAAG,UAAU,EAC/BA,EAAG,cAAcA,EAAG,WAAYA,EAAG,mBAAoBA,EAAG,oBAAoB,EAC9EA,EAAG,cAAcA,EAAG,WAAYA,EAAG,mBAAoBA,EAAG,MAAM,IAEhEA,EAAG,cAAcA,EAAG,WAAYA,EAAG,mBAAoBA,EAAG,MAAM,EAChEA,EAAG,cAAcA,EAAG,WAAYA,EAAG,mBAAoBA,EAAG,MAAM,EAChEA,EAAG,cAAcA,EAAG,WAAYA,EAAG,eAAgBA,EAAG,aAAa,EACnEA,EAAG,cAAcA,EAAG,WAAYA,EAAG,eAAgBA,EAAG,aAAa,GAGrEA,EAAG,WAAW2C,CAAO,EACrB3C,EAAG,WAAW,EAAG,EAAG,EAAG,CAAC,EACxBA,EAAG,OAAOA,EAAG,KAAK,EAClBA,EAAG,UAAUA,EAAG,UAAWA,EAAG,mBAAmB,EAEjD,KAAK,GAAKA,EACV,KAAK,UAAY2C,EACjB,KAAK,SAAWC,EAChB,KAAK,UAAYE,EACjB,KAAK,UAAY,CACf,IAAK9C,EAAG,kBAAkB2C,EAAS,OAAO,EAC1C,GAAI3C,EAAG,kBAAkB2C,EAAS,MAAM,CAAA,EAE1C,KAAK,WAAa,CAChB,QAAS3C,EAAG,mBAAmB2C,EAAS,OAAO,EAC/C,MAAO3C,EAAG,mBAAmB2C,EAAS,SAAS,EAC/C,MAAO3C,EAAG,mBAAmB2C,EAAS,SAAS,EAC/C,SAAU3C,EAAG,mBAAmB2C,EAAS,YAAY,EACrD,YAAa3C,EAAG,mBAAmB2C,EAAS,eAAe,EAC3D,aAAc3C,EAAG,mBAAmB2C,EAAS,gBAAgB,EAC7D,aAAc3C,EAAG,mBAAmB2C,EAAS,gBAAgB,EAC7D,YAAa3C,EAAG,mBAAmB2C,EAAS,eAAe,EAC3D,UAAW3C,EAAG,mBAAmB2C,EAAS,aAAa,EACvD,UAAW3C,EAAG,mBAAmB2C,EAAS,aAAa,EACvD,OAAQ3C,EAAG,mBAAmB2C,EAAS,UAAU,CAAA,CAErD,CAEQ,mBACN3C,EACAgD,EACAC,EACqB,CACrB,MAAMC,EAAK,KAAK,kBAAkBlD,EAAIA,EAAG,cAAegD,CAAQ,EAC1DG,EAAK,KAAK,kBAAkBnD,EAAIA,EAAG,gBAAiBiD,CAAQ,EAElE,GAAI,CAACC,GAAM,CAACC,EACV,OAAID,GAAIlD,EAAG,aAAakD,CAAE,EACtBC,GAAInD,EAAG,aAAamD,CAAE,EAEnB,KAGT,MAAMR,EAAU3C,EAAG,cAAA,EAEnB,GAAI,CAAC2C,EAAS,OAAO,KAMrB,GAJA3C,EAAG,aAAa2C,EAASO,CAAE,EAC3BlD,EAAG,aAAa2C,EAASQ,CAAE,EAC3BnD,EAAG,YAAY2C,CAAO,EAElB,CAAC3C,EAAG,oBAAoB2C,EAAS3C,EAAG,WAAW,EAAG,CACpD,MAAMoD,EAAOpD,EAAG,kBAAkB2C,CAAO,GAAK,qBAE9C,YAAK,eAAiB,wBAAwBS,CAAI,GAElD,QAAQ,KAAK,sCAAuCA,CAAI,EAExDpD,EAAG,cAAc2C,CAAO,EACxB3C,EAAG,aAAakD,CAAE,EAClBlD,EAAG,aAAamD,CAAE,EAEX,IACT,CAEA,OAAAnD,EAAG,aAAa2C,EAASO,CAAE,EAC3BlD,EAAG,aAAa2C,EAASQ,CAAE,EAC3BnD,EAAG,aAAakD,CAAE,EAClBlD,EAAG,aAAamD,CAAE,EAEXR,CACT,CAEQ,kBACN3C,EACAqD,EACAC,EACoB,CACpB,MAAMC,EAASvD,EAAG,aAAaqD,CAAI,EAEnC,GAAI,CAACE,EAAQ,OAAO,KAKpB,GAHAvD,EAAG,aAAauD,EAAQD,CAAM,EAC9BtD,EAAG,cAAcuD,CAAM,EAEnB,CAACvD,EAAG,mBAAmBuD,EAAQvD,EAAG,cAAc,EAAG,CACrD,MAAMoD,EAAOpD,EAAG,iBAAiBuD,CAAM,GAAK,wBAE5C,YAAK,eAAiB,0BAA0BH,CAAI,GAEpD,QAAQ,KAAK,wCAAyCA,CAAI,EAE1DpD,EAAG,aAAauD,CAAM,EAEf,IACT,CAEA,OAAOA,CACT,CAEQ,uBAA8B,CAC/B,KAAK,KACN,KAAK,WAAW,KAAK,GAAG,cAAc,KAAK,SAAS,EACpD,KAAK,UAAU,KAAK,GAAG,aAAa,KAAK,QAAQ,EACjD,KAAK,WAAW,KAAK,GAAG,cAAc,KAAK,SAAS,EAExD,KAAK,UAAY,KACjB,KAAK,SAAW,KAChB,KAAK,UAAY,KACjB,KAAK,UAAY,KACjB,KAAK,WAAa,KAClB,KAAK,GAAK,KACZ,CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reel-deal",
3
- "version": "0.1.0-dev.1",
3
+ "version": "0.1.0",
4
4
  "description": "High-performance WebGL slot reel animation for any HTMLCanvasElement.",
5
5
  "author": "ux-ui.pro",
6
6
  "license": "MIT",