@office-iss/react-native-win32 0.0.0-canary.264 → 0.0.0-canary.265

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/.flowconfig +1 -1
  2. package/CHANGELOG.json +14981 -14942
  3. package/CHANGELOG.md +31 -19
  4. package/Libraries/Animated/AnimatedImplementation.js +2 -2
  5. package/Libraries/Animated/NativeAnimatedAllowlist.js +20 -9
  6. package/Libraries/Animated/animations/Animation.js +1 -4
  7. package/Libraries/Animated/createAnimatedComponent.js +13 -0
  8. package/Libraries/Animated/nodes/AnimatedNode.js +39 -45
  9. package/Libraries/Animated/nodes/AnimatedObject.js +13 -3
  10. package/Libraries/Animated/nodes/AnimatedProps.js +81 -37
  11. package/Libraries/Animated/nodes/AnimatedStyle.js +104 -39
  12. package/Libraries/Animated/nodes/AnimatedTransform.js +55 -22
  13. package/Libraries/Animated/nodes/AnimatedWithChildren.js +1 -3
  14. package/Libraries/Animated/useAnimatedProps.js +38 -20
  15. package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +3 -1
  16. package/Libraries/Components/ScrollView/ScrollView.js +12 -9
  17. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +3 -0
  18. package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +10 -0
  19. package/Libraries/Components/TextInput/TextInput.d.ts +19 -0
  20. package/Libraries/Components/TextInput/TextInput.flow.js +17 -1
  21. package/Libraries/Components/TextInput/TextInput.js +17 -1
  22. package/Libraries/Components/TextInput/TextInput.win32.js +17 -1
  23. package/Libraries/Components/Touchable/TouchableBounce.js +1 -1
  24. package/Libraries/Components/Touchable/TouchableHighlight.js +2 -2
  25. package/Libraries/Components/Touchable/TouchableOpacity.js +1 -1
  26. package/Libraries/Components/View/ReactNativeStyleAttributes.js +6 -2
  27. package/Libraries/Core/ReactNativeVersion.js +2 -2
  28. package/Libraries/Image/AssetSourceResolver.js +12 -1
  29. package/Libraries/Modal/Modal.d.ts +7 -0
  30. package/Libraries/Modal/Modal.js +9 -1
  31. package/Libraries/NativeComponent/BaseViewConfig.android.js +7 -2
  32. package/Libraries/NativeComponent/BaseViewConfig.ios.js +11 -2
  33. package/Libraries/NativeComponent/BaseViewConfig.win32.js +1 -1
  34. package/Libraries/NativeComponent/StaticViewConfigValidator.js +0 -1
  35. package/Libraries/ReactNative/AppRegistry.js +2 -6
  36. package/Libraries/ReactNative/getNativeComponentAttributes.js +4 -0
  37. package/Libraries/Renderer/shims/ReactNativeTypes.js +3 -3
  38. package/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +5 -6
  39. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +102 -5
  40. package/Libraries/StyleSheet/StyleSheetTypes.js +9 -5
  41. package/Libraries/StyleSheet/processBoxShadow.js +5 -7
  42. package/Libraries/StyleSheet/processFilter.js +4 -4
  43. package/Libraries/Text/TextNativeComponent.js +0 -1
  44. package/Libraries/Utilities/HMRClient.js +5 -5
  45. package/overrides.json +6 -6
  46. package/package.json +18 -16
  47. package/src/private/animated/NativeAnimatedHelper.js +12 -8
  48. package/src/private/animated/NativeAnimatedHelper.win32.js +12 -8
  49. package/src/private/animated/useAnimatedPropsMemo.js +349 -0
  50. package/src/private/components/HScrollViewNativeComponents.js +9 -8
  51. package/src/private/components/SafeAreaView_INTERNAL_DO_NOT_USE.js +13 -9
  52. package/src/private/components/VScrollViewNativeComponents.js +9 -8
  53. package/src/private/featureflags/ReactNativeFeatureFlags.js +50 -22
  54. package/src/private/featureflags/ReactNativeFeatureFlagsBase.js +8 -2
  55. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +7 -4
  56. package/src/private/webapis/dom/geometry/DOMRect.js +2 -2
  57. package/src/private/webapis/dom/geometry/DOMRectReadOnly.js +2 -2
  58. package/types/experimental.d.ts +0 -105
  59. package/types/modules/Codegen.d.ts +6 -0
