motion 12.27.1 → 12.27.3-alpha.0
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 +235 -311
- 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 = (any) => any;
|
|
84
|
+
const noop$1 = (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$1;
|
|
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$1,
|
|
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, true);
|
|
482
|
+
const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = /* @__PURE__ */ createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop$1, 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 : ease;
|
|
1432
|
+
const easingFunction = Array.isArray(ease) ? ease[i] || noop$1 : 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$1;
|
|
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$1);
|
|
2787
2787
|
if (this.pendingTimeline) {
|
|
2788
2788
|
this.stopTimeline = animation.attachTimeline(this.pendingTimeline);
|
|
2789
2789
|
this.pendingTimeline = undefined;
|
|
@@ -4195,6 +4195,9 @@
|
|
|
4195
4195
|
]);
|
|
4196
4196
|
|
|
4197
4197
|
function resolveElements(elementOrSelector, scope, selectorCache) {
|
|
4198
|
+
if (elementOrSelector == null) {
|
|
4199
|
+
return [];
|
|
4200
|
+
}
|
|
4198
4201
|
if (elementOrSelector instanceof EventTarget) {
|
|
4199
4202
|
return [elementOrSelector];
|
|
4200
4203
|
}
|
|
@@ -4207,7 +4210,7 @@
|
|
|
4207
4210
|
root.querySelectorAll(elementOrSelector);
|
|
4208
4211
|
return elements ? Array.from(elements) : [];
|
|
4209
4212
|
}
|
|
4210
|
-
return Array.from(elementOrSelector);
|
|
4213
|
+
return Array.from(elementOrSelector).filter((element) => element != null);
|
|
4211
4214
|
}
|
|
4212
4215
|
|
|
4213
4216
|
function createSelectorEffect(subjectEffect) {
|
|
@@ -5399,7 +5402,7 @@
|
|
|
5399
5402
|
constructor(update, options = {}) {
|
|
5400
5403
|
this.currentSubject = "root";
|
|
5401
5404
|
this.targets = new Map();
|
|
5402
|
-
this.notifyReady = noop;
|
|
5405
|
+
this.notifyReady = noop$1;
|
|
5403
5406
|
this.readyPromise = new Promise((resolve) => {
|
|
5404
5407
|
this.notifyReady = resolve;
|
|
5405
5408
|
});
|
|
@@ -7454,7 +7457,7 @@
|
|
|
7454
7457
|
: values.borderRadius;
|
|
7455
7458
|
}
|
|
7456
7459
|
const easeCrossfadeIn = /*@__PURE__*/ compress(0, 0.5, circOut);
|
|
7457
|
-
const easeCrossfadeOut = /*@__PURE__*/ compress(0.5, 0.95, noop);
|
|
7460
|
+
const easeCrossfadeOut = /*@__PURE__*/ compress(0.5, 0.95, noop$1);
|
|
7458
7461
|
function compress(min, max, easing) {
|
|
7459
7462
|
return (p) => {
|
|
7460
7463
|
// Could replace ifs with clamp
|
|
@@ -7680,7 +7683,7 @@
|
|
|
7680
7683
|
cancelTreeOptimisedTransformAnimations(parent);
|
|
7681
7684
|
}
|
|
7682
7685
|
}
|
|
7683
|
-
function createProjectionNode
|
|
7686
|
+
function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
|
|
7684
7687
|
return class ProjectionNode {
|
|
7685
7688
|
constructor(latestValues = {}, parent = defaultParent?.()) {
|
|
7686
7689
|
/**
|
|
@@ -9218,7 +9221,7 @@
|
|
|
9218
9221
|
*/
|
|
9219
9222
|
const roundPoint = userAgentContains("applewebkit/") && !userAgentContains("chrome/")
|
|
9220
9223
|
? Math.round
|
|
9221
|
-
: noop;
|
|
9224
|
+
: noop$1;
|
|
9222
9225
|
function roundAxis(axis) {
|
|
9223
9226
|
// Round to the nearest .5 pixels to support subpixel layouts
|
|
9224
9227
|
axis.min = roundPoint(axis.min);
|
|
@@ -9237,7 +9240,7 @@
|
|
|
9237
9240
|
return node !== node.root && node.scroll?.wasRoot;
|
|
9238
9241
|
}
|
|
9239
9242
|
|
|
9240
|
-
const DocumentProjectionNode = createProjectionNode
|
|
9243
|
+
const DocumentProjectionNode = createProjectionNode({
|
|
9241
9244
|
attachResizeListener: (ref, notify) => addDomEvent(ref, "resize", notify),
|
|
9242
9245
|
measureScroll: () => ({
|
|
9243
9246
|
x: document.documentElement.scrollLeft || document.body.scrollLeft,
|
|
@@ -9272,7 +9275,7 @@
|
|
|
9272
9275
|
const rootProjectionNode = {
|
|
9273
9276
|
current: undefined,
|
|
9274
9277
|
};
|
|
9275
|
-
const HTMLProjectionNode = createProjectionNode
|
|
9278
|
+
const HTMLProjectionNode = createProjectionNode({
|
|
9276
9279
|
measureScroll: (instance) => ({
|
|
9277
9280
|
x: instance.scrollLeft,
|
|
9278
9281
|
y: instance.scrollTop,
|
|
@@ -9292,315 +9295,112 @@
|
|
|
9292
9295
|
checkIsScrollRoot: (instance) => Boolean(window.getComputedStyle(instance).position === "fixed"),
|
|
9293
9296
|
});
|
|
9294
9297
|
|
|
9295
|
-
const
|
|
9296
|
-
|
|
9297
|
-
const elements = Array.from(scope.querySelectorAll(LAYOUT_SELECTOR));
|
|
9298
|
-
// Include scope itself if it's an Element (not Document) and has layout attributes
|
|
9299
|
-
if (scope instanceof Element && hasLayout(scope)) {
|
|
9300
|
-
elements.unshift(scope);
|
|
9301
|
-
}
|
|
9302
|
-
return elements;
|
|
9303
|
-
}
|
|
9304
|
-
function getLayoutId(element) {
|
|
9305
|
-
return element.getAttribute("data-layout-id");
|
|
9306
|
-
}
|
|
9307
|
-
function hasLayout(element) {
|
|
9308
|
-
return (element.hasAttribute("data-layout") ||
|
|
9309
|
-
element.hasAttribute("data-layout-id"));
|
|
9310
|
-
}
|
|
9311
|
-
|
|
9312
|
-
let scaleCorrectorAdded = false;
|
|
9313
|
-
/**
|
|
9314
|
-
* Track active projection nodes per element to handle animation interruption.
|
|
9315
|
-
* When a new animation starts on an element that already has an active animation,
|
|
9316
|
-
* we need to stop the old animation so the new one can start from the current
|
|
9317
|
-
* visual position.
|
|
9318
|
-
*/
|
|
9319
|
-
const activeProjectionNodes = new WeakMap();
|
|
9320
|
-
function ensureScaleCorrectors() {
|
|
9321
|
-
if (scaleCorrectorAdded)
|
|
9322
|
-
return;
|
|
9323
|
-
scaleCorrectorAdded = true;
|
|
9324
|
-
addScaleCorrector({
|
|
9325
|
-
borderRadius: {
|
|
9326
|
-
...correctBorderRadius,
|
|
9327
|
-
applyTo: [
|
|
9328
|
-
"borderTopLeftRadius",
|
|
9329
|
-
"borderTopRightRadius",
|
|
9330
|
-
"borderBottomLeftRadius",
|
|
9331
|
-
"borderBottomRightRadius",
|
|
9332
|
-
],
|
|
9333
|
-
},
|
|
9334
|
-
borderTopLeftRadius: correctBorderRadius,
|
|
9335
|
-
borderTopRightRadius: correctBorderRadius,
|
|
9336
|
-
borderBottomLeftRadius: correctBorderRadius,
|
|
9337
|
-
borderBottomRightRadius: correctBorderRadius,
|
|
9338
|
-
boxShadow: correctBoxShadow,
|
|
9339
|
-
});
|
|
9340
|
-
}
|
|
9341
|
-
/**
|
|
9342
|
-
* Get DOM depth of an element
|
|
9343
|
-
*/
|
|
9344
|
-
function getDepth(element) {
|
|
9345
|
-
let depth = 0;
|
|
9346
|
-
let current = element.parentElement;
|
|
9347
|
-
while (current) {
|
|
9348
|
-
depth++;
|
|
9349
|
-
current = current.parentElement;
|
|
9350
|
-
}
|
|
9351
|
-
return depth;
|
|
9352
|
-
}
|
|
9353
|
-
/**
|
|
9354
|
-
* Find the closest projection parent for an element
|
|
9355
|
-
*/
|
|
9356
|
-
function findProjectionParent(element, nodeCache) {
|
|
9357
|
-
let parent = element.parentElement;
|
|
9358
|
-
while (parent) {
|
|
9359
|
-
const node = nodeCache.get(parent);
|
|
9360
|
-
if (node)
|
|
9361
|
-
return node;
|
|
9362
|
-
parent = parent.parentElement;
|
|
9363
|
-
}
|
|
9364
|
-
return undefined;
|
|
9365
|
-
}
|
|
9366
|
-
/**
|
|
9367
|
-
* Create or reuse a projection node for an element
|
|
9368
|
-
*/
|
|
9369
|
-
function createProjectionNode(element, parent, options, transition) {
|
|
9370
|
-
// Check for existing active node - reuse it to preserve animation state
|
|
9371
|
-
const existingNode = activeProjectionNodes.get(element);
|
|
9372
|
-
if (existingNode) {
|
|
9373
|
-
const visualElement = existingNode.options.visualElement;
|
|
9374
|
-
// Update transition options for the new animation
|
|
9375
|
-
const nodeTransition = transition
|
|
9376
|
-
? { duration: transition.duration, ease: transition.ease }
|
|
9377
|
-
: { duration: 0.3, ease: "easeOut" };
|
|
9378
|
-
existingNode.setOptions({
|
|
9379
|
-
...existingNode.options,
|
|
9380
|
-
animate: true,
|
|
9381
|
-
transition: nodeTransition,
|
|
9382
|
-
...options,
|
|
9383
|
-
});
|
|
9384
|
-
// Re-mount the node if it was previously unmounted
|
|
9385
|
-
// This re-adds it to root.nodes so didUpdate() will process it
|
|
9386
|
-
if (!existingNode.instance) {
|
|
9387
|
-
existingNode.mount(element);
|
|
9388
|
-
}
|
|
9389
|
-
return { node: existingNode, visualElement };
|
|
9390
|
-
}
|
|
9391
|
-
// No existing node - create a new one
|
|
9392
|
-
const latestValues = {};
|
|
9393
|
-
const visualElement = new HTMLVisualElement({
|
|
9394
|
-
visualState: {
|
|
9395
|
-
latestValues,
|
|
9396
|
-
renderState: {
|
|
9397
|
-
transformOrigin: {},
|
|
9398
|
-
transform: {},
|
|
9399
|
-
style: {},
|
|
9400
|
-
vars: {},
|
|
9401
|
-
},
|
|
9402
|
-
},
|
|
9403
|
-
presenceContext: null,
|
|
9404
|
-
props: {},
|
|
9405
|
-
});
|
|
9406
|
-
const node = new HTMLProjectionNode(latestValues, parent);
|
|
9407
|
-
// Convert AnimationOptions to transition format for the projection system
|
|
9408
|
-
const nodeTransition = transition
|
|
9409
|
-
? { duration: transition.duration, ease: transition.ease }
|
|
9410
|
-
: { duration: 0.3, ease: "easeOut" };
|
|
9411
|
-
node.setOptions({
|
|
9412
|
-
visualElement,
|
|
9413
|
-
layout: true,
|
|
9414
|
-
animate: true,
|
|
9415
|
-
transition: nodeTransition,
|
|
9416
|
-
...options,
|
|
9417
|
-
});
|
|
9418
|
-
node.mount(element);
|
|
9419
|
-
visualElement.projection = node;
|
|
9420
|
-
// Track this node as the active one for this element
|
|
9421
|
-
activeProjectionNodes.set(element, node);
|
|
9422
|
-
return { node, visualElement };
|
|
9423
|
-
}
|
|
9424
|
-
/**
|
|
9425
|
-
* Build a projection tree from a list of elements
|
|
9426
|
-
*/
|
|
9427
|
-
function buildProjectionTree(elements, existingContext, options) {
|
|
9428
|
-
ensureScaleCorrectors();
|
|
9429
|
-
const nodes = existingContext?.nodes ?? new Map();
|
|
9430
|
-
const visualElements = existingContext?.visualElements ?? new Map();
|
|
9431
|
-
const group = existingContext?.group ?? nodeGroup();
|
|
9432
|
-
const defaultTransition = options?.defaultTransition;
|
|
9433
|
-
const sharedTransitions = options?.sharedTransitions;
|
|
9434
|
-
// Sort elements by DOM depth (parents before children)
|
|
9435
|
-
const sorted = [...elements].sort((a, b) => getDepth(a) - getDepth(b));
|
|
9436
|
-
let root = existingContext?.root;
|
|
9437
|
-
for (const element of sorted) {
|
|
9438
|
-
// Skip if already has a node
|
|
9439
|
-
if (nodes.has(element))
|
|
9440
|
-
continue;
|
|
9441
|
-
const parent = findProjectionParent(element, nodes);
|
|
9442
|
-
const layoutId = getLayoutId(element);
|
|
9443
|
-
const layoutMode = element.getAttribute("data-layout");
|
|
9444
|
-
const nodeOptions = {
|
|
9445
|
-
layoutId: layoutId ?? undefined,
|
|
9446
|
-
animationType: parseLayoutMode(layoutMode),
|
|
9447
|
-
};
|
|
9448
|
-
// Use layoutId-specific transition if available, otherwise use default
|
|
9449
|
-
const transition = layoutId && sharedTransitions?.get(layoutId)
|
|
9450
|
-
? sharedTransitions.get(layoutId)
|
|
9451
|
-
: defaultTransition;
|
|
9452
|
-
const { node, visualElement } = createProjectionNode(element, parent, nodeOptions, transition);
|
|
9453
|
-
nodes.set(element, node);
|
|
9454
|
-
visualElements.set(element, visualElement);
|
|
9455
|
-
group.add(node);
|
|
9456
|
-
if (!root) {
|
|
9457
|
-
root = node.root;
|
|
9458
|
-
}
|
|
9459
|
-
}
|
|
9460
|
-
return {
|
|
9461
|
-
nodes,
|
|
9462
|
-
visualElements,
|
|
9463
|
-
group,
|
|
9464
|
-
root: root,
|
|
9465
|
-
};
|
|
9466
|
-
}
|
|
9467
|
-
/**
|
|
9468
|
-
* Parse the data-layout attribute value
|
|
9469
|
-
*/
|
|
9470
|
-
function parseLayoutMode(value) {
|
|
9471
|
-
if (value === "position")
|
|
9472
|
-
return "position";
|
|
9473
|
-
if (value === "size")
|
|
9474
|
-
return "size";
|
|
9475
|
-
if (value === "preserve-aspect")
|
|
9476
|
-
return "preserve-aspect";
|
|
9477
|
-
return "both";
|
|
9478
|
-
}
|
|
9479
|
-
/**
|
|
9480
|
-
* Clean up projection nodes for specific elements.
|
|
9481
|
-
* If elementsToCleanup is provided, only those elements are cleaned up.
|
|
9482
|
-
* If not provided, all nodes are cleaned up.
|
|
9483
|
-
*
|
|
9484
|
-
* This allows persisting elements to keep their nodes between animations,
|
|
9485
|
-
* matching React's behavior where nodes persist for elements that remain in the DOM.
|
|
9486
|
-
*/
|
|
9487
|
-
function cleanupProjectionTree(context, elementsToCleanup) {
|
|
9488
|
-
const elementsToProcess = elementsToCleanup
|
|
9489
|
-
? [...context.nodes.entries()].filter(([el]) => elementsToCleanup.has(el))
|
|
9490
|
-
: [...context.nodes.entries()];
|
|
9491
|
-
for (const [element, node] of elementsToProcess) {
|
|
9492
|
-
context.group.remove(node);
|
|
9493
|
-
node.unmount();
|
|
9494
|
-
// Only clear from activeProjectionNodes if this is still the active node.
|
|
9495
|
-
// A newer animation might have already taken over.
|
|
9496
|
-
if (activeProjectionNodes.get(element) === node) {
|
|
9497
|
-
activeProjectionNodes.delete(element);
|
|
9498
|
-
}
|
|
9499
|
-
context.nodes.delete(element);
|
|
9500
|
-
context.visualElements.delete(element);
|
|
9501
|
-
}
|
|
9502
|
-
}
|
|
9503
|
-
|
|
9298
|
+
const layoutSelector = "[data-layout], [data-layout-id]";
|
|
9299
|
+
const noop = () => { };
|
|
9504
9300
|
class LayoutAnimationBuilder {
|
|
9505
9301
|
constructor(scope, updateDom, defaultOptions) {
|
|
9506
9302
|
this.sharedTransitions = new Map();
|
|
9507
9303
|
this.notifyReady = noop;
|
|
9508
|
-
this.
|
|
9304
|
+
this.rejectReady = noop;
|
|
9509
9305
|
this.scope = scope;
|
|
9510
9306
|
this.updateDom = updateDom;
|
|
9511
9307
|
this.defaultOptions = defaultOptions;
|
|
9512
|
-
this.readyPromise = new Promise((resolve) => {
|
|
9308
|
+
this.readyPromise = new Promise((resolve, reject) => {
|
|
9513
9309
|
this.notifyReady = resolve;
|
|
9310
|
+
this.rejectReady = reject;
|
|
9311
|
+
});
|
|
9312
|
+
microtask.read((_frameData) => {
|
|
9313
|
+
this.start().then(this.notifyReady).catch(this.rejectReady);
|
|
9514
9314
|
});
|
|
9515
|
-
// Queue execution on microtask to allow builder methods to be called
|
|
9516
|
-
queueMicrotask(() => this.execute());
|
|
9517
9315
|
}
|
|
9518
|
-
shared(id,
|
|
9519
|
-
this.sharedTransitions.set(id,
|
|
9316
|
+
shared(id, transition) {
|
|
9317
|
+
this.sharedTransitions.set(id, transition);
|
|
9520
9318
|
return this;
|
|
9521
9319
|
}
|
|
9522
|
-
then(
|
|
9523
|
-
return this.readyPromise.then(
|
|
9320
|
+
then(resolve, reject) {
|
|
9321
|
+
return this.readyPromise.then(resolve, reject);
|
|
9524
9322
|
}
|
|
9525
|
-
async
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
|
|
9538
|
-
|
|
9539
|
-
}
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
const
|
|
9546
|
-
const
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
for (const element of exiting) {
|
|
9559
|
-
const node = context.nodes.get(element);
|
|
9560
|
-
node?.getStack()?.remove(node);
|
|
9323
|
+
async start() {
|
|
9324
|
+
const beforeElements = collectLayoutElements(this.scope);
|
|
9325
|
+
const beforeRecords = this.buildRecords(beforeElements);
|
|
9326
|
+
const exitCandidates = collectExitCandidates(beforeRecords);
|
|
9327
|
+
beforeRecords.forEach(({ projection }) => {
|
|
9328
|
+
projection.isPresent = true;
|
|
9329
|
+
projection.willUpdate();
|
|
9330
|
+
});
|
|
9331
|
+
await this.updateDom();
|
|
9332
|
+
const afterElements = collectLayoutElements(this.scope);
|
|
9333
|
+
const afterRecords = this.buildRecords(afterElements);
|
|
9334
|
+
const exitRecords = this.handleExitingElements(beforeRecords, afterRecords, exitCandidates);
|
|
9335
|
+
afterRecords.forEach(({ projection }) => {
|
|
9336
|
+
projection.isPresent = true;
|
|
9337
|
+
});
|
|
9338
|
+
const root = getProjectionRoot(afterRecords, beforeRecords);
|
|
9339
|
+
root?.didUpdate();
|
|
9340
|
+
await new Promise((resolve) => {
|
|
9341
|
+
frame.postRender(() => resolve());
|
|
9342
|
+
});
|
|
9343
|
+
const animations = collectAnimations(afterRecords, exitRecords);
|
|
9344
|
+
const animation = new GroupAnimation(animations);
|
|
9345
|
+
if (exitRecords.length) {
|
|
9346
|
+
const cleanup = () => {
|
|
9347
|
+
exitRecords.forEach(({ element, visualElement }) => {
|
|
9348
|
+
if (element.isConnected) {
|
|
9349
|
+
element.remove();
|
|
9350
|
+
}
|
|
9351
|
+
visualElement.unmount();
|
|
9352
|
+
visualElementStore.delete(element);
|
|
9353
|
+
});
|
|
9354
|
+
};
|
|
9355
|
+
animation.finished.then(cleanup, cleanup);
|
|
9561
9356
|
}
|
|
9562
|
-
|
|
9563
|
-
|
|
9357
|
+
return animation;
|
|
9358
|
+
}
|
|
9359
|
+
buildRecords(elements) {
|
|
9360
|
+
const records = [];
|
|
9361
|
+
const recordMap = new Map();
|
|
9362
|
+
for (const element of elements) {
|
|
9363
|
+
const parentRecord = findParentRecord(element, recordMap, this.scope);
|
|
9364
|
+
const { layout, layoutId } = readLayoutAttributes(element);
|
|
9365
|
+
const override = layoutId
|
|
9366
|
+
? this.sharedTransitions.get(layoutId)
|
|
9367
|
+
: undefined;
|
|
9368
|
+
const transition = override || this.defaultOptions;
|
|
9369
|
+
const record = getOrCreateRecord(element, parentRecord?.projection, {
|
|
9370
|
+
layout,
|
|
9371
|
+
layoutId,
|
|
9372
|
+
animationType: typeof layout === "string" ? layout : "both",
|
|
9373
|
+
transition: transition,
|
|
9374
|
+
});
|
|
9375
|
+
recordMap.set(element, record);
|
|
9376
|
+
records.push(record);
|
|
9564
9377
|
}
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
const
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9378
|
+
return records;
|
|
9379
|
+
}
|
|
9380
|
+
handleExitingElements(beforeRecords, afterRecords, exitCandidates) {
|
|
9381
|
+
const afterElementsSet = new Set(afterRecords.map((record) => record.element));
|
|
9382
|
+
const exiting = [];
|
|
9383
|
+
beforeRecords.forEach((record) => {
|
|
9384
|
+
if (afterElementsSet.has(record.element))
|
|
9385
|
+
return;
|
|
9386
|
+
const exitRecord = exitCandidates.get(record.element);
|
|
9387
|
+
if (!exitRecord) {
|
|
9388
|
+
record.visualElement.unmount();
|
|
9389
|
+
visualElementStore.delete(record.element);
|
|
9390
|
+
return;
|
|
9391
|
+
}
|
|
9392
|
+
if (!exitRecord.element.isConnected) {
|
|
9393
|
+
reinstateExitElement(exitRecord);
|
|
9394
|
+
}
|
|
9395
|
+
record.projection.isPresent = false;
|
|
9396
|
+
if (record.projection.options.layoutId) {
|
|
9397
|
+
record.projection.relegate();
|
|
9584
9398
|
}
|
|
9585
|
-
|
|
9399
|
+
exiting.push(record);
|
|
9586
9400
|
});
|
|
9587
|
-
|
|
9588
|
-
}
|
|
9589
|
-
getBuildOptions() {
|
|
9590
|
-
return {
|
|
9591
|
-
defaultTransition: this.defaultOptions || {
|
|
9592
|
-
duration: 0.3,
|
|
9593
|
-
ease: "easeOut",
|
|
9594
|
-
},
|
|
9595
|
-
sharedTransitions: this.sharedTransitions.size > 0
|
|
9596
|
-
? this.sharedTransitions
|
|
9597
|
-
: undefined,
|
|
9598
|
-
};
|
|
9401
|
+
return exiting;
|
|
9599
9402
|
}
|
|
9600
9403
|
}
|
|
9601
|
-
/**
|
|
9602
|
-
* Parse arguments for animateLayout overloads
|
|
9603
|
-
*/
|
|
9604
9404
|
function parseAnimateLayoutArgs(scopeOrUpdateDom, updateDomOrOptions, options) {
|
|
9605
9405
|
// animateLayout(updateDom)
|
|
9606
9406
|
if (typeof scopeOrUpdateDom === "function") {
|
|
@@ -9614,11 +9414,125 @@
|
|
|
9614
9414
|
const elements = resolveElements(scopeOrUpdateDom);
|
|
9615
9415
|
const scope = elements[0] || document;
|
|
9616
9416
|
return {
|
|
9617
|
-
scope
|
|
9417
|
+
scope,
|
|
9618
9418
|
updateDom: updateDomOrOptions,
|
|
9619
9419
|
defaultOptions: options,
|
|
9620
9420
|
};
|
|
9621
9421
|
}
|
|
9422
|
+
function collectLayoutElements(scope) {
|
|
9423
|
+
const elements = Array.from(scope.querySelectorAll(layoutSelector));
|
|
9424
|
+
if (scope instanceof Element && scope.matches(layoutSelector)) {
|
|
9425
|
+
if (!elements.includes(scope)) {
|
|
9426
|
+
elements.unshift(scope);
|
|
9427
|
+
}
|
|
9428
|
+
}
|
|
9429
|
+
return elements;
|
|
9430
|
+
}
|
|
9431
|
+
function readLayoutAttributes(element) {
|
|
9432
|
+
const layoutId = element.getAttribute("data-layout-id") || undefined;
|
|
9433
|
+
const rawLayout = element.getAttribute("data-layout");
|
|
9434
|
+
let layout;
|
|
9435
|
+
if (rawLayout === "" || rawLayout === "true") {
|
|
9436
|
+
layout = true;
|
|
9437
|
+
}
|
|
9438
|
+
else if (rawLayout) {
|
|
9439
|
+
layout = rawLayout;
|
|
9440
|
+
}
|
|
9441
|
+
return {
|
|
9442
|
+
layout,
|
|
9443
|
+
layoutId,
|
|
9444
|
+
layoutExit: element.hasAttribute("data-layout-exit"),
|
|
9445
|
+
};
|
|
9446
|
+
}
|
|
9447
|
+
function createVisualState() {
|
|
9448
|
+
return {
|
|
9449
|
+
latestValues: {},
|
|
9450
|
+
renderState: {
|
|
9451
|
+
transform: {},
|
|
9452
|
+
transformOrigin: {},
|
|
9453
|
+
style: {},
|
|
9454
|
+
vars: {},
|
|
9455
|
+
},
|
|
9456
|
+
};
|
|
9457
|
+
}
|
|
9458
|
+
function getOrCreateRecord(element, parentProjection, projectionOptions) {
|
|
9459
|
+
const existing = visualElementStore.get(element);
|
|
9460
|
+
const visualElement = existing ??
|
|
9461
|
+
new HTMLVisualElement({
|
|
9462
|
+
props: {},
|
|
9463
|
+
presenceContext: null,
|
|
9464
|
+
visualState: createVisualState(),
|
|
9465
|
+
}, { allowProjection: true });
|
|
9466
|
+
if (!existing || !visualElement.projection) {
|
|
9467
|
+
visualElement.projection = new HTMLProjectionNode(visualElement.latestValues, parentProjection);
|
|
9468
|
+
}
|
|
9469
|
+
visualElement.projection.setOptions({
|
|
9470
|
+
...projectionOptions,
|
|
9471
|
+
visualElement,
|
|
9472
|
+
});
|
|
9473
|
+
if (!visualElement.current) {
|
|
9474
|
+
visualElement.mount(element);
|
|
9475
|
+
}
|
|
9476
|
+
if (!existing) {
|
|
9477
|
+
visualElementStore.set(element, visualElement);
|
|
9478
|
+
}
|
|
9479
|
+
return {
|
|
9480
|
+
element,
|
|
9481
|
+
visualElement,
|
|
9482
|
+
projection: visualElement.projection,
|
|
9483
|
+
};
|
|
9484
|
+
}
|
|
9485
|
+
function findParentRecord(element, recordMap, scope) {
|
|
9486
|
+
let parent = element.parentElement;
|
|
9487
|
+
while (parent) {
|
|
9488
|
+
const record = recordMap.get(parent);
|
|
9489
|
+
if (record)
|
|
9490
|
+
return record;
|
|
9491
|
+
if (parent === scope)
|
|
9492
|
+
break;
|
|
9493
|
+
parent = parent.parentElement;
|
|
9494
|
+
}
|
|
9495
|
+
return undefined;
|
|
9496
|
+
}
|
|
9497
|
+
function collectExitCandidates(records) {
|
|
9498
|
+
const exitCandidates = new Map();
|
|
9499
|
+
records.forEach((record) => {
|
|
9500
|
+
const { layoutExit } = readLayoutAttributes(record.element);
|
|
9501
|
+
if (!layoutExit)
|
|
9502
|
+
return;
|
|
9503
|
+
exitCandidates.set(record.element, {
|
|
9504
|
+
...record,
|
|
9505
|
+
parent: record.element.parentNode,
|
|
9506
|
+
nextSibling: record.element.nextSibling,
|
|
9507
|
+
});
|
|
9508
|
+
});
|
|
9509
|
+
return exitCandidates;
|
|
9510
|
+
}
|
|
9511
|
+
function reinstateExitElement(record) {
|
|
9512
|
+
if (!record.parent)
|
|
9513
|
+
return;
|
|
9514
|
+
if (record.nextSibling && record.nextSibling.parentNode === record.parent) {
|
|
9515
|
+
record.parent.insertBefore(record.element, record.nextSibling);
|
|
9516
|
+
}
|
|
9517
|
+
else {
|
|
9518
|
+
record.parent.appendChild(record.element);
|
|
9519
|
+
}
|
|
9520
|
+
}
|
|
9521
|
+
function getProjectionRoot(afterRecords, beforeRecords) {
|
|
9522
|
+
const record = afterRecords[0] || beforeRecords[0];
|
|
9523
|
+
return record?.projection.root;
|
|
9524
|
+
}
|
|
9525
|
+
function collectAnimations(afterRecords, exitRecords) {
|
|
9526
|
+
const animations = new Set();
|
|
9527
|
+
const addAnimation = (record) => {
|
|
9528
|
+
const animation = record.projection.currentAnimation;
|
|
9529
|
+
if (animation)
|
|
9530
|
+
animations.add(animation);
|
|
9531
|
+
};
|
|
9532
|
+
afterRecords.forEach(addAnimation);
|
|
9533
|
+
exitRecords.forEach(addAnimation);
|
|
9534
|
+
return Array.from(animations);
|
|
9535
|
+
}
|
|
9622
9536
|
|
|
9623
9537
|
/**
|
|
9624
9538
|
* @deprecated
|
|
@@ -9641,6 +9555,9 @@
|
|
|
9641
9555
|
}
|
|
9642
9556
|
|
|
9643
9557
|
function resolveSubjects(subject, keyframes, scope, selectorCache) {
|
|
9558
|
+
if (subject == null) {
|
|
9559
|
+
return [];
|
|
9560
|
+
}
|
|
9644
9561
|
if (typeof subject === "string" && isDOMKeyframes(keyframes)) {
|
|
9645
9562
|
return resolveElements(subject, scope, selectorCache);
|
|
9646
9563
|
}
|
|
@@ -9648,7 +9565,7 @@
|
|
|
9648
9565
|
return Array.from(subject);
|
|
9649
9566
|
}
|
|
9650
9567
|
else if (Array.isArray(subject)) {
|
|
9651
|
-
return subject;
|
|
9568
|
+
return subject.filter((s) => s != null);
|
|
9652
9569
|
}
|
|
9653
9570
|
else {
|
|
9654
9571
|
return [subject];
|
|
@@ -10024,12 +9941,15 @@
|
|
|
10024
9941
|
: keyframes, options ? options.default || options : options));
|
|
10025
9942
|
}
|
|
10026
9943
|
else {
|
|
9944
|
+
// Gracefully handle null/undefined subjects (e.g., from querySelector returning null)
|
|
9945
|
+
if (subject == null) {
|
|
9946
|
+
return animations;
|
|
9947
|
+
}
|
|
10027
9948
|
const subjects = resolveSubjects(subject, keyframes, scope);
|
|
10028
9949
|
const numSubjects = subjects.length;
|
|
10029
9950
|
exports.invariant(Boolean(numSubjects), "No valid elements provided.", "no-valid-elements");
|
|
10030
9951
|
for (let i = 0; i < numSubjects; i++) {
|
|
10031
9952
|
const thisSubject = subjects[i];
|
|
10032
|
-
exports.invariant(thisSubject !== null, "You're trying to perform an animation on null. Ensure that selectors are correctly finding elements and refs are correctly hydrated.", "animate-null");
|
|
10033
9953
|
const createVisualElement = thisSubject instanceof Element
|
|
10034
9954
|
? createDOMVisualElement
|
|
10035
9955
|
: createObjectVisualElement;
|
|
@@ -10102,6 +10022,10 @@
|
|
|
10102
10022
|
const animate = createScopedAnimate();
|
|
10103
10023
|
|
|
10104
10024
|
function animateElements(elementOrSelector, keyframes, options, scope) {
|
|
10025
|
+
// Gracefully handle null/undefined elements (e.g., from querySelector returning null)
|
|
10026
|
+
if (elementOrSelector == null) {
|
|
10027
|
+
return [];
|
|
10028
|
+
}
|
|
10105
10029
|
const elements = resolveElements(elementOrSelector, scope);
|
|
10106
10030
|
const numElements = elements.length;
|
|
10107
10031
|
exports.invariant(Boolean(numElements), "No valid elements provided.", "no-valid-elements");
|
|
@@ -10502,7 +10426,7 @@
|
|
|
10502
10426
|
const getEventTarget = (element) => element === document.scrollingElement ? window : element;
|
|
10503
10427
|
function scrollInfo(onScroll, { container = document.scrollingElement, ...options } = {}) {
|
|
10504
10428
|
if (!container)
|
|
10505
|
-
return noop;
|
|
10429
|
+
return noop$1;
|
|
10506
10430
|
let containerHandlers = onScrollHandlers.get(container);
|
|
10507
10431
|
/**
|
|
10508
10432
|
* Get the onScroll handlers for this container.
|
|
@@ -10630,7 +10554,7 @@
|
|
|
10630
10554
|
|
|
10631
10555
|
function scroll(onScroll, { axis = "y", container = document.scrollingElement, ...options } = {}) {
|
|
10632
10556
|
if (!container)
|
|
10633
|
-
return noop;
|
|
10557
|
+
return noop$1;
|
|
10634
10558
|
const optionsWithDefaults = { axis, container, ...options };
|
|
10635
10559
|
return typeof onScroll === "function"
|
|
10636
10560
|
? attachToFunction(onScroll, optionsWithDefaults)
|
|
@@ -10791,7 +10715,7 @@
|
|
|
10791
10715
|
exports.createBox = createBox;
|
|
10792
10716
|
exports.createDelta = createDelta;
|
|
10793
10717
|
exports.createGeneratorEasing = createGeneratorEasing;
|
|
10794
|
-
exports.createProjectionNode = createProjectionNode
|
|
10718
|
+
exports.createProjectionNode = createProjectionNode;
|
|
10795
10719
|
exports.createRenderBatcher = createRenderBatcher;
|
|
10796
10720
|
exports.createScopedAnimate = createScopedAnimate;
|
|
10797
10721
|
exports.cubicBezier = cubicBezier;
|
|
@@ -10905,7 +10829,7 @@
|
|
|
10905
10829
|
exports.motionValue = motionValue;
|
|
10906
10830
|
exports.moveItem = moveItem;
|
|
10907
10831
|
exports.nodeGroup = nodeGroup;
|
|
10908
|
-
exports.noop = noop;
|
|
10832
|
+
exports.noop = noop$1;
|
|
10909
10833
|
exports.number = number;
|
|
10910
10834
|
exports.numberValueTypes = numberValueTypes;
|
|
10911
10835
|
exports.observeTimeline = observeTimeline;
|