{
  "name": "sliding-slider",
  "type": "registry:ui",
  "componentName": "sliding-number",
  "description": "Sliding number component with interactive slider control.",
  "files": [
    {
      "path": "sliding-slider.tsx",
      "content": "'use client';\nimport { SlidingNumber } from '@/components/core/sliding-number';\nimport { useState } from 'react';\n\nexport function SlidingNumberWithSlider() {\n  const [value, setValue] = useState(100);\n\n  return (\n    <div className='flex flex-col items-start gap-0'>\n      <div className='flex items-center gap-2 font-mono'>Current ARR:</div>\n      <div className='inline-flex items-center gap-1 font-mono leading-none'>\n        $<SlidingNumber value={value} />\n      </div>\n      <input\n        type='range'\n        value={value}\n        min={500}\n        max={100000}\n        step={50}\n        onChange={(e) => setValue(+e.target.value)}\n        className='mt-2 accent-indigo-950'\n      />\n    </div>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "components/core/sliding-number.tsx",
      "content": "'use client';\nimport { useEffect, useId } from 'react';\nimport {\n  MotionValue,\n  motion,\n  useSpring,\n  useTransform,\n  motionValue,\n} from 'motion/react';\nimport useMeasure from 'react-use-measure';\n\nconst TRANSITION = {\n  type: 'spring' as const,\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    >\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 =\n    padStart && integerValue < 10 ? `0${integerPart}` : integerPart;\n  const integerDigits = paddedInteger.split('');\n  const integerPlaces = integerDigits.map((_, i) =>\n    Math.pow(10, integerDigits.length - i - 1)\n  );\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:ui"
    }
  ]
}