{"version":3,"sources":["../src/SlotMachine.tsx","../src/useSlotMachine.ts"],"sourcesContent":["import React, {\n  forwardRef,\n  useCallback,\n  useEffect,\n  useImperativeHandle,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport type { SlotMachineHandle, SlotMachineProps } from './types';\nimport { useSlotMachineEngine } from './useSlotMachine';\n\n// ---- Default icons (inline SVG) ----\nconst ShuffleIcon = () => (\n  <svg\n    width=\"1em\"\n    height=\"1em\"\n    viewBox=\"0 0 24 24\"\n    fill=\"none\"\n    stroke=\"currentColor\"\n    strokeWidth={2}\n    strokeLinecap=\"round\"\n    strokeLinejoin=\"round\"\n    style={{ marginRight: 6, verticalAlign: 'middle' }}\n  >\n    <polyline points=\"1 4 1 10 7 10\" />\n    <polyline points=\"23 20 23 14 17 14\" />\n    <path d=\"M20.49 9A9 9 0 0 0 5.64 5.64L1 10M23 14L18.36 18.36A9 9 0 0 1 3.51 15\" />\n  </svg>\n);\n\nconst StopIcon = () => (\n  <svg\n    width=\"1em\"\n    height=\"1em\"\n    viewBox=\"0 0 24 24\"\n    fill=\"currentColor\"\n    stroke=\"none\"\n    style={{ marginRight: 6, verticalAlign: 'middle' }}\n  >\n    <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\" />\n  </svg>\n);\n\n// ---- CSS blur class map ----\nconst blurClass: Record<string, string> = {\n  fast: 'rsm-tile--blur-fast',\n  normal: 'rsm-tile--blur-medium',\n  slow: 'rsm-tile--blur-slow',\n  turtle: 'rsm-tile--blur-turtle',\n};\n\n/** Number of full copies of displayItems in the tile strip for seamless wraparound. */\nconst TILE_COPIES = 3;\n\n/**\n * React SlotMachine component — a 1:1 port of jQuery-SlotMachine.\n *\n * @example\n * ```tsx\n * <SlotMachine\n *   items={['Apple', 'Banana', 'Cherry', 'Date']}\n *   options={{ active: 0, delay: 300, direction: 'up', easing: true, easeDuration: 600 }}\n *   onStop={({ item, index }) => console.log('Winner:', item)}\n * />\n * ```\n */\nexport const SlotMachine = forwardRef<SlotMachineHandle, SlotMachineProps>(\n  function SlotMachine(\n    {\n      items,\n      itemKeys,\n      initialItem,\n      options,\n      onStop,\n      onShuffle,\n      className,\n      style,\n      slotHeight = '100px',\n      slotWidth = '100%',\n      borderRadius = '12px',\n      slotBackground = '#ffffff',\n      slotBoxShadow,\n      enableGradientMask = true,\n      enableBlur = true,\n      shuffleLabel = 'Shuffle!',\n      stopLabel = 'Stop!',\n      hideButtons = false,\n      shuffleButtonClassName,\n      stopButtonClassName,\n      buttonsClassName,\n      shuffleIcon,\n      stopIcon,\n      tileClassName,\n    },\n    ref,\n  ) {\n    // ---- initialItem support ----\n    const hasInitialItem = initialItem !== undefined && initialItem !== null;\n\n    // The items displayed in the slot (initialItem prepended if provided)\n    const displayItems = useMemo<React.ReactNode[]>(() => {\n      if (!hasInitialItem) return items;\n      return [initialItem, ...items];\n    }, [hasInitialItem, initialItem, items]);\n\n    const logicalCount = displayItems.length;\n\n    // ---- Numeric slot height ----\n    const slotHeightNum = useMemo(() => parseFloat(slotHeight), [slotHeight]);\n\n    // ---- Wrap engine options so randomize never picks index 0 when initialItem is set ----\n    const engineOptions = useMemo(() => {\n      const base = {\n        ...options,\n        active: options?.active ?? 0,\n      };\n      if (!hasInitialItem) return base;\n      const userRandomize = options?.randomize;\n      return {\n        ...base,\n        randomize: userRandomize\n          ? (active: number, total: number) => {\n              const result = userRandomize(active, total);\n              return result <= 0 ? 1 : result;\n            }\n          : (_active: number, total: number) =>\n              Math.floor(Math.random() * (total - 1)) + 1,\n      };\n    }, [hasInitialItem, options]);\n\n    const {\n      active: engineActive,\n      running,\n      stopping,\n      speedTier,\n      callbacks,\n      shuffle,\n      stop,\n      next,\n      prev,\n    } = useSlotMachineEngine(logicalCount, engineOptions);\n\n    // ---- Visual active (extended range for seamless wraparound) ----\n    const direction = options?.direction ?? 'up';\n    const prevEngineActiveRef = useRef(engineActive);\n\n    // visualActive lives in [logicalCount, 2*logicalCount-1] (middle copy)\n    const [visualActive, setVisualActive] = useState<number>(() => {\n      const start = engineOptions.active ?? 0;\n      return logicalCount > 0 ? logicalCount + start : 0;\n    });\n\n    const visualActiveRef = useRef(visualActive);\n    visualActiveRef.current = visualActive;\n\n    // Skip-transition flag — set when we wrap visualActive to stay within the tile list\n    const [skipTransition, setSkipTransition] = useState(false);\n\n    // Reset skipTransition after the wrapped frame commits\n    useEffect(() => {\n      if (!skipTransition) return;\n      const raf = requestAnimationFrame(() => setSkipTransition(false));\n      return () => cancelAnimationFrame(raf);\n    }, [skipTransition]);\n\n    // Determine if render is needed (skip if 0 items)\n    const hasItems = logicalCount > 0;\n\n    // When engine active changes, extend visualActive past the copy boundary if wrapping\n    useEffect(() => {\n      if (!hasItems) return;\n      const prev = prevEngineActiveRef.current;\n      const next = engineActive;\n      prevEngineActiveRef.current = next;\n\n      if (prev === next) return;\n\n      const totalTiles = TILE_COPIES * logicalCount;\n      let visual = visualActiveRef.current;\n      let didWrap = false;\n\n      if (direction === 'up') {\n        // Always move FORWARD in visual space\n        const delta = (next - prev + logicalCount) % logicalCount;\n        const step = delta === 0 ? logicalCount : delta;\n        visual += step;\n      } else {\n        // Always move BACKWARD in visual space\n        const delta = (prev - next + logicalCount) % logicalCount;\n        const step = delta === 0 ? logicalCount : delta;\n        visual -= step;\n      }\n\n      // Wrap to stay within tile list bounds (visual jump is invisible —\n      // tile content repeats every logicalCount)\n      if (visual >= totalTiles) {\n        visual -= logicalCount;\n        didWrap = true;\n      } else if (visual < 0) {\n        visual += logicalCount;\n        didWrap = true;\n      }\n\n      if (didWrap) {\n        setSkipTransition(true);\n      }\n\n      visualActiveRef.current = visual;\n      setVisualActive(visual);\n    }, [engineActive, direction, logicalCount, hasItems]);\n\n    // After the machine stops, snap visualActive back to the middle copy\n    const wasRunningRef = useRef(running || stopping);\n    useEffect(() => {\n      const wasActive = wasRunningRef.current;\n      wasRunningRef.current = running || stopping;\n\n      // Only snap when transitioning from active → idle\n      if (wasActive && !running && !stopping && hasItems) {\n        // Snap to the middle copy (logicalCount .. 2*logicalCount-1)\n        const snapped =\n          ((visualActiveRef.current % logicalCount) + logicalCount) % logicalCount +\n          logicalCount;\n        if (snapped !== visualActiveRef.current) {\n          visualActiveRef.current = snapped;\n          setVisualActive(snapped);\n        }\n      }\n    }, [running, stopping, logicalCount, hasItems]);\n\n    // ---- Tile list: TILE_COPIES full copies of displayItems ----\n    const tileList = useMemo((): React.ReactNode[] => {\n      if (!hasItems) return [];\n      const result: React.ReactNode[] = [];\n      for (let copy = 0; copy < TILE_COPIES; copy++) {\n        for (let i = 0; i < logicalCount; i++) {\n          result.push(displayItems[i]);\n        }\n      }\n      return result;\n    }, [displayItems, logicalCount, hasItems]);\n\n    // ---- TranslateY based on visualActive ----\n    const translateY = useMemo(() => {\n      if (!hasItems) return 0;\n      return -(visualActive) * slotHeightNum;\n    }, [visualActive, slotHeightNum, hasItems]);\n\n    // ---- Dynamic transition style ----\n    const tilesStyle: React.CSSProperties = useMemo(() => {\n      // Wrap-frame: instant jump (no visible change — tile content repeats)\n      if (skipTransition) {\n        return {\n          transform: `translateY(${translateY}px)`,\n          transition: 'none',\n        };\n      }\n\n      const baseDelay = options?.delay ?? 200;\n      let duration: number;\n      let easing: string;\n\n      if (running || stopping) {\n        switch (speedTier) {\n          case 'fast':\n            duration = baseDelay / 1.5;\n            easing = 'linear';\n            break;\n          case 'normal':\n            duration = baseDelay;\n            easing = 'ease-out';\n            break;\n          case 'slow':\n            duration = baseDelay * 1.5;\n            easing = 'ease-out';\n            break;\n          case 'turtle':\n            duration = baseDelay * 3;\n            easing = 'ease-out';\n            break;\n          default:\n            duration = baseDelay;\n            easing = 'ease-out';\n        }\n      } else {\n        // Idle snap-back: instant (no visible transition since we snap to same visual)\n        duration = 0;\n        easing = 'linear';\n      }\n\n      return {\n        transform: `translateY(${translateY}px)`,\n        transition: duration > 0\n          ? `transform ${duration / 1000}s ${easing}`\n          : 'none',\n      };\n    }, [translateY, speedTier, running, stopping, options?.delay, skipTransition]);\n\n    // Wire callbacks via the mutable ref\n    useEffect(() => {\n      callbacks.current.onShuffle = onShuffle;\n    }, [onShuffle, callbacks]);\n    useEffect(() => {\n      callbacks.current.onStop = (winner) => {\n        // initialItem (index 0) is never a winner — skip silently\n        if (hasInitialItem && winner.index <= 0) return;\n        const itemIndex = hasInitialItem ? winner.index - 1 : winner.index;\n        onStop?.({\n          item: items[itemIndex],\n          index: itemIndex,\n          key: itemKeys?.[itemIndex],\n        });\n      };\n    }, [onStop, items, itemKeys, callbacks, hasInitialItem]);\n\n    // Expose imperative handle\n    const handle: SlotMachineHandle = useMemo(\n      () => ({\n        shuffle,\n        stop,\n        next,\n        prev,\n        get active() {\n          return engineActive;\n        },\n        get running() {\n          return running;\n        },\n        get stopping() {\n          return stopping;\n        },\n      }),\n      [shuffle, stop, next, prev, engineActive, running, stopping],\n    );\n    useImperativeHandle(ref, () => handle, [handle]);\n\n    // Blur state — derive from speedTier\n    const blur = enableBlur ? (blurClass[speedTier] ?? '') : '';\n\n    const wrapperBoxShadow =\n      slotBoxShadow ?? '0 4px 24px rgba(0,0,0,0.12)';\n\n    // Only render tiles if there are items\n    if (logicalCount === 0) {\n      return (\n        <div\n          className={`rsm-wrapper ${className ?? ''}`}\n          style={{\n            display: 'inline-flex',\n            flexDirection: 'column',\n            alignItems: 'center',\n            gap: '16px',\n            ...style,\n          }}\n        >\n          <div\n            className=\"rsm-window\"\n            style={{\n              width: slotWidth,\n              height: slotHeight,\n              borderRadius,\n              background: slotBackground,\n              boxShadow: wrapperBoxShadow,\n              overflow: 'hidden',\n              position: 'relative',\n              display: 'flex',\n              alignItems: 'center',\n              justifyContent: 'center',\n              color: '#999',\n              fontSize: '0.9rem',\n            }}\n          >\n            No items\n          </div>\n        </div>\n      );\n    }\n\n    return (\n      <div\n        className={`rsm-wrapper ${className ?? ''}`}\n        style={{\n          display: 'inline-flex',\n          flexDirection: 'column',\n          alignItems: 'center',\n          gap: '16px',\n          ...style,\n        }}\n      >\n        {/* Slot window */}\n        <div\n          className={`rsm-window ${enableGradientMask ? 'rsm-window--gradient' : ''}`}\n          style={{\n            width: slotWidth,\n            height: slotHeight,\n            borderRadius,\n            background: slotBackground,\n            boxShadow: wrapperBoxShadow,\n            overflow: 'hidden',\n            position: 'relative',\n          }}\n        >\n          <div className=\"rsm-tiles\" style={tilesStyle}>\n            {tileList.map((item, i) => (\n              <div\n                key={i}\n                className={`rsm-tile ${tileClassName ?? ''} ${blur}`}\n                style={{ height: slotHeight, flexShrink: 0 }}\n              >\n                {item}\n              </div>\n            ))}\n          </div>\n        </div>\n\n        {/* Buttons */}\n        {!hideButtons && (\n          <div\n            className={`rsm-buttons ${buttonsClassName ?? ''}`}\n            style={{\n              display: 'flex',\n              gap: '12px',\n              justifyContent: 'center',\n            }}\n          >\n            {!running ? (\n              <button\n                type=\"button\"\n                className={`rsm-btn rsm-btn--shuffle ${shuffleButtonClassName ?? ''}`}\n                onClick={() => shuffle(999999)}\n                disabled={items.length === 0}\n              >\n                {shuffleIcon ?? <ShuffleIcon />}\n                <span>{shuffleLabel}</span>\n              </button>\n            ) : (\n              <button\n                type=\"button\"\n                className={`rsm-btn rsm-btn--stop ${stopButtonClassName ?? ''}`}\n                onClick={() => stop(0)}\n              >\n                {stopIcon ?? <StopIcon />}\n                <span>{stopLabel}</span>\n              </button>\n            )}\n          </div>\n        )}\n      </div>\n    );\n  },\n);\n\nexport default SlotMachine;\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { SpeedTier } from './types';\n\n// ---- Helpers ----\nexport const timeout = (ms: number) => new Promise<void>((res) => setTimeout(res, ms));\n\n// ---- Defaults ----\nexport interface SlotMachineEngineOptions {\n  active?: number;\n  delay?: number;\n  /** 'up' or 'down' — direction items appear to scroll. */\n  direction?: 'up' | 'down';\n  /** Custom randomize function. (active, total) => nextIndex */\n  randomize?: (active: number, total: number) => number;\n  /** Enable ease-in/out phases. Default: true. */\n  easing?: boolean;\n  /** Duration in ms of each easing phase. Default: 600. */\n  easeDuration?: number;\n}\n\nfunction defaultRandomize(_active: number, max: number): number {\n  return Math.floor(Math.random() * max);\n}\n\nconst DEFAULT_DELAY = 200;\n\nexport interface SlotMachineEngineState {\n  /** Current visible item index. */\n  active: number;\n  /** Is the machine currently spinning? */\n  running: boolean;\n  /** Is the machine decelerating to a stop? */\n  stopping: boolean;\n  /** Current speed tier (for blur / visual effects). */\n  speedTier: SpeedTier | 'stop';\n  /** Callbacks the engine invokes — set by the consumer. */\n  callbacks: React.MutableRefObject<SlotMachineCallbacks>;\n}\n\nexport interface SlotMachineCallbacks {\n  onShuffle?: (nextIndex: number) => void;\n  onStop?: (winner: { index: number }) => void;\n}\n\nexport interface SlotMachineEngine extends SlotMachineEngineState {\n  shuffle: (spins?: number) => void;\n  stop: (spins?: number) => void;\n  next: () => void;\n  prev: () => void;\n}\n\n/**\n * Core slot-machine engine as a React hook.\n *\n * Manages index state, spin-cycle scheduling, speed tiers, and stop logic.\n * The consumer (SlotMachine component) reads `active`, `running`, `stopping`,\n * and `speedTier` to drive CSS animations and blur effects.\n */\nexport function useSlotMachineEngine(\n  itemCount: number,\n  options?: SlotMachineEngineOptions,\n): SlotMachineEngine {\n  // ---- Mutable options ref (avoids stale closures) ----\n  const optsRef = useRef<Required<SlotMachineEngineOptions>>({\n    active: 0,\n    delay: DEFAULT_DELAY,\n    direction: 'up',\n    randomize: defaultRandomize,\n    easing: true,\n    easeDuration: 600,\n  });\n\n  useEffect(() => {\n    optsRef.current = {\n      active: options?.active ?? 0,\n      delay: options?.delay ?? DEFAULT_DELAY,\n      direction: options?.direction ?? 'up',\n      randomize: options?.randomize ?? defaultRandomize,\n      easing: options?.easing ?? true,\n      easeDuration: options?.easeDuration ?? 600,\n    };\n  }, [options?.active, options?.delay, options?.direction, options?.randomize, options?.easing, options?.easeDuration]);\n\n  // ---- State ----\n  const [active, setActive] = useState<number>(() => {\n    const a = options?.active ?? 0;\n    return a < 0 || a >= itemCount || itemCount === 0 ? 0 : a;\n  });\n\n  const activeRef = useRef(active);\n  activeRef.current = active;\n\n  const [running, setRunning] = useState(false);\n  const runningRef = useRef(false);\n\n  const [stopping, setStopping] = useState(false);\n  const stoppingRef = useRef(false);\n\n  const [speedTier, setSpeedTier] = useState<SpeedTier | 'stop'>('stop');\n\n  // Internal mutable state\n  const nextActiveRef = useRef<number | null>(null);\n  /** Pre-determined winner — set once in shuffle, never overwritten by ticks. */\n  const winnerRef = useRef<number | null>(null);\n  const remainingRef = useRef(0);\n  const abortRef = useRef(false);\n\n  // Callbacks ref\n  const callbacks = useRef<SlotMachineCallbacks>({});\n\n  // ---- Index helpers ----\n  const prevIdx = useCallback(\n    (idx: number) => (idx <= 0 ? itemCount - 1 : idx - 1),\n    [itemCount],\n  );\n  const nextIdx = useCallback(\n    (idx: number) => (idx + 1 < itemCount ? idx + 1 : 0),\n    [itemCount],\n  );\n\n  // ---- Speed calculation with ease-in / ease-out phases ----\n  const calcSpeed = useCallback(\n    (\n      remaining: number,\n      elapsed: number,\n      isStopping: boolean,\n    ): { delay: number; tier: SpeedTier; timing: string } => {\n      const baseDelay = optsRef.current.delay;\n      const useEasing = optsRef.current.easing;\n      const easeMs = optsRef.current.easeDuration;\n      // Convert ease duration to tick counts (approximate)\n      const easeTicks = Math.max(2, Math.round(easeMs / baseDelay));\n\n      let d = baseDelay;\n      let tier: SpeedTier = 'fast';\n      let timing = 'linear';\n\n      if (!useEasing) {\n        // Constant speed — no acceleration/deceleration\n        d = isStopping ? baseDelay * 2 : baseDelay / 1.5;\n        tier = isStopping ? 'turtle' : 'fast';\n        timing = 'linear';\n      } else if (isStopping) {\n        // Ease-out: decelerate over easeTicks\n        const decelRemaining = Math.min(remaining, easeTicks);\n        const progress = Math.max(0, Math.min(1, (easeTicks - decelRemaining) / (easeTicks - 1)));\n        const multiplier = 1 + progress * 4; // 1x → 5x base delay\n        d = baseDelay * multiplier;\n        tier = decelRemaining <= 2 ? 'turtle' : decelRemaining <= easeTicks / 2 ? 'slow' : 'normal';\n        timing = 'ease-out';\n      } else if (elapsed < easeTicks) {\n        // Ease-in: accelerate over first easeTicks (delay 2.5x → 1x)\n        const progress = elapsed / easeTicks;\n        const multiplier = 2.5 - progress * 1.5;\n        d = baseDelay * multiplier;\n        tier = elapsed < easeTicks / 2 ? 'slow' : 'normal';\n        timing = 'ease-out';\n      } else {\n        // Constant-speed phase\n        d = baseDelay / 1.5;\n        tier = 'fast';\n        timing = 'linear';\n      }\n\n      return { delay: d, tier, timing };\n    },\n    [],\n  );\n\n  // ---- One tick of spinning ----\n  const tick = useCallback(\n    async (_remaining: number, elapsed: number): Promise<void> => {\n      if (abortRef.current) return;\n\n      // Always read fresh refs — doStop may mutate them during await\n      const remaining = remainingRef.current;\n      const isStopping = stoppingRef.current;\n\n      const { delay, tier } = calcSpeed(remaining, elapsed, isStopping);\n      setSpeedTier(tier);\n\n      // Determine the index to show for this tick\n      const isFinalTick = isStopping && remaining <= 1;\n      const next = isFinalTick\n        ? winnerRef.current! // final tick → use pre-determined winner (never clobbered)\n        : optsRef.current.randomize(activeRef.current, itemCount);\n\n      if (!isFinalTick) {\n        nextActiveRef.current = next;\n      }\n      callbacks.current.onShuffle?.(next);\n\n      // Update active → consumer animates via CSS transition\n      activeRef.current = next;\n      setActive(next);\n\n      await timeout(delay);\n      if (abortRef.current) return;\n\n      // Decrement — using the ref value (may have been capped by doStop during await)\n      const newRemaining = remainingRef.current - 1;\n      remainingRef.current = newRemaining;\n\n      // Re-read stopping state (doStop may have fired during await)\n      if (stoppingRef.current) {\n        // In stopping phase: decelerate through remaining ticks, then finish\n        if (newRemaining >= 1) {\n          await tick(newRemaining, elapsed + 1);\n        } else {\n          // All deceleration ticks exhausted → finalize stop\n          setSpeedTier('stop');\n          stoppingRef.current = false;\n          runningRef.current = false;\n          setStopping(false);\n          setRunning(false);\n          nextActiveRef.current = null;\n          winnerRef.current = null;\n          callbacks.current.onStop?.({ index: next });\n        }\n      } else if (runningRef.current) {\n        if (newRemaining >= 1) {\n          await tick(newRemaining, elapsed + 1);\n        } else {\n          // All spins exhausted → execute stop sequence\n          await doStop(0);\n        }\n      }\n    },\n    [itemCount, calcSpeed],\n  );\n\n  // ---- Stop sequence (decelerate & land on winner) ----\n  const doStop = useCallback(\n    async (extraSpins: number) => {\n      // If stop() is called with extra spins while still running, just update the counter\n      if (runningRef.current && !stoppingRef.current && extraSpins > 0) {\n        remainingRef.current = extraSpins;\n        return;\n      }\n\n      if (!runningRef.current || stoppingRef.current) return;\n\n      stoppingRef.current = true;\n      setStopping(true);\n\n      // Ensure we have enough ticks for a visible deceleration\n      const currentRemaining = remainingRef.current;\n      if (currentRemaining > 6 || !isFinite(currentRemaining)) {\n        remainingRef.current = 6; // cap at 6 deceleration ticks\n      } else if (currentRemaining < 3) {\n        remainingRef.current = 3; // pad to at least 3 deceleration ticks\n      }\n      // else: 3–6 ticks remaining — decelerate naturally through them\n    },\n    [],\n  );\n\n  // ---- Public API ----\n  const shuffle = useCallback(\n    (spins: number = 5) => {\n      if (runningRef.current || stoppingRef.current || itemCount === 0) return;\n\n      abortRef.current = false;\n      runningRef.current = true;\n      setRunning(true);\n\n      // Pre-determine the winner — store in dedicated ref that ticks never overwrite\n      const winner = optsRef.current.randomize(activeRef.current, itemCount);\n      winnerRef.current = winner;\n      nextActiveRef.current = winner;\n      remainingRef.current = spins;\n\n      tick(spins, 0);\n    },\n    [itemCount, tick],\n  );\n\n  const stop = useCallback(\n    (spins: number = 0) => {\n      if (!runningRef.current || stoppingRef.current) {\n        // Allow scheduling extra spins while running\n        if (runningRef.current && !stoppingRef.current && spins > 0) {\n          remainingRef.current = spins;\n        }\n        return;\n      }\n      doStop(spins);\n    },\n    [doStop],\n  );\n\n  const next = useCallback(() => {\n    if (runningRef.current || stoppingRef.current || itemCount === 0) return;\n    const nxt = nextIdx(activeRef.current);\n    nextActiveRef.current = nxt;\n    runningRef.current = true;\n    stoppingRef.current = true;\n    setRunning(true);\n    setStopping(true);\n    setSpeedTier('turtle');\n\n    const { delay } = calcSpeed(1, 0, true);\n    timeout(delay).then(() => {\n      activeRef.current = nxt;\n      setActive(nxt);\n      setSpeedTier('stop');\n      stoppingRef.current = false;\n      runningRef.current = false;\n      setStopping(false);\n      setRunning(false);\n      nextActiveRef.current = null;\n      callbacks.current.onStop?.({ index: nxt });\n    });\n  }, [itemCount, nextIdx, calcSpeed]);\n\n  const prev = useCallback(() => {\n    if (runningRef.current || stoppingRef.current || itemCount === 0) return;\n    const prv = prevIdx(activeRef.current);\n    nextActiveRef.current = prv;\n    runningRef.current = true;\n    stoppingRef.current = true;\n    setRunning(true);\n    setStopping(true);\n    setSpeedTier('turtle');\n\n    const { delay } = calcSpeed(1, 0, true);\n    timeout(delay).then(() => {\n      activeRef.current = prv;\n      setActive(prv);\n      setSpeedTier('stop');\n      stoppingRef.current = false;\n      runningRef.current = false;\n      setStopping(false);\n      setRunning(false);\n      nextActiveRef.current = null;\n      callbacks.current.onStop?.({ index: prv });\n    });\n  }, [itemCount, prevIdx, calcSpeed]);\n\n  return {\n    active,\n    running,\n    stopping,\n    speedTier,\n    callbacks,\n    shuffle,\n    stop,\n    next,\n    prev,\n  };\n}\n\n"],"mappings":"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","names":["useEffect","useRef","useState","next","SlotMachine","useRef","useState","useEffect","prev","next"]}