react-native-list 2.0.0-alpha.1 → 2.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +26 -28
  2. package/lib/ReactFabricMirror.d.ts +4 -0
  3. package/lib/ReactFabricMirror.js +515 -0
  4. package/lib/UiListModule.d.ts +2 -0
  5. package/lib/UiListModule.js +2 -0
  6. package/lib/index.d.ts +8 -0
  7. package/lib/index.js +21 -0
  8. package/lib/privateGlobals.d.ts +14 -0
  9. package/lib/privateGlobals.js +2 -0
  10. package/lib/renderer/RenderHelper.d.ts +2 -0
  11. package/lib/renderer/RenderHelper.js +11 -0
  12. package/lib/renderer/UiManagerHelper.d.ts +2 -0
  13. package/lib/renderer/UiManagerHelper.js +2 -0
  14. package/lib/renderer/fabric/RenderHelper.d.ts +2 -0
  15. package/lib/renderer/fabric/RenderHelper.js +11 -0
  16. package/lib/renderer/fabric/UiManagerHelper.d.ts +2 -0
  17. package/lib/renderer/fabric/UiManagerHelper.js +2 -0
  18. package/lib/renderer/react/ReactFabricMirror.d.ts +4 -0
  19. package/lib/renderer/react/ReactFabricMirror.js +515 -0
  20. package/lib/renderer/react/ReactFabricRenderer.d.ts +3 -0
  21. package/lib/renderer/react/ReactFabricRenderer.js +9 -0
  22. package/lib/specs/IOSWorkletsModuleProxyHolder.nitro.d.ts +6 -0
  23. package/lib/specs/IOSWorkletsModuleProxyHolder.nitro.js +1 -0
  24. package/lib/specs/UIListModule.nitro.d.ts +9 -0
  25. package/lib/specs/UIListModule.nitro.js +1 -0
  26. package/lib/specs/UIManagerHelper.nitro.d.ts +13 -0
  27. package/lib/specs/UIManagerHelper.nitro.js +1 -0
  28. package/lib/specs/UiListView.nitro.d.ts +20 -0
  29. package/lib/specs/UiListView.nitro.js +1 -0
  30. package/lib/specs/ViewHolder.nitro.d.ts +6 -0
  31. package/lib/specs/ViewHolder.nitro.js +1 -0
  32. package/lib/views/List.d.ts +35 -0
  33. package/lib/views/List.js +225 -0
  34. package/lib/views/UiListHostComponent.d.ts +2 -0
  35. package/lib/views/UiListHostComponent.js +3 -0
  36. package/metro-config.js +77 -5
  37. package/package.json +2 -2
