motion 14.3.0 → 14.3.1
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.
- package/dist/motion.dev.js +184 -92
- package/dist/motion.js +1 -1
- package/package.json +3 -3
package/dist/motion.dev.js
CHANGED
|
@@ -3546,6 +3546,7 @@
|
|
|
3546
3546
|
constructor(options) {
|
|
3547
3547
|
const element = getOwner(options).current;
|
|
3548
3548
|
const { driver = frameloopDriver } = options;
|
|
3549
|
+
let animation;
|
|
3549
3550
|
/**
|
|
3550
3551
|
* Before JSAnimation replaces the type with its generator.
|
|
3551
3552
|
*/
|
|
@@ -3575,11 +3576,12 @@
|
|
|
3575
3576
|
stop: () => {
|
|
3576
3577
|
js.stop();
|
|
3577
3578
|
const group = getGroup(element);
|
|
3578
|
-
group
|
|
3579
|
+
group && !group.isFinishing && group.release(animation);
|
|
3579
3580
|
},
|
|
3580
3581
|
};
|
|
3581
3582
|
};
|
|
3582
3583
|
super(options);
|
|
3584
|
+
animation = this;
|
|
3583
3585
|
this.canAccelerate = canAccelerate;
|
|
3584
3586
|
/**
|
|
3585
3587
|
* stop is bound in JSAnimation, so wrap it rather than override.
|
|
@@ -3735,8 +3737,14 @@
|
|
|
3735
3737
|
}
|
|
3736
3738
|
return super.time;
|
|
3737
3739
|
}
|
|
3740
|
+
/**
|
|
3741
|
+
* A JS animation sets its motion value from a seek on its next tick.
|
|
3742
|
+
* This doesn't tick, so set it now, rather than leave it to be set
|
|
3743
|
+
* when this next stops.
|
|
3744
|
+
*/
|
|
3738
3745
|
set time(newTime) {
|
|
3739
3746
|
super.time = newTime;
|
|
3747
|
+
this.isAccelerated() && this.sync();
|
|
3740
3748
|
}
|
|
3741
3749
|
/**
|
|
3742
3750
|
* Scroll timelines set time every frame, so run these on the main
|
|
@@ -3764,6 +3772,7 @@
|
|
|
3764
3772
|
let segments = [];
|
|
3765
3773
|
let needsBuild = false;
|
|
3766
3774
|
let isScheduled = false;
|
|
3775
|
+
let isEnded = false;
|
|
3767
3776
|
let hasChurned = false;
|
|
3768
3777
|
let lastChurn = -Infinity;
|
|
3769
3778
|
const has = (key) => {
|
|
@@ -3880,8 +3889,19 @@
|
|
|
3880
3889
|
for (const track of moving) {
|
|
3881
3890
|
const values = at.map((t) => track.numberAt(t));
|
|
3882
3891
|
const [first] = values;
|
|
3883
|
-
const
|
|
3884
|
-
const
|
|
3892
|
+
const changes = values.map((value) => value - first);
|
|
3893
|
+
const end = changes[changes.length - 1];
|
|
3894
|
+
/**
|
|
3895
|
+
* A value that ends only a tiny way from where it started, as
|
|
3896
|
+
* a round trip does if it's built just after it starts, or
|
|
3897
|
+
* from a float residue, ends where it started. Dividing by
|
|
3898
|
+
* that tiny range would stretch the easing to values the
|
|
3899
|
+
* compositor can't render.
|
|
3900
|
+
*/
|
|
3901
|
+
const range = changes.some((change) => Math.abs(change) * easingTolerance > Math.abs(end))
|
|
3902
|
+
? 0
|
|
3903
|
+
: end;
|
|
3904
|
+
const progress = changes.map((change) => range ? change / range : change);
|
|
3885
3905
|
/**
|
|
3886
3906
|
* A value that doesn't change, like one still in its delay,
|
|
3887
3907
|
* fits any easing. One that changes but ends where it started
|
|
@@ -4183,6 +4203,18 @@
|
|
|
4183
4203
|
}
|
|
4184
4204
|
return true;
|
|
4185
4205
|
};
|
|
4206
|
+
/**
|
|
4207
|
+
* If no animations are left, write where they got to and cancel the
|
|
4208
|
+
* WAAPI animations. Returns whether the group ended.
|
|
4209
|
+
*/
|
|
4210
|
+
const end = () => {
|
|
4211
|
+
if (tracks.size)
|
|
4212
|
+
return false;
|
|
4213
|
+
isEnded = true;
|
|
4214
|
+
transformGroups.delete(element);
|
|
4215
|
+
group.isJS || stop();
|
|
4216
|
+
return true;
|
|
4217
|
+
};
|
|
4186
4218
|
const build = () => {
|
|
4187
4219
|
const now = time.now();
|
|
4188
4220
|
/**
|
|
@@ -4210,15 +4242,14 @@
|
|
|
4210
4242
|
group.isFinishing = false;
|
|
4211
4243
|
}
|
|
4212
4244
|
isScheduled = false;
|
|
4245
|
+
if (isEnded)
|
|
4246
|
+
return;
|
|
4213
4247
|
tracks.forEach(({ state }, track) => {
|
|
4214
4248
|
if (state === "idle" || state === "finished")
|
|
4215
4249
|
tracks.delete(track);
|
|
4216
4250
|
});
|
|
4217
|
-
if (
|
|
4218
|
-
transformGroups.delete(element);
|
|
4219
|
-
group.isJS || stop();
|
|
4251
|
+
if (end())
|
|
4220
4252
|
return;
|
|
4221
|
-
}
|
|
4222
4253
|
for (const track of tracks) {
|
|
4223
4254
|
if (!track.canAccelerate)
|
|
4224
4255
|
return group.demote(true);
|
|
@@ -4250,6 +4281,8 @@
|
|
|
4250
4281
|
isJS: false,
|
|
4251
4282
|
isFinishing: false,
|
|
4252
4283
|
schedule(build_, isChurn) {
|
|
4284
|
+
if (isEnded)
|
|
4285
|
+
return;
|
|
4253
4286
|
needsBuild || (needsBuild = build_);
|
|
4254
4287
|
hasChurned || (hasChurned = !!isChurn);
|
|
4255
4288
|
/**
|
|
@@ -4264,6 +4297,21 @@
|
|
|
4264
4297
|
: queueMicrotask(build);
|
|
4265
4298
|
}
|
|
4266
4299
|
},
|
|
4300
|
+
/**
|
|
4301
|
+
* End the group now, rather than when it next builds, so the
|
|
4302
|
+
* element's transform is the caller's again as soon as its last
|
|
4303
|
+
* animation is stopped.
|
|
4304
|
+
*/
|
|
4305
|
+
release(track) {
|
|
4306
|
+
/**
|
|
4307
|
+
* Only drop the stopped animation. Others can be idle because
|
|
4308
|
+
* they're part way through play(), and are about to run.
|
|
4309
|
+
*/
|
|
4310
|
+
const { state } = track;
|
|
4311
|
+
if (state === "idle" || state === "finished")
|
|
4312
|
+
tracks.delete(track);
|
|
4313
|
+
end() || group.schedule(true);
|
|
4314
|
+
},
|
|
4267
4315
|
/**
|
|
4268
4316
|
* An outside write. Rebuild once, but if it keeps happening, move
|
|
4269
4317
|
* to the main thread.
|
|
@@ -4278,7 +4326,7 @@
|
|
|
4278
4326
|
}
|
|
4279
4327
|
},
|
|
4280
4328
|
demote(canReturn) {
|
|
4281
|
-
if (group.isJS)
|
|
4329
|
+
if (group.isJS || isEnded)
|
|
4282
4330
|
return;
|
|
4283
4331
|
/**
|
|
4284
4332
|
* Unless only another animation is holding the group on the
|
|
@@ -5285,11 +5333,11 @@
|
|
|
5285
5333
|
}
|
|
5286
5334
|
return sample({ x: tx, y: ty }, { x: 0, y: 0 });
|
|
5287
5335
|
},
|
|
5288
|
-
|
|
5336
|
+
animateValues(getValue, target, transition, delay, animations) {
|
|
5289
5337
|
if (!("x" in target || "y" in target))
|
|
5290
5338
|
return;
|
|
5291
|
-
const xValue =
|
|
5292
|
-
const yValue =
|
|
5339
|
+
const xValue = getValue("x");
|
|
5340
|
+
const yValue = getValue("y");
|
|
5293
5341
|
const xRaw = target.x;
|
|
5294
5342
|
const yRaw = target.y;
|
|
5295
5343
|
const xFrom = (Array.isArray(xRaw) && xRaw[0] != null
|
|
@@ -5312,7 +5360,7 @@
|
|
|
5312
5360
|
// concurrent rotate animation composes and nothing accumulates
|
|
5313
5361
|
// on interrupt.
|
|
5314
5362
|
const pathRotationValue = interpolate(0).rotate !== undefined
|
|
5315
|
-
?
|
|
5363
|
+
? getValue("pathRotation")
|
|
5316
5364
|
: undefined;
|
|
5317
5365
|
const pathTransition = {
|
|
5318
5366
|
delay,
|
|
@@ -5522,7 +5570,9 @@
|
|
|
5522
5570
|
const path = transition?.path;
|
|
5523
5571
|
if (path) {
|
|
5524
5572
|
// path mutates `target` to claim x/y; loop below skips them.
|
|
5525
|
-
path.
|
|
5573
|
+
path.animateValues
|
|
5574
|
+
? path.animateValues((key) => visualElement.getValue(key, visualElement.latestValues[key] ?? 0), target, transition, delay, animations)
|
|
5575
|
+
: path.animateVisualElement?.(visualElement, target, transition, delay, animations);
|
|
5526
5576
|
}
|
|
5527
5577
|
for (const key in target) {
|
|
5528
5578
|
const value = visualElement.getValue(key, visualElement.latestValues[key] ?? null);
|
|
@@ -5981,8 +6031,16 @@
|
|
|
5981
6031
|
*/
|
|
5982
6032
|
function animateValues(getValue, keyframes, transition = {}, element) {
|
|
5983
6033
|
const animations = [];
|
|
5984
|
-
const { velocity } = transition;
|
|
6034
|
+
const { velocity, path } = transition;
|
|
5985
6035
|
const reduceMotion = transition.reduceMotion ?? element?.shouldReduceMotion;
|
|
6036
|
+
/**
|
|
6037
|
+
* Only elements have x/y to move along a path. path claims them by
|
|
6038
|
+
* deleting them, so hand it a copy.
|
|
6039
|
+
*/
|
|
6040
|
+
if (path?.animateValues && element) {
|
|
6041
|
+
keyframes = { ...keyframes };
|
|
6042
|
+
path.animateValues(getValue, keyframes, transition, 0, animations);
|
|
6043
|
+
}
|
|
5986
6044
|
for (const key in keyframes) {
|
|
5987
6045
|
if (key === "transition" || key === "transitionEnd")
|
|
5988
6046
|
continue;
|
|
@@ -6587,7 +6645,7 @@
|
|
|
6587
6645
|
}
|
|
6588
6646
|
}
|
|
6589
6647
|
const addSVGValue = (element, state, key, value) => {
|
|
6590
|
-
if (key.startsWith("path")) {
|
|
6648
|
+
if (key.startsWith("path") && !transformProps.has(key)) {
|
|
6591
6649
|
return addSVGPathValue(element, state, key, value);
|
|
6592
6650
|
}
|
|
6593
6651
|
else if (key.startsWith("attr")) {
|
|
@@ -6688,6 +6746,7 @@
|
|
|
6688
6746
|
values.rotate ||
|
|
6689
6747
|
values.rotateX ||
|
|
6690
6748
|
values.rotateY ||
|
|
6749
|
+
values.rotateZ ||
|
|
6691
6750
|
values.skewX ||
|
|
6692
6751
|
values.skewY);
|
|
6693
6752
|
}
|
|
@@ -10473,7 +10532,7 @@
|
|
|
10473
10532
|
transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
|
|
10474
10533
|
}
|
|
10475
10534
|
if (latestTransform) {
|
|
10476
|
-
const { transformPerspective, rotate, pathRotation, rotateX, rotateY, skewX, skewY, } = latestTransform;
|
|
10535
|
+
const { transformPerspective, rotate, pathRotation, rotateX, rotateY, rotateZ, skewX, skewY, } = latestTransform;
|
|
10477
10536
|
if (transformPerspective)
|
|
10478
10537
|
transform = `perspective(${transformPerspective}px) ${transform}`;
|
|
10479
10538
|
if (rotate)
|
|
@@ -10485,6 +10544,8 @@
|
|
|
10485
10544
|
transform += `rotateX(${rotateX}deg) `;
|
|
10486
10545
|
if (rotateY)
|
|
10487
10546
|
transform += `rotateY(${rotateY}deg) `;
|
|
10547
|
+
if (rotateZ)
|
|
10548
|
+
transform += `rotateZ(${rotateZ}deg) `;
|
|
10488
10549
|
if (skewX)
|
|
10489
10550
|
transform += `skewX(${skewX}deg) `;
|
|
10490
10551
|
if (skewY)
|
|
@@ -10503,6 +10564,15 @@
|
|
|
10503
10564
|
}
|
|
10504
10565
|
|
|
10505
10566
|
const numBorders = cornerRadiusProps.length;
|
|
10567
|
+
const mixedTransforms = [
|
|
10568
|
+
"rotate",
|
|
10569
|
+
"rotateX",
|
|
10570
|
+
"rotateY",
|
|
10571
|
+
"rotateZ",
|
|
10572
|
+
"skewX",
|
|
10573
|
+
"skewY",
|
|
10574
|
+
];
|
|
10575
|
+
const numMixedTransforms = mixedTransforms.length;
|
|
10506
10576
|
const isPx = (value) => typeof value === "number" || px.test(value);
|
|
10507
10577
|
function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnlyMember) {
|
|
10508
10578
|
if (shouldCrossfadeOpacity) {
|
|
@@ -10537,10 +10607,14 @@
|
|
|
10537
10607
|
}
|
|
10538
10608
|
}
|
|
10539
10609
|
/**
|
|
10540
|
-
* Mix rotation
|
|
10610
|
+
* Mix rotation and skew. These can't be projected, so mix them every
|
|
10611
|
+
* frame rather than leaving them frozen at the animation-start snapshot.
|
|
10541
10612
|
*/
|
|
10542
|
-
|
|
10543
|
-
|
|
10613
|
+
for (let i = 0; i < numMixedTransforms; i++) {
|
|
10614
|
+
const key = mixedTransforms[i];
|
|
10615
|
+
if (follow[key] || lead[key]) {
|
|
10616
|
+
target[key] = mixNumber$1(follow[key] || 0, lead[key] || 0, progress);
|
|
10617
|
+
}
|
|
10544
10618
|
}
|
|
10545
10619
|
}
|
|
10546
10620
|
function getRadius(values, radiusName) {
|
|
@@ -10990,82 +11064,92 @@
|
|
|
10990
11064
|
if (layoutId) {
|
|
10991
11065
|
this.root.registerSharedNode(layoutId, this);
|
|
10992
11066
|
}
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
11001
|
-
|
|
11067
|
+
this.addLayoutListener();
|
|
11068
|
+
}
|
|
11069
|
+
/**
|
|
11070
|
+
* Only register the layout animation handler if this node requires
|
|
11071
|
+
* layout animation. This is called on mount, and again whenever options
|
|
11072
|
+
* change, as `layout` or `layoutId` may be enabled after mount.
|
|
11073
|
+
*/
|
|
11074
|
+
addLayoutListener() {
|
|
11075
|
+
const { layoutId, layout, visualElement, animate } = this.options;
|
|
11076
|
+
if (!this.instance ||
|
|
11077
|
+
this.hasLayoutListener ||
|
|
11078
|
+
animate === false ||
|
|
11079
|
+
!visualElement ||
|
|
11080
|
+
!(layoutId || layout))
|
|
11081
|
+
return;
|
|
11082
|
+
this.hasLayoutListener = true;
|
|
11083
|
+
this.addEventListener("didUpdate", ({ delta, hasLayoutChanged, hasRelativeLayoutChanged, layout: newLayout, }) => {
|
|
11084
|
+
if (this.isAnimationBlocked) {
|
|
11085
|
+
this.target = undefined;
|
|
11086
|
+
this.relativeTarget = undefined;
|
|
11087
|
+
return;
|
|
11088
|
+
}
|
|
11089
|
+
// TODO: Check here if an animation exists
|
|
11090
|
+
const layoutTransition = this.options.transition ||
|
|
11091
|
+
visualElement.getDefaultTransition() ||
|
|
11092
|
+
defaultLayoutTransition;
|
|
11093
|
+
const { onLayoutAnimationStart, onLayoutAnimationComplete, } = visualElement.getProps();
|
|
11094
|
+
/**
|
|
11095
|
+
* The target layout of the element might stay the same,
|
|
11096
|
+
* but its position relative to its parent has changed.
|
|
11097
|
+
*/
|
|
11098
|
+
const hasTargetChanged = !this.targetLayout ||
|
|
11099
|
+
!boxEqualsRounded(this.targetLayout, newLayout);
|
|
11100
|
+
/*
|
|
11101
|
+
* Note: Disabled to fix relative animations always triggering new
|
|
11102
|
+
* layout animations. If this causes further issues, we can try
|
|
11103
|
+
* a different approach to detecting relative target changes.
|
|
11104
|
+
*/
|
|
11105
|
+
// || hasRelativeLayoutChanged
|
|
11106
|
+
/**
|
|
11107
|
+
* If the layout hasn't seemed to have changed, it might be that the
|
|
11108
|
+
* element is visually in the same place in the document but its position
|
|
11109
|
+
* relative to its parent has indeed changed. So here we check for that.
|
|
11110
|
+
*/
|
|
11111
|
+
const hasOnlyRelativeTargetChanged = !hasLayoutChanged && hasRelativeLayoutChanged;
|
|
11112
|
+
if (this.options.layoutRoot ||
|
|
11113
|
+
this.resumeFrom ||
|
|
11114
|
+
hasOnlyRelativeTargetChanged ||
|
|
11115
|
+
(hasLayoutChanged &&
|
|
11116
|
+
(hasTargetChanged || !this.currentAnimation))) {
|
|
11117
|
+
if (this.resumeFrom) {
|
|
11118
|
+
this.resumingFrom = this.resumeFrom;
|
|
11119
|
+
this.resumingFrom.resumingFrom = undefined;
|
|
11120
|
+
}
|
|
11121
|
+
const animationOptions = {
|
|
11122
|
+
...getValueTransition$1(layoutTransition, "layout"),
|
|
11123
|
+
onPlay: onLayoutAnimationStart,
|
|
11124
|
+
onComplete: onLayoutAnimationComplete,
|
|
11125
|
+
};
|
|
11126
|
+
if (visualElement.shouldReduceMotion ||
|
|
11127
|
+
this.options.layoutRoot) {
|
|
11128
|
+
animationOptions.delay = 0;
|
|
11129
|
+
animationOptions.type = false;
|
|
11002
11130
|
}
|
|
11003
|
-
|
|
11004
|
-
const layoutTransition = this.options.transition ||
|
|
11005
|
-
visualElement.getDefaultTransition() ||
|
|
11006
|
-
defaultLayoutTransition;
|
|
11007
|
-
const { onLayoutAnimationStart, onLayoutAnimationComplete, } = visualElement.getProps();
|
|
11131
|
+
this.startAnimation(animationOptions);
|
|
11008
11132
|
/**
|
|
11009
|
-
*
|
|
11010
|
-
*
|
|
11011
|
-
*/
|
|
11012
|
-
const hasTargetChanged = !this.targetLayout ||
|
|
11013
|
-
!boxEqualsRounded(this.targetLayout, newLayout);
|
|
11014
|
-
/*
|
|
11015
|
-
* Note: Disabled to fix relative animations always triggering new
|
|
11016
|
-
* layout animations. If this causes further issues, we can try
|
|
11017
|
-
* a different approach to detecting relative target changes.
|
|
11133
|
+
* Set animation origin after starting animation to avoid layout jump
|
|
11134
|
+
* caused by stopping previous layout animation
|
|
11018
11135
|
*/
|
|
11019
|
-
|
|
11136
|
+
this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged, animationOptions.path);
|
|
11137
|
+
}
|
|
11138
|
+
else {
|
|
11020
11139
|
/**
|
|
11021
|
-
* If the layout hasn't
|
|
11022
|
-
*
|
|
11023
|
-
*
|
|
11140
|
+
* If the layout hasn't changed and we have an animation that hasn't started yet,
|
|
11141
|
+
* finish it immediately. Otherwise it will be animating from a location
|
|
11142
|
+
* that was probably never committed to screen and look like a jumpy box.
|
|
11024
11143
|
*/
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
this.resumeFrom ||
|
|
11028
|
-
hasOnlyRelativeTargetChanged ||
|
|
11029
|
-
(hasLayoutChanged &&
|
|
11030
|
-
(hasTargetChanged || !this.currentAnimation))) {
|
|
11031
|
-
if (this.resumeFrom) {
|
|
11032
|
-
this.resumingFrom = this.resumeFrom;
|
|
11033
|
-
this.resumingFrom.resumingFrom = undefined;
|
|
11034
|
-
}
|
|
11035
|
-
const animationOptions = {
|
|
11036
|
-
...getValueTransition$1(layoutTransition, "layout"),
|
|
11037
|
-
onPlay: onLayoutAnimationStart,
|
|
11038
|
-
onComplete: onLayoutAnimationComplete,
|
|
11039
|
-
};
|
|
11040
|
-
if (visualElement.shouldReduceMotion ||
|
|
11041
|
-
this.options.layoutRoot) {
|
|
11042
|
-
animationOptions.delay = 0;
|
|
11043
|
-
animationOptions.type = false;
|
|
11044
|
-
}
|
|
11045
|
-
this.startAnimation(animationOptions);
|
|
11046
|
-
/**
|
|
11047
|
-
* Set animation origin after starting animation to avoid layout jump
|
|
11048
|
-
* caused by stopping previous layout animation
|
|
11049
|
-
*/
|
|
11050
|
-
this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged, animationOptions
|
|
11051
|
-
.path);
|
|
11144
|
+
if (!hasLayoutChanged) {
|
|
11145
|
+
finishAnimation(this);
|
|
11052
11146
|
}
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
* If the layout hasn't changed and we have an animation that hasn't started yet,
|
|
11056
|
-
* finish it immediately. Otherwise it will be animating from a location
|
|
11057
|
-
* that was probably never committed to screen and look like a jumpy box.
|
|
11058
|
-
*/
|
|
11059
|
-
if (!hasLayoutChanged) {
|
|
11060
|
-
finishAnimation(this);
|
|
11061
|
-
}
|
|
11062
|
-
if (this.isLead() && this.options.onExitComplete) {
|
|
11063
|
-
this.options.onExitComplete();
|
|
11064
|
-
}
|
|
11147
|
+
if (this.isLead() && this.options.onExitComplete) {
|
|
11148
|
+
this.options.onExitComplete();
|
|
11065
11149
|
}
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
}
|
|
11150
|
+
}
|
|
11151
|
+
this.targetLayout = newLayout;
|
|
11152
|
+
});
|
|
11069
11153
|
}
|
|
11070
11154
|
unmount() {
|
|
11071
11155
|
this.options.layoutId && this.willUpdate();
|
|
@@ -11075,6 +11159,7 @@
|
|
|
11075
11159
|
this.parent && this.parent.children.delete(this);
|
|
11076
11160
|
this.instance = undefined;
|
|
11077
11161
|
this.eventHandlers.clear();
|
|
11162
|
+
this.hasLayoutListener = false;
|
|
11078
11163
|
cancelFrame(this.updateProjection);
|
|
11079
11164
|
}
|
|
11080
11165
|
// only on the root
|
|
@@ -11245,7 +11330,16 @@
|
|
|
11245
11330
|
}
|
|
11246
11331
|
clearAllSnapshots() {
|
|
11247
11332
|
this.nodes.forEach(clearSnapshot);
|
|
11248
|
-
|
|
11333
|
+
/**
|
|
11334
|
+
* A stack's last member can unmount while a replacement with the
|
|
11335
|
+
* same layoutId mounts in the same commit, so the stack (and its
|
|
11336
|
+
* lead) must outlive the unmount for the replacement to resume
|
|
11337
|
+
* from it. By now that handoff has happened, so stacks that are
|
|
11338
|
+
* still empty only retain unmounted nodes and can be released.
|
|
11339
|
+
*/
|
|
11340
|
+
this.sharedNodes.forEach((stack, layoutId) => stack.members.length
|
|
11341
|
+
? stack.removeLeadSnapshot()
|
|
11342
|
+
: this.sharedNodes.delete(layoutId));
|
|
11249
11343
|
}
|
|
11250
11344
|
scheduleUpdateProjection() {
|
|
11251
11345
|
if (!this.projectionUpdateScheduled) {
|
|
@@ -11469,6 +11563,7 @@
|
|
|
11469
11563
|
...options,
|
|
11470
11564
|
crossfade: options.crossfade !== undefined ? options.crossfade : true,
|
|
11471
11565
|
};
|
|
11566
|
+
this.addLayoutListener();
|
|
11472
11567
|
}
|
|
11473
11568
|
clearMeasurements() {
|
|
11474
11569
|
this.scroll = undefined;
|
|
@@ -12398,9 +12493,6 @@
|
|
|
12398
12493
|
function resetSkewAndRotation(node) {
|
|
12399
12494
|
node.resetSkewAndRotation();
|
|
12400
12495
|
}
|
|
12401
|
-
function removeLeadSnapshots(stack) {
|
|
12402
|
-
stack.removeLeadSnapshot();
|
|
12403
|
-
}
|
|
12404
12496
|
function mixAxisDeltaLinear(output, delta, p) {
|
|
12405
12497
|
output.translate = mixNumber$1(delta.translate, 0, p);
|
|
12406
12498
|
output.scale = mixNumber$1(delta.scale, 1, p);
|