├── e2e ├── temp │ └── .keep ├── index.spec.tsx-snapshots │ ├── smoke-webview-issue144-jsx-2-chromium.txt │ ├── smoke-webview-with-wasm-jsx-2-chromium.txt │ ├── smoke-webview-issue45-jsx-2-chromium.txt │ ├── smoke-webview-with-css-jsx-2-chromium.txt │ ├── smoke-webview-app-export-named-jsx-2-chromium.txt │ ├── smoke-webview-app-export-non-jsx-2-chromium.txt │ ├── smoke-webview-app-export-commonjs-jsx-2-chromium.txt │ ├── smoke-webview-app-export-default-jsx-2-chromium.txt │ ├── smoke-webview-app-export-default-tsx-2-chromium.txt │ ├── smoke-webview-app-export-default-preact-jsx-2-chromium.txt │ ├── smoke-webview-app-export-default-react-jsx-2-chromium.txt │ ├── smoke-webview-app-export-default-web-jsx-2-chromium.txt │ ├── smoke-webview-issue144-jsx-3-chromium.txt │ ├── smoke-webview-issue45-jsx-3-chromium.txt │ ├── smoke-webview-with-md-jsx-3-chromium.txt │ ├── smoke-webview-with-txt-jsx-3-chromium.txt │ ├── smoke-webview-with-html-jsx-3-chromium.txt │ ├── smoke-webview-with-json-jsx-3-chromium.txt │ ├── smoke-webview-with-wasm-jsx-3-chromium.txt │ ├── smoke-webview-app-export-default-jsx-3-chromium.txt │ ├── smoke-webview-app-export-default-tsx-3-chromium.txt │ ├── smoke-webview-app-export-named-jsx-3-chromium.txt │ ├── smoke-webview-app-export-non-jsx-3-chromium.txt │ ├── smoke-webview-with-image-bmp-jsx-3-chromium.txt │ ├── smoke-webview-with-image-gif-jsx-3-chromium.txt │ ├── smoke-webview-with-image-jpeg-jsx-3-chromium.txt │ ├── smoke-webview-with-image-jpg-jsx-3-chromium.txt │ ├── smoke-webview-with-image-png-jsx-3-chromium.txt │ ├── smoke-webview-with-image-svg-jsx-3-chromium.txt │ ├── smoke-webview-with-image-webp-jsx-3-chromium.txt │ ├── smoke-webview-app-export-commonjs-jsx-3-chromium.txt │ ├── smoke-webview-app-export-default-preact-jsx-3-chromium.txt │ ├── smoke-webview-app-export-default-react-jsx-3-chromium.txt │ ├── smoke-webview-app-export-default-web-jsx-3-chromium.txt │ ├── smoke-webview-with-txt-jsx-2-chromium.txt │ ├── smoke-webview-with-json-jsx-2-chromium.txt │ ├── smoke-webview-with-image-svg-jsx-2-chromium.txt │ ├── smoke-webview-with-html-jsx-2-chromium.txt │ ├── smoke-webview-with-md-jsx-2-chromium.txt │ ├── smoke-webview-with-image-gif-jsx-2-chromium.txt │ ├── smoke-webview-with-image-webp-jsx-2-chromium.txt │ ├── smoke-webview-with-image-png-jsx-2-chromium.txt │ ├── smoke-webview-with-image-jpeg-jsx-2-chromium.txt │ ├── smoke-webview-with-image-jpg-jsx-2-chromium.txt │ └── smoke-webview-app-export-default-preact-jsx-1-chromium.txt └── index.spec.tsx ├── .npmrc ├── src ├── web │ ├── index.ts │ ├── core.ts │ ├── preact.ts │ ├── react.ts │ └── react.spec.tsx ├── constants.ts ├── types.ts ├── index.ts ├── plugin │ ├── html.ts │ ├── index.ts │ ├── babel.ts │ ├── babel.spec.ts │ └── bundler.ts └── native │ └── index.ts ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── check.yml ├── fixtures ├── assets │ ├── add.wasm │ ├── twitter.bmp │ ├── twitter.gif │ ├── twitter.jpg │ ├── twitter.png │ ├── twitter.jpeg │ ├── twitter.webp │ ├── example.txt │ ├── twitter.svg │ ├── example.json │ ├── example.md │ └── example.html ├── components │ ├── Component-preact.jsx │ ├── Component.jsx │ └── Component-native.jsx ├── app-export-default-web.jsx ├── app-export-default-preact.jsx ├── app-export-non.jsx ├── with-md.jsx ├── app-export-default.jsx ├── app-export-default.tsx ├── with-txt.jsx ├── app-export-commonjs.jsx ├── app-export-named.jsx ├── app-export-default-react.jsx ├── with-json.jsx ├── with-css.jsx ├── with-html.jsx ├── with-image-bmp.jsx ├── with-image-gif.jsx ├── with-image-jpg.jsx ├── with-image-png.jsx ├── with-image-svg.jsx ├── with-image-jpeg.jsx ├── with-image-webp.jsx ├── issue45.jsx ├── with-wasm.jsx └── issue144.jsx ├── examples ├── DempApp │ ├── hooks │ │ ├── useColorScheme.ts │ │ ├── useColorScheme.web.ts │ │ └── useThemeColor.ts │ ├── WebApp │ │ ├── Octocat.png │ │ ├── button.jsx │ │ ├── example.css │ │ └── index.jsx │ ├── assets │ │ ├── images │ │ │ ├── icon.png │ │ │ ├── favicon.png │ │ │ ├── splash.png │ │ │ ├── react-logo.png │ │ │ ├── adaptive-icon.png │ │ │ ├── react-logo@2x.png │ │ │ ├── react-logo@3x.png │ │ │ └── partial-react-logo.png │ │ └── fonts │ │ │ └── SpaceMono-Regular.ttf │ ├── babel.config.js │ ├── tsconfig.json │ ├── metro.config.js │ ├── components │ │ ├── __tests__ │ │ │ ├── ThemedText-test.tsx │ │ │ └── __snapshots__ │ │ │ │ └── ThemedText-test.tsx.snap │ │ ├── navigation │ │ │ └── TabBarIcon.tsx │ │ ├── ThemedView.tsx │ │ ├── ExternalLink.tsx │ │ ├── HelloWave.tsx │ │ ├── Collapsible.tsx │ │ ├── ThemedText.tsx │ │ └── ParallaxScrollView.tsx │ ├── .gitignore │ ├── constants │ │ └── Colors.ts │ ├── app.json │ ├── app │ │ ├── +not-found.tsx │ │ ├── (tabs) │ │ │ ├── _layout.tsx │ │ │ ├── index.tsx │ │ │ └── explore.tsx │ │ ├── _layout.tsx │ │ └── +html.tsx │ ├── package.json │ ├── README.md │ └── scripts │ │ └── reset-project.js ├── ios.gif └── android.gif ├── .gitignore ├── docs ├── API.md ├── plugin │ ├── API.md │ └── functions │ │ ├── transform.md │ │ └── createTransformer.md ├── index │ ├── API.md │ ├── interfaces │ │ ├── WebViewMessage.md │ │ └── ReactNativeMessage.md │ └── functions │ │ └── useWebViewMessage.md └── web │ ├── react │ ├── API.md │ └── functions │ │ ├── webViewCreateRoot.md │ │ ├── emit.md │ │ ├── useNativeMessage.md │ │ └── webViewRender.md │ └── preact │ ├── API.md │ └── functions │ ├── useNativeMessage.md │ └── webViewRender.md ├── vitest.config.ts ├── typedoc.json ├── tsconfig.json ├── LICENSE ├── rollup.config.mjs ├── playwright.config.ts ├── package.json └── README.md /e2e/temp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | legacy-peer-deps=true 2 | -------------------------------------------------------------------------------- /src/web/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./react"; 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | -------------------------------------------------------------------------------- /fixtures/assets/add.wasm: -------------------------------------------------------------------------------- 1 | asm`add 2 |  j -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-issue144-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
dummy
-------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-wasm-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
sum: 3
-------------------------------------------------------------------------------- /examples/DempApp/hooks/useColorScheme.ts: -------------------------------------------------------------------------------- 1 | export { useColorScheme } from 'react-native'; 2 | -------------------------------------------------------------------------------- /examples/ios.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/ios.gif -------------------------------------------------------------------------------- /examples/android.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/android.gif -------------------------------------------------------------------------------- /fixtures/assets/twitter.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/fixtures/assets/twitter.bmp -------------------------------------------------------------------------------- /fixtures/assets/twitter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/fixtures/assets/twitter.gif -------------------------------------------------------------------------------- /fixtures/assets/twitter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/fixtures/assets/twitter.jpg -------------------------------------------------------------------------------- /fixtures/assets/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/fixtures/assets/twitter.png -------------------------------------------------------------------------------- /fixtures/assets/twitter.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/fixtures/assets/twitter.jpeg -------------------------------------------------------------------------------- /fixtures/assets/twitter.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/fixtures/assets/twitter.webp -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | node_modules 3 | e2e/temp 4 | /test-results/ 5 | /playwright-report/ 6 | /blob-report/ 7 | /playwright/.cache/ 8 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-issue45-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-css-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /examples/DempApp/WebApp/Octocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/WebApp/Octocat.png -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-named-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-non-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /examples/DempApp/assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/images/icon.png -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-commonjs-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-tsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /examples/DempApp/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/images/favicon.png -------------------------------------------------------------------------------- /examples/DempApp/assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/images/splash.png -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-preact-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-react-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | /** @internal */ 2 | export const TO_WEB_EVENT_KEY = "rn-web-bridge"; 3 | /** @internal */ 4 | export const WEB_ROOT_ID = "rnrb-root"; 5 | -------------------------------------------------------------------------------- /examples/DempApp/assets/images/react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/images/react-logo.png -------------------------------------------------------------------------------- /examples/DempApp/assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /examples/DempApp/assets/images/react-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/images/react-logo@2x.png -------------------------------------------------------------------------------- /examples/DempApp/assets/images/react-logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/images/react-logo@3x.png -------------------------------------------------------------------------------- /examples/DempApp/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-web-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
hoge
-------------------------------------------------------------------------------- /examples/DempApp/assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /examples/DempApp/assets/images/partial-react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inokawa/react-native-react-bridge/HEAD/examples/DempApp/assets/images/partial-react-logo.png -------------------------------------------------------------------------------- /examples/DempApp/WebApp/button.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const Button = ({children, onClick}) => { 4 | return ; 5 | }; 6 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export interface WebViewMessage { 2 | type: string; 3 | data: T; 4 | } 5 | 6 | export interface ReactNativeMessage { 7 | type: string; 8 | data: T; 9 | } 10 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Modules for React Native 3 | * 4 | * @module 5 | */ 6 | export type { ReactNativeMessage, WebViewMessage } from "./types"; 7 | export { useWebViewMessage } from "./native"; 8 | -------------------------------------------------------------------------------- /fixtures/components/Component-preact.jsx: -------------------------------------------------------------------------------- 1 | export default () => { 2 | return ( 3 |
4 | hoge 5 |
6 | ); 7 | }; 8 | -------------------------------------------------------------------------------- /fixtures/components/Component.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default () => { 4 | return ( 5 |
hoge
6 | ); 7 | }; 8 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-issue144-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-issue45-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-md-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-txt-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/API.md: -------------------------------------------------------------------------------- 1 | **API** 2 | 3 | *** 4 | 5 | # API 6 | 7 | ## Modules 8 | 9 | - [index](index/API.md) 10 | - [plugin](plugin/API.md) 11 | - [web/react](web/react/API.md) 12 | - [web/preact](web/preact/API.md) 13 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-html-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-json-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-wasm-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | 3 | export default defineConfig({ 4 | test: { 5 | root: "src", 6 | environment: "node", 7 | clearMocks: true, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-tsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-named-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-non-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-image-bmp-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-image-gif-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-image-jpeg-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-image-jpg-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-image-png-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-image-svg-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-image-webp-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-commonjs-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-preact-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-react-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/plugin/API.md: -------------------------------------------------------------------------------- 1 | [**API**](../API.md) 2 | 3 | *** 4 | 5 | # plugin 6 | 7 | Custom babelTransformer for metro bundler 8 | 9 | ## Functions 10 | 11 | - [createTransformer](functions/createTransformer.md) 12 | - [transform](functions/transform.md) 13 | -------------------------------------------------------------------------------- /fixtures/app-export-default-web.jsx: -------------------------------------------------------------------------------- 1 | import { webViewRender } from "react-native-react-bridge/lib/web"; 2 | import Comp from "./components/Component-native"; 3 | 4 | const App = () => { 5 | return ; 6 | }; 7 | 8 | export default webViewRender(); 9 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-app-export-default-web-jsx-3-chromium.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /fixtures/app-export-default-preact.jsx: -------------------------------------------------------------------------------- 1 | import { webViewRender } from "react-native-react-bridge/lib/web/preact"; 2 | import Comp from "./components/Component-preact"; 3 | 4 | const App = () => { 5 | return ; 6 | }; 7 | 8 | export default webViewRender(); 9 | -------------------------------------------------------------------------------- /fixtures/app-export-non.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import Comp from "./components/Component"; 4 | 5 | const App = () => { 6 | return ; 7 | }; 8 | 9 | webViewRender(); 10 | -------------------------------------------------------------------------------- /fixtures/with-md.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import data from "./assets/example.md"; 4 | 5 | const App = () => { 6 | return
{data}
; 7 | }; 8 | 9 | export default webViewRender(); 10 | -------------------------------------------------------------------------------- /fixtures/app-export-default.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import Comp from "./components/Component"; 4 | 5 | const App = () => { 6 | return ; 7 | }; 8 | 9 | export default webViewRender(); 10 | -------------------------------------------------------------------------------- /fixtures/app-export-default.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import Comp from "./components/Component"; 4 | 5 | const App = () => { 6 | return ; 7 | }; 8 | 9 | export default webViewRender(); 10 | -------------------------------------------------------------------------------- /fixtures/components/Component-native.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View } from "react-native"; 3 | 4 | export default () => { 5 | return ( 6 | 7 | hoge 8 | 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /fixtures/with-txt.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import data from "./assets/example.txt"; 4 | 5 | const App = () => { 6 | return
{data}
; 7 | }; 8 | 9 | export default webViewRender(); 10 | -------------------------------------------------------------------------------- /fixtures/app-export-commonjs.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import Comp from "./components/Component"; 4 | 5 | const App = () => { 6 | return ; 7 | }; 8 | 9 | module.exports = webViewRender(); 10 | -------------------------------------------------------------------------------- /fixtures/app-export-named.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import Comp from "./components/Component"; 4 | 5 | const App = () => { 6 | return ; 7 | }; 8 | 9 | export const foo = webViewRender(); 10 | -------------------------------------------------------------------------------- /fixtures/app-export-default-react.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewCreateRoot } from "react-native-react-bridge/lib/web"; 3 | import Comp from "./components/Component"; 4 | 5 | const App = () => { 6 | return ; 7 | }; 8 | 9 | export default webViewCreateRoot(); 10 | -------------------------------------------------------------------------------- /fixtures/with-json.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import data from "./assets/example.json"; 4 | 5 | const App = () => { 6 | return
{JSON.stringify(data)}
; 7 | }; 8 | 9 | export default webViewRender(); 10 | -------------------------------------------------------------------------------- /fixtures/with-css.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewCreateRoot } from "react-native-react-bridge/lib/web"; 3 | import Comp from "./components/Component"; 4 | import "./assets/example.css"; 5 | 6 | const App = () => { 7 | return ; 8 | }; 9 | 10 | export default webViewCreateRoot(); 11 | -------------------------------------------------------------------------------- /fixtures/with-html.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import html from "./assets/example.html"; 4 | 5 | const App = () => { 6 | return
; 7 | }; 8 | 9 | export default webViewRender(); 10 | -------------------------------------------------------------------------------- /docs/index/API.md: -------------------------------------------------------------------------------- 1 | [**API**](../API.md) 2 | 3 | *** 4 | 5 | # index 6 | 7 | Modules for React Native 8 | 9 | ## Functions 10 | 11 | - [useWebViewMessage](functions/useWebViewMessage.md) 12 | 13 | ## Interfaces 14 | 15 | - [ReactNativeMessage](interfaces/ReactNativeMessage.md) 16 | - [WebViewMessage](interfaces/WebViewMessage.md) 17 | -------------------------------------------------------------------------------- /docs/web/react/API.md: -------------------------------------------------------------------------------- 1 | [**API**](../../API.md) 2 | 3 | *** 4 | 5 | # web/react 6 | 7 | Modules for React DOM 8 | 9 | ## Functions 10 | 11 | - [webViewRender](functions/webViewRender.md) 12 | - [webViewCreateRoot](functions/webViewCreateRoot.md) 13 | - [useNativeMessage](functions/useNativeMessage.md) 14 | - [emit](functions/emit.md) 15 | -------------------------------------------------------------------------------- /fixtures/with-image-bmp.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import url from "./assets/twitter.bmp"; 4 | 5 | const App = () => { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | }; 12 | 13 | export default webViewRender(); 14 | -------------------------------------------------------------------------------- /fixtures/with-image-gif.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import url from "./assets/twitter.gif"; 4 | 5 | const App = () => { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | }; 12 | 13 | export default webViewRender(); 14 | -------------------------------------------------------------------------------- /fixtures/with-image-jpg.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import url from "./assets/twitter.jpg"; 4 | 5 | const App = () => { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | }; 12 | 13 | export default webViewRender(); 14 | -------------------------------------------------------------------------------- /fixtures/with-image-png.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import url from "./assets/twitter.png"; 4 | 5 | const App = () => { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | }; 12 | 13 | export default webViewRender(); 14 | -------------------------------------------------------------------------------- /fixtures/with-image-svg.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import url from "./assets/twitter.svg"; 4 | 5 | const App = () => { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | }; 12 | 13 | export default webViewRender(); 14 | -------------------------------------------------------------------------------- /examples/DempApp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true, 5 | "paths": { 6 | "@/*": [ 7 | "./*" 8 | ] 9 | } 10 | }, 11 | "include": [ 12 | "**/*.ts", 13 | "**/*.tsx", 14 | ".expo/types/**/*.ts", 15 | "expo-env.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /fixtures/with-image-jpeg.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import url from "./assets/twitter.jpeg"; 4 | 5 | const App = () => { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | }; 12 | 13 | export default webViewRender(); 14 | -------------------------------------------------------------------------------- /fixtures/with-image-webp.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import url from "./assets/twitter.webp"; 4 | 5 | const App = () => { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | }; 12 | 13 | export default webViewRender(); 14 | -------------------------------------------------------------------------------- /docs/web/preact/API.md: -------------------------------------------------------------------------------- 1 | [**API**](../../API.md) 2 | 3 | *** 4 | 5 | # web/preact 6 | 7 | Modules for Preact 8 | 9 | ## Functions 10 | 11 | - [webViewRender](functions/webViewRender.md) 12 | - [useNativeMessage](functions/useNativeMessage.md) 13 | 14 | ## References 15 | 16 | ### emit 17 | 18 | Re-exports [emit](../react/functions/emit.md) 19 | -------------------------------------------------------------------------------- /examples/DempApp/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig } = require("expo/metro-config"); 2 | 3 | /** @type {import('expo/metro-config').MetroConfig} */ 4 | const config = getDefaultConfig(__dirname); 5 | 6 | config.transformer.babelTransformerPath = require.resolve( 7 | "react-native-react-bridge/lib/plugin" 8 | ); 9 | 10 | module.exports = config; 11 | -------------------------------------------------------------------------------- /fixtures/issue45.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import Comp from "./components/Component"; 4 | 5 | const text = "foo `bar`"; 6 | console.log(text); 7 | console.log(`baz`); 8 | 9 | const App = () => { 10 | return ; 11 | }; 12 | 13 | export default webViewRender(); 14 | -------------------------------------------------------------------------------- /examples/DempApp/components/__tests__/ThemedText-test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | 4 | import { ThemedText } from '../ThemedText'; 5 | 6 | it(`renders correctly`, () => { 7 | const tree = renderer.create(Snapshot test!).toJSON(); 8 | 9 | expect(tree).toMatchSnapshot(); 10 | }); 11 | -------------------------------------------------------------------------------- /examples/DempApp/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | 16 | # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb 17 | # The following patterns were generated by expo-cli 18 | 19 | expo-env.d.ts 20 | # @end expo-cli -------------------------------------------------------------------------------- /fixtures/with-wasm.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { webViewRender } from "react-native-react-bridge/lib/web"; 3 | import * as wasm from "./assets/add.wasm"; 4 | 5 | const App = () => { 6 | let res; 7 | try { 8 | res = wasm.add(1, 2); 9 | } catch (err) { 10 | res = err.toString(); 11 | } 12 | return
sum: {res}
; 13 | }; 14 | 15 | export default webViewRender(); 16 | -------------------------------------------------------------------------------- /docs/plugin/functions/transform.md: -------------------------------------------------------------------------------- 1 | [**API**](../../API.md) 2 | 3 | *** 4 | 5 | # Function: transform() 6 | 7 | > **transform**(`args`): `Promise`\<`any`\> 8 | 9 | Defined in: [src/plugin/index.ts:53](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/plugin/index.ts#L53) 10 | 11 | ## Parameters 12 | 13 | ### args 14 | 15 | `any` 16 | 17 | ## Returns 18 | 19 | `Promise`\<`any`\> 20 | -------------------------------------------------------------------------------- /fixtures/assets/example.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 2 | Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 3 | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 4 | Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 5 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": [ 3 | "./src/index.ts", 4 | "./src/plugin", 5 | "./src/web/react.ts", 6 | "./src/web/preact.ts" 7 | ], 8 | "out": "docs", 9 | "name": "API", 10 | "plugin": ["typedoc-plugin-markdown"], 11 | "readme": "none", 12 | "excludeExternals": true, 13 | "sort": ["kind"], 14 | "groupOrder": ["Function", "Interface", "TypeAlias"], 15 | "githubPages": false, 16 | "entryFileName": "API.md", 17 | "hideBreadcrumbs": true 18 | } 19 | -------------------------------------------------------------------------------- /examples/DempApp/WebApp/example.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 1rem; 3 | } 4 | 5 | textarea { 6 | padding: 10px; 7 | line-height: 1.5; 8 | border-radius: 5px; 9 | border: 1px solid #ccc; 10 | box-shadow: 1px 1px 1px #999; 11 | } 12 | 13 | button { 14 | border: 0; 15 | line-height: 2.5; 16 | padding: 0 10px; 17 | text-align: center; 18 | color: #777; 19 | border-radius: 5px; 20 | background-color: white; 21 | border: 1px solid #777; 22 | cursor: pointer; 23 | } 24 | -------------------------------------------------------------------------------- /examples/DempApp/components/__tests__/__snapshots__/ThemedText-test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`renders correctly 1`] = ` 4 | 22 | Snapshot test! 23 | 24 | `; 25 | -------------------------------------------------------------------------------- /e2e/index.spec.tsx-snapshots/smoke-webview-with-txt-jsx-2-chromium.txt: -------------------------------------------------------------------------------- 1 |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 2 | Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 3 | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 4 | Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 5 |
-------------------------------------------------------------------------------- /examples/DempApp/hooks/useColorScheme.web.ts: -------------------------------------------------------------------------------- 1 | // NOTE: The default React Native styling doesn't support server rendering. 2 | // Server rendered styles should not change between the first render of the HTML 3 | // and the first render on the client. Typically, web developers will use CSS media queries 4 | // to render different styles on the client and server, these aren't directly supported in React Native 5 | // but can be achieved using a styling library like Nativewind. 6 | export function useColorScheme() { 7 | return 'light'; 8 | } 9 | -------------------------------------------------------------------------------- /docs/web/react/functions/webViewCreateRoot.md: -------------------------------------------------------------------------------- 1 | [**API**](../../../API.md) 2 | 3 | *** 4 | 5 | # Function: webViewCreateRoot() 6 | 7 | > **webViewCreateRoot**(`root`): `string` 8 | 9 | Defined in: [src/web/react.ts:26](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/web/react.ts#L26) 10 | 11 | [webViewRender](webViewRender.md) but initiated with React's createRoot 12 | 13 | ## Parameters 14 | 15 | ### root 16 | 17 | `ReactElement` 18 | 19 | ## Returns 20 | 21 | `string` 22 | -------------------------------------------------------------------------------- /examples/DempApp/components/navigation/TabBarIcon.tsx: -------------------------------------------------------------------------------- 1 | // You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/ 2 | 3 | import Ionicons from '@expo/vector-icons/Ionicons'; 4 | import { type IconProps } from '@expo/vector-icons/build/createIconSet'; 5 | import { type ComponentProps } from 'react'; 6 | 7 | export function TabBarIcon({ style, ...rest }: IconProps['name']>) { 8 | return ; 9 | } 10 | -------------------------------------------------------------------------------- /src/plugin/html.ts: -------------------------------------------------------------------------------- 1 | import { WEB_ROOT_ID } from "../constants"; 2 | 3 | /** 4 | * @internal 5 | */ 6 | export const wrapWithWebViewHTML = (js: string): string => ` 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | `; 19 | -------------------------------------------------------------------------------- /examples/DempApp/components/ThemedView.tsx: -------------------------------------------------------------------------------- 1 | import { View, type ViewProps } from 'react-native'; 2 | 3 | import { useThemeColor } from '@/hooks/useThemeColor'; 4 | 5 | export type ThemedViewProps = ViewProps & { 6 | lightColor?: string; 7 | darkColor?: string; 8 | }; 9 | 10 | export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) { 11 | const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background'); 12 | 13 | return ; 14 | } 15 | -------------------------------------------------------------------------------- /docs/web/react/functions/emit.md: -------------------------------------------------------------------------------- 1 | [**API**](../../../API.md) 2 | 3 | *** 4 | 5 | # Function: emit() 6 | 7 | > **emit**\<`T`\>(`message`): `void` 8 | 9 | Defined in: [src/web/core.ts:13](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/web/core.ts#L13) 10 | 11 | A function to send a message to React Native 12 | 13 | ## Type Parameters 14 | 15 | • **T** 16 | 17 | ## Parameters 18 | 19 | ### message 20 | 21 | [`WebViewMessage`](../../../index/interfaces/WebViewMessage.md)\<`T`\> 22 | 23 | ## Returns 24 | 25 | `void` 26 | -------------------------------------------------------------------------------- /docs/web/react/functions/useNativeMessage.md: -------------------------------------------------------------------------------- 1 | [**API**](../../../API.md) 2 | 3 | *** 4 | 5 | # Function: useNativeMessage() 6 | 7 | > **useNativeMessage**\<`T`\>(`onSubscribe`): `void` 8 | 9 | Defined in: [src/web/react.ts:34](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/web/react.ts#L34) 10 | 11 | A hook to subscribe messages from React Native. 12 | 13 | ## Type Parameters 14 | 15 | • **T** 16 | 17 | ## Parameters 18 | 19 | ### onSubscribe 20 | 21 | (`message`) => `void` 22 | 23 | ## Returns 24 | 25 | `void` 26 | -------------------------------------------------------------------------------- /docs/web/preact/functions/useNativeMessage.md: -------------------------------------------------------------------------------- 1 | [**API**](../../../API.md) 2 | 3 | *** 4 | 5 | # Function: useNativeMessage() 6 | 7 | > **useNativeMessage**\<`T`\>(`onSubscribe`): `void` 8 | 9 | Defined in: [src/web/preact.ts:25](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/web/preact.ts#L25) 10 | 11 | A hook to subscribe messages from React Native. 12 | 13 | ## Type Parameters 14 | 15 | • **T** 16 | 17 | ## Parameters 18 | 19 | ### onSubscribe 20 | 21 | (`message`) => `void` 22 | 23 | ## Returns 24 | 25 | `void` 26 | -------------------------------------------------------------------------------- /docs/web/react/functions/webViewRender.md: -------------------------------------------------------------------------------- 1 | [**API**](../../../API.md) 2 | 3 | *** 4 | 5 | # Function: webViewRender() 6 | 7 | > **webViewRender**(`root`): `string` 8 | 9 | Defined in: [src/web/react.ts:18](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/web/react.ts#L18) 10 | 11 | The entry point of web file 12 | 13 | This statement is detected by babelTransformer as an entry point 14 | All dependencies are resolved, compressed and stringified into one file 15 | 16 | ## Parameters 17 | 18 | ### root 19 | 20 | `ReactElement` 21 | 22 | ## Returns 23 | 24 | `string` 25 | -------------------------------------------------------------------------------- /docs/web/preact/functions/webViewRender.md: -------------------------------------------------------------------------------- 1 | [**API**](../../../API.md) 2 | 3 | *** 4 | 5 | # Function: webViewRender() 6 | 7 | > **webViewRender**(`root`): `string` 8 | 9 | Defined in: [src/web/preact.ts:17](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/web/preact.ts#L17) 10 | 11 | The entry point of web file 12 | 13 | This statement is detected by babelTransformer as an entry point 14 | All dependencies are resolved, compressed and stringified into one file 15 | 16 | ## Parameters 17 | 18 | ### root 19 | 20 | `ComponentChild` 21 | 22 | ## Returns 23 | 24 | `string` 25 | -------------------------------------------------------------------------------- /fixtures/issue144.jsx: -------------------------------------------------------------------------------- 1 | import { webViewRender } from "react-native-react-bridge/lib/web"; 2 | 3 | let Root = () => { 4 | // prettier-ignore 5 | let issue = function inspect(value) { 6 | switch (typeof value) { 7 | case 'string': 8 | if (value.includes("'")) { 9 | if (!value.includes('"')) { 10 | return `"${value}"`; 11 | } else if (!value.includes('`') && !value.includes('${')) { 12 | return `\`${value}\``; 13 | } 14 | } 15 | } 16 | }; 17 | console.log(issue); 18 | 19 | return
dummy
; 20 | }; 21 | 22 | export default webViewRender(); 23 | -------------------------------------------------------------------------------- /examples/DempApp/hooks/useThemeColor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Learn more about light and dark modes: 3 | * https://docs.expo.dev/guides/color-schemes/ 4 | */ 5 | 6 | import { useColorScheme } from 'react-native'; 7 | 8 | import { Colors } from '@/constants/Colors'; 9 | 10 | export function useThemeColor( 11 | props: { light?: string; dark?: string }, 12 | colorName: keyof typeof Colors.light & keyof typeof Colors.dark 13 | ) { 14 | const theme = useColorScheme() ?? 'light'; 15 | const colorFromProps = props[theme]; 16 | 17 | if (colorFromProps) { 18 | return colorFromProps; 19 | } else { 20 | return Colors[theme][colorName]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: check 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | setup: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Setup Node 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: "lts/*" 22 | cache: "npm" 23 | 24 | - run: npm ci 25 | - run: npm run tsc 26 | - run: npm run test 27 | 28 | - run: npx playwright install chromium 29 | - run: npm run e2e 30 | -------------------------------------------------------------------------------- /docs/plugin/functions/createTransformer.md: -------------------------------------------------------------------------------- 1 | [**API**](../../API.md) 2 | 3 | *** 4 | 5 | # Function: createTransformer() 6 | 7 | > **createTransformer**(`esbuildOptions`): (`args`) => `Promise`\<`any`\> 8 | 9 | Defined in: [src/plugin/index.ts:35](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/plugin/index.ts#L35) 10 | 11 | ## Parameters 12 | 13 | ### esbuildOptions 14 | 15 | `Omit`\<`BuildOptions`, `"write"` \| `"entryPoints"` \| `"alias"`\> = `{}` 16 | 17 | ## Returns 18 | 19 | `Function` 20 | 21 | ### Parameters 22 | 23 | #### args 24 | 25 | `any` 26 | 27 | ### Returns 28 | 29 | `Promise`\<`any`\> 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Platform:** 20 | - Version of [react-native, expo]: [x.x.x] 21 | - Version of this package: [x.x.x] 22 | - OS: [iOS, Android] 23 | - Running on: [Device, Simulator] 24 | - JavaScript engine: [Hermes, JavaScriptCore] 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /docs/index/interfaces/WebViewMessage.md: -------------------------------------------------------------------------------- 1 | [**API**](../../API.md) 2 | 3 | *** 4 | 5 | # Interface: WebViewMessage\ 6 | 7 | Defined in: [src/types.ts:1](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/types.ts#L1) 8 | 9 | ## Type Parameters 10 | 11 | • **T** 12 | 13 | ## Properties 14 | 15 | ### type 16 | 17 | > **type**: `string` 18 | 19 | Defined in: [src/types.ts:2](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/types.ts#L2) 20 | 21 | *** 22 | 23 | ### data 24 | 25 | > **data**: `T` 26 | 27 | Defined in: [src/types.ts:3](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/types.ts#L3) 28 | -------------------------------------------------------------------------------- /docs/index/interfaces/ReactNativeMessage.md: -------------------------------------------------------------------------------- 1 | [**API**](../../API.md) 2 | 3 | *** 4 | 5 | # Interface: ReactNativeMessage\ 6 | 7 | Defined in: [src/types.ts:6](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/types.ts#L6) 8 | 9 | ## Type Parameters 10 | 11 | • **T** 12 | 13 | ## Properties 14 | 15 | ### type 16 | 17 | > **type**: `string` 18 | 19 | Defined in: [src/types.ts:7](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/types.ts#L7) 20 | 21 | *** 22 | 23 | ### data 24 | 25 | > **data**: `T` 26 | 27 | Defined in: [src/types.ts:8](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/types.ts#L8) 28 | -------------------------------------------------------------------------------- /examples/DempApp/components/ExternalLink.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'expo-router'; 2 | import { openBrowserAsync } from 'expo-web-browser'; 3 | import { type ComponentProps } from 'react'; 4 | import { Platform } from 'react-native'; 5 | 6 | type Props = Omit, 'href'> & { href: string }; 7 | 8 | export function ExternalLink({ href, ...rest }: Props) { 9 | return ( 10 | { 15 | if (Platform.OS !== 'web') { 16 | // Prevent the default behavior of linking to the default browser on native. 17 | event.preventDefault(); 18 | // Open the link in an in-app browser. 19 | await openBrowserAsync(href); 20 | } 21 | }} 22 | /> 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /examples/DempApp/constants/Colors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Below are the colors that are used in the app. The colors are defined in the light and dark mode. 3 | * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc. 4 | */ 5 | 6 | const tintColorLight = '#0a7ea4'; 7 | const tintColorDark = '#fff'; 8 | 9 | export const Colors = { 10 | light: { 11 | text: '#11181C', 12 | background: '#fff', 13 | tint: tintColorLight, 14 | icon: '#687076', 15 | tabIconDefault: '#687076', 16 | tabIconSelected: tintColorLight, 17 | }, 18 | dark: { 19 | text: '#ECEDEE', 20 | background: '#151718', 21 | tint: tintColorDark, 22 | icon: '#9BA1A6', 23 | tabIconDefault: '#9BA1A6', 24 | tabIconSelected: tintColorDark, 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /src/web/core.ts: -------------------------------------------------------------------------------- 1 | import { TO_WEB_EVENT_KEY, WEB_ROOT_ID } from "../constants"; 2 | import type { ReactNativeMessage, WebViewMessage } from "../types"; 3 | 4 | /** 5 | * @internal 6 | */ 7 | export const getWebViewRootElement = (): HTMLElement => 8 | document.getElementById(WEB_ROOT_ID)!; 9 | 10 | /** 11 | * A function to send a message to React Native 12 | */ 13 | export const emitToNative = (message: WebViewMessage) => { 14 | (window as any).ReactNativeWebView.postMessage(JSON.stringify(message)); 15 | }; 16 | 17 | /** 18 | * @internal 19 | */ 20 | export const listenNativeMessage = ( 21 | onSubscribe: (message: ReactNativeMessage) => void 22 | ) => { 23 | const listener = (e: any) => { 24 | onSubscribe({ type: e.detail.type, data: e.detail.data }); 25 | }; 26 | window.addEventListener(TO_WEB_EVENT_KEY, listener); 27 | return () => { 28 | window.removeEventListener(TO_WEB_EVENT_KEY, listener); 29 | }; 30 | }; 31 | -------------------------------------------------------------------------------- /examples/DempApp/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "DempApp", 4 | "slug": "DempApp", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/images/icon.png", 8 | "scheme": "myapp", 9 | "userInterfaceStyle": "automatic", 10 | "splash": { 11 | "image": "./assets/images/splash.png", 12 | "resizeMode": "contain", 13 | "backgroundColor": "#ffffff" 14 | }, 15 | "ios": { 16 | "supportsTablet": true 17 | }, 18 | "android": { 19 | "adaptiveIcon": { 20 | "foregroundImage": "./assets/images/adaptive-icon.png", 21 | "backgroundColor": "#ffffff" 22 | } 23 | }, 24 | "web": { 25 | "bundler": "metro", 26 | "output": "static", 27 | "favicon": "./assets/images/favicon.png" 28 | }, 29 | "plugins": [ 30 | "expo-router" 31 | ], 32 | "experiments": { 33 | "typedRoutes": true 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/DempApp/app/+not-found.tsx: -------------------------------------------------------------------------------- 1 | import { Link, Stack } from 'expo-router'; 2 | import { StyleSheet } from 'react-native'; 3 | 4 | import { ThemedText } from '@/components/ThemedText'; 5 | import { ThemedView } from '@/components/ThemedView'; 6 | 7 | export default function NotFoundScreen() { 8 | return ( 9 | <> 10 | 11 | 12 | This screen doesn't exist. 13 | 14 | Go to home screen! 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | const styles = StyleSheet.create({ 22 | container: { 23 | flex: 1, 24 | alignItems: 'center', 25 | justifyContent: 'center', 26 | padding: 20, 27 | }, 28 | link: { 29 | marginTop: 15, 30 | paddingVertical: 15, 31 | }, 32 | }); 33 | -------------------------------------------------------------------------------- /src/web/preact.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Modules for Preact 3 | * 4 | * @module 5 | */ 6 | import { useEffect } from "preact/compat"; 7 | import { render, ComponentChild } from "preact"; 8 | import { listenNativeMessage, emitToNative, getWebViewRootElement } from "./core"; 9 | import type { ReactNativeMessage } from "../types"; 10 | 11 | /** 12 | * The entry point of web file 13 | * 14 | * This statement is detected by babelTransformer as an entry point 15 | * All dependencies are resolved, compressed and stringified into one file 16 | */ 17 | export const webViewRender = (root: ComponentChild): string => { 18 | render(root, getWebViewRootElement()); 19 | return ""; // dummy 20 | }; 21 | 22 | /** 23 | * A hook to subscribe messages from React Native. 24 | */ 25 | export const useNativeMessage = ( 26 | onSubscribe: (message: ReactNativeMessage) => void 27 | ) => { 28 | useEffect(() => listenNativeMessage(onSubscribe), [onSubscribe]); 29 | }; 30 | 31 | export { emitToNative as emit }; 32 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "esnext", 5 | "moduleResolution": "bundler", 6 | "jsx": "react-jsx", 7 | "lib": ["dom", "dom.iterable", "esnext"], 8 | "strict": true, 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noUnusedLocals": true, 17 | "noUnusedParameters": true, 18 | "noUncheckedIndexedAccess": true, 19 | "noPropertyAccessFromIndexSignature": true, 20 | "noImplicitReturns": true, 21 | "noImplicitOverride": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "allowUnreachableCode": false, 24 | "allowUnusedLabels": false, 25 | // "exactOptionalPropertyTypes": true, 26 | "stripInternal": true 27 | }, 28 | "include": ["src"], 29 | "exclude": ["node_modules"] 30 | } 31 | -------------------------------------------------------------------------------- /examples/DempApp/components/HelloWave.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import Animated, { 3 | useSharedValue, 4 | useAnimatedStyle, 5 | withTiming, 6 | withRepeat, 7 | withSequence, 8 | } from 'react-native-reanimated'; 9 | 10 | import { ThemedText } from '@/components/ThemedText'; 11 | 12 | export function HelloWave() { 13 | const rotationAnimation = useSharedValue(0); 14 | 15 | rotationAnimation.value = withRepeat( 16 | withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })), 17 | 4 // Run the animation 4 times 18 | ); 19 | 20 | const animatedStyle = useAnimatedStyle(() => ({ 21 | transform: [{ rotate: `${rotationAnimation.value}deg` }], 22 | })); 23 | 24 | return ( 25 | 26 | 👋 27 | 28 | ); 29 | } 30 | 31 | const styles = StyleSheet.create({ 32 | text: { 33 | fontSize: 28, 34 | lineHeight: 32, 35 | marginTop: -6, 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /docs/index/functions/useWebViewMessage.md: -------------------------------------------------------------------------------- 1 | [**API**](../../API.md) 2 | 3 | *** 4 | 5 | # Function: useWebViewMessage() 6 | 7 | > **useWebViewMessage**\<`T`\>(`onSubscribe`): `object` 8 | 9 | Defined in: [src/native/index.ts:28](https://github.com/inokawa/react-native-react-bridge/blob/a54748fc9a4bfd9c93c7e9a7c5213de725bd9170/src/native/index.ts#L28) 10 | 11 | A hook to subscribe messages from WebView. 12 | 13 | ## Type Parameters 14 | 15 | • **T** 16 | 17 | ## Parameters 18 | 19 | ### onSubscribe 20 | 21 | (`message`) => `void` 22 | 23 | ## Returns 24 | 25 | `object` 26 | 27 | ### ref 28 | 29 | > **ref**: `RefObject`\<`WebView`\<\{\}\>\> 30 | 31 | ### onMessage() 32 | 33 | > **onMessage**: (`event`) => `void` 34 | 35 | #### Parameters 36 | 37 | ##### event 38 | 39 | `WebViewMessageEvent` 40 | 41 | #### Returns 42 | 43 | `void` 44 | 45 | ### emit() 46 | 47 | > **emit**: (`message`) => `void` 48 | 49 | #### Parameters 50 | 51 | ##### message 52 | 53 | [`ReactNativeMessage`](../interfaces/ReactNativeMessage.md)\<`T`\> 54 | 55 | #### Returns 56 | 57 | `void` 58 | -------------------------------------------------------------------------------- /examples/DempApp/WebApp/index.jsx: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react'; 2 | import { 3 | webViewRender, 4 | emit, 5 | useNativeMessage, 6 | } from 'react-native-react-bridge/lib/web'; 7 | import './example.css'; 8 | import png from './Octocat.png'; 9 | import {Button} from './button'; 10 | 11 | const style = { 12 | width: '100vw', 13 | height: '100vh', 14 | margin: 'auto', 15 | backgroundColor: 'lightblue', 16 | }; 17 | 18 | const Root = () => { 19 | const [data, setData] = useState('This is Web'); 20 | useNativeMessage(message => { 21 | if (message.type === 'hello') { 22 | setData(message.data); 23 | } 24 | }); 25 | return ( 26 |
27 |
28 | 29 |
30 |