@@ -0,0 +1,14 @@
1
+ import type * as ReactModule from 'react';
2
+ import type { UiManagerBinding } from './specs/UIManagerHelper.nitro';
3
+ declare global {
4
+ var log: (...args: unknown[]) => void;
5
+ var nativeFabricUIManager: UiManagerBinding;
6
+ interface GlobalThis {
7
+ React: typeof ReactModule;
8
+ }
9
+ interface Performance {
10
+ now(): number;
11
+ }
12
+ var performance: Performance;
13
+ }
14
+ export {};
@@ -0,0 +1,2 @@
1
+ 'use strict';
2
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare const uiListModuleBoxed: import("react-native-nitro-modules").BoxedHybridObject<import("../specs/UIListModule.nitro").UiListModule>;
2
+ export declare function renderSyncWorklet(): void;
@@ -0,0 +1,11 @@
1
+ import { NitroModules } from 'react-native-nitro-modules';
2
+ import { uiListModule } from '../UiListModule';
3
+ import { uiManagerHelper } from './UiManagerHelper';
4
+ export const uiListModuleBoxed = NitroModules.box(uiListModule);
5
+ const capturedOnJS = global.nativeFabricUIManager;
6
+ const uiManagerHelperBoxed = NitroModules.box(uiManagerHelper);
7
+ export function renderSyncWorklet() {
8
+ 'worklet';
9
+ const uiManagerHelperUnboxed = uiManagerHelperBoxed.unbox();
10
+ uiManagerHelperUnboxed.renderSync(capturedOnJS);
11
+ }
@@ -0,0 +1,2 @@
1
+ import { UiManagerHelper } from '../specs/UIManagerHelper.nitro';
2
+ export declare const uiManagerHelper: UiManagerHelper;
@@ -0,0 +1,2 @@
1
+ import { NitroModules } from 'react-native-nitro-modules';
2
+ export const uiManagerHelper = NitroModules.createHybridObject('UiManagerHelper');
@@ -0,0 +1,2 @@
1
+ export declare const uiListModuleBoxed: import("react-native-nitro-modules").BoxedHybridObject<import("../../specs/UIListModule.nitro").UiListModule>;
2
+ export declare function renderSyncWorklet(): void;
@@ -0,0 +1,11 @@
1
+ import { NitroModules } from 'react-native-nitro-modules';
2
+ import { uiListModule } from '../../UiListModule';
3
+ import { uiManagerHelper } from './UiManagerHelper';
4
+ export const uiListModuleBoxed = NitroModules.box(uiListModule);
5
+ const capturedOnJS = global.nativeFabricUIManager;
6
+ const uiManagerHelperBoxed = NitroModules.box(uiManagerHelper);
7
+ export function renderSyncWorklet() {
8
+ 'worklet';
9
+ const uiManagerHelperUnboxed = uiManagerHelperBoxed.unbox();
10
+ uiManagerHelperUnboxed.renderSync(capturedOnJS);
11
+ }
@@ -0,0 +1,2 @@
1
+ import { UiManagerHelper } from '../../specs/UIManagerHelper.nitro';
2
+ export declare const uiManagerHelper: UiManagerHelper;
@@ -0,0 +1,2 @@
1
+ import { NitroModules } from 'react-native-nitro-modules';
2
+ export const uiManagerHelper = NitroModules.createHybridObject('UiManagerHelper');
@@ -0,0 +1,4 @@
1
+ import type * as ReactModule from 'react';
2
+ declare function nativeLog(...args: unknown[]): void;
3
+ declare function reactRender(element: ReactModule.ReactElement, callback?: () => void): void;
4
+ export { nativeLog, reactRender };
@@ -0,0 +1,515 @@
1
+ /* eslint-disable @react-native/no-deep-imports, @typescript-eslint/no-unused-vars, no-dupe-keys, prettier/prettier */
2
+ // @ts-nocheck
3
+ function nativeLog(...args) {
4
+ global._log?.('[ReactFabricMirror] ' +
5
+ args
6
+ .map((a) => {
7
+ try {
8
+ return JSON.stringify(a);
9
+ }
10
+ catch (e) {
11
+ return '<failed to parse> ' + String(a);
12
+ }
13
+ })
14
+ .join(' '));
15
+ }
16
+ global.log = nativeLog;
17
+ const Reconciler = require('react-reconciler');
18
+ // FabricUIManager is basically a wrapper around global.nativeFabricUIManager
19
+ // but caches each function to avoid recreating a jsi::HostFunction on each call.
20
+ const { getFabricUIManager, } = require('react-native/Libraries/ReactNative/FabricUIManager');
21
+ const uiManager = getFabricUIManager();
22
+ const { create: createAttributePayload, diff: diffAttributePayloads, } = require('react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactNativeAttributePayload');
23
+ const ReactNativeViewConfigRegistry = require('react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry');
24
+ global.rootHostContext = {};
25
+ global.childHostContext = {};
26
+ const { NoEventPriority, DefaultEventPriority, DiscreteEventPriority, ContinuousEventPriority, IdleEventPriority, } = require('react-reconciler/constants');
27
+ global.currentUpdatePriority = NoEventPriority;
28
+ global.rootInstance = {
29
+ containerTag: 3,
30
+ publicInstance: null,
31
+ };
32
+ const { getPublicInstance, } = require('../../../shims/react-fiber-config-fabric.js');
33
+ //#region Event handling
34
+ const EventPluginUtilsModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/EventPluginUtils');
35
+ const { setComponentTree } = EventPluginUtilsModule;
36
+ const { injectEventPluginOrder, injectEventPluginsByName, plugins: legacyPlugins, } = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/EventPluginRegistry');
37
+ const ResponderEventPluginModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/ResponderEventPlugin');
38
+ const ReactNativeEventPluginOrderModule = require('../../../../third_party/react/packages/react-native-renderer/src/ReactNativeEventPluginOrder');
39
+ const ReactFabricGlobalResponderHandlerModule = require('../../../../third_party/react/packages/react-native-renderer/src/ReactFabricGlobalResponderHandler');
40
+ const SyntheticEventModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/SyntheticEvent');
41
+ const accumulateIntoModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/accumulateInto');
42
+ const forEachAccumulatedModule = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/forEachAccumulated');
43
+ const { batchedUpdates, } = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/ReactGenericBatching');
44
+ const { runEventsInBatch, } = require('../../../../third_party/react/packages/react-native-renderer/src/legacy-events/EventBatching');
45
+ const { HostComponent } = require('react-reconciler/src/ReactWorkTags');
46
+ const ResponderEventPlugin = ResponderEventPluginModule.default ?? ResponderEventPluginModule;
47
+ const ReactNativeEventPluginOrder = ReactNativeEventPluginOrderModule.default ?? ReactNativeEventPluginOrderModule;
48
+ const ReactFabricGlobalResponderHandler = ReactFabricGlobalResponderHandlerModule.default ??
49
+ ReactFabricGlobalResponderHandlerModule;
50
+ const SyntheticEvent = SyntheticEventModule.default ?? SyntheticEventModule;
51
+ const accumulateInto = accumulateIntoModule.default ?? accumulateIntoModule;
52
+ const forEachAccumulated = forEachAccumulatedModule.default ?? forEachAccumulatedModule;
53
+ const { customBubblingEventTypes, customDirectEventTypes } = ReactNativeViewConfigRegistry;
54
+ function getParent(inst) {
55
+ do {
56
+ inst = inst.return;
57
+ } while (inst && inst.tag !== HostComponent);
58
+ return inst || null;
59
+ }
60
+ function traverseTwoPhase(inst, fn, arg, skipBubbling) {
61
+ const path = [];
62
+ while (inst) {
63
+ path.push(inst);
64
+ inst = getParent(inst);
65
+ }
66
+ for (let i = path.length - 1; i >= 0; i--) {
67
+ fn(path[i], 'captured', arg);
68
+ }
69
+ if (skipBubbling) {
70
+ fn(path[0], 'bubbled', arg);
71
+ }
72
+ else {
73
+ for (let i = 0; i < path.length; i++) {
74
+ fn(path[i], 'bubbled', arg);
75
+ }
76
+ }
77
+ }
78
+ function getListener(inst, registrationName) {
79
+ const stateNode = inst.stateNode;
80
+ if (stateNode == null) {
81
+ return null;
82
+ }
83
+ const props = EventPluginUtilsModule.getFiberCurrentPropsFromNode(stateNode);
84
+ if (props == null) {
85
+ return null;
86
+ }
87
+ const listener = props[registrationName];
88
+ if (listener != null && typeof listener !== 'function') {
89
+ throw new Error(`Expected \`${registrationName}\` listener to be a function, got \`${typeof listener}\`.`);
90
+ }
91
+ return listener;
92
+ }
93
+ function listenerAtPhase(inst, event, propagationPhase) {
94
+ const registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
95
+ return getListener(inst, registrationName);
96
+ }
97
+ function accumulateDirectionalDispatches(inst, phase, event) {
98
+ const listener = listenerAtPhase(inst, event, phase);
99
+ if (listener) {
100
+ event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
101
+ event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
102
+ }
103
+ }
104
+ function accumulateTwoPhaseDispatchesSingle(event) {
105
+ if (event && event.dispatchConfig.phasedRegistrationNames) {
106
+ traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event, false);
107
+ }
108
+ }
109
+ function accumulateTwoPhaseDispatches(events) {
110
+ forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
111
+ }
112
+ function accumulateCapturePhaseDispatches(event) {
113
+ if (event && event.dispatchConfig.phasedRegistrationNames) {
114
+ traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event, true);
115
+ }
116
+ }
117
+ function accumulateDispatches(inst, _ignoredDirection, event) {
118
+ if (inst && event && event.dispatchConfig.registrationName) {
119
+ const registrationName = event.dispatchConfig.registrationName;
120
+ const listener = getListener(inst, registrationName);
121
+ if (listener) {
122
+ event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
123
+ event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
124
+ }
125
+ }
126
+ }
127
+ function accumulateDirectDispatchesSingle(event) {
128
+ if (event && event.dispatchConfig.registrationName) {
129
+ accumulateDispatches(event._targetInst, null, event);
130
+ }
131
+ }
132
+ function accumulateDirectDispatches(events) {
133
+ forEachAccumulated(events, accumulateDirectDispatchesSingle);
134
+ }
135
+ const ReactNativeBridgeEventPlugin = {
136
+ eventTypes: {},
137
+ extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
138
+ if (targetInst == null) {
139
+ return null;
140
+ }
141
+ const bubbleDispatchConfig = customBubblingEventTypes[topLevelType];
142
+ const directDispatchConfig = customDirectEventTypes[topLevelType];
143
+ if (!bubbleDispatchConfig && !directDispatchConfig) {
144
+ throw new Error(`Unsupported top level event type "${topLevelType}" dispatched`);
145
+ }
146
+ const event = SyntheticEvent.getPooled(bubbleDispatchConfig || directDispatchConfig, targetInst, nativeEvent, nativeEventTarget);
147
+ if (bubbleDispatchConfig) {
148
+ const skipBubbling = event != null &&
149
+ event.dispatchConfig.phasedRegistrationNames != null &&
150
+ event.dispatchConfig.phasedRegistrationNames.skipBubbling;
151
+ if (skipBubbling) {
152
+ accumulateCapturePhaseDispatches(event);
153
+ }
154
+ else {
155
+ accumulateTwoPhaseDispatches(event);
156
+ }
157
+ }
158
+ else if (directDispatchConfig) {
159
+ accumulateDirectDispatches(event);
160
+ }
161
+ else {
162
+ return null;
163
+ }
164
+ return event;
165
+ },
166
+ };
167
+ function extractPluginEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
168
+ let events = null;
169
+ for (let i = 0; i < legacyPlugins.length; i++) {
170
+ const plugin = legacyPlugins[i];
171
+ if (plugin) {
172
+ const extractedEvents = plugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
173
+ if (extractedEvents) {
174
+ events = accumulateInto(events, extractedEvents);
175
+ }
176
+ }
177
+ }
178
+ return events;
179
+ }
180
+ function runExtractedPluginEventsInBatch(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
181
+ const events = extractPluginEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
182
+ runEventsInBatch(events);
183
+ }
184
+ function ensureLegacyEventPluginsInjected() {
185
+ try {
186
+ injectEventPluginOrder(ReactNativeEventPluginOrder);
187
+ }
188
+ catch (error) {
189
+ // The plugin order can only be injected once for a given registry instance.
190
+ if (!String(error).includes('Cannot inject event plugin ordering more than once')) {
191
+ throw error;
192
+ }
193
+ }
194
+ injectEventPluginsByName({
195
+ ResponderEventPlugin,
196
+ ReactNativeBridgeEventPlugin,
197
+ });
198
+ setComponentTree(
199
+ // Equivalent to ReactFabricComponentTree.getFiberCurrentPropsFromNode
200
+ (instance) => instance?.canonical?.currentProps ?? null,
201
+ // Equivalent to ReactFabricComponentTree.getInstanceFromNode
202
+ (node) => {
203
+ if (node?.canonical != null &&
204
+ node.canonical.internalInstanceHandle != null) {
205
+ return node.canonical.internalInstanceHandle;
206
+ }
207
+ return node ?? null;
208
+ },
209
+ // Equivalent to ReactFabricComponentTree.getNodeFromInstance
210
+ (fiber) => {
211
+ const publicInstance = getPublicInstance(fiber.stateNode);
212
+ if (publicInstance == null) {
213
+ throw new Error('Could not find host instance from fiber');
214
+ }
215
+ return publicInstance;
216
+ });
217
+ ResponderEventPlugin.injection.injectGlobalResponderHandler(ReactFabricGlobalResponderHandler);
218
+ }
219
+ ensureLegacyEventPluginsInjected();
220
+ function dispatchEvent(target, topLevelType, nativeEvent) {
221
+ const targetFiber = target;
222
+ let eventTarget = null;
223
+ if (targetFiber != null) {
224
+ const stateNode = targetFiber.stateNode;
225
+ if (stateNode != null) {
226
+ eventTarget = getPublicInstance(stateNode);
227
+ }
228
+ }
229
+ batchedUpdates(() => {
230
+ runExtractedPluginEventsInBatch(topLevelType, targetFiber, nativeEvent, eventTarget);
231
+ });
232
+ }
233
+ // This will be retrieved on the native side in JSI ... hm or we call and set it?
234
+ global.handleEvent = dispatchEvent;
235
+ //#endregion
236
+ // Counter for uniquely identifying views.
237
+ // % 10 === 1 means it is a rootTag.
238
+ // % 2 === 0 means it is a Fabric tag.
239
+ // This means that they never overlap.
240
+ global.nextReactTag = 200_000_000;
241
+ // ^ Why is this number so high?
242
+ // We share the ReactInstance (ie we don't create a seperate one)
243
+ // That means our surface shares the RCTComponentViewRegistry on iOS with the main React Native renderer.
244
+ // When creating new views its checking if the tag already exists, meaning we can't use the same tags that react is using. Bummer!\
245
+ // TODO: find a better solution for this
246
+ const HostConfig = {
247
+ now: performance.now,
248
+ getRootHostContext(rootContainerInstance) {
249
+ return global.rootHostContext;
250
+ },
251
+ getChildHostContext() {
252
+ return global.childHostContext;
253
+ },
254
+ // prepareForCommit(containerInfo) {},
255
+ // resetAfterCommit(containerInfo) {},
256
+ supportsPersistence: true,
257
+ createInstance: (type, props, rootContainerInstance, _currentHostContext, workInProgress) => {
258
+ const tag = global.nextReactTag;
259
+ global.nextReactTag += 2;
260
+ const viewConfig = ReactNativeViewConfigRegistry.get(type);
261
+ const updatePayload = createAttributePayload(props, viewConfig.validAttributes);
262
+ let node;
263
+ try {
264
+ nativeLog('[createInstance] calling createNode with type=', type, 'tag=', tag);
265
+ nativeLog('[createInstance] props=', updatePayload);
266
+ node = uiManager.createNode(tag, // reactTag
267
+ viewConfig.uiViewClassName, // viewName
268
+ rootContainerInstance.containerTag, // rootTag
269
+ updatePayload, // props
270
+ workInProgress // internalInstanceHandle
271
+ );
272
+ }
273
+ catch (e) {
274
+ nativeLog('[createInstance] ERROR in createNode:', e.message || String(e));
275
+ nativeLog('Stack:', new Error().stack);
276
+ throw e;
277
+ }
278
+ return {
279
+ node: node,
280
+ canonical: {
281
+ nativeTag: tag,
282
+ viewConfig, // TODO: is this needed? for what
283
+ currentProps: props, // funny, react is passing here props instead of updatePayload, is this okay?
284
+ internalInstanceHandle: workInProgress,
285
+ publicInstance: null,
286
+ publicRootInstance: rootContainerInstance.publicInstance,
287
+ },
288
+ };
289
+ },
290
+ finalizeInitialChildren(parentInstance, type, props, hostContext) {
291
+ nativeLog('[finalizeInitialChildren]');
292
+ return false;
293
+ },
294
+ cloneInstance(instance, type, oldProps, newProps, keepChildren, newChildSet) {
295
+ nativeLog('[cloneInstance] tag=', instance.canonical.nativeTag);
296
+ const viewConfig = instance.canonical.viewConfig;
297
+ const updatePayload = diffAttributePayloads(oldProps, newProps, viewConfig.validAttributes);
298
+ nativeLog('[cloneInstance] updatePayload=', updatePayload);
299
+ // TODO: If the event handlers have changed, we need to update the current props
300
+ // in the commit phase but there is no host config hook to do it yet.
301
+ // So instead we hack it by updating it in the render phase.
302
+ instance.canonical.currentProps = newProps;
303
+ const node = instance.node;
304
+ let clone;
305
+ if (keepChildren) {
306
+ if (updatePayload !== null) {
307
+ clone = uiManager.cloneNodeWithNewProps(node, updatePayload);
308
+ }
309
+ else {
310
+ // No changes
311
+ return instance;
312
+ }
313
+ }
314
+ else {
315
+ // If passChildrenWhenCloningPersistedNodes is enabled, children will be non-null
316
+ if (newChildSet != null) {
317
+ if (updatePayload !== null) {
318
+ clone = uiManager.cloneNodeWithNewChildrenAndProps(node, newChildSet, updatePayload);
319
+ }
320
+ else {
321
+ clone = uiManager.cloneNodeWithNewChildren(node, newChildSet);
322
+ }
323
+ }
324
+ else {
325
+ if (updatePayload !== null) {
326
+ clone = uiManager.cloneNodeWithNewChildrenAndProps(node, updatePayload);
327
+ }
328
+ else {
329
+ clone = uiManager.cloneNodeWithNewChildren(node);
330
+ }
331
+ }
332
+ }
333
+ return {
334
+ node: clone,
335
+ canonical: instance.canonical,
336
+ };
337
+ },
338
+ createTextInstance(text, rootContainerInstance, hostContext, internalInstanceHandle) {
339
+ const tag = global.nextReactTag;
340
+ global.nextReactTag += 2;
341
+ const node = uiManager.createNode(tag, // reactTag
342
+ 'RCTRawText', // viewName
343
+ rootContainerInstance.containerTag, // rootTag
344
+ { text: text }, // props
345
+ internalInstanceHandle // instance handle
346
+ );
347
+ return {
348
+ node: node,
349
+ };
350
+ },
351
+ createContainerChildSet() {
352
+ nativeLog('[createContainerChildSet]');
353
+ return uiManager.createChildSet();
354
+ },
355
+ appendChildToContainerChildSet(childSet, child) {
356
+ nativeLog('[appendChildToContainerChildSet]');
357
+ uiManager.appendChildToSet(childSet, child.node);
358
+ },
359
+ finalizeContainerChildren(container, newChildren) {
360
+ // Noop - children will be replaced in replaceContainerChildren
361
+ nativeLog('[finalizeContainerChildren]');
362
+ },
363
+ appendInitialChild(parentInstance, child) {
364
+ nativeLog('[appendInitialChild]');
365
+ uiManager.appendChild(parentInstance.node, child.node);
366
+ },
367
+ replaceContainerChildren(container, newChildren) {
368
+ nativeLog('[replaceContainerChildren]');
369
+ uiManager.completeRoot(container.containerTag, newChildren);
370
+ },
371
+ // TODO: hm, this could get problematic, to share event priorities between the fabric ui manager.
372
+ // Maybe we need to create a clone of the ui manager? the important thing is that all view managers are resolved when we do so.
373
+ // However that would concern me if commitHooks from reanimated would work.
374
+ setCurrentUpdatePriority(priority) {
375
+ global.currentUpdatePriority = priority;
376
+ },
377
+ getCurrentUpdatePriority() {
378
+ return global.currentUpdatePriority;
379
+ },
380
+ resolveUpdatePriority() {
381
+ if (global.currentUpdatePriority !== NoEventPriority) {
382
+ return global.currentUpdatePriority;
383
+ }
384
+ else {
385
+ return DefaultEventPriority;
386
+ }
387
+ // TODO:
388
+ /* const currentEventPriority = fabricGetCurrentEventPriority
389
+ ? fabricGetCurrentEventPriority()
390
+ : null;
391
+
392
+ if (currentEventPriority != null) {
393
+ switch (currentEventPriority) {
394
+ case FabricDiscretePriority:
395
+ return DiscreteEventPriority;
396
+ case FabricContinuousPriority:
397
+ return ContinuousEventPriority;
398
+ case FabricIdlePriority:
399
+ return IdleEventPriority;
400
+ case FabricDefaultPriority:
401
+ default:
402
+ return DefaultEventPriority;
403
+ }
404
+ }
405
+
406
+ return DefaultEventPriority; */
407
+ },
408
+ getPublicInstance(instance) {
409
+ return getPublicInstance(instance);
410
+ },
411
+ // getPublicTextInstance(textInstance, internalInstanceHandle) {
412
+ // if (textInstance.publicInstance == null) {
413
+ // textInstance.publicInstance = createPublicTextInstance(
414
+ // internalInstanceHandle
415
+ // )
416
+ // }
417
+ // return textInstance.publicInstance
418
+ // },
419
+ // getPublicInstanceFromInternalInstanceHandle(internalInstanceHandle) {
420
+ // const instance = internalInstanceHandle.stateNode
421
+ // // React resets all the fields in the fiber when the component is unmounted
422
+ // // to prevent memory leaks.
423
+ // if (instance == null) {
424
+ // return null
425
+ // }
426
+ // if (internalInstanceHandle.tag === HostText) {
427
+ // const textInstance = instance
428
+ // return this.getPublicTextInstance(textInstance, internalInstanceHandle)
429
+ // }
430
+ // const elementInstance = internalInstanceHandle.stateNode
431
+ // return this.getPublicInstance(elementInstance)
432
+ // },
433
+ prepareForCommit(containerInfo) {
434
+ return null;
435
+ },
436
+ resetAfterCommit(containerInfo) { },
437
+ trackSchedulerEvent() { },
438
+ resolveEventType() {
439
+ return null;
440
+ },
441
+ resolveEventTimeStamp() {
442
+ return -1.1;
443
+ },
444
+ shouldAttemptEagerTransition() {
445
+ return false;
446
+ },
447
+ shouldSetTextContent(type, props) {
448
+ return false;
449
+ },
450
+ // TODO: microtask scheduling, should work with worklets on the UI thread i believe! not sure though if even RN implements this?
451
+ supportsMicrotasks: false,
452
+ detachDeletedInstance(node) { },
453
+ beforeActiveInstanceBlur(internalInstanceHandle) {
454
+ // noop
455
+ },
456
+ afterActiveInstanceBlur() {
457
+ // noop
458
+ },
459
+ preparePortalMount(portalInstance) {
460
+ // noop
461
+ },
462
+ detachDeletedInstance(node) {
463
+ // noop
464
+ },
465
+ requestPostPaintCallback(callback) {
466
+ // noop
467
+ },
468
+ maySuspendCommit(type, props) {
469
+ return false;
470
+ },
471
+ maySuspendCommitOnUpdate(type, oldProps, newProps) {
472
+ return false;
473
+ },
474
+ maySuspendCommitInSyncRender(type, props) {
475
+ return false;
476
+ },
477
+ preloadInstance(instance, type, props) {
478
+ return true;
479
+ },
480
+ startSuspendingCommit() {
481
+ return null;
482
+ },
483
+ suspendInstance(state, instance, type, props) { },
484
+ suspendOnActiveViewTransition(state, container) { },
485
+ waitForCommitToBeReady(state, timeoutOffset) {
486
+ return null;
487
+ },
488
+ getSuspendedCommitReason(state, rootContainer) {
489
+ return null;
490
+ },
491
+ isPrimaryRenderer: false,
492
+ };
493
+ const Renderer = Reconciler(HostConfig);
494
+ global.React = require('react');
495
+ function reactRender(element, callback) {
496
+ if (!global.rootContainer) {
497
+ global.rootContainer = Renderer.createContainer(global.rootInstance, 0, // concurrentRoot ? 1 : 0
498
+ null, false, null, 'ui-renderer', function onUncaughtError(error, info) {
499
+ nativeLog('[Error][ReactFabricMirror] Uncaught error in React renderer: ', error, info);
500
+ }, function onCaughtError(error, info) {
501
+ nativeLog('[Error][ReactFabricMirror] Caught error in React renderer: ', error, info);
502
+ }, function onRecoverableError(error, info) {
503
+ nativeLog('[Error][ReactFabricMirror] Recoverable error in React renderer: ', error, info);
504
+ }, function nativeOnDefaultTransitionIndicator() {
505
+ // Native doesn't have a default indicator.
506
+ });
507
+ }
508
+ // updateContainerSync + flushSyncWork is making the renderer work immediately/blocking/…sync
509
+ Renderer.updateContainerSync(element, global.rootContainer, null, callback);
510
+ // Renderer.flushPassiveEffects();
511
+ Renderer.flushSyncWork();
512
+ nativeLog('[ReactFabricMirror] updateContainer finished');
513
+ }
514
+ nativeLog('[ReactFabricMirror] ReactFabricMirror initialized');
515
+ export { nativeLog, reactRender };
@@ -0,0 +1,3 @@
1
+ type ReactFabricMirrorModule = typeof import('./ReactFabricMirror');
2
+ export declare function getReactFabricRenderer(): ReactFabricMirrorModule;
3
+ export {};
@@ -0,0 +1,9 @@
1
+ // This has to be a function so that its a worklet which can be called on the UI runtime.
2
+ // Never import the ReactFabricMirrorModule directly from non-worklet code!
3
+ export function getReactFabricRenderer() {
4
+ 'worklet';
5
+ // This file is generated by `bun bundle:js`. It contains setting up the React instance on the UI runtime.
6
+ // This is what will do the "react render phase" of our react tree. Note that this is seperate from the
7
+ // fabric tree rendering + mounting. This is just react stuff.
8
+ return require('react-native-list/src/renderer/react/ReactFabricMirror.bundle');
9
+ }
@@ -0,0 +1,6 @@
1
+ import { HybridObject } from 'react-native-nitro-modules';
2
+ export interface IOSWorkletsModuleProxyHolder extends HybridObject<{
3
+ android: 'kotlin';
4
+ ios: 'swift';
5
+ }> {
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { HybridObject } from 'react-native-nitro-modules';
2
+ import type { IOSWorkletsModuleProxyHolder } from './IOSWorkletsModuleProxyHolder.nitro';
3
+ export interface UiListModule extends HybridObject<{
4
+ android: 'kotlin';
5
+ ios: 'swift';
6
+ }> {
7
+ iosGetWorkletsModule(): IOSWorkletsModuleProxyHolder;
8
+ setupExternalSurface(workletsModuleHolder: IOSWorkletsModuleProxyHolder | null): void;
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { CustomType, HybridObject } from 'react-native-nitro-modules';
2
+ type UiManagerBidningType = {
3
+ _stubToMakeNitroHappy_doesNotExist_doNotUse: void;
4
+ };
5
+ export type UiManagerBinding = CustomType<UiManagerBidningType, 'std::shared_ptr<facebook::react::UIManagerBinding>', {
6
+ include: 'JSIConverter+UIManagerBinding.hpp';
7
+ }>;
8
+ export interface UiManagerHelper extends HybridObject<{
9
+ android: 'c++';
10
+ }> {
11
+ renderSync(nativeFabricUIManager: UiManagerBinding): void;
12
+ }
13
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { AnyMap, HybridView, HybridViewMethods, HybridViewProps, Sync } from 'react-native-nitro-modules';
2
+ import { UiListModule } from './UIListModule.nitro';
3
+ export interface NativeListItem {
4
+ key: string;
5
+ type: string;
6
+ width?: number;
7
+ height?: number;
8
+ data: AnyMap;
9
+ }
10
+ export interface UiListViewProps extends HybridViewProps {
11
+ }
12
+ export interface UiListViewMethods extends HybridViewMethods {
13
+ setListCallbacks(uiListModule: UiListModule, createView: Sync<(type: string) => number>, updateView: Sync<(reactTag: number, item: NativeListItem, index: number) => boolean>, isContentEqual: Sync<(oldItem: NativeListItem, newItem: NativeListItem) => boolean>): void;
14
+ setData(items: NativeListItem[], animated: boolean): void;
15
+ insertItem(index: number, item: NativeListItem): void;
16
+ updateItem(index: number, item: NativeListItem): void;
17
+ removeItem(index: number): void;
18
+ moveItem(fromIndex: number, toIndex: number): void;
19
+ }
20
+ export type UiListView = HybridView<UiListViewProps, UiListViewMethods>;
@@ -0,0 +1 @@
1
+ export {};