@symbiote-native/react 0.1.0

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 (148) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +149 -0
  3. package/build/components/activity-indicator/index.android.d.ts +2 -0
  4. package/build/components/activity-indicator/index.android.js +13 -0
  5. package/build/components/activity-indicator/index.d.ts +1 -0
  6. package/build/components/activity-indicator/index.ios.d.ts +2 -0
  7. package/build/components/activity-indicator/index.ios.js +10 -0
  8. package/build/components/activity-indicator/index.js +4 -0
  9. package/build/components/activity-indicator/shared.d.ts +7 -0
  10. package/build/components/activity-indicator/shared.js +20 -0
  11. package/build/components/button.d.ts +6 -0
  12. package/build/components/button.js +42 -0
  13. package/build/components/drawer-layout-android/index.android.d.ts +3 -0
  14. package/build/components/drawer-layout-android/index.android.js +93 -0
  15. package/build/components/drawer-layout-android/index.d.ts +3 -0
  16. package/build/components/drawer-layout-android/index.js +19 -0
  17. package/build/components/drawer-layout-android/shared.d.ts +19 -0
  18. package/build/components/drawer-layout-android/shared.js +7 -0
  19. package/build/components/flat-list/index.d.ts +73 -0
  20. package/build/components/flat-list/index.js +86 -0
  21. package/build/components/image/index.d.ts +9 -0
  22. package/build/components/image/index.js +28 -0
  23. package/build/components/image-background/index.d.ts +10 -0
  24. package/build/components/image-background/index.js +46 -0
  25. package/build/components/input-accessory-view/index.d.ts +11 -0
  26. package/build/components/input-accessory-view/index.js +14 -0
  27. package/build/components/keyboard-avoiding-view/index.d.ts +17 -0
  28. package/build/components/keyboard-avoiding-view/index.js +85 -0
  29. package/build/components/modal/index.d.ts +24 -0
  30. package/build/components/modal/index.js +56 -0
  31. package/build/components/pressable/index.d.ts +30 -0
  32. package/build/components/pressable/index.js +100 -0
  33. package/build/components/refresh-control/index.d.ts +17 -0
  34. package/build/components/refresh-control/index.js +21 -0
  35. package/build/components/safe-area-view/index.d.ts +11 -0
  36. package/build/components/safe-area-view/index.js +18 -0
  37. package/build/components/scroll-view/index.android.d.ts +3 -0
  38. package/build/components/scroll-view/index.android.js +53 -0
  39. package/build/components/scroll-view/index.d.ts +1 -0
  40. package/build/components/scroll-view/index.ios.d.ts +3 -0
  41. package/build/components/scroll-view/index.ios.js +27 -0
  42. package/build/components/scroll-view/index.js +4 -0
  43. package/build/components/scroll-view/shared.d.ts +98 -0
  44. package/build/components/scroll-view/shared.js +195 -0
  45. package/build/components/scroll-view/sticky-header.d.ts +9 -0
  46. package/build/components/scroll-view/sticky-header.js +161 -0
  47. package/build/components/section-list/index.d.ts +8 -0
  48. package/build/components/section-list/index.js +12 -0
  49. package/build/components/switch/index.android.d.ts +2 -0
  50. package/build/components/switch/index.android.js +12 -0
  51. package/build/components/switch/index.d.ts +1 -0
  52. package/build/components/switch/index.ios.d.ts +2 -0
  53. package/build/components/switch/index.ios.js +10 -0
  54. package/build/components/switch/index.js +6 -0
  55. package/build/components/switch/shared.d.ts +10 -0
  56. package/build/components/switch/shared.js +59 -0
  57. package/build/components/text-input/index.d.ts +50 -0
  58. package/build/components/text-input/index.js +167 -0
  59. package/build/components/touchable/index.d.ts +20 -0
  60. package/build/components/touchable/index.js +95 -0
  61. package/build/components/touchable-native-feedback/index.d.ts +18 -0
  62. package/build/components/touchable-native-feedback/index.js +32 -0
  63. package/build/components/virtualized-list/index.d.ts +73 -0
  64. package/build/components/virtualized-list/index.js +552 -0
  65. package/build/components/virtualized-section-list/index.d.ts +66 -0
  66. package/build/components/virtualized-section-list/index.js +99 -0
  67. package/build/components.d.ts +54 -0
  68. package/build/components.js +17 -0
  69. package/build/create-portal.d.ts +4 -0
  70. package/build/create-portal.js +23 -0
  71. package/build/create-tunnel.d.ts +12 -0
  72. package/build/create-tunnel.js +60 -0
  73. package/build/descriptor-to-react/index.d.ts +3 -0
  74. package/build/descriptor-to-react/index.js +15 -0
  75. package/build/hooks/use-color-scheme.d.ts +2 -0
  76. package/build/hooks/use-color-scheme.js +13 -0
  77. package/build/hooks/use-window-dimensions.d.ts +2 -0
  78. package/build/hooks/use-window-dimensions.js +30 -0
  79. package/build/host-config.d.ts +7 -0
  80. package/build/host-config.js +169 -0
  81. package/build/host-instance.d.ts +3 -0
  82. package/build/host-instance.js +20 -0
  83. package/build/index.d.ts +98 -0
  84. package/build/index.js +85 -0
  85. package/build/modules/accessibility-info/index.android.d.ts +2 -0
  86. package/build/modules/accessibility-info/index.android.js +4 -0
  87. package/build/modules/accessibility-info/index.d.ts +1 -0
  88. package/build/modules/accessibility-info/index.ios.d.ts +2 -0
  89. package/build/modules/accessibility-info/index.ios.js +3 -0
  90. package/build/modules/accessibility-info/index.js +5 -0
  91. package/build/modules/accessibility-info/shared.d.ts +1 -0
  92. package/build/modules/accessibility-info/shared.js +1 -0
  93. package/build/modules/action-sheet-ios.d.ts +2 -0
  94. package/build/modules/action-sheet-ios.js +4 -0
  95. package/build/modules/alert.d.ts +2 -0
  96. package/build/modules/alert.js +5 -0
  97. package/build/modules/animated/create-animated-component.d.ts +12 -0
  98. package/build/modules/animated/create-animated-component.js +125 -0
  99. package/build/modules/animated/index.d.ts +52 -0
  100. package/build/modules/animated/index.js +84 -0
  101. package/build/modules/app-registry/index.d.ts +7 -0
  102. package/build/modules/app-registry/index.js +26 -0
  103. package/build/modules/app-state.d.ts +2 -0
  104. package/build/modules/app-state.js +3 -0
  105. package/build/modules/appearance.d.ts +2 -0
  106. package/build/modules/appearance.js +3 -0
  107. package/build/modules/back-handler.d.ts +2 -0
  108. package/build/modules/back-handler.js +3 -0
  109. package/build/modules/dimensions.d.ts +2 -0
  110. package/build/modules/dimensions.js +3 -0
  111. package/build/modules/i18n-manager.d.ts +2 -0
  112. package/build/modules/i18n-manager.js +4 -0
  113. package/build/modules/keyboard.d.ts +2 -0
  114. package/build/modules/keyboard.js +3 -0
  115. package/build/modules/layout-animation.d.ts +2 -0
  116. package/build/modules/layout-animation.js +3 -0
  117. package/build/modules/linking.d.ts +2 -0
  118. package/build/modules/linking.js +4 -0
  119. package/build/modules/permissions-android.d.ts +2 -0
  120. package/build/modules/permissions-android.js +3 -0
  121. package/build/modules/settings.d.ts +1 -0
  122. package/build/modules/settings.js +4 -0
  123. package/build/modules/share.d.ts +2 -0
  124. package/build/modules/share.js +4 -0
  125. package/build/modules/status-bar/index.android.d.ts +3 -0
  126. package/build/modules/status-bar/index.android.js +89 -0
  127. package/build/modules/status-bar/index.d.ts +1 -0
  128. package/build/modules/status-bar/index.ios.d.ts +3 -0
  129. package/build/modules/status-bar/index.ios.js +64 -0
  130. package/build/modules/status-bar/index.js +4 -0
  131. package/build/modules/status-bar/shared.d.ts +6 -0
  132. package/build/modules/status-bar/shared.js +6 -0
  133. package/build/modules/text-input-state.d.ts +1 -0
  134. package/build/modules/text-input-state.js +3 -0
  135. package/build/modules/toast-android.d.ts +1 -0
  136. package/build/modules/toast-android.js +4 -0
  137. package/build/modules/vibration.d.ts +1 -0
  138. package/build/modules/vibration.js +4 -0
  139. package/build/reconciler-constants.d.ts +7 -0
  140. package/build/reconciler-constants.js +12 -0
  141. package/build/render.d.ts +7 -0
  142. package/build/render.js +60 -0
  143. package/build/utils/responder-props.d.ts +1 -0
  144. package/build/utils/responder-props.js +1 -0
  145. package/build/utils/styles.d.ts +1 -0
  146. package/build/utils/styles.js +1 -0
  147. package/metro-css-parser.cjs +11 -0
  148. package/package.json +53 -0
