{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "row-count",
  "title": "Row Count",
  "description": "A large number rolls up across stacked ruled rows, ending 27,300,000 with a small label.",
  "dependencies": ["remotion", "@remotion/google-fonts"],
  "files": [
    {
      "path": "registry/remocn/row-count/index.tsx",
      "content": "\"use client\";\n\nimport { loadFont as loadPlexSans } from \"@remotion/google-fonts/IBMPlexSans\";\nimport { useMemo } from \"react\";\nimport {\n  AbsoluteFill,\n  Easing,\n  interpolate,\n  spring,\n  useCurrentFrame,\n  useVideoConfig,\n} from \"remotion\";\n\nconst plex = loadPlexSans(\"normal\", {\n  weights: [\"400\", \"500\"],\n  subsets: [\"latin\"],\n});\n\nexport interface RowCountProps {\n  value?: number;\n  from?: number;\n  prefix?: string;\n  label?: string;\n  accent?: string;\n  background?: string;\n  speed?: number;\n  theme?: \"dark\" | \"light\";\n}\n\nconst THEMES = {\n  dark: {\n    bg: \"#0F1B2D\",\n    ink: \"#F3F5F8\",\n    muted: \"#93A1B5\",\n    comma: \"#4D5D75\",\n    rule: \"rgba(243, 245, 248, 0.22)\",\n    accent: \"#FF9900\",\n  },\n  light: {\n    bg: \"#FFFFFF\",\n    ink: \"#0F1B2D\",\n    muted: \"#5A677A\",\n    comma: \"#B5BDC9\",\n    rule: \"rgba(15, 27, 45, 0.2)\",\n    accent: \"#C76A00\",\n  },\n} as const;\n\nconst FIG = 0.6;\nconst COMMA = 0.26;\nconst ROW = 1.0;\nconst TRACK = -0.02;\n\nconst COUNT_AT = 6;\nconst COUNT_LEN = 78;\n\nconst EASE_OUT = Easing.bezier(0.22, 1, 0.36, 1);\nconst EASE_COUNT = Easing.bezier(0.3, 0.1, 0.2, 1);\nconst CLAMP = {\n  extrapolateLeft: \"clamp\",\n  extrapolateRight: \"clamp\",\n} as const;\n\nfunction groups(n: number): string[] {\n  const s = String(Math.max(0, Math.floor(n)));\n  const out: string[] = [];\n  for (let end = s.length; end > 0; end -= 3) {\n    out.unshift(s.slice(Math.max(0, end - 3), end));\n  }\n  return out;\n}\n\nexport function RowCount({\n  value = 27300000,\n  from = 1,\n  prefix = \"\",\n  label = \"frames rendered in every region, every night\",\n  accent,\n  background,\n  speed = 1,\n  theme = \"dark\",\n}: RowCountProps) {\n  const t = useCurrentFrame() * speed;\n  const { width: W, height: H, fps } = useVideoConfig();\n  const c = THEMES[theme];\n  const transparent = background === \"transparent\";\n  const stage = transparent ? \"transparent\" : (background ?? c.bg);\n\n  const target = Math.max(1, Math.floor(value));\n  const start = Math.min(target, Math.max(1, Math.floor(from)));\n  const finalRows = groups(target).length;\n\n  const p = interpolate(t, [COUNT_AT, COUNT_AT + COUNT_LEN], [0, 1], {\n    ...CLAMP,\n    easing: EASE_COUNT,\n  });\n  const live =\n    p >= 1\n      ? target\n      : Math.floor(start * (target / start) ** Math.min(1, Math.max(0, p)));\n  const g = groups(live);\n  const rows = g.length;\n\n  const rowBorn = useMemo(() => {\n    const born: number[] = [];\n    for (let k = 0; k < finalRows; k++) {\n      const thresh = 1000 ** k;\n      if (thresh <= start) {\n        born.push(-100);\n        continue;\n      }\n      let lo = COUNT_AT;\n      let hi = COUNT_AT + COUNT_LEN;\n      for (let i = 0; i < 24; i++) {\n        const mid = (lo + hi) / 2;\n        const pm = interpolate(mid, [COUNT_AT, COUNT_AT + COUNT_LEN], [0, 1], {\n          ...CLAMP,\n          easing: EASE_COUNT,\n        });\n        const v = start * (target / start) ** pm;\n        if (v >= thresh) hi = mid;\n        else lo = mid;\n      }\n      born.push(hi);\n    }\n    return born;\n  }, [finalRows, start, target]);\n\n  const shift = (k: number) => {\n    let s = 0;\n    for (let j = k + 1; j < finalRows; j++) {\n      s += spring({\n        frame: t - rowBorn[j] + 4,\n        fps,\n        config: { damping: 16, stiffness: 140, mass: 0.8 },\n      });\n    }\n    return s;\n  };\n  let rowsAnim = 1;\n  for (let k = 1; k < finalRows; k++) {\n    rowsAnim += spring({\n      frame: t - rowBorn[k] + 4,\n      fps,\n      config: { damping: 16, stiffness: 140, mass: 0.8 },\n    });\n  }\n\n  const portrait = H > W * 1.1;\n  const margin = Math.min(W, H) * 0.09;\n  const prefixW = prefix ? Array.from(prefix).length * FIG : 0;\n  const colW = prefixW + 3 * FIG + 2 * TRACK;\n  const labelSize = label\n    ? portrait\n      ? Math.min(W * 0.06, H * 0.034)\n      : Math.min(H * 0.042, W * 0.026)\n    : 0;\n  const labelW = portrait ? W - margin * 2 : W * 0.34;\n  const labelBlock = portrait && label ? labelSize * 1.3 * 3 + margin * 0.6 : 0;\n  const ruleY = margin;\n  const avail = H - margin * 2 - labelBlock - margin * 0.3;\n  const F = Math.min(\n    avail / (Math.max(2, finalRows) * ROW),\n    (W * (portrait ? 0.74 : 0.5)) / (colW + COMMA),\n    H * 0.3,\n  );\n  const rowH = F * ROW;\n  const colRight = W - margin - COMMA * F;\n  const firstTop = ruleY + labelBlock + margin * 0.3;\n\n  const ruleP = interpolate(t, [0, 16], [0, 1], { ...CLAMP, easing: EASE_OUT });\n  const enter = interpolate(t, [0, 14], [0, 1], { ...CLAMP, easing: EASE_OUT });\n  const labelP = interpolate(t, [6, 24], [0, 1], {\n    ...CLAMP,\n    easing: EASE_OUT,\n  });\n\n  const rowEls = g.map((grp, idx) => {\n    const k = rows - 1 - idx;\n    const born = interpolate(t, [rowBorn[k], rowBorn[k] + 10], [0, 1], {\n      ...CLAMP,\n      easing: EASE_OUT,\n    });\n    const isNew = k === 0 ? enter : born;\n    const y = firstTop + shift(k) * rowH;\n    const topness = Math.max(0, 1 - Math.abs(rowsAnim - 1 - k));\n    const text = (k === rows - 1 ? prefix : \"\") + grp;\n    const comma = k > 0;\n    return (\n      <div key={`r${k}`}>\n        <div\n          style={{\n            position: \"absolute\",\n            left: 0,\n            width: W,\n            top: y,\n            height: rowH,\n            overflow: \"hidden\",\n          }}\n        >\n          <div\n            style={{\n              position: \"absolute\",\n              right: W - colRight,\n              top: (isNew - 1) * rowH,\n              height: rowH,\n              display: \"flex\",\n              alignItems: \"baseline\",\n              fontFamily: plex.fontFamily,\n              fontWeight: 500,\n              fontSize: F,\n              lineHeight: `${rowH}px`,\n              letterSpacing: `${TRACK}em`,\n              fontFeatureSettings: '\"tnum\" 1, \"lnum\" 1',\n              whiteSpace: \"pre\",\n            }}\n          >\n            <span style={{ position: \"relative\", color: c.ink }}>\n              {text}\n              <span\n                aria-hidden\n                style={{\n                  position: \"absolute\",\n                  inset: 0,\n                  opacity: topness,\n                  color: accent ?? c.accent,\n                }}\n              >\n                {text}\n              </span>\n            </span>\n            {comma ? (\n              <span\n                style={{\n                  position: \"absolute\",\n                  left: \"100%\",\n                  color: c.comma,\n                  letterSpacing: 0,\n                }}\n              >\n                ,\n              </span>\n            ) : null}\n          </div>\n        </div>\n        <div\n          style={{\n            position: \"absolute\",\n            left: margin + (W - margin * 2) * (1 - isNew),\n            right: margin,\n            top: y + rowH,\n            height: 1,\n            background: c.rule,\n          }}\n        />\n      </div>\n    );\n  });\n\n  const labelEl = label ? (\n    <div\n      style={{\n        position: \"absolute\",\n        left: margin,\n        width: labelW,\n        top: ruleY + labelSize * 0.9,\n        height: labelSize * 1.3 * 3,\n        overflow: \"hidden\",\n      }}\n    >\n      <div\n        style={{\n          fontFamily: plex.fontFamily,\n          fontWeight: 400,\n          fontSize: labelSize,\n          lineHeight: 1.3,\n          letterSpacing: \"-0.005em\",\n          color: c.muted,\n          textWrap: \"balance\",\n          transform: `translateY(${((1 - labelP) * labelSize * 4).toFixed(2)}px)`,\n        }}\n      >\n        {label}\n      </div>\n    </div>\n  ) : null;\n\n  return (\n    <AbsoluteFill style={{ background: stage, overflow: \"hidden\" }}>\n      <div\n        style={{\n          position: \"absolute\",\n          left: margin,\n          top: ruleY,\n          width: (W - margin * 2) * ruleP,\n          height: Math.max(2, H * 0.003),\n          background: c.ink,\n        }}\n      />\n      {rowEls}\n      {labelEl}\n    </AbsoluteFill>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/row-count.tsx"
    }
  ],
  "type": "registry:component"
}
