From b2347a98a04cf7348a0b5505fdbff2ba9e00a899 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Tue, 9 Apr 2024 07:57:20 -0700 Subject: [PATCH] Add react-native-test-library package (#43068) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43068 This diff adds `react-native-test-library` package. It contains native module and native component example, and targets both the new and the old architecture. It has structure similar to many OSS React Native libraries, and is supposed to be used to test the integration with third-party libraries. It is integrated with RNTester as the **OSS Library Example** screen. {F1457510909} **Change Background** tests native commands. **Set Opacity** tests native props. **Get Random Number** tests native module. Changelog: [Internal] Reviewed By: RSNara Differential Revision: D50793835 --- .gitignore | 1 + .../OSSLibraryExample.podspec | 24 +++ packages/react-native-test-library/README.md | 9 ++ .../android/build.gradle.kts | 35 +++++ .../android/gradle.properties | 4 + .../fbreact/specs/NativeSampleModuleSpec.java | 37 +++++ .../SampleNativeComponentManagerDelegate.java | 44 ++++++ ...SampleNativeComponentManagerInterface.java | 20 +++ .../osslibraryexample/NativeSampleModule.kt | 30 ++++ .../OSSLibraryExamplePackage.kt | 21 +++ .../SampleNativeComponentViewManager.kt | 103 +++++++++++++ .../osslibraryexample/SampleNativeView.kt | 97 ++++++++++++ .../android/src/main/jni/CMakeLists.txt | 49 ++++++ .../jni/OSSLibraryExampleSpec-generated.cpp | 32 ++++ .../src/main/jni/OSSLibraryExampleSpec.h | 31 ++++ .../ComponentDescriptors.cpp | 22 +++ .../ComponentDescriptors.h | 24 +++ .../OSSLibraryExampleSpec/EventEmitters.cpp | 95 ++++++++++++ .../OSSLibraryExampleSpec/EventEmitters.h | 49 ++++++ .../OSSLibraryExampleSpecJSI-generated.cpp | 26 ++++ .../OSSLibraryExampleSpecJSI.h | 63 ++++++++ .../OSSLibraryExampleSpec/Props.cpp | 26 ++++ .../components/OSSLibraryExampleSpec/Props.h | 29 ++++ .../OSSLibraryExampleSpec/ShadowNodes.cpp | 17 +++ .../OSSLibraryExampleSpec/ShadowNodes.h | 32 ++++ .../OSSLibraryExampleSpec/States.cpp | 16 ++ .../components/OSSLibraryExampleSpec/States.h | 34 +++++ .../react-native-test-library/babel.config.js | 10 ++ packages/react-native-test-library/index.js | 15 ++ .../ComponentDescriptors.cpp | 22 +++ .../ComponentDescriptors.h | 24 +++ .../OSSLibraryExampleSpec/EventEmitters.cpp | 95 ++++++++++++ .../ios/OSSLibraryExampleSpec/EventEmitters.h | 49 ++++++ .../OSSLibraryExampleSpec-generated.mm | 29 ++++ .../OSSLibraryExampleSpec.h | 43 ++++++ .../ios/OSSLibraryExampleSpec/Props.cpp | 26 ++++ .../ios/OSSLibraryExampleSpec/Props.h | 29 ++++ .../RCTComponentViewHelpers.h | 50 +++++++ .../ios/OSSLibraryExampleSpec/ShadowNodes.cpp | 17 +++ .../ios/OSSLibraryExampleSpec/ShadowNodes.h | 32 ++++ .../ios/OSSLibraryExampleSpec/States.cpp | 16 ++ .../ios/OSSLibraryExampleSpec/States.h | 34 +++++ .../OSSLibraryExampleSpecJSI-generated.cpp | 26 ++++ .../ios/OSSLibraryExampleSpecJSI.h | 63 ++++++++ .../ios/RCTNativeSampleModule.mm | 47 ++++++ .../RCTSampleNativeComponentComponentView.mm | 139 ++++++++++++++++++ .../RCTSampleNativeComponentViewManager.mm | 70 +++++++++ .../react-native-test-library/package.json | 49 ++++++ .../src/NativeSampleModule.js | 19 +++ .../src/SampleNativeComponent.js | 59 ++++++++ packages/rn-tester/Podfile | 1 + .../rn-tester/android/app/build.gradle.kts | 1 + .../react/uiapp/RNTesterApplication.kt | 2 + .../OSSLibraryExample/OSSLibraryExample.js | 128 ++++++++++++++++ .../js/utils/RNTesterList.android.js | 4 + .../rn-tester/js/utils/RNTesterList.ios.js | 4 + packages/rn-tester/metro.config.js | 1 + packages/rn-tester/package.json | 1 + settings.gradle.kts | 1 + 59 files changed, 2076 insertions(+) create mode 100644 packages/react-native-test-library/OSSLibraryExample.podspec create mode 100644 packages/react-native-test-library/README.md create mode 100644 packages/react-native-test-library/android/build.gradle.kts create mode 100644 packages/react-native-test-library/android/gradle.properties create mode 100644 packages/react-native-test-library/android/src/main/java/com/facebook/fbreact/specs/NativeSampleModuleSpec.java create mode 100644 packages/react-native-test-library/android/src/main/java/com/facebook/react/viewmanagers/SampleNativeComponentManagerDelegate.java create mode 100644 packages/react-native-test-library/android/src/main/java/com/facebook/react/viewmanagers/SampleNativeComponentManagerInterface.java create mode 100644 packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/NativeSampleModule.kt create mode 100644 packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/OSSLibraryExamplePackage.kt create mode 100644 packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeComponentViewManager.kt create mode 100644 packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeView.kt create mode 100644 packages/react-native-test-library/android/src/main/jni/CMakeLists.txt create mode 100644 packages/react-native-test-library/android/src/main/jni/OSSLibraryExampleSpec-generated.cpp create mode 100644 packages/react-native-test-library/android/src/main/jni/OSSLibraryExampleSpec.h create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ComponentDescriptors.cpp create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ComponentDescriptors.h create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/EventEmitters.cpp create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/EventEmitters.h create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/OSSLibraryExampleSpecJSI-generated.cpp create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/OSSLibraryExampleSpecJSI.h create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/Props.cpp create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/Props.h create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ShadowNodes.cpp create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ShadowNodes.h create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/States.cpp create mode 100644 packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/States.h create mode 100644 packages/react-native-test-library/babel.config.js create mode 100644 packages/react-native-test-library/index.js create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/ComponentDescriptors.cpp create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/ComponentDescriptors.h create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/EventEmitters.cpp create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/EventEmitters.h create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/OSSLibraryExampleSpec-generated.mm create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/OSSLibraryExampleSpec.h create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/Props.cpp create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/Props.h create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/RCTComponentViewHelpers.h create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/ShadowNodes.cpp create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/ShadowNodes.h create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/States.cpp create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpec/States.h create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpecJSI-generated.cpp create mode 100644 packages/react-native-test-library/ios/OSSLibraryExampleSpecJSI.h create mode 100644 packages/react-native-test-library/ios/RCTNativeSampleModule.mm create mode 100644 packages/react-native-test-library/ios/RCTSampleNativeComponentComponentView.mm create mode 100644 packages/react-native-test-library/ios/RCTSampleNativeComponentViewManager.mm create mode 100644 packages/react-native-test-library/package.json create mode 100644 packages/react-native-test-library/src/NativeSampleModule.js create mode 100644 packages/react-native-test-library/src/SampleNativeComponent.js create mode 100644 packages/rn-tester/js/examples/OSSLibraryExample/OSSLibraryExample.js diff --git a/.gitignore b/.gitignore index 626d954cfa3f18..919d110e1bd216 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ project.xcworkspace /packages/react-native/template/android/app/build/ /packages/react-native/template/android/build/ /packages/react-native-popup-menu-android/android/build/ +/packages/react-native-test-library/android/build/ # Buck .buckd diff --git a/packages/react-native-test-library/OSSLibraryExample.podspec b/packages/react-native-test-library/OSSLibraryExample.podspec new file mode 100644 index 00000000000000..232273917fd080 --- /dev/null +++ b/packages/react-native-test-library/OSSLibraryExample.podspec @@ -0,0 +1,24 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require 'json' + +package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) + +Pod::Spec.new do |s| + s.name = 'OSSLibraryExample' + s.version = package['version'] + s.summary = package['description'] + s.description = package['description'] + s.homepage = package['homepage'] + s.license = package['license'] + s.platforms = min_supported_versions + s.author = 'Meta Platforms, Inc. and its affiliates' + s.source = { :git => package['repository']['url'], :tag => "#{s.version}" } + + s.source_files = 'ios/**/*.{h,m,mm,cpp}' + + install_modules_dependencies(s) +end diff --git a/packages/react-native-test-library/README.md b/packages/react-native-test-library/README.md new file mode 100644 index 00000000000000..77df8a6791b313 --- /dev/null +++ b/packages/react-native-test-library/README.md @@ -0,0 +1,9 @@ +## Important +This package is for testing only. It is a subject to frequent change. It does not represent the recomended structure for React native libraries. It should not be used as a referece for such purposes. + +## Building +``` +yarn install +yarn build +npx react-native codegen +``` diff --git a/packages/react-native-test-library/android/build.gradle.kts b/packages/react-native-test-library/android/build.gradle.kts new file mode 100644 index 00000000000000..211f237a5e8f74 --- /dev/null +++ b/packages/react-native-test-library/android/build.gradle.kts @@ -0,0 +1,35 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +plugins { + id("com.facebook.react") + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) +} + +android { + compileSdk = libs.versions.compileSdk.get().toInt() + buildToolsVersion = libs.versions.buildTools.get() + namespace = "com.facebook.react.osslibraryexample" + + defaultConfig { + minSdk = libs.versions.minSdk.get().toInt() + targetSdk = libs.versions.targetSdk.get().toInt() + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { jvmTarget = "17" } +} + +dependencies { + // Build React Native from source + implementation(project(":packages:react-native:ReactAndroid")) +} diff --git a/packages/react-native-test-library/android/gradle.properties b/packages/react-native-test-library/android/gradle.properties new file mode 100644 index 00000000000000..92a0f87956c8c7 --- /dev/null +++ b/packages/react-native-test-library/android/gradle.properties @@ -0,0 +1,4 @@ + +# We want to have more fine grained control on the Java version for +# ReactAndroid, therefore we disable RGNP Java version alignment mechanism +react.internal.disableJavaVersionAlignment=true diff --git a/packages/react-native-test-library/android/src/main/java/com/facebook/fbreact/specs/NativeSampleModuleSpec.java b/packages/react-native-test-library/android/src/main/java/com/facebook/fbreact/specs/NativeSampleModuleSpec.java new file mode 100644 index 00000000000000..94148064208997 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/java/com/facebook/fbreact/specs/NativeSampleModuleSpec.java @@ -0,0 +1,37 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJavaSpec.js + * + * @nolint + */ + +package com.facebook.fbreact.specs; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import javax.annotation.Nonnull; + +public abstract class NativeSampleModuleSpec extends ReactContextBaseJavaModule implements TurboModule { + public static final String NAME = "NativeSampleModule"; + + public NativeSampleModuleSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public @Nonnull String getName() { + return NAME; + } + + @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip + public abstract double getRandomNumber(); +} diff --git a/packages/react-native-test-library/android/src/main/java/com/facebook/react/viewmanagers/SampleNativeComponentManagerDelegate.java b/packages/react-native-test-library/android/src/main/java/com/facebook/react/viewmanagers/SampleNativeComponentManagerDelegate.java new file mode 100644 index 00000000000000..e25a276cda9898 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/java/com/facebook/react/viewmanagers/SampleNativeComponentManagerDelegate.java @@ -0,0 +1,44 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; + +public class SampleNativeComponentManagerDelegate & SampleNativeComponentManagerInterface> extends BaseViewManagerDelegate { + public SampleNativeComponentManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "opacity": + mViewManager.setOpacity(view, value == null ? 0f : ((Double) value).floatValue()); + break; + case "values": + mViewManager.setValues(view, (ReadableArray) value); + break; + default: + super.setProperty(view, propName, value); + } + } + + @Override + public void receiveCommand(T view, String commandName, ReadableArray args) { + switch (commandName) { + case "changeBackgroundColor": + mViewManager.changeBackgroundColor(view, args.getString(0)); + break; + } + } +} diff --git a/packages/react-native-test-library/android/src/main/java/com/facebook/react/viewmanagers/SampleNativeComponentManagerInterface.java b/packages/react-native-test-library/android/src/main/java/com/facebook/react/viewmanagers/SampleNativeComponentManagerInterface.java new file mode 100644 index 00000000000000..83cdf8fbfa3bc9 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/java/com/facebook/react/viewmanagers/SampleNativeComponentManagerInterface.java @@ -0,0 +1,20 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.ReadableArray; + +public interface SampleNativeComponentManagerInterface { + void setOpacity(T view, float value); + void setValues(T view, @Nullable ReadableArray value); + void changeBackgroundColor(T view, String color); +} diff --git a/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/NativeSampleModule.kt b/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/NativeSampleModule.kt new file mode 100644 index 00000000000000..e9154478094fb5 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/NativeSampleModule.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnative.osslibraryexample + +import com.facebook.fbreact.specs.NativeSampleModuleSpec +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.module.annotations.ReactModule + +@ReactModule(name = NativeSampleModuleSpec.NAME) +public class NativeSampleModule(reactContext: ReactApplicationContext?) : + ReactContextBaseJavaModule(reactContext) { + + override fun getName(): String = NAME + + private companion object { + const val NAME = "NativeSampleModule" + } + + @ReactMethod + public fun getRandomNumber(): Int { + return (0..99).random() + } +} diff --git a/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/OSSLibraryExamplePackage.kt b/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/OSSLibraryExamplePackage.kt new file mode 100644 index 00000000000000..a8da27f7fe49e0 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/OSSLibraryExamplePackage.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnative.osslibraryexample + +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.uimanager.ViewManager + +public class OSSLibraryExamplePackage : ReactPackage { + override fun createNativeModules(reactContext: ReactApplicationContext): List = + listOf(NativeSampleModule(reactContext)) + + override fun createViewManagers(reactContext: ReactApplicationContext): List> = + listOf(SampleNativeComponentViewManager()) +} diff --git a/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeComponentViewManager.kt b/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeComponentViewManager.kt new file mode 100644 index 00000000000000..037e98db7db1a8 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeComponentViewManager.kt @@ -0,0 +1,103 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnative.osslibraryexample + +import android.annotation.SuppressLint +import android.graphics.Color +import com.facebook.react.bridge.ReadableArray +import com.facebook.react.common.MapBuilder +import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.uimanager.SimpleViewManager +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.ViewProps +import com.facebook.react.uimanager.annotations.ReactProp +import com.facebook.react.viewmanagers.SampleNativeComponentManagerInterface + +/** Legacy View manager (non Fabric compatible) for {@link SampleNativeView} components. */ +@ReactModule(name = SampleNativeComponentViewManager.REACT_CLASS) +internal class SampleNativeComponentViewManager : + SimpleViewManager(), SampleNativeComponentManagerInterface { + + override fun getName(): String = REACT_CLASS + + // @ReactProp(name = ViewProps.OPACITY, defaultFloat = 1f) + override fun setOpacity(view: SampleNativeView, opacity: Float) { + super.setOpacity(view, opacity) + } + + @SuppressLint("BadMethodUse-android.view.View.setBackgroundColor") + @ReactProp(name = ViewProps.COLOR) + fun setColor(view: SampleNativeView, color: String) { + view.setBackgroundColor(Color.parseColor(color)) + } + + @ReactProp(name = "cornerRadius") + fun setCornerRadius(view: SampleNativeView, cornerRadius: Float) { + view.setCornerRadius(cornerRadius) + } + + override fun createViewInstance(reactContext: ThemedReactContext): SampleNativeView = + SampleNativeView(reactContext) + + @SuppressLint("BadMethodUse-android.view.View.setBackgroundColor") + override fun changeBackgroundColor(view: SampleNativeView, color: String) { + view.setBackgroundColor(Color.parseColor(color)) + } + + override fun getExportedViewConstants(): Map = mapOf("PI" to 3.14) + + override fun getExportedCustomBubblingEventTypeConstants(): Map { + return MapBuilder.builder() + .put( + "onColorChanged", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of("bubbled", "onColorChanged", "captured", "onColorChangedCapture"))) + .put( + "topIntArrayChanged", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of( + "bubbled", "topIntArrayChanged", "captured", "topIntArrayChangedCapture"))) + .build() + } + + @SuppressLint("BadMethodUse-android.view.View.setBackgroundColor") + override fun receiveCommand(view: SampleNativeView, commandId: String, args: ReadableArray?) { + if (commandId.contentEquals("changeBackgroundColor")) { + val sentColor: Int = Color.parseColor(args?.getString(0)) + view.setBackgroundColor(sentColor) + } + } + + @SuppressLint("BadMethodUse-android.view.View.setBackgroundColor") + @Suppress("DEPRECATION") // We intentionally want to test against the legacy API here. + override fun receiveCommand(view: SampleNativeView, commandId: Int, args: ReadableArray?) { + when (commandId) { + COMMAND_CHANGE_BACKGROUND_COLOR -> { + val sentColor: Int = Color.parseColor(args?.getString(0)) + view.setBackgroundColor(sentColor) + } + } + } + + override fun getCommandsMap(): Map = + mapOf("changeBackgroundColor" to COMMAND_CHANGE_BACKGROUND_COLOR) + + companion object { + const val REACT_CLASS = "SampleNativeComponent" + const val COMMAND_CHANGE_BACKGROUND_COLOR = 42 + } + + @ReactProp(name = "values") + override fun setValues(view: SampleNativeView, value: ReadableArray?) { + val values = mutableListOf() + value?.toArrayList()?.forEach { values.add((it as Double).toInt()) } + view.emitOnArrayChangedEvent(values) + } +} diff --git a/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeView.kt b/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeView.kt new file mode 100644 index 00000000000000..34ea4b8ea5b48c --- /dev/null +++ b/packages/react-native-test-library/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeView.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnative.osslibraryexample + +import android.graphics.drawable.GradientDrawable +import android.view.View +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.ReactContext +import com.facebook.react.bridge.WritableArray +import com.facebook.react.bridge.WritableMap +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.UIManagerHelper +import com.facebook.react.uimanager.events.Event + +public class SampleNativeView(context: ThemedReactContext) : View(context) { + private var currentColor = 0 + private var background: GradientDrawable = GradientDrawable() + private val reactContext: ReactContext = context.reactApplicationContext + + override fun setBackgroundColor(color: Int) { + if (color != currentColor) { + background.setColor(color) + currentColor = color + setBackground(background) + } + } + + public fun setCornerRadius(cornerRadius: Float) { + background.cornerRadius = cornerRadius + setBackground(background) + } + + public fun emitOnArrayChangedEvent(ints: List) { + val newIntArray = Arguments.createArray() + val newBoolArray = Arguments.createArray() + val newFloatArray = Arguments.createArray() + val newDoubleArray = Arguments.createArray() + val newYesNoArray = Arguments.createArray() + val newStringArray = Arguments.createArray() + val newObjectArray = Arguments.createArray() + val newArrayArray = Arguments.createArray() + + for (i in ints) { + newIntArray.pushInt(i * 2) + newBoolArray.pushBoolean(i % 2 == 1) + newFloatArray.pushDouble(i * 3.14) + newDoubleArray.pushDouble(i / 3.14) + newYesNoArray.pushString(if (i % 2 == 1) "yep" else "nope") + newStringArray.pushString(i.toString()) + + val latLon = Arguments.createMap() + latLon.putDouble("lat", -1.0 * i) + latLon.putDouble("lon", 2.0 * i) + newObjectArray.pushMap(latLon) + + val innerArray: WritableArray = Arguments.createArray() + innerArray.pushInt(i) + innerArray.pushInt(i) + innerArray.pushInt(i) + newArrayArray.pushArray(innerArray) + } + + val payload = + Arguments.createMap().apply { + putArray("values", newIntArray) + putArray("boolValues", newBoolArray) + putArray("floats", newFloatArray) + putArray("doubles", newDoubleArray) + putArray("yesNos", newYesNoArray) + putArray("strings", newStringArray) + putArray("latLons", newObjectArray) + putArray("multiArrays", newArrayArray) + } + + val reactContext = context as ReactContext + val surfaceId = UIManagerHelper.getSurfaceId(reactContext) + val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id) + val event = OnIntArrayChangedEvent(surfaceId, id, payload) + + eventDispatcher?.dispatchEvent(event) + } + + private inner class OnIntArrayChangedEvent( + surfaceId: Int, + viewId: Int, + private val payload: WritableMap + ) : Event(surfaceId, viewId) { + override fun getEventName() = "topIntArrayChanged" + + override fun getEventData() = payload + } +} diff --git a/packages/react-native-test-library/android/src/main/jni/CMakeLists.txt b/packages/react-native-test-library/android/src/main/jni/CMakeLists.txt new file mode 100644 index 00000000000000..ab02a2a4a4170d --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +file(GLOB react_codegen_SRCS CONFIGURE_DEPENDS *.cpp react/renderer/components/OSSLibraryExampleSpec/*.cpp) + +add_library( + react_codegen_OSSLibraryExampleSpec + SHARED + ${react_codegen_SRCS} +) + +target_include_directories(react_codegen_OSSLibraryExampleSpec PUBLIC . react/renderer/components/OSSLibraryExampleSpec) + +target_link_libraries( + react_codegen_OSSLibraryExampleSpec + fbjni + folly_runtime + glog + jsi + react_codegen_rncore + react_debug + react_nativemodule_core + react_render_componentregistry + react_render_core + react_render_debug + react_render_graphics + react_render_imagemanager + react_render_mapbuffer + react_utils + rrc_image + rrc_view + turbomodulejsijni + yoga +) + +target_compile_options( + react_codegen_OSSLibraryExampleSpec + PRIVATE + -DLOG_TAG=\"ReactNative\" + -fexceptions + -frtti + -std=c++20 + -Wall +) diff --git a/packages/react-native-test-library/android/src/main/jni/OSSLibraryExampleSpec-generated.cpp b/packages/react-native-test-library/android/src/main/jni/OSSLibraryExampleSpec-generated.cpp new file mode 100644 index 00000000000000..b940af418aa7a2 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/OSSLibraryExampleSpec-generated.cpp @@ -0,0 +1,32 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJniCpp.js + */ + +#include "OSSLibraryExampleSpec.h" + +namespace facebook::react { + +static facebook::jsi::Value __hostFunction_NativeSampleModuleSpecJSI_getRandomNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static jmethodID cachedMethodId = nullptr; + return static_cast(turboModule).invokeJavaMethod(rt, NumberKind, "getRandomNumber", "()D", args, count, cachedMethodId); +} + +NativeSampleModuleSpecJSI::NativeSampleModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) + : JavaTurboModule(params) { + methodMap_["getRandomNumber"] = MethodMetadata {0, __hostFunction_NativeSampleModuleSpecJSI_getRandomNumber}; +} + +std::shared_ptr OSSLibraryExampleSpec_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == "NativeSampleModule") { + return std::make_shared(params); + } + return nullptr; +} + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/OSSLibraryExampleSpec.h b/packages/react-native-test-library/android/src/main/jni/OSSLibraryExampleSpec.h new file mode 100644 index 00000000000000..6d39f6b6de3dbf --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/OSSLibraryExampleSpec.h @@ -0,0 +1,31 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJniH.js + */ + +#pragma once + +#include +#include +#include + +namespace facebook::react { + +/** + * JNI C++ class for module 'NativeSampleModule' + */ +class JSI_EXPORT NativeSampleModuleSpecJSI : public JavaTurboModule { +public: + NativeSampleModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); +}; + + +JSI_EXPORT +std::shared_ptr OSSLibraryExampleSpec_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms); + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ComponentDescriptors.cpp b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ComponentDescriptors.cpp new file mode 100644 index 00000000000000..385369e4c052a3 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ComponentDescriptors.cpp @@ -0,0 +1,22 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateComponentDescriptorCpp.js + */ + +#include "ComponentDescriptors.h" +#include +#include + +namespace facebook::react { + +void OSSLibraryExampleSpec_registerComponentDescriptorsFromCodegen( + std::shared_ptr registry) { +registry->add(concreteComponentDescriptorProvider()); +} + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ComponentDescriptors.h b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ComponentDescriptors.h new file mode 100644 index 00000000000000..eac078b81d9d74 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ComponentDescriptors.h @@ -0,0 +1,24 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateComponentDescriptorH.js + */ + +#pragma once + +#include "ShadowNodes.h" +#include +#include + +namespace facebook::react { + +using SampleNativeComponentComponentDescriptor = ConcreteComponentDescriptor; + +void OSSLibraryExampleSpec_registerComponentDescriptorsFromCodegen( + std::shared_ptr registry); + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/EventEmitters.cpp b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/EventEmitters.cpp new file mode 100644 index 00000000000000..c5746ac5306da6 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/EventEmitters.cpp @@ -0,0 +1,95 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateEventEmitterCpp.js + */ + +#include "EventEmitters.h" + + +namespace facebook::react { + +void SampleNativeComponentEventEmitter::onIntArrayChanged(OnIntArrayChanged $event) const { + dispatchEvent("intArrayChanged", [$event=std::move($event)](jsi::Runtime &runtime) { + auto $payload = jsi::Object(runtime); + + auto values = jsi::Array(runtime, $event.values.size()); + size_t valuesIndex = 0; + for (auto valuesValue : $event.values) { + values.setValueAtIndex(runtime, valuesIndex++, valuesValue); + } + $payload.setProperty(runtime, "values", values); + + + auto boolValues = jsi::Array(runtime, $event.boolValues.size()); + size_t boolValuesIndex = 0; + for (auto boolValuesValue : $event.boolValues) { + boolValues.setValueAtIndex(runtime, boolValuesIndex++, (bool)boolValuesValue); + } + $payload.setProperty(runtime, "boolValues", boolValues); + + + auto floats = jsi::Array(runtime, $event.floats.size()); + size_t floatsIndex = 0; + for (auto floatsValue : $event.floats) { + floats.setValueAtIndex(runtime, floatsIndex++, floatsValue); + } + $payload.setProperty(runtime, "floats", floats); + + + auto doubles = jsi::Array(runtime, $event.doubles.size()); + size_t doublesIndex = 0; + for (auto doublesValue : $event.doubles) { + doubles.setValueAtIndex(runtime, doublesIndex++, doublesValue); + } + $payload.setProperty(runtime, "doubles", doubles); + + + auto yesNos = jsi::Array(runtime, $event.yesNos.size()); + size_t yesNosIndex = 0; + for (auto yesNosValue : $event.yesNos) { + yesNos.setValueAtIndex(runtime, yesNosIndex++, toString(yesNosValue)); + } + $payload.setProperty(runtime, "yesNos", yesNos); + + + auto strings = jsi::Array(runtime, $event.strings.size()); + size_t stringsIndex = 0; + for (auto stringsValue : $event.strings) { + strings.setValueAtIndex(runtime, stringsIndex++, stringsValue); + } + $payload.setProperty(runtime, "strings", strings); + + + auto latLons = jsi::Array(runtime, $event.latLons.size()); + size_t latLonsIndex = 0; + for (auto latLonsValue : $event.latLons) { + auto latLonsObject = jsi::Object(runtime); + latLonsObject.setProperty(runtime, "lat", latLonsValue.lat); +latLonsObject.setProperty(runtime, "lon", latLonsValue.lon); + latLons.setValueAtIndex(runtime, latLonsIndex++, latLonsObject); + } + $payload.setProperty(runtime, "latLons", latLons); + + + auto multiArrays = jsi::Array(runtime, $event.multiArrays.size()); + size_t multiArraysIndex = 0; + for (auto multiArraysValue : $event.multiArrays) { + auto multiArraysArray = jsi::Array(runtime, multiArraysValue.size()); + size_t multiArraysIndexInternal = 0; + for (auto multiArraysValueInternal : multiArraysValue) { + multiArraysArray.setValueAtIndex(runtime, multiArraysIndexInternal++, multiArraysValueInternal); + } + multiArrays.setValueAtIndex(runtime, multiArraysIndex++, multiArraysArray); + } + $payload.setProperty(runtime, "multiArrays", multiArrays); + + return $payload; + }); +} + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/EventEmitters.h b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/EventEmitters.h new file mode 100644 index 00000000000000..bfb9cc27ae82e1 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/EventEmitters.h @@ -0,0 +1,49 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateEventEmitterH.js + */ +#pragma once + +#include + + +namespace facebook::react { +class SampleNativeComponentEventEmitter : public ViewEventEmitter { + public: + using ViewEventEmitter::ViewEventEmitter; + + enum class OnIntArrayChangedYesNos { + Yep, + Nope + }; + + static char const *toString(const OnIntArrayChangedYesNos value) { + switch (value) { + case OnIntArrayChangedYesNos::Yep: return "yep"; + case OnIntArrayChangedYesNos::Nope: return "nope"; + } + } + + struct OnIntArrayChangedLatLons { + double lat; + double lon; + }; + + struct OnIntArrayChanged { + std::vector values; + std::vector boolValues; + std::vector floats; + std::vector doubles; + std::vector yesNos; + std::vector strings; + std::vector latLons; + std::vector> multiArrays; + }; + void onIntArrayChanged(OnIntArrayChanged value) const; +}; +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/OSSLibraryExampleSpecJSI-generated.cpp b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/OSSLibraryExampleSpecJSI-generated.cpp new file mode 100644 index 00000000000000..fc734d9e6f30e6 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/OSSLibraryExampleSpecJSI-generated.cpp @@ -0,0 +1,26 @@ +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleCpp.js + */ + +#include "OSSLibraryExampleSpecJSI.h" + +namespace facebook::react { + +static jsi::Value __hostFunction_NativeSampleModuleCxxSpecJSI_getRandomNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getRandomNumber( + rt + ); +} + +NativeSampleModuleCxxSpecJSI::NativeSampleModuleCxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule("NativeSampleModule", jsInvoker) { + methodMap_["getRandomNumber"] = MethodMetadata {0, __hostFunction_NativeSampleModuleCxxSpecJSI_getRandomNumber}; +} + + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/OSSLibraryExampleSpecJSI.h b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/OSSLibraryExampleSpecJSI.h new file mode 100644 index 00000000000000..7955b323295eec --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/OSSLibraryExampleSpecJSI.h @@ -0,0 +1,63 @@ +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleH.js + */ + +#pragma once + +#include +#include + +namespace facebook::react { + + + class JSI_EXPORT NativeSampleModuleCxxSpecJSI : public TurboModule { +protected: + NativeSampleModuleCxxSpecJSI(std::shared_ptr jsInvoker); + +public: + virtual double getRandomNumber(jsi::Runtime &rt) = 0; + +}; + +template +class JSI_EXPORT NativeSampleModuleCxxSpec : public TurboModule { +public: + jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override { + return delegate_.get(rt, propName); + } + + static constexpr std::string_view kModuleName = "NativeSampleModule"; + +protected: + NativeSampleModuleCxxSpec(std::shared_ptr jsInvoker) + : TurboModule(std::string{NativeSampleModuleCxxSpec::kModuleName}, jsInvoker), + delegate_(reinterpret_cast(this), jsInvoker) {} + +private: + class Delegate : public NativeSampleModuleCxxSpecJSI { + public: + Delegate(T *instance, std::shared_ptr jsInvoker) : + NativeSampleModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + + double getRandomNumber(jsi::Runtime &rt) override { + static_assert( + bridging::getParameterCount(&T::getRandomNumber) == 1, + "Expected getRandomNumber(...) to have 1 parameters"); + + return bridging::callFromJs( + rt, &T::getRandomNumber, jsInvoker_, instance_); + } + + private: + T *instance_; + }; + + Delegate delegate_; +}; + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/Props.cpp b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/Props.cpp new file mode 100644 index 00000000000000..595766f26bd083 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/Props.cpp @@ -0,0 +1,26 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GeneratePropsCpp.js + */ + +#include "Props.h" +#include +#include + +namespace facebook::react { + +SampleNativeComponentProps::SampleNativeComponentProps( + const PropsParserContext &context, + const SampleNativeComponentProps &sourceProps, + const RawProps &rawProps): ViewProps(context, sourceProps, rawProps), + + opacity(convertRawProp(context, rawProps, "opacity", sourceProps.opacity, {0.0})), + values(convertRawProp(context, rawProps, "values", sourceProps.values, {})) + {} + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/Props.h b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/Props.h new file mode 100644 index 00000000000000..fd7ad9642bcb22 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/Props.h @@ -0,0 +1,29 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GeneratePropsH.js + */ +#pragma once + +#include +#include +#include + +namespace facebook::react { + +class SampleNativeComponentProps final : public ViewProps { + public: + SampleNativeComponentProps() = default; + SampleNativeComponentProps(const PropsParserContext& context, const SampleNativeComponentProps &sourceProps, const RawProps &rawProps); + +#pragma mark - Props + + Float opacity{0.0}; + std::vector values{}; +}; + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ShadowNodes.cpp b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ShadowNodes.cpp new file mode 100644 index 00000000000000..790189cffd6e1e --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ShadowNodes.cpp @@ -0,0 +1,17 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateShadowNodeCpp.js + */ + +#include "ShadowNodes.h" + +namespace facebook::react { + +extern const char SampleNativeComponentComponentName[] = "SampleNativeComponent"; + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ShadowNodes.h b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ShadowNodes.h new file mode 100644 index 00000000000000..20b9db3837a1c7 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/ShadowNodes.h @@ -0,0 +1,32 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateShadowNodeH.js + */ + +#pragma once + +#include "EventEmitters.h" +#include "Props.h" +#include "States.h" +#include +#include + +namespace facebook::react { + +JSI_EXPORT extern const char SampleNativeComponentComponentName[]; + +/* + * `ShadowNode` for component. + */ +using SampleNativeComponentShadowNode = ConcreteViewShadowNode< + SampleNativeComponentComponentName, + SampleNativeComponentProps, + SampleNativeComponentEventEmitter, + SampleNativeComponentState>; + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/States.cpp b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/States.cpp new file mode 100644 index 00000000000000..1dbb184cbddb62 --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/States.cpp @@ -0,0 +1,16 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateStateCpp.js + */ +#include "States.h" + +namespace facebook::react { + + + +} // namespace facebook::react diff --git a/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/States.h b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/States.h new file mode 100644 index 00000000000000..f4d6efa82c0acf --- /dev/null +++ b/packages/react-native-test-library/android/src/main/jni/react/renderer/components/OSSLibraryExampleSpec/States.h @@ -0,0 +1,34 @@ +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateStateH.js + */ +#pragma once + +#ifdef ANDROID +#include +#include +#include +#endif + +namespace facebook::react { + +class SampleNativeComponentState { +public: + SampleNativeComponentState() = default; + +#ifdef ANDROID + SampleNativeComponentState(SampleNativeComponentState const &previousState, folly::dynamic data){}; + folly::dynamic getDynamic() const { + return {}; + }; + MapBuffer getMapBuffer() const { + return MapBufferBuilder::EMPTY(); + }; +#endif +}; + +} // namespace facebook::react \ No newline at end of file diff --git a/packages/react-native-test-library/babel.config.js b/packages/react-native-test-library/babel.config.js new file mode 100644 index 00000000000000..3bcc1e3d56e200 --- /dev/null +++ b/packages/react-native-test-library/babel.config.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +module.exports = { + presets: [['module:@react-native/babel-preset', {disableStaticViewConfigsCodegen: false}]], +}; diff --git a/packages/react-native-test-library/index.js b/packages/react-native-test-library/index.js new file mode 100644 index 00000000000000..a623cdc1ef00de --- /dev/null +++ b/packages/react-native-test-library/index.js @@ -0,0 +1,15 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +export {default as SampleNativeComponent} from './src/SampleNativeComponent'; +export type {NativeComponentType} from './src/SampleNativeComponent'; +import {Commands as SampleNativeComponentCommands} from './src/SampleNativeComponent'; +export {SampleNativeComponentCommands}; +export {default as NativeSampleModule} from './src/NativeSampleModule'; diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ComponentDescriptors.cpp b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ComponentDescriptors.cpp new file mode 100644 index 00000000000000..385369e4c052a3 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ComponentDescriptors.cpp @@ -0,0 +1,22 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateComponentDescriptorCpp.js + */ + +#include "ComponentDescriptors.h" +#include +#include + +namespace facebook::react { + +void OSSLibraryExampleSpec_registerComponentDescriptorsFromCodegen( + std::shared_ptr registry) { +registry->add(concreteComponentDescriptorProvider()); +} + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ComponentDescriptors.h b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ComponentDescriptors.h new file mode 100644 index 00000000000000..eac078b81d9d74 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ComponentDescriptors.h @@ -0,0 +1,24 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateComponentDescriptorH.js + */ + +#pragma once + +#include "ShadowNodes.h" +#include +#include + +namespace facebook::react { + +using SampleNativeComponentComponentDescriptor = ConcreteComponentDescriptor; + +void OSSLibraryExampleSpec_registerComponentDescriptorsFromCodegen( + std::shared_ptr registry); + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/EventEmitters.cpp b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/EventEmitters.cpp new file mode 100644 index 00000000000000..c5746ac5306da6 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/EventEmitters.cpp @@ -0,0 +1,95 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateEventEmitterCpp.js + */ + +#include "EventEmitters.h" + + +namespace facebook::react { + +void SampleNativeComponentEventEmitter::onIntArrayChanged(OnIntArrayChanged $event) const { + dispatchEvent("intArrayChanged", [$event=std::move($event)](jsi::Runtime &runtime) { + auto $payload = jsi::Object(runtime); + + auto values = jsi::Array(runtime, $event.values.size()); + size_t valuesIndex = 0; + for (auto valuesValue : $event.values) { + values.setValueAtIndex(runtime, valuesIndex++, valuesValue); + } + $payload.setProperty(runtime, "values", values); + + + auto boolValues = jsi::Array(runtime, $event.boolValues.size()); + size_t boolValuesIndex = 0; + for (auto boolValuesValue : $event.boolValues) { + boolValues.setValueAtIndex(runtime, boolValuesIndex++, (bool)boolValuesValue); + } + $payload.setProperty(runtime, "boolValues", boolValues); + + + auto floats = jsi::Array(runtime, $event.floats.size()); + size_t floatsIndex = 0; + for (auto floatsValue : $event.floats) { + floats.setValueAtIndex(runtime, floatsIndex++, floatsValue); + } + $payload.setProperty(runtime, "floats", floats); + + + auto doubles = jsi::Array(runtime, $event.doubles.size()); + size_t doublesIndex = 0; + for (auto doublesValue : $event.doubles) { + doubles.setValueAtIndex(runtime, doublesIndex++, doublesValue); + } + $payload.setProperty(runtime, "doubles", doubles); + + + auto yesNos = jsi::Array(runtime, $event.yesNos.size()); + size_t yesNosIndex = 0; + for (auto yesNosValue : $event.yesNos) { + yesNos.setValueAtIndex(runtime, yesNosIndex++, toString(yesNosValue)); + } + $payload.setProperty(runtime, "yesNos", yesNos); + + + auto strings = jsi::Array(runtime, $event.strings.size()); + size_t stringsIndex = 0; + for (auto stringsValue : $event.strings) { + strings.setValueAtIndex(runtime, stringsIndex++, stringsValue); + } + $payload.setProperty(runtime, "strings", strings); + + + auto latLons = jsi::Array(runtime, $event.latLons.size()); + size_t latLonsIndex = 0; + for (auto latLonsValue : $event.latLons) { + auto latLonsObject = jsi::Object(runtime); + latLonsObject.setProperty(runtime, "lat", latLonsValue.lat); +latLonsObject.setProperty(runtime, "lon", latLonsValue.lon); + latLons.setValueAtIndex(runtime, latLonsIndex++, latLonsObject); + } + $payload.setProperty(runtime, "latLons", latLons); + + + auto multiArrays = jsi::Array(runtime, $event.multiArrays.size()); + size_t multiArraysIndex = 0; + for (auto multiArraysValue : $event.multiArrays) { + auto multiArraysArray = jsi::Array(runtime, multiArraysValue.size()); + size_t multiArraysIndexInternal = 0; + for (auto multiArraysValueInternal : multiArraysValue) { + multiArraysArray.setValueAtIndex(runtime, multiArraysIndexInternal++, multiArraysValueInternal); + } + multiArrays.setValueAtIndex(runtime, multiArraysIndex++, multiArraysArray); + } + $payload.setProperty(runtime, "multiArrays", multiArrays); + + return $payload; + }); +} + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/EventEmitters.h b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/EventEmitters.h new file mode 100644 index 00000000000000..bfb9cc27ae82e1 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/EventEmitters.h @@ -0,0 +1,49 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateEventEmitterH.js + */ +#pragma once + +#include + + +namespace facebook::react { +class SampleNativeComponentEventEmitter : public ViewEventEmitter { + public: + using ViewEventEmitter::ViewEventEmitter; + + enum class OnIntArrayChangedYesNos { + Yep, + Nope + }; + + static char const *toString(const OnIntArrayChangedYesNos value) { + switch (value) { + case OnIntArrayChangedYesNos::Yep: return "yep"; + case OnIntArrayChangedYesNos::Nope: return "nope"; + } + } + + struct OnIntArrayChangedLatLons { + double lat; + double lon; + }; + + struct OnIntArrayChanged { + std::vector values; + std::vector boolValues; + std::vector floats; + std::vector doubles; + std::vector yesNos; + std::vector strings; + std::vector latLons; + std::vector> multiArrays; + }; + void onIntArrayChanged(OnIntArrayChanged value) const; +}; +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/OSSLibraryExampleSpec-generated.mm b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/OSSLibraryExampleSpec-generated.mm new file mode 100644 index 00000000000000..faf7056af985a4 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/OSSLibraryExampleSpec-generated.mm @@ -0,0 +1,29 @@ +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#import "OSSLibraryExampleSpec.h" + + +namespace facebook::react { + + static facebook::jsi::Value __hostFunction_NativeSampleModuleSpecJSI_getRandomNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, "getRandomNumber", @selector(getRandomNumber), args, count); + } + + NativeSampleModuleSpecJSI::NativeSampleModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_["getRandomNumber"] = MethodMetadata {0, __hostFunction_NativeSampleModuleSpecJSI_getRandomNumber}; + + } +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/OSSLibraryExampleSpec.h b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/OSSLibraryExampleSpec.h new file mode 100644 index 00000000000000..462a85d5c430e4 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/OSSLibraryExampleSpec.h @@ -0,0 +1,43 @@ +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +@protocol NativeSampleModuleSpec + +- (NSNumber *)getRandomNumber; + +@end +namespace facebook::react { + /** + * ObjC++ class for module 'NativeSampleModule' + */ + class JSI_EXPORT NativeSampleModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; +} // namespace facebook::react + diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/Props.cpp b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/Props.cpp new file mode 100644 index 00000000000000..595766f26bd083 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/Props.cpp @@ -0,0 +1,26 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GeneratePropsCpp.js + */ + +#include "Props.h" +#include +#include + +namespace facebook::react { + +SampleNativeComponentProps::SampleNativeComponentProps( + const PropsParserContext &context, + const SampleNativeComponentProps &sourceProps, + const RawProps &rawProps): ViewProps(context, sourceProps, rawProps), + + opacity(convertRawProp(context, rawProps, "opacity", sourceProps.opacity, {0.0})), + values(convertRawProp(context, rawProps, "values", sourceProps.values, {})) + {} + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/Props.h b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/Props.h new file mode 100644 index 00000000000000..fd7ad9642bcb22 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/Props.h @@ -0,0 +1,29 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GeneratePropsH.js + */ +#pragma once + +#include +#include +#include + +namespace facebook::react { + +class SampleNativeComponentProps final : public ViewProps { + public: + SampleNativeComponentProps() = default; + SampleNativeComponentProps(const PropsParserContext& context, const SampleNativeComponentProps &sourceProps, const RawProps &rawProps); + +#pragma mark - Props + + Float opacity{0.0}; + std::vector values{}; +}; + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/RCTComponentViewHelpers.h b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/RCTComponentViewHelpers.h new file mode 100644 index 00000000000000..d6e5a3531eedff --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/RCTComponentViewHelpers.h @@ -0,0 +1,50 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GenerateComponentHObjCpp.js +*/ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol RCTSampleNativeComponentViewProtocol +- (void)changeBackgroundColor:(NSString *)color; +@end + +RCT_EXTERN inline void RCTSampleNativeComponentHandleCommand( + id componentView, + NSString const *commandName, + NSArray const *args) +{ + if ([commandName isEqualToString:@"changeBackgroundColor"]) { +#if RCT_DEBUG + if ([args count] != 1) { + RCTLogError(@"%@ command %@ received %d arguments, expected %d.", @"SampleNativeComponent", commandName, (int)[args count], 1); + return; + } +#endif + + NSObject *arg0 = args[0]; +#if RCT_DEBUG + if (!RCTValidateTypeOfViewCommandArgument(arg0, [NSString class], @"string", @"SampleNativeComponent", commandName, @"1st")) { + return; + } +#endif + NSString * color = (NSString *)arg0; + + [componentView changeBackgroundColor:color]; + return; +} + +#if RCT_DEBUG + RCTLogError(@"%@ received command %@, which is not a supported command.", @"SampleNativeComponent", commandName); +#endif +} + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ShadowNodes.cpp b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ShadowNodes.cpp new file mode 100644 index 00000000000000..790189cffd6e1e --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ShadowNodes.cpp @@ -0,0 +1,17 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateShadowNodeCpp.js + */ + +#include "ShadowNodes.h" + +namespace facebook::react { + +extern const char SampleNativeComponentComponentName[] = "SampleNativeComponent"; + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ShadowNodes.h b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ShadowNodes.h new file mode 100644 index 00000000000000..20b9db3837a1c7 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/ShadowNodes.h @@ -0,0 +1,32 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateShadowNodeH.js + */ + +#pragma once + +#include "EventEmitters.h" +#include "Props.h" +#include "States.h" +#include +#include + +namespace facebook::react { + +JSI_EXPORT extern const char SampleNativeComponentComponentName[]; + +/* + * `ShadowNode` for component. + */ +using SampleNativeComponentShadowNode = ConcreteViewShadowNode< + SampleNativeComponentComponentName, + SampleNativeComponentProps, + SampleNativeComponentEventEmitter, + SampleNativeComponentState>; + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/States.cpp b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/States.cpp new file mode 100644 index 00000000000000..1dbb184cbddb62 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/States.cpp @@ -0,0 +1,16 @@ + +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateStateCpp.js + */ +#include "States.h" + +namespace facebook::react { + + + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpec/States.h b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/States.h new file mode 100644 index 00000000000000..f4d6efa82c0acf --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpec/States.h @@ -0,0 +1,34 @@ +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateStateH.js + */ +#pragma once + +#ifdef ANDROID +#include +#include +#include +#endif + +namespace facebook::react { + +class SampleNativeComponentState { +public: + SampleNativeComponentState() = default; + +#ifdef ANDROID + SampleNativeComponentState(SampleNativeComponentState const &previousState, folly::dynamic data){}; + folly::dynamic getDynamic() const { + return {}; + }; + MapBuffer getMapBuffer() const { + return MapBufferBuilder::EMPTY(); + }; +#endif +}; + +} // namespace facebook::react \ No newline at end of file diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpecJSI-generated.cpp b/packages/react-native-test-library/ios/OSSLibraryExampleSpecJSI-generated.cpp new file mode 100644 index 00000000000000..fc734d9e6f30e6 --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpecJSI-generated.cpp @@ -0,0 +1,26 @@ +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleCpp.js + */ + +#include "OSSLibraryExampleSpecJSI.h" + +namespace facebook::react { + +static jsi::Value __hostFunction_NativeSampleModuleCxxSpecJSI_getRandomNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getRandomNumber( + rt + ); +} + +NativeSampleModuleCxxSpecJSI::NativeSampleModuleCxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule("NativeSampleModule", jsInvoker) { + methodMap_["getRandomNumber"] = MethodMetadata {0, __hostFunction_NativeSampleModuleCxxSpecJSI_getRandomNumber}; +} + + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/OSSLibraryExampleSpecJSI.h b/packages/react-native-test-library/ios/OSSLibraryExampleSpecJSI.h new file mode 100644 index 00000000000000..7955b323295eec --- /dev/null +++ b/packages/react-native-test-library/ios/OSSLibraryExampleSpecJSI.h @@ -0,0 +1,63 @@ +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleH.js + */ + +#pragma once + +#include +#include + +namespace facebook::react { + + + class JSI_EXPORT NativeSampleModuleCxxSpecJSI : public TurboModule { +protected: + NativeSampleModuleCxxSpecJSI(std::shared_ptr jsInvoker); + +public: + virtual double getRandomNumber(jsi::Runtime &rt) = 0; + +}; + +template +class JSI_EXPORT NativeSampleModuleCxxSpec : public TurboModule { +public: + jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override { + return delegate_.get(rt, propName); + } + + static constexpr std::string_view kModuleName = "NativeSampleModule"; + +protected: + NativeSampleModuleCxxSpec(std::shared_ptr jsInvoker) + : TurboModule(std::string{NativeSampleModuleCxxSpec::kModuleName}, jsInvoker), + delegate_(reinterpret_cast(this), jsInvoker) {} + +private: + class Delegate : public NativeSampleModuleCxxSpecJSI { + public: + Delegate(T *instance, std::shared_ptr jsInvoker) : + NativeSampleModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + + double getRandomNumber(jsi::Runtime &rt) override { + static_assert( + bridging::getParameterCount(&T::getRandomNumber) == 1, + "Expected getRandomNumber(...) to have 1 parameters"); + + return bridging::callFromJs( + rt, &T::getRandomNumber, jsInvoker_, instance_); + } + + private: + T *instance_; + }; + + Delegate delegate_; +}; + +} // namespace facebook::react diff --git a/packages/react-native-test-library/ios/RCTNativeSampleModule.mm b/packages/react-native-test-library/ios/RCTNativeSampleModule.mm new file mode 100644 index 00000000000000..b5a059b7f6e61a --- /dev/null +++ b/packages/react-native-test-library/ios/RCTNativeSampleModule.mm @@ -0,0 +1,47 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#ifdef RCT_NEW_ARCH_ENABLED +#import "OSSLibraryExampleSpec/OSSLibraryExampleSpec.h" +#else +#import +#endif + +#import +#include +#include + +#ifdef RCT_NEW_ARCH_ENABLED +@interface RCTNativeSampleModule : NSObject +#else +@interface RCTNativeSampleModule : NSObject +#endif + +@end + +@implementation RCTNativeSampleModule + +RCT_EXPORT_MODULE(); + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} +#endif + +#ifdef RCT_NEW_ARCH_ENABLED +- (NSNumber *)getRandomNumber +#else +RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSNumber *, getRandomNumber) +#endif +{ + return @(arc4random_uniform(99)); +} + +@end diff --git a/packages/react-native-test-library/ios/RCTSampleNativeComponentComponentView.mm b/packages/react-native-test-library/ios/RCTSampleNativeComponentComponentView.mm new file mode 100644 index 00000000000000..13dca042838eab --- /dev/null +++ b/packages/react-native-test-library/ios/RCTSampleNativeComponentComponentView.mm @@ -0,0 +1,139 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "OSSLibraryExampleSpec/ComponentDescriptors.h" +#import "OSSLibraryExampleSpec/EventEmitters.h" +#import "OSSLibraryExampleSpec/Props.h" +#import "OSSLibraryExampleSpec/RCTComponentViewHelpers.h" + +#import "RCTFabricComponentsPlugins.h" + +#import +#import +#import + +using namespace facebook::react; + +static UIColor *UIColorFromHexString(const std::string hexString) +{ + unsigned rgbValue = 0; + NSString *colorString = [NSString stringWithCString:hexString.c_str() encoding:[NSString defaultCStringEncoding]]; + NSScanner *scanner = [NSScanner scannerWithString:colorString]; + [scanner setScanLocation:1]; // bypass '#' character + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0 + green:((rgbValue & 0xFF00) >> 8) / 255.0 + blue:(rgbValue & 0xFF) / 255.0 + alpha:1.0]; +} + +@interface RCTSampleNativeComponentComponentView : RCTViewComponentView + +@property (nonatomic, copy) RCTBubblingEventBlock onIntArrayChanged; + +@end + +@implementation RCTSampleNativeComponentComponentView { + UIView *_view; +} + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +// Load is not invoked if it is not defined, therefore, we must ask to update this. +// See the Apple documentation: https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc +// "[...] but only if the newly loaded class or category implements a method that can respond." ++ (void)load +{ + [super load]; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + + _view = [[UIView alloc] init]; + _view.backgroundColor = [UIColor redColor]; + + self.contentView = _view; + } + + return self; +} + +- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps +{ + const auto &oldViewProps = *std::static_pointer_cast(_props); + const auto &newViewProps = *std::static_pointer_cast(props); + + if (oldViewProps.values != newViewProps.values) { + if (_eventEmitter) { + std::vector newVector = {}; + std::vector newBoolVector = {}; + std::vector newFloatVector = {}; + std::vector newDoubleVector = {}; + std::vector newYesNoVector = {}; + std::vector newStringVector = {}; + std::vector newLatLonVector = {}; + std::vector> newIntVectorVector = {}; + for (auto val : newViewProps.values) { + newVector.push_back(val * 2); + newBoolVector.push_back(val % 2 ? true : false); + newFloatVector.push_back(val * 3.14); + newDoubleVector.push_back(val / 3.14); + newYesNoVector.push_back( + val % 2 ? SampleNativeComponentEventEmitter::OnIntArrayChangedYesNos::Yep + : SampleNativeComponentEventEmitter::OnIntArrayChangedYesNos::Nope); + newStringVector.push_back(std::to_string(val)); + newLatLonVector.push_back({-1.0 * val, 2.0 * val}); + newIntVectorVector.push_back({val, val, val}); + } + SampleNativeComponentEventEmitter::OnIntArrayChanged value = { + newVector, + newBoolVector, + newFloatVector, + newDoubleVector, + newYesNoVector, + newStringVector, + newLatLonVector, + newIntVectorVector}; + std::static_pointer_cast(_eventEmitter)->onIntArrayChanged(value); + } + } + + [super updateProps:props oldProps:oldProps]; +} + +- (void)onChange:(UIView *)sender +{ + // No-op + // std::dynamic_pointer_cast(_eventEmitter) + // ->onChange(ViewEventEmitter::OnChange{.value = static_cast(sender.on)}); +} + +#pragma mark - Native Commands + +- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args +{ + RCTSampleNativeComponentHandleCommand(self, commandName, args); +} + +- (void)changeBackgroundColor:(NSString *)color +{ + _view.backgroundColor = UIColorFromHexString(std::string(color.UTF8String)); +} + +@end + +Class SampleNativeComponentCls(void) +{ + return RCTSampleNativeComponentComponentView.class; +} diff --git a/packages/react-native-test-library/ios/RCTSampleNativeComponentViewManager.mm b/packages/react-native-test-library/ios/RCTSampleNativeComponentViewManager.mm new file mode 100644 index 00000000000000..ffe7c6c9e013bc --- /dev/null +++ b/packages/react-native-test-library/ios/RCTSampleNativeComponentViewManager.mm @@ -0,0 +1,70 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import + +static UIColor *UIColorFromHexString(const std::string hexString) +{ + unsigned rgbValue = 0; + NSString *colorString = [NSString stringWithCString:hexString.c_str() encoding:[NSString defaultCStringEncoding]]; + NSScanner *scanner = [NSScanner scannerWithString:colorString]; + [scanner setScanLocation:1]; // bypass '#' character + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0 + green:((rgbValue & 0xFF00) >> 8) / 255.0 + blue:(rgbValue & 0xFF) / 255.0 + alpha:1.0]; +} + +@interface RCTSampleNativeComponentViewManager : RCTViewManager +@end + +@implementation RCTSampleNativeComponentViewManager + +RCT_EXPORT_MODULE(SampleNativeComponent) + +RCT_REMAP_VIEW_PROPERTY(color, backgroundColor, UIColor) + +RCT_REMAP_VIEW_PROPERTY(opacity, alpha, CGFloat) + +RCT_EXPORT_VIEW_PROPERTY(onColorChanged, RCTBubblingEventBlock) + +RCT_CUSTOM_VIEW_PROPERTY(cornerRadius, CGFloat, UIView) +{ + view.clipsToBounds = true; + NSNumber *cornerRadius = (NSNumber *)json; + view.layer.cornerRadius = [cornerRadius floatValue]; +} + +RCT_EXPORT_METHOD(changeBackgroundColor : (nonnull NSNumber *)reactTag color : (NSString *)color) +{ + [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { + if (UIView *view = [RCTSampleNativeComponentViewManager getViewByTag:viewRegistry reactTag:reactTag]) { + view.backgroundColor = UIColorFromHexString(std::string(color.UTF8String)); + } + }]; +} + ++ (UIView *)getViewByTag:(NSDictionary *)viewRegistry reactTag:(nonnull NSNumber *)reactTag +{ + UIView *view = viewRegistry[reactTag]; + if (view == nil) { + RCTLogError(@"Cannot find view with tag #%@", reactTag); + } + return view; +} + +- (UIView *)view +{ + UIView *view = [UIView new]; + view.backgroundColor = UIColor.redColor; + return view; +} + +@end diff --git a/packages/react-native-test-library/package.json b/packages/react-native-test-library/package.json new file mode 100644 index 00000000000000..570f625463fc24 --- /dev/null +++ b/packages/react-native-test-library/package.json @@ -0,0 +1,49 @@ +{ + "name": "@react-native/oss-library-example", + "version": "0.0.1", + "private": true, + "description": "Package that includes native module exapmle, native component example, targets both the old and the new architecture. It should serve as an example of a real-world OSS library.", + "license": "MIT", + "homepage": "https://github.com/facebook/react-native.git", + "repository": { + "type": "git", + "url": "https://github.com/facebook/react-native.git", + "directory": "packages/react-native-test-library" + }, + "main": "./index.js", + "exports": { + "./": "./index.js", + "./package.json": "./package.json" + }, + "scripts": { + "build": "yarn clean && babel --out-dir lib src", + "clean": "rimraf lib", + "codegen": "npx react-native codegen", + "prepare": "yarn run codegen && yarn run build" + }, + "files": [ + "generated" + ], + "devDependencies": { + "@babel/core": "^7.20.0", + "@react-native/babel-preset": "0.75.0-main", + "react-native": "*" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + }, + "codegenConfig": { + "name": "OSSLibraryExampleSpec", + "type": "all", + "jsSrcsDir": "src", + "outputDir": { + "ios": "ios", + "android": "android/src/main" + }, + "includesGeneratedCode": true, + "android": { + "javaPackageName": "com.reactnative.osslibraryexample" + } + } +} diff --git a/packages/react-native-test-library/src/NativeSampleModule.js b/packages/react-native-test-library/src/NativeSampleModule.js new file mode 100644 index 00000000000000..de546b74e53d62 --- /dev/null +++ b/packages/react-native-test-library/src/NativeSampleModule.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; + +import {TurboModuleRegistry} from 'react-native'; + +export interface Spec extends TurboModule { + +getRandomNumber: () => number; +} + +export default (TurboModuleRegistry.get('NativeSampleModule'): ?Spec); diff --git a/packages/react-native-test-library/src/SampleNativeComponent.js b/packages/react-native-test-library/src/SampleNativeComponent.js new file mode 100644 index 00000000000000..b70a4947ee5bb3 --- /dev/null +++ b/packages/react-native-test-library/src/SampleNativeComponent.js @@ -0,0 +1,59 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; +import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; +import type { + BubblingEventHandler, + Double, + Float, + Int32, +} from 'react-native/Libraries/Types/CodegenTypes'; + +import * as React from 'react'; +import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +type Event = $ReadOnly<{ + values: $ReadOnlyArray, + boolValues: $ReadOnlyArray, + floats: $ReadOnlyArray, + doubles: $ReadOnlyArray, + yesNos: $ReadOnlyArray<'yep' | 'nope'>, + strings: $ReadOnlyArray, + latLons: $ReadOnlyArray<{|lat: Double, lon: Double|}>, + multiArrays: $ReadOnlyArray<$ReadOnlyArray>, +}>; + +type NativeProps = $ReadOnly<{| + ...ViewProps, + opacity?: Float, + values: $ReadOnlyArray, + + // Events + onIntArrayChanged?: ?BubblingEventHandler, +|}>; + +export type NativeComponentType = HostComponent; + +interface NativeCommands { + +changeBackgroundColor: ( + viewRef: React.ElementRef, + color: string, + ) => void; +} + +export const Commands: NativeCommands = codegenNativeCommands({ + supportedCommands: ['changeBackgroundColor'], +}); + +export default (codegenNativeComponent( + 'SampleNativeComponent', +): NativeComponentType); diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index 38b8c251da3862..7e723ec52341e6 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -60,6 +60,7 @@ def pods(target_name, options = {}) pod 'ScreenshotManager', :path => "NativeModuleExample" pod 'MyNativeView', :path => "NativeComponentExample" pod 'NativeCxxModuleExample', :path => "NativeCxxModuleExample" + pod 'OSSLibraryExample', :path => '../react-native-test-library' end target 'RNTester' do diff --git a/packages/rn-tester/android/app/build.gradle.kts b/packages/rn-tester/android/app/build.gradle.kts index e2c69a64985e34..30b5ad58d5c7a8 100644 --- a/packages/rn-tester/android/app/build.gradle.kts +++ b/packages/rn-tester/android/app/build.gradle.kts @@ -152,6 +152,7 @@ dependencies { // Build React Native from source implementation(project(":packages:react-native:ReactAndroid")) implementation(project(":packages:react-native-popup-menu-android:android")) + implementation(project(":packages:react-native-test-library:android")) // Consume Hermes as built from source only for the Hermes variant. "hermesImplementation"(project(":packages:react-native:ReactAndroid:hermes-engine")) diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.kt b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.kt index 8d863a242ca2cf..fdda006ee5534a 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.kt +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.kt @@ -32,6 +32,7 @@ import com.facebook.react.uiapp.component.MyNativeViewManager import com.facebook.react.uimanager.ReactShadowNode import com.facebook.react.uimanager.ViewManager import com.facebook.soloader.SoLoader +import com.reactnative.osslibraryexample.OSSLibraryExamplePackage class RNTesterApplication : Application(), ReactApplication { override val reactNativeHost: ReactNativeHost by lazy { @@ -46,6 +47,7 @@ class RNTesterApplication : Application(), ReactApplication { return listOf( MainReactPackage(), PopupMenuPackage(), + OSSLibraryExamplePackage(), object : TurboReactPackage() { override fun getModule( name: String, diff --git a/packages/rn-tester/js/examples/OSSLibraryExample/OSSLibraryExample.js b/packages/rn-tester/js/examples/OSSLibraryExample/OSSLibraryExample.js new file mode 100644 index 00000000000000..633b71648a6bc6 --- /dev/null +++ b/packages/rn-tester/js/examples/OSSLibraryExample/OSSLibraryExample.js @@ -0,0 +1,128 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +'use strict'; + +import type {NativeComponentType} from '@react-native/oss-library-example'; + +import { + SampleNativeComponent, + SampleNativeComponentCommands, +} from '@react-native/oss-library-example'; +import {NativeSampleModule} from '@react-native/oss-library-example'; +import * as React from 'react'; +import {useRef, useState} from 'react'; +import {Button, Text, View} from 'react-native'; +import {StyleSheet} from 'react-native'; + +const colors = [ + '#0000FF', + '#FF0000', + '#00FF00', + '#003300', + '#330000', + '#000033', +]; + +// $FlowFixMe[value-as-type] +const styles: StyleSheet = StyleSheet.create({ + container: { + flex: 1, + }, + column: { + flex: 2, + justifyContent: 'center', + paddingLeft: 5, + paddingRight: 5, + }, +}); + +function SampleNativeComponentContainer(props: {}): React.Node { + const ref = useRef | null>(null); + const [opacity, setOpacity] = useState(1.0); + const [arrayValues, setArrayValues] = useState([1, 2, 3]); + return ( + + { + console.log(event.nativeEvent.values); + console.log(event.nativeEvent.boolValues); + console.log(event.nativeEvent.floats); + console.log(event.nativeEvent.doubles); + console.log(event.nativeEvent.yesNos); + console.log(event.nativeEvent.strings); + console.log(event.nativeEvent.latLons); + console.log(event.nativeEvent.multiArrays); + }} + /> +