{"version":3,"sources":["../src/animatednumber/index.tsx"],"names":["motion","useState","useRef","useReducedMotion","useEffect","jsx"],"mappings":";;;;;;;;AA4BA,SAAS,cAAc,CAAA,EAAmB;AACxC,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,QAAA,EAAS;AAChC;AAGA,SAAS,QAAQ,CAAA,EAAmB;AAClC,EAAA,OAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,GAAG,CAAC,CAAA;AAC9B;AAEO,SAAS,cAAA,CAAe;AAAA,EAC7B,KAAA;AAAA,EACA,QAAA,GAAWA,YAAO,SAAA,CAAU,QAAA;AAAA,EAC5B,MAAA,GAAS,aAAA;AAAA,EACT,SAAA;AAAA,EACA;AACF,CAAA,EAAwB;AACtB,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,eAAiB,KAAK,CAAA;AACpD,EAAA,MAAM,UAAA,GAAaC,aAAO,KAAK,CAAA;AAC/B,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AACrB,EAAA,MAAM,UAAUC,sBAAA,EAAiB;AAEjC,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,UAAA,CAAW,YAAY,KAAA,EAAO;AAClC,IAAA,IAAI,OAAA,IAAW,YAAY,CAAA,EAAG;AAC5B,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,QAAQ,UAAA,CAAW,OAAA;AACzB,IAAA,MAAM,QAAQ,KAAA,GAAQ,KAAA;AACtB,IAAA,MAAM,EAAA,GAAK,YAAY,GAAA,EAAI;AAC3B,IAAA,IAAI,GAAA,GAAM,CAAA;AACV,IAAA,MAAM,IAAA,GAAO,CAAC,GAAA,KAAgB;AAC5B,MAAA,MAAM,IAAI,IAAA,CAAK,GAAA,CAAA,CAAK,GAAA,GAAM,EAAA,IAAM,UAAU,CAAC,CAAA;AAC3C,MAAA,UAAA,CAAW,KAAA,GAAQ,KAAA,GAAQ,OAAA,CAAQ,CAAC,CAAC,CAAA;AACrC,MAAA,IAAI,CAAA,GAAI,CAAA,EAAG,GAAA,GAAM,qBAAA,CAAsB,IAAI,CAAA;AAAA,IAC7C,CAAA;AACA,IAAA,GAAA,GAAM,sBAAsB,IAAI,CAAA;AAChC,IAAA,OAAO,MAAM,qBAAqB,GAAG,CAAA;AAAA,EACvC,CAAA,EAAG,CAAC,KAAA,EAAO,QAAA,EAAU,OAAO,CAAC,CAAA;AAE7B,EAAA,uBACEC,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAsB,KAAA,EAAO,EAAE,kBAAA,EAAoB,cAAA,EAAgB,GAAG,KAAA,EAAM,EAC/E,QAAA,EAAA,MAAA,CAAO,OAAO,CAAA,EACjB,CAAA;AAEJ","file":"animatednumber.cjs","sourcesContent":["/**\n * AnimatedNumber (web). Counts a number up (or down) to its new value —\n * for score reveals, streak counters, and any moment where the change is\n * the point. A number that travels reads as an event; one that snaps\n * reads as a correction.\n *\n *   <AnimatedNumber value={score} />\n *   <AnimatedNumber value={total} format={(n) => `$${n.toFixed(2)}`} />\n *   <AnimatedNumber value={xp} duration={800} />\n *\n * rAF-driven with an ease-out interpolation (default length\n * motion.celebrate, 500ms). Digits render tabular-nums so the layout\n * doesn't wobble mid-count. Reduced motion snaps to the value instantly.\n */\nimport { useEffect, useRef, useState, type CSSProperties } from \"react\";\nimport { motion } from \"@plyxui/core\";\nimport { useReducedMotion } from \"@plyxui/hooks\";\n\nexport interface AnimatedNumberProps {\n  value: number;\n  /** Count duration in ms. Default motion.celebrate (500). */\n  duration?: number;\n  /** Render the interpolated value. Default rounds to an integer string. */\n  format?: (n: number) => string;\n  className?: string;\n  style?: CSSProperties;\n}\n\nfunction defaultFormat(n: number): string {\n  return Math.round(n).toString();\n}\n\n// easeOutCubic — fast start, gentle landing on the final digit.\nfunction easeOut(t: number): number {\n  return 1 - Math.pow(1 - t, 3);\n}\n\nexport function AnimatedNumber({\n  value,\n  duration = motion.celebrate.duration,\n  format = defaultFormat,\n  className,\n  style,\n}: AnimatedNumberProps) {\n  const [display, setDisplay] = useState<number>(value);\n  const displayRef = useRef(value);\n  displayRef.current = display;\n  const reduced = useReducedMotion();\n\n  useEffect(() => {\n    if (displayRef.current === value) return;\n    if (reduced || duration <= 0) {\n      setDisplay(value);\n      return;\n    }\n    const start = displayRef.current;\n    const delta = value - start;\n    const t0 = performance.now();\n    let raf = 0;\n    const tick = (now: number) => {\n      const t = Math.min((now - t0) / duration, 1);\n      setDisplay(start + delta * easeOut(t));\n      if (t < 1) raf = requestAnimationFrame(tick);\n    };\n    raf = requestAnimationFrame(tick);\n    return () => cancelAnimationFrame(raf);\n  }, [value, duration, reduced]);\n\n  return (\n    <span className={className} style={{ fontVariantNumeric: \"tabular-nums\", ...style }}>\n      {format(display)}\n    </span>\n  );\n}\n"]}