: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
class DOMKeyframesResolver extends KeyframeResolver {
constructor(unresolvedKeyframes, onComplete, name, motionValue) {
super(unresolvedKeyframes, onComplete, name, motionValue, motionValue === null || motionValue === void 0 ? void 0 : motionValue.owner, true);
const { unresolvedKeyframes, element, name } = this;
* If any keyframe is a CSS variable, we need to find its value by sampling the element
for (let i = 0; i < unresolvedKeyframes.length; i++) {
const keyframe = unresolvedKeyframes[i];
if (typeof keyframe === "string" && isCSSVariableToken(keyframe)) {
const resolved = getVariableValue(keyframe, element.current);
if (resolved !== undefined) {
unresolvedKeyframes[i] = resolved;
if (i === unresolvedKeyframes.length - 1) {
this.finalKeyframe = keyframe;
* Resolve "none" values. We do this potentially twice - once before and once after measuring keyframes.
* This could be seen as inefficient but it's a trade-off to avoid measurements in more situations, which
* have a far bigger performance impact.
this.resolveNoneKeyframes();
* Check to see if unit type has changed. If so schedule jobs that will
* temporarily set styles to the destination keyframes.
* Skip if we have more than two keyframes or this isn't a positional value.
* TODO: We can throw if there are multiple keyframes and the value type changes.
if (!positionalKeys.has(name) || unresolvedKeyframes.length !== 2) {
const [origin, target] = unresolvedKeyframes;
const originType = findDimensionValueType(origin);
const targetType = findDimensionValueType(target);
* Either we don't recognise these value types or we can animate between them.
if (originType === targetType)
* If both values are numbers or pixels, we can animate between them by
* converting them to numbers.
if (isNumOrPxType(originType) && isNumOrPxType(targetType)) {
for (let i = 0; i < unresolvedKeyframes.length; i++) {
const value = unresolvedKeyframes[i];
if (typeof value === "string") {
unresolvedKeyframes[i] = parseFloat(value);
* Else, the only way to resolve this is by measuring the element.
this.needsMeasurement = true;
const { unresolvedKeyframes, name } = this;
const noneKeyframeIndexes = [];
for (let i = 0; i < unresolvedKeyframes.length; i++) {
if (isNone(unresolvedKeyframes[i])) {
noneKeyframeIndexes.push(i);
if (noneKeyframeIndexes.length) {
makeNoneKeyframesAnimatable(unresolvedKeyframes, noneKeyframeIndexes, name);
const { element, unresolvedKeyframes, name } = this;
this.suspendedScrollY = window.pageYOffset;
this.measuredOrigin = positionalValues[name](element.measureViewportBox(), window.getComputedStyle(element.current));
unresolvedKeyframes[0] = this.measuredOrigin;
// Set final key frame to measure after next render
const measureKeyframe = unresolvedKeyframes[unresolvedKeyframes.length - 1];
if (measureKeyframe !== undefined) {
element.getValue(name, measureKeyframe).jump(measureKeyframe, false);
const { element, name, unresolvedKeyframes } = this;
const value = element.getValue(name);
value && value.jump(this.measuredOrigin, false);
const finalKeyframeIndex = unresolvedKeyframes.length - 1;
const finalKeyframe = unresolvedKeyframes[finalKeyframeIndex];
unresolvedKeyframes[finalKeyframeIndex] = positionalValues[name](element.measureViewportBox(), window.getComputedStyle(element.current));
if (finalKeyframe !== null && this.finalKeyframe === undefined) {
this.finalKeyframe = finalKeyframe;
// If we removed transform values, reapply them before the next render
if ((_a = this.removedTransforms) === null || _a === void 0 ? void 0 : _a.length) {
this.removedTransforms.forEach(([unsetTransformName, unsetTransformValue]) => {
.getValue(unsetTransformName)
.set(unsetTransformValue);
this.resolveNoneKeyframes();
;// CONCATENATED MODULE: ./node_modules/framer-motion/dist/es/utils/memo.mjs
function memo(callback) {
if (result === undefined)
;// CONCATENATED MODULE: ./node_modules/framer-motion/dist/es/animation/utils/is-animatable.mjs
* Check if a value is animatable. Examples:
* ✅: 100, "100px", "#fff"
* ❌: "block", "url(2.jpg)"
const isAnimatable = (value, name) => {
// If the list of keys tat might be non-animatable grows, replace with Set
// If it's a number or a keyframes array, we can animate it. We might at some point
// need to do a deep isAnimatable check of keyframes, or let Popmotion handle this,
// but for now lets leave it like this for performance reasons
if (typeof value === "number" || Array.isArray(value))
if (typeof value === "string" && // It's animatable if we have a string
(complex.test(value) || value === "0") && // And it contains numbers and/or colors
!value.startsWith("url(") // Unless it starts with "url("
;// CONCATENATED MODULE: ./node_modules/framer-motion/dist/es/animation/animators/utils/can-animate.mjs
function hasKeyframesChanged(keyframes) {
const current = keyframes[0];
if (keyframes.length === 1)
for (let i = 0; i < keyframes.length; i++) {
if (keyframes[i] !== current)
function canAnimate(keyframes, name, type, velocity) {
* Check if we're able to animate between the start and end keyframes,
* and throw a warning if we're attempting to animate between one that's
* animatable and another that isn't.
const originKeyframe = keyframes[0];
if (originKeyframe === null)
* These aren't traditionally animatable but we do support them.
* In future we could look into making this more generic or replacing
* this function with mix() === mixImmediate
if (name === "display" || name === "visibility")
const targetKeyframe = keyframes[keyframes.length - 1];
const isOriginAnimatable = isAnimatable(originKeyframe, name);
const isTargetAnimatable = isAnimatable(targetKeyframe, name);
warning(isOriginAnimatable === isTargetAnimatable, `You are trying to animate ${name} from "${originKeyframe}" to "${targetKeyframe}". ${originKeyframe} is not an animatable value - to enable this animation set ${originKeyframe} to a value animatable to ${targetKeyframe} via the \`style\` property.`);
// Always skip if any of these are true
if (!isOriginAnimatable || !isTargetAnimatable) {
return hasKeyframesChanged(keyframes) || (type === "spring" && velocity);
;// CONCATENATED MODULE: ./node_modules/framer-motion/dist/es/animation/animators/BaseAnimation.mjs
constructor({ autoplay = true, delay = 0, type = "keyframes", repeat = 0, repeatDelay = 0, repeatType = "loop", ...options }) {
// Track whether the animation has been stopped. Stopped animations won't restart.
this.hasAttemptedResolve = false;
this.updateFinishedPromise();
* A getter for resolved data. If keyframes are not yet resolved, accessing
* this.resolved will synchronously flush all pending keyframe resolvers.
* This is a deoptimisation, but at its worst still batches read/writes.
if (!this._resolved && !this.hasAttemptedResolve) {
flushKeyframeResolvers();
* A method to be called when the keyframes resolver completes. This method
* will check if its possible to run the animation and, if not, skip it.
* Otherwise, it will call initPlayback on the implementing class.
onKeyframesResolved(keyframes, finalKeyframe) {
this.hasAttemptedResolve = true;
const { name, type, velocity, delay, onComplete, onUpdate, isGenerator, } = this.options;
* If we can't animate this value with the resolved keyframes
* then we should complete it immediately.
if (!isGenerator && !canAnimate(keyframes, name, type, velocity)) {
if (instantAnimationState.current || !delay) {
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(getFinalKeyframe(keyframes, this.options, finalKeyframe));
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
this.resolveFinishedPromise();
this.options.duration = 0;
const resolvedAnimation = this.initPlayback(keyframes, finalKeyframe);
if (resolvedAnimation === false)
* Allows the returned animation to be awaited or promise-chained. Currently
* resolves when the animation finishes at all but in a future update could/should
return this.currentFinishedPromise.then(resolve, reject);
updateFinishedPromise() {
this.currentFinishedPromise = new Promise((resolve) => {
this.resolveFinishedPromise = resolve;
;// CONCATENATED MODULE: ./node_modules/framer-motion/dist/es/utils/velocity-per-second.mjs
Convert velocity into velocity per second
@param [number]: Unit per frame
@param [number]: Frame duration in ms
function velocityPerSecond(velocity, frameDuration) {
return frameDuration ? velocity * (1000 / frameDuration) : 0;
;// CONCATENATED MODULE: ./node_modules/framer-motion/dist/es/animation/generators/utils/velocity.mjs
const velocitySampleDuration = 5; // ms
function calcGeneratorVelocity(resolveValue, t, current) {
const prevT = Math.max(t - velocitySampleDuration, 0);
return velocityPerSecond(current - resolveValue(prevT), t - prevT);
;// CONCATENATED MODULE: ./node_modules/framer-motion/dist/es/animation/generators/spring/find.mjs
const minDuration = 0.01;
const maxDuration = 10.0;
function findSpring({ duration = 800, bounce = 0.25, velocity = 0, mass = 1, }) {
warning(duration <= secondsToMilliseconds(maxDuration), "Spring duration must be 10 seconds or less");
let dampingRatio = 1 - bounce;
* Restrict dampingRatio and duration to within acceptable ranges.
dampingRatio = clamp_clamp(minDamping, maxDamping, dampingRatio);
duration = clamp_clamp(minDuration, maxDuration, millisecondsToSeconds(duration));
envelope = (undampedFreq) => {
const exponentialDecay = undampedFreq * dampingRatio;
const delta = exponentialDecay * duration;
const a = exponentialDecay - velocity;
const b = calcAngularFreq(undampedFreq, dampingRatio);
const c = Math.exp(-delta);
return safeMin - (a / b) * c;
derivative = (undampedFreq) => {
const exponentialDecay = undampedFreq * dampingRatio;
const delta = exponentialDecay * duration;
const d = delta * velocity + velocity;
const e = Math.pow(dampingRatio, 2) * Math.pow(undampedFreq, 2) * duration;
const f = Math.exp(-delta);
const g = calcAngularFreq(Math.pow(undampedFreq, 2), dampingRatio);
const factor = -envelope(undampedFreq) + safeMin > 0 ? -1 : 1;
return (factor * ((d - e) * f)) / g;
* Critically-damped spring
envelope = (undampedFreq) => {
const a = Math.exp(-undampedFreq * duration);
const b = (undampedFreq - velocity) * duration + 1;
derivative = (undampedFreq) => {
const a = Math.exp(-undampedFreq * duration);
const b = (velocity - undampedFreq) * (duration * duration);
const initialGuess = 5 / duration;
const undampedFreq = approximateRoot(envelope, derivative, initialGuess);
duration = secondsToMilliseconds(duration);
if (isNaN(undampedFreq)) {
const stiffness = Math.pow(undampedFreq, 2) * mass;
damping: dampingRatio * 2 * Math.sqrt(mass * stiffness),
const rootIterations = 12;
function approximateRoot(envelope, derivative, initialGuess) {
let result = initialGuess;
for (let i = 1; i < rootIterations; i++) {
result = result - envelope(result) / derivative(result);
function calcAngularFreq(undampedFreq, dampingRatio) {
return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
;// CONCATENATED MODULE: ./node_modules/framer-motion/dist/es/animation/generators/spring/index.mjs
const durationKeys = ["duration", "bounce"];
const physicsKeys = ["stiffness", "damping", "mass"];
function isSpringType(options, keys) {
return keys.some((key) => options[key] !== undefined);
function getSpringOptions(options) {
isResolvedFromDuration: false,
// stiffness/damping/mass overrides duration/bounce
if (!isSpringType(options, physicsKeys) &&
isSpringType(options, durationKeys)) {
const derived = findSpring(options);
springOptions.isResolvedFromDuration = true;
function spring({ keyframes, restDelta, restSpeed, ...options }) {
const origin = keyframes[0];
const target = keyframes[keyframes.length - 1];
* This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
* to reduce GC during animation.
const state = { done: false, value: origin };
const { stiffness, damping, mass, duration, velocity, isResolvedFromDuration, } = getSpringOptions({
velocity: -millisecondsToSeconds(options.velocity || 0),
const initialVelocity = velocity || 0.0;
const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
const initialDelta = target - origin;
const undampedAngularFreq = millisecondsToSeconds(Math.sqrt(stiffness / mass));
* If we're working on a granular scale, use smaller defaults for determining
* when the spring is finished.
* These defaults have been selected emprically based on what strikes a good
* ratio between feeling good and finishing as soon as changes are imperceptible.
const isGranularScale = Math.abs(initialDelta) < 5;
restSpeed || (restSpeed = isGranularScale ? 0.01 : 2);
restDelta || (restDelta = isGranularScale ? 0.005 : 0.5);
const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
dampingRatio * undampedAngularFreq * initialDelta) /
Math.sin(angularFreq * t) +
initialDelta * Math.cos(angularFreq * t)));
else if (dampingRatio === 1) {
// Critically damped spring
resolveSpring = (t) => target -
Math.exp(-undampedAngularFreq * t) *
(initialVelocity + undampedAngularFreq * initialDelta) * t);
const dampedAngularFreq = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
// When performing sinh or cosh values can hit Infinity so we cap them here
const freqForT = Math.min(dampedAngularFreq * t, 300);
dampingRatio * undampedAngularFreq * initialDelta) *