{
  "name": "fps",
  "type": "registry:ui",
  "dependencies": [],
  "files": [
    {
      "path": "ui/fps.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport * as ReactDOM from \"react-dom\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst fpsVariants = cva(\n  \"z-50 flex shrink-0 items-center gap-2 rounded-sm border bg-background/80 px-3 py-1.5 font-mono text-sm text-foreground backdrop-blur-sm\",\n  {\n    variants: {\n      strategy: {\n        fixed: \"fixed\",\n        absolute: \"absolute\",\n      },\n      position: {\n        \"top-left\": \"top-4 left-4\",\n        \"top-right\": \"top-4 right-4\",\n        \"bottom-left\": \"bottom-4 left-4\",\n        \"bottom-right\": \"right-4 bottom-4\",\n      },\n      status: {\n        good: \"text-primary\",\n        warning: \"text-orange-500\",\n        error: \"text-destructive\",\n      },\n    },\n    defaultVariants: {\n      strategy: \"fixed\",\n      position: \"top-right\",\n      status: \"good\",\n    },\n  },\n);\n\ninterface FpsProps\n  extends\n    React.ComponentProps<\"div\">,\n    Omit<VariantProps<typeof fpsVariants>, \"status\"> {\n  label?: string;\n  updateInterval?: number;\n  warningThreshold?: number;\n  errorThreshold?: number;\n  portalContainer?: Element | DocumentFragment | null;\n  enabled?: boolean;\n}\n\nfunction Fps(props: FpsProps) {\n  const {\n    strategy = \"fixed\",\n    position = \"top-right\",\n    label,\n    updateInterval = 500,\n    warningThreshold = 30,\n    errorThreshold = 20,\n    portalContainer: portalContainerProp,\n    enabled = true,\n    className,\n    ...fpsProps\n  } = props;\n\n  const [mounted, setMounted] = React.useState(false);\n  const [fps, setFps] = React.useState(0);\n  const frameCountRef = React.useRef(0);\n  const lastTimeRef = React.useRef(performance.now());\n  const animationFrameRef = React.useRef<number | null>(null);\n  const updateTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(\n    null,\n  );\n\n  React.useLayoutEffect(() => setMounted(true), []);\n\n  const status = React.useMemo(() => {\n    if (fps < errorThreshold) return \"error\";\n    if (fps < warningThreshold) return \"warning\";\n    return \"good\";\n  }, [fps, errorThreshold, warningThreshold]);\n\n  React.useEffect(() => {\n    if (!enabled || typeof window === \"undefined\") return;\n\n    function measureFps() {\n      const now = performance.now();\n      const delta = now - lastTimeRef.current;\n      frameCountRef.current += 1;\n\n      if (delta >= updateInterval) {\n        const currentFps = Math.round((frameCountRef.current * 1000) / delta);\n        setFps(currentFps);\n        frameCountRef.current = 0;\n        lastTimeRef.current = now;\n      }\n\n      animationFrameRef.current = requestAnimationFrame(measureFps);\n    }\n\n    animationFrameRef.current = requestAnimationFrame(measureFps);\n\n    return () => {\n      if (animationFrameRef.current !== null) {\n        cancelAnimationFrame(animationFrameRef.current);\n      }\n      if (updateTimeoutRef.current !== null) {\n        clearTimeout(updateTimeoutRef.current);\n      }\n    };\n  }, [enabled, updateInterval]);\n\n  if (!enabled) return null;\n\n  const portalContainer =\n    strategy === \"absolute\"\n      ? null\n      : (portalContainerProp ?? (mounted ? globalThis.document?.body : null));\n\n  const Comp = (\n    <div\n      aria-hidden=\"true\"\n      data-slot=\"fps\"\n      {...fpsProps}\n      className={cn(fpsVariants({ strategy, position, status }), className)}\n    >\n      {label && (\n        <span data-slot=\"fps-label\" className=\"text-muted-foreground\">\n          {label}:\n        </span>\n      )}\n      <span data-slot=\"fps-value\">{fps}</span>\n    </div>\n  );\n\n  return portalContainer ? ReactDOM.createPortal(Comp, portalContainer) : Comp;\n}\n\nexport { Fps };\n",
      "target": ""
    }
  ]
}