framer-motion 9.0.2 → 9.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/cjs/index.js +3344 -3260
  2. package/dist/es/animation/hooks/use-animated-state.mjs +3 -3
  3. package/dist/es/animation/index.mjs +3 -5
  4. package/dist/es/animation/legacy-popmotion/index.mjs +6 -2
  5. package/dist/es/animation/legacy-popmotion/inertia.mjs +4 -5
  6. package/dist/es/components/AnimatePresence/use-presence.mjs +0 -1
  7. package/dist/es/events/add-dom-event.mjs +6 -0
  8. package/dist/es/events/add-pointer-event.mjs +8 -0
  9. package/dist/es/events/use-dom-event.mjs +2 -5
  10. package/dist/es/gestures/drag/VisualElementDragControls.mjs +31 -30
  11. package/dist/es/gestures/drag/index.mjs +27 -0
  12. package/dist/es/gestures/focus.mjs +42 -0
  13. package/dist/es/gestures/hover.mjs +32 -0
  14. package/dist/es/gestures/{PanSession.mjs → pan/PanSession.mjs} +8 -8
  15. package/dist/es/gestures/pan/index.mjs +38 -0
  16. package/dist/es/gestures/press.mjs +109 -0
  17. package/dist/es/index.mjs +1 -1
  18. package/dist/es/motion/features/Feature.mjs +9 -0
  19. package/dist/es/motion/features/animation/exit.mjs +32 -0
  20. package/dist/es/motion/features/animation/index.mjs +38 -0
  21. package/dist/es/motion/features/animations.mjs +8 -37
  22. package/dist/es/motion/features/definitions.mjs +17 -23
  23. package/dist/es/motion/features/drag.mjs +12 -5
  24. package/dist/es/motion/features/gestures.mjs +16 -9
  25. package/dist/es/motion/features/layout/MeasureLayout.mjs +5 -5
  26. package/dist/es/motion/features/layout.mjs +11 -0
  27. package/dist/es/motion/features/load-features.mjs +4 -6
  28. package/dist/es/motion/features/viewport/index.mjs +96 -0
  29. package/dist/es/motion/index.mjs +12 -13
  30. package/dist/es/motion/utils/use-visual-element.mjs +8 -2
  31. package/dist/es/projection/geometry/delta-apply.mjs +9 -2
  32. package/dist/es/projection/geometry/delta-calc.mjs +2 -2
  33. package/dist/es/projection/geometry/delta-remove.mjs +2 -2
  34. package/dist/es/projection/node/DocumentProjectionNode.mjs +1 -1
  35. package/dist/es/projection/node/create-projection-node.mjs +65 -57
  36. package/dist/es/projection/node/group.mjs +5 -3
  37. package/dist/es/projection/shared/stack.mjs +7 -5
  38. package/dist/es/render/VisualElement.mjs +68 -47
  39. package/dist/es/render/dom/DOMVisualElement.mjs +1 -2
  40. package/dist/es/render/dom/features-max.mjs +2 -4
  41. package/dist/es/render/dom/motion.mjs +5 -6
  42. package/dist/es/render/dom/utils/create-config.mjs +1 -2
  43. package/dist/es/render/dom/value-types/animatable-none.mjs +3 -2
  44. package/dist/es/render/svg/SVGVisualElement.mjs +2 -2
  45. package/dist/es/render/utils/animation-state.mjs +6 -2
  46. package/dist/es/render/utils/animation.mjs +4 -4
  47. package/dist/es/render/utils/motion-values.mjs +1 -1
  48. package/dist/es/render/utils/setters.mjs +14 -9
  49. package/dist/es/value/index.mjs +1 -1
  50. package/dist/es/value/utils/is-motion-value.mjs +1 -1
  51. package/dist/framer-motion.dev.js +3341 -3257
  52. package/dist/framer-motion.js +1 -1
  53. package/dist/index.d.ts +85 -77
  54. package/dist/projection.dev.js +217 -177
  55. package/dist/size-rollup-dom-animation-assets.js +1 -1
  56. package/dist/size-rollup-dom-animation-m.js +1 -1
  57. package/dist/size-rollup-dom-animation.js +1 -1
  58. package/dist/size-rollup-dom-max-assets.js +1 -1
  59. package/dist/size-rollup-dom-max.js +1 -1
  60. package/dist/size-rollup-m.js +1 -1
  61. package/dist/size-rollup-motion.js +1 -1
  62. package/dist/size-webpack-dom-animation.js +1 -1
  63. package/dist/size-webpack-dom-max.js +1 -1
  64. package/dist/size-webpack-m.js +1 -1
  65. package/dist/three-entry.d.ts +74 -38
  66. package/package.json +8 -8
  67. package/dist/es/events/use-pointer-event.mjs +0 -11
  68. package/dist/es/gestures/drag/use-drag.mjs +0 -20
  69. package/dist/es/gestures/use-focus-gesture.mjs +0 -37
  70. package/dist/es/gestures/use-hover-gesture.mjs +0 -32
  71. package/dist/es/gestures/use-pan-gesture.mjs +0 -46
  72. package/dist/es/gestures/use-tap-gesture.mjs +0 -115
  73. package/dist/es/motion/features/layout/index.mjs +0 -7
  74. package/dist/es/motion/features/viewport/use-viewport.mjs +0 -97
  75. package/dist/es/motion/utils/VisualElementHandler.mjs +0 -19
  76. package/dist/es/motion/utils/make-renderless-component.mjs +0 -6