package/CHANGELOG.md CHANGED
@@ -1,21 +1,33 @@
1
- # Change Log - @office-iss/react-native-win32
2
-
3
- <!-- This log was last generated on Thu, 26 Sep 2024 16:04:45 GMT and should not be manually modified. -->
4
-
5
- <!-- Start content -->
6
-
7
- ## 0.0.0-canary.264
8
-
9
- Thu, 26 Sep 2024 16:04:45 GMT
10
-
11
- ### Changes
12
-
13
- - RN Integration 9/9 (1422161+marlenecota@users.noreply.github.com)
14
- - Bump @rnw-scripts/eslint-config to v1.2.28
15
- - Bump @rnw-scripts/jest-out-of-tree-snapshot-resolver to v1.1.32
16
- - Bump @rnw-scripts/just-task to v2.3.45
17
- - Bump react-native-platform-override to v1.9.47
18
-
1
+ # Change Log - @office-iss/react-native-win32
2
+
3
+ <!-- This log was last generated on Mon, 07 Oct 2024 19:54:26 GMT and should not be manually modified. -->
4
+
5
+ <!-- Start content -->
6
+
7
+ ## 0.0.0-canary.265
8
+
9
+ Mon, 07 Oct 2024 19:54:26 GMT
10
+
11
+ ### Changes
12
+
13
+ - integrate RN nightly 0.77.0-nightly-20240921-1747f57c6 (tatianakapos@microsoft.com)
14
+ - Bump @rnw-scripts/eslint-config to v1.2.29
15
+ - Bump @rnw-scripts/jest-out-of-tree-snapshot-resolver to v1.1.33
16
+ - Bump @rnw-scripts/just-task to v2.3.46
17
+ - Bump react-native-platform-override to v1.9.48
18
+
19
+ ## 0.0.0-canary.263
20
+
21
+ Thu, 26 Sep 2024 17:38:26 GMT
22
+
23
+ ### Changes
24
+
25
+ - RN Integration 9/9 (1422161+marlenecota@users.noreply.github.com)
26
+ - Bump @rnw-scripts/eslint-config to v1.2.27
27
+ - Bump @rnw-scripts/jest-out-of-tree-snapshot-resolver to v1.1.31
28
+ - Bump @rnw-scripts/just-task to v2.3.44
29
+ - Bump react-native-platform-override to v1.9.46
30
+
19
31
  ## 0.0.0-canary.262
20
32
 
21
33
  Sat, 07 Sep 2024 05:14:10 GMT
@@ -5679,4 +5691,4 @@ Mon, 01 May 2017 19:28:16 GMT
5679
5691
 
5680
5692
  ### Patches
5681
5693
 
