SPB Git

spb/qwhpi Public

QHPI — Quebec Housing Price Index: quality-adjusted, hierarchically pooled housing price indexes.

Python 63.9% TypeScript 25.4% CSS 5.5% TeX 3.5% SQL 0.8% Makefile 0.5% Dockerfile 0.5%
1.5 KB · 57 lines tsx
Raw Blame History
1/**2 * =============================================================================3 * QWHPI — Quebec Weekly Housing Price Index4 * Author  : Simon-Pierre Boucher5 * Contact : contact@spboucher.ai6 * File    : web/components/CountUp.tsx7 * Purpose : Animated number count-up (easeOut, reduced-motion aware).8 * =============================================================================9 */10"use client";1112import { useEffect, useRef, useState } from "react";1314export default function CountUp({15  value,16  decimals = 1,17  duration = 1100,18  prefix = "",19  suffix = "",20}: {21  value: number;22  decimals?: number;23  duration?: number;24  prefix?: string;25  suffix?: string;26}) {27  const [display, setDisplay] = useState(0);28  const raf = useRef<number>(0);2930  useEffect(() => {31    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {32      setDisplay(value);33      return;34    }35    const t0 = performance.now();36    const tick = (t: number) => {37      const p = Math.min(1, (t - t0) / duration);38      const eased = 1 - Math.pow(1 - p, 3);39      setDisplay(value * eased);40      if (p < 1) raf.current = requestAnimationFrame(tick);41    };42    raf.current = requestAnimationFrame(tick);43    return () => cancelAnimationFrame(raf.current);44  }, [value, duration]);4546  return (47    <span style={{ fontVariantNumeric: "tabular-nums" }}>48      {prefix}49      {display.toLocaleString("en-CA", {50        minimumFractionDigits: decimals,51        maximumFractionDigits: decimals,52      })}53      {suffix}54    </span>55  );56}57