import { LinearGradient } from 'expo-linear-gradient' import React, { useState, createContext, useContext } from 'react' import { View, StyleSheet } from 'react-native' import { View as MotiView } from '../components' import { AnimatePresence, MotiTransitionProp } from '../core' import { DEFAULT_SKELETON_SIZE as DEFAULT_SIZE, defaultDarkColors, defaultLightColors, baseColors, } from './shared' import { MotiSkeletonProps } from './types' export default function Skeleton(props: MotiSkeletonProps) { const skeletonGroupContext = useContext(SkeletonGroupContext) const { radius = 8, children, show = skeletonGroupContext ?? !children, width, height = children ? undefined : DEFAULT_SIZE, boxHeight, colorMode = 'dark', colors = colorMode === 'dark' ? defaultDarkColors : defaultLightColors, backgroundColor = colors[0] ?? colors[1] ?? baseColors[colorMode]?.secondary, backgroundSize = 6, disableExitAnimation, transition, } = props const [measuredWidth, setMeasuredWidth] = useState(0) const getBorderRadius = () => { if (radius === 'square') { return 0 } if (radius === 'round') { return 99999 } return radius } const borderRadius = getBorderRadius() const getOuterHeight = () => { if (boxHeight != null) return boxHeight if (show && !children) { return height } return undefined } const outerHeight = getOuterHeight() return ( {children} {show && ( { if (measuredWidth === nativeEvent.layout.width) return setMeasuredWidth(nativeEvent.layout.width) }} pointerEvents="none" > )} ) } const AnimatedGradient = React.memo( function AnimatedGradient({ measuredWidth, colors, backgroundSize, transition = {}, }: { measuredWidth: number colors: string[] backgroundSize: number transition?: MotiTransitionProp }) { return ( ) }, function propsAreEqual(prev, next) { if (prev.measuredWidth !== next.measuredWidth) return false if (prev.backgroundSize !== next.backgroundSize) return false const didColorsChange = prev.colors.some((color, index) => { return color !== next.colors[index] }) if (didColorsChange) return false // transition changes will not be respected, but it'll be in the key return true } ) const SkeletonGroupContext = createContext(undefined) function SkeletonGroup({ children, show, }: { children: React.ReactNode /** * If `true`, all `Skeleton` children components will be shown. * * If `false`, the `Skeleton` children will be hidden. */ show: boolean }) { return ( {children} ) } Skeleton.Group = SkeletonGroup