first commit
This commit is contained in:
9
node_modules/framer-motion/dist/es/motion/features/Feature.mjs
generated
vendored
Normal file
9
node_modules/framer-motion/dist/es/motion/features/Feature.mjs
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
class Feature {
|
||||
constructor(node) {
|
||||
this.isMounted = false;
|
||||
this.node = node;
|
||||
}
|
||||
update() { }
|
||||
}
|
||||
|
||||
export { Feature };
|
||||
36
node_modules/framer-motion/dist/es/motion/features/animation/exit.mjs
generated
vendored
Normal file
36
node_modules/framer-motion/dist/es/motion/features/animation/exit.mjs
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Feature } from '../Feature.mjs';
|
||||
|
||||
let id = 0;
|
||||
class ExitAnimationFeature extends Feature {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.id = id++;
|
||||
}
|
||||
update() {
|
||||
if (!this.node.presenceContext)
|
||||
return;
|
||||
const { isPresent, onExitComplete } = this.node.presenceContext;
|
||||
const { isPresent: prevIsPresent } = this.node.prevPresenceContext || {};
|
||||
if (!this.node.animationState || isPresent === prevIsPresent) {
|
||||
return;
|
||||
}
|
||||
const exitAnimation = this.node.animationState.setActive("exit", !isPresent);
|
||||
if (onExitComplete && !isPresent) {
|
||||
exitAnimation.then(() => {
|
||||
onExitComplete(this.id);
|
||||
});
|
||||
}
|
||||
}
|
||||
mount() {
|
||||
const { register, onExitComplete } = this.node.presenceContext || {};
|
||||
if (onExitComplete) {
|
||||
onExitComplete(this.id);
|
||||
}
|
||||
if (register) {
|
||||
this.unmount = register(this.id);
|
||||
}
|
||||
}
|
||||
unmount() { }
|
||||
}
|
||||
|
||||
export { ExitAnimationFeature };
|
||||
40
node_modules/framer-motion/dist/es/motion/features/animation/index.mjs
generated
vendored
Normal file
40
node_modules/framer-motion/dist/es/motion/features/animation/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { isAnimationControls } from '../../../animation/utils/is-animation-controls.mjs';
|
||||
import { createAnimationState } from '../../../render/utils/animation-state.mjs';
|
||||
import { Feature } from '../Feature.mjs';
|
||||
|
||||
class AnimationFeature extends Feature {
|
||||
/**
|
||||
* We dynamically generate the AnimationState manager as it contains a reference
|
||||
* to the underlying animation library. We only want to load that if we load this,
|
||||
* so people can optionally code split it out using the `m` component.
|
||||
*/
|
||||
constructor(node) {
|
||||
super(node);
|
||||
node.animationState || (node.animationState = createAnimationState(node));
|
||||
}
|
||||
updateAnimationControlsSubscription() {
|
||||
const { animate } = this.node.getProps();
|
||||
if (isAnimationControls(animate)) {
|
||||
this.unmountControls = animate.subscribe(this.node);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Subscribe any provided AnimationControls to the component's VisualElement
|
||||
*/
|
||||
mount() {
|
||||
this.updateAnimationControlsSubscription();
|
||||
}
|
||||
update() {
|
||||
const { animate } = this.node.getProps();
|
||||
const { animate: prevAnimate } = this.node.prevProps || {};
|
||||
if (animate !== prevAnimate) {
|
||||
this.updateAnimationControlsSubscription();
|
||||
}
|
||||
}
|
||||
unmount() {
|
||||
this.node.animationState.reset();
|
||||
this.unmountControls?.();
|
||||
}
|
||||
}
|
||||
|
||||
export { AnimationFeature };
|
||||
13
node_modules/framer-motion/dist/es/motion/features/animations.mjs
generated
vendored
Normal file
13
node_modules/framer-motion/dist/es/motion/features/animations.mjs
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { AnimationFeature } from './animation/index.mjs';
|
||||
import { ExitAnimationFeature } from './animation/exit.mjs';
|
||||
|
||||
const animations = {
|
||||
animation: {
|
||||
Feature: AnimationFeature,
|
||||
},
|
||||
exit: {
|
||||
Feature: ExitAnimationFeature,
|
||||
},
|
||||
};
|
||||
|
||||
export { animations };
|
||||
28
node_modules/framer-motion/dist/es/motion/features/definitions.mjs
generated
vendored
Normal file
28
node_modules/framer-motion/dist/es/motion/features/definitions.mjs
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
const featureProps = {
|
||||
animation: [
|
||||
"animate",
|
||||
"variants",
|
||||
"whileHover",
|
||||
"whileTap",
|
||||
"exit",
|
||||
"whileInView",
|
||||
"whileFocus",
|
||||
"whileDrag",
|
||||
],
|
||||
exit: ["exit"],
|
||||
drag: ["drag", "dragControls"],
|
||||
focus: ["whileFocus"],
|
||||
hover: ["whileHover", "onHoverStart", "onHoverEnd"],
|
||||
tap: ["whileTap", "onTap", "onTapStart", "onTapCancel"],
|
||||
pan: ["onPan", "onPanStart", "onPanSessionStart", "onPanEnd"],
|
||||
inView: ["whileInView", "onViewportEnter", "onViewportLeave"],
|
||||
layout: ["layout", "layoutId"],
|
||||
};
|
||||
const featureDefinitions = {};
|
||||
for (const key in featureProps) {
|
||||
featureDefinitions[key] = {
|
||||
isEnabled: (props) => featureProps[key].some((name) => !!props[name]),
|
||||
};
|
||||
}
|
||||
|
||||
export { featureDefinitions };
|
||||
17
node_modules/framer-motion/dist/es/motion/features/drag.mjs
generated
vendored
Normal file
17
node_modules/framer-motion/dist/es/motion/features/drag.mjs
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { DragGesture } from '../../gestures/drag/index.mjs';
|
||||
import { PanGesture } from '../../gestures/pan/index.mjs';
|
||||
import { MeasureLayout } from './layout/MeasureLayout.mjs';
|
||||
import { HTMLProjectionNode } from '../../projection/node/HTMLProjectionNode.mjs';
|
||||
|
||||
const drag = {
|
||||
pan: {
|
||||
Feature: PanGesture,
|
||||
},
|
||||
drag: {
|
||||
Feature: DragGesture,
|
||||
ProjectionNode: HTMLProjectionNode,
|
||||
MeasureLayout,
|
||||
},
|
||||
};
|
||||
|
||||
export { drag };
|
||||
21
node_modules/framer-motion/dist/es/motion/features/gestures.mjs
generated
vendored
Normal file
21
node_modules/framer-motion/dist/es/motion/features/gestures.mjs
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import { HoverGesture } from '../../gestures/hover.mjs';
|
||||
import { FocusGesture } from '../../gestures/focus.mjs';
|
||||
import { PressGesture } from '../../gestures/press.mjs';
|
||||
import { InViewFeature } from './viewport/index.mjs';
|
||||
|
||||
const gestureAnimations = {
|
||||
inView: {
|
||||
Feature: InViewFeature,
|
||||
},
|
||||
tap: {
|
||||
Feature: PressGesture,
|
||||
},
|
||||
focus: {
|
||||
Feature: FocusGesture,
|
||||
},
|
||||
hover: {
|
||||
Feature: HoverGesture,
|
||||
},
|
||||
};
|
||||
|
||||
export { gestureAnimations };
|
||||
11
node_modules/framer-motion/dist/es/motion/features/layout.mjs
generated
vendored
Normal file
11
node_modules/framer-motion/dist/es/motion/features/layout.mjs
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { HTMLProjectionNode } from '../../projection/node/HTMLProjectionNode.mjs';
|
||||
import { MeasureLayout } from './layout/MeasureLayout.mjs';
|
||||
|
||||
const layout = {
|
||||
layout: {
|
||||
ProjectionNode: HTMLProjectionNode,
|
||||
MeasureLayout,
|
||||
},
|
||||
};
|
||||
|
||||
export { layout };
|
||||
147
node_modules/framer-motion/dist/es/motion/features/layout/MeasureLayout.mjs
generated
vendored
Normal file
147
node_modules/framer-motion/dist/es/motion/features/layout/MeasureLayout.mjs
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
"use client";
|
||||
import { jsx } from 'react/jsx-runtime';
|
||||
import { frame, microtask } from 'motion-dom';
|
||||
import { useContext, Component } from 'react';
|
||||
import { usePresence } from '../../../components/AnimatePresence/use-presence.mjs';
|
||||
import { LayoutGroupContext } from '../../../context/LayoutGroupContext.mjs';
|
||||
import { SwitchLayoutGroupContext } from '../../../context/SwitchLayoutGroupContext.mjs';
|
||||
import { globalProjectionState } from '../../../projection/node/state.mjs';
|
||||
import { correctBorderRadius } from '../../../projection/styles/scale-border-radius.mjs';
|
||||
import { correctBoxShadow } from '../../../projection/styles/scale-box-shadow.mjs';
|
||||
import { addScaleCorrector } from '../../../projection/styles/scale-correction.mjs';
|
||||
|
||||
/**
|
||||
* Track whether we've taken any snapshots yet. If not,
|
||||
* we can safely skip notification of didUpdate.
|
||||
*
|
||||
* Difficult to capture in a test but to prevent flickering
|
||||
* we must set this to true either on update or unmount.
|
||||
* Running `next-env/layout-id` in Safari will show this behaviour if broken.
|
||||
*/
|
||||
let hasTakenAnySnapshot = false;
|
||||
class MeasureLayoutWithContext extends Component {
|
||||
/**
|
||||
* This only mounts projection nodes for components that
|
||||
* need measuring, we might want to do it for all components
|
||||
* in order to incorporate transforms
|
||||
*/
|
||||
componentDidMount() {
|
||||
const { visualElement, layoutGroup, switchLayoutGroup, layoutId } = this.props;
|
||||
const { projection } = visualElement;
|
||||
addScaleCorrector(defaultScaleCorrectors);
|
||||
if (projection) {
|
||||
if (layoutGroup.group)
|
||||
layoutGroup.group.add(projection);
|
||||
if (switchLayoutGroup && switchLayoutGroup.register && layoutId) {
|
||||
switchLayoutGroup.register(projection);
|
||||
}
|
||||
if (hasTakenAnySnapshot) {
|
||||
projection.root.didUpdate();
|
||||
}
|
||||
projection.addEventListener("animationComplete", () => {
|
||||
this.safeToRemove();
|
||||
});
|
||||
projection.setOptions({
|
||||
...projection.options,
|
||||
onExitComplete: () => this.safeToRemove(),
|
||||
});
|
||||
}
|
||||
globalProjectionState.hasEverUpdated = true;
|
||||
}
|
||||
getSnapshotBeforeUpdate(prevProps) {
|
||||
const { layoutDependency, visualElement, drag, isPresent } = this.props;
|
||||
const { projection } = visualElement;
|
||||
if (!projection)
|
||||
return null;
|
||||
/**
|
||||
* TODO: We use this data in relegate to determine whether to
|
||||
* promote a previous element. There's no guarantee its presence data
|
||||
* will have updated by this point - if a bug like this arises it will
|
||||
* have to be that we markForRelegation and then find a new lead some other way,
|
||||
* perhaps in didUpdate
|
||||
*/
|
||||
projection.isPresent = isPresent;
|
||||
hasTakenAnySnapshot = true;
|
||||
if (drag ||
|
||||
prevProps.layoutDependency !== layoutDependency ||
|
||||
layoutDependency === undefined ||
|
||||
prevProps.isPresent !== isPresent) {
|
||||
projection.willUpdate();
|
||||
}
|
||||
else {
|
||||
this.safeToRemove();
|
||||
}
|
||||
if (prevProps.isPresent !== isPresent) {
|
||||
if (isPresent) {
|
||||
projection.promote();
|
||||
}
|
||||
else if (!projection.relegate()) {
|
||||
/**
|
||||
* If there's another stack member taking over from this one,
|
||||
* it's in charge of the exit animation and therefore should
|
||||
* be in charge of the safe to remove. Otherwise we call it here.
|
||||
*/
|
||||
frame.postRender(() => {
|
||||
const stack = projection.getStack();
|
||||
if (!stack || !stack.members.length) {
|
||||
this.safeToRemove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
componentDidUpdate() {
|
||||
const { projection } = this.props.visualElement;
|
||||
if (projection) {
|
||||
projection.root.didUpdate();
|
||||
microtask.postRender(() => {
|
||||
if (!projection.currentAnimation && projection.isLead()) {
|
||||
this.safeToRemove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
componentWillUnmount() {
|
||||
const { visualElement, layoutGroup, switchLayoutGroup: promoteContext, } = this.props;
|
||||
const { projection } = visualElement;
|
||||
hasTakenAnySnapshot = true;
|
||||
if (projection) {
|
||||
projection.scheduleCheckAfterUnmount();
|
||||
if (layoutGroup && layoutGroup.group)
|
||||
layoutGroup.group.remove(projection);
|
||||
if (promoteContext && promoteContext.deregister)
|
||||
promoteContext.deregister(projection);
|
||||
}
|
||||
}
|
||||
safeToRemove() {
|
||||
const { safeToRemove } = this.props;
|
||||
safeToRemove && safeToRemove();
|
||||
}
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function MeasureLayout(props) {
|
||||
const [isPresent, safeToRemove] = usePresence();
|
||||
const layoutGroup = useContext(LayoutGroupContext);
|
||||
return (jsx(MeasureLayoutWithContext, { ...props, layoutGroup: layoutGroup, switchLayoutGroup: useContext(SwitchLayoutGroupContext), isPresent: isPresent, safeToRemove: safeToRemove }));
|
||||
}
|
||||
const defaultScaleCorrectors = {
|
||||
borderRadius: {
|
||||
...correctBorderRadius,
|
||||
applyTo: [
|
||||
"borderTopLeftRadius",
|
||||
"borderTopRightRadius",
|
||||
"borderBottomLeftRadius",
|
||||
"borderBottomRightRadius",
|
||||
],
|
||||
},
|
||||
borderTopLeftRadius: correctBorderRadius,
|
||||
borderTopRightRadius: correctBorderRadius,
|
||||
borderBottomLeftRadius: correctBorderRadius,
|
||||
borderBottomRightRadius: correctBorderRadius,
|
||||
boxShadow: correctBoxShadow,
|
||||
};
|
||||
|
||||
export { MeasureLayout };
|
||||
12
node_modules/framer-motion/dist/es/motion/features/load-features.mjs
generated
vendored
Normal file
12
node_modules/framer-motion/dist/es/motion/features/load-features.mjs
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { featureDefinitions } from './definitions.mjs';
|
||||
|
||||
function loadFeatures(features) {
|
||||
for (const key in features) {
|
||||
featureDefinitions[key] = {
|
||||
...featureDefinitions[key],
|
||||
...features[key],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { loadFeatures };
|
||||
72
node_modules/framer-motion/dist/es/motion/features/viewport/index.mjs
generated
vendored
Normal file
72
node_modules/framer-motion/dist/es/motion/features/viewport/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Feature } from '../Feature.mjs';
|
||||
import { observeIntersection } from './observers.mjs';
|
||||
|
||||
const thresholdNames = {
|
||||
some: 0,
|
||||
all: 1,
|
||||
};
|
||||
class InViewFeature extends Feature {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.hasEnteredView = false;
|
||||
this.isInView = false;
|
||||
}
|
||||
startObserver() {
|
||||
this.unmount();
|
||||
const { viewport = {} } = this.node.getProps();
|
||||
const { root, margin: rootMargin, amount = "some", once } = viewport;
|
||||
const options = {
|
||||
root: root ? root.current : undefined,
|
||||
rootMargin,
|
||||
threshold: typeof amount === "number" ? amount : thresholdNames[amount],
|
||||
};
|
||||
const onIntersectionUpdate = (entry) => {
|
||||
const { isIntersecting } = entry;
|
||||
/**
|
||||
* If there's been no change in the viewport state, early return.
|
||||
*/
|
||||
if (this.isInView === isIntersecting)
|
||||
return;
|
||||
this.isInView = isIntersecting;
|
||||
/**
|
||||
* Handle hasEnteredView. If this is only meant to run once, and
|
||||
* element isn't visible, early return. Otherwise set hasEnteredView to true.
|
||||
*/
|
||||
if (once && !isIntersecting && this.hasEnteredView) {
|
||||
return;
|
||||
}
|
||||
else if (isIntersecting) {
|
||||
this.hasEnteredView = true;
|
||||
}
|
||||
if (this.node.animationState) {
|
||||
this.node.animationState.setActive("whileInView", isIntersecting);
|
||||
}
|
||||
/**
|
||||
* Use the latest committed props rather than the ones in scope
|
||||
* when this observer is created
|
||||
*/
|
||||
const { onViewportEnter, onViewportLeave } = this.node.getProps();
|
||||
const callback = isIntersecting ? onViewportEnter : onViewportLeave;
|
||||
callback && callback(entry);
|
||||
};
|
||||
return observeIntersection(this.node.current, options, onIntersectionUpdate);
|
||||
}
|
||||
mount() {
|
||||
this.startObserver();
|
||||
}
|
||||
update() {
|
||||
if (typeof IntersectionObserver === "undefined")
|
||||
return;
|
||||
const { props, prevProps } = this.node;
|
||||
const hasOptionsChanged = ["amount", "margin", "root"].some(hasViewportOptionChanged(props, prevProps));
|
||||
if (hasOptionsChanged) {
|
||||
this.startObserver();
|
||||
}
|
||||
}
|
||||
unmount() { }
|
||||
}
|
||||
function hasViewportOptionChanged({ viewport = {} }, { viewport: prevViewport = {} } = {}) {
|
||||
return (name) => viewport[name] !== prevViewport[name];
|
||||
}
|
||||
|
||||
export { InViewFeature };
|
||||
49
node_modules/framer-motion/dist/es/motion/features/viewport/observers.mjs
generated
vendored
Normal file
49
node_modules/framer-motion/dist/es/motion/features/viewport/observers.mjs
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Map an IntersectionHandler callback to an element. We only ever make one handler for one
|
||||
* element, so even though these handlers might all be triggered by different
|
||||
* observers, we can keep them in the same map.
|
||||
*/
|
||||
const observerCallbacks = new WeakMap();
|
||||
/**
|
||||
* Multiple observers can be created for multiple element/document roots. Each with
|
||||
* different settings. So here we store dictionaries of observers to each root,
|
||||
* using serialised settings (threshold/margin) as lookup keys.
|
||||
*/
|
||||
const observers = new WeakMap();
|
||||
const fireObserverCallback = (entry) => {
|
||||
const callback = observerCallbacks.get(entry.target);
|
||||
callback && callback(entry);
|
||||
};
|
||||
const fireAllObserverCallbacks = (entries) => {
|
||||
entries.forEach(fireObserverCallback);
|
||||
};
|
||||
function initIntersectionObserver({ root, ...options }) {
|
||||
const lookupRoot = root || document;
|
||||
/**
|
||||
* If we don't have an observer lookup map for this root, create one.
|
||||
*/
|
||||
if (!observers.has(lookupRoot)) {
|
||||
observers.set(lookupRoot, {});
|
||||
}
|
||||
const rootObservers = observers.get(lookupRoot);
|
||||
const key = JSON.stringify(options);
|
||||
/**
|
||||
* If we don't have an observer for this combination of root and settings,
|
||||
* create one.
|
||||
*/
|
||||
if (!rootObservers[key]) {
|
||||
rootObservers[key] = new IntersectionObserver(fireAllObserverCallbacks, { root, ...options });
|
||||
}
|
||||
return rootObservers[key];
|
||||
}
|
||||
function observeIntersection(element, options, callback) {
|
||||
const rootInteresectionObserver = initIntersectionObserver(options);
|
||||
observerCallbacks.set(element, callback);
|
||||
rootInteresectionObserver.observe(element);
|
||||
return () => {
|
||||
observerCallbacks.delete(element);
|
||||
rootInteresectionObserver.unobserve(element);
|
||||
};
|
||||
}
|
||||
|
||||
export { observeIntersection };
|
||||
108
node_modules/framer-motion/dist/es/motion/index.mjs
generated
vendored
Normal file
108
node_modules/framer-motion/dist/es/motion/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
"use client";
|
||||
import { jsxs, jsx } from 'react/jsx-runtime';
|
||||
import { warning, invariant } from 'motion-utils';
|
||||
import { forwardRef, useContext } from 'react';
|
||||
import { LayoutGroupContext } from '../context/LayoutGroupContext.mjs';
|
||||
import { LazyContext } from '../context/LazyContext.mjs';
|
||||
import { MotionConfigContext } from '../context/MotionConfigContext.mjs';
|
||||
import { MotionContext } from '../context/MotionContext/index.mjs';
|
||||
import { useCreateMotionContext } from '../context/MotionContext/create.mjs';
|
||||
import { useRender } from '../render/dom/use-render.mjs';
|
||||
import { isSVGComponent } from '../render/dom/utils/is-svg-component.mjs';
|
||||
import { useHTMLVisualState } from '../render/html/use-html-visual-state.mjs';
|
||||
import { useSVGVisualState } from '../render/svg/use-svg-visual-state.mjs';
|
||||
import { isBrowser } from '../utils/is-browser.mjs';
|
||||
import { featureDefinitions } from './features/definitions.mjs';
|
||||
import { loadFeatures } from './features/load-features.mjs';
|
||||
import { motionComponentSymbol } from './utils/symbol.mjs';
|
||||
import { useMotionRef } from './utils/use-motion-ref.mjs';
|
||||
import { useVisualElement } from './utils/use-visual-element.mjs';
|
||||
|
||||
/**
|
||||
* Create a `motion` component.
|
||||
*
|
||||
* This function accepts a Component argument, which can be either a string (ie "div"
|
||||
* for `motion.div`), or an actual React component.
|
||||
*
|
||||
* Alongside this is a config option which provides a way of rendering the provided
|
||||
* component "offline", or outside the React render cycle.
|
||||
*/
|
||||
function createMotionComponent(Component, { forwardMotionProps = false } = {}, preloadedFeatures, createVisualElement) {
|
||||
preloadedFeatures && loadFeatures(preloadedFeatures);
|
||||
const useVisualState = isSVGComponent(Component)
|
||||
? useSVGVisualState
|
||||
: useHTMLVisualState;
|
||||
function MotionDOMComponent(props, externalRef) {
|
||||
/**
|
||||
* If we need to measure the element we load this functionality in a
|
||||
* separate class component in order to gain access to getSnapshotBeforeUpdate.
|
||||
*/
|
||||
let MeasureLayout;
|
||||
const configAndProps = {
|
||||
...useContext(MotionConfigContext),
|
||||
...props,
|
||||
layoutId: useLayoutId(props),
|
||||
};
|
||||
const { isStatic } = configAndProps;
|
||||
const context = useCreateMotionContext(props);
|
||||
const visualState = useVisualState(props, isStatic);
|
||||
if (!isStatic && isBrowser) {
|
||||
useStrictMode(configAndProps, preloadedFeatures);
|
||||
const layoutProjection = getProjectionFunctionality(configAndProps);
|
||||
MeasureLayout = layoutProjection.MeasureLayout;
|
||||
/**
|
||||
* Create a VisualElement for this component. A VisualElement provides a common
|
||||
* interface to renderer-specific APIs (ie DOM/Three.js etc) as well as
|
||||
* providing a way of rendering to these APIs outside of the React render loop
|
||||
* for more performant animations and interactions
|
||||
*/
|
||||
context.visualElement = useVisualElement(Component, visualState, configAndProps, createVisualElement, layoutProjection.ProjectionNode);
|
||||
}
|
||||
/**
|
||||
* The mount order and hierarchy is specific to ensure our element ref
|
||||
* is hydrated by the time features fire their effects.
|
||||
*/
|
||||
return (jsxs(MotionContext.Provider, { value: context, children: [MeasureLayout && context.visualElement ? (jsx(MeasureLayout, { visualElement: context.visualElement, ...configAndProps })) : null, useRender(Component, props, useMotionRef(visualState, context.visualElement, externalRef), visualState, isStatic, forwardMotionProps)] }));
|
||||
}
|
||||
MotionDOMComponent.displayName = `motion.${typeof Component === "string"
|
||||
? Component
|
||||
: `create(${Component.displayName ?? Component.name ?? ""})`}`;
|
||||
const ForwardRefMotionComponent = forwardRef(MotionDOMComponent);
|
||||
ForwardRefMotionComponent[motionComponentSymbol] = Component;
|
||||
return ForwardRefMotionComponent;
|
||||
}
|
||||
function useLayoutId({ layoutId }) {
|
||||
const layoutGroupId = useContext(LayoutGroupContext).id;
|
||||
return layoutGroupId && layoutId !== undefined
|
||||
? layoutGroupId + "-" + layoutId
|
||||
: layoutId;
|
||||
}
|
||||
function useStrictMode(configAndProps, preloadedFeatures) {
|
||||
const isStrict = useContext(LazyContext).strict;
|
||||
/**
|
||||
* If we're in development mode, check to make sure we're not rendering a motion component
|
||||
* as a child of LazyMotion, as this will break the file-size benefits of using it.
|
||||
*/
|
||||
if (process.env.NODE_ENV !== "production" &&
|
||||
preloadedFeatures &&
|
||||
isStrict) {
|
||||
const strictMessage = "You have rendered a `motion` component within a `LazyMotion` component. This will break tree shaking. Import and render a `m` component instead.";
|
||||
configAndProps.ignoreStrict
|
||||
? warning(false, strictMessage, "lazy-strict-mode")
|
||||
: invariant(false, strictMessage, "lazy-strict-mode");
|
||||
}
|
||||
}
|
||||
function getProjectionFunctionality(props) {
|
||||
const { drag, layout } = featureDefinitions;
|
||||
if (!drag && !layout)
|
||||
return {};
|
||||
const combined = { ...drag, ...layout };
|
||||
return {
|
||||
MeasureLayout: drag?.isEnabled(props) || layout?.isEnabled(props)
|
||||
? combined.MeasureLayout
|
||||
: undefined,
|
||||
ProjectionNode: combined.ProjectionNode,
|
||||
};
|
||||
}
|
||||
|
||||
export { createMotionComponent };
|
||||
11
node_modules/framer-motion/dist/es/motion/utils/is-forced-motion-value.mjs
generated
vendored
Normal file
11
node_modules/framer-motion/dist/es/motion/utils/is-forced-motion-value.mjs
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { transformProps } from 'motion-dom';
|
||||
import { scaleCorrectors } from '../../projection/styles/scale-correction.mjs';
|
||||
|
||||
function isForcedMotionValue(key, { layout, layoutId }) {
|
||||
return (transformProps.has(key) ||
|
||||
key.startsWith("origin") ||
|
||||
((layout || layoutId !== undefined) &&
|
||||
(!!scaleCorrectors[key] || key === "opacity")));
|
||||
}
|
||||
|
||||
export { isForcedMotionValue };
|
||||
12
node_modules/framer-motion/dist/es/motion/utils/is-motion-component.mjs
generated
vendored
Normal file
12
node_modules/framer-motion/dist/es/motion/utils/is-motion-component.mjs
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { motionComponentSymbol } from './symbol.mjs';
|
||||
|
||||
/**
|
||||
* Checks if a component is a `motion` component.
|
||||
*/
|
||||
function isMotionComponent(component) {
|
||||
return (component !== null &&
|
||||
typeof component === "object" &&
|
||||
motionComponentSymbol in component);
|
||||
}
|
||||
|
||||
export { isMotionComponent };
|
||||
3
node_modules/framer-motion/dist/es/motion/utils/symbol.mjs
generated
vendored
Normal file
3
node_modules/framer-motion/dist/es/motion/utils/symbol.mjs
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
const motionComponentSymbol = Symbol.for("motionComponentSymbol");
|
||||
|
||||
export { motionComponentSymbol };
|
||||
17
node_modules/framer-motion/dist/es/motion/utils/unwrap-motion-component.mjs
generated
vendored
Normal file
17
node_modules/framer-motion/dist/es/motion/utils/unwrap-motion-component.mjs
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { isMotionComponent } from './is-motion-component.mjs';
|
||||
import { motionComponentSymbol } from './symbol.mjs';
|
||||
|
||||
/**
|
||||
* Unwraps a `motion` component and returns either a string for `motion.div` or
|
||||
* the React component for `motion(Component)`.
|
||||
*
|
||||
* If the component is not a `motion` component it returns undefined.
|
||||
*/
|
||||
function unwrapMotionComponent(component) {
|
||||
if (isMotionComponent(component)) {
|
||||
return component[motionComponentSymbol];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export { unwrapMotionComponent };
|
||||
38
node_modules/framer-motion/dist/es/motion/utils/use-motion-ref.mjs
generated
vendored
Normal file
38
node_modules/framer-motion/dist/es/motion/utils/use-motion-ref.mjs
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
"use client";
|
||||
import { useCallback } from 'react';
|
||||
import { isRefObject } from '../../utils/is-ref-object.mjs';
|
||||
|
||||
/**
|
||||
* Creates a ref function that, when called, hydrates the provided
|
||||
* external ref and VisualElement.
|
||||
*/
|
||||
function useMotionRef(visualState, visualElement, externalRef) {
|
||||
return useCallback((instance) => {
|
||||
if (instance) {
|
||||
visualState.onMount && visualState.onMount(instance);
|
||||
}
|
||||
if (visualElement) {
|
||||
if (instance) {
|
||||
visualElement.mount(instance);
|
||||
}
|
||||
else {
|
||||
visualElement.unmount();
|
||||
}
|
||||
}
|
||||
if (externalRef) {
|
||||
if (typeof externalRef === "function") {
|
||||
externalRef(instance);
|
||||
}
|
||||
else if (isRefObject(externalRef)) {
|
||||
externalRef.current = instance;
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Include externalRef in dependencies to ensure the callback updates
|
||||
* when the ref changes, allowing proper ref forwarding.
|
||||
*/
|
||||
[visualElement]);
|
||||
}
|
||||
|
||||
export { useMotionRef };
|
||||
140
node_modules/framer-motion/dist/es/motion/utils/use-visual-element.mjs
generated
vendored
Normal file
140
node_modules/framer-motion/dist/es/motion/utils/use-visual-element.mjs
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
"use client";
|
||||
import { useContext, useRef, useInsertionEffect, useEffect } from 'react';
|
||||
import { optimizedAppearDataAttribute } from '../../animation/optimized-appear/data-id.mjs';
|
||||
import { LazyContext } from '../../context/LazyContext.mjs';
|
||||
import { MotionConfigContext } from '../../context/MotionConfigContext.mjs';
|
||||
import { MotionContext } from '../../context/MotionContext/index.mjs';
|
||||
import { PresenceContext } from '../../context/PresenceContext.mjs';
|
||||
import { SwitchLayoutGroupContext } from '../../context/SwitchLayoutGroupContext.mjs';
|
||||
import { isRefObject } from '../../utils/is-ref-object.mjs';
|
||||
import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';
|
||||
|
||||
function useVisualElement(Component, visualState, props, createVisualElement, ProjectionNodeConstructor) {
|
||||
const { visualElement: parent } = useContext(MotionContext);
|
||||
const lazyContext = useContext(LazyContext);
|
||||
const presenceContext = useContext(PresenceContext);
|
||||
const reducedMotionConfig = useContext(MotionConfigContext).reducedMotion;
|
||||
const visualElementRef = useRef(null);
|
||||
/**
|
||||
* If we haven't preloaded a renderer, check to see if we have one lazy-loaded
|
||||
*/
|
||||
createVisualElement =
|
||||
createVisualElement ||
|
||||
lazyContext.renderer;
|
||||
if (!visualElementRef.current && createVisualElement) {
|
||||
visualElementRef.current = createVisualElement(Component, {
|
||||
visualState,
|
||||
parent,
|
||||
props,
|
||||
presenceContext,
|
||||
blockInitialAnimation: presenceContext
|
||||
? presenceContext.initial === false
|
||||
: false,
|
||||
reducedMotionConfig,
|
||||
});
|
||||
}
|
||||
const visualElement = visualElementRef.current;
|
||||
/**
|
||||
* Load Motion gesture and animation features. These are rendered as renderless
|
||||
* components so each feature can optionally make use of React lifecycle methods.
|
||||
*/
|
||||
const initialLayoutGroupConfig = useContext(SwitchLayoutGroupContext);
|
||||
if (visualElement &&
|
||||
!visualElement.projection &&
|
||||
ProjectionNodeConstructor &&
|
||||
(visualElement.type === "html" || visualElement.type === "svg")) {
|
||||
createProjectionNode(visualElementRef.current, props, ProjectionNodeConstructor, initialLayoutGroupConfig);
|
||||
}
|
||||
const isMounted = useRef(false);
|
||||
useInsertionEffect(() => {
|
||||
/**
|
||||
* Check the component has already mounted before calling
|
||||
* `update` unnecessarily. This ensures we skip the initial update.
|
||||
*/
|
||||
if (visualElement && isMounted.current) {
|
||||
visualElement.update(props, presenceContext);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Cache this value as we want to know whether HandoffAppearAnimations
|
||||
* was present on initial render - it will be deleted after this.
|
||||
*/
|
||||
const optimisedAppearId = props[optimizedAppearDataAttribute];
|
||||
const wantsHandoff = useRef(Boolean(optimisedAppearId) &&
|
||||
!window.MotionHandoffIsComplete?.(optimisedAppearId) &&
|
||||
window.MotionHasOptimisedAnimation?.(optimisedAppearId));
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
if (!visualElement)
|
||||
return;
|
||||
isMounted.current = true;
|
||||
window.MotionIsMounted = true;
|
||||
visualElement.updateFeatures();
|
||||
visualElement.scheduleRenderMicrotask();
|
||||
/**
|
||||
* Ideally this function would always run in a useEffect.
|
||||
*
|
||||
* However, if we have optimised appear animations to handoff from,
|
||||
* it needs to happen synchronously to ensure there's no flash of
|
||||
* incorrect styles in the event of a hydration error.
|
||||
*
|
||||
* So if we detect a situtation where optimised appear animations
|
||||
* are running, we use useLayoutEffect to trigger animations.
|
||||
*/
|
||||
if (wantsHandoff.current && visualElement.animationState) {
|
||||
visualElement.animationState.animateChanges();
|
||||
}
|
||||
});
|
||||
useEffect(() => {
|
||||
if (!visualElement)
|
||||
return;
|
||||
if (!wantsHandoff.current && visualElement.animationState) {
|
||||
visualElement.animationState.animateChanges();
|
||||
}
|
||||
if (wantsHandoff.current) {
|
||||
// This ensures all future calls to animateChanges() in this component will run in useEffect
|
||||
queueMicrotask(() => {
|
||||
window.MotionHandoffMarkAsComplete?.(optimisedAppearId);
|
||||
});
|
||||
wantsHandoff.current = false;
|
||||
}
|
||||
/**
|
||||
* Now we've finished triggering animations for this element we
|
||||
* can wipe the enteringChildren set for the next render.
|
||||
*/
|
||||
visualElement.enteringChildren = undefined;
|
||||
});
|
||||
return visualElement;
|
||||
}
|
||||
function createProjectionNode(visualElement, props, ProjectionNodeConstructor, initialPromotionConfig) {
|
||||
const { layoutId, layout, drag, dragConstraints, layoutScroll, layoutRoot, layoutCrossfade, } = props;
|
||||
visualElement.projection = new ProjectionNodeConstructor(visualElement.latestValues, props["data-framer-portal-id"]
|
||||
? undefined
|
||||
: getClosestProjectingNode(visualElement.parent));
|
||||
visualElement.projection.setOptions({
|
||||
layoutId,
|
||||
layout,
|
||||
alwaysMeasureLayout: Boolean(drag) || (dragConstraints && isRefObject(dragConstraints)),
|
||||
visualElement,
|
||||
/**
|
||||
* TODO: Update options in an effect. This could be tricky as it'll be too late
|
||||
* to update by the time layout animations run.
|
||||
* We also need to fix this safeToRemove by linking it up to the one returned by usePresence,
|
||||
* ensuring it gets called if there's no potential layout animations.
|
||||
*
|
||||
*/
|
||||
animationType: typeof layout === "string" ? layout : "both",
|
||||
initialPromotionConfig,
|
||||
crossfade: layoutCrossfade,
|
||||
layoutScroll,
|
||||
layoutRoot,
|
||||
});
|
||||
}
|
||||
function getClosestProjectingNode(visualElement) {
|
||||
if (!visualElement)
|
||||
return undefined;
|
||||
return visualElement.options.allowProjection !== false
|
||||
? visualElement.projection
|
||||
: getClosestProjectingNode(visualElement.parent);
|
||||
}
|
||||
|
||||
export { useVisualElement };
|
||||
80
node_modules/framer-motion/dist/es/motion/utils/use-visual-state.mjs
generated
vendored
Normal file
80
node_modules/framer-motion/dist/es/motion/utils/use-visual-state.mjs
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
"use client";
|
||||
import { useContext } from 'react';
|
||||
import { isAnimationControls } from '../../animation/utils/is-animation-controls.mjs';
|
||||
import { MotionContext } from '../../context/MotionContext/index.mjs';
|
||||
import { PresenceContext } from '../../context/PresenceContext.mjs';
|
||||
import { isControllingVariants, isVariantNode } from '../../render/utils/is-controlling-variants.mjs';
|
||||
import { resolveVariantFromProps } from '../../render/utils/resolve-variants.mjs';
|
||||
import { useConstant } from '../../utils/use-constant.mjs';
|
||||
import { resolveMotionValue } from '../../value/utils/resolve-motion-value.mjs';
|
||||
|
||||
function makeState({ scrapeMotionValuesFromProps, createRenderState, }, props, context, presenceContext) {
|
||||
const state = {
|
||||
latestValues: makeLatestValues(props, context, presenceContext, scrapeMotionValuesFromProps),
|
||||
renderState: createRenderState(),
|
||||
};
|
||||
return state;
|
||||
}
|
||||
function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
|
||||
const values = {};
|
||||
const motionValues = scrapeMotionValues(props, {});
|
||||
for (const key in motionValues) {
|
||||
values[key] = resolveMotionValue(motionValues[key]);
|
||||
}
|
||||
let { initial, animate } = props;
|
||||
const isControllingVariants$1 = isControllingVariants(props);
|
||||
const isVariantNode$1 = isVariantNode(props);
|
||||
if (context &&
|
||||
isVariantNode$1 &&
|
||||
!isControllingVariants$1 &&
|
||||
props.inherit !== false) {
|
||||
if (initial === undefined)
|
||||
initial = context.initial;
|
||||
if (animate === undefined)
|
||||
animate = context.animate;
|
||||
}
|
||||
let isInitialAnimationBlocked = presenceContext
|
||||
? presenceContext.initial === false
|
||||
: false;
|
||||
isInitialAnimationBlocked = isInitialAnimationBlocked || initial === false;
|
||||
const variantToSet = isInitialAnimationBlocked ? animate : initial;
|
||||
if (variantToSet &&
|
||||
typeof variantToSet !== "boolean" &&
|
||||
!isAnimationControls(variantToSet)) {
|
||||
const list = Array.isArray(variantToSet) ? variantToSet : [variantToSet];
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const resolved = resolveVariantFromProps(props, list[i]);
|
||||
if (resolved) {
|
||||
const { transitionEnd, transition, ...target } = resolved;
|
||||
for (const key in target) {
|
||||
let valueTarget = target[key];
|
||||
if (Array.isArray(valueTarget)) {
|
||||
/**
|
||||
* Take final keyframe if the initial animation is blocked because
|
||||
* we want to initialise at the end of that blocked animation.
|
||||
*/
|
||||
const index = isInitialAnimationBlocked
|
||||
? valueTarget.length - 1
|
||||
: 0;
|
||||
valueTarget = valueTarget[index];
|
||||
}
|
||||
if (valueTarget !== null) {
|
||||
values[key] = valueTarget;
|
||||
}
|
||||
}
|
||||
for (const key in transitionEnd) {
|
||||
values[key] = transitionEnd[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
const makeUseVisualState = (config) => (props, isStatic) => {
|
||||
const context = useContext(MotionContext);
|
||||
const presenceContext = useContext(PresenceContext);
|
||||
const make = () => makeState(config, props, context, presenceContext);
|
||||
return isStatic ? make() : useConstant(make);
|
||||
};
|
||||
|
||||
export { makeUseVisualState };
|
||||
57
node_modules/framer-motion/dist/es/motion/utils/valid-prop.mjs
generated
vendored
Normal file
57
node_modules/framer-motion/dist/es/motion/utils/valid-prop.mjs
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* A list of all valid MotionProps.
|
||||
*
|
||||
* @privateRemarks
|
||||
* This doesn't throw if a `MotionProp` name is missing - it should.
|
||||
*/
|
||||
const validMotionProps = new Set([
|
||||
"animate",
|
||||
"exit",
|
||||
"variants",
|
||||
"initial",
|
||||
"style",
|
||||
"values",
|
||||
"variants",
|
||||
"transition",
|
||||
"transformTemplate",
|
||||
"custom",
|
||||
"inherit",
|
||||
"onBeforeLayoutMeasure",
|
||||
"onAnimationStart",
|
||||
"onAnimationComplete",
|
||||
"onUpdate",
|
||||
"onDragStart",
|
||||
"onDrag",
|
||||
"onDragEnd",
|
||||
"onMeasureDragConstraints",
|
||||
"onDirectionLock",
|
||||
"onDragTransitionEnd",
|
||||
"_dragX",
|
||||
"_dragY",
|
||||
"onHoverStart",
|
||||
"onHoverEnd",
|
||||
"onViewportEnter",
|
||||
"onViewportLeave",
|
||||
"globalTapTarget",
|
||||
"ignoreStrict",
|
||||
"viewport",
|
||||
]);
|
||||
/**
|
||||
* Check whether a prop name is a valid `MotionProp` key.
|
||||
*
|
||||
* @param key - Name of the property to check
|
||||
* @returns `true` is key is a valid `MotionProp`.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
function isValidMotionProp(key) {
|
||||
return (key.startsWith("while") ||
|
||||
(key.startsWith("drag") && key !== "draggable") ||
|
||||
key.startsWith("layout") ||
|
||||
key.startsWith("onTap") ||
|
||||
key.startsWith("onPan") ||
|
||||
key.startsWith("onLayout") ||
|
||||
validMotionProps.has(key));
|
||||
}
|
||||
|
||||
export { isValidMotionProp };
|
||||
Reference in New Issue
Block a user