Skip to content

Commit 33e50f5

Browse files
zeyapfacebook-github-bot
authored andcommitted
(js part) Support PlatformColor type of toValue and interpolation outputRange (facebook#54457)
Summary: ## Changelog: [General] [Added] (js part) Support PlatformColor type of toValue and interpolation outputRange Reviewed By: javache Differential Revision: D86255713
1 parent e08abbc commit 33e50f5

File tree

5 files changed

+84
-34
lines changed

5 files changed

+84
-34
lines changed

packages/react-native/Libraries/Animated/createAnimatedComponent.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* @format
99
*/
1010

11+
import type {NativeColorValue} from '../StyleSheet/StyleSheetTypes';
1112
import type AnimatedAddition from './nodes/AnimatedAddition';
1213
import type AnimatedDiffClamp from './nodes/AnimatedDiffClamp';
1314
import type AnimatedDivision from './nodes/AnimatedDivision';
@@ -46,6 +47,7 @@ export type WithAnimatedValue<+T> = T extends Builtin | Nullable
4647
| AnimatedInterpolation<number | string>
4748
| AnimatedInterpolation<number>
4849
| AnimatedInterpolation<string>
50+
| AnimatedInterpolation<NativeColorValue>
4951
: T extends $ReadOnlyArray<infer P>
5052
? $ReadOnlyArray<WithAnimatedValue<P>>
5153
: T extends {...}

packages/react-native/Libraries/Animated/nodes/AnimatedInterpolation.js

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
'use strict';
1414

15+
import type {NativeColorValue} from '../../StyleSheet/StyleSheetTypes';
1516
import type {PlatformConfig} from '../AnimatedPlatformConfig';
1617
import type AnimatedNode from './AnimatedNode';
1718
import type {AnimatedNodeConfig} from './AnimatedNode';
@@ -26,7 +27,14 @@ import invariant from 'invariant';
2627

2728
type ExtrapolateType = 'extend' | 'identity' | 'clamp';
2829

29-
export type InterpolationConfigType<OutputT: number | string> = $ReadOnly<{
30+
export type InterpolationConfigSupportedOutputType =
31+
| number
32+
| string
33+
| NativeColorValue;
34+
35+
export type InterpolationConfigType<
36+
OutputT: InterpolationConfigSupportedOutputType,
37+
> = $ReadOnly<{
3038
...AnimatedNodeConfig,
3139
inputRange: $ReadOnlyArray<number>,
3240
outputRange: $ReadOnlyArray<OutputT>,
@@ -82,6 +90,28 @@ function createNumericInterpolation(
8290
};
8391
}
8492

93+
function createPlatformColorInterpolation(
94+
config: InterpolationConfigType<NativeColorValue>,
95+
): (input: number) => NativeColorValue {
96+
const outputRange = config.outputRange;
97+
const outputRangeIndices = Array.from(Array(outputRange.length).keys());
98+
const interpolateIndex = createNumericInterpolation({
99+
...config,
100+
inputRange: config.inputRange,
101+
outputRange: outputRangeIndices,
102+
});
103+
104+
return input => {
105+
const interpolateResult = interpolateIndex(input);
106+
if (!Number.isInteger(interpolateResult)) {
107+
console.warn(
108+
'PlatformColor interpolation should happen natively, here we fallback to the closest color',
109+
);
110+
}
111+
return outputRange[Math.floor(interpolateResult)];
112+
};
113+
}
114+
85115
function interpolate(
86116
input: number,
87117
inputMin: number,
@@ -277,7 +307,7 @@ function findRange(input: number, inputRange: $ReadOnlyArray<number>) {
277307
return i - 1;
278308
}
279309

280-
function checkValidRanges<OutputT: number | string>(
310+
function checkValidRanges<OutputT: InterpolationConfigSupportedOutputType>(
281311
inputRange: $ReadOnlyArray<number>,
282312
outputRange: $ReadOnlyArray<OutputT>,
283313
) {
@@ -304,7 +334,7 @@ function checkValidInputRange(arr: $ReadOnlyArray<number>) {
304334
}
305335
}
306336

307-
function checkInfiniteRange<OutputT: number | string>(
337+
function checkInfiniteRange<OutputT: InterpolationConfigSupportedOutputType>(
308338
name: string,
309339
arr: $ReadOnlyArray<OutputT>,
310340
) {
@@ -322,7 +352,7 @@ function checkInfiniteRange<OutputT: number | string>(
322352
}
323353

324354
export default class AnimatedInterpolation<
325-
OutputT: number | string,
355+
OutputT: InterpolationConfigSupportedOutputType,
326356
> extends AnimatedWithChildren {
327357
_parent: AnimatedNode;
328358
_config: InterpolationConfigType<OutputT>;
@@ -347,6 +377,10 @@ export default class AnimatedInterpolation<
347377
const config = this._config;
348378
if (config.outputRange && typeof config.outputRange[0] === 'string') {
349379
this._interpolation = (createStringInterpolation((config: any)): any);
380+
} else if (typeof config.outputRange[0] === 'object') {
381+
this._interpolation = (createPlatformColorInterpolation(
382+
(config: any),
383+
): any);
350384
} else {
351385
this._interpolation = (createNumericInterpolation((config: any)): any);
352386
}
@@ -403,6 +437,8 @@ export default class AnimatedInterpolation<
403437
return NativeAnimatedHelper.transformDataType(value);
404438
}
405439
}): any);
440+
} else if (typeof outputRange[0] === 'object') {
441+
outputType = 'platform_color';
406442
}
407443

408444
return {

packages/react-native/Libraries/Animated/nodes/AnimatedValue.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import type {EventSubscription} from '../../vendor/emitter/EventEmitter';
1212
import type {PlatformConfig} from '../AnimatedPlatformConfig';
1313
import type Animation from '../animations/Animation';
1414
import type {EndCallback} from '../animations/Animation';
15-
import type {InterpolationConfigType} from './AnimatedInterpolation';
15+
import type {
16+
InterpolationConfigSupportedOutputType,
17+
InterpolationConfigType,
18+
} from './AnimatedInterpolation';
1619
import type AnimatedNode from './AnimatedNode';
1720
import type {AnimatedNodeConfig} from './AnimatedNode';
1821
import type AnimatedTracking from './AnimatedTracking';
@@ -298,7 +301,7 @@ export default class AnimatedValue extends AnimatedWithChildren {
298301
* Interpolates the value before updating the property, e.g. mapping 0-1 to
299302
* 0-10.
300303
*/
301-
interpolate<OutputT: number | string>(
304+
interpolate<OutputT: InterpolationConfigSupportedOutputType>(
302305
config: InterpolationConfigType<OutputT>,
303306
): AnimatedInterpolation<OutputT> {
304307
return new AnimatedInterpolation(this, config);

packages/react-native/ReactNativeApi.d.ts

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<1eb51bd683ea578d108218d5a48c42ec>>
7+
* @generated SignedSource<<fe4e120a96b8868072879c03da80112b>>
88
*
99
* This file was generated by scripts/js-api/build-types/index.js.
1010
*/
@@ -1453,7 +1453,7 @@ declare class AnimatedEvent {
14531453
)
14541454
}
14551455
declare class AnimatedInterpolation_default<
1456-
OutputT extends number | string,
1456+
OutputT extends InterpolationConfigSupportedOutputType,
14571457
> extends AnimatedWithChildren_default {
14581458
constructor(
14591459
parent: AnimatedNode_default,
@@ -1534,7 +1534,7 @@ declare class AnimatedValue_default extends AnimatedWithChildren_default {
15341534
constructor(value: number, config?: AnimatedValueConfig | null | undefined)
15351535
extractOffset(): void
15361536
flattenOffset(): void
1537-
interpolate<OutputT extends number | string>(
1537+
interpolate<OutputT extends InterpolationConfigSupportedOutputType>(
15381538
config: InterpolationConfigType<OutputT>,
15391539
): AnimatedInterpolation_default<OutputT>
15401540
removeAllListeners(): void
@@ -2766,17 +2766,22 @@ declare type InternalTextInput = (
27662766
ref?: React.Ref<TextInputInstance>
27672767
},
27682768
) => React.ReactNode
2769-
declare type InterpolationConfigType<OutputT extends number | string> =
2770-
Readonly<
2771-
AnimatedNodeConfig & {
2772-
extrapolate?: ExtrapolateType
2773-
extrapolateLeft?: ExtrapolateType
2774-
extrapolateRight?: ExtrapolateType
2775-
inputRange: ReadonlyArray<number>
2776-
outputRange: ReadonlyArray<OutputT>
2777-
easing?: (input: number) => number
2778-
}
2779-
>
2769+
declare type InterpolationConfigSupportedOutputType =
2770+
| NativeColorValue
2771+
| number
2772+
| string
2773+
declare type InterpolationConfigType<
2774+
OutputT extends InterpolationConfigSupportedOutputType,
2775+
> = Readonly<
2776+
AnimatedNodeConfig & {
2777+
extrapolate?: ExtrapolateType
2778+
extrapolateLeft?: ExtrapolateType
2779+
extrapolateRight?: ExtrapolateType
2780+
inputRange: ReadonlyArray<number>
2781+
outputRange: ReadonlyArray<OutputT>
2782+
easing?: (input: number) => number
2783+
}
2784+
>
27802785
declare type IOSKeyboardEvent = Readonly<
27812786
BaseKeyboardEvent & {
27822787
isEventFromThisApp: boolean
@@ -5899,6 +5904,7 @@ declare type WithAnimatedValue<T> = T extends Builtin | Nullable
58995904
| AnimatedAddition_default
59005905
| AnimatedDiffClamp_default
59015906
| AnimatedDivision_default
5907+
| AnimatedInterpolation_default<NativeColorValue>
59025908
| AnimatedInterpolation_default<number | string>
59035909
| AnimatedInterpolation_default<number>
59045910
| AnimatedInterpolation_default<string>
@@ -5940,7 +5946,7 @@ export {
59405946
AlertOptions, // a0cdac0f
59415947
AlertType, // 5ab91217
59425948
AndroidKeyboardEvent, // e03becc8
5943-
Animated, // 6b6a0b2e
5949+
Animated, // e48a2408
59445950
AppConfig, // ebddad4b
59455951
AppRegistry, // 6cdee1d6
59465952
AppState, // f7097b1b
@@ -5986,8 +5992,8 @@ export {
59865992
EventSubscription, // b8d084aa
59875993
ExtendedExceptionData, // 5a6ccf5a
59885994
FilterFunction, // bf24c0e3
5989-
FlatList, // cbb48cbe
5990-
FlatListProps, // 451be810
5995+
FlatList, // ee0215d3
5996+
FlatListProps, // 53c344dc
59915997
FocusEvent, // 529b43eb
59925998
FontVariant, // 7c7558bb
59935999
GestureResponderEvent, // b466f6d6
@@ -6120,14 +6126,14 @@ export {
61206126
ScrollToLocationParamsType, // d7ecdad1
61216127
ScrollView, // 7fb7c469
61226128
ScrollViewImperativeMethods, // eb20aa46
6123-
ScrollViewProps, // 27986ff5
6129+
ScrollViewProps, // bb4d0dd0
61246130
ScrollViewPropsAndroid, // 84e2134b
61256131
ScrollViewPropsIOS, // d83c9733
61266132
ScrollViewScrollToOptions, // 3313411e
61276133
SectionBase, // b376bddc
6128-
SectionList, // ff1193b2
6134+
SectionList, // 84642036
61296135
SectionListData, // 119baf83
6130-
SectionListProps, // c9ac8e07
6136+
SectionListProps, // 4fe82009
61316137
SectionListRenderItem, // 1fad0435
61326138
SectionListRenderItemInfo, // 745e1992
61336139
Separators, // 6a45f7e3
@@ -6176,7 +6182,7 @@ export {
61766182
TouchableNativeFeedback, // aaa5b42c
61776183
TouchableNativeFeedbackProps, // 372d3213
61786184
TouchableOpacity, // 7e33acfd
6179-
TouchableOpacityProps, // ba6c0ba4
6185+
TouchableOpacityProps, // 73c84562
61806186
TouchableWithoutFeedback, // 7363a906
61816187
TouchableWithoutFeedbackProps, // 68e3d87f
61826188
TransformsStyle, // 65e70f18
@@ -6192,17 +6198,17 @@ export {
61926198
ViewStyle, // c2db0e6e
61936199
VirtualViewMode, // 85a69ef6
61946200
VirtualizedList, // 4d513939
6195-
VirtualizedListProps, // a99d36db
6201+
VirtualizedListProps, // 06d07d2b
61966202
VirtualizedSectionList, // 446ba0df
6197-
VirtualizedSectionListProps, // 6cd4b378
6203+
VirtualizedSectionListProps, // 05937609
61986204
WrapperComponentProvider, // 9cf3844c
61996205
codegenNativeCommands, // e16d62f7
62006206
codegenNativeComponent, // ed4c8103
62016207
findNodeHandle, // c6b08494
62026208
processColor, // 00453092
62036209
registerCallableModule, // 86b65226
62046210
requireNativeComponent, // e659aa32
6205-
useAnimatedValue, // 2c80bbc2
6211+
useAnimatedValue, // b18adb63
62066212
useColorScheme, // c216d6f7
62076213
useWindowDimensions, // bb4b683f
62086214
}

packages/react-native/src/private/animated/NativeAnimatedValidation.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@
88
* @format
99
*/
1010

11-
import type {InterpolationConfigType} from '../../../Libraries/Animated/nodes/AnimatedInterpolation';
11+
import type {
12+
InterpolationConfigSupportedOutputType,
13+
InterpolationConfigType,
14+
} from '../../../Libraries/Animated/nodes/AnimatedInterpolation';
1215

1316
import {
1417
isSupportedInterpolationParam,
1518
isSupportedStyleProp,
1619
isSupportedTransformProp,
1720
} from '../../../Libraries/Animated/NativeAnimatedAllowlist';
1821

19-
export function validateInterpolation<OutputT: number | string>(
20-
config: InterpolationConfigType<OutputT>,
21-
): void {
22+
export function validateInterpolation<
23+
OutputT: InterpolationConfigSupportedOutputType,
24+
>(config: InterpolationConfigType<OutputT>): void {
2225
for (const key in config) {
2326
if (key !== 'debugID' && !isSupportedInterpolationParam(key)) {
2427
console.error(

0 commit comments

Comments
 (0)