Files
react-native/Libraries/StyleSheet/processTransform.js
T
Andrew ee33385cdd Unify platform behavior of processTransform (#33579)
Summary:
Currently both iOS and Android send over the list of transforms as an array.   But there is an if statement that causes other platforms to get a matrix.  This prevents other platforms from being able to use the fabric ViewProps class and the conversion functions as they exist in core, as those expect the transforms to be an array.

Stop special casing iOS and android. - Which will allow for example Windows to be able to share more fabric code.

## Changelog

[Internal] [Changed] - All platforms should get transform sent to native as an array of transform operations instead of a matrix

Pull Request resolved: https://github.com/facebook/react-native/pull/33579

Test Plan:
Similar change made in react-native-windows.
https://github.com/microsoft/react-native-windows/issues/9797

Reviewed By: NickGerleman

Differential Revision: D38615676

Pulled By: cortinico

fbshipit-source-id: 8861afe6bf34bebb09dd82f7365faf007dd79cbf
2022-08-15 06:37:16 -07:00

164 lines
4.6 KiB
JavaScript

/**
* 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.
*
* @format
* @flow
*/
'use strict';
const invariant = require('invariant');
const stringifySafe = require('../Utilities/stringifySafe').default;
/**
* Generate a transform matrix based on the provided transforms, and use that
* within the style object instead.
*
* This allows us to provide an API that is similar to CSS, where transforms may
* be applied in an arbitrary order, and yet have a universal, singular
* interface to native code.
*/
function processTransform(
transform: Array<Object>,
): Array<Object> | Array<number> {
if (__DEV__) {
_validateTransforms(transform);
}
return transform;
}
function _validateTransforms(transform: Array<Object>): void {
transform.forEach(transformation => {
const keys = Object.keys(transformation);
invariant(
keys.length === 1,
'You must specify exactly one property per transform object. Passed properties: %s',
stringifySafe(transformation),
);
const key = keys[0];
const value = transformation[key];
_validateTransform(key, value, transformation);
});
}
function _validateTransform(
key:
| string
| $TEMPORARY$string<'matrix'>
| $TEMPORARY$string<'perspective'>
| $TEMPORARY$string<'rotate'>
| $TEMPORARY$string<'rotateX'>
| $TEMPORARY$string<'rotateY'>
| $TEMPORARY$string<'rotateZ'>
| $TEMPORARY$string<'scale'>
| $TEMPORARY$string<'scaleX'>
| $TEMPORARY$string<'scaleY'>
| $TEMPORARY$string<'skewX'>
| $TEMPORARY$string<'skewY'>
| $TEMPORARY$string<'translate'>
| $TEMPORARY$string<'translateX'>
| $TEMPORARY$string<'translateY'>,
value: any | number | string,
transformation: any,
) {
invariant(
!value.getValue,
'You passed an Animated.Value to a normal component. ' +
'You need to wrap that component in an Animated. For example, ' +
'replace <View /> by <Animated.View />.',
);
const multivalueTransforms = ['matrix', 'translate'];
if (multivalueTransforms.indexOf(key) !== -1) {
invariant(
Array.isArray(value),
'Transform with key of %s must have an array as the value: %s',
key,
stringifySafe(transformation),
);
}
switch (key) {
case 'matrix':
invariant(
value.length === 9 || value.length === 16,
'Matrix transform must have a length of 9 (2d) or 16 (3d). ' +
'Provided matrix has a length of %s: %s',
/* $FlowFixMe[prop-missing] (>=0.84.0 site=react_native_fb) This
* comment suppresses an error found when Flow v0.84 was deployed. To
* see the error, delete this comment and run Flow. */
value.length,
stringifySafe(transformation),
);
break;
case 'translate':
invariant(
value.length === 2 || value.length === 3,
'Transform with key translate must be an array of length 2 or 3, found %s: %s',
/* $FlowFixMe[prop-missing] (>=0.84.0 site=react_native_fb) This
* comment suppresses an error found when Flow v0.84 was deployed. To
* see the error, delete this comment and run Flow. */
value.length,
stringifySafe(transformation),
);
break;
case 'rotateX':
case 'rotateY':
case 'rotateZ':
case 'rotate':
case 'skewX':
case 'skewY':
invariant(
typeof value === 'string',
'Transform with key of "%s" must be a string: %s',
key,
stringifySafe(transformation),
);
invariant(
value.indexOf('deg') > -1 || value.indexOf('rad') > -1,
'Rotate transform must be expressed in degrees (deg) or radians ' +
'(rad): %s',
stringifySafe(transformation),
);
break;
case 'perspective':
invariant(
typeof value === 'number',
'Transform with key of "%s" must be a number: %s',
key,
stringifySafe(transformation),
);
invariant(
value !== 0,
'Transform with key of "%s" cannot be zero: %s',
key,
stringifySafe(transformation),
);
break;
case 'translateX':
case 'translateY':
case 'scale':
case 'scaleX':
case 'scaleY':
invariant(
typeof value === 'number',
'Transform with key of "%s" must be a number: %s',
key,
stringifySafe(transformation),
);
break;
default:
invariant(
false,
'Invalid transform %s: %s',
key,
stringifySafe(transformation),
);
}
}
module.exports = processTransform;