{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "skeleton-card",
  "title": "Card skeleton",
  "description": "Styled skeleton: the Card set. 5 decorative skeleton variations (MediaSkeleton, ProfileSkeleton, ListSkeleton, GridSkeleton, ArticleSkeleton) on the ai2 token system, powered by framer-motion, reduced-motion aware and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "motion@^12.42.2"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/skeleton-card.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\nimport { motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Card skeleton family: 5 composite card layouts (media card, profile card, list, grid, article). The difference is not in the ANIMATION but in the STRUCTURE - every variant builds a different card skeleton; the pulse is the same calm token pulse in all of them. The widths are fixed and the delays index-derived (NO Math.random, deterministic SSR). Colour comes ONLY from tokens. Skeletons are decorative: the root is aria-hidden. The pulse stops under reduced motion. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\ntype Props = React.ComponentProps<\"div\"> & { size?: StyledSize }\n\n/* Shared calm pulse (framer-motion, NO keyframes). */\nfunction Block({ className, delay = 0 }: { className?: string; delay?: number }) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.span\n      className={cn(\"block rounded-md bg-secondary\", className)}\n      animate={reduce ? undefined : { opacity: [0.5, 1, 0.5] }}\n      transition={\n        reduce ? undefined : { duration: 1.6, ease: \"easeInOut\", repeat: Infinity, delay }\n      }\n    />\n  )\n}\n\nconst line: Record<StyledSize, string> = {\n  sm: \"h-2.5\",\n  md: \"h-3\",\n  lg: \"h-3.5\",\n  xl: \"h-4\",\n}\n\nconst head: Record<StyledSize, string> = {\n  sm: \"h-3.5\",\n  md: \"h-4\",\n  lg: \"h-5\",\n  xl: \"h-6\",\n}\n\nconst media: Record<StyledSize, string> = {\n  sm: \"h-20\",\n  md: \"h-28\",\n  lg: \"h-36\",\n  xl: \"h-44\",\n}\n\nconst avatar: Record<StyledSize, string> = {\n  sm: \"size-8\",\n  md: \"size-10\",\n  lg: \"size-12\",\n  xl: \"size-14\",\n}\n\nconst gap: Record<StyledSize, string> = {\n  sm: \"gap-2\",\n  md: \"gap-3\",\n  lg: \"gap-3.5\",\n  xl: \"gap-4\",\n}\n\nconst pad: Record<StyledSize, string> = {\n  sm: \"p-3\",\n  md: \"p-4\",\n  lg: \"p-5\",\n  xl: \"p-6\",\n}\n\n/* Her varyantin kabugu: token yuzeyi + kenarlik. */\nconst card = \"flex w-full flex-col rounded-xl border border-border bg-card\"\n\n/* Media: an image area on top, a title plus two lines below. */\nexport function MediaSkeleton({ className, size = \"md\", ...props }: Props) {\n  return (\n    <div\n      data-slot=\"styled-skeleton\"\n      aria-hidden=\"true\"\n      className={cn(card, \"overflow-hidden\", className)}\n      {...props}\n    >\n      <Block className={cn(\"w-full rounded-none\", media[size])} />\n      <div className={cn(\"flex flex-col\", gap[size], pad[size])}>\n        <Block className={cn(\"w-2/3 rounded-lg\", head[size])} delay={0.12} />\n        <Block className={cn(\"w-full\", line[size])} delay={0.24} />\n        <Block className={cn(\"w-4/5\", line[size])} delay={0.36} />\n      </div>\n    </div>\n  )\n}\n\n/* Profile: a centred avatar, a name, a second line and two action pills. */\nexport function ProfileSkeleton({ className, size = \"md\", ...props }: Props) {\n  return (\n    <div\n      data-slot=\"styled-skeleton\"\n      aria-hidden=\"true\"\n      className={cn(card, \"items-center text-center\", gap[size], pad[size], className)}\n      {...props}\n    >\n      <Block className={cn(\"rounded-full\", avatar[size])} />\n      <Block className={cn(\"w-1/2 rounded-lg\", head[size])} delay={0.12} />\n      <Block className={cn(\"w-2/3\", line[size])} delay={0.24} />\n      <div className={cn(\"flex w-full items-center justify-center\", gap[size])}>\n        <Block className={cn(\"w-20 rounded-full\", head[size])} delay={0.36} />\n        <Block className={cn(\"w-20 rounded-full\", head[size])} delay={0.48} />\n      </div>\n    </div>\n  )\n}\n\n/* List: n rows, each a small thumbnail plus two lines of text. */\nexport function ListSkeleton({\n  className,\n  size = \"md\",\n  count = 3,\n  ...props\n}: Props & { count?: number }) {\n  return (\n    <div\n      data-slot=\"styled-skeleton\"\n      aria-hidden=\"true\"\n      className={cn(card, gap[size], pad[size], className)}\n      {...props}\n    >\n      {Array.from({ length: count }, (_, i) => (\n        <div key={i} className={cn(\"flex w-full items-center\", gap[size])}>\n          <Block className={cn(\"shrink-0 rounded-lg\", avatar[size])} delay={i * 0.12} />\n          <div className={cn(\"flex min-w-0 flex-1 flex-col\", \"gap-2\")}>\n            <Block className={cn(\"w-1/2\", head[size])} delay={i * 0.12 + 0.06} />\n            <Block className={cn(\"w-4/5\", line[size])} delay={i * 0.12 + 0.12} />\n          </div>\n        </div>\n      ))}\n    </div>\n  )\n}\n\n/* Grid: a two-column tile grid, each tile an image plus one line. */\nexport function GridSkeleton({\n  className,\n  size = \"md\",\n  count = 4,\n  ...props\n}: Props & { count?: number }) {\n  return (\n    <div\n      data-slot=\"styled-skeleton\"\n      aria-hidden=\"true\"\n      className={cn(\"grid w-full grid-cols-2\", gap[size], className)}\n      {...props}\n    >\n      {Array.from({ length: count }, (_, i) => (\n        <div key={i} className={cn(card, \"overflow-hidden\")}>\n          <Block className={cn(\"w-full rounded-none\", media[size])} delay={i * 0.12} />\n          <div className={cn(\"flex flex-col gap-2\", pad[size])}>\n            <Block className={cn(\"w-3/4\", head[size])} delay={i * 0.12 + 0.06} />\n            <Block className={cn(\"w-1/2\", line[size])} delay={i * 0.12 + 0.12} />\n          </div>\n        </div>\n      ))}\n    </div>\n  )\n}\n\n/* Article: kapak gorseli, baslik, paragraf ve yazar satiri. */\nexport function ArticleSkeleton({ className, size = \"md\", ...props }: Props) {\n  return (\n    <div\n      data-slot=\"styled-skeleton\"\n      aria-hidden=\"true\"\n      className={cn(card, \"overflow-hidden\", className)}\n      {...props}\n    >\n      <Block className={cn(\"w-full rounded-none\", media[size])} />\n      <div className={cn(\"flex flex-col\", gap[size], pad[size])}>\n        <Block className={cn(\"w-5/6 rounded-lg\", head[size])} delay={0.12} />\n        <Block className={cn(\"w-full\", line[size])} delay={0.24} />\n        <Block className={cn(\"w-11/12\", line[size])} delay={0.36} />\n        <Block className={cn(\"w-3/5\", line[size])} delay={0.48} />\n        <div className={cn(\"mt-1 flex items-center border-t border-border pt-3\", gap[size])}>\n          <Block className={cn(\"shrink-0 rounded-full\", avatar[size])} delay={0.6} />\n          <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n            <Block className={cn(\"w-1/3\", line[size])} delay={0.66} />\n            <Block className={cn(\"w-1/4\", line[size])} delay={0.72} />\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/skeleton-card.tsx"
    }
  ],
  "categories": [
    "styled",
    "skeleton"
  ],
  "type": "registry:component"
}