All files / src/components/LazyMotion index.tsx

100% Statements 27/27
100% Branches 6/6
100% Functions 4/4
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 8330x 30x 30x 30x                                                                               30x 24x 24x             24x 18x 18x 18x     24x 5x 1x 1x 1x 1x         24x                       53x    
import * as React from "react"
import { useEffect, useRef, useState } from "react"
import { LazyContext } from "../../context/LazyContext"
import { loadFeatures } from "../../motion/features/definitions"
import { FeatureBundle, LazyFeatureBundle } from "../../motion/features/types"
import { CreateVisualElement } from "../../render/types"
import { LazyProps } from "./types"
 
/**
 * Used in conjunction with the `m` component to reduce bundle size.
 *
 * `m` is a version of the `motion` component that only loads functionality
 * critical for the initial render.
 *
 * `LazyMotion` can then be used to either synchronously or asynchronously
 * load animation and gesture support.
 *
 * ```jsx
 * // Synchronous loading
 * import { LazyMotion, m, domAnimations } from "framer-motion"
 *
 * function App() {
 *   return (
 *     <LazyMotion features={domAnimations}>
 *       <m.div animate={{ scale: 2 }} />
 *     </LazyMotion>
 *   )
 * }
 *
 * // Asynchronous loading
 * import { LazyMotion, m } from "framer-motion"
 *
 * function App() {
 *   return (
 *     <LazyMotion features={() => import('./path/to/domAnimations')}>
 *       <m.div animate={{ scale: 2 }} />
 *     </LazyMotion>
 *   )
 * }
 * ```
 *
 * @public
 */
export function LazyMotion({ children, features, strict = false }: LazyProps) {
    const [, setIsLoaded] = useState(!isLazyBundle(features))
    const loadedRenderer = useRef<undefined | CreateVisualElement<any>>(
        undefined
    )
 
    /**
     * If this is a synchronous load, load features immediately
     */
    if (!isLazyBundle(features)) {
        const { renderer, ...loadedFeatures } = features
        loadedRenderer.current = renderer
        loadFeatures(loadedFeatures)
    }
 
    useEffect(() => {
        if (isLazyBundle(features)) {
            features().then(({ renderer, ...loadedFeatures }) => {
                loadFeatures(loadedFeatures)
                loadedRenderer.current = renderer
                setIsLoaded(true)
            })
        }
    }, [])
 
    return (
        <LazyContext.Provider
            value={{ renderer: loadedRenderer.current, strict }}
        >
            {children}
        </LazyContext.Provider>
    )
}
 
function isLazyBundle(
    features: FeatureBundle | LazyFeatureBundle
): features is LazyFeatureBundle {
    return typeof features === "function"
}