pixi-reels 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/{ReelSymbol-BxoiwQ-r.cjs → ReelSymbol-BJGylIyA.cjs} +2 -2
  3. package/dist/{ReelSymbol-BxoiwQ-r.cjs.map → ReelSymbol-BJGylIyA.cjs.map} +1 -1
  4. package/dist/{ReelSymbol-C9QQ30ER.js → ReelSymbol-DBbmNOIa.js} +2 -2
  5. package/dist/{ReelSymbol-C9QQ30ER.js.map → ReelSymbol-DBbmNOIa.js.map} +1 -1
  6. package/dist/{SpineSymbol-DAqBuFX2.cjs → SpineSymbol-C6V3FScO.cjs} +2 -2
  7. package/dist/{SpineSymbol-DAqBuFX2.cjs.map → SpineSymbol-C6V3FScO.cjs.map} +1 -1
  8. package/dist/{SpineSymbol-C_pacfc4.js → SpineSymbol-w7zxDNo_.js} +2 -2
  9. package/dist/{SpineSymbol-C_pacfc4.js.map → SpineSymbol-w7zxDNo_.js.map} +1 -1
  10. package/dist/config/types.d.ts +41 -0
  11. package/dist/config/types.d.ts.map +1 -1
  12. package/dist/core/Reel.d.ts +7 -0
  13. package/dist/core/Reel.d.ts.map +1 -1
  14. package/dist/core/ReelSet.d.ts +58 -5
  15. package/dist/core/ReelSet.d.ts.map +1 -1
  16. package/dist/{debug-BmrZG9xv.js → debug-C1xsPOVH.js} +65 -24
  17. package/dist/debug-C1xsPOVH.js.map +1 -0
  18. package/dist/debug-CWou81X6.cjs +4 -0
  19. package/dist/debug-CWou81X6.cjs.map +1 -0
  20. package/dist/events/ReelEvents.d.ts +24 -0
  21. package/dist/events/ReelEvents.d.ts.map +1 -1
  22. package/dist/horizontal/HorizontalReel.d.ts.map +1 -1
  23. package/dist/index.cjs +1 -1
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.ts +7 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +280 -45
  28. package/dist/index.js.map +1 -1
  29. package/dist/snapshot/SpinTextureCache.d.ts +149 -0
  30. package/dist/snapshot/SpinTextureCache.d.ts.map +1 -0
  31. package/dist/snapshot/StaticSpinSymbol.d.ts +123 -0
  32. package/dist/snapshot/StaticSpinSymbol.d.ts.map +1 -0
  33. package/dist/spin/SpinController.d.ts +80 -4
  34. package/dist/spin/SpinController.d.ts.map +1 -1
  35. package/dist/spin/anticipationRecipes.d.ts +51 -0
  36. package/dist/spin/anticipationRecipes.d.ts.map +1 -0
  37. package/dist/spin/phases/AnticipationPhase.d.ts +3 -2
  38. package/dist/spin/phases/AnticipationPhase.d.ts.map +1 -1
  39. package/dist/spin/phases/StartPhase.d.ts.map +1 -1
  40. package/dist/spin/phases/StopPhase.d.ts +9 -0
  41. package/dist/spin/phases/StopPhase.d.ts.map +1 -1
  42. package/dist/spine/SpineReelSymbol.d.ts.map +1 -1
  43. package/dist/spine.cjs +1 -1
  44. package/dist/spine.cjs.map +1 -1
  45. package/dist/spine.js +4 -4
  46. package/dist/spine.js.map +1 -1
  47. package/dist/symbols/ReelSymbol.d.ts +14 -4
  48. package/dist/symbols/ReelSymbol.d.ts.map +1 -1
  49. package/dist/testing.cjs +1 -1
  50. package/dist/testing.js +2 -2
  51. package/package.json +1 -1
  52. package/dist/debug-Bj1W7zDw.cjs +0 -4
  53. package/dist/debug-Bj1W7zDw.cjs.map +0 -1
  54. package/dist/debug-BmrZG9xv.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # pixi-reels
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#186](https://github.com/schmooky/pixi-reels/pull/186) [`b6d1649`](https://github.com/schmooky/pixi-reels/commit/b6d1649ec8102f64063479e81dacd5ad920606e8) Thanks [@igaming-bulochka](https://github.com/igaming-bulochka)! - Add: static / motion-blurred snapshot spinning — spin cached textures instead of live symbols. New `SpinTextureCache` captures any symbol into a per-symbolId `RenderTexture` (or accepts hand-authored textures via `setStatic` / `setBlurred`, which always win and are never destroyed by the cache) and bakes a motion-blur variant in a one-time `BlurFilter` pass — no filters run during the spin. The smear follows the reel's travel axis: vertical by default, `blur: { axis: 'x' }` for a `HorizontalReel` strip. New `StaticSpinSymbol` wraps any `ReelSymbol` (Spine included): while the reel spins it deactivates the inner symbol and shows the cached snapshot, crossfading crisp→blurred over `blurRampMs`; symbols wrapping in mid-spin only retarget a sprite texture; on land the live symbol is reactivated. `prewarmSpinTextures()` bakes all ids up front so the first spin never hitches. Engine: `onReelSpinStart` now also fires (with a new `joinedMidSpin` arg) on symbols installed while a reel is already spinning, spin start/end notifications reach buffer rows, a slam-stopped `StartPhase` no longer skips `notifySpinStart`, and `HorizontalReel` now fires the symbol spin hooks across its conveyor (`onReelSpinStart` at `spin()` and on mid-spin feeds; `onReelSpinEnd` at `setResult()` so the visible deceleration runs crisp and the landing window feeds in live — what lands is never blurred; `onReelLanded` on land) — fixing Spine `autoPlayBlur` gaps where mid-spin, slammed, or horizontal-strip symbols stayed on `idle`. Spin-state hooks must now be idempotent; `SpineReelSymbol.playBlur()` no longer restarts an already-running blur loop, and `SpineReelSymbol` applies the idle pose immediately on activation (`spine.update(0)`) so same-frame renders and snapshot captures see the posed skeleton instead of nothing.
8
+
9
+ ## 1.3.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#183](https://github.com/schmooky/pixi-reels/pull/183) [`5bddccb`](https://github.com/schmooky/pixi-reels/commit/5bddccb105e7a913f4858c2e86e119c7098b9319) Thanks [@igaming-bulochka](https://github.com/igaming-bulochka)! - Add: staggered / sequential anticipation so teasing reels build tension one after another instead of all slowing down at once.
14
+
15
+ `setAnticipation(reelIndices, stagger?)` now takes a second argument controlling when each reel BEGINS its slow-down (offsets are by tease-order, not raw reel index):
16
+
17
+ - `0` (default) — every anticipation reel starts slowing together (unchanged behaviour).
18
+ - `number` — reel at tease-order `k` starts `k * stagger` ms after the first.
19
+ - `number[]` — explicit per-tease-order offset in ms.
20
+ - `'sequential'` — each reel waits until the previous anticipation reel has fully landed before it starts.
21
+
22
+ Add: progressive slow-down. Pass `setAnticipation(reels, { stagger, slowdown })` where `slowdown` (`{ from, to, holdFrom, holdTo }`) interpolates across the tease sequence, so each successive reel decelerates to a lower speed and/or holds longer than the last — the escalating "each reel crawls slower than the one before" build-up. Omit it for the previous flat 30%-and-hold tease.
23
+
24
+ Add: `duration` override — `setAnticipation(reels, { duration })` sets the tease hold in ms regardless of the active speed profile, so anticipation keeps playing in Turbo / SuperTurbo (whose profiles use `anticipationDelay: 0` and previously skipped it entirely).
25
+
26
+ Add: `anticipation:reel` (`{ reelIndex, order, total }`) and `anticipation:reelEnd` (`{ reelIndex }`) events — a dedicated per-reel tease start/end signal so games can drive tension SFX, pitch ramps (`order / (total - 1)`), and escalating visuals without re-deriving the tease set from `spin:stopping`. Fired only for reels that actually tease.
27
+
28
+ Add: `anticipationForScatters(grid, { symbol, trigger, mode })` — derive the tease reel list straight from a result grid (`grid` is the same `ColumnTarget[]` you pass to `setResult`). Anticipation begins on the reel after the `trigger`-th scatter; `mode: 'all-remaining'` teases every following reel, `'scatter-only'` teases only reels that actually hold the symbol (so a 3-scatter result doesn't slow the empty reels).
29
+
30
+ Fix: after an anticipation tease the reel now carries its slow speed into the stop and crawls onto its landing frame, instead of snapping back to full spin speed and doing a fast re-spin into position.
31
+
32
+ `spin:stopping` now fires when a reel actually begins slowing (after its stagger offset), so tease SFX/VFX can sync to the real start. The stagger and slowdown reset at the start of every `spin()`.
33
+
34
+ Also: `setStopDelays(null)` / `setDropOrder(null)` now CLEAR a per-reel stop-delay override and restore the default `i * speed.stopDelay` stagger — distinct from passing all-zeros (which lands every reel simultaneously).
35
+
3
36
  ## 1.2.0
4
37
 
5
38
  ### Minor Changes
@@ -1,2 +1,2 @@
1
- let e=require(`pixi.js`);var t=require(`gsap`).gsap;function n(e){t=e}function r(){return t}var i=class{view;_symbolId=``;_isDestroyed=!1;constructor(){this.view=new e.Container}get symbolId(){return this._symbolId}get isDestroyed(){return this._isDestroyed}activate(e){this._symbolId=e,this.view.visible=!0,this.view.alpha=1,this.view.scale.set(1,1),this.view.rotation=0,this.view.filters=null,this.view.zIndex=0,this.onActivate(e)}deactivate(){this.stopAnimation(),this.onDeactivate(),this._symbolId=``,this.view.visible=!1,this.view.alpha=1,this.view.scale.set(1,1),this.view.rotation=0,this.view.filters=null,this.view.zIndex=0}reset(){this.deactivate()}destroy(){this._isDestroyed||=(this.stopAnimation(),this.onDeactivate(),this.onDestroy(),this.view.destroyed||this.view.destroy({children:!0}),!0)}onDestroy(){}async playDestroy(e){let t=this.view,n=t.pivot.x,i=t.pivot.y,a=t.x,o=t.y,s=t.getLocalBounds(),c=s.x+s.width/2,l=s.y+s.height/2;t.pivot.set(c,l),t.x=a+(c-n),t.y=o+(l-i);let u=e?.delay??0,d=e?.signal,f=()=>{t.alpha=0,t.scale.set(0,0)};if(d?.aborted){f(),t.pivot.set(n,i),t.x=a,t.y=o,t.scale.set(1,1),t.alpha=0;return}await new Promise(e=>{let n=r().timeline({onComplete:()=>{d&&d.removeEventListener(`abort`,i),e()},delay:u}).to(t.scale,{x:1.1,y:1.1,duration:.06,ease:`back.out(2.5)`}).to(t.scale,{x:0,y:0,duration:.14,ease:`power3.in`},`<+=0.04`).to(t,{alpha:0,duration:.14,ease:`power3.in`},`<`),i=()=>{n.kill(),f(),e()};d&&d.addEventListener(`abort`,i,{once:!0})}),t.pivot.set(n,i),t.x=a,t.y=o,t.scale.set(1,1)}onReelSpinStart(){}onReelSpinEnd(){}onReelLanded(){}};Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return i}});
2
- //# sourceMappingURL=ReelSymbol-BxoiwQ-r.cjs.map
1
+ let e=require(`pixi.js`);var t=require(`gsap`).gsap;function n(e){t=e}function r(){return t}var i=class{view;_symbolId=``;_isDestroyed=!1;constructor(){this.view=new e.Container}get symbolId(){return this._symbolId}get isDestroyed(){return this._isDestroyed}activate(e){this._symbolId=e,this.view.visible=!0,this.view.alpha=1,this.view.scale.set(1,1),this.view.rotation=0,this.view.filters=null,this.view.zIndex=0,this.onActivate(e)}deactivate(){this.stopAnimation(),this.onDeactivate(),this._symbolId=``,this.view.visible=!1,this.view.alpha=1,this.view.scale.set(1,1),this.view.rotation=0,this.view.filters=null,this.view.zIndex=0}reset(){this.deactivate()}destroy(){this._isDestroyed||=(this.stopAnimation(),this.onDeactivate(),this.onDestroy(),this.view.destroyed||this.view.destroy({children:!0}),!0)}onDestroy(){}async playDestroy(e){let t=this.view,n=t.pivot.x,i=t.pivot.y,a=t.x,o=t.y,s=t.getLocalBounds(),c=s.x+s.width/2,l=s.y+s.height/2;t.pivot.set(c,l),t.x=a+(c-n),t.y=o+(l-i);let u=e?.delay??0,d=e?.signal,f=()=>{t.alpha=0,t.scale.set(0,0)};if(d?.aborted){f(),t.pivot.set(n,i),t.x=a,t.y=o,t.scale.set(1,1),t.alpha=0;return}await new Promise(e=>{let n=r().timeline({onComplete:()=>{d&&d.removeEventListener(`abort`,i),e()},delay:u}).to(t.scale,{x:1.1,y:1.1,duration:.06,ease:`back.out(2.5)`}).to(t.scale,{x:0,y:0,duration:.14,ease:`power3.in`},`<+=0.04`).to(t,{alpha:0,duration:.14,ease:`power3.in`},`<`),i=()=>{n.kill(),f(),e()};d&&d.addEventListener(`abort`,i,{once:!0})}),t.pivot.set(n,i),t.x=a,t.y=o,t.scale.set(1,1)}onReelSpinStart(e){}onReelSpinEnd(){}onReelLanded(){}};Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return i}});
2
+ //# sourceMappingURL=ReelSymbol-BJGylIyA.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReelSymbol-BxoiwQ-r.cjs","names":[],"sources":["../src/utils/gsapRef.ts","../src/symbols/ReelSymbol.ts"],"sourcesContent":["import { gsap as defaultGsap } from 'gsap';\n\n/**\n * The gsap instance every phase, motion tween, and cascade animation in\n * the engine reads from.\n *\n * **Why this indirection exists:** under tools that resolve modules through\n * symlinked workspaces (vite + a locally-linked pixi-reels, pnpm dev\n * setups, esbuild plugin chains), the gsap import inside the lib's\n * compiled `dist/index.js` and the gsap import in the consumer's source\n * can resolve to *different module instances*. each with its own root\n * timeline. The consumer drives one, the lib's tweens live on the other,\n * and reels stall at progress 0.\n *\n * The fix: every internal animation site reads gsap through `getGsap()`\n * instead of importing the `'gsap'` module directly. The builder method\n * `ReelSetBuilder.gsap(myGsap)` rebinds the singleton so the consumer's\n * gsap is the one the engine uses.\n *\n * Defaults to the gsap import resolved at lib-load time, so consumers\n * who don't hit the dual-instance trap don't have to do anything.\n */\nlet currentGsap: typeof defaultGsap = defaultGsap;\n\n/**\n * Replace the gsap instance the engine drives. Call this BEFORE\n * `ReelSetBuilder.build()` (the builder does this for you when you call\n * `.gsap(instance)`).\n *\n * Process-global: there's only one bound instance at a time. If you\n * build several ReelSets with different gsap instances, the last\n * `setGsap` call wins.\n */\nexport function setGsap(g: typeof defaultGsap): void {\n currentGsap = g;\n}\n\n/** The currently-bound gsap instance. */\nexport function getGsap(): typeof defaultGsap {\n return currentGsap;\n}\n","import { Container } from 'pixi.js';\nimport type { Disposable } from '../utils/Disposable.js';\nimport { getGsap } from '../utils/gsapRef.js';\n\n/**\n * One visible cell on a reel. the thing that actually draws.\n *\n * `ReelSymbol` is the abstract base class. Subclass it to pick a rendering\n * technology (`SpriteSymbol`, `AnimatedSpriteSymbol`, `SpineSymbol`, or a\n * custom class of your own). The reel set pools instances aggressively:\n * one instance is reused many times as it scrolls off one identity and on\n * to another, so implementations must never assume \"I was just created\".\n *\n * Required lifecycle hooks:\n *\n * - `onActivate(symbolId)`. the pool just handed me a new identity. Swap\n * texture, restart animations, bring myself out of any \"ended\" pose.\n * - `onDeactivate()`. I am about to be pooled. Pause animations, clear\n * listeners, leave myself in a clean state for the next activation.\n * - `playWin()`. the spotlight is celebrating me. Return a promise that\n * resolves when the one-shot animation is done.\n * - `stopAnimation()`. spotlight is over, return to idle.\n * - `resize(w, h)`. the reel's cell size changed (on every symbol swap).\n * Store the dimensions and reposition internal children. Forgetting\n * this is the single most common \"why do my symbols scatter\" bug.\n *\n * ```\n * create → activate(symbolId) → [playWin / stopAnimation]\n * → deactivate\n * → activate(newId) → ...\n * ```\n *\n * There's no hidden GC. Hold resources? Override `onDestroy()`.\n */\nexport abstract class ReelSymbol implements Disposable {\n /** The PixiJS container that holds this symbol's visual. */\n public readonly view: Container;\n\n private _symbolId: string = '';\n private _isDestroyed = false;\n\n constructor() {\n this.view = new Container();\n }\n\n get symbolId(): string {\n return this._symbolId;\n }\n\n get isDestroyed(): boolean {\n return this._isDestroyed;\n }\n\n /**\n * Activate the symbol with a new identity. Called when the symbol enters\n * the visible reel or is recycled from the pool. Resets container\n * transform / filter state for parity with deactivate().\n */\n activate(symbolId: string): void {\n this._symbolId = symbolId;\n this.view.visible = true;\n this.view.alpha = 1;\n this.view.scale.set(1, 1);\n this.view.rotation = 0;\n this.view.filters = null;\n this.view.zIndex = 0;\n this.onActivate(symbolId);\n }\n\n /**\n * Deactivate the symbol before returning it to the pool. Stops\n * animations, hides the view, and resets container transform / filter\n * state so subclass decorations don't leak across recycles.\n */\n deactivate(): void {\n this.stopAnimation();\n this.onDeactivate();\n this._symbolId = '';\n this.view.visible = false;\n this.view.alpha = 1;\n this.view.scale.set(1, 1);\n this.view.rotation = 0;\n this.view.filters = null;\n this.view.zIndex = 0;\n }\n\n /** Pool reset. aliases deactivate. */\n reset(): void {\n this.deactivate();\n }\n\n destroy(): void {\n if (this._isDestroyed) return;\n this.stopAnimation();\n this.onDeactivate();\n this.onDestroy();\n if (!this.view.destroyed) this.view.destroy({ children: true });\n this._isDestroyed = true;\n }\n\n /** Subclass hook: set up visuals for the given symbolId. */\n protected abstract onActivate(symbolId: string): void;\n\n /** Subclass hook: clean up visuals. */\n protected abstract onDeactivate(): void;\n\n /** Subclass hook: additional cleanup on destroy. */\n protected onDestroy(): void {\n // Override if needed\n }\n\n /** Play the win/highlight animation for this symbol. Resolves when complete. */\n abstract playWin(): Promise<void>;\n\n /** Immediately stop any running animation and return to idle. */\n abstract stopAnimation(): void;\n\n /** Resize the symbol's visual to fit the given dimensions. */\n abstract resize(width: number, height: number): void;\n\n /**\n * Play the cascade-destruction animation for this symbol. Called by\n * consumers (typically via `reelSet.destroySymbols(...)`) to disintegrate\n * a winning cell before the next cascade refill drops fresh symbols in.\n *\n * Default implementation: brief scale-up \"charge\" then implode (scale 0\n * + spin + fade), squishing around the symbol's bounding-box CENTER\n * regardless of the view's anchor. Total ~320 ms. The view is left at\n * `alpha: 0` (destroyed); position / pivot are restored so pool reuse\n * via `_replaceSymbol`'s same-id fast path doesn't inherit a stale\n * pivot offset.\n *\n * Override in subclasses for art-appropriate destruction. e.g. a\n * Spine symbol can play its `disintegration` track here, or a sprite\n * symbol can swap to a shatter atlas. The promise must resolve when\n * the symbol is no longer visible.\n *\n * Default animation: a snappy \"poof\". tiny anticipation pop (~60 ms)\n * then a fast implode to `scale: 0` + `alpha: 0` (~140 ms), centered on\n * the symbol's bounds. ~200 ms total. No rotation. designed to read\n * cleanly under win-cluster pacing without competing with the win\n * presenter.\n *\n * `opts.delay`. seconds to wait before the animation starts. Use to\n * stagger a cluster of winners (e.g. `i * 0.015`).\n * `opts.signal`. abort signal. If aborted (now or mid-animation), the\n * tween is killed and the view is snapped to its destroyed pose\n * (`alpha: 0`, transform restored). The promise resolves normally. abort\n * means \"skip to the end,\" not \"fail\". Subclasses that override this\n * method MUST honor the signal or document why they can't (e.g. a Spine\n * `disintegration` track is uninterruptible).\n */\n async playDestroy(opts?: { delay?: number; signal?: AbortSignal }): Promise<void> {\n const view = this.view;\n // Capture original transform so pool reuse sees a clean state.\n const originalPivotX = view.pivot.x;\n const originalPivotY = view.pivot.y;\n const originalX = view.x;\n const originalY = view.y;\n\n // Pivot to bounds-center so the scale collapses around the visual\n // centre instead of the view's (0,0) corner. and compensate position\n // so the symbol doesn't visibly jump when the pivot moves.\n const bounds = view.getLocalBounds();\n const cx = bounds.x + bounds.width / 2;\n const cy = bounds.y + bounds.height / 2;\n view.pivot.set(cx, cy);\n view.x = originalX + (cx - originalPivotX);\n view.y = originalY + (cy - originalPivotY);\n\n const delay = opts?.delay ?? 0;\n const signal = opts?.signal;\n\n const snapDestroyed = (): void => {\n view.alpha = 0;\n view.scale.set(0, 0);\n };\n\n // Pre-abort: skip the tween entirely and snap to the destroyed pose.\n if (signal?.aborted) {\n snapDestroyed();\n view.pivot.set(originalPivotX, originalPivotY);\n view.x = originalX;\n view.y = originalY;\n view.scale.set(1, 1);\n view.alpha = 0;\n return;\n }\n\n await new Promise<void>((resolve) => {\n const tl = getGsap()\n .timeline({ onComplete: () => {\n if (signal) signal.removeEventListener('abort', onAbort);\n resolve();\n }, delay })\n // Brief anticipation pop. small upscale, ~60 ms, with overshoot\n // so the implode reads as a release. No rotation.\n .to(view.scale, { x: 1.1, y: 1.1, duration: 0.06, ease: 'back.out(2.5)' })\n // Snap implode. scale -> 0 + alpha -> 0 together, snappy ease-in\n // so the symbol collapses into the cell centre and is gone.\n .to(view.scale, { x: 0, y: 0, duration: 0.14, ease: 'power3.in' }, '<+=0.04')\n .to(view, { alpha: 0, duration: 0.14, ease: 'power3.in' }, '<');\n\n const onAbort = (): void => {\n tl.kill();\n snapDestroyed();\n resolve();\n };\n if (signal) signal.addEventListener('abort', onAbort, { once: true });\n });\n\n // Restore transform. alpha stays 0 (the symbol IS destroyed). Scale\n // restored to 1 so pool reuse via `_replaceSymbol`'s same-id fast path\n // doesn't inherit a stale 0× scale; _replaceSymbol also resets scale\n // explicitly but a defensive restore here makes the destroyed cell\n // observably \"ready to be re-skinned\" between calls.\n view.pivot.set(originalPivotX, originalPivotY);\n view.x = originalX;\n view.y = originalY;\n view.scale.set(1, 1);\n }\n\n /**\n * Lifecycle hook: the owning reel has started spinning.\n * Default: no-op. Override (e.g. SpineReelSymbol.autoPlayBlur) to swap to\n * a blur animation automatically.\n */\n onReelSpinStart(): void {}\n\n /**\n * Lifecycle hook: the owning reel is about to stop (just before bounce).\n * Default: no-op.\n */\n onReelSpinEnd(): void {}\n\n /**\n * Lifecycle hook: the owning reel has landed on its final symbols.\n * Default: no-op. Override (e.g. SpineReelSymbol.autoPlayLanding) to fire\n * a landing animation concurrently with the bounce.\n */\n onReelLanded(): void {}\n}\n"],"mappings":"yBAsBA,IAAI,kBAAkC,KAWtC,SAAgB,EAAQ,EAA6B,CACnD,EAAc,EAIhB,SAAgB,GAA8B,CAC5C,OAAO,ECLT,IAAsB,EAAtB,KAAuD,CAErD,KAEA,UAA4B,GAC5B,aAAuB,GAEvB,aAAc,CACZ,KAAK,KAAO,IAAI,EAAA,UAGlB,IAAI,UAAmB,CACrB,OAAO,KAAK,UAGd,IAAI,aAAuB,CACzB,OAAO,KAAK,aAQd,SAAS,EAAwB,CAC/B,KAAK,UAAY,EACjB,KAAK,KAAK,QAAU,GACpB,KAAK,KAAK,MAAQ,EAClB,KAAK,KAAK,MAAM,IAAI,EAAG,EAAE,CACzB,KAAK,KAAK,SAAW,EACrB,KAAK,KAAK,QAAU,KACpB,KAAK,KAAK,OAAS,EACnB,KAAK,WAAW,EAAS,CAQ3B,YAAmB,CACjB,KAAK,eAAe,CACpB,KAAK,cAAc,CACnB,KAAK,UAAY,GACjB,KAAK,KAAK,QAAU,GACpB,KAAK,KAAK,MAAQ,EAClB,KAAK,KAAK,MAAM,IAAI,EAAG,EAAE,CACzB,KAAK,KAAK,SAAW,EACrB,KAAK,KAAK,QAAU,KACpB,KAAK,KAAK,OAAS,EAIrB,OAAc,CACZ,KAAK,YAAY,CAGnB,SAAgB,CACV,AAKJ,KAAK,gBAJL,KAAK,eAAe,CACpB,KAAK,cAAc,CACnB,KAAK,WAAW,CACX,KAAK,KAAK,WAAW,KAAK,KAAK,QAAQ,CAAE,SAAU,GAAM,CAAC,CAC3C,IAUtB,WAA4B,EA6C5B,MAAM,YAAY,EAAgE,CAChF,IAAM,EAAO,KAAK,KAEZ,EAAiB,EAAK,MAAM,EAC5B,EAAiB,EAAK,MAAM,EAC5B,EAAY,EAAK,EACjB,EAAY,EAAK,EAKjB,EAAS,EAAK,gBAAgB,CAC9B,EAAK,EAAO,EAAI,EAAO,MAAQ,EAC/B,EAAK,EAAO,EAAI,EAAO,OAAS,EACtC,EAAK,MAAM,IAAI,EAAI,EAAG,CACtB,EAAK,EAAI,GAAa,EAAK,GAC3B,EAAK,EAAI,GAAa,EAAK,GAE3B,IAAM,EAAQ,GAAM,OAAS,EACvB,EAAS,GAAM,OAEf,MAA4B,CAChC,EAAK,MAAQ,EACb,EAAK,MAAM,IAAI,EAAG,EAAE,EAItB,GAAI,GAAQ,QAAS,CACnB,GAAe,CACf,EAAK,MAAM,IAAI,EAAgB,EAAe,CAC9C,EAAK,EAAI,EACT,EAAK,EAAI,EACT,EAAK,MAAM,IAAI,EAAG,EAAE,CACpB,EAAK,MAAQ,EACb,OAGF,MAAM,IAAI,QAAe,GAAY,CACnC,IAAM,EAAK,GAAS,CACjB,SAAS,CAAE,eAAkB,CACxB,GAAQ,EAAO,oBAAoB,QAAS,EAAQ,CACxD,GAAS,EACR,QAAO,CAAC,CAGV,GAAG,EAAK,MAAO,CAAE,EAAG,IAAK,EAAG,IAAK,SAAU,IAAM,KAAM,gBAAiB,CAAC,CAGzE,GAAG,EAAK,MAAO,CAAE,EAAG,EAAG,EAAG,EAAG,SAAU,IAAM,KAAM,YAAa,CAAE,UAAU,CAC5E,GAAG,EAAM,CAAE,MAAO,EAAG,SAAU,IAAM,KAAM,YAAa,CAAE,IAAI,CAE3D,MAAsB,CAC1B,EAAG,MAAM,CACT,GAAe,CACf,GAAS,EAEP,GAAQ,EAAO,iBAAiB,QAAS,EAAS,CAAE,KAAM,GAAM,CAAC,EACrE,CAOF,EAAK,MAAM,IAAI,EAAgB,EAAe,CAC9C,EAAK,EAAI,EACT,EAAK,EAAI,EACT,EAAK,MAAM,IAAI,EAAG,EAAE,CAQtB,iBAAwB,EAMxB,eAAsB,EAOtB,cAAqB"}
1
+ {"version":3,"file":"ReelSymbol-BJGylIyA.cjs","names":[],"sources":["../src/utils/gsapRef.ts","../src/symbols/ReelSymbol.ts"],"sourcesContent":["import { gsap as defaultGsap } from 'gsap';\n\n/**\n * The gsap instance every phase, motion tween, and cascade animation in\n * the engine reads from.\n *\n * **Why this indirection exists:** under tools that resolve modules through\n * symlinked workspaces (vite + a locally-linked pixi-reels, pnpm dev\n * setups, esbuild plugin chains), the gsap import inside the lib's\n * compiled `dist/index.js` and the gsap import in the consumer's source\n * can resolve to *different module instances*. each with its own root\n * timeline. The consumer drives one, the lib's tweens live on the other,\n * and reels stall at progress 0.\n *\n * The fix: every internal animation site reads gsap through `getGsap()`\n * instead of importing the `'gsap'` module directly. The builder method\n * `ReelSetBuilder.gsap(myGsap)` rebinds the singleton so the consumer's\n * gsap is the one the engine uses.\n *\n * Defaults to the gsap import resolved at lib-load time, so consumers\n * who don't hit the dual-instance trap don't have to do anything.\n */\nlet currentGsap: typeof defaultGsap = defaultGsap;\n\n/**\n * Replace the gsap instance the engine drives. Call this BEFORE\n * `ReelSetBuilder.build()` (the builder does this for you when you call\n * `.gsap(instance)`).\n *\n * Process-global: there's only one bound instance at a time. If you\n * build several ReelSets with different gsap instances, the last\n * `setGsap` call wins.\n */\nexport function setGsap(g: typeof defaultGsap): void {\n currentGsap = g;\n}\n\n/** The currently-bound gsap instance. */\nexport function getGsap(): typeof defaultGsap {\n return currentGsap;\n}\n","import { Container } from 'pixi.js';\nimport type { Disposable } from '../utils/Disposable.js';\nimport { getGsap } from '../utils/gsapRef.js';\n\n/**\n * One visible cell on a reel. the thing that actually draws.\n *\n * `ReelSymbol` is the abstract base class. Subclass it to pick a rendering\n * technology (`SpriteSymbol`, `AnimatedSpriteSymbol`, `SpineSymbol`, or a\n * custom class of your own). The reel set pools instances aggressively:\n * one instance is reused many times as it scrolls off one identity and on\n * to another, so implementations must never assume \"I was just created\".\n *\n * Required lifecycle hooks:\n *\n * - `onActivate(symbolId)`. the pool just handed me a new identity. Swap\n * texture, restart animations, bring myself out of any \"ended\" pose.\n * - `onDeactivate()`. I am about to be pooled. Pause animations, clear\n * listeners, leave myself in a clean state for the next activation.\n * - `playWin()`. the spotlight is celebrating me. Return a promise that\n * resolves when the one-shot animation is done.\n * - `stopAnimation()`. spotlight is over, return to idle.\n * - `resize(w, h)`. the reel's cell size changed (on every symbol swap).\n * Store the dimensions and reposition internal children. Forgetting\n * this is the single most common \"why do my symbols scatter\" bug.\n *\n * ```\n * create → activate(symbolId) → [playWin / stopAnimation]\n * → deactivate\n * → activate(newId) → ...\n * ```\n *\n * There's no hidden GC. Hold resources? Override `onDestroy()`.\n */\nexport abstract class ReelSymbol implements Disposable {\n /** The PixiJS container that holds this symbol's visual. */\n public readonly view: Container;\n\n private _symbolId: string = '';\n private _isDestroyed = false;\n\n constructor() {\n this.view = new Container();\n }\n\n get symbolId(): string {\n return this._symbolId;\n }\n\n get isDestroyed(): boolean {\n return this._isDestroyed;\n }\n\n /**\n * Activate the symbol with a new identity. Called when the symbol enters\n * the visible reel or is recycled from the pool. Resets container\n * transform / filter state for parity with deactivate().\n */\n activate(symbolId: string): void {\n this._symbolId = symbolId;\n this.view.visible = true;\n this.view.alpha = 1;\n this.view.scale.set(1, 1);\n this.view.rotation = 0;\n this.view.filters = null;\n this.view.zIndex = 0;\n this.onActivate(symbolId);\n }\n\n /**\n * Deactivate the symbol before returning it to the pool. Stops\n * animations, hides the view, and resets container transform / filter\n * state so subclass decorations don't leak across recycles.\n */\n deactivate(): void {\n this.stopAnimation();\n this.onDeactivate();\n this._symbolId = '';\n this.view.visible = false;\n this.view.alpha = 1;\n this.view.scale.set(1, 1);\n this.view.rotation = 0;\n this.view.filters = null;\n this.view.zIndex = 0;\n }\n\n /** Pool reset. aliases deactivate. */\n reset(): void {\n this.deactivate();\n }\n\n destroy(): void {\n if (this._isDestroyed) return;\n this.stopAnimation();\n this.onDeactivate();\n this.onDestroy();\n if (!this.view.destroyed) this.view.destroy({ children: true });\n this._isDestroyed = true;\n }\n\n /** Subclass hook: set up visuals for the given symbolId. */\n protected abstract onActivate(symbolId: string): void;\n\n /** Subclass hook: clean up visuals. */\n protected abstract onDeactivate(): void;\n\n /** Subclass hook: additional cleanup on destroy. */\n protected onDestroy(): void {\n // Override if needed\n }\n\n /** Play the win/highlight animation for this symbol. Resolves when complete. */\n abstract playWin(): Promise<void>;\n\n /** Immediately stop any running animation and return to idle. */\n abstract stopAnimation(): void;\n\n /** Resize the symbol's visual to fit the given dimensions. */\n abstract resize(width: number, height: number): void;\n\n /**\n * Play the cascade-destruction animation for this symbol. Called by\n * consumers (typically via `reelSet.destroySymbols(...)`) to disintegrate\n * a winning cell before the next cascade refill drops fresh symbols in.\n *\n * Default implementation: brief scale-up \"charge\" then implode (scale 0\n * + spin + fade), squishing around the symbol's bounding-box CENTER\n * regardless of the view's anchor. Total ~320 ms. The view is left at\n * `alpha: 0` (destroyed); position / pivot are restored so pool reuse\n * via `_replaceSymbol`'s same-id fast path doesn't inherit a stale\n * pivot offset.\n *\n * Override in subclasses for art-appropriate destruction. e.g. a\n * Spine symbol can play its `disintegration` track here, or a sprite\n * symbol can swap to a shatter atlas. The promise must resolve when\n * the symbol is no longer visible.\n *\n * Default animation: a snappy \"poof\". tiny anticipation pop (~60 ms)\n * then a fast implode to `scale: 0` + `alpha: 0` (~140 ms), centered on\n * the symbol's bounds. ~200 ms total. No rotation. designed to read\n * cleanly under win-cluster pacing without competing with the win\n * presenter.\n *\n * `opts.delay`. seconds to wait before the animation starts. Use to\n * stagger a cluster of winners (e.g. `i * 0.015`).\n * `opts.signal`. abort signal. If aborted (now or mid-animation), the\n * tween is killed and the view is snapped to its destroyed pose\n * (`alpha: 0`, transform restored). The promise resolves normally. abort\n * means \"skip to the end,\" not \"fail\". Subclasses that override this\n * method MUST honor the signal or document why they can't (e.g. a Spine\n * `disintegration` track is uninterruptible).\n */\n async playDestroy(opts?: { delay?: number; signal?: AbortSignal }): Promise<void> {\n const view = this.view;\n // Capture original transform so pool reuse sees a clean state.\n const originalPivotX = view.pivot.x;\n const originalPivotY = view.pivot.y;\n const originalX = view.x;\n const originalY = view.y;\n\n // Pivot to bounds-center so the scale collapses around the visual\n // centre instead of the view's (0,0) corner. and compensate position\n // so the symbol doesn't visibly jump when the pivot moves.\n const bounds = view.getLocalBounds();\n const cx = bounds.x + bounds.width / 2;\n const cy = bounds.y + bounds.height / 2;\n view.pivot.set(cx, cy);\n view.x = originalX + (cx - originalPivotX);\n view.y = originalY + (cy - originalPivotY);\n\n const delay = opts?.delay ?? 0;\n const signal = opts?.signal;\n\n const snapDestroyed = (): void => {\n view.alpha = 0;\n view.scale.set(0, 0);\n };\n\n // Pre-abort: skip the tween entirely and snap to the destroyed pose.\n if (signal?.aborted) {\n snapDestroyed();\n view.pivot.set(originalPivotX, originalPivotY);\n view.x = originalX;\n view.y = originalY;\n view.scale.set(1, 1);\n view.alpha = 0;\n return;\n }\n\n await new Promise<void>((resolve) => {\n const tl = getGsap()\n .timeline({ onComplete: () => {\n if (signal) signal.removeEventListener('abort', onAbort);\n resolve();\n }, delay })\n // Brief anticipation pop. small upscale, ~60 ms, with overshoot\n // so the implode reads as a release. No rotation.\n .to(view.scale, { x: 1.1, y: 1.1, duration: 0.06, ease: 'back.out(2.5)' })\n // Snap implode. scale -> 0 + alpha -> 0 together, snappy ease-in\n // so the symbol collapses into the cell centre and is gone.\n .to(view.scale, { x: 0, y: 0, duration: 0.14, ease: 'power3.in' }, '<+=0.04')\n .to(view, { alpha: 0, duration: 0.14, ease: 'power3.in' }, '<');\n\n const onAbort = (): void => {\n tl.kill();\n snapDestroyed();\n resolve();\n };\n if (signal) signal.addEventListener('abort', onAbort, { once: true });\n });\n\n // Restore transform. alpha stays 0 (the symbol IS destroyed). Scale\n // restored to 1 so pool reuse via `_replaceSymbol`'s same-id fast path\n // doesn't inherit a stale 0× scale; _replaceSymbol also resets scale\n // explicitly but a defensive restore here makes the destroyed cell\n // observably \"ready to be re-skinned\" between calls.\n view.pivot.set(originalPivotX, originalPivotY);\n view.x = originalX;\n view.y = originalY;\n view.scale.set(1, 1);\n }\n\n /**\n * Lifecycle hook: the owning reel is spinning.\n * Default: no-op. Override (e.g. SpineReelSymbol.autoPlayBlur,\n * StaticSpinSymbol) to swap to a spin presentation automatically.\n *\n * Fired on every strip symbol (visible AND buffer rows) when the reel\n * enters the spin phase, and again with `joinedMidSpin: true` on each\n * symbol freshly installed while the reel is already spinning (pool\n * recycling wipes symbol state, so a wrapped-in symbol can't know the\n * reel is moving without this). Implementations MUST be idempotent.\n * the same instance can be notified more than once per spin.\n *\n * @param joinedMidSpin true when this symbol was installed into a reel\n * already at speed (skip start-of-spin transitions like blur ramps).\n */\n onReelSpinStart(_joinedMidSpin?: boolean): void {}\n\n /**\n * Lifecycle hook: the owning reel is about to stop (just before bounce).\n * Default: no-op.\n */\n onReelSpinEnd(): void {}\n\n /**\n * Lifecycle hook: the owning reel has landed on its final symbols.\n * Default: no-op. Override (e.g. SpineReelSymbol.autoPlayLanding) to fire\n * a landing animation concurrently with the bounce.\n */\n onReelLanded(): void {}\n}\n"],"mappings":"yBAsBA,IAAI,kBAAkC,KAWtC,SAAgB,EAAQ,EAA6B,CACnD,EAAc,EAIhB,SAAgB,GAA8B,CAC5C,OAAO,ECLT,IAAsB,EAAtB,KAAuD,CAErD,KAEA,UAA4B,GAC5B,aAAuB,GAEvB,aAAc,CACZ,KAAK,KAAO,IAAI,EAAA,UAGlB,IAAI,UAAmB,CACrB,OAAO,KAAK,UAGd,IAAI,aAAuB,CACzB,OAAO,KAAK,aAQd,SAAS,EAAwB,CAC/B,KAAK,UAAY,EACjB,KAAK,KAAK,QAAU,GACpB,KAAK,KAAK,MAAQ,EAClB,KAAK,KAAK,MAAM,IAAI,EAAG,EAAE,CACzB,KAAK,KAAK,SAAW,EACrB,KAAK,KAAK,QAAU,KACpB,KAAK,KAAK,OAAS,EACnB,KAAK,WAAW,EAAS,CAQ3B,YAAmB,CACjB,KAAK,eAAe,CACpB,KAAK,cAAc,CACnB,KAAK,UAAY,GACjB,KAAK,KAAK,QAAU,GACpB,KAAK,KAAK,MAAQ,EAClB,KAAK,KAAK,MAAM,IAAI,EAAG,EAAE,CACzB,KAAK,KAAK,SAAW,EACrB,KAAK,KAAK,QAAU,KACpB,KAAK,KAAK,OAAS,EAIrB,OAAc,CACZ,KAAK,YAAY,CAGnB,SAAgB,CACV,AAKJ,KAAK,gBAJL,KAAK,eAAe,CACpB,KAAK,cAAc,CACnB,KAAK,WAAW,CACX,KAAK,KAAK,WAAW,KAAK,KAAK,QAAQ,CAAE,SAAU,GAAM,CAAC,CAC3C,IAUtB,WAA4B,EA6C5B,MAAM,YAAY,EAAgE,CAChF,IAAM,EAAO,KAAK,KAEZ,EAAiB,EAAK,MAAM,EAC5B,EAAiB,EAAK,MAAM,EAC5B,EAAY,EAAK,EACjB,EAAY,EAAK,EAKjB,EAAS,EAAK,gBAAgB,CAC9B,EAAK,EAAO,EAAI,EAAO,MAAQ,EAC/B,EAAK,EAAO,EAAI,EAAO,OAAS,EACtC,EAAK,MAAM,IAAI,EAAI,EAAG,CACtB,EAAK,EAAI,GAAa,EAAK,GAC3B,EAAK,EAAI,GAAa,EAAK,GAE3B,IAAM,EAAQ,GAAM,OAAS,EACvB,EAAS,GAAM,OAEf,MAA4B,CAChC,EAAK,MAAQ,EACb,EAAK,MAAM,IAAI,EAAG,EAAE,EAItB,GAAI,GAAQ,QAAS,CACnB,GAAe,CACf,EAAK,MAAM,IAAI,EAAgB,EAAe,CAC9C,EAAK,EAAI,EACT,EAAK,EAAI,EACT,EAAK,MAAM,IAAI,EAAG,EAAE,CACpB,EAAK,MAAQ,EACb,OAGF,MAAM,IAAI,QAAe,GAAY,CACnC,IAAM,EAAK,GAAS,CACjB,SAAS,CAAE,eAAkB,CACxB,GAAQ,EAAO,oBAAoB,QAAS,EAAQ,CACxD,GAAS,EACR,QAAO,CAAC,CAGV,GAAG,EAAK,MAAO,CAAE,EAAG,IAAK,EAAG,IAAK,SAAU,IAAM,KAAM,gBAAiB,CAAC,CAGzE,GAAG,EAAK,MAAO,CAAE,EAAG,EAAG,EAAG,EAAG,SAAU,IAAM,KAAM,YAAa,CAAE,UAAU,CAC5E,GAAG,EAAM,CAAE,MAAO,EAAG,SAAU,IAAM,KAAM,YAAa,CAAE,IAAI,CAE3D,MAAsB,CAC1B,EAAG,MAAM,CACT,GAAe,CACf,GAAS,EAEP,GAAQ,EAAO,iBAAiB,QAAS,EAAS,CAAE,KAAM,GAAM,CAAC,EACrE,CAOF,EAAK,MAAM,IAAI,EAAgB,EAAe,CAC9C,EAAK,EAAI,EACT,EAAK,EAAI,EACT,EAAK,MAAM,IAAI,EAAG,EAAE,CAkBtB,gBAAgB,EAAgC,EAMhD,eAAsB,EAOtB,cAAqB"}
@@ -72,11 +72,11 @@ var a = class {
72
72
  d && d.addEventListener("abort", r, { once: !0 });
73
73
  }), t.pivot.set(n, r), t.x = a, t.y = o, t.scale.set(1, 1);
