import shouldForwardProp from "@styled-system/should-forward-prop"; import { AnimatePresence, domAnimation, LazyMotion, m as Motion } from "framer-motion"; import React, { useRef } from "react"; import { keyframes, styled } from "styled-components"; import { borderRadius, layout, space } from "styled-system"; import { animationHandler, animationMap, animationVariants, appearAnimation, disappearAnimation, } from "../../util/animationToolkit"; import { animation as ANIMATION, SkeletonCoreProps, SkeletonProps, variant as VARIANT } from "./types"; const waves = keyframes` from { left: -150px; } to { left: 100%; } `; const pulse = keyframes` 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } `; const AnimationWrapper = styled(Motion.div)` position: relative; will-change: opacity; opacity: 0; &.appear { animation: ${appearAnimation} 0.3s ease-in-out forwards; } &.disappear { animation: ${disappearAnimation} 0.3s ease-in-out forwards; } `; const SkeletonWrapper = styled.div.withConfig({ shouldForwardProp })` position: relative; ${layout} ${space} overflow: hidden; `; const Root = styled.div.withConfig({ shouldForwardProp })` min-height: 20px; display: block; background-color: ${({ theme, isDark }) => (isDark ? theme.colors.inputSecondary : theme.colors.backgroundDisabled)}; border-radius: ${({ variant, theme }) => variant === VARIANT.CIRCLE ? theme.radii.circle : variant === VARIANT.ROUND ? theme.radii.default : theme.radii.small}; ${layout} ${space} ${borderRadius} `; const Pulse = styled(Root)` animation: ${pulse} 2s infinite ease-out; transform: translate3d(0, 0, 0); `; const Waves = styled(Root)` overflow: hidden; transform: translate3d(0, 0, 0); &:before { content: ""; position: absolute; background-image: linear-gradient(90deg, transparent, rgba(243, 243, 243, 0.5), transparent); top: 0; left: -150px; height: 100%; width: 150px; animation: ${waves} 2s cubic-bezier(0.4, 0, 0.2, 1) infinite; } `; const Skeleton: React.FC> = ({ variant = VARIANT.RECT, animation = ANIMATION.PULSE, ...props }) => { if (animation === ANIMATION.WAVES) { return ; } return ; }; export const SkeletonCore: React.FC> = ({ variant = VARIANT.RECT, animation = ANIMATION.PULSE, isDataReady = false, children, wrapperProps, skeletonTop = "0", skeletonLeft = "0", width, height, mr, ml, ...props }) => { const animationRef = useRef(null); const skeletonRef = useRef(null); return ( {isDataReady && ( animationHandler(animationRef.current)} {...animationMap} variants={animationVariants} transition={{ duration: 0.3 }} > {children} )} {!isDataReady && ( animationHandler(skeletonRef.current)} {...animationMap} variants={animationVariants} transition={{ duration: 0.3 }} > {animation === ANIMATION.WAVES ? ( ) : ( )} )} ); }; export default Skeleton;