UNPKG

351 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
3 typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
4 (global = global || self, factory(global.Motion = {}, global.React));
5}(this, (function (exports, React) { 'use strict';
6
7 var React__default = 'default' in React ? React['default'] : React;
8
9 /*! *****************************************************************************
10 Copyright (c) Microsoft Corporation.
11
12 Permission to use, copy, modify, and/or distribute this software for any
13 purpose with or without fee is hereby granted.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
16 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
17 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
18 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 PERFORMANCE OF THIS SOFTWARE.
22 ***************************************************************************** */
23 /* global Reflect, Promise */
24
25 var extendStatics = function(d, b) {
26 extendStatics = Object.setPrototypeOf ||
27 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
28 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
29 return extendStatics(d, b);
30 };
31
32 function __extends(d, b) {
33 extendStatics(d, b);
34 function __() { this.constructor = d; }
35 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
36 }
37
38 var __assign = function() {
39 __assign = Object.assign || function __assign(t) {
40 for (var s, i = 1, n = arguments.length; i < n; i++) {
41 s = arguments[i];
42 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
43 }
44 return t;
45 };
46 return __assign.apply(this, arguments);
47 };
48
49 function __rest(s, e) {
50 var t = {};
51 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
52 t[p] = s[p];
53 if (s != null && typeof Object.getOwnPropertySymbols === "function")
54 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
55 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
56 t[p[i]] = s[p[i]];
57 }
58 return t;
59 }
60
61 function __spreadArrays() {
62 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
63 for (var r = Array(s), k = 0, i = 0; i < il; i++)
64 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
65 r[k] = a[j];
66 return r;
67 }
68
69 var isRefObject = function (ref) {
70 return typeof ref === "object" && ref.hasOwnProperty("current");
71 };
72
73 var warning = function () { };
74 var invariant = function () { };
75 {
76 warning = function (check, message) {
77 if (!check && typeof console !== 'undefined') {
78 console.warn(message);
79 }
80 };
81 invariant = function (check, message) {
82 if (!check) {
83 throw new Error(message);
84 }
85 };
86 }
87
88 var prevTime = 0;
89 var onNextFrame = typeof window !== 'undefined' && window.requestAnimationFrame !== undefined
90 ? function (callback) { return window.requestAnimationFrame(callback); }
91 : function (callback) {
92 var timestamp = Date.now();
93 var timeToCall = Math.max(0, 16.7 - (timestamp - prevTime));
94 prevTime = timestamp + timeToCall;
95 setTimeout(function () { return callback(prevTime); }, timeToCall);
96 };
97
98 var createStep = (function (setRunNextFrame) {
99 var processToRun = [];
100 var processToRunNextFrame = [];
101 var numThisFrame = 0;
102 var isProcessing = false;
103 var i = 0;
104 var cancelled = new WeakSet();
105 var toKeepAlive = new WeakSet();
106 var renderStep = {
107 cancel: function (process) {
108 var indexOfCallback = processToRunNextFrame.indexOf(process);
109 cancelled.add(process);
110 if (indexOfCallback !== -1) {
111 processToRunNextFrame.splice(indexOfCallback, 1);
112 }
113 },
114 process: function (frame) {
115 var _a;
116 isProcessing = true;
117 _a = [
118 processToRunNextFrame,
119 processToRun
120 ], processToRun = _a[0], processToRunNextFrame = _a[1];
121 processToRunNextFrame.length = 0;
122 numThisFrame = processToRun.length;
123 if (numThisFrame) {
124 var process_1;
125 for (i = 0; i < numThisFrame; i++) {
126 process_1 = processToRun[i];
127 process_1(frame);
128 if (toKeepAlive.has(process_1) === true && !cancelled.has(process_1)) {
129 renderStep.schedule(process_1);
130 setRunNextFrame(true);
131 }
132 }
133 }
134 isProcessing = false;
135 },
136 schedule: function (process, keepAlive, immediate) {
137 if (keepAlive === void 0) { keepAlive = false; }
138 if (immediate === void 0) { immediate = false; }
139 invariant(typeof process === 'function', 'Argument must be a function');
140 var addToCurrentBuffer = immediate && isProcessing;
141 var buffer = addToCurrentBuffer ? processToRun : processToRunNextFrame;
142 cancelled.delete(process);
143 if (keepAlive)
144 toKeepAlive.add(process);
145 if (buffer.indexOf(process) === -1) {
146 buffer.push(process);
147 if (addToCurrentBuffer)
148 numThisFrame = processToRun.length;
149 }
150 }
151 };
152 return renderStep;
153 });
154
155 var StepId;
156 (function (StepId) {
157 StepId["Read"] = "read";
158 StepId["Update"] = "update";
159 StepId["Render"] = "render";
160 StepId["PostRender"] = "postRender";
161 StepId["FixedUpdate"] = "fixedUpdate";
162 })(StepId || (StepId = {}));
163
164 var maxElapsed = 40;
165 var defaultElapsed = (1 / 60) * 1000;
166 var useDefaultElapsed = true;
167 var willRunNextFrame = false;
168 var isProcessing = false;
169 var frame = {
170 delta: 0,
171 timestamp: 0
172 };
173 var stepsOrder = [
174 StepId.Read,
175 StepId.Update,
176 StepId.Render,
177 StepId.PostRender
178 ];
179 var setWillRunNextFrame = function (willRun) { return (willRunNextFrame = willRun); };
180 var _a = stepsOrder.reduce(function (acc, key) {
181 var step = createStep(setWillRunNextFrame);
182 acc.sync[key] = function (process, keepAlive, immediate) {
183 if (keepAlive === void 0) { keepAlive = false; }
184 if (immediate === void 0) { immediate = false; }
185 if (!willRunNextFrame)
186 startLoop();
187 step.schedule(process, keepAlive, immediate);
188 return process;
189 };
190 acc.cancelSync[key] = function (process) { return step.cancel(process); };
191 acc.steps[key] = step;
192 return acc;
193 }, {
194 steps: {},
195 sync: {},
196 cancelSync: {}
197 }), steps = _a.steps, sync = _a.sync, cancelSync = _a.cancelSync;
198 var processStep = function (stepId) { return steps[stepId].process(frame); };
199 var processFrame = function (timestamp) {
200 willRunNextFrame = false;
201 frame.delta = useDefaultElapsed
202 ? defaultElapsed
203 : Math.max(Math.min(timestamp - frame.timestamp, maxElapsed), 1);
204 if (!useDefaultElapsed)
205 defaultElapsed = frame.delta;
206 frame.timestamp = timestamp;
207 isProcessing = true;
208 stepsOrder.forEach(processStep);
209 isProcessing = false;
210 if (willRunNextFrame) {
211 useDefaultElapsed = false;
212 onNextFrame(processFrame);
213 }
214 };
215 var startLoop = function () {
216 willRunNextFrame = true;
217 useDefaultElapsed = true;
218 if (!isProcessing)
219 onNextFrame(processFrame);
220 };
221 var getFrameData = function () { return frame; };
222
223 var clamp = function (min, max) { return function (v) {
224 return Math.max(Math.min(v, max), min);
225 }; };
226 var sanitize = function (v) { return (v % 1 ? Number(v.toFixed(5)) : v); };
227 var floatRegex = /(-)?(\d[\d\.]*)/g;
228 var colorRegex = /(#[0-9a-f]{6}|#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2,3}\s*\/*\s*[\d\.]+%?\))/gi;
229 var singleColorRegex = /^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2,3}\s*\/*\s*[\d\.]+%?\))$/i;
230
231 var number = {
232 test: function (v) { return typeof v === 'number'; },
233 parse: parseFloat,
234 transform: function (v) { return v; }
235 };
236 var alpha = __assign(__assign({}, number), { transform: clamp(0, 1) });
237 var scale = __assign(__assign({}, number), { default: 1 });
238
239 var createUnitType = function (unit) { return ({
240 test: function (v) {
241 return typeof v === 'string' && v.endsWith(unit) && v.split(' ').length === 1;
242 },
243 parse: parseFloat,
244 transform: function (v) { return "" + v + unit; }
245 }); };
246 var degrees = createUnitType('deg');
247 var percent = createUnitType('%');
248 var px = createUnitType('px');
249 var vh = createUnitType('vh');
250 var vw = createUnitType('vw');
251 var progressPercentage = __assign(__assign({}, percent), { parse: function (v) { return percent.parse(v) / 100; }, transform: function (v) { return percent.transform(v * 100); } });
252
253 var getValueFromFunctionString = function (value) {
254 return value.substring(value.indexOf('(') + 1, value.lastIndexOf(')'));
255 };
256 var clampRgbUnit = clamp(0, 255);
257 var isRgba = function (v) { return v.red !== undefined; };
258 var isHsla = function (v) { return v.hue !== undefined; };
259 function getValuesAsArray(value) {
260 return getValueFromFunctionString(value)
261 .replace(/(,|\/)/g, ' ')
262 .split(/ \s*/);
263 }
264 var splitColorValues = function (terms) {
265 return function (v) {
266 if (typeof v !== 'string')
267 return v;
268 var values = {};
269 var valuesArray = getValuesAsArray(v);
270 for (var i = 0; i < 4; i++) {
271 values[terms[i]] =
272 valuesArray[i] !== undefined ? parseFloat(valuesArray[i]) : 1;
273 }
274 return values;
275 };
276 };
277 var rgbaTemplate = function (_a) {
278 var red = _a.red, green = _a.green, blue = _a.blue, _b = _a.alpha, alpha = _b === void 0 ? 1 : _b;
279 return "rgba(" + red + ", " + green + ", " + blue + ", " + alpha + ")";
280 };
281 var hslaTemplate = function (_a) {
282 var hue = _a.hue, saturation = _a.saturation, lightness = _a.lightness, _b = _a.alpha, alpha = _b === void 0 ? 1 : _b;
283 return "hsla(" + hue + ", " + saturation + ", " + lightness + ", " + alpha + ")";
284 };
285 var rgbUnit = __assign(__assign({}, number), { transform: function (v) { return Math.round(clampRgbUnit(v)); } });
286 function isColorString(color, colorType) {
287 return color.startsWith(colorType) && singleColorRegex.test(color);
288 }
289 var rgba = {
290 test: function (v) { return (typeof v === 'string' ? isColorString(v, 'rgb') : isRgba(v)); },
291 parse: splitColorValues(['red', 'green', 'blue', 'alpha']),
292 transform: function (_a) {
293 var red = _a.red, green = _a.green, blue = _a.blue, _b = _a.alpha, alpha$1 = _b === void 0 ? 1 : _b;
294 return rgbaTemplate({
295 red: rgbUnit.transform(red),
296 green: rgbUnit.transform(green),
297 blue: rgbUnit.transform(blue),
298 alpha: sanitize(alpha.transform(alpha$1))
299 });
300 }
301 };
302 var hsla = {
303 test: function (v) { return (typeof v === 'string' ? isColorString(v, 'hsl') : isHsla(v)); },
304 parse: splitColorValues(['hue', 'saturation', 'lightness', 'alpha']),
305 transform: function (_a) {
306 var hue = _a.hue, saturation = _a.saturation, lightness = _a.lightness, _b = _a.alpha, alpha$1 = _b === void 0 ? 1 : _b;
307 return hslaTemplate({
308 hue: Math.round(hue),
309 saturation: percent.transform(sanitize(saturation)),
310 lightness: percent.transform(sanitize(lightness)),
311 alpha: sanitize(alpha.transform(alpha$1))
312 });
313 }
314 };
315 var hex = __assign(__assign({}, rgba), { test: function (v) { return typeof v === 'string' && isColorString(v, '#'); }, parse: function (v) {
316 var r = '';
317 var g = '';
318 var b = '';
319 if (v.length > 4) {
320 r = v.substr(1, 2);
321 g = v.substr(3, 2);
322 b = v.substr(5, 2);
323 }
324 else {
325 r = v.substr(1, 1);
326 g = v.substr(2, 1);
327 b = v.substr(3, 1);
328 r += r;
329 g += g;
330 b += b;
331 }
332 return {
333 red: parseInt(r, 16),
334 green: parseInt(g, 16),
335 blue: parseInt(b, 16),
336 alpha: 1
337 };
338 } });
339 var color = {
340 test: function (v) {
341 return (typeof v === 'string' && singleColorRegex.test(v)) ||
342 isRgba(v) ||
343 isHsla(v);
344 },
345 parse: function (v) {
346 if (rgba.test(v)) {
347 return rgba.parse(v);
348 }
349 else if (hsla.test(v)) {
350 return hsla.parse(v);
351 }
352 else if (hex.test(v)) {
353 return hex.parse(v);
354 }
355 return v;
356 },
357 transform: function (v) {
358 if (isRgba(v)) {
359 return rgba.transform(v);
360 }
361 else if (isHsla(v)) {
362 return hsla.transform(v);
363 }
364 return v;
365 }
366 };
367
368 var COLOR_TOKEN = '${c}';
369 var NUMBER_TOKEN = '${n}';
370 var convertNumbersToZero = function (v) {
371 return typeof v === 'number' ? 0 : v;
372 };
373 var complex = {
374 test: function (v) {
375 if (typeof v !== 'string' || !isNaN(v))
376 return false;
377 var numValues = 0;
378 var foundNumbers = v.match(floatRegex);
379 var foundColors = v.match(colorRegex);
380 if (foundNumbers)
381 numValues += foundNumbers.length;
382 if (foundColors)
383 numValues += foundColors.length;
384 return numValues > 0;
385 },
386 parse: function (v) {
387 var input = v;
388 var parsed = [];
389 var foundColors = input.match(colorRegex);
390 if (foundColors) {
391 input = input.replace(colorRegex, COLOR_TOKEN);
392 parsed.push.apply(parsed, foundColors.map(color.parse));
393 }
394 var foundNumbers = input.match(floatRegex);
395 if (foundNumbers) {
396 parsed.push.apply(parsed, foundNumbers.map(number.parse));
397 }
398 return parsed;
399 },
400 createTransformer: function (prop) {
401 var template = prop;
402 var token = 0;
403 var foundColors = prop.match(colorRegex);
404 var numColors = foundColors ? foundColors.length : 0;
405 if (foundColors) {
406 for (var i = 0; i < numColors; i++) {
407 template = template.replace(foundColors[i], COLOR_TOKEN);
408 token++;
409 }
410 }
411 var foundNumbers = template.match(floatRegex);
412 var numNumbers = foundNumbers ? foundNumbers.length : 0;
413 if (foundNumbers) {
414 for (var i = 0; i < numNumbers; i++) {
415 template = template.replace(foundNumbers[i], NUMBER_TOKEN);
416 token++;
417 }
418 }
419 return function (v) {
420 var output = template;
421 for (var i = 0; i < token; i++) {
422 output = output.replace(i < numColors ? COLOR_TOKEN : NUMBER_TOKEN, i < numColors ? color.transform(v[i]) : sanitize(v[i]));
423 }
424 return output;
425 };
426 },
427 getAnimatableNone: function (target) {
428 var parsedTarget = complex.parse(target);
429 var targetTransformer = complex.createTransformer(target);
430 return targetTransformer(parsedTarget.map(convertNumbersToZero));
431 }
432 };
433
434 var DEFAULT_OVERSHOOT_STRENGTH = 1.525;
435 var reversed = function (easing) {
436 return function (p) {
437 return 1 - easing(1 - p);
438 };
439 };
440 var mirrored = function (easing) {
441 return function (p) {
442 return p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
443 };
444 };
445 var createReversedEasing = reversed;
446 var createMirroredEasing = mirrored;
447 var createExpoIn = function (power) {
448 return function (p) {
449 return Math.pow(p, power);
450 };
451 };
452 var createBackIn = function (power) {
453 return function (p) {
454 return p * p * ((power + 1) * p - power);
455 };
456 };
457 var createAnticipateEasing = function (power) {
458 var backEasing = createBackIn(power);
459 return function (p) {
460 return (p *= 2) < 1 ? 0.5 * backEasing(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
461 };
462 };
463 var linear = function (p) {
464 return p;
465 };
466 var easeIn = /*#__PURE__*/createExpoIn(2);
467 var easeOut = /*#__PURE__*/reversed(easeIn);
468 var easeInOut = /*#__PURE__*/mirrored(easeIn);
469 var circIn = function (p) {
470 return 1 - Math.sin(Math.acos(p));
471 };
472 var circOut = /*#__PURE__*/reversed(circIn);
473 var circInOut = /*#__PURE__*/mirrored(circOut);
474 var backIn = /*#__PURE__*/createBackIn(DEFAULT_OVERSHOOT_STRENGTH);
475 var backOut = /*#__PURE__*/reversed(backIn);
476 var backInOut = /*#__PURE__*/mirrored(backIn);
477 var anticipate = /*#__PURE__*/createAnticipateEasing(DEFAULT_OVERSHOOT_STRENGTH);
478 var BOUNCE_FIRST_THRESHOLD = 4.0 / 11.0;
479 var BOUNCE_SECOND_THRESHOLD = 8.0 / 11.0;
480 var BOUNCE_THIRD_THRESHOLD = 9.0 / 10.0;
481 var ca = 4356.0 / 361.0;
482 var cb = 35442.0 / 1805.0;
483 var cc = 16061.0 / 1805.0;
484 var bounceOut = function (p) {
485 var p2 = p * p;
486 return p < BOUNCE_FIRST_THRESHOLD ? 7.5625 * p2 : p < BOUNCE_SECOND_THRESHOLD ? 9.075 * p2 - 9.9 * p + 3.4 : p < BOUNCE_THIRD_THRESHOLD ? ca * p2 - cb * p + cc : 10.8 * p * p - 20.52 * p + 10.72;
487 };
488 var bounceIn = function (p) {
489 return 1.0 - bounceOut(1.0 - p);
490 };
491 var bounceInOut = function (p) {
492 return p < 0.5 ? 0.5 * (1.0 - bounceOut(1.0 - p * 2.0)) : 0.5 * bounceOut(p * 2.0 - 1.0) + 0.5;
493 };
494 var NEWTON_ITERATIONS = 8;
495 var NEWTON_MIN_SLOPE = 0.001;
496 var SUBDIVISION_PRECISION = 0.0000001;
497 var SUBDIVISION_MAX_ITERATIONS = 10;
498 var K_SPLINE_TABLE_SIZE = 11;
499 var K_SAMPLE_STEP_SIZE = 1.0 / (K_SPLINE_TABLE_SIZE - 1.0);
500 var FLOAT_32_SUPPORTED = typeof Float32Array !== 'undefined';
501 var a = function (a1, a2) {
502 return 1.0 - 3.0 * a2 + 3.0 * a1;
503 };
504 var b = function (a1, a2) {
505 return 3.0 * a2 - 6.0 * a1;
506 };
507 var c = function (a1) {
508 return 3.0 * a1;
509 };
510 var getSlope = function (t, a1, a2) {
511 return 3.0 * a(a1, a2) * t * t + 2.0 * b(a1, a2) * t + c(a1);
512 };
513 var calcBezier = function (t, a1, a2) {
514 return ((a(a1, a2) * t + b(a1, a2)) * t + c(a1)) * t;
515 };
516 function cubicBezier(mX1, mY1, mX2, mY2) {
517 var sampleValues = FLOAT_32_SUPPORTED ? new Float32Array(K_SPLINE_TABLE_SIZE) : new Array(K_SPLINE_TABLE_SIZE);
518 var binarySubdivide = function (aX, aA, aB) {
519 var i = 0;
520 var currentX;
521 var currentT;
522 do {
523 currentT = aA + (aB - aA) / 2.0;
524 currentX = calcBezier(currentT, mX1, mX2) - aX;
525 if (currentX > 0.0) {
526 aB = currentT;
527 } else {
528 aA = currentT;
529 }
530 } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
531 return currentT;
532 };
533 var newtonRaphsonIterate = function (aX, aGuessT) {
534 var i = 0;
535 var currentSlope = 0;
536 var currentX;
537 for (; i < NEWTON_ITERATIONS; ++i) {
538 currentSlope = getSlope(aGuessT, mX1, mX2);
539 if (currentSlope === 0.0) {
540 return aGuessT;
541 }
542 currentX = calcBezier(aGuessT, mX1, mX2) - aX;
543 aGuessT -= currentX / currentSlope;
544 }
545 return aGuessT;
546 };
547 var calcSampleValues = function () {
548 for (var i = 0; i < K_SPLINE_TABLE_SIZE; ++i) {
549 sampleValues[i] = calcBezier(i * K_SAMPLE_STEP_SIZE, mX1, mX2);
550 }
551 };
552 var getTForX = function (aX) {
553 var intervalStart = 0.0;
554 var currentSample = 1;
555 var lastSample = K_SPLINE_TABLE_SIZE - 1;
556 var dist = 0.0;
557 var guessForT = 0.0;
558 var initialSlope = 0.0;
559 for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
560 intervalStart += K_SAMPLE_STEP_SIZE;
561 }
562 --currentSample;
563 dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
564 guessForT = intervalStart + dist * K_SAMPLE_STEP_SIZE;
565 initialSlope = getSlope(guessForT, mX1, mX2);
566 if (initialSlope >= NEWTON_MIN_SLOPE) {
567 return newtonRaphsonIterate(aX, guessForT);
568 } else if (initialSlope === 0.0) {
569 return guessForT;
570 } else {
571 return binarySubdivide(aX, intervalStart, intervalStart + K_SAMPLE_STEP_SIZE);
572 }
573 };
574 calcSampleValues();
575 var resolver = function (aX) {
576 var returnValue;
577 if (mX1 === mY1 && mX2 === mY2) {
578 returnValue = aX;
579 } else if (aX === 0) {
580 returnValue = 0;
581 } else if (aX === 1) {
582 returnValue = 1;
583 } else {
584 returnValue = calcBezier(getTForX(aX), mY1, mY2);
585 }
586 return returnValue;
587 };
588 return resolver;
589 }
590
591 var easingLookup = /*#__PURE__*/Object.freeze({
592 __proto__: null,
593 reversed: reversed,
594 mirrored: mirrored,
595 createReversedEasing: createReversedEasing,
596 createMirroredEasing: createMirroredEasing,
597 createExpoIn: createExpoIn,
598 createBackIn: createBackIn,
599 createAnticipateEasing: createAnticipateEasing,
600 linear: linear,
601 easeIn: easeIn,
602 easeOut: easeOut,
603 easeInOut: easeInOut,
604 circIn: circIn,
605 circOut: circOut,
606 circInOut: circInOut,
607 backIn: backIn,
608 backOut: backOut,
609 backInOut: backInOut,
610 anticipate: anticipate,
611 bounceOut: bounceOut,
612 bounceIn: bounceIn,
613 bounceInOut: bounceInOut,
614 cubicBezier: cubicBezier
615 });
616
617 var zeroPoint = {
618 x: 0,
619 y: 0,
620 z: 0
621 };
622 var isNum = function (v) { return typeof v === 'number'; };
623
624 var curryRange = (function (func) { return function (min, max, v) { return (v !== undefined ? func(min, max, v) : function (cv) { return func(min, max, cv); }); }; });
625
626 var clamp$1 = function (min, max, v) {
627 return Math.min(Math.max(v, min), max);
628 };
629 var clamp$1$1 = curryRange(clamp$1);
630
631 var isPoint = (function (point) {
632 return point.hasOwnProperty('x') && point.hasOwnProperty('y');
633 });
634
635 var isPoint3D = (function (point) {
636 return isPoint(point) && point.hasOwnProperty('z');
637 });
638
639 var distance1D = function (a, b) { return Math.abs(a - b); };
640 var distance = (function (a, b) {
641 if (b === void 0) { b = zeroPoint; }
642 if (isNum(a) && isNum(b)) {
643 return distance1D(a, b);
644 }
645 else if (isPoint(a) && isPoint(b)) {
646 var xDelta = distance1D(a.x, b.x);
647 var yDelta = distance1D(a.y, b.y);
648 var zDelta = isPoint3D(a) && isPoint3D(b) ? distance1D(a.z, b.z) : 0;
649 return Math.sqrt(Math.pow(xDelta, 2) + Math.pow(yDelta, 2) + Math.pow(zDelta, 2));
650 }
651 return 0;
652 });
653
654 var progress = (function (from, to, value) {
655 var toFromDifference = to - from;
656 return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
657 });
658
659 var mix = (function (from, to, progress) {
660 return -progress * from + progress * to + from;
661 });
662
663 /*! *****************************************************************************
664 Copyright (c) Microsoft Corporation. All rights reserved.
665 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
666 this file except in compliance with the License. You may obtain a copy of the
667 License at http://www.apache.org/licenses/LICENSE-2.0
668
669 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
670 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
671 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
672 MERCHANTABLITY OR NON-INFRINGEMENT.
673
674 See the Apache Version 2.0 License for specific language governing permissions
675 and limitations under the License.
676 ***************************************************************************** */
677
678 var __assign$1 = function() {
679 __assign$1 = Object.assign || function __assign(t) {
680 for (var s, i = 1, n = arguments.length; i < n; i++) {
681 s = arguments[i];
682 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
683 }
684 return t;
685 };
686 return __assign$1.apply(this, arguments);
687 };
688
689 var mixLinearColor = function (from, to, v) {
690 var fromExpo = from * from;
691 var toExpo = to * to;
692 return Math.sqrt(Math.max(0, v * (toExpo - fromExpo) + fromExpo));
693 };
694 var colorTypes = [hex, rgba, hsla];
695 var getColorType = function (v) {
696 return colorTypes.find(function (type) { return type.test(v); });
697 };
698 var notAnimatable = function (color$$1) {
699 return "'" + color$$1 + "' is not an animatable color. Use the equivalent color code instead.";
700 };
701 var mixColor = (function (from, to) {
702 var fromColorType = getColorType(from);
703 var toColorType = getColorType(to);
704 invariant(!!fromColorType, notAnimatable(from));
705 invariant(!!toColorType, notAnimatable(to));
706 invariant(fromColorType.transform === toColorType.transform, 'Both colors must be hex/RGBA, OR both must be HSLA.');
707 var fromColor = fromColorType.parse(from);
708 var toColor = toColorType.parse(to);
709 var blended = __assign$1({}, fromColor);
710 var mixFunc = fromColorType === hsla ? mix : mixLinearColor;
711 return function (v) {
712 for (var key in blended) {
713 if (key !== 'alpha') {
714 blended[key] = mixFunc(fromColor[key], toColor[key], v);
715 }
716 }
717 blended.alpha = mix(fromColor.alpha, toColor.alpha, v);
718 return fromColorType.transform(blended);
719 };
720 });
721
722 var combineFunctions = function (a, b) { return function (v) { return b(a(v)); }; };
723 var pipe = (function () {
724 var transformers = [];
725 for (var _i = 0; _i < arguments.length; _i++) {
726 transformers[_i] = arguments[_i];
727 }
728 return transformers.reduce(combineFunctions);
729 });
730
731 function getMixer(origin, target) {
732 if (isNum(origin)) {
733 return function (v) { return mix(origin, target, v); };
734 }
735 else if (color.test(origin)) {
736 return mixColor(origin, target);
737 }
738 else {
739 return mixComplex(origin, target);
740 }
741 }
742 var mixArray = function (from, to) {
743 var output = from.slice();
744 var numValues = output.length;
745 var blendValue = from.map(function (fromThis, i) { return getMixer(fromThis, to[i]); });
746 return function (v) {
747 for (var i = 0; i < numValues; i++) {
748 output[i] = blendValue[i](v);
749 }
750 return output;
751 };
752 };
753 var mixObject = function (origin, target) {
754 var output = __assign$1({}, origin, target);
755 var blendValue = {};
756 for (var key in output) {
757 if (origin[key] !== undefined && target[key] !== undefined) {
758 blendValue[key] = getMixer(origin[key], target[key]);
759 }
760 }
761 return function (v) {
762 for (var key in blendValue) {
763 output[key] = blendValue[key](v);
764 }
765 return output;
766 };
767 };
768 function analyse(value) {
769 var parsed = complex.parse(value);
770 var numValues = parsed.length;
771 var numNumbers = 0;
772 var numRGB = 0;
773 var numHSL = 0;
774 for (var i = 0; i < numValues; i++) {
775 if (numNumbers || typeof parsed[i] === 'number') {
776 numNumbers++;
777 }
778 else {
779 if (parsed[i].hue !== undefined) {
780 numHSL++;
781 }
782 else {
783 numRGB++;
784 }
785 }
786 }
787 return { parsed: parsed, numNumbers: numNumbers, numRGB: numRGB, numHSL: numHSL };
788 }
789 var mixComplex = function (origin, target) {
790 var template = complex.createTransformer(target);
791 var originStats = analyse(origin);
792 var targetStats = analyse(target);
793 invariant(originStats.numHSL === targetStats.numHSL &&
794 originStats.numRGB === targetStats.numRGB &&
795 originStats.numNumbers >= targetStats.numNumbers, "Complex values '" + origin + "' and '" + target + "' too different to mix. Ensure all colors are of the same type.");
796 return pipe(mixArray(originStats.parsed, targetStats.parsed), template);
797 };
798
799 var mixNumber = function (from, to) { return function (p) { return mix(from, to, p); }; };
800 function detectMixerFactory(v) {
801 if (typeof v === 'number') {
802 return mixNumber;
803 }
804 else if (typeof v === 'string') {
805 if (color.test(v)) {
806 return mixColor;
807 }
808 else {
809 return mixComplex;
810 }
811 }
812 else if (Array.isArray(v)) {
813 return mixArray;
814 }
815 else if (typeof v === 'object') {
816 return mixObject;
817 }
818 }
819 function createMixers(output, ease, customMixer) {
820 var mixers = [];
821 var mixerFactory = customMixer || detectMixerFactory(output[0]);
822 var numMixers = output.length - 1;
823 for (var i = 0; i < numMixers; i++) {
824 var mixer = mixerFactory(output[i], output[i + 1]);
825 if (ease) {
826 var easingFunction = Array.isArray(ease) ? ease[i] : ease;
827 mixer = pipe(easingFunction, mixer);
828 }
829 mixers.push(mixer);
830 }
831 return mixers;
832 }
833 function fastInterpolate(_a, _b) {
834 var from = _a[0], to = _a[1];
835 var mixer = _b[0];
836 return function (v) { return mixer(progress(from, to, v)); };
837 }
838 function slowInterpolate(input, mixers) {
839 var inputLength = input.length;
840 var lastInputIndex = inputLength - 1;
841 return function (v) {
842 var mixerIndex = 0;
843 var foundMixerIndex = false;
844 if (v <= input[0]) {
845 foundMixerIndex = true;
846 }
847 else if (v >= input[lastInputIndex]) {
848 mixerIndex = lastInputIndex - 1;
849 foundMixerIndex = true;
850 }
851 if (!foundMixerIndex) {
852 var i = 1;
853 for (; i < inputLength; i++) {
854 if (input[i] > v || i === lastInputIndex) {
855 break;
856 }
857 }
858 mixerIndex = i - 1;
859 }
860 var progressInRange = progress(input[mixerIndex], input[mixerIndex + 1], v);
861 return mixers[mixerIndex](progressInRange);
862 };
863 }
864 function interpolate(input, output, _a) {
865 var _b = _a === void 0 ? {} : _a, _c = _b.clamp, clamp = _c === void 0 ? true : _c, ease = _b.ease, mixer = _b.mixer;
866 var inputLength = input.length;
867 invariant(inputLength === output.length, 'Both input and output ranges must be the same length');
868 invariant(!ease || !Array.isArray(ease) || ease.length === inputLength - 1, 'Array of easing functions must be of length `input.length - 1`, as it applies to the transitions **between** the defined values.');
869 if (input[0] > input[inputLength - 1]) {
870 input = [].concat(input);
871 output = [].concat(output);
872 input.reverse();
873 output.reverse();
874 }
875 var mixers = createMixers(output, ease, mixer);
876 var interpolator = inputLength === 2
877 ? fastInterpolate(input, mixers)
878 : slowInterpolate(input, mixers);
879 return clamp
880 ? pipe(clamp$1$1(input[0], input[inputLength - 1]), interpolator)
881 : interpolator;
882 }
883
884 var velocityPerSecond = (function (velocity, frameDuration) {
885 return frameDuration ? velocity * (1000 / frameDuration) : 0;
886 });
887
888 var wrap = function (min, max, v) {
889 var rangeSize = max - min;
890 return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
891 };
892 var wrap$1 = curryRange(wrap);
893
894 var clampProgress = clamp$1$1(0, 1);
895
896 var isFloat = function (value) {
897 return !isNaN(parseFloat(value));
898 };
899 /**
900 * `MotionValue` is used to track the state and velocity of motion values.
901 *
902 * @public
903 */
904 var MotionValue = /** @class */ (function () {
905 /**
906 * @param init - The initiating value
907 * @param config - Optional configuration options
908 *
909 * - `transformer`: A function to transform incoming values with.
910 *
911 * @internal
912 */
913 function MotionValue(init) {
914 var _this = this;
915 /**
916 * Duration, in milliseconds, since last updating frame.
917 *
918 * @internal
919 */
920 this.timeDelta = 0;
921 /**
922 * Timestamp of the last time this `MotionValue` was updated.
923 *
924 * @internal
925 */
926 this.lastUpdated = 0;
927 /**
928 * Tracks whether this value can output a velocity. Currently this is only true
929 * if the value is numerical, but we might be able to widen the scope here and support
930 * other value types.
931 *
932 * @internal
933 */
934 this.canTrackVelocity = false;
935 this.updateAndNotify = function (v, render) {
936 if (render === void 0) { render = true; }
937 _this.prev = _this.current;
938 _this.current = v;
939 if (_this.updateSubscribers && _this.prev !== _this.current) {
940 _this.updateSubscribers.forEach(_this.notifySubscriber);
941 }
942 if (render && _this.renderSubscribers) {
943 _this.renderSubscribers.forEach(_this.notifySubscriber);
944 }
945 // Update timestamp
946 var _a = getFrameData(), delta = _a.delta, timestamp = _a.timestamp;
947 if (_this.lastUpdated !== timestamp) {
948 _this.timeDelta = delta;
949 _this.lastUpdated = timestamp;
950 sync.postRender(_this.scheduleVelocityCheck);
951 }
952 };
953 /**
954 * Notify a subscriber with the latest value.
955 *
956 * This is an instanced and bound function to prevent generating a new
957 * function once per frame.
958 *
959 * @param subscriber - The subscriber to notify.
960 *
961 * @internal
962 */
963 this.notifySubscriber = function (subscriber) {
964 subscriber(_this.current);
965 };
966 /**
967 * Schedule a velocity check for the next frame.
968 *
969 * This is an instanced and bound function to prevent generating a new
970 * function once per frame.
971 *
972 * @internal
973 */
974 this.scheduleVelocityCheck = function () { return sync.postRender(_this.velocityCheck); };
975 /**
976 * Updates `prev` with `current` if the value hasn't been updated this frame.
977 * This ensures velocity calculations return `0`.
978 *
979 * This is an instanced and bound function to prevent generating a new
980 * function once per frame.
981 *
982 * @internal
983 */
984 this.velocityCheck = function (_a) {
985 var timestamp = _a.timestamp;
986 if (timestamp !== _this.lastUpdated) {
987 _this.prev = _this.current;
988 }
989 };
990 this.set(init, false);
991 this.canTrackVelocity = isFloat(this.current);
992 }
993 /**
994 * Subscribes a subscriber function to a subscription list.
995 *
996 * @param subscriptions - A `Set` of subscribers.
997 * @param subscription - A subscriber function.
998 */
999 MotionValue.prototype.subscribeTo = function (subscriptions, subscription) {
1000 var _this = this;
1001 var updateSubscriber = function () { return subscription(_this.current); };
1002 subscriptions.add(updateSubscriber);
1003 return function () { return subscriptions.delete(updateSubscriber); };
1004 };
1005 /**
1006 * Adds a function that will be notified when the `MotionValue` is updated.
1007 *
1008 * It returns a function that, when called, will cancel the subscription.
1009 *
1010 * When calling `onChange` inside a React component, it should be wrapped with the
1011 * `useEffect` hook. As it returns an unsubscribe function, this should be returned
1012 * from the `useEffect` function to ensure you don't add duplicate subscribers..
1013 *
1014 * @library
1015 *
1016 * ```jsx
1017 * function MyComponent() {
1018 * const x = useMotionValue(0)
1019 * const y = useMotionValue(0)
1020 * const opacity = useMotionValue(1)
1021 *
1022 * useEffect(() => {
1023 * function updateOpacity() {
1024 * const maxXY = Math.max(x.get(), y.get())
1025 * const newOpacity = transform(maxXY, [0, 100], [1, 0])
1026 * opacity.set(newOpacity)
1027 * }
1028 *
1029 * const unsubscribeX = x.onChange(updateOpacity)
1030 * const unsubscribeY = y.onChange(updateOpacity)
1031 *
1032 * return () => {
1033 * unsubscribeX()
1034 * unsubscribeY()
1035 * }
1036 * }, [])
1037 *
1038 * return <Frame x={x} />
1039 * }
1040 * ```
1041 *
1042 * @motion
1043 *
1044 * ```jsx
1045 * export const MyComponent = () => {
1046 * const x = useMotionValue(0)
1047 * const y = useMotionValue(0)
1048 * const opacity = useMotionValue(1)
1049 *
1050 * useEffect(() => {
1051 * function updateOpacity() {
1052 * const maxXY = Math.max(x.get(), y.get())
1053 * const newOpacity = transform(maxXY, [0, 100], [1, 0])
1054 * opacity.set(newOpacity)
1055 * }
1056 *
1057 * const unsubscribeX = x.onChange(updateOpacity)
1058 * const unsubscribeY = y.onChange(updateOpacity)
1059 *
1060 * return () => {
1061 * unsubscribeX()
1062 * unsubscribeY()
1063 * }
1064 * }, [])
1065 *
1066 * return <motion.div style={{ x }} />
1067 * }
1068 * ```
1069 *
1070 * @internalremarks
1071 *
1072 * We could look into a `useOnChange` hook if the above lifecycle management proves confusing.
1073 *
1074 * ```jsx
1075 * useOnChange(x, () => {})
1076 * ```
1077 *
1078 * @param subscriber - A function that receives the latest value.
1079 * @returns A function that, when called, will cancel this subscription.
1080 *
1081 * @public
1082 */
1083 MotionValue.prototype.onChange = function (subscription) {
1084 if (!this.updateSubscribers)
1085 this.updateSubscribers = new Set();
1086 return this.subscribeTo(this.updateSubscribers, subscription);
1087 };
1088 MotionValue.prototype.clearListeners = function () {
1089 var _a;
1090 (_a = this.updateSubscribers) === null || _a === void 0 ? void 0 : _a.clear();
1091 };
1092 /**
1093 * Adds a function that will be notified when the `MotionValue` requests a render.
1094 *
1095 * @param subscriber - A function that's provided the latest value.
1096 * @returns A function that, when called, will cancel this subscription.
1097 *
1098 * @internal
1099 */
1100 MotionValue.prototype.onRenderRequest = function (subscription) {
1101 if (!this.renderSubscribers)
1102 this.renderSubscribers = new Set();
1103 // Render immediately
1104 this.notifySubscriber(subscription);
1105 return this.subscribeTo(this.renderSubscribers, subscription);
1106 };
1107 /**
1108 * Attaches a passive effect to the `MotionValue`.
1109 *
1110 * @internal
1111 */
1112 MotionValue.prototype.attach = function (passiveEffect) {
1113 this.passiveEffect = passiveEffect;
1114 };
1115 /**
1116 * Sets the state of the `MotionValue`.
1117 *
1118 * @remarks
1119 *
1120 * ```jsx
1121 * const x = useMotionValue(0)
1122 * x.set(10)
1123 * ```
1124 *
1125 * @param latest - Latest value to set.
1126 * @param render - Whether to notify render subscribers. Defaults to `true`
1127 *
1128 * @public
1129 */
1130 MotionValue.prototype.set = function (v, render) {
1131 if (render === void 0) { render = true; }
1132 if (!render || !this.passiveEffect) {
1133 this.updateAndNotify(v, render);
1134 }
1135 else {
1136 this.passiveEffect(v, this.updateAndNotify);
1137 }
1138 };
1139 /**
1140 * Returns the latest state of `MotionValue`
1141 *
1142 * @returns - The latest state of `MotionValue`
1143 *
1144 * @public
1145 */
1146 MotionValue.prototype.get = function () {
1147 return this.current;
1148 };
1149 /**
1150 * @public
1151 */
1152 MotionValue.prototype.getPrevious = function () {
1153 return this.prev;
1154 };
1155 /**
1156 * Returns the latest velocity of `MotionValue`
1157 *
1158 * @returns - The latest velocity of `MotionValue`. Returns `0` if the state is non-numerical.
1159 *
1160 * @public
1161 */
1162 MotionValue.prototype.getVelocity = function () {
1163 // This could be isFloat(this.prev) && isFloat(this.current), but that would be wasteful
1164 return this.canTrackVelocity
1165 ? // These casts could be avoided if parseFloat would be typed better
1166 velocityPerSecond(parseFloat(this.current) -
1167 parseFloat(this.prev), this.timeDelta)
1168 : 0;
1169 };
1170 /**
1171 * Registers a new animation to control this `MotionValue`. Only one
1172 * animation can drive a `MotionValue` at one time.
1173 *
1174 * ```jsx
1175 * value.start()
1176 * ```
1177 *
1178 * @param animation - A function that starts the provided animation
1179 *
1180 * @internal
1181 */
1182 MotionValue.prototype.start = function (animation) {
1183 var _this = this;
1184 this.stop();
1185 return new Promise(function (resolve) {
1186 _this.stopAnimation = animation(resolve);
1187 }).then(function () { return _this.clearAnimation(); });
1188 };
1189 /**
1190 * Stop the currently active animation.
1191 *
1192 * @public
1193 */
1194 MotionValue.prototype.stop = function () {
1195 if (this.stopAnimation)
1196 this.stopAnimation();
1197 this.clearAnimation();
1198 };
1199 /**
1200 * Returns `true` if this value is currently animating.
1201 *
1202 * @public
1203 */
1204 MotionValue.prototype.isAnimating = function () {
1205 return !!this.stopAnimation;
1206 };
1207 MotionValue.prototype.clearAnimation = function () {
1208 this.stopAnimation = null;
1209 };
1210 /**
1211 * Destroy and clean up subscribers to this `MotionValue`.
1212 *
1213 * The `MotionValue` hooks like `useMotionValue` and `useTransform` automatically
1214 * handle the lifecycle of the returned `MotionValue`, so this method is only necessary if you've manually
1215 * created a `MotionValue` via the `motionValue` function.
1216 *
1217 * @public
1218 */
1219 MotionValue.prototype.destroy = function () {
1220 this.updateSubscribers && this.updateSubscribers.clear();
1221 this.renderSubscribers && this.renderSubscribers.clear();
1222 this.stop();
1223 };
1224 return MotionValue;
1225 }());
1226 /**
1227 * @internal
1228 */
1229 function motionValue(init) {
1230 return new MotionValue(init);
1231 }
1232
1233 /**
1234 * VisualElement is an abstract class that provides a generic animation-optimised interface to the
1235 * underlying renderer.
1236 *
1237 * Currently many features interact directly with HTMLVisualElement/SVGVisualElement
1238 * but the idea is we can create, for instance, a ThreeVisualElement that extends
1239 * VisualElement and we can quickly offer all the same features.
1240 */
1241 var VisualElement = /** @class */ (function () {
1242 function VisualElement(parent, ref) {
1243 var _this = this;
1244 // An iterable list of current children
1245 this.children = new Set();
1246 // The latest resolved MotionValues
1247 this.latest = {};
1248 // A map of MotionValues used to animate this element
1249 this.values = new Map();
1250 // Unsubscription callbacks for each MotionValue
1251 this.valueSubscriptions = new Map();
1252 // A configuration for this VisualElement, each derived class can extend this.
1253 this.config = {};
1254 // A pre-bound call to the user-provided `onUpdate` callback. This won't
1255 // be called more than once per frame.
1256 this.update = function () { return _this.config.onUpdate(_this.latest); };
1257 // Pre-bound version of render
1258 this.triggerRender = function () { return _this.render(); };
1259 this.scheduleRender = function () { return sync.render(_this.triggerRender, false, true); };
1260 // This function gets passed to the rendered component's `ref` prop
1261 // and is used to mount/unmount the VisualElement
1262 this.ref = function (element) {
1263 element ? _this.mount(element) : _this.unmount();
1264 if (!_this.externalRef)
1265 return;
1266 if (typeof _this.externalRef === "function") {
1267 _this.externalRef(element);
1268 }
1269 else if (isRefObject(_this.externalRef)) {
1270 _this.externalRef.current = element;
1271 }
1272 };
1273 // Create a relationship with the provided parent.
1274 this.parent = parent;
1275 this.rootParent = parent ? parent.rootParent : this;
1276 this.treePath = parent ? __spreadArrays(parent.treePath, [parent]) : [];
1277 // Calculate the depth of this node in the VisualElement graph
1278 this.depth = parent ? parent.depth + 1 : 0;
1279 // A reference to any externally-defined React ref. This might live better
1280 // outside the VisualElement and be handled in a hook.
1281 this.externalRef = ref;
1282 }
1283 VisualElement.prototype.subscribe = function (child) {
1284 var _this = this;
1285 this.children.add(child);
1286 return function () { return _this.children.delete(child); };
1287 };
1288 // Check whether this element has a MotionValue of the provided key
1289 VisualElement.prototype.hasValue = function (key) {
1290 return this.values.has(key);
1291 };
1292 // Add a MotionValue
1293 VisualElement.prototype.addValue = function (key, value) {
1294 if (this.hasValue(key))
1295 this.removeValue(key);
1296 this.values.set(key, value);
1297 this.latest[key] = value.get();
1298 if (this.element)
1299 this.subscribeToValue(key, value);
1300 };
1301 // Remove a MotionValue
1302 VisualElement.prototype.removeValue = function (key) {
1303 var unsubscribe = this.valueSubscriptions.get(key);
1304 unsubscribe && unsubscribe();
1305 this.values.delete(key);
1306 delete this.latest[key];
1307 this.valueSubscriptions.delete(key);
1308 };
1309 VisualElement.prototype.getValue = function (key, defaultValue) {
1310 var value = this.values.get(key);
1311 if (value === undefined && defaultValue !== undefined) {
1312 value = new MotionValue(defaultValue);
1313 this.addValue(key, value);
1314 }
1315 return value;
1316 };
1317 // Iterate over all MotionValues
1318 VisualElement.prototype.forEachValue = function (callback) {
1319 this.values.forEach(callback);
1320 };
1321 // Get the underlying rendered instance of this VisualElement. For instance in
1322 // HTMLVisualElement this will be a HTMLElement.
1323 VisualElement.prototype.getInstance = function () {
1324 return this.element;
1325 };
1326 VisualElement.prototype.updateConfig = function (config) {
1327 if (config === void 0) { config = {}; }
1328 this.config = __assign({}, config);
1329 };
1330 // Set a single `latest` value
1331 VisualElement.prototype.setSingleStaticValue = function (key, value) {
1332 this.latest[key] = value;
1333 };
1334 // Statically set values to `latest` without needing a MotionValue
1335 VisualElement.prototype.setStaticValues = function (values, value) {
1336 if (typeof values === "string") {
1337 this.setSingleStaticValue(values, value);
1338 }
1339 else {
1340 for (var key in values) {
1341 this.setSingleStaticValue(key, values[key]);
1342 }
1343 }
1344 };
1345 VisualElement.prototype.scheduleUpdateLayoutDelta = function () {
1346 sync.update(this.rootParent.updateLayoutDelta, false, true);
1347 };
1348 // Subscribe to changes in a MotionValue
1349 VisualElement.prototype.subscribeToValue = function (key, value) {
1350 var _this = this;
1351 var onChange = function (latest) {
1352 _this.setSingleStaticValue(key, latest);
1353 _this.latest[key] = latest;
1354 _this.config.onUpdate && sync.update(_this.update, false, true);
1355 };
1356 var unsubscribeOnChange = value.onChange(onChange);
1357 var unsubscribeOnRender = value.onRenderRequest(this.scheduleRender);
1358 this.valueSubscriptions.set(key, function () {
1359 unsubscribeOnChange();
1360 unsubscribeOnRender();
1361 });
1362 };
1363 // Mount the VisualElement with the actual DOM element
1364 VisualElement.prototype.mount = function (element) {
1365 var _this = this;
1366 invariant(!!element, "No ref found. Ensure components created with motion.custom forward refs using React.forwardRef");
1367 if (this.parent) {
1368 this.removeFromParent = this.parent.subscribe(this);
1369 }
1370 /**
1371 * Save the element to this.element as a semantic API, this.current to the VisualElement
1372 * is compatible with existing RefObject APIs.
1373 */
1374 this.element = this.current = element;
1375 // Subscribe to any pre-existing MotionValues
1376 this.forEachValue(function (value, key) { return _this.subscribeToValue(key, value); });
1377 };
1378 // Unmount the VisualElement and cancel any scheduled updates
1379 VisualElement.prototype.unmount = function () {
1380 var _this = this;
1381 this.forEachValue(function (_, key) { return _this.removeValue(key); });
1382 cancelSync.update(this.update);
1383 cancelSync.render(this.render);
1384 this.removeFromParent && this.removeFromParent();
1385 };
1386 return VisualElement;
1387 }());
1388
1389 function noop(any) {
1390 return any;
1391 }
1392
1393 /**
1394 * Bounding boxes tend to be defined as top, left, right, bottom. For various operations
1395 * it's easier to consider each axis individually. This function returns a bounding box
1396 * as a map of single-axis min/max values.
1397 */
1398 function convertBoundingBoxToAxisBox(_a) {
1399 var top = _a.top, left = _a.left, right = _a.right, bottom = _a.bottom;
1400 return {
1401 x: { min: left, max: right },
1402 y: { min: top, max: bottom },
1403 };
1404 }
1405 function convertAxisBoxToBoundingBox(_a) {
1406 var x = _a.x, y = _a.y;
1407 return {
1408 top: y.min,
1409 bottom: y.max,
1410 left: x.min,
1411 right: x.max,
1412 };
1413 }
1414 /**
1415 * Applies a TransformPoint function to a bounding box. TransformPoint is usually a function
1416 * provided by Framer to allow measured points to be corrected for device scaling. This is used
1417 * when measuring DOM elements and DOM event points.
1418 */
1419 function transformBoundingBox(_a, transformPoint) {
1420 var top = _a.top, left = _a.left, bottom = _a.bottom, right = _a.right;
1421 if (transformPoint === void 0) { transformPoint = noop; }
1422 var topLeft = transformPoint({ x: left, y: top });
1423 var bottomRight = transformPoint({ x: right, y: bottom });
1424 return {
1425 top: topLeft.y,
1426 left: topLeft.x,
1427 bottom: bottomRight.y,
1428 right: bottomRight.x,
1429 };
1430 }
1431 /**
1432 * Create an empty axis box of zero size
1433 */
1434 function axisBox() {
1435 return { x: { min: 0, max: 1 }, y: { min: 0, max: 1 } };
1436 }
1437 function copyAxisBox(box) {
1438 return {
1439 x: __assign({}, box.x),
1440 y: __assign({}, box.y),
1441 };
1442 }
1443 /**
1444 * Create an empty box delta
1445 */
1446 var zeroDelta = {
1447 translate: 0,
1448 scale: 1,
1449 origin: 0,
1450 originPoint: 0,
1451 };
1452 function delta() {
1453 return {
1454 x: __assign({}, zeroDelta),
1455 y: __assign({}, zeroDelta),
1456 };
1457 }
1458
1459 /**
1460 * ValueType for "auto"
1461 */
1462 var auto = {
1463 test: function (v) { return v === "auto"; },
1464 parse: function (v) { return v; },
1465 };
1466 /**
1467 * ValueType for ints
1468 */
1469 var int = __assign(__assign({}, number), { transform: Math.round });
1470 /**
1471 * A map of default value types for common values
1472 */
1473 var defaultValueTypes = {
1474 // Color props
1475 color: color,
1476 backgroundColor: color,
1477 outlineColor: color,
1478 fill: color,
1479 stroke: color,
1480 // Border props
1481 borderColor: color,
1482 borderTopColor: color,
1483 borderRightColor: color,
1484 borderBottomColor: color,
1485 borderLeftColor: color,
1486 borderWidth: px,
1487 borderTopWidth: px,
1488 borderRightWidth: px,
1489 borderBottomWidth: px,
1490 borderLeftWidth: px,
1491 borderRadius: px,
1492 radius: px,
1493 borderTopLeftRadius: px,
1494 borderTopRightRadius: px,
1495 borderBottomRightRadius: px,
1496 borderBottomLeftRadius: px,
1497 // Positioning props
1498 width: px,
1499 maxWidth: px,
1500 height: px,
1501 maxHeight: px,
1502 size: px,
1503 top: px,
1504 right: px,
1505 bottom: px,
1506 left: px,
1507 // Spacing props
1508 padding: px,
1509 paddingTop: px,
1510 paddingRight: px,
1511 paddingBottom: px,
1512 paddingLeft: px,
1513 margin: px,
1514 marginTop: px,
1515 marginRight: px,
1516 marginBottom: px,
1517 marginLeft: px,
1518 // Transform props
1519 rotate: degrees,
1520 rotateX: degrees,
1521 rotateY: degrees,
1522 rotateZ: degrees,
1523 scale: scale,
1524 scaleX: scale,
1525 scaleY: scale,
1526 scaleZ: scale,
1527 skew: degrees,
1528 skewX: degrees,
1529 skewY: degrees,
1530 distance: px,
1531 translateX: px,
1532 translateY: px,
1533 translateZ: px,
1534 x: px,
1535 y: px,
1536 z: px,
1537 perspective: px,
1538 opacity: alpha,
1539 originX: progressPercentage,
1540 originY: progressPercentage,
1541 originZ: px,
1542 // Misc
1543 zIndex: int,
1544 // SVG
1545 fillOpacity: alpha,
1546 strokeOpacity: alpha,
1547 numOctaves: int,
1548 };
1549 /**
1550 * A list of value types commonly used for dimensions
1551 */
1552 var dimensionValueTypes = [number, px, percent, degrees, vw, vh, auto];
1553 /**
1554 * Tests a provided value against a ValueType
1555 */
1556 var testValueType = function (v) { return function (type) { return type.test(v); }; };
1557 /**
1558 * Tests a dimensional value against the list of dimension ValueTypes
1559 */
1560 var findDimensionValueType = function (v) {
1561 return dimensionValueTypes.find(testValueType(v));
1562 };
1563 /**
1564 * A list of all ValueTypes
1565 */
1566 var valueTypes = __spreadArrays(dimensionValueTypes, [color, complex]);
1567 /**
1568 * Tests a value against the list of ValueTypes
1569 */
1570 var findValueType = function (v) { return valueTypes.find(testValueType(v)); };
1571 /**
1572 * Gets the default ValueType for the provided value key
1573 */
1574 var getDefaultValueType = function (key) { return defaultValueTypes[key]; };
1575 /**
1576 * Provided a value and a ValueType, returns the value as that value type.
1577 */
1578 var getValueAsType = function (value, type) {
1579 return type && typeof value === "number"
1580 ? type.transform(value)
1581 : value;
1582 };
1583
1584 /**
1585 * A list of all transformable axes. We'll use this list to generated a version
1586 * of each axes for each transform.
1587 */
1588 var axes = ["", "X", "Y", "Z"];
1589 /**
1590 * An ordered array of each transformable value. By default, transform values
1591 * will be sorted to this order.
1592 */
1593 var order = ["translate", "scale", "rotate", "skew", "transformPerspective"];
1594 /**
1595 * Generate a list of every possible transform key.
1596 */
1597 var transformProps = ["x", "y", "z"];
1598 order.forEach(function (operationKey) {
1599 axes.forEach(function (axesKey) { return transformProps.push(operationKey + axesKey); });
1600 });
1601 /**
1602 * A function to use with Array.sort to sort transform keys by their default order.
1603 */
1604 function sortTransformProps(a, b) {
1605 return transformProps.indexOf(a) - transformProps.indexOf(b);
1606 }
1607 /**
1608 * A quick lookup for transform props.
1609 */
1610 var transformPropSet = new Set(transformProps);
1611 function isTransformProp(key) {
1612 return transformPropSet.has(key);
1613 }
1614 /**
1615 * A quick lookup for transform origin props
1616 */
1617 var transformOriginProps = new Set(["originX", "originY", "originZ"]);
1618 function isTransformOriginProp(key) {
1619 return transformOriginProps.has(key);
1620 }
1621
1622 var translateAlias = {
1623 x: "translateX",
1624 y: "translateY",
1625 z: "translateZ",
1626 };
1627 /**
1628 * Build a CSS transform style from individual x/y/scale etc properties.
1629 *
1630 * This outputs with a default order of transforms/scales/rotations, this can be customised by
1631 * providing a transformTemplate function.
1632 */
1633 function buildTransform(transform, transformKeys, transformTemplate, transformIsDefault, enableHardwareAcceleration, allowTransformNone) {
1634 if (enableHardwareAcceleration === void 0) { enableHardwareAcceleration = true; }
1635 if (allowTransformNone === void 0) { allowTransformNone = true; }
1636 // The transform string we're going to build into
1637 var transformString = "";
1638 // Track whether the defined transform has a defined z so we don't add a
1639 // second to enable hardware acceleration
1640 var transformHasZ = false;
1641 // Transform keys into their default order - this will determine the output order.
1642 transformKeys.sort(sortTransformProps);
1643 // Loop over each transform and build them into transformString
1644 var numTransformKeys = transformKeys.length;
1645 for (var i = 0; i < numTransformKeys; i++) {
1646 var key = transformKeys[i];
1647 transformString += (translateAlias[key] || key) + "(" + transform[key] + ") ";
1648 if (key === "z")
1649 transformHasZ = true;
1650 }
1651 if (!transformHasZ && enableHardwareAcceleration) {
1652 transformString += "translateZ(0)";
1653 }
1654 else {
1655 transformString = transformString.trim();
1656 }
1657 // If we have a custom `transform` template, pass our transform values and
1658 // generated transformString to that before returning
1659 if (transformTemplate) {
1660 transformString = transformTemplate(transform, transformIsDefault ? "" : transformString);
1661 }
1662 else if (allowTransformNone && transformIsDefault) {
1663 transformString = "none";
1664 }
1665 return transformString;
1666 }
1667
1668 /**
1669 * Returns true if the provided key is a CSS variable
1670 */
1671 function isCSSVariable(key) {
1672 return key.startsWith("--");
1673 }
1674
1675 function pixelsToPercent(pixels, axis) {
1676 return (pixels / (axis.max - axis.min)) * 100;
1677 }
1678 /**
1679 * We always correct borderRadius as a percentage rather than pixels to reduce paints.
1680 * For example, if you are projecting a box that is 100px wide with a 10px borderRadius
1681 * into a box that is 200px wide with a 20px borderRadius, that is actually a 10%
1682 * borderRadius in both states. If we animate between the two in pixels that will trigger
1683 * a paint each time. If we animate between the two in percentage we'll avoid a paint.
1684 */
1685 function correctBorderRadius(latest, viewportBox) {
1686 /**
1687 * If latest is a string, we either presume it's already a percentage, in which case it'll
1688 * already be stretched appropriately, or it's another value type which we don't support.
1689 */
1690 if (typeof latest !== "number")
1691 return latest;
1692 /**
1693 * If latest is a number, it's a pixel value. We use the current viewportBox to calculate that
1694 * pixel value as a percentage of each axis
1695 */
1696 var x = pixelsToPercent(latest, viewportBox.x);
1697 var y = pixelsToPercent(latest, viewportBox.y);
1698 return x + "% " + y + "%";
1699 }
1700 function correctBoxShadow(latest, _viewportBox, delta, treeScale) {
1701 // GC Warning - this creates a function and object every frame
1702 var shadow = complex.parse(latest);
1703 var template = complex.createTransformer(latest);
1704 // Calculate the overall context scale
1705 var xScale = delta.x.scale * treeScale.x;
1706 var yScale = delta.y.scale * treeScale.y;
1707 // Scale x/y
1708 shadow[1] /= xScale;
1709 shadow[2] /= yScale;
1710 /**
1711 * Ideally we'd correct x and y scales individually, but because blur and
1712 * spread apply to both we have to take a scale average and apply that instead.
1713 * We could potentially improve the outcome of this by incorporating the ratio between
1714 * the two scales.
1715 */
1716 var averageScale = mix(xScale, yScale, 0.5);
1717 // Blur
1718 if (typeof shadow[3] === "number")
1719 shadow[3] /= averageScale;
1720 // Spread
1721 if (typeof shadow[4] === "number")
1722 shadow[4] /= averageScale;
1723 return template(shadow);
1724 }
1725 var borderCorrectionDefinition = {
1726 process: correctBorderRadius,
1727 };
1728 var valueScaleCorrection = {
1729 borderRadius: __assign(__assign({}, borderCorrectionDefinition), { applyTo: [
1730 "borderTopLeftRadius",
1731 "borderTopRightRadius",
1732 "borderBottomLeftRadius",
1733 "borderBottomRightRadius",
1734 ] }),
1735 borderTopLeftRadius: borderCorrectionDefinition,
1736 borderTopRightRadius: borderCorrectionDefinition,
1737 borderBottomLeftRadius: borderCorrectionDefinition,
1738 borderBottomRightRadius: borderCorrectionDefinition,
1739 boxShadow: {
1740 process: correctBoxShadow,
1741 },
1742 };
1743 /**
1744 * @internal
1745 */
1746 function addScaleCorrection(correctors) {
1747 for (var key in correctors) {
1748 valueScaleCorrection[key] = correctors[key];
1749 }
1750 }
1751
1752 function createDeltaTransform(delta, treeScale) {
1753 var x = delta.x.translate / treeScale.x;
1754 var y = delta.y.translate / treeScale.y;
1755 var scaleX = delta.x.scale;
1756 var scaleY = delta.y.scale;
1757 return "translate3d(" + x + "px, " + y + "px, 0) scale(" + scaleX + ", " + scaleY + ")";
1758 }
1759
1760 /**
1761 * Build style and CSS variables
1762 *
1763 * This function converts a Motion style prop:
1764 *
1765 * { x: 100, width: 100, originX: 0.5 }
1766 *
1767 * Into an object with default value types applied and default
1768 * transform order set:
1769 *
1770 * {
1771 * transform: 'translateX(100px) translateZ(0)`,
1772 * width: '100px',
1773 * transformOrigin: '50% 50%'
1774 * }
1775 *
1776 * Styles are saved to `style` and CSS vars to `vars`.
1777 *
1778 * This function works with mutative data structures.
1779 */
1780 function buildHTMLStyles(latest, style, vars, transform, transformOrigin, transformKeys, _a, isLayoutProjectionEnabled, delta, deltaFinal, treeScale, targetBox) {
1781 var enableHardwareAcceleration = _a.enableHardwareAcceleration, transformTemplate = _a.transformTemplate, allowTransformNone = _a.allowTransformNone;
1782 // Empty the transformKeys array. As we're throwing out refs to its items
1783 // this might not be as cheap as suspected. Maybe using the array as a buffer
1784 // with a manual incrementation would be better.
1785 transformKeys.length = 0;
1786 // Track whether we encounter any transform or transformOrigin values.
1787 var hasTransform = !!isLayoutProjectionEnabled;
1788 var hasTransformOrigin = !!isLayoutProjectionEnabled;
1789 // Does the calculated transform essentially equal "none"?
1790 var transformIsNone = true;
1791 /**
1792 * Loop over all our latest animated values and decide whether to handle them
1793 * as a style or CSS variable. Transforms and transform origins are kept seperately
1794 * for further processing
1795 */
1796 for (var key in latest) {
1797 var value = latest[key];
1798 // Convert the value to its default value type, ie 0 -> "0px"
1799 var valueType = getDefaultValueType(key);
1800 var valueAsType = getValueAsType(value, valueType);
1801 if (isTransformProp(key)) {
1802 // If this is a transform, flag and enable further transform processing
1803 hasTransform = true;
1804 transform[key] = valueAsType;
1805 transformKeys.push(key);
1806 if (!transformIsNone)
1807 continue;
1808 // If all the transform keys we've so far encountered are their default value
1809 // then check to see if this one isn't
1810 var defaultValue = valueType.default !== undefined ? valueType.default : 0;
1811 if (value !== defaultValue)
1812 transformIsNone = false;
1813 }
1814 else if (isTransformOriginProp(key)) {
1815 // If this is a transform origin, flag and enable further transform-origin processing
1816 transformOrigin[key] = valueAsType;
1817 hasTransformOrigin = true;
1818 }
1819 else if (key !== "transform" || typeof value !== "function") {
1820 // Handle all remaining values. Decide which map to save to depending
1821 // on whether this is a CSS variable
1822 var bucket = isCSSVariable(key) ? vars : style;
1823 // If we need to perform scale correction, and we have a handler for this
1824 // value type (ie borderRadius), perform it
1825 if (isLayoutProjectionEnabled && valueScaleCorrection[key]) {
1826 var corrected = valueScaleCorrection[key].process(value, targetBox, delta, treeScale);
1827 /**
1828 * Scale-correctable values can define a number of other values to break
1829 * down into. For instance borderRadius needs applying to borderBottomLeftRadius etc
1830 */
1831 var applyTo = valueScaleCorrection[key].applyTo;
1832 if (applyTo) {
1833 var num = applyTo.length;
1834 for (var i = 0; i < num; i++) {
1835 bucket[applyTo[i]] = corrected;
1836 }
1837 }
1838 else {
1839 bucket[key] = corrected;
1840 }
1841 }
1842 else {
1843 bucket[key] = valueAsType;
1844 }
1845 }
1846 }
1847 // Only process transform if values aren't defaults
1848 if (hasTransform || transformTemplate) {
1849 if (!isLayoutProjectionEnabled) {
1850 style.transform = buildTransform(transform, transformKeys, transformTemplate, transformIsNone, enableHardwareAcceleration, allowTransformNone);
1851 }
1852 else {
1853 style.transform = createDeltaTransform(deltaFinal, treeScale);
1854 if (transformTemplate)
1855 style.transform = transformTemplate(transform, style.transform);
1856 }
1857 }
1858 // Only process transform origin if values aren't default
1859 if (hasTransformOrigin) {
1860 var originX = isLayoutProjectionEnabled
1861 ? deltaFinal.x.origin * 100 + "%"
1862 : transformOrigin.originX || "50%";
1863 var originY = isLayoutProjectionEnabled
1864 ? deltaFinal.y.origin * 100 + "%"
1865 : transformOrigin.originY || "50%";
1866 var originZ = transformOrigin.originZ || "0";
1867 style.transformOrigin = originX + " " + originY + " " + originZ;
1868 }
1869 }
1870
1871 /**
1872 * Reset an axis to the provided origin box.
1873 *
1874 * This is a mutative operation.
1875 */
1876 function resetAxis(axis, originAxis) {
1877 axis.min = originAxis.min;
1878 axis.max = originAxis.max;
1879 }
1880 /**
1881 * Reset a box to the provided origin box.
1882 *
1883 * This is a mutative operation.
1884 */
1885 function resetBox(box, originBox) {
1886 resetAxis(box.x, originBox.x);
1887 resetAxis(box.y, originBox.y);
1888 }
1889 /**
1890 * Scales a point based on a factor and an originPoint
1891 */
1892 function scalePoint(point, scale, originPoint) {
1893 var distanceFromOrigin = point - originPoint;
1894 var scaled = scale * distanceFromOrigin;
1895 return originPoint + scaled;
1896 }
1897 /**
1898 * Applies a translate/scale delta to a point
1899 */
1900 function applyPointDelta(point, translate, scale, originPoint, boxScale) {
1901 if (boxScale !== undefined) {
1902 point = scalePoint(point, boxScale, originPoint);
1903 }
1904 return scalePoint(point, scale, originPoint) + translate;
1905 }
1906 /**
1907 * Applies a translate/scale delta to an axis
1908 */
1909 function applyAxisDelta(axis, translate, scale, originPoint, boxScale) {
1910 if (translate === void 0) { translate = 0; }
1911 if (scale === void 0) { scale = 1; }
1912 axis.min = applyPointDelta(axis.min, translate, scale, originPoint, boxScale);
1913 axis.max = applyPointDelta(axis.max, translate, scale, originPoint, boxScale);
1914 }
1915 /**
1916 * Applies a translate/scale delta to a box
1917 */
1918 function applyBoxDelta(box, _a) {
1919 var x = _a.x, y = _a.y;
1920 applyAxisDelta(box.x, x.translate, x.scale, x.originPoint);
1921 applyAxisDelta(box.y, y.translate, y.scale, y.originPoint);
1922 }
1923 /**
1924 * Apply a transform to an axis from the latest resolved motion values.
1925 * This function basically acts as a bridge between a flat motion value map
1926 * and applyAxisDelta
1927 */
1928 function applyAxisTransforms(final, axis, transforms, _a) {
1929 var key = _a[0], scaleKey = _a[1], originKey = _a[2];
1930 // Copy the current axis to the final axis before mutation
1931 final.min = axis.min;
1932 final.max = axis.max;
1933 var originPoint = mix(axis.min, axis.max, transforms[originKey] || 0.5);
1934 // Apply the axis delta to the final axis
1935 applyAxisDelta(final, transforms[key], transforms[scaleKey], originPoint, transforms.scale);
1936 }
1937 /**
1938 * The names of the motion values we want to apply as translation, scale and origin.
1939 */
1940 var xKeys = ["x", "scaleX", "originX"];
1941 var yKeys = ["y", "scaleY", "originY"];
1942 /**
1943 * Apply a transform to a box from the latest resolved motion values.
1944 */
1945 function applyBoxTransforms(finalBox, box, transforms) {
1946 applyAxisTransforms(finalBox.x, box.x, transforms, xKeys);
1947 applyAxisTransforms(finalBox.y, box.y, transforms, yKeys);
1948 }
1949 /**
1950 * Remove a delta from a point. This is essentially the steps of applyPointDelta in reverse
1951 */
1952 function removePointDelta(point, translate, scale, originPoint, boxScale) {
1953 point -= translate;
1954 point = scalePoint(point, 1 / scale, originPoint);
1955 if (boxScale !== undefined) {
1956 point = scalePoint(point, 1 / boxScale, originPoint);
1957 }
1958 return point;
1959 }
1960 /**
1961 * Remove a delta from an axis. This is essentially the steps of applyAxisDelta in reverse
1962 */
1963 function removeAxisDelta(axis, translate, scale, origin, boxScale) {
1964 if (translate === void 0) { translate = 0; }
1965 if (scale === void 0) { scale = 1; }
1966 if (origin === void 0) { origin = 0.5; }
1967 var originPoint = mix(axis.min, axis.max, origin) - translate;
1968 axis.min = removePointDelta(axis.min, translate, scale, originPoint, boxScale);
1969 axis.max = removePointDelta(axis.max, translate, scale, originPoint, boxScale);
1970 }
1971 /**
1972 * Remove a transforms from an axis. This is essentially the steps of applyAxisTransforms in reverse
1973 * and acts as a bridge between motion values and removeAxisDelta
1974 */
1975 function removeAxisTransforms(axis, transforms, _a) {
1976 var key = _a[0], scaleKey = _a[1], originKey = _a[2];
1977 removeAxisDelta(axis, transforms[key], transforms[scaleKey], transforms[originKey], transforms.scale);
1978 }
1979 /**
1980 * Remove a transforms from an box. This is essentially the steps of applyAxisBox in reverse
1981 * and acts as a bridge between motion values and removeAxisDelta
1982 */
1983 function removeBoxTransforms(box, transforms) {
1984 removeAxisTransforms(box.x, transforms, xKeys);
1985 removeAxisTransforms(box.y, transforms, yKeys);
1986 }
1987 /**
1988 * Apply a tree of deltas to a box. We do this to calculate the effect of all the transforms
1989 * in a tree upon our box before then calculating how to project it into our desired viewport-relative box
1990 *
1991 * This is the final nested loop within HTMLVisualElement.updateLayoutDelta
1992 */
1993 function applyTreeDeltas(box, treePath) {
1994 var treeLength = treePath.length;
1995 for (var i = 0; i < treeLength; i++) {
1996 applyBoxDelta(box, treePath[i].delta);
1997 }
1998 }
1999
2000 var clampProgress$1 = clamp$1$1(0, 1);
2001 /**
2002 * Returns true if the provided value is within maxDistance of the provided target
2003 */
2004 function isNear(value, target, maxDistance) {
2005 if (target === void 0) { target = 0; }
2006 if (maxDistance === void 0) { maxDistance = 0.01; }
2007 return distance(value, target) < maxDistance;
2008 }
2009 /**
2010 * Calculate the translate needed to be applied to source to get target
2011 */
2012 function calcTranslate(source, target, origin) {
2013 var sourcePoint = mix(source.min, source.max, origin);
2014 var targetPoint = mix(target.min, target.max, origin);
2015 return targetPoint - sourcePoint;
2016 }
2017 /**
2018 * Calculate a transform origin relative to the source axis, between 0-1, that results
2019 * in an asthetically pleasing scale/transform needed to project from source to target.
2020 */
2021 function calcOrigin(source, target) {
2022 var origin = 0.5;
2023 var sourceLength = source.max - source.min;
2024 var targetLength = target.max - target.min;
2025 if (targetLength > sourceLength) {
2026 origin = progress(target.min, target.max - sourceLength, source.min);
2027 }
2028 else if (sourceLength > targetLength) {
2029 origin = progress(source.min, source.max - targetLength, target.min);
2030 }
2031 return clampProgress$1(origin);
2032 }
2033 /**
2034 * Update the AxisDelta with a transform that projects source into target.
2035 *
2036 * The transform `origin` is optional. If not provided, it'll be automatically
2037 * calculated based on the relative positions of the two bounding boxes.
2038 */
2039 function updateAxisDelta(delta, source, target, origin) {
2040 var sourceLength = source.max - source.min;
2041 var targetLength = target.max - target.min;
2042 delta.origin = origin === undefined ? calcOrigin(source, target) : origin;
2043 delta.originPoint = mix(source.min, source.max, delta.origin);
2044 delta.scale = targetLength / sourceLength;
2045 if (isNear(delta.scale, 1, 0.0001))
2046 delta.scale = 1;
2047 delta.translate = calcTranslate(source, target, delta.origin);
2048 if (isNear(delta.translate))
2049 delta.translate = 0;
2050 }
2051 /**
2052 * Update the BoxDelta with a transform that projects the source into the target.
2053 *
2054 * The transform `origin` is optional. If not provided, it'll be automatically
2055 * calculated based on the relative positions of the two bounding boxes.
2056 */
2057 function updateBoxDelta(delta, source, target, origin) {
2058 updateAxisDelta(delta.x, source.x, target.x, origin);
2059 updateAxisDelta(delta.y, source.y, target.y, origin);
2060 }
2061 /**
2062 * Update the treeScale by incorporating the parent's latest scale into its treeScale.
2063 */
2064 function updateTreeScale(treeScale, parentTreeScale, parentDelta) {
2065 treeScale.x = parentTreeScale.x * parentDelta.x.scale;
2066 treeScale.y = parentTreeScale.y * parentDelta.y.scale;
2067 }
2068
2069 // Call a handler once for each axis
2070 function eachAxis(handler) {
2071 return [handler("x"), handler("y")];
2072 }
2073
2074 var Observer = /*#__PURE__*/function () {
2075 function Observer(_a, observer) {
2076 var _this = this;
2077 var middleware = _a.middleware,
2078 onComplete = _a.onComplete;
2079 this.isActive = true;
2080 this.update = function (v) {
2081 if (_this.observer.update) _this.updateObserver(v);
2082 };
2083 this.complete = function () {
2084 if (_this.observer.complete && _this.isActive) _this.observer.complete();
2085 if (_this.onComplete) _this.onComplete();
2086 _this.isActive = false;
2087 };
2088 this.error = function (err) {
2089 if (_this.observer.error && _this.isActive) _this.observer.error(err);
2090 _this.isActive = false;
2091 };
2092 this.observer = observer;
2093 this.updateObserver = function (v) {
2094 return observer.update(v);
2095 };
2096 this.onComplete = onComplete;
2097 if (observer.update && middleware && middleware.length) {
2098 middleware.forEach(function (m) {
2099 return _this.updateObserver = m(_this.updateObserver, _this.complete);
2100 });
2101 }
2102 }
2103 return Observer;
2104 }();
2105 var createObserver = function (observerCandidate, _a, onComplete) {
2106 var middleware = _a.middleware;
2107 if (typeof observerCandidate === 'function') {
2108 return new Observer({ middleware: middleware, onComplete: onComplete }, { update: observerCandidate });
2109 } else {
2110 return new Observer({ middleware: middleware, onComplete: onComplete }, observerCandidate);
2111 }
2112 };
2113
2114 var Action = /*#__PURE__*/function () {
2115 function Action(props) {
2116 if (props === void 0) {
2117 props = {};
2118 }
2119 this.props = props;
2120 }
2121 Action.prototype.create = function (props) {
2122 return new Action(props);
2123 };
2124 Action.prototype.start = function (observerCandidate) {
2125 if (observerCandidate === void 0) {
2126 observerCandidate = {};
2127 }
2128 var isComplete = false;
2129 var subscription = {
2130 stop: function () {
2131 return undefined;
2132 }
2133 };
2134 var _a = this.props,
2135 init = _a.init,
2136 observerProps = __rest(_a, ["init"]);
2137 var observer = createObserver(observerCandidate, observerProps, function () {
2138 isComplete = true;
2139 subscription.stop();
2140 });
2141 var api = init(observer);
2142 subscription = api ? __assign({}, subscription, api) : subscription;
2143 if (isComplete) subscription.stop();
2144 return subscription;
2145 };
2146 Action.prototype.applyMiddleware = function (middleware) {
2147 return this.create(__assign({}, this.props, { middleware: this.props.middleware ? [middleware].concat(this.props.middleware) : [middleware] }));
2148 };
2149 Action.prototype.pipe = function () {
2150 var funcs = [];
2151 for (var _i = 0; _i < arguments.length; _i++) {
2152 funcs[_i] = arguments[_i];
2153 }
2154 var pipedUpdate = funcs.length === 1 ? funcs[0] : pipe.apply(void 0, funcs);
2155 return this.applyMiddleware(function (update) {
2156 return function (v) {
2157 return update(pipedUpdate(v));
2158 };
2159 });
2160 };
2161 return Action;
2162 }();
2163 var action = function (init) {
2164 return new Action({ init: init });
2165 };
2166
2167 var createVectorTests = function (typeTests) {
2168 var testNames = Object.keys(typeTests);
2169 var isVectorProp = function (prop, key) {
2170 return prop !== undefined && !typeTests[key](prop);
2171 };
2172 var getVectorKeys = function (props) {
2173 return testNames.reduce(function (vectorKeys, key) {
2174 if (isVectorProp(props[key], key)) vectorKeys.push(key);
2175 return vectorKeys;
2176 }, []);
2177 };
2178 var testVectorProps = function (props) {
2179 return props && testNames.some(function (key) {
2180 return isVectorProp(props[key], key);
2181 });
2182 };
2183 return { getVectorKeys: getVectorKeys, testVectorProps: testVectorProps };
2184 };
2185 var unitTypes = [px, percent, degrees, vh, vw];
2186 var findUnitType = function (prop) {
2187 return unitTypes.find(function (type) {
2188 return type.test(prop);
2189 });
2190 };
2191 var isUnitProp = function (prop) {
2192 return Boolean(findUnitType(prop));
2193 };
2194 var createAction = function (action, props) {
2195 return action(props);
2196 };
2197 var createUnitAction = function (action, _a) {
2198 var from = _a.from,
2199 to = _a.to,
2200 props = __rest(_a, ["from", "to"]);
2201 var unitType = findUnitType(from) || findUnitType(to);
2202 var transform = unitType.transform,
2203 parse = unitType.parse;
2204 return action(__assign({}, props, { from: typeof from === 'string' ? parse(from) : from, to: typeof to === 'string' ? parse(to) : to })).pipe(transform);
2205 };
2206 var createMixerAction = function (mixer) {
2207 return function (action, _a) {
2208 var from = _a.from,
2209 to = _a.to,
2210 props = __rest(_a, ["from", "to"]);
2211 return action(__assign({}, props, { from: 0, to: 1 })).pipe(mixer(from, to));
2212 };
2213 };
2214 var createColorAction = /*#__PURE__*/createMixerAction(mixColor);
2215 var createComplexAction = /*#__PURE__*/createMixerAction(mixComplex);
2216 var createVectorAction = function (action, typeTests) {
2217 var _a = createVectorTests(typeTests),
2218 testVectorProps = _a.testVectorProps,
2219 getVectorKeys = _a.getVectorKeys;
2220 var vectorAction = function (props) {
2221 var isVector = testVectorProps(props);
2222 if (!isVector) return action(props);
2223 var vectorKeys = getVectorKeys(props);
2224 var testKey = vectorKeys[0];
2225 var testProp = props[testKey];
2226 return getActionCreator(testProp)(action, props, vectorKeys);
2227 };
2228 return vectorAction;
2229 };
2230 var getActionCreator = function (prop) {
2231 if (typeof prop === 'number') {
2232 return createAction;
2233 } else if (isUnitProp(prop)) {
2234 return createUnitAction;
2235 } else if (color.test(prop)) {
2236 return createColorAction;
2237 } else if (complex.test(prop)) {
2238 return createComplexAction;
2239 } else {
2240 return createAction;
2241 }
2242 };
2243
2244 var decay = function (props) {
2245 if (props === void 0) {
2246 props = {};
2247 }
2248 return action(function (_a) {
2249 var complete = _a.complete,
2250 update = _a.update;
2251 var _b = props.velocity,
2252 velocity = _b === void 0 ? 0 : _b,
2253 _c = props.from,
2254 from = _c === void 0 ? 0 : _c,
2255 _d = props.power,
2256 power = _d === void 0 ? 0.8 : _d,
2257 _e = props.timeConstant,
2258 timeConstant = _e === void 0 ? 350 : _e,
2259 _f = props.restDelta,
2260 restDelta = _f === void 0 ? 0.5 : _f,
2261 modifyTarget = props.modifyTarget;
2262 var elapsed = 0;
2263 var amplitude = power * velocity;
2264 var idealTarget = Math.round(from + amplitude);
2265 var target = typeof modifyTarget === 'undefined' ? idealTarget : modifyTarget(idealTarget);
2266 var process = sync.update(function (_a) {
2267 var frameDelta = _a.delta;
2268 elapsed += frameDelta;
2269 var delta = -amplitude * Math.exp(-elapsed / timeConstant);
2270 var isMoving = delta > restDelta || delta < -restDelta;
2271 var current = isMoving ? target + delta : target;
2272 update(current);
2273 if (!isMoving) {
2274 cancelSync.update(process);
2275 complete();
2276 }
2277 }, true);
2278 return {
2279 stop: function () {
2280 return cancelSync.update(process);
2281 }
2282 };
2283 });
2284 };
2285 var vectorDecay = /*#__PURE__*/createVectorAction(decay, {
2286 from: number.test,
2287 modifyTarget: function (func) {
2288 return typeof func === 'function';
2289 },
2290 velocity: number.test
2291 });
2292
2293 var spring = function (props) {
2294 if (props === void 0) {
2295 props = {};
2296 }
2297 return action(function (_a) {
2298 var update = _a.update,
2299 complete = _a.complete;
2300 var _b = props.velocity,
2301 velocity = _b === void 0 ? 0.0 : _b;
2302 var _c = props.from,
2303 from = _c === void 0 ? 0.0 : _c,
2304 _d = props.to,
2305 to = _d === void 0 ? 0.0 : _d,
2306 _e = props.stiffness,
2307 stiffness = _e === void 0 ? 100 : _e,
2308 _f = props.damping,
2309 damping = _f === void 0 ? 10 : _f,
2310 _g = props.mass,
2311 mass = _g === void 0 ? 1.0 : _g,
2312 _h = props.restSpeed,
2313 restSpeed = _h === void 0 ? 0.01 : _h,
2314 _j = props.restDelta,
2315 restDelta = _j === void 0 ? 0.01 : _j;
2316 var initialVelocity = velocity ? -(velocity / 1000) : 0.0;
2317 var t = 0;
2318 var delta = to - from;
2319 var position = from;
2320 var prevPosition = position;
2321 var process = sync.update(function (_a) {
2322 var timeDelta = _a.delta;
2323 t += timeDelta;
2324 var dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
2325 var angularFreq = Math.sqrt(stiffness / mass) / 1000;
2326 prevPosition = position;
2327 if (dampingRatio < 1) {
2328 var envelope = Math.exp(-dampingRatio * angularFreq * t);
2329 var expoDecay = angularFreq * Math.sqrt(1.0 - dampingRatio * dampingRatio);
2330 position = to - envelope * ((initialVelocity + dampingRatio * angularFreq * delta) / expoDecay * Math.sin(expoDecay * t) + delta * Math.cos(expoDecay * t));
2331 } else {
2332 var envelope = Math.exp(-angularFreq * t);
2333 position = to - envelope * (delta + (initialVelocity + angularFreq * delta) * t);
2334 }
2335 velocity = velocityPerSecond(position - prevPosition, timeDelta);
2336 var isBelowVelocityThreshold = Math.abs(velocity) <= restSpeed;
2337 var isBelowDisplacementThreshold = Math.abs(to - position) <= restDelta;
2338 if (isBelowVelocityThreshold && isBelowDisplacementThreshold) {
2339 position = to;
2340 update(position);
2341 cancelSync.update(process);
2342 complete();
2343 } else {
2344 update(position);
2345 }
2346 }, true);
2347 return {
2348 stop: function () {
2349 return cancelSync.update(process);
2350 }
2351 };
2352 });
2353 };
2354 var vectorSpring = /*#__PURE__*/createVectorAction(spring, {
2355 from: number.test,
2356 to: number.test,
2357 stiffness: number.test,
2358 damping: number.test,
2359 mass: number.test,
2360 velocity: number.test
2361 });
2362
2363 var inertia = function (_a) {
2364 var _b = _a.from,
2365 from = _b === void 0 ? 0 : _b,
2366 _c = _a.velocity,
2367 velocity = _c === void 0 ? 0 : _c,
2368 min = _a.min,
2369 max = _a.max,
2370 _d = _a.power,
2371 power = _d === void 0 ? 0.8 : _d,
2372 _e = _a.timeConstant,
2373 timeConstant = _e === void 0 ? 700 : _e,
2374 _f = _a.bounceStiffness,
2375 bounceStiffness = _f === void 0 ? 500 : _f,
2376 _g = _a.bounceDamping,
2377 bounceDamping = _g === void 0 ? 10 : _g,
2378 _h = _a.restDelta,
2379 restDelta = _h === void 0 ? 1 : _h,
2380 modifyTarget = _a.modifyTarget;
2381 return action(function (_a) {
2382 var update = _a.update,
2383 complete = _a.complete;
2384 var prev = from;
2385 var current = from;
2386 var activeAnimation;
2387 var isSpring = false;
2388 var isLessThanMin = function (v) {
2389 return min !== undefined && v <= min;
2390 };
2391 var isMoreThanMax = function (v) {
2392 return max !== undefined && v >= max;
2393 };
2394 var isOutOfBounds = function (v) {
2395 return isLessThanMin(v) || isMoreThanMax(v);
2396 };
2397 var isTravellingAwayFromBounds = function (v, currentVelocity) {
2398 return isLessThanMin(v) && currentVelocity < 0 || isMoreThanMax(v) && currentVelocity > 0;
2399 };
2400 var onUpdate = function (v) {
2401 update(v);
2402 prev = current;
2403 current = v;
2404 velocity = velocityPerSecond(current - prev, getFrameData().delta);
2405 if (activeAnimation && !isSpring && isTravellingAwayFromBounds(v, velocity)) {
2406 startSpring({ from: v, velocity: velocity });
2407 }
2408 };
2409 var startAnimation = function (animation, next) {
2410 activeAnimation && activeAnimation.stop();
2411 activeAnimation = animation.start({
2412 update: onUpdate,
2413 complete: function () {
2414 if (next) {
2415 next();
2416 return;
2417 }
2418 complete();
2419 }
2420 });
2421 };
2422 var startSpring = function (props) {
2423 isSpring = true;
2424 startAnimation(vectorSpring(__assign({}, props, { to: isLessThanMin(props.from) ? min : max, stiffness: bounceStiffness, damping: bounceDamping, restDelta: restDelta })));
2425 };
2426 if (isOutOfBounds(from)) {
2427 startSpring({ from: from, velocity: velocity });
2428 } else if (velocity !== 0) {
2429 var animation = vectorDecay({
2430 from: from,
2431 velocity: velocity,
2432 timeConstant: timeConstant,
2433 power: power,
2434 restDelta: isOutOfBounds(from) ? 20 : restDelta,
2435 modifyTarget: modifyTarget
2436 });
2437 startAnimation(animation, function () {
2438 if (isOutOfBounds(current)) {
2439 startSpring({ from: current, velocity: velocity });
2440 } else {
2441 complete();
2442 }
2443 });
2444 } else {
2445 complete();
2446 }
2447 return {
2448 stop: function () {
2449 return activeAnimation && activeAnimation.stop();
2450 }
2451 };
2452 });
2453 };
2454 var index = /*#__PURE__*/createVectorAction(inertia, {
2455 from: number.test,
2456 velocity: number.test,
2457 min: number.test,
2458 max: number.test,
2459 damping: number.test,
2460 stiffness: number.test,
2461 modifyTarget: function (func) {
2462 return typeof func === 'function';
2463 }
2464 });
2465
2466 var scrubber = function (_a) {
2467 var _b = _a.from,
2468 from = _b === void 0 ? 0 : _b,
2469 _c = _a.to,
2470 to = _c === void 0 ? 1 : _c,
2471 _d = _a.ease,
2472 ease = _d === void 0 ? linear : _d,
2473 _e = _a.reverseEase,
2474 reverseEase = _e === void 0 ? false : _e;
2475 if (reverseEase) {
2476 ease = createReversedEasing(ease);
2477 }
2478 return action(function (_a) {
2479 var update = _a.update;
2480 return {
2481 seek: function (progress) {
2482 return update(progress);
2483 }
2484 };
2485 }).pipe(ease, function (v) {
2486 return mix(from, to, v);
2487 });
2488 };
2489 var vectorScrubber = /*#__PURE__*/createVectorAction(scrubber, {
2490 ease: function (func) {
2491 return typeof func === 'function';
2492 },
2493 from: number.test,
2494 to: number.test
2495 });
2496
2497 var clampProgress$2 = /*#__PURE__*/clamp$1$1(0, 1);
2498 var tween = function (props) {
2499 if (props === void 0) {
2500 props = {};
2501 }
2502 return action(function (_a) {
2503 var update = _a.update,
2504 complete = _a.complete;
2505 var _b = props.duration,
2506 duration = _b === void 0 ? 300 : _b,
2507 _c = props.ease,
2508 ease = _c === void 0 ? easeOut : _c,
2509 _d = props.flip,
2510 flip = _d === void 0 ? 0 : _d,
2511 _e = props.loop,
2512 loop = _e === void 0 ? 0 : _e,
2513 _f = props.yoyo,
2514 yoyo = _f === void 0 ? 0 : _f,
2515 _g = props.repeatDelay,
2516 repeatDelay = _g === void 0 ? 0 : _g;
2517 var _h = props.from,
2518 from = _h === void 0 ? 0 : _h,
2519 _j = props.to,
2520 to = _j === void 0 ? 1 : _j,
2521 _k = props.elapsed,
2522 elapsed = _k === void 0 ? 0 : _k,
2523 _l = props.flipCount,
2524 flipCount = _l === void 0 ? 0 : _l,
2525 _m = props.yoyoCount,
2526 yoyoCount = _m === void 0 ? 0 : _m,
2527 _o = props.loopCount,
2528 loopCount = _o === void 0 ? 0 : _o;
2529 var playhead = vectorScrubber({ from: from, to: to, ease: ease }).start(update);
2530 var currentProgress = 0;
2531 var process;
2532 var isActive = false;
2533 var reverseAnimation = function (reverseEase) {
2534 var _a;
2535 if (reverseEase === void 0) {
2536 reverseEase = false;
2537 }
2538 _a = [to, from], from = _a[0], to = _a[1];
2539 playhead = vectorScrubber({ from: from, to: to, ease: ease, reverseEase: reverseEase }).start(update);
2540 };
2541 var isTweenComplete = function () {
2542 var isComplete = isActive && elapsed > duration + repeatDelay;
2543 if (!isComplete) return false;
2544 if (isComplete && !loop && !flip && !yoyo) return true;
2545 var overtime = elapsed - duration;
2546 elapsed = overtime - repeatDelay;
2547 if (loop && loopCount < loop) {
2548 loopCount++;
2549 return false;
2550 } else if (flip && flipCount < flip) {
2551 flipCount++;
2552 reverseAnimation();
2553 return false;
2554 } else if (yoyo && yoyoCount < yoyo) {
2555 yoyoCount++;
2556 reverseAnimation(yoyoCount % 2 !== 0);
2557 return false;
2558 }
2559 return true;
2560 };
2561 var updateTween = function () {
2562 currentProgress = clampProgress$2(progress(0, duration, elapsed));
2563 playhead.seek(currentProgress);
2564 };
2565 var startTimer = function () {
2566 isActive = true;
2567 process = sync.update(function (_a) {
2568 var delta = _a.delta;
2569 elapsed += delta;
2570 updateTween();
2571 if (isTweenComplete()) {
2572 cancelSync.update(process);
2573 complete && sync.update(complete, false, true);
2574 }
2575 }, true);
2576 };
2577 var stopTimer = function () {
2578 isActive = false;
2579 if (process) cancelSync.update(process);
2580 };
2581 startTimer();
2582 return {
2583 isActive: function () {
2584 return isActive;
2585 },
2586 getElapsed: function () {
2587 return clamp$1$1(0, duration, elapsed);
2588 },
2589 getProgress: function () {
2590 return currentProgress;
2591 },
2592 stop: function () {
2593 stopTimer();
2594 },
2595 pause: function () {
2596 stopTimer();
2597 return this;
2598 },
2599 resume: function () {
2600 if (!isActive) startTimer();
2601 return this;
2602 },
2603 seek: function (newProgress) {
2604 elapsed = mix(0, duration, newProgress);
2605 sync.update(updateTween, false, true);
2606 return this;
2607 },
2608 reverse: function () {
2609 reverseAnimation();
2610 return this;
2611 }
2612 };
2613 });
2614 };
2615
2616 var clampProgress$1$1 = /*#__PURE__*/clamp$1$1(0, 1);
2617 var defaultEasings = function (values, easing) {
2618 return values.map(function () {
2619 return easing || easeOut;
2620 }).splice(0, values.length - 1);
2621 };
2622 var defaultTimings = function (values) {
2623 var numValues = values.length;
2624 return values.map(function (value, i) {
2625 return i !== 0 ? i / (numValues - 1) : 0;
2626 });
2627 };
2628 var interpolateScrubbers = function (input, scrubbers, update) {
2629 var rangeLength = input.length;
2630 var finalInputIndex = rangeLength - 1;
2631 var finalScrubberIndex = finalInputIndex - 1;
2632 var subs = scrubbers.map(function (scrub) {
2633 return scrub.start(update);
2634 });
2635 return function (v) {
2636 if (v <= input[0]) {
2637 subs[0].seek(0);
2638 }
2639 if (v >= input[finalInputIndex]) {
2640 subs[finalScrubberIndex].seek(1);
2641 }
2642 var i = 1;
2643 for (; i < rangeLength; i++) {
2644 if (input[i] > v || i === finalInputIndex) break;
2645 }
2646 var progressInRange = progress(input[i - 1], input[i], v);
2647 subs[i - 1].seek(clampProgress$1$1(progressInRange));
2648 };
2649 };
2650 var keyframes = function (_a) {
2651 var easings = _a.easings,
2652 _b = _a.ease,
2653 ease = _b === void 0 ? linear : _b,
2654 times = _a.times,
2655 values = _a.values,
2656 tweenProps = __rest(_a, ["easings", "ease", "times", "values"]);
2657 easings = Array.isArray(easings) ? easings : defaultEasings(values, easings);
2658 times = times || defaultTimings(values);
2659 var scrubbers = easings.map(function (easing, i) {
2660 return vectorScrubber({
2661 from: values[i],
2662 to: values[i + 1],
2663 ease: easing
2664 });
2665 });
2666 return tween(__assign({}, tweenProps, { ease: ease })).applyMiddleware(function (update) {
2667 return interpolateScrubbers(times, scrubbers, update);
2668 });
2669 };
2670
2671 var listen = function (element, events, options) {
2672 return action(function (_a) {
2673 var update = _a.update;
2674 var eventNames = events.split(' ').map(function (eventName) {
2675 element.addEventListener(eventName, update, options);
2676 return eventName;
2677 });
2678 return {
2679 stop: function () {
2680 return eventNames.forEach(function (eventName) {
2681 return element.removeEventListener(eventName, update, options);
2682 });
2683 }
2684 };
2685 });
2686 };
2687
2688 var defaultPointerPos = function () {
2689 return {
2690 clientX: 0,
2691 clientY: 0,
2692 pageX: 0,
2693 pageY: 0,
2694 x: 0,
2695 y: 0
2696 };
2697 };
2698 var eventToPoint = function (e, point) {
2699 if (point === void 0) {
2700 point = defaultPointerPos();
2701 }
2702 point.clientX = point.x = e.clientX;
2703 point.clientY = point.y = e.clientY;
2704 point.pageX = e.pageX;
2705 point.pageY = e.pageY;
2706 return point;
2707 };
2708
2709 var points = [/*#__PURE__*/defaultPointerPos()];
2710 if (typeof document !== 'undefined') {
2711 var updatePointsLocation = function (_a) {
2712 var touches = _a.touches;
2713 var numTouches = touches.length;
2714 points.length = 0;
2715 for (var i = 0; i < numTouches; i++) {
2716 var thisTouch = touches[i];
2717 points.push(eventToPoint(thisTouch));
2718 }
2719 };
2720 listen(document, 'touchstart touchmove', {
2721 passive: true,
2722 capture: true
2723 }).start(updatePointsLocation);
2724 }
2725
2726 var point = /*#__PURE__*/defaultPointerPos();
2727 if (typeof document !== 'undefined') {
2728 var updatePointLocation = function (e) {
2729 eventToPoint(e, point);
2730 };
2731 listen(document, 'mousedown mousemove', true).start(updatePointLocation);
2732 }
2733
2734 var delay = function (timeToDelay) {
2735 return action(function (_a) {
2736 var complete = _a.complete;
2737 var timeout = setTimeout(complete, timeToDelay);
2738 return {
2739 stop: function () {
2740 return clearTimeout(timeout);
2741 }
2742 };
2743 });
2744 };
2745
2746 var isKeyframesTarget = function (v) {
2747 return Array.isArray(v);
2748 };
2749
2750 var underDampedSpring = function () { return ({
2751 type: "spring",
2752 stiffness: 500,
2753 damping: 25,
2754 restDelta: 0.5,
2755 restSpeed: 10,
2756 }); };
2757 var overDampedSpring = function (to) { return ({
2758 type: "spring",
2759 stiffness: 700,
2760 damping: to === 0 ? 100 : 35,
2761 }); };
2762 var linearTween = function () { return ({
2763 ease: "linear",
2764 duration: 0.3,
2765 }); };
2766 var keyframes$1 = function (values) { return ({
2767 type: "keyframes",
2768 duration: 0.8,
2769 values: values,
2770 }); };
2771 var defaultTransitions = {
2772 x: underDampedSpring,
2773 y: underDampedSpring,
2774 z: underDampedSpring,
2775 rotate: underDampedSpring,
2776 rotateX: underDampedSpring,
2777 rotateY: underDampedSpring,
2778 rotateZ: underDampedSpring,
2779 scaleX: overDampedSpring,
2780 scaleY: overDampedSpring,
2781 scale: overDampedSpring,
2782 opacity: linearTween,
2783 backgroundColor: linearTween,
2784 color: linearTween,
2785 default: overDampedSpring,
2786 };
2787 var getDefaultTransition = function (valueKey, to) {
2788 var transitionFactory;
2789 if (isKeyframesTarget(to)) {
2790 transitionFactory = keyframes$1;
2791 }
2792 else {
2793 transitionFactory =
2794 defaultTransitions[valueKey] || defaultTransitions.default;
2795 }
2796 return __assign({ to: to }, transitionFactory(to));
2797 };
2798
2799 /**
2800 * A Popmotion action that accepts a single `to` prop. When it starts, it immediately
2801 * updates with `to` and then completes. By using this we can compose instant transitions
2802 * in with the same logic that applies `delay` or returns a `Promise` etc.
2803 *
2804 * Accepting `duration` is a little bit of a hack that simply defers the completetion of
2805 * the animation until after the duration finishes. This is for situations when you're **only**
2806 * animating non-animatable values and then setting something on `transitionEnd`. Really
2807 * you want this to fire after the "animation" finishes, rather than instantly.
2808 *
2809 * ```
2810 * animate={{
2811 * display: 'block',
2812 * transitionEnd: { display: 'none' }
2813 * }}
2814 * ```
2815 */
2816 var just = function (_a) {
2817 var to = _a.to, duration = _a.duration;
2818 return action(function (_a) {
2819 var update = _a.update, complete = _a.complete;
2820 update(to);
2821 duration ? delay(duration).start({ complete: complete }) : complete();
2822 });
2823 };
2824
2825 var easingDefinitionToFunction = function (definition) {
2826 if (Array.isArray(definition)) {
2827 // If cubic bezier definition, create bezier curve
2828 invariant(definition.length === 4, "Cubic bezier arrays must contain four numerical values.");
2829 var x1 = definition[0], y1 = definition[1], x2 = definition[2], y2 = definition[3];
2830 return cubicBezier(x1, y1, x2, y2);
2831 }
2832 else if (typeof definition === "string") {
2833 // Else lookup from table
2834 invariant(easingLookup[definition] !== undefined, "Invalid easing type '" + definition + "'");
2835 return easingLookup[definition];
2836 }
2837 return definition;
2838 };
2839 var isEasingArray = function (ease) {
2840 return Array.isArray(ease) && typeof ease[0] !== "number";
2841 };
2842
2843 var isDurationAnimation = function (v) {
2844 return v.hasOwnProperty("duration") || v.hasOwnProperty("repeatDelay");
2845 };
2846
2847 /**
2848 * Check if a value is animatable. Examples:
2849 *
2850 * ✅: 100, "100px", "#fff"
2851 * ❌: "block", "url(2.jpg)"
2852 * @param value
2853 *
2854 * @internal
2855 */
2856 var isAnimatable = function (key, value) {
2857 // If the list of keys tat might be non-animatable grows, replace with Set
2858 if (key === "zIndex")
2859 return false;
2860 // If it's a number or a keyframes array, we can animate it. We might at some point
2861 // need to do a deep isAnimatable check of keyframes, or let Popmotion handle this,
2862 // but for now lets leave it like this for performance reasons
2863 if (typeof value === "number" || Array.isArray(value))
2864 return true;
2865 if (typeof value === "string" && // It's animatable if we have a string
2866 complex.test(value) && // And it contains numbers and/or colors
2867 !value.startsWith("url(") // Unless it starts with "url("
2868 ) {
2869 return true;
2870 }
2871 return false;
2872 };
2873
2874 /**
2875 * Converts seconds to milliseconds
2876 *
2877 * @param seconds - Time in seconds.
2878 * @return milliseconds - Converted time in milliseconds.
2879 */
2880 var secondsToMilliseconds = function (seconds) { return seconds * 1000; };
2881
2882 var transitions = { tween: tween, spring: vectorSpring, keyframes: keyframes, inertia: index, just: just };
2883 var transitionOptionParser = {
2884 tween: function (opts) {
2885 if (opts.ease) {
2886 var ease = isEasingArray(opts.ease) ? opts.ease[0] : opts.ease;
2887 opts.ease = easingDefinitionToFunction(ease);
2888 }
2889 return opts;
2890 },
2891 keyframes: function (_a) {
2892 var from = _a.from, to = _a.to, velocity = _a.velocity, opts = __rest(_a, ["from", "to", "velocity"]);
2893 if (opts.values && opts.values[0] === null) {
2894 var values = __spreadArrays(opts.values);
2895 values[0] = from;
2896 opts.values = values;
2897 }
2898 if (opts.ease) {
2899 opts.easings = isEasingArray(opts.ease)
2900 ? opts.ease.map(easingDefinitionToFunction)
2901 : easingDefinitionToFunction(opts.ease);
2902 }
2903 opts.ease = linear;
2904 return opts;
2905 },
2906 };
2907 var isTransitionDefined = function (_a) {
2908 var when = _a.when, delay = _a.delay, delayChildren = _a.delayChildren, staggerChildren = _a.staggerChildren, staggerDirection = _a.staggerDirection, transition = __rest(_a, ["when", "delay", "delayChildren", "staggerChildren", "staggerDirection"]);
2909 return Object.keys(transition).length;
2910 };
2911 var getTransitionDefinition = function (key, to, transitionDefinition) {
2912 var delay = transitionDefinition ? transitionDefinition.delay : 0;
2913 // If no object, return default transition
2914 // A better way to handle this would be to deconstruct out all the shared Orchestration props
2915 // and see if there's any props remaining
2916 if (transitionDefinition === undefined ||
2917 !isTransitionDefined(transitionDefinition)) {
2918 return __assign({ delay: delay }, getDefaultTransition(key, to));
2919 }
2920 var valueTransitionDefinition = transitionDefinition[key] ||
2921 transitionDefinition.default ||
2922 transitionDefinition;
2923 if (valueTransitionDefinition.type === false) {
2924 return {
2925 delay: valueTransitionDefinition.hasOwnProperty("delay")
2926 ? valueTransitionDefinition.delay
2927 : delay,
2928 to: isKeyframesTarget(to)
2929 ? to[to.length - 1]
2930 : to,
2931 type: "just",
2932 };
2933 }
2934 else if (isKeyframesTarget(to)) {
2935 return __assign(__assign({ values: to, duration: 0.8, delay: delay, ease: "linear" }, valueTransitionDefinition), {
2936 // This animation must be keyframes if we're animating through an array
2937 type: "keyframes" });
2938 }
2939 else {
2940 return __assign({ type: "tween", to: to,
2941 delay: delay }, valueTransitionDefinition);
2942 }
2943 };
2944 var preprocessOptions = function (type, opts) {
2945 return transitionOptionParser[type]
2946 ? transitionOptionParser[type](opts)
2947 : opts;
2948 };
2949 var getAnimation = function (key, value, target, transition) {
2950 var origin = value.get();
2951 var isOriginAnimatable = isAnimatable(key, origin);
2952 var isTargetAnimatable = isAnimatable(key, target);
2953 // TODO we could probably improve this check to ensure both values are of the same type -
2954 // for instance 100 to #fff. This might live better in Popmotion.
2955 warning(isOriginAnimatable === isTargetAnimatable, "You are trying to animate " + key + " from \"" + origin + "\" to \"" + target + "\". " + origin + " is not an animatable value - to enable this animation set " + origin + " to a value animatable to " + target + " via the `style` property.");
2956 // Parse the `transition` prop and return options for the Popmotion animation
2957 var _a = getTransitionDefinition(key, target, transition), _b = _a.type, type = _b === void 0 ? "tween" : _b, transitionDefinition = __rest(_a, ["type"]);
2958 // If this is an animatable pair of values, return an animation, otherwise use `just`
2959 var actionFactory = isOriginAnimatable && isTargetAnimatable
2960 ? transitions[type]
2961 : just;
2962 var opts = preprocessOptions(type, __assign({ from: origin, velocity: value.getVelocity() }, transitionDefinition));
2963 // Convert duration from Framer Motion's seconds into Popmotion's milliseconds
2964 if (isDurationAnimation(opts)) {
2965 if (opts.duration) {
2966 opts.duration = secondsToMilliseconds(opts.duration);
2967 }
2968 if (opts.repeatDelay) {
2969 opts.repeatDelay = secondsToMilliseconds(opts.repeatDelay);
2970 }
2971 }
2972 return [actionFactory, opts];
2973 };
2974 /**
2975 * Start animation on a value. This function completely encapsulates Popmotion-specific logic.
2976 *
2977 * @internal
2978 */
2979 function startAnimation(key, value, target, _a) {
2980 if (_a === void 0) { _a = {}; }
2981 var _b = _a.delay, delay$1 = _b === void 0 ? 0 : _b, transition = __rest(_a, ["delay"]);
2982 return value.start(function (complete) {
2983 var activeAnimation;
2984 var _a = getAnimation(key, value, target, transition), animationFactory = _a[0], _b = _a[1], valueDelay = _b.delay, options = __rest(_b, ["delay"]);
2985 if (valueDelay !== undefined) {
2986 delay$1 = valueDelay;
2987 }
2988 var animate = function () {
2989 var animation = animationFactory(options);
2990 // Bind animation opts to animation
2991 activeAnimation = animation.start({
2992 update: function (v) { return value.set(v); },
2993 complete: complete,
2994 });
2995 };
2996 // If we're delaying this animation, only resolve it **after** the delay to
2997 // ensure the value's resolve velocity is up-to-date.
2998 if (delay$1) {
2999 activeAnimation = delay(secondsToMilliseconds(delay$1)).start({
3000 complete: animate,
3001 });
3002 }
3003 else {
3004 animate();
3005 }
3006 return function () {
3007 if (activeAnimation)
3008 activeAnimation.stop();
3009 };
3010 });
3011 }
3012
3013 /**
3014 * Measure and return the element bounding box.
3015 *
3016 * We convert the box into an AxisBox2D to make it easier to work with each axis
3017 * individually and programmatically.
3018 *
3019 * This function optionally accepts a transformPagePoint function which allows us to compensate
3020 * for, for instance, measuring the element within a scaled plane like a Framer devivce preview component.
3021 */
3022 function getBoundingBox(element, transformPagePoint) {
3023 var box = element.getBoundingClientRect();
3024 return convertBoundingBoxToAxisBox(transformBoundingBox(box, transformPagePoint));
3025 }
3026
3027 /**
3028 * A VisualElement for HTMLElements
3029 */
3030 var HTMLVisualElement = /** @class */ (function (_super) {
3031 __extends(HTMLVisualElement, _super);
3032 function HTMLVisualElement() {
3033 var _this = _super !== null && _super.apply(this, arguments) || this;
3034 /**
3035 *
3036 */
3037 _this.defaultConfig = {
3038 enableHardwareAcceleration: true,
3039 allowTransformNone: true,
3040 };
3041 /**
3042 * A mutable record of styles we want to apply directly to the rendered Element
3043 * every frame. We use a mutable data structure to reduce GC during animations.
3044 */
3045 _this.style = {};
3046 /**
3047 * A record of styles we only want to apply via React. This gets set in useMotionValues
3048 * and applied in the render function. I'd prefer this to live somewhere else to decouple
3049 * VisualElement from React but works for now.
3050 */
3051 _this.reactStyle = {};
3052 /**
3053 * A mutable record of CSS variables we want to apply directly to the rendered Element
3054 * every frame. We use a mutable data structure to reduce GC during animations.
3055 */
3056 _this.vars = {};
3057 /**
3058 * A mutable record of transforms we want to apply directly to the rendered Element
3059 * every frame. We use a mutable data structure to reduce GC during animations.
3060 */
3061 _this.transform = {};
3062 /**
3063 * A mutable record of transform origins we want to apply directly to the rendered Element
3064 * every frame. We use a mutable data structure to reduce GC during animations.
3065 */
3066 _this.transformOrigin = {};
3067 /**
3068 * A mutable record of transform keys we want to apply to the rendered Element. We order
3069 * this to order transforms in the desired order. We use a mutable data structure to reduce GC during animations.
3070 */
3071 _this.transformKeys = [];
3072 _this.config = _this.defaultConfig;
3073 /**
3074 * ========================================
3075 * Layout
3076 * ========================================
3077 */
3078 _this.isLayoutProjectionEnabled = false;
3079 /**
3080 * A set of layout update event handlers. These are only called once all layouts have been read,
3081 * making it safe to perform DOM write operations.
3082 */
3083 _this.layoutUpdateListeners = new Set();
3084 /**
3085 * Keep track of whether the viewport box has been updated since the last render.
3086 * If it has, we want to fire the onViewportBoxUpdate listener.
3087 */
3088 _this.hasViewportBoxUpdated = false;
3089 /**
3090 * The visual target we want to project our component into on a given frame
3091 * before applying transforms defined in `animate` or `style`.
3092 *
3093 * This is considered mutable to avoid object creation on each frame.
3094 */
3095 _this.targetBoxFinal = axisBox();
3096 /**
3097 * The overall scale of the local coordinate system as transformed by all parents
3098 * of this component. We use this for scale correction on our calculated layouts
3099 * and scale-affected values like `boxShadow`.
3100 *
3101 * This is considered mutable to avoid object creation on each frame.
3102 */
3103 _this.treeScale = { x: 1, y: 1 };
3104 /**
3105 * The delta between the boxCorrected and the desired
3106 * targetBox (before user-set transforms are applied). The calculated output will be
3107 * handed to the renderer and used as part of the style correction calculations, for
3108 * instance calculating how to display the desired border-radius correctly.
3109 *
3110 * This is considered mutable to avoid object creation on each frame.
3111 */
3112 _this.delta = delta();
3113 /**
3114 * The delta between the boxCorrected and the desired targetBoxFinal. The calculated
3115 * output will be handed to the renderer and used to project the boxCorrected into
3116 * the targetBoxFinal.
3117 *
3118 * This is considered mutable to avoid object creation on each frame.
3119 */
3120 _this.deltaFinal = delta();
3121 /**
3122 *
3123 */
3124 _this.stopLayoutAxisAnimation = {
3125 x: function () { },
3126 y: function () { },
3127 };
3128 _this.isTargetBoxLocked = false;
3129 /**
3130 *
3131 */
3132 _this.axisProgress = {
3133 x: motionValue(0),
3134 y: motionValue(0),
3135 };
3136 _this.updateLayoutDelta = function () {
3137 _this.isLayoutProjectionEnabled && _this.box && _this.updateLayoutDeltas();
3138 /**
3139 * Ensure all children layouts are also updated.
3140 *
3141 * This uses a pre-bound function executor rather than a lamda to avoid creating a new function
3142 * multiple times per frame (source of mid-animation GC)
3143 */
3144 _this.children.forEach(fireUpdateLayoutDelta);
3145 };
3146 return _this;
3147 }
3148 /**
3149 * When a value is removed, we want to make sure it's removed from all rendered data structures.
3150 */
3151 HTMLVisualElement.prototype.removeValue = function (key) {
3152 _super.prototype.removeValue.call(this, key);
3153 delete this.vars[key];
3154 delete this.style[key];
3155 };
3156 /**
3157 * Empty the mutable data structures by re-creating them. We can do this every React render
3158 * as the comparative workload to the rest of the render is very low and this is also when
3159 * we want to reflect values that might have been removed by the render.
3160 */
3161 HTMLVisualElement.prototype.clean = function () {
3162 this.style = {};
3163 this.vars = {};
3164 this.transform = {};
3165 };
3166 HTMLVisualElement.prototype.updateConfig = function (config) {
3167 if (config === void 0) { config = {}; }
3168 this.config = __assign(__assign({}, this.defaultConfig), config);
3169 };
3170 /**
3171 * Read a value directly from the HTMLElement style.
3172 */
3173 HTMLVisualElement.prototype.read = function (key) {
3174 return this.getComputedStyle()[key] || 0;
3175 };
3176 /**
3177 * Read a value directly from the HTMLElement in case it's not defined by a Motion
3178 * prop. If it's a transform, we just return a pre-defined default value as reading these
3179 * out of a matrix is either error-prone or can incur a big payload for little benefit.
3180 */
3181 HTMLVisualElement.prototype.readNativeValue = function (key) {
3182 if (isTransformProp(key)) {
3183 var defaultValueType = getDefaultValueType(key);
3184 return defaultValueType ? defaultValueType.default || 0 : 0;
3185 }
3186 else {
3187 return this.read(key);
3188 }
3189 };
3190 HTMLVisualElement.prototype.enableLayoutProjection = function () {
3191 this.isLayoutProjectionEnabled = true;
3192 };
3193 HTMLVisualElement.prototype.hide = function () {
3194 if (this.isVisible === false)
3195 return;
3196 this.isVisible = false;
3197 this.scheduleRender();
3198 };
3199 HTMLVisualElement.prototype.show = function () {
3200 if (this.isVisible === true)
3201 return;
3202 this.isVisible = true;
3203 this.scheduleRender();
3204 };
3205 /**
3206 * Register an event listener to fire when the layout is updated. We might want to expose support
3207 * for this via a `motion` prop.
3208 */
3209 HTMLVisualElement.prototype.onLayoutUpdate = function (callback) {
3210 var _this = this;
3211 this.layoutUpdateListeners.add(callback);
3212 return function () { return _this.layoutUpdateListeners.delete(callback); };
3213 };
3214 /**
3215 * To be called when all layouts are successfully updated. In turn we can notify layoutUpdate
3216 * subscribers.
3217 */
3218 HTMLVisualElement.prototype.layoutReady = function (config) {
3219 var _this = this;
3220 this.layoutUpdateListeners.forEach(function (listener) {
3221 listener(_this.box, _this.prevViewportBox || _this.box, config);
3222 });
3223 };
3224 /**
3225 * Measure and return the Element's bounding box. We convert it to a AxisBox2D
3226 * structure to make it easier to work on each individual axis generically.
3227 */
3228 HTMLVisualElement.prototype.getBoundingBox = function () {
3229 var transformPagePoint = this.config.transformPagePoint;
3230 return getBoundingBox(this.element, transformPagePoint);
3231 };
3232 HTMLVisualElement.prototype.getBoundingBoxWithoutTransforms = function () {
3233 var bbox = this.getBoundingBox();
3234 removeBoxTransforms(bbox, this.latest);
3235 return bbox;
3236 };
3237 /**
3238 * Return the computed style after a render.
3239 */
3240 HTMLVisualElement.prototype.getComputedStyle = function () {
3241 return window.getComputedStyle(this.element);
3242 };
3243 /**
3244 *
3245 */
3246 HTMLVisualElement.prototype.snapshotBoundingBox = function () {
3247 this.prevViewportBox = this.getBoundingBoxWithoutTransforms();
3248 /**
3249 * Update targetBox to match the prevViewportBox. This is just to ensure
3250 * that targetBox is affected by scroll in the same way as the measured box
3251 */
3252 var _a = this.axisProgress, x = _a.x, y = _a.y;
3253 if (!this.isTargetBoxLocked && !x.isAnimating() && !y.isAnimating()) {
3254 this.targetBox = copyAxisBox(this.prevViewportBox);
3255 }
3256 };
3257 HTMLVisualElement.prototype.measureLayout = function () {
3258 this.box = this.getBoundingBox();
3259 this.boxCorrected = copyAxisBox(this.box);
3260 if (!this.targetBox)
3261 this.targetBox = copyAxisBox(this.box);
3262 };
3263 /**
3264 * Ensure the targetBox reflects the latest visual box on screen
3265 */
3266 HTMLVisualElement.prototype.refreshTargetBox = function () {
3267 this.targetBox = this.getBoundingBoxWithoutTransforms();
3268 };
3269 HTMLVisualElement.prototype.lockTargetBox = function () {
3270 this.isTargetBoxLocked = true;
3271 };
3272 HTMLVisualElement.prototype.unlockTargetBox = function () {
3273 this.stopLayoutAnimation();
3274 this.isTargetBoxLocked = false;
3275 };
3276 /**
3277 * Reset the transform on the current Element. This is called as part
3278 * of a batched process across the entire layout tree. To remove this write
3279 * cycle it'd be interesting to see if it's possible to "undo" all the current
3280 * layout transforms up the tree in the same way this.getBoundingBoxWithoutTransforms
3281 * works
3282 */
3283 HTMLVisualElement.prototype.resetTransform = function () {
3284 var transformTemplate = this.config.transformTemplate;
3285 this.element.style.transform = transformTemplate
3286 ? transformTemplate({}, "")
3287 : "none";
3288 // Ensure that whatever happens next, we restore our transform
3289 this.scheduleRender();
3290 };
3291 /**
3292 * Set new min/max boundaries to project an axis into
3293 */
3294 HTMLVisualElement.prototype.setAxisTarget = function (axis, min, max) {
3295 var targetAxis = this.targetBox[axis];
3296 targetAxis.min = min;
3297 targetAxis.max = max;
3298 // Flag that we want to fire the onViewportBoxUpdate event handler
3299 this.hasViewportBoxUpdated = true;
3300 this.rootParent.scheduleUpdateLayoutDelta();
3301 };
3302 /**
3303 *
3304 */
3305 HTMLVisualElement.prototype.startLayoutAxisAnimation = function (axis, transition) {
3306 var _this = this;
3307 var progress = this.axisProgress[axis];
3308 var _a = this.targetBox[axis], min = _a.min, max = _a.max;
3309 var length = max - min;
3310 progress.clearListeners();
3311 progress.set(min);
3312 progress.set(min); // Set twice to hard-reset velocity
3313 progress.onChange(function (v) { return _this.setAxisTarget(axis, v, v + length); });
3314 return startAnimation(axis, progress, 0, transition);
3315 };
3316 HTMLVisualElement.prototype.stopLayoutAnimation = function () {
3317 var _this = this;
3318 eachAxis(function (axis) { return _this.axisProgress[axis].stop(); });
3319 };
3320 /**
3321 * Update the layout deltas to reflect the relative positions of the layout
3322 * and the desired target box
3323 */
3324 HTMLVisualElement.prototype.updateLayoutDeltas = function () {
3325 var _a, _b;
3326 /**
3327 * Reset the corrected box with the latest values from box, as we're then going
3328 * to perform mutative operations on it.
3329 */
3330 resetBox(this.boxCorrected, this.box);
3331 /**
3332 * If this component has a parent, update this treeScale by incorporating the parent's
3333 * delta into its treeScale.
3334 */
3335 if (this.parent) {
3336 updateTreeScale(this.treeScale, this.parent.treeScale, this.parent.delta);
3337 }
3338 /**
3339 * Apply all the parent deltas to this box to produce the corrected box. This
3340 * is the layout box, as it will appear on screen as a result of the transforms of its parents.
3341 */
3342 applyTreeDeltas(this.boxCorrected, this.treePath);
3343 /**
3344 * Update the delta between the corrected box and the target box before user-set transforms were applied.
3345 * This will allow us to calculate the corrected borderRadius and boxShadow to compensate
3346 * for our layout reprojection, but still allow them to be scaled correctly by the user.
3347 * It might be that to simplify this we may want to accept that user-set scale is also corrected
3348 * and we wouldn't have to keep and calc both deltas, OR we could support a user setting
3349 * to allow people to choose whether these styles are corrected based on just the
3350 * layout reprojection or the final bounding box.
3351 */
3352 updateBoxDelta(this.delta, this.boxCorrected, this.targetBox);
3353 /**
3354 * If we have a listener for the viewport box, fire it.
3355 */
3356 this.hasViewportBoxUpdated && ((_b = (_a = this.config).onViewportBoxUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, this.targetBox, this.delta));
3357 this.hasViewportBoxUpdated = false;
3358 /**
3359 * Ensure this element renders on the next frame if the projection transform has changed.
3360 */
3361 var deltaTransform = createDeltaTransform(this.delta, this.treeScale);
3362 deltaTransform !== this.deltaTransform && this.scheduleRender();
3363 this.deltaTransform = deltaTransform;
3364 };
3365 HTMLVisualElement.prototype.updateTransformDeltas = function () {
3366 if (!this.isLayoutProjectionEnabled || !this.box)
3367 return;
3368 /**
3369 * Apply the latest user-set transforms to the targetBox to produce the targetBoxFinal.
3370 * This is the final box that we will then project into by calculating a transform delta and
3371 * applying it to the corrected box.
3372 */
3373 applyBoxTransforms(this.targetBoxFinal, this.targetBox, this.latest);
3374 /**
3375 * Update the delta between the corrected box and the final target box, after
3376 * user-set transforms are applied to it. This will be used by the renderer to
3377 * create a transform style that will reproject the element from its actual layout
3378 * into the desired bounding box.
3379 */
3380 updateBoxDelta(this.deltaFinal, this.boxCorrected, this.targetBoxFinal);
3381 };
3382 /**
3383 * ========================================
3384 * Build & render
3385 * ========================================
3386 */
3387 /**
3388 * Build a style prop using the latest resolved MotionValues
3389 */
3390 HTMLVisualElement.prototype.build = function () {
3391 this.updateTransformDeltas();
3392 if (this.isVisible !== undefined) {
3393 this.style.visibility = this.isVisible ? "visible" : "hidden";
3394 }
3395 buildHTMLStyles(this.latest, this.style, this.vars, this.transform, this.transformOrigin, this.transformKeys, this.config, this.isLayoutProjectionEnabled && !!this.box, this.delta, this.deltaFinal, this.treeScale, this.targetBoxFinal);
3396 };
3397 /**
3398 * Render the Element by rebuilding and applying the latest styles and vars.
3399 */
3400 HTMLVisualElement.prototype.render = function () {
3401 // Rebuild the latest animated values into style and vars caches.
3402 this.build();
3403 // Directly assign style into the Element's style prop. In tests Object.assign is the
3404 // fastest way to assign styles.
3405 Object.assign(this.element.style, this.style);
3406 // Loop over any CSS variables and assign those.
3407 for (var key in this.vars) {
3408 this.element.style.setProperty(key, this.vars[key]);
3409 }
3410 };
3411 return HTMLVisualElement;
3412 }(VisualElement));
3413 /**
3414 * Pre-bound version of updateLayoutDelta so we're not creating a new function multiple
3415 * times per frame.
3416 */
3417 var fireUpdateLayoutDelta = function (child) {
3418 return child.updateLayoutDelta();
3419 };
3420
3421 /**
3422 * Creates a constant value over the lifecycle of a component.
3423 *
3424 * Even if `useMemo` is provided an empty array as its final argument, it doesn't offer
3425 * a guarantee that it won't re-run for performance reasons later on. By using `useConstant`
3426 * you can ensure that initialisers don't execute twice or more.
3427 */
3428 function useConstant(init) {
3429 var ref = React.useRef(null);
3430 if (ref.current === null) {
3431 ref.current = init();
3432 }
3433 return ref.current;
3434 }
3435
3436 function calcOrigin$1(origin, offset, size) {
3437 return typeof origin === "string"
3438 ? origin
3439 : px.transform(offset + size * origin);
3440 }
3441 /**
3442 * The SVG transform origin defaults are different to CSS and is less intuitive,
3443 * so we use the measured dimensions of the SVG to reconcile these.
3444 */
3445 function calcSVGTransformOrigin(dimensions, originX, originY) {
3446 var pxOriginX = calcOrigin$1(originX, dimensions.x, dimensions.width);
3447 var pxOriginY = calcOrigin$1(originY, dimensions.y, dimensions.height);
3448 return pxOriginX + " " + pxOriginY;
3449 }
3450
3451 // Convert a progress 0-1 to a pixels value based on the provided length
3452 var progressToPixels = function (progress, length) {
3453 return px.transform(progress * length);
3454 };
3455 var dashKeys = {
3456 offset: "stroke-dashoffset",
3457 array: "stroke-dasharray",
3458 };
3459 var camelKeys = {
3460 offset: "strokeDashoffset",
3461 array: "strokeDasharray",
3462 };
3463 /**
3464 * Build SVG path properties. Uses the path's measured length to convert
3465 * our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
3466 * and stroke-dasharray attributes.
3467 *
3468 * This function is mutative to reduce per-frame GC.
3469 */
3470 function buildSVGPath(attrs, totalLength, length, spacing, offset, useDashCase) {
3471 if (spacing === void 0) { spacing = 1; }
3472 if (offset === void 0) { offset = 0; }
3473 if (useDashCase === void 0) { useDashCase = true; }
3474 // We use dash case when setting attributes directly to the DOM node and camel case
3475 // when defining props on a React component.
3476 var keys = useDashCase ? dashKeys : camelKeys;
3477 // Build the dash offset
3478 attrs[keys.offset] = progressToPixels(-offset, totalLength);
3479 // Build the dash array
3480 var pathLength = progressToPixels(length, totalLength);
3481 var pathSpacing = progressToPixels(spacing, totalLength);
3482 attrs[keys.array] = pathLength + " " + pathSpacing;
3483 }
3484
3485 var unmeasured = { x: 0, y: 0, width: 0, height: 0 };
3486 /**
3487 * Build SVG visual attrbutes, like cx and style.transform
3488 */
3489 function buildSVGAttrs(_a, style, vars, attrs, transform, transformOrigin, transformKeys, config, dimensions, totalPathLength, isLayoutProjectionEnabled, delta, deltaFinal, treeScale, targetBox) {
3490 var attrX = _a.attrX, attrY = _a.attrY, originX = _a.originX, originY = _a.originY, pathLength = _a.pathLength, _b = _a.pathSpacing, pathSpacing = _b === void 0 ? 1 : _b, _c = _a.pathOffset, pathOffset = _c === void 0 ? 0 : _c,
3491 // This is object creation, which we try to avoid per-frame.
3492 latest = __rest(_a, ["attrX", "attrY", "originX", "originY", "pathLength", "pathSpacing", "pathOffset"]);
3493 /**
3494 * With SVG we treat all animated values as attributes rather than CSS, so we build into attrs
3495 */
3496 buildHTMLStyles(latest, attrs, vars, transform, transformOrigin, transformKeys, config, isLayoutProjectionEnabled, delta, deltaFinal, treeScale, targetBox);
3497 /**
3498 * However, we apply transforms as CSS transforms. So if we detect a transform we take it from attrs
3499 * and copy it into style.
3500 */
3501 if (attrs.transform) {
3502 style.transform = attrs.transform;
3503 delete attrs.transform;
3504 }
3505 // Parse transformOrigin
3506 if (originX !== undefined || originY !== undefined || style.transform) {
3507 style.transformOrigin = calcSVGTransformOrigin(dimensions || unmeasured, originX !== undefined ? originX : 0.5, originY !== undefined ? originY : 0.5);
3508 }
3509 // Treat x/y not as shortcuts but as actual attributes
3510 if (attrX !== undefined)
3511 attrs.x = attrX;
3512 if (attrY !== undefined)
3513 attrs.y = attrY;
3514 // Build SVG path if one has been measured
3515 if (totalPathLength !== undefined && pathLength !== undefined) {
3516 buildSVGPath(attrs, totalPathLength, pathLength, pathSpacing, pathOffset, false);
3517 }
3518 return attrs;
3519 }
3520
3521 /**
3522 * A set of attribute names that are always read/written as camel case.
3523 */
3524 var camelCaseAttributes = new Set([
3525 "baseFrequency",
3526 "diffuseConstant",
3527 "kernelMatrix",
3528 "kernelUnitLength",
3529 "keySplines",
3530 "keyTimes",
3531 "limitingConeAngle",
3532 "markerHeight",
3533 "markerWidth",
3534 "numOctaves",
3535 "targetX",
3536 "targetY",
3537 "surfaceScale",
3538 "specularConstant",
3539 "specularExponent",
3540 "stdDeviation",
3541 "tableValues",
3542 ]);
3543
3544 var CAMEL_CASE_PATTERN = /([a-z])([A-Z])/g;
3545 var REPLACE_TEMPLATE = "$1-$2";
3546 /**
3547 * Convert camelCase to dash-case properties.
3548 */
3549 var camelToDash = function (str) {
3550 return str.replace(CAMEL_CASE_PATTERN, REPLACE_TEMPLATE).toLowerCase();
3551 };
3552
3553 /**
3554 * A VisualElement for SVGElements. Inherits from and extends HTMLVisualElement as the two
3555 * share data structures.
3556 */
3557 var SVGVisualElement = /** @class */ (function (_super) {
3558 __extends(SVGVisualElement, _super);
3559 function SVGVisualElement() {
3560 var _this = _super !== null && _super.apply(this, arguments) || this;
3561 /**
3562 * A mutable record of attributes we want to apply directly to the rendered Element
3563 * every frame. We use a mutable data structure to reduce GC during animations.
3564 */
3565 _this.attrs = {};
3566 /**
3567 * We disable hardware acceleration for SVG transforms as they're not currently able to be accelerated.
3568 */
3569 _this.defaultConfig = {
3570 enableHardwareAcceleration: false,
3571 };
3572 /**
3573 * Without duplicating this call from HTMLVisualElement we end up with HTMLVisualElement.defaultConfig
3574 * being assigned to config
3575 */
3576 _this.config = _this.defaultConfig;
3577 return _this;
3578 }
3579 /**
3580 * Measure the SVG element on mount. This can affect page rendering so there might be a
3581 * better time to perform this - for instance dynamically only if there's a transform-origin dependent
3582 * transform being set (like rotate)
3583 */
3584 SVGVisualElement.prototype.mount = function (element) {
3585 _super.prototype.mount.call(this, element);
3586 this.measure();
3587 };
3588 /**
3589 * Update the SVG dimensions and path length
3590 */
3591 SVGVisualElement.prototype.measure = function () {
3592 try {
3593 this.dimensions =
3594 typeof this.element.getBBox ===
3595 "function"
3596 ? this.element.getBBox()
3597 : this.element.getBoundingClientRect();
3598 }
3599 catch (e) {
3600 // Most likely trying to measure an unrendered element under Firefox
3601 this.dimensions = { x: 0, y: 0, width: 0, height: 0 };
3602 }
3603 if (isPath(this.element)) {
3604 this.totalPathLength = this.element.getTotalLength();
3605 }
3606 };
3607 /**
3608 * Empty the mutable data structures in case attrs have been removed between renders.
3609 */
3610 SVGVisualElement.prototype.clean = function () {
3611 _super.prototype.clean.call(this);
3612 this.attrs = {};
3613 };
3614 /**
3615 * Read an attribute directly from the SVGElement
3616 */
3617 SVGVisualElement.prototype.read = function (key) {
3618 key = !camelCaseAttributes.has(key) ? camelToDash(key) : key;
3619 return this.element.getAttribute(key);
3620 };
3621 SVGVisualElement.prototype.build = function () {
3622 this.updateTransformDeltas();
3623 buildSVGAttrs(this.latest, this.style, this.vars, this.attrs, this.transform, this.transformOrigin, this.transformKeys, this.config, this.dimensions, this.totalPathLength, this.isLayoutProjectionEnabled && !!this.box, this.delta, this.deltaFinal, this.treeScale, this.targetBoxFinal);
3624 };
3625 SVGVisualElement.prototype.render = function () {
3626 // Update HTML styles and CSS variables
3627 _super.prototype.render.call(this);
3628 // Loop through attributes and apply them to the SVGElement
3629 for (var key in this.attrs) {
3630 this.element.setAttribute(camelToDash(key), this.attrs[key]);
3631 }
3632 };
3633 return SVGVisualElement;
3634 }(HTMLVisualElement));
3635 function isPath(element) {
3636 return element.tagName === "path";
3637 }
3638
3639 /**
3640 * @internal
3641 */
3642 /**
3643 * @internal
3644 */
3645 var svgElements = [
3646 "animate",
3647 "circle",
3648 "clipPath",
3649 "defs",
3650 "desc",
3651 "ellipse",
3652 "feBlend",
3653 "feColorMatrix",
3654 "feComponentTransfer",
3655 "feComposite",
3656 "feConvolveMatrix",
3657 "feDiffuseLighting",
3658 "feDisplacementMap",
3659 "feDistantLight",
3660 "feDropShadow",
3661 "feFlood",
3662 "feFuncA",
3663 "feFuncB",
3664 "feFuncG",
3665 "feFuncR",
3666 "feGaussianBlur",
3667 "feImage",
3668 "feMerge",
3669 "feMergeNode",
3670 "feMorphology",
3671 "feOffset",
3672 "fePointLight",
3673 "feSpecularLighting",
3674 "feSpotLight",
3675 "feTile",
3676 "feTurbulence",
3677 "filter",
3678 "foreignObject",
3679 "g",
3680 "image",
3681 "line",
3682 "linearGradient",
3683 "marker",
3684 "mask",
3685 "metadata",
3686 "path",
3687 "pattern",
3688 "polygon",
3689 "polyline",
3690 "radialGradient",
3691 "rect",
3692 "stop",
3693 "svg",
3694 "switch",
3695 "symbol",
3696 "text",
3697 "textPath",
3698 "tspan",
3699 "use",
3700 "view",
3701 ];
3702
3703 var svgTagNames = new Set(svgElements);
3704 /**
3705 * Determine whether this is a HTML or SVG component based on if the provided
3706 * Component is a string and a recognised SVG tag. A potentially better way to
3707 * do this would be to offer a `motion.customSVG` function and determine this
3708 * when we generate the `motion.circle` etc components.
3709 */
3710 function isSVGComponent(Component) {
3711 return typeof Component === "string" && svgTagNames.has(Component);
3712 }
3713
3714 /**
3715 * @public
3716 */
3717 var PresenceContext = React.createContext(null);
3718
3719 /**
3720 * When a component is the child of `AnimatePresence`, it can use `usePresence`
3721 * to access information about whether it's still present in the React tree.
3722 *
3723 * ```jsx
3724 * import { usePresence } from "framer-motion"
3725 *
3726 * export const Component = () => {
3727 * const [isPresent, safeToRemove] = usePresence()
3728 *
3729 * useEffect(() => {
3730 * !isPresent setTimeout(safeToRemove, 1000)
3731 * }, [isPresent])
3732 *
3733 * return <div />
3734 * }
3735 * ```
3736 *
3737 * If `isPresent` is `false`, it means that a component has been removed the tree, but
3738 * `AnimatePresence` won't really remove it until `safeToRemove` has been called.
3739 *
3740 * @public
3741 */
3742 function usePresence() {
3743 var context = React.useContext(PresenceContext);
3744 if (context === null)
3745 return [true, null];
3746 var isPresent = context.isPresent, onExitComplete = context.onExitComplete, register = context.register;
3747 // It's safe to call the following hooks conditionally (after an early return) because the context will always
3748 // either be null or non-null for the lifespan of the component.
3749 // Replace with useOpaqueId when released in React
3750 var id = useUniqueId();
3751 React.useEffect(function () { return register(id); }, []);
3752 var safeToRemove = function () { return onExitComplete === null || onExitComplete === void 0 ? void 0 : onExitComplete(id); };
3753 return !isPresent && onExitComplete ? [false, safeToRemove] : [true];
3754 }
3755 /**
3756 * @public
3757 */
3758 function useIsPresent() {
3759 var context = React.useContext(PresenceContext);
3760 return context === null ? true : context.isPresent;
3761 }
3762 var counter = 0;
3763 var incrementId = function () { return counter++; };
3764 var useUniqueId = function () { return useConstant(incrementId); };
3765
3766 /**
3767 * DOM-flavoured variation of the useVisualElement hook. Used to create either a HTMLVisualElement
3768 * or SVGVisualElement for the component.
3769 */
3770 var useDomVisualElement = function (Component, props, parent, isStatic, ref) {
3771 var visualElement = useConstant(function () {
3772 var DOMVisualElement = isSVGComponent(Component)
3773 ? SVGVisualElement
3774 : HTMLVisualElement;
3775 return new DOMVisualElement(parent, ref);
3776 });
3777 visualElement.updateConfig(__assign({ enableHardwareAcceleration: !isStatic }, props));
3778 visualElement.layoutId = props.layoutId;
3779 var isPresent = useIsPresent();
3780 visualElement.isPresent =
3781 props.isPresent !== undefined ? props.isPresent : isPresent;
3782 return visualElement;
3783 };
3784
3785 /**
3786 * A list of all valid MotionProps.
3787 *
3788 * @internalremarks
3789 * This doesn't throw if a `MotionProp` name is missing - it should.
3790 */
3791 var validMotionProps = new Set([
3792 "initial",
3793 "animate",
3794 "exit",
3795 "style",
3796 "variants",
3797 "transition",
3798 "transformTemplate",
3799 "transformValues",
3800 "custom",
3801 "inherit",
3802 "static",
3803 "layout",
3804 "layoutId",
3805 "onLayoutAnimationComplete",
3806 "onViewportBoxUpdate",
3807 "onAnimationStart",
3808 "onAnimationComplete",
3809 "onUpdate",
3810 "onDragStart",
3811 "onDrag",
3812 "onDragEnd",
3813 "onMeasureDragConstraints",
3814 "onDirectionLock",
3815 "onDragTransitionEnd",
3816 "drag",
3817 "dragControls",
3818 "dragListener",
3819 "dragConstraints",
3820 "dragDirectionLock",
3821 "dragElastic",
3822 "dragMomentum",
3823 "dragPropagation",
3824 "dragTransition",
3825 "onPan",
3826 "onPanStart",
3827 "onPanEnd",
3828 "onPanSessionStart",
3829 "onTap",
3830 "onTapStart",
3831 "onTapCancel",
3832 "whileHover",
3833 "whileTap",
3834 "onHoverEnd",
3835 "onHoverStart",
3836 ]);
3837 /**
3838 * Check whether a prop name is a valid `MotionProp` key.
3839 *
3840 * @param key - Name of the property to check
3841 * @returns `true` is key is a valid `MotionProp`.
3842 *
3843 * @public
3844 */
3845 function isValidMotionProp(key) {
3846 return validMotionProps.has(key);
3847 }
3848
3849 var isPropValid = function (key) { return !isValidMotionProp(key); };
3850 /**
3851 * Emotion and Styled Components both allow users to pass through arbitrary props to their components
3852 * to dynamically generate CSS. They both use the `@emotion/is-prop-valid` package to determine which
3853 * of these should be passed to the underlying DOM node.
3854 *
3855 * However, when styling a Motion component `styled(motion.div)`, both packages pass through *all* props
3856 * as it's seen as an arbitrary component rather than a DOM node. Motion only allows arbitrary props
3857 * passed through the `custom` prop so it doesn't *need* the payload or computational overhead of
3858 * `@emotion/is-prop-valid`, however to fix this problem we need to use it.
3859 *
3860 * By making it an optionalDependency we can offer this functionality only in the situations where it's
3861 * actually required.
3862 */
3863 try {
3864 var emotionIsPropValid_1 = require("@emotion/is-prop-valid").default;
3865 isPropValid = function (key) {
3866 // Handle events explicitly as Emotion validates them all as true
3867 if (key.startsWith("on")) {
3868 return !isValidMotionProp(key);
3869 }
3870 else {
3871 return emotionIsPropValid_1(key);
3872 }
3873 };
3874 }
3875 catch (_a) {
3876 // We don't need to actually do anything here - the fallback is the existing `isPropValid`.
3877 }
3878 function filterProps(props) {
3879 var domProps = {};
3880 for (var key in props) {
3881 if (isPropValid(key))
3882 domProps[key] = props[key];
3883 }
3884 return domProps;
3885 }
3886
3887 function buildHTMLProps(visualElement, _a) {
3888 var drag = _a.drag;
3889 // The `any` isn't ideal but it is the type of createElement props argument
3890 var htmlProps = {
3891 style: __assign(__assign(__assign({}, visualElement.reactStyle), visualElement.style), visualElement.vars),
3892 };
3893 if (!!drag) {
3894 // Disable text selection
3895 htmlProps.style.userSelect = "none";
3896 // Disable the ghost element when a user drags
3897 htmlProps.draggable = false;
3898 }
3899 return htmlProps;
3900 }
3901
3902 /**
3903 * Build React props for SVG elements
3904 */
3905 function buildSVGProps(visualElement) {
3906 return __assign(__assign({}, visualElement.attrs), { style: __assign({}, visualElement.reactStyle) });
3907 }
3908
3909 function render(Component, props, visualElement) {
3910 // Only filter props from components we control, ie `motion.div`. If this
3911 // is a custom component pass along everything provided to it.
3912 var forwardedProps = typeof Component === "string" ? filterProps(props) : props;
3913 /**
3914 * Every render, empty and rebuild the animated values to be applied to our Element.
3915 * During animation these data structures are used in a mutable fashion to reduce
3916 * garbage collection, but between renders we can flush them to remove values
3917 * that might have been taken out of the provided props.
3918 */
3919 visualElement.clean();
3920 visualElement.build();
3921 // Generate props to visually render this component
3922 var visualProps = isSVGComponent(Component)
3923 ? buildSVGProps(visualElement)
3924 : buildHTMLProps(visualElement, props);
3925 return React.createElement(Component, __assign(__assign(__assign({}, forwardedProps), { ref: visualElement.ref }), visualProps));
3926 }
3927
3928 function isCSSVariable$1(value) {
3929 return typeof value === "string" && value.startsWith("var(--");
3930 }
3931 /**
3932 * Parse Framer's special CSS variable format into a CSS token and a fallback.
3933 *
3934 * ```
3935 * `var(--foo, #fff)` => [`--foo`, '#fff']
3936 * ```
3937 *
3938 * @param current
3939 */
3940 var cssVariableRegex = /var\((--[a-zA-Z0-9-_]+),? ?([a-zA-Z0-9 ()%#.,-]+)?\)/;
3941 function parseCSSVariable(current) {
3942 var match = cssVariableRegex.exec(current);
3943 if (!match)
3944 return [,];
3945 var token = match[1], fallback = match[2];
3946 return [token, fallback];
3947 }
3948 var maxDepth = 4;
3949 function getVariableValue(current, element, depth) {
3950 if (depth === void 0) { depth = 1; }
3951 invariant(depth <= maxDepth, "Max CSS variable fallback depth detected in property \"" + current + "\". This may indicate a circular fallback dependency.");
3952 var _a = parseCSSVariable(current), token = _a[0], fallback = _a[1];
3953 // No CSS variable detected
3954 if (!token)
3955 return;
3956 // Attempt to read this CSS variable off the element
3957 var resolved = window.getComputedStyle(element).getPropertyValue(token);
3958 if (resolved) {
3959 return resolved;
3960 }
3961 else if (isCSSVariable$1(fallback)) {
3962 // The fallback might itself be a CSS variable, in which case we attempt to resolve it too.
3963 return getVariableValue(fallback, element, depth + 1);
3964 }
3965 else {
3966 return fallback;
3967 }
3968 }
3969 /**
3970 * Resolve CSS variables from
3971 *
3972 * @internal
3973 */
3974 function resolveCSSVariables(visualElement, _a, transitionEnd) {
3975 var target = __rest(_a, []);
3976 var element = visualElement.getInstance();
3977 if (!(element instanceof HTMLElement))
3978 return { target: target, transitionEnd: transitionEnd };
3979 // If `transitionEnd` isn't `undefined`, clone it. We could clone `target` and `transitionEnd`
3980 // only if they change but I think this reads clearer and this isn't a performance-critical path.
3981 if (transitionEnd) {
3982 transitionEnd = __assign({}, transitionEnd);
3983 }
3984 // Go through existing `MotionValue`s and ensure any existing CSS variables are resolved
3985 visualElement.forEachValue(function (value) {
3986 var current = value.get();
3987 if (!isCSSVariable$1(current))
3988 return;
3989 var resolved = getVariableValue(current, element);
3990 if (resolved)
3991 value.set(resolved);
3992 });
3993 // Cycle through every target property and resolve CSS variables. Currently
3994 // we only read single-var properties like `var(--foo)`, not `calc(var(--foo) + 20px)`
3995 for (var key in target) {
3996 var current = target[key];
3997 if (!isCSSVariable$1(current))
3998 continue;
3999 var resolved = getVariableValue(current, element);
4000 if (!resolved)
4001 continue;
4002 // Clone target if it hasn't already been
4003 target[key] = resolved;
4004 // If the user hasn't already set this key on `transitionEnd`, set it to the unresolved
4005 // CSS variable. This will ensure that after the animation the component will reflect
4006 // changes in the value of the CSS variable.
4007 if (transitionEnd && transitionEnd[key] === undefined) {
4008 transitionEnd[key] = current;
4009 }
4010 }
4011 return { target: target, transitionEnd: transitionEnd };
4012 }
4013
4014 var positionalKeys = new Set([
4015 "width",
4016 "height",
4017 "top",
4018 "left",
4019 "right",
4020 "bottom",
4021 "x",
4022 "y",
4023 ]);
4024 var isPositionalKey = function (key) { return positionalKeys.has(key); };
4025 var hasPositionalKey = function (target) {
4026 return Object.keys(target).some(isPositionalKey);
4027 };
4028 var setAndResetVelocity = function (value, to) {
4029 // Looks odd but setting it twice doesn't render, it'll just
4030 // set both prev and current to the latest value
4031 value.set(to, false);
4032 value.set(to);
4033 };
4034 var isNumOrPxType = function (v) {
4035 return v === number || v === px;
4036 };
4037 var BoundingBoxDimension;
4038 (function (BoundingBoxDimension) {
4039 BoundingBoxDimension["width"] = "width";
4040 BoundingBoxDimension["height"] = "height";
4041 BoundingBoxDimension["left"] = "left";
4042 BoundingBoxDimension["right"] = "right";
4043 BoundingBoxDimension["top"] = "top";
4044 BoundingBoxDimension["bottom"] = "bottom";
4045 })(BoundingBoxDimension || (BoundingBoxDimension = {}));
4046 var getPosFromMatrix = function (matrix, pos) {
4047 return parseFloat(matrix.split(", ")[pos]);
4048 };
4049 var getTranslateFromMatrix = function (pos2, pos3) { return function (_bbox, _a) {
4050 var transform = _a.transform;
4051 if (transform === "none" || !transform)
4052 return 0;
4053 var matrix3d = transform.match(/^matrix3d\((.+)\)$/);
4054 if (matrix3d) {
4055 return getPosFromMatrix(matrix3d[1], pos3);
4056 }
4057 else {
4058 var matrix = transform.match(/^matrix\((.+)\)$/);
4059 if (matrix) {
4060 return getPosFromMatrix(matrix[1], pos2);
4061 }
4062 else {
4063 return 0;
4064 }
4065 }
4066 }; };
4067 var transformKeys = new Set(["x", "y", "z"]);
4068 var nonTranslationalTransformKeys = transformProps.filter(function (key) { return !transformKeys.has(key); });
4069 function removeNonTranslationalTransform(visualElement) {
4070 var removedTransforms = [];
4071 nonTranslationalTransformKeys.forEach(function (key) {
4072 var value = visualElement.getValue(key);
4073 if (value !== undefined) {
4074 removedTransforms.push([key, value.get()]);
4075 value.set(key.startsWith("scale") ? 1 : 0);
4076 }
4077 });
4078 // Apply changes to element before measurement
4079 if (removedTransforms.length)
4080 visualElement.render();
4081 return removedTransforms;
4082 }
4083 var positionalValues = {
4084 // Dimensions
4085 width: function (_a) {
4086 var x = _a.x;
4087 return x.max - x.min;
4088 },
4089 height: function (_a) {
4090 var y = _a.y;
4091 return y.max - y.min;
4092 },
4093 top: function (_bbox, _a) {
4094 var top = _a.top;
4095 return parseFloat(top);
4096 },
4097 left: function (_bbox, _a) {
4098 var left = _a.left;
4099 return parseFloat(left);
4100 },
4101 bottom: function (_a, _b) {
4102 var y = _a.y;
4103 var top = _b.top;
4104 return parseFloat(top) + (y.max - y.min);
4105 },
4106 right: function (_a, _b) {
4107 var x = _a.x;
4108 var left = _b.left;
4109 return parseFloat(left) + (x.max - x.min);
4110 },
4111 // Transform
4112 x: getTranslateFromMatrix(4, 13),
4113 y: getTranslateFromMatrix(5, 14),
4114 };
4115 var convertChangedValueTypes = function (target, visualElement, changedKeys) {
4116 var originBbox = visualElement.getBoundingBox();
4117 var elementComputedStyle = visualElement.getComputedStyle();
4118 var display = elementComputedStyle.display, top = elementComputedStyle.top, left = elementComputedStyle.left, bottom = elementComputedStyle.bottom, right = elementComputedStyle.right, transform = elementComputedStyle.transform;
4119 var originComputedStyle = { top: top, left: left, bottom: bottom, right: right, transform: transform };
4120 // If the element is currently set to display: "none", make it visible before
4121 // measuring the target bounding box
4122 if (display === "none") {
4123 visualElement.setStaticValues("display", target.display || "block");
4124 }
4125 // Apply the latest values (as set in checkAndConvertChangedValueTypes)
4126 visualElement.render();
4127 var targetBbox = visualElement.getBoundingBox();
4128 changedKeys.forEach(function (key) {
4129 // Restore styles to their **calculated computed style**, not their actual
4130 // originally set style. This allows us to animate between equivalent pixel units.
4131 var value = visualElement.getValue(key);
4132 setAndResetVelocity(value, positionalValues[key](originBbox, originComputedStyle));
4133 target[key] = positionalValues[key](targetBbox, elementComputedStyle);
4134 });
4135 return target;
4136 };
4137 var checkAndConvertChangedValueTypes = function (visualElement, target, origin, transitionEnd) {
4138 if (origin === void 0) { origin = {}; }
4139 if (transitionEnd === void 0) { transitionEnd = {}; }
4140 target = __assign({}, target);
4141 transitionEnd = __assign({}, transitionEnd);
4142 var targetPositionalKeys = Object.keys(target).filter(isPositionalKey);
4143 // We want to remove any transform values that could affect the element's bounding box before
4144 // it's measured. We'll reapply these later.
4145 var removedTransformValues = [];
4146 var hasAttemptedToRemoveTransformValues = false;
4147 var changedValueTypeKeys = [];
4148 targetPositionalKeys.forEach(function (key) {
4149 var value = visualElement.getValue(key);
4150 if (!visualElement.hasValue(key))
4151 return;
4152 var from = origin[key];
4153 var to = target[key];
4154 var fromType = findDimensionValueType(from);
4155 var toType;
4156 // TODO: The current implementation of this basically throws an error
4157 // if you try and do value conversion via keyframes. There's probably
4158 // a way of doing this but the performance implications would need greater scrutiny,
4159 // as it'd be doing multiple resize-remeasure operations.
4160 if (isKeyframesTarget(to)) {
4161 var numKeyframes = to.length;
4162 for (var i = to[0] === null ? 1 : 0; i < numKeyframes; i++) {
4163 if (!toType) {
4164 toType = findDimensionValueType(to[i]);
4165 invariant(toType === fromType ||
4166 (isNumOrPxType(fromType) && isNumOrPxType(toType)), "Keyframes must be of the same dimension as the current value");
4167 }
4168 else {
4169 invariant(findDimensionValueType(to[i]) === toType, "All keyframes must be of the same type");
4170 }
4171 }
4172 }
4173 else {
4174 toType = findDimensionValueType(to);
4175 }
4176 if (fromType !== toType) {
4177 // If they're both just number or px, convert them both to numbers rather than
4178 // relying on resize/remeasure to convert (which is wasteful in this situation)
4179 if (isNumOrPxType(fromType) && isNumOrPxType(toType)) {
4180 var current = value.get();
4181 if (typeof current === "string") {
4182 value.set(parseFloat(current));
4183 }
4184 if (typeof to === "string") {
4185 target[key] = parseFloat(to);
4186 }
4187 else if (Array.isArray(to) && toType === px) {
4188 target[key] = to.map(parseFloat);
4189 }
4190 }
4191 else {
4192 // If we're going to do value conversion via DOM measurements, we first
4193 // need to remove non-positional transform values that could affect the bbox measurements.
4194 if (!hasAttemptedToRemoveTransformValues) {
4195 removedTransformValues = removeNonTranslationalTransform(visualElement);
4196 hasAttemptedToRemoveTransformValues = true;
4197 }
4198 changedValueTypeKeys.push(key);
4199 transitionEnd[key] =
4200 transitionEnd[key] !== undefined
4201 ? transitionEnd[key]
4202 : target[key];
4203 setAndResetVelocity(value, to);
4204 }
4205 }
4206 });
4207 if (changedValueTypeKeys.length) {
4208 var convertedTarget = convertChangedValueTypes(target, visualElement, changedValueTypeKeys);
4209 // If we removed transform values, reapply them before the next render
4210 if (removedTransformValues.length) {
4211 removedTransformValues.forEach(function (_a) {
4212 var key = _a[0], value = _a[1];
4213 visualElement.getValue(key).set(value);
4214 });
4215 }
4216 // Reapply original values
4217 visualElement.render();
4218 return { target: convertedTarget, transitionEnd: transitionEnd };
4219 }
4220 else {
4221 return { target: target, transitionEnd: transitionEnd };
4222 }
4223 };
4224 /**
4225 * Convert value types for x/y/width/height/top/left/bottom/right
4226 *
4227 * Allows animation between `'auto'` -> `'100%'` or `0` -> `'calc(50% - 10vw)'`
4228 *
4229 * @internal
4230 */
4231 function unitConversion(visualElement, target, origin, transitionEnd) {
4232 return hasPositionalKey(target)
4233 ? checkAndConvertChangedValueTypes(visualElement, target, origin, transitionEnd)
4234 : { target: target, transitionEnd: transitionEnd };
4235 }
4236
4237 /**
4238 * Parse a DOM variant to make it animatable. This involves resolving CSS variables
4239 * and ensuring animations like "20%" => "calc(50vw)" are performed in pixels.
4240 */
4241 var parseDomVariant = function (visualElement, target, origin, transitionEnd) {
4242 var resolved = resolveCSSVariables(visualElement, target, transitionEnd);
4243 target = resolved.target;
4244 transitionEnd = resolved.transitionEnd;
4245 return unitConversion(visualElement, target, origin, transitionEnd);
4246 };
4247
4248 /**
4249 * Use callback either only on the initial render or on all renders. In concurrent mode
4250 * the "initial" render might run multiple times
4251 *
4252 * @param callback - Callback to run
4253 * @param isInitialOnly - Set to `true` to only run on initial render, or `false` for all renders. Defaults to `false`.
4254 *
4255 * @public
4256 */
4257 function useInitialOrEveryRender(callback, isInitialOnly) {
4258 if (isInitialOnly === void 0) { isInitialOnly = false; }
4259 var isInitialRender = React.useRef(true);
4260 if (!isInitialOnly || (isInitialOnly && isInitialRender.current)) {
4261 callback();
4262 }
4263 isInitialRender.current = false;
4264 }
4265
4266 /**
4267 * Control animations on one or more components.
4268 *
4269 * @public
4270 */
4271 var AnimationControls = /** @class */ (function () {
4272 function AnimationControls() {
4273 /**
4274 * Track whether the host component has mounted.
4275 *
4276 * @internal
4277 */
4278 this.hasMounted = false;
4279 /**
4280 * Pending animations that are started before a component is mounted.
4281 *
4282 * @internal
4283 */
4284 this.pendingAnimations = [];
4285 /**
4286 * A collection of linked component animation controls.
4287 *
4288 * @internal
4289 */
4290 this.componentControls = new Set();
4291 }
4292 /**
4293 * Set variants on this and all child components.
4294 *
4295 * @param variants - The variants to set
4296 *
4297 * @internal
4298 */
4299 AnimationControls.prototype.setVariants = function (variants) {
4300 this.variants = variants;
4301 this.componentControls.forEach(function (controls) {
4302 return controls.setVariants(variants);
4303 });
4304 };
4305 /**
4306 * Set a default transition on this and all child components
4307 *
4308 * @param transition - The default transition to set
4309 *
4310 * @internal
4311 */
4312 AnimationControls.prototype.setDefaultTransition = function (transition) {
4313 this.defaultTransition = transition;
4314 this.componentControls.forEach(function (controls) {
4315 return controls.setDefaultTransition(transition);
4316 });
4317 };
4318 /**
4319 * Subscribes a component's animation controls to this.
4320 *
4321 * @param controls - The controls to subscribe
4322 * @returns An unsubscribe function.
4323 *
4324 * @internal
4325 */
4326 AnimationControls.prototype.subscribe = function (controls) {
4327 var _this = this;
4328 this.componentControls.add(controls);
4329 if (this.variants)
4330 controls.setVariants(this.variants);
4331 if (this.defaultTransition)
4332 controls.setDefaultTransition(this.defaultTransition);
4333 return function () { return _this.componentControls.delete(controls); };
4334 };
4335 /**
4336 * Starts an animation on all linked components.
4337 *
4338 * @remarks
4339 *
4340 * ```jsx
4341 * controls.start("variantLabel")
4342 * controls.start({
4343 * x: 0,
4344 * transition: { duration: 1 }
4345 * })
4346 * ```
4347 *
4348 * @param definition - Properties or variant label to animate to
4349 * @param transition - Optional `transtion` to apply to a variant
4350 * @returns - A `Promise` that resolves when all animations have completed.
4351 *
4352 * @public
4353 */
4354 AnimationControls.prototype.start = function (definition, transitionOverride) {
4355 var _this = this;
4356 if (this.hasMounted) {
4357 var animations_1 = [];
4358 this.componentControls.forEach(function (controls) {
4359 var animation = controls.start(definition, {
4360 transitionOverride: transitionOverride,
4361 });
4362 animations_1.push(animation);
4363 });
4364 return Promise.all(animations_1);
4365 }
4366 else {
4367 return new Promise(function (resolve) {
4368 _this.pendingAnimations.push({
4369 animation: [definition, transitionOverride],
4370 resolve: resolve,
4371 });
4372 });
4373 }
4374 };
4375 /**
4376 * Instantly set to a set of properties or a variant.
4377 *
4378 * ```jsx
4379 * // With properties
4380 * controls.set({ opacity: 0 })
4381 *
4382 * // With variants
4383 * controls.set("hidden")
4384 * ```
4385 *
4386 * @internalremarks
4387 * We could perform a similar trick to `.start` where this can be called before mount
4388 * and we maintain a list of of pending actions that get applied on mount. But the
4389 * expectation of `set` is that it happens synchronously and this would be difficult
4390 * to do before any children have even attached themselves. It's also poor practise
4391 * and we should discourage render-synchronous `.start` calls rather than lean into this.
4392 *
4393 * @public
4394 */
4395 AnimationControls.prototype.set = function (definition) {
4396 invariant(this.hasMounted, "controls.set() should only be called after a component has mounted. Consider calling within a useEffect hook.");
4397 return this.componentControls.forEach(function (controls) {
4398 return controls.apply(definition);
4399 });
4400 };
4401 /**
4402 * Stops animations on all linked components.
4403 *
4404 * ```jsx
4405 * controls.stop()
4406 * ```
4407 *
4408 * @public
4409 */
4410 AnimationControls.prototype.stop = function () {
4411 this.componentControls.forEach(function (controls) { return controls.stop(); });
4412 };
4413 /**
4414 * Initialises the animation controls.
4415 *
4416 * @internal
4417 */
4418 AnimationControls.prototype.mount = function () {
4419 var _this = this;
4420 this.hasMounted = true;
4421 this.pendingAnimations.forEach(function (_a) {
4422 var animation = _a.animation, resolve = _a.resolve;
4423 return _this.start.apply(_this, animation).then(resolve);
4424 });
4425 };
4426 /**
4427 * Stops all child animations when the host component unmounts.
4428 *
4429 * @internal
4430 */
4431 AnimationControls.prototype.unmount = function () {
4432 this.hasMounted = false;
4433 this.stop();
4434 };
4435 return AnimationControls;
4436 }());
4437 /**
4438 * @internal
4439 */
4440 var animationControls = function () { return new AnimationControls(); };
4441
4442 /**
4443 * @internal
4444 */
4445 var MotionContext = React.createContext({
4446 static: false,
4447 });
4448 var isVariantLabel = function (v) {
4449 return typeof v === "string" || Array.isArray(v);
4450 };
4451 var isAnimationControls = function (v) {
4452 return v instanceof AnimationControls;
4453 };
4454 /**
4455 * Set up the context for children motion components.
4456 *
4457 * We also use this opportunity to apply `initial` values
4458 */
4459 var useMotionContext = function (parentContext, controls, visualElement, isStatic, _a) {
4460 if (isStatic === void 0) { isStatic = false; }
4461 var initial = _a.initial, animate = _a.animate, variants = _a.variants, whileTap = _a.whileTap, whileHover = _a.whileHover, layoutId = _a.layoutId;
4462 // Determine whether this is a root element of an AnimatePresence component
4463 var presenceContext = React.useContext(PresenceContext);
4464 var presenceId = presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.id;
4465 visualElement.isPresenceRoot = parentContext.presenceId !== presenceId;
4466 // Override initial with that from a parent context, if defined
4467 if ((presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.initial) !== undefined) {
4468 initial = presenceContext.initial;
4469 }
4470 var initialState;
4471 if (initial === false && !isAnimationControls(animate)) {
4472 initialState = animate;
4473 }
4474 else if (typeof initial !== "boolean") {
4475 initialState = initial;
4476 }
4477 // Track mounted status so children can detect whether they were present during their
4478 // parent's first render
4479 var hasMounted = React.useRef(false);
4480 // We propagate this component's VisualElementAnimationControls *if* we're being provided variants,
4481 // if we're being used to control variants, or if we're being passed animation controls.
4482 // Otherwise this component should be "invisible" to variant propagation. This is a slight concession
4483 // to Framer X where every `Frame` is a `motion` component and it might be if we change that in the future
4484 // that this restriction is removed.
4485 var shouldPropagateControls = variants ||
4486 isVariantLabel(animate) ||
4487 isVariantLabel(whileTap) ||
4488 isVariantLabel(whileHover) ||
4489 isAnimationControls(animate);
4490 // If this component's `initial` prop is a variant label, propagate it. Otherwise pass the parent's.
4491 var targetInitial = isVariantLabel(initialState)
4492 ? initialState
4493 : parentContext.initial;
4494 // If this is a variant tree we need to propagate the `animate` prop in case new children are added after
4495 // the tree initially animates.
4496 var targetAnimate = isVariantLabel(animate)
4497 ? animate
4498 : parentContext.animate;
4499 // Only allow `initial` to trigger context re-renders if this is a `static` component (ie we're on the Framer canvas)
4500 // or in another non-animation/interaction environment.
4501 var initialDependency = isStatic ? targetInitial : null;
4502 // Only allow `animate` to trigger context re-renders if it's a variant label. If this is an array of
4503 // variant labels there's probably an optimisation to deep-compare but it might be an over-optimisation.
4504 // We want to do this as we rely on React's component rendering order each render cycle to determine
4505 // the new order of any child components for the `staggerChildren` functionality.
4506 var animateDependency = shouldPropagateControls && isVariantLabel(targetAnimate)
4507 ? targetAnimate
4508 : null;
4509 // The context to provide to the child. We `useMemo` because although `controls` and `initial` are
4510 // unlikely to change, by making the context an object it'll be considered a new value every render.
4511 // So all child motion components will re-render as a result.
4512 var context = React.useMemo(function () { return ({
4513 controls: shouldPropagateControls
4514 ? controls
4515 : parentContext.controls,
4516 initial: targetInitial,
4517 animate: targetAnimate,
4518 visualElement: visualElement,
4519 hasMounted: hasMounted,
4520 isReducedMotion: parentContext.isReducedMotion,
4521 presenceId: presenceId,
4522 }); }, [
4523 initialDependency,
4524 animateDependency,
4525 parentContext.isReducedMotion,
4526 animate,
4527 layoutId,
4528 presenceId,
4529 ]);
4530 // Update the `static` property every render. This is unlikely to change but also essentially free.
4531 context.static = isStatic;
4532 // Set initial state. If this is a static component (ie in Framer canvas), respond to updates
4533 // in `initial`.
4534 useInitialOrEveryRender(function () {
4535 var initialToApply = initialState || parentContext.initial;
4536 initialToApply && controls.apply(initialToApply);
4537 }, !isStatic);
4538 React.useEffect(function () {
4539 hasMounted.current = true;
4540 }, []);
4541 return context;
4542 };
4543
4544 var checkShouldInheritVariant = function (_a) {
4545 var animate = _a.animate, variants = _a.variants, _b = _a.inherit, inherit = _b === void 0 ? true : _b;
4546 return (inherit &&
4547 !!variants &&
4548 (!animate || animate instanceof AnimationControls));
4549 };
4550
4551 var isMotionValue = function (value) {
4552 return value instanceof MotionValue;
4553 };
4554
4555 /**
4556 * Scrape props for MotionValues and add/remove them to this component's
4557 * VisualElement
4558 */
4559 function useMotionValues(visualElement, props) {
4560 var prev = useConstant(empty);
4561 /**
4562 * Remove MotionValues that are no longer present
4563 */
4564 for (var key in prev) {
4565 var isTransform = isTransformProp(key) || isTransformOriginProp(key);
4566 var existsAsProp = props[key];
4567 var existsAsStyle = props.style && props.style[key];
4568 var propIsMotionValue = existsAsProp && isMotionValue(props[key]);
4569 var styleIsMotionValue = existsAsStyle && isMotionValue(props.style[key]);
4570 var transformRemoved = isTransform && !existsAsProp && !existsAsStyle;
4571 var motionValueRemoved = !isTransform && !propIsMotionValue && !styleIsMotionValue;
4572 if (transformRemoved || motionValueRemoved) {
4573 visualElement.removeValue(key);
4574 delete prev[key];
4575 }
4576 }
4577 /**
4578 * Add incoming MotionValues
4579 */
4580 addMotionValues(visualElement, prev, props);
4581 if (props.style)
4582 addMotionValues(visualElement, prev, props.style, true);
4583 /**
4584 * Transform custom values if provided a handler, ie size -> width/height
4585 * Ideally we'd ditch this by removing support for size and other custom values from Framer.
4586 */
4587 if (props.transformValues) {
4588 visualElement.reactStyle = props.transformValues(visualElement.reactStyle);
4589 }
4590 }
4591 /**
4592 * Add incoming MotionValues
4593 *
4594 * TODO: Type the VisualElements properly
4595 */
4596 function addMotionValues(visualElement, prev, source, isStyle) {
4597 if (isStyle === void 0) { isStyle = false; }
4598 if (isStyle)
4599 visualElement.reactStyle = {};
4600 for (var key in source) {
4601 var value = source[key];
4602 var foundMotionValue = false;
4603 if (isMotionValue(value)) {
4604 // If this is a MotionValue, add it if it isn't a reserved key
4605 if (!reservedNames.has(key)) {
4606 visualElement.addValue(key, value);
4607 foundMotionValue = true;
4608 }
4609 }
4610 else if (isTransformProp(key) || isTransformOriginProp(key)) {
4611 // If this is a transform prop, always create a MotionValue
4612 // to ensure we can reconcile them all together.
4613 if (!visualElement.hasValue(key)) {
4614 visualElement.addValue(key, motionValue(value));
4615 }
4616 else if (value !== prev[key]) {
4617 // If the MotionValue already exists, update it with the
4618 // latest incoming value
4619 var motion = visualElement.getValue(key);
4620 motion.set(value);
4621 }
4622 foundMotionValue = true;
4623 }
4624 else if (isStyle) {
4625 visualElement.reactStyle[key] = value;
4626 }
4627 if (foundMotionValue)
4628 prev[key] = value;
4629 }
4630 }
4631 /**
4632 * These are props we accept as MotionValues but don't want to add
4633 * to the VisualElement
4634 */
4635 var reservedNames = new Set([]);
4636 var empty = function () { return ({}); };
4637
4638 var isCustomValue = function (v) {
4639 return Boolean(v && typeof v === "object" && v.mix && v.toValue);
4640 };
4641 var resolveFinalValueInKeyframes = function (v) {
4642 // TODO maybe throw if v.length - 1 is placeholder token?
4643 return isKeyframesTarget(v) ? v[v.length - 1] || 0 : v;
4644 };
4645
4646 /**
4647 * Check if value is a numerical string, ie a string that is purely a number eg "100" or "-100.1"
4648 */
4649 var isNumericalString = function (v) { return /^\-?\d*\.?\d+$/.test(v); };
4650
4651 /**
4652 * Get the current value of every `MotionValue` in a `VisualElement`
4653 */
4654 var getCurrent = function (visualElement) {
4655 var current = {};
4656 visualElement.forEachValue(function (value, key) { return (current[key] = value.get()); });
4657 return current;
4658 };
4659 /**
4660 * Get the current velocity of every `MotionValue` in a `VisualElement`
4661 */
4662 var getVelocity = function (visualElement) {
4663 var velocity = {};
4664 visualElement.forEachValue(function (value, key) { return (velocity[key] = value.getVelocity()); });
4665 return velocity;
4666 };
4667 /**
4668 * Check if value is a function that returns a `Target`. A generic typeof === 'function'
4669 * check, just helps with typing.
4670 */
4671 var isTargetResolver = function (p) {
4672 return typeof p === "function";
4673 };
4674 /**
4675 * Check if value is a list of variant labels
4676 */
4677 var isVariantLabels = function (v) { return Array.isArray(v); };
4678 /**
4679 * Control animations for a single component
4680 *
4681 * @internal
4682 */
4683 var VisualElementAnimationControls = /** @class */ (function () {
4684 function VisualElementAnimationControls(visualElement, _a) {
4685 var _this = this;
4686 var makeTargetAnimatable = _a.makeTargetAnimatable;
4687 /**
4688 * A reference to the component's latest props. We could probably ditch this in
4689 * favour to a reference to the `custom` prop now we don't send all props through
4690 * to target resolvers.
4691 */
4692 this.props = {};
4693 /**
4694 * The component's variants, as provided by `variants`
4695 */
4696 this.variants = {};
4697 /**
4698 * A set of values that we animate back to when a value is cleared of all overrides.
4699 */
4700 this.baseTarget = {};
4701 /**
4702 * A series of target overrides that we can animate to/from when overrides are set/cleared.
4703 */
4704 this.overrides = [];
4705 /**
4706 * A series of target overrides as they were originally resolved.
4707 */
4708 this.resolvedOverrides = [];
4709 /**
4710 * A Set of currently active override indexes
4711 */
4712 this.activeOverrides = new Set();
4713 /**
4714 * A Set of value keys that are currently animating.
4715 */
4716 this.isAnimating = new Set();
4717 /**
4718 * Check if the associated `VisualElement` has a key with the provided string.
4719 * Pre-bound to the class so we can provide directly to the `filter` in `checkForNewValues`.
4720 */
4721 this.hasValue = function (key) { return !_this.visualElement.hasValue(key); };
4722 this.visualElement = visualElement;
4723 this.makeTargetAnimatable = makeTargetAnimatable;
4724 this.visualElement.forEachValue(function (value, key) { return (_this.baseTarget[key] = value.get()); });
4725 }
4726 /**
4727 * Set the reference to the component's props.
4728 * @param props -
4729 */
4730 VisualElementAnimationControls.prototype.setProps = function (props) {
4731 this.props = props;
4732 };
4733 /**
4734 * Set the reference to the component's variants
4735 * @param variants -
4736 */
4737 VisualElementAnimationControls.prototype.setVariants = function (variants) {
4738 if (variants)
4739 this.variants = variants;
4740 };
4741 /**
4742 * Set the component's default transition
4743 * @param transition -
4744 */
4745 VisualElementAnimationControls.prototype.setDefaultTransition = function (transition) {
4746 if (transition)
4747 this.defaultTransition = transition;
4748 };
4749 /**
4750 * Set motion values without animation.
4751 *
4752 * @param definition -
4753 * @param isActive -
4754 */
4755 VisualElementAnimationControls.prototype.setValues = function (definition, _a) {
4756 var _b = _a === void 0 ? {} : _a, _c = _b.isActive, isActive = _c === void 0 ? new Set() : _c, priority = _b.priority;
4757 var _d = this.resolveVariant(definition), target = _d.target, transitionEnd = _d.transitionEnd;
4758 target = this.transformValues(__assign(__assign({}, target), transitionEnd));
4759 for (var key in target) {
4760 if (isActive.has(key))
4761 return;
4762 isActive.add(key);
4763 if (target) {
4764 var targetValue = resolveFinalValueInKeyframes(target[key]);
4765 if (this.visualElement.hasValue(key)) {
4766 var value = this.visualElement.getValue(key);
4767 value && value.set(targetValue);
4768 }
4769 else {
4770 this.visualElement.addValue(key, motionValue(targetValue));
4771 }
4772 if (!priority)
4773 this.baseTarget[key] = targetValue;
4774 }
4775 }
4776 };
4777 /**
4778 * Allows `transformValues` to be set by a component that allows us to
4779 * transform the values in a given `Target`. This allows Framer Library
4780 * to extend Framer Motion to animate `Color` variables etc. Currently we have
4781 * to manually support these extended types here in Framer Motion.
4782 *
4783 * @param values -
4784 */
4785 VisualElementAnimationControls.prototype.transformValues = function (values) {
4786 var transformValues = this.props.transformValues;
4787 return transformValues ? transformValues(values) : values;
4788 };
4789 /**
4790 * Check a `Target` for new values we haven't animated yet, and add them
4791 * to the `MotionValueMap`.
4792 *
4793 * Currently there's functionality here that is DOM-specific, we should allow
4794 * this functionality to be injected by the factory that creates DOM-specific
4795 * components.
4796 *
4797 * @param target -
4798 */
4799 VisualElementAnimationControls.prototype.checkForNewValues = function (target) {
4800 var newValueKeys = Object.keys(target).filter(this.hasValue);
4801 var numNewValues = newValueKeys.length;
4802 if (!numNewValues)
4803 return;
4804 for (var i = 0; i < numNewValues; i++) {
4805 var key = newValueKeys[i];
4806 var targetValue = target[key];
4807 var value = null;
4808 // If this is a keyframes value, we can attempt to use the first value in the
4809 // array as that's going to be the first value of the animation anyway
4810 if (Array.isArray(targetValue)) {
4811 value = targetValue[0];
4812 }
4813 // If it isn't a keyframes or the first keyframes value was set as `null`, read the
4814 // value from the DOM. It might be worth investigating whether to check props (for SVG)
4815 // or props.style (for HTML) if the value exists there before attempting to read.
4816 if (value === null) {
4817 var readValue = this.visualElement.readNativeValue(key);
4818 value = readValue !== undefined ? readValue : target[key];
4819 invariant(value !== null, "No initial value for \"" + key + "\" can be inferred. Ensure an initial value for \"" + key + "\" is defined on the component.");
4820 }
4821 if (typeof value === "string" && isNumericalString(value)) {
4822 // If this is a number read as a string, ie "0" or "200", convert it to a number
4823 value = parseFloat(value);
4824 }
4825 else if (!findValueType(value) && complex.test(targetValue)) {
4826 // If value is not recognised as animatable, ie "none", create an animatable version origin based on the target
4827 value = complex.getAnimatableNone(targetValue);
4828 }
4829 this.visualElement.addValue(key, motionValue(value));
4830 this.baseTarget[key] = value;
4831 }
4832 };
4833 /**
4834 * Resolve a variant from its label or resolver into an actual `Target` we can animate to.
4835 * @param variant -
4836 */
4837 VisualElementAnimationControls.prototype.resolveVariant = function (variant) {
4838 if (!variant) {
4839 return {
4840 target: undefined,
4841 transition: undefined,
4842 transitionEnd: undefined,
4843 };
4844 }
4845 if (isTargetResolver(variant)) {
4846 // resolve current and velocity
4847 variant = variant(this.props.custom, getCurrent(this.visualElement), getVelocity(this.visualElement));
4848 }
4849 var _a = variant.transition, transition = _a === void 0 ? this.defaultTransition : _a, transitionEnd = variant.transitionEnd, target = __rest(variant, ["transition", "transitionEnd"]);
4850 return { transition: transition, transitionEnd: transitionEnd, target: target };
4851 };
4852 /**
4853 * Get the highest active override priority index
4854 */
4855 VisualElementAnimationControls.prototype.getHighestPriority = function () {
4856 if (!this.activeOverrides.size)
4857 return 0;
4858 return Math.max.apply(Math, Array.from(this.activeOverrides));
4859 };
4860 /**
4861 * Set an override. We add this layer of indirection so if, for instance, a tap gesture
4862 * starts and overrides a hover gesture, when we clear the tap gesture and fallback to the
4863 * hover gesture, if that hover gesture has changed in the meantime we can go to that rather
4864 * than the one that was resolved when the hover gesture animation started.
4865 *
4866 * @param definition -
4867 * @param overrideIndex -
4868 */
4869 VisualElementAnimationControls.prototype.setOverride = function (definition, overrideIndex) {
4870 this.overrides[overrideIndex] = definition;
4871 if (this.children) {
4872 this.children.forEach(function (child) {
4873 return child.setOverride(definition, overrideIndex);
4874 });
4875 }
4876 };
4877 /**
4878 * Start an override animation.
4879 * @param overrideIndex -
4880 */
4881 VisualElementAnimationControls.prototype.startOverride = function (overrideIndex) {
4882 var override = this.overrides[overrideIndex];
4883 if (override) {
4884 return this.start(override, { priority: overrideIndex });
4885 }
4886 };
4887 /**
4888 * Clear an override. We check every value we animated to in this override to see if
4889 * its present on any lower-priority overrides. If not, we animate it back to its base target.
4890 * @param overrideIndex -
4891 */
4892 VisualElementAnimationControls.prototype.clearOverride = function (overrideIndex) {
4893 var _this = this;
4894 if (this.children) {
4895 this.children.forEach(function (child) { return child.clearOverride(overrideIndex); });
4896 }
4897 var override = this.overrides[overrideIndex];
4898 if (!override)
4899 return;
4900 this.activeOverrides.delete(overrideIndex);
4901 var highest = this.getHighestPriority();
4902 this.resetIsAnimating();
4903 if (highest) {
4904 var highestOverride = this.overrides[highest];
4905 highestOverride && this.startOverride(highest);
4906 }
4907 // Figure out which remaining values were affected by the override and animate those
4908 var overrideTarget = this.resolvedOverrides[overrideIndex];
4909 if (!overrideTarget)
4910 return;
4911 var remainingValues = {};
4912 for (var key in this.baseTarget) {
4913 if (overrideTarget[key] !== undefined) {
4914 remainingValues[key] = this.baseTarget[key];
4915 }
4916 }
4917 this.onStart();
4918 this.animate(remainingValues).then(function () { return _this.onComplete(); });
4919 };
4920 /**
4921 * Apply a target/variant without any animation
4922 */
4923 VisualElementAnimationControls.prototype.apply = function (definition) {
4924 if (Array.isArray(definition)) {
4925 return this.applyVariantLabels(definition);
4926 }
4927 else if (typeof definition === "string") {
4928 return this.applyVariantLabels([definition]);
4929 }
4930 else {
4931 this.setValues(definition);
4932 }
4933 };
4934 /**
4935 * Apply variant labels without animation
4936 */
4937 VisualElementAnimationControls.prototype.applyVariantLabels = function (variantLabelList) {
4938 var _this = this;
4939 var isActive = new Set();
4940 var reversedList = __spreadArrays(variantLabelList).reverse();
4941 reversedList.forEach(function (key) {
4942 var _a = _this.resolveVariant(_this.variants[key]), target = _a.target, transitionEnd = _a.transitionEnd;
4943 if (transitionEnd) {
4944 _this.setValues(transitionEnd, { isActive: isActive });
4945 }
4946 if (target) {
4947 _this.setValues(target, { isActive: isActive });
4948 }
4949 if (_this.children && _this.children.size) {
4950 _this.children.forEach(function (child) {
4951 return child.applyVariantLabels(variantLabelList);
4952 });
4953 }
4954 });
4955 };
4956 VisualElementAnimationControls.prototype.start = function (definition, opts) {
4957 var _this = this;
4958 if (opts === void 0) { opts = {}; }
4959 if (opts.priority) {
4960 this.activeOverrides.add(opts.priority);
4961 }
4962 this.resetIsAnimating(opts.priority);
4963 var animation;
4964 if (isVariantLabels(definition)) {
4965 animation = this.animateVariantLabels(definition, opts);
4966 }
4967 else if (typeof definition === "string") {
4968 animation = this.animateVariant(definition, opts);
4969 }
4970 else {
4971 animation = this.animate(definition, opts);
4972 }
4973 this.onStart();
4974 return animation.then(function () { return _this.onComplete(); });
4975 };
4976 VisualElementAnimationControls.prototype.animate = function (animationDefinition, _a) {
4977 var _this = this;
4978 var _b = _a === void 0 ? {} : _a, _c = _b.delay, delay = _c === void 0 ? 0 : _c, _d = _b.priority, priority = _d === void 0 ? 0 : _d, transitionOverride = _b.transitionOverride;
4979 var _e = this.resolveVariant(animationDefinition), target = _e.target, transition = _e.transition, transitionEnd = _e.transitionEnd;
4980 if (transitionOverride) {
4981 transition = transitionOverride;
4982 }
4983 if (!target)
4984 return Promise.resolve();
4985 target = this.transformValues(target);
4986 if (transitionEnd) {
4987 transitionEnd = this.transformValues(transitionEnd);
4988 }
4989 this.checkForNewValues(target);
4990 var origin = this.transformValues(getOrigin(target, transition, this.visualElement));
4991 if (this.makeTargetAnimatable) {
4992 var animatable = this.makeTargetAnimatable(this.visualElement, target, origin, transitionEnd);
4993 target = animatable.target;
4994 transitionEnd = animatable.transitionEnd;
4995 }
4996 if (priority) {
4997 this.resolvedOverrides[priority] = target;
4998 }
4999 this.checkForNewValues(target);
5000 var animations = [];
5001 for (var key in target) {
5002 var value = this.visualElement.getValue(key);
5003 if (!value || !target || target[key] === undefined)
5004 continue;
5005 var valueTarget = target[key];
5006 if (!priority) {
5007 this.baseTarget[key] = resolveFinalValueInKeyframes(valueTarget);
5008 }
5009 if (this.isAnimating.has(key))
5010 continue;
5011 this.isAnimating.add(key);
5012 animations.push(startAnimation(key, value, valueTarget, __assign({ delay: delay }, transition)));
5013 }
5014 var allAnimations = Promise.all(animations);
5015 return transitionEnd
5016 ? allAnimations.then(function () {
5017 _this.setValues(transitionEnd, { priority: priority });
5018 })
5019 : allAnimations;
5020 };
5021 VisualElementAnimationControls.prototype.animateVariantLabels = function (variantLabels, opts) {
5022 var _this = this;
5023 var animations = __spreadArrays(variantLabels).reverse()
5024 .map(function (label) { return _this.animateVariant(label, opts); });
5025 return Promise.all(animations);
5026 };
5027 VisualElementAnimationControls.prototype.animateVariant = function (variantLabel, opts) {
5028 var _this = this;
5029 var when = false;
5030 var delayChildren = 0;
5031 var staggerChildren = 0;
5032 var staggerDirection = 1;
5033 var priority = (opts && opts.priority) || 0;
5034 var variant = this.variants[variantLabel];
5035 var getAnimations = variant
5036 ? function () { return _this.animate(variant, opts); }
5037 : function () { return Promise.resolve(); };
5038 var getChildrenAnimations = this.children
5039 ? function () {
5040 return _this.animateChildren(variantLabel, delayChildren, staggerChildren, staggerDirection, priority);
5041 }
5042 : function () { return Promise.resolve(); };
5043 if (variant && this.children) {
5044 var transition = this.resolveVariant(variant).transition;
5045 if (transition) {
5046 when = transition.when || when;
5047 delayChildren = transition.delayChildren || delayChildren;
5048 staggerChildren = transition.staggerChildren || staggerChildren;
5049 staggerDirection =
5050 transition.staggerDirection || staggerDirection;
5051 }
5052 }
5053 if (when) {
5054 var _a = when === "beforeChildren"
5055 ? [getAnimations, getChildrenAnimations]
5056 : [getChildrenAnimations, getAnimations], first = _a[0], last = _a[1];
5057 return first().then(last);
5058 }
5059 else {
5060 return Promise.all([getAnimations(), getChildrenAnimations()]);
5061 }
5062 };
5063 VisualElementAnimationControls.prototype.animateChildren = function (variantLabel, delayChildren, staggerChildren, staggerDirection, priority) {
5064 if (delayChildren === void 0) { delayChildren = 0; }
5065 if (staggerChildren === void 0) { staggerChildren = 0; }
5066 if (staggerDirection === void 0) { staggerDirection = 1; }
5067 if (priority === void 0) { priority = 0; }
5068 if (!this.children) {
5069 return Promise.resolve();
5070 }
5071 var animations = [];
5072 var maxStaggerDuration = (this.children.size - 1) * staggerChildren;
5073 var generateStaggerDuration = staggerDirection === 1
5074 ? function (i) { return i * staggerChildren; }
5075 : function (i) { return maxStaggerDuration - i * staggerChildren; };
5076 Array.from(this.children).forEach(function (childControls, i) {
5077 var animation = childControls.animateVariant(variantLabel, {
5078 priority: priority,
5079 delay: delayChildren + generateStaggerDuration(i),
5080 });
5081 animations.push(animation);
5082 });
5083 return Promise.all(animations);
5084 };
5085 VisualElementAnimationControls.prototype.onStart = function () {
5086 var onAnimationStart = this.props.onAnimationStart;
5087 onAnimationStart && onAnimationStart();
5088 };
5089 VisualElementAnimationControls.prototype.onComplete = function () {
5090 var onAnimationComplete = this.props.onAnimationComplete;
5091 onAnimationComplete && onAnimationComplete();
5092 };
5093 VisualElementAnimationControls.prototype.checkOverrideIsAnimating = function (priority) {
5094 var numOverrides = this.overrides.length;
5095 for (var i = priority + 1; i < numOverrides; i++) {
5096 var resolvedOverride = this.resolvedOverrides[i];
5097 if (resolvedOverride) {
5098 for (var key in resolvedOverride) {
5099 this.isAnimating.add(key);
5100 }
5101 }
5102 }
5103 };
5104 VisualElementAnimationControls.prototype.resetIsAnimating = function (priority) {
5105 if (priority === void 0) { priority = 0; }
5106 this.isAnimating.clear();
5107 // If this isn't the highest priority gesture, block the animation
5108 // of anything that's currently being animated
5109 if (priority < this.getHighestPriority()) {
5110 this.checkOverrideIsAnimating(priority);
5111 }
5112 if (this.children) {
5113 this.children.forEach(function (child) { return child.resetIsAnimating(priority); });
5114 }
5115 };
5116 VisualElementAnimationControls.prototype.stop = function () {
5117 this.visualElement.forEachValue(function (value) { return value.stop(); });
5118 };
5119 /**
5120 * Add the controls of a child component.
5121 * @param controls -
5122 */
5123 VisualElementAnimationControls.prototype.addChild = function (controls) {
5124 if (!this.children) {
5125 this.children = new Set();
5126 }
5127 this.children.add(controls);
5128 // We set child overrides when `setOverride` is called, but also have to do it here
5129 // as the first time `setOverride` is called all the children might not have been added yet.
5130 this.overrides.forEach(function (override, i) {
5131 override && controls.setOverride(override, i);
5132 });
5133 };
5134 VisualElementAnimationControls.prototype.removeChild = function (controls) {
5135 if (!this.children) {
5136 return;
5137 }
5138 this.children.delete(controls);
5139 };
5140 VisualElementAnimationControls.prototype.resetChildren = function () {
5141 if (this.children)
5142 this.children.clear();
5143 };
5144 return VisualElementAnimationControls;
5145 }());
5146 function getOriginFromTransition(key, transition) {
5147 if (!transition)
5148 return;
5149 var valueTransition = transition[key] || transition["default"] || transition;
5150 return valueTransition.from;
5151 }
5152 function getOrigin(target, transition, visualElement) {
5153 var _a, _b;
5154 var origin = {};
5155 for (var key in target) {
5156 origin[key] = (_a = getOriginFromTransition(key, transition)) !== null && _a !== void 0 ? _a : (_b = visualElement.getValue(key)) === null || _b === void 0 ? void 0 : _b.get();
5157 }
5158 return origin;
5159 }
5160
5161 /**
5162 * Creates an imperative set of controls to trigger animations.
5163 *
5164 * This allows a consolidated, uniform API for animations, to be triggered by other APIs like the `animate` prop, or the gesture handlers.
5165 *
5166 * @internal
5167 */
5168 function useVisualElementAnimation(visualElement, props, config) {
5169 var subscribeToParentControls = checkShouldInheritVariant(props);
5170 var variants = props.variants, transition = props.transition;
5171 var parentControls = React.useContext(MotionContext).controls;
5172 var presenceContext = React.useContext(PresenceContext);
5173 var controls = useConstant(function () { return new VisualElementAnimationControls(visualElement, config); });
5174 // Reset and resubscribe children every render to ensure stagger order is correct
5175 if (!presenceContext || presenceContext.isPresent) {
5176 controls.resetChildren();
5177 controls.setProps(props);
5178 controls.setVariants(variants);
5179 controls.setDefaultTransition(transition);
5180 }
5181 // We have to subscribe to the parent controls within a useEffect rather than during render,
5182 // as
5183 React.useEffect(function () {
5184 if (subscribeToParentControls && parentControls) {
5185 parentControls.addChild(controls);
5186 }
5187 });
5188 React.useEffect(function () {
5189 return function () {
5190 // Remove reference to onAnimationComplete from controls. All the MotionValues
5191 // are unsubscribed from this component separately. We let animations run out
5192 // as they might be animating other components.
5193 var onAnimationComplete = props.onAnimationComplete, unmountProps = __rest(props, ["onAnimationComplete"]);
5194 controls.setProps(unmountProps);
5195 parentControls && parentControls.removeChild(controls);
5196 };
5197 }, []);
5198 return controls;
5199 }
5200
5201 /**
5202 * @public
5203 */
5204 var MotionConfigContext = React.createContext({
5205 transformPagePoint: function (p) { return p; },
5206 features: [],
5207 });
5208 /**
5209 * MotionConfig can be used in combination with the `m` component to cut bundle size
5210 * and dynamically load only the features you use.
5211 *
5212 * ```jsx
5213 * import {
5214 * m as motion,
5215 * AnimationFeature,
5216 * MotionConfig
5217 * } from "framer-motion"
5218 *
5219 * export function App() {
5220 * return (
5221 * <MotionConfig features={[AnimationFeature]}>
5222 * <motion.div animate={{ x: 100 }} />
5223 * </MotionConfig>
5224 * )
5225 * }
5226 * ```
5227 *
5228 * @public
5229 */
5230 function MotionConfig(_a) {
5231 var children = _a.children, _b = _a.features, features = _b === void 0 ? [] : _b, props = __rest(_a, ["children", "features"]);
5232 var pluginContext = React.useContext(MotionConfigContext);
5233 var loadedFeatures = __spreadArrays(pluginContext.features, features);
5234 // We do want to rerender children when the number of loaded features changes
5235 var value = React.useMemo(function () { return ({ features: loadedFeatures }); }, [
5236 loadedFeatures.length,
5237 ]);
5238 // Mutative to prevent triggering rerenders in all listening
5239 // components every time this component renders
5240 for (var key in props) {
5241 value[key] = props[key];
5242 }
5243 return (React.createElement(MotionConfigContext.Provider, { value: value }, children));
5244 }
5245
5246 /**
5247 * Load features via renderless components based on the provided MotionProps
5248 */
5249 function useFeatures(defaultFeatures, isStatic, visualElement, controls, props, context, parentContext, shouldInheritVariant) {
5250 var plugins = React.useContext(MotionConfigContext);
5251 // If this is a static component, or we're rendering on the server, we don't load
5252 // any feature components
5253 if (isStatic || typeof window === "undefined")
5254 return null;
5255 var allFeatures = __spreadArrays(defaultFeatures, plugins.features);
5256 var numFeatures = allFeatures.length;
5257 var features = [];
5258 // Decide which features we should render and add them to the returned array
5259 for (var i = 0; i < numFeatures; i++) {
5260 var _a = allFeatures[i], shouldRender = _a.shouldRender, key = _a.key, getComponent = _a.getComponent;
5261 if (shouldRender(props, parentContext)) {
5262 var Component = getComponent(props);
5263 Component &&
5264 features.push(React.createElement(Component, __assign({ key: key }, props, { localContext: context, parentContext: parentContext, visualElement: visualElement, controls: controls, inherit: shouldInheritVariant })));
5265 }
5266 }
5267 return features;
5268 }
5269
5270 var Presence;
5271 (function (Presence) {
5272 Presence[Presence["Entering"] = 0] = "Entering";
5273 Presence[Presence["Present"] = 1] = "Present";
5274 Presence[Presence["Exiting"] = 2] = "Exiting";
5275 })(Presence || (Presence = {}));
5276 var VisibilityAction;
5277 (function (VisibilityAction) {
5278 VisibilityAction[VisibilityAction["Hide"] = 0] = "Hide";
5279 VisibilityAction[VisibilityAction["Show"] = 1] = "Show";
5280 })(VisibilityAction || (VisibilityAction = {}));
5281
5282 /**
5283 * Default handlers for batching VisualElements
5284 */
5285 var defaultHandler = {
5286 measureLayout: function (child) { return child.measureLayout(); },
5287 layoutReady: function (child) { return child.layoutReady(); },
5288 };
5289 /**
5290 * Sort VisualElements by tree depth, so we process the highest elements first.
5291 */
5292 var sortByDepth = function (a, b) {
5293 return a.depth - b.depth;
5294 };
5295 /**
5296 * Create a batcher to process VisualElements
5297 */
5298 function createBatcher() {
5299 var queue = new Set();
5300 var add = function (child) { return queue.add(child); };
5301 var flush = function (_a) {
5302 var _b = _a === void 0 ? defaultHandler : _a, measureLayout = _b.measureLayout, layoutReady = _b.layoutReady;
5303 var order = Array.from(queue).sort(sortByDepth);
5304 /**
5305 * Write: Reset any transforms on children elements so we can read their actual layout
5306 */
5307 order.forEach(function (child) { return child.resetTransform(); });
5308 /**
5309 * Read: Measure the actual layout
5310 */
5311 order.forEach(measureLayout);
5312 /**
5313 * Write: Notify the VisualElements they're ready for further write operations.
5314 */
5315 order.forEach(layoutReady);
5316 /**
5317 * After all children have started animating, ensure any Entering components are set to Present.
5318 * If we add deferred animations (set up all animations and then start them in two loops) this
5319 * could be moved to the start loop. But it needs to happen after all the animations configs
5320 * are generated in AnimateSharedLayout as this relies on presence data
5321 */
5322 order.forEach(function (child) {
5323 if (child.isPresent)
5324 child.presence = Presence.Present;
5325 });
5326 queue.clear();
5327 };
5328 return { add: add, flush: flush };
5329 }
5330 function isSharedLayout(context) {
5331 return !!context.forceUpdate;
5332 }
5333 var SharedLayoutContext = React.createContext(createBatcher());
5334
5335 function useUnmountEffect(callback) {
5336 return React.useEffect(function () { return function () { return callback(); }; }, []);
5337 }
5338
5339 function useSnapshotOnUnmount(visualElement) {
5340 var syncLayout = React.useContext(SharedLayoutContext);
5341 useUnmountEffect(function () {
5342 if (isSharedLayout(syncLayout))
5343 syncLayout.remove(visualElement);
5344 });
5345 }
5346
5347 /**
5348 * Create a `motion` component.
5349 *
5350 * This function accepts a Component argument, which can be either a string (ie "div"
5351 * for `motion.div`), or an actual React component.
5352 *
5353 * Alongside this is a config option which provides a way of rendering the provided
5354 * component "offline", or outside the React render cycle.
5355 *
5356 * @internal
5357 */
5358 function createMotionComponent(Component, _a) {
5359 var defaultFeatures = _a.defaultFeatures, useVisualElement = _a.useVisualElement, render = _a.render, animationControlsConfig = _a.animationControlsConfig;
5360 function MotionComponent(props, externalRef) {
5361 var parentContext = React.useContext(MotionContext);
5362 var shouldInheritVariant = checkShouldInheritVariant(props);
5363 /**
5364 * If a component isStatic, we only visually update it as a
5365 * result of a React re-render, rather than any interactions or animations.
5366 * If this component or any ancestor isStatic, we disable hardware acceleration
5367 * and don't load any additional functionality.
5368 */
5369 var isStatic = parentContext.static || props.static || false;
5370 /**
5371 * Create a VisualElement for this component. A VisualElement provides a common
5372 * interface to renderer-specific APIs (ie DOM/Three.js etc) as well as
5373 * providing a way of rendering to these APIs outside of the React render loop
5374 * for more performant animations and interactions
5375 */
5376 var visualElement = useVisualElement(Component, props, parentContext.visualElement, isStatic, externalRef);
5377 /**
5378 * Scrape MotionValues from props and add/remove them to/from
5379 * the VisualElement as necessary.
5380 */
5381 useMotionValues(visualElement, props);
5382 /**
5383 * Create animation controls for the VisualElement. It might be
5384 * interesting to try and combine this with VisualElement itself in a further refactor.
5385 */
5386 var controls = useVisualElementAnimation(visualElement, props, animationControlsConfig);
5387 /**
5388 * Build the MotionContext to pass on to the next `motion` component.
5389 */
5390 var context = useMotionContext(parentContext, controls, visualElement, isStatic, props);
5391 /**
5392 * Load features as renderless components unless the component isStatic
5393 */
5394 var features = useFeatures(defaultFeatures, isStatic, visualElement, controls, props, context, parentContext, shouldInheritVariant);
5395 var component = render(Component, props, visualElement);
5396 /**
5397 *
5398 */
5399 useSnapshotOnUnmount(visualElement);
5400 // The mount order and hierarchy is specific to ensure our element ref is hydrated by the time
5401 // all plugins and features has to execute.
5402 return (React.createElement(React.Fragment, null,
5403 React.createElement(MotionContext.Provider, { value: context }, component),
5404 features));
5405 }
5406 return React.forwardRef(MotionComponent);
5407 }
5408
5409 function createLock(name) {
5410 var lock = null;
5411 return function () {
5412 var openLock = function () {
5413 lock = null;
5414 };
5415 if (lock === null) {
5416 lock = name;
5417 return openLock;
5418 }
5419 return false;
5420 };
5421 }
5422 var globalHorizontalLock = createLock("dragHorizontal");
5423 var globalVerticalLock = createLock("dragVertical");
5424 function getGlobalLock(drag) {
5425 var lock = false;
5426 if (drag === "y") {
5427 lock = globalVerticalLock();
5428 }
5429 else if (drag === "x") {
5430 lock = globalHorizontalLock();
5431 }
5432 else {
5433 var openHorizontal_1 = globalHorizontalLock();
5434 var openVertical_1 = globalVerticalLock();
5435 if (openHorizontal_1 && openVertical_1) {
5436 lock = function () {
5437 openHorizontal_1();
5438 openVertical_1();
5439 };
5440 }
5441 else {
5442 // Release the locks because we don't use them
5443 if (openHorizontal_1)
5444 openHorizontal_1();
5445 if (openVertical_1)
5446 openVertical_1();
5447 }
5448 }
5449 return lock;
5450 }
5451
5452 var isViewportScrollBlocked = false;
5453 var isBrowser = typeof window !== "undefined";
5454 if (isBrowser) {
5455 document.addEventListener("touchmove", function (event) {
5456 if (isViewportScrollBlocked) {
5457 event.preventDefault();
5458 }
5459 }, { passive: false });
5460 }
5461 var blockViewportScroll = function () { return (isViewportScrollBlocked = true); };
5462 var unblockViewportScroll = function () { return (isViewportScrollBlocked = false); };
5463
5464 function addDomEvent(target, eventName, handler, options) {
5465 if (!handler)
5466 return;
5467 target.addEventListener(eventName, handler, options);
5468 return function () { return target.removeEventListener(eventName, handler, options); };
5469 }
5470 /**
5471 * Attaches an event listener directly to the provided DOM element.
5472 *
5473 * Bypassing React's event system can be desirable, for instance when attaching non-passive
5474 * event handlers.
5475 *
5476 * ```jsx
5477 * const ref = useRef(null)
5478 *
5479 * useDomEvent(ref, 'wheel', onWheel, { passive: false })
5480 *
5481 * return <div ref={ref} />
5482 * ```
5483 *
5484 * @param ref - React.RefObject that's been provided to the element you want to bind the listener to.
5485 * @param eventName - Name of the event you want listen for.
5486 * @param handler - Function to fire when receiving the event.
5487 * @param options - Options to pass to `Event.addEventListener`.
5488 *
5489 * @public
5490 */
5491 function useDomEvent(ref, eventName, handler, options) {
5492 React.useEffect(function () {
5493 var element = ref.current;
5494 if (handler && element) {
5495 return addDomEvent(element, eventName, handler, options);
5496 }
5497 }, [ref, eventName, handler, options]);
5498 }
5499
5500 function isMouseEvent(event) {
5501 // PointerEvent inherits from MouseEvent so we can't use a straight instanceof check.
5502 if (typeof PointerEvent !== "undefined" && event instanceof PointerEvent) {
5503 return !!(event.pointerType === "mouse");
5504 }
5505 return event instanceof MouseEvent;
5506 }
5507 function isTouchEvent(event) {
5508 var hasTouches = !!event.touches;
5509 return hasTouches;
5510 }
5511
5512 /**
5513 * Filters out events not attached to the primary pointer (currently left mouse button)
5514 * @param eventHandler
5515 */
5516 function filterPrimaryPointer(eventHandler) {
5517 if (!eventHandler)
5518 return undefined;
5519 return function (event) {
5520 var isMouseEvent = event instanceof MouseEvent;
5521 var isPrimaryPointer = !isMouseEvent ||
5522 (isMouseEvent && event.button === 0);
5523 if (isPrimaryPointer) {
5524 eventHandler(event);
5525 }
5526 };
5527 }
5528 var defaultPagePoint = { pageX: 0, pageY: 0 };
5529 function pointFromTouch(e, pointType) {
5530 if (pointType === void 0) { pointType = "page"; }
5531 var primaryTouch = e.touches[0] || e.changedTouches[0];
5532 var point = primaryTouch || defaultPagePoint;
5533 return {
5534 x: point[pointType + "X"],
5535 y: point[pointType + "Y"],
5536 };
5537 }
5538 function pointFromMouse(point, pointType) {
5539 if (pointType === void 0) { pointType = "page"; }
5540 return {
5541 x: point[pointType + "X"],
5542 y: point[pointType + "Y"],
5543 };
5544 }
5545 function extractEventInfo(event, pointType) {
5546 if (pointType === void 0) { pointType = "page"; }
5547 return {
5548 point: isTouchEvent(event)
5549 ? pointFromTouch(event, pointType)
5550 : pointFromMouse(event, pointType),
5551 };
5552 }
5553 function getViewportPointFromEvent(event) {
5554 return extractEventInfo(event, "client");
5555 }
5556 var wrapHandler = function (handler, shouldFilterPrimaryPointer) {
5557 if (shouldFilterPrimaryPointer === void 0) { shouldFilterPrimaryPointer = false; }
5558 if (!handler)
5559 return;
5560 var listener = function (event) { return handler(event, extractEventInfo(event)); };
5561 return shouldFilterPrimaryPointer
5562 ? filterPrimaryPointer(listener)
5563 : listener;
5564 };
5565
5566 var isBrowser$1 = typeof window !== "undefined";
5567 // We check for event support via functions in case they've been mocked by a testing suite.
5568 var supportsPointerEvents = function () {
5569 return isBrowser$1 && window.onpointerdown === null;
5570 };
5571 var supportsTouchEvents = function () {
5572 return isBrowser$1 && window.ontouchstart === null;
5573 };
5574 var supportsMouseEvents = function () {
5575 return isBrowser$1 && window.onmousedown === null;
5576 };
5577
5578 var mouseEventNames = {
5579 pointerdown: "mousedown",
5580 pointermove: "mousemove",
5581 pointerup: "mouseup",
5582 pointercancel: "mousecancel",
5583 pointerover: "mouseover",
5584 pointerout: "mouseout",
5585 pointerenter: "mouseenter",
5586 pointerleave: "mouseleave",
5587 };
5588 var touchEventNames = {
5589 pointerdown: "touchstart",
5590 pointermove: "touchmove",
5591 pointerup: "touchend",
5592 pointercancel: "touchcancel",
5593 };
5594 function getPointerEventName(name) {
5595 if (supportsPointerEvents()) {
5596 return name;
5597 }
5598 else if (supportsTouchEvents()) {
5599 return touchEventNames[name];
5600 }
5601 else if (supportsMouseEvents()) {
5602 return mouseEventNames[name];
5603 }
5604 return name;
5605 }
5606 function addPointerEvent(target, eventName, handler, options) {
5607 return addDomEvent(target, getPointerEventName(eventName), wrapHandler(handler, eventName === "pointerdown"), options);
5608 }
5609 function usePointerEvent(ref, eventName, handler, options) {
5610 return useDomEvent(ref, getPointerEventName(eventName), wrapHandler(handler, eventName === "pointerdown"), options);
5611 }
5612
5613 /** @public */
5614 var Point;
5615 (function (Point) {
5616 /** @beta */
5617 Point.subtract = function (a, b) {
5618 return { x: a.x - b.x, y: a.y - b.y };
5619 };
5620 /** @beta */
5621 Point.relativeTo = function (idOrElem) {
5622 var elem;
5623 var getElem = function () {
5624 // Caching element here could be leaky because of React lifecycle
5625 if (elem !== undefined)
5626 return elem;
5627 if (typeof idOrElem === "string") {
5628 elem = document.getElementById(idOrElem);
5629 }
5630 else {
5631 elem = idOrElem;
5632 }
5633 return elem;
5634 };
5635 return function (_a) {
5636 var x = _a.x, y = _a.y;
5637 var localElem = getElem();
5638 if (!localElem)
5639 return undefined;
5640 var rect = localElem.getBoundingClientRect();
5641 return {
5642 x: x - rect.left - window.scrollX,
5643 y: y - rect.top - window.scrollY,
5644 };
5645 };
5646 };
5647 })(Point || (Point = {}));
5648
5649 /**
5650 * @internal
5651 */
5652 var PanSession = /** @class */ (function () {
5653 function PanSession(event, handlers, _a) {
5654 var _this = this;
5655 var transformPagePoint = (_a === void 0 ? {} : _a).transformPagePoint;
5656 /**
5657 * @internal
5658 */
5659 this.startEvent = null;
5660 /**
5661 * @internal
5662 */
5663 this.lastMoveEvent = null;
5664 /**
5665 * @internal
5666 */
5667 this.lastMoveEventInfo = null;
5668 /**
5669 * @internal
5670 */
5671 this.handlers = {};
5672 this.updatePoint = function () {
5673 if (!(_this.lastMoveEvent && _this.lastMoveEventInfo))
5674 return;
5675 var info = getPanInfo(_this.lastMoveEventInfo, _this.history);
5676 var isPanStarted = _this.startEvent !== null;
5677 // Only start panning if the offset is larger than 3 pixels. If we make it
5678 // any larger than this we'll want to reset the pointer history
5679 // on the first update to avoid visual snapping to the cursoe.
5680 var isDistancePastThreshold = distance(info.offset, { x: 0, y: 0 }) >= 3;
5681 if (!isPanStarted && !isDistancePastThreshold)
5682 return;
5683 var point = info.point;
5684 var timestamp = getFrameData().timestamp;
5685 _this.history.push(__assign(__assign({}, point), { timestamp: timestamp }));
5686 var _a = _this.handlers, onStart = _a.onStart, onMove = _a.onMove;
5687 if (!isPanStarted) {
5688 onStart && onStart(_this.lastMoveEvent, info);
5689 _this.startEvent = _this.lastMoveEvent;
5690 }
5691 onMove && onMove(_this.lastMoveEvent, info);
5692 };
5693 // If we have more than one touch, don't start detecting this gesture
5694 if (isTouchEvent(event) && event.touches.length > 1)
5695 return;
5696 this.handlers = handlers;
5697 this.transformPagePoint = transformPagePoint;
5698 var info = extractEventInfo(event);
5699 var initialInfo = transformPoint(info, this.transformPagePoint);
5700 var point = initialInfo.point;
5701 var timestamp = getFrameData().timestamp;
5702 this.history = [__assign(__assign({}, point), { timestamp: timestamp })];
5703 var onSessionStart = handlers.onSessionStart;
5704 onSessionStart &&
5705 onSessionStart(event, getPanInfo(initialInfo, this.history));
5706 var removeOnPointerMove = addPointerEvent(window, "pointermove", function (event, info) { return _this.handlePointerMove(event, info); });
5707 var removeOnPointerUp = addPointerEvent(window, "pointerup", function (event, info) { return _this.handlePointerUp(event, info); });
5708 this.removeListeners = function () {
5709 removeOnPointerMove && removeOnPointerMove();
5710 removeOnPointerUp && removeOnPointerUp();
5711 };
5712 }
5713 PanSession.prototype.handlePointerMove = function (event, info) {
5714 this.lastMoveEvent = event;
5715 this.lastMoveEventInfo = transformPoint(info, this.transformPagePoint);
5716 // Because Safari doesn't trigger mouseup events when it's above a `<select>`
5717 if (isMouseEvent(event) && event.buttons === 0) {
5718 this.handlePointerUp(event, info);
5719 return;
5720 }
5721 // Throttle mouse move event to once per frame
5722 sync.update(this.updatePoint, true);
5723 };
5724 PanSession.prototype.handlePointerUp = function (event, info) {
5725 this.end();
5726 var onEnd = this.handlers.onEnd;
5727 if (!onEnd)
5728 return;
5729 var panInfo = getPanInfo(transformPoint(info, this.transformPagePoint), this.history);
5730 onEnd && onEnd(event, panInfo);
5731 };
5732 PanSession.prototype.updateHandlers = function (handlers) {
5733 this.handlers = handlers;
5734 };
5735 PanSession.prototype.end = function () {
5736 this.removeListeners && this.removeListeners();
5737 cancelSync.update(this.updatePoint);
5738 unblockViewportScroll();
5739 };
5740 return PanSession;
5741 }());
5742 function transformPoint(info, transformPagePoint) {
5743 return transformPagePoint ? { point: transformPagePoint(info.point) } : info;
5744 }
5745 function getPanInfo(_a, history) {
5746 var point = _a.point;
5747 return {
5748 point: point,
5749 delta: Point.subtract(point, lastDevicePoint(history)),
5750 offset: Point.subtract(point, startDevicePoint(history)),
5751 velocity: getVelocity$1(history, 0.1),
5752 };
5753 }
5754 function startDevicePoint(history) {
5755 return history[0];
5756 }
5757 function lastDevicePoint(history) {
5758 return history[history.length - 1];
5759 }
5760 function getVelocity$1(history, timeDelta) {
5761 if (history.length < 2) {
5762 return { x: 0, y: 0 };
5763 }
5764 var i = history.length - 1;
5765 var timestampedPoint = null;
5766 var lastPoint = lastDevicePoint(history);
5767 while (i >= 0) {
5768 timestampedPoint = history[i];
5769 if (lastPoint.timestamp - timestampedPoint.timestamp >
5770 secondsToMilliseconds(timeDelta)) {
5771 break;
5772 }
5773 i--;
5774 }
5775 if (!timestampedPoint) {
5776 return { x: 0, y: 0 };
5777 }
5778 var time = (lastPoint.timestamp - timestampedPoint.timestamp) / 1000;
5779 if (time === 0) {
5780 return { x: 0, y: 0 };
5781 }
5782 var currentVelocity = {
5783 x: (lastPoint.x - timestampedPoint.x) / time,
5784 y: (lastPoint.y - timestampedPoint.y) / time,
5785 };
5786 if (currentVelocity.x === Infinity) {
5787 currentVelocity.x = 0;
5788 }
5789 if (currentVelocity.y === Infinity) {
5790 currentVelocity.y = 0;
5791 }
5792 return currentVelocity;
5793 }
5794
5795 /**
5796 * Apply constraints to a point. These constraints are both physical along an
5797 * axis, and an elastic factor that determines how much to constrain the point
5798 * by if it does lie outside the defined parameters.
5799 */
5800 function applyConstraints(point, _a, elastic) {
5801 var min = _a.min, max = _a.max;
5802 if (min !== undefined && point < min) {
5803 // If we have a min point defined, and this is outside of that, constrain
5804 point = elastic ? mix(min, point, elastic) : Math.max(point, min);
5805 }
5806 else if (max !== undefined && point > max) {
5807 // If we have a max point defined, and this is outside of that, constrain
5808 point = elastic ? mix(max, point, elastic) : Math.min(point, max);
5809 }
5810 return point;
5811 }
5812 /**
5813 * Calculates a min projection point based on a pointer, pointer progress
5814 * within the drag target, and constraints.
5815 *
5816 * For instance if an element was 100px width, we were dragging from 0.25
5817 * along this axis, the pointer is at 200px, and there were no constraints,
5818 * we would calculate a min projection point of 175px.
5819 */
5820 function calcConstrainedMinPoint(point, length, progress, constraints, elastic) {
5821 // Calculate a min point for this axis and apply it to the current pointer
5822 var min = point - length * progress;
5823 return constraints ? applyConstraints(min, constraints, elastic) : min;
5824 }
5825 /**
5826 * Calculate constraints in terms of the viewport when
5827 * defined relatively to the measured axis.
5828 */
5829 function calcRelativeAxisConstraints(axis, min, max) {
5830 var constraints = {};
5831 var length = axis.max - axis.min;
5832 if (min !== undefined) {
5833 constraints.min = axis.min + min;
5834 }
5835 if (max !== undefined) {
5836 constraints.max = Math.max(axis.min + max - length, axis.min);
5837 }
5838 return constraints;
5839 }
5840 /**
5841 * Calculate constraints in terms of the viewport when
5842 * defined relatively to the measured bounding box.
5843 */
5844 function calcRelativeConstraints(layoutBox, _a) {
5845 var top = _a.top, left = _a.left, bottom = _a.bottom, right = _a.right;
5846 return {
5847 x: calcRelativeAxisConstraints(layoutBox.x, left, right),
5848 y: calcRelativeAxisConstraints(layoutBox.y, top, bottom),
5849 };
5850 }
5851 /**
5852 * Calculate viewport constraints when defined as another viewport-relative axis
5853 */
5854 function calcViewportAxisConstraints(layoutAxis, constraintsAxis) {
5855 var _a;
5856 var min = constraintsAxis.min - layoutAxis.min;
5857 var max = constraintsAxis.max - layoutAxis.max;
5858 // If the constraints axis is actually smaller than the layout axis then we can
5859 // flip the constraints
5860 if (constraintsAxis.max - constraintsAxis.min <
5861 layoutAxis.max - layoutAxis.min) {
5862 _a = [max, min], min = _a[0], max = _a[1];
5863 }
5864 return {
5865 min: layoutAxis.min + min,
5866 max: layoutAxis.min + max,
5867 };
5868 }
5869 /**
5870 * Calculate viewport constraints when defined as another viewport-relative box
5871 */
5872 function calcViewportConstraints(layoutBox, constraintsBox) {
5873 return {
5874 x: calcViewportAxisConstraints(layoutBox.x, constraintsBox.x),
5875 y: calcViewportAxisConstraints(layoutBox.y, constraintsBox.y),
5876 };
5877 }
5878 /**
5879 * Calculate the an axis position based on two axes and a progress value.
5880 */
5881 function calcPositionFromProgress(axis, constraints, progress) {
5882 var axisLength = axis.max - axis.min;
5883 var min = mix(constraints.min, constraints.max - axisLength, progress);
5884 return { min: min, max: min + axisLength };
5885 }
5886
5887 var elementDragControls = new WeakMap();
5888 /**
5889 *
5890 */
5891 var lastPointerEvent;
5892 var VisualElementDragControls = /** @class */ (function () {
5893 function VisualElementDragControls(_a) {
5894 var visualElement = _a.visualElement;
5895 /**
5896 * Track whether we're currently dragging.
5897 *
5898 * @internal
5899 */
5900 this.isDragging = false;
5901 /**
5902 * The current direction of drag, or `null` if both.
5903 *
5904 * @internal
5905 */
5906 this.currentDirection = null;
5907 /**
5908 * The permitted boundaries of travel, in pixels.
5909 *
5910 * @internal
5911 */
5912 this.constraints = false;
5913 /**
5914 * A reference to the host component's latest props.
5915 *
5916 * @internal
5917 */
5918 this.props = {};
5919 /**
5920 * Track the initial position of the cursor relative to the dragging element
5921 * when dragging starts as a value of 0-1 on each axis. We then use this to calculate
5922 * an ideal bounding box for the VisualElement renderer to project into every frame.
5923 *
5924 * @internal
5925 */
5926 this.cursorProgress = {
5927 x: 0.5,
5928 y: 0.5,
5929 };
5930 // This is a reference to the global drag gesture lock, ensuring only one component
5931 // can "capture" the drag of one or both axes.
5932 // TODO: Look into moving this into pansession?
5933 this.openGlobalLock = null;
5934 /**
5935 * @internal
5936 */
5937 this.panSession = null;
5938 this.visualElement = visualElement;
5939 this.visualElement.enableLayoutProjection();
5940 elementDragControls.set(visualElement, this);
5941 }
5942 /**
5943 * Instantiate a PanSession for the drag gesture
5944 *
5945 * @public
5946 */
5947 VisualElementDragControls.prototype.start = function (originEvent, _a) {
5948 var _this = this;
5949 var _b = _a === void 0 ? {} : _a, _c = _b.snapToCursor, snapToCursor = _c === void 0 ? false : _c, cursorProgress = _b.cursorProgress;
5950 /**
5951 * If this drag session has been manually triggered by the user, it might be from an event
5952 * outside the draggable element. If snapToCursor is set to true, we need to measure the position
5953 * of the element and snap it to the cursor.
5954 */
5955 snapToCursor && this.snapToCursor(originEvent);
5956 var onSessionStart = function () {
5957 // Initiate viewport scroll blocking on touch start. This is a very aggressive approach
5958 // which has come out of the difficulty in us being able to do this once a scroll gesture
5959 // has initiated in mobile browsers. This means if there's a horizontally-scrolling carousel
5960 // on a page we can't let a user scroll the page itself from it. Ideally what we'd do is
5961 // trigger this once we've got a scroll direction determined. This approach sort-of worked
5962 // but if the component was dragged too far in a single frame page scrolling would initiate.
5963 blockViewportScroll();
5964 // Stop any animations on both axis values immediately. This allows the user to throw and catch
5965 // the component.
5966 _this.stopMotion();
5967 };
5968 var onStart = function (event, info) {
5969 var _a, _b;
5970 // Attempt to grab the global drag gesture lock - maybe make this part of PanSession
5971 var _c = _this.props, drag = _c.drag, dragPropagation = _c.dragPropagation;
5972 if (drag && !dragPropagation) {
5973 if (_this.openGlobalLock)
5974 _this.openGlobalLock();
5975 _this.openGlobalLock = getGlobalLock(drag);
5976 // If we don 't have the lock, don't start dragging
5977 if (!_this.openGlobalLock)
5978 return;
5979 }
5980 /**
5981 * Record the progress of the mouse within the draggable element on each axis.
5982 * onPan, we're going to use this to calculate a new bounding box for the element to
5983 * project into. This will ensure that even if the DOM element moves via a relayout, it'll
5984 * stick to the correct place under the pointer.
5985 */
5986 _this.prepareBoundingBox();
5987 _this.visualElement.lockTargetBox();
5988 /**
5989 * Resolve the drag constraints. These are either set as top/right/bottom/left constraints
5990 * relative to the element's layout, or a ref to another element. Both need converting to
5991 * viewport coordinates.
5992 */
5993 _this.resolveDragConstraints();
5994 /**
5995 * When dragging starts, we want to find where the cursor is relative to the bounding box
5996 * of the element. Every frame, we calculate a new bounding box using this relative position
5997 * and let the visualElement renderer figure out how to reproject the element into this bounding
5998 * box.
5999 *
6000 * By doing it this way, rather than applying an x/y transform directly to the element,
6001 * we can ensure the component always visually sticks to the cursor as we'd expect, even
6002 * if the DOM element itself changes layout as a result of React updates the user might
6003 * make based on the drag position.
6004 */
6005 var point = getViewportPointFromEvent(event).point;
6006 eachAxis(function (axis) {
6007 var _a = _this.visualElement.targetBox[axis], min = _a.min, max = _a.max;
6008 _this.cursorProgress[axis] = cursorProgress
6009 ? cursorProgress[axis]
6010 : progress(min, max, point[axis]);
6011 });
6012 // Set current drag status
6013 _this.isDragging = true;
6014 _this.currentDirection = null;
6015 // Fire onDragStart event
6016 (_b = (_a = _this.props).onDragStart) === null || _b === void 0 ? void 0 : _b.call(_a, event, info);
6017 };
6018 var onMove = function (event, info) {
6019 var _a, _b, _c, _d;
6020 var _e = _this.props, dragPropagation = _e.dragPropagation, dragDirectionLock = _e.dragDirectionLock;
6021 // If we didn't successfully receive the gesture lock, early return.
6022 if (!dragPropagation && !_this.openGlobalLock)
6023 return;
6024 var offset = info.offset;
6025 // Attempt to detect drag direction if directionLock is true
6026 if (dragDirectionLock && _this.currentDirection === null) {
6027 _this.currentDirection = getCurrentDirection(offset);
6028 // If we've successfully set a direction, notify listener
6029 if (_this.currentDirection !== null) {
6030 (_b = (_a = _this.props).onDirectionLock) === null || _b === void 0 ? void 0 : _b.call(_a, _this.currentDirection);
6031 }
6032 return;
6033 }
6034 // Update each point with the latest position
6035 _this.updateAxis("x", event);
6036 _this.updateAxis("y", event);
6037 // Fire onDrag event
6038 (_d = (_c = _this.props).onDrag) === null || _d === void 0 ? void 0 : _d.call(_c, event, info);
6039 // Update the last pointer event
6040 lastPointerEvent = event;
6041 };
6042 var onEnd = function (event, info) { return _this.stop(event, info); };
6043 var transformPagePoint = this.props.transformPagePoint;
6044 this.panSession = new PanSession(originEvent, {
6045 onSessionStart: onSessionStart,
6046 onStart: onStart,
6047 onMove: onMove,
6048 onEnd: onEnd,
6049 }, { transformPagePoint: transformPagePoint });
6050 };
6051 /**
6052 * Ensure the component's layout and target bounding boxes are up-to-date.
6053 */
6054 VisualElementDragControls.prototype.prepareBoundingBox = function () {
6055 var element = this.visualElement.getInstance();
6056 var transform = element.style.transform;
6057 this.visualElement.resetTransform();
6058 this.visualElement.measureLayout();
6059 element.style.transform = transform;
6060 this.visualElement.refreshTargetBox();
6061 };
6062 VisualElementDragControls.prototype.resolveDragConstraints = function () {
6063 var dragConstraints = this.props.dragConstraints;
6064 if (dragConstraints) {
6065 this.constraints = isRefObject(dragConstraints)
6066 ? this.resolveRefConstraints(this.visualElement.box, dragConstraints)
6067 : calcRelativeConstraints(this.visualElement.box, dragConstraints);
6068 }
6069 else {
6070 this.constraints = false;
6071 }
6072 };
6073 VisualElementDragControls.prototype.resolveRefConstraints = function (layoutBox, constraints) {
6074 var _a = this.props, onMeasureDragConstraints = _a.onMeasureDragConstraints, transformPagePoint = _a.transformPagePoint;
6075 var constraintsElement = constraints.current;
6076 invariant(constraintsElement !== null, "If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.");
6077 this.constraintsBox = getBoundingBox(constraintsElement, transformPagePoint);
6078 var measuredConstraints = calcViewportConstraints(layoutBox, this.constraintsBox);
6079 /**
6080 * If there's an onMeasureDragConstraints listener we call it and
6081 * if different constraints are returned, set constraints to that
6082 */
6083 if (onMeasureDragConstraints) {
6084 var userConstraints = onMeasureDragConstraints(convertAxisBoxToBoundingBox(measuredConstraints));
6085 if (userConstraints) {
6086 measuredConstraints = convertBoundingBoxToAxisBox(userConstraints);
6087 }
6088 }
6089 return measuredConstraints;
6090 };
6091 VisualElementDragControls.prototype.cancelDrag = function () {
6092 unblockViewportScroll();
6093 this.isDragging = false;
6094 this.panSession && this.panSession.end();
6095 this.panSession = null;
6096 if (!this.props.dragPropagation && this.openGlobalLock) {
6097 this.openGlobalLock();
6098 this.openGlobalLock = null;
6099 }
6100 };
6101 VisualElementDragControls.prototype.stop = function (event, info) {
6102 var _a;
6103 this.visualElement.unlockTargetBox();
6104 (_a = this.panSession) === null || _a === void 0 ? void 0 : _a.end();
6105 this.panSession = null;
6106 var isDragging = this.isDragging;
6107 this.cancelDrag();
6108 if (!isDragging)
6109 return;
6110 var _b = this.props, dragMomentum = _b.dragMomentum, dragElastic = _b.dragElastic, onDragEnd = _b.onDragEnd;
6111 if (dragMomentum || dragElastic) {
6112 var velocity = info.velocity;
6113 this.animateDragEnd(velocity);
6114 }
6115 onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(event, info);
6116 };
6117 VisualElementDragControls.prototype.snapToCursor = function (event) {
6118 this.prepareBoundingBox();
6119 this.cursorProgress.x = 0.5;
6120 this.cursorProgress.y = 0.5;
6121 this.updateAxis("x", event);
6122 this.updateAxis("y", event);
6123 };
6124 /**
6125 * Update the specified axis with the latest pointer information.
6126 */
6127 VisualElementDragControls.prototype.updateAxis = function (axis, event) {
6128 var _a;
6129 var _b = this.props, drag = _b.drag, dragElastic = _b.dragElastic;
6130 // If we're not dragging this axis, do an early return.
6131 if (!shouldDrag(axis, drag, this.currentDirection))
6132 return;
6133 // Get the actual layout bounding box of the element
6134 var axisLayout = this.visualElement.box[axis];
6135 // Calculate its current length. In the future we might want to lerp this to animate
6136 // between lengths if the layout changes as we change the DOM
6137 var axisLength = axisLayout.max - axisLayout.min;
6138 // Get the initial progress that the pointer sat on this axis on gesture start.
6139 var axisProgress = this.cursorProgress[axis];
6140 var point = getViewportPointFromEvent(event).point;
6141 // Calculate a new min point based on the latest pointer position, constraints and elastic
6142 var min = calcConstrainedMinPoint(point[axis], axisLength, axisProgress, (_a = this.constraints) === null || _a === void 0 ? void 0 : _a[axis], dragElastic);
6143 // Update the axis viewport target with this new min and the length
6144 this.visualElement.setAxisTarget(axis, min, min + axisLength);
6145 };
6146 VisualElementDragControls.prototype.updateProps = function (_a) {
6147 var _b = _a.drag, drag = _b === void 0 ? false : _b, _c = _a.dragDirectionLock, dragDirectionLock = _c === void 0 ? false : _c, _d = _a.dragPropagation, dragPropagation = _d === void 0 ? false : _d, _e = _a.dragConstraints, dragConstraints = _e === void 0 ? false : _e, _f = _a.dragElastic, dragElastic = _f === void 0 ? 0.35 : _f, _g = _a.dragMomentum, dragMomentum = _g === void 0 ? true : _g, remainingProps = __rest(_a, ["drag", "dragDirectionLock", "dragPropagation", "dragConstraints", "dragElastic", "dragMomentum"]);
6148 this.props = __assign({ drag: drag,
6149 dragDirectionLock: dragDirectionLock,
6150 dragPropagation: dragPropagation,
6151 dragConstraints: dragConstraints,
6152 dragElastic: dragElastic,
6153 dragMomentum: dragMomentum }, remainingProps);
6154 };
6155 VisualElementDragControls.prototype.animateDragEnd = function (velocity) {
6156 var _this = this;
6157 var _a = this.props, drag = _a.drag, dragMomentum = _a.dragMomentum, dragElastic = _a.dragElastic, dragTransition = _a.dragTransition;
6158 var momentumAnimations = eachAxis(function (axis) {
6159 if (!shouldDrag(axis, drag, _this.currentDirection)) {
6160 return;
6161 }
6162 var transition = _this.constraints ? _this.constraints[axis] : {};
6163 /**
6164 * Overdamp the boundary spring if `dragElastic` is disabled. There's still a frame
6165 * of spring animations so we should look into adding a disable spring option to `inertia`.
6166 * We could do something here where we affect the `bounceStiffness` and `bounceDamping`
6167 * using the value of `dragElastic`.
6168 */
6169 var bounceStiffness = dragElastic ? 200 : 1000000;
6170 var bounceDamping = dragElastic ? 40 : 10000000;
6171 var inertia = __assign(__assign({ type: "inertia", velocity: dragMomentum ? velocity[axis] : 0, bounceStiffness: bounceStiffness,
6172 bounceDamping: bounceDamping, timeConstant: 750, restDelta: 1, restSpeed: 10 }, dragTransition), transition);
6173 // If we're not animating on an externally-provided `MotionValue` we can use the
6174 // component's animation controls which will handle interactions with whileHover (etc),
6175 // otherwise we just have to animate the `MotionValue` itself.
6176 return _this.visualElement.startLayoutAxisAnimation(axis, inertia);
6177 });
6178 // Run all animations and then resolve the new drag constraints.
6179 return Promise.all(momentumAnimations).then(function () {
6180 var _a, _b;
6181 (_b = (_a = _this.props).onDragTransitionEnd) === null || _b === void 0 ? void 0 : _b.call(_a);
6182 });
6183 };
6184 VisualElementDragControls.prototype.stopMotion = function () {
6185 this.visualElement.stopLayoutAnimation();
6186 };
6187 VisualElementDragControls.prototype.scalePoint = function () {
6188 var _this = this;
6189 var _a = this.props, drag = _a.drag, dragConstraints = _a.dragConstraints;
6190 if (!isRefObject(dragConstraints) || !this.constraintsBox)
6191 return;
6192 // Stop any current animations as there can be some visual glitching if we resize mid animation
6193 this.stopMotion();
6194 // Record the relative progress of the targetBox relative to the constraintsBox
6195 var boxProgress = { x: 0, y: 0 };
6196 eachAxis(function (axis) {
6197 boxProgress[axis] = calcOrigin(_this.visualElement.targetBox[axis], _this.constraintsBox[axis]);
6198 });
6199 /**
6200 * For each axis, calculate the current progress of the layout axis within the constraints.
6201 * Then, using the latest layout and constraints measurements, reposition the new layout axis
6202 * proportionally within the constraints.
6203 */
6204 this.prepareBoundingBox();
6205 this.resolveDragConstraints();
6206 eachAxis(function (axis) {
6207 if (!shouldDrag(axis, drag, null))
6208 return;
6209 // Calculate the position of the targetBox relative to the constraintsBox using the
6210 // previously calculated progress
6211 var _a = calcPositionFromProgress(_this.visualElement.targetBox[axis], _this.constraintsBox[axis], boxProgress[axis]), min = _a.min, max = _a.max;
6212 _this.visualElement.setAxisTarget(axis, min, max);
6213 });
6214 };
6215 VisualElementDragControls.prototype.mount = function (visualElement) {
6216 var _this = this;
6217 var element = visualElement.getInstance();
6218 /**
6219 * Attach a pointerdown event listener on this DOM element to initiate drag tracking.
6220 */
6221 var stopPointerListener = addPointerEvent(element, "pointerdown", function (event) {
6222 var _a = _this.props, drag = _a.drag, _b = _a.dragListener, dragListener = _b === void 0 ? true : _b;
6223 drag && dragListener && _this.start(event);
6224 });
6225 /**
6226 * Attach a window resize listener to scale the draggable target within its defined
6227 * constraints as the window resizes.
6228 */
6229 var stopResizeListener = addDomEvent(window, "resize", function () {
6230 _this.scalePoint();
6231 });
6232 /**
6233 * Ensure drag constraints are resolved correctly relative to the dragging element
6234 * whenever its layout changes.
6235 */
6236 var stopLayoutUpdateListener = visualElement.onLayoutUpdate(function () {
6237 if (_this.isDragging)
6238 _this.resolveDragConstraints();
6239 });
6240 /**
6241 * If the previous component with this same layoutId was dragging at the time
6242 * it was unmounted, we want to continue the same gesture on this component.
6243 */
6244 var prevSnapshot = visualElement.prevSnapshot;
6245 (prevSnapshot === null || prevSnapshot === void 0 ? void 0 : prevSnapshot.isDragging) &&
6246 this.start(lastPointerEvent, {
6247 cursorProgress: prevSnapshot.cursorProgress,
6248 });
6249 /**
6250 * Return a function that will teardown the drag gesture
6251 */
6252 return function () {
6253 stopPointerListener === null || stopPointerListener === void 0 ? void 0 : stopPointerListener();
6254 stopResizeListener === null || stopResizeListener === void 0 ? void 0 : stopResizeListener();
6255 stopLayoutUpdateListener === null || stopLayoutUpdateListener === void 0 ? void 0 : stopLayoutUpdateListener();
6256 _this.cancelDrag();
6257 };
6258 };
6259 return VisualElementDragControls;
6260 }());
6261 function shouldDrag(direction, drag, currentDirection) {
6262 return ((drag === true || drag === direction) &&
6263 (currentDirection === null || currentDirection === direction));
6264 }
6265 /**
6266 * Based on an x/y offset determine the current drag direction. If both axis' offsets are lower
6267 * than the provided threshold, return `null`.
6268 *
6269 * @param offset - The x/y offset from origin.
6270 * @param lockThreshold - (Optional) - the minimum absolute offset before we can determine a drag direction.
6271 */
6272 function getCurrentDirection(offset, lockThreshold) {
6273 if (lockThreshold === void 0) { lockThreshold = 10; }
6274 var direction = null;
6275 if (Math.abs(offset.y) > lockThreshold) {
6276 direction = "y";
6277 }
6278 else if (Math.abs(offset.x) > lockThreshold) {
6279 direction = "x";
6280 }
6281 return direction;
6282 }
6283
6284 /**
6285 * A hook that allows an element to be dragged.
6286 *
6287 * @internal
6288 */
6289 function useDrag(props, visualElement) {
6290 var groupDragControls = props.dragControls;
6291 var transformPagePoint = React.useContext(MotionConfigContext).transformPagePoint;
6292 var dragControls = useConstant(function () {
6293 return new VisualElementDragControls({
6294 visualElement: visualElement,
6295 });
6296 });
6297 dragControls.updateProps(__assign(__assign({}, props), { transformPagePoint: transformPagePoint }));
6298 // If we've been provided a DragControls for manual control over the drag gesture,
6299 // subscribe this component to it on mount.
6300 React.useEffect(function () { return groupDragControls && groupDragControls.subscribe(dragControls); }, [dragControls]);
6301 // Mount the drag controls with the visualElement
6302 React.useEffect(function () { return dragControls.mount(visualElement); }, []);
6303 }
6304
6305 var makeRenderlessComponent = function (hook) { return function (props) {
6306 hook(props);
6307 return null;
6308 }; };
6309
6310 var Component = makeRenderlessComponent(function (_a) {
6311 var visualElement = _a.visualElement, props = __rest(_a, ["visualElement"]);
6312 return useDrag(props, visualElement);
6313 });
6314 /**
6315 * @public
6316 */
6317 var Drag = {
6318 key: "drag",
6319 shouldRender: function (props) { return !!props.drag; },
6320 getComponent: function () { return Component; },
6321 };
6322
6323 /**
6324 *
6325 * @param handlers -
6326 * @param ref -
6327 *
6328 * @internalremarks
6329 * Currently this sets new pan gesture functions every render. The memo route has been explored
6330 * in the past but ultimately we're still creating new functions every render. An optimisation
6331 * to explore is creating the pan gestures and loading them into a `ref`.
6332 *
6333 * @internal
6334 */
6335 function usePanGesture(_a, ref) {
6336 var onPan = _a.onPan, onPanStart = _a.onPanStart, onPanEnd = _a.onPanEnd, onPanSessionStart = _a.onPanSessionStart;
6337 var hasPanEvents = onPan || onPanStart || onPanEnd || onPanSessionStart;
6338 var panSession = React.useRef(null);
6339 var transformPagePoint = React.useContext(MotionConfigContext).transformPagePoint;
6340 var handlers = {
6341 onSessionStart: onPanSessionStart,
6342 onStart: onPanStart,
6343 onMove: onPan,
6344 onEnd: function (event, info) {
6345 panSession.current = null;
6346 onPanEnd && onPanEnd(event, info);
6347 },
6348 };
6349 React.useEffect(function () {
6350 if (panSession.current !== null) {
6351 panSession.current.updateHandlers(handlers);
6352 }
6353 });
6354 function onPointerDown(event) {
6355 panSession.current = new PanSession(event, handlers, {
6356 transformPagePoint: transformPagePoint,
6357 });
6358 }
6359 usePointerEvent(ref, "pointerdown", hasPanEvents && onPointerDown);
6360 useUnmountEffect(function () { return panSession.current && panSession.current.end(); });
6361 }
6362
6363 /**
6364 * Recursively traverse up the tree to check whether the provided child node
6365 * is the parent or a descendant of it.
6366 *
6367 * @param parent - Element to find
6368 * @param child - Element to test against parent
6369 */
6370 var isNodeOrChild = function (parent, child) {
6371 if (!child) {
6372 return false;
6373 }
6374 else if (parent === child) {
6375 return true;
6376 }
6377 else {
6378 return isNodeOrChild(parent, child.parentElement);
6379 }
6380 };
6381
6382 var order$1 = ["whileHover", "whileTap", "whileDrag"];
6383 var getGesturePriority = function (gesture) {
6384 return order$1.indexOf(gesture) + 1;
6385 };
6386
6387 var tapGesturePriority = getGesturePriority("whileTap");
6388 /**
6389 * @param handlers -
6390 * @internal
6391 */
6392 function useTapGesture(_a, ref) {
6393 var onTap = _a.onTap, onTapStart = _a.onTapStart, onTapCancel = _a.onTapCancel, whileTap = _a.whileTap, controls = _a.controls;
6394 var hasTapListeners = onTap || onTapStart || onTapCancel || whileTap;
6395 var isTapping = React.useRef(false);
6396 var cancelPointerEventListener = React.useRef(null);
6397 function removePointerUp() {
6398 cancelPointerEventListener.current &&
6399 cancelPointerEventListener.current();
6400 cancelPointerEventListener.current = null;
6401 }
6402 if (whileTap && controls) {
6403 controls.setOverride(whileTap, tapGesturePriority);
6404 }
6405 // We load this event handler into a ref so we can later refer to
6406 // onPointerUp.current which will always have reference to the latest props
6407 var onPointerUp = React.useRef(null);
6408 onPointerUp.current = function (event, info) {
6409 var element = ref.current;
6410 removePointerUp();
6411 if (!isTapping.current || !element)
6412 return;
6413 isTapping.current = false;
6414 if (controls && whileTap) {
6415 controls.clearOverride(tapGesturePriority);
6416 }
6417 // Check the gesture lock - if we get it, it means no drag gesture is active
6418 // and we can safely fire the tap gesture.
6419 var openGestureLock = getGlobalLock(true);
6420 if (!openGestureLock)
6421 return;
6422 openGestureLock();
6423 if (!isNodeOrChild(element, event.target)) {
6424 onTapCancel && onTapCancel(event, info);
6425 }
6426 else {
6427 onTap && onTap(event, info);
6428 }
6429 };
6430 function onPointerDown(event, info) {
6431 removePointerUp();
6432 cancelPointerEventListener.current = addPointerEvent(window, "pointerup", function (event, info) { return onPointerUp.current(event, info); });
6433 var element = ref.current;
6434 if (!element || isTapping.current)
6435 return;
6436 isTapping.current = true;
6437 onTapStart && onTapStart(event, info);
6438 if (controls && whileTap) {
6439 controls.startOverride(tapGesturePriority);
6440 }
6441 }
6442 usePointerEvent(ref, "pointerdown", hasTapListeners ? onPointerDown : undefined);
6443 useUnmountEffect(removePointerUp);
6444 }
6445
6446 var hoverPriority = getGesturePriority("whileHover");
6447 var filterTouch = function (listener) { return function (event, info) {
6448 if (isMouseEvent(event))
6449 listener(event, info);
6450 }; };
6451 /**
6452 *
6453 * @param props
6454 * @param ref
6455 * @internal
6456 */
6457 function useHoverGesture(_a, ref) {
6458 var whileHover = _a.whileHover, onHoverStart = _a.onHoverStart, onHoverEnd = _a.onHoverEnd, controls = _a.controls;
6459 if (whileHover && controls) {
6460 controls.setOverride(whileHover, hoverPriority);
6461 }
6462 usePointerEvent(ref, "pointerenter", filterTouch(function (event, info) {
6463 if (onHoverStart)
6464 onHoverStart(event, info);
6465 if (whileHover && controls) {
6466 controls.startOverride(hoverPriority);
6467 }
6468 }));
6469 usePointerEvent(ref, "pointerleave", filterTouch(function (event, info) {
6470 if (onHoverEnd)
6471 onHoverEnd(event, info);
6472 if (whileHover && controls) {
6473 controls.clearOverride(hoverPriority);
6474 }
6475 }));
6476 }
6477
6478 /**
6479 * Add pan and tap gesture recognition to an element.
6480 *
6481 * @param props - Gesture event handlers
6482 * @param ref - React `ref` containing a DOM `Element`
6483 * @public
6484 */
6485 function useGestures(props, ref) {
6486 usePanGesture(props, ref);
6487 useTapGesture(props, ref);
6488 useHoverGesture(props, ref);
6489 }
6490
6491 var gestureProps = [
6492 "onPan",
6493 "onPanStart",
6494 "onPanEnd",
6495 "onPanSessionStart",
6496 "onTap",
6497 "onTapStart",
6498 "onTapCancel",
6499 "whileTap",
6500 "whileHover",
6501 "onHoverStart",
6502 "onHoverEnd",
6503 ];
6504 var GestureComponent = makeRenderlessComponent(function (_a) {
6505 var visualElement = _a.visualElement, props = __rest(_a, ["visualElement"]);
6506 useGestures(props, visualElement);
6507 });
6508 /**
6509 * @public
6510 */
6511 var Gestures = {
6512 key: "gestures",
6513 shouldRender: function (props) {
6514 return gestureProps.some(function (key) { return props.hasOwnProperty(key); });
6515 },
6516 getComponent: function () { return GestureComponent; },
6517 };
6518
6519 var ExitComponent = makeRenderlessComponent(function (props) {
6520 var animate = props.animate, controls = props.controls, exit = props.exit;
6521 var _a = usePresence(), isPresent = _a[0], onExitComplete = _a[1];
6522 var presenceContext = React.useContext(PresenceContext);
6523 var isPlayingExitAnimation = React.useRef(false);
6524 var custom = (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.custom) !== undefined
6525 ? presenceContext.custom
6526 : props.custom;
6527 React.useEffect(function () {
6528 if (!isPresent) {
6529 if (!isPlayingExitAnimation.current && exit) {
6530 controls.setProps(__assign(__assign({}, props), { custom: custom }));
6531 controls.start(exit).then(onExitComplete);
6532 }
6533 isPlayingExitAnimation.current = true;
6534 }
6535 else if (isPlayingExitAnimation.current &&
6536 animate &&
6537 typeof animate !== "boolean" &&
6538 !(animate instanceof AnimationControls)) {
6539 controls.start(animate);
6540 }
6541 if (isPresent) {
6542 isPlayingExitAnimation.current = false;
6543 }
6544 }, [animate, controls, custom, exit, isPresent, onExitComplete, props]);
6545 });
6546 /**
6547 * @public
6548 */
6549 var Exit = {
6550 key: "exit",
6551 shouldRender: function (props) { return !!props.exit && !checkShouldInheritVariant(props); },
6552 getComponent: function () { return ExitComponent; },
6553 };
6554
6555 var AnimatePropType;
6556 (function (AnimatePropType) {
6557 AnimatePropType["Target"] = "Target";
6558 AnimatePropType["VariantLabel"] = "VariantLabel";
6559 AnimatePropType["AnimationSubscription"] = "AnimationSubscription";
6560 })(AnimatePropType || (AnimatePropType = {}));
6561
6562 function shallowCompare(next, prev) {
6563 if (prev === null)
6564 return false;
6565 var prevLength = prev.length;
6566 if (prevLength !== next.length)
6567 return false;
6568 for (var i = 0; i < prevLength; i++) {
6569 if (prev[i] !== next[i])
6570 return false;
6571 }
6572 return true;
6573 }
6574
6575 var hasUpdated = function (prev, next) {
6576 return (next !== undefined &&
6577 (Array.isArray(prev) && Array.isArray(next)
6578 ? !shallowCompare(next, prev)
6579 : prev !== next));
6580 };
6581 function targetWithoutTransition(_a, mergeTransitionEnd) {
6582 if (mergeTransitionEnd === void 0) { mergeTransitionEnd = false; }
6583 var transition = _a.transition, transitionEnd = _a.transitionEnd, target = __rest(_a, ["transition", "transitionEnd"]);
6584 return mergeTransitionEnd
6585 ? __assign(__assign({}, target), transitionEnd)
6586 : target;
6587 }
6588 /**
6589 * Handle the `animate` prop when its an object of values, ie:
6590 *
6591 * ```jsx
6592 * <motion.div animate={{ opacity: 1 }} />
6593 * ```
6594 *
6595 * @internalremarks
6596 * It might be worth consolidating this with `use-variants`
6597 *
6598 * ```jsx
6599 * <motion.div animate="visible" />
6600 * ```
6601 *
6602 * @param target
6603 * @param controls
6604 * @param values
6605 * @param transition
6606 *
6607 * @internal
6608 */
6609 function useAnimateProp(targetAndTransition, controls, visualElement, defaultTransition) {
6610 var isInitialRender = React.useRef(true);
6611 var prevValues = React.useRef(null);
6612 if (!prevValues.current) {
6613 prevValues.current = targetWithoutTransition(targetAndTransition, true);
6614 }
6615 React.useEffect(function () {
6616 var targetToAnimate = {};
6617 // These are the values we're actually animating
6618 var animatingTarget = targetWithoutTransition(targetAndTransition);
6619 // This is the target as it'll be once transitionEnd values are applied
6620 var finalTarget = targetWithoutTransition(targetAndTransition, true);
6621 // Detect which values have changed between renders
6622 for (var key in animatingTarget) {
6623 // This value should animate on mount if this value doesn't already exist (wasn't
6624 // defined in `style` or `initial`) or if it does exist and it's already changed.
6625 var shouldAnimateOnMount = isInitialRender.current &&
6626 (!visualElement.hasValue(key) ||
6627 visualElement.getValue(key).get() !== finalTarget[key]);
6628 // If this value has updated between renders or it's we're animating this value on mount,
6629 // add it to the animate target.
6630 var isValidValue = finalTarget[key] !== null;
6631 var valueHasUpdated = hasUpdated(prevValues.current[key], finalTarget[key]);
6632 if (isValidValue && (valueHasUpdated || shouldAnimateOnMount)) {
6633 targetToAnimate[key] = animatingTarget[key];
6634 }
6635 }
6636 isInitialRender.current = false;
6637 prevValues.current = __assign(__assign({}, prevValues.current), finalTarget);
6638 if (Object.keys(targetToAnimate).length) {
6639 controls.start(__assign(__assign({}, targetToAnimate), { transition: targetAndTransition.transition || defaultTransition, transitionEnd: targetAndTransition.transitionEnd }));
6640 }
6641 }, [targetAndTransition]);
6642 }
6643
6644 var labelsToArray = function (label) {
6645 if (!label) {
6646 return [];
6647 }
6648 if (Array.isArray(label)) {
6649 return label;
6650 }
6651 return [label];
6652 };
6653 var resolveVariantLabels = function (variant) {
6654 var unresolvedVariant = variant instanceof MotionValue ? variant.get() : variant;
6655 return Array.from(new Set(labelsToArray(unresolvedVariant)));
6656 };
6657 /**
6658 * Hooks in React sometimes accept a dependency array as their final argument. (ie useEffect/useMemo)
6659 * When values in this array change, React re-runs the dependency. However if the array
6660 * contains a variable number of items, React throws an error.
6661 */
6662 var asDependencyList = function (list) { return [
6663 list.join(","),
6664 ]; };
6665
6666 var hasVariantChanged = function (oldVariant, newVariant) {
6667 return oldVariant.join(",") !== newVariant.join(",");
6668 };
6669 /**
6670 * Handle variants and the `animate` prop when its set as variant labels.
6671 *
6672 * @param initial - Initial variant(s)
6673 * @param animate - Variant(s) to animate to
6674 * @param inherit - `true` is inheriting animations from parent
6675 * @param controls - Animation controls
6676 *
6677 * @internal
6678 */
6679 function useVariants(initial, animate, inherit, controls) {
6680 var targetVariants = resolveVariantLabels(animate);
6681 var context = React.useContext(MotionContext);
6682 var parentAlreadyMounted = context.hasMounted && context.hasMounted.current;
6683 var hasMounted = React.useRef(false);
6684 React.useEffect(function () {
6685 var shouldAnimate = false;
6686 if (inherit) {
6687 // If we're inheriting variant changes and the parent has already
6688 // mounted when this component loads, we need to manually trigger
6689 // this animation.
6690 shouldAnimate = !!parentAlreadyMounted;
6691 targetVariants = resolveVariantLabels(context.animate);
6692 }
6693 else {
6694 shouldAnimate =
6695 hasMounted.current ||
6696 hasVariantChanged(resolveVariantLabels(initial), targetVariants);
6697 }
6698 shouldAnimate && controls.start(targetVariants);
6699 hasMounted.current = true;
6700 }, asDependencyList(targetVariants));
6701 }
6702
6703 /**
6704 * `useAnimationGroupSubscription` allows a component to subscribe to an
6705 * externally-created `AnimationControls`, created by the `useAnimation` hook.
6706 *
6707 * @param animation
6708 * @param controls
6709 *
6710 * @internal
6711 */
6712 function useAnimationGroupSubscription(animation, controls) {
6713 var unsubscribe = React.useMemo(function () { return animation.subscribe(controls); }, [
6714 animation,
6715 ]);
6716 React.useEffect(function () { return function () {
6717 unsubscribe && unsubscribe();
6718 }; }, [unsubscribe]);
6719 }
6720
6721 var _a$1, _b;
6722 var AnimatePropComponents = (_a$1 = {},
6723 _a$1[AnimatePropType.Target] = makeRenderlessComponent(function (_a) {
6724 var animate = _a.animate, controls = _a.controls, visualElement = _a.visualElement, transition = _a.transition;
6725 return useAnimateProp(animate, controls, visualElement, transition);
6726 }),
6727 _a$1[AnimatePropType.VariantLabel] = makeRenderlessComponent(function (_a) {
6728 var animate = _a.animate, _b = _a.inherit, inherit = _b === void 0 ? true : _b, controls = _a.controls, initial = _a.initial;
6729 return useVariants(initial, animate, inherit, controls);
6730 }),
6731 _a$1[AnimatePropType.AnimationSubscription] = makeRenderlessComponent(function (_a) {
6732 var animate = _a.animate, controls = _a.controls;
6733 return useAnimationGroupSubscription(animate, controls);
6734 }),
6735 _a$1);
6736 var isVariantLabel$1 = function (prop) {
6737 return Array.isArray(prop) || typeof prop === "string";
6738 };
6739 var isAnimationSubscription = function (_a) {
6740 var animate = _a.animate;
6741 return animate instanceof AnimationControls;
6742 };
6743 var animationProps = ["initial", "animate", "whileTap", "whileHover"];
6744 var animatePropTypeTests = (_b = {},
6745 _b[AnimatePropType.Target] = function (props) {
6746 return (props.animate !== undefined &&
6747 !isVariantLabel$1(props.animate) &&
6748 !isAnimationSubscription(props));
6749 },
6750 _b[AnimatePropType.VariantLabel] = function (props) {
6751 return (props.variants !== undefined ||
6752 animationProps.some(function (key) { return typeof props[key] === "string"; }));
6753 },
6754 _b[AnimatePropType.AnimationSubscription] = isAnimationSubscription,
6755 _b);
6756 var getAnimationComponent = function (props) {
6757 var animatePropType = undefined;
6758 for (var key in AnimatePropType) {
6759 if (animatePropTypeTests[key](props)) {
6760 animatePropType = key;
6761 }
6762 }
6763 return animatePropType ? AnimatePropComponents[animatePropType] : undefined;
6764 };
6765 /**
6766 * @public
6767 */
6768 var Animation = {
6769 key: "animation",
6770 shouldRender: function () { return true; },
6771 getComponent: getAnimationComponent,
6772 };
6773
6774 function tweenAxis(target, prev, next, p) {
6775 target.min = mix(prev.min, next.min, p);
6776 target.max = mix(prev.max, next.max, p);
6777 }
6778
6779 var progressTarget = 1000;
6780 var Animate = /** @class */ (function (_super) {
6781 __extends(Animate, _super);
6782 function Animate() {
6783 var _this = _super !== null && _super.apply(this, arguments) || this;
6784 _this.frameTarget = {
6785 x: { min: 0, max: 0 },
6786 y: { min: 0, max: 0 },
6787 };
6788 _this.stopAxisAnimation = {
6789 x: undefined,
6790 y: undefined,
6791 };
6792 _this.animate = function (target, origin, _a) {
6793 if (_a === void 0) { _a = {}; }
6794 var originBox = _a.originBox, targetBox = _a.targetBox, visibilityAction = _a.visibilityAction, config = __rest(_a, ["originBox", "targetBox", "visibilityAction"]);
6795 var _b = _this.props, visualElement = _b.visualElement, layout = _b.layout;
6796 /**
6797 * Allow the measured origin (prev bounding box) and target (actual layout) to be
6798 * overridden by the provided config.
6799 */
6800 origin = originBox || origin;
6801 target = targetBox || target;
6802 var boxHasMoved = hasMoved(origin, target);
6803 var animations = eachAxis(function (axis) {
6804 /**
6805 * If layout is set to "position", we can resize the origin box based on the target
6806 * box and only animate its position.
6807 */
6808 if (layout === "position") {
6809 var targetLength = target[axis].max - target[axis].min;
6810 origin[axis].max = origin[axis].min + targetLength;
6811 }
6812 if (visualElement.isTargetBoxLocked) {
6813 return;
6814 }
6815 else if (visibilityAction !== undefined) {
6816 // If we're meant to show/hide the visualElement, do so
6817 visibilityAction === VisibilityAction.Hide
6818 ? visualElement.hide()
6819 : visualElement.show();
6820 }
6821 else if (boxHasMoved) {
6822 // If the box has moved, animate between it's current visual state and its
6823 // final state
6824 return _this.animateAxis(axis, target[axis], origin[axis], config);
6825 }
6826 else {
6827 // If the box has remained in the same place, immediately set the axis target
6828 // to the final desired state
6829 return visualElement.setAxisTarget(axis, target[axis].min, target[axis].max);
6830 }
6831 });
6832 // Force a render to ensure there's no flash of uncorrected bounding box.
6833 visualElement.render();
6834 /**
6835 * If this visualElement isn't present (ie it's been removed from the tree by the user but
6836 * kept in by the tree by AnimatePresence) then call safeToRemove when all axis animations
6837 * have successfully finished.
6838 */
6839 return Promise.all(animations).then(function () {
6840 var _a, _b;
6841 (_b = (_a = _this.props).onLayoutAnimationComplete) === null || _b === void 0 ? void 0 : _b.call(_a);
6842 if (visualElement.isPresent) {
6843 visualElement.presence = Presence.Present;
6844 }
6845 else {
6846 _this.safeToRemove();
6847 }
6848 });
6849 };
6850 return _this;
6851 }
6852 Animate.prototype.componentDidMount = function () {
6853 var visualElement = this.props.visualElement;
6854 visualElement.enableLayoutProjection();
6855 this.unsubLayoutReady = visualElement.onLayoutUpdate(this.animate);
6856 };
6857 Animate.prototype.componentWillUnmount = function () {
6858 var _this = this;
6859 this.unsubLayoutReady();
6860 eachAxis(function (axis) { var _a, _b; return (_b = (_a = _this.stopAxisAnimation)[axis]) === null || _b === void 0 ? void 0 : _b.call(_a); });
6861 };
6862 /**
6863 * TODO: This manually performs animations on the visualElement's layout progress
6864 * values. It'd be preferable to amend the HTMLVisualElement.startLayoutAxisAnimation
6865 * API to accept more custom animations like this.
6866 */
6867 Animate.prototype.animateAxis = function (axis, target, origin, _a) {
6868 var _b, _c;
6869 var _d = _a === void 0 ? {} : _a, transition = _d.transition, crossfadeOpacity = _d.crossfadeOpacity;
6870 (_c = (_b = this.stopAxisAnimation)[axis]) === null || _c === void 0 ? void 0 : _c.call(_b);
6871 var visualElement = this.props.visualElement;
6872 var frameTarget = this.frameTarget[axis];
6873 var layoutProgress = visualElement.axisProgress[axis];
6874 /**
6875 * Set layout progress back to 0. We set it twice to hard-reset any velocity that might
6876 * be re-incoporated into a subsequent spring animation.
6877 */
6878 layoutProgress.clearListeners();
6879 layoutProgress.set(0);
6880 layoutProgress.set(0);
6881 /**
6882 * If this is a crossfade animation, create a function that updates both the opacity of this component
6883 * and the one being crossfaded out.
6884 */
6885 var crossfade = crossfadeOpacity && this.createCrossfadeAnimation(crossfadeOpacity);
6886 /**
6887 * Create an animation function to run once per frame. This will tween the visual bounding box from
6888 * origin to target using the latest progress value.
6889 */
6890 var frame = function () {
6891 // Convert the latest layoutProgress, which is a value from 0-1000, into a 0-1 progress
6892 var p = layoutProgress.get() / progressTarget;
6893 // Tween the axis and update the visualElement with the latest values
6894 tweenAxis(frameTarget, origin, target, p);
6895 visualElement.setAxisTarget(axis, frameTarget.min, frameTarget.max);
6896 // If this is a crossfade animation, update both elements.
6897 crossfade === null || crossfade === void 0 ? void 0 : crossfade(p);
6898 };
6899 // Synchronously run a frame to ensure there's no flash of the uncorrected bounding box.
6900 frame();
6901 // Start the animation on this axis
6902 var animation = startAnimation(axis === "x" ? "layoutX" : "layoutY", layoutProgress, progressTarget, transition || this.props.transition || defaultTransition);
6903 // Create a function to stop animation on this specific axis
6904 var unsubscribeProgress = layoutProgress.onChange(frame);
6905 this.stopAxisAnimation[axis] = function () {
6906 layoutProgress.stop();
6907 unsubscribeProgress();
6908 };
6909 return animation;
6910 };
6911 Animate.prototype.createCrossfadeAnimation = function (crossfadeOpacity) {
6912 var visualElement = this.props.visualElement;
6913 var opacity = visualElement.getValue("opacity", 0);
6914 return function (p) {
6915 opacity.set(easeCrossfadeIn(mix(0, 1, p)));
6916 crossfadeOpacity.set(easeCrossfadeOut(mix(1, 0, p)));
6917 };
6918 };
6919 Animate.prototype.safeToRemove = function () {
6920 var _a, _b;
6921 (_b = (_a = this.props).safeToRemove) === null || _b === void 0 ? void 0 : _b.call(_a);
6922 };
6923 Animate.prototype.render = function () {
6924 return null;
6925 };
6926 return Animate;
6927 }(React.Component));
6928 function AnimateLayoutContextProvider(props) {
6929 var _a = usePresence(), safeToRemove = _a[1];
6930 return React.createElement(Animate, __assign({}, props, { safeToRemove: safeToRemove }));
6931 }
6932 function hasMoved(a, b) {
6933 return hasAxisMoved(a.x, b.x) || hasAxisMoved(a.y, b.y);
6934 }
6935 function hasAxisMoved(a, b) {
6936 return a.min !== b.min || a.max !== b.max;
6937 }
6938 var defaultTransition = {
6939 duration: 0.45,
6940 ease: [0.4, 0, 0.1, 1],
6941 };
6942 function compress(min, max, easing) {
6943 return function (p) {
6944 // Could replace ifs with clamp
6945 if (p < min)
6946 return 0;
6947 if (p > max)
6948 return 1;
6949 return easing(progress(min, max, p));
6950 };
6951 }
6952 var easeCrossfadeIn = compress(0, 0.5, circOut);
6953 var easeCrossfadeOut = compress(0.5, 0.95, linear);
6954 /**
6955 * @public
6956 */
6957 var AnimateLayout = {
6958 key: "animate-layout",
6959 shouldRender: function (props) { return !!props.layout || !!props.layoutId; },
6960 getComponent: function () { return AnimateLayoutContextProvider; },
6961 };
6962
6963 /**
6964 * This component is responsible for scheduling the measuring of the motion component
6965 */
6966 var Measure = /** @class */ (function (_super) {
6967 __extends(Measure, _super);
6968 function Measure(props) {
6969 var _this = _super.call(this, props) || this;
6970 /**
6971 * If this component isn't the child of a SyncContext, make it responsible for flushing
6972 * the layout batcher
6973 */
6974 var syncLayout = props.syncLayout;
6975 if (!isSharedLayout(syncLayout)) {
6976 _this.componentDidUpdate = function () { return syncLayout.flush(); };
6977 }
6978 return _this;
6979 }
6980 /**
6981 * If this is a child of a SyncContext, register the VisualElement with it on mount.
6982 */
6983 Measure.prototype.componentDidMount = function () {
6984 var _a = this.props, syncLayout = _a.syncLayout, visualElement = _a.visualElement;
6985 isSharedLayout(syncLayout) && syncLayout.register(visualElement);
6986 };
6987 /**
6988 * If this is a child of a SyncContext, notify it that it needs to re-render. It will then
6989 * handle the snapshotting.
6990 *
6991 * If it is stand-alone component, add it to the batcher.
6992 */
6993 Measure.prototype.getSnapshotBeforeUpdate = function () {
6994 var _a = this.props, syncLayout = _a.syncLayout, visualElement = _a.visualElement;
6995 if (isSharedLayout(syncLayout)) {
6996 syncLayout.syncUpdate();
6997 }
6998 else {
6999 visualElement.snapshotBoundingBox();
7000 syncLayout.add(visualElement);
7001 }
7002 return null;
7003 };
7004 Measure.prototype.componentDidUpdate = function () { };
7005 Measure.prototype.render = function () {
7006 return null;
7007 };
7008 return Measure;
7009 }(React__default.Component));
7010 function MeasureContextProvider(props) {
7011 var syncLayout = React.useContext(SharedLayoutContext);
7012 return React__default.createElement(Measure, __assign({}, props, { syncLayout: syncLayout }));
7013 }
7014 var MeasureLayout = {
7015 key: "measure-layout",
7016 shouldRender: function (props) {
7017 return !!props.drag || !!props.layout || !!props.layoutId;
7018 },
7019 getComponent: function () { return MeasureContextProvider; },
7020 };
7021
7022 /**
7023 * Convert any React component into a `motion` component. The provided component
7024 * **must** use `React.forwardRef` to the underlying DOM component you want to animate.
7025 *
7026 * ```jsx
7027 * const Component = React.forwardRef((props, ref) => {
7028 * return <div ref={ref} />
7029 * })
7030 *
7031 * const MotionComponent = motion.custom(Component)
7032 * ```
7033 *
7034 * @public
7035 */
7036 function createMotionProxy(defaultFeatures) {
7037 var config = {
7038 defaultFeatures: defaultFeatures,
7039 useVisualElement: useDomVisualElement,
7040 render: render,
7041 animationControlsConfig: {
7042 makeTargetAnimatable: parseDomVariant,
7043 },
7044 };
7045 function custom(Component) {
7046 return createMotionComponent(Component, config);
7047 }
7048 var componentCache = new Map();
7049 function get(target, key) {
7050 if (key === "custom")
7051 return target.custom;
7052 if (!componentCache.has(key)) {
7053 componentCache.set(key, createMotionComponent(key, config));
7054 }
7055 return componentCache.get(key);
7056 }
7057 return new Proxy({ custom: custom }, { get: get });
7058 }
7059 /**
7060 * HTML & SVG components, optimised for use with gestures and animation. These can be used as
7061 * drop-in replacements for any HTML & SVG component, all CSS & SVG properties are supported.
7062 *
7063 * @public
7064 */
7065 var motion = /*@__PURE__*/ createMotionProxy([
7066 MeasureLayout,
7067 Animation,
7068 Drag,
7069 Gestures,
7070 Exit,
7071 AnimateLayout,
7072 ]);
7073 /**
7074 * @public
7075 */
7076 var m = /*@__PURE__*/ createMotionProxy([MeasureLayout]);
7077
7078 function useForceUpdate() {
7079 var _a = React.useState(0), forcedRenderCount = _a[0], setForcedRenderCount = _a[1];
7080 return React.useCallback(function () { return setForcedRenderCount(forcedRenderCount + 1); }, [
7081 forcedRenderCount,
7082 ]);
7083 }
7084
7085 var presenceId = 0;
7086 function getPresenceId() {
7087 var id = presenceId;
7088 presenceId++;
7089 return id;
7090 }
7091 var PresenceChild = function (_a) {
7092 var children = _a.children, initial = _a.initial, isPresent = _a.isPresent, onExitComplete = _a.onExitComplete, custom = _a.custom;
7093 var presenceChildren = useConstant(newChildrenMap);
7094 var context = {
7095 id: useConstant(getPresenceId),
7096 initial: initial,
7097 isPresent: isPresent,
7098 custom: custom,
7099 onExitComplete: function (childId) {
7100 presenceChildren.set(childId, true);
7101 var allComplete = true;
7102 presenceChildren.forEach(function (isComplete) {
7103 if (!isComplete)
7104 allComplete = false;
7105 });
7106 allComplete && (onExitComplete === null || onExitComplete === void 0 ? void 0 : onExitComplete());
7107 },
7108 register: function (childId) {
7109 presenceChildren.set(childId, false);
7110 return function () { return presenceChildren.delete(childId); };
7111 },
7112 };
7113 React.useMemo(function () {
7114 presenceChildren.forEach(function (_, key) { return presenceChildren.set(key, false); });
7115 }, [isPresent]);
7116 return (React.createElement(PresenceContext.Provider, { value: context }, children));
7117 };
7118 function newChildrenMap() {
7119 return new Map();
7120 }
7121
7122 function getChildKey(child) {
7123 return child.key || "";
7124 }
7125 function updateChildLookup(children, allChildren) {
7126 var seenChildren = new Set() ;
7127 children.forEach(function (child) {
7128 var key = getChildKey(child);
7129 if ( seenChildren) {
7130 if (seenChildren.has(key)) {
7131 console.warn("Children of AnimatePresence require unique keys. \"" + key + "\" is a duplicate.");
7132 }
7133 seenChildren.add(key);
7134 }
7135 allChildren.set(key, child);
7136 });
7137 }
7138 function onlyElements(children) {
7139 var filtered = [];
7140 // We use forEach here instead of map as map mutates the component key by preprending `.$`
7141 React.Children.forEach(children, function (child) {
7142 if (React.isValidElement(child))
7143 filtered.push(child);
7144 });
7145 return filtered;
7146 }
7147 /**
7148 * `AnimatePresence` enables the animation of components that have been removed from the tree.
7149 *
7150 * When adding/removing more than a single child, every child **must** be given a unique `key` prop.
7151 *
7152 * @library
7153 *
7154 * Any `Frame` components that have an `exit` property defined will animate out when removed from
7155 * the tree.
7156 *
7157 * ```jsx
7158 * import { Frame, AnimatePresence } from 'framer'
7159 *
7160 * // As items are added and removed from `items`
7161 * export function Items({ items }) {
7162 * return (
7163 * <AnimatePresence>
7164 * {items.map(item => (
7165 * <Frame
7166 * key={item.id}
7167 * initial={{ opacity: 0 }}
7168 * animate={{ opacity: 1 }}
7169 * exit={{ opacity: 0 }}
7170 * />
7171 * ))}
7172 * </AnimatePresence>
7173 * )
7174 * }
7175 * ```
7176 *
7177 * You can sequence exit animations throughout a tree using variants.
7178 *
7179 * @motion
7180 *
7181 * Any `motion` components that have an `exit` property defined will animate out when removed from
7182 * the tree.
7183 *
7184 * ```jsx
7185 * import { motion, AnimatePresence } from 'framer-motion'
7186 *
7187 * export const Items = ({ items }) => (
7188 * <AnimatePresence>
7189 * {items.map(item => (
7190 * <motion.div
7191 * key={item.id}
7192 * initial={{ opacity: 0 }}
7193 * animate={{ opacity: 1 }}
7194 * exit={{ opacity: 0 }}
7195 * />
7196 * ))}
7197 * </AnimatePresence>
7198 * )
7199 * ```
7200 *
7201 * You can sequence exit animations throughout a tree using variants.
7202 *
7203 * If a child contains multiple `motion` components with `exit` props, it will only unmount the child
7204 * once all `motion` components have finished animating out. Likewise, any components using
7205 * `usePresence` all need to call `safeToRemove`.
7206 *
7207 * @public
7208 */
7209 var AnimatePresence = function (_a) {
7210 var children = _a.children, custom = _a.custom, _b = _a.initial, initial = _b === void 0 ? true : _b, onExitComplete = _a.onExitComplete, exitBeforeEnter = _a.exitBeforeEnter;
7211 // We want to force a re-render once all exiting animations have finished. We
7212 // either use a local forceRender function, or one from a parent context if it exists.
7213 var forceRender = useForceUpdate();
7214 var layoutContext = React.useContext(SharedLayoutContext);
7215 if (isSharedLayout(layoutContext)) {
7216 forceRender = layoutContext.forceUpdate;
7217 }
7218 var isInitialRender = React.useRef(true);
7219 // Filter out any children that aren't ReactElements. We can only track ReactElements with a props.key
7220 var filteredChildren = onlyElements(children);
7221 // Keep a living record of the children we're actually rendering so we
7222 // can diff to figure out which are entering and exiting
7223 var presentChildren = React.useRef(filteredChildren);
7224 // A lookup table to quickly reference components by key
7225 var allChildren = React.useRef(new Map())
7226 .current;
7227 // A living record of all currently exiting components.
7228 var exiting = React.useRef(new Set()).current;
7229 updateChildLookup(filteredChildren, allChildren);
7230 // If this is the initial component render, just deal with logic surrounding whether
7231 // we play onMount animations or not.
7232 if (isInitialRender.current) {
7233 isInitialRender.current = false;
7234 return (React.createElement(React.Fragment, null, filteredChildren.map(function (child) { return (React.createElement(PresenceChild, { key: getChildKey(child), isPresent: true, initial: initial ? undefined : false }, child)); })));
7235 }
7236 // If this is a subsequent render, deal with entering and exiting children
7237 var childrenToRender = __spreadArrays(filteredChildren);
7238 // Diff the keys of the currently-present and target children to update our
7239 // exiting list.
7240 var presentKeys = presentChildren.current.map(getChildKey);
7241 var targetKeys = filteredChildren.map(getChildKey);
7242 // Diff the present children with our target children and mark those that are exiting
7243 var numPresent = presentKeys.length;
7244 for (var i = 0; i < numPresent; i++) {
7245 var key = presentKeys[i];
7246 if (targetKeys.indexOf(key) === -1) {
7247 exiting.add(key);
7248 }
7249 else {
7250 // In case this key has re-entered, remove from the exiting list
7251 exiting.delete(key);
7252 }
7253 }
7254 // If we currently have exiting children, and we're deferring rendering incoming children
7255 // until after all current children have exiting, empty the childrenToRender array
7256 if (exitBeforeEnter && exiting.size) {
7257 childrenToRender = [];
7258 }
7259 // Loop through all currently exiting components and clone them to overwrite `animate`
7260 // with any `exit` prop they might have defined.
7261 exiting.forEach(function (key) {
7262 // If this component is actually entering again, early return
7263 if (targetKeys.indexOf(key) !== -1)
7264 return;
7265 var child = allChildren.get(key);
7266 if (!child)
7267 return;
7268 var insertionIndex = presentKeys.indexOf(key);
7269 var onExit = function () {
7270 allChildren.delete(key);
7271 exiting.delete(key);
7272 // Remove this child from the present children
7273 var removeIndex = presentChildren.current.findIndex(function (presentChild) { return presentChild.key === key; });
7274 presentChildren.current.splice(removeIndex, 1);
7275 // Defer re-rendering until all exiting children have indeed left
7276 if (!exiting.size) {
7277 presentChildren.current = filteredChildren;
7278 forceRender();
7279 onExitComplete && onExitComplete();
7280 }
7281 };
7282 childrenToRender.splice(insertionIndex, 0, React.createElement(PresenceChild, { key: getChildKey(child), isPresent: false, onExitComplete: onExit, custom: custom }, child));
7283 });
7284 // Add `MotionContext` even to children that don't need it to ensure we're rendering
7285 // the same tree between renders
7286 childrenToRender = childrenToRender.map(function (child) {
7287 var key = child.key;
7288 return exiting.has(key) ? (child) : (React.createElement(PresenceChild, { key: getChildKey(child), isPresent: true }, child));
7289 });
7290 presentChildren.current = childrenToRender;
7291 if (
7292 exitBeforeEnter &&
7293 childrenToRender.length > 1) {
7294 console.warn("You're attempting to animate multiple children within AnimatePresence, but its exitBeforeEnter prop is set to true. This will lead to odd visual behaviour.");
7295 }
7296 return (React.createElement(React.Fragment, null, exiting.size
7297 ? childrenToRender
7298 : childrenToRender.map(function (child) { return React.cloneElement(child); })));
7299 };
7300
7301 function createSwitchAnimation(child, stack) {
7302 if (stack && child !== stack.lead) {
7303 return { visibilityAction: VisibilityAction.Hide };
7304 }
7305 else if (stack &&
7306 child.presence !== Presence.Entering &&
7307 child === stack.lead &&
7308 stack.lead !== stack.prevLead) {
7309 return { visibilityAction: VisibilityAction.Show };
7310 }
7311 var originBox;
7312 var targetBox;
7313 if (child.presence === Presence.Entering) {
7314 originBox = stack === null || stack === void 0 ? void 0 : stack.getFollowOrigin();
7315 }
7316 else if (child.presence === Presence.Exiting) {
7317 targetBox = stack === null || stack === void 0 ? void 0 : stack.getFollowTarget();
7318 }
7319 return { originBox: originBox, targetBox: targetBox };
7320 }
7321 function createCrossfadeAnimation(child, stack) {
7322 var _a, _b, _c;
7323 var config = {};
7324 var stackLead = stack && stack.lead;
7325 var stackLeadPresence = stackLead === null || stackLead === void 0 ? void 0 : stackLead.presence;
7326 if (stack && child === stackLead) {
7327 if (child.presence === Presence.Entering) {
7328 config.originBox = stack.getFollowOrigin();
7329 }
7330 else if (child.presence === Presence.Exiting) {
7331 config.targetBox = stack.getFollowTarget();
7332 }
7333 }
7334 else if (stack && child === stack.follow) {
7335 config.transition = stack.getLeadTransition();
7336 if (stackLeadPresence === Presence.Entering) {
7337 config.targetBox = stack.getLeadTarget();
7338 }
7339 else if (stackLeadPresence === Presence.Exiting) {
7340 config.originBox = stack.getLeadOrigin();
7341 }
7342 }
7343 // If neither the lead or follow component is the root child of AnimatePresence,
7344 // don't handle crossfade animations
7345 if (!((_a = stack === null || stack === void 0 ? void 0 : stack.follow) === null || _a === void 0 ? void 0 : _a.isPresenceRoot) && !(stackLead === null || stackLead === void 0 ? void 0 : stackLead.isPresenceRoot)) {
7346 return config;
7347 }
7348 if (!stack || child === stackLead) {
7349 if (child.presence === Presence.Entering) {
7350 config.crossfadeOpacity = (_b = stack === null || stack === void 0 ? void 0 : stack.follow) === null || _b === void 0 ? void 0 : _b.getValue("opacity", 0);
7351 }
7352 }
7353 else if (stack && child === stack.follow) {
7354 if (!stackLead || stackLeadPresence === Presence.Entering) ;
7355 else if (stackLeadPresence === Presence.Exiting) {
7356 config.crossfadeOpacity = (_c = stack === null || stack === void 0 ? void 0 : stack.lead) === null || _c === void 0 ? void 0 : _c.getValue("opacity", 1);
7357 }
7358 }
7359 else {
7360 config.visibilityAction = VisibilityAction.Hide;
7361 }
7362 return config;
7363 }
7364
7365 /**
7366 * For each layout animation, we want to identify two components
7367 * within a stack that will serve as the "lead" and "follow" components.
7368 *
7369 * In the switch animation, the lead component performs the entire animation.
7370 * It uses the follow bounding box to animate out from and back to. The follow
7371 * component is hidden.
7372 *
7373 * In the crossfade animation, both the lead and follow components perform
7374 * the entire animation, animating from the follow origin bounding box to the lead
7375 * target bounding box.
7376 *
7377 * Generalising a stack as First In Last Out, *searching from the end* we can
7378 * generally consider the lead component to be:
7379 * - If the last child is present, the last child
7380 * - If the last child is exiting, the last *encountered* exiting component
7381 */
7382 function findLeadAndFollow(stack, _a) {
7383 var prevLead = _a[0], prevFollow = _a[1];
7384 var lead = undefined;
7385 var leadIndex = 0;
7386 var follow = undefined;
7387 // Find the lead child first
7388 var numInStack = stack.length;
7389 var lastIsPresent = false;
7390 for (var i = numInStack - 1; i >= 0; i--) {
7391 var child = stack[i];
7392 var isLastInStack = i === numInStack - 1;
7393 if (isLastInStack)
7394 lastIsPresent = child.isPresent;
7395 if (lastIsPresent) {
7396 lead = child;
7397 }
7398 else {
7399 // If the child before this will be present, make this the
7400 // lead.
7401 var prev = stack[i - 1];
7402 if (prev && prev.isPresent)
7403 lead = child;
7404 }
7405 if (lead) {
7406 leadIndex = i;
7407 break;
7408 }
7409 }
7410 if (!lead)
7411 lead = stack[0];
7412 // Find the follow child
7413 follow = stack[leadIndex - 1];
7414 // If the lead component is exiting, find the closest follow
7415 // present component
7416 if (lead) {
7417 for (var i = leadIndex - 1; i >= 0; i--) {
7418 var child = stack[i];
7419 if (child.isPresent) {
7420 follow = child;
7421 break;
7422 }
7423 }
7424 }
7425 // If the lead has changed and the previous lead still exists in the
7426 // stack, set it to the previous lead. This allows us to differentiate between
7427 // a, b, c(exit) -> a, b(exit), c(exit)
7428 // and
7429 // a, b(exit), c -> a, b(exit), c(exit)
7430 if (lead !== prevLead &&
7431 !lastIsPresent &&
7432 follow === prevFollow &&
7433 stack.find(function (stackChild) { return stackChild === prevLead; })) {
7434 lead = prevLead;
7435 }
7436 return [lead, follow];
7437 }
7438 var LayoutStack = /** @class */ (function () {
7439 function LayoutStack() {
7440 this.order = [];
7441 // Track whether we've ever had a child
7442 this.hasChildren = false;
7443 }
7444 LayoutStack.prototype.add = function (child) {
7445 var _a;
7446 var layoutOrder = child.config.layoutOrder;
7447 if (layoutOrder === undefined) {
7448 this.order.push(child);
7449 }
7450 else {
7451 var index = this.order.findIndex(function (stackChild) {
7452 return layoutOrder <= (stackChild.config.layoutOrder || 0);
7453 });
7454 if (index === -1) {
7455 child.presence = this.hasChildren
7456 ? Presence.Entering
7457 : Presence.Present;
7458 index = this.order.length;
7459 }
7460 this.order.splice(index, 0, child);
7461 }
7462 /**
7463 *
7464 */
7465 // Load previous values from snapshot into this child
7466 // TODO Neaten up
7467 // TODO Double check when reimplementing move
7468 // TODO Add isDragging status and
7469 if (this.snapshot) {
7470 child.prevSnapshot = this.snapshot;
7471 // TODO Remove in favour of above
7472 child.prevViewportBox = this.snapshot.boundingBox;
7473 var latest = this.snapshot.latestMotionValues;
7474 for (var key in latest) {
7475 if (!child.hasValue(key)) {
7476 child.addValue(key, motionValue(latest[key]));
7477 }
7478 else {
7479 (_a = child.getValue(key)) === null || _a === void 0 ? void 0 : _a.set(latest[key]);
7480 }
7481 }
7482 }
7483 this.hasChildren = true;
7484 };
7485 LayoutStack.prototype.remove = function (child) {
7486 var index = this.order.findIndex(function (stackChild) { return child === stackChild; });
7487 if (index !== -1)
7488 this.order.splice(index, 1);
7489 };
7490 LayoutStack.prototype.updateLeadAndFollow = function () {
7491 this.prevLead = this.lead;
7492 this.prevFollow = this.follow;
7493 var _a = findLeadAndFollow(this.order, [
7494 this.lead,
7495 this.follow,
7496 ]), lead = _a[0], follow = _a[1];
7497 this.lead = lead;
7498 this.follow = follow;
7499 };
7500 LayoutStack.prototype.updateSnapshot = function () {
7501 if (!this.lead)
7502 return;
7503 var snapshot = {
7504 boundingBox: this.lead.prevViewportBox,
7505 latestMotionValues: {},
7506 };
7507 this.lead.forEachValue(function (value, key) {
7508 var latest = value.get();
7509 if (!isTransformProp(latest)) {
7510 snapshot.latestMotionValues[key] = latest;
7511 }
7512 });
7513 var dragControls = elementDragControls.get(this.lead);
7514 if (dragControls && dragControls.isDragging) {
7515 snapshot.isDragging = true;
7516 snapshot.cursorProgress = dragControls.cursorProgress;
7517 }
7518 this.snapshot = snapshot;
7519 };
7520 LayoutStack.prototype.isLeadPresent = function () {
7521 var _a;
7522 return this.lead && ((_a = this.lead) === null || _a === void 0 ? void 0 : _a.presence) !== Presence.Exiting;
7523 };
7524 LayoutStack.prototype.shouldStackAnimate = function () {
7525 return true;
7526 // return this.lead && this.lead?.isPresent
7527 // ? this.lead?.props?._shouldAnimate === true
7528 // : this.follow && this.follow?.props._shouldAnimate === true
7529 };
7530 LayoutStack.prototype.getFollowOrigin = function () {
7531 var _a;
7532 // This shouldAnimate check is quite specifically a fix for the optimisation made in Framer
7533 // where components are kept in the tree ready to be re-used
7534 return this.follow // && this.follow.shouldAnimate
7535 ? this.follow.prevViewportBox
7536 : (_a = this.snapshot) === null || _a === void 0 ? void 0 : _a.boundingBox;
7537 };
7538 LayoutStack.prototype.getFollowTarget = function () {
7539 var _a;
7540 return (_a = this.follow) === null || _a === void 0 ? void 0 : _a.box;
7541 };
7542 LayoutStack.prototype.getLeadOrigin = function () {
7543 var _a;
7544 return (_a = this.lead) === null || _a === void 0 ? void 0 : _a.prevViewportBox;
7545 };
7546 LayoutStack.prototype.getLeadTarget = function () {
7547 var _a;
7548 return (_a = this.lead) === null || _a === void 0 ? void 0 : _a.box;
7549 };
7550 LayoutStack.prototype.getLeadTransition = function () {
7551 var _a;
7552 return (_a = this.lead) === null || _a === void 0 ? void 0 : _a.config.transition;
7553 };
7554 return LayoutStack;
7555 }());
7556
7557 /**
7558 * @public
7559 */
7560 var AnimateSharedLayout = /** @class */ (function (_super) {
7561 __extends(AnimateSharedLayout, _super);
7562 function AnimateSharedLayout() {
7563 var _this = _super !== null && _super.apply(this, arguments) || this;
7564 /**
7565 * A list of all the children in the shared layout
7566 */
7567 _this.children = new Set();
7568 /**
7569 * As animate components with a defined `layoutId` are added/removed to the tree,
7570 * we store them in order. When one is added, it will animate out from the
7571 * previous one, and when it's removed, it'll animate to the previous one.
7572 */
7573 _this.stacks = new Map();
7574 /**
7575 * Track whether the component has mounted. If it hasn't, the presence of added children
7576 * are set to Present, whereas if it has they're considered Entering
7577 */
7578 _this.hasMounted = false;
7579 /**
7580 * Track whether we already have an update scheduled. If we don't, we'll run snapshots
7581 * and schedule one.
7582 */
7583 _this.updateScheduled = false;
7584 /**
7585 * Tracks whether we already have a render scheduled. If we don't, we'll force one with this.forceRender
7586 */
7587 _this.renderScheduled = false;
7588 /**
7589 * The methods provided to all children in the shared layout tree.
7590 */
7591 _this.syncContext = __assign(__assign({}, createBatcher()), { syncUpdate: function (force) { return _this.scheduleUpdate(force); }, forceUpdate: function () {
7592 // By copying syncContext to itself, when this component re-renders it'll also re-render
7593 // all children subscribed to the SharedLayout context.
7594 _this.syncContext = __assign({}, _this.syncContext);
7595 _this.scheduleUpdate(true);
7596 }, register: function (child) { return _this.addChild(child); }, remove: function (child) { return _this.removeChild(child); } });
7597 return _this;
7598 }
7599 AnimateSharedLayout.prototype.componentDidMount = function () {
7600 this.hasMounted = true;
7601 this.updateStacks();
7602 };
7603 AnimateSharedLayout.prototype.componentDidUpdate = function () {
7604 this.startLayoutAnimation();
7605 };
7606 AnimateSharedLayout.prototype.shouldComponentUpdate = function () {
7607 this.renderScheduled = true;
7608 return true;
7609 };
7610 AnimateSharedLayout.prototype.startLayoutAnimation = function () {
7611 var _this = this;
7612 /**
7613 * Reset update and render scheduled status
7614 */
7615 this.renderScheduled = this.updateScheduled = false;
7616 var type = this.props.type;
7617 /**
7618 * Update presence metadata based on the latest AnimatePresence status.
7619 * This is a kind of goofy way of dealing with this, perhaps there's a better model to find.
7620 */
7621 this.children.forEach(function (child) {
7622 if (!child.isPresent) {
7623 child.presence = Presence.Exiting;
7624 }
7625 else if (child.presence !== Presence.Entering) {
7626 child.presence =
7627 child.presence === Presence.Exiting
7628 ? Presence.Entering
7629 : Presence.Present;
7630 }
7631 });
7632 /**
7633 * In every layoutId stack, nominate a component to lead the animation and another
7634 * to follow
7635 */
7636 this.updateStacks();
7637 /**
7638 * Decide which animation to use between shared layoutId components
7639 */
7640 var createAnimation = type === "crossfade"
7641 ? createCrossfadeAnimation
7642 : createSwitchAnimation;
7643 /**
7644 * Create a handler which we can use to flush the children animations
7645 */
7646 var handler = {
7647 measureLayout: function (child) { return child.measureLayout(); },
7648 layoutReady: function (child) {
7649 var layoutId = child.layoutId;
7650 child.layoutReady(createAnimation(child, _this.getStack(layoutId)));
7651 },
7652 };
7653 /**
7654 * Shared layout animations can be used without the AnimateSharedLayout wrapping component.
7655 * This requires some co-ordination across components to stop layout thrashing
7656 * and ensure measurements are taken at the correct time.
7657 *
7658 * Here we use that same mechanism of schedule/flush.
7659 */
7660 this.children.forEach(function (child) { return _this.syncContext.add(child); });
7661 this.syncContext.flush(handler);
7662 /**
7663 * Clear snapshots so subsequent rerenders don't retain memory of outgoing components
7664 */
7665 this.stacks.forEach(function (stack) { return (stack.snapshot = undefined); });
7666 };
7667 AnimateSharedLayout.prototype.updateStacks = function () {
7668 this.stacks.forEach(function (stack) { return stack.updateLeadAndFollow(); });
7669 };
7670 AnimateSharedLayout.prototype.scheduleUpdate = function (force) {
7671 if (force === void 0) { force = false; }
7672 if (!(force || !this.updateScheduled))
7673 return;
7674 /**
7675 * Flag we've scheduled an update
7676 */
7677 this.updateScheduled = true;
7678 /**
7679 * Snapshot children
7680 */
7681 this.children.forEach(function (child) { return child.snapshotBoundingBox(); });
7682 /**
7683 * Every child keeps a local snapshot, but we also want to record
7684 * snapshots of the visible children as, if they're are being removed
7685 * in this render, we can still access them.
7686 */
7687 this.stacks.forEach(function (stack) { return stack.updateSnapshot(); });
7688 /**
7689 * Force a rerender by setting state if we aren't already going to render.
7690 */
7691 if (force || !this.renderScheduled) {
7692 this.renderScheduled = true;
7693 this.forceUpdate();
7694 }
7695 };
7696 AnimateSharedLayout.prototype.addChild = function (child) {
7697 this.children.add(child);
7698 this.addToStack(child);
7699 child.presence = this.hasMounted ? Presence.Entering : Presence.Present;
7700 };
7701 AnimateSharedLayout.prototype.removeChild = function (child) {
7702 this.scheduleUpdate();
7703 this.children.delete(child);
7704 this.removeFromStack(child);
7705 };
7706 AnimateSharedLayout.prototype.addToStack = function (child) {
7707 var stack = this.getStack(child.layoutId);
7708 stack === null || stack === void 0 ? void 0 : stack.add(child);
7709 };
7710 AnimateSharedLayout.prototype.removeFromStack = function (child) {
7711 var stack = this.getStack(child.layoutId);
7712 stack === null || stack === void 0 ? void 0 : stack.remove(child);
7713 };
7714 /**
7715 * Return a stack of animate children based on the provided layoutId.
7716 * Will create a stack if none currently exists with that layoutId.
7717 */
7718 AnimateSharedLayout.prototype.getStack = function (id) {
7719 if (id === undefined)
7720 return;
7721 // Create stack if it doesn't already exist
7722 !this.stacks.has(id) && this.stacks.set(id, new LayoutStack());
7723 return this.stacks.get(id);
7724 };
7725 AnimateSharedLayout.prototype.render = function () {
7726 return (React.createElement(SharedLayoutContext.Provider, { value: this.syncContext }, this.props.children));
7727 };
7728 return AnimateSharedLayout;
7729 }(React.Component));
7730
7731 /**
7732 * Creates a `MotionValue` to track the state and velocity of a value.
7733 *
7734 * Usually, these are created automatically. For advanced use-cases, like use with `useTransform`, you can create `MotionValue`s externally and pass them into the animated component via the `style` prop.
7735 *
7736 * @library
7737 *
7738 * ```jsx
7739 * export function MyComponent() {
7740 * const scale = useMotionValue(1)
7741 *
7742 * return <Frame scale={scale} />
7743 * }
7744 * ```
7745 *
7746 * @motion
7747 *
7748 * ```jsx
7749 * export const MyComponent = () => {
7750 * const scale = useMotionValue(1)
7751 *
7752 * return <motion.div style={{ scale }} />
7753 * }
7754 * ```
7755 *
7756 * @param initial - The initial state.
7757 *
7758 * @public
7759 */
7760 function useMotionValue(initial) {
7761 return useConstant(function () { return motionValue(initial); });
7762 }
7763
7764 /**
7765 * If the provided value is a MotionValue, this returns the actual value, otherwise just the value itself
7766 *
7767 * TODO: Remove and move to library
7768 *
7769 * @internal
7770 */
7771 function resolveMotionValue(value) {
7772 var unwrappedValue = value instanceof MotionValue ? value.get() : value;
7773 return isCustomValue(unwrappedValue)
7774 ? unwrappedValue.toValue()
7775 : unwrappedValue;
7776 }
7777
7778 var isCustomValueType = function (v) {
7779 return typeof v === "object" && v.mix;
7780 };
7781 var getMixer$1 = function (v) { return (isCustomValueType(v) ? v.mix : undefined); };
7782 function transform() {
7783 var args = [];
7784 for (var _i = 0; _i < arguments.length; _i++) {
7785 args[_i] = arguments[_i];
7786 }
7787 var useImmediate = !Array.isArray(args[0]);
7788 var argOffset = useImmediate ? 0 : -1;
7789 var inputValue = args[0 + argOffset];
7790 var inputRange = args[1 + argOffset];
7791 var outputRange = args[2 + argOffset];
7792 var options = args[3 + argOffset];
7793 var interpolator = interpolate(inputRange, outputRange, __assign({ mixer: getMixer$1(outputRange[0]) }, options));
7794 return useImmediate ? interpolator(inputValue) : interpolator;
7795 }
7796
7797 var isTransformer = function (v) {
7798 return typeof v === "function";
7799 };
7800 function useTransform(parent, customTransform, to, options) {
7801 var comparitor = isTransformer(customTransform)
7802 ? [parent]
7803 : [parent, customTransform.join(","), to === null || to === void 0 ? void 0 : to.join(",")];
7804 var transformer = React.useMemo(function () {
7805 return isTransformer(customTransform)
7806 ? customTransform
7807 : transform(customTransform, to, options);
7808 }, comparitor);
7809 var initialValue = transformer(parent.get());
7810 var value = useMotionValue(initialValue);
7811 // Handle subscription to parent
7812 var unsubscribe = React.useRef();
7813 React.useMemo(function () {
7814 unsubscribe.current && unsubscribe.current();
7815 unsubscribe.current = parent.onChange(function (v) { return value.set(transformer(v)); });
7816 // Manually set with the latest parent value in case we've re-parented
7817 value.set(initialValue);
7818 }, [parent, value, transformer]);
7819 useUnmountEffect(function () { return unsubscribe.current && unsubscribe.current(); });
7820 return value;
7821 }
7822
7823 // Keep things reasonable and avoid scale: Infinity. In practise we might need
7824 // to add another value, opacity, that could interpolate scaleX/Y [0,0.01] => [0,1]
7825 // to simply hide content at unreasonable scales.
7826 var maxScale = 100000;
7827 var invertScale = function (scale) {
7828 return scale > 0.001 ? 1 / scale : maxScale;
7829 };
7830 /**
7831 * Returns a `MotionValue` each for `scaleX` and `scaleY` that update with the inverse
7832 * of their respective parent scales.
7833 *
7834 * This is useful for undoing the distortion of content when scaling a parent component.
7835 *
7836 * By default, `useInvertedScale` will automatically fetch `scaleX` and `scaleY` from the nearest parent.
7837 * By passing other `MotionValue`s in as `useInvertedScale({ scaleX, scaleY })`, it will invert the output
7838 * of those instead.
7839 *
7840 * @motion
7841 *
7842 * ```jsx
7843 * const MyComponent = () => {
7844 * const { scaleX, scaleY } = useInvertedScale()
7845 * return <motion.div style={{ scaleX, scaleY }} />
7846 * }
7847 * ```
7848 *
7849 * @library
7850 *
7851 * ```jsx
7852 * function MyComponent() {
7853 * const { scaleX, scaleY } = useInvertedScale()
7854 * return <Frame scaleX={scaleX} scaleY={scaleY} />
7855 * }
7856 * ```
7857 *
7858 * @public
7859 */
7860 function useInvertedScale(scale) {
7861 var parentScaleX = useMotionValue(1);
7862 var parentScaleY = useMotionValue(1);
7863 var visualElement = React.useContext(MotionContext).visualElement;
7864 invariant(!!(scale || visualElement), "If no scale values are provided, useInvertedScale must be used within a child of another motion component.");
7865 if (scale) {
7866 parentScaleX = scale.scaleX || parentScaleX;
7867 parentScaleY = scale.scaleY || parentScaleY;
7868 }
7869 else if (visualElement) {
7870 parentScaleX = visualElement.getValue("scaleX", 1);
7871 parentScaleY = visualElement.getValue("scaleY", 1);
7872 }
7873 var scaleX = useTransform(parentScaleX, invertScale);
7874 var scaleY = useTransform(parentScaleY, invertScale);
7875 return { scaleX: scaleX, scaleY: scaleY };
7876 }
7877
7878 function useOnChange(value, callback) {
7879 React.useEffect(function () { return (isMotionValue(value) ? value.onChange(callback) : undefined); }, [value]);
7880 }
7881
7882 /**
7883 * Creates a `MotionValue` that, when `set`, will use a spring animation to animate to its new state.
7884 *
7885 * It can either work as a stand-alone `MotionValue` by initialising it with a value, or as a subscriber
7886 * to another `MotionValue`.
7887 *
7888 * @remarks
7889 *
7890 * ```jsx
7891 * const x = useSpring(0, { stiffness: 300 })
7892 * const y = useSpring(x, { damping: 10 })
7893 * ```
7894 *
7895 * @param inputValue - `MotionValue` or number. If provided a `MotionValue`, when the input `MotionValue` changes, the created `MotionValue` will spring towards that value.
7896 * @param springConfig - Configuration options for the spring.
7897 * @returns `MotionValue`
7898 *
7899 * @public
7900 */
7901 function useSpring(source, config) {
7902 if (config === void 0) { config = {}; }
7903 var activeSpringAnimation = React.useRef(null);
7904 var value = useMotionValue(isMotionValue(source) ? source.get() : source);
7905 React.useMemo(function () {
7906 return value.attach(function (v, set) {
7907 if (activeSpringAnimation.current) {
7908 activeSpringAnimation.current.stop();
7909 }
7910 activeSpringAnimation.current = vectorSpring(__assign({ from: value.get(), to: v, velocity: value.getVelocity() }, config)).start(set);
7911 return value.get();
7912 });
7913 }, Object.values(config));
7914 useOnChange(source, function (v) { return value.set(parseFloat(v)); });
7915 return value;
7916 }
7917
7918 function createScrollMotionValues() {
7919 return {
7920 scrollX: motionValue(0),
7921 scrollY: motionValue(0),
7922 scrollXProgress: motionValue(0),
7923 scrollYProgress: motionValue(0),
7924 };
7925 }
7926 function setProgress(offset, maxOffset, value) {
7927 value.set(!offset || !maxOffset ? 0 : offset / maxOffset);
7928 }
7929 function createScrollUpdater(values, getOffsets) {
7930 var update = function () {
7931 var _a = getOffsets(), xOffset = _a.xOffset, yOffset = _a.yOffset, xMaxOffset = _a.xMaxOffset, yMaxOffset = _a.yMaxOffset;
7932 // Set absolute positions
7933 values.scrollX.set(xOffset);
7934 values.scrollY.set(yOffset);
7935 // Set 0-1 progress
7936 setProgress(xOffset, xMaxOffset, values.scrollXProgress);
7937 setProgress(yOffset, yMaxOffset, values.scrollYProgress);
7938 };
7939 update();
7940 return update;
7941 }
7942
7943 var isBrowser$2 = typeof window !== "undefined";
7944 var useIsomorphicLayoutEffect = isBrowser$2 ? React.useLayoutEffect : React.useEffect;
7945
7946 var getElementScrollOffsets = function (element) { return function () {
7947 return {
7948 xOffset: element.scrollLeft,
7949 yOffset: element.scrollTop,
7950 xMaxOffset: element.scrollWidth - element.offsetWidth,
7951 yMaxOffset: element.scrollHeight - element.offsetHeight,
7952 };
7953 }; };
7954 /**
7955 * Returns MotionValues that update when the provided element scrolls:
7956 *
7957 * - `scrollX` — Horizontal scroll distance in pixels.
7958 * - `scrollY` — Vertical scroll distance in pixels.
7959 * - `scrollXProgress` — Horizontal scroll progress between `0` and `1`.
7960 * - `scrollYProgress` — Vertical scroll progress between `0` and `1`.
7961 *
7962 * This element must be set to `overflow: scroll` on either or both axes to report scroll offset.
7963 *
7964 * @library
7965 *
7966 * ```jsx
7967 * import * as React from "react"
7968 * import {
7969 * Frame,
7970 * useElementScroll,
7971 * useTransform
7972 * } from "framer"
7973 *
7974 * export function MyComponent() {
7975 * const ref = React.useRef()
7976 * const { scrollYProgress } = useElementScroll(ref)
7977 *
7978 * return (
7979 * <Frame ref={ref}>
7980 * <Frame scaleX={scrollYProgress} />
7981 * </Frame>
7982 * )
7983 * }
7984 * ```
7985 *
7986 * @motion
7987 *
7988 * ```jsx
7989 * export const MyComponent = () => {
7990 * const ref = useRef()
7991 * const { scrollYProgress } = useElementScroll(ref)
7992 *
7993 * return (
7994 * <div ref={ref}>
7995 * <motion.div style={{ scaleX: scrollYProgress }} />
7996 * </div>
7997 * )
7998 * }
7999 * ```
8000 *
8001 * @public
8002 */
8003 function useElementScroll(ref) {
8004 var values = useConstant(createScrollMotionValues);
8005 useIsomorphicLayoutEffect(function () {
8006 var element = ref.current;
8007 invariant(!!element, "ref provided to useScroll must be passed into a HTML element.");
8008 if (!element)
8009 return;
8010 var updateScrollValues = createScrollUpdater(values, getElementScrollOffsets(element));
8011 var scrollListener = addDomEvent(element, "scroll", updateScrollValues, { passive: true });
8012 var resizeListener = addDomEvent(element, "resize", updateScrollValues);
8013 return function () {
8014 scrollListener && scrollListener();
8015 resizeListener && resizeListener();
8016 };
8017 }, []);
8018 return values;
8019 }
8020
8021 var viewportScrollValues = createScrollMotionValues();
8022 function getViewportScrollOffsets() {
8023 return {
8024 xOffset: window.pageXOffset,
8025 yOffset: window.pageYOffset,
8026 xMaxOffset: document.body.clientWidth - window.innerWidth,
8027 yMaxOffset: document.body.clientHeight - window.innerHeight,
8028 };
8029 }
8030 var hasListeners = false;
8031 function addEventListeners() {
8032 hasListeners = true;
8033 if (typeof window === "undefined")
8034 return;
8035 var updateScrollValues = createScrollUpdater(viewportScrollValues, getViewportScrollOffsets);
8036 addDomEvent(window, "scroll", updateScrollValues, { passive: true });
8037 addDomEvent(window, "resize", updateScrollValues);
8038 }
8039 /**
8040 * Returns MotionValues that update when the viewport scrolls:
8041 *
8042 * - `scrollX` — Horizontal scroll distance in pixels.
8043 * - `scrollY` — Vertical scroll distance in pixels.
8044 * - `scrollXProgress` — Horizontal scroll progress between `0` and `1`.
8045 * - `scrollYProgress` — Vertical scroll progress between `0` and `1`.
8046 *
8047 * @library
8048 *
8049 * ```jsx
8050 * import * as React from "react"
8051 * import {
8052 * Frame,
8053 * useViewportScroll,
8054 * useTransform
8055 * } from "framer"
8056 *
8057 * export function MyComponent() {
8058 * const { scrollYProgress } = useViewportScroll()
8059 * return <Frame scaleX={scrollYProgress} />
8060 * }
8061 * ```
8062 *
8063 * @motion
8064 *
8065 * ```jsx
8066 * export const MyComponent = () => {
8067 * const { scrollYProgress } = useViewportScroll()
8068 * return <motion.div style={{ scaleX: scrollYProgress }} />
8069 * }
8070 * ```
8071 *
8072 * @public
8073 */
8074 function useViewportScroll() {
8075 useIsomorphicLayoutEffect(function () {
8076 !hasListeners && addEventListeners();
8077 }, []);
8078 return viewportScrollValues;
8079 }
8080
8081 /**
8082 * Creates `AnimationControls`, which can be used to manually start, stop
8083 * and sequence animations on one or more components.
8084 *
8085 * The returned `AnimationControls` should be passed to the `animate` property
8086 * of the components you want to animate.
8087 *
8088 * These components can then be animated with the `start` method.
8089 *
8090 * @library
8091 *
8092 * ```jsx
8093 * import * as React from 'react'
8094 * import { Frame, useAnimation } from 'framer'
8095 *
8096 * export function MyComponent(props) {
8097 * const controls = useAnimation()
8098 *
8099 * controls.start({
8100 * x: 100,
8101 * transition: { duration: 0.5 },
8102 * })
8103 *
8104 * return <Frame animate={controls} />
8105 * }
8106 * ```
8107 *
8108 * @motion
8109 *
8110 * ```jsx
8111 * import * as React from 'react'
8112 * import { motion, useAnimation } from 'framer-motion'
8113 *
8114 * export function MyComponent(props) {
8115 * const controls = useAnimation()
8116 *
8117 * controls.start({
8118 * x: 100,
8119 * transition: { duration: 0.5 },
8120 * })
8121 *
8122 * return <motion.div animate={controls} />
8123 * }
8124 * ```
8125 *
8126 * @returns Animation controller with `start` and `stop` methods
8127 *
8128 * @public
8129 */
8130 function useAnimation() {
8131 var animationControls = useConstant(function () { return new AnimationControls(); });
8132 React.useEffect(function () {
8133 animationControls.mount();
8134 return function () { return animationControls.unmount(); };
8135 }, []);
8136 return animationControls;
8137 }
8138
8139 /**
8140 * Cycles through a series of visual properties. Can be used to toggle between or cycle through animations. It works similar to `useState` in React. It is provided an initial array of possible states, and returns an array of two arguments.
8141 *
8142 * @library
8143 *
8144 * ```jsx
8145 * import * as React from "react"
8146 * import { Frame, useCycle } from "framer"
8147 *
8148 * export function MyComponent() {
8149 * const [x, cycleX] = useCycle(0, 50, 100)
8150 *
8151 * return (
8152 * <Frame
8153 * animate={{ x: x }}
8154 * onTap={() => cycleX()}
8155 * />
8156 * )
8157 * }
8158 * ```
8159 *
8160 * @motion
8161 *
8162 * An index value can be passed to the returned `cycle` function to cycle to a specific index.
8163 *
8164 * ```jsx
8165 * import * as React from "react"
8166 * import { motion, useCycle } from "framer-motion"
8167 *
8168 * export const MyComponent = () => {
8169 * const [x, cycleX] = useCycle(0, 50, 100)
8170 *
8171 * return (
8172 * <motion.div
8173 * animate={{ x: x }}
8174 * onTap={() => cycleX()}
8175 * />
8176 * )
8177 * }
8178 * ```
8179 *
8180 * @param items - items to cycle through
8181 * @returns [currentState, cycleState]
8182 *
8183 * @public
8184 */
8185 function useCycle() {
8186 var items = [];
8187 for (var _i = 0; _i < arguments.length; _i++) {
8188 items[_i] = arguments[_i];
8189 }
8190 // TODO: After Framer X beta, remove this warning
8191 warning(items.length > 1, "useCycle syntax has changed. `useCycle([0, 1, 2])` becomes `useCycle(0, 1, 2)`");
8192 var index = React.useRef(0);
8193 var _a = React.useState(items[index.current]), item = _a[0], setItem = _a[1];
8194 return [
8195 item,
8196 function (next) {
8197 index.current =
8198 typeof next !== "number"
8199 ? wrap$1(0, items.length, index.current + 1)
8200 : next;
8201 setItem(items[index.current]);
8202 },
8203 ];
8204 }
8205
8206 // Does this device prefer reduced motion? Returns `null` server-side.
8207 var prefersReducedMotion = motionValue(null);
8208 if (typeof window !== "undefined") {
8209 if (window.matchMedia) {
8210 var motionMediaQuery_1 = window.matchMedia("(prefers-reduced-motion)");
8211 var setReducedMotionPreferences = function () {
8212 return prefersReducedMotion.set(motionMediaQuery_1.matches);
8213 };
8214 motionMediaQuery_1.addListener(setReducedMotionPreferences);
8215 setReducedMotionPreferences();
8216 }
8217 else {
8218 prefersReducedMotion.set(false);
8219 }
8220 }
8221 function determineShouldReduceMotion(prefersReduced, isReducedMotion) {
8222 return typeof isReducedMotion === "boolean"
8223 ? isReducedMotion
8224 : Boolean(prefersReduced);
8225 }
8226 /**
8227 * A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
8228 *
8229 * This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
8230 * `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
8231 *
8232 * It will actively respond to changes and re-render your components with the latest setting.
8233 *
8234 * ```jsx
8235 * export function Sidebar({ isOpen }) {
8236 * const shouldReduceMotion = useReducedMotion()
8237 * const closedX = shouldReduceMotion ? 0 : "-100%"
8238 *
8239 * return (
8240 * <motion.div animate={{
8241 * opacity: isOpen ? 1 : 0,
8242 * x: isOpen ? 0 : closedX
8243 * }} />
8244 * )
8245 * }
8246 * ```
8247 *
8248 * @return boolean
8249 *
8250 * @public
8251 */
8252 function useReducedMotion() {
8253 var isReducedMotion = React.useContext(MotionContext).isReducedMotion;
8254 var _a = React.useState(determineShouldReduceMotion(prefersReducedMotion.get(), isReducedMotion)), shouldReduceMotion = _a[0], setShouldReduceMotion = _a[1];
8255 React.useEffect(function () {
8256 return prefersReducedMotion.onChange(function (v) {
8257 setShouldReduceMotion(determineShouldReduceMotion(v, isReducedMotion));
8258 });
8259 }, [setShouldReduceMotion, isReducedMotion]);
8260 return shouldReduceMotion;
8261 }
8262
8263 /**
8264 * Define accessibility options for a tree. Can be used to force the tree into Reduced Motion mode,
8265 * or disable device detection.
8266 *
8267 * @internal
8268 */
8269 function ReducedMotion(_a) {
8270 var children = _a.children, enabled = _a.enabled;
8271 var context = React.useContext(MotionContext);
8272 context = React.useMemo(function () { return (__assign(__assign({}, context), { isReducedMotion: enabled })); }, [enabled]);
8273 return (React.createElement(MotionContext.Provider, { value: context }, children));
8274 }
8275
8276 /**
8277 * Can manually trigger a drag gesture on one or more `drag`-enabled `motion` components.
8278 *
8279 * @library
8280 *
8281 * ```jsx
8282 * const dragControls = useDragControls()
8283 *
8284 * function startDrag(event) {
8285 * dragControls.start(event, { snapToCursor: true })
8286 * }
8287 *
8288 * return (
8289 * <>
8290 * <Frame onTapStart={startDrag} />
8291 * <Frame drag="x" dragControls={dragControls} />
8292 * </>
8293 * )
8294 * ```
8295 *
8296 * @motion
8297 *
8298 * ```jsx
8299 * const dragControls = useDragControls()
8300 *
8301 * function startDrag(event) {
8302 * dragControls.start(event, { snapToCursor: true })
8303 * }
8304 *
8305 * return (
8306 * <>
8307 * <div onMouseDown={startDrag} />
8308 * <motion.div drag="x" dragControls={dragControls} />
8309 * </>
8310 * )
8311 * ```
8312 *
8313 * @public
8314 */
8315 var DragControls = /** @class */ (function () {
8316 function DragControls() {
8317 this.componentControls = new Set();
8318 }
8319 /**
8320 * Subscribe a component's internal `VisualElementDragControls` to the user-facing API.
8321 *
8322 * @internal
8323 */
8324 DragControls.prototype.subscribe = function (controls) {
8325 var _this = this;
8326 this.componentControls.add(controls);
8327 return function () { return _this.componentControls.delete(controls); };
8328 };
8329 /**
8330 * Start a drag gesture on every `motion` component that has this set of drag controls
8331 * passed into it via the `dragControls` prop.
8332 *
8333 * ```jsx
8334 * dragControls.start(e, {
8335 * snapToCursor: true
8336 * })
8337 * ```
8338 *
8339 * @param event - A mouse/touch/pointer event.
8340 * @param options - Options
8341 *
8342 * @public
8343 */
8344 DragControls.prototype.start = function (event, options) {
8345 this.componentControls.forEach(function (controls) {
8346 controls.start(event.nativeEvent || event, options);
8347 });
8348 };
8349 return DragControls;
8350 }());
8351 var createDragControls = function () { return new DragControls(); };
8352 /**
8353 * Usually, dragging is initiated by pressing down on a `motion` component with a `drag` prop
8354 * and moving it. For some use-cases, for instance clicking at an arbitrary point on a video scrubber, we
8355 * might want to initiate that dragging from a different component than the draggable one.
8356 *
8357 * By creating a `dragControls` using the `useDragControls` hook, we can pass this into
8358 * the draggable component's `dragControls` prop. It exposes a `start` method
8359 * that can start dragging from pointer events on other components.
8360 *
8361 * @library
8362 *
8363 * ```jsx
8364 * const dragControls = useDragControls()
8365 *
8366 * function startDrag(event) {
8367 * dragControls.start(event, { snapToCursor: true })
8368 * }
8369 *
8370 * return (
8371 * <>
8372 * <Frame onTapStart={startDrag} />
8373 * <Frame drag="x" dragControls={dragControls} />
8374 * </>
8375 * )
8376 * ```
8377 *
8378 * @motion
8379 *
8380 * ```jsx
8381 * const dragControls = useDragControls()
8382 *
8383 * function startDrag(event) {
8384 * dragControls.start(event, { snapToCursor: true })
8385 * }
8386 *
8387 * return (
8388 * <>
8389 * <div onMouseDown={startDrag} />
8390 * <motion.div drag="x" dragControls={dragControls} />
8391 * </>
8392 * )
8393 * ```
8394 *
8395 * @public
8396 */
8397 function useDragControls() {
8398 return useConstant(createDragControls);
8399 }
8400
8401 /**
8402 * Uses the ref that is passed in, or creates a new one
8403 * @param external - External ref
8404 * @internal
8405 */
8406 function useExternalRef(externalRef) {
8407 // We're conditionally calling `useRef` here which is sort of naughty as hooks
8408 // shouldn't be called conditionally. However, Framer Motion will break if this
8409 // condition changes anyway. It might be possible to use an invariant here to
8410 // make it explicit, but I expect changing `ref` is not normal behaviour.
8411 var ref = !externalRef || typeof externalRef === "function"
8412 ? React.useRef(null)
8413 : externalRef;
8414 // Handle `ref` functions. Again, calling the hook conditionally is kind of naughty
8415 // but `ref` types changing between renders would break Motion anyway. If we receive
8416 // bug reports about this, we should track the provided ref and throw an invariant
8417 // rather than move the conditional to inside the useEffect as this will be fired
8418 // for every Frame component within Framer.
8419 if (externalRef && typeof externalRef === "function") {
8420 React.useEffect(function () {
8421 externalRef(ref.current);
8422 return function () { return externalRef(null); };
8423 }, []);
8424 }
8425 return ref;
8426 }
8427
8428 /**
8429 * This is just a very basic VisualElement, more of a hack to keep supporting useAnimatedState with
8430 * the latest APIs.
8431 */
8432 var StateVisualElement = /** @class */ (function (_super) {
8433 __extends(StateVisualElement, _super);
8434 function StateVisualElement() {
8435 var _this = _super !== null && _super.apply(this, arguments) || this;
8436 _this.initialState = {};
8437 return _this;
8438 }
8439 StateVisualElement.prototype.updateLayoutDelta = function () { };
8440 StateVisualElement.prototype.build = function () { };
8441 StateVisualElement.prototype.clean = function () { };
8442 StateVisualElement.prototype.getBoundingBox = function () {
8443 return { x: { min: 0, max: 0 }, y: { min: 0, max: 0 } };
8444 };
8445 StateVisualElement.prototype.readNativeValue = function (key) {
8446 return this.initialState[key] || 0;
8447 };
8448 StateVisualElement.prototype.render = function () {
8449 this.build();
8450 };
8451 return StateVisualElement;
8452 }(VisualElement));
8453 /**
8454 * This is not an officially supported API and may be removed
8455 * on any version.
8456 * @internal
8457 */
8458 function useAnimatedState(initialState) {
8459 var _a = React.useState(initialState), animationState = _a[0], setAnimationState = _a[1];
8460 var visualElement = useConstant(function () { return new StateVisualElement(); });
8461 visualElement.updateConfig({
8462 onUpdate: function (v) { return setAnimationState(__assign({}, v)); },
8463 });
8464 visualElement.initialState = initialState;
8465 var controls = useVisualElementAnimation(visualElement, {}, {});
8466 React.useEffect(function () {
8467 visualElement.mount({});
8468 return function () { return visualElement.unmount(); };
8469 }, []);
8470 var startAnimation = useConstant(function () { return function (animationDefinition) {
8471 return controls.start(animationDefinition);
8472 }; });
8473 return [animationState, startAnimation];
8474 }
8475
8476 exports.AnimateLayoutFeature = AnimateLayout;
8477 exports.AnimatePresence = AnimatePresence;
8478 exports.AnimateSharedLayout = AnimateSharedLayout;
8479 exports.AnimationControls = AnimationControls;
8480 exports.AnimationFeature = Animation;
8481 exports.DragControls = DragControls;
8482 exports.DragFeature = Drag;
8483 exports.ExitFeature = Exit;
8484 exports.GesturesFeature = Gestures;
8485 exports.MotionConfig = MotionConfig;
8486 exports.MotionConfigContext = MotionConfigContext;
8487 exports.MotionContext = MotionContext;
8488 exports.MotionValue = MotionValue;
8489 exports.PresenceContext = PresenceContext;
8490 exports.ReducedMotion = ReducedMotion;
8491 exports.VisualElementAnimationControls = VisualElementAnimationControls;
8492 exports.addScaleCorrection = addScaleCorrection;
8493 exports.animationControls = animationControls;
8494 exports.createMotionComponent = createMotionComponent;
8495 exports.isValidMotionProp = isValidMotionProp;
8496 exports.m = m;
8497 exports.motion = motion;
8498 exports.motionValue = motionValue;
8499 exports.resolveMotionValue = resolveMotionValue;
8500 exports.transform = transform;
8501 exports.useAnimatedState = useAnimatedState;
8502 exports.useAnimation = useAnimation;
8503 exports.useCycle = useCycle;
8504 exports.useDomEvent = useDomEvent;
8505 exports.useDragControls = useDragControls;
8506 exports.useElementScroll = useElementScroll;
8507 exports.useExternalRef = useExternalRef;
8508 exports.useGestures = useGestures;
8509 exports.useInvertedScale = useInvertedScale;
8510 exports.useIsPresent = useIsPresent;
8511 exports.useMotionValue = useMotionValue;
8512 exports.usePanGesture = usePanGesture;
8513 exports.usePresence = usePresence;
8514 exports.useReducedMotion = useReducedMotion;
8515 exports.useSpring = useSpring;
8516 exports.useTapGesture = useTapGesture;
8517 exports.useTransform = useTransform;
8518 exports.useViewportScroll = useViewportScroll;
8519
8520 Object.defineProperty(exports, '__esModule', { value: true });
8521
8522})));