74
74
  }
75
- onReelSpinStart() {}
75
+ onReelSpinStart(e) {}
76
76
  onReelSpinEnd() {}
77
77
  onReelLanded() {}
78
78
  };
79
79
  //#endregion
80
80
  export { i as n, r, a as t };
81
81
 
82
- //# sourceMappingURL=ReelSymbol-C9QQ30ER.js.map
82
+ //# sourceMappingURL=ReelSymbol-DBbmNOIa.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReelSymbol-C9QQ30ER.js","names":[],"sources":["../src/utils/gsapRef.ts","../src/symbols/ReelSymbol.ts"],"sourcesContent":["import { gsap as defaultGsap } from 'gsap';\n\n/**\n * The gsap instance every phase, motion tween, and cascade animation in\n * the engine reads from.\n *\n * **Why this indirection exists:** under tools that resolve modules through\n * symlinked workspaces (vite + a locally-linked pixi-reels, pnpm dev\n * setups, esbuild plugin chains), the gsap import inside the lib's\n * compiled `dist/index.js` and the gsap import in the consumer's source\n * can resolve to *different module instances*. each with its own root\n * timeline. The consumer drives one, the lib's tweens live on the other,\n * and reels stall at progress 0.\n *\n * The fix: every internal animation site reads gsap through `getGsap()`\n * instead of importing the `'gsap'` module directly. The builder method\n * `ReelSetBuilder.gsap(myGsap)` rebinds the singleton so the consumer's\n * gsap is the one the engine uses.\n *\n * Defaults to the gsap import resolved at lib-load time, so consumers\n * who don't hit the dual-instance trap don't have to do anything.\n */\nlet currentGsap: typeof defaultGsap = defaultGsap;\n\n/**\n * Replace the gsap instance the engine drives. Call this BEFORE\n * `ReelSetBuilder.build()` (the builder does this for you when you call\n * `.gsap(instance)`).\n *\n * Process-global: there's only one bound instance at a time. If you\n * build several ReelSets with different gsap instances, the last\n * `setGsap` call wins.\n */\nexport function setGsap(g: typeof defaultGsap): void {\n currentGsap = g;\n}\n\n/** The currently-bound gsap instance. */\nexport function getGsap(): typeof defaultGsap {\n return currentGsap;\n}\n","import { Container } from 'pixi.js';\nimport type { Disposable } from '../utils/Disposable.js';\nimport { getGsap } from '../utils/gsapRef.js';\n\n/**\n * One visible cell on a reel. the thing that actually draws.\n *\n * `ReelSymbol` is the abstract base class. Subclass it to pick a rendering\n * technology (`SpriteSymbol`, `AnimatedSpriteSymbol`, `SpineSymbol`, or a\n * custom class of your own). The reel set pools instances aggressively:\n * one instance is reused many times as it scrolls off one identity and on\n * to another, so implementations must never assume \"I was just created\".\n *\n * Required lifecycle hooks:\n *\n * - `onActivate(symbolId)`. the pool just handed me a new identity. Swap\n * texture, restart animations, bring myself out of any \"ended\" pose.\n * - `onDeactivate()`. I am about to be pooled. Pause animations, clear\n * listeners, leave myself in a clean state for the next activation.\n * - `playWin()`. the spotlight is celebrating me. Return a promise that\n * resolves when the one-shot animation is done.\n * - `stopAnimation()`. spotlight is over, return to idle.\n * - `resize(w, h)`. the reel's cell size changed (on every symbol swap).\n * Store the dimensions and reposition internal children. Forgetting\n * this is the single most common \"why do my symbols scatter\" bug.\n *\n * ```\n * create → activate(symbolId) → [playWin / stopAnimation]\n * → deactivate\n * → activate(newId) → ...\n * ```\n *\n * There's no hidden GC. Hold resources? Override `onDestroy()`.\n */\nexport abstract class ReelSymbol implements Disposable {\n /** The PixiJS container that holds this symbol's visual. */\n public readonly view: Container;\n\n private _symbolId: string = '';\n private _isDestroyed = false;\n\n constructor() {\n this.view = new Container();\n }\n\n get symbolId(): string {\n return this._symbolId;\n }\n\n get isDestroyed(): boolean {\n return this._isDestroyed;\n }\n\n /**\n * Activate the symbol with a new identity. Called when the symbol enters\n * the visible reel or is recycled from the pool. Resets container\n * transform / filter state for parity with deactivate().\n */\n activate(symbolId: string): void {\n this._symbolId = symbolId;\n this.view.visible = true;\n this.view.alpha = 1;\n this.view.scale.set(1, 1);\n this.view.rotation = 0;\n this.view.filters = null;\n this.view.zIndex = 0;\n this.onActivate(symbolId);\n }\n\n /**\n * Deactivate the symbol before returning it to the pool. Stops\n * animations, hides the view, and resets container transform / filter\n * state so subclass decorations don't leak across recycles.\n */\n deactivate(): void {\n this.stopAnimation();\n this.onDeactivate();\n this._symbolId = '';\n this.view.visible = false;\n this.view.alpha = 1;\n this.view.scale.set(1, 1);\n this.view.rotation = 0;\n this.view.filters = null;\n this.view.zIndex = 0;\n }\n\n /** Pool reset. aliases deactivate. */\n reset(): void {\n this.deactivate();\n }\n\n destroy(): void {\n if (this._isDestroyed) return;\n this.stopAnimation();\n this.onDeactivate();\n this.onDestroy();\n if (!this.view.destroyed) this.view.destroy({ children: true });\n this._isDestroyed = true;\n }\n\n /** Subclass hook: set up visuals for the given symbolId. */\n protected abstract onActivate(symbolId: string): void;\n\n /** Subclass hook: clean up visuals. */\n protected abstract onDeactivate(): void;\n\n /** Subclass hook: additional cleanup on destroy. */\n protected onDestroy(): void {\n // Override if needed\n }\n\n /** Play the win/highlight animation for this symbol. Resolves when complete. */\n abstract playWin(): Promise<void>;\n\n /** Immediately stop any running animation and return to idle. */\n abstract stopAnimation(): void;\n\n /** Resize the symbol's visual to fit the given dimensions. */\n abstract resize(width: number, height: number): void;\n\n /**\n * Play the cascade-destruction animation for this symbol. Called by\n * consumers (typically via `reelSet.destroySymbols(...)`) to disintegrate\n * a winning cell before the next cascade refill drops fresh symbols in.\n *\n * Default implementation: brief scale-up \"charge\" then implode (scale 0\n * + spin + fade), squishing around the symbol's bounding-box CENTER\n * regardless of the view's anchor. Total ~320 ms. The view is left at\n * `alpha: 0` (destroyed); position / pivot are restored so pool reuse\n * via `_replaceSymbol`'s same-id fast path doesn't inherit a stale\n * pivot offset.\n *\n * Override in subclasses for art-appropriate destruction. e.g. a\n * Spine symbol can play its `disintegration` track here, or a sprite\n * symbol can swap to a shatter atlas. The promise must resolve when\n * the symbol is no longer visible.\n *\n * Default animation: a snappy \"poof\". tiny anticipation pop (~60 ms)\n * then a fast implode to `scale: 0` + `alpha: 0` (~140 ms), centered on\n * the symbol's bounds. ~200 ms total. No rotation. designed to read\n * cleanly under win-cluster pacing without competing with the win\n * presenter.\n *\n * `opts.delay`. seconds to wait before the animation starts. Use to\n * stagger a cluster of winners (e.g. `i * 0.015`).\n * `opts.signal`. abort signal. If aborted (now or mid-animation), the\n * tween is killed and the view is snapped to its destroyed pose\n * (`alpha: 0`, transform restored). The promise resolves normally. abort\n * means \"skip to the end,\" not \"fail\". Subclasses that override this\n * method MUST honor the signal or document why they can't (e.g. a Spine\n * `disintegration` track is uninterruptible).\n */\n async playDestroy(opts?: { delay?: number; signal?: AbortSignal }): Promise<void> {\n const view = this.view;\n // Capture original transform so pool reuse sees a clean state.\n const originalPivotX = view.pivot.x;\n const originalPivotY = view.pivot.y;\n const originalX = view.x;\n const originalY = view.y;\n\n // Pivot to bounds-center so the scale collapses around the visual\n // centre instead of the view's (0,0) corner. and compensate position\n // so the symbol doesn't visibly jump when the pivot moves.\n const bounds = view.getLocalBounds();\n const cx = bounds.x + bounds.width / 2;\n const cy = bounds.y + bounds.height / 2;\n view.pivot.set(cx, cy);\n view.x = originalX + (cx - originalPivotX);\n view.y = originalY + (cy - originalPivotY);\n\n const delay = opts?.delay ?? 0;\n const signal = opts?.signal;\n\n const snapDestroyed = (): void => {\n view.alpha = 0;\n view.scale.set(0, 0);\n };\n\n // Pre-abort: skip the tween entirely and snap to the destroyed pose.\n if (signal?.aborted) {\n snapDestroyed();\n view.pivot.set(originalPivotX, originalPivotY);\n view.x = originalX;\n view.y = originalY;\n view.scale.set(1, 1);\n view.alpha = 0;\n return;\n }\n\n await new Promise<void>((resolve) => {\n const tl = getGsap()\n .timeline({ onComplete: () => {\n if (signal) signal.removeEventListener('abort', onAbort);\n resolve();\n }, delay })\n // Brief anticipation pop. small upscale, ~60 ms, with overshoot\n // so the implode reads as a release. No rotation.\n .to(view.scale, { x: 1.1, y: 1.1, duration: 0.06, ease: 'back.out(2.5)' })\n // Snap implode. scale -> 0 + alpha -> 0 together, snappy ease-in\n // so the symbol collapses into the cell centre and is gone.\n .to(view.scale, { x: 0, y: 0, duration: 0.14, ease: 'power3.in' }, '<+=0.04')\n .to(view, { alpha: 0, duration: 0.14, ease: 'power3.in' }, '<');\n\n const onAbort = (): void => {\n tl.kill();\n snapDestroyed();\n resolve();\n };\n if (signal) signal.addEventListener('abort', onAbort, { once: true });\n });\n\n // Restore transform. alpha stays 0 (the symbol IS destroyed). Scale\n // restored to 1 so pool reuse via `_replaceSymbol`'s same-id fast path\n // doesn't inherit a stale 0× scale; _replaceSymbol also resets scale\n // explicitly but a defensive restore here makes the destroyed cell\n // observably \"ready to be re-skinned\" between calls.\n view.pivot.set(originalPivotX, originalPivotY);\n view.x = originalX;\n view.y = originalY;\n view.scale.set(1, 1);\n }\n\n /**\n * Lifecycle hook: the owning reel has started spinning.\n * Default: no-op. Override (e.g. SpineReelSymbol.autoPlayBlur) to swap to\n * a blur animation automatically.\n */\n onReelSpinStart(): void {}\n\n /**\n * Lifecycle hook: the owning reel is about to stop (just before bounce).\n * Default: no-op.\n */\n onReelSpinEnd(): void {}\n\n /**\n * Lifecycle hook: the owning reel has landed on its final symbols.\n * Default: no-op. Override (e.g. SpineReelSymbol.autoPlayLanding) to fire\n * a landing animation concurrently with the bounce.\n */\n onReelLanded(): void {}\n}\n"],"mappings":";;;AAsBA,IAAI,IAAkC;AAWtC,SAAgB,EAAQ,GAA6B;AACnD,KAAc;;AAIhB,SAAgB,IAA8B;AAC5C,QAAO;;;;ACLT,IAAsB,IAAtB,MAAuD;CAErD;CAEA,YAA4B;CAC5B,eAAuB;CAEvB,cAAc;AACZ,OAAK,OAAO,IAAI,GAAW;;CAG7B,IAAI,WAAmB;AACrB,SAAO,KAAK;;CAGd,IAAI,cAAuB;AACzB,SAAO,KAAK;;CAQd,SAAS,GAAwB;AAQ/B,EAPA,KAAK,YAAY,GACjB,KAAK,KAAK,UAAU,IACpB,KAAK,KAAK,QAAQ,GAClB,KAAK,KAAK,MAAM,IAAI,GAAG,EAAE,EACzB,KAAK,KAAK,WAAW,GACrB,KAAK,KAAK,UAAU,MACpB,KAAK,KAAK,SAAS,GACnB,KAAK,WAAW,EAAS;;CAQ3B,aAAmB;AASjB,EARA,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,YAAY,IACjB,KAAK,KAAK,UAAU,IACpB,KAAK,KAAK,QAAQ,GAClB,KAAK,KAAK,MAAM,IAAI,GAAG,EAAE,EACzB,KAAK,KAAK,WAAW,GACrB,KAAK,KAAK,UAAU,MACpB,KAAK,KAAK,SAAS;;CAIrB,QAAc;AACZ,OAAK,YAAY;;CAGnB,UAAgB;AACV,EAKJ,KAAK,kBAJL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,WAAW,EACX,KAAK,KAAK,aAAW,KAAK,KAAK,QAAQ,EAAE,UAAU,IAAM,CAAC,EAC3C;;CAUtB,YAA4B;CA6C5B,MAAM,YAAY,GAAgE;EAChF,IAAM,IAAO,KAAK,MAEZ,IAAiB,EAAK,MAAM,GAC5B,IAAiB,EAAK,MAAM,GAC5B,IAAY,EAAK,GACjB,IAAY,EAAK,GAKjB,IAAS,EAAK,gBAAgB,EAC9B,IAAK,EAAO,IAAI,EAAO,QAAQ,GAC/B,IAAK,EAAO,IAAI,EAAO,SAAS;AAGtC,EAFA,EAAK,MAAM,IAAI,GAAI,EAAG,EACtB,EAAK,IAAI,KAAa,IAAK,IAC3B,EAAK,IAAI,KAAa,IAAK;EAE3B,IAAM,IAAQ,GAAM,SAAS,GACvB,IAAS,GAAM,QAEf,UAA4B;AAEhC,GADA,EAAK,QAAQ,GACb,EAAK,MAAM,IAAI,GAAG,EAAE;;AAItB,MAAI,GAAQ,SAAS;AAMnB,GALA,GAAe,EACf,EAAK,MAAM,IAAI,GAAgB,EAAe,EAC9C,EAAK,IAAI,GACT,EAAK,IAAI,GACT,EAAK,MAAM,IAAI,GAAG,EAAE,EACpB,EAAK,QAAQ;AACb;;AAiCF,EA9BA,MAAM,IAAI,SAAe,MAAY;GACnC,IAAM,IAAK,GAAS,CACjB,SAAS;IAAE,kBAAkB;AAE5B,KADI,KAAQ,EAAO,oBAAoB,SAAS,EAAQ,EACxD,GAAS;;IACR;IAAO,CAAC,CAGV,GAAG,EAAK,OAAO;IAAE,GAAG;IAAK,GAAG;IAAK,UAAU;IAAM,MAAM;IAAiB,CAAC,CAGzE,GAAG,EAAK,OAAO;IAAE,GAAG;IAAG,GAAG;IAAG,UAAU;IAAM,MAAM;IAAa,EAAE,UAAU,CAC5E,GAAG,GAAM;IAAE,OAAO;IAAG,UAAU;IAAM,MAAM;IAAa,EAAE,IAAI,EAE3D,UAAsB;AAG1B,IAFA,EAAG,MAAM,EACT,GAAe,EACf,GAAS;;AAEX,GAAI,KAAQ,EAAO,iBAAiB,SAAS,GAAS,EAAE,MAAM,IAAM,CAAC;IACrE,EAOF,EAAK,MAAM,IAAI,GAAgB,EAAe,EAC9C,EAAK,IAAI,GACT,EAAK,IAAI,GACT,EAAK,MAAM,IAAI,GAAG,EAAE;;CAQtB,kBAAwB;CAMxB,gBAAsB;CAOtB,eAAqB"}
1
+ {"version":3,"file":"ReelSymbol-DBbmNOIa.js","names":[],"sources":["../src/utils/gsapRef.ts","../src/symbols/ReelSymbol.ts"],"sourcesContent":["import { gsap as defaultGsap } from 'gsap';\n\n/**\n * The gsap instance every phase, motion tween, and cascade animation in\n * the engine reads from.\n *\n * **Why this indirection exists:** under tools that resolve modules through\n * symlinked workspaces (vite + a locally-linked pixi-reels, pnpm dev\n * setups, esbuild plugin chains), the gsap import inside the lib's\n * compiled `dist/index.js` and the gsap import in the consumer's source\n * can resolve to *different module instances*. each with its own root\n * timeline. The consumer drives one, the lib's tweens live on the other,\n * and reels stall at progress 0.\n *\n * The fix: every internal animation site reads gsap through `getGsap()`\n * instead of importing the `'gsap'` module directly. The builder method\n * `ReelSetBuilder.gsap(myGsap)` rebinds the singleton so the consumer's\n * gsap is the one the engine uses.\n *\n * Defaults to the gsap import resolved at lib-load time, so consumers\n * who don't hit the dual-instance trap don't have to do anything.\n */\nlet currentGsap: typeof defaultGsap = defaultGsap;\n\n/**\n * Replace the gsap instance the engine drives. Call this BEFORE\n * `ReelSetBuilder.build()` (the builder does this for you when you call\n * `.gsap(instance)`).\n *\n * Process-global: there's only one bound instance at a time. If you\n * build several ReelSets with different gsap instances, the last\n * `setGsap` call wins.\n */\nexport function setGsap(g: typeof defaultGsap): void {\n currentGsap = g;\n}\n\n/** The currently-bound gsap instance. */\nexport function getGsap(): typeof defaultGsap {\n return currentGsap;\n}\n","import { Container } from 'pixi.js';\nimport type { Disposable } from '../utils/Disposable.js';\nimport { getGsap } from '../utils/gsapRef.js';\n\n/**\n * One visible cell on a reel. the thing that actually draws.\n *\n * `ReelSymbol` is the abstract base class. Subclass it to pick a rendering\n * technology (`SpriteSymbol`, `AnimatedSpriteSymbol`, `SpineSymbol`, or a\n * custom class of your own). The reel set pools instances aggressively:\n * one instance is reused many times as it scrolls off one identity and on\n * to another, so implementations must never assume \"I was just created\".\n *\n * Required lifecycle hooks:\n *\n * - `onActivate(symbolId)`. the pool just handed me a new identity. Swap\n * texture, restart animations, bring myself out of any \"ended\" pose.\n * - `onDeactivate()`. I am about to be pooled. Pause animations, clear\n * listeners, leave myself in a clean state for the next activation.\n * - `playWin()`. the spotlight is celebrating me. Return a promise that\n * resolves when the one-shot animation is done.\n * - `stopAnimation()`. spotlight is over, return to idle.\n * - `resize(w, h)`. the reel's cell size changed (on every symbol swap).\n * Store the dimensions and reposition internal children. Forgetting\n * this is the single most common \"why do my symbols scatter\" bug.\n *\n * ```\n * create → activate(symbolId) → [playWin / stopAnimation]\n * → deactivate\n * → activate(newId) → ...\n * ```\n *\n * There's no hidden GC. Hold resources? Override `onDestroy()`.\n */\nexport abstract class ReelSymbol implements Disposable {\n /** The PixiJS container that holds this symbol's visual. */\n public readonly view: Container;\n\n private _symbolId: string = '';\n private _isDestroyed = false;\n\n constructor() {\n this.view = new Container();\n }\n\n get symbolId(): string {\n return this._symbolId;\n }\n\n get isDestroyed(): boolean {\n return this._isDestroyed;\n }\n\n /**\n * Activate the symbol with a new identity. Called when the symbol enters\n * the visible reel or is recycled from the pool. Resets container\n * transform / filter state for parity with deactivate().\n */\n activate(symbolId: string): void {\n this._symbolId = symbolId;\n this.view.visible = true;\n this.view.alpha = 1;\n this.view.scale.set(1, 1);\n this.view.rotation = 0;\n this.view.filters = null;\n this.view.zIndex = 0;\n this.onActivate(symbolId);\n }\n\n /**\n * Deactivate the symbol before returning it to the pool. Stops\n * animations, hides the view, and resets container transform / filter\n * state so subclass decorations don't leak across recycles.\n */\n deactivate(): void {\n this.stopAnimation();\n this.onDeactivate();\n this._symbolId = '';\n this.view.visible = false;\n this.view.alpha = 1;\n this.view.scale.set(1, 1);\n this.view.rotation = 0;\n this.view.filters = null;\n this.view.zIndex = 0;\n }\n\n /** Pool reset. aliases deactivate. */\n reset(): void {\n this.deactivate();\n }\n\n destroy(): void {\n if (this._isDestroyed) return;\n this.stopAnimation();\n this.onDeactivate();\n this.onDestroy();\n if (!this.view.destroyed) this.view.destroy({ children: true });\n this._isDestroyed = true;\n }\n\n /** Subclass hook: set up visuals for the given symbolId. */\n protected abstract onActivate(symbolId: string): void;\n\n /** Subclass hook: clean up visuals. */\n protected abstract onDeactivate(): void;\n\n /** Subclass hook: additional cleanup on destroy. */\n protected onDestroy(): void {\n // Override if needed\n }\n\n /** Play the win/highlight animation for this symbol. Resolves when complete. */\n abstract playWin(): Promise<void>;\n\n /** Immediately stop any running animation and return to idle. */\n abstract stopAnimation(): void;\n\n /** Resize the symbol's visual to fit the given dimensions. */\n abstract resize(width: number, height: number): void;\n\n /**\n * Play the cascade-destruction animation for this symbol. Called by\n * consumers (typically via `reelSet.destroySymbols(...)`) to disintegrate\n * a winning cell before the next cascade refill drops fresh symbols in.\n *\n * Default implementation: brief scale-up \"charge\" then implode (scale 0\n * + spin + fade), squishing around the symbol's bounding-box CENTER\n * regardless of the view's anchor. Total ~320 ms. The view is left at\n * `alpha: 0` (destroyed); position / pivot are restored so pool reuse\n * via `_replaceSymbol`'s same-id fast path doesn't inherit a stale\n * pivot offset.\n *\n * Override in subclasses for art-appropriate destruction. e.g. a\n * Spine symbol can play its `disintegration` track here, or a sprite\n * symbol can swap to a shatter atlas. The promise must resolve when\n * the symbol is no longer visible.\n *\n * Default animation: a snappy \"poof\". tiny anticipation pop (~60 ms)\n * then a fast implode to `scale: 0` + `alpha: 0` (~140 ms), centered on\n * the symbol's bounds. ~200 ms total. No rotation. designed to read\n * cleanly under win-cluster pacing without competing with the win\n * presenter.\n *\n * `opts.delay`. seconds to wait before the animation starts. Use to\n * stagger a cluster of winners (e.g. `i * 0.015`).\n * `opts.signal`. abort signal. If aborted (now or mid-animation), the\n * tween is killed and the view is snapped to its destroyed pose\n * (`alpha: 0`, transform restored). The promise resolves normally. abort\n * means \"skip to the end,\" not \"fail\". Subclasses that override this\n * method MUST honor the signal or document why they can't (e.g. a Spine\n * `disintegration` track is uninterruptible).\n */\n async playDestroy(opts?: { delay?: number; signal?: AbortSignal }): Promise<void> {\n const view = this.view;\n // Capture original transform so pool reuse sees a clean state.\n const originalPivotX = view.pivot.x;\n const originalPivotY = view.pivot.y;\n const originalX = view.x;\n const originalY = view.y;\n\n // Pivot to bounds-center so the scale collapses around the visual\n // centre instead of the view's (0,0) corner. and compensate position\n // so the symbol doesn't visibly jump when the pivot moves.\n const bounds = view.getLocalBounds();\n const cx = bounds.x + bounds.width / 2;\n const cy = bounds.y + bounds.height / 2;\n view.pivot.set(cx, cy);\n view.x = originalX + (cx - originalPivotX);\n view.y = originalY + (cy - originalPivotY);\n\n const delay = opts?.delay ?? 0;\n const signal = opts?.signal;\n\n const snapDestroyed = (): void => {\n view.alpha = 0;\n view.scale.set(0, 0);\n };\n\n // Pre-abort: skip the tween entirely and snap to the destroyed pose.\n if (signal?.aborted) {\n snapDestroyed();\n view.pivot.set(originalPivotX, originalPivotY);\n view.x = originalX;\n view.y = originalY;\n view.scale.set(1, 1);\n view.alpha = 0;\n return;\n }\n\n await new Promise<void>((resolve) => {\n const tl = getGsap()\n .timeline({ onComplete: () => {\n if (signal) signal.removeEventListener('abort', onAbort);\n resolve();\n }, delay })\n // Brief anticipation pop. small upscale, ~60 ms, with overshoot\n // so the implode reads as a release. No rotation.\n .to(view.scale, { x: 1.1, y: 1.1, duration: 0.06, ease: 'back.out(2.5)' })\n // Snap implode. scale -> 0 + alpha -> 0 together, snappy ease-in\n // so the symbol collapses into the cell centre and is gone.\n .to(view.scale, { x: 0, y: 0, duration: 0.14, ease: 'power3.in' }, '<+=0.04')\n .to(view, { alpha: 0, duration: 0.14, ease: 'power3.in' }, '<');\n\n const onAbort = (): void => {\n tl.kill();\n snapDestroyed();\n resolve();\n };\n if (signal) signal.addEventListener('abort', onAbort, { once: true });\n });\n\n // Restore transform. alpha stays 0 (the symbol IS destroyed). Scale\n // restored to 1 so pool reuse via `_replaceSymbol`'s same-id fast path\n // doesn't inherit a stale 0× scale; _replaceSymbol also resets scale\n // explicitly but a defensive restore here makes the destroyed cell\n // observably \"ready to be re-skinned\" between calls.\n view.pivot.set(originalPivotX, originalPivotY);\n view.x = originalX;\n view.y = originalY;\n view.scale.set(1, 1);\n }\n\n /**\n * Lifecycle hook: the owning reel is spinning.\n * Default: no-op. Override (e.g. SpineReelSymbol.autoPlayBlur,\n * StaticSpinSymbol) to swap to a spin presentation automatically.\n *\n * Fired on every strip symbol (visible AND buffer rows) when the reel\n * enters the spin phase, and again with `joinedMidSpin: true` on each\n * symbol freshly installed while the reel is already spinning (pool\n * recycling wipes symbol state, so a wrapped-in symbol can't know the\n * reel is moving without this). Implementations MUST be idempotent.\n * the same instance can be notified more than once per spin.\n *\n * @param joinedMidSpin true when this symbol was installed into a reel\n * already at speed (skip start-of-spin transitions like blur ramps).\n */\n onReelSpinStart(_joinedMidSpin?: boolean): void {}\n\n /**\n * Lifecycle hook: the owning reel is about to stop (just before bounce).\n * Default: no-op.\n */\n onReelSpinEnd(): void {}\n\n /**\n * Lifecycle hook: the owning reel has landed on its final symbols.\n * Default: no-op. Override (e.g. SpineReelSymbol.autoPlayLanding) to fire\n * a landing animation concurrently with the bounce.\n */\n onReelLanded(): void {}\n}\n"],"mappings":";;;AAsBA,IAAI,IAAkC;AAWtC,SAAgB,EAAQ,GAA6B;AACnD,KAAc;;AAIhB,SAAgB,IAA8B;AAC5C,QAAO;;;;ACLT,IAAsB,IAAtB,MAAuD;CAErD;CAEA,YAA4B;CAC5B,eAAuB;CAEvB,cAAc;AACZ,OAAK,OAAO,IAAI,GAAW;;CAG7B,IAAI,WAAmB;AACrB,SAAO,KAAK;;CAGd,IAAI,cAAuB;AACzB,SAAO,KAAK;;CAQd,SAAS,GAAwB;AAQ/B,EAPA,KAAK,YAAY,GACjB,KAAK,KAAK,UAAU,IACpB,KAAK,KAAK,QAAQ,GAClB,KAAK,KAAK,MAAM,IAAI,GAAG,EAAE,EACzB,KAAK,KAAK,WAAW,GACrB,KAAK,KAAK,UAAU,MACpB,KAAK,KAAK,SAAS,GACnB,KAAK,WAAW,EAAS;;CAQ3B,aAAmB;AASjB,EARA,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,YAAY,IACjB,KAAK,KAAK,UAAU,IACpB,KAAK,KAAK,QAAQ,GAClB,KAAK,KAAK,MAAM,IAAI,GAAG,EAAE,EACzB,KAAK,KAAK,WAAW,GACrB,KAAK,KAAK,UAAU,MACpB,KAAK,KAAK,SAAS;;CAIrB,QAAc;AACZ,OAAK,YAAY;;CAGnB,UAAgB;AACV,EAKJ,KAAK,kBAJL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,WAAW,EACX,KAAK,KAAK,aAAW,KAAK,KAAK,QAAQ,EAAE,UAAU,IAAM,CAAC,EAC3C;;CAUtB,YAA4B;CA6C5B,MAAM,YAAY,GAAgE;EAChF,IAAM,IAAO,KAAK,MAEZ,IAAiB,EAAK,MAAM,GAC5B,IAAiB,EAAK,MAAM,GAC5B,IAAY,EAAK,GACjB,IAAY,EAAK,GAKjB,IAAS,EAAK,gBAAgB,EAC9B,IAAK,EAAO,IAAI,EAAO,QAAQ,GAC/B,IAAK,EAAO,IAAI,EAAO,SAAS;AAGtC,EAFA,EAAK,MAAM,IAAI,GAAI,EAAG,EACtB,EAAK,IAAI,KAAa,IAAK,IAC3B,EAAK,IAAI,KAAa,IAAK;EAE3B,IAAM,IAAQ,GAAM,SAAS,GACvB,IAAS,GAAM,QAEf,UAA4B;AAEhC,GADA,EAAK,QAAQ,GACb,EAAK,MAAM,IAAI,GAAG,EAAE;;AAItB,MAAI,GAAQ,SAAS;AAMnB,GALA,GAAe,EACf,EAAK,MAAM,IAAI,GAAgB,EAAe,EAC9C,EAAK,IAAI,GACT,EAAK,IAAI,GACT,EAAK,MAAM,IAAI,GAAG,EAAE,EACpB,EAAK,QAAQ;AACb;;AAiCF,EA9BA,MAAM,IAAI,SAAe,MAAY;GACnC,IAAM,IAAK,GAAS,CACjB,SAAS;IAAE,kBAAkB;AAE5B,KADI,KAAQ,EAAO,oBAAoB,SAAS,EAAQ,EACxD,GAAS;;IACR;IAAO,CAAC,CAGV,GAAG,EAAK,OAAO;IAAE,GAAG;IAAK,GAAG;IAAK,UAAU;IAAM,MAAM;IAAiB,CAAC,CAGzE,GAAG,EAAK,OAAO;IAAE,GAAG;IAAG,GAAG;IAAG,UAAU;IAAM,MAAM;IAAa,EAAE,UAAU,CAC5E,GAAG,GAAM;IAAE,OAAO;IAAG,UAAU;IAAM,MAAM;IAAa,EAAE,IAAI,EAE3D,UAAsB;AAG1B,IAFA,EAAG,MAAM,EACT,GAAe,EACf,GAAS;;AAEX,GAAI,KAAQ,EAAO,iBAAiB,SAAS,GAAS,EAAE,MAAM,IAAM,CAAC;IACrE,EAOF,EAAK,MAAM,IAAI,GAAgB,EAAe,EAC9C,EAAK,IAAI,GACT,EAAK,IAAI,GACT,EAAK,MAAM,IAAI,GAAG,EAAE;;CAkBtB,gBAAgB,GAAgC;CAMhD,gBAAsB;CAOtB,eAAqB"}
@@ -1,2 +1,2 @@
1
- const e=require(`./ReelSymbol-BxoiwQ-r.cjs`);var t=null,n=(async()=>{try{t=(await import(`@esotericsoftware/spine-pixi-v8`)).Spine}catch{}})();function r(){return n}var i=class extends e.t{_spine=null;_skeletonDataMap;_idleAnimation;_winAnimation;_defaultSkin;_winResolve=null;_currentSkeletonKey=``;_strict;constructor(e){if(super(),!t)throw Error(`SpineSymbol could not use @esotericsoftware/spine-pixi-v8. Either it is not installed (npm install @esotericsoftware/spine-pixi-v8), or its dynamic import has not resolved yet on a cold start — await whenSpineReady() before constructing SpineSymbols.`);this._skeletonDataMap=e.skeletonDataMap,this._idleAnimation=e.idleAnimation??`idle`,this._winAnimation=e.winAnimation??`win`,this._defaultSkin=e.defaultSkin??`default`,this._strict=e.strict??!1}onActivate(e){let n=this._skeletonDataMap[e];if(n){if(this._currentSkeletonKey!==e&&(this._spine&&(this.view.removeChild(this._spine),this._spine.destroy()),this._spine=new t({skeletonData:n}),this.view.addChild(this._spine),this._currentSkeletonKey=e),this._spine.skeleton.data.findSkin(this._defaultSkin)&&(this._spine.skeleton.setSkinByName(this._defaultSkin),this._spine.skeleton.setSlotsToSetupPose()),this._spine.skeleton.data.findAnimation(this._idleAnimation))this._spine.state.setAnimation(0,this._idleAnimation,!0);else if(this._strict)throw Error(`SpineSymbol(strict): idle animation '${this._idleAnimation}' not found on skeleton '${e}'.`)}}onDeactivate(){if(this._spine&&(this._spine.state.clearListeners(),this._spine.state.clearTracks()),this._winResolve){let e=this._winResolve;this._winResolve=null,e()}}async playWin(){if(this._spine){if(!this._spine.skeleton.data.findAnimation(this._winAnimation)){if(this._strict)throw Error(`SpineSymbol(strict): win animation '${this._winAnimation}' not found on skeleton '${this._currentSkeletonKey}'.`);return}return new Promise(e=>{this._winResolve=e;let t=this._spine.state.setAnimation(0,this._winAnimation,!1);this._spine.state.addListener({complete:n=>{n===t&&(this._spine.state.clearListeners(),this._spine.skeleton.data.findAnimation(this._idleAnimation)&&this._spine.state.setAnimation(0,this._idleAnimation,!0),this._winResolve=null,e())}})})}}stopAnimation(){this._spine&&(this._spine.state.clearListeners(),this._spine.skeleton.data.findAnimation(this._idleAnimation)&&this._spine.state.setAnimation(0,this._idleAnimation,!0),this._winResolve&&=(this._winResolve(),null))}resize(e,t){if(!this._spine)return;let n=this._spine.getBounds();n.width>0&&n.height>0&&this._spine.scale.set(e/n.width,t/n.height)}onDestroy(){if(this._spine&&=(this._spine.state.clearListeners(),this._spine.destroy(),null),this._winResolve){let e=this._winResolve;this._winResolve=null,e()}}};Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return i}});
2
- //# sourceMappingURL=SpineSymbol-DAqBuFX2.cjs.map
1
+ const e=require(`./ReelSymbol-BJGylIyA.cjs`);var t=null,n=(async()=>{try{t=(await import(`@esotericsoftware/spine-pixi-v8`)).Spine}catch{}})();function r(){return n}var i=class extends e.t{_spine=null;_skeletonDataMap;_idleAnimation;_winAnimation;_defaultSkin;_winResolve=null;_currentSkeletonKey=``;_strict;constructor(e){if(super(),!t)throw Error(`SpineSymbol could not use @esotericsoftware/spine-pixi-v8. Either it is not installed (npm install @esotericsoftware/spine-pixi-v8), or its dynamic import has not resolved yet on a cold start — await whenSpineReady() before constructing SpineSymbols.`);this._skeletonDataMap=e.skeletonDataMap,this._idleAnimation=e.idleAnimation??`idle`,this._winAnimation=e.winAnimation??`win`,this._defaultSkin=e.defaultSkin??`default`,this._strict=e.strict??!1}onActivate(e){let n=this._skeletonDataMap[e];if(n){if(this._currentSkeletonKey!==e&&(this._spine&&(this.view.removeChild(this._spine),this._spine.destroy()),this._spine=new t({skeletonData:n}),this.view.addChild(this._spine),this._currentSkeletonKey=e),this._spine.skeleton.data.findSkin(this._defaultSkin)&&(this._spine.skeleton.setSkinByName(this._defaultSkin),this._spine.skeleton.setSlotsToSetupPose()),this._spine.skeleton.data.findAnimation(this._idleAnimation))this._spine.state.setAnimation(0,this._idleAnimation,!0);else if(this._strict)throw Error(`SpineSymbol(strict): idle animation '${this._idleAnimation}' not found on skeleton '${e}'.`)}}onDeactivate(){if(this._spine&&(this._spine.state.clearListeners(),this._spine.state.clearTracks()),this._winResolve){let e=this._winResolve;this._winResolve=null,e()}}async playWin(){if(this._spine){if(!this._spine.skeleton.data.findAnimation(this._winAnimation)){if(this._strict)throw Error(`SpineSymbol(strict): win animation '${this._winAnimation}' not found on skeleton '${this._currentSkeletonKey}'.`);return}return new Promise(e=>{this._winResolve=e;let t=this._spine.state.setAnimation(0,this._winAnimation,!1);this._spine.state.addListener({complete:n=>{n===t&&(this._spine.state.clearListeners(),this._spine.skeleton.data.findAnimation(this._idleAnimation)&&this._spine.state.setAnimation(0,this._idleAnimation,!0),this._winResolve=null,e())}})})}}stopAnimation(){this._spine&&(this._spine.state.clearListeners(),this._spine.skeleton.data.findAnimation(this._idleAnimation)&&this._spine.state.setAnimation(0,this._idleAnimation,!0),this._winResolve&&=(this._winResolve(),null))}resize(e,t){if(!this._spine)return;let n=this._spine.getBounds();n.width>0&&n.height>0&&this._spine.scale.set(e/n.width,t/n.height)}onDestroy(){if(this._spine&&=(this._spine.state.clearListeners(),this._spine.destroy(),null),this._winResolve){let e=this._winResolve;this._winResolve=null,e()}}};Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return i}});
2
+ //# sourceMappingURL=SpineSymbol-C6V3FScO.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"SpineSymbol-DAqBuFX2.cjs","names":[],"sources":["../src/symbols/SpineSymbol.ts"],"sourcesContent":["import { ReelSymbol } from './ReelSymbol.js';\n\n// Spine types imported dynamically. this is an optional peer dependency\nlet SpineClass: any = null;\n\n// Kick off the optional import at module init and keep the promise so callers\n// can wait for it. Without this, constructing a SpineSymbol on a cold start\n// (before the dynamic import resolves) throws the \"not installed\" error even\n// when Spine IS installed — it just hadn't finished loading yet.\nconst spineReady: Promise<void> = (async () => {\n try {\n const spineModule = await import('@esotericsoftware/spine-pixi-v8');\n SpineClass = spineModule.Spine;\n } catch {\n // Spine not available. SpineSymbol will throw on construction.\n }\n})();\n\n/**\n * Resolves once the optional `@esotericsoftware/spine-pixi-v8` import has\n * settled (whether or not it was installed). Await this before constructing\n * `SpineSymbol`s if you build the reel set immediately on app start, so a cold\n * load can't throw the misleading \"not installed\" error.\n */\nexport function whenSpineReady(): Promise<void> {\n return spineReady;\n}\n\nexport interface SpineSymbolOptions {\n /** Map of symbolId → SkeletonData. */\n skeletonDataMap: Record<string, any>;\n /** Default animation name to play in idle. Default: 'idle'. */\n idleAnimation?: string;\n /** Animation name to play on win. Default: 'win'. */\n winAnimation?: string;\n /** Default skin name. Default: 'default'. */\n defaultSkin?: string;\n /**\n * Fail loud on unmapped animations. When `true`, activating or winning with\n * a configured animation name that the skeleton doesn't define throws instead\n * of silently showing nothing (catches typos like `ide` vs `idle`). Default\n * `false` to preserve the lenient behavior. See ADR 011.\n */\n strict?: boolean;\n}\n\n/**\n * Symbol implementation using Spine 2D skeletal animation.\n *\n * Requires `@esotericsoftware/spine-pixi-v8` as an optional peer dependency.\n * If Spine is not installed, constructing a SpineSymbol will throw.\n */\nexport class SpineSymbol extends ReelSymbol {\n private _spine: any = null;\n private _skeletonDataMap: Record<string, any>;\n private _idleAnimation: string;\n private _winAnimation: string;\n private _defaultSkin: string;\n private _winResolve: (() => void) | null = null;\n private _currentSkeletonKey: string = '';\n private _strict: boolean;\n\n constructor(options: SpineSymbolOptions) {\n super();\n if (!SpineClass) {\n throw new Error(\n 'SpineSymbol could not use @esotericsoftware/spine-pixi-v8. Either it is ' +\n 'not installed (npm install @esotericsoftware/spine-pixi-v8), or its ' +\n 'dynamic import has not resolved yet on a cold start — await ' +\n 'whenSpineReady() before constructing SpineSymbols.',\n );\n }\n this._skeletonDataMap = options.skeletonDataMap;\n this._idleAnimation = options.idleAnimation ?? 'idle';\n this._winAnimation = options.winAnimation ?? 'win';\n this._defaultSkin = options.defaultSkin ?? 'default';\n this._strict = options.strict ?? false;\n }\n\n protected onActivate(symbolId: string): void {\n const skeletonData = this._skeletonDataMap[symbolId];\n if (!skeletonData) return;\n\n // Reuse existing spine if same skeleton data\n if (this._currentSkeletonKey !== symbolId) {\n if (this._spine) {\n this.view.removeChild(this._spine);\n this._spine.destroy();\n }\n this._spine = new SpineClass({ skeletonData });\n this.view.addChild(this._spine);\n this._currentSkeletonKey = symbolId;\n }\n\n // Set to idle\n if (this._spine.skeleton.data.findSkin(this._defaultSkin)) {\n this._spine.skeleton.setSkinByName(this._defaultSkin);\n this._spine.skeleton.setSlotsToSetupPose();\n }\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n } else if (this._strict) {\n throw new Error(\n `SpineSymbol(strict): idle animation '${this._idleAnimation}' not found ` +\n `on skeleton '${symbolId}'.`,\n );\n }\n }\n\n protected onDeactivate(): void {\n if (this._spine) {\n this._spine.state.clearListeners();\n this._spine.state.clearTracks();\n }\n // Settle any pending playWin so awaiters don't hang when the symbol is\n // recycled mid-animation. Mirrors the same fix in SpineReelSymbol.\n if (this._winResolve) {\n const r = this._winResolve;\n this._winResolve = null;\n r();\n }\n }\n\n async playWin(): Promise<void> {\n if (!this._spine) return;\n if (!this._spine.skeleton.data.findAnimation(this._winAnimation)) {\n if (this._strict) {\n throw new Error(\n `SpineSymbol(strict): win animation '${this._winAnimation}' not found ` +\n `on skeleton '${this._currentSkeletonKey}'.`,\n );\n }\n return;\n }\n\n return new Promise<void>((resolve) => {\n this._winResolve = resolve;\n const entry = this._spine.state.setAnimation(0, this._winAnimation, false);\n this._spine.state.addListener({\n complete: (trackEntry: any) => {\n if (trackEntry === entry) {\n this._spine.state.clearListeners();\n // Return to idle\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n }\n this._winResolve = null;\n resolve();\n }\n },\n });\n });\n }\n\n stopAnimation(): void {\n if (!this._spine) return;\n this._spine.state.clearListeners();\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n }\n if (this._winResolve) {\n this._winResolve();\n this._winResolve = null;\n }\n }\n\n resize(width: number, height: number): void {\n if (!this._spine) return;\n const bounds = this._spine.getBounds();\n if (bounds.width > 0 && bounds.height > 0) {\n this._spine.scale.set(\n width / bounds.width,\n height / bounds.height,\n );\n }\n }\n\n protected override onDestroy(): void {\n if (this._spine) {\n this._spine.state.clearListeners();\n this._spine.destroy();\n this._spine = null;\n }\n if (this._winResolve) {\n const r = this._winResolve;\n this._winResolve = null;\n r();\n }\n }\n}\n"],"mappings":"6CAGA,IAAI,EAAkB,KAMhB,GAA6B,SAAY,CAC7C,GAAI,CAEF,GADoB,MAAM,OAAO,oCACR,WACnB,MAGN,CAQJ,SAAgB,GAAgC,CAC9C,OAAO,EA2BT,IAAa,EAAb,cAAiC,EAAA,CAAW,CAC1C,OAAsB,KACtB,iBACA,eACA,cACA,aACA,YAA2C,KAC3C,oBAAsC,GACtC,QAEA,YAAY,EAA6B,CAEvC,GADA,OAAO,CACH,CAAC,EACH,MAAU,MACR,6PAID,CAEH,KAAK,iBAAmB,EAAQ,gBAChC,KAAK,eAAiB,EAAQ,eAAiB,OAC/C,KAAK,cAAgB,EAAQ,cAAgB,MAC7C,KAAK,aAAe,EAAQ,aAAe,UAC3C,KAAK,QAAU,EAAQ,QAAU,GAGnC,WAAqB,EAAwB,CAC3C,IAAM,EAAe,KAAK,iBAAiB,GACtC,KAkBL,IAfI,KAAK,sBAAwB,IAC3B,KAAK,SACP,KAAK,KAAK,YAAY,KAAK,OAAO,CAClC,KAAK,OAAO,SAAS,EAEvB,KAAK,OAAS,IAAI,EAAW,CAAE,eAAc,CAAC,CAC9C,KAAK,KAAK,SAAS,KAAK,OAAO,CAC/B,KAAK,oBAAsB,GAIzB,KAAK,OAAO,SAAS,KAAK,SAAS,KAAK,aAAa,GACvD,KAAK,OAAO,SAAS,cAAc,KAAK,aAAa,CACrD,KAAK,OAAO,SAAS,qBAAqB,EAExC,KAAK,OAAO,SAAS,KAAK,cAAc,KAAK,eAAe,CAC9D,KAAK,OAAO,MAAM,aAAa,EAAG,KAAK,eAAgB,GAAK,SACnD,KAAK,QACd,MAAU,MACR,wCAAwC,KAAK,eAAe,2BAC5C,EAAS,IAC1B,EAIL,cAA+B,CAO7B,GANI,KAAK,SACP,KAAK,OAAO,MAAM,gBAAgB,CAClC,KAAK,OAAO,MAAM,aAAa,EAI7B,KAAK,YAAa,CACpB,IAAM,EAAI,KAAK,YACf,KAAK,YAAc,KACnB,GAAG,EAIP,MAAM,SAAyB,CACxB,QAAK,OACV,IAAI,CAAC,KAAK,OAAO,SAAS,KAAK,cAAc,KAAK,cAAc,CAAE,CAChE,GAAI,KAAK,QACP,MAAU,MACR,uCAAuC,KAAK,cAAc,2BAC1C,KAAK,oBAAoB,IAC1C,CAEH,OAGF,OAAO,IAAI,QAAe,GAAY,CACpC,KAAK,YAAc,EACnB,IAAM,EAAQ,KAAK,OAAO,MAAM,aAAa,EAAG,KAAK,cAAe,GAAM,CAC1E,KAAK,OAAO,MAAM,YAAY,CAC5B,SAAW,GAAoB,CACzB,IAAe,IACjB,KAAK,OAAO,MAAM,gBAAgB,CAE9B,KAAK,OAAO,SAAS,KAAK,cAAc,KAAK,eAAe,EAC9D,KAAK,OAAO,MAAM,aAAa,EAAG,KAAK,eAAgB,GAAK,CAE9D,KAAK,YAAc,KACnB,GAAS,GAGd,CAAC,EACF,EAGJ,eAAsB,CACf,KAAK,SACV,KAAK,OAAO,MAAM,gBAAgB,CAC9B,KAAK,OAAO,SAAS,KAAK,cAAc,KAAK,eAAe,EAC9D,KAAK,OAAO,MAAM,aAAa,EAAG,KAAK,eAAgB,GAAK,CAE9D,AAEE,KAAK,eADL,KAAK,aAAa,CACC,OAIvB,OAAO,EAAe,EAAsB,CAC1C,GAAI,CAAC,KAAK,OAAQ,OAClB,IAAM,EAAS,KAAK,OAAO,WAAW,CAClC,EAAO,MAAQ,GAAK,EAAO,OAAS,GACtC,KAAK,OAAO,MAAM,IAChB,EAAQ,EAAO,MACf,EAAS,EAAO,OACjB,CAIL,WAAqC,CAMnC,GALA,AAGE,KAAK,UAFL,KAAK,OAAO,MAAM,gBAAgB,CAClC,KAAK,OAAO,SAAS,CACP,MAEZ,KAAK,YAAa,CACpB,IAAM,EAAI,KAAK,YACf,KAAK,YAAc,KACnB,GAAG"}
1
+ {"version":3,"file":"SpineSymbol-C6V3FScO.cjs","names":[],"sources":["../src/symbols/SpineSymbol.ts"],"sourcesContent":["import { ReelSymbol } from './ReelSymbol.js';\n\n// Spine types imported dynamically. this is an optional peer dependency\nlet SpineClass: any = null;\n\n// Kick off the optional import at module init and keep the promise so callers\n// can wait for it. Without this, constructing a SpineSymbol on a cold start\n// (before the dynamic import resolves) throws the \"not installed\" error even\n// when Spine IS installed — it just hadn't finished loading yet.\nconst spineReady: Promise<void> = (async () => {\n try {\n const spineModule = await import('@esotericsoftware/spine-pixi-v8');\n SpineClass = spineModule.Spine;\n } catch {\n // Spine not available. SpineSymbol will throw on construction.\n }\n})();\n\n/**\n * Resolves once the optional `@esotericsoftware/spine-pixi-v8` import has\n * settled (whether or not it was installed). Await this before constructing\n * `SpineSymbol`s if you build the reel set immediately on app start, so a cold\n * load can't throw the misleading \"not installed\" error.\n */\nexport function whenSpineReady(): Promise<void> {\n return spineReady;\n}\n\nexport interface SpineSymbolOptions {\n /** Map of symbolId → SkeletonData. */\n skeletonDataMap: Record<string, any>;\n /** Default animation name to play in idle. Default: 'idle'. */\n idleAnimation?: string;\n /** Animation name to play on win. Default: 'win'. */\n winAnimation?: string;\n /** Default skin name. Default: 'default'. */\n defaultSkin?: string;\n /**\n * Fail loud on unmapped animations. When `true`, activating or winning with\n * a configured animation name that the skeleton doesn't define throws instead\n * of silently showing nothing (catches typos like `ide` vs `idle`). Default\n * `false` to preserve the lenient behavior. See ADR 011.\n */\n strict?: boolean;\n}\n\n/**\n * Symbol implementation using Spine 2D skeletal animation.\n *\n * Requires `@esotericsoftware/spine-pixi-v8` as an optional peer dependency.\n * If Spine is not installed, constructing a SpineSymbol will throw.\n */\nexport class SpineSymbol extends ReelSymbol {\n private _spine: any = null;\n private _skeletonDataMap: Record<string, any>;\n private _idleAnimation: string;\n private _winAnimation: string;\n private _defaultSkin: string;\n private _winResolve: (() => void) | null = null;\n private _currentSkeletonKey: string = '';\n private _strict: boolean;\n\n constructor(options: SpineSymbolOptions) {\n super();\n if (!SpineClass) {\n throw new Error(\n 'SpineSymbol could not use @esotericsoftware/spine-pixi-v8. Either it is ' +\n 'not installed (npm install @esotericsoftware/spine-pixi-v8), or its ' +\n 'dynamic import has not resolved yet on a cold start — await ' +\n 'whenSpineReady() before constructing SpineSymbols.',\n );\n }\n this._skeletonDataMap = options.skeletonDataMap;\n this._idleAnimation = options.idleAnimation ?? 'idle';\n this._winAnimation = options.winAnimation ?? 'win';\n this._defaultSkin = options.defaultSkin ?? 'default';\n this._strict = options.strict ?? false;\n }\n\n protected onActivate(symbolId: string): void {\n const skeletonData = this._skeletonDataMap[symbolId];\n if (!skeletonData) return;\n\n // Reuse existing spine if same skeleton data\n if (this._currentSkeletonKey !== symbolId) {\n if (this._spine) {\n this.view.removeChild(this._spine);\n this._spine.destroy();\n }\n this._spine = new SpineClass({ skeletonData });\n this.view.addChild(this._spine);\n this._currentSkeletonKey = symbolId;\n }\n\n // Set to idle\n if (this._spine.skeleton.data.findSkin(this._defaultSkin)) {\n this._spine.skeleton.setSkinByName(this._defaultSkin);\n this._spine.skeleton.setSlotsToSetupPose();\n }\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n } else if (this._strict) {\n throw new Error(\n `SpineSymbol(strict): idle animation '${this._idleAnimation}' not found ` +\n `on skeleton '${symbolId}'.`,\n );\n }\n }\n\n protected onDeactivate(): void {\n if (this._spine) {\n this._spine.state.clearListeners();\n this._spine.state.clearTracks();\n }\n // Settle any pending playWin so awaiters don't hang when the symbol is\n // recycled mid-animation. Mirrors the same fix in SpineReelSymbol.\n if (this._winResolve) {\n const r = this._winResolve;\n this._winResolve = null;\n r();\n }\n }\n\n async playWin(): Promise<void> {\n if (!this._spine) return;\n if (!this._spine.skeleton.data.findAnimation(this._winAnimation)) {\n if (this._strict) {\n throw new Error(\n `SpineSymbol(strict): win animation '${this._winAnimation}' not found ` +\n `on skeleton '${this._currentSkeletonKey}'.`,\n );\n }\n return;\n }\n\n return new Promise<void>((resolve) => {\n this._winResolve = resolve;\n const entry = this._spine.state.setAnimation(0, this._winAnimation, false);\n this._spine.state.addListener({\n complete: (trackEntry: any) => {\n if (trackEntry === entry) {\n this._spine.state.clearListeners();\n // Return to idle\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n }\n this._winResolve = null;\n resolve();\n }\n },\n });\n });\n }\n\n stopAnimation(): void {\n if (!this._spine) return;\n this._spine.state.clearListeners();\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n }\n if (this._winResolve) {\n this._winResolve();\n this._winResolve = null;\n }\n }\n\n resize(width: number, height: number): void {\n if (!this._spine) return;\n const bounds = this._spine.getBounds();\n if (bounds.width > 0 && bounds.height > 0) {\n this._spine.scale.set(\n width / bounds.width,\n height / bounds.height,\n );\n }\n }\n\n protected override onDestroy(): void {\n if (this._spine) {\n this._spine.state.clearListeners();\n this._spine.destroy();\n this._spine = null;\n }\n if (this._winResolve) {\n const r = this._winResolve;\n this._winResolve = null;\n r();\n }\n }\n}\n"],"mappings":"6CAGA,IAAI,EAAkB,KAMhB,GAA6B,SAAY,CAC7C,GAAI,CAEF,GADoB,MAAM,OAAO,oCACR,WACnB,MAGN,CAQJ,SAAgB,GAAgC,CAC9C,OAAO,EA2BT,IAAa,EAAb,cAAiC,EAAA,CAAW,CAC1C,OAAsB,KACtB,iBACA,eACA,cACA,aACA,YAA2C,KAC3C,oBAAsC,GACtC,QAEA,YAAY,EAA6B,CAEvC,GADA,OAAO,CACH,CAAC,EACH,MAAU,MACR,6PAID,CAEH,KAAK,iBAAmB,EAAQ,gBAChC,KAAK,eAAiB,EAAQ,eAAiB,OAC/C,KAAK,cAAgB,EAAQ,cAAgB,MAC7C,KAAK,aAAe,EAAQ,aAAe,UAC3C,KAAK,QAAU,EAAQ,QAAU,GAGnC,WAAqB,EAAwB,CAC3C,IAAM,EAAe,KAAK,iBAAiB,GACtC,KAkBL,IAfI,KAAK,sBAAwB,IAC3B,KAAK,SACP,KAAK,KAAK,YAAY,KAAK,OAAO,CAClC,KAAK,OAAO,SAAS,EAEvB,KAAK,OAAS,IAAI,EAAW,CAAE,eAAc,CAAC,CAC9C,KAAK,KAAK,SAAS,KAAK,OAAO,CAC/B,KAAK,oBAAsB,GAIzB,KAAK,OAAO,SAAS,KAAK,SAAS,KAAK,aAAa,GACvD,KAAK,OAAO,SAAS,cAAc,KAAK,aAAa,CACrD,KAAK,OAAO,SAAS,qBAAqB,EAExC,KAAK,OAAO,SAAS,KAAK,cAAc,KAAK,eAAe,CAC9D,KAAK,OAAO,MAAM,aAAa,EAAG,KAAK,eAAgB,GAAK,SACnD,KAAK,QACd,MAAU,MACR,wCAAwC,KAAK,eAAe,2BAC5C,EAAS,IAC1B,EAIL,cAA+B,CAO7B,GANI,KAAK,SACP,KAAK,OAAO,MAAM,gBAAgB,CAClC,KAAK,OAAO,MAAM,aAAa,EAI7B,KAAK,YAAa,CACpB,IAAM,EAAI,KAAK,YACf,KAAK,YAAc,KACnB,GAAG,EAIP,MAAM,SAAyB,CACxB,QAAK,OACV,IAAI,CAAC,KAAK,OAAO,SAAS,KAAK,cAAc,KAAK,cAAc,CAAE,CAChE,GAAI,KAAK,QACP,MAAU,MACR,uCAAuC,KAAK,cAAc,2BAC1C,KAAK,oBAAoB,IAC1C,CAEH,OAGF,OAAO,IAAI,QAAe,GAAY,CACpC,KAAK,YAAc,EACnB,IAAM,EAAQ,KAAK,OAAO,MAAM,aAAa,EAAG,KAAK,cAAe,GAAM,CAC1E,KAAK,OAAO,MAAM,YAAY,CAC5B,SAAW,GAAoB,CACzB,IAAe,IACjB,KAAK,OAAO,MAAM,gBAAgB,CAE9B,KAAK,OAAO,SAAS,KAAK,cAAc,KAAK,eAAe,EAC9D,KAAK,OAAO,MAAM,aAAa,EAAG,KAAK,eAAgB,GAAK,CAE9D,KAAK,YAAc,KACnB,GAAS,GAGd,CAAC,EACF,EAGJ,eAAsB,CACf,KAAK,SACV,KAAK,OAAO,MAAM,gBAAgB,CAC9B,KAAK,OAAO,SAAS,KAAK,cAAc,KAAK,eAAe,EAC9D,KAAK,OAAO,MAAM,aAAa,EAAG,KAAK,eAAgB,GAAK,CAE9D,AAEE,KAAK,eADL,KAAK,aAAa,CACC,OAIvB,OAAO,EAAe,EAAsB,CAC1C,GAAI,CAAC,KAAK,OAAQ,OAClB,IAAM,EAAS,KAAK,OAAO,WAAW,CAClC,EAAO,MAAQ,GAAK,EAAO,OAAS,GACtC,KAAK,OAAO,MAAM,IAChB,EAAQ,EAAO,MACf,EAAS,EAAO,OACjB,CAIL,WAAqC,CAMnC,GALA,AAGE,KAAK,UAFL,KAAK,OAAO,MAAM,gBAAgB,CAClC,KAAK,OAAO,SAAS,CACP,MAEZ,KAAK,YAAa,CACpB,IAAM,EAAI,KAAK,YACf,KAAK,YAAc,KACnB,GAAG"}
@@ -1,4 +1,4 @@
1
- import { t as e } from "./ReelSymbol-C9QQ30ER.js";
1
+ import { t as e } from "./ReelSymbol-DBbmNOIa.js";
2
2
  //#region src/symbols/SpineSymbol.ts
