react-native-windows 0.77.0-preview.1 → 0.77.0-preview.3

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.
@@ -1,356 +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 AnimatedProps from '../../../Libraries/Animated/nodes/AnimatedProps';
13
- import type {AnimatedPropsAllowlist} from '../../../Libraries/Animated/nodes/AnimatedProps';
14
- import type {AnimatedStyleAllowlist} from '../../../Libraries/Animated/nodes/AnimatedStyle';
15
-
16
- import {AnimatedEvent} from '../../../Libraries/Animated/AnimatedEvent';
17
- import AnimatedNode from '../../../Libraries/Animated/nodes/AnimatedNode';
18
- import {isPlainObject} from '../../../Libraries/Animated/nodes/AnimatedObject';
19
- import flattenStyle from '../../../Libraries/StyleSheet/flattenStyle';
20
- import nullthrows from 'nullthrows';
21
- import {useMemo, useState} from 'react';
22
-
23
- type CompositeKey = {
24
- style?: {[string]: CompositeKeyComponent},
25
- [string]:
26
- | CompositeKeyComponent
27
- | AnimatedEvent
28
- | $ReadOnlyArray<mixed>
29
- | $ReadOnly<{[string]: mixed}>,
30
- };
31
-
32
- type CompositeKeyComponent =
33
- | AnimatedNode
34
- | Array<CompositeKeyComponent | null>
35
- | {[string]: CompositeKeyComponent};
36
-
37
- type $ReadOnlyCompositeKey = $ReadOnly<{
38
- style?: $ReadOnly<{[string]: CompositeKeyComponent}>,
39
- [string]:
40
- | $ReadOnlyCompositeKeyComponent
41
- | AnimatedEvent
42
- | $ReadOnlyArray<mixed>
43
- | $ReadOnly<{[string]: mixed}>,
44
- }>;
45
-
46
- type $ReadOnlyCompositeKeyComponent =
47
- | AnimatedNode
48
- | $ReadOnlyArray<$ReadOnlyCompositeKeyComponent | null>
49
- | $ReadOnly<{[string]: $ReadOnlyCompositeKeyComponent}>;
50
-
51
- /**
52
- * A hook that returns an `AnimatedProps` object that is memoized based on the
53
- * subset of `props` that are instances of `AnimatedNode` or `AnimatedEvent`.
54
- */
55
- export function useAnimatedPropsMemo(
56
- create: () => AnimatedProps,
57
- // TODO: Make this two separate arguments after the experiment is over. This
58
- // is only an array-like structure to make it easier to experiment with this
59
- // and `useMemo`.
60
- [allowlist, props]: [?AnimatedPropsAllowlist, {[string]: mixed}],
61
- ): AnimatedProps {
62
- const compositeKey = useMemo(
63
- () => createCompositeKeyForProps(props, allowlist),
64
- [allowlist, props],
65
- );
66
-
67
- const [state, setState] = useState<{
68
- allowlist: ?AnimatedPropsAllowlist,
69
- compositeKey: $ReadOnlyCompositeKey | null,
70
- value: AnimatedProps,
71
- }>(() => ({
72
- allowlist,
73
- compositeKey,
74
- value: create(),
75
- }));
76
-
77
- if (
78
- state.allowlist !== allowlist ||
79
- !areCompositeKeysEqual(state.compositeKey, compositeKey)
80
- ) {
81
- setState({
82
- allowlist,
83
- compositeKey,
84
- value: create(),
85
- });
86
- }
87
- return state.value;
88
- }
89
-
90
- /**
91
- * Creates a new composite key for a `props` object that can be used to detect
92
- * whether a new `AnimatedProps` instance must be created.
93
- *
94
- * - With an allowlist, those props are searched for `AnimatedNode` instances.
95
- * - Without an allowlist, `style` is searched for `AnimatedNode` instances,
96
- * but all other objects and arrays are included (not searched). We do not
97
- * search objects and arrays without an allowlist in case they are very large
98
- * data structures. We safely traverse `style` becuase it is bounded.
99
- *
100
- * Any `AnimatedEvent` instances at the first depth are always included.
101
- *
102
- * If `props` contains no `AnimatedNode` or `AnimatedEvent` instances, this
103
- * returns null.
104
- */
105
- export function createCompositeKeyForProps(
106
- props: $ReadOnly<{[string]: mixed}>,
107
- allowlist: ?AnimatedPropsAllowlist,
108
- ): $ReadOnlyCompositeKey | null {
109
- let compositeKey: CompositeKey | null = null;
110
-
111
- const keys = Object.keys(props);
112
- for (let ii = 0, length = keys.length; ii < length; ii++) {
113
- const key = keys[ii];
114
- const value = props[key];
115
-
116
- if (allowlist == null || hasOwn(allowlist, key)) {
117
- let compositeKeyComponent;
118
- if (key === 'style') {
119
- // $FlowFixMe[incompatible-call] - `style` is a valid argument.
120
- // $FlowFixMe[incompatible-type] - `flattenStyle` returns an object.
121
- const flatStyle: ?{[string]: mixed} = flattenStyle(value);
122
- if (flatStyle != null) {
123
- compositeKeyComponent = createCompositeKeyForObject(
124
- flatStyle,
125
- allowlist?.style,
126
- );
127
- }
128
- } else if (
129
- value instanceof AnimatedNode ||
130
- value instanceof AnimatedEvent
131
- ) {
132
- compositeKeyComponent = value;
133
- } else if (Array.isArray(value)) {
134
- compositeKeyComponent =
135
- allowlist == null ? value : createCompositeKeyForArray(value);
136
- } else if (isPlainObject(value)) {
137
- compositeKeyComponent =
138
- allowlist == null ? value : createCompositeKeyForObject(value);
139
- }
140
- if (compositeKeyComponent != null) {
141
- if (compositeKey == null) {
142
- compositeKey = {} as CompositeKey;
143
- }
144
- compositeKey[key] = compositeKeyComponent;
145
- }
146
- }
147
- }
148
-
149
- return compositeKey;
150
- }
151
-
152
- /**
153
- * Creates a new composite key for an array that retains all values that are or
154
- * contain `AnimatedNode` instances, and `null` for the rest.
155
- *
156
- * If `array` contains no `AnimatedNode` instances, this returns null.
157
- */
158
- function createCompositeKeyForArray(
159
- array: $ReadOnlyArray<mixed>,
160
- ): $ReadOnlyArray<$ReadOnlyCompositeKeyComponent | null> | null {
161
- let compositeKey: Array<$ReadOnlyCompositeKeyComponent | null> | null = null;
162
-
163
- for (let ii = 0, length = array.length; ii < length; ii++) {
164
- const value = array[ii];
165
-
166
- let compositeKeyComponent;
167
- if (value instanceof AnimatedNode) {
168
- compositeKeyComponent = value;
169
- } else if (Array.isArray(value)) {
170
- compositeKeyComponent = createCompositeKeyForArray(value);
171
- } else if (isPlainObject(value)) {
172
- compositeKeyComponent = createCompositeKeyForObject(value);
173
- }
174
- if (compositeKeyComponent != null) {
175
- if (compositeKey == null) {
176
- compositeKey = new Array<$ReadOnlyCompositeKeyComponent | null>(
177
- array.length,
178
- ).fill(null);
179
- }
180
- compositeKey[ii] = compositeKeyComponent;
181
- }
182
- }
183
-
184
- return compositeKey;
185
- }
186
-
187
- /**
188
- * Creates a new composite key for an object that retains only properties that
189
- * are or contain `AnimatedNode` instances.
190
- *
191
- * When used to create composite keys for `style` props:
192
- *
193
- * - With an allowlist, those properties are searched.
194
- * - Without an allowlist, every property is searched.
195
- *
196
- * If `object` contains no `AnimatedNode` instances, this returns null.
197
- */
198
- function createCompositeKeyForObject(
199
- object: $ReadOnly<{[string]: mixed}>,
200
- allowlist?: ?AnimatedStyleAllowlist,
201
- ): $ReadOnly<{[string]: $ReadOnlyCompositeKeyComponent}> | null {
202
- let compositeKey: {[string]: $ReadOnlyCompositeKeyComponent} | null = null;
203
-
204
- const keys = Object.keys(object);
205
- for (let ii = 0, length = keys.length; ii < length; ii++) {
206
- const key = keys[ii];
207
-
208
- if (allowlist == null || hasOwn(allowlist, key)) {
209
- const value = object[key];
210
-
211
- let compositeKeyComponent;
212
- if (value instanceof AnimatedNode) {
213
- compositeKeyComponent = value;
214
- } else if (Array.isArray(value)) {
215
- compositeKeyComponent = createCompositeKeyForArray(value);
216
- } else if (isPlainObject(value)) {
217
- compositeKeyComponent = createCompositeKeyForObject(value);
218
- }
219
- if (compositeKeyComponent != null) {
220
- if (compositeKey == null) {
221
- compositeKey = {} as {[string]: $ReadOnlyCompositeKeyComponent};
222
- }
223
- compositeKey[key] = compositeKeyComponent;
224
- }
225
- }
226
- }
227
-
228
- return compositeKey;
229
- }
230
-
231
- export function areCompositeKeysEqual(
232
- maybePrev: $ReadOnlyCompositeKey | null,
233
- maybeNext: $ReadOnlyCompositeKey | null,
234
- allowlist: ?AnimatedPropsAllowlist,
235
- ): boolean {
236
- if (maybePrev === maybeNext) {
237
- return true;
238
- }
239
- if (maybePrev === null || maybeNext === null) {
240
- return false;
241
- }
242
- // Help Flow retain the type refinements of these.
243
- const prev = maybePrev;
244
- const next = maybeNext;
245
-
246
- const keys = Object.keys(prev);
247
- const length = keys.length;
248
- if (length !== Object.keys(next).length) {
249
- return false;
250
- }
251
- for (let ii = 0; ii < length; ii++) {
252
- const key = keys[ii];
253
- if (!hasOwn(next, key)) {
254
- return false;
255
- }
256
- const prevComponent = prev[key];
257
- const nextComponent = next[key];
258
-
259
- if (key === 'style') {
260
- // We know style components are objects with non-mixed values.
261
- if (
262
- !areCompositeKeyComponentsEqual(
263
- // $FlowIgnore[incompatible-cast]
264
- prevComponent as $ReadOnlyCompositeKeyComponent,
265
- // $FlowIgnore[incompatible-cast]
266
- nextComponent as $ReadOnlyCompositeKeyComponent,
267
- )
268
- ) {
269
- return false;
270
- }
271
- } else if (
272
- prevComponent instanceof AnimatedNode ||
273
- prevComponent instanceof AnimatedEvent
274
- ) {
275
- if (prevComponent !== nextComponent) {
276
- return false;
277
- }
278
- } else {
279
- // When `allowlist` is null, the components must be the same. Otherwise,
280
- // we created the components using deep traversal, so deep compare them.
281
- if (allowlist == null) {
282
- if (prevComponent !== nextComponent) {
283
- return false;
284
- }
285
- } else {
286
- if (
287
- !areCompositeKeyComponentsEqual(
288
- // $FlowIgnore[incompatible-cast]
289
- prevComponent as $ReadOnlyCompositeKeyComponent,
290
- // $FlowIgnore[incompatible-cast]
291
- nextComponent as $ReadOnlyCompositeKeyComponent,
292
- )
293
- ) {
294
- return false;
295
- }
296
- }
297
- }
298
- }
299
- return true;
300
- }
301
-
302
- function areCompositeKeyComponentsEqual(
303
- prev: $ReadOnlyCompositeKeyComponent | null,
304
- next: $ReadOnlyCompositeKeyComponent | null,
305
- ): boolean {
306
- if (prev === next) {
307
- return true;
308
- }
309
- if (prev instanceof AnimatedNode) {
310
- return prev === next;
311
- }
312
- if (Array.isArray(prev)) {
313
- if (!Array.isArray(next)) {
314
- return false;
315
- }
316
- const length = prev.length;
317
- if (length !== next.length) {
318
- return false;
319
- }
320
- for (let ii = 0; ii < length; ii++) {
321
- if (!areCompositeKeyComponentsEqual(prev[ii], next[ii])) {
322
- return false;
323
- }
324
- }
325
- return true;
326
- }
327
- if (isPlainObject(prev)) {
328
- if (!isPlainObject(next)) {
329
- return false;
330
- }
331
- const keys = Object.keys(prev);
332
- const length = keys.length;
333
- if (length !== Object.keys(next).length) {
334
- return false;
335
- }
336
- for (let ii = 0; ii < length; ii++) {
337
- const key = keys[ii];
338
- if (
339
- !hasOwn(nullthrows(next), key) ||
340
- !areCompositeKeyComponentsEqual(prev[key], next[key])
341
- ) {
342
- return false;
343
- }
344
- }
345
- return true;
346
- }
347
- return false;
348
- }
349
-
350
- // Supported versions of JSC do not implement the newer Object.hasOwn. Remove
351
- // this shim when they do.
352
- // $FlowIgnore[method-unbinding]
353
- const _hasOwnProp = Object.prototype.hasOwnProperty;
354
- const hasOwn: (obj: $ReadOnly<{...}>, prop: string) => boolean =
355
- // $FlowIgnore[method-unbinding]
356
- Object.hasOwn ?? ((obj, prop) => _hasOwnProp.call(obj, prop));