framer-motion 10.12.8-alpha.2 → 10.12.8

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var indexLegacy = require('./index-legacy-bcb6edf0.js');
5
+ var indexLegacy = require('./index-legacy-9f6d433e.js');
6
6
 
7
7
 
8
8
 
@@ -2645,7 +2645,7 @@ class MotionValue {
2645
2645
  * This will be replaced by the build step with the latest version number.
2646
2646
  * When MotionValues are provided to motion components, warn if versions are mixed.
2647
2647
  */
2648
- this.version = "10.12.8-alpha.2";
2648
+ this.version = "10.12.8";
2649
2649
  /**
2650
2650
  * Duration, in milliseconds, since last updating frame.
2651
2651
  *
@@ -3817,7 +3817,7 @@ function updateMotionValuesFromProps(element, next, prev) {
3817
3817
  * and warn against mismatches.
3818
3818
  */
3819
3819
  if (process.env.NODE_ENV === "development") {
3820
- warnOnce(nextValue.version === "10.12.8-alpha.2", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.12.8-alpha.2 may not work as expected.`);
3820
+ warnOnce(nextValue.version === "10.12.8", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.12.8 may not work as expected.`);
3821
3821
  }
3822
3822
  }
3823
3823
  else if (isMotionValue(prevValue)) {
@@ -3985,7 +3985,7 @@ class VisualElement {
3985
3985
  mount(instance) {
3986
3986
  this.current = instance;
3987
3987
  visualElementStore.set(instance, this);
3988
- if (this.projection) {
3988
+ if (this.projection && !this.projection.instance) {
3989
3989
  this.projection.mount(instance);
3990
3990
  }
3991
3991
  if (this.parent && this.isVariantNode && !this.isControllingVariants) {
@@ -4051,7 +4051,7 @@ class VisualElement {
4051
4051
  }
4052
4052
  return this.sortInstanceNodePosition(this.current, other.current);
4053
4053
  }
4054
- loadFeatures({ children, ...renderedProps }, isStrict, preloadedFeatures, projectionId, initialLayoutGroupConfig) {
4054
+ loadFeatures({ children, ...renderedProps }, isStrict, preloadedFeatures, initialLayoutGroupConfig) {
4055
4055
  let ProjectionNodeConstructor;
4056
4056
  let MeasureLayout;
4057
4057
  /**
@@ -4081,7 +4081,7 @@ class VisualElement {
4081
4081
  }
4082
4082
  }
4083
4083
  if (!this.projection && ProjectionNodeConstructor) {
4084
- this.projection = new ProjectionNodeConstructor(projectionId, this.latestValues, this.parent && this.parent.projection);
4084
+ this.projection = new ProjectionNodeConstructor(this.latestValues, this.parent && this.parent.projection);
4085
4085
  const { layoutId, layout, drag, dragConstraints, layoutScroll, layoutRoot, } = renderedProps;
4086
4086
  this.projection.setOptions({
4087
4087
  layoutId,
package/dist/cjs/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
- var indexLegacy = require('./index-legacy-bcb6edf0.js');
6
+ var indexLegacy = require('./index-legacy-9f6d433e.js');
7
7
 
8
8
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
9
 
@@ -160,48 +160,6 @@ function loadFeatures(features) {
160
160
  }
161
161
  }
162
162
 
163
- /**
164
- * Creates a constant value over the lifecycle of a component.
165
- *
166
- * Even if `useMemo` is provided an empty array as its final argument, it doesn't offer
167
- * a guarantee that it won't re-run for performance reasons later on. By using `useConstant`
168
- * you can ensure that initialisers don't execute twice or more.
169
- */
170
- function useConstant(init) {
171
- const ref = React.useRef(null);
172
- if (ref.current === null) {
173
- ref.current = init();
174
- }
175
- return ref.current;
176
- }
177
-
178
- /**
179
- * This should only ever be modified on the client otherwise it'll
180
- * persist through server requests. If we need instanced states we
181
- * could lazy-init via root.
182
- */
183
- const globalProjectionState = {
184
- /**
185
- * Global flag as to whether the tree has animated since the last time
186
- * we resized the window
187
- */
188
- hasAnimatedSinceResize: true,
189
- /**
190
- * We set this to true once, on the first update. Any nodes added to the tree beyond that
191
- * update will be given a `data-projection-id` attribute.
192
- */
193
- hasEverUpdated: false,
194
- };
195
-
196
- let id$3 = 1;
197
- function useProjectionId() {
198
- return useConstant(() => {
199
- if (globalProjectionState.hasEverUpdated) {
200
- return id$3++;
201
- }
202
- });
203
- }
204
-
205
163
  const LayoutGroupContext = React.createContext({});
206
164
 
207
165
  /**
@@ -235,18 +193,6 @@ function createMotionComponent({ preloadedFeatures, createVisualElement, useRend
235
193
  };
236
194
  const { isStatic } = configAndProps;
237
195
  const context = useCreateMotionContext(props);
238
- /**
239
- * Create a unique projection ID for this component. If a new component is added
240
- * during a layout animation we'll use this to query the DOM and hydrate its ref early, allowing
241
- * us to measure it as soon as any layout effect flushes pending layout animations.
242
- *
243
- * Performance note: It'd be better not to have to search the DOM for these elements.
244
- * For newly-entering components it could be enough to only correct treeScale, in which
245
- * case we could mount in a scale-correction mode. This wouldn't be enough for
246
- * shared element transitions however. Perhaps for those we could revert to a root node
247
- * that gets forceRendered and layout animations are triggered on its layout effect.
248
- */
249
- const projectionId = isStatic ? undefined : useProjectionId();
250
196
  const visualState = useVisualState(props, isStatic);
251
197
  if (!isStatic && indexLegacy.isBrowser) {
252
198
  /**
@@ -265,7 +211,7 @@ function createMotionComponent({ preloadedFeatures, createVisualElement, useRend
265
211
  if (context.visualElement) {
266
212
  MeasureLayout = context.visualElement.loadFeatures(
267
213
  // Note: Pass the full new combined props to correctly re-render dynamic feature components.
268
- configAndProps, isStrict, preloadedFeatures, projectionId, initialLayoutGroupConfig);
214
+ configAndProps, isStrict, preloadedFeatures, initialLayoutGroupConfig);
269
215
  }
270
216
  }
271
217
  /**
@@ -274,7 +220,7 @@ function createMotionComponent({ preloadedFeatures, createVisualElement, useRend
274
220
  */
275
221
  return (React__namespace.createElement(MotionContext.Provider, { value: context },
276
222
  MeasureLayout && context.visualElement ? (React__namespace.createElement(MeasureLayout, { visualElement: context.visualElement, ...configAndProps })) : null,
277
- useRender(Component, props, projectionId, useMotionRef(visualState, context.visualElement, externalRef), visualState, isStatic, context.visualElement)));
223
+ useRender(Component, props, useMotionRef(visualState, context.visualElement, externalRef), visualState, isStatic, context.visualElement)));
278
224
  }
279
225
  const ForwardRefComponent = React.forwardRef(MotionComponent);
280
226
  ForwardRefComponent[motionComponentSymbol] = Component;
@@ -582,7 +528,7 @@ function useSVGProps(props, visualState, _isStatic, Component) {
582
528
  }
583
529
 
584
530
  function createUseRender(forwardMotionProps = false) {
585
- const useRender = (Component, props, projectionId, ref, { latestValues }, isStatic) => {
531
+ const useRender = (Component, props, ref, { latestValues }, isStatic) => {
586
532
  const useVisualProps = isSVGComponent(Component)
587
533
  ? useSVGProps
588
534
  : useHTMLProps;
@@ -600,9 +546,6 @@ function createUseRender(forwardMotionProps = false) {
600
546
  */
601
547
  const { children } = props;
602
548
  const renderedChildren = React.useMemo(() => (indexLegacy.isMotionValue(children) ? children.get() : children), [children]);
603
- if (projectionId) {
604
- elementProps["data-projection-id"] = projectionId;
605
- }
606
549
  return React.createElement(Component, {
607
550
  ...elementProps,
608
551
  children: renderedChildren,
@@ -611,6 +554,21 @@ function createUseRender(forwardMotionProps = false) {
611
554
  return useRender;
612
555
  }
613
556
 
557
+ /**
558
+ * Creates a constant value over the lifecycle of a component.
559
+ *
560
+ * Even if `useMemo` is provided an empty array as its final argument, it doesn't offer
561
+ * a guarantee that it won't re-run for performance reasons later on. By using `useConstant`
562
+ * you can ensure that initialisers don't execute twice or more.
563
+ */
564
+ function useConstant(init) {
565
+ const ref = React.useRef(null);
566
+ if (ref.current === null) {
567
+ ref.current = init();
568
+ }
569
+ return ref.current;
570
+ }
571
+
614
572
  /**
615
573
  * If the provided value is a MotionValue, this returns the actual value, otherwise just the value itself
616
574
  *
@@ -2771,6 +2729,24 @@ class FlatTree {
2771
2729
  }
2772
2730
  }
2773
2731
 
2732
+ /**
2733
+ * This should only ever be modified on the client otherwise it'll
2734
+ * persist through server requests. If we need instanced states we
2735
+ * could lazy-init via root.
2736
+ */
2737
+ const globalProjectionState = {
2738
+ /**
2739
+ * Global flag as to whether the tree has animated since the last time
2740
+ * we resized the window
2741
+ */
2742
+ hasAnimatedSinceResize: true,
2743
+ /**
2744
+ * We set this to true once, on the first update. Any nodes added to the tree beyond that
2745
+ * update will be given a `data-projection-id` attribute.
2746
+ */
2747
+ hasEverUpdated: false,
2748
+ };
2749
+
2774
2750
  function record(data) {
2775
2751
  if (window.MotionDebug) {
2776
2752
  window.MotionDebug.record(data);
@@ -2796,7 +2772,7 @@ const projectionFrameData = {
2796
2772
  };
2797
2773
  function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
2798
2774
  return class ProjectionNode {
2799
- constructor(elementId, latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
2775
+ constructor(latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
2800
2776
  /**
2801
2777
  * A unique ID generated for every projection node.
2802
2778
  */
@@ -2882,8 +2858,9 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
2882
2858
  *
2883
2859
  */
2884
2860
  this.eventHandlers = new Map();
2861
+ this.hasTreeAnimated = false;
2885
2862
  // Note: Currently only running on root node
2886
- this.potentialNodes = new Map();
2863
+ this.updateScheduled = false;
2887
2864
  this.checkUpdateFailed = () => {
2888
2865
  if (this.isUpdating) {
2889
2866
  this.isUpdating = false;
@@ -2918,13 +2895,11 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
2918
2895
  */
2919
2896
  // TODO Only running on root node
2920
2897
  this.sharedNodes = new Map();
2921
- this.elementId = elementId;
2922
2898
  this.latestValues = latestValues;
2923
2899
  this.root = parent ? parent.root || parent : this;
2924
2900
  this.path = parent ? [...parent.path, parent] : [];
2925
2901
  this.parent = parent;
2926
2902
  this.depth = parent ? parent.depth + 1 : 0;
2927
- elementId && this.root.registerPotentialNode(elementId, this);
2928
2903
  for (let i = 0; i < this.path.length; i++) {
2929
2904
  this.path[i].shouldResetTransform = true;
2930
2905
  }
@@ -2944,13 +2919,10 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
2944
2919
  hasListeners(name) {
2945
2920
  return this.eventHandlers.has(name);
2946
2921
  }
2947
- registerPotentialNode(elementId, node) {
2948
- this.potentialNodes.set(elementId, node);
2949
- }
2950
2922
  /**
2951
2923
  * Lifecycles
2952
2924
  */
2953
- mount(instance, isLayoutDirty = false) {
2925
+ mount(instance, isLayoutDirty = this.root.hasTreeAnimated) {
2954
2926
  if (this.instance)
2955
2927
  return;
2956
2928
  this.isSVG = indexLegacy.isSVGElement(instance);
@@ -2961,7 +2933,6 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
2961
2933
  }
2962
2934
  this.root.nodes.add(this);
2963
2935
  this.parent && this.parent.children.add(this);
2964
- this.elementId && this.root.potentialNodes.delete(this.elementId);
2965
2936
  if (isLayoutDirty && (layout || layoutId)) {
2966
2937
  this.isLayoutDirty = true;
2967
2938
  }
@@ -3086,6 +3057,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3086
3057
  return visualElement && visualElement.getProps().transformTemplate;
3087
3058
  }
3088
3059
  willUpdate(shouldNotifyListeners = true) {
3060
+ this.root.hasTreeAnimated = true;
3089
3061
  if (this.root.isUpdateBlocked()) {
3090
3062
  this.options.onExitComplete && this.options.onExitComplete();
3091
3063
  return;
@@ -3112,8 +3084,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3112
3084
  this.updateSnapshot();
3113
3085
  shouldNotifyListeners && this.notifyListeners("willUpdate");
3114
3086
  }
3115
- // Note: Currently only running on root node
3116
- didUpdate() {
3087
+ update() {
3088
+ this.updateScheduled = false;
3117
3089
  const updateWasBlocked = this.isUpdateBlocked();
3118
3090
  // When doing an instant transition, we skip the layout update,
3119
3091
  // but should still clean up the measurements so that the next
@@ -3127,16 +3099,6 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3127
3099
  if (!this.isUpdating)
3128
3100
  return;
3129
3101
  this.isUpdating = false;
3130
- /**
3131
- * Search for and mount newly-added projection elements.
3132
- *
3133
- * TODO: Every time a new component is rendered we could search up the tree for
3134
- * the closest mounted node and query from there rather than document.
3135
- */
3136
- if (this.potentialNodes.size) {
3137
- this.potentialNodes.forEach(mountNodeEarly);
3138
- this.potentialNodes.clear();
3139
- }
3140
3102
  /**
3141
3103
  * Write
3142
3104
  */
@@ -3157,6 +3119,12 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3157
3119
  indexLegacy.steps.preRender.process(indexLegacy.frameData);
3158
3120
  indexLegacy.steps.render.process(indexLegacy.frameData);
3159
3121
  }
3122
+ didUpdate() {
3123
+ if (!this.updateScheduled) {
3124
+ this.updateScheduled = true;
3125
+ queueMicrotask(() => this.update());
3126
+ }
3127
+ }
3160
3128
  clearAllSnapshots() {
3161
3129
  this.nodes.forEach(clearSnapshot);
3162
3130
  this.sharedNodes.forEach(removeLeadSnapshots);
@@ -3183,16 +3151,11 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3183
3151
  * Update measurements
3184
3152
  */
3185
3153
  updateSnapshot() {
3186
- var _a, _b;
3187
3154
  if (this.snapshot || !this.instance)
3188
3155
  return;
3189
3156
  this.snapshot = this.measure();
3190
- if (((_b = (_a = this.instance) === null || _a === void 0 ? void 0 : _a.dataset) === null || _b === void 0 ? void 0 : _b.framerName) === "Top") {
3191
- console.log("Update snapshot", this.snapshot.measuredBox.y);
3192
- }
3193
3157
  }
3194
3158
  updateLayout() {
3195
- var _a, _b;
3196
3159
  if (!this.instance)
3197
3160
  return;
3198
3161
  // TODO: Incorporate into a forwarded scroll offset
@@ -3216,9 +3179,6 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3216
3179
  }
3217
3180
  const prevLayout = this.layout;
3218
3181
  this.layout = this.measure(false);
3219
- if (((_b = (_a = this.instance) === null || _a === void 0 ? void 0 : _a.dataset) === null || _b === void 0 ? void 0 : _b.framerName) === "Top") {
3220
- console.log("Update layout", this.layout.measuredBox.y);
3221
- }
3222
3182
  this.layoutCorrected = indexLegacy.createBox();
3223
3183
  this.isLayoutDirty = false;
3224
3184
  this.projectionDelta = undefined;
@@ -3549,7 +3509,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3549
3509
  this.layout);
3550
3510
  }
3551
3511
  calcProjection() {
3552
- var _a, _b, _c, _d;
3512
+ var _a;
3553
3513
  const lead = this.getLead();
3554
3514
  const isShared = Boolean(this.resumingFrom) || this !== lead;
3555
3515
  let canSkip = true;
@@ -3575,9 +3535,6 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3575
3535
  if (this.resolvedRelativeTargetAt === indexLegacy.frameData.timestamp) {
3576
3536
  canSkip = false;
3577
3537
  }
3578
- if (((_c = (_b = this.instance) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c.framerName) === "Top") {
3579
- console.log("Calc projection", canSkip, (_d = this.target) === null || _d === void 0 ? void 0 : _d.y);
3580
- }
3581
3538
  if (canSkip)
3582
3539
  return;
3583
3540
  const { layout, layoutId } = this.options;
@@ -4202,23 +4159,6 @@ const defaultLayoutTransition = {
4202
4159
  duration: 0.45,
4203
4160
  ease: [0.4, 0, 0.1, 1],
4204
4161
  };
4205
- function mountNodeEarly(node, elementId) {
4206
- /**
4207
- * Rather than searching the DOM from document we can search the
4208
- * path for the deepest mounted ancestor and search from there
4209
- */
4210
- let searchNode = node.root;
4211
- for (let i = node.path.length - 1; i >= 0; i--) {
4212
- if (Boolean(node.path[i].instance)) {
4213
- searchNode = node.path[i];
4214
- break;
4215
- }
4216
- }
4217
- const searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
4218
- const element = searchElement.querySelector(`[data-projection-id="${elementId}"]`);
4219
- if (element)
4220
- node.mount(element, true);
4221
- }
4222
4162
  function roundAxis(axis) {
4223
4163
  axis.min = Math.round(axis.min);
4224
4164
  axis.max = Math.round(axis.max);
@@ -4252,7 +4192,7 @@ const HTMLProjectionNode = createProjectionNode({
4252
4192
  }),
4253
4193
  defaultParent: () => {
4254
4194
  if (!rootProjectionNode.current) {
4255
- const documentNode = new DocumentProjectionNode(0, {});
4195
+ const documentNode = new DocumentProjectionNode({});
4256
4196
  documentNode.mount(window);
4257
4197
  documentNode.setOptions({ layoutScroll: true });
4258
4198
  rootProjectionNode.current = documentNode;
@@ -4491,9 +4431,11 @@ class MeasureLayoutWithContext extends React__default["default"].Component {
4491
4431
  const { projection } = this.props.visualElement;
4492
4432
  if (projection) {
4493
4433
  projection.root.didUpdate();
4494
- if (!projection.currentAnimation && projection.isLead()) {
4495
- this.safeToRemove();
4496
- }
4434
+ queueMicrotask(() => {
4435
+ if (!projection.currentAnimation && projection.isLead()) {
4436
+ this.safeToRemove();
4437
+ }
4438
+ });
4497
4439
  }
4498
4440
  }
4499
4441
  componentWillUnmount() {
@@ -80,9 +80,11 @@ class MeasureLayoutWithContext extends React__default.Component {
80
80
  const { projection } = this.props.visualElement;
81
81
  if (projection) {
82
82
  projection.root.didUpdate();
83
- if (!projection.currentAnimation && projection.isLead()) {
84
- this.safeToRemove();
85
- }
83
+ queueMicrotask(() => {
84
+ if (!projection.currentAnimation && projection.isLead()) {
85
+ this.safeToRemove();
86
+ }
87
+ });
86
88
  }
87
89
  }
88
90
  componentWillUnmount() {
@@ -7,7 +7,6 @@ import { useMotionRef } from './utils/use-motion-ref.mjs';
7
7
  import { useCreateMotionContext } from '../context/MotionContext/create.mjs';
8
8
  import { loadFeatures } from './features/load-features.mjs';
9
9
  import { isBrowser } from '../utils/is-browser.mjs';
10
- import { useProjectionId } from '../projection/node/id.mjs';
11
10
  import { LayoutGroupContext } from '../context/LayoutGroupContext.mjs';
12
11
  import { LazyContext } from '../context/LazyContext.mjs';
13
12
  import { SwitchLayoutGroupContext } from '../context/SwitchLayoutGroupContext.mjs';
@@ -37,18 +36,6 @@ function createMotionComponent({ preloadedFeatures, createVisualElement, useRend
37
36
  };
38
37
  const { isStatic } = configAndProps;
39
38
  const context = useCreateMotionContext(props);
40
- /**
41
- * Create a unique projection ID for this component. If a new component is added
42
- * during a layout animation we'll use this to query the DOM and hydrate its ref early, allowing
43
- * us to measure it as soon as any layout effect flushes pending layout animations.
44
- *
45
- * Performance note: It'd be better not to have to search the DOM for these elements.
46
- * For newly-entering components it could be enough to only correct treeScale, in which
47
- * case we could mount in a scale-correction mode. This wouldn't be enough for
48
- * shared element transitions however. Perhaps for those we could revert to a root node
49
- * that gets forceRendered and layout animations are triggered on its layout effect.
50
- */
51
- const projectionId = isStatic ? undefined : useProjectionId();
52
39
  const visualState = useVisualState(props, isStatic);
53
40
  if (!isStatic && isBrowser) {
54
41
  /**
@@ -67,7 +54,7 @@ function createMotionComponent({ preloadedFeatures, createVisualElement, useRend
67
54
  if (context.visualElement) {
68
55
  MeasureLayout = context.visualElement.loadFeatures(
69
56
  // Note: Pass the full new combined props to correctly re-render dynamic feature components.
70
- configAndProps, isStrict, preloadedFeatures, projectionId, initialLayoutGroupConfig);
57
+ configAndProps, isStrict, preloadedFeatures, initialLayoutGroupConfig);
71
58
  }
72
59
  }
73
60
  /**
@@ -76,7 +63,7 @@ function createMotionComponent({ preloadedFeatures, createVisualElement, useRend
76
63
  */
77
64
  return (React.createElement(MotionContext.Provider, { value: context },
78
65
  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)));
66
+ useRender(Component, props, useMotionRef(visualState, context.visualElement, externalRef), visualState, isStatic, context.visualElement)));
80
67
  }
81
68
  const ForwardRefComponent = forwardRef(MotionComponent);
82
69
  ForwardRefComponent[motionComponentSymbol] = Component;
@@ -11,7 +11,7 @@ const HTMLProjectionNode = createProjectionNode({
11
11
  }),
12
12
  defaultParent: () => {
13
13
  if (!rootProjectionNode.current) {
14
- const documentNode = new DocumentProjectionNode(0, {});
14
+ const documentNode = new DocumentProjectionNode({});
15
15
  documentNode.mount(window);
16
16
  documentNode.setOptions({ layoutScroll: true });
17
17
  rootProjectionNode.current = documentNode;
@@ -42,7 +42,7 @@ const projectionFrameData = {
42
42
  };
43
43
  function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
44
44
  return class ProjectionNode {
45
- constructor(elementId, latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
45
+ constructor(latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
46
46
  /**
47
47
  * A unique ID generated for every projection node.
48
48
  */
@@ -128,8 +128,9 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
128
128
  *
129
129
  */
130
130
  this.eventHandlers = new Map();
131
+ this.hasTreeAnimated = false;
131
132
  // Note: Currently only running on root node
132
- this.potentialNodes = new Map();
133
+ this.updateScheduled = false;
133
134
  this.checkUpdateFailed = () => {
134
135
  if (this.isUpdating) {
135
136
  this.isUpdating = false;
@@ -164,13 +165,11 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
164
165
  */
165
166
  // TODO Only running on root node
166
167
  this.sharedNodes = new Map();
167
- this.elementId = elementId;
168
168
  this.latestValues = latestValues;
169
169
  this.root = parent ? parent.root || parent : this;
170
170
  this.path = parent ? [...parent.path, parent] : [];
171
171
  this.parent = parent;
172
172
  this.depth = parent ? parent.depth + 1 : 0;
173
- elementId && this.root.registerPotentialNode(elementId, this);
174
173
  for (let i = 0; i < this.path.length; i++) {
175
174
  this.path[i].shouldResetTransform = true;
176
175
  }
@@ -190,13 +189,10 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
190
189
  hasListeners(name) {
191
190
  return this.eventHandlers.has(name);
192
191
  }
193
- registerPotentialNode(elementId, node) {
194
- this.potentialNodes.set(elementId, node);
195
- }
196
192
  /**
197
193
  * Lifecycles
198
194
  */
199
- mount(instance, isLayoutDirty = false) {
195
+ mount(instance, isLayoutDirty = this.root.hasTreeAnimated) {
200
196
  if (this.instance)
201
197
  return;
202
198
  this.isSVG = isSVGElement(instance);
@@ -207,7 +203,6 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
207
203
  }
208
204
  this.root.nodes.add(this);
209
205
  this.parent && this.parent.children.add(this);
210
- this.elementId && this.root.potentialNodes.delete(this.elementId);
211
206
  if (isLayoutDirty && (layout || layoutId)) {
212
207
  this.isLayoutDirty = true;
213
208
  }
@@ -332,6 +327,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
332
327
  return visualElement && visualElement.getProps().transformTemplate;
333
328
  }
334
329
  willUpdate(shouldNotifyListeners = true) {
330
+ this.root.hasTreeAnimated = true;
335
331
  if (this.root.isUpdateBlocked()) {
336
332
  this.options.onExitComplete && this.options.onExitComplete();
337
333
  return;
@@ -358,8 +354,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
358
354
  this.updateSnapshot();
359
355
  shouldNotifyListeners && this.notifyListeners("willUpdate");
360
356
  }
361
- // Note: Currently only running on root node
362
- didUpdate() {
357
+ update() {
358
+ this.updateScheduled = false;
363
359
  const updateWasBlocked = this.isUpdateBlocked();
364
360
  // When doing an instant transition, we skip the layout update,
365
361
  // but should still clean up the measurements so that the next
@@ -373,16 +369,6 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
373
369
  if (!this.isUpdating)
374
370
  return;
375
371
  this.isUpdating = false;
376
- /**
377
- * Search for and mount newly-added projection elements.
378
- *
379
- * TODO: Every time a new component is rendered we could search up the tree for
380
- * the closest mounted node and query from there rather than document.
381
- */
382
- if (this.potentialNodes.size) {
383
- this.potentialNodes.forEach(mountNodeEarly);
384
- this.potentialNodes.clear();
385
- }
386
372
  /**
387
373
  * Write
388
374
  */
@@ -403,6 +389,12 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
403
389
  steps.preRender.process(frameData);
404
390
  steps.render.process(frameData);
405
391
  }
392
+ didUpdate() {
393
+ if (!this.updateScheduled) {
394
+ this.updateScheduled = true;
395
+ queueMicrotask(() => this.update());
396
+ }
397
+ }
406
398
  clearAllSnapshots() {
407
399
  this.nodes.forEach(clearSnapshot);
408
400
  this.sharedNodes.forEach(removeLeadSnapshots);
@@ -429,16 +421,11 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
429
421
  * Update measurements
430
422
  */
431
423
  updateSnapshot() {
432
- var _a, _b;
433
424
  if (this.snapshot || !this.instance)
434
425
  return;
435
426
  this.snapshot = this.measure();
436
- if (((_b = (_a = this.instance) === null || _a === void 0 ? void 0 : _a.dataset) === null || _b === void 0 ? void 0 : _b.framerName) === "Top") {
437
- console.log("Update snapshot", this.snapshot.measuredBox.y);
438
- }
439
427
  }
440
428
  updateLayout() {
441
- var _a, _b;
442
429
  if (!this.instance)
443
430
  return;
444
431
  // TODO: Incorporate into a forwarded scroll offset
@@ -462,9 +449,6 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
462
449
  }
463
450
  const prevLayout = this.layout;
464
451
  this.layout = this.measure(false);
465
- if (((_b = (_a = this.instance) === null || _a === void 0 ? void 0 : _a.dataset) === null || _b === void 0 ? void 0 : _b.framerName) === "Top") {
466
- console.log("Update layout", this.layout.measuredBox.y);
467
- }
468
452
  this.layoutCorrected = createBox();
469
453
  this.isLayoutDirty = false;
470
454
  this.projectionDelta = undefined;
@@ -795,7 +779,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
795
779
  this.layout);
796
780
  }
797
781
  calcProjection() {
798
- var _a, _b, _c, _d;
782
+ var _a;
799
783
  const lead = this.getLead();
800
784
  const isShared = Boolean(this.resumingFrom) || this !== lead;
801
785
  let canSkip = true;
@@ -821,9 +805,6 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
821
805
  if (this.resolvedRelativeTargetAt === frameData.timestamp) {
822
806
  canSkip = false;
823
807
  }
824
- if (((_c = (_b = this.instance) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c.framerName) === "Top") {
825
- console.log("Calc projection", canSkip, (_d = this.target) === null || _d === void 0 ? void 0 : _d.y);
826
- }
827
808
  if (canSkip)
828
809
  return;
829
810
  const { layout, layoutId } = this.options;
@@ -1448,23 +1429,6 @@ const defaultLayoutTransition = {
1448
1429
  duration: 0.45,
1449
1430
  ease: [0.4, 0, 0.1, 1],
1450
1431
  };
1451
- function mountNodeEarly(node, elementId) {
1452
- /**
1453
- * Rather than searching the DOM from document we can search the
1454
- * path for the deepest mounted ancestor and search from there
1455
- */
1456
- let searchNode = node.root;
1457
- for (let i = node.path.length - 1; i >= 0; i--) {
1458
- if (Boolean(node.path[i].instance)) {
1459
- searchNode = node.path[i];
1460
- break;
1461
- }
1462
- }
1463
- const searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
1464
- const element = searchElement.querySelector(`[data-projection-id="${elementId}"]`);
1465
- if (element)
1466
- node.mount(element, true);
1467
- }
1468
1432
  function roundAxis(axis) {
1469
1433
  axis.min = Math.round(axis.min);
1470
1434
  axis.max = Math.round(axis.max);