5682
- - Move @office-iss/react-native to 0.40.1 to fix build
5694
+ - Move @office-iss/react-native to 0.40.1 to fix build
@@ -373,7 +373,7 @@ const parallel = function (
373
373
  const stopTogether = !(config && config.stopTogether === false);
374
374
 
375
375
  const result = {
376
- start: function (callback?: ?EndCallback) {
376
+ start: function (callback?: ?EndCallback, isLooping?: boolean) {
377
377
  if (doneCount === animations.length) {
378
378
  callback && callback({finished: true});
379
379
  return;
@@ -397,7 +397,7 @@ const parallel = function (
397
397
  if (!animation) {
398
398
  cb({finished: true});
399
399
  } else {
400
- animation.start(cb);
400
+ animation.start(cb, isLooping);
401
401
  }
402
402
  });
403
403
  },
@@ -8,6 +8,8 @@
8
8
  * @format
9
9
  */
10
10
 
11
+ import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps';
12
+
11
13
  import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
12
14
 
13
15
  /**
@@ -16,7 +18,7 @@ import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNa
16
18
  * In general native animated implementation should support any numeric or color property that
17
19
  * doesn't need to be updated through the shadow view hierarchy (all non-layout properties).
18
20
  */
19
- const SUPPORTED_COLOR_STYLES: {[string]: boolean} = {
21
+ const SUPPORTED_COLOR_STYLES: {[string]: true} = {
20
22
  backgroundColor: true,
21
23
  borderBottomColor: true,
22
24
  borderColor: true,
@@ -29,7 +31,7 @@ const SUPPORTED_COLOR_STYLES: {[string]: boolean} = {
29
31
  tintColor: true,
30
32
  };
31
33
 
32
- const SUPPORTED_STYLES: {[string]: boolean} = {
34
+ const SUPPORTED_STYLES: {[string]: true} = {
33
35
  ...SUPPORTED_COLOR_STYLES,
34
36
  borderBottomEndRadius: true,
35
37
  borderBottomLeftRadius: true,
@@ -58,7 +60,7 @@ const SUPPORTED_STYLES: {[string]: boolean} = {
58
60
  translateY: true,
59
61
  };
60
62
 
61
- const SUPPORTED_TRANSFORMS: {[string]: boolean} = {
63
+ const SUPPORTED_TRANSFORMS: {[string]: true} = {
62
64
  translateX: true,
63
65
  translateY: true,
64
66
  scale: true,
@@ -71,10 +73,12 @@ const SUPPORTED_TRANSFORMS: {[string]: boolean} = {
71
73
  perspective: true,
72
74
  skewX: true,
73
75
  skewY: true,
74
- matrix: ReactNativeFeatureFlags.shouldUseAnimatedObjectForTransform(),
76
+ ...(ReactNativeFeatureFlags.shouldUseAnimatedObjectForTransform()
77
+ ? {matrix: true}
78
+ : {}),
75
79
  };
76
80
 
77
- const SUPPORTED_INTERPOLATION_PARAMS: {[string]: boolean} = {
81
+ const SUPPORTED_INTERPOLATION_PARAMS: {[string]: true} = {
78
82
  inputRange: true,
79
83
  outputRange: true,
80
84
  extrapolate: true,
@@ -82,6 +86,13 @@ const SUPPORTED_INTERPOLATION_PARAMS: {[string]: boolean} = {
82
86
  extrapolateLeft: true,
83
87
  };
84
88
 
89
+ /**
90
+ * Default allowlist for component props that support native animated values.
91
+ */
92
+ export default {
93
+ style: SUPPORTED_STYLES,
94
+ } as AnimatedPropsAllowlist;
95
+
85
96
  export function allowInterpolationParam(param: string): void {
86
97
  SUPPORTED_INTERPOLATION_PARAMS[param] = true;
87
98
  }
@@ -95,17 +106,17 @@ export function allowTransformProp(prop: string): void {
95
106
  }
96
107
 
97
108
  export function isSupportedColorStyleProp(prop: string): boolean {
98
- return SUPPORTED_COLOR_STYLES[prop] === true;
109
+ return Object.hasOwn(SUPPORTED_COLOR_STYLES, prop);
99
110
  }
100
111
 
101
112
  export function isSupportedInterpolationParam(param: string): boolean {
102
- return SUPPORTED_INTERPOLATION_PARAMS[param] === true;
113
+ return Object.hasOwn(SUPPORTED_INTERPOLATION_PARAMS, param);
103
114
  }
104
115
 
105
116
  export function isSupportedStyleProp(prop: string): boolean {
106
- return SUPPORTED_STYLES[prop] === true;
117
+ return Object.hasOwn(SUPPORTED_STYLES, prop);
107
118
  }
108
119
 
109
120
  export function isSupportedTransformProp(prop: string): boolean {
110
- return SUPPORTED_TRANSFORMS[prop] === true;
121
+ return Object.hasOwn(SUPPORTED_TRANSFORMS, prop);
111
122
  }
@@ -110,10 +110,7 @@ export default class Animation {
110
110
  if (value != null) {
111
111
  animatedValue.__onAnimatedValueUpdateReceived(value);
112
112
 
113
- if (
114
- ReactNativeFeatureFlags.shouldSkipStateUpdatesForLoopingAnimations() &&
115
- this.__isLooping
116
- ) {
113
+ if (this.__isLooping) {
117
114
  return;
118
115
  }
119
116
 
@@ -8,6 +8,8 @@
8
8
  * @format
9
9
  */
10
10
 
11
+ import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps';
12
+
11
13
  import composeStyles from '../../src/private/styles/composeStyles';
12
14
  import View from '../Components/View/View';
13
15
  import useMergeRefs from '../Utilities/useMergeRefs';
@@ -32,12 +34,23 @@ export type AnimatedComponentType<
32
34
 
33
35
  export default function createAnimatedComponent<TProps: {...}, TInstance>(
34
36
  Component: React.AbstractComponent<TProps, TInstance>,
37
+ ): AnimatedComponentType<TProps, TInstance> {
38
+ return unstable_createAnimatedComponentWithAllowlist(Component, null);
39
+ }
40
+
41
+ export function unstable_createAnimatedComponentWithAllowlist<
42
+ TProps: {...},
43
+ TInstance,
44
+ >(
45
+ Component: React.AbstractComponent<TProps, TInstance>,
46
+ allowlist: ?AnimatedPropsAllowlist,
35
47
  ): AnimatedComponentType<TProps, TInstance> {
36
48
  const AnimatedComponent = React.forwardRef<AnimatedProps<TProps>, TInstance>(
37
49
  (props, forwardedRef) => {
38
50
  const [reducedProps, callbackRef] = useAnimatedProps<TProps, TInstance>(
39
51
  // $FlowFixMe[incompatible-call]
40
52
  props,
53
+ allowlist,
41
54
  );
42
55
  const ref = useMergeRefs<TInstance>(callbackRef, forwardedRef);
43
56
 
@@ -8,8 +8,6 @@
8
8
  * @format
9
9
  */
10
10
 
11
- 'use strict';
12
-
13
11
  import type {EventSubscription} from '../../vendor/emitter/EventEmitter';
14
12
  import type {PlatformConfig} from '../AnimatedPlatformConfig';
15
13
 
@@ -29,12 +27,11 @@ let _assertNativeAnimatedModule: ?() => void = () => {
29
27
  _assertNativeAnimatedModule = null;
30
28
  };
31
29
 
32
- // Note(vjeux): this would be better as an interface but flow doesn't
33
- // support them yet
34
30
  export default class AnimatedNode {
35
31
  #listeners: Map<string, ValueListenerCallback> = new Map();
32
+ #updateSubscription: ?EventSubscription = null;
33
+
36
34
  _platformConfig: ?PlatformConfig = undefined;
37
- __nativeAnimatedValueListener: ?EventSubscription = null;
38
35
  __attach(): void {}
39
36
  __detach(): void {
40
37
  this.removeAllListeners();
@@ -56,16 +53,17 @@ export default class AnimatedNode {
56
53
  /* Methods and props used by native Animated impl */
57
54
  __isNative: boolean = false;
58
55
  __nativeTag: ?number = undefined;
59
- __shouldUpdateListenersForNewNativeTag: boolean = false;
60
56
 
61
57
  __makeNative(platformConfig: ?PlatformConfig): void {
62
- if (!this.__isNative) {
63
- throw new Error('This node cannot be made a "native" animated node');
64
- }
58
+ // Subclasses are expected to set `__isNative` to true before this.
59
+ invariant(
60
+ this.__isNative,
61
+ 'This node cannot be made a "native" animated node',
62
+ );
65
63
 
66
64
  this._platformConfig = platformConfig;
67
65
  if (this.#listeners.size > 0) {
68
- this._startListeningToNativeValueUpdates();
66
+ this.#ensureUpdateSubscriptionExists();
69
67
  }
70
68
  }
71
69
 
@@ -80,7 +78,7 @@ export default class AnimatedNode {
80
78
  const id = String(_uniqueId++);
81
79
  this.#listeners.set(id, callback);
82
80
  if (this.__isNative) {
83
- this._startListeningToNativeValueUpdates();
81
+ this.#ensureUpdateSubscriptionExists();
84
82
  }
85
83
  return id;
86
84
  }
@@ -94,7 +92,7 @@ export default class AnimatedNode {
94
92
  removeListener(id: string): void {
95
93
  this.#listeners.delete(id);
96
94
  if (this.__isNative && this.#listeners.size === 0) {
97
- this._stopListeningForNativeValueUpdates();
95
+ this.#updateSubscription?.remove();
98
96
  }
99
97
  }
100
98
 
@@ -106,7 +104,7 @@ export default class AnimatedNode {
106
104
  removeAllListeners(): void {
107
105
  this.#listeners.clear();
108
106
  if (this.__isNative) {
109
- this._stopListeningForNativeValueUpdates();
107
+ this.#updateSubscription?.remove();
110
108
  }
111
109
  }
112
110
 
@@ -114,33 +112,36 @@ export default class AnimatedNode {
114
112
  return this.#listeners.size > 0;
115
113
  }
116
114
 
117
- _startListeningToNativeValueUpdates() {
118
- if (
119
- this.__nativeAnimatedValueListener &&
120
- !this.__shouldUpdateListenersForNewNativeTag
121
- ) {
115
+ #ensureUpdateSubscriptionExists(): void {
116
+ if (this.#updateSubscription != null) {
122
117
  return;
123
118
  }
124
-
125
- if (this.__shouldUpdateListenersForNewNativeTag) {
126
- this.__shouldUpdateListenersForNewNativeTag = false;
127
- this._stopListeningForNativeValueUpdates();
128
- }
129
-
130
- startListeningToAnimatedNodeValue(this.__getNativeTag());
131
- this.__nativeAnimatedValueListener =
119
+ const nativeTag = this.__getNativeTag();
120
+ startListeningToAnimatedNodeValue(nativeTag);
121
+ const subscription: EventSubscription =
132
122
  NativeAnimatedHelper.nativeEventEmitter.addListener(
133
123
  'onAnimatedValueUpdate',
134
124
  data => {
135
- if (data.tag !== this.__getNativeTag()) {
136
- return;
125
+ if (data.tag === nativeTag) {
126
+ this.__onAnimatedValueUpdateReceived(data.value);
137
127
  }
138
- this.__onAnimatedValueUpdateReceived(data.value);
139
128
  },
140
129
  );
130
+
131
+ this.#updateSubscription = {
132
+ remove: () => {
133
+ // Only this function assigns to `this.#updateSubscription`.
134
+ if (this.#updateSubscription == null) {
135
+ return;
136
+ }
137
+ this.#updateSubscription = null;
138
+ subscription.remove();
139
+ stopListeningToAnimatedNodeValue(nativeTag);
140
+ },
141
+ };
141
142
  }
142
143
 
143
- __onAnimatedValueUpdateReceived(value: number) {
144
+ __onAnimatedValueUpdateReceived(value: number): void {
144
145
  this.__callListeners(value);
145
146
  }
146
147
 
@@ -151,16 +152,6 @@ export default class AnimatedNode {
151
152
  });
152
153
  }
153
154
 
154
- _stopListeningForNativeValueUpdates() {
155
- if (!this.__nativeAnimatedValueListener) {
156
- return;
157
- }
158
-
159
- this.__nativeAnimatedValueListener.remove();
160
- this.__nativeAnimatedValueListener = null;
161
- stopListeningToAnimatedNodeValue(this.__getNativeTag());
162
- }
163
-
164
155
  __getNativeTag(): number {
165
156
  let nativeTag = this.__nativeTag;
166
157
  if (nativeTag == null) {
@@ -181,7 +172,6 @@ export default class AnimatedNode {
181
172
  config.platformConfig = this._platformConfig;
182
173
  }
183
174
  NativeAnimatedHelper.API.createAnimatedNode(nativeTag, config);
184
- this.__shouldUpdateListenersForNewNativeTag = true;
185
175
  }
186
176
  return nativeTag;
187
177
  }
@@ -192,10 +182,6 @@ export default class AnimatedNode {
192
182
  );
193
183
  }
194
184
 
195
- toJSON(): any {
196
- return this.__getValue();
197
- }
198
-
199
185
  __getPlatformConfig(): ?PlatformConfig {
200
186
  return this._platformConfig;
201
187
  }
@@ -203,4 +189,12 @@ export default class AnimatedNode {
203
189
  __setPlatformConfig(platformConfig: ?PlatformConfig) {
204
190
  this._platformConfig = platformConfig;
205
191
  }
192
+
193
+ /**
194
+ * NOTE: This is intended to prevent `JSON.stringify` from throwing "cyclic
195
+ * structure" errors in React DevTools. Avoid depending on this!
196
+ */
197
+ toJSON(): mixed {
198
+ return this.__getValue();
199
+ }
206
200
  }
@@ -19,9 +19,11 @@ import * as React from 'react';
19
19
 
20
20
  const MAX_DEPTH = 5;
21
21
 
22
- /* $FlowIssue[incompatible-type-guard] - Flow does not know that the prototype
23
- and ReactElement checks preserve the type refinement of `value`. */
24
- function isPlainObject(value: mixed): value is $ReadOnly<{[string]: mixed}> {
22
+ export function isPlainObject(
23
+ value: mixed,
24
+ /* $FlowIssue[incompatible-type-guard] - Flow does not know that the prototype
25
+ and ReactElement checks preserve the type refinement of `value`. */
26
+ ): value is $ReadOnly<{[string]: mixed}> {
25
27
  return (
26
28
  value !== null &&
27
29
  typeof value === 'object' &&
@@ -109,6 +111,14 @@ export default class AnimatedObject extends AnimatedWithChildren {
109
111
  });
110
112
  }
111
113
 
114
+ __getValueWithStaticObject(staticObject: mixed): any {
115
+ const nodes = this.#nodes;
116
+ let index = 0;
117
+ // NOTE: We can depend on `this._value` and `staticObject` sharing a
118
+ // structure because of `useAnimatedPropsMemo`.
119
+ return mapAnimatedNodes(staticObject, () => nodes[index++].__getValue());
120
+ }
121
+
112
122
  __getAnimatedValue(): any {
113
123
  return mapAnimatedNodes(this._value, node => {
114
124
  return node.__getAnimatedValue();
@@ -8,9 +8,8 @@
8
8
  * @format
9
9
  */
10
10
 
11
- 'use strict';
12
-
13
11
  import type {PlatformConfig} from '../AnimatedPlatformConfig';
12
+ import type {AnimatedStyleAllowlist} from './AnimatedStyle';
14
13
 
15
14
  import {findNodeHandle} from '../../ReactNative/RendererProxy';
16
15
  import {AnimatedEvent} from '../AnimatedEvent';
@@ -20,30 +19,33 @@ import AnimatedObject from './AnimatedObject';
20
19
  import AnimatedStyle from './AnimatedStyle';
21
20
  import invariant from 'invariant';
22
21
 
22
+ export type AnimatedPropsAllowlist = $ReadOnly<{
23
+ style?: ?AnimatedStyleAllowlist,
24
+ [string]: true,
25
+ }>;
26
+
23
27
  function createAnimatedProps(
24
- inputProps: Object,
25
- ): [$ReadOnlyArray<string>, $ReadOnlyArray<AnimatedNode>, Object] {
28
+ inputProps: {[string]: mixed},
29
+ allowlist: ?AnimatedPropsAllowlist,
30
+ ): [$ReadOnlyArray<string>, $ReadOnlyArray<AnimatedNode>, {[string]: mixed}] {
26
31
  const nodeKeys: Array<string> = [];
27
32
  const nodes: Array<AnimatedNode> = [];
28
- const props: Object = {};
33
+ const props: {[string]: mixed} = {};
29
34
 
30
35
  const keys = Object.keys(inputProps);
31
36
  for (let ii = 0, length = keys.length; ii < length; ii++) {
32
37
  const key = keys[ii];
33
38
  const value = inputProps[key];
34
39
 
35
- if (key === 'style') {
36
- const node = new AnimatedStyle(value);
37
- nodeKeys.push(key);
38
- nodes.push(node);
39
- props[key] = node;
40
- } else if (value instanceof AnimatedNode) {
41
- const node = value;
42
- nodeKeys.push(key);
43
- nodes.push(node);
44
- props[key] = node;
45
- } else {
46
- const node = AnimatedObject.from(value);
40
+ if (allowlist == null || Object.hasOwn(allowlist, key)) {
41
+ let node;
42
+ if (key === 'style') {
43
+ node = AnimatedStyle.from(value, allowlist?.style);
44
+ } else if (value instanceof AnimatedNode) {
45
+ node = value;
46
+ } else {
47
+ node = AnimatedObject.from(value);
48
+ }
47
49
  if (node == null) {
48
50
  props[key] = value;
49
51
  } else {
@@ -51,6 +53,20 @@ function createAnimatedProps(
51
53
  nodes.push(node);
52
54
  props[key] = node;
53
55
  }
56
+ } else {
57
+ if (__DEV__) {
58
+ // WARNING: This is a potentially expensive check that we should only
59
+ // do in development. Without this check in development, it might be
60
+ // difficult to identify which props need to be allowlisted.
61
+ if (AnimatedObject.from(inputProps[key]) != null) {
62
+ console.error(
63
+ `AnimatedProps: ${key} is not allowlisted for animation, but it ` +
64
+ 'contains AnimatedNode values; props allowing animation: ',
65
+ allowlist,
66
+ );
67
+ }
68
+ }
69
+ props[key] = value;
54
70
  }
55
71
  }
56
72
 
@@ -58,29 +74,32 @@ function createAnimatedProps(
58
74
  }
59
75
 
60
76
  export default class AnimatedProps extends AnimatedNode {
77
+ #animatedView: any = null;
78
+ #callback: () => void;
61
79
  #nodeKeys: $ReadOnlyArray<string>;
62
80
  #nodes: $ReadOnlyArray<AnimatedNode>;
81
+ #props: {[string]: mixed};
63
82
 
64
- _animatedView: any = null;
65
- _props: Object;
66
- _callback: () => void;
67
-
68
- constructor(inputProps: Object, callback: () => void) {
83
+ constructor(
84
+ inputProps: {[string]: mixed},
85
+ callback: () => void,
86
+ allowlist?: ?AnimatedPropsAllowlist,
87
+ ) {
69
88
  super();
70
- const [nodeKeys, nodes, props] = createAnimatedProps(inputProps);
89
+ const [nodeKeys, nodes, props] = createAnimatedProps(inputProps, allowlist);
71
90
  this.#nodeKeys = nodeKeys;
72
91
  this.#nodes = nodes;
73
- this._props = props;
74
- this._callback = callback;
92
+ this.#props = props;
93
+ this.#callback = callback;
75
94
  }
76
95
 
77
96
  __getValue(): Object {
78
- const props: {[string]: any | ((...args: any) => void)} = {};
97
+ const props: {[string]: mixed} = {};
79
98
 
80
- const keys = Object.keys(this._props);
99
+ const keys = Object.keys(this.#props);
81
100
  for (let ii = 0, length = keys.length; ii < length; ii++) {
82
101
  const key = keys[ii];
83
- const value = this._props[key];
102
+ const value = this.#props[key];
84
103
 
85
104
  if (value instanceof AnimatedNode) {
86
105
  props[key] = value.__getValue();
@@ -94,8 +113,33 @@ export default class AnimatedProps extends AnimatedNode {
94
113
  return props;
95
114
  }
96
115
 
116
+ /**
117
+ * Creates a new `props` object that contains the same props as the supplied
118
+ * `staticProps` object, except with animated nodes for any props that were
119
+ * created by this `AnimatedProps` instance.
120
+ */
121
+ __getValueWithStaticProps(staticProps: Object): Object {
122
+ const props: {[string]: mixed} = {...staticProps};
123
+
124
+ const keys = Object.keys(staticProps);
125
+ for (let ii = 0, length = keys.length; ii < length; ii++) {
126
+ const key = keys[ii];
127
+ const maybeNode = this.#props[key];
128
+
129
+ if (key === 'style' && maybeNode instanceof AnimatedStyle) {
130
+ props[key] = maybeNode.__getValueWithStaticStyle(staticProps.style);
131
+ } else if (maybeNode instanceof AnimatedNode) {
132
+ props[key] = maybeNode.__getValue();
133
+ } else if (maybeNode instanceof AnimatedEvent) {
134
+ props[key] = maybeNode.__getHandler();
135
+ }
136
+ }
137
+
138
+ return props;
139
+ }
140
+
97
141
  __getAnimatedValue(): Object {
98
- const props: {[string]: any} = {};
142
+ const props: {[string]: mixed} = {};
99
143
 
100
144
  const nodeKeys = this.#nodeKeys;
101
145
  const nodes = this.#nodes;
@@ -117,10 +161,10 @@ export default class AnimatedProps extends AnimatedNode {
117
161
  }
118
162
 
119
163
  __detach(): void {
120
- if (this.__isNative && this._animatedView) {
164
+ if (this.__isNative && this.#animatedView) {
121
165
  this.__disconnectAnimatedView();
122
166
  }
123
- this._animatedView = null;
167
+ this.#animatedView = null;
124
168
 
125
169
  const nodes = this.#nodes;
126
170
  for (let ii = 0, length = nodes.length; ii < length; ii++) {
@@ -132,7 +176,7 @@ export default class AnimatedProps extends AnimatedNode {
132
176
  }
133
177
 
134
178
  update(): void {
135
- this._callback();
179
+ this.#callback();
136
180
  }
137
181
 
138
182
  __makeNative(platformConfig: ?PlatformConfig): void {
@@ -150,17 +194,17 @@ export default class AnimatedProps extends AnimatedNode {
150
194
  // where it will be needed to traverse the graph of attached values.
151
195
  super.__setPlatformConfig(platformConfig);
152
196
 
153
- if (this._animatedView) {
197
+ if (this.#animatedView) {
154
198
  this.__connectAnimatedView();
155
199
  }
156
200
  }
157
201
  }
158
202
 
159
203
  setNativeView(animatedView: any): void {
160
- if (this._animatedView === animatedView) {
204
+ if (this.#animatedView === animatedView) {
161
205
  return;
162
206
  }
163
- this._animatedView = animatedView;
207
+ this.#animatedView = animatedView;
164
208
  if (this.__isNative) {
165
209
  this.__connectAnimatedView();
166
210
  }
@@ -168,7 +212,7 @@ export default class AnimatedProps extends AnimatedNode {
168
212
 
169
213
  __connectAnimatedView(): void {
170
214
  invariant(this.__isNative, 'Expected node to be marked as "native"');
171
- const nativeViewTag: ?number = findNodeHandle(this._animatedView);
215
+ const nativeViewTag: ?number = findNodeHandle(this.#animatedView);
172
216
  invariant(
173
217
  nativeViewTag != null,
174
218
  'Unable to locate attached view in the native tree',
@@ -181,7 +225,7 @@ export default class AnimatedProps extends AnimatedNode {
181
225
 
182
226
  __disconnectAnimatedView(): void {
183
227
  invariant(this.__isNative, 'Expected node to be marked as "native"');
184
- const nativeViewTag: ?number = findNodeHandle(this._animatedView);
228
+ const nativeViewTag: ?number = findNodeHandle(this.#animatedView);
185
229
  invariant(
186
230
  nativeViewTag != null,
187
231
  'Unable to locate attached view in the native tree',