react-native code-gen > Add a C++ only TurboModule example (for Android/iOS/macOS/Windows) (#35138)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/35138

Changelog:

[General][Added] - Add a C++ only TurboModule example (for Android/iOS/macOS/Windows)

react-native@0.69 introduced a new bridging layer to ease integration for pure C++ TurboModules using C++ std:: types directly instead of the lower level jsi:: types:
https://github.com/facebook/react-native/tree/v0.69.0/ReactCommon/react/bridging

This bridging layer can be used in JSI functions or more conveniently in C++ TurboModules.

Here is a example of an C++ only TurboModule which will work on Android and iOS and macOS/Windows (using microsoft/react-native-macos|windows) only using flow/TypeScript and standard C++ types.

C++ only TurboModules are very handy as they do not require to work with JSI APIs - instead std:: or custom C++ can by used.

Reviewed By: javache

Differential Revision: D39011736

fbshipit-source-id: 84c833d8540671fde8505f1aeb0265074b248730
This commit is contained in:
Christoph Purrer
2022-11-09 10:48:49 -08:00
committed by Facebook GitHub Bot
parent bbb3a6146c
commit d07575b1c6
17 changed files with 745 additions and 1 deletions
+27
View File
@@ -1,3 +1,4 @@
load("@fbsource//tools/build_defs:glob_defs.bzl", "subdir_glob")
load("@fbsource//xplat/hermes/defs:hermes.bzl", "HERMES_BYTECODE_VERSION")
load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native")
load("//tools/build_defs:fb_xplat_platform_specific_rule.bzl", "fb_xplat_platform_specific_rule")
@@ -10,6 +11,7 @@ load("//tools/build_defs/apple:flag_defs.bzl", "get_objc_arc_preprocessor_flags"
load("//tools/build_defs/oss:metro_defs.bzl", "rn_library")
load(
"//tools/build_defs/oss:rn_defs.bzl",
"ANDROID",
"APPLE",
"YOGA_APPLE_TARGET",
"js_library_glob",
@@ -49,6 +51,7 @@ rn_library(
srcs = js_library_glob(
[
"js",
"NativeCxxModuleExample",
"NativeModuleExample",
"NativeComponentExample",
"RCTTest",
@@ -61,10 +64,13 @@ rn_library(
],
),
codegen_components = True,
codegen_modules = True,
labels = [
"pfh:ReactNative_CommonInfrastructurePlaceholder",
],
native_component_spec_name = "AppSpecs",
native_module_android_package_name = "com.facebook.fbreact.specs",
native_module_spec_name = "AppSpecs",
skip_processors = True,
visibility = ["PUBLIC"],
deps = [
@@ -319,3 +325,24 @@ rn_xplat_cxx_library2(
"//xplat/js/react-native-github:RCTFabricComponentViewsBase",
],
)
rn_xplat_cxx_library2(
name = "NativeCxxModuleExample",
srcs = glob(["NativeCxxModuleExample/*.cpp"]),
header_namespace = "",
exported_headers = subdir_glob(
[
("NativeCxxModuleExample", "*.h"),
],
prefix = "NativeCxxModuleExample",
),
fbandroid_compiler_flags = [
"-fexceptions",
"-frtti",
],
platforms = (ANDROID, APPLE),
visibility = ["PUBLIC"],
deps = [
":AppSpecsJSI",
],
)
@@ -0,0 +1,29 @@
# 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)
add_compile_options(
-fexceptions
-frtti
-std=c++17
-Wall
-Wpedantic
-Wno-gnu-zero-variadic-macro-arguments
-DFOLLY_NO_CONFIG=1
-DLOG_TAG=\"ReactNative\")
file(GLOB nativecxxmoduleexample_SRC CONFIGURE_DEPENDS *.cpp)
add_library(nativecxxmoduleexample STATIC ${nativecxxmoduleexample_SRC})
target_include_directories(nativecxxmoduleexample PUBLIC .)
target_include_directories(react_codegen_AppSpecs PUBLIC .)
target_link_libraries(nativecxxmoduleexample
fbjni
jsi
react_nativemodule_core
react_codegen_AppSpecs)
@@ -0,0 +1,110 @@
/*
* 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.
*/
#include "NativeCxxModuleExample.h"
namespace facebook::react {
NativeCxxModuleExample::NativeCxxModuleExample(
std::shared_ptr<CallInvoker> jsInvoker)
: NativeCxxModuleExampleCxxSpec(std::move(jsInvoker)) {}
void NativeCxxModuleExample::getValueWithCallback(
jsi::Runtime &rt,
AsyncCallback<std::string> callback) {
callback({"value from callback!"});
}
std::vector<std::optional<ObjectStruct>> NativeCxxModuleExample::getArray(
jsi::Runtime &rt,
std::vector<std::optional<ObjectStruct>> arg) {
return arg;
}
bool NativeCxxModuleExample::getBool(jsi::Runtime &rt, bool arg) {
return arg;
}
ConstantsStruct NativeCxxModuleExample::getConstants(jsi::Runtime &rt) {
return ConstantsStruct{true, 69, "react-native"};
}
int32_t NativeCxxModuleExample::getEnum(jsi::Runtime &rt, int32_t arg) {
return arg;
}
std::map<std::string, std::optional<int32_t>> NativeCxxModuleExample::getMap(
jsi::Runtime &rt,
std::map<std::string, std::optional<int32_t>> arg) {
return arg;
}
double NativeCxxModuleExample::getNumber(jsi::Runtime &rt, double arg) {
return arg;
}
ObjectStruct NativeCxxModuleExample::getObject(
jsi::Runtime &rt,
ObjectStruct arg) {
return arg;
}
std::set<float> NativeCxxModuleExample::getSet(
jsi::Runtime &rt,
std::set<float> arg) {
return arg;
}
std::string NativeCxxModuleExample::getString(
jsi::Runtime &rt,
std::string arg) {
return arg;
}
std::string NativeCxxModuleExample::getUnion(
jsi::Runtime &rt,
float x,
std::string y,
jsi::Object z) {
std::string result = "x: " + std::to_string(x) + ", y: " + y + ", z: { ";
if (z.hasProperty(rt, "value")) {
result += "value: ";
result += std::to_string(z.getProperty(rt, "value").getNumber());
} else if (z.hasProperty(rt, "low")) {
result += "low: ";
result += z.getProperty(rt, "low").getString(rt).utf8(rt);
}
result += " }";
return result;
}
ValueStruct NativeCxxModuleExample::getValue(
jsi::Runtime &rt,
double x,
std::string y,
ObjectStruct z) {
ValueStruct result{x, y, z};
return result;
}
AsyncPromise<std::string> NativeCxxModuleExample::getValueWithPromise(
jsi::Runtime &rt,
bool error) {
auto promise = AsyncPromise<std::string>(rt, jsInvoker_);
if (error) {
promise.reject("intentional promise rejection");
} else {
promise.resolve("result!");
}
return promise;
}
void NativeCxxModuleExample::voidFunc(jsi::Runtime &rt) {
// Nothing to do
}
} // namespace facebook::react
@@ -0,0 +1,68 @@
/*
* 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.
*/
#pragma once
#if __has_include(<React-Codegen/AppSpecsJSI.h>) // CocoaPod headers on Apple
#include <React-Codegen/AppSpecsJSI.h>
#elif __has_include("AppSpecsJSI.h") // Cmake headers on Android
#include "AppSpecsJSI.h"
#else // BUCK headers
#include <AppSpecs/AppSpecsJSI.h>
#endif
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "NativeCxxModuleExample_ConstantsStruct.h"
#include "NativeCxxModuleExample_ObjectStruct.h"
#include "NativeCxxModuleExample_ValueStruct.h"
namespace facebook::react {
class NativeCxxModuleExample
: public NativeCxxModuleExampleCxxSpec<NativeCxxModuleExample> {
public:
NativeCxxModuleExample(std::shared_ptr<CallInvoker> jsInvoker);
void getValueWithCallback(
jsi::Runtime &rt,
AsyncCallback<std::string> callback);
std::vector<std::optional<ObjectStruct>> getArray(
jsi::Runtime &rt,
std::vector<std::optional<ObjectStruct>> arg);
bool getBool(jsi::Runtime &rt, bool arg);
ConstantsStruct getConstants(jsi::Runtime &rt);
int32_t getEnum(jsi::Runtime &rt, int32_t arg);
std::map<std::string, std::optional<int32_t>> getMap(
jsi::Runtime &rt,
std::map<std::string, std::optional<int32_t>> arg);
double getNumber(jsi::Runtime &rt, double arg);
ObjectStruct getObject(jsi::Runtime &rt, ObjectStruct arg);
std::set<float> getSet(jsi::Runtime &rt, std::set<float> arg);
std::string getString(jsi::Runtime &rt, std::string arg);
std::string getUnion(jsi::Runtime &rt, float x, std::string y, jsi::Object z);
ValueStruct
getValue(jsi::Runtime &rt, double x, std::string y, ObjectStruct z);
AsyncPromise<std::string> getValueWithPromise(jsi::Runtime &rt, bool error);
void voidFunc(jsi::Runtime &rt);
};
} // namespace facebook::react
@@ -0,0 +1,64 @@
/**
* 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';
/** FIXME: Enable flow-enum support
export enum EnumInt {
A = 23,
B = 42,
}
*/
export type UnionFloat = 1.44 | 2.88 | 5.76;
export type UnionString = 'One' | 'Two' | 'Three';
export type UnionObject = {value: number} | {low: string};
export type ConstantsStruct = {|
const1: boolean,
const2: number,
const3: string,
|};
export type ObjectStruct = {|
a: number,
b: string,
c?: ?string,
|};
export type ValueStruct = {|
x: number,
y: string,
z: ObjectStruct,
|};
export interface Spec extends TurboModule {
+getArray: (arg: Array<ObjectStruct | null>) => Array<ObjectStruct | null>;
+getBool: (arg: boolean) => boolean;
+getConstants: () => ConstantsStruct;
// FIXME: Enable flow-enum support
+getEnum: (arg: number /*EnumInt*/) => number /*EnumInt*/;
+getMap: (arg: {[key: string]: ?number}) => {[key: string]: ?number};
+getNumber: (arg: number) => number;
+getObject: (arg: ObjectStruct) => ObjectStruct;
+getSet: (arg: Array<number>) => Array<number>;
+getString: (arg: string) => string;
+getUnion: (x: UnionFloat, y: UnionString, z: UnionObject) => string;
+getValue: (x: number, y: string, z: ObjectStruct) => ValueStruct;
+getValueWithCallback: (callback: (value: string) => void) => void;
+getValueWithPromise: (error: boolean) => Promise<string>;
+voidFunc: () => void;
}
export default (TurboModuleRegistry.get<Spec>(
'NativeCxxModuleExampleCxx',
): ?Spec);
@@ -0,0 +1,31 @@
# 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 = "NativeCxxModuleExample"
s.version = package["version"]
s.summary = package["description"]
s.description = "NativeCxxModuleExample"
s.homepage = "https://github.com/facebook/react-native.git"
s.license = "MIT"
s.platforms = { :ios => "12.4" }
s.compiler_flags = '-Wno-nullability-completeness'
s.author = "Meta Platforms, Inc. and its affiliates"
s.source = { :git => "https://github.com/facebook/react-native.git", :tag => "#{s.version}" }
s.source_files = "**/*.{h,cpp}"
s.requires_arc = true
s.pod_target_xcconfig = {
"USE_HEADERMAP" => "YES",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
}
install_modules_dependencies(s)
s.dependency "ReactCommon/turbomodule/core"
end
@@ -0,0 +1,37 @@
/*
* 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.
*/
#pragma once
#include <react/bridging/Bridging.h>
#include <optional>
#include <string>
namespace facebook::react {
struct ConstantsStruct {
bool const1;
int32_t const2;
std::string const3;
bool operator==(const ConstantsStruct &other) const {
return const1 == other.const1 && const2 == other.const2 &&
const3 == other.const3;
}
};
template <>
struct Bridging<ConstantsStruct> {
static jsi::Object toJs(jsi::Runtime &rt, const ConstantsStruct &value) {
auto result = facebook::jsi::Object(rt);
result.setProperty(rt, "const1", bridging::toJs(rt, value.const1));
result.setProperty(rt, "const2", bridging::toJs(rt, value.const2));
result.setProperty(rt, "const3", bridging::toJs(rt, value.const3));
return result;
}
};
} // namespace facebook::react
@@ -0,0 +1,52 @@
/*
* 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.
*/
#pragma once
#include <react/bridging/Bridging.h>
#include <optional>
#include <string>
namespace facebook::react {
struct ObjectStruct {
int32_t a;
std::string b;
std::optional<std::string> c;
bool operator==(const ObjectStruct &other) const {
return a == other.a && b == other.b && c == other.c;
}
};
template <>
struct Bridging<ObjectStruct> {
static ObjectStruct fromJs(
jsi::Runtime &rt,
const jsi::Object &value,
const std::shared_ptr<CallInvoker> &jsInvoker) {
ObjectStruct result{
bridging::fromJs<int32_t>(rt, value.getProperty(rt, "a"), jsInvoker),
bridging::fromJs<std::string>(
rt, value.getProperty(rt, "b"), jsInvoker),
bridging::fromJs<std::optional<std::string>>(
rt, value.getProperty(rt, "c"), jsInvoker)};
return result;
}
static jsi::Object toJs(jsi::Runtime &rt, const ObjectStruct &value) {
auto result = facebook::jsi::Object(rt);
result.setProperty(rt, "a", bridging::toJs(rt, value.a));
result.setProperty(rt, "b", bridging::toJs(rt, value.b));
if (value.c) {
result.setProperty(rt, "c", bridging::toJs(rt, value.c.value()));
}
return result;
}
};
} // namespace facebook::react
@@ -0,0 +1,50 @@
/*
* 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.
*/
#pragma once
#include <react/bridging/Bridging.h>
#include <optional>
#include <string>
#include "NativeCxxModuleExample_ObjectStruct.h"
namespace facebook::react {
struct ValueStruct {
double x;
std::string y;
ObjectStruct z;
bool operator==(const ValueStruct &other) const {
return x == other.x && y == other.y && z == other.z;
}
};
template <>
struct Bridging<ValueStruct> {
static ValueStruct fromJs(
jsi::Runtime &rt,
const jsi::Object &value,
const std::shared_ptr<CallInvoker> &jsInvoker) {
ValueStruct result{
bridging::fromJs<double>(rt, value.getProperty(rt, "x"), jsInvoker),
bridging::fromJs<std::string>(
rt, value.getProperty(rt, "y"), jsInvoker),
bridging::fromJs<ObjectStruct>(
rt, value.getProperty(rt, "z"), jsInvoker)};
return result;
}
static jsi::Object toJs(jsi::Runtime &rt, const ValueStruct &value) {
auto result = facebook::jsi::Object(rt);
result.setProperty(rt, "x", bridging::toJs(rt, value.x));
result.setProperty(rt, "y", bridging::toJs(rt, value.y));
result.setProperty(rt, "z", bridging::toJs(rt, value.z));
return result;
}
};
} // namespace facebook::react
+3
View File
@@ -48,6 +48,9 @@ def pods(target_name, options = {}, use_flipper: !IN_CI && !USE_FRAMEWORKS)
# RNTester native modules and components
pod 'ScreenshotManager', :path => "NativeModuleExample"
if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
pod 'NativeCxxModuleExample', :path => "NativeCxxModuleExample"
end
end
target 'RNTester' do
@@ -7,6 +7,9 @@
#import "RNTesterTurboModuleProvider.h"
#ifdef RCT_NEW_ARCH_ENABLED
#import <NativeCxxModuleExample/NativeCxxModuleExample.h>
#endif
#import <React/CoreModulesPlugins.h>
#import <ReactCommon/RCTSampleTurboModule.h>
#import <ReactCommon/SampleTurboCxxModule.h>
@@ -28,7 +31,11 @@ std::shared_ptr<TurboModule> RNTesterTurboModuleProvider(
if (name == "SampleTurboCxxModule") {
return std::make_shared<SampleTurboCxxModule>(jsInvoker);
}
#ifdef RCT_NEW_ARCH_ENABLED
if (name == "NativeCxxModuleExampleCxx") {
return std::make_shared<NativeCxxModuleExample>(jsInvoker);
}
#endif
return nullptr;
}
@@ -11,7 +11,11 @@ project(appmodules)
include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)
add_subdirectory(${REACT_COMMON_DIR}/react/nativemodule/samples/platform/android/ sampleturbomodule_build)
add_subdirectory(${REACT_COMMON_DIR}/../packages/rn-tester/NativeCxxModuleExample/ nativecxxmoduleexample_build)
# RN Tester needs to link against the sample turbomobule
target_link_libraries(${CMAKE_PROJECT_NAME}
sampleturbomodule)
# RN Tester needs to link against the NativeCxxModuleExample
target_link_libraries(${CMAKE_PROJECT_NAME}
nativecxxmoduleexample)
@@ -8,6 +8,7 @@
#include <AppSpecs.h>
#include <DefaultComponentsRegistry.h>
#include <DefaultTurboModuleManagerDelegate.h>
#include <NativeCxxModuleExample.h>
#include <ReactCommon/SampleTurboModuleSpec.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
@@ -26,6 +27,9 @@ void registerComponents(
std::shared_ptr<TurboModule> cxxModuleProvider(
const std::string &name,
const std::shared_ptr<CallInvoker> &jsInvoker) {
if (name == "NativeCxxModuleExampleCxx") {
return std::make_shared<NativeCxxModuleExample>(jsInvoker);
}
return nullptr;
}
@@ -0,0 +1,222 @@
/**
* 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 strict-local
*/
import type {RootTag} from 'react-native/Libraries/ReactNative/RootTag';
import {
StyleSheet,
Text,
View,
FlatList,
Platform,
TouchableOpacity,
RootTagContext,
} from 'react-native';
import * as React from 'react';
import NativeCxxModuleExample /*EnumInt,*/ from '../../../NativeCxxModuleExample/NativeCxxModuleExample';
type State = {|
testResults: {
[string]: {
type: string,
value: mixed,
...
},
...
},
|};
type Examples =
| 'callback'
| 'getArray'
| 'getBool'
| 'getConstants'
| 'getEnum'
| 'getMap'
| 'getNumber'
| 'getObject'
| 'getSet'
| 'getString'
| 'getUnion'
| 'getValue'
| 'promise'
| 'rejectPromise'
| 'voidFunc';
class NativeCxxModuleExampleExample extends React.Component<{||}, State> {
static contextType: React$Context<RootTag> = RootTagContext;
state: State = {
testResults: {},
};
// Add calls to methods in TurboModule here
// $FlowFixMe[missing-local-annot]
_tests = {
callback: () =>
NativeCxxModuleExample?.getValueWithCallback(callbackValue =>
this._setResult('callback', callbackValue),
),
getArray: () =>
NativeCxxModuleExample?.getArray([
{a: 1, b: 'foo'},
{a: 2, b: 'bar'},
null,
]),
getBool: () => NativeCxxModuleExample?.getBool(true),
getConstants: () => NativeCxxModuleExample?.getConstants(),
getEnum: () => NativeCxxModuleExample?.getEnum(/*EnumInt.A*/ 2),
getMap: () => NativeCxxModuleExample?.getMap({a: 1, b: null, c: 3}),
getNumber: () => NativeCxxModuleExample?.getNumber(99.95),
getObject: () =>
NativeCxxModuleExample?.getObject({a: 1, b: 'foo', c: null}),
getSet: () => NativeCxxModuleExample?.getSet([1, 1.1, 1.1, 1.1, 2]),
getString: () => NativeCxxModuleExample?.getString('Hello'),
getUnion: () => NativeCxxModuleExample?.getUnion(1.44, 'Two', {low: '12'}),
getValue: () =>
NativeCxxModuleExample?.getValue(5, 'test', {a: 1, b: 'foo'}),
promise: () =>
NativeCxxModuleExample?.getValueWithPromise(false).then(valuePromise =>
this._setResult('promise', valuePromise),
),
rejectPromise: () =>
NativeCxxModuleExample?.getValueWithPromise(true)
.then(() => {})
.catch(e => this._setResult('rejectPromise', e.message)),
voidFunc: () => NativeCxxModuleExample?.voidFunc(),
};
_setResult(
name: string | Examples,
result:
| $FlowFixMe
| void
| Array<$FlowFixMe>
| boolean
| {const1: boolean, const2: number, const3: string}
| number
| {[key: string]: ?number}
| Promise<mixed>
| number
| string,
) {
this.setState(({testResults}) => ({
testResults: {
...testResults,
/* $FlowFixMe[invalid-computed-prop] (>=0.111.0 site=react_native_fb)
* This comment suppresses an error found when Flow v0.111 was
* deployed. To see the error, delete this comment and run Flow. */
[name]: {value: result, type: typeof result},
},
}));
}
_renderResult(name: Examples): React.Node {
const result = this.state.testResults[name] || {};
return (
<View style={styles.result}>
<Text style={[styles.value]}>{JSON.stringify(result.value)}</Text>
<Text style={[styles.type]}>{result.type}</Text>
</View>
);
}
componentDidMount(): void {
if (global.__turboModuleProxy == null) {
throw new Error(
'Cannot load this example because TurboModule is not configured.',
);
}
Object.keys(this._tests).forEach(item =>
this._setResult(item, this._tests[item]()),
);
}
render(): React.Node {
return (
<View style={styles.container}>
<View style={styles.item}>
<TouchableOpacity
style={[styles.column, styles.button]}
onPress={() =>
Object.keys(this._tests).forEach(item =>
this._setResult(item, this._tests[item]()),
)
}>
<Text style={styles.buttonTextLarge}>Run all tests</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => this.setState({testResults: {}})}
style={[styles.column, styles.button]}>
<Text style={styles.buttonTextLarge}>Clear results</Text>
</TouchableOpacity>
</View>
<FlatList
data={Object.keys(this._tests)}
keyExtractor={item => item}
renderItem={({item}) => (
<View style={styles.item}>
<TouchableOpacity
style={[styles.column, styles.button]}
onPress={e => this._setResult(item, this._tests[item]())}>
<Text style={styles.buttonText}>{item}</Text>
</TouchableOpacity>
<View style={[styles.column]}>{this._renderResult(item)}</View>
</View>
)}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
item: {
flexDirection: 'row',
margin: 6,
},
column: {
flex: 2,
justifyContent: 'center',
padding: 3,
},
result: {
alignItems: 'stretch',
justifyContent: 'space-between',
},
value: {
fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
fontSize: 12,
},
type: {
color: '#333',
fontSize: 10,
},
button: {
borderColor: '#444',
padding: 3,
flex: 1,
},
buttonTextLarge: {
textAlign: 'center',
color: 'rgb(0,122,255)',
fontSize: 16,
padding: 6,
},
buttonText: {
color: 'rgb(0,122,255)',
textAlign: 'center',
},
});
module.exports = NativeCxxModuleExampleExample;
@@ -0,0 +1,27 @@
/**
* 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';
const React = require('react');
const NativeCxxModuleExampleExample = require('./NativeCxxModuleExampleExample');
exports.displayName = (undefined: ?string);
exports.title = 'Cxx TurboModule';
exports.category = 'Basic';
exports.description = 'Usage of Cxx TurboModule';
exports.examples = [
{
title: 'TurboCxxModuleExample',
render: function (): React.Element<any> {
return <NativeCxxModuleExampleExample />;
},
},
];
@@ -288,6 +288,11 @@ const APIs: Array<RNTesterModuleInfo> = [
category: 'Basic',
module: require('../examples/TurboModule/TurboModuleExample'),
},
{
key: 'TurboCxxModuleExample',
category: 'Basic',
module: require('../examples/TurboModule/TurboCxxModuleExample'),
},
];
if (ReactNativeFeatureFlags.shouldEmitW3CPointerEvents()) {
@@ -258,6 +258,10 @@ const APIs: Array<RNTesterModuleInfo> = [
key: 'TurboModuleExample',
module: require('../examples/TurboModule/TurboModuleExample'),
},
{
key: 'TurboCxxModuleExample',
module: require('../examples/TurboModule/TurboCxxModuleExample'),
},
{
key: 'VibrationExample',
module: require('../examples/Vibration/VibrationExample'),