framer-motion
Version:
A simple and powerful JavaScript animation library
69 lines (66 loc) • 2.04 kB
JavaScript
"use client";
import { jsx } from 'react/jsx-runtime';
import { useState, useRef, useEffect } from 'react';
import { LazyContext } from '../../context/LazyContext.mjs';
import { loadFeatures } from '../../motion/features/load-features.mjs';
/**
* 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, domAnimation } from "framer-motion"
*
* function App() {
* return (
* <LazyMotion features={domAnimation}>
* <m.div animate={{ scale: 2 }} />
* </LazyMotion>
* )
* }
*
* // Asynchronous loading
* import { LazyMotion, m } from "framer-motion"
*
* function App() {
* return (
* <LazyMotion features={() => import('./path/to/domAnimation')}>
* <m.div animate={{ scale: 2 }} />
* </LazyMotion>
* )
* }
* ```
*
* @public
*/
function LazyMotion({ children, features, strict = false }) {
const [, setIsLoaded] = useState(!isLazyBundle(features));
const loadedRenderer = useRef(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 (jsx(LazyContext.Provider, { value: { renderer: loadedRenderer.current, strict }, children: children }));
}
function isLazyBundle(features) {
return typeof features === "function";
}
export { LazyMotion };