@@ -0,0 +1,38 @@
1
+ import { isAnimationControls } from '../../../animation/utils/is-animation-controls.mjs';
2
+ import { createAnimationState } from '../../../render/utils/animation-state.mjs';
3
+ import { Feature } from '../Feature.mjs';
4
+
5
+ class AnimationFeature extends Feature {
6
+ /**
7
+ * We dynamically generate the AnimationState manager as it contains a reference
8
+ * to the underlying animation library. We only want to load that if we load this,
9
+ * so people can optionally code split it out using the `m` component.
10
+ */
11
+ constructor(node) {
12
+ super(node);
13
+ node.animationState || (node.animationState = createAnimationState(node));
14
+ }
15
+ updateAnimationControlsSubscription() {
16
+ const { animate } = this.node.getProps();
17
+ this.unmount();
18
+ if (isAnimationControls(animate)) {
19
+ this.unmount = animate.subscribe(this.node);
20
+ }
21
+ }
22
+ /**
23
+ * Subscribe any provided AnimationControls to the component's VisualElement
24
+ */
25
+ mount() {
26
+ this.updateAnimationControlsSubscription();
27
+ }
28
+ update() {
29
+ const { animate } = this.node.getProps();
30
+ const { animate: prevAnimate } = this.node.prevProps || {};
31
+ if (animate !== prevAnimate) {
32
+ this.updateAnimationControlsSubscription();
33
+ }
34
+ }
35
+ unmount() { }
36
+ }
37
+
38
+ export { AnimationFeature };
@@ -1,42 +1,13 @@
1
- import { useEffect, useContext } from 'react';
2
- import { isAnimationControls } from '../../animation/utils/is-animation-controls.mjs';
3
- import { usePresence } from '../../components/AnimatePresence/use-presence.mjs';
4
- import { PresenceContext } from '../../context/PresenceContext.mjs';
5
- import { createAnimationState } from '../../render/utils/animation-state.mjs';
6
- import { AnimationType } from '../../render/utils/types.mjs';
7
- import { makeRenderlessComponent } from '../utils/make-renderless-component.mjs';
1
+ import { AnimationFeature } from './animation/index.mjs';
2
+ import { ExitAnimationFeature } from './animation/exit.mjs';
8
3
 
9
4
  const animations = {
10
- animation: makeRenderlessComponent(({ visualElement, animate }) => {
11
- /**
12
- * We dynamically generate the AnimationState manager as it contains a reference
13
- * to the underlying animation library. We only want to load that if we load this,
14
- * so people can optionally code split it out using the `m` component.
15
- */
16
- visualElement.animationState || (visualElement.animationState = createAnimationState(visualElement));
17
- /**
18
- * Subscribe any provided AnimationControls to the component's VisualElement
19
- */
20
- if (isAnimationControls(animate)) {
21
- useEffect(() => animate.subscribe(visualElement), [animate]);
22
- }
23
- }),
24
- exit: makeRenderlessComponent((props) => {
25
- const { custom, visualElement } = props;
26
- const [isPresent, safeToRemove] = usePresence();
27
- const presenceContext = useContext(PresenceContext);
28
- useEffect(() => {
29
- visualElement.isPresent = isPresent;
30
- const animation = visualElement.animationState &&
31
- visualElement.animationState.setActive(AnimationType.Exit, !isPresent, {
32
- custom: (presenceContext && presenceContext.custom) ||
33
- custom,
34
- });
35
- if (animation && !isPresent) {
36
- animation.then(safeToRemove);
37
- }
38
- }, [isPresent]);
39
- }),
5
+ animation: {
6
+ Feature: AnimationFeature,
7
+ },
8
+ exit: {
9
+ Feature: ExitAnimationFeature,
10
+ },
40
11
  };
