@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.
- package/.flowconfig +1 -1
- package/CHANGELOG.json +14981 -14942
- package/CHANGELOG.md +31 -19
- package/Libraries/Animated/AnimatedImplementation.js +2 -2
- package/Libraries/Animated/NativeAnimatedAllowlist.js +20 -9
- package/Libraries/Animated/animations/Animation.js +1 -4
- package/Libraries/Animated/createAnimatedComponent.js +13 -0
- package/Libraries/Animated/nodes/AnimatedNode.js +39 -45
- package/Libraries/Animated/nodes/AnimatedObject.js +13 -3
- package/Libraries/Animated/nodes/AnimatedProps.js +81 -37
- package/Libraries/Animated/nodes/AnimatedStyle.js +104 -39
- package/Libraries/Animated/nodes/AnimatedTransform.js +55 -22
- package/Libraries/Animated/nodes/AnimatedWithChildren.js +1 -3
- package/Libraries/Animated/useAnimatedProps.js +38 -20
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +3 -1
- package/Libraries/Components/ScrollView/ScrollView.js +12 -9
- package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +3 -0
- package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +10 -0
- package/Libraries/Components/TextInput/TextInput.d.ts +19 -0
- package/Libraries/Components/TextInput/TextInput.flow.js +17 -1
- package/Libraries/Components/TextInput/TextInput.js +17 -1
- package/Libraries/Components/TextInput/TextInput.win32.js +17 -1
- package/Libraries/Components/Touchable/TouchableBounce.js +1 -1
- package/Libraries/Components/Touchable/TouchableHighlight.js +2 -2
- package/Libraries/Components/Touchable/TouchableOpacity.js +1 -1
- package/Libraries/Components/View/ReactNativeStyleAttributes.js +6 -2
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Image/AssetSourceResolver.js +12 -1
- package/Libraries/Modal/Modal.d.ts +7 -0
- package/Libraries/Modal/Modal.js +9 -1
- package/Libraries/NativeComponent/BaseViewConfig.android.js +7 -2
- package/Libraries/NativeComponent/BaseViewConfig.ios.js +11 -2
- package/Libraries/NativeComponent/BaseViewConfig.win32.js +1 -1
- package/Libraries/NativeComponent/StaticViewConfigValidator.js +0 -1
- package/Libraries/ReactNative/AppRegistry.js +2 -6
- package/Libraries/ReactNative/getNativeComponentAttributes.js +4 -0
- package/Libraries/Renderer/shims/ReactNativeTypes.js +3 -3
- package/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +5 -6
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +102 -5
- package/Libraries/StyleSheet/StyleSheetTypes.js +9 -5
- package/Libraries/StyleSheet/processBoxShadow.js +5 -7
- package/Libraries/StyleSheet/processFilter.js +4 -4
- package/Libraries/Text/TextNativeComponent.js +0 -1
- package/Libraries/Utilities/HMRClient.js +5 -5
- package/overrides.json +6 -6
- package/package.json +18 -16
- package/src/private/animated/NativeAnimatedHelper.js +12 -8
- package/src/private/animated/NativeAnimatedHelper.win32.js +12 -8
- package/src/private/animated/useAnimatedPropsMemo.js +349 -0
- package/src/private/components/HScrollViewNativeComponents.js +9 -8
- package/src/private/components/SafeAreaView_INTERNAL_DO_NOT_USE.js +13 -9
- package/src/private/components/VScrollViewNativeComponents.js +9 -8
- package/src/private/featureflags/ReactNativeFeatureFlags.js +50 -22
- package/src/private/featureflags/ReactNativeFeatureFlagsBase.js +8 -2
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +7 -4
- package/src/private/webapis/dom/geometry/DOMRect.js +2 -2
- package/src/private/webapis/dom/geometry/DOMRectReadOnly.js +2 -2
- package/types/experimental.d.ts +0 -105
- package/types/modules/Codegen.d.ts +6 -0
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
11
|
import type {PlatformConfig} from '../AnimatedPlatformConfig';
|
|
14
12
|
|
|
15
13
|
import {validateStyles} from '../../../src/private/animated/NativeAnimatedValidation';
|
|
@@ -21,24 +19,34 @@ import AnimatedObject from './AnimatedObject';
|
|
|
21
19
|
import AnimatedTransform from './AnimatedTransform';
|
|
22
20
|
import AnimatedWithChildren from './AnimatedWithChildren';
|
|
23
21
|
|
|
22
|
+
export type AnimatedStyleAllowlist = $ReadOnly<{[string]: true}>;
|
|
23
|
+
|
|
24
24
|
function createAnimatedStyle(
|
|
25
25
|
inputStyle: {[string]: mixed},
|
|
26
|
+
allowlist: ?AnimatedStyleAllowlist,
|
|
26
27
|
keepUnanimatedValues: boolean,
|
|
27
|
-
): [$ReadOnlyArray<string>, $ReadOnlyArray<AnimatedNode>,
|
|
28
|
+
): [$ReadOnlyArray<string>, $ReadOnlyArray<AnimatedNode>, {[string]: mixed}] {
|
|
28
29
|
const nodeKeys: Array<string> = [];
|
|
29
30
|
const nodes: Array<AnimatedNode> = [];
|
|
30
|
-
const style: {[string]:
|
|
31
|
+
const style: {[string]: mixed} = {};
|
|
31
32
|
|
|
32
33
|
const keys = Object.keys(inputStyle);
|
|
33
34
|
for (let ii = 0, length = keys.length; ii < length; ii++) {
|
|
34
35
|
const key = keys[ii];
|
|
35
36
|
const value = inputStyle[key];
|
|
36
37
|
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
if (allowlist == null || Object.hasOwn(allowlist, key)) {
|
|
39
|
+
let node;
|
|
40
|
+
if (value != null && key === 'transform') {
|
|
41
|
+
node = ReactNativeFeatureFlags.shouldUseAnimatedObjectForTransform()
|
|
42
|
+
? AnimatedObject.from(value)
|
|
43
|
+
: // $FlowFixMe[incompatible-call] - `value` is mixed.
|
|
44
|
+
AnimatedTransform.from(value);
|
|
45
|
+
} else if (value instanceof AnimatedNode) {
|
|
46
|
+
node = value;
|
|
47
|
+
} else {
|
|
48
|
+
node = AnimatedObject.from(value);
|
|
49
|
+
}
|
|
42
50
|
if (node == null) {
|
|
43
51
|
if (keepUnanimatedValues) {
|
|
44
52
|
style[key] = value;
|
|
@@ -48,21 +56,21 @@ function createAnimatedStyle(
|
|
|
48
56
|
nodes.push(node);
|
|
49
57
|
style[key] = node;
|
|
50
58
|
}
|
|
51
|
-
} else if (value instanceof AnimatedNode) {
|
|
52
|
-
const node = value;
|
|
53
|
-
nodeKeys.push(key);
|
|
54
|
-
nodes.push(node);
|
|
55
|
-
style[key] = value;
|
|
56
59
|
} else {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
if (__DEV__) {
|
|
61
|
+
// WARNING: This is a potentially expensive check that we should only
|
|
62
|
+
// do in development. Without this check in development, it might be
|
|
63
|
+
// difficult to identify which styles need to be allowlisted.
|
|
64
|
+
if (AnimatedObject.from(inputStyle[key]) != null) {
|
|
65
|
+
console.error(
|
|
66
|
+
`AnimatedStyle: ${key} is not allowlisted for animation, but it ` +
|
|
67
|
+
'contains AnimatedNode values; styles allowing animation: ',
|
|
68
|
+
allowlist,
|
|
69
|
+
);
|
|
61
70
|
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
style[key] = node;
|
|
71
|
+
}
|
|
72
|
+
if (keepUnanimatedValues) {
|
|
73
|
+
style[key] = value;
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
76
|
}
|
|
@@ -71,34 +79,54 @@ function createAnimatedStyle(
|
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
export default class AnimatedStyle extends AnimatedWithChildren {
|
|
82
|
+
#inputStyle: any;
|
|
74
83
|
#nodeKeys: $ReadOnlyArray<string>;
|
|
75
84
|
#nodes: $ReadOnlyArray<AnimatedNode>;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
#style: {[string]: mixed};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Creates an `AnimatedStyle` if `value` contains `AnimatedNode` instances.
|
|
89
|
+
* Otherwise, returns `null`.
|
|
90
|
+
*/
|
|
91
|
+
static from(
|
|
92
|
+
inputStyle: any,
|
|
93
|
+
allowlist: ?AnimatedStyleAllowlist,
|
|
94
|
+
): ?AnimatedStyle {
|
|
95
|
+
const flatStyle = flattenStyle(inputStyle);
|
|
96
|
+
if (flatStyle == null) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
83
99
|
const [nodeKeys, nodes, style] = createAnimatedStyle(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// to instantiation sites.
|
|
87
|
-
flattenStyle(inputStyle) ?? {},
|
|
100
|
+
flatStyle,
|
|
101
|
+
allowlist,
|
|
88
102
|
Platform.OS !== 'web',
|
|
89
103
|
);
|
|
104
|
+
if (nodes.length === 0) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
return new AnimatedStyle(nodeKeys, nodes, style, inputStyle);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
constructor(
|
|
111
|
+
nodeKeys: $ReadOnlyArray<string>,
|
|
112
|
+
nodes: $ReadOnlyArray<AnimatedNode>,
|
|
113
|
+
style: {[string]: mixed},
|
|
114
|
+
inputStyle: any,
|
|
115
|
+
) {
|
|
116
|
+
super();
|
|
90
117
|
this.#nodeKeys = nodeKeys;
|
|
91
118
|
this.#nodes = nodes;
|
|
92
|
-
this
|
|
119
|
+
this.#style = style;
|
|
120
|
+
this.#inputStyle = inputStyle;
|
|
93
121
|
}
|
|
94
122
|
|
|
95
123
|
__getValue(): Object | Array<Object> {
|
|
96
|
-
const style: {[string]:
|
|
124
|
+
const style: {[string]: mixed} = {};
|
|
97
125
|
|
|
98
|
-
const keys = Object.keys(this
|
|
126
|
+
const keys = Object.keys(this.#style);
|
|
99
127
|
for (let ii = 0, length = keys.length; ii < length; ii++) {
|
|
100
128
|
const key = keys[ii];
|
|
101
|
-
const value = this
|
|
129
|
+
const value = this.#style[key];
|
|
102
130
|
|
|
103
131
|
if (value instanceof AnimatedNode) {
|
|
104
132
|
style[key] = value.__getValue();
|
|
@@ -107,11 +135,48 @@ export default class AnimatedStyle extends AnimatedWithChildren {
|
|
|
107
135
|
}
|
|
108
136
|
}
|
|
109
137
|
|
|
110
|
-
return Platform.OS === 'web' ? [this
|
|
138
|
+
return Platform.OS === 'web' ? [this.#inputStyle, style] : style;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Creates a new `style` object that contains the same style properties as
|
|
143
|
+
* the supplied `staticStyle` object, except with animated nodes for any
|
|
144
|
+
* style properties that were created by this `AnimatedStyle` instance.
|
|
145
|
+
*/
|
|
146
|
+
__getValueWithStaticStyle(staticStyle: Object): Object | Array<Object> {
|
|
147
|
+
const flatStaticStyle = flattenStyle(staticStyle);
|
|
148
|
+
const style: {[string]: mixed} =
|
|
149
|
+
flatStaticStyle == null
|
|
150
|
+
? {}
|
|
151
|
+
: flatStaticStyle === staticStyle
|
|
152
|
+
? // Copy the input style, since we'll mutate it below.
|
|
153
|
+
{...flatStaticStyle}
|
|
154
|
+
: // Reuse `flatStaticStyle` if it is a newly created object.
|
|
155
|
+
flatStaticStyle;
|
|
156
|
+
|
|
157
|
+
const keys = Object.keys(style);
|
|
158
|
+
for (let ii = 0, length = keys.length; ii < length; ii++) {
|
|
159
|
+
const key = keys[ii];
|
|
160
|
+
const maybeNode = this.#style[key];
|
|
161
|
+
|
|
162
|
+
if (key === 'transform' && maybeNode instanceof AnimatedTransform) {
|
|
163
|
+
style[key] = maybeNode.__getValueWithStaticTransforms(
|
|
164
|
+
// NOTE: This check should not be necessary, but the types are not
|
|
165
|
+
// enforced as of this writing.
|
|
166
|
+
Array.isArray(style[key]) ? style[key] : [],
|
|
167
|
+
);
|
|
168
|
+
} else if (maybeNode instanceof AnimatedObject) {
|
|
169
|
+
style[key] = maybeNode.__getValueWithStaticObject(style[key]);
|
|
170
|
+
} else if (maybeNode instanceof AnimatedNode) {
|
|
171
|
+
style[key] = maybeNode.__getValue();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return Platform.OS === 'web' ? [this.#inputStyle, style] : style;
|
|
111
176
|
}
|
|
112
177
|
|
|
113
178
|
__getAnimatedValue(): Object {
|
|
114
|
-
const style: {[string]:
|
|
179
|
+
const style: {[string]: mixed} = {};
|
|
115
180
|
|
|
116
181
|
const nodeKeys = this.#nodeKeys;
|
|
117
182
|
const nodes = this.#nodes;
|
|
@@ -26,37 +26,58 @@ type Transform<T = AnimatedNode> = {
|
|
|
26
26
|
| {[string]: number | string | T},
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
function flatAnimatedNodes(
|
|
30
|
+
transforms: $ReadOnlyArray<Transform<>>,
|
|
31
|
+
): Array<AnimatedNode> {
|
|
32
|
+
const nodes = [];
|
|
33
|
+
for (let ii = 0, length = transforms.length; ii < length; ii++) {
|
|
34
|
+
const transform = transforms[ii];
|
|
35
|
+
// There should be exactly one property in `transform`.
|
|
36
|
+
for (const key in transform) {
|
|
37
|
+
const value = transform[key];
|
|
38
|
+
if (value instanceof AnimatedNode) {
|
|
39
|
+
nodes.push(value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return nodes;
|
|
44
|
+
}
|
|
45
|
+
|
|
29
46
|
export default class AnimatedTransform extends AnimatedWithChildren {
|
|
30
47
|
// NOTE: For potentially historical reasons, some operations only operate on
|
|
31
48
|
// the first level of AnimatedNode instances. This optimizes that bevavior.
|
|
32
|
-
#
|
|
49
|
+
#nodes: $ReadOnlyArray<AnimatedNode>;
|
|
33
50
|
|
|
34
51
|
_transforms: $ReadOnlyArray<Transform<>>;
|
|
35
52
|
|
|
36
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Creates an `AnimatedTransform` if `transforms` contains `AnimatedNode`
|
|
55
|
+
* instances. Otherwise, returns `null`.
|
|
56
|
+
*/
|
|
57
|
+
static from(transforms: $ReadOnlyArray<Transform<>>): ?AnimatedTransform {
|
|
58
|
+
const nodes = flatAnimatedNodes(
|
|
59
|
+
// NOTE: This check should not be necessary, but the types are not
|
|
60
|
+
// enforced as of this writing. This check should be hoisted to
|
|
61
|
+
// instantiation sites.
|
|
62
|
+
Array.isArray(transforms) ? transforms : [],
|
|
63
|
+
);
|
|
64
|
+
if (nodes.length === 0) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return new AnimatedTransform(nodes, transforms);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
constructor(
|
|
71
|
+
nodes: $ReadOnlyArray<AnimatedNode>,
|
|
72
|
+
transforms: $ReadOnlyArray<Transform<>>,
|
|
73
|
+
) {
|
|
37
74
|
super();
|
|
75
|
+
this.#nodes = nodes;
|
|
38
76
|
this._transforms = transforms;
|
|
39
|
-
|
|
40
|
-
const shallowNodes = [];
|
|
41
|
-
// NOTE: This check should not be necessary, but the types are not enforced
|
|
42
|
-
// as of this writing. This check should be hoisted to instantiation sites.
|
|
43
|
-
if (Array.isArray(transforms)) {
|
|
44
|
-
for (let ii = 0, length = transforms.length; ii < length; ii++) {
|
|
45
|
-
const transform = transforms[ii];
|
|
46
|
-
// There should be exactly one property in `transform`.
|
|
47
|
-
for (const key in transform) {
|
|
48
|
-
const value = transform[key];
|
|
49
|
-
if (value instanceof AnimatedNode) {
|
|
50
|
-
shallowNodes.push(value);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
this.#shallowNodes = shallowNodes;
|
|
56
77
|
}
|
|
57
78
|
|
|
58
79
|
__makeNative(platformConfig: ?PlatformConfig) {
|
|
59
|
-
const nodes = this.#
|
|
80
|
+
const nodes = this.#nodes;
|
|
60
81
|
for (let ii = 0, length = nodes.length; ii < length; ii++) {
|
|
61
82
|
const node = nodes[ii];
|
|
62
83
|
node.__makeNative(platformConfig);
|
|
@@ -70,6 +91,18 @@ export default class AnimatedTransform extends AnimatedWithChildren {
|
|
|
70
91
|
);
|
|
71
92
|
}
|
|
72
93
|
|
|
94
|
+
__getValueWithStaticTransforms(
|
|
95
|
+
staticTransforms: $ReadOnlyArray<Object>,
|
|
96
|
+
): $ReadOnlyArray<Object> {
|
|
97
|
+
const values = [];
|
|
98
|
+
mapTransforms(this._transforms, node => {
|
|
99
|
+
values.push(node.__getValue());
|
|
100
|
+
});
|
|
101
|
+
// NOTE: We can depend on `this._transforms` and `staticTransforms` sharing
|
|
102
|
+
// a structure because of `useAnimatedPropsMemo`.
|
|
103
|
+
return mapTransforms(staticTransforms, () => values.shift());
|
|
104
|
+
}
|
|
105
|
+
|
|
73
106
|
__getAnimatedValue(): $ReadOnlyArray<Transform<any>> {
|
|
74
107
|
return mapTransforms(this._transforms, animatedNode =>
|
|
75
108
|
animatedNode.__getAnimatedValue(),
|
|
@@ -77,7 +110,7 @@ export default class AnimatedTransform extends AnimatedWithChildren {
|
|
|
77
110
|
}
|
|
78
111
|
|
|
79
112
|
__attach(): void {
|
|
80
|
-
const nodes = this.#
|
|
113
|
+
const nodes = this.#nodes;
|
|
81
114
|
for (let ii = 0, length = nodes.length; ii < length; ii++) {
|
|
82
115
|
const node = nodes[ii];
|
|
83
116
|
node.__addChild(this);
|
|
@@ -85,7 +118,7 @@ export default class AnimatedTransform extends AnimatedWithChildren {
|
|
|
85
118
|
}
|
|
86
119
|
|
|
87
120
|
__detach(): void {
|
|
88
|
-
const nodes = this.#
|
|
121
|
+
const nodes = this.#nodes;
|
|
89
122
|
for (let ii = 0, length = nodes.length; ii < length; ii++) {
|
|
90
123
|
const node = nodes[ii];
|
|
91
124
|
node.__removeChild(this);
|
|
@@ -28,12 +28,10 @@ export default class AnimatedWithChildren extends AnimatedNode {
|
|
|
28
28
|
const children = this._children;
|
|
29
29
|
let length = children.length;
|
|
30
30
|
if (length > 0) {
|
|
31
|
-
const nativeTag = this.__getNativeTag();
|
|
32
|
-
|
|
33
31
|
for (let ii = 0; ii < length; ii++) {
|
|
34
32
|
const child = children[ii];
|
|
35
33
|
child.__makeNative(platformConfig);
|
|
36
|
-
connectAnimatedNodes(
|
|
34
|
+
connectAnimatedNodes(this.__getNativeTag(), child.__getNativeTag());
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
37
|
}
|
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps';
|
|
13
12
|
import type {EventSubscription} from '../EventEmitter/NativeEventEmitter';
|
|
14
13
|
|
|
15
14
|
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
|
|
@@ -23,11 +22,13 @@ import AnimatedValue from './nodes/AnimatedValue';
|
|
|
23
22
|
import {
|
|
24
23
|
useCallback,
|
|
25
24
|
useEffect,
|
|
25
|
+
useInsertionEffect,
|
|
26
26
|
useLayoutEffect,
|
|
27
27
|
useMemo,
|
|
28
28
|
useReducer,
|
|
29
29
|
useRef,
|
|
30
30
|
} from 'react';
|
|
31
|
+
import {useAnimatedPropsMemo} from '../../src/private/animated/useAnimatedPropsMemo';
|
|
31
32
|
|
|
32
33
|
type ReducedProps<TProps> = {
|
|
33
34
|
...TProps,
|
|
@@ -36,34 +37,48 @@ type ReducedProps<TProps> = {
|
|
|
36
37
|
};
|
|
37
38
|
type CallbackRef<T> = T => mixed;
|
|
38
39
|
|
|
40
|
+
type UpdateCallback = () => void;
|
|
41
|
+
|
|
39
42
|
type AnimatedValueListeners = Array<{
|
|
40
43
|
propValue: AnimatedValue,
|
|
41
44
|
listenerId: string,
|
|
42
45
|
}>;
|
|
43
46
|
|
|
47
|
+
const useMemoOrAnimatedPropsMemo =
|
|
48
|
+
ReactNativeFeatureFlags.enableAnimatedPropsMemo()
|
|
49
|
+
? useAnimatedPropsMemo
|
|
50
|
+
: useMemo;
|
|
51
|
+
|
|
44
52
|
export default function useAnimatedProps<TProps: {...}, TInstance>(
|
|
45
53
|
props: TProps,
|
|
54
|
+
allowlist?: ?AnimatedPropsAllowlist,
|
|
46
55
|
): [ReducedProps<TProps>, CallbackRef<TInstance | null>] {
|
|
47
56
|
const [, scheduleUpdate] = useReducer<number, void>(count => count + 1, 0);
|
|
48
|
-
const onUpdateRef = useRef
|
|
57
|
+
const onUpdateRef = useRef<UpdateCallback | null>(null);
|
|
49
58
|
const timerRef = useRef<TimeoutID | null>(null);
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const node =
|
|
56
|
-
() =>
|
|
57
|
-
|
|
60
|
+
const allowlistIfEnabled = ReactNativeFeatureFlags.enableAnimatedAllowlist()
|
|
61
|
+
? allowlist
|
|
62
|
+
: null;
|
|
63
|
+
|
|
64
|
+
const node = useMemoOrAnimatedPropsMemo(
|
|
65
|
+
() =>
|
|
66
|
+
new AnimatedProps(
|
|
67
|
+
props,
|
|
68
|
+
() => onUpdateRef.current?.(),
|
|
69
|
+
allowlistIfEnabled,
|
|
70
|
+
),
|
|
71
|
+
[allowlistIfEnabled, props],
|
|
58
72
|
);
|
|
73
|
+
|
|
59
74
|
const useNativePropsInFabric =
|
|
60
75
|
ReactNativeFeatureFlags.shouldUseSetNativePropsInFabric();
|
|
61
76
|
const useSetNativePropsInNativeAnimationsInFabric =
|
|
62
77
|
ReactNativeFeatureFlags.shouldUseSetNativePropsInNativeAnimationsInFabric();
|
|
63
78
|
|
|
64
79
|
const useAnimatedPropsLifecycle =
|
|
65
|
-
ReactNativeFeatureFlags.
|
|
66
|
-
?
|
|
80
|
+
ReactNativeFeatureFlags.useInsertionEffectsForAnimations()
|
|
81
|
+
? useAnimatedPropsLifecycle_insertionEffects
|
|
67
82
|
: useAnimatedPropsLifecycle_layoutEffects;
|
|
68
83
|
|
|
69
84
|
useAnimatedPropsLifecycle(node);
|
|
@@ -195,14 +210,19 @@ export default function useAnimatedProps<TProps: {...}, TInstance>(
|
|
|
195
210
|
);
|
|
196
211
|
const callbackRef = useRefEffect<TInstance>(refEffect);
|
|
197
212
|
|
|
198
|
-
return [reduceAnimatedProps<TProps>(node), callbackRef];
|
|
213
|
+
return [reduceAnimatedProps<TProps>(node, props), callbackRef];
|
|
199
214
|
}
|
|
200
215
|
|
|
201
|
-
function reduceAnimatedProps<TProps>(
|
|
216
|
+
function reduceAnimatedProps<TProps>(
|
|
217
|
+
node: AnimatedProps,
|
|
218
|
+
props: TProps,
|
|
219
|
+
): ReducedProps<TProps> {
|
|
202
220
|
// Force `collapsable` to be false so that the native view is not flattened.
|
|
203
221
|
// Flattened views cannot be accurately referenced by the native driver.
|
|
204
222
|
return {
|
|
205
|
-
...
|
|
223
|
+
...(ReactNativeFeatureFlags.enableAnimatedPropsMemo()
|
|
224
|
+
? node.__getValueWithStaticProps(props)
|
|
225
|
+
: node.__getValue()),
|
|
206
226
|
collapsable: false,
|
|
207
227
|
};
|
|
208
228
|
}
|
|
@@ -301,10 +321,8 @@ function useAnimatedPropsLifecycle_layoutEffects(node: AnimatedProps): void {
|
|
|
301
321
|
* uses reference counting to determine when to recursively detach its children
|
|
302
322
|
* nodes. So in order to optimize this, we avoid detaching until the next attach
|
|
303
323
|
* unless we are unmounting.
|
|
304
|
-
*
|
|
305
|
-
* NOTE: unlike `useAnimatedPropsLifecycle_layoutEffects`, this version uses passive effects to setup animation graph.
|
|
306
324
|
*/
|
|
307
|
-
function
|
|
325
|
+
function useAnimatedPropsLifecycle_insertionEffects(node: AnimatedProps): void {
|
|
308
326
|
const prevNodeRef = useRef<?AnimatedProps>(null);
|
|
309
327
|
const isUnmountingRef = useRef<boolean>(false);
|
|
310
328
|
|
|
@@ -315,14 +333,14 @@ function useAnimatedPropsLifecycle_passiveEffects(node: AnimatedProps): void {
|
|
|
315
333
|
NativeAnimatedHelper.API.flushQueue();
|
|
316
334
|
});
|
|
317
335
|
|
|
318
|
-
|
|
336
|
+
useInsertionEffect(() => {
|
|
319
337
|
isUnmountingRef.current = false;
|
|
320
338
|
return () => {
|
|
321
339
|
isUnmountingRef.current = true;
|
|
322
340
|
};
|
|
323
341
|
}, []);
|
|
324
342
|
|
|
325
|
-
|
|
343
|
+
useInsertionEffect(() => {
|
|
326
344
|
node.__attach();
|
|
327
345
|
let drivenAnimationEndedListener: ?EventSubscription = null;
|
|
328
346
|
|
|
@@ -85,7 +85,9 @@ const ProgressBarAndroid = (
|
|
|
85
85
|
animating = true,
|
|
86
86
|
...restProps
|
|
87
87
|
}: ProgressBarAndroidProps,
|
|
88
|
-
forwardedRef: ?React.
|
|
88
|
+
forwardedRef: ?React.RefSetter<
|
|
89
|
+
React.ElementRef<typeof ProgressBarAndroidNativeComponent>,
|
|
90
|
+
>,
|
|
89
91
|
) => {
|
|
90
92
|
return (
|
|
91
93
|
<ProgressBarAndroidNativeComponent
|
|
@@ -1931,19 +1931,22 @@ function createRefForwarder<TNativeInstance, TPublicInstance>(
|
|
|
1931
1931
|
return state;
|
|
1932
1932
|
}
|
|
1933
1933
|
|
|
1934
|
+
// TODO: After upgrading to React 19, remove `forwardRef` from this component.
|
|
1934
1935
|
// NOTE: This wrapper component is necessary because `ScrollView` is a class
|
|
1935
1936
|
// component and we need to map `ref` to a differently named prop. This can be
|
|
1936
1937
|
// removed when `ScrollView` is a functional component.
|
|
1937
|
-
function Wrapper(
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1938
|
+
const Wrapper = React.forwardRef(function Wrapper(
|
|
1939
|
+
props: Props,
|
|
1940
|
+
ref: ?React.RefSetter<PublicScrollViewInstance>,
|
|
1941
|
+
): React.Node {
|
|
1942
|
+
return ref == null ? (
|
|
1943
|
+
<ScrollView {...props} />
|
|
1944
|
+
) : (
|
|
1945
|
+
<ScrollView {...props} scrollViewRef={ref} />
|
|
1946
|
+
);
|
|
1947
|
+
});
|
|
1946
1948
|
Wrapper.displayName = 'ScrollView';
|
|
1949
|
+
// $FlowExpectedError[prop-missing]
|
|
1947
1950
|
Wrapper.Context = ScrollViewContext;
|
|
1948
1951
|
|
|
1949
1952
|
module.exports = ((Wrapper: $FlowFixMe): React.AbstractComponent<
|
|
@@ -160,6 +160,9 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
|
|
|
160
160
|
snapToInterval: true,
|
|
161
161
|
snapToOffsets: true,
|
|
162
162
|
snapToStart: true,
|
|
163
|
+
verticalScrollIndicatorInsets: {
|
|
164
|
+
diff: require('../../Utilities/differ/insetsDiffer'),
|
|
165
|
+
},
|
|
163
166
|
zoomScale: true,
|
|
164
167
|
...ConditionallyIgnoredEventHandlers({
|
|
165
168
|
onScrollBeginDrag: true,
|
|
@@ -85,8 +85,15 @@ const RCTTextInputViewConfig = {
|
|
|
85
85
|
topContentSizeChange: {
|
|
86
86
|
registrationName: 'onContentSizeChange',
|
|
87
87
|
},
|
|
88
|
+
topChangeSync: {
|
|
89
|
+
registrationName: 'onChangeSync',
|
|
90
|
+
},
|
|
91
|
+
topKeyPressSync: {
|
|
92
|
+
registrationName: 'onKeyPressSync',
|
|
93
|
+
},
|
|
88
94
|
},
|
|
89
95
|
validAttributes: {
|
|
96
|
+
dynamicTypeRamp: true,
|
|
90
97
|
fontSize: true,
|
|
91
98
|
fontWeight: true,
|
|
92
99
|
fontVariant: true,
|
|
@@ -144,12 +151,15 @@ const RCTTextInputViewConfig = {
|
|
|
144
151
|
showSoftInputOnFocus: true,
|
|
145
152
|
autoFocus: true,
|
|
146
153
|
lineBreakStrategyIOS: true,
|
|
154
|
+
lineBreakModeIOS: true,
|
|
147
155
|
smartInsertDelete: true,
|
|
148
156
|
...ConditionallyIgnoredEventHandlers({
|
|
149
157
|
onChange: true,
|
|
150
158
|
onSelectionChange: true,
|
|
151
159
|
onContentSizeChange: true,
|
|
152
160
|
onScroll: true,
|
|
161
|
+
onChangeSync: true,
|
|
162
|
+
onKeyPressSync: true,
|
|
153
163
|
}),
|
|
154
164
|
},
|
|
155
165
|
};
|
|
@@ -255,6 +255,9 @@ export interface TextInputIOSProps {
|
|
|
255
255
|
* - `'birthdateDay'` (iOS 17+)
|
|
256
256
|
* - `'birthdateMonth'` (iOS 17+)
|
|
257
257
|
* - `'birthdateYear'` (iOS 17+)
|
|
258
|
+
* - `'dateTime'` (iOS 15+)
|
|
259
|
+
* - `'flightNumber'` (iOS 15+)
|
|
260
|
+
* - `'shipmentTrackingNumber'` (iOS 15+)
|
|
258
261
|
*
|
|
259
262
|
*/
|
|
260
263
|
textContentType?:
|
|
@@ -299,6 +302,9 @@ export interface TextInputIOSProps {
|
|
|
299
302
|
| 'birthdateDay'
|
|
300
303
|
| 'birthdateMonth'
|
|
301
304
|
| 'birthdateYear'
|
|
305
|
+
| 'dateTime'
|
|
306
|
+
| 'flightNumber'
|
|
307
|
+
| 'shipmentTrackingNumber'
|
|
302
308
|
| undefined;
|
|
303
309
|
|
|
304
310
|
/**
|
|
@@ -316,6 +322,19 @@ export interface TextInputIOSProps {
|
|
|
316
322
|
| 'push-out'
|
|
317
323
|
| undefined;
|
|
318
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Set line break mode on iOS.
|
|
327
|
+
* @platform ios
|
|
328
|
+
*/
|
|
329
|
+
lineBreakModeIOS?:
|
|
330
|
+
| 'wordWrapping'
|
|
331
|
+
| 'char'
|
|
332
|
+
| 'clip'
|
|
333
|
+
| 'head'
|
|
334
|
+
| 'middle'
|
|
335
|
+
| 'tail'
|
|
336
|
+
| undefined;
|
|
337
|
+
|
|
319
338
|
/**
|
|
320
339
|
* If `false`, the iOS system will not insert an extra space after a paste operation
|
|
321
340
|
* neither delete one or two spaces after a cut or delete operation.
|
|
@@ -198,7 +198,10 @@ export type TextContentType =
|
|
|
198
198
|
| 'birthdate'
|
|
199
199
|
| 'birthdateDay'
|
|
200
200
|
| 'birthdateMonth'
|
|
201
|
-
| 'birthdateYear'
|
|
201
|
+
| 'birthdateYear'
|
|
202
|
+
| 'dateTime'
|
|
203
|
+
| 'flightNumber'
|
|
204
|
+
| 'shipmentTrackingNumber';
|
|
202
205
|
|
|
203
206
|
export type enterKeyHintType =
|
|
204
207
|
| 'enter'
|
|
@@ -312,6 +315,19 @@ type IOSProps = $ReadOnly<{|
|
|
|
312
315
|
*/
|
|
313
316
|
lineBreakStrategyIOS?: ?('none' | 'standard' | 'hangul-word' | 'push-out'),
|
|
314
317
|
|
|
318
|
+
/**
|
|
319
|
+
* Set line break mode on iOS.
|
|
320
|
+
* @platform ios
|
|
321
|
+
*/
|
|
322
|
+
lineBreakModeIOS?: ?(
|
|
323
|
+
| 'wordWrapping'
|
|
324
|
+
| 'char'
|
|
325
|
+
| 'clip'
|
|
326
|
+
| 'head'
|
|
327
|
+
| 'middle'
|
|
328
|
+
| 'tail'
|
|
329
|
+
),
|
|
330
|
+
|
|
315
331
|
/**
|
|
316
332
|
* If `false`, the iOS system will not insert an extra space after a paste operation
|
|
317
333
|
* neither delete one or two spaces after a cut or delete operation.
|
|
@@ -238,7 +238,10 @@ export type TextContentType =
|
|
|
238
238
|
| 'birthdate'
|
|
239
239
|
| 'birthdateDay'
|
|
240
240
|
| 'birthdateMonth'
|
|
241
|
-
| 'birthdateYear'
|
|
241
|
+
| 'birthdateYear'
|
|
242
|
+
| 'dateTime'
|
|
243
|
+
| 'flightNumber'
|
|
244
|
+
| 'shipmentTrackingNumber';
|
|
242
245
|
|
|
243
246
|
export type enterKeyHintType =
|
|
244
247
|
// Cross Platform
|
|
@@ -358,6 +361,19 @@ type IOSProps = $ReadOnly<{|
|
|
|
358
361
|
*/
|
|
359
362
|
lineBreakStrategyIOS?: ?('none' | 'standard' | 'hangul-word' | 'push-out'),
|
|
360
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Set line break mode on iOS.
|
|
366
|
+
* @platform ios
|
|
367
|
+
*/
|
|
368
|
+
lineBreakModeIOS?: ?(
|
|
369
|
+
| 'wordWrapping'
|
|
370
|
+
| 'char'
|
|
371
|
+
| 'clip'
|
|
372
|
+
| 'head'
|
|
373
|
+
| 'middle'
|
|
374
|
+
| 'tail'
|
|
375
|
+
),
|
|
376
|
+
|
|
361
377
|
/**
|
|
362
378
|
* If `false`, the iOS system will not insert an extra space after a paste operation
|
|
363
379
|
* neither delete one or two spaces after a cut or delete operation.
|