motion 12.27.3-alpha.1 → 12.27.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.
- package/dist/motion.dev.js +308 -230
- package/dist/motion.js +1 -1
- package/package.json +3 -3
package/dist/motion.dev.js
CHANGED
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/*#__NO_SIDE_EFFECTS__*/
|
|
84
|
-
const noop
|
|
84
|
+
const noop = (any) => any;
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
87
|
* Pipe
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
function cubicBezier(mX1, mY1, mX2, mY2) {
|
|
228
228
|
// If this is a linear gradient, return linear easing
|
|
229
229
|
if (mX1 === mY1 && mX2 === mY2)
|
|
230
|
-
return noop
|
|
230
|
+
return noop;
|
|
231
231
|
const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
|
|
232
232
|
// If animation is at start/end, return t without easing
|
|
233
233
|
return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
|
|
@@ -278,7 +278,7 @@
|
|
|
278
278
|
const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
|
|
279
279
|
|
|
280
280
|
const easingLookup = {
|
|
281
|
-
linear: noop
|
|
281
|
+
linear: noop,
|
|
282
282
|
easeIn,
|
|
283
283
|
easeInOut,
|
|
284
284
|
easeOut,
|
|
@@ -479,7 +479,7 @@
|
|
|
479
479
|
return { schedule, cancel, state, steps };
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
-
const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = /* @__PURE__ */ createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop
|
|
482
|
+
const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = /* @__PURE__ */ createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
|
|
483
483
|
|
|
484
484
|
let now;
|
|
485
485
|
function clearTime() {
|
|
@@ -1429,7 +1429,7 @@
|
|
|
1429
1429
|
for (let i = 0; i < numMixers; i++) {
|
|
1430
1430
|
let mixer = mixerFactory(output[i], output[i + 1]);
|
|
1431
1431
|
if (ease) {
|
|
1432
|
-
const easingFunction = Array.isArray(ease) ? ease[i] || noop
|
|
1432
|
+
const easingFunction = Array.isArray(ease) ? ease[i] || noop : ease;
|
|
1433
1433
|
mixer = pipe(easingFunction, mixer);
|
|
1434
1434
|
}
|
|
1435
1435
|
mixers.push(mixer);
|
|
@@ -2491,7 +2491,7 @@
|
|
|
2491
2491
|
this.animation.onfinish = null;
|
|
2492
2492
|
if (timeline && supportsScrollTimeline()) {
|
|
2493
2493
|
this.animation.timeline = timeline;
|
|
2494
|
-
return noop
|
|
2494
|
+
return noop;
|
|
2495
2495
|
}
|
|
2496
2496
|
else {
|
|
2497
2497
|
return observe(this);
|
|
@@ -2783,7 +2783,7 @@
|
|
|
2783
2783
|
: new JSAnimation(resolvedOptions);
|
|
2784
2784
|
animation.finished.then(() => {
|
|
2785
2785
|
this.notifyFinished();
|
|
2786
|
-
}).catch(noop
|
|
2786
|
+
}).catch(noop);
|
|
2787
2787
|
if (this.pendingTimeline) {
|
|
2788
2788
|
this.stopTimeline = animation.attachTimeline(this.pendingTimeline);
|
|
2789
2789
|
this.pendingTimeline = undefined;
|
|
@@ -5402,7 +5402,7 @@
|
|
|
5402
5402
|
constructor(update, options = {}) {
|
|
5403
5403
|
this.currentSubject = "root";
|
|
5404
5404
|
this.targets = new Map();
|
|
5405
|
-
this.notifyReady = noop
|
|
5405
|
+
this.notifyReady = noop;
|
|
5406
5406
|
this.readyPromise = new Promise((resolve) => {
|
|
5407
5407
|
this.notifyReady = resolve;
|
|
5408
5408
|
});
|
|
@@ -7457,7 +7457,7 @@
|
|
|
7457
7457
|
: values.borderRadius;
|
|
7458
7458
|
}
|
|
7459
7459
|
const easeCrossfadeIn = /*@__PURE__*/ compress(0, 0.5, circOut);
|
|
7460
|
-
const easeCrossfadeOut = /*@__PURE__*/ compress(0.5, 0.95, noop
|
|
7460
|
+
const easeCrossfadeOut = /*@__PURE__*/ compress(0.5, 0.95, noop);
|
|
7461
7461
|
function compress(min, max, easing) {
|
|
7462
7462
|
return (p) => {
|
|
7463
7463
|
// Could replace ifs with clamp
|
|
@@ -7683,7 +7683,7 @@
|
|
|
7683
7683
|
cancelTreeOptimisedTransformAnimations(parent);
|
|
7684
7684
|
}
|
|
7685
7685
|
}
|
|
7686
|
-
function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
|
|
7686
|
+
function createProjectionNode$1({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
|
|
7687
7687
|
return class ProjectionNode {
|
|
7688
7688
|
constructor(latestValues = {}, parent = defaultParent?.()) {
|
|
7689
7689
|
/**
|
|
@@ -9221,7 +9221,7 @@
|
|
|
9221
9221
|
*/
|
|
9222
9222
|
const roundPoint = userAgentContains("applewebkit/") && !userAgentContains("chrome/")
|
|
9223
9223
|
? Math.round
|
|
9224
|
-
: noop
|
|
9224
|
+
: noop;
|
|
9225
9225
|
function roundAxis(axis) {
|
|
9226
9226
|
// Round to the nearest .5 pixels to support subpixel layouts
|
|
9227
9227
|
axis.min = roundPoint(axis.min);
|
|
@@ -9240,7 +9240,7 @@
|
|
|
9240
9240
|
return node !== node.root && node.scroll?.wasRoot;
|
|
9241
9241
|
}
|
|
9242
9242
|
|
|
9243
|
-
const DocumentProjectionNode = createProjectionNode({
|
|
9243
|
+
const DocumentProjectionNode = createProjectionNode$1({
|
|
9244
9244
|
attachResizeListener: (ref, notify) => addDomEvent(ref, "resize", notify),
|
|
9245
9245
|
measureScroll: () => ({
|
|
9246
9246
|
x: document.documentElement.scrollLeft || document.body.scrollLeft,
|
|
@@ -9275,7 +9275,7 @@
|
|
|
9275
9275
|
const rootProjectionNode = {
|
|
9276
9276
|
current: undefined,
|
|
9277
9277
|
};
|
|
9278
|
-
const HTMLProjectionNode = createProjectionNode({
|
|
9278
|
+
const HTMLProjectionNode = createProjectionNode$1({
|
|
9279
9279
|
measureScroll: (instance) => ({
|
|
9280
9280
|
x: instance.scrollLeft,
|
|
9281
9281
|
y: instance.scrollTop,
|
|
@@ -9295,113 +9295,315 @@
|
|
|
9295
9295
|
checkIsScrollRoot: (instance) => Boolean(window.getComputedStyle(instance).position === "fixed"),
|
|
9296
9296
|
});
|
|
9297
9297
|
|
|
9298
|
-
const
|
|
9299
|
-
|
|
9298
|
+
const LAYOUT_SELECTOR = "[data-layout], [data-layout-id]";
|
|
9299
|
+
function getLayoutElements(scope) {
|
|
9300
|
+
const elements = Array.from(scope.querySelectorAll(LAYOUT_SELECTOR));
|
|
9301
|
+
// Include scope itself if it's an Element (not Document) and has layout attributes
|
|
9302
|
+
if (scope instanceof Element && hasLayout(scope)) {
|
|
9303
|
+
elements.unshift(scope);
|
|
9304
|
+
}
|
|
9305
|
+
return elements;
|
|
9306
|
+
}
|
|
9307
|
+
function getLayoutId(element) {
|
|
9308
|
+
return element.getAttribute("data-layout-id");
|
|
9309
|
+
}
|
|
9310
|
+
function hasLayout(element) {
|
|
9311
|
+
return (element.hasAttribute("data-layout") ||
|
|
9312
|
+
element.hasAttribute("data-layout-id"));
|
|
9313
|
+
}
|
|
9314
|
+
|
|
9315
|
+
let scaleCorrectorAdded = false;
|
|
9316
|
+
/**
|
|
9317
|
+
* Track active projection nodes per element to handle animation interruption.
|
|
9318
|
+
* When a new animation starts on an element that already has an active animation,
|
|
9319
|
+
* we need to stop the old animation so the new one can start from the current
|
|
9320
|
+
* visual position.
|
|
9321
|
+
*/
|
|
9322
|
+
const activeProjectionNodes = new WeakMap();
|
|
9323
|
+
function ensureScaleCorrectors() {
|
|
9324
|
+
if (scaleCorrectorAdded)
|
|
9325
|
+
return;
|
|
9326
|
+
scaleCorrectorAdded = true;
|
|
9327
|
+
addScaleCorrector({
|
|
9328
|
+
borderRadius: {
|
|
9329
|
+
...correctBorderRadius,
|
|
9330
|
+
applyTo: [
|
|
9331
|
+
"borderTopLeftRadius",
|
|
9332
|
+
"borderTopRightRadius",
|
|
9333
|
+
"borderBottomLeftRadius",
|
|
9334
|
+
"borderBottomRightRadius",
|
|
9335
|
+
],
|
|
9336
|
+
},
|
|
9337
|
+
borderTopLeftRadius: correctBorderRadius,
|
|
9338
|
+
borderTopRightRadius: correctBorderRadius,
|
|
9339
|
+
borderBottomLeftRadius: correctBorderRadius,
|
|
9340
|
+
borderBottomRightRadius: correctBorderRadius,
|
|
9341
|
+
boxShadow: correctBoxShadow,
|
|
9342
|
+
});
|
|
9343
|
+
}
|
|
9344
|
+
/**
|
|
9345
|
+
* Get DOM depth of an element
|
|
9346
|
+
*/
|
|
9347
|
+
function getDepth(element) {
|
|
9348
|
+
let depth = 0;
|
|
9349
|
+
let current = element.parentElement;
|
|
9350
|
+
while (current) {
|
|
9351
|
+
depth++;
|
|
9352
|
+
current = current.parentElement;
|
|
9353
|
+
}
|
|
9354
|
+
return depth;
|
|
9355
|
+
}
|
|
9356
|
+
/**
|
|
9357
|
+
* Find the closest projection parent for an element
|
|
9358
|
+
*/
|
|
9359
|
+
function findProjectionParent(element, nodeCache) {
|
|
9360
|
+
let parent = element.parentElement;
|
|
9361
|
+
while (parent) {
|
|
9362
|
+
const node = nodeCache.get(parent);
|
|
9363
|
+
if (node)
|
|
9364
|
+
return node;
|
|
9365
|
+
parent = parent.parentElement;
|
|
9366
|
+
}
|
|
9367
|
+
return undefined;
|
|
9368
|
+
}
|
|
9369
|
+
/**
|
|
9370
|
+
* Create or reuse a projection node for an element
|
|
9371
|
+
*/
|
|
9372
|
+
function createProjectionNode(element, parent, options, transition) {
|
|
9373
|
+
// Check for existing active node - reuse it to preserve animation state
|
|
9374
|
+
const existingNode = activeProjectionNodes.get(element);
|
|
9375
|
+
if (existingNode) {
|
|
9376
|
+
const visualElement = existingNode.options.visualElement;
|
|
9377
|
+
// Update transition options for the new animation
|
|
9378
|
+
const nodeTransition = transition
|
|
9379
|
+
? { duration: transition.duration, ease: transition.ease }
|
|
9380
|
+
: { duration: 0.3, ease: "easeOut" };
|
|
9381
|
+
existingNode.setOptions({
|
|
9382
|
+
...existingNode.options,
|
|
9383
|
+
animate: true,
|
|
9384
|
+
transition: nodeTransition,
|
|
9385
|
+
...options,
|
|
9386
|
+
});
|
|
9387
|
+
// Re-mount the node if it was previously unmounted
|
|
9388
|
+
// This re-adds it to root.nodes so didUpdate() will process it
|
|
9389
|
+
if (!existingNode.instance) {
|
|
9390
|
+
existingNode.mount(element);
|
|
9391
|
+
}
|
|
9392
|
+
return { node: existingNode, visualElement };
|
|
9393
|
+
}
|
|
9394
|
+
// No existing node - create a new one
|
|
9395
|
+
const latestValues = {};
|
|
9396
|
+
const visualElement = new HTMLVisualElement({
|
|
9397
|
+
visualState: {
|
|
9398
|
+
latestValues,
|
|
9399
|
+
renderState: {
|
|
9400
|
+
transformOrigin: {},
|
|
9401
|
+
transform: {},
|
|
9402
|
+
style: {},
|
|
9403
|
+
vars: {},
|
|
9404
|
+
},
|
|
9405
|
+
},
|
|
9406
|
+
presenceContext: null,
|
|
9407
|
+
props: {},
|
|
9408
|
+
});
|
|
9409
|
+
const node = new HTMLProjectionNode(latestValues, parent);
|
|
9410
|
+
// Convert AnimationOptions to transition format for the projection system
|
|
9411
|
+
const nodeTransition = transition
|
|
9412
|
+
? { duration: transition.duration, ease: transition.ease }
|
|
9413
|
+
: { duration: 0.3, ease: "easeOut" };
|
|
9414
|
+
node.setOptions({
|
|
9415
|
+
visualElement,
|
|
9416
|
+
layout: true,
|
|
9417
|
+
animate: true,
|
|
9418
|
+
transition: nodeTransition,
|
|
9419
|
+
...options,
|
|
9420
|
+
});
|
|
9421
|
+
node.mount(element);
|
|
9422
|
+
visualElement.projection = node;
|
|
9423
|
+
// Track this node as the active one for this element
|
|
9424
|
+
activeProjectionNodes.set(element, node);
|
|
9425
|
+
return { node, visualElement };
|
|
9426
|
+
}
|
|
9427
|
+
/**
|
|
9428
|
+
* Build a projection tree from a list of elements
|
|
9429
|
+
*/
|
|
9430
|
+
function buildProjectionTree(elements, existingContext, options) {
|
|
9431
|
+
ensureScaleCorrectors();
|
|
9432
|
+
const nodes = existingContext?.nodes ?? new Map();
|
|
9433
|
+
const visualElements = existingContext?.visualElements ?? new Map();
|
|
9434
|
+
const group = existingContext?.group ?? nodeGroup();
|
|
9435
|
+
const defaultTransition = options?.defaultTransition;
|
|
9436
|
+
const sharedTransitions = options?.sharedTransitions;
|
|
9437
|
+
// Sort elements by DOM depth (parents before children)
|
|
9438
|
+
const sorted = [...elements].sort((a, b) => getDepth(a) - getDepth(b));
|
|
9439
|
+
let root = existingContext?.root;
|
|
9440
|
+
for (const element of sorted) {
|
|
9441
|
+
// Skip if already has a node
|
|
9442
|
+
if (nodes.has(element))
|
|
9443
|
+
continue;
|
|
9444
|
+
const parent = findProjectionParent(element, nodes);
|
|
9445
|
+
const layoutId = getLayoutId(element);
|
|
9446
|
+
const layoutMode = element.getAttribute("data-layout");
|
|
9447
|
+
const nodeOptions = {
|
|
9448
|
+
layoutId: layoutId ?? undefined,
|
|
9449
|
+
animationType: parseLayoutMode(layoutMode),
|
|
9450
|
+
};
|
|
9451
|
+
// Use layoutId-specific transition if available, otherwise use default
|
|
9452
|
+
const transition = layoutId && sharedTransitions?.get(layoutId)
|
|
9453
|
+
? sharedTransitions.get(layoutId)
|
|
9454
|
+
: defaultTransition;
|
|
9455
|
+
const { node, visualElement } = createProjectionNode(element, parent, nodeOptions, transition);
|
|
9456
|
+
nodes.set(element, node);
|
|
9457
|
+
visualElements.set(element, visualElement);
|
|
9458
|
+
group.add(node);
|
|
9459
|
+
if (!root) {
|
|
9460
|
+
root = node.root;
|
|
9461
|
+
}
|
|
9462
|
+
}
|
|
9463
|
+
return {
|
|
9464
|
+
nodes,
|
|
9465
|
+
visualElements,
|
|
9466
|
+
group,
|
|
9467
|
+
root: root,
|
|
9468
|
+
};
|
|
9469
|
+
}
|
|
9470
|
+
/**
|
|
9471
|
+
* Parse the data-layout attribute value
|
|
9472
|
+
*/
|
|
9473
|
+
function parseLayoutMode(value) {
|
|
9474
|
+
if (value === "position")
|
|
9475
|
+
return "position";
|
|
9476
|
+
if (value === "size")
|
|
9477
|
+
return "size";
|
|
9478
|
+
if (value === "preserve-aspect")
|
|
9479
|
+
return "preserve-aspect";
|
|
9480
|
+
return "both";
|
|
9481
|
+
}
|
|
9482
|
+
/**
|
|
9483
|
+
* Clean up projection nodes for specific elements.
|
|
9484
|
+
* If elementsToCleanup is provided, only those elements are cleaned up.
|
|
9485
|
+
* If not provided, all nodes are cleaned up.
|
|
9486
|
+
*
|
|
9487
|
+
* This allows persisting elements to keep their nodes between animations,
|
|
9488
|
+
* matching React's behavior where nodes persist for elements that remain in the DOM.
|
|
9489
|
+
*/
|
|
9490
|
+
function cleanupProjectionTree(context, elementsToCleanup) {
|
|
9491
|
+
const elementsToProcess = elementsToCleanup
|
|
9492
|
+
? [...context.nodes.entries()].filter(([el]) => elementsToCleanup.has(el))
|
|
9493
|
+
: [...context.nodes.entries()];
|
|
9494
|
+
for (const [element, node] of elementsToProcess) {
|
|
9495
|
+
context.group.remove(node);
|
|
9496
|
+
node.unmount();
|
|
9497
|
+
// Only clear from activeProjectionNodes if this is still the active node.
|
|
9498
|
+
// A newer animation might have already taken over.
|
|
9499
|
+
if (activeProjectionNodes.get(element) === node) {
|
|
9500
|
+
activeProjectionNodes.delete(element);
|
|
9501
|
+
}
|
|
9502
|
+
context.nodes.delete(element);
|
|
9503
|
+
context.visualElements.delete(element);
|
|
9504
|
+
}
|
|
9505
|
+
}
|
|
9506
|
+
|
|
9300
9507
|
class LayoutAnimationBuilder {
|
|
9301
9508
|
constructor(scope, updateDom, defaultOptions) {
|
|
9302
9509
|
this.sharedTransitions = new Map();
|
|
9303
9510
|
this.notifyReady = noop;
|
|
9304
|
-
this.
|
|
9511
|
+
this.executed = false;
|
|
9305
9512
|
this.scope = scope;
|
|
9306
9513
|
this.updateDom = updateDom;
|
|
9307
9514
|
this.defaultOptions = defaultOptions;
|
|
9308
|
-
this.readyPromise = new Promise((resolve
|
|
9515
|
+
this.readyPromise = new Promise((resolve) => {
|
|
9309
9516
|
this.notifyReady = resolve;
|
|
9310
|
-
this.rejectReady = reject;
|
|
9311
|
-
});
|
|
9312
|
-
microtask.read(() => {
|
|
9313
|
-
this.start().then(this.notifyReady).catch(this.rejectReady);
|
|
9314
9517
|
});
|
|
9518
|
+
// Queue execution on microtask to allow builder methods to be called
|
|
9519
|
+
queueMicrotask(() => this.execute());
|
|
9315
9520
|
}
|
|
9316
|
-
shared(id,
|
|
9317
|
-
this.sharedTransitions.set(id,
|
|
9521
|
+
shared(id, options) {
|
|
9522
|
+
this.sharedTransitions.set(id, options);
|
|
9318
9523
|
return this;
|
|
9319
9524
|
}
|
|
9320
|
-
then(
|
|
9321
|
-
return this.readyPromise.then(
|
|
9525
|
+
then(onfulfilled, onrejected) {
|
|
9526
|
+
return this.readyPromise.then(onfulfilled, onrejected);
|
|
9322
9527
|
}
|
|
9323
|
-
async
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
const
|
|
9345
|
-
const
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
});
|
|
9355
|
-
};
|
|
9356
|
-
animation.finished.then(cleanup, cleanup);
|
|
9528
|
+
async execute() {
|
|
9529
|
+
if (this.executed)
|
|
9530
|
+
return;
|
|
9531
|
+
this.executed = true;
|
|
9532
|
+
let context;
|
|
9533
|
+
// Phase 1: Pre-mutation - Build projection tree and take snapshots
|
|
9534
|
+
const beforeElements = getLayoutElements(this.scope);
|
|
9535
|
+
if (beforeElements.length > 0) {
|
|
9536
|
+
context = buildProjectionTree(beforeElements, undefined, this.getBuildOptions());
|
|
9537
|
+
context.root.startUpdate();
|
|
9538
|
+
for (const node of context.nodes.values()) {
|
|
9539
|
+
node.isLayoutDirty = false;
|
|
9540
|
+
node.willUpdate();
|
|
9541
|
+
}
|
|
9542
|
+
}
|
|
9543
|
+
// Phase 2: Execute DOM update
|
|
9544
|
+
this.updateDom();
|
|
9545
|
+
// Phase 3: Post-mutation - Compare before/after elements
|
|
9546
|
+
const afterElements = getLayoutElements(this.scope);
|
|
9547
|
+
const beforeSet = new Set(beforeElements);
|
|
9548
|
+
const afterSet = new Set(afterElements);
|
|
9549
|
+
const entering = afterElements.filter((el) => !beforeSet.has(el));
|
|
9550
|
+
const exiting = beforeElements.filter((el) => !afterSet.has(el));
|
|
9551
|
+
// Build projection nodes for entering elements
|
|
9552
|
+
if (entering.length > 0) {
|
|
9553
|
+
context = buildProjectionTree(entering, context, this.getBuildOptions());
|
|
9554
|
+
}
|
|
9555
|
+
// No layout elements - return empty animation
|
|
9556
|
+
if (!context) {
|
|
9557
|
+
this.notifyReady(new GroupAnimation([]));
|
|
9558
|
+
return;
|
|
9357
9559
|
}
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
const recordMap = new Map();
|
|
9363
|
-
for (const element of elements) {
|
|
9364
|
-
const parentRecord = findParentRecord(element, recordMap, this.scope);
|
|
9365
|
-
const { layout, layoutId } = readLayoutAttributes(element);
|
|
9366
|
-
const override = layoutId
|
|
9367
|
-
? this.sharedTransitions.get(layoutId)
|
|
9368
|
-
: undefined;
|
|
9369
|
-
const transition = override || this.defaultOptions;
|
|
9370
|
-
const record = getOrCreateRecord(element, parentRecord?.projection, {
|
|
9371
|
-
layout,
|
|
9372
|
-
layoutId,
|
|
9373
|
-
animationType: typeof layout === "string" ? layout : "both",
|
|
9374
|
-
transition: transition,
|
|
9375
|
-
});
|
|
9376
|
-
recordMap.set(element, record);
|
|
9377
|
-
records.push(record);
|
|
9560
|
+
// Handle shared elements
|
|
9561
|
+
for (const element of exiting) {
|
|
9562
|
+
const node = context.nodes.get(element);
|
|
9563
|
+
node?.getStack()?.remove(node);
|
|
9378
9564
|
}
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9565
|
+
for (const element of entering) {
|
|
9566
|
+
context.nodes.get(element)?.promote();
|
|
9567
|
+
}
|
|
9568
|
+
// Phase 4: Animate
|
|
9569
|
+
context.root.didUpdate();
|
|
9570
|
+
await new Promise((resolve) => frame.postRender(() => resolve()));
|
|
9571
|
+
const animations = [];
|
|
9572
|
+
for (const node of context.nodes.values()) {
|
|
9573
|
+
if (node.currentAnimation) {
|
|
9574
|
+
animations.push(node.currentAnimation);
|
|
9575
|
+
}
|
|
9576
|
+
}
|
|
9577
|
+
const groupAnimation = new GroupAnimation(animations);
|
|
9578
|
+
groupAnimation.finished.then(() => {
|
|
9579
|
+
// Only clean up nodes for elements no longer in the document.
|
|
9580
|
+
// Elements still in DOM keep their nodes so subsequent animations
|
|
9581
|
+
// can use the stored position snapshots (A→B→A pattern).
|
|
9582
|
+
const elementsToCleanup = new Set();
|
|
9583
|
+
for (const element of context.nodes.keys()) {
|
|
9584
|
+
if (!document.contains(element)) {
|
|
9585
|
+
elementsToCleanup.add(element);
|
|
9586
|
+
}
|
|
9399
9587
|
}
|
|
9400
|
-
|
|
9588
|
+
cleanupProjectionTree(context, elementsToCleanup);
|
|
9401
9589
|
});
|
|
9402
|
-
|
|
9590
|
+
this.notifyReady(groupAnimation);
|
|
9591
|
+
}
|
|
9592
|
+
getBuildOptions() {
|
|
9593
|
+
return {
|
|
9594
|
+
defaultTransition: this.defaultOptions || {
|
|
9595
|
+
duration: 0.3,
|
|
9596
|
+
ease: "easeOut",
|
|
9597
|
+
},
|
|
9598
|
+
sharedTransitions: this.sharedTransitions.size > 0
|
|
9599
|
+
? this.sharedTransitions
|
|
9600
|
+
: undefined,
|
|
9601
|
+
};
|
|
9403
9602
|
}
|
|
9404
9603
|
}
|
|
9604
|
+
/**
|
|
9605
|
+
* Parse arguments for animateLayout overloads
|
|
9606
|
+
*/
|
|
9405
9607
|
function parseAnimateLayoutArgs(scopeOrUpdateDom, updateDomOrOptions, options) {
|
|
9406
9608
|
// animateLayout(updateDom)
|
|
9407
9609
|
if (typeof scopeOrUpdateDom === "function") {
|
|
@@ -9415,135 +9617,11 @@
|
|
|
9415
9617
|
const elements = resolveElements(scopeOrUpdateDom);
|
|
9416
9618
|
const scope = elements[0] || document;
|
|
9417
9619
|
return {
|
|
9418
|
-
scope,
|
|
9620
|
+
scope: scope instanceof Document ? scope : scope,
|
|
9419
9621
|
updateDom: updateDomOrOptions,
|
|
9420
9622
|
defaultOptions: options,
|
|
9421
9623
|
};
|
|
9422
9624
|
}
|
|
9423
|
-
function collectLayoutElements(scope) {
|
|
9424
|
-
const elements = Array.from(scope.querySelectorAll(layoutSelector));
|
|
9425
|
-
if (scope instanceof Element && scope.matches(layoutSelector)) {
|
|
9426
|
-
if (!elements.includes(scope)) {
|
|
9427
|
-
elements.unshift(scope);
|
|
9428
|
-
}
|
|
9429
|
-
}
|
|
9430
|
-
return elements;
|
|
9431
|
-
}
|
|
9432
|
-
function readLayoutAttributes(element) {
|
|
9433
|
-
const layoutId = element.getAttribute("data-layout-id") || undefined;
|
|
9434
|
-
const rawLayout = element.getAttribute("data-layout");
|
|
9435
|
-
let layout;
|
|
9436
|
-
if (rawLayout === "" || rawLayout === "true") {
|
|
9437
|
-
layout = true;
|
|
9438
|
-
}
|
|
9439
|
-
else if (rawLayout) {
|
|
9440
|
-
layout = rawLayout;
|
|
9441
|
-
}
|
|
9442
|
-
return {
|
|
9443
|
-
layout,
|
|
9444
|
-
layoutId,
|
|
9445
|
-
layoutExit: element.hasAttribute("data-layout-exit"),
|
|
9446
|
-
};
|
|
9447
|
-
}
|
|
9448
|
-
function createVisualState() {
|
|
9449
|
-
return {
|
|
9450
|
-
latestValues: {},
|
|
9451
|
-
renderState: {
|
|
9452
|
-
transform: {},
|
|
9453
|
-
transformOrigin: {},
|
|
9454
|
-
style: {},
|
|
9455
|
-
vars: {},
|
|
9456
|
-
},
|
|
9457
|
-
};
|
|
9458
|
-
}
|
|
9459
|
-
function seedProjectionSnapshot(projection) {
|
|
9460
|
-
const projectionNode = projection;
|
|
9461
|
-
if (!projectionNode.currentAnimation && !projectionNode.pendingAnimation) {
|
|
9462
|
-
return;
|
|
9463
|
-
}
|
|
9464
|
-
const snapshot = projection.measure(false);
|
|
9465
|
-
snapshot.latestValues =
|
|
9466
|
-
projectionNode.animationValues || projection.latestValues;
|
|
9467
|
-
projection.snapshot = snapshot;
|
|
9468
|
-
}
|
|
9469
|
-
function getOrCreateRecord(element, parentProjection, projectionOptions) {
|
|
9470
|
-
const existing = visualElementStore.get(element);
|
|
9471
|
-
const visualElement = existing ??
|
|
9472
|
-
new HTMLVisualElement({
|
|
9473
|
-
props: {},
|
|
9474
|
-
presenceContext: null,
|
|
9475
|
-
visualState: createVisualState(),
|
|
9476
|
-
}, { allowProjection: true });
|
|
9477
|
-
if (!existing || !visualElement.projection) {
|
|
9478
|
-
visualElement.projection = new HTMLProjectionNode(visualElement.latestValues, parentProjection);
|
|
9479
|
-
}
|
|
9480
|
-
visualElement.projection.setOptions({
|
|
9481
|
-
...projectionOptions,
|
|
9482
|
-
visualElement,
|
|
9483
|
-
});
|
|
9484
|
-
if (!visualElement.current) {
|
|
9485
|
-
visualElement.mount(element);
|
|
9486
|
-
}
|
|
9487
|
-
if (!existing) {
|
|
9488
|
-
visualElementStore.set(element, visualElement);
|
|
9489
|
-
}
|
|
9490
|
-
return {
|
|
9491
|
-
element,
|
|
9492
|
-
visualElement,
|
|
9493
|
-
projection: visualElement.projection,
|
|
9494
|
-
};
|
|
9495
|
-
}
|
|
9496
|
-
function findParentRecord(element, recordMap, scope) {
|
|
9497
|
-
let parent = element.parentElement;
|
|
9498
|
-
while (parent) {
|
|
9499
|
-
const record = recordMap.get(parent);
|
|
9500
|
-
if (record)
|
|
9501
|
-
return record;
|
|
9502
|
-
if (parent === scope)
|
|
9503
|
-
break;
|
|
9504
|
-
parent = parent.parentElement;
|
|
9505
|
-
}
|
|
9506
|
-
return undefined;
|
|
9507
|
-
}
|
|
9508
|
-
function collectExitCandidates(records) {
|
|
9509
|
-
const exitCandidates = new Map();
|
|
9510
|
-
records.forEach((record) => {
|
|
9511
|
-
const { layoutExit } = readLayoutAttributes(record.element);
|
|
9512
|
-
if (!layoutExit)
|
|
9513
|
-
return;
|
|
9514
|
-
exitCandidates.set(record.element, {
|
|
9515
|
-
...record,
|
|
9516
|
-
parent: record.element.parentNode,
|
|
9517
|
-
nextSibling: record.element.nextSibling,
|
|
9518
|
-
});
|
|
9519
|
-
});
|
|
9520
|
-
return exitCandidates;
|
|
9521
|
-
}
|
|
9522
|
-
function reinstateExitElement(record) {
|
|
9523
|
-
if (!record.parent)
|
|
9524
|
-
return;
|
|
9525
|
-
if (record.nextSibling && record.nextSibling.parentNode === record.parent) {
|
|
9526
|
-
record.parent.insertBefore(record.element, record.nextSibling);
|
|
9527
|
-
}
|
|
9528
|
-
else {
|
|
9529
|
-
record.parent.appendChild(record.element);
|
|
9530
|
-
}
|
|
9531
|
-
}
|
|
9532
|
-
function getProjectionRoot(afterRecords, beforeRecords) {
|
|
9533
|
-
const record = afterRecords[0] || beforeRecords[0];
|
|
9534
|
-
return record?.projection.root;
|
|
9535
|
-
}
|
|
9536
|
-
function collectAnimations(afterRecords, exitRecords) {
|
|
9537
|
-
const animations = new Set();
|
|
9538
|
-
const addAnimation = (record) => {
|
|
9539
|
-
const animation = record.projection.currentAnimation;
|
|
9540
|
-
if (animation)
|
|
9541
|
-
animations.add(animation);
|
|
9542
|
-
};
|
|
9543
|
-
afterRecords.forEach(addAnimation);
|
|
9544
|
-
exitRecords.forEach(addAnimation);
|
|
9545
|
-
return Array.from(animations);
|
|
9546
|
-
}
|
|
9547
9625
|
|
|
9548
9626
|
/**
|
|
9549
9627
|
* @deprecated
|
|
@@ -10437,7 +10515,7 @@
|
|
|
10437
10515
|
const getEventTarget = (element) => element === document.scrollingElement ? window : element;
|
|
10438
10516
|
function scrollInfo(onScroll, { container = document.scrollingElement, ...options } = {}) {
|
|
10439
10517
|
if (!container)
|
|
10440
|
-
return noop
|
|
10518
|
+
return noop;
|
|
10441
10519
|
let containerHandlers = onScrollHandlers.get(container);
|
|
10442
10520
|
/**
|
|
10443
10521
|
* Get the onScroll handlers for this container.
|
|
@@ -10565,7 +10643,7 @@
|
|
|
10565
10643
|
|
|
10566
10644
|
function scroll(onScroll, { axis = "y", container = document.scrollingElement, ...options } = {}) {
|
|
10567
10645
|
if (!container)
|
|
10568
|
-
return noop
|
|
10646
|
+
return noop;
|
|
10569
10647
|
const optionsWithDefaults = { axis, container, ...options };
|
|
10570
10648
|
return typeof onScroll === "function"
|
|
10571
10649
|
? attachToFunction(onScroll, optionsWithDefaults)
|
|
@@ -10726,7 +10804,7 @@
|
|
|
10726
10804
|
exports.createBox = createBox;
|
|
10727
10805
|
exports.createDelta = createDelta;
|
|
10728
10806
|
exports.createGeneratorEasing = createGeneratorEasing;
|
|
10729
|
-
exports.createProjectionNode = createProjectionNode;
|
|
10807
|
+
exports.createProjectionNode = createProjectionNode$1;
|
|
10730
10808
|
exports.createRenderBatcher = createRenderBatcher;
|
|
10731
10809
|
exports.createScopedAnimate = createScopedAnimate;
|
|
10732
10810
|
exports.cubicBezier = cubicBezier;
|
|
@@ -10840,7 +10918,7 @@
|
|
|
10840
10918
|
exports.motionValue = motionValue;
|
|
10841
10919
|
exports.moveItem = moveItem;
|
|
10842
10920
|
exports.nodeGroup = nodeGroup;
|
|
10843
|
-
exports.noop = noop
|
|
10921
|
+
exports.noop = noop;
|
|
10844
10922
|
exports.number = number;
|
|
10845
10923
|
exports.numberValueTypes = numberValueTypes;
|
|
10846
10924
|
exports.observeTimeline = observeTimeline;
|