@@ -0,0 +1,3 @@
1
+ // LayoutAnimation moved to @symbiote-native/engine (a framework-agnostic native-bridge consumer
2
+ // re-exported by every adapter). This thin re-export keeps @symbiote-native/react's surface identical.
3
+ export { LayoutAnimation } from '@symbiote-native/engine';
@@ -0,0 +1,2 @@
1
+ export { Linking } from '@symbiote-native/engine';
2
+ export type { IUrlEvent } from '@symbiote-native/engine';
@@ -0,0 +1,4 @@
1
+ // Linking now lives framework-agnostic in @symbiote-native/engine (imperative native-bridge
2
+ // module, no visual, no lifecycle). The React adapter re-exports it verbatim; the
3
+ // platform split (linking.ios/linking.android) lives inside engine. See ADR 0019.
4
+ export { Linking } from '@symbiote-native/engine';
@@ -0,0 +1,2 @@
1
+ export { PermissionsAndroid, PERMISSIONS, RESULTS } from '@symbiote-native/engine';
2
+ export type { IPermission, IPermissionStatus, IRationale } from '@symbiote-native/engine';
@@ -0,0 +1,3 @@
1
+ // PermissionsAndroid moved to @symbiote-native/engine (a framework-agnostic device-state module
2
+ // re-exported by every adapter). This thin re-export keeps @symbiote-native/react's surface identical.
3
+ export { PermissionsAndroid, PERMISSIONS, RESULTS } from '@symbiote-native/engine';
@@ -0,0 +1 @@
1
+ export { Settings } from '@symbiote-native/engine';
@@ -0,0 +1,4 @@
1
+ // Settings now lives framework-agnostic in @symbiote-native/engine (imperative native-bridge
2
+ // module, no visual, no lifecycle). The React adapter re-exports it verbatim so the
3
+ // public surface is unchanged. See ADR 0019.
4
+ export { Settings } from '@symbiote-native/engine';
@@ -0,0 +1,2 @@
1
+ export { Share } from '@symbiote-native/engine';
2
+ export type { IShareContent, IShareOptions, IShareAction } from '@symbiote-native/engine';
@@ -0,0 +1,4 @@
1
+ // Share now lives framework-agnostic in @symbiote-native/engine (imperative native-bridge
2
+ // module, no visual, no lifecycle). The React adapter re-exports it verbatim; the
3
+ // platform split (share.ios/share.android) lives inside engine. See ADR 0019.
4
+ export { Share } from '@symbiote-native/engine';
@@ -0,0 +1,3 @@
1
+ import type { IStatusBarComponent } from './shared';
2
+ export type { IStatusBarProps, IStatusBarStyle } from './shared';
3
+ export declare const StatusBar: IStatusBarComponent;
@@ -0,0 +1,89 @@
1
+ // StatusBar on Android: drives the Android StatusBarManager from props (and from the
2
+ // static methods). Android's native module is a DIFFERENT shape from iOS: single-arg
3
+ // setHidden(hidden) / setStyle(style) plus setColor/setTranslucent, same module name
4
+ // ('StatusBarManager'). Metro picks this on an Android host; iOS keeps its own shape.
5
+ //
6
+ // The native-call logic stays in the adapter (not the engine): the platform module shape
7
+ // diverges iOS/Android and the headless smokes import this file by name (tsx has no platform
8
+ // picker, so routing through the engine barrel would resolve the iOS base on every platform).
9
+ // The engine owns only the pure shared contract: types, constants, hideTransition.
10
+ //
11
+ // History: this used to be a no-op. Driving the window flags from the bridgeless surface
12
+ // blanked the app: a status-bar relayout triggered stopSurface, which threw "Global was
13
+ // not installed" because RN installs global.RN$stopSurface from its own renderer, which this
14
+ // renderer replaces. Now that render.ts installs RN$stopSurface and tears surfaces down cleanly, the
15
+ // relayout survives and the bar updates without blanking (verified on device: show/hide +
16
+ // light/dark text). See render.ts installStopSurfaceGlobal + native-module-platform-routing.
17
+ import { useEffect } from 'react';
18
+ import { dlog, getNativeModule, processColor, STATUS_BAR_MANAGER, } from '@symbiote-native/engine';
19
+ // processColor returns `unknown` (its result is platform-dependent); narrow to the
20
+ // number Fabric/native expects, like RN's invariant before setColor. A non-number
21
+ // (null for an unparseable color, headless identity passthrough of a string) is dropped.
22
+ function applyBackgroundColor(manager, color, animated) {
23
+ const processed = processColor(color);
24
+ if (typeof processed !== 'number') {
25
+ dlog(`StatusBar android: backgroundColor ${String(color)} did not process to an int — skipping`);
26
+ return;
27
+ }
28
+ // RISK: driving the window background flag once blanked the bridgeless surface
29
+ // (see header). Routed cleanly here but DEVICE-VERIFY-PENDING.
30
+ dlog(`StatusBar android setColor -> ${processed} animated=${animated}`);
31
+ manager.setColor(processed, animated);
32
+ }
33
+ // Renders null and applies its props to the native module in an effect, on mount and on
34
+ // every prop change, same contract as iOS, with the single-arg Android setters.
35
+ const StatusBarAndroid = props => {
36
+ const { barStyle, hidden, animated = false, backgroundColor, translucent } = props;
37
+ useEffect(() => {
38
+ const manager = getNativeModule(STATUS_BAR_MANAGER);
39
+ if (manager === null) {
40
+ dlog('StatusBar android: StatusBarManager not resolvable — skipping');
41
+ return;
42
+ }
43
+ dlog(`StatusBar android -> barStyle=${barStyle} hidden=${hidden} translucent=${translucent} bg=${String(backgroundColor)}`);
44
+ if (barStyle !== undefined)
45
+ manager.setStyle(barStyle);
46
+ if (hidden !== undefined)
47
+ manager.setHidden(hidden);
48
+ if (translucent !== undefined)
49
+ manager.setTranslucent(translucent);
50
+ if (backgroundColor !== undefined)
51
+ applyBackgroundColor(manager, backgroundColor, animated);
52
+ }, [barStyle, hidden, animated, backgroundColor, translucent]);
53
+ return null;
54
+ };
55
+ StatusBarAndroid.setBarStyle = style => {
56
+ dlog(`StatusBar.setBarStyle android ${style}`);
57
+ getNativeModule(STATUS_BAR_MANAGER)?.setStyle(style);
58
+ };
59
+ StatusBarAndroid.setHidden = hidden => {
60
+ dlog(`StatusBar.setHidden android ${hidden}`);
61
+ getNativeModule(STATUS_BAR_MANAGER)?.setHidden(hidden);
62
+ };
63
+ StatusBarAndroid.setNetworkActivityIndicatorVisible = () => {
64
+ // No Android equivalent, an iOS-only concept.
65
+ dlog('StatusBar.setNetworkActivityIndicatorVisible (android no-op)');
66
+ };
67
+ StatusBarAndroid.setBackgroundColor = (color, animated = false) => {
68
+ dlog(`StatusBar.setBackgroundColor android ${String(color)}`);
69
+ const manager = getNativeModule(STATUS_BAR_MANAGER);
70
+ if (manager === null)
71
+ return;
72
+ applyBackgroundColor(manager, color, animated);
73
+ };
74
+ StatusBarAndroid.setTranslucent = translucent => {
75
+ // RISK: window translucent flag is device-verify-pending (may blank the surface).
76
+ dlog(`StatusBar.setTranslucent android ${translucent}`);
77
+ getNativeModule(STATUS_BAR_MANAGER)?.setTranslucent(translucent);
78
+ };
79
+ // Android exposes the bar height as a native constant; undefined if the module or the
80
+ // constant is absent (older RN, or a fake that doesn't define getConstants). Read lazily
81
+ // (getter, not a value) so nothing touches native at import time.
82
+ Object.defineProperty(StatusBarAndroid, 'currentHeight', {
83
+ get() {
84
+ return getNativeModule(STATUS_BAR_MANAGER)?.getConstants?.()
85
+ .HEIGHT;
86
+ },
87
+ enumerable: true,
88
+ });
89
+ export const StatusBar = StatusBarAndroid;
@@ -0,0 +1 @@
1
+ export * from './index.ios';
@@ -0,0 +1,3 @@
1
+ import type { IStatusBarComponent } from './shared';
2
+ export type { IStatusBarProps, IStatusBarStyle } from './shared';
3
+ export declare const StatusBar: IStatusBarComponent;
@@ -0,0 +1,64 @@
1
+ // StatusBar on iOS: drives the iOS `StatusBarManager` TurboModule from its props
2
+ // (and from static methods). The native contract is RN's spec at
3
+ // .vendors/react-native/.../src/private/specs_DEPRECATED/modules/NativeStatusBarManagerIOS.js:
4
+ // setStyle(statusBarStyle?: string, animated: boolean)
5
+ // setHidden(hidden: boolean, withAnimation: 'none' | 'fade' | 'slide')
6
+ // setNetworkActivityIndicatorVisible(visible: boolean)
7
+ // Only those three setters are mirrored as the hand-written interface, the typed trust
8
+ // boundary getNativeModule<T> resolves against. Metro picks this on an iOS host.
9
+ //
10
+ // The native-call logic stays in the adapter (not the engine): the platform module shape
11
+ // diverges iOS/Android and the headless smokes import this file by name (tsx has no
12
+ // platform picker, so routing through the engine barrel would resolve the iOS base on every
13
+ // platform). The engine owns only the pure shared contract: types, constants, hideTransition.
14
+ import { useEffect } from 'react';
15
+ import { dlog, getNativeModule, STATUS_BAR_MANAGER, STATIC_HIDE_TRANSITION, hideTransition, } from '@symbiote-native/engine';
16
+ // StatusBar renders null and applies its props to the native module in an effect,
17
+ // on mount and on every prop change. Simplification vs RN: RN maintains a
18
+ // prop-merge stack so nested StatusBars compose (deepest/last wins). This module
19
+ // direct-applies a single component's props, which is correct for one StatusBar.
20
+ export const StatusBar = props => {
21
+ const { barStyle, hidden, animated = false, networkActivityIndicatorVisible } = props;
22
+ useEffect(() => {
23
+ // Resolve lazily inside the effect, not at import, keeps this module importable
24
+ // headless before a fake __turboModuleProxy is installed. Non-enforcing: a
25
+ // declarative StatusBar must NOT crash the whole render if the module can't resolve.
26
+ const manager = getNativeModule(STATUS_BAR_MANAGER);
27
+ if (manager === null) {
28
+ dlog('StatusBar: StatusBarManager not resolvable via __turboModuleProxy — skipping');
29
+ return;
30
+ }
31
+ dlog('StatusBar -> applying props to StatusBarManager');
32
+ if (barStyle !== undefined)
33
+ manager.setStyle(barStyle, animated);
34
+ if (hidden !== undefined)
35
+ manager.setHidden(hidden, hideTransition(animated));
36
+ if (networkActivityIndicatorVisible !== undefined) {
37
+ manager.setNetworkActivityIndicatorVisible(networkActivityIndicatorVisible);
38
+ }
39
+ }, [barStyle, hidden, animated, networkActivityIndicatorVisible]);
40
+ return null;
41
+ };
42
+ // The static API mirrors the declarative component: non-throwing. A missing optional
43
+ // native module is a no-op.
44
+ StatusBar.setBarStyle = (style, animated = false) => {
45
+ dlog('StatusBar.setBarStyle');
46
+ getNativeModule(STATUS_BAR_MANAGER)?.setStyle(style, animated);
47
+ };
48
+ StatusBar.setHidden = (hidden, animation = STATIC_HIDE_TRANSITION) => {
49
+ dlog('StatusBar.setHidden');
50
+ getNativeModule(STATUS_BAR_MANAGER)?.setHidden(hidden, animation);
51
+ };
52
+ StatusBar.setNetworkActivityIndicatorVisible = visible => {
53
+ dlog('StatusBar.setNetworkActivityIndicatorVisible');
54
+ getNativeModule(STATUS_BAR_MANAGER)?.setNetworkActivityIndicatorVisible(visible);
55
+ };
56
+ // Android-only on RN, inert on iOS (the iOS status bar has no background color and
57
+ // is never translucent in RN's sense). Present so the contract is platform-uniform.
58
+ StatusBar.setBackgroundColor = () => {
59
+ dlog('StatusBar.setBackgroundColor (ios no-op)');
60
+ };
61
+ StatusBar.setTranslucent = () => {
62
+ dlog('StatusBar.setTranslucent (ios no-op)');
63
+ };
64
+ // currentHeight is Android-only; absent on iOS (RN sets it to null on iOS).
@@ -0,0 +1,4 @@
1
+ // Base / default StatusBar: re-exports the iOS build. Metro overrides this with
2
+ // status-bar.ios.ts / .android.ts on a real host; under tsx / tsc / web the host config
3
+ // resolves here. Filename is the selector, no Platform.OS read. See status-bar-shared.ts.
4
+ export * from './index.ios';
@@ -0,0 +1,6 @@
1
+ import type { FC } from 'react';
2
+ import type { IStatusBarImperative, IStatusBarProps } from '@symbiote-native/engine';
3
+ export type { IStatusBarProps, IStatusBarStyle, IStatusBarAnimation, } from '@symbiote-native/engine';
4
+ export interface IStatusBarComponent extends FC<IStatusBarProps>, IStatusBarImperative {
5
+ currentHeight?: number;
6
+ }
@@ -0,0 +1,6 @@
1
+ // StatusBar is the React-side contract. The pure types + the imperative API + applyStatusBarProps
2
+ // live in @symbiote-native/engine (shared verbatim with every adapter); React supplies only the
3
+ // declarative component shape: an FC that renders null and applies the props in an effect, with
4
+ // the imperative statics attached to the function object (RN's StatusBar). IStatusBarComponent
5
+ // is the one React-coupled type (it names React's FC), so it stays here, not in the engine.
6
+ export {};
@@ -0,0 +1 @@
1
+ export { currentlyFocusedInput, setInputFocused, setInputBlurred, blurTextInput, } from '@symbiote-native/engine';
@@ -0,0 +1,3 @@
1
+ // TextInputState moved to @symbiote-native/engine (a framework-agnostic module: Keyboard.dismiss
2
+ // and TextInput both reach it). This thin re-export keeps the adapter's import path stable.
3
+ export { currentlyFocusedInput, setInputFocused, setInputBlurred, blurTextInput, } from '@symbiote-native/engine';
@@ -0,0 +1 @@
1
+ export { ToastAndroid } from '@symbiote-native/engine';
@@ -0,0 +1,4 @@
1
+ // ToastAndroid now lives framework-agnostic in @symbiote-native/engine (imperative
2
+ // native-bridge module, no visual, no lifecycle). The React adapter re-exports it
3
+ // verbatim so the public surface is unchanged. See ADR 0019.
4
+ export { ToastAndroid } from '@symbiote-native/engine';
@@ -0,0 +1 @@
1
+ export { Vibration } from '@symbiote-native/engine';
@@ -0,0 +1,4 @@
1
+ // Vibration now lives framework-agnostic in @symbiote-native/engine (imperative native-bridge
2
+ // module, no visual, no lifecycle). The React adapter re-exports it verbatim; the
3
+ // platform split (vibration.ios/vibration.android) lives inside engine. See ADR 0019.
4
+ export { Vibration } from '@symbiote-native/engine';
@@ -0,0 +1,7 @@
1
+ export declare const LegacyRoot = 0;
2
+ export declare const ConcurrentRoot = 1;
3
+ export declare const NoEventPriority = 0;
4
+ export declare const DiscreteEventPriority = 2;
5
+ export declare const ContinuousEventPriority = 8;
6
+ export declare const DefaultEventPriority = 32;
7
+ export declare const IdleEventPriority = 268435456;
@@ -0,0 +1,12 @@
1
+ // Inlined from react-reconciler/constants. The package ships CommonJS only, so
2
+ // importing the subpath under ESM/bundler resolution is fragile; these values
3
+ // are stable.
4
+ // https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactRootTags.js
5
+ // https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactEventPriorities.js
6
+ export const LegacyRoot = 0;
7
+ export const ConcurrentRoot = 1;
8
+ export const NoEventPriority = 0;
9
+ export const DiscreteEventPriority = 2;
10
+ export const ContinuousEventPriority = 8;
11
+ export const DefaultEventPriority = 32;
12
+ export const IdleEventPriority = 268435456;
@@ -0,0 +1,7 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type IRootTag, type SymbioteSurface } from '@symbiote-native/engine';
3
+ export declare function mount(rootTag: IRootTag, element: ReactNode): SymbioteSurface;
4
+ export declare function unmount(rootTag: IRootTag): void;
5
+ declare global {
6
+ var RN$stopSurface: ((surfaceId: number) => void) | undefined;
7
+ }
@@ -0,0 +1,60 @@
1
+ // Mount a React element tree onto a Fabric surface. The native host hands us a
2
+ // rootTag (via AppRegistry.registerRunnable); we create a surface for it and let
3
+ // the reconciler drive shared, which commits into nativeFabricUIManager.
4
+ import { createSurface, disposeRoot, setEventDispatcher, dlog, } from '@symbiote-native/engine';
5
+ import reconciler, { withDiscretePriority } from './host-config';
6
+ import { LegacyRoot } from './reconciler-constants';
7
+ const noop = () => { };
8
+ // A native event runs the listener (which may call setState) outside React's
9
+ // loop. Run it at discrete priority so the update takes the sync lane, then
10
+ // flush that work synchronously to paint the result.
11
+ setEventDispatcher(run => {
12
+ withDiscretePriority(run);
13
+ // @ts-expect-error flushSyncWork exists at runtime in react-reconciler 0.33
14
+ reconciler.flushSyncWork();
15
+ });
16
+ const containers = new Map();
17
+ // Unmount a surface's React tree (render null → empty completeRoot, clearing the
18
+ // native views) and drop its shared root container so a later mount on the same
19
+ // rootTag rebuilds from scratch instead of cloning the stopped surface's dead handles.
20
+ function teardown(rootTag) {
21
+ const container = containers.get(rootTag);
22
+ if (container === undefined)
23
+ return;
24
+ // @ts-expect-error updateContainerSync exists at runtime in react-reconciler 0.33
25
+ reconciler.updateContainerSync(null, container, null, noop);
26
+ // @ts-expect-error flushSyncWork exists at runtime in react-reconciler 0.33
27
+ reconciler.flushSyncWork();
28
+ containers.delete(rootTag);
29
+ disposeRoot(rootTag);
30
+ }
31
+ export function mount(rootTag, element) {
32
+ // A re-mount on a live rootTag (host restarted the surface without stopping it
33
+ // first) starts clean. Otherwise the stale container double-drives the surface.
34
+ teardown(rootTag);
35
+ const surface = createSurface(rootTag);
36
+ const container = reconciler.createContainer(surface, LegacyRoot, null, false, null, 'symbiote', noop, noop, noop, noop, null);
37
+ containers.set(rootTag, container);
38
+ // react-reconciler 0.33 exposes updateContainerSync + flushSyncWork for an
39
+ // immediate render/commit; @types 0.32 still lists the older updateContainer /
40
+ // flushSync names, so these calls are type-suppressed until the types catch up.
41
+ // @ts-expect-error updateContainerSync exists at runtime in react-reconciler 0.33
42
+ reconciler.updateContainerSync(element, container, null, noop);
43
+ // @ts-expect-error flushSyncWork exists at runtime in react-reconciler 0.33
44
+ reconciler.flushSyncWork();
45
+ return surface;
46
+ }
47
+ // Tear down a surface by rootTag, the public pair of `mount`. This is also the JS half of
48
+ // the bridgeless `RN$stopSurface` contract (see installStopSurfaceGlobal): the native
49
+ // AppRegistryBinding calls our global to stop a surface; we unmount its tree and dispose its root.
50
+ export function unmount(rootTag) {
51
+ dlog(`unmount root=${rootTag}`);
52
+ teardown(rootTag);
53
+ }
54
+ function installStopSurfaceGlobal() {
55
+ globalThis.RN$stopSurface = (surfaceId) => {
56
+ unmount(surfaceId);
57
+ };
58
+ dlog('installed global.RN$stopSurface');
59
+ }
60
+ installStopSurfaceGlobal();
@@ -0,0 +1 @@
1
+ export type { IResponderProps } from '@symbiote-native/components';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export type { IViewStyle, ITextStyle, IStyleProp, IDimensionValue, IFlexAlign, IFlexJustify, ITransformProp, IBoxShadowValue, IDropShadowValue, IFilterFunction, IBlendMode, } from '@symbiote-native/engine';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ // Re-exports @symbiote-native/css-parser verbatim from INSIDE this package, so a consuming app's own
2
+ // require('@symbiote-native/react/metro-css-parser') resolves css-parser relative to THIS file's
3
+ // location (adapters/react/node_modules, where css-parser IS a real dependency — see
4
+ // package.json), not relative to the app's own node_modules, which does not and should not
5
+ // need to declare @symbiote-native/css-parser itself. Node resolves each require() relative to the
6
+ // requiring FILE's own location, so this indirection is what actually removes the extra install
7
+ // step, not pnpm hoisting (which does not propagate this transitively across workspace packages
8
+ // the way a flat classic node_modules would). .cjs, not .js: this package is "type": "module",
9
+ // and Metro's babelTransformerPath loading expects a require()-able module. See the
10
+ // symbiote-sfc-style-compiler skill.
11
+ module.exports = require('@symbiote-native/css-parser');
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@symbiote-native/react",
3
+ "version": "0.1.0",
4
+ "description": "SymbioteJS's React adapter — a react-reconciler host config (mutation mode) driving real native iOS/Android views through stock React Native Fabric.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/OneEyed1366/symbiote-native.git",
8
+ "directory": "adapters/react"
9
+ },
10
+ "homepage": "https://github.com/OneEyed1366/symbiote-native/tree/master/adapters/react#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/OneEyed1366/symbiote-native/issues"
13
+ },
14
+ "author": "Andrey Prokopenko <psevdoproger@gmail.com>",
15
+ "type": "module",
16
+ "main": "./build/index.js",
17
+ "module": "./build/index.js",
18
+ "types": "./build/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./build/index.d.ts",
22
+ "default": "./build/index.js"
23
+ },
24
+ "./metro-css-parser": "./metro-css-parser.cjs"
25
+ },
26
+ "files": [
27
+ "build",
28
+ "metro-css-parser.cjs"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "dependencies": {
34
+ "react-reconciler": "^0.33.0",
35
+ "@symbiote-native/components": "0.1.0",
36
+ "@symbiote-native/engine": "0.1.0",
37
+ "@symbiote-native/css-parser": "0.1.0"
38
+ },
39
+ "peerDependencies": {
40
+ "react": ">=19.0.0",
41
+ "react-native": ">=0.86"
42
+ },
43
+ "devDependencies": {
44
+ "@types/react": "^19.2.0",
45
+ "@types/react-reconciler": "^0.32.2",
46
+ "react": "19.2.3",
47
+ "@symbiote-native/test-utils": "0.0.0"
48
+ },
49
+ "scripts": {
50
+ "typecheck": "tsc --build",
51
+ "format": "prettier --write \"src/**/*.{ts,tsx}\""
52
+ }
53
+ }