@callstack/react-native-brownfield 3.0.0 → 3.1.0-rc.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.
@@ -17,12 +17,17 @@ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
17
17
  import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
18
18
  import com.facebook.react.soloader.OpenSourceMergedSoMapping
19
19
  import com.facebook.soloader.SoLoader
20
+ import java.util.concurrent.CopyOnWriteArrayList
20
21
  import java.util.concurrent.atomic.AtomicBoolean
21
22
 
22
23
  fun interface OnJSBundleLoaded {
23
24
  operator fun invoke(initialized: Boolean)
24
25
  }
25
26
 
27
+ fun interface OnMessageListener {
28
+ fun onMessage(message: String)
29
+ }
30
+
26
31
  /**
27
32
  * The threshold RN version based on which we decide whether to
28
33
  * load JNI libs or not. We only load JNI libs on version less
@@ -31,9 +36,12 @@ fun interface OnJSBundleLoaded {
31
36
  private const val RN_THRESHOLD_VERSION = "0.80.0"
32
37
 
33
38
  class ReactNativeBrownfield private constructor(val reactHost: ReactHost) {
39
+ private val messageListeners = CopyOnWriteArrayList<OnMessageListener>()
40
+
34
41
  companion object {
35
42
  private lateinit var instance: ReactNativeBrownfield
36
43
  private val initialized = AtomicBoolean()
44
+ private const val LOG_TAG = "ReactNativeBrownfield"
37
45
 
38
46
  @JvmStatic
39
47
  val shared: ReactNativeBrownfield get() = instance
@@ -77,7 +85,8 @@ class ReactNativeBrownfield private constructor(val reactHost: ReactHost) {
77
85
  packageList = (options["packages"] as? List<*> ?: emptyList<ReactPackage>())
78
86
  .filterIsInstance<ReactPackage>(),
79
87
  jsMainModulePath = options["mainModuleName"] as? String ?: "index",
80
- jsBundleAssetPath = options["bundleAssetPath"] as? String ?: "index.android.bundle",
88
+ jsBundleAssetPath = options["bundleAssetPath"] as? String
89
+ ?: "index.android.bundle",
81
90
  jsBundleFilePath = options["bundleFilePath"] as? String,
82
91
  useDevSupport = options["useDeveloperSupport"] as? Boolean
83
92
  ?: ReactBuildConfig.DEBUG,
@@ -112,6 +121,42 @@ class ReactNativeBrownfield private constructor(val reactHost: ReactHost) {
112
121
  }
113
122
  }
114
123
 
124
+ /**
125
+ * Send a serialized JSON message to the React Native JS application. This resembles the web `window.postMessage` API.
126
+ * @note This method is available only on the New Architecture - on Old Architecture, it will be a no-op.
127
+ * @param message - The serialized JSON message to send to the React Native JS application.
128
+ * @example
129
+ * val json = JSONObject().put("text", text).toString()
130
+ * ReactNativeBrownfield.shared.postMessage(json)
131
+ */
132
+ fun postMessage(message: String) {
133
+ ReactNativeBrownfieldModule.emitMessageFromNative(message)
134
+ }
135
+
136
+ /**
137
+ * Register a listener for messages sent from the React Native JS application.
138
+ * @note This method is available only on the New Architecture - on Old Architecture, it will be a no-op.
139
+ * @param listener - The listener to register.
140
+ */
141
+ fun addMessageListener(listener: OnMessageListener) {
142
+ messageListeners.add(listener)
143
+ }
144
+
145
+ /**
146
+ * Remove a previously registered message listener.
147
+ * @note This method is available only on the New Architecture - on Old Architecture, it will be a no-op.
148
+ * @param listener - The listener to remove.
149
+ */
150
+ fun removeMessageListener(listener: OnMessageListener) {
151
+ messageListeners.remove(listener)
152
+ }
153
+
154
+ internal fun dispatchMessage(message: String) {
155
+ for (listener in messageListeners) {
156
+ listener.onMessage(message)
157
+ }
158
+ }
159
+
115
160
  fun createView(
116
161
  activity: FragmentActivity?,
117
162
  moduleName: String,
@@ -1,12 +1,33 @@
1
1
  package com.callstack.reactnativebrownfield
2
2
 
3
+ import android.util.Log
3
4
  import com.facebook.react.bridge.ReactApplicationContext
4
5
  import com.facebook.react.bridge.ReactMethod
6
+ import com.facebook.react.bridge.buildReadableMap
5
7
 
6
- class ReactNativeBrownfieldModule(reactContext: ReactApplicationContext) :
8
+ class ReactNativeBrownfieldModule(val reactContext: ReactApplicationContext) :
7
9
  NativeReactNativeBrownfieldModuleSpec(reactContext) {
8
10
  companion object {
9
11
  var shouldPopToNative: Boolean = false
12
+ private const val LOG_TAG = "ReactNativeBrownfieldModule"
13
+
14
+ private var sharedInstance: ReactNativeBrownfieldModule? = null
15
+
16
+ fun emitMessageFromNative(text: String) {
17
+ if (sharedInstance == null) {
18
+ Log.w(
19
+ LOG_TAG,
20
+ "No instance of ReactNativeBrownfieldModule found. Message will not be emitted."
21
+ )
22
+ }
23
+ sharedInstance?.emitOnBrownfieldMessage(buildReadableMap {
24
+ put("text", text)
25
+ })
26
+ }
27
+ }
28
+
29
+ init {
30
+ sharedInstance = this
10
31
  }
11
32
 
12
33
  @ReactMethod
@@ -25,6 +46,11 @@ class ReactNativeBrownfieldModule(reactContext: ReactApplicationContext) :
25
46
  shouldPopToNative = enabled
26
47
  }
27
48
 
49
+ override fun postMessage(message: String) {
50
+ ReactNativeBrownfield.shared.dispatchMessage(message)
51
+ }
52
+
53
+
28
54
  private fun onBackPressed() {
29
55
  reactApplicationContext.currentActivity?.runOnUiThread {
30
56
  reactApplicationContext.currentActivity?.onBackPressed()
@@ -1,5 +1,6 @@
1
1
  package com.callstack.reactnativebrownfield
2
2
 
3
+ import android.util.Log
3
4
  import com.facebook.react.bridge.ReactApplicationContext
4
5
  import com.facebook.react.bridge.ReactContextBaseJavaModule
5
6
  import com.facebook.react.bridge.ReactMethod
@@ -8,6 +9,14 @@ class ReactNativeBrownfieldModule(reactContext: ReactApplicationContext) :
8
9
  ReactContextBaseJavaModule(reactContext) {
9
10
  companion object {
10
11
  var shouldPopToNative: Boolean = false
12
+ private const val LOG_TAG = "ReactNativeBrownfieldModule"
13
+
14
+ fun emitMessageFromNative(text: String) {
15
+ Log.w(
16
+ LOG_TAG,
17
+ "ReactNativeBrownfieldModule::emitMessageFromNative only supports the New Architecture. This call is ineffective and will not cause any messages to be emitted."
18
+ )
19
+ }
11
20
  }
12
21
 
13
22
  @ReactMethod
@@ -26,6 +35,17 @@ class ReactNativeBrownfieldModule(reactContext: ReactApplicationContext) :
26
35
  shouldPopToNative = isFirstRoute
27
36
  }
28
37
 
38
+ @ReactMethod
39
+ fun postMessage(message: String) {
40
+ ReactNativeBrownfield.shared.dispatchMessage(message)
41
+ }
42
+
43
+ @ReactMethod
44
+ fun addListener(eventName: String) {}
45
+
46
+ @ReactMethod
47
+ fun removeListeners(count: Double) {}
48
+
29
49
  private fun onBackPressed() {
30
50
  reactApplicationContext.currentActivity?.runOnUiThread {
31
51
  reactApplicationContext.currentActivity?.onBackPressed()
@@ -9,4 +9,12 @@ extension Notification.Name {
9
9
  * Notification sent to enable/disable the pop gesture recognizer.
10
10
  */
11
11
  public static let togglePopGestureRecognizer = Notification.Name("TogglePopGestureRecognizerNotification")
12
+ /**
13
+ * Notification sent when JS calls postMessage. UserInfo contains "message" key.
14
+ */
15
+ public static let brownfieldMessageFromJS = Notification.Name("BrownfieldMessageFromJSNotification")
16
+ /**
17
+ * Notification sent by native code to forward a message to JS. UserInfo contains "message" key.
18
+ */
19
+ public static let brownfieldMessageToJS = Notification.Name("BrownfieldMessageToJSNotification")
12
20
  }
@@ -134,4 +134,42 @@ internal import Expo
134
134
  ReactNativeHostRuntime.shared.startReactNative(onBundleLoaded: onBundleLoaded)
135
135
  #endif
136
136
  }
137
+
138
+ /**
139
+ * Send a serialized JSON message to the React Native JS application.
140
+ * The message is delivered as a `brownfieldMessage` DeviceEventEmitter event.
141
+ *
142
+ * @param message - The serialized JSON message to send to the React Native JS application.
143
+ * @example
144
+ * let json = "{\"text\":\"\(text)\"}"
145
+ * ReactNativeBrownfield.shared.postMessage(json)
146
+ */
147
+ @objc public func postMessage(_ message: String) {
148
+ let userInfo: [String: Any] = ["message": message]
149
+ DispatchQueue.main.async {
150
+ NotificationCenter.default.post(
151
+ name: Notification.Name.brownfieldMessageToJS,
152
+ object: nil,
153
+ userInfo: userInfo
154
+ )
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Subscribe to messages sent from JavaScript via `ReactNativeBrownfield.postMessage()`.
160
+ *
161
+ * @param handler Called with the raw JSON string sent from JS.
162
+ * @return An observer token. Pass it to `NotificationCenter.default.removeObserver(_:)` to unsubscribe.
163
+ */
164
+ @objc public func onMessage(_ handler: @escaping (String) -> Void) -> NSObjectProtocol {
165
+ return NotificationCenter.default.addObserver(
166
+ forName: Notification.Name.brownfieldMessageFromJS,
167
+ object: nil,
168
+ queue: .main
169
+ ) { notification in
170
+ if let message = notification.userInfo?["message"] as? String {
171
+ handler(message)
172
+ }
173
+ }
174
+ }
137
175
  }
@@ -3,6 +3,10 @@
3
3
  #import <ReactNativeBrownfield/ReactNativeBrownfield.h>
4
4
 
5
5
  @interface ReactNativeBrownfieldModule : NativeReactNativeBrownfieldModuleSpecBase <NativeReactNativeBrownfieldModuleSpec>
6
+
7
+ // Static helper for native code to emit events
8
+ + (void)emitMessageFromNative:(NSString *)message;
9
+
6
10
  @end
7
11
 
8
12
  #endif
@@ -10,6 +10,44 @@
10
10
 
11
11
  RCT_EXPORT_MODULE(ReactNativeBrownfield);
12
12
 
13
+ static ReactNativeBrownfieldModule *_sharedInstance = nil;
14
+
15
+ - (instancetype)init {
16
+ self = [super init];
17
+ if (self) {
18
+ _sharedInstance = self;
19
+
20
+ [[NSNotificationCenter defaultCenter] addObserver:self
21
+ selector:@selector(handleNativeToJSMessage:)
22
+ name:@"BrownfieldMessageToJSNotification"
23
+ object:nil];
24
+ }
25
+ return self;
26
+ }
27
+
28
+ - (void)dealloc {
29
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
30
+
31
+ if (_sharedInstance == self) {
32
+ _sharedInstance = nil;
33
+ }
34
+ }
35
+
36
+ - (void)handleNativeToJSMessage:(NSNotification *)notification {
37
+ NSString *message = notification.userInfo[@"message"];
38
+ if (message) {
39
+ [ReactNativeBrownfieldModule emitMessageFromNative:message];
40
+ }
41
+ }
42
+
43
+ + (void)emitMessageFromNative:(NSString *)message {
44
+ if (_sharedInstance) {
45
+ [_sharedInstance emitOnBrownfieldMessage:@{ @"text": message }];
46
+ } else {
47
+ NSLog(@"ReactNativeBrownfieldModule is not initialized, dropping message");
48
+ }
49
+ }
50
+
13
51
  RCT_EXPORT_METHOD(setPopGestureRecognizerEnabled:(BOOL)enabled) {
14
52
  [ReactNativeBrownfieldModuleImpl setPopGestureRecognizerEnabled:enabled];
15
53
  }
@@ -18,6 +56,14 @@ RCT_EXPORT_METHOD(popToNative:(BOOL)animated) {
18
56
  [ReactNativeBrownfieldModuleImpl popToNativeWithAnimated:animated];
19
57
  }
20
58
 
59
+ RCT_EXPORT_METHOD(postMessage:(NSString *)message) {
60
+ [ReactNativeBrownfieldModuleImpl postMessage:message];
61
+ }
62
+
63
+ RCT_EXPORT_METHOD(addListener:(NSString *)eventName) {}
64
+
65
+ RCT_EXPORT_METHOD(removeListeners:(double)count) {}
66
+
21
67
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
22
68
  return std::make_shared<facebook::react::NativeReactNativeBrownfieldModuleSpecJSI>(params);
23
69
  }
@@ -15,4 +15,11 @@ public class ReactNativeBrownfieldModuleImpl: NSObject {
15
15
  NotificationCenter.default.post(name: Notification.Name.popToNative, object: nil, userInfo: userInfo)
16
16
  }
17
17
  }
18
+
19
+ static public func postMessage(_ message: String) {
20
+ let userInfo: [String: Any] = ["message": message]
21
+ DispatchQueue.main.async {
22
+ NotificationCenter.default.post(name: Notification.Name.brownfieldMessageFromJS, object: nil, userInfo: userInfo)
23
+ }
24
+ }
18
25
  }
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeReactNativeBrownfieldModule.ts"],"mappings":"gFACA,IAAAA,YAAA,CAAAC,OAAA,iBAAmD,IAAAC,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAqBpCC,gCAAmB,CAACC,YAAY,CAAO,uBAAuB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeReactNativeBrownfieldModule.ts"],"mappings":"gFACA,IAAAA,YAAA,CAAAC,OAAA,iBAAmD,IAAAC,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAiCpCC,gCAAmB,CAACC,YAAY,CAAO,uBAAuB,CAAC","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _reactNative=require("react-native");var _NativeReactNativeBrownfieldModule=_interopRequireDefault(require("./NativeReactNativeBrownfieldModule"));var ReactNativeBrownfield={popToNative:function popToNative(animated){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.popToNative(!!animated);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.popToNative(false);}else{console.warn('Not implemented: popToNative');}},setNativeBackGestureAndButtonEnabled:function setNativeBackGestureAndButtonEnabled(enabled){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.setPopGestureRecognizerEnabled(enabled);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.setHardwareBackButtonEnabled(enabled);}else{console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');}}};var _default=exports.default=ReactNativeBrownfield;
1
+ var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _reactNative=require("react-native");var _NativeReactNativeBrownfieldModule=_interopRequireDefault(require("./NativeReactNativeBrownfieldModule"));var ReactNativeBrownfield={popToNative:function popToNative(animated){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.popToNative(!!animated);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.popToNative(false);}else{console.warn('Not implemented: popToNative');}},setNativeBackGestureAndButtonEnabled:function setNativeBackGestureAndButtonEnabled(enabled){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.setPopGestureRecognizerEnabled(enabled);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.setHardwareBackButtonEnabled(enabled);}else{console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');}},postMessage:function postMessage(data){var serialized=JSON.stringify(data);_NativeReactNativeBrownfieldModule.default.postMessage(serialized);},onMessage:function onMessage(callback){var subscription=_NativeReactNativeBrownfieldModule.default.onBrownfieldMessage(function(payload){try{callback({data:JSON.parse(payload.text)});}catch(_unused){callback({data:payload.text});}});return{remove:function remove(){return subscription.remove();}};}};var _default=exports.default=ReactNativeBrownfield;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_NativeReactNativeBrownfieldModule","_interopRequireDefault","ReactNativeBrownfield","popToNative","animated","Platform","OS","ReactNativeBrownfieldModule","console","warn","setNativeBackGestureAndButtonEnabled","enabled","setPopGestureRecognizerEnabled","setHardwareBackButtonEnabled","_default","exports","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"mKAAA,IAAAA,YAAA,CAAAC,OAAA,iBACA,IAAAC,kCAAA,CAAAC,sBAAA,CAAAF,OAAA,yCAEA,GAAM,CAAAG,qBAAqB,CAAG,CAC5BC,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,QAAkB,CAAW,CACzC,GAAIC,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBC,0CAA2B,CAACJ,WAAW,CAAC,CAAC,CAACC,QAAQ,CAAC,CACrD,CAAC,IAAM,IAAIC,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCC,0CAA2B,CAACJ,WAAW,CAAC,KAAK,CAAC,CAChD,CAAC,IAAM,CACLK,OAAO,CAACC,IAAI,CAAC,8BAA8B,CAAC,CAC9C,CACF,CAAC,CAEDC,oCAAoC,CAAE,QAAtC,CAAAA,oCAAoCA,CAAGC,OAAgB,CAAW,CAChE,GAAIN,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBC,0CAA2B,CAACK,8BAA8B,CAACD,OAAO,CAAC,CACrE,CAAC,IAAM,IAAIN,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCC,0CAA2B,CAACM,4BAA4B,CAACF,OAAO,CAAC,CACnE,CAAC,IAAM,CACLH,OAAO,CAACC,IAAI,CAAC,qDAAqD,CAAC,CACrE,CACF,CACF,CAAC,CAAC,IAAAK,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAEad,qBAAqB","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_NativeReactNativeBrownfieldModule","_interopRequireDefault","ReactNativeBrownfield","popToNative","animated","Platform","OS","ReactNativeBrownfieldModule","console","warn","setNativeBackGestureAndButtonEnabled","enabled","setPopGestureRecognizerEnabled","setHardwareBackButtonEnabled","postMessage","data","serialized","JSON","stringify","onMessage","callback","subscription","onBrownfieldMessage","payload","parse","text","_unused","remove","_default","exports","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"mKAAA,IAAAA,YAAA,CAAAC,OAAA,iBAEA,IAAAC,kCAAA,CAAAC,sBAAA,CAAAF,OAAA,yCAMA,GAAM,CAAAG,qBAAqB,CAAG,CAQ5BC,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,QAAkB,CAAW,CACzC,GAAIC,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBC,0CAA2B,CAACJ,WAAW,CAAC,CAAC,CAACC,QAAQ,CAAC,CACrD,CAAC,IAAM,IAAIC,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCC,0CAA2B,CAACJ,WAAW,CAAC,KAAK,CAAC,CAChD,CAAC,IAAM,CACLK,OAAO,CAACC,IAAI,CAAC,8BAA8B,CAAC,CAC9C,CACF,CAAC,CAUDC,oCAAoC,CAAE,QAAtC,CAAAA,oCAAoCA,CAAGC,OAAgB,CAAW,CAChE,GAAIN,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBC,0CAA2B,CAACK,8BAA8B,CAACD,OAAO,CAAC,CACrE,CAAC,IAAM,IAAIN,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCC,0CAA2B,CAACM,4BAA4B,CAACF,OAAO,CAAC,CACnE,CAAC,IAAM,CACLH,OAAO,CAACC,IAAI,CAAC,qDAAqD,CAAC,CACrE,CACF,CAAC,CAYDK,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,IAAa,CAAW,CACpC,GAAM,CAAAC,UAAU,CAAGC,IAAI,CAACC,SAAS,CAACH,IAAI,CAAC,CACvCR,0CAA2B,CAACO,WAAW,CAACE,UAAU,CAAC,CACrD,CAAC,CAeDG,SAAS,CAAE,QAAX,CAAAA,SAASA,CACPC,QAAuC,CACZ,CAC3B,GAAM,CAAAC,YAAY,CAAGd,0CAA2B,CAACe,mBAAmB,CAClE,SAACC,OAAO,CAAK,CACX,GAAI,CACFH,QAAQ,CAAC,CAAEL,IAAI,CAAEE,IAAI,CAACO,KAAK,CAACD,OAAO,CAACE,IAAI,CAAE,CAAC,CAAC,CAC9C,CAAE,MAAAC,OAAA,CAAM,CACNN,QAAQ,CAAC,CAAEL,IAAI,CAAEQ,OAAO,CAACE,IAAK,CAAC,CAAC,CAClC,CACF,CACF,CAAC,CACD,MAAO,CAAEE,MAAM,CAAE,QAAR,CAAAA,MAAMA,CAAA,QAAQ,CAAAN,YAAY,CAACM,MAAM,CAAC,CAAC,EAAC,CAAC,CAChD,CACF,CAAC,CAAC,IAAAC,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAEa5B,qBAAqB","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeReactNativeBrownfieldModule.ts"],"mappings":"gFACA,IAAAA,YAAA,CAAAC,OAAA,iBAAmD,IAAAC,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAqBpCC,gCAAmB,CAACC,YAAY,CAAO,uBAAuB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeReactNativeBrownfieldModule.ts"],"mappings":"gFACA,IAAAA,YAAA,CAAAC,OAAA,iBAAmD,IAAAC,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAiCpCC,gCAAmB,CAACC,YAAY,CAAO,uBAAuB,CAAC","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _reactNative=require("react-native");var _NativeReactNativeBrownfieldModule=_interopRequireDefault(require("./NativeReactNativeBrownfieldModule"));var ReactNativeBrownfield={popToNative:function popToNative(animated){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.popToNative(!!animated);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.popToNative(false);}else{console.warn('Not implemented: popToNative');}},setNativeBackGestureAndButtonEnabled:function setNativeBackGestureAndButtonEnabled(enabled){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.setPopGestureRecognizerEnabled(enabled);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.setHardwareBackButtonEnabled(enabled);}else{console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');}}};var _default=exports.default=ReactNativeBrownfield;
1
+ var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _reactNative=require("react-native");var _NativeReactNativeBrownfieldModule=_interopRequireDefault(require("./NativeReactNativeBrownfieldModule"));var ReactNativeBrownfield={popToNative:function popToNative(animated){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.popToNative(!!animated);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.popToNative(false);}else{console.warn('Not implemented: popToNative');}},setNativeBackGestureAndButtonEnabled:function setNativeBackGestureAndButtonEnabled(enabled){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.setPopGestureRecognizerEnabled(enabled);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.setHardwareBackButtonEnabled(enabled);}else{console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');}},postMessage:function postMessage(data){var serialized=JSON.stringify(data);_NativeReactNativeBrownfieldModule.default.postMessage(serialized);},onMessage:function onMessage(callback){var subscription=_NativeReactNativeBrownfieldModule.default.onBrownfieldMessage(function(payload){try{callback({data:JSON.parse(payload.text)});}catch(_unused){callback({data:payload.text});}});return{remove:function remove(){return subscription.remove();}};}};var _default=exports.default=ReactNativeBrownfield;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_NativeReactNativeBrownfieldModule","_interopRequireDefault","ReactNativeBrownfield","popToNative","animated","Platform","OS","ReactNativeBrownfieldModule","console","warn","setNativeBackGestureAndButtonEnabled","enabled","setPopGestureRecognizerEnabled","setHardwareBackButtonEnabled","_default","exports","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"mKAAA,IAAAA,YAAA,CAAAC,OAAA,iBACA,IAAAC,kCAAA,CAAAC,sBAAA,CAAAF,OAAA,yCAEA,GAAM,CAAAG,qBAAqB,CAAG,CAC5BC,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,QAAkB,CAAW,CACzC,GAAIC,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBC,0CAA2B,CAACJ,WAAW,CAAC,CAAC,CAACC,QAAQ,CAAC,CACrD,CAAC,IAAM,IAAIC,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCC,0CAA2B,CAACJ,WAAW,CAAC,KAAK,CAAC,CAChD,CAAC,IAAM,CACLK,OAAO,CAACC,IAAI,CAAC,8BAA8B,CAAC,CAC9C,CACF,CAAC,CAEDC,oCAAoC,CAAE,QAAtC,CAAAA,oCAAoCA,CAAGC,OAAgB,CAAW,CAChE,GAAIN,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBC,0CAA2B,CAACK,8BAA8B,CAACD,OAAO,CAAC,CACrE,CAAC,IAAM,IAAIN,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCC,0CAA2B,CAACM,4BAA4B,CAACF,OAAO,CAAC,CACnE,CAAC,IAAM,CACLH,OAAO,CAACC,IAAI,CAAC,qDAAqD,CAAC,CACrE,CACF,CACF,CAAC,CAAC,IAAAK,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAEad,qBAAqB","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_NativeReactNativeBrownfieldModule","_interopRequireDefault","ReactNativeBrownfield","popToNative","animated","Platform","OS","ReactNativeBrownfieldModule","console","warn","setNativeBackGestureAndButtonEnabled","enabled","setPopGestureRecognizerEnabled","setHardwareBackButtonEnabled","postMessage","data","serialized","JSON","stringify","onMessage","callback","subscription","onBrownfieldMessage","payload","parse","text","_unused","remove","_default","exports","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"mKAAA,IAAAA,YAAA,CAAAC,OAAA,iBAEA,IAAAC,kCAAA,CAAAC,sBAAA,CAAAF,OAAA,yCAMA,GAAM,CAAAG,qBAAqB,CAAG,CAQ5BC,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,QAAkB,CAAW,CACzC,GAAIC,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBC,0CAA2B,CAACJ,WAAW,CAAC,CAAC,CAACC,QAAQ,CAAC,CACrD,CAAC,IAAM,IAAIC,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCC,0CAA2B,CAACJ,WAAW,CAAC,KAAK,CAAC,CAChD,CAAC,IAAM,CACLK,OAAO,CAACC,IAAI,CAAC,8BAA8B,CAAC,CAC9C,CACF,CAAC,CAUDC,oCAAoC,CAAE,QAAtC,CAAAA,oCAAoCA,CAAGC,OAAgB,CAAW,CAChE,GAAIN,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBC,0CAA2B,CAACK,8BAA8B,CAACD,OAAO,CAAC,CACrE,CAAC,IAAM,IAAIN,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCC,0CAA2B,CAACM,4BAA4B,CAACF,OAAO,CAAC,CACnE,CAAC,IAAM,CACLH,OAAO,CAACC,IAAI,CAAC,qDAAqD,CAAC,CACrE,CACF,CAAC,CAYDK,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,IAAa,CAAW,CACpC,GAAM,CAAAC,UAAU,CAAGC,IAAI,CAACC,SAAS,CAACH,IAAI,CAAC,CACvCR,0CAA2B,CAACO,WAAW,CAACE,UAAU,CAAC,CACrD,CAAC,CAeDG,SAAS,CAAE,QAAX,CAAAA,SAASA,CACPC,QAAuC,CACZ,CAC3B,GAAM,CAAAC,YAAY,CAAGd,0CAA2B,CAACe,mBAAmB,CAClE,SAACC,OAAO,CAAK,CACX,GAAI,CACFH,QAAQ,CAAC,CAAEL,IAAI,CAAEE,IAAI,CAACO,KAAK,CAACD,OAAO,CAACE,IAAI,CAAE,CAAC,CAAC,CAC9C,CAAE,MAAAC,OAAA,CAAM,CACNN,QAAQ,CAAC,CAAEL,IAAI,CAAEQ,OAAO,CAACE,IAAK,CAAC,CAAC,CAClC,CACF,CACF,CAAC,CACD,MAAO,CAAEE,MAAM,CAAE,QAAR,CAAAA,MAAMA,CAAA,QAAQ,CAAAN,YAAY,CAACM,MAAM,CAAC,CAAC,EAAC,CAAC,CAChD,CACF,CAAC,CAAC,IAAAC,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAEa5B,qBAAqB","ignoreList":[]}
@@ -1,4 +1,7 @@
1
- import type { TurboModule } from 'react-native';
1
+ import type { CodegenTypes, TurboModule } from 'react-native';
2
+ export type BrownfieldMessagePayload = {
3
+ text: string;
4
+ };
2
5
  export interface Spec extends TurboModule {
3
6
  /**
4
7
  * Navigate back to the native part of the application.
@@ -14,6 +17,11 @@ export interface Spec extends TurboModule {
14
17
  * @platform android
15
18
  */
16
19
  setHardwareBackButtonEnabled(enabled: boolean): void;
20
+ /**
21
+ * Send a serialized JSON message to the native host application.
22
+ */
23
+ postMessage(message: string): void;
24
+ readonly onBrownfieldMessage: CodegenTypes.EventEmitter<BrownfieldMessagePayload>;
17
25
  }
18
26
  declare const _default: Spec;
19
27
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeReactNativeBrownfieldModule.d.ts","sourceRoot":"","sources":["../../../../src/NativeReactNativeBrownfieldModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IAErC;;;OAGG;IACH,8BAA8B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAEvD;;;OAGG;IACH,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACtD;;AAED,wBAA+E"}
1
+ {"version":3,"file":"NativeReactNativeBrownfieldModule.d.ts","sourceRoot":"","sources":["../../../../src/NativeReactNativeBrownfieldModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG9D,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IAErC;;;OAGG;IACH,8BAA8B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAEvD;;;OAGG;IACH,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAErD;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAGnC,QAAQ,CAAC,mBAAmB,EAAE,YAAY,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC;CACnF;;AAED,wBAA+E"}
@@ -1,6 +1,51 @@
1
+ export interface MessageEvent {
2
+ data: unknown;
3
+ }
1
4
  declare const ReactNativeBrownfield: {
5
+ /**
6
+ * Pop to the native screen.
7
+ * @param animated - Whether to animate the transition (iOS only).
8
+ * @platform android, ios
9
+ * @example
10
+ * ReactNativeBrownfield.popToNative(true);
11
+ */
2
12
  popToNative: (animated?: boolean) => void;
13
+ /**
14
+ * Enable or disable the iOS native back gesture and Android hardware back button.
15
+ * @note This method is available both on the New Architecture and the Old Architecture.
16
+ * @param enabled - Whether to enable native back gesture and button.
17
+ * @platform android, ios
18
+ * @example
19
+ * ReactNativeBrownfield.setNativeBackGestureAndButtonEnabled(true);
20
+ */
3
21
  setNativeBackGestureAndButtonEnabled: (enabled: boolean) => void;
22
+ /**
23
+ * Send a JSON-serializable message to the native host application. This resembles the web `window.postMessage` API.
24
+ * @note This method is available both on the New Architecture and the Old Architecture.
25
+ * @note This method requires the `data` to be JSON-serializable. The method does not catch any serialization errors thrown
26
+ * by the `JSON.stringify` function, this is the responsibility of the caller.
27
+ * @param data - The data to send to the native host application.
28
+ * @platform android, ios
29
+ * @example
30
+ * ReactNativeBrownfield.postMessage({ text: 'Hello from React Native!', id: 2 });
31
+ */
32
+ postMessage: (data: unknown) => void;
33
+ /**
34
+ * Subscribe to messages sent from the native host application. Returns a subscription object with a `remove()` method for cleanup.
35
+ * @param callback - The callback to invoke when a message is received from the native host application.
36
+ * @returns A subscription object with a `remove` method for cleanup.
37
+ * @platform android, ios
38
+ * @example
39
+ * const subscription = ReactNativeBrownfield.onMessage((event: MessageEvent) => {
40
+ * console.log('Received from native:', event.data);
41
+ * });
42
+ *
43
+ * // Later, to unsubscribe:
44
+ * subscription.remove();
45
+ */
46
+ onMessage: (callback: (event: MessageEvent) => void) => {
47
+ remove: () => void;
48
+ };
4
49
  };
5
50
  export default ReactNativeBrownfield;
6
51
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,qBAAqB;6BACA,OAAO,KAAG,IAAI;oDAUS,OAAO,KAAG,IAAI;CAS/D,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,QAAA,MAAM,qBAAqB;IACzB;;;;;;OAMG;6BACsB,OAAO,KAAG,IAAI;IAUvC;;;;;;;OAOG;oDAC6C,OAAO,KAAG,IAAI;IAU9D;;;;;;;;;OASG;wBACiB,OAAO,KAAG,IAAI;IAKlC;;;;;;;;;;;;OAYG;0BAES,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,KACtC;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;CAY1B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -1,4 +1,7 @@
1
- import type { TurboModule } from 'react-native';
1
+ import type { CodegenTypes, TurboModule } from 'react-native';
2
+ export type BrownfieldMessagePayload = {
3
+ text: string;
4
+ };
2
5
  export interface Spec extends TurboModule {
3
6
  /**
4
7
  * Navigate back to the native part of the application.
@@ -14,6 +17,11 @@ export interface Spec extends TurboModule {
14
17
  * @platform android
15
18
  */
16
19
  setHardwareBackButtonEnabled(enabled: boolean): void;
20
+ /**
21
+ * Send a serialized JSON message to the native host application.
22
+ */
23
+ postMessage(message: string): void;
24
+ readonly onBrownfieldMessage: CodegenTypes.EventEmitter<BrownfieldMessagePayload>;
17
25
  }
18
26
  declare const _default: Spec;
19
27
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeReactNativeBrownfieldModule.d.ts","sourceRoot":"","sources":["../../../../src/NativeReactNativeBrownfieldModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IAErC;;;OAGG;IACH,8BAA8B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAEvD;;;OAGG;IACH,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACtD;;AAED,wBAA+E"}
1
+ {"version":3,"file":"NativeReactNativeBrownfieldModule.d.ts","sourceRoot":"","sources":["../../../../src/NativeReactNativeBrownfieldModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG9D,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IAErC;;;OAGG;IACH,8BAA8B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAEvD;;;OAGG;IACH,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAErD;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAGnC,QAAQ,CAAC,mBAAmB,EAAE,YAAY,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC;CACnF;;AAED,wBAA+E"}
@@ -1,6 +1,51 @@
1
+ export interface MessageEvent {
2
+ data: unknown;
3
+ }
1
4
  declare const ReactNativeBrownfield: {
5
+ /**
6
+ * Pop to the native screen.
7
+ * @param animated - Whether to animate the transition (iOS only).
8
+ * @platform android, ios
9
+ * @example
10
+ * ReactNativeBrownfield.popToNative(true);
11
+ */
2
12
  popToNative: (animated?: boolean) => void;
13
+ /**
14
+ * Enable or disable the iOS native back gesture and Android hardware back button.
15
+ * @note This method is available both on the New Architecture and the Old Architecture.
16
+ * @param enabled - Whether to enable native back gesture and button.
17
+ * @platform android, ios
18
+ * @example
19
+ * ReactNativeBrownfield.setNativeBackGestureAndButtonEnabled(true);
20
+ */
3
21
  setNativeBackGestureAndButtonEnabled: (enabled: boolean) => void;
22
+ /**
23
+ * Send a JSON-serializable message to the native host application. This resembles the web `window.postMessage` API.
24
+ * @note This method is available both on the New Architecture and the Old Architecture.
25
+ * @note This method requires the `data` to be JSON-serializable. The method does not catch any serialization errors thrown
26
+ * by the `JSON.stringify` function, this is the responsibility of the caller.
27
+ * @param data - The data to send to the native host application.
28
+ * @platform android, ios
29
+ * @example
30
+ * ReactNativeBrownfield.postMessage({ text: 'Hello from React Native!', id: 2 });
31
+ */
32
+ postMessage: (data: unknown) => void;
33
+ /**
34
+ * Subscribe to messages sent from the native host application. Returns a subscription object with a `remove()` method for cleanup.
35
+ * @param callback - The callback to invoke when a message is received from the native host application.
36
+ * @returns A subscription object with a `remove` method for cleanup.
37
+ * @platform android, ios
38
+ * @example
39
+ * const subscription = ReactNativeBrownfield.onMessage((event: MessageEvent) => {
40
+ * console.log('Received from native:', event.data);
41
+ * });
42
+ *
43
+ * // Later, to unsubscribe:
44
+ * subscription.remove();
45
+ */
46
+ onMessage: (callback: (event: MessageEvent) => void) => {
47
+ remove: () => void;
48
+ };
4
49
  };
5
50
  export default ReactNativeBrownfield;
6
51
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,qBAAqB;6BACA,OAAO,KAAG,IAAI;oDAUS,OAAO,KAAG,IAAI;CAS/D,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,QAAA,MAAM,qBAAqB;IACzB;;;;;;OAMG;6BACsB,OAAO,KAAG,IAAI;IAUvC;;;;;;;OAOG;oDAC6C,OAAO,KAAG,IAAI;IAU9D;;;;;;;;;OASG;wBACiB,OAAO,KAAG,IAAI;IAKlC;;;;;;;;;;;;OAYG;0BAES,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,KACtC;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;CAY1B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callstack/react-native-brownfield",
3
- "version": "3.0.0",
3
+ "version": "3.1.0-rc.2",
4
4
  "license": "MIT",
5
5
  "author": "Michal Chudziak <mike.chudziak@callstack.com>",
6
6
  "bin": {
@@ -1,6 +1,10 @@
1
- import type { TurboModule } from 'react-native';
1
+ import type { CodegenTypes, TurboModule } from 'react-native';
2
2
  import { TurboModuleRegistry } from 'react-native';
3
3
 
4
+ export type BrownfieldMessagePayload = {
5
+ text: string;
6
+ };
7
+
4
8
  export interface Spec extends TurboModule {
5
9
  /**
6
10
  * Navigate back to the native part of the application.
@@ -18,6 +22,14 @@ export interface Spec extends TurboModule {
18
22
  * @platform android
19
23
  */
20
24
  setHardwareBackButtonEnabled(enabled: boolean): void;
25
+
26
+ /**
27
+ * Send a serialized JSON message to the native host application.
28
+ */
29
+ postMessage(message: string): void;
30
+
31
+ // Event emitter - must be readonly
32
+ readonly onBrownfieldMessage: CodegenTypes.EventEmitter<BrownfieldMessagePayload>;
21
33
  }
22
34
 
23
35
  export default TurboModuleRegistry.getEnforcing<Spec>('ReactNativeBrownfield');
package/src/index.ts CHANGED
@@ -1,7 +1,19 @@
1
1
  import { Platform } from 'react-native';
2
+
2
3
  import ReactNativeBrownfieldModule from './NativeReactNativeBrownfieldModule';
3
4
 
5
+ export interface MessageEvent {
6
+ data: unknown;
7
+ }
8
+
4
9
  const ReactNativeBrownfield = {
10
+ /**
11
+ * Pop to the native screen.
12
+ * @param animated - Whether to animate the transition (iOS only).
13
+ * @platform android, ios
14
+ * @example
15
+ * ReactNativeBrownfield.popToNative(true);
16
+ */
5
17
  popToNative: (animated?: boolean): void => {
6
18
  if (Platform.OS === 'ios') {
7
19
  ReactNativeBrownfieldModule.popToNative(!!animated);
@@ -12,6 +24,14 @@ const ReactNativeBrownfield = {
12
24
  }
13
25
  },
14
26
 
27
+ /**
28
+ * Enable or disable the iOS native back gesture and Android hardware back button.
29
+ * @note This method is available both on the New Architecture and the Old Architecture.
30
+ * @param enabled - Whether to enable native back gesture and button.
31
+ * @platform android, ios
32
+ * @example
33
+ * ReactNativeBrownfield.setNativeBackGestureAndButtonEnabled(true);
34
+ */
15
35
  setNativeBackGestureAndButtonEnabled: (enabled: boolean): void => {
16
36
  if (Platform.OS === 'ios') {
17
37
  ReactNativeBrownfieldModule.setPopGestureRecognizerEnabled(enabled);
@@ -21,6 +41,49 @@ const ReactNativeBrownfield = {
21
41
  console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');
22
42
  }
23
43
  },
44
+
45
+ /**
46
+ * Send a JSON-serializable message to the native host application. This resembles the web `window.postMessage` API.
47
+ * @note This method is available both on the New Architecture and the Old Architecture.
48
+ * @note This method requires the `data` to be JSON-serializable. The method does not catch any serialization errors thrown
49
+ * by the `JSON.stringify` function, this is the responsibility of the caller.
50
+ * @param data - The data to send to the native host application.
51
+ * @platform android, ios
52
+ * @example
53
+ * ReactNativeBrownfield.postMessage({ text: 'Hello from React Native!', id: 2 });
54
+ */
55
+ postMessage: (data: unknown): void => {
56
+ const serialized = JSON.stringify(data);
57
+ ReactNativeBrownfieldModule.postMessage(serialized);
58
+ },
59
+
60
+ /**
61
+ * Subscribe to messages sent from the native host application. Returns a subscription object with a `remove()` method for cleanup.
62
+ * @param callback - The callback to invoke when a message is received from the native host application.
63
+ * @returns A subscription object with a `remove` method for cleanup.
64
+ * @platform android, ios
65
+ * @example
66
+ * const subscription = ReactNativeBrownfield.onMessage((event: MessageEvent) => {
67
+ * console.log('Received from native:', event.data);
68
+ * });
69
+ *
70
+ * // Later, to unsubscribe:
71
+ * subscription.remove();
72
+ */
73
+ onMessage: (
74
+ callback: (event: MessageEvent) => void
75
+ ): { remove: () => void } => {
76
+ const subscription = ReactNativeBrownfieldModule.onBrownfieldMessage(
77
+ (payload) => {
78
+ try {
79
+ callback({ data: JSON.parse(payload.text) });
80
+ } catch {
81
+ callback({ data: payload.text });
82
+ }
83
+ }
84
+ );
85
+ return { remove: () => subscription.remove() };
86
+ },
24
87
  };
25
88
 
26
89
  export default ReactNativeBrownfield;