3
3
  var t = null, n = (async () => {
4
4
  try {
@@ -67,4 +67,4 @@ var i = class extends e {
67
67
  //#endregion
68
68
  export { r as n, i as t };
69
69
 
70
- //# sourceMappingURL=SpineSymbol-C_pacfc4.js.map
70
+ //# sourceMappingURL=SpineSymbol-w7zxDNo_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SpineSymbol-C_pacfc4.js","names":[],"sources":["../src/symbols/SpineSymbol.ts"],"sourcesContent":["import { ReelSymbol } from './ReelSymbol.js';\n\n// Spine types imported dynamically. this is an optional peer dependency\nlet SpineClass: any = null;\n\n// Kick off the optional import at module init and keep the promise so callers\n// can wait for it. Without this, constructing a SpineSymbol on a cold start\n// (before the dynamic import resolves) throws the \"not installed\" error even\n// when Spine IS installed — it just hadn't finished loading yet.\nconst spineReady: Promise<void> = (async () => {\n try {\n const spineModule = await import('@esotericsoftware/spine-pixi-v8');\n SpineClass = spineModule.Spine;\n } catch {\n // Spine not available. SpineSymbol will throw on construction.\n }\n})();\n\n/**\n * Resolves once the optional `@esotericsoftware/spine-pixi-v8` import has\n * settled (whether or not it was installed). Await this before constructing\n * `SpineSymbol`s if you build the reel set immediately on app start, so a cold\n * load can't throw the misleading \"not installed\" error.\n */\nexport function whenSpineReady(): Promise<void> {\n return spineReady;\n}\n\nexport interface SpineSymbolOptions {\n /** Map of symbolId → SkeletonData. */\n skeletonDataMap: Record<string, any>;\n /** Default animation name to play in idle. Default: 'idle'. */\n idleAnimation?: string;\n /** Animation name to play on win. Default: 'win'. */\n winAnimation?: string;\n /** Default skin name. Default: 'default'. */\n defaultSkin?: string;\n /**\n * Fail loud on unmapped animations. When `true`, activating or winning with\n * a configured animation name that the skeleton doesn't define throws instead\n * of silently showing nothing (catches typos like `ide` vs `idle`). Default\n * `false` to preserve the lenient behavior. See ADR 011.\n */\n strict?: boolean;\n}\n\n/**\n * Symbol implementation using Spine 2D skeletal animation.\n *\n * Requires `@esotericsoftware/spine-pixi-v8` as an optional peer dependency.\n * If Spine is not installed, constructing a SpineSymbol will throw.\n */\nexport class SpineSymbol extends ReelSymbol {\n private _spine: any = null;\n private _skeletonDataMap: Record<string, any>;\n private _idleAnimation: string;\n private _winAnimation: string;\n private _defaultSkin: string;\n private _winResolve: (() => void) | null = null;\n private _currentSkeletonKey: string = '';\n private _strict: boolean;\n\n constructor(options: SpineSymbolOptions) {\n super();\n if (!SpineClass) {\n throw new Error(\n 'SpineSymbol could not use @esotericsoftware/spine-pixi-v8. Either it is ' +\n 'not installed (npm install @esotericsoftware/spine-pixi-v8), or its ' +\n 'dynamic import has not resolved yet on a cold start — await ' +\n 'whenSpineReady() before constructing SpineSymbols.',\n );\n }\n this._skeletonDataMap = options.skeletonDataMap;\n this._idleAnimation = options.idleAnimation ?? 'idle';\n this._winAnimation = options.winAnimation ?? 'win';\n this._defaultSkin = options.defaultSkin ?? 'default';\n this._strict = options.strict ?? false;\n }\n\n protected onActivate(symbolId: string): void {\n const skeletonData = this._skeletonDataMap[symbolId];\n if (!skeletonData) return;\n\n // Reuse existing spine if same skeleton data\n if (this._currentSkeletonKey !== symbolId) {\n if (this._spine) {\n this.view.removeChild(this._spine);\n this._spine.destroy();\n }\n this._spine = new SpineClass({ skeletonData });\n this.view.addChild(this._spine);\n this._currentSkeletonKey = symbolId;\n }\n\n // Set to idle\n if (this._spine.skeleton.data.findSkin(this._defaultSkin)) {\n this._spine.skeleton.setSkinByName(this._defaultSkin);\n this._spine.skeleton.setSlotsToSetupPose();\n }\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n } else if (this._strict) {\n throw new Error(\n `SpineSymbol(strict): idle animation '${this._idleAnimation}' not found ` +\n `on skeleton '${symbolId}'.`,\n );\n }\n }\n\n protected onDeactivate(): void {\n if (this._spine) {\n this._spine.state.clearListeners();\n this._spine.state.clearTracks();\n }\n // Settle any pending playWin so awaiters don't hang when the symbol is\n // recycled mid-animation. Mirrors the same fix in SpineReelSymbol.\n if (this._winResolve) {\n const r = this._winResolve;\n this._winResolve = null;\n r();\n }\n }\n\n async playWin(): Promise<void> {\n if (!this._spine) return;\n if (!this._spine.skeleton.data.findAnimation(this._winAnimation)) {\n if (this._strict) {\n throw new Error(\n `SpineSymbol(strict): win animation '${this._winAnimation}' not found ` +\n `on skeleton '${this._currentSkeletonKey}'.`,\n );\n }\n return;\n }\n\n return new Promise<void>((resolve) => {\n this._winResolve = resolve;\n const entry = this._spine.state.setAnimation(0, this._winAnimation, false);\n this._spine.state.addListener({\n complete: (trackEntry: any) => {\n if (trackEntry === entry) {\n this._spine.state.clearListeners();\n // Return to idle\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n }\n this._winResolve = null;\n resolve();\n }\n },\n });\n });\n }\n\n stopAnimation(): void {\n if (!this._spine) return;\n this._spine.state.clearListeners();\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n }\n if (this._winResolve) {\n this._winResolve();\n this._winResolve = null;\n }\n }\n\n resize(width: number, height: number): void {\n if (!this._spine) return;\n const bounds = this._spine.getBounds();\n if (bounds.width > 0 && bounds.height > 0) {\n this._spine.scale.set(\n width / bounds.width,\n height / bounds.height,\n );\n }\n }\n\n protected override onDestroy(): void {\n if (this._spine) {\n this._spine.state.clearListeners();\n this._spine.destroy();\n this._spine = null;\n }\n if (this._winResolve) {\n const r = this._winResolve;\n this._winResolve = null;\n r();\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SpineSymbol-w7zxDNo_.js","names":[],"sources":["../src/symbols/SpineSymbol.ts"],"sourcesContent":["import { ReelSymbol } from './ReelSymbol.js';\n\n// Spine types imported dynamically. this is an optional peer dependency\nlet SpineClass: any = null;\n\n// Kick off the optional import at module init and keep the promise so callers\n// can wait for it. Without this, constructing a SpineSymbol on a cold start\n// (before the dynamic import resolves) throws the \"not installed\" error even\n// when Spine IS installed — it just hadn't finished loading yet.\nconst spineReady: Promise<void> = (async () => {\n try {\n const spineModule = await import('@esotericsoftware/spine-pixi-v8');\n SpineClass = spineModule.Spine;\n } catch {\n // Spine not available. SpineSymbol will throw on construction.\n }\n})();\n\n/**\n * Resolves once the optional `@esotericsoftware/spine-pixi-v8` import has\n * settled (whether or not it was installed). Await this before constructing\n * `SpineSymbol`s if you build the reel set immediately on app start, so a cold\n * load can't throw the misleading \"not installed\" error.\n */\nexport function whenSpineReady(): Promise<void> {\n return spineReady;\n}\n\nexport interface SpineSymbolOptions {\n /** Map of symbolId → SkeletonData. */\n skeletonDataMap: Record<string, any>;\n /** Default animation name to play in idle. Default: 'idle'. */\n idleAnimation?: string;\n /** Animation name to play on win. Default: 'win'. */\n winAnimation?: string;\n /** Default skin name. Default: 'default'. */\n defaultSkin?: string;\n /**\n * Fail loud on unmapped animations. When `true`, activating or winning with\n * a configured animation name that the skeleton doesn't define throws instead\n * of silently showing nothing (catches typos like `ide` vs `idle`). Default\n * `false` to preserve the lenient behavior. See ADR 011.\n */\n strict?: boolean;\n}\n\n/**\n * Symbol implementation using Spine 2D skeletal animation.\n *\n * Requires `@esotericsoftware/spine-pixi-v8` as an optional peer dependency.\n * If Spine is not installed, constructing a SpineSymbol will throw.\n */\nexport class SpineSymbol extends ReelSymbol {\n private _spine: any = null;\n private _skeletonDataMap: Record<string, any>;\n private _idleAnimation: string;\n private _winAnimation: string;\n private _defaultSkin: string;\n private _winResolve: (() => void) | null = null;\n private _currentSkeletonKey: string = '';\n private _strict: boolean;\n\n constructor(options: SpineSymbolOptions) {\n super();\n if (!SpineClass) {\n throw new Error(\n 'SpineSymbol could not use @esotericsoftware/spine-pixi-v8. Either it is ' +\n 'not installed (npm install @esotericsoftware/spine-pixi-v8), or its ' +\n 'dynamic import has not resolved yet on a cold start — await ' +\n 'whenSpineReady() before constructing SpineSymbols.',\n );\n }\n this._skeletonDataMap = options.skeletonDataMap;\n this._idleAnimation = options.idleAnimation ?? 'idle';\n this._winAnimation = options.winAnimation ?? 'win';\n this._defaultSkin = options.defaultSkin ?? 'default';\n this._strict = options.strict ?? false;\n }\n\n protected onActivate(symbolId: string): void {\n const skeletonData = this._skeletonDataMap[symbolId];\n if (!skeletonData) return;\n\n // Reuse existing spine if same skeleton data\n if (this._currentSkeletonKey !== symbolId) {\n if (this._spine) {\n this.view.removeChild(this._spine);\n this._spine.destroy();\n }\n this._spine = new SpineClass({ skeletonData });\n this.view.addChild(this._spine);\n this._currentSkeletonKey = symbolId;\n }\n\n // Set to idle\n if (this._spine.skeleton.data.findSkin(this._defaultSkin)) {\n this._spine.skeleton.setSkinByName(this._defaultSkin);\n this._spine.skeleton.setSlotsToSetupPose();\n }\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n } else if (this._strict) {\n throw new Error(\n `SpineSymbol(strict): idle animation '${this._idleAnimation}' not found ` +\n `on skeleton '${symbolId}'.`,\n );\n }\n }\n\n protected onDeactivate(): void {\n if (this._spine) {\n this._spine.state.clearListeners();\n this._spine.state.clearTracks();\n }\n // Settle any pending playWin so awaiters don't hang when the symbol is\n // recycled mid-animation. Mirrors the same fix in SpineReelSymbol.\n if (this._winResolve) {\n const r = this._winResolve;\n this._winResolve = null;\n r();\n }\n }\n\n async playWin(): Promise<void> {\n if (!this._spine) return;\n if (!this._spine.skeleton.data.findAnimation(this._winAnimation)) {\n if (this._strict) {\n throw new Error(\n `SpineSymbol(strict): win animation '${this._winAnimation}' not found ` +\n `on skeleton '${this._currentSkeletonKey}'.`,\n );\n }\n return;\n }\n\n return new Promise<void>((resolve) => {\n this._winResolve = resolve;\n const entry = this._spine.state.setAnimation(0, this._winAnimation, false);\n this._spine.state.addListener({\n complete: (trackEntry: any) => {\n if (trackEntry === entry) {\n this._spine.state.clearListeners();\n // Return to idle\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n }\n this._winResolve = null;\n resolve();\n }\n },\n });\n });\n }\n\n stopAnimation(): void {\n if (!this._spine) return;\n this._spine.state.clearListeners();\n if (this._spine.skeleton.data.findAnimation(this._idleAnimation)) {\n this._spine.state.setAnimation(0, this._idleAnimation, true);\n }\n if (this._winResolve) {\n this._winResolve();\n this._winResolve = null;\n }\n }\n\n resize(width: number, height: number): void {\n if (!this._spine) return;\n const bounds = this._spine.getBounds();\n if (bounds.width > 0 && bounds.height > 0) {\n this._spine.scale.set(\n width / bounds.width,\n height / bounds.height,\n );\n }\n }\n\n protected override onDestroy(): void {\n if (this._spine) {\n this._spine.state.clearListeners();\n this._spine.destroy();\n this._spine = null;\n }\n if (this._winResolve) {\n const r = this._winResolve;\n this._winResolve = null;\n r();\n }\n }\n}\n"],"mappings":"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"}
@@ -61,6 +61,47 @@ export interface SpinOptions {
61
61
  */
62
62
  timeoutMs?: number;
63
63
  }
64
+ /**
65
+ * How the START of each anticipation reel's slow-down is spaced (offsets are
66
+ * by tease-order, i.e. position within the anticipation set, not raw reel
67
+ * index):
68
+ * - `0` (default) — every anticipation reel begins slowing together.
69
+ * - `number` — reel at tease-order `k` starts `k * value` ms after the first.
70
+ * - `number[]` — explicit per-tease-order offset in ms.
71
+ * - `'sequential'` — each reel waits until the previous anticipation reel
72
+ * has fully landed before it starts.
73
+ */
74
+ export type AnticipationStagger = number | number[] | 'sequential';
75
+ /**
76
+ * Progressive slow-down across the tease sequence. Values interpolate linearly
77
+ * across tease-order (first anticipation reel → last), so each successive reel
78
+ * decelerates deeper and/or holds longer than the one before it. This is what
79
+ * turns a flat "everyone drops to 30%" tease into an escalating "each reel
80
+ * crawls slower than the last" build-up.
81
+ */
82
+ export interface AnticipationSlowdown {
83
+ /** Speed multiplier (fraction of spin speed) the FIRST tease reel slows to. Default `0.3`. */
84
+ from?: number;
85
+ /** Speed multiplier the LAST tease reel slows to. Default = `from` (flat). Lower = slower/more tension. */
86
+ to?: number;
87
+ /** Hold-duration multiplier for the FIRST tease reel (scales `anticipationDelay`). Default `1`. */
88
+ holdFrom?: number;
89
+ /** Hold-duration multiplier for the LAST tease reel. Default = `holdFrom`. `>1` = later reels hold longer. */
90
+ holdTo?: number;
91
+ }
92
+ /** Full anticipation configuration. The object form of `setAnticipation`'s second argument. */
93
+ export interface AnticipationOptions {
94
+ stagger?: AnticipationStagger;
95
+ slowdown?: AnticipationSlowdown;
96
+ /**
97
+ * Explicit tease hold in ms, overriding the active speed profile's
98
+ * `anticipationDelay`. Pass a positive value to keep the tease playing in
99
+ * Turbo / SuperTurbo (whose profiles set `anticipationDelay: 0`, which would
100
+ * otherwise skip anticipation entirely). When `slowdown.holdFrom/holdTo` are
101
+ * also set, this is the base they scale.
102
+ */
103
+ duration?: number;
104
+ }
64
105
  /** Timing and animation profile for a speed mode. */
65
106
  export interface SpeedProfile {
66
107
  readonly name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
@@ -170,6 +170,13 @@ export declare class Reel implements Disposable {
170
170
  private _symbolGapX;
171
171
  private _isDestroyed;
172
172
  private _isStopping;
173
+ /**
174
+ * True between `notifySpinStart()` and `notifySpinEnd()`. While set,
175
+ * `_replaceSymbol` fires `onReelSpinStart(true)` on each freshly
176
+ * installed symbol so it can join the spin presentation (pool recycling
177
+ * wipes per-instance state, so the symbol can't know on its own).
178
+ */
179
+ private _spinPresentationActive;
173
180
  private _isNudging;
174
181
  /**
175
182
  * Symbol-id queue consulted by `_onSymbolWrapped` during a nudge. Each
@@ -1 +1 @@
1
- {"version":3,"file":"Reel.d.ts","sourceRoot":"","sources":["../../src/core/Reel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Reel.d.ts","sourceRoot":"","sources":["../../src/core/Reel.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { Container } from 'pixi.js';
2
2
  import { Disposable } from '../utils/Disposable.js';
3
- import { ReelSetInternalConfig, CellBounds, SpinOptions } from '../config/types.js';
3
+ import { ReelSetInternalConfig, CellBounds, SpinOptions, AnticipationStagger, AnticipationOptions } from '../config/types.js';
4
4
  import { EventEmitter } from '../events/EventEmitter.js';
5
5
  import { ReelSetEvents, SpinResult, RunCascadeResult as RunCascadeResultBase } from '../events/ReelEvents.js';
6
6
  import { Reel, NudgeOptions } from './Reel.js';
@@ -588,8 +588,53 @@ export declare class ReelSet extends Container implements Disposable {
588
588
  * Requires `.tumble(...)` on the builder (same as `refill()`).
589
589
  */
590
590
  runCascade(opts: RunCascadeOptions): Promise<RunCascadeResult>;
591
- /** Set which reels should show anticipation before stopping. */
592
- setAnticipation(reelIndices: number[]): void;
591
+ /**
592
+ * Set which reels should show anticipation before stopping, and how their
593
+ * slow-downs are spaced via `stagger`:
594
+ *
595
+ * - `0` (default): every anticipation reel begins slowing at once (the
596
+ * historical parallel behaviour).
597
+ * - `number`: reel at tease-order `k` starts its slow-down `k * stagger`
598
+ * ms after the first, so the tease sweeps across the reels.
599
+ * - `number[]`: explicit per-tease-order offset in ms.
600
+ * - `'sequential'`: each reel waits until the previous anticipation reel
601
+ * has fully landed before it starts. maximal one-at-a-time tension.
602
+ *
603
+ * Offsets are by tease-order (position in `reelIndices`), not raw reel
604
+ * index. Reset at the start of every `spin()`.
605
+ *
606
+ * Pass a `{ stagger, slowdown, duration }` object to shape the tease more:
607
+ * - `slowdown` interpolates across the tease sequence so each successive
608
+ * reel slows to a lower speed (`from` → `to`) and/or holds longer
609
+ * (`holdFrom` → `holdTo`) — the escalating "each reel crawls slower than
610
+ * the last" build-up. See {@link AnticipationSlowdown}.
611
+ * - `duration` (ms) overrides the profile's `anticipationDelay`, so the
612
+ * tease plays even in Turbo / SuperTurbo (whose profiles use
613
+ * `anticipationDelay: 0` and would otherwise skip anticipation).
614
+ *
615
+ * Listen to `anticipation:reel` ({ reelIndex, order, total }) to drive
616
+ * per-step tension SFX / a pitch ramp, and `anticipation:reelEnd` to stop it.
617
+ *
618
+ * @example
619
+ * // Classic "2 scatters showing" sweep across the last three reels:
620
+ * reelSet.setResult(grid);
621
+ * reelSet.setAnticipation([2, 3, 4], 450); // 450ms apart
622
+ * reelSet.setAnticipation([2, 3, 4], 'sequential'); // strict one-by-one
623
+ *
624
+ * // Keep the tease alive in turbo (profile anticipationDelay is 0):
625
+ * reelSet.setAnticipation([2, 3, 4], { duration: 350, stagger: 200 });
626
+ *
627
+ * // Escalating slow-down: later reels crawl slower and hold longer.
628
+ * reelSet.setAnticipation([2, 3, 4], {
629
+ * stagger: 400,
630
+ * slowdown: { from: 0.45, to: 0.12, holdTo: 2 },
631
+ * });
632
+ *
633
+ * // Drive which reels tease straight from the result grid:
634
+ * const reels = anticipationForScatters(grid, { symbol: 'SCAT', trigger: 2 });
635
+ * reelSet.setAnticipation(reels, { stagger: 'sequential', slowdown: { from: 0.4, to: 0.1 } });
636
+ */
637
+ setAnticipation(reelIndices: number[], options?: AnticipationStagger | AnticipationOptions): void;
593
638
  /**
594
639
  * Override the per-reel stop delay (in ms). Pass one value per reel.
595
640
  *
@@ -600,11 +645,18 @@ export declare class ReelSet extends Container implements Disposable {
600
645
  * want every internal `refill()` to honor it. If your rounds use
601
646
  * different patterns, re-set explicitly per round.
602
647
  *
648
+ * Pass `null` to CLEAR the override and restore the default
649
+ * `i * speed.stopDelay` stagger. this is distinct from `[]` / all-zeros
650
+ * (which lands every reel simultaneously). Use it to undo a one-off
651
+ * per-round pattern without hard-coding the default back in.
652
+ *
603
653
  * @example
604
654
  * // Stagger the last two reels more than the default for dramatic effect:
605
655
  * reelSet.setStopDelays([0, 140, 280, 600, 1100]);
656
+ * // ...later, go back to the profile default:
657
+ * reelSet.setStopDelays(null);
606
658
  */
607
- setStopDelays(delays: number[]): void;
659
+ setStopDelays(delays: number[] | null): void;
608
660
  /**
609
661
  * Round-aware spin skip. The button-press entry point. The first press
610
662
  * in a round slams the current drop AND applies a round-scoped side
@@ -796,8 +848,9 @@ export declare class ReelSet extends Container implements Disposable {
796
848
  * reelSet.setDropOrder('rtl'); // right-to-left
797
849
  * reelSet.setDropOrder('all'); // all columns simultaneously
798
850
  * reelSet.setDropOrder([0, 0, 200, 200, 400]); // custom per-reel delays
851
+ * reelSet.setDropOrder(null); // clear the override, restore the default
799
852
  */
800
- setDropOrder(order: 'ltr' | 'rtl' | 'all' | number[], stepMs?: number): void;
853
+ setDropOrder(order: 'ltr' | 'rtl' | 'all' | number[] | null, stepMs?: number): void;
801
854
  get isSpinning(): boolean;
802
855
  /** Whether this slot was built with `.multiways(...)`. */
803
856
  get isMultiWaysSlot(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"ReelSet.d.ts","sourceRoot":"","sources":["../../src/core/ReelSet.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ReelSet.d.ts","sourceRoot":"","sources":["../../src/core/ReelSet.ts"],"names":[],"mappings":"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"}