{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "skeleton-reveal",
  "title": "Skeleton Reveal",
  "description": "A skeleton that pulses while loading, then cross-fades and un-blurs into the real content.",
  "files": [
    {
      "path": "components/spectrumui/skeleton-reveal.tsx",
      "content": "/**\n * Spectrum UI — SkeletonReveal\n *\n * A placeholder that pulses while loading, then cross-fades and un-blurs into\n * the real content. The motion is the \"Skeleton loader and reveal\" recipe from\n * transitions.dev (Jakub Antalík): its namespaced `t-skel` CSS is embedded\n * verbatim (with one change — the content layer stays in flow so the slot\n * sizes itself), and this component drives the `is-pulsing` / `is-revealed` /\n * `is-resetting` classes from a `loading` prop, including the snap-back when\n * loading starts again.\n *\n * Dependencies: @/lib/utils\n *\n * @example\n * <SkeletonReveal loading={isLoading} skeleton={<RowSkeleton />}>\n *   <Row user={user} />\n * </SkeletonReveal>\n */\n\n'use client';\n\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface SkeletonRevealProps {\n  /** While true the skeleton shows and pulses; flipping to false reveals the content */\n  loading: boolean;\n  /** Placeholder layer — bring your own bars and avatar */\n  skeleton: React.ReactNode;\n  /** Real content, rendered in the same slot */\n  children: React.ReactNode;\n  /** Pulse cycles before settling. Default 1 */\n  pulseCount?: number;\n  /** One pulse cycle in ms. Default 1000 */\n  pulseDuration?: number;\n  /** Cross-fade duration in ms. Default 400 */\n  revealDuration?: number;\n  className?: string;\n}\n\n// transitions.dev · skeleton-loader-and-reveal · content layer kept in flow\nconst CSS = `\n.t-skel{position:relative}\n.t-skel-skeleton{position:absolute;inset:0;z-index:1;opacity:1;filter:blur(0);transition:opacity var(--reveal-dur) var(--reveal-ease),filter var(--reveal-dur) var(--reveal-ease)}\n.t-skel-content{position:relative;z-index:2;opacity:0;filter:blur(var(--reveal-blur));transition:opacity var(--reveal-dur) var(--reveal-ease),filter var(--reveal-dur) var(--reveal-ease)}\n.t-skel.is-revealed .t-skel-skeleton{opacity:0;filter:blur(var(--reveal-blur))}\n.t-skel.is-revealed .t-skel-content{opacity:1;filter:blur(0)}\n.t-skel.is-resetting .t-skel-skeleton,.t-skel.is-resetting .t-skel-content{transition:none !important}\n.t-skel-skeleton.is-pulsing > *{animation:t-skel-pulse var(--pulse-dur) ease-in-out var(--pulse-count)}\n@keyframes t-skel-pulse{0%,100%{opacity:1}50%{opacity:var(--pulse-min)}}\n@media (prefers-reduced-motion: reduce){.t-skel-skeleton,.t-skel-content{transition:none !important}.t-skel-skeleton.is-pulsing > *{animation:none !important}}\n`;\n\nexport function SkeletonReveal({\n  loading,\n  skeleton,\n  children,\n  pulseCount = 1,\n  pulseDuration = 1000,\n  revealDuration = 400,\n  className,\n}: SkeletonRevealProps) {\n  const ref = React.useRef<HTMLDivElement>(null);\n  const wasLoading = React.useRef(loading);\n\n  // Replaying: snap back to the skeleton without animating the reverse\n  React.useLayoutEffect(() => {\n    const el = ref.current;\n    if (!el) return;\n    if (loading && !wasLoading.current) {\n      el.classList.add('is-resetting');\n      void el.offsetWidth;\n      el.classList.remove('is-resetting');\n    }\n    wasLoading.current = loading;\n  }, [loading]);\n\n  return (\n    <>\n      <style>{CSS}</style>\n      <div\n        ref={ref}\n        className={cn('t-skel', !loading && 'is-revealed', className)}\n        aria-busy={loading || undefined}\n        style={\n          {\n            '--pulse-dur': `${pulseDuration}ms`,\n            '--pulse-count': pulseCount,\n            '--pulse-min': 0.5,\n            '--reveal-dur': `${revealDuration}ms`,\n            '--reveal-blur': '2px',\n            '--reveal-ease': 'ease-in-out',\n          } as React.CSSProperties\n        }\n      >\n        <div className={cn('t-skel-skeleton', loading && 'is-pulsing')} aria-hidden>\n          {skeleton}\n        </div>\n        <div className=\"t-skel-content\">{children}</div>\n      </div>\n    </>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/spectrumui/skeleton-reveal.tsx"
    }
  ],
  "type": "registry:component"
}
