UNPKG

addimated

Version:

An always interruptable, declarative animation library for React

250 lines (206 loc) 8.32 kB
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread"; import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; import _createClass from "@babel/runtime/helpers/esm/createClass"; import invariant from "invariant"; import normalizeColor from "normalize-css-color"; var linear = function linear(t) { return t; }; /** * Very handy helper to map input ranges to output ranges with an easing * function and custom behavior outside of the ranges. */ var Interpolation = /*#__PURE__*/ function () { function Interpolation() { _classCallCheck(this, Interpolation); } _createClass(Interpolation, null, [{ key: "create", value: function create(config) { if (config.outputRange && typeof config.outputRange[0] === "string") { return createInterpolationFromStringOutputRange(config); } var outputRange = config.outputRange; checkInfiniteRange("outputRange", outputRange); var inputRange = config.inputRange; checkInfiniteRange("inputRange", inputRange); checkValidInputRange(inputRange); !(inputRange.length === outputRange.length) ? process.env.NODE_ENV !== "production" ? invariant(false, "inputRange (" + inputRange.length + ") and outputRange (" + outputRange.length + ") must have the same length") : invariant(false) : void 0; var easing = config.easing || linear; var extrapolateLeft = "extend"; if (config.extrapolateLeft !== undefined) { extrapolateLeft = config.extrapolateLeft; } else if (config.extrapolate !== undefined) { extrapolateLeft = config.extrapolate; } var extrapolateRight = "extend"; if (config.extrapolateRight !== undefined) { extrapolateRight = config.extrapolateRight; } else if (config.extrapolate !== undefined) { extrapolateRight = config.extrapolate; } return function (input) { !(typeof input === "number") ? process.env.NODE_ENV !== "production" ? invariant(false, "Cannot interpolation an input which is not a number") : invariant(false) : void 0; var range = findRange(input, inputRange); return interpolate(input, inputRange[range], inputRange[range + 1], outputRange[range], outputRange[range + 1], easing, extrapolateLeft, extrapolateRight); }; } }]); return Interpolation; }(); function interpolate(input, inputMin, inputMax, outputMin, outputMax, easing, extrapolateLeft, extrapolateRight) { var result = input; // Extrapolate if (result < inputMin) { if (extrapolateLeft === "identity") { return result; } else if (extrapolateLeft === "clamp") { result = inputMin; } else if (extrapolateLeft === "extend") {// noop } } if (result > inputMax) { if (extrapolateRight === "identity") { return result; } else if (extrapolateRight === "clamp") { result = inputMax; } else if (extrapolateRight === "extend") {// noop } } if (outputMin === outputMax) { return outputMin; } if (inputMin === inputMax) { if (input <= inputMin) { return outputMin; } return outputMax; } // Input Range if (inputMin === -Infinity) { result = -result; } else if (inputMax === Infinity) { result = result - inputMin; } else { result = (result - inputMin) / (inputMax - inputMin); } // Easing result = easing(result); // Output Range if (outputMin === -Infinity) { result = -result; } else if (outputMax === Infinity) { result = result + outputMin; } else { result = result * (outputMax - outputMin) + outputMin; } return result; } function colorToRgba(input) { var int32Color = normalizeColor(input); if (int32Color === null) { return input; } int32Color = int32Color || 0; // $FlowIssue var r = (int32Color & 0xff000000) >>> 24; var g = (int32Color & 0x00ff0000) >>> 16; var b = (int32Color & 0x0000ff00) >>> 8; var a = (int32Color & 0x000000ff) / 255; return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(a, ")"); } // eslint-disable-next-line var stringShapeRegex = /[0-9\.-]+/g; /** * Supports string shapes by extracting numbers so new values can be computed, * and recombines those values into new strings of the same shape. Supports * things like: * * rgba(123, 42, 99, 0.36) // colors * -45deg // values with units */ function createInterpolationFromStringOutputRange(config) { var outputRange = config.outputRange; !(outputRange.length >= 2) ? process.env.NODE_ENV !== "production" ? invariant(false, "Bad output range") : invariant(false) : void 0; outputRange = outputRange.map(colorToRgba); checkPattern(outputRange); // ['rgba(0, 100, 200, 0)', 'rgba(50, 150, 250, 0.5)'] // -> // [ // [0, 50], // [100, 150], // [200, 250], // [0, 0.5], // ] /* $FlowFixMe(>=0.18.0): `outputRange[0].match()` can return `null`. Need to * guard against this possibility. */ var outputRanges = outputRange[0].match(stringShapeRegex).map(function () { return []; }); outputRange.forEach(function (value) { /* $FlowFixMe(>=0.18.0): `value.match()` can return `null`. Need to guard * against this possibility. */ value.match(stringShapeRegex).forEach(function (number, i) { outputRanges[i].push(+number); }); }); /* $FlowFixMe(>=0.18.0): `outputRange[0].match()` can return `null`. Need to * guard against this possibility. */ var interpolations = outputRange[0].match(stringShapeRegex).map(function (value, i) { return Interpolation.create(_objectSpread({}, config, { outputRange: outputRanges[i] })); }); // rgba requires that the r,g,b are integers.... so we want to round them, but we *dont* want to // round the opacity (4th column). var shouldRound = /^rgb/.test(outputRange[0]); return function (input) { var i = 0; // 'rgba(0, 100, 200, 0)' // -> // 'rgba(${interpolations[0](input)}, ${interpolations[1](input)}, ...' return outputRange[0].replace(stringShapeRegex, function () { var val = interpolations[i++](input); if (typeof val === "string") { val = parseInt(val, 10); } return String(shouldRound && i < 4 ? Math.round(val) : val); }); }; } function checkPattern(arr) { var pattern = arr[0].replace(stringShapeRegex, ""); for (var i = 1; i < arr.length; ++i) { !(pattern === arr[i].replace(stringShapeRegex, "")) ? process.env.NODE_ENV !== "production" ? invariant(false, "invalid pattern " + arr[0] + " and " + arr[i]) : invariant(false) : void 0; } } function findRange(input, inputRange) { for (var i = 1; i < inputRange.length - 1; ++i) { if (inputRange[i] >= input) { break; } } return i - 1; } function checkValidInputRange(arr) { !(arr.length >= 2) ? process.env.NODE_ENV !== "production" ? invariant(false, "inputRange must have at least 2 elements") : invariant(false) : void 0; for (var i = 1; i < arr.length; ++i) { !(arr[i] >= arr[i - 1]) ? process.env.NODE_ENV !== "production" ? invariant(false, /* $FlowFixMe(>=0.13.0) - In the addition expression below this comment, * one or both of the operands may be something that doesn't cleanly * convert to a string, like undefined, null, and object, etc. If you really * mean this implicit string conversion, you can do something like * String(myThing) */ "inputRange must be monotonically increasing " + arr) : invariant(false) : void 0; } } function checkInfiniteRange(name, arr) { !(arr.length >= 2) ? process.env.NODE_ENV !== "production" ? invariant(false, name + " must have at least 2 elements") : invariant(false) : void 0; !(arr.length !== 2 || arr[0] !== -Infinity || arr[1] !== Infinity) ? process.env.NODE_ENV !== "production" ? invariant(false, /* $FlowFixMe(>=0.13.0) - In the addition expression below this comment, * one or both of the operands may be something that doesn't cleanly convert * to a string, like undefined, null, and object, etc. If you really mean * this implicit string conversion, you can do something like * String(myThing) */ name + "cannot be ]-infinity;+infinity[ " + arr) : invariant(false) : void 0; } export { Interpolation }; //# sourceMappingURL=Interpolation.js.map