@office-iss/react-native-win32 0.0.0-canary.260 → 0.0.0-canary.261
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 +4 -3
- package/CHANGELOG.json +16 -1
- package/CHANGELOG.md +12 -4
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Lists/SectionListModern.js +2 -2
- package/Libraries/NativeComponent/NativeComponentRegistry.js +13 -20
- package/Libraries/NativeComponent/StaticViewConfigValidator.js +0 -21
- package/Libraries/ReactNative/RendererImplementation.js +2 -2
- package/Libraries/Renderer/shims/ReactNativeTypes.js +9 -4
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +3 -3
- package/Libraries/StyleSheet/StyleSheetTypes.js +1 -1
- package/Libraries/StyleSheet/processBackgroundImage.js +136 -38
- package/Libraries/StyleSheet/processFilter.js +4 -4
- package/Libraries/Utilities/Appearance.js +65 -73
- package/Libraries/Utilities/DevLoadingView.js +2 -4
- package/Libraries/Utilities/stringifyViewConfig.js +22 -0
- package/Libraries/Utilities/useColorScheme.js +3 -3
- package/index.js +1 -1
- package/index.win32.js +1 -1
- package/jest/setup.js +0 -4
- package/overrides.json +3 -3
- package/package.json +11 -11
- package/src/private/featureflags/ReactNativeFeatureFlags.js +12 -6
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +2 -2
- package/src/private/specs/modules/NativeAppearance.js +3 -3
- package/src/private/webapis/intersectionobserver/IntersectionObserver.js +4 -2
- package/src/private/webapis/intersectionobserver/IntersectionObserverManager.js +9 -9
- package/src/private/webapis/mutationobserver/MutationObserver.js +4 -2
- package/src/private/webapis/mutationobserver/MutationObserverManager.js +19 -10
- package/Libraries/Utilities/verifyComponentAttributeEquivalence.js +0 -135
package/.flowconfig
CHANGED
|
@@ -54,8 +54,6 @@
|
|
|
54
54
|
.*/node_modules/sample-apps/.*
|
|
55
55
|
.*/node_modules/playground/.*
|
|
56
56
|
|
|
57
|
-
; Ignore templates for 'npx @react-native-community/cli init'
|
|
58
|
-
<PROJECT_ROOT>/packages/react-native/template/.*
|
|
59
57
|
<PROJECT_ROOT>/packages/react-native/sdks/.*
|
|
60
58
|
|
|
61
59
|
; Ignore the codegen e2e tests
|
|
@@ -67,6 +65,9 @@
|
|
|
67
65
|
; Ignore "BUCK" generated dirs
|
|
68
66
|
<PROJECT_ROOT>/\.buckd/
|
|
69
67
|
|
|
68
|
+
; Ignore cache files
|
|
69
|
+
.*/node_modules/.cache*
|
|
70
|
+
|
|
70
71
|
; Ignore the src-win folder - flow files are combined with ones from react-native into the root Libraries folder
|
|
71
72
|
.*/react-native-win32/src-win/.*
|
|
72
73
|
|
|
@@ -159,4 +160,4 @@ untyped-import
|
|
|
159
160
|
untyped-type-import
|
|
160
161
|
|
|
161
162
|
[version]
|
|
162
|
-
^0.
|
|
163
|
+
^0.244.0
|
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,22 @@
|
|
|
2
2
|
"name": "@office-iss/react-native-win32",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Thu, 05 Sep 2024 05:13:08 GMT",
|
|
6
|
+
"version": "0.0.0-canary.261",
|
|
7
|
+
"tag": "@office-iss/react-native-win32_v0.0.0-canary.261",
|
|
8
|
+
"comments": {
|
|
9
|
+
"prerelease": [
|
|
10
|
+
{
|
|
11
|
+
"author": "34109996+chiaramooney@users.noreply.github.com",
|
|
12
|
+
"package": "@office-iss/react-native-win32",
|
|
13
|
+
"commit": "277d6f06a3e1bf1650cd9d1e7b4f22e0619968e9",
|
|
14
|
+
"comment": "Integrate 8/20"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Wed, 28 Aug 2024 05:14:44 GMT",
|
|
6
21
|
"version": "0.0.0-canary.260",
|
|
7
22
|
"tag": "@office-iss/react-native-win32_v0.0.0-canary.260",
|
|
8
23
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
# Change Log - @office-iss/react-native-win32
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Thu, 05 Sep 2024 05:13:08 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
-
## 0.0.0-canary.
|
|
7
|
+
## 0.0.0-canary.261
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Thu, 05 Sep 2024 05:13:08 GMT
|
|
10
10
|
|
|
11
11
|
### Changes
|
|
12
12
|
|
|
13
|
-
-
|
|
13
|
+
- Integrate 8/20 (34109996+chiaramooney@users.noreply.github.com)
|
|
14
14
|
|
|
15
|
+
## 0.0.0-canary.260
|
|
16
|
+
|
|
17
|
+
Wed, 28 Aug 2024 05:14:44 GMT
|
|
18
|
+
|
|
19
|
+
### Changes
|
|
20
|
+
|
|
21
|
+
- integrate 0.76.0-nightly-20240816-17017d2b8 (tatianakapos@microsoft.com)
|
|
22
|
+
|
|
15
23
|
## 0.0.0-canary.259
|
|
16
24
|
|
|
17
25
|
Thu, 22 Aug 2024 05:24:27 GMT
|
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
SectionBase as _SectionBase,
|
|
17
17
|
VirtualizedSectionListProps,
|
|
18
18
|
} from '@react-native/virtualized-lists';
|
|
19
|
-
import type {AbstractComponent,
|
|
19
|
+
import type {AbstractComponent, ElementRef} from 'react';
|
|
20
20
|
|
|
21
21
|
import Platform from '../Utilities/Platform';
|
|
22
22
|
import {VirtualizedSectionList} from '@react-native/virtualized-lists';
|
|
@@ -56,7 +56,7 @@ type OptionalProps<SectionT: SectionBase<any>> = {|
|
|
|
56
56
|
...
|
|
57
57
|
},
|
|
58
58
|
...
|
|
59
|
-
}) => null |
|
|
59
|
+
}) => null | React.MixedElement,
|
|
60
60
|
/**
|
|
61
61
|
* A marker property for telling the list to re-render (since it implements `PureComponent`). If
|
|
62
62
|
* any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the
|
|
@@ -17,7 +17,6 @@ import type {
|
|
|
17
17
|
import getNativeComponentAttributes from '../ReactNative/getNativeComponentAttributes';
|
|
18
18
|
import UIManager from '../ReactNative/UIManager';
|
|
19
19
|
import * as ReactNativeViewConfigRegistry from '../Renderer/shims/ReactNativeViewConfigRegistry';
|
|
20
|
-
import verifyComponentAttributeEquivalence from '../Utilities/verifyComponentAttributeEquivalence';
|
|
21
20
|
import * as StaticViewConfigValidator from './StaticViewConfigValidator';
|
|
22
21
|
import {createViewConfig} from './ViewConfig';
|
|
23
22
|
import invariant from 'invariant';
|
|
@@ -35,7 +34,6 @@ let getRuntimeConfig;
|
|
|
35
34
|
export function setRuntimeConfigProvider(
|
|
36
35
|
runtimeConfigProvider: (name: string) => ?{
|
|
37
36
|
native: boolean,
|
|
38
|
-
strict: boolean,
|
|
39
37
|
verify: boolean,
|
|
40
38
|
},
|
|
41
39
|
): void {
|
|
@@ -55,9 +53,8 @@ export function get<Config>(
|
|
|
55
53
|
viewConfigProvider: () => PartialViewConfig,
|
|
56
54
|
): HostComponent<Config> {
|
|
57
55
|
ReactNativeViewConfigRegistry.register(name, () => {
|
|
58
|
-
const {native,
|
|
56
|
+
const {native, verify} = getRuntimeConfig?.(name) ?? {
|
|
59
57
|
native: !global.RN$Bridgeless,
|
|
60
|
-
strict: false,
|
|
61
58
|
verify: false,
|
|
62
59
|
};
|
|
63
60
|
|
|
@@ -92,23 +89,19 @@ export function get<Config>(
|
|
|
92
89
|
? createViewConfig(viewConfigProvider())
|
|
93
90
|
: viewConfig;
|
|
94
91
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
const validationOutput = StaticViewConfigValidator.validate(
|
|
93
|
+
name,
|
|
94
|
+
nativeViewConfig,
|
|
95
|
+
staticViewConfig,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
if (validationOutput.type === 'invalid') {
|
|
99
|
+
console.error(
|
|
100
|
+
StaticViewConfigValidator.stringifyValidationResult(
|
|
101
|
+
name,
|
|
102
|
+
validationOutput,
|
|
103
|
+
),
|
|
100
104
|
);
|
|
101
|
-
|
|
102
|
-
if (validationOutput.type === 'invalid') {
|
|
103
|
-
console.error(
|
|
104
|
-
StaticViewConfigValidator.stringifyValidationResult(
|
|
105
|
-
name,
|
|
106
|
-
validationOutput,
|
|
107
|
-
),
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
} else {
|
|
111
|
-
verifyComponentAttributeEquivalence(nativeViewConfig, staticViewConfig);
|
|
112
105
|
}
|
|
113
106
|
}
|
|
114
107
|
|
|
@@ -22,11 +22,6 @@ export type Difference =
|
|
|
22
22
|
path: Array<string>,
|
|
23
23
|
nativeValue: mixed,
|
|
24
24
|
staticValue: mixed,
|
|
25
|
-
}
|
|
26
|
-
| {
|
|
27
|
-
type: 'unexpected',
|
|
28
|
-
path: Array<string>,
|
|
29
|
-
staticValue: mixed,
|
|
30
25
|
};
|
|
31
26
|
|
|
32
27
|
export type ValidationResult = ValidResult | InvalidResult;
|
|
@@ -90,8 +85,6 @@ export function stringifyValidationResult(
|
|
|
90
85
|
return `- '${path.join('.')}' is missing.`;
|
|
91
86
|
case 'unequal':
|
|
92
87
|
return `- '${path.join('.')}' is the wrong value.`;
|
|
93
|
-
case 'unexpected':
|
|
94
|
-
return `- '${path.join('.')}' is present but not expected to be.`;
|
|
95
88
|
}
|
|
96
89
|
}),
|
|
97
90
|
'',
|
|
@@ -145,20 +138,6 @@ function accumulateDifferences(
|
|
|
145
138
|
});
|
|
146
139
|
}
|
|
147
140
|
}
|
|
148
|
-
|
|
149
|
-
for (const staticKey in staticObject) {
|
|
150
|
-
if (
|
|
151
|
-
!nativeObject.hasOwnProperty(staticKey) &&
|
|
152
|
-
// $FlowFixMe[invalid-computed-prop]
|
|
153
|
-
!isIgnored(staticObject[staticKey])
|
|
154
|
-
) {
|
|
155
|
-
differences.push({
|
|
156
|
-
path: [...path, staticKey],
|
|
157
|
-
type: 'unexpected',
|
|
158
|
-
staticValue: staticObject[staticKey],
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
141
|
}
|
|
163
142
|
|
|
164
143
|
function ifObject(value: mixed): ?{...} {
|
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
Node,
|
|
15
15
|
} from '../Renderer/shims/ReactNativeTypes';
|
|
16
16
|
import type ReactFabricHostComponent from './ReactFabricPublicInstance/ReactFabricHostComponent';
|
|
17
|
-
import type {
|
|
17
|
+
import type {ElementRef, ElementType} from 'react';
|
|
18
18
|
|
|
19
19
|
import {
|
|
20
20
|
onCaughtError,
|
|
@@ -28,7 +28,7 @@ export function renderElement({
|
|
|
28
28
|
useFabric,
|
|
29
29
|
useConcurrentRoot,
|
|
30
30
|
}: {
|
|
31
|
-
element:
|
|
31
|
+
element: React.MixedElement,
|
|
32
32
|
rootTag: number,
|
|
33
33
|
useFabric: boolean,
|
|
34
34
|
useConcurrentRoot: boolean,
|
|
@@ -7,10 +7,15 @@
|
|
|
7
7
|
* @noformat
|
|
8
8
|
* @nolint
|
|
9
9
|
* @flow strict
|
|
10
|
-
* @generated SignedSource<<
|
|
10
|
+
* @generated SignedSource<<89361333bb6b688486e35849a9c669a6>>
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
ElementRef,
|
|
15
|
+
ElementType,
|
|
16
|
+
MixedElement,
|
|
17
|
+
AbstractComponent,
|
|
18
|
+
} from 'react';
|
|
14
19
|
|
|
15
20
|
export type MeasureOnSuccessCallback = (
|
|
16
21
|
x: number,
|
|
@@ -222,7 +227,7 @@ export type ReactNativeType = {
|
|
|
222
227
|
eventType: string,
|
|
223
228
|
): void,
|
|
224
229
|
render(
|
|
225
|
-
element:
|
|
230
|
+
element: MixedElement,
|
|
226
231
|
containerTag: number,
|
|
227
232
|
callback: ?() => void,
|
|
228
233
|
options: ?RenderRootOptions,
|
|
@@ -257,7 +262,7 @@ export type ReactFabricType = {
|
|
|
257
262
|
eventType: string,
|
|
258
263
|
): void,
|
|
259
264
|
render(
|
|
260
|
-
element:
|
|
265
|
+
element: MixedElement,
|
|
261
266
|
containerTag: number,
|
|
262
267
|
callback: ?() => void,
|
|
263
268
|
concurrentRoot: ?boolean,
|
|
@@ -276,10 +276,10 @@ export type BlendMode =
|
|
|
276
276
|
export type GradientValue = {
|
|
277
277
|
type: 'linearGradient';
|
|
278
278
|
// Angle or direction enums
|
|
279
|
-
direction
|
|
280
|
-
colorStops:
|
|
279
|
+
direction?: string | undefined;
|
|
280
|
+
colorStops: ReadonlyArray<{
|
|
281
281
|
color: ColorValue;
|
|
282
|
-
|
|
282
|
+
positions?: ReadonlyArray<string[]> | undefined;
|
|
283
283
|
}>;
|
|
284
284
|
};
|
|
285
285
|
|
|
@@ -45,33 +45,34 @@ export default function processBackgroundImage(
|
|
|
45
45
|
result = parseCSSLinearGradient(backgroundImage);
|
|
46
46
|
} else if (Array.isArray(backgroundImage)) {
|
|
47
47
|
for (const bgImage of backgroundImage) {
|
|
48
|
-
const processedColorStops
|
|
48
|
+
const processedColorStops: Array<{
|
|
49
|
+
color: ProcessedColorValue,
|
|
50
|
+
position: number | null,
|
|
51
|
+
}> = [];
|
|
49
52
|
for (let index = 0; index < bgImage.colorStops.length; index++) {
|
|
50
|
-
const
|
|
51
|
-
const processedColor = processColor(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Currently we only support percentage and undefined value for color stop position.
|
|
55
|
-
if (typeof stop.position === 'undefined') {
|
|
56
|
-
processedPosition =
|
|
57
|
-
bgImage.colorStops.length === 1
|
|
58
|
-
? 1
|
|
59
|
-
: index / (bgImage.colorStops.length - 1);
|
|
60
|
-
} else if (stop.position.endsWith('%')) {
|
|
61
|
-
processedPosition = parseFloat(stop.position) / 100;
|
|
62
|
-
} else {
|
|
63
|
-
// If a color stop position is invalid, return an empty array and do not apply gradient. Same as web.
|
|
53
|
+
const colorStop = bgImage.colorStops[index];
|
|
54
|
+
const processedColor = processColor(colorStop.color);
|
|
55
|
+
if (processedColor == null) {
|
|
56
|
+
// If a color is invalid, return an empty array and do not apply gradient. Same as web.
|
|
64
57
|
return [];
|
|
65
58
|
}
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
if (colorStop.positions != null && colorStop.positions.length > 0) {
|
|
60
|
+
for (const position of colorStop.positions) {
|
|
61
|
+
if (position.endsWith('%')) {
|
|
62
|
+
processedColorStops.push({
|
|
63
|
+
color: processedColor,
|
|
64
|
+
position: parseFloat(position) / 100,
|
|
65
|
+
});
|
|
66
|
+
} else {
|
|
67
|
+
// If a position is invalid, return an empty array and do not apply gradient. Same as web.
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
68
72
|
processedColorStops.push({
|
|
69
73
|
color: processedColor,
|
|
70
|
-
position:
|
|
74
|
+
position: null,
|
|
71
75
|
});
|
|
72
|
-
} else {
|
|
73
|
-
// If a color is invalid, return an empty array and do not apply gradient. Same as web.
|
|
74
|
-
return [];
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
|
|
@@ -96,12 +97,14 @@ export default function processBackgroundImage(
|
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
|
|
100
|
+
const fixedColorStops = getFixedColorStops(processedColorStops);
|
|
101
|
+
|
|
99
102
|
if (points != null) {
|
|
100
103
|
result = result.concat({
|
|
101
104
|
type: 'linearGradient',
|
|
102
105
|
start: points.start,
|
|
103
106
|
end: points.end,
|
|
104
|
-
colorStops:
|
|
107
|
+
colorStops: fixedColorStops,
|
|
105
108
|
});
|
|
106
109
|
}
|
|
107
110
|
}
|
|
@@ -123,7 +126,7 @@ function parseCSSLinearGradient(
|
|
|
123
126
|
let points = TO_BOTTOM_START_END_POINTS;
|
|
124
127
|
const trimmedDirection = parts[0].trim().toLowerCase();
|
|
125
128
|
const colorStopRegex =
|
|
126
|
-
/\s*((?:(?:rgba?|hsla?)\s*\([^)]+\))|#[0-9a-fA-F]+|[a-zA-Z]+)(?:\s+([0-9.]+%?))?\s*/gi;
|
|
129
|
+
/\s*((?:(?:rgba?|hsla?)\s*\([^)]+\))|#[0-9a-fA-F]+|[a-zA-Z]+)(?:\s+(-?[0-9.]+%?)(?:\s+(-?[0-9.]+%?))?)?\s*/gi;
|
|
127
130
|
|
|
128
131
|
if (ANGLE_UNIT_REGEX.test(trimmedDirection)) {
|
|
129
132
|
const angle = parseAngle(trimmedDirection);
|
|
@@ -154,32 +157,50 @@ function parseCSSLinearGradient(
|
|
|
154
157
|
const fullColorStopsStr = parts.join(',');
|
|
155
158
|
let colorStopMatch;
|
|
156
159
|
while ((colorStopMatch = colorStopRegex.exec(fullColorStopsStr))) {
|
|
157
|
-
const [, color,
|
|
160
|
+
const [, color, position1, position2] = colorStopMatch;
|
|
158
161
|
const processedColor = processColor(color.trim().toLowerCase());
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
if (processedColor == null) {
|
|
163
|
+
// If a color is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (typeof position1 !== 'undefined') {
|
|
168
|
+
if (position1.endsWith('%')) {
|
|
169
|
+
colorStops.push({
|
|
170
|
+
color: processedColor,
|
|
171
|
+
position: parseFloat(position1) / 100,
|
|
172
|
+
});
|
|
173
|
+
} else {
|
|
174
|
+
// If a position is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
163
178
|
colorStops.push({
|
|
164
179
|
color: processedColor,
|
|
165
|
-
position:
|
|
180
|
+
position: null,
|
|
166
181
|
});
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (typeof position2 !== 'undefined') {
|
|
185
|
+
if (position2.endsWith('%')) {
|
|
186
|
+
colorStops.push({
|
|
187
|
+
color: processedColor,
|
|
188
|
+
position: parseFloat(position2) / 100,
|
|
189
|
+
});
|
|
190
|
+
} else {
|
|
191
|
+
// If a position is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
170
194
|
}
|
|
171
195
|
}
|
|
172
196
|
|
|
197
|
+
const fixedColorStops = getFixedColorStops(colorStops);
|
|
198
|
+
|
|
173
199
|
gradients.push({
|
|
174
200
|
type: 'linearGradient',
|
|
175
201
|
start: points.start,
|
|
176
202
|
end: points.end,
|
|
177
|
-
colorStops:
|
|
178
|
-
color: stop.color,
|
|
179
|
-
position:
|
|
180
|
-
stop.position ??
|
|
181
|
-
(array.length === 1 ? 1 : index / (array.length - 1)),
|
|
182
|
-
})),
|
|
203
|
+
colorStops: fixedColorStops,
|
|
183
204
|
});
|
|
184
205
|
}
|
|
185
206
|
|
|
@@ -284,3 +305,80 @@ function parseAngle(angle: string): ?number {
|
|
|
284
305
|
return null;
|
|
285
306
|
}
|
|
286
307
|
}
|
|
308
|
+
|
|
309
|
+
// https://drafts.csswg.org/css-images-4/#color-stop-fixup
|
|
310
|
+
function getFixedColorStops(
|
|
311
|
+
colorStops: $ReadOnlyArray<{
|
|
312
|
+
color: ProcessedColorValue,
|
|
313
|
+
position: number | null,
|
|
314
|
+
}>,
|
|
315
|
+
): Array<{
|
|
316
|
+
color: ProcessedColorValue,
|
|
317
|
+
position: number,
|
|
318
|
+
}> {
|
|
319
|
+
let fixedColorStops: Array<{
|
|
320
|
+
color: ProcessedColorValue,
|
|
321
|
+
position: number,
|
|
322
|
+
}> = [];
|
|
323
|
+
let hasNullPositions = false;
|
|
324
|
+
let maxPositionSoFar = colorStops[0].position ?? 0;
|
|
325
|
+
for (let i = 0; i < colorStops.length; i++) {
|
|
326
|
+
const colorStop = colorStops[i];
|
|
327
|
+
let newPosition = colorStop.position;
|
|
328
|
+
if (newPosition === null) {
|
|
329
|
+
// Step 1:
|
|
330
|
+
// If the first color stop does not have a position,
|
|
331
|
+
// set its position to 0%. If the last color stop does not have a position,
|
|
332
|
+
// set its position to 100%.
|
|
333
|
+
if (i === 0) {
|
|
334
|
+
newPosition = 0;
|
|
335
|
+
} else if (i === colorStops.length - 1) {
|
|
336
|
+
newPosition = 1;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Step 2:
|
|
340
|
+
// If a color stop or transition hint has a position
|
|
341
|
+
// that is less than the specified position of any color stop or transition hint
|
|
342
|
+
// before it in the list, set its position to be equal to the
|
|
343
|
+
// largest specified position of any color stop or transition hint before it.
|
|
344
|
+
if (newPosition !== null) {
|
|
345
|
+
newPosition = Math.max(newPosition, maxPositionSoFar);
|
|
346
|
+
fixedColorStops[i] = {
|
|
347
|
+
color: colorStop.color,
|
|
348
|
+
position: newPosition,
|
|
349
|
+
};
|
|
350
|
+
maxPositionSoFar = newPosition;
|
|
351
|
+
} else {
|
|
352
|
+
hasNullPositions = true;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Step 3:
|
|
357
|
+
// If any color stop still does not have a position,
|
|
358
|
+
// then, for each run of adjacent color stops without positions,
|
|
359
|
+
// set their positions so that they are evenly spaced between the preceding and
|
|
360
|
+
// following color stops with positions.
|
|
361
|
+
if (hasNullPositions) {
|
|
362
|
+
let lastDefinedIndex = 0;
|
|
363
|
+
for (let i = 1; i < fixedColorStops.length; i++) {
|
|
364
|
+
if (fixedColorStops[i] !== undefined) {
|
|
365
|
+
const unpositionedStops = i - lastDefinedIndex - 1;
|
|
366
|
+
if (unpositionedStops > 0) {
|
|
367
|
+
const startPosition = fixedColorStops[lastDefinedIndex].position;
|
|
368
|
+
const endPosition = fixedColorStops[i].position;
|
|
369
|
+
const increment =
|
|
370
|
+
(endPosition - startPosition) / (unpositionedStops + 1);
|
|
371
|
+
for (let j = 1; j <= unpositionedStops; j++) {
|
|
372
|
+
fixedColorStops[lastDefinedIndex + j] = {
|
|
373
|
+
color: colorStops[lastDefinedIndex + j].color,
|
|
374
|
+
position: startPosition + increment * j,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
lastDefinedIndex = i;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return fixedColorStops;
|
|
384
|
+
}
|
|
@@ -44,8 +44,8 @@ export default function processFilter(
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
if (typeof filter === 'string') {
|
|
47
|
-
// matches on functions with args like "drop-shadow(1
|
|
48
|
-
const regex = /([\w-]+)\(([^)]
|
|
47
|
+
// matches on functions with args and nested functions like "drop-shadow(10 10 10 rgba(0, 0, 0, 1))"
|
|
48
|
+
const regex = /([\w-]+)\(([^()]*|\([^()]*\)|[^()]*\([^()]*\)[^()]*)\)/g;
|
|
49
49
|
let matches;
|
|
50
50
|
|
|
51
51
|
while ((matches = regex.exec(filter))) {
|
|
@@ -254,8 +254,8 @@ function parseDropShadowString(rawDropShadow: string): ?DropShadowPrimitive {
|
|
|
254
254
|
let lengthCount = 0;
|
|
255
255
|
let keywordDetectedAfterLength = false;
|
|
256
256
|
|
|
257
|
-
// split
|
|
258
|
-
for (const arg of rawDropShadow.split(/\s
|
|
257
|
+
// split args by all whitespaces that are not in parenthesis
|
|
258
|
+
for (const arg of rawDropShadow.split(/\s+(?![^(]*\))/)) {
|
|
259
259
|
const processedColor = processColor(arg);
|
|
260
260
|
if (processedColor != null) {
|
|
261
261
|
if (dropShadow.color != null) {
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import NativeEventEmitter from '../EventEmitter/NativeEventEmitter';
|
|
12
|
-
import Platform from '../Utilities/Platform';
|
|
13
12
|
import EventEmitter, {
|
|
14
13
|
type EventSubscription,
|
|
15
14
|
} from '../vendor/emitter/EventEmitter';
|
|
@@ -20,88 +19,81 @@ import NativeAppearance, {
|
|
|
20
19
|
} from './NativeAppearance';
|
|
21
20
|
import invariant from 'invariant';
|
|
22
21
|
|
|
23
|
-
type AppearanceListener = (preferences: AppearancePreferences) => void;
|
|
24
22
|
const eventEmitter = new EventEmitter<{
|
|
25
|
-
change: [
|
|
23
|
+
change: [{colorScheme: ?ColorSchemeName}],
|
|
26
24
|
}>();
|
|
27
25
|
|
|
28
26
|
type NativeAppearanceEventDefinitions = {
|
|
29
27
|
appearanceChanged: [AppearancePreferences],
|
|
30
28
|
};
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
colorScheme === 'dark' ||
|
|
45
|
-
colorScheme === 'light' ||
|
|
46
|
-
colorScheme == null,
|
|
47
|
-
"Unrecognized color scheme. Did you mean 'dark' or 'light'?",
|
|
48
|
-
);
|
|
49
|
-
eventEmitter.emit('change', {colorScheme});
|
|
50
|
-
},
|
|
51
|
-
);
|
|
30
|
+
// Cache the color scheme to reduce the cost of reading it between changes.
|
|
31
|
+
// NOTE: If `NativeAppearance` is null, this will always be null.
|
|
32
|
+
let appearance: ?{colorScheme: ?ColorSchemeName} = null;
|
|
33
|
+
|
|
34
|
+
if (NativeAppearance != null) {
|
|
35
|
+
new NativeEventEmitter<NativeAppearanceEventDefinitions>(
|
|
36
|
+
NativeAppearance,
|
|
37
|
+
).addListener('appearanceChanged', (newAppearance: AppearancePreferences) => {
|
|
38
|
+
const colorScheme = toColorScheme(newAppearance.colorScheme);
|
|
39
|
+
appearance = {colorScheme};
|
|
40
|
+
eventEmitter.emit('change', appearance);
|
|
41
|
+
});
|
|
52
42
|
}
|
|
53
43
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
getColorScheme(): ?ColorSchemeName {
|
|
66
|
-
if (__DEV__) {
|
|
67
|
-
if (isAsyncDebugging) {
|
|
68
|
-
// Hard code light theme when using the async debugger as
|
|
69
|
-
// sync calls aren't supported
|
|
70
|
-
return 'light';
|
|
71
|
-
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns the current color scheme preference. This value may change, so the
|
|
46
|
+
* value should not be cached without either listening to changes or using
|
|
47
|
+
* the `useColorScheme` hook.
|
|
48
|
+
*/
|
|
49
|
+
export function getColorScheme(): ?ColorSchemeName {
|
|
50
|
+
if (__DEV__) {
|
|
51
|
+
if (isAsyncDebugging) {
|
|
52
|
+
// Hard code light theme when using the async debugger as
|
|
53
|
+
// sync calls aren't supported
|
|
54
|
+
return 'light';
|
|
72
55
|
}
|
|
56
|
+
}
|
|
57
|
+
let colorScheme = null;
|
|
58
|
+
if (NativeAppearance != null) {
|
|
59
|
+
if (appearance == null) {
|
|
60
|
+
// Lazily initialize `appearance`. This should only happen once because
|
|
61
|
+
// we never reassign a null value to `appearance`.
|
|
62
|
+
appearance = {
|
|
63
|
+
colorScheme: toColorScheme(NativeAppearance.getColorScheme()),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
colorScheme = appearance.colorScheme;
|
|
67
|
+
}
|
|
68
|
+
return colorScheme;
|
|
69
|
+
}
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"Unrecognized color scheme. Did you mean 'dark' or 'light'?",
|
|
84
|
-
);
|
|
85
|
-
return nativeColorScheme;
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
setColorScheme(colorScheme: ?ColorSchemeName): void {
|
|
89
|
-
const nativeColorScheme = colorScheme == null ? 'unspecified' : colorScheme;
|
|
90
|
-
|
|
91
|
-
invariant(
|
|
92
|
-
colorScheme === 'dark' || colorScheme === 'light' || colorScheme == null,
|
|
93
|
-
"Unrecognized color scheme. Did you mean 'dark', 'light' or null?",
|
|
94
|
-
);
|
|
71
|
+
/**
|
|
72
|
+
* Updates the current color scheme to the supplied value.
|
|
73
|
+
*/
|
|
74
|
+
export function setColorScheme(colorScheme: ?ColorSchemeName): void {
|
|
75
|
+
if (NativeAppearance != null) {
|
|
76
|
+
NativeAppearance.setColorScheme(colorScheme ?? 'unspecified');
|
|
77
|
+
appearance = {colorScheme};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
95
80
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Add an event handler that is fired when appearance preferences change.
|
|
83
|
+
*/
|
|
84
|
+
export function addChangeListener(
|
|
85
|
+
listener: ({colorScheme: ?ColorSchemeName}) => void,
|
|
86
|
+
): EventSubscription {
|
|
87
|
+
return eventEmitter.addListener('change', listener);
|
|
88
|
+
}
|
|
100
89
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
90
|
+
/**
|
|
91
|
+
* TODO: (hramos) T52919652 Use ?ColorSchemeName once codegen supports union
|
|
92
|
+
*/
|
|
93
|
+
function toColorScheme(colorScheme: ?string): ?ColorSchemeName {
|
|
94
|
+
invariant(
|
|
95
|
+
colorScheme === 'dark' || colorScheme === 'light' || colorScheme == null,
|
|
96
|
+
"Unrecognized color scheme. Did you mean 'dark', 'light' or null?",
|
|
97
|
+
);
|
|
98
|
+
return colorScheme;
|
|
99
|
+
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import processColor from '../StyleSheet/processColor';
|
|
12
|
-
import
|
|
12
|
+
import {getColorScheme} from './Appearance';
|
|
13
13
|
import NativeDevLoadingView from './NativeDevLoadingView';
|
|
14
14
|
|
|
15
15
|
const COLOR_SCHEME = {
|
|
@@ -39,9 +39,7 @@ module.exports = {
|
|
|
39
39
|
showMessage(message: string, type: 'load' | 'refresh') {
|
|
40
40
|
if (NativeDevLoadingView) {
|
|
41
41
|
const colorScheme =
|
|
42
|
-
|
|
43
|
-
? COLOR_SCHEME.dark
|
|
44
|
-
: COLOR_SCHEME.default;
|
|
42
|
+
getColorScheme() === 'dark' ? COLOR_SCHEME.dark : COLOR_SCHEME.default;
|
|
45
43
|
|
|
46
44
|
const colorSet = colorScheme[type];
|
|
47
45
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @flow
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export default function stringifyViewConfig(viewConfig: any): string {
|
|
12
|
+
return JSON.stringify(
|
|
13
|
+
viewConfig,
|
|
14
|
+
(key, val) => {
|
|
15
|
+
if (typeof val === 'function') {
|
|
16
|
+
return `ƒ ${val.name}`;
|
|
17
|
+
}
|
|
18
|
+
return val;
|
|
19
|
+
},
|
|
20
|
+
2,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
|
|
13
13
|
import type {ColorSchemeName} from './NativeAppearance';
|
|
14
14
|
|
|
15
|
-
import
|
|
15
|
+
import {addChangeListener, getColorScheme} from './Appearance';
|
|
16
16
|
import {useSyncExternalStore} from 'react';
|
|
17
17
|
|
|
18
18
|
const subscribe = (onStoreChange: () => void) => {
|
|
19
|
-
const appearanceSubscription =
|
|
19
|
+
const appearanceSubscription = addChangeListener(onStoreChange);
|
|
20
20
|
return () => appearanceSubscription.remove();
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export default function useColorScheme(): ?ColorSchemeName {
|
|
24
|
-
return useSyncExternalStore(subscribe,
|
|
24
|
+
return useSyncExternalStore(subscribe, getColorScheme);
|
|
25
25
|
}
|
package/index.js
CHANGED
|
@@ -82,7 +82,7 @@ import typeof StyleSheet from './Libraries/StyleSheet/StyleSheet';
|
|
|
82
82
|
import typeof Text from './Libraries/Text/Text';
|
|
83
83
|
import typeof * as TurboModuleRegistry from './Libraries/TurboModule/TurboModuleRegistry';
|
|
84
84
|
import typeof UTFSequence from './Libraries/UTFSequence';
|
|
85
|
-
import typeof Appearance from './Libraries/Utilities/Appearance';
|
|
85
|
+
import typeof * as Appearance from './Libraries/Utilities/Appearance';
|
|
86
86
|
import typeof BackHandler from './Libraries/Utilities/BackHandler';
|
|
87
87
|
import typeof DeviceInfo from './Libraries/Utilities/DeviceInfo';
|
|
88
88
|
import typeof DevSettings from './Libraries/Utilities/DevSettings';
|
package/index.win32.js
CHANGED
|
@@ -82,7 +82,7 @@ import typeof StyleSheet from './Libraries/StyleSheet/StyleSheet';
|
|
|
82
82
|
import typeof Text from './Libraries/Text/Text';
|
|
83
83
|
import typeof * as TurboModuleRegistry from './Libraries/TurboModule/TurboModuleRegistry';
|
|
84
84
|
import typeof UTFSequence from './Libraries/UTFSequence';
|
|
85
|
-
import typeof Appearance from './Libraries/Utilities/Appearance';
|
|
85
|
+
import typeof * as Appearance from './Libraries/Utilities/Appearance';
|
|
86
86
|
import typeof BackHandler from './Libraries/Utilities/BackHandler';
|
|
87
87
|
import typeof DeviceInfo from './Libraries/Utilities/DeviceInfo';
|
|
88
88
|
import typeof DevSettings from './Libraries/Utilities/DevSettings';
|
package/jest/setup.js
CHANGED
|
@@ -392,10 +392,6 @@ jest
|
|
|
392
392
|
.mock('../Libraries/ReactNative/requireNativeComponent', () => {
|
|
393
393
|
return jest.requireActual('./mockNativeComponent');
|
|
394
394
|
})
|
|
395
|
-
.mock(
|
|
396
|
-
'../Libraries/Utilities/verifyComponentAttributeEquivalence',
|
|
397
|
-
() => function () {},
|
|
398
|
-
)
|
|
399
395
|
.mock('../Libraries/Vibration/Vibration', () => ({
|
|
400
396
|
vibrate: jest.fn(),
|
|
401
397
|
cancel: jest.fn(),
|
package/overrides.json
CHANGED
|
@@ -7,19 +7,19 @@
|
|
|
7
7
|
"**/__snapshots__/**",
|
|
8
8
|
"src-win/rntypes/**"
|
|
9
9
|
],
|
|
10
|
-
"baseVersion": "0.76.0-nightly-
|
|
10
|
+
"baseVersion": "0.76.0-nightly-20240824-09e88448c",
|
|
11
11
|
"overrides": [
|
|
12
12
|
{
|
|
13
13
|
"type": "derived",
|
|
14
14
|
"file": ".flowconfig",
|
|
15
15
|
"baseFile": ".flowconfig",
|
|
16
|
-
"baseHash": "
|
|
16
|
+
"baseHash": "27c9677306d4f1bd627a346969c592aee606811a"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"type": "derived",
|
|
20
20
|
"file": "src-win/index.win32.js",
|
|
21
21
|
"baseFile": "packages/react-native/index.js",
|
|
22
|
-
"baseHash": "
|
|
22
|
+
"baseHash": "da5d9e79c8c14c56ba00f73c8514c06e6fffe8ed"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"type": "platform",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@office-iss/react-native-win32",
|
|
3
|
-
"version": "0.0.0-canary.
|
|
3
|
+
"version": "0.0.0-canary.261",
|
|
4
4
|
"description": "Implementation of react native on top of Office's Win32 platform.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
"@react-native-community/cli-platform-android": "14.0.0",
|
|
31
31
|
"@react-native-community/cli-platform-ios": "14.0.0",
|
|
32
32
|
"@react-native/assets": "1.0.0",
|
|
33
|
-
"@react-native/assets-registry": "0.76.0-nightly-
|
|
34
|
-
"@react-native/codegen": "0.76.0-nightly-
|
|
35
|
-
"@react-native/community-cli-plugin": "0.76.0-nightly-
|
|
36
|
-
"@react-native/gradle-plugin": "0.76.0-nightly-
|
|
37
|
-
"@react-native/js-polyfills": "0.76.0-nightly-
|
|
38
|
-
"@react-native/normalize-colors": "0.76.0-nightly-
|
|
39
|
-
"@react-native/virtualized-lists": "0.76.0-nightly-
|
|
33
|
+
"@react-native/assets-registry": "0.76.0-nightly-20240824-09e88448c",
|
|
34
|
+
"@react-native/codegen": "0.76.0-nightly-20240824-09e88448c",
|
|
35
|
+
"@react-native/community-cli-plugin": "0.76.0-nightly-20240824-09e88448c",
|
|
36
|
+
"@react-native/gradle-plugin": "0.76.0-nightly-20240824-09e88448c",
|
|
37
|
+
"@react-native/js-polyfills": "0.76.0-nightly-20240824-09e88448c",
|
|
38
|
+
"@react-native/normalize-colors": "0.76.0-nightly-20240824-09e88448c",
|
|
39
|
+
"@react-native/virtualized-lists": "0.76.0-nightly-20240824-09e88448c",
|
|
40
40
|
"abort-controller": "^3.0.0",
|
|
41
41
|
"anser": "^1.4.9",
|
|
42
42
|
"ansi-regex": "^5.0.0",
|
|
@@ -82,19 +82,19 @@
|
|
|
82
82
|
"@types/prop-types": "15.7.1",
|
|
83
83
|
"@types/react": "^18.2.6",
|
|
84
84
|
"eslint": "^8.19.0",
|
|
85
|
-
"flow-bin": "^0.
|
|
85
|
+
"flow-bin": "^0.244.0",
|
|
86
86
|
"jscodeshift": "^0.14.0",
|
|
87
87
|
"just-scripts": "^1.3.3",
|
|
88
88
|
"prettier": "2.8.8",
|
|
89
89
|
"react": "19.0.0-rc-fb9a90fa48-20240614",
|
|
90
|
-
"react-native": "0.76.0-nightly-
|
|
90
|
+
"react-native": "0.76.0-nightly-20240824-09e88448c",
|
|
91
91
|
"react-native-platform-override": "^1.9.45",
|
|
92
92
|
"typescript": "5.0.4"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
95
|
"@types/react": "^18.2.6",
|
|
96
96
|
"react": "^19.0.0-rc-fb9a90fa48-20240614",
|
|
97
|
-
"react-native": "0.76.0-nightly-
|
|
97
|
+
"react-native": "0.76.0-nightly-20240824-09e88448c"
|
|
98
98
|
},
|
|
99
99
|
"beachball": {
|
|
100
100
|
"defaultNpmTag": "canary",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @generated SignedSource<<
|
|
7
|
+
* @generated SignedSource<<3c32ce3847859db45d2e8bafb3cc31a1>>
|
|
8
8
|
* @flow strict-local
|
|
9
9
|
*/
|
|
10
10
|
|
|
@@ -30,6 +30,7 @@ export type ReactNativeFeatureFlagsJsOnly = {
|
|
|
30
30
|
animatedShouldDebounceQueueFlush: Getter<boolean>,
|
|
31
31
|
animatedShouldUseSingleOp: Getter<boolean>,
|
|
32
32
|
enableAccessToHostTreeInFabric: Getter<boolean>,
|
|
33
|
+
enableOptimisedVirtualizedCells: Getter<boolean>,
|
|
33
34
|
isLayoutAnimationEnabled: Getter<boolean>,
|
|
34
35
|
shouldSkipStateUpdatesForLoopingAnimations: Getter<boolean>,
|
|
35
36
|
shouldUseAnimatedObjectForTransform: Getter<boolean>,
|
|
@@ -48,7 +49,6 @@ export type ReactNativeFeatureFlags = {
|
|
|
48
49
|
commonTestFlag: Getter<boolean>,
|
|
49
50
|
allowRecursiveCommitsWithSynchronousMountOnAndroid: Getter<boolean>,
|
|
50
51
|
batchRenderingUpdatesInEventLoop: Getter<boolean>,
|
|
51
|
-
changeOrderOfMountingInstructionsOnAndroid: Getter<boolean>,
|
|
52
52
|
completeReactInstanceCreationOnBgThreadOnAndroid: Getter<boolean>,
|
|
53
53
|
destroyFabricSurfacesInReactInstanceManager: Getter<boolean>,
|
|
54
54
|
enableAlignItemsBaselineOnFabricIOS: Getter<boolean>,
|
|
@@ -60,6 +60,7 @@ export type ReactNativeFeatureFlags = {
|
|
|
60
60
|
enableFabricLogs: Getter<boolean>,
|
|
61
61
|
enableFabricRendererExclusively: Getter<boolean>,
|
|
62
62
|
enableGranularShadowTreeStateReconciliation: Getter<boolean>,
|
|
63
|
+
enableLayoutAnimationsOnIOS: Getter<boolean>,
|
|
63
64
|
enableLongTaskAPI: Getter<boolean>,
|
|
64
65
|
enableMicrotasks: Getter<boolean>,
|
|
65
66
|
enablePropsUpdateReconciliationAndroid: Getter<boolean>,
|
|
@@ -112,6 +113,11 @@ export const animatedShouldUseSingleOp: Getter<boolean> = createJavaScriptFlagGe
|
|
|
112
113
|
*/
|
|
113
114
|
export const enableAccessToHostTreeInFabric: Getter<boolean> = createJavaScriptFlagGetter('enableAccessToHostTreeInFabric', false);
|
|
114
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Removing unnecessary rerenders Virtualized cells after any rerenders of Virualized list. Works with strict=true option
|
|
118
|
+
*/
|
|
119
|
+
export const enableOptimisedVirtualizedCells: Getter<boolean> = createJavaScriptFlagGetter('enableOptimisedVirtualizedCells', false);
|
|
120
|
+
|
|
115
121
|
/**
|
|
116
122
|
* Function used to enable / disabled Layout Animations in React Native.
|
|
117
123
|
*/
|
|
@@ -169,10 +175,6 @@ export const allowRecursiveCommitsWithSynchronousMountOnAndroid: Getter<boolean>
|
|
|
169
175
|
* When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop.
|
|
170
176
|
*/
|
|
171
177
|
export const batchRenderingUpdatesInEventLoop: Getter<boolean> = createNativeFlagGetter('batchRenderingUpdatesInEventLoop', false);
|
|
172
|
-
/**
|
|
173
|
-
* When enabled, insert of views on Android will be moved from the beginning of the IntBufferBatchMountItem to be after layout updates.
|
|
174
|
-
*/
|
|
175
|
-
export const changeOrderOfMountingInstructionsOnAndroid: Getter<boolean> = createNativeFlagGetter('changeOrderOfMountingInstructionsOnAndroid', false);
|
|
176
178
|
/**
|
|
177
179
|
* Do not wait for a main-thread dispatch to complete init to start executing work on the JS thread on Android
|
|
178
180
|
*/
|
|
@@ -217,6 +219,10 @@ export const enableFabricRendererExclusively: Getter<boolean> = createNativeFlag
|
|
|
217
219
|
* When enabled, the renderer would only fail commits when they propagate state and the last commit that updated state changed before committing.
|
|
218
220
|
*/
|
|
219
221
|
export const enableGranularShadowTreeStateReconciliation: Getter<boolean> = createNativeFlagGetter('enableGranularShadowTreeStateReconciliation', false);
|
|
222
|
+
/**
|
|
223
|
+
* When enabled, LayoutAnimations API will animate state changes on iOS.
|
|
224
|
+
*/
|
|
225
|
+
export const enableLayoutAnimationsOnIOS: Getter<boolean> = createNativeFlagGetter('enableLayoutAnimationsOnIOS', true);
|
|
220
226
|
/**
|
|
221
227
|
* Enables the reporting of long tasks through `PerformanceObserver`. Only works if the event loop is enabled.
|
|
222
228
|
*/
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @generated SignedSource<<
|
|
7
|
+
* @generated SignedSource<<1f1710a12f6980b23bb6c0ece0060b59>>
|
|
8
8
|
* @flow strict-local
|
|
9
9
|
*/
|
|
10
10
|
|
|
@@ -26,7 +26,6 @@ export interface Spec extends TurboModule {
|
|
|
26
26
|
+commonTestFlag?: () => boolean;
|
|
27
27
|
+allowRecursiveCommitsWithSynchronousMountOnAndroid?: () => boolean;
|
|
28
28
|
+batchRenderingUpdatesInEventLoop?: () => boolean;
|
|
29
|
-
+changeOrderOfMountingInstructionsOnAndroid?: () => boolean;
|
|
30
29
|
+completeReactInstanceCreationOnBgThreadOnAndroid?: () => boolean;
|
|
31
30
|
+destroyFabricSurfacesInReactInstanceManager?: () => boolean;
|
|
32
31
|
+enableAlignItemsBaselineOnFabricIOS?: () => boolean;
|
|
@@ -38,6 +37,7 @@ export interface Spec extends TurboModule {
|
|
|
38
37
|
+enableFabricLogs?: () => boolean;
|
|
39
38
|
+enableFabricRendererExclusively?: () => boolean;
|
|
40
39
|
+enableGranularShadowTreeStateReconciliation?: () => boolean;
|
|
40
|
+
+enableLayoutAnimationsOnIOS?: () => boolean;
|
|
41
41
|
+enableLongTaskAPI?: () => boolean;
|
|
42
42
|
+enableMicrotasks?: () => boolean;
|
|
43
43
|
+enablePropsUpdateReconciliationAndroid?: () => boolean;
|
|
@@ -14,19 +14,19 @@ import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboMod
|
|
|
14
14
|
|
|
15
15
|
export type ColorSchemeName = 'light' | 'dark';
|
|
16
16
|
|
|
17
|
-
export type AppearancePreferences = {
|
|
17
|
+
export type AppearancePreferences = {
|
|
18
18
|
// TODO: (hramos) T52919652 Use ?ColorSchemeName once codegen supports union
|
|
19
19
|
// types.
|
|
20
20
|
/* 'light' | 'dark' */
|
|
21
21
|
colorScheme?: ?string,
|
|
22
|
-
|
|
22
|
+
};
|
|
23
23
|
|
|
24
24
|
export interface Spec extends TurboModule {
|
|
25
25
|
// TODO: (hramos) T52919652 Use ?ColorSchemeName once codegen supports union
|
|
26
26
|
// types.
|
|
27
27
|
/* 'light' | 'dark' */
|
|
28
28
|
+getColorScheme: () => ?string;
|
|
29
|
-
+setColorScheme
|
|
29
|
+
+setColorScheme: (colorScheme: string) => void;
|
|
30
30
|
|
|
31
31
|
// RCTEventEmitter
|
|
32
32
|
+addListener: (eventName: string) => void;
|
|
@@ -141,12 +141,14 @@ export default class IntersectionObserver {
|
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
IntersectionObserverManager.observe({
|
|
144
|
+
const didStartObserving = IntersectionObserverManager.observe({
|
|
145
145
|
intersectionObserverId: this._getOrCreateIntersectionObserverId(),
|
|
146
146
|
target,
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
if (didStartObserving) {
|
|
150
|
+
this._observationTargets.add(target);
|
|
151
|
+
}
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
/**
|
|
@@ -116,10 +116,10 @@ export function observe({
|
|
|
116
116
|
}: {
|
|
117
117
|
intersectionObserverId: IntersectionObserverId,
|
|
118
118
|
target: ReactNativeElement,
|
|
119
|
-
}):
|
|
119
|
+
}): boolean {
|
|
120
120
|
if (NativeIntersectionObserver == null) {
|
|
121
121
|
warnNoNativeIntersectionObserver();
|
|
122
|
-
return;
|
|
122
|
+
return false;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
const registeredObserver = registeredIntersectionObservers.get(
|
|
@@ -129,15 +129,13 @@ export function observe({
|
|
|
129
129
|
console.error(
|
|
130
130
|
`IntersectionObserverManager: could not start observing target because IntersectionObserver with ID ${intersectionObserverId} was not registered.`,
|
|
131
131
|
);
|
|
132
|
-
return;
|
|
132
|
+
return false;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
const targetShadowNode = getShadowNode(target);
|
|
136
136
|
if (targetShadowNode == null) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
);
|
|
140
|
-
return;
|
|
137
|
+
// The target is disconnected. We can't observe it anymore.
|
|
138
|
+
return false;
|
|
141
139
|
}
|
|
142
140
|
|
|
143
141
|
const instanceHandle = getInstanceHandle(target);
|
|
@@ -145,7 +143,7 @@ export function observe({
|
|
|
145
143
|
console.error(
|
|
146
144
|
'IntersectionObserverManager: could not find reference to instance handle from target',
|
|
147
145
|
);
|
|
148
|
-
return;
|
|
146
|
+
return false;
|
|
149
147
|
}
|
|
150
148
|
|
|
151
149
|
// Store the mapping between the instance handle and the target so we can
|
|
@@ -160,11 +158,13 @@ export function observe({
|
|
|
160
158
|
isConnected = true;
|
|
161
159
|
}
|
|
162
160
|
|
|
163
|
-
|
|
161
|
+
NativeIntersectionObserver.observe({
|
|
164
162
|
intersectionObserverId,
|
|
165
163
|
targetShadowNode,
|
|
166
164
|
thresholds: registeredObserver.observer.thresholds,
|
|
167
165
|
});
|
|
166
|
+
|
|
167
|
+
return true;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
export function unobserve(
|
|
@@ -121,13 +121,15 @@ export default class MutationObserver {
|
|
|
121
121
|
MutationObserverManager.unobserve(mutationObserverId, target);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
MutationObserverManager.observe({
|
|
124
|
+
const didStartObserving = MutationObserverManager.observe({
|
|
125
125
|
mutationObserverId,
|
|
126
126
|
target,
|
|
127
127
|
subtree: Boolean(options?.subtree),
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
if (didStartObserving) {
|
|
131
|
+
this._observationTargets.add(target);
|
|
132
|
+
}
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
_unobserve(target: ReactNativeElement): void {
|
|
@@ -43,6 +43,13 @@ const registeredMutationObservers: Map<
|
|
|
43
43
|
$ReadOnly<{observer: MutationObserver, callback: MutationObserverCallback}>,
|
|
44
44
|
> = new Map();
|
|
45
45
|
|
|
46
|
+
// The mapping between ReactNativeElement and their corresponding shadow node
|
|
47
|
+
// needs to be kept here because React removes the link when unmounting.
|
|
48
|
+
const targetToShadowNodeMap: WeakMap<
|
|
49
|
+
ReactNativeElement,
|
|
50
|
+
ReturnType<typeof getShadowNode>,
|
|
51
|
+
> = new WeakMap();
|
|
52
|
+
|
|
46
53
|
/**
|
|
47
54
|
* Registers the given mutation observer and returns a unique ID for it,
|
|
48
55
|
* which is required to start observing targets.
|
|
@@ -85,10 +92,10 @@ export function observe({
|
|
|
85
92
|
mutationObserverId: MutationObserverId,
|
|
86
93
|
target: ReactNativeElement,
|
|
87
94
|
subtree: boolean,
|
|
88
|
-
}):
|
|
95
|
+
}): boolean {
|
|
89
96
|
if (NativeMutationObserver == null) {
|
|
90
97
|
warnNoNativeMutationObserver();
|
|
91
|
-
return;
|
|
98
|
+
return false;
|
|
92
99
|
}
|
|
93
100
|
|
|
94
101
|
const registeredObserver =
|
|
@@ -97,17 +104,17 @@ export function observe({
|
|
|
97
104
|
console.error(
|
|
98
105
|
`MutationObserverManager: could not start observing target because MutationObserver with ID ${mutationObserverId} was not registered.`,
|
|
99
106
|
);
|
|
100
|
-
return;
|
|
107
|
+
return false;
|
|
101
108
|
}
|
|
102
109
|
|
|
103
110
|
const targetShadowNode = getShadowNode(target);
|
|
104
111
|
if (targetShadowNode == null) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
);
|
|
108
|
-
return;
|
|
112
|
+
// The target is disconnected. We can't observe it anymore.
|
|
113
|
+
return false;
|
|
109
114
|
}
|
|
110
115
|
|
|
116
|
+
targetToShadowNodeMap.set(target, targetShadowNode);
|
|
117
|
+
|
|
111
118
|
if (!isConnected) {
|
|
112
119
|
NativeMutationObserver.connect(
|
|
113
120
|
notifyMutationObservers,
|
|
@@ -121,11 +128,13 @@ export function observe({
|
|
|
121
128
|
isConnected = true;
|
|
122
129
|
}
|
|
123
130
|
|
|
124
|
-
|
|
131
|
+
NativeMutationObserver.observe({
|
|
125
132
|
mutationObserverId,
|
|
126
133
|
targetShadowNode,
|
|
127
134
|
subtree,
|
|
128
135
|
});
|
|
136
|
+
|
|
137
|
+
return true;
|
|
129
138
|
}
|
|
130
139
|
|
|
131
140
|
export function unobserve(
|
|
@@ -146,10 +155,10 @@ export function unobserve(
|
|
|
146
155
|
return;
|
|
147
156
|
}
|
|
148
157
|
|
|
149
|
-
const targetShadowNode =
|
|
158
|
+
const targetShadowNode = targetToShadowNodeMap.get(target);
|
|
150
159
|
if (targetShadowNode == null) {
|
|
151
160
|
console.error(
|
|
152
|
-
'MutationObserverManager: could not find
|
|
161
|
+
'MutationObserverManager: could not find registration data for target',
|
|
153
162
|
);
|
|
154
163
|
return;
|
|
155
164
|
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
* @format
|
|
8
|
-
* @flow
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import PlatformBaseViewConfig from '../NativeComponent/PlatformBaseViewConfig';
|
|
12
|
-
import {type ViewConfig} from '../Renderer/shims/ReactNativeTypes';
|
|
13
|
-
|
|
14
|
-
const IGNORED_KEYS = ['transform', 'hitSlop'];
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* The purpose of this function is to validate that the view config that
|
|
18
|
-
* native exposes for a given view manager is the same as the view config
|
|
19
|
-
* that is specified for that view manager in JS.
|
|
20
|
-
*
|
|
21
|
-
* In order to improve perf, we want to avoid calling into native to get
|
|
22
|
-
* the view config when each view manager is used. To do this, we are moving
|
|
23
|
-
* the configs to JS. In the future we will use these JS based view configs
|
|
24
|
-
* to codegen the view manager on native to ensure they stay in sync without
|
|
25
|
-
* this runtime check.
|
|
26
|
-
*
|
|
27
|
-
* If this function fails, that likely means a change was made to the native
|
|
28
|
-
* view manager without updating the JS config as well. Ideally you can make
|
|
29
|
-
* that direct change to the JS config. If you don't know what the differences
|
|
30
|
-
* are, the best approach I've found is to create a view that prints
|
|
31
|
-
* the return value of getNativeComponentAttributes, and then copying that
|
|
32
|
-
* text and pasting it back into JS:
|
|
33
|
-
* <Text selectable={true}>{JSON.stringify(getNativeComponentAttributes('RCTView'))}</Text>
|
|
34
|
-
*
|
|
35
|
-
* This is meant to be a stopgap until the time comes when we only have a
|
|
36
|
-
* single source of truth. I wonder if this message will still be here two
|
|
37
|
-
* years from now...
|
|
38
|
-
*/
|
|
39
|
-
export default function verifyComponentAttributeEquivalence(
|
|
40
|
-
nativeViewConfig: ViewConfig,
|
|
41
|
-
staticViewConfig: ViewConfig,
|
|
42
|
-
) {
|
|
43
|
-
for (const prop of [
|
|
44
|
-
'validAttributes',
|
|
45
|
-
'bubblingEventTypes',
|
|
46
|
-
'directEventTypes',
|
|
47
|
-
]) {
|
|
48
|
-
const diff = Object.keys(
|
|
49
|
-
lefthandObjectDiff(nativeViewConfig[prop], staticViewConfig[prop]),
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
if (diff.length > 0) {
|
|
53
|
-
const name =
|
|
54
|
-
staticViewConfig.uiViewClassName ?? nativeViewConfig.uiViewClassName;
|
|
55
|
-
console.error(
|
|
56
|
-
`'${name}' has a view config that does not match native. ` +
|
|
57
|
-
`'${prop}' is missing: ${diff.join(', ')}`,
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Return the different key-value pairs of the right object, by iterating through the keys in the left object
|
|
64
|
-
// Note it won't return a difference where a key is missing in the left but exists the right.
|
|
65
|
-
function lefthandObjectDiff(leftObj: Object, rightObj: Object): Object {
|
|
66
|
-
const differentKeys: {[string]: any | {...}} = {};
|
|
67
|
-
|
|
68
|
-
function compare(leftItem: any, rightItem: any, key: string) {
|
|
69
|
-
if (typeof leftItem !== typeof rightItem && leftItem != null) {
|
|
70
|
-
differentKeys[key] = rightItem;
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (typeof leftItem === 'object') {
|
|
75
|
-
const objDiff = lefthandObjectDiff(leftItem, rightItem);
|
|
76
|
-
if (Object.keys(objDiff).length > 1) {
|
|
77
|
-
differentKeys[key] = objDiff;
|
|
78
|
-
}
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (leftItem !== rightItem) {
|
|
83
|
-
differentKeys[key] = rightItem;
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
for (const key in leftObj) {
|
|
89
|
-
if (IGNORED_KEYS.includes(key)) {
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (!rightObj) {
|
|
94
|
-
differentKeys[key] = {};
|
|
95
|
-
} else if (leftObj.hasOwnProperty(key)) {
|
|
96
|
-
compare(leftObj[key], rightObj[key], key);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return differentKeys;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function getConfigWithoutViewProps(
|
|
104
|
-
viewConfig: ViewConfig,
|
|
105
|
-
propName: string,
|
|
106
|
-
): {...} {
|
|
107
|
-
// $FlowFixMe[invalid-computed-prop]
|
|
108
|
-
if (!viewConfig[propName]) {
|
|
109
|
-
return {};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
Object.keys(viewConfig[propName])
|
|
114
|
-
// $FlowFixMe[invalid-computed-prop]
|
|
115
|
-
.filter(prop => !PlatformBaseViewConfig[propName][prop])
|
|
116
|
-
.reduce<{[string]: any}>((obj, prop) => {
|
|
117
|
-
// $FlowFixMe[invalid-computed-prop]
|
|
118
|
-
obj[prop] = viewConfig[propName][prop];
|
|
119
|
-
return obj;
|
|
120
|
-
}, {})
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export function stringifyViewConfig(viewConfig: any): string {
|
|
125
|
-
return JSON.stringify(
|
|
126
|
-
viewConfig,
|
|
127
|
-
(key, val) => {
|
|
128
|
-
if (typeof val === 'function') {
|
|
129
|
-
return `ƒ ${val.name}`;
|
|
130
|
-
}
|
|
131
|
-
return val;
|
|
132
|
-
},
|
|
133
|
-
2,
|
|
134
|
-
);
|
|
135
|
-
}
|