41
12
 
42
13
  export { animations };
@@ -1,9 +1,5 @@
1
- const createDefinition = (propNames) => ({
2
- isEnabled: (props) => propNames.some((name) => !!props[name]),
3
- });
4
- const featureDefinitions = {
5
- measureLayout: createDefinition(["layout", "layoutId", "drag"]),
6
- animation: createDefinition([
1
+ const featureProps = {
2
+ animation: [
7
3
  "animate",
8
4
  "exit",
9
5
  "variants",
@@ -12,23 +8,21 @@ const featureDefinitions = {
12
8
  "whileFocus",
13
9
  "whileDrag",
14
10
  "whileInView",
15
- ]),
16
- exit: createDefinition(["exit"]),
17
- drag: createDefinition(["drag", "dragControls"]),
18
- focus: createDefinition(["whileFocus"]),
19
- hover: createDefinition(["whileHover", "onHoverStart", "onHoverEnd"]),
20
- tap: createDefinition(["whileTap", "onTap", "onTapStart", "onTapCancel"]),
21
- pan: createDefinition([
22
- "onPan",
23
- "onPanStart",
24
- "onPanSessionStart",
25
- "onPanEnd",
26
- ]),
27
- inView: createDefinition([
28
- "whileInView",
29
- "onViewportEnter",
30
- "onViewportLeave",
31
- ]),
11
+ ],
12
+ exit: ["exit"],
13
+ drag: ["drag", "dragControls"],
14
+ focus: ["whileFocus"],
15
+ hover: ["whileHover", "onHoverStart", "onHoverEnd"],
16
+ tap: ["whileTap", "onTap", "onTapStart", "onTapCancel"],
17
+ pan: ["onPan", "onPanStart", "onPanSessionStart", "onPanEnd"],
18
+ inView: ["whileInView", "onViewportEnter", "onViewportLeave"],
19
+ layout: ["layout", "layoutId"],
32
20
  };
21
+ const featureDefinitions = {};
22
+ for (const key in featureProps) {
23
+ featureDefinitions[key] = {
24
+ isEnabled: (props) => featureProps[key].some((name) => !!props[name]),
25
+ };
26
+ }
33
27
 
34
28
  export { featureDefinitions };
@@ -1,10 +1,17 @@
1
- import { useDrag } from '../../gestures/drag/use-drag.mjs';
2
- import { usePanGesture } from '../../gestures/use-pan-gesture.mjs';
3
- import { makeRenderlessComponent } from '../utils/make-renderless-component.mjs';
1
+ import { DragGesture } from '../../gestures/drag/index.mjs';
2
+ import { PanGesture } from '../../gestures/pan/index.mjs';
3
+ import { MeasureLayout } from './layout/MeasureLayout.mjs';
4
+ import { HTMLProjectionNode } from '../../projection/node/HTMLProjectionNode.mjs';
4
5
 
5
6
  const drag = {
6
- pan: makeRenderlessComponent(usePanGesture),
7
- drag: makeRenderlessComponent(useDrag),
7
+ pan: {
8
+ Feature: PanGesture,
9
+ },
10
+ drag: {
11
+ Feature: DragGesture,
12
+ ProjectionNode: HTMLProjectionNode,
13
+ MeasureLayout,
14
+ },
8
15
  };
9
16
 
10
17
  export { drag };
@@ -1,14 +1,21 @@
1
- import { useFocusGesture } from '../../gestures/use-focus-gesture.mjs';
2
- import { useHoverGesture } from '../../gestures/use-hover-gesture.mjs';
3
- import { useTapGesture } from '../../gestures/use-tap-gesture.mjs';
4
- import { useViewport } from './viewport/use-viewport.mjs';
5
- import { makeRenderlessComponent } from '../utils/make-renderless-component.mjs';
1
+ import { HoverGesture } from '../../gestures/hover.mjs';
2
+ import { FocusGesture } from '../../gestures/focus.mjs';
3
+ import { PressGesture } from '../../gestures/press.mjs';
4
+ import { InViewFeature } from './viewport/index.mjs';
6
5
 
7
6
  const gestureAnimations = {
8
- inView: makeRenderlessComponent(useViewport),
9
- tap: makeRenderlessComponent(useTapGesture),
10
- focus: makeRenderlessComponent(useFocusGesture),
11
- hover: makeRenderlessComponent(useHoverGesture),
7
+ inView: {
8
+ Feature: InViewFeature,
9
+ },
10
+ tap: {
11
+ Feature: PressGesture,
12
+ },
13
+ focus: {
14
+ Feature: FocusGesture,
15
+ },
16
+ hover: {
17
+ Feature: HoverGesture,
18
+ },
12
19
  };
13
20
 
14
21
  export { gestureAnimations };
@@ -67,8 +67,8 @@ class MeasureLayoutWithContext extends React__default.Component {
67
67
  * be in charge of the safe to remove. Otherwise we call it here.
68
68
  */
69
69
  sync.postRender(() => {
70
- var _a;
71
- if (!((_a = projection.getStack()) === null || _a === void 0 ? void 0 : _a.members.length)) {
70
+ const stack = projection.getStack();
71
+ if (!stack || !stack.members.length) {
72
72
  this.safeToRemove();
73
73
  }
74
74
  });
@@ -90,15 +90,15 @@ class MeasureLayoutWithContext extends React__default.Component {
90
90
  const { projection } = visualElement;
91
91
  if (projection) {
92
92
  projection.scheduleCheckAfterUnmount();
93
- if (layoutGroup === null || layoutGroup === void 0 ? void 0 : layoutGroup.group)
93
+ if (layoutGroup && layoutGroup.group)
94
94
  layoutGroup.group.remove(projection);
95
- if (promoteContext === null || promoteContext === void 0 ? void 0 : promoteContext.deregister)
95
+ if (promoteContext && promoteContext.deregister)
96
96
  promoteContext.deregister(projection);
97
97
  }
98
98
  }
99
99
  safeToRemove() {
100
100
  const { safeToRemove } = this.props;
101
- safeToRemove === null || safeToRemove === void 0 ? void 0 : safeToRemove();
101
+ safeToRemove && safeToRemove();
102
102
  }
103
103
  render() {
104
104
  return null;
@@ -0,0 +1,11 @@
1
+ import { HTMLProjectionNode } from '../../projection/node/HTMLProjectionNode.mjs';
2
+ import { MeasureLayout } from './layout/MeasureLayout.mjs';
3
+
4
+ const layout = {
5
+ layout: {
6
+ ProjectionNode: HTMLProjectionNode,
7
+ MeasureLayout,
8
+ },
9
+ };
10
+
11
+ export { layout };
@@ -2,12 +2,10 @@ import { featureDefinitions } from './definitions.mjs';
2
2
 
3
3
  function loadFeatures(features) {
4
4
  for (const key in features) {
5
- if (key === "projectionNodeConstructor") {
6
- featureDefinitions.projectionNodeConstructor = features[key];
7
- }
8
- else {
9
- featureDefinitions[key].Component = features[key];
10
- }
5
+ featureDefinitions[key] = {
6
+ ...featureDefinitions[key],
7
+ ...features[key],
8
+ };
11
9
  }
12
10
  }
13
11
 
@@ -0,0 +1,96 @@
1
+ import { AnimationType } from '../../../render/utils/types.mjs';
2
+ import { Feature } from '../Feature.mjs';
3
+ import { observeIntersection } from './observers.mjs';
4
+
5
+ const thresholdNames = {
6
+ some: 0,
7
+ all: 1,
8
+ };
9
+ class InViewFeature extends Feature {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.hasEnteredView = false;
13
+ this.isInView = false;
14
+ }
15
+ /**
16
+ * TODO: Remove this in 10.0
17
+ */
18
+ viewportFallback() {
19
+ /**
20
+ * Fire this in an rAF because, at this point, the animation state
21
+ * won't have flushed for the first time and there's certain logic in
22
+ * there that behaves differently on the initial animation.
23
+ */
24
+ requestAnimationFrame(() => {
25
+ this.hasEnteredView = true;
26
+ const { onViewportEnter } = this.node.getProps();
27
+ onViewportEnter && onViewportEnter(null);
28
+ if (this.node.animationState) {
29
+ this.node.animationState.setActive(AnimationType.InView, true);
30
+ }
31
+ });
32
+ }
33
+ startObserver() {
34
+ this.unmount();
35
+ const { viewport = {} } = this.node.getProps();
36
+ const { root, margin: rootMargin, amount = "some", once, fallback = true, } = viewport;
37
+ if (typeof IntersectionObserver === "undefined") {
38
+ if (fallback)
39
+ this.viewportFallback();
40
+ return;
41
+ }
42
+ const options = {
43
+ root: root ? root.current : undefined,
44
+ rootMargin,
45
+ threshold: typeof amount === "number" ? amount : thresholdNames[amount],
46
+ };
47
+ const onIntersectionUpdate = (entry) => {
48
+ const { isIntersecting } = entry;
49
+ /**
50
+ * If there's been no change in the viewport state, early return.
51
+ */
52
+ if (this.isInView === isIntersecting)
53
+ return;
54
+ this.isInView = isIntersecting;
55
+ /**
56
+ * Handle hasEnteredView. If this is only meant to run once, and
57
+ * element isn't visible, early return. Otherwise set hasEnteredView to true.
58
+ */
59
+ if (once && !isIntersecting && this.hasEnteredView) {
60
+ return;
61
+ }
62
+ else if (isIntersecting) {
63
+ this.hasEnteredView = true;
64
+ }
65
+ if (this.node.animationState) {
66
+ this.node.animationState.setActive(AnimationType.InView, isIntersecting);
67
+ }
68
+ /**
69
+ * Use the latest committed props rather than the ones in scope
70
+ * when this observer is created
71
+ */
72
+ const { onViewportEnter, onViewportLeave } = this.node.getProps();
73
+ const callback = isIntersecting ? onViewportEnter : onViewportLeave;
74
+ callback && callback(entry);
75
+ };
76
+ return observeIntersection(this.node.current, options, onIntersectionUpdate);
77
+ }
78
+ mount() {
79
+ this.startObserver();
80
+ }
81
+ update() {
82
+ if (typeof IntersectionObserver === "undefined")
83
+ return;
84
+ const { props, prevProps } = this.node;
85
+ const hasOptionsChanged = ["amount", "margin", "root"].some(hasViewportOptionChanged(props, prevProps));
86
+ if (hasOptionsChanged) {
87
+ this.startObserver();
88
+ }
89
+ }
90
+ unmount() { }
91
+ }
92
+ function hasViewportOptionChanged({ viewport = {} }, { viewport: prevViewport = {} } = {}) {
93
+ return (name) => viewport[name] !== prevViewport[name];
94
+ }
95
+
96
+ export { InViewFeature };
@@ -5,12 +5,10 @@ import { MotionContext } from '../context/MotionContext/index.mjs';
5
5
  import { useVisualElement } from './utils/use-visual-element.mjs';
6
6
  import { useMotionRef } from './utils/use-motion-ref.mjs';
7
7
  import { useCreateMotionContext } from '../context/MotionContext/create.mjs';
8
- import { featureDefinitions } from './features/definitions.mjs';
9
8
  import { loadFeatures } from './features/load-features.mjs';
10
9
  import { isBrowser } from '../utils/is-browser.mjs';
11
10
  import { useProjectionId } from '../projection/node/id.mjs';
12
11
  import { LayoutGroupContext } from '../context/LayoutGroupContext.mjs';
13
- import { VisualElementHandler } from './utils/VisualElementHandler.mjs';
14
12
  import { LazyContext } from '../context/LazyContext.mjs';
15
13
  import { SwitchLayoutGroupContext } from '../context/SwitchLayoutGroupContext.mjs';
16
14
  import { motionComponentSymbol } from './utils/symbol.mjs';
@@ -24,16 +22,20 @@ import { motionComponentSymbol } from './utils/symbol.mjs';
24
22
  * Alongside this is a config option which provides a way of rendering the provided
25
23
  * component "offline", or outside the React render cycle.
26
24
  */
27
- function createMotionComponent({ preloadedFeatures, createVisualElement, projectionNodeConstructor, useRender, useVisualState, Component, }) {
25
+ function createMotionComponent({ preloadedFeatures, createVisualElement, useRender, useVisualState, Component, }) {
28
26
  preloadedFeatures && loadFeatures(preloadedFeatures);
29
27
  function MotionComponent(props, externalRef) {
28
+ /**
29
+ * If we need to measure the element we load this functionality in a
30
+ * separate class component in order to gain access to getSnapshotBeforeUpdate.
31
+ */
32
+ let MeasureLayout;
30
33
  const configAndProps = {
31
34
  ...useContext(MotionConfigContext),
32
35
  ...props,
33
36
  layoutId: useLayoutId(props),
34
37
  };
35
38
  const { isStatic } = configAndProps;
36
- let features = null;
37
39
  const context = useCreateMotionContext(props);
38
40
  /**
39
41
  * Create a unique projection ID for this component. If a new component is added
@@ -47,9 +49,6 @@ function createMotionComponent({ preloadedFeatures, createVisualElement, project
47
49
  * that gets forceRendered and layout animations are triggered on its layout effect.
48
50
  */
49
51
  const projectionId = isStatic ? undefined : useProjectionId();
50
- /**
51
- *
52
- */
53
52
  const visualState = useVisualState(props, isStatic);
54
53
  if (!isStatic && isBrowser) {
55
54
  /**
@@ -64,20 +63,20 @@ function createMotionComponent({ preloadedFeatures, createVisualElement, project
64
63
  * components so each feature can optionally make use of React lifecycle methods.
65
64
  */
66
65
  const initialLayoutGroupConfig = useContext(SwitchLayoutGroupContext);
66
+ const isStrict = useContext(LazyContext).strict;
67
67
  if (context.visualElement) {
68
- features = context.visualElement.loadFeatures(
68
+ MeasureLayout = context.visualElement.loadFeatures(
69
69
  // Note: Pass the full new combined props to correctly re-render dynamic feature components.
70
- configAndProps, useContext(LazyContext).strict, preloadedFeatures, projectionId, projectionNodeConstructor ||
71
- featureDefinitions.projectionNodeConstructor, initialLayoutGroupConfig);
70
+ configAndProps, isStrict, preloadedFeatures, projectionId, initialLayoutGroupConfig);
72
71
  }
73
72
  }
74
73
  /**
75
74
  * The mount order and hierarchy is specific to ensure our element ref
76
75
  * is hydrated by the time features fire their effects.
77
76
  */
78
- return (React.createElement(VisualElementHandler, { visualElement: context.visualElement, props: configAndProps },
79
- features,
80
- React.createElement(MotionContext.Provider, { value: context }, useRender(Component, props, projectionId, useMotionRef(visualState, context.visualElement, externalRef), visualState, isStatic, context.visualElement))));
77
+ return (React.createElement(MotionContext.Provider, { value: context },
78
+ MeasureLayout && context.visualElement ? (React.createElement(MeasureLayout, { visualElement: context.visualElement, ...configAndProps })) : null,
79
+ useRender(Component, props, projectionId, useMotionRef(visualState, context.visualElement, externalRef), visualState, isStatic, context.visualElement)));
81
80
  }
82
81
  const ForwardRefComponent = forwardRef(MotionComponent);
83
82
  ForwardRefComponent[motionComponentSymbol] = Component;
@@ -1,4 +1,4 @@
1
- import { useContext, useRef, useEffect } from 'react';
1
+ import { useContext, useRef, useInsertionEffect, useEffect } from 'react';
2
2
  import { PresenceContext } from '../../context/PresenceContext.mjs';
3
3
  import { useVisualElementContext } from '../../context/MotionContext/index.mjs';
4
4
  import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';
@@ -20,7 +20,7 @@ function useVisualElement(Component, visualState, props, createVisualElement) {
20
20
  visualState,
21
21
  parent,
22
22
  props,
23
- presenceId: presenceContext ? presenceContext.id : undefined,
23
+ presenceContext,
24
24
  blockInitialAnimation: presenceContext
25
25
  ? presenceContext.initial === false
26
26
  : false,
@@ -28,9 +28,15 @@ function useVisualElement(Component, visualState, props, createVisualElement) {
28
28
  });
29
29
  }
30
30
  const visualElement = visualElementRef.current;
31
+ useInsertionEffect(() => {
32
+ visualElement && visualElement.update(props, presenceContext);
33
+ });
31
34
  useIsomorphicLayoutEffect(() => {
32
35
  visualElement && visualElement.render();
33
36
  });
37
+ useEffect(() => {
38
+ visualElement && visualElement.updateFeatures();
39
+ });
34
40
  /**
35
41
  * Ideally this function would always run in a useEffect.
36
42
  *
@@ -39,7 +39,6 @@ function applyBoxDelta(box, { x, y }) {
39
39
  * This is the final nested loop within updateLayoutDelta for future refactoring
40
40
  */
41
41
  function applyTreeDeltas(box, treeScale, treePath, isSharedTransition = false) {
42
- var _a, _b;
43
42
  const treeLength = treePath.length;
44
43
  if (!treeLength)
45
44
  return;
@@ -50,8 +49,16 @@ function applyTreeDeltas(box, treeScale, treePath, isSharedTransition = false) {
50
49
  for (let i = 0; i < treeLength; i++) {
51
50
  node = treePath[i];
52
51
  delta = node.projectionDelta;
53
- if (((_b = (_a = node.instance) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.display) === "contents")
52
+ /**
53
+ * TODO: Prefer to remove this, but currently we have motion components with
54
+ * display: contents in Framer.
55
+ */
56
+ const instance = node.instance;
57
+ if (instance &&
58
+ instance.style &&
59
+ instance.style.display === "contents") {
54
60
  continue;
61
+ }
55
62
  if (isSharedTransition &&
56
63
  node.options.layoutScroll &&
57
64
  node.scroll &&
@@ -18,8 +18,8 @@ function calcAxisDelta(delta, source, target, origin = 0.5) {
18
18
  delta.translate = 0;
19
19
  }
20
20
  function calcBoxDelta(delta, source, target, origin) {
21
- calcAxisDelta(delta.x, source.x, target.x, origin === null || origin === void 0 ? void 0 : origin.originX);
22
- calcAxisDelta(delta.y, source.y, target.y, origin === null || origin === void 0 ? void 0 : origin.originY);
21
+ calcAxisDelta(delta.x, source.x, target.x, origin ? origin.originX : undefined);
22
+ calcAxisDelta(delta.y, source.y, target.y, origin ? origin.originY : undefined);
23
23
  }
24
24
  function calcRelativeAxis(target, relative, parent) {
25
25
  target.min = parent.min + relative.min;
@@ -47,8 +47,8 @@ const yKeys = ["y", "scaleY", "originY"];
47
47
  * and acts as a bridge between motion values and removeAxisDelta
48
48
  */
49
49
  function removeBoxTransforms(box, transforms, originBox, sourceBox) {
50
- removeAxisTransforms(box.x, transforms, xKeys, originBox === null || originBox === void 0 ? void 0 : originBox.x, sourceBox === null || sourceBox === void 0 ? void 0 : sourceBox.x);
51
- removeAxisTransforms(box.y, transforms, yKeys, originBox === null || originBox === void 0 ? void 0 : originBox.y, sourceBox === null || sourceBox === void 0 ? void 0 : sourceBox.y);
50
+ removeAxisTransforms(box.x, transforms, xKeys, originBox ? originBox.x : undefined, sourceBox ? sourceBox.x : undefined);
51
+ removeAxisTransforms(box.y, transforms, yKeys, originBox ? originBox.y : undefined, sourceBox ? sourceBox.y : undefined);
52
52
  }
53
53
 
54
54
  export { removeAxisDelta, removeAxisTransforms, removeBoxTransforms, removePointDelta };
@@ -1,5 +1,5 @@
1
1
  import { createProjectionNode } from './create-projection-node.mjs';
2
- import { addDomEvent } from '../../events/use-dom-event.mjs';
2
+ import { addDomEvent } from '../../events/add-dom-event.mjs';
3
3
 
4
4
  const DocumentProjectionNode = createProjectionNode({
5
5
  attachResizeListener: (ref, notify) => addDomEvent(ref, "resize", notify),