// =============================================================================
// hl-num.jsx — Number renderer with optional smooth value interpolation
// =============================================================================
// Default: pure formatting, no animation, no color change.
//
// Opt-in animate={true}: smooth rAF value interpolation (~350ms ease-out).
// No color tint — just the digits gliding to the new value. Used sparingly
// for high-value figures the user wants to track at a glance.
// =============================================================================

function NumFlow(props) {
  const value    = props.value;
  const format   = props.format || ((v) => String(v));
  const animate  = props.animate === true;
  const duration = props.duration != null ? props.duration : 350;

  if (!animate) {
    return <span style={{ fontVariantNumeric: 'tabular-nums' }}>{format(value)}</span>;
  }

  const [display, setDisplay] = React.useState(value);
  const startRef  = React.useRef(value);
  const targetRef = React.useRef(value);
  const tStartRef = React.useRef(0);
  const rafRef    = React.useRef(0);

  React.useEffect(() => {
    if (!isFinite(value)) { setDisplay(value); return; }
    const prev = targetRef.current;
    if (value === prev) return;
    if (!isFinite(prev)) {
      targetRef.current = value;
      startRef.current  = value;
      setDisplay(value);
      return;
    }
    startRef.current  = display;
    targetRef.current = value;
    tStartRef.current = performance.now();
    cancelAnimationFrame(rafRef.current);
    const step = (now) => {
      const k = Math.min(1, (now - tStartRef.current) / duration);
      const e = 1 - Math.pow(1 - k, 3); // ease-out cubic
      const cur = startRef.current + (targetRef.current - startRef.current) * e;
      setDisplay(k === 1 ? targetRef.current : cur);
      if (k < 1) rafRef.current = requestAnimationFrame(step);
    };
    rafRef.current = requestAnimationFrame(step);
  }, [value, duration]);

  React.useEffect(() => () => cancelAnimationFrame(rafRef.current), []);

  return <span style={{ fontVariantNumeric: 'tabular-nums' }}>{format(display)}</span>;
}

NumFlow.usd    = ({ value, d=2, ...rest }) => <NumFlow value={value} format={(v)=>window.fmt.usd(v, d)} {...rest}/>;
NumFlow.signed = ({ value, d=2, ...rest }) => <NumFlow value={value} format={(v)=>window.fmt.signed(v, d)} {...rest}/>;
NumFlow.num    = ({ value, d=2, ...rest }) => <NumFlow value={value} format={(v)=>window.fmt.num(v, d)} {...rest}/>;
NumFlow.pct    = ({ value, ...rest })      => <NumFlow value={value} format={(v)=>window.fmt.pct(v)} {...rest}/>;

window.NumFlow = NumFlow;
