{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sliding-number",
  "type": "registry:component",
  "title": "Sliding Number",
  "author": "Toby Belhome",
  "description": "A component that slides numbers.",
  "dependencies": [
    "motion",
    "react-use-measure"
  ],
  "registryDependencies": [
    "http://localhost:3000/r/sliding-number.json"
  ],
  "files": [
    {
      "path": "examples/motion/components/sliding-number/01/page.tsx",
      "content": "\"use client\";\n\nimport { motion } from \"motion/react\";\nimport { useEffect, useState } from \"react\";\nimport { SlidingNumber } from \"./sliding-number\";\n\nexport default function SlidingNumberBasic() {\n  const [value, setValue] = useState(0);\n\n  useEffect(() => {\n    if (value === 100) return;\n\n    const interval = setInterval(() => {\n      setValue(value + 1);\n    }, 10);\n    return () => clearInterval(interval);\n  }, [value]);\n\n  return (\n    <motion.div\n      initial={{ y: 0, fontSize: `${24}px` }}\n      animate={{ y: 0, fontSize: `${24}px` }}\n      transition={{\n        ease: [1, 0, 0.35, 0.95],\n        duration: 1.5,\n        delay: 0.3\n      }}>\n      <div className=\"inline-flex items-center\">\n        <SlidingNumber value={value} />%\n      </div>\n    </motion.div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/sliding-number/sliding-number-example.tsx"
    },
    {
      "path": "examples/motion/components/sliding-number/01/sliding-number.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useId } from \"react\";\nimport { MotionValue, motion, useSpring, useTransform, motionValue } from \"motion/react\";\nimport { Transition } from \"motion\";\nimport useMeasure from \"react-use-measure\";\n\nconst TRANSITION: Transition = {\n  type: \"spring\",\n  stiffness: 280,\n  damping: 18,\n  mass: 0.3\n};\n\nfunction Digit({ value, place }: { value: number; place: number }) {\n  const valueRoundedToPlace = Math.floor(value / place) % 10;\n  const initial = motionValue(valueRoundedToPlace);\n  const animatedValue = useSpring(initial, TRANSITION);\n\n  useEffect(() => {\n    animatedValue.set(valueRoundedToPlace);\n  }, [animatedValue, valueRoundedToPlace]);\n\n  return (\n    <div className=\"relative inline-block w-[1ch] overflow-x-visible overflow-y-clip leading-none tabular-nums\">\n      <div className=\"invisible\">0</div>\n      {Array.from({ length: 10 }, (_, i) => (\n        <Number key={i} mv={animatedValue} number={i} />\n      ))}\n    </div>\n  );\n}\n\nfunction Number({ mv, number }: { mv: MotionValue<number>; number: number }) {\n  const uniqueId = useId();\n  const [ref, bounds] = useMeasure();\n\n  const y = useTransform(mv, (latest) => {\n    if (!bounds.height) return 0;\n    const placeValue = latest % 10;\n    const offset = (10 + number - placeValue) % 10;\n    let memo = offset * bounds.height;\n\n    if (offset > 5) {\n      memo -= 10 * bounds.height;\n    }\n\n    return memo;\n  });\n\n  // don't render the animated number until we know the height\n  if (!bounds.height) {\n    return (\n      <span ref={ref} className=\"invisible absolute\">\n        {number}\n      </span>\n    );\n  }\n\n  return (\n    <motion.span\n      style={{ y }}\n      layoutId={`${uniqueId}-${number}`}\n      className=\"absolute inset-0 flex items-center justify-center\"\n      transition={TRANSITION}\n      ref={ref}>\n      {number}\n    </motion.span>\n  );\n}\n\ntype SlidingNumberProps = {\n  value: number;\n  padStart?: boolean;\n  decimalSeparator?: string;\n};\n\nexport function SlidingNumber({\n  value,\n  padStart = false,\n  decimalSeparator = \".\"\n}: SlidingNumberProps) {\n  const absValue = Math.abs(value);\n  const [integerPart, decimalPart] = absValue.toString().split(\".\");\n  const integerValue = parseInt(integerPart, 10);\n  const paddedInteger = padStart && integerValue < 10 ? `0${integerPart}` : integerPart;\n  const integerDigits = paddedInteger.split(\"\");\n  const integerPlaces = integerDigits.map((_, i) => Math.pow(10, integerDigits.length - i - 1));\n\n  return (\n    <div className=\"flex items-center\">\n      {value < 0 && \"-\"}\n      {integerDigits.map((_, index) => (\n        <Digit\n          key={`pos-${integerPlaces[index]}`}\n          value={integerValue}\n          place={integerPlaces[index]}\n        />\n      ))}\n      {decimalPart && (\n        <>\n          <span>{decimalSeparator}</span>\n          {decimalPart.split(\"\").map((_, index) => (\n            <Digit\n              key={`decimal-${index}`}\n              value={parseInt(decimalPart, 10)}\n              place={Math.pow(10, decimalPart.length - index - 1)}\n            />\n          ))}\n        </>\n      )}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/sliding-number/sliding-number.tsx"
    }
  ],
  "meta": {
    "isPro": false
  }
}