{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "skeleton",
  "title": "Skeleton",
  "description": "A component to display placeholder content while in a loading state.",
  "dependencies": [
    "react-native-reanimated"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "ui/skeleton.tsx",
      "content": "import { createContext, useContext, useEffect, useMemo } from \"react\";\nimport Animated, {\n  type SharedValue,\n  useAnimatedStyle,\n  useSharedValue,\n  withRepeat,\n  withTiming,\n} from \"react-native-reanimated\";\nimport { cn } from \"@/lib/utils\";\n\n// Constants\nconst ANIMATION_DURATION = 1000;\nconst MIN_OPACITY = 0.4;\nconst MAX_OPACITY = 1;\n\n// Types\ntype InternalSkeletonGroupContextType = {\n  opacity: SharedValue<number>;\n};\n\ntype SkeletonGroupProps = {\n  children: React.ReactNode;\n};\n\ntype SkeletonProps = React.ComponentProps<typeof Animated.View>;\n\n// Context\nconst SkeletonGroupContext =\n  createContext<InternalSkeletonGroupContextType | null>(null);\n\nconst useSkeletonGroupContext = () => useContext(SkeletonGroupContext);\n\n// Components\nexport const SkeletonGroup = ({ children }: SkeletonGroupProps) => {\n  const opacity = useSharedValue(MIN_OPACITY);\n\n  useEffect(() => {\n    opacity.value = withRepeat(\n      withTiming(MAX_OPACITY, { duration: ANIMATION_DURATION }),\n      -1,\n      true\n    );\n  }, [opacity]);\n\n  const ctx = useMemo(() => {\n    return {\n      opacity,\n    };\n  }, [opacity]);\n\n  return (\n    <SkeletonGroupContext.Provider value={ctx}>\n      {children}\n    </SkeletonGroupContext.Provider>\n  );\n};\n\nexport const Skeleton = ({ className, ...props }: SkeletonProps) => {\n  const groupContext = useSkeletonGroupContext();\n  const localOpacity = useSharedValue(MIN_OPACITY);\n  const opacity = groupContext?.opacity ?? localOpacity;\n\n  useEffect(() => {\n    if (groupContext) {\n      return;\n    }\n\n    localOpacity.value = withRepeat(\n      withTiming(MAX_OPACITY, { duration: ANIMATION_DURATION }),\n      -1,\n      true\n    );\n  }, [groupContext, localOpacity]);\n\n  const animatedStyle = useAnimatedStyle(() => {\n    return {\n      opacity: opacity.value,\n    };\n  });\n\n  return (\n    <Animated.View\n      className={cn(\"w-full rounded-md bg-accent\", className)}\n      data-slot=\"skeleton\"\n      style={animatedStyle}\n      {...props}\n    />\n  );\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
