{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "skeleton",
  "title": "UI Skeleton",
  "description": "A skeleton→content crossfade whose loading/loaded state is a pure function of the timeline. The Skeleton renderer is pure (reads no frame); only the composed SkeletonBlock shimmer reads it. SkeletonStyle opacities sum to 1 so the box never dims; real children sit in normal flow and the placeholder (a lines/card layout or a custom node) is an absolute overlay.",
  "dependencies": ["remotion"],
  "registryDependencies": ["@remocn/remocn-ui", "@remocn/skeleton-block"],
  "files": [
    {
      "path": "registry/remocn-ui/skeleton/index.tsx",
      "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { SkeletonBlock } from \"@/components/remocn/skeleton-block\";\nimport { type RemocnTheme, useRemocnTheme } from \"@/lib/remocn-ui\";\n\nexport type SkeletonState = \"loading\" | \"loaded\";\n\nexport type SkeletonLayout = \"lines\" | \"card\";\n\nexport interface SkeletonProps {\n  state?: SkeletonState;\n  style?: SkeletonStyle;\n  children?: ReactNode;\n  placeholder?: ReactNode;\n  layout?: SkeletonLayout;\n  speed?: number;\n  theme?: Partial<RemocnTheme>;\n  className?: string;\n}\n\nexport interface SkeletonStyle {\n  skeletonOpacity: number;\n  contentOpacity: number;\n}\n\nexport function skeletonStyle(state: SkeletonState): SkeletonStyle {\n  switch (state) {\n    case \"loaded\":\n      return { skeletonOpacity: 0, contentOpacity: 1 };\n    default:\n      return { skeletonOpacity: 1, contentOpacity: 0 };\n  }\n}\n\nfunction LayoutPlaceholder({\n  layout,\n  speed,\n  baseColor,\n}: {\n  layout: SkeletonLayout;\n  speed?: number;\n  baseColor: string;\n}) {\n  const shimmer = { speed, baseColor };\n  if (layout === \"card\") {\n    return (\n      <div style={{ display: \"flex\", gap: 14, alignItems: \"center\" }}>\n        {}\n        <SkeletonBlock\n          width={48}\n          height={48}\n          radius={24}\n          flexShrink={0}\n          {...shimmer}\n        />\n        <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n          <SkeletonBlock width={180} height={14} {...shimmer} />\n          <SkeletonBlock width={120} height={14} {...shimmer} />\n        </div>\n      </div>\n    );\n  }\n  return (\n    <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n      <SkeletonBlock width={260} height={14} {...shimmer} />\n      <SkeletonBlock width={240} height={14} {...shimmer} />\n      <SkeletonBlock width={160} height={14} {...shimmer} />\n    </div>\n  );\n}\n\nexport function Skeleton({\n  state = \"loading\",\n  style,\n  children,\n  placeholder,\n  layout = \"lines\",\n  speed,\n  theme: themeOverride,\n  className,\n}: SkeletonProps) {\n  const theme = useRemocnTheme(themeOverride, \"light\");\n  const v = style ?? skeletonStyle(state);\n\n  const placeholderLayer = placeholder ?? (\n    <LayoutPlaceholder layout={layout} speed={speed} baseColor={theme.muted} />\n  );\n\n  return (\n    <div\n      className={className}\n      style={{\n        position: \"relative\",\n        display: \"inline-block\",\n        fontFamily:\n          \"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif\",\n      }}\n    >\n      {}\n      <div style={{ opacity: v.contentOpacity }}>{children}</div>\n      {}\n      <div\n        style={{\n          position: \"absolute\",\n          inset: 0,\n          opacity: v.skeletonOpacity,\n          pointerEvents: \"none\",\n        }}\n      >\n        {placeholderLayer}\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/skeleton.tsx"
    },
    {
      "path": "registry/remocn-ui/skeleton/use-skeleton-transition.ts",
      "content": "\"use client\";\n\nimport {\n  type SkeletonState,\n  type SkeletonStyle,\n  skeletonStyle,\n} from \"@/components/remocn/skeleton\";\nimport { easings, type Step, useStateTransition } from \"@/lib/remocn-ui\";\n\nexport const DEFAULT_DURATION = 12;\n\nexport function tweenSkeletonStyle(\n  a: SkeletonStyle,\n  b: SkeletonStyle,\n  t: number,\n): SkeletonStyle {\n  return {\n    skeletonOpacity:\n      a.skeletonOpacity + (b.skeletonOpacity - a.skeletonOpacity) * t,\n    contentOpacity:\n      a.contentOpacity + (b.contentOpacity - a.contentOpacity) * t,\n  };\n}\n\nexport interface SkeletonTransitionOptions {\n  mode?: \"light\" | \"dark\";\n  speed?: number;\n  defaultDuration?: number;\n}\n\nexport function useSkeletonTransition(\n  steps: Step<SkeletonState>[],\n  opts: SkeletonTransitionOptions = {},\n): SkeletonStyle {\n  const { speed = 1, defaultDuration = DEFAULT_DURATION } = opts;\n  const { from, to, progress } = useStateTransition(\n    steps,\n    \"loading\",\n    speed,\n    defaultDuration,\n  );\n  const t = easings.out(progress);\n  return tweenSkeletonStyle(skeletonStyle(from), skeletonStyle(to), t);\n}\n",
      "type": "registry:component",
      "target": "components/remocn/use-skeleton-transition.ts"
    }
  ],
  "type": "registry:component"
}
