UNPKG

@tamagui/react-native-web-lite

Version:
198 lines (197 loc) 7.11 kB
import { AnimatedWithChildren } from "./AnimatedWithChildren.mjs"; import { NativeAnimatedHelper } from "../NativeAnimatedHelper.mjs"; import { normalizeColor, invariant } from "@tamagui/react-native-web-internals"; const __DEV__ = process.env.NODE_ENV !== "production"; const linear = t => t; function createInterpolation(config) { if (config.outputRange && typeof config.outputRange[0] === "string") { return createInterpolationFromStringOutputRange(config); } const outputRange = config.outputRange; const inputRange = config.inputRange; if (__DEV__) { checkInfiniteRange("outputRange", outputRange); checkInfiniteRange("inputRange", inputRange); checkValidInputRange(inputRange); invariant(inputRange.length === outputRange.length, "inputRange (" + inputRange.length + ") and outputRange (" + outputRange.length + ") must have the same length"); } const easing = config.easing || linear; let extrapolateLeft = "extend"; if (config.extrapolateLeft !== void 0) { extrapolateLeft = config.extrapolateLeft; } else if (config.extrapolate !== void 0) { extrapolateLeft = config.extrapolate; } let extrapolateRight = "extend"; if (config.extrapolateRight !== void 0) { extrapolateRight = config.extrapolateRight; } else if (config.extrapolate !== void 0) { extrapolateRight = config.extrapolate; } return input => { invariant(typeof input === "number", "Cannot interpolation an input which is not a number"); const range = findRange(input, inputRange); return interpolate(input, inputRange[range], inputRange[range + 1], outputRange[range], outputRange[range + 1], easing, extrapolateLeft, extrapolateRight); }; } function interpolate(input, inputMin, inputMax, outputMin, outputMax, easing, extrapolateLeft, extrapolateRight) { let result = input; if (result < inputMin) { if (extrapolateLeft === "identity") { return result; } else if (extrapolateLeft === "clamp") { result = inputMin; } else if (extrapolateLeft === "extend") {} } if (result > inputMax) { if (extrapolateRight === "identity") { return result; } else if (extrapolateRight === "clamp") { result = inputMax; } else if (extrapolateRight === "extend") {} } if (outputMin === outputMax) { return outputMin; } if (inputMin === inputMax) { if (input <= inputMin) { return outputMin; } return outputMax; } if (inputMin === -Infinity) { result = -result; } else if (inputMax === Infinity) { result = result - inputMin; } else { result = (result - inputMin) / (inputMax - inputMin); } result = easing(result); if (outputMin === -Infinity) { result = -result; } else if (outputMax === Infinity) { result = result + outputMin; } else { result = result * (outputMax - outputMin) + outputMin; } return result; } function colorToRgba(input) { let normalizedColor = normalizeColor(input); if (normalizedColor === null || typeof normalizedColor !== "number") { return input; } normalizedColor = normalizedColor || 0; const r = (normalizedColor & 4278190080) >>> 24; const g = (normalizedColor & 16711680) >>> 16; const b = (normalizedColor & 65280) >>> 8; const a = (normalizedColor & 255) / 255; return `rgba(${r}, ${g}, ${b}, ${a})`; } const stringShapeRegex = /[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/g; function createInterpolationFromStringOutputRange(config) { let outputRange = config.outputRange; invariant(outputRange.length >= 2, "Bad output range"); outputRange = outputRange.map(colorToRgba); checkPattern(outputRange); const outputRanges = outputRange[0].match(stringShapeRegex).map(() => []); outputRange.forEach(value => { value.match(stringShapeRegex).forEach((number, i) => { outputRanges[i].push(+number); }); }); const interpolations = outputRange[0].match(stringShapeRegex).map((value, i) => { return createInterpolation({ ...config, outputRange: outputRanges[i] }); }); const shouldRound = isRgbOrRgba(outputRange[0]); return input => { let i = 0; return outputRange[0].replace(stringShapeRegex, () => { let val = +interpolations[i++](input); if (shouldRound) { val = i < 4 ? Math.round(val) : Math.round(val * 1e3) / 1e3; } return String(val); }); }; } function isRgbOrRgba(range) { return typeof range === "string" && range.startsWith("rgb"); } function checkPattern(arr) { const pattern = arr[0].replace(stringShapeRegex, ""); for (let i = 1; i < arr.length; ++i) { invariant(pattern === arr[i].replace(stringShapeRegex, ""), "invalid pattern " + arr[0] + " and " + arr[i]); } } function findRange(input, inputRange) { let i; for (i = 1; i < inputRange.length - 1; ++i) { if (inputRange[i] >= input) { break; } } return i - 1; } function checkValidInputRange(arr) { invariant(arr.length >= 2, "inputRange must have at least 2 elements"); const message = "inputRange must be monotonically non-decreasing " + String(arr); for (let i = 1; i < arr.length; ++i) { invariant(arr[i] >= arr[i - 1], message); } } function checkInfiniteRange(name, arr) { invariant(arr.length >= 2, name + " must have at least 2 elements"); invariant(arr.length !== 2 || arr[0] !== -Infinity || arr[1] !== Infinity, name + "cannot be ]-infinity;+infinity[ " + arr); } class AnimatedInterpolation extends AnimatedWithChildren { // Export for testing. static __createInterpolation = createInterpolation; constructor(parent, config) { super(); this._parent = parent; this._config = config; this._interpolation = createInterpolation(config); } __makeNative(platformConfig) { this._parent.__makeNative(platformConfig); super.__makeNative(platformConfig); } __getValue() { const parentValue = this._parent.__getValue(); invariant(typeof parentValue === "number", "Cannot interpolate an input which is not a number."); return this._interpolation(parentValue); } interpolate(config) { return new AnimatedInterpolation(this, config); } __attach() { this._parent.__addChild(this); } __detach() { this._parent.__removeChild(this); super.__detach(); } __transformDataType(range) { return range.map(NativeAnimatedHelper.transformDataType); } __getNativeConfig() { if (__DEV__) { NativeAnimatedHelper.validateInterpolation(this._config); } return { inputRange: this._config.inputRange, // Only the `outputRange` can contain strings so we don't need to transform `inputRange` here outputRange: this.__transformDataType(this._config.outputRange), extrapolateLeft: this._config.extrapolateLeft || this._config.extrapolate || "extend", extrapolateRight: this._config.extrapolateRight || this._config.extrapolate || "extend", type: "interpolation" }; } } var AnimatedInterpolation_default = AnimatedInterpolation; export { AnimatedInterpolation, AnimatedInterpolation_default as default }; //# sourceMappingURL=AnimatedInterpolation.mjs.map