Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
move reactjs re-export stubs to their own files
  • Loading branch information
Archmonger committed Dec 11, 2025
commit bb8fe0f7ebf2b9c4db5d31d9177bdb8b97372985
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# --- Build Artifacts ---
src/reactpy/static/index.js*
src/reactpy/static/*.js*
src/reactpy/static/morphdom/
src/reactpy/static/pyscript/

Expand Down
23 changes: 12 additions & 11 deletions src/build_scripts/clean_js_dir.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,30 @@

# Get the path to the JS source directory
js_src_dir = pathlib.Path(__file__).parent.parent / "js"

# Get the paths to all `dist` folders in the JS source directory
dist_dirs = glob.glob(str(js_src_dir / "**/dist"), recursive=True)

# Get the paths to all `node_modules` folders in the JS source directory
node_modules_dirs = glob.glob(str(js_src_dir / "**/node_modules"), recursive=True)

# Get the paths to all `tsconfig.tsbuildinfo` files in the JS source directory
tsconfig_tsbuildinfo_files = glob.glob(
str(js_src_dir / "**/tsconfig.tsbuildinfo"), recursive=True
)
static_output_dir = pathlib.Path(__file__).parent.parent / "reactpy" / "static"

# Delete all `dist` folders
dist_dirs = glob.glob(str(js_src_dir / "**/dist"), recursive=True)
for dist_dir in dist_dirs:
with contextlib.suppress(FileNotFoundError):
shutil.rmtree(dist_dir)

# Delete all `node_modules` folders
node_modules_dirs = glob.glob(str(js_src_dir / "**/node_modules"), recursive=True)
for node_modules_dir in node_modules_dirs:
with contextlib.suppress(FileNotFoundError):
shutil.rmtree(node_modules_dir)

# Delete all `tsconfig.tsbuildinfo` files
tsconfig_tsbuildinfo_files = glob.glob(
str(js_src_dir / "**/tsconfig.tsbuildinfo"), recursive=True
)
for tsconfig_tsbuildinfo_file in tsconfig_tsbuildinfo_files:
with contextlib.suppress(FileNotFoundError):
os.remove(tsconfig_tsbuildinfo_file)

# Delete all `index-*.js` files
index_js_files = glob.glob(str(static_output_dir / "index-*.js*"))
for index_js_file in index_js_files:
with contextlib.suppress(FileNotFoundError):
os.remove(index_js_file)
2 changes: 1 addition & 1 deletion src/js/packages/@reactpy/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"license": "MIT",
"name": "@reactpy/app",
"scripts": {
"build": "bun build \"src/index.ts\" --outdir=\"../../../../reactpy/static/\" --minify --sourcemap=\"linked\"",
"build": "bun build \"src/index.ts\" \"src/react.ts\" \"src/react-dom.ts\" \"src/react-jsx-runtime.ts\" --outdir=\"../../../../reactpy/static/\" --minify --sourcemap=\"linked\" --splitting",
"checkTypes": "tsc --noEmit"
}
}
9 changes: 1 addition & 8 deletions src/js/packages/@reactpy/app/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
export {
mountReactPy,
React,
ReactDOM,
jsx,
jsxs,
Fragment,
} from "@reactpy/client";
export { mountReactPy } from "@reactpy/client";
6 changes: 6 additions & 0 deletions src/js/packages/@reactpy/app/src/react-dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import ReactDOM from "preact/compat";

// @ts-ignore
export * from "preact/compat";

export default ReactDOM;
1 change: 1 addition & 0 deletions src/js/packages/@reactpy/app/src/react-jsx-runtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "preact/jsx-runtime";
6 changes: 6 additions & 0 deletions src/js/packages/@reactpy/app/src/react.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from "preact/compat";

// @ts-ignore
export * from "preact/compat";

export default React;
3 changes: 2 additions & 1 deletion src/js/packages/@reactpy/app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"compilerOptions": {
"composite": true,
"outDir": "dist",
"rootDir": "src"
"rootDir": "src",
"esModuleInterop": true
},
"extends": "../../../tsconfig.json",
"include": ["src"],
Expand Down
4 changes: 4 additions & 0 deletions src/reactpy/web/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
reactjs_component_from_string,
reactjs_component_from_url,
)
from reactpy.web.utils import (
reactjs_import_map,
)

__all__ = [
"export",
Expand All @@ -18,4 +21,5 @@
"reactjs_component_from_npm",
"reactjs_component_from_string",
"reactjs_component_from_url",
"reactjs_import_map",
]
3 changes: 3 additions & 0 deletions src/reactpy/web/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ def reactjs_component_from_npm(
) -> VdomConstructor | list[VdomConstructor]:
"""Import a component from an NPM package.

Is is mandatory to load `reactpy.web.reactjs_import_map()` on your page before using this
function. It is recommended to put this within your HTML <head> content.

Parameters:
package:
The name of the NPM package.
Expand Down
18 changes: 18 additions & 0 deletions src/reactpy/web/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,24 @@ def resolve_module_exports_from_source(
return names, references


def reactjs_import_map():
from reactpy import config, html

base_url = config.REACTPY_PATH_PREFIX.current.strip("/")
return html.script(
{"type": "importmap"},
f"""
{{
"imports": {{
"react": "/{base_url}/static/react.js",
"react-dom": "/{base_url}/static/react-dom.js",
"react/jsx-runtime": "/{base_url}/static/react-jsx-runtime.js"
}}
}}
""",
)


def _resolve_relative_url(base_url: str, rel_url: str) -> str:
if not rel_url.startswith("."):
if rel_url.startswith("/"):
Expand Down
30 changes: 30 additions & 0 deletions tests/test_web/test_npm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import pytest

import reactpy
from reactpy import html
from reactpy.testing import BackendFixture, DisplayFixture
from reactpy.web import reactjs_component_from_npm, reactjs_import_map


@pytest.mark.anyio
async def test_reactjs_component_from_npm_react_bootstrap():
async with BackendFixture(html_head=html.head(reactjs_import_map())) as backend:
async with DisplayFixture(backend=backend) as display:
Button = reactjs_component_from_npm(
"react-bootstrap", "Button", version="2.10.2"
)

@reactpy.component
def App():
return Button({"variant": "primary", "id": "test-button"}, "Click me")

await display.show(App)

button = await display.page.wait_for_selector("#test-button")
assert await button.inner_text() == "Click me"

# Check if it has the correct class for primary variant
# React Bootstrap buttons usually have 'btn' and 'btn-primary' classes
classes = await button.get_attribute("class")
assert "btn" in classes
assert "btn-primary" in classes
Loading