{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "skeleton",
  "type": "registry:ui",
  "dependencies": [
    "class-variance-authority",
    "clsx",
    "tailwind-merge"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "skeleton.tsx",
      "target": "components/ui/skeleton.tsx",
      "type": "registry:ui",
      "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n/* One animation, not two: the sheen alone. `content-visibility` lets the\n * browser skip a skeleton that has scrolled out of view, animation included,\n * and a full-page skeleton is dozens of these. */\nexport const skeletonVariants = cva(\n  \"skeleton-sheen relative block bg-sunken [content-visibility:auto]\",\n  {\n    variants: {\n      variant: {\n        text: \"h-4 w-full rounded-md\",\n        circle: \"aspect-square rounded-full\",\n        rect: \"rounded-lg\",\n      },\n    },\n    defaultVariants: { variant: \"text\" },\n  },\n);\n\nexport interface SkeletonProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof skeletonVariants> {\n  width?: string | number;\n  height?: string | number;\n  radius?: string | number;\n}\n\nexport const Skeleton = React.forwardRef<HTMLDivElement, SkeletonProps>(\n  ({ className, variant, width, height, radius, style, ...props }, ref) => (\n    <div\n      ref={ref}\n      aria-hidden=\"true\"\n      data-usva-skeleton=\"\"\n      className={cn(skeletonVariants({ variant }), className)}\n      style={{\n        width,\n        height,\n        ...(radius !== undefined ? { borderRadius: radius } : {}),\n        ...style,\n      }}\n      {...props}\n    />\n  ),\n);\nSkeleton.displayName = \"Skeleton\";\n\nexport interface SkeletonMirrorProps\n  extends React.HTMLAttributes<HTMLDivElement> {\n  /** When false, renders children normally. Defaults to true. */\n  loading?: boolean;\n  label?: string;\n  children: React.ReactNode;\n}\n\n/**\n * Auto-infers a skeleton from the layout it wraps: it renders your real\n * children with every leaf greyed into a shaped block, so the placeholder\n * always matches the component. One glimmer travels around the outline of the\n * whole skeleton (plus a soft sweep across it), not per block.\n */\nexport const SkeletonMirror = React.forwardRef<\n  HTMLDivElement,\n  SkeletonMirrorProps\n>(\n  (\n    { className, loading = true, label = \"Loading\", children, ...props },\n    ref,\n  ) => {\n    if (!loading) return <>{children}</>;\n    return (\n      <div\n        ref={ref}\n        role=\"status\"\n        aria-label={label}\n        className={cn(\n          \"skeleton-sheen relative isolate select-none rounded-2xl\",\n          className,\n        )}\n        {...props}\n      >\n        <div aria-hidden=\"true\" className=\"skeleton-mask pointer-events-none\">\n          {children}\n        </div>\n        <span\n          aria-hidden=\"true\"\n          className=\"pointer-events-none absolute inset-0 animate-shimmer motion-reduce:animate-none\"\n        />\n        <span className=\"sr-only\">{label}</span>\n      </div>\n    );\n  },\n);\nSkeletonMirror.displayName = \"SkeletonMirror\";\n"
    },
    {
      "path": "skeleton-group.tsx",
      "target": "components/ui/skeleton-group.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface SkeletonGroupProps\n  extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const SkeletonGroup = React.forwardRef<\n  HTMLDivElement,\n  SkeletonGroupProps\n>(({ className, children, ...props }, ref) => {\n  const groupRef = React.useRef<HTMLDivElement>(null);\n\n  React.useImperativeHandle(ref, () => groupRef.current as HTMLDivElement, []);\n\n  React.useLayoutEffect(() => {\n    const group = groupRef.current;\n    if (!group) return;\n\n    const skeletons = new Set<HTMLElement>();\n\n    const measure = () => {\n      const groupRect = group.getBoundingClientRect();\n      group.style.setProperty(\n        \"--usva-skeleton-group-width\",\n        `${groupRect.width}px`,\n      );\n      group.style.setProperty(\n        \"--usva-skeleton-group-height\",\n        `${groupRect.height}px`,\n      );\n\n      for (const skeleton of skeletons) {\n        const skeletonRect = skeleton.getBoundingClientRect();\n        skeleton.style.setProperty(\n          \"--usva-skeleton-offset-x\",\n          `${skeletonRect.left - groupRect.left}px`,\n        );\n        skeleton.style.setProperty(\n          \"--usva-skeleton-offset-y\",\n          `${skeletonRect.top - groupRect.top}px`,\n        );\n      }\n    };\n\n    const resizeObserver =\n      typeof ResizeObserver === \"undefined\"\n        ? null\n        : new ResizeObserver(measure);\n    resizeObserver?.observe(group);\n\n    const syncSkeletons = () => {\n      const next = new Set(\n        Array.from(\n          group.querySelectorAll<HTMLElement>(\"[data-usva-skeleton]\"),\n        ).filter(\n          (skeleton) => skeleton.closest(\"[data-skeleton-group]\") === group,\n        ),\n      );\n\n      for (const skeleton of skeletons) {\n        if (next.has(skeleton)) continue;\n        resizeObserver?.unobserve(skeleton);\n        delete skeleton.dataset.skeletonGrouped;\n        skeleton.style.removeProperty(\"--usva-skeleton-offset-x\");\n        skeleton.style.removeProperty(\"--usva-skeleton-offset-y\");\n        skeletons.delete(skeleton);\n      }\n\n      for (const skeleton of next) {\n        if (skeletons.has(skeleton)) continue;\n        skeletons.add(skeleton);\n        skeleton.dataset.skeletonGrouped = \"\";\n        resizeObserver?.observe(skeleton);\n      }\n\n      measure();\n    };\n\n    syncSkeletons();\n\n    const mutationObserver =\n      typeof MutationObserver === \"undefined\"\n        ? null\n        : new MutationObserver(syncSkeletons);\n    mutationObserver?.observe(group, { childList: true, subtree: true });\n    window.addEventListener(\"resize\", measure);\n\n    return () => {\n      mutationObserver?.disconnect();\n      resizeObserver?.disconnect();\n      window.removeEventListener(\"resize\", measure);\n      group.style.removeProperty(\"--usva-skeleton-group-width\");\n      group.style.removeProperty(\"--usva-skeleton-group-height\");\n      for (const skeleton of skeletons) {\n        delete skeleton.dataset.skeletonGrouped;\n        skeleton.style.removeProperty(\"--usva-skeleton-offset-x\");\n        skeleton.style.removeProperty(\"--usva-skeleton-offset-y\");\n      }\n    };\n  }, []);\n\n  return (\n    <div\n      ref={groupRef}\n      data-skeleton-group=\"\"\n      className={cn(\"skeleton-group\", className)}\n      {...props}\n    >\n      {children}\n    </div>\n  );\n});\nSkeletonGroup.displayName = \"SkeletonGroup\";\n"
    }
  ]
}