UNPKG

react-native

Version:

A framework for building native apps using React

166 lines (148 loc) 5.06 kB
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow * @format */ 'use strict'; import type {PlatformConfig} from '../AnimatedPlatformConfig'; import {validateTransform} from '../../../src/private/animated/NativeAnimatedValidation'; import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; import AnimatedNode from './AnimatedNode'; import AnimatedWithChildren from './AnimatedWithChildren'; type Transform<T = AnimatedNode> = { [string]: | number | string | T | $ReadOnlyArray<number | string | T> | {[string]: number | string | T}, }; export default class AnimatedTransform extends AnimatedWithChildren { // NOTE: For potentially historical reasons, some operations only operate on // the first level of AnimatedNode instances. This optimizes that bevavior. #shallowNodes: $ReadOnlyArray<AnimatedNode>; _transforms: $ReadOnlyArray<Transform<>>; constructor(transforms: $ReadOnlyArray<Transform<>>) { super(); this._transforms = transforms; const shallowNodes = []; // NOTE: This check should not be necessary, but the types are not enforced // as of this writing. This check should be hoisted to instantiation sites. if (Array.isArray(transforms)) { for (let ii = 0, length = transforms.length; ii < length; ii++) { const transform = transforms[ii]; // There should be exactly one property in `transform`. for (const key in transform) { const value = transform[key]; if (value instanceof AnimatedNode) { shallowNodes.push(value); } } } } this.#shallowNodes = shallowNodes; } __makeNative(platformConfig: ?PlatformConfig) { const nodes = this.#shallowNodes; for (let ii = 0, length = nodes.length; ii < length; ii++) { const node = nodes[ii]; node.__makeNative(platformConfig); } super.__makeNative(platformConfig); } __getValue(): $ReadOnlyArray<Transform<any>> { return mapTransforms(this._transforms, animatedNode => animatedNode.__getValue(), ); } __getAnimatedValue(): $ReadOnlyArray<Transform<any>> { return mapTransforms(this._transforms, animatedNode => animatedNode.__getAnimatedValue(), ); } __attach(): void { const nodes = this.#shallowNodes; for (let ii = 0, length = nodes.length; ii < length; ii++) { const node = nodes[ii]; node.__addChild(this); } } __detach(): void { const nodes = this.#shallowNodes; for (let ii = 0, length = nodes.length; ii < length; ii++) { const node = nodes[ii]; node.__removeChild(this); } super.__detach(); } __getNativeConfig(): any { const transformsConfig: Array<any> = []; const transforms = this._transforms; for (let ii = 0, length = transforms.length; ii < length; ii++) { const transform = transforms[ii]; // There should be exactly one property in `transform`. for (const key in transform) { const value = transform[key]; if (value instanceof AnimatedNode) { transformsConfig.push({ type: 'animated', property: key, nodeTag: value.__getNativeTag(), }); } else { transformsConfig.push({ type: 'static', property: key, /* $FlowFixMe[incompatible-call] - `value` can be an array or an object. This is not currently handled by `transformDataType`. Migrating to `TransformObject` might solve this. */ value: NativeAnimatedHelper.transformDataType(value), }); } } } if (__DEV__) { validateTransform(transformsConfig); } return { type: 'transform', transforms: transformsConfig, }; } } function mapTransforms<T>( transforms: $ReadOnlyArray<Transform<>>, mapFunction: AnimatedNode => T, ): $ReadOnlyArray<Transform<T>> { return transforms.map(transform => { const result: Transform<T> = {}; // There should be exactly one property in `transform`. for (const key in transform) { const value = transform[key]; if (value instanceof AnimatedNode) { result[key] = mapFunction(value); } else if (Array.isArray(value)) { result[key] = value.map(element => element instanceof AnimatedNode ? mapFunction(element) : element, ); } else if (typeof value === 'object') { const object: {[string]: number | string | T} = {}; for (const propertyName in value) { const propertyValue = value[propertyName]; object[propertyName] = propertyValue instanceof AnimatedNode ? mapFunction(propertyValue) : propertyValue; } result[key] = object; } else { result[key] = value; } } return result; }); }