@office-iss/react-native-win32 0.0.0-canary.276 → 0.0.0-canary.278
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 +2 -1
- package/CHANGELOG.json +31 -1
- package/CHANGELOG.md +20 -4
- package/Libraries/Animated/NativeAnimatedAllowlist.js +4 -4
- package/Libraries/Animated/animations/Animation.js +13 -1
- package/Libraries/Animated/animations/DecayAnimation.js +1 -0
- package/Libraries/Animated/animations/SpringAnimation.js +1 -0
- package/Libraries/Animated/animations/TimingAnimation.js +1 -0
- package/Libraries/Animated/nodes/AnimatedAddition.js +8 -2
- package/Libraries/Animated/nodes/AnimatedColor.js +4 -1
- package/Libraries/Animated/nodes/AnimatedDiffClamp.js +9 -2
- package/Libraries/Animated/nodes/AnimatedDivision.js +8 -2
- package/Libraries/Animated/nodes/AnimatedInterpolation.js +4 -1
- package/Libraries/Animated/nodes/AnimatedModulo.js +4 -2
- package/Libraries/Animated/nodes/AnimatedMultiplication.js +8 -2
- package/Libraries/Animated/nodes/AnimatedNode.js +25 -0
- package/Libraries/Animated/nodes/AnimatedObject.js +8 -2
- package/Libraries/Animated/nodes/AnimatedProps.js +13 -2
- package/Libraries/Animated/nodes/AnimatedStyle.js +13 -2
- package/Libraries/Animated/nodes/AnimatedSubtraction.js +8 -2
- package/Libraries/Animated/nodes/AnimatedTracking.js +4 -1
- package/Libraries/Animated/nodes/AnimatedTransform.js +4 -1
- package/Libraries/Animated/nodes/AnimatedValue.js +4 -1
- package/Libraries/Animated/nodes/AnimatedValueXY.js +3 -1
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/LayoutAnimation/LayoutAnimation.js +2 -2
- package/Libraries/Network/FormData.js +11 -3
- package/Libraries/Text/Text.d.ts +6 -1
- package/Libraries/Text/TextProps.js +2 -2
- package/Libraries/Text/TextProps.win32.js +2 -2
- package/overrides.json +4 -4
- package/package.json +10 -11
- package/src/private/animated/useAnimatedPropsMemo.js +12 -4
- package/src/private/featureflags/ReactNativeFeatureFlags.js +18 -7
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +3 -2
- package/src/private/webapis/dom/nodes/ReactNativeElement.js +48 -6
- package/src/private/webapis/dom/nodes/ReadOnlyNode.js +3 -1
- package/src/private/webapis/intersectionobserver/IntersectionObserver.js +11 -11
- package/src/private/webapis/intersectionobserver/IntersectionObserverEntry.js +1 -1
- package/src/private/webapis/intersectionobserver/IntersectionObserverManager.js +1 -1
- package/src/private/webapis/intersectionobserver/specs/NativeIntersectionObserver.js +1 -0
- package/src/private/webapis/performance/Performance.js +0 -12
- package/src/private/webapis/performance/specs/NativePerformance.js +0 -11
- package/src-win/Libraries/Text/Text.d.ts +6 -1
- package/Libraries/ReactNative/__mocks__/FabricUIManager.js +0 -334
- package/src/private/webapis/dom/nodes/specs/__mocks__/NativeDOMMock.js +0 -413
- package/src/private/webapis/intersectionobserver/specs/__mocks__/NativeIntersectionObserver.js +0 -181
- package/src/private/webapis/mutationobserver/specs/__mocks__/NativeMutationObserver.js +0 -327
|
@@ -1,413 +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
|
-
* @flow strict-local
|
|
8
|
-
* @format
|
|
9
|
-
* @oncall react_native
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type {
|
|
13
|
-
InternalInstanceHandle,
|
|
14
|
-
Node,
|
|
15
|
-
} from '../../../../../../../Libraries/Renderer/shims/ReactNativeTypes';
|
|
16
|
-
import type {
|
|
17
|
-
MeasureInWindowOnSuccessCallback,
|
|
18
|
-
MeasureLayoutOnSuccessCallback,
|
|
19
|
-
MeasureOnSuccessCallback,
|
|
20
|
-
} from '../NativeDOM';
|
|
21
|
-
import typeof NativeDOM from '../NativeDOM';
|
|
22
|
-
|
|
23
|
-
import {
|
|
24
|
-
ensureHostNode,
|
|
25
|
-
fromNode,
|
|
26
|
-
getAncestorsInCurrentTree,
|
|
27
|
-
getNodeInCurrentTree,
|
|
28
|
-
} from '../../../../../../../Libraries/ReactNative/__mocks__/FabricUIManager';
|
|
29
|
-
|
|
30
|
-
function* dfs(node: ?Node): Iterator<Node> {
|
|
31
|
-
if (node == null) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
yield node;
|
|
36
|
-
|
|
37
|
-
for (const child of fromNode(node).children) {
|
|
38
|
-
yield* dfs(child);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function hasDisplayNone(node: Node): boolean {
|
|
43
|
-
const props = fromNode(node).props;
|
|
44
|
-
// Style is flattened when passed to native, so there's no style object.
|
|
45
|
-
// $FlowFixMe[prop-missing]
|
|
46
|
-
return props != null && props.display === 'none';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const NativeDOMMock: NativeDOM = {
|
|
50
|
-
getBoundingClientRect: jest.fn(
|
|
51
|
-
(
|
|
52
|
-
node: Node,
|
|
53
|
-
includeTransform: boolean,
|
|
54
|
-
): [
|
|
55
|
-
/* x:*/ number,
|
|
56
|
-
/* y:*/ number,
|
|
57
|
-
/* width:*/ number,
|
|
58
|
-
/* height:*/ number,
|
|
59
|
-
] => {
|
|
60
|
-
ensureHostNode(node);
|
|
61
|
-
|
|
62
|
-
const nodeInCurrentTree = getNodeInCurrentTree(node);
|
|
63
|
-
const currentProps =
|
|
64
|
-
nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null;
|
|
65
|
-
if (currentProps == null) {
|
|
66
|
-
return [0, 0, 0, 0];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const boundingClientRectForTests: ?{
|
|
70
|
-
x: number,
|
|
71
|
-
y: number,
|
|
72
|
-
width: number,
|
|
73
|
-
height: number,
|
|
74
|
-
} =
|
|
75
|
-
// $FlowExpectedError[prop-missing]
|
|
76
|
-
currentProps.__boundingClientRectForTests;
|
|
77
|
-
|
|
78
|
-
if (boundingClientRectForTests == null) {
|
|
79
|
-
return [0, 0, 0, 0];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const {x, y, width, height} = boundingClientRectForTests;
|
|
83
|
-
return [x, y, width, height];
|
|
84
|
-
},
|
|
85
|
-
),
|
|
86
|
-
|
|
87
|
-
hasPointerCapture: jest.fn((node: Node, pointerId: number): boolean => false),
|
|
88
|
-
|
|
89
|
-
setPointerCapture: jest.fn((node: Node, pointerId: number): void => {}),
|
|
90
|
-
|
|
91
|
-
releasePointerCapture: jest.fn((node: Node, pointerId: number): void => {}),
|
|
92
|
-
|
|
93
|
-
getParentNode: jest.fn((node: Node): ?InternalInstanceHandle => {
|
|
94
|
-
const ancestors = getAncestorsInCurrentTree(node);
|
|
95
|
-
if (ancestors == null || ancestors.length - 2 < 0) {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const [parentOfParent, position] = ancestors[ancestors.length - 2];
|
|
100
|
-
const parentInCurrentTree = fromNode(parentOfParent).children[position];
|
|
101
|
-
return fromNode(parentInCurrentTree).instanceHandle;
|
|
102
|
-
}),
|
|
103
|
-
|
|
104
|
-
getChildNodes: jest.fn(
|
|
105
|
-
(node: Node): $ReadOnlyArray<InternalInstanceHandle> => {
|
|
106
|
-
const nodeInCurrentTree = getNodeInCurrentTree(node);
|
|
107
|
-
|
|
108
|
-
if (nodeInCurrentTree == null) {
|
|
109
|
-
return [];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return fromNode(nodeInCurrentTree).children.map(
|
|
113
|
-
child => fromNode(child).instanceHandle,
|
|
114
|
-
);
|
|
115
|
-
},
|
|
116
|
-
),
|
|
117
|
-
|
|
118
|
-
isConnected: jest.fn((node: Node): boolean => {
|
|
119
|
-
return getNodeInCurrentTree(node) != null;
|
|
120
|
-
}),
|
|
121
|
-
|
|
122
|
-
getTextContent: jest.fn((node: Node): string => {
|
|
123
|
-
const nodeInCurrentTree = getNodeInCurrentTree(node);
|
|
124
|
-
|
|
125
|
-
let result = '';
|
|
126
|
-
|
|
127
|
-
if (nodeInCurrentTree == null) {
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
for (const childNode of dfs(nodeInCurrentTree)) {
|
|
132
|
-
if (fromNode(childNode).viewName === 'RCTRawText') {
|
|
133
|
-
const props = fromNode(childNode).props;
|
|
134
|
-
// $FlowExpectedError[prop-missing]
|
|
135
|
-
const maybeString: ?string = props.text;
|
|
136
|
-
if (typeof maybeString === 'string') {
|
|
137
|
-
result += maybeString;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return result;
|
|
142
|
-
}),
|
|
143
|
-
|
|
144
|
-
compareDocumentPosition: jest.fn((node: Node, otherNode: Node): number => {
|
|
145
|
-
/* eslint-disable no-bitwise */
|
|
146
|
-
const ReadOnlyNode = require('../../ReadOnlyNode').default;
|
|
147
|
-
|
|
148
|
-
// Quick check for node vs. itself
|
|
149
|
-
if (fromNode(node).reactTag === fromNode(otherNode).reactTag) {
|
|
150
|
-
return 0;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (fromNode(node).rootTag !== fromNode(otherNode).rootTag) {
|
|
154
|
-
return ReadOnlyNode.DOCUMENT_POSITION_DISCONNECTED;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const ancestors = getAncestorsInCurrentTree(node);
|
|
158
|
-
if (ancestors == null) {
|
|
159
|
-
return ReadOnlyNode.DOCUMENT_POSITION_DISCONNECTED;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const otherAncestors = getAncestorsInCurrentTree(otherNode);
|
|
163
|
-
if (otherAncestors == null) {
|
|
164
|
-
return ReadOnlyNode.DOCUMENT_POSITION_DISCONNECTED;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Consume all common ancestors
|
|
168
|
-
let i = 0;
|
|
169
|
-
while (
|
|
170
|
-
i < ancestors.length &&
|
|
171
|
-
i < otherAncestors.length &&
|
|
172
|
-
ancestors[i][1] === otherAncestors[i][1]
|
|
173
|
-
) {
|
|
174
|
-
i++;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (i === ancestors.length) {
|
|
178
|
-
return (
|
|
179
|
-
ReadOnlyNode.DOCUMENT_POSITION_CONTAINED_BY |
|
|
180
|
-
ReadOnlyNode.DOCUMENT_POSITION_FOLLOWING
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (i === otherAncestors.length) {
|
|
185
|
-
return (
|
|
186
|
-
ReadOnlyNode.DOCUMENT_POSITION_CONTAINS |
|
|
187
|
-
ReadOnlyNode.DOCUMENT_POSITION_PRECEDING
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (ancestors[i][1] > otherAncestors[i][1]) {
|
|
192
|
-
return ReadOnlyNode.DOCUMENT_POSITION_PRECEDING;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return ReadOnlyNode.DOCUMENT_POSITION_FOLLOWING;
|
|
196
|
-
}),
|
|
197
|
-
|
|
198
|
-
getOffset: jest.fn(
|
|
199
|
-
(
|
|
200
|
-
node: Node,
|
|
201
|
-
): [
|
|
202
|
-
/* offsetParent: */ ?InternalInstanceHandle,
|
|
203
|
-
/* offsetTop: */ number,
|
|
204
|
-
/* offsetLeft: */ number,
|
|
205
|
-
] => {
|
|
206
|
-
const ancestors = getAncestorsInCurrentTree(node);
|
|
207
|
-
if (ancestors == null) {
|
|
208
|
-
return [null, 0, 0];
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const [parent, position] = ancestors[ancestors.length - 1];
|
|
212
|
-
const nodeInCurrentTree = fromNode(parent).children[position];
|
|
213
|
-
|
|
214
|
-
const currentProps =
|
|
215
|
-
nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null;
|
|
216
|
-
if (currentProps == null || hasDisplayNone(nodeInCurrentTree)) {
|
|
217
|
-
return [null, 0, 0];
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const offsetForTests: ?{
|
|
221
|
-
top: number,
|
|
222
|
-
left: number,
|
|
223
|
-
} =
|
|
224
|
-
// $FlowExpectedError[prop-missing]
|
|
225
|
-
currentProps.__offsetForTests;
|
|
226
|
-
|
|
227
|
-
if (offsetForTests == null) {
|
|
228
|
-
return [null, 0, 0];
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
let currentIndex = ancestors.length - 1;
|
|
232
|
-
while (currentIndex >= 0 && !hasDisplayNone(ancestors[currentIndex][0])) {
|
|
233
|
-
currentIndex--;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (currentIndex >= 0) {
|
|
237
|
-
// The node or one of its ancestors have display: none
|
|
238
|
-
return [null, 0, 0];
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return [
|
|
242
|
-
fromNode(parent).instanceHandle,
|
|
243
|
-
offsetForTests.top,
|
|
244
|
-
offsetForTests.left,
|
|
245
|
-
];
|
|
246
|
-
},
|
|
247
|
-
),
|
|
248
|
-
|
|
249
|
-
getScrollPosition: jest.fn(
|
|
250
|
-
(node: Node): [/* scrollLeft: */ number, /* scrollTop: */ number] => {
|
|
251
|
-
ensureHostNode(node);
|
|
252
|
-
|
|
253
|
-
const nodeInCurrentTree = getNodeInCurrentTree(node);
|
|
254
|
-
const currentProps =
|
|
255
|
-
nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null;
|
|
256
|
-
if (currentProps == null) {
|
|
257
|
-
return [0, 0];
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const scrollForTests: ?{
|
|
261
|
-
scrollLeft: number,
|
|
262
|
-
scrollTop: number,
|
|
263
|
-
...
|
|
264
|
-
} =
|
|
265
|
-
// $FlowExpectedError[prop-missing]
|
|
266
|
-
currentProps.__scrollForTests;
|
|
267
|
-
|
|
268
|
-
if (scrollForTests == null) {
|
|
269
|
-
return [0, 0];
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const {scrollLeft, scrollTop} = scrollForTests;
|
|
273
|
-
return [scrollLeft, scrollTop];
|
|
274
|
-
},
|
|
275
|
-
),
|
|
276
|
-
|
|
277
|
-
getScrollSize: jest.fn(
|
|
278
|
-
(node: Node): [/* scrollLeft: */ number, /* scrollTop: */ number] => {
|
|
279
|
-
ensureHostNode(node);
|
|
280
|
-
|
|
281
|
-
const nodeInCurrentTree = getNodeInCurrentTree(node);
|
|
282
|
-
const currentProps =
|
|
283
|
-
nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null;
|
|
284
|
-
if (currentProps == null) {
|
|
285
|
-
return [0, 0];
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const scrollForTests: ?{
|
|
289
|
-
scrollWidth: number,
|
|
290
|
-
scrollHeight: number,
|
|
291
|
-
...
|
|
292
|
-
} =
|
|
293
|
-
// $FlowExpectedError[prop-missing]
|
|
294
|
-
currentProps.__scrollForTests;
|
|
295
|
-
|
|
296
|
-
if (scrollForTests == null) {
|
|
297
|
-
return [0, 0];
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const {scrollWidth, scrollHeight} = scrollForTests;
|
|
301
|
-
return [scrollWidth, scrollHeight];
|
|
302
|
-
},
|
|
303
|
-
),
|
|
304
|
-
|
|
305
|
-
getInnerSize: jest.fn(
|
|
306
|
-
(node: Node): [/* width: */ number, /* height: */ number] => {
|
|
307
|
-
ensureHostNode(node);
|
|
308
|
-
|
|
309
|
-
const nodeInCurrentTree = getNodeInCurrentTree(node);
|
|
310
|
-
const currentProps =
|
|
311
|
-
nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null;
|
|
312
|
-
if (currentProps == null) {
|
|
313
|
-
return [0, 0];
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
const innerSizeForTests: ?{
|
|
317
|
-
width: number,
|
|
318
|
-
height: number,
|
|
319
|
-
...
|
|
320
|
-
} =
|
|
321
|
-
// $FlowExpectedError[prop-missing]
|
|
322
|
-
currentProps.__innerSizeForTests;
|
|
323
|
-
|
|
324
|
-
if (innerSizeForTests == null) {
|
|
325
|
-
return [0, 0];
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const {width, height} = innerSizeForTests;
|
|
329
|
-
return [width, height];
|
|
330
|
-
},
|
|
331
|
-
),
|
|
332
|
-
|
|
333
|
-
getBorderWidth: jest.fn(
|
|
334
|
-
(
|
|
335
|
-
node: Node,
|
|
336
|
-
): [
|
|
337
|
-
/* topWidth: */ number,
|
|
338
|
-
/* rightWidth: */ number,
|
|
339
|
-
/* bottomWidth: */ number,
|
|
340
|
-
/* leftWidth: */ number,
|
|
341
|
-
] => {
|
|
342
|
-
ensureHostNode(node);
|
|
343
|
-
|
|
344
|
-
const nodeInCurrentTree = getNodeInCurrentTree(node);
|
|
345
|
-
const currentProps =
|
|
346
|
-
nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null;
|
|
347
|
-
if (currentProps == null) {
|
|
348
|
-
return [0, 0, 0, 0];
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
const borderSizeForTests: ?{
|
|
352
|
-
topWidth?: number,
|
|
353
|
-
rightWidth?: number,
|
|
354
|
-
bottomWidth?: number,
|
|
355
|
-
leftWidth?: number,
|
|
356
|
-
...
|
|
357
|
-
} =
|
|
358
|
-
// $FlowExpectedError[prop-missing]
|
|
359
|
-
currentProps.__borderSizeForTests;
|
|
360
|
-
|
|
361
|
-
if (borderSizeForTests == null) {
|
|
362
|
-
return [0, 0, 0, 0];
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const {
|
|
366
|
-
topWidth = 0,
|
|
367
|
-
rightWidth = 0,
|
|
368
|
-
bottomWidth = 0,
|
|
369
|
-
leftWidth = 0,
|
|
370
|
-
} = borderSizeForTests;
|
|
371
|
-
return [topWidth, rightWidth, bottomWidth, leftWidth];
|
|
372
|
-
},
|
|
373
|
-
),
|
|
374
|
-
|
|
375
|
-
getTagName: jest.fn((node: Node): string => {
|
|
376
|
-
ensureHostNode(node);
|
|
377
|
-
return 'RN:' + fromNode(node).viewName;
|
|
378
|
-
}),
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Legacy layout APIs
|
|
382
|
-
*/
|
|
383
|
-
|
|
384
|
-
measure: jest.fn((node: Node, callback: MeasureOnSuccessCallback): void => {
|
|
385
|
-
ensureHostNode(node);
|
|
386
|
-
|
|
387
|
-
callback(10, 10, 100, 100, 0, 0);
|
|
388
|
-
}),
|
|
389
|
-
|
|
390
|
-
measureInWindow: jest.fn(
|
|
391
|
-
(node: Node, callback: MeasureInWindowOnSuccessCallback): void => {
|
|
392
|
-
ensureHostNode(node);
|
|
393
|
-
|
|
394
|
-
callback(10, 10, 100, 100);
|
|
395
|
-
},
|
|
396
|
-
),
|
|
397
|
-
|
|
398
|
-
measureLayout: jest.fn(
|
|
399
|
-
(
|
|
400
|
-
node: Node,
|
|
401
|
-
relativeNode: Node,
|
|
402
|
-
onFail: () => void,
|
|
403
|
-
onSuccess: MeasureLayoutOnSuccessCallback,
|
|
404
|
-
): void => {
|
|
405
|
-
ensureHostNode(node);
|
|
406
|
-
ensureHostNode(relativeNode);
|
|
407
|
-
|
|
408
|
-
onSuccess(1, 1, 100, 100);
|
|
409
|
-
},
|
|
410
|
-
),
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
export default NativeDOMMock;
|
package/src/private/webapis/intersectionobserver/specs/__mocks__/NativeIntersectionObserver.js
DELETED
|
@@ -1,181 +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
|
-
* @flow strict-local
|
|
8
|
-
* @format
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type ReactNativeElement from '../../../dom/nodes/ReactNativeElement';
|
|
12
|
-
import type IntersectionObserver from '../../IntersectionObserver';
|
|
13
|
-
import type {
|
|
14
|
-
NativeIntersectionObserverEntry,
|
|
15
|
-
NativeIntersectionObserverObserveOptions,
|
|
16
|
-
Spec,
|
|
17
|
-
} from '../NativeIntersectionObserver';
|
|
18
|
-
|
|
19
|
-
import {getFabricUIManager} from '../../../../../../Libraries/ReactNative/__mocks__/FabricUIManager';
|
|
20
|
-
import {getShadowNode} from '../../../dom/nodes/ReadOnlyNode';
|
|
21
|
-
import invariant from 'invariant';
|
|
22
|
-
import nullthrows from 'nullthrows';
|
|
23
|
-
|
|
24
|
-
type ObserverState = {
|
|
25
|
-
thresholds: $ReadOnlyArray<number>,
|
|
26
|
-
rootThresholds?: ?$ReadOnlyArray<number>,
|
|
27
|
-
intersecting: boolean,
|
|
28
|
-
currentThreshold: ?number,
|
|
29
|
-
currentRootThreshold: ?number,
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
type Observation = {
|
|
33
|
-
...NativeIntersectionObserverObserveOptions,
|
|
34
|
-
state: ObserverState,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
let pendingRecords: Array<NativeIntersectionObserverEntry> = [];
|
|
38
|
-
let callback: ?() => void;
|
|
39
|
-
let observations: Array<Observation> = [];
|
|
40
|
-
|
|
41
|
-
const FabricUIManagerMock = nullthrows(getFabricUIManager());
|
|
42
|
-
|
|
43
|
-
function createRecordFromObservation(
|
|
44
|
-
observation: Observation,
|
|
45
|
-
): NativeIntersectionObserverEntry {
|
|
46
|
-
return {
|
|
47
|
-
intersectionObserverId: observation.intersectionObserverId,
|
|
48
|
-
targetInstanceHandle: FabricUIManagerMock.__getInstanceHandleFromNode(
|
|
49
|
-
// $FlowExpectedError[incompatible-call]
|
|
50
|
-
observation.targetShadowNode,
|
|
51
|
-
),
|
|
52
|
-
targetRect: observation.state.intersecting ? [0, 0, 1, 1] : [20, 20, 1, 1],
|
|
53
|
-
rootRect: [0, 0, 10, 10],
|
|
54
|
-
intersectionRect: observation.state.intersecting ? [0, 0, 1, 1] : null,
|
|
55
|
-
isIntersectingAboveThresholds: observation.state.intersecting,
|
|
56
|
-
time: performance.now(),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function notifyIntersectionObservers(): void {
|
|
61
|
-
callback?.();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const NativeIntersectionObserverMock = {
|
|
65
|
-
observe: (options: NativeIntersectionObserverObserveOptions): void => {
|
|
66
|
-
invariant(
|
|
67
|
-
observations.find(
|
|
68
|
-
observation =>
|
|
69
|
-
observation.intersectionObserverId ===
|
|
70
|
-
options.intersectionObserverId &&
|
|
71
|
-
observation.targetShadowNode === options.targetShadowNode,
|
|
72
|
-
) == null,
|
|
73
|
-
'unexpected duplicate call to observe',
|
|
74
|
-
);
|
|
75
|
-
const observation = {
|
|
76
|
-
...options,
|
|
77
|
-
state: {
|
|
78
|
-
thresholds: options.thresholds,
|
|
79
|
-
rootThresholds: options.rootThresholds,
|
|
80
|
-
intersecting: false,
|
|
81
|
-
currentThreshold: null,
|
|
82
|
-
currentRootThreshold: null,
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
observations.push(observation);
|
|
86
|
-
pendingRecords.push(createRecordFromObservation(observation));
|
|
87
|
-
setImmediate(notifyIntersectionObservers);
|
|
88
|
-
},
|
|
89
|
-
unobserve: (
|
|
90
|
-
intersectionObserverId: number,
|
|
91
|
-
targetShadowNode: mixed,
|
|
92
|
-
): void => {
|
|
93
|
-
const observationIndex = observations.findIndex(
|
|
94
|
-
observation =>
|
|
95
|
-
observation.intersectionObserverId === intersectionObserverId &&
|
|
96
|
-
observation.targetShadowNode === targetShadowNode,
|
|
97
|
-
);
|
|
98
|
-
invariant(
|
|
99
|
-
observationIndex !== -1,
|
|
100
|
-
'unexpected duplicate call to unobserve',
|
|
101
|
-
);
|
|
102
|
-
observations.splice(observationIndex, 1);
|
|
103
|
-
|
|
104
|
-
pendingRecords = pendingRecords.filter(
|
|
105
|
-
record =>
|
|
106
|
-
record.intersectionObserverId !== intersectionObserverId ||
|
|
107
|
-
record.targetInstanceHandle !==
|
|
108
|
-
FabricUIManagerMock.__getInstanceHandleFromNode(
|
|
109
|
-
// $FlowExpectedError[incompatible-call]
|
|
110
|
-
targetShadowNode,
|
|
111
|
-
),
|
|
112
|
-
);
|
|
113
|
-
},
|
|
114
|
-
connect: (notifyIntersectionObserversCallback: () => void): void => {
|
|
115
|
-
invariant(callback == null, 'unexpected call to connect');
|
|
116
|
-
invariant(
|
|
117
|
-
notifyIntersectionObserversCallback != null,
|
|
118
|
-
'unexpected null notify intersection observers callback',
|
|
119
|
-
);
|
|
120
|
-
callback = notifyIntersectionObserversCallback;
|
|
121
|
-
},
|
|
122
|
-
disconnect: (): void => {
|
|
123
|
-
invariant(callback != null, 'unexpected call to disconnect');
|
|
124
|
-
callback = null;
|
|
125
|
-
},
|
|
126
|
-
takeRecords: (): $ReadOnlyArray<NativeIntersectionObserverEntry> => {
|
|
127
|
-
const currentRecords = pendingRecords;
|
|
128
|
-
pendingRecords = [];
|
|
129
|
-
return currentRecords;
|
|
130
|
-
},
|
|
131
|
-
__forceTransitionForTests: (
|
|
132
|
-
observer: IntersectionObserver,
|
|
133
|
-
target: ReactNativeElement,
|
|
134
|
-
) => {
|
|
135
|
-
const targetShadowNode = getShadowNode(target);
|
|
136
|
-
const observation = observations.find(
|
|
137
|
-
obs =>
|
|
138
|
-
obs.intersectionObserverId === observer.__getObserverID() &&
|
|
139
|
-
obs.targetShadowNode === targetShadowNode,
|
|
140
|
-
);
|
|
141
|
-
invariant(
|
|
142
|
-
observation != null,
|
|
143
|
-
'cannot force transition on an unobserved target',
|
|
144
|
-
);
|
|
145
|
-
if (observation.state.intersecting) {
|
|
146
|
-
observation.state.intersecting = false;
|
|
147
|
-
observation.state.currentThreshold = null;
|
|
148
|
-
observation.state.currentRootThreshold = null;
|
|
149
|
-
} else {
|
|
150
|
-
observation.state.intersecting = true;
|
|
151
|
-
observation.state.currentThreshold = observation.thresholds[0];
|
|
152
|
-
observation.state.currentRootThreshold =
|
|
153
|
-
observation.rootThresholds != null
|
|
154
|
-
? observation.rootThresholds[0]
|
|
155
|
-
: null;
|
|
156
|
-
}
|
|
157
|
-
pendingRecords.push(createRecordFromObservation(observation));
|
|
158
|
-
setImmediate(notifyIntersectionObservers);
|
|
159
|
-
},
|
|
160
|
-
__getObservationsForTests: (
|
|
161
|
-
observer: IntersectionObserver,
|
|
162
|
-
): Array<{targetShadowNode: mixed, thresholds: $ReadOnlyArray<number>}> => {
|
|
163
|
-
const intersectionObserverId = observer.__getObserverID();
|
|
164
|
-
return observations
|
|
165
|
-
.filter(
|
|
166
|
-
observation =>
|
|
167
|
-
observation.intersectionObserverId === intersectionObserverId,
|
|
168
|
-
)
|
|
169
|
-
.map(observation => ({
|
|
170
|
-
targetShadowNode: observation.targetShadowNode,
|
|
171
|
-
thresholds: observation.thresholds,
|
|
172
|
-
}));
|
|
173
|
-
},
|
|
174
|
-
__isConnected: (): boolean => {
|
|
175
|
-
return callback != null;
|
|
176
|
-
},
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
(NativeIntersectionObserverMock: Spec);
|
|
180
|
-
|
|
181
|
-
export default NativeIntersectionObserverMock;
|