diff --git a/docs/docs/docs/api-reference/brownfield-navigation.mdx/javascript-usage.mdx b/docs/docs/docs/api-reference/brownfield-navigation.mdx/javascript-usage.mdx index 5f29855a..bc187a97 100644 --- a/docs/docs/docs/api-reference/brownfield-navigation.mdx/javascript-usage.mdx +++ b/docs/docs/docs/api-reference/brownfield-navigation.mdx/javascript-usage.mdx @@ -48,7 +48,7 @@ Rerun codegen if any of these change: - Method return types ```bash -yarn brownfield:navigation-codegen +npx brownfield navigation:codegen ``` ## Common errors diff --git a/docs/docs/docs/api-reference/brownie/codegen.mdx b/docs/docs/docs/api-reference/brownie/codegen.mdx index bdb56698..d6f55a2b 100644 --- a/docs/docs/docs/api-reference/brownie/codegen.mdx +++ b/docs/docs/docs/api-reference/brownie/codegen.mdx @@ -54,7 +54,6 @@ The generated struct: - Conforms to `BrownieStoreProtocol` with auto-generated `storeName` - Uses mutable `var` properties - ## How It Works 1. CLI recursively finds all `*.brownie.ts` files diff --git a/docs/docs/docs/api-reference/brownie/getting-started.mdx b/docs/docs/docs/api-reference/brownie/getting-started.mdx index 6a792772..1966c3f2 100644 --- a/docs/docs/docs/api-reference/brownie/getting-started.mdx +++ b/docs/docs/docs/api-reference/brownie/getting-started.mdx @@ -73,12 +73,15 @@ The CLI generates native types and builds everything into XCFrameworks: npx brownfield package:ios --scheme YourScheme --configuration Release ``` -This produces the following in `ios/.brownfield/package/`: +This produces the following in `ios/.brownfield/package/build/`: - `YourScheme.xcframework` - Your React Native module -- `Brownie.xcframework` - Shared state library -- `ReactBrownfield.xcframework` - Brownfield integration - `hermesvm.xcframework` - JavaScript engine (or `hermes.xcframework` for RN < 0.82.0) +- `ReactBrownfield.xcframework` - Brownfield integration +- `Brownie.xcframework` - Shared state library (only when using the Brownie package) +- `BrownfieldNavigation.xcframework` - Brownfield navigation integration (only when using the brownfield-navigation package) + +The `ios/.brownfield/build/` directory contains the build cache. :::info The `package:ios` command automatically runs `brownfield codegen` to generate Swift types from your `.brownie.ts` files. @@ -87,7 +90,7 @@ The `package:ios` command automatically runs `brownfield codegen` to generate Sw ## Step 5: Add Frameworks to Native App 1. Open your native Xcode project -2. Drag all XCFrameworks from `ios/.brownfield/package/` into your project +2. Drag all XCFrameworks from `ios/.brownfield/package/build/` into your project 3. In target settings → **General** → **Frameworks, Libraries, and Embedded Content**, set all to **Embed & Sign** ## Step 6: Register Store in Swift diff --git a/docs/docs/docs/api-reference/react-native-brownfield/java.mdx b/docs/docs/docs/api-reference/react-native-brownfield/java.mdx index 13325814..581f3e12 100644 --- a/docs/docs/docs/api-reference/react-native-brownfield/java.mdx +++ b/docs/docs/docs/api-reference/react-native-brownfield/java.mdx @@ -158,12 +158,12 @@ ReactNativeBrownfield.getShared() Creates a React Native view with a given module name. It automatically uses an instance of React Native created in `initialize` method. This is useful when embedding React Native views directly in your native layouts. -| Param | Required | Type | Description | -| ------------- | -------- | ------------------ | ---------------------------------------------------------- | -| context | Yes | `Context` | Android context to create the view | -| activity | No | `FragmentActivity` | Activity hosting the view, used for lifecycle management | -| moduleName | Yes | `String` | Name of React Native component registered to `AppRegistry` | -| launchOptions | No | `Bundle` | Initial properties to be passed to React Native component | +| Param | Required | Type | Description | +| ------------- | -------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| activity | No | `FragmentActivity` | Activity hosting the view, used for lifecycle management. Required for proper lifecycle; may be null only when passing a custom `reactDelegate`. | +| moduleName | Yes | `String` | Name of React Native component registered to `AppRegistry`. | +| launchOptions | No | `Bundle` | Initial properties to be passed to React Native component. | +| reactDelegate | No | `ReactDelegateWrapper` | Optional custom delegate. If passed, the `activity` argument is ignored. | Returns: `FrameLayout` - A view containing the React Native component. @@ -172,13 +172,25 @@ Returns: `FrameLayout` - A view containing the React Native component. ```java // In a Fragment or Activity FrameLayout reactView = ReactNativeBrownfield.getShared().createView( - context, activity, "ReactNative" ); container.addView(reactView); ``` +```java +// With initial properties +Bundle props = new Bundle(); +props.putInt("score", 12); +FrameLayout reactView = ReactNativeBrownfield.getShared().createView( + activity, + "ReactNative", + null, + props +); +container.addView(reactView); +``` + ##### `postMessage` Send a JSON string to the React Native JS layer. The message is delivered as a `brownfieldMessage` DeviceEventEmitter event and can be received using `ReactNativeBrownfield.onMessage()` on the JS side. diff --git a/docs/docs/docs/api-reference/react-native-brownfield/javascript.mdx b/docs/docs/docs/api-reference/react-native-brownfield/javascript.mdx index b26c48d5..9a981e1f 100644 --- a/docs/docs/docs/api-reference/react-native-brownfield/javascript.mdx +++ b/docs/docs/docs/api-reference/react-native-brownfield/javascript.mdx @@ -37,14 +37,14 @@ ReactNativeBrownfield.setNativeBackGestureAndButtonEnabled(true); A method to pop to native screen used to push React Native experience. ```ts -ReactNativeBrownfield.popToNative(animated: boolean); +ReactNativeBrownfield.popToNative(animated?: boolean); ``` **Parameters:** -| Param | Type | Description | -| -------- | --------- | -------------------------------------------- | -| animated | `boolean` | Whether to animate the transition (iOS only) | +| Param | Type | Description | +| -------- | --------- | ------------------------------------------------------------------------------------------------------ | +| animated | `boolean` | Optional. Whether to animate the transition (iOS only). Defaults to `false`, has no effect on Android. | **Example:** diff --git a/docs/docs/docs/api-reference/react-native-brownfield/kotlin.mdx b/docs/docs/docs/api-reference/react-native-brownfield/kotlin.mdx index c1f35511..d9b888d0 100644 --- a/docs/docs/docs/api-reference/react-native-brownfield/kotlin.mdx +++ b/docs/docs/docs/api-reference/react-native-brownfield/kotlin.mdx @@ -137,12 +137,12 @@ ReactNativeBrownfield.shared Creates a React Native view with a given module name. It automatically uses an instance of React Native created in `initialize` method. This is useful when embedding React Native views directly in your native layouts or Jetpack Compose UI. -| Param | Required | Type | Description | -| ------------- | -------- | ------------------ | ---------------------------------------------------------- | -| context | Yes | `Context` | Android context to create the view | -| activity | No | `FragmentActivity` | Activity hosting the view, used for lifecycle management | -| moduleName | Yes | `String` | Name of React Native component registered to `AppRegistry` | -| launchOptions | No | `Bundle` | Initial properties to be passed to React Native component | +| Param | Required | Type | Description | +| ------------- | -------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| activity | No | `FragmentActivity` | Activity hosting the view, used for lifecycle management. Required for proper lifecycle; may be null only when using a custom `reactDelegate`. | +| moduleName | Yes | `String` | Name of React Native component registered to `AppRegistry`. | +| launchOptions | No | `Bundle` | Initial properties to be passed to React Native component. | +| reactDelegate | No | `ReactDelegateWrapper` | Optional custom delegate. If passed, the `activity` argument is ignored. | Returns: `FrameLayout` - A view containing the React Native component. @@ -151,18 +151,28 @@ Returns: `FrameLayout` - A view containing the React Native component. ```kotlin // In a Fragment or Activity val reactView = ReactNativeBrownfield.shared.createView( - context, activity, "ReactNative" ) container.addView(reactView) ``` +```kotlin +// With initial properties +val props = Bundle().apply { putInt("score", 12) } +val reactView = ReactNativeBrownfield.shared.createView( + activity, + "ReactNative", + launchOptions = props +) +container.addView(reactView) +``` + ```kotlin // With Jetpack Compose AndroidView( - factory = { context -> - ReactNativeBrownfield.shared.createView(context, fragmentActivity, "ReactNative") + factory = { + ReactNativeBrownfield.shared.createView(fragmentActivity, "ReactNative") }, modifier = Modifier.fillMaxSize() ) diff --git a/docs/docs/docs/api-reference/react-native-brownfield/objective-c.mdx b/docs/docs/docs/api-reference/react-native-brownfield/objective-c.mdx index 92744f21..d4fdd476 100644 --- a/docs/docs/docs/api-reference/react-native-brownfield/objective-c.mdx +++ b/docs/docs/docs/api-reference/react-native-brownfield/objective-c.mdx @@ -28,12 +28,12 @@ A singleton that keeps an instance of `ReactNativeBrownfield` object. #### Properties -| Property | Type | Default | Description | -| ------------------ | ---------- | --------------- | --------------------------------------------------------- | -| `entryFile` | `NSString` | `index` | Path to JavaScript root. | -| `fallbackResource` | `NSString` | `nil` | Path to bundle fallback resource. | -| `bundlePath` | `NSString` | `main.jsbundle` | Path to bundle fallback resource. | -| `bundle` | `NSBundle` | `Bundle.main` | Bundle instance to lookup the JavaScript bundle resource. | +| Property | Type | Default | Description | +| ------------------- | ------------------ | --------------- | ------------------------------------------------------------------------------ | +| `entryFile` | `NSString` | `index` | Path to JavaScript root. | +| `bundlePath` | `NSString` | `main.jsbundle` | Path to JavaScript bundle file. | +| `bundle` | `NSBundle` | `Bundle.main` | Bundle instance to lookup the JavaScript bundle resource. | +| `bundleURLOverride` | `NSURL *(^)(void)` | `nil` | Dynamic bundle URL provider. When set, overrides default bundle load behavior. | --- @@ -43,10 +43,9 @@ A singleton that keeps an instance of `ReactNativeBrownfield` object. Starts React Native, produces an instance of React Native. You can use it to initialize React Native in your app. -| Param | Required | Type | Description | -| ---------------- | -------- | --------------- | -------------------------------------------------- | -| `onBundleLoaded` | No | `void(^)(void)` | Callback invoked after JS bundle is fully loaded. | -| `launchOptions` | No | `NSDictionary` | Launch options, typically passed from AppDelegate. | +| Param | Required | Type | Description | +| ---------------- | -------- | --------------- | ------------------------------------------------- | +| `onBundleLoaded` | No | `void(^)(void)` | Callback invoked after JS bundle is fully loaded. | **Examples:** @@ -60,12 +59,6 @@ Starts React Native, produces an instance of React Native. You can use it to ini }]; ``` -```objc -[[ReactNativeBrownfield shared] startReactNative:^(void){ - NSLog(@"React Native started"); -}, launchOptions]; -``` - ##### `view` Creates a React Native view for the specified module name. @@ -82,6 +75,17 @@ Creates a React Native view for the specified module name. UIView *view = [[ReactNativeBrownfield shared] viewWithModuleName:@"ReactNative" initialProps:@{@"score": @12}]; ``` +##### `application:didFinishLaunchingWithOptions:` + +Mirrors the host runtime app delegate API. Call this from your `AppDelegate` if you need to forward launch options to the brownfield runtime (e.g. when using Expo). + +| Param | Required | Type | Description | +| --------------- | -------- | ----------------- | -------------------------- | +| `application` | Yes | `UIApplication *` | The application instance. | +| `launchOptions` | No | `NSDictionary *` | Launch options dictionary. | + +Returns: `BOOL` – return value is passed through from the runtime. + ##### `postMessage` Send a JSON string to the React Native JS layer. The message is delivered as a `brownfieldMessage` DeviceEventEmitter event. diff --git a/docs/docs/docs/api-reference/react-native-brownfield/swift.mdx b/docs/docs/docs/api-reference/react-native-brownfield/swift.mdx index 000f332c..1678b053 100644 --- a/docs/docs/docs/api-reference/react-native-brownfield/swift.mdx +++ b/docs/docs/docs/api-reference/react-native-brownfield/swift.mdx @@ -31,8 +31,7 @@ ReactNativeBrownfield.shared | Property | Type | Default | Description | | ------------------- | --------------- | --------------- | ---------------------------------------------------------------------------------------------- | | `entryFile` | `String` | `index` | Path to JavaScript root. | -| `fallbackResource` | `String?` | `nil` | Path to bundle fallback resource. | -| `bundlePath` | `String` | `main.jsbundle` | Path to bundle fallback resource. | +| `bundlePath` | `String` | `main.jsbundle` | Path to JavaScript bundle file. | | `bundle` | `Bundle` | `Bundle.main` | Bundle instance to lookup the JavaScript bundle resource. | | `bundleURLOverride` | `(() -> URL?)?` | `nil` | Dynamic bundle URL provider called on every bundle load. When set, overrides default behavior. | @@ -44,10 +43,9 @@ ReactNativeBrownfield.shared Starts React Native. You can use it to initialize React Native in your app. -| Param | Required | Type | Description | -| ---------------- | -------- | --------------------- | -------------------------------------------------- | -| `onBundleLoaded` | No | `(() -> Void)?` | Callback invoked after JS bundle is fully loaded. | -| `launchOptions` | No | `[AnyHashable: Any]?` | Launch options, typically passed from AppDelegate. | +| Param | Required | Type | Description | +| ---------------- | -------- | --------------- | ------------------------------------------------- | +| `onBundleLoaded` | No | `(() -> Void)?` | Callback invoked after JS bundle is fully loaded. | **Examples:** @@ -61,12 +59,6 @@ ReactNativeBrownfield.shared.startReactNative(onBundleLoaded: { }) ``` -```swift -ReactNativeBrownfield.shared.startReactNative(onBundleLoaded: { - print("React Native started") -}, launchOptions: launchOptions) -``` - ##### `view` Creates a React Native view for the specified module name. @@ -105,6 +97,28 @@ let json = try! JSONSerialization.data(withJSONObject: payload) ReactNativeBrownfield.shared.postMessage(String(data: json, encoding: .utf8)!) ``` +##### `application(_:didFinishLaunchingWithOptions:)` + +Mirrors the host runtime app delegate API. Call this from your `AppDelegate` if you need to forward `application(_:didFinishLaunchingWithOptions:)` to the brownfield runtime (e.g. when using Expo). + +| Param | Required | Type | Description | +| --------------- | -------- | ---------------------------------------- | -------------------------- | +| `application` | Yes | `UIApplication` | The application instance. | +| `launchOptions` | No | `[UIApplication.LaunchOptionsKey: Any]?` | Launch options dictionary. | + +Returns: `Bool` – return value is passed through from the runtime. + +**Example:** + +```swift +func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? +) -> Bool { + return ReactNativeBrownfield.shared.application(application, didFinishLaunchingWithOptions: launchOptions) +} +``` + ##### `onMessage` Subscribe to messages sent from JavaScript via `ReactNativeBrownfield.postMessage()`. Returns an observer token that can be used to unsubscribe. diff --git a/docs/docs/docs/cli/brownfield.mdx b/docs/docs/docs/cli/brownfield.mdx index 6f14aa47..0d61e0a6 100644 --- a/docs/docs/docs/cli/brownfield.mdx +++ b/docs/docs/docs/cli/brownfield.mdx @@ -29,7 +29,7 @@ Available arguments: | --extra-params | Custom params that will be passed to xcodebuild command | | --export-extra-params | Custom params that will be passed to xcodebuild export archive command. Example: `--export-extra-params "-allowProvisioningUpdates"` | | --export-options-plist | Name of the export options file for archiving. Defaults to: `ExportOptions.plist` | -| --build-folder | Location for iOS build artifacts. Corresponds to Xcode's "-derivedDataPath". By default, the '\/build' path will be used. | +| --build-folder | Location for iOS build artifacts. Corresponds to Xcode's "-derivedDataPath". By default, the '\/.brownfield/build' path will be used. | | --destination | Define destination(s) for the build. You can pass multiple destinations as separate values or repeated use of the flag. Values: "simulator", "device", or xcodebuild destinations | | --archive | Create an Xcode archive (IPA) of the build, required for uploading to App Store Connect or distributing to TestFlight | | --no-install-pods | Skip automatic CocoaPods installation | @@ -37,13 +37,22 @@ Available arguments: | --local | Force local build with xcodebuild | | --verbose | Enable verbose logging | -The build directory will be placed in the `/.brownfield/build` folder by default and the build outputs (XCFrameworks) will be created in the `/.brownfield/package` folder: +The build directory will be placed in the `/.brownfield/build` folder by default and the build outputs (XCFrameworks) will be created in the `/.brownfield/package/build` folder: -- `package/.xcframework`, e.g. in the `apps/RNApp` demo project, the output will be at `apps/RNApp/ios/.brownfield/package/BrownfieldLib.xcframework`. -- `package/hermesvm.xcframework` for RN >= 0.82.0 or `package/hermes.xcframework` otherwise -- `ReactBrownfield.xcframework` +- `package/build/.xcframework`, e.g. in the `apps/RNApp` demo project, the output will be at `apps/RNApp/ios/.brownfield/package/build/BrownfieldLib.xcframework`. +- `package/build/hermesvm.xcframework` for RN >= 0.82.0 or `package/build/hermes.xcframework` otherwise +- `package/build/ReactBrownfield.xcframework` +- `package/build/Brownie.xcframework` (only when using the Brownie package) +- `package/build/BrownfieldNavigation.xcframework` (only when using the Navigation package) -The consumer project needs to embed all 3 frameworks. +The consumer project needs to embed the required frameworks: + +- `.xcframework` - Your React Native module +- `hermesvm.xcframework` - JavaScript runtime (or `hermes.xcframework` for RN < 0.82.0) +- `ReactBrownfield.xcframework` - React Native Brownfield library + +If you are using the Brownie package, you will also need to embed `Brownie.xcframework`. +If you are using the brownfield-navigation package, you will also need to embed `BrownfieldNavigation.xcframework`. ## Android diff --git a/docs/docs/docs/contributing.md b/docs/docs/docs/contributing.md index a610526a..0af2faca 100644 --- a/docs/docs/docs/contributing.md +++ b/docs/docs/docs/contributing.md @@ -1,4 +1,3 @@ # Contributing Checkout project's [CONTRIBUTING.md](https://github.com/callstack/react-native-brownfield/blob/main/CONTRIBUTING.md) for more information. - diff --git a/docs/docs/docs/getting-started/introduction.mdx b/docs/docs/docs/getting-started/introduction.mdx index 876c2eb8..29d69ec7 100644 --- a/docs/docs/docs/getting-started/introduction.mdx +++ b/docs/docs/docs/getting-started/introduction.mdx @@ -19,6 +19,7 @@ React Native Brownfield is a library that simplifies integrating React Native in | Tested React Native Version | React Native Brownfield Version | | --------------------------- | ------------------------------- | +| 0.83.x | 3.x | | 0.81.x, 0.82.x | 2.x, 3.x | | 0.78.x | ^1.2.0 | diff --git a/docs/docs/docs/getting-started/ios.mdx b/docs/docs/docs/getting-started/ios.mdx index 8d222215..b4f353e9 100644 --- a/docs/docs/docs/getting-started/ios.mdx +++ b/docs/docs/docs/getting-started/ios.mdx @@ -113,15 +113,17 @@ Use the brownfield CLI to package your React Native app: npx brownfield package:ios --scheme --configuration Release ``` -This creates the XCFramework in **`.brownfield/ios/package/`**. +This creates the XCFramework in **`ios/.brownfield/package/build/`** (relative to your project root). ## 6. Add the Framework to Your iOS App -1. Open **`.brownfield/ios/package`** directory +1. Open **`ios/.brownfield/package/build`** directory (relative to your React Native project root) 2. Drag these files into your native iOS app's Xcode project: - - **`hermesvm.xcframework`** - JavaScript runtime + - **`.xcframework`** - Your React Native framework + - **`hermesvm.xcframework`** - JavaScript runtime (or `hermes.xcframework` for RN < 0.82.0) - **`ReactBrownfield.xcframework`** - React Native Brownfield library - - **`.xcframework`** - Your framework + - `Brownie.xcframework` - Brownie shared state library (only when using the Brownie package) + - `BrownfieldNavigation.xcframework` - Brownfield navigation integration (only when using the brownfield-navigation package) for React Native navigation ![Frameworks in Xcode Sidebar](/images/frameworks-sidebar.png) diff --git a/docs/docs/docs/getting-started/quick-start.mdx b/docs/docs/docs/getting-started/quick-start.mdx index 8b0c9c01..13499245 100644 --- a/docs/docs/docs/getting-started/quick-start.mdx +++ b/docs/docs/docs/getting-started/quick-start.mdx @@ -39,7 +39,7 @@ Integrating React Native into an existing native app requires packaging your Jav - **iOS** → **XCFramework** (`.xcframework`) - **Android** → **AAR** (`.aar`) -#### With Rock +#### Without the CLI Without the CLI, this process involves: @@ -53,11 +53,11 @@ The **Brownfield CLI automates all of this** with simple commands. ### What does it do? -| Command | Platform | Output | -| ----------------------- | -------- | ---------------------------------------------------------------------------------------------------- | -| **`package:ios`** | iOS | Creates an XCFramework containing your React Native app, Hermes runtime, and all native dependencies | -| **`package:aar`** | Android | Creates a Fat-AAR containing your React Native app bundled with all native dependencies | -| **`publish-local:aar`** | Android | Publishes the AAR to your local Maven repository for easy consumption | +| Command | Platform | Output | +| --------------------- | -------- | ---------------------------------------------------------------------------------------------------- | +| **`package:ios`** | iOS | Creates an XCFramework containing your React Native app, Hermes runtime, and all native dependencies | +| **`package:android`** | Android | Creates a Fat-AAR containing your React Native app bundled with all native dependencies | +| **`publish:android`** | Android | Publishes the AAR to your local Maven repository for easy consumption | ### How does it make integration easier? diff --git a/docs/docs/docs/guides/troubleshooting.mdx b/docs/docs/docs/guides/troubleshooting.mdx index 12b3011c..df493a10 100644 --- a/docs/docs/docs/guides/troubleshooting.mdx +++ b/docs/docs/docs/guides/troubleshooting.mdx @@ -4,9 +4,9 @@ This section provides a troubleshooting guide for common issues encountered when ## [Android] `Error: duplicate resources` during `:app:mergeReleaseAssets` -An error like `Error: duplicate resources` during the `:app:mergeReleaseAssets` phase may occur if you have upgraded your React Native version from a version less than `0.82.0`, to a version greater than or equal to (>=) `0.82.0`. +An error like `Error: duplicate resources` during the `:app:mergeReleaseAssets` phase may occur if you have upgraded your React Native version from a version less than `0.82.0`, to a version greater than or equal to (>=) `0.82.0`. -This is because RN 0.82.0 changed the path to which the JS bundle is written to from `build/generated/assets/createBundleReleaseJsAndAssets/` to `build/generated/assets/react/release/`, and analogously changed the path for `res/createBundleReleaseJsAndAssets/`. +This is because RN 0.82.0 changed the path to which the JS bundle is written to from `build/generated/assets/createBundleReleaseJsAndAssets/` to `build/generated/assets/react/release/`, and analogously changed the path for `res/createBundleReleaseJsAndAssets/`. The brownfield Gradle plugin adds both directories to the source sets, potentially causing a conflict of artifacts. To fix this, just once clean your build directory (precisely, the `app/build/` directory) and rebuild the project. All subsequent builds should work fine. diff --git a/packages/cli/src/brownfield/commands/packageIos.ts b/packages/cli/src/brownfield/commands/packageIos.ts index d01e8ca5..4b4cb12c 100644 --- a/packages/cli/src/brownfield/commands/packageIos.ts +++ b/packages/cli/src/brownfield/commands/packageIos.ts @@ -118,7 +118,7 @@ export const packageIosCommand = curryOptions( outputPath: brownieOutputPath, }); - // Strip the binary from Browniexcframework to make it interface-only. + // Strip the binary from Brownie.xcframework to make it interface-only. // This avoids duplicate symbols when consumer apps embed both BrownfieldLib // (which contains Brownie symbols) and Brownie.xcframework. stripFrameworkBinary(brownieOutputPath);