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