UNPKG

framer-motion

Version:

<p align="center"> <img src="https://user-images.githubusercontent.com/38039349/60953119-d3c6f300-a2fc-11e9-9596-4978e5d52180.png" width="176" height="170" alt="Framer Motion" /> </p>

1,262 lines (1,211 loc) • 276 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) : typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) : (global = global || self, factory(global.Motion = {}, global.React)); }(this, function (exports, React) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } /** * Uses the ref that is passed in, or creates a new one * @param external - External ref * @internal */ function useExternalRef(external) { // We're conditionally calling `useRef` here which is sort of naughty as hooks // shouldn't be called conditionally. However, Framer Motion will break if this // condition changes anyway. It might be possible to use an invariant here to // make it explicit, but I expect changing `ref` is not normal behaviour. var ref = !external || typeof external === "function" ? React.useRef(null) : external; React.useEffect(function () { if (external && typeof external === "function") { external(ref.current); return function () { return external(null); }; } }, []); return ref; } var warning = function () { }; var invariant = function () { }; { warning = function (check, message) { if (!check && typeof console !== 'undefined') { console.warn(message); } }; invariant = function (check, message) { if (!check) { throw new Error(message); } }; } var prevTime = 0; var onNextFrame = typeof window !== 'undefined' && window.requestAnimationFrame !== undefined ? function (callback) { return window.requestAnimationFrame(callback); } : function (callback) { var timestamp = Date.now(); var timeToCall = Math.max(0, 16.7 - (timestamp - prevTime)); prevTime = timestamp + timeToCall; setTimeout(function () { return callback(prevTime); }, timeToCall); }; var createStep = (function (setRunNextFrame) { var processToRun = []; var processToRunNextFrame = []; var numThisFrame = 0; var isProcessing = false; var i = 0; var cancelled = new WeakSet(); var toKeepAlive = new WeakSet(); var renderStep = { cancel: function (process) { var indexOfCallback = processToRunNextFrame.indexOf(process); cancelled.add(process); if (indexOfCallback !== -1) { processToRunNextFrame.splice(indexOfCallback, 1); } }, process: function (frame) { var _a; isProcessing = true; _a = [ processToRunNextFrame, processToRun ], processToRun = _a[0], processToRunNextFrame = _a[1]; processToRunNextFrame.length = 0; numThisFrame = processToRun.length; if (numThisFrame) { var process_1; for (i = 0; i < numThisFrame; i++) { process_1 = processToRun[i]; process_1(frame); if (toKeepAlive.has(process_1) === true && !cancelled.has(process_1)) { renderStep.schedule(process_1); setRunNextFrame(true); } } } isProcessing = false; }, schedule: function (process, keepAlive, immediate) { if (keepAlive === void 0) { keepAlive = false; } if (immediate === void 0) { immediate = false; } invariant(typeof process === 'function', 'Argument must be a function'); var addToCurrentBuffer = immediate && isProcessing; var buffer = addToCurrentBuffer ? processToRun : processToRunNextFrame; cancelled.delete(process); if (keepAlive) toKeepAlive.add(process); if (buffer.indexOf(process) === -1) { buffer.push(process); if (addToCurrentBuffer) numThisFrame = processToRun.length; } } }; return renderStep; }); var StepId; (function (StepId) { StepId["Read"] = "read"; StepId["Update"] = "update"; StepId["Render"] = "render"; StepId["PostRender"] = "postRender"; StepId["FixedUpdate"] = "fixedUpdate"; })(StepId || (StepId = {})); var maxElapsed = 40; var defaultElapsed = (1 / 60) * 1000; var useDefaultElapsed = true; var willRunNextFrame = false; var isProcessing = false; var frame = { delta: 0, timestamp: 0 }; var stepsOrder = [ StepId.Read, StepId.Update, StepId.Render, StepId.PostRender ]; var setWillRunNextFrame = function (willRun) { return (willRunNextFrame = willRun); }; var _a = stepsOrder.reduce(function (acc, key) { var step = createStep(setWillRunNextFrame); acc.sync[key] = function (process, keepAlive, immediate) { if (keepAlive === void 0) { keepAlive = false; } if (immediate === void 0) { immediate = false; } if (!willRunNextFrame) startLoop(); step.schedule(process, keepAlive, immediate); return process; }; acc.cancelSync[key] = function (process) { return step.cancel(process); }; acc.steps[key] = step; return acc; }, { steps: {}, sync: {}, cancelSync: {} }), steps = _a.steps, sync = _a.sync, cancelSync = _a.cancelSync; var processStep = function (stepId) { return steps[stepId].process(frame); }; var processFrame = function (timestamp) { willRunNextFrame = false; frame.delta = useDefaultElapsed ? defaultElapsed : Math.max(Math.min(timestamp - frame.timestamp, maxElapsed), 1); if (!useDefaultElapsed) defaultElapsed = frame.delta; frame.timestamp = timestamp; isProcessing = true; stepsOrder.forEach(processStep); isProcessing = false; if (willRunNextFrame) { useDefaultElapsed = false; onNextFrame(processFrame); } }; var startLoop = function () { willRunNextFrame = true; useDefaultElapsed = true; if (!isProcessing) onNextFrame(processFrame); }; var getFrameData = function () { return frame; }; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign$1 = function() { __assign$1 = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign$1.apply(this, arguments); }; var clamp = function (min, max) { return function (v) { return Math.max(Math.min(v, max), min); }; }; var sanitize = function (v) { return (v % 1 ? Number(v.toFixed(5)) : v); }; var floatRegex = /(-)?(\d[\d\.]*)/g; var colorRegex = /(#[0-9a-f]{6}|#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\))/gi; var singleColorRegex = /^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\))$/i; var number = { test: function (v) { return typeof v === 'number'; }, parse: parseFloat, transform: function (v) { return v; } }; var alpha = __assign$1({}, number, { transform: clamp(0, 1) }); var scale = __assign$1({}, number, { default: 1 }); var createUnitType = function (unit) { return ({ test: function (v) { return typeof v === 'string' && v.endsWith(unit) && v.split(' ').length === 1; }, parse: parseFloat, transform: function (v) { return "" + v + unit; } }); }; var degrees = createUnitType('deg'); var percent = createUnitType('%'); var px = createUnitType('px'); var vh = createUnitType('vh'); var vw = createUnitType('vw'); var progressPercentage = __assign$1({}, percent, { parse: function (v) { return percent.parse(v) / 100; }, transform: function (v) { return percent.transform(v * 100); } }); var getValueFromFunctionString = function (value) { return value.substring(value.indexOf('(') + 1, value.lastIndexOf(')')); }; var clampRgbUnit = clamp(0, 255); var isRgba = function (v) { return v.red !== undefined; }; var isHsla = function (v) { return v.hue !== undefined; }; var splitColorValues = function (terms) { return function (v) { if (typeof v !== 'string') return v; var values = {}; var valuesArray = getValueFromFunctionString(v).split(/,\s*/); for (var i = 0; i < 4; i++) { values[terms[i]] = valuesArray[i] !== undefined ? parseFloat(valuesArray[i]) : 1; } return values; }; }; var rgbaTemplate = function (_a) { var red = _a.red, green = _a.green, blue = _a.blue, _b = _a.alpha, alpha$$1 = _b === void 0 ? 1 : _b; return "rgba(" + red + ", " + green + ", " + blue + ", " + alpha$$1 + ")"; }; var hslaTemplate = function (_a) { var hue = _a.hue, saturation = _a.saturation, lightness = _a.lightness, _b = _a.alpha, alpha$$1 = _b === void 0 ? 1 : _b; return "hsla(" + hue + ", " + saturation + ", " + lightness + ", " + alpha$$1 + ")"; }; var rgbUnit = __assign$1({}, number, { transform: function (v) { return Math.round(clampRgbUnit(v)); } }); function isColorString(color, colorType) { return color.startsWith(colorType) && singleColorRegex.test(color); } var rgba = { test: function (v) { return (typeof v === 'string' ? isColorString(v, 'rgb') : isRgba(v)); }, parse: splitColorValues(['red', 'green', 'blue', 'alpha']), transform: function (_a) { var red = _a.red, green = _a.green, blue = _a.blue, _b = _a.alpha, alpha$$1 = _b === void 0 ? 1 : _b; return rgbaTemplate({ red: rgbUnit.transform(red), green: rgbUnit.transform(green), blue: rgbUnit.transform(blue), alpha: sanitize(alpha.transform(alpha$$1)) }); } }; var hsla = { test: function (v) { return (typeof v === 'string' ? isColorString(v, 'hsl') : isHsla(v)); }, parse: splitColorValues(['hue', 'saturation', 'lightness', 'alpha']), transform: function (_a) { var hue = _a.hue, saturation = _a.saturation, lightness = _a.lightness, _b = _a.alpha, alpha$$1 = _b === void 0 ? 1 : _b; return hslaTemplate({ hue: Math.round(hue), saturation: percent.transform(sanitize(saturation)), lightness: percent.transform(sanitize(lightness)), alpha: sanitize(alpha.transform(alpha$$1)) }); } }; var hex = __assign$1({}, rgba, { test: function (v) { return typeof v === 'string' && isColorString(v, '#'); }, parse: function (v) { var r = ''; var g = ''; var b = ''; if (v.length > 4) { r = v.substr(1, 2); g = v.substr(3, 2); b = v.substr(5, 2); } else { r = v.substr(1, 1); g = v.substr(2, 1); b = v.substr(3, 1); r += r; g += g; b += b; } return { red: parseInt(r, 16), green: parseInt(g, 16), blue: parseInt(b, 16), alpha: 1 }; } }); var color = { test: function (v) { return (typeof v === 'string' && singleColorRegex.test(v)) || isRgba(v) || isHsla(v); }, parse: function (v) { if (rgba.test(v)) { return rgba.parse(v); } else if (hsla.test(v)) { return hsla.parse(v); } else if (hex.test(v)) { return hex.parse(v); } return v; }, transform: function (v) { if (isRgba(v)) { return rgba.transform(v); } else if (isHsla(v)) { return hsla.transform(v); } return v; } }; var COLOR_TOKEN = '${c}'; var NUMBER_TOKEN = '${n}'; var convertNumbersToZero = function (v) { return typeof v === 'number' ? 0 : v; }; var complex = { test: function (v) { if (typeof v !== 'string' || !isNaN(v)) return false; var numValues = 0; var foundNumbers = v.match(floatRegex); var foundColors = v.match(colorRegex); if (foundNumbers) numValues += foundNumbers.length; if (foundColors) numValues += foundColors.length; return numValues > 0; }, parse: function (v) { var input = v; var parsed = []; var foundColors = input.match(colorRegex); if (foundColors) { input = input.replace(colorRegex, COLOR_TOKEN); parsed.push.apply(parsed, foundColors.map(color.parse)); } var foundNumbers = input.match(floatRegex); if (foundNumbers) { parsed.push.apply(parsed, foundNumbers.map(number.parse)); } return parsed; }, createTransformer: function (prop) { var template = prop; var token = 0; var foundColors = prop.match(colorRegex); var numColors = foundColors ? foundColors.length : 0; if (foundColors) { for (var i = 0; i < numColors; i++) { template = template.replace(foundColors[i], COLOR_TOKEN); token++; } } var foundNumbers = template.match(floatRegex); var numNumbers = foundNumbers ? foundNumbers.length : 0; if (foundNumbers) { for (var i = 0; i < numNumbers; i++) { template = template.replace(foundNumbers[i], NUMBER_TOKEN); token++; } } return function (v) { var output = template; for (var i = 0; i < token; i++) { output = output.replace(i < numColors ? COLOR_TOKEN : NUMBER_TOKEN, i < numColors ? color.transform(v[i]) : sanitize(v[i])); } return output; }; }, getAnimatableNone: function (target) { var parsedTarget = complex.parse(target); var targetTransformer = complex.createTransformer(target); return targetTransformer(parsedTarget.map(convertNumbersToZero)); } }; var zeroPoint = { x: 0, y: 0, z: 0 }; var isNum = function (v) { return typeof v === 'number'; }; var curryRange = (function (func) { return function (min, max, v) { return (v !== undefined ? func(min, max, v) : function (cv) { return func(min, max, cv); }); }; }); var clamp$1 = function (min, max, v) { return Math.min(Math.max(v, min), max); }; var clamp$1$1 = curryRange(clamp$1); var isPoint = (function (point) { return point.hasOwnProperty('x') && point.hasOwnProperty('y'); }); var isPoint3D = (function (point) { return isPoint(point) && point.hasOwnProperty('z'); }); var distance1D = function (a, b) { return Math.abs(a - b); }; var distance = (function (a, b) { if (b === void 0) { b = zeroPoint; } if (isNum(a) && isNum(b)) { return distance1D(a, b); } else if (isPoint(a) && isPoint(b)) { var xDelta = distance1D(a.x, b.x); var yDelta = distance1D(a.y, b.y); var zDelta = isPoint3D(a) && isPoint3D(b) ? distance1D(a.z, b.z) : 0; return Math.sqrt(Math.pow(xDelta, 2) + Math.pow(yDelta, 2) + Math.pow(zDelta, 2)); } return 0; }); var progress = (function (from, to, value) { var toFromDifference = to - from; return toFromDifference === 0 ? 1 : (value - from) / toFromDifference; }); var mix = (function (from, to, progress) { return -progress * from + progress * to + from; }); /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign$2 = function() { __assign$2 = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign$2.apply(this, arguments); }; var mixLinearColor = function (from, to, v) { var fromExpo = from * from; var toExpo = to * to; return Math.sqrt(Math.max(0, v * (toExpo - fromExpo) + fromExpo)); }; var colorTypes = [hex, rgba, hsla]; var getColorType = function (v) { return colorTypes.find(function (type) { return type.test(v); }); }; var notAnimatable = function (color$$1) { return "'" + color$$1 + "' is not an animatable color. Use the equivalent color code instead."; }; var mixColor = (function (from, to) { var fromColorType = getColorType(from); var toColorType = getColorType(to); invariant(!!fromColorType, notAnimatable(from)); invariant(!!toColorType, notAnimatable(to)); invariant(fromColorType.transform === toColorType.transform, 'Both colors must be hex/RGBA, OR both must be HSLA.'); var fromColor = fromColorType.parse(from); var toColor = toColorType.parse(to); var blended = __assign$2({}, fromColor); var mixFunc = fromColorType === hsla ? mix : mixLinearColor; return function (v) { for (var key in blended) { if (key !== 'alpha') { blended[key] = mixFunc(fromColor[key], toColor[key], v); } } blended.alpha = mix(fromColor.alpha, toColor.alpha, v); return fromColorType.transform(blended); }; }); var combineFunctions = function (a, b) { return function (v) { return b(a(v)); }; }; var pipe = (function () { var transformers = []; for (var _i = 0; _i < arguments.length; _i++) { transformers[_i] = arguments[_i]; } return transformers.reduce(combineFunctions); }); function getMixer(origin, target) { if (isNum(origin)) { return function (v) { return mix(origin, target, v); }; } else if (color.test(origin)) { return mixColor(origin, target); } else { return mixComplex(origin, target); } } var mixArray = function (from, to) { var output = from.slice(); var numValues = output.length; var blendValue = from.map(function (fromThis, i) { return getMixer(fromThis, to[i]); }); return function (v) { for (var i = 0; i < numValues; i++) { output[i] = blendValue[i](v); } return output; }; }; var mixObject = function (origin, target) { var output = __assign$2({}, origin, target); var blendValue = {}; for (var key in output) { if (origin[key] !== undefined && target[key] !== undefined) { blendValue[key] = getMixer(origin[key], target[key]); } } return function (v) { for (var key in blendValue) { output[key] = blendValue[key](v); } return output; }; }; function analyse(value) { var parsed = complex.parse(value); var numValues = parsed.length; var numNumbers = 0; var numRGB = 0; var numHSL = 0; for (var i = 0; i < numValues; i++) { if (numNumbers || typeof parsed[i] === 'number') { numNumbers++; } else { if (parsed[i].hue !== undefined) { numHSL++; } else { numRGB++; } } } return { parsed: parsed, numNumbers: numNumbers, numRGB: numRGB, numHSL: numHSL }; } var mixComplex = function (origin, target) { var template = complex.createTransformer(target); var originStats = analyse(origin); var targetStats = analyse(target); invariant(originStats.numHSL === targetStats.numHSL && originStats.numRGB === targetStats.numRGB && originStats.numNumbers >= targetStats.numNumbers, "Complex values '" + origin + "' and '" + target + "' too different to mix. Ensure all colors are of the same type."); return pipe(mixArray(originStats.parsed, targetStats.parsed), template); }; var mixNumber = function (from, to) { return function (p) { return mix(from, to, p); }; }; function detectMixerFactory(v) { if (typeof v === 'number') { return mixNumber; } else if (typeof v === 'string') { if (color.test(v)) { return mixColor; } else { return mixComplex; } } else if (Array.isArray(v)) { return mixArray; } else if (typeof v === 'object') { return mixObject; } } function createMixers(output, ease, customMixer) { var mixers = []; var mixerFactory = customMixer || detectMixerFactory(output[0]); var numMixers = output.length - 1; for (var i = 0; i < numMixers; i++) { var mixer = mixerFactory(output[i], output[i + 1]); if (ease) { var easingFunction = Array.isArray(ease) ? ease[i] : ease; mixer = pipe(easingFunction, mixer); } mixers.push(mixer); } return mixers; } function fastInterpolate(_a, _b) { var from = _a[0], to = _a[1]; var mixer = _b[0]; return function (v) { return mixer(progress(from, to, v)); }; } function slowInterpolate(input, mixers) { var inputLength = input.length; var lastInputIndex = inputLength - 1; return function (v) { var mixerIndex = 0; var foundMixerIndex = false; if (v <= input[0]) { foundMixerIndex = true; } else if (v >= input[lastInputIndex]) { mixerIndex = lastInputIndex - 1; foundMixerIndex = true; } if (!foundMixerIndex) { var i = 1; for (; i < inputLength; i++) { if (input[i] > v || i === lastInputIndex) { break; } } mixerIndex = i - 1; } var progressInRange = progress(input[mixerIndex], input[mixerIndex + 1], v); return mixers[mixerIndex](progressInRange); }; } function interpolate(input, output, _a) { var _b = _a === void 0 ? {} : _a, _c = _b.clamp, clamp = _c === void 0 ? true : _c, ease = _b.ease, mixer = _b.mixer; var inputLength = input.length; invariant(inputLength === output.length, 'Both input and output ranges must be the same length'); 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.'); if (input[0] > input[inputLength - 1]) { input = [].concat(input); output = [].concat(output); input.reverse(); output.reverse(); } var mixers = createMixers(output, ease, mixer); var interpolator = inputLength === 2 ? fastInterpolate(input, mixers) : slowInterpolate(input, mixers); return clamp ? pipe(clamp$1$1(input[0], input[inputLength - 1]), interpolator) : interpolator; } var velocityPerSecond = (function (velocity, frameDuration) { return frameDuration ? velocity * (1000 / frameDuration) : 0; }); var wrap = function (min, max, v) { var rangeSize = max - min; return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min; }; var wrap$1 = curryRange(wrap); var clampProgress = clamp$1$1(0, 1); var isFloat = function (value) { return !isNaN(parseFloat(value)); }; /** * `MotionValue` is used to track the state and velocity of motion values. * * @public */ var MotionValue = /** @class */ (function () { /** * @param init - The initiating value * @param config - Optional configuration options * * - `transformer`: A function to transform incoming values with. * * @internal */ function MotionValue(init, _a) { var _this = this; var _b = _a === void 0 ? {} : _a, transformer = _b.transformer, parent = _b.parent; /** * Duration, in milliseconds, since last updating frame. * * @internal */ this.timeDelta = 0; /** * Timestamp of the last time this `MotionValue` was updated. * * @internal */ this.lastUpdated = 0; /** * Tracks whether this value can output a velocity. Currently this is only true * if the value is numerical, but we might be able to widen the scope here and support * other value types. * * @internal */ this.canTrackVelocity = false; this.updateAndNotify = function (v, render) { if (render === void 0) { render = true; } _this.prev = _this.current; _this.current = _this.transformer ? _this.transformer(v) : v; if (_this.updateSubscribers && _this.prev !== _this.current) { _this.updateSubscribers.forEach(_this.notifySubscriber); } if (_this.children) { _this.children.forEach(_this.setChild); } if (render && _this.renderSubscribers) { _this.renderSubscribers.forEach(_this.notifySubscriber); } // Update timestamp var _a = getFrameData(), delta = _a.delta, timestamp = _a.timestamp; if (_this.lastUpdated !== timestamp) { _this.timeDelta = delta; _this.lastUpdated = timestamp; sync.postRender(_this.scheduleVelocityCheck); } }; /** * Notify a subscriber with the latest value. * * This is an instanced and bound function to prevent generating a new * function once per frame. * * @param subscriber - The subscriber to notify. * * @internal */ this.notifySubscriber = function (subscriber) { subscriber(_this.current); }; /** * Schedule a velocity check for the next frame. * * This is an instanced and bound function to prevent generating a new * function once per frame. * * @internal */ this.scheduleVelocityCheck = function () { return sync.postRender(_this.velocityCheck); }; /** * Updates `prev` with `current` if the value hasn't been updated this frame. * This ensures velocity calculations return `0`. * * This is an instanced and bound function to prevent generating a new * function once per frame. * * @internal */ this.velocityCheck = function (_a) { var timestamp = _a.timestamp; if (timestamp !== _this.lastUpdated) { _this.prev = _this.current; } }; /** * Updates child `MotionValue`. * * @param child - Child `MotionValue`. * * @internal */ this.setChild = function (child) { return child.set(_this.current); }; this.parent = parent; this.transformer = transformer; this.set(init, false); this.canTrackVelocity = isFloat(this.current); } /** * Creates a new `MotionValue` that's subscribed to the output of this one. * * @param config - Optional configuration options * * - `transformer`: A function to transform incoming values with. * * @internal */ MotionValue.prototype.addChild = function (config) { if (config === void 0) { config = {}; } var child = new MotionValue(this.current, __assign({ parent: this }, config)); if (!this.children) this.children = new Set(); this.children.add(child); return child; }; /** * Stops a `MotionValue` from being subscribed to this one. * * @param child - The subscribed `MotionValue` * * @internal */ MotionValue.prototype.removeChild = function (child) { if (!this.children) { return; } this.children.delete(child); }; /** * Subscribes a subscriber function to a subscription list. * * @param subscriptions - A `Set` of subscribers. * @param subscription - A subscriber function. */ MotionValue.prototype.subscribeTo = function (subscriptions, subscription) { var _this = this; var updateSubscriber = function () { return subscription(_this.current); }; subscriptions.add(updateSubscriber); return function () { return subscriptions.delete(updateSubscriber); }; }; /** * Adds a function that will be notified when the `MotionValue` is updated. * * It returns a function that, when called, will cancel the subscription. * * When calling `onChange` inside a React component, it should be wrapped with the * `useEffect` hook. As it returns an unsubscribe function, this should be returned * from the `useEffect` function to ensure you don't add duplicate subscribers.. * * @library * * ```jsx * function MyComponent() { * const x = useMotionValue(0) * const y = useMotionValue(0) * const opacity = useMotionValue(1) * * useEffect(() => { * function updateOpacity() { * const maxXY = Math.max(x.get(), y.get()) * const newOpacity = transform(maxXY, [0, 100], [1, 0]) * opacity.set(newOpacity) * } * * const unsubscribeX = x.onChange(updateOpacity) * const unsubscribeY = y.onChange(updateOpacity) * * return () => { * unsubscribeX() * unsubscribeY() * } * }, []) * * return <Frame x={x} /> * } * ``` * * @motion * * ```jsx * export const MyComponent = () => { * const x = useMotionValue(0) * const y = useMotionValue(0) * const opacity = useMotionValue(1) * * useEffect(() => { * function updateOpacity() { * const maxXY = Math.max(x.get(), y.get()) * const newOpacity = transform(maxXY, [0, 100], [1, 0]) * opacity.set(newOpacity) * } * * const unsubscribeX = x.onChange(updateOpacity) * const unsubscribeY = y.onChange(updateOpacity) * * return () => { * unsubscribeX() * unsubscribeY() * } * }, []) * * return <motion.div style={{ x }} /> * } * ``` * * @internalremarks * * We could look into a `useOnChange` hook if the above lifecycle management proves confusing. * * ```jsx * useOnChange(x, () => {}) * ``` * * @param subscriber - A function that receives the latest value. * @returns A function that, when called, will cancel this subscription. * * @public */ MotionValue.prototype.onChange = function (subscription) { if (!this.updateSubscribers) this.updateSubscribers = new Set(); return this.subscribeTo(this.updateSubscribers, subscription); }; /** * Adds a function that will be notified when the `MotionValue` requests a render. * * @param subscriber - A function that's provided the latest value. * @returns A function that, when called, will cancel this subscription. * * @internal */ MotionValue.prototype.onRenderRequest = function (subscription) { if (!this.renderSubscribers) this.renderSubscribers = new Set(); // Render immediately this.notifySubscriber(subscription); return this.subscribeTo(this.renderSubscribers, subscription); }; /** * Attaches a passive effect to the `MotionValue`. * * @internal */ MotionValue.prototype.attach = function (passiveEffect) { this.passiveEffect = passiveEffect; }; /** * Sets the state of the `MotionValue`. * * @remarks * * ```jsx * const x = useMotionValue(0) * x.set(10) * ``` * * @param latest - Latest value to set. * @param render - Whether to notify render subscribers. Defaults to `true` * * @public */ MotionValue.prototype.set = function (v, render) { if (render === void 0) { render = true; } if (!render || !this.passiveEffect) { this.updateAndNotify(v, render); } else { this.passiveEffect(v, this.updateAndNotify); } }; /** * Returns the latest state of `MotionValue` * * @returns - The latest state of `MotionValue` * * @public */ MotionValue.prototype.get = function () { return this.current; }; /** * Returns the latest velocity of `MotionValue` * * @returns - The latest velocity of `MotionValue`. Returns `0` if the state is non-numerical. * * @public */ MotionValue.prototype.getVelocity = function () { // This could be isFloat(this.prev) && isFloat(this.current), but that would be wasteful return this.canTrackVelocity ? // These casts could be avoided if parseFloat would be typed better velocityPerSecond(parseFloat(this.current) - parseFloat(this.prev), this.timeDelta) : 0; }; /** * Registers a new animation to control this `MotionValue`. Only one * animation can drive a `MotionValue` at one time. * * ```jsx * value.start() * ``` * * @param animation - A function that starts the provided animation * * @internal */ MotionValue.prototype.start = function (animation) { var _this = this; this.stop(); return new Promise(function (resolve) { _this.stopAnimation = animation(resolve); }).then(function () { return _this.clearAnimation(); }); }; /** * Stop the currently active animation. * * @public */ MotionValue.prototype.stop = function () { if (this.stopAnimation) this.stopAnimation(); this.clearAnimation(); }; /** * Returns `true` if this value is currently animating. * * @public */ MotionValue.prototype.isAnimating = function () { return !!this.stopAnimation; }; MotionValue.prototype.clearAnimation = function () { this.stopAnimation = null; }; /** * Destroy and clean up subscribers to this `MotionValue`. * * The `MotionValue` hooks like `useMotionValue` and `useTransform` automatically * handle the lifecycle of the returned `MotionValue`, so this method is only necessary if you've manually * created a `MotionValue` via the `motionValue` function. * * @public */ MotionValue.prototype.destroy = function () { this.updateSubscribers && this.updateSubscribers.clear(); this.renderSubscribers && this.renderSubscribers.clear(); this.parent && this.parent.removeChild(this); this.stop(); }; return MotionValue; }()); /** * @internal */ function motionValue(init, opts) { return new MotionValue(init, opts); } /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign$3 = function () { __assign$3 = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign$3.apply(this, arguments); }; function __rest$1(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) t[p[i]] = s[p[i]]; return t; } var createStyler = function (_a) { var onRead = _a.onRead, onRender = _a.onRender, _b = _a.uncachedValues, uncachedValues = _b === void 0 ? new Set() : _b, _c = _a.useCache, useCache = _c === void 0 ? true : _c; return function (_a) { if (_a === void 0) { _a = {}; } var props = __rest$1(_a, []); var state = {}; var changedValues = []; var hasChanged = false; function setValue(key, value) { if (key.startsWith('--')) { props.hasCSSVariable = true; } var currentValue = state[key]; state[key] = value; if (state[key] === currentValue) return; if (changedValues.indexOf(key) === -1) { changedValues.push(key); } if (!hasChanged) { hasChanged = true; sync.render(styler.render); } } var styler = { get: function (key, forceRead) { if (forceRead === void 0) { forceRead = false; } var useCached = !forceRead && useCache && !uncachedValues.has(key) && state[key] !== undefined; return useCached ? state[key] : onRead(key, props); }, set: function (values, value) { if (typeof values === 'string') { setValue(values, value); } else { for (var key in values) { setValue(key, values[key]); } } return this; }, render: function (forceRender) { if (forceRender === void 0) { forceRender = false; } if (hasChanged || forceRender === true) { onRender(state, props, changedValues); hasChanged = false; changedValues.length = 0; } return this; } }; return styler; }; }; var CAMEL_CASE_PATTERN = /([a-z])([A-Z])/g; var REPLACE_TEMPLATE = '$1-$2'; var camelToDash = function (str) { return str.replace(CAMEL_CASE_PATTERN, REPLACE_TEMPLATE).toLowerCase(); }; var camelCache = /*#__PURE__*/new Map(); var dashCache = /*#__PURE__*/new Map(); var prefixes = ['Webkit', 'Moz', 'O', 'ms', '']; var numPrefixes = prefixes.length; var isBrowser = typeof document !== 'undefined'; var testElement; var setDashPrefix = function (key, prefixed) { return dashCache.set(key, camelToDash(prefixed)); }; var testPrefix = function (key) { testElement = testElement || document.createElement('div'); for (var i = 0; i < numPrefixes; i++) { var prefix = prefixes[i]; var noPrefix = prefix === ''; var prefixedPropertyName = noPrefix ? key : prefix + key.charAt(0).toUpperCase() + key.slice(1); if (prefixedPropertyName in testElement.style || noPrefix) { camelCache.set(key, prefixedPropertyName); setDashPrefix(key, "" + (noPrefix ? '' : '-') + camelToDash(prefixedPropertyName)); } } }; var setServerProperty = function (key) { return setDashPrefix(key, key); }; var prefixer = function (key, asDashCase) { if (asDashCase === void 0) { asDashCase = false; } var cache = asDashCase ? dashCache : camelCache; if (!cache.has(key)) isBrowser ? testPrefix(key) : setServerProperty(key); return cache.get(key) || key; }; var axes = ['', 'X', 'Y', 'Z']; var order = ['translate', 'scale', 'rotate', 'skew', 'transformPerspective']; var transformProps = /*#__PURE__*/order.reduce(function (acc, key) { return axes.reduce(function (axesAcc, axesKey) { axesAcc.push(key + axesKey); return axesAcc; }, acc); }, ['x', 'y', 'z']); var transformPropDictionary = /*#__PURE__*/transformProps.reduce(function (dict, key) { dict[key] = true; return dict; }, {}); function isTransformProp(key) { return transformPropDictionary[key] === true; } function sortTransformProps(a, b) { return transformProps.indexOf(a) - transformProps.indexOf(b); } var transformOriginProps = /*#__PURE__*/new Set(['originX', 'originY', 'originZ']); function isTransformOriginProp(key) { return transformOriginProps.has(key); } var int = /*#__PURE__*/__assign$3({}, number, { transform: Math.round }); var valueTypes = { color: color, backgroundColor: color, outlineColor: color,