Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
227 commits
Select commit Hold shift + click to select a range
fb92b78
plan one native macos and add one-macos skeleton
natew Oct 21, 2026
b3d70fb
add one-macos host, mounting, toggle and app template (unbuilt)
natew Oct 21, 2026
216cc5b
fix one-macos core build: header paths, drop native modules not neede…
natew Oct 21, 2026
dfeee7d
record macos lane bundle baselines
natew Oct 21, 2026
4d28057
one-macos: boot JSC host, mount view/text/toggle, embed deps framewor…
natew Oct 21, 2026
a703f37
plan: split Platform by importer, record host review
natew Oct 21, 2026
484d81c
add macos as a native js platform
natew Oct 21, 2026
fb4fb5b
add the macos-basic js fixture
natew Oct 21, 2026
fa6e8f3
split macos Platform by importer
natew Oct 21, 2026
87e50ee
macos: fail instead of falling back for missing one-macos, stubs and …
natew Oct 21, 2026
4fb6097
lockfile for one-macos and macos-basic workspaces
natew Oct 21, 2026
a7ad90f
macos: load the built one.macos entry instead of src
natew Oct 21, 2026
1b9ecc2
vxrn: type the macos compiler environment
natew Oct 21, 2026
0100f17
macos: static view config for OneMacToggle
natew Oct 21, 2026
f17ece4
plan: record ios/android/web gate result
natew Oct 21, 2026
5240b0b
macos: load built .macos variants, keep reanimated and the ios toolba…
natew Oct 21, 2026
dc57930
regenerate one types for the macos platform
natew Oct 21, 2026
623043a
plan: hermes, nitro and worklets on mac from M1
natew Oct 21, 2026
5f908d3
macos: build Nitro core, install NitroModules, more boot TurboModules
natew Oct 21, 2026
83c586a
macos: run the main runtime on Hermes, drop JSC
natew Oct 21, 2026
573189b
macos: build worklets core, safe area module, record M1 host result
natew Oct 21, 2026
f8de1ce
macos: fixed size class and no hinge, shared with web
natew Oct 21, 2026
e519038
macos: One.UI.Image on react native's image
natew Oct 21, 2026
a4a29a5
macos: real route mounts, op-sqlite, NativeDOM, linking and console
natew Oct 21, 2026
7e183d1
regenerate one types for macos variants
natew Oct 21, 2026
8e2cc88
macos: own stack navigator props so ios and android bytes stay unchanged
natew Oct 21, 2026
bcd02cd
plan: m1 done, gate at 8e2cc88e1c
natew Oct 21, 2026
41a00ac
plan: ship mac inside the default one install
natew Oct 21, 2026
7622915
macos: move one-macos into packages/one/macos, drop the committed xco…
natew Oct 21, 2026
2fac9ba
macos: pointer, hover, cursor, focus and key press
natew Oct 21, 2026
ae87bb7
macos: ScrollView on NSScrollView and Image
natew Oct 21, 2026
ed23248
plan: m2 review of move, pointer and scroll commits
natew Oct 21, 2026
b0761a2
macos: ScrollView state follows every scroll, apply initial contentOf…
natew Oct 21, 2026
eef8e83
macos: dark mode event, repaint on appearance change
natew Oct 21, 2026
235d8d4
macos: TextInput on NSTextView
natew Oct 21, 2026
2070373
router: accept .macos route and layout files
natew Oct 21, 2026
0cba4c3
plan: m2 textinput review, consumer batch 1 decisions
natew Oct 21, 2026
ab09a46
macos: toggle shares OneNativeControlled with iOS
natew Oct 21, 2026
5b60246
macos: key prepared deps and hermes on the installed version
natew Oct 21, 2026
86324f6
Fail macos bundles on unsupported imports
natew Oct 21, 2026
1e459a2
plan: review toggle sharing, cache keys, bundle-time import errors
natew Oct 21, 2026
fa47640
plan: planner handoff to s63941
natew Oct 21, 2026
bfec6c9
macos: TextInput on NSTextField and NSTextView scroll view, public js…
natew Oct 21, 2026
efb7ce9
macos: native animated module via RN C++ AnimatedModule, split-view m…
natew Oct 21, 2026
724ae02
Integrate existing macOS host with main
natew Oct 23, 2026
d10d8ab
Fix macOS native animation updates and reload lifetime
natew Oct 23, 2026
55bb498
Fix macOS accessibility presses in inactive windows
natew Oct 23, 2026
edde76e
Implement macOS HTTP networking
natew Oct 23, 2026
dad00b6
Back macOS fetch with native blobs
natew Oct 23, 2026
a30893b
fix(vxrn): keep a bundle's own top-level addEventListener in the nati…
natew Oct 23, 2026
478f390
Add native macOS buttons and segmented controls
natew Oct 23, 2026
61cda88
Register native macOS idle callbacks
natew Oct 23, 2026
7d1cc2f
Merge commit '478f390923' into tm/one-macos-live-assembly
natew Oct 23, 2026
e2d5d27
Resolve macOS PlatformColor through AppKit NSColor
natew Oct 23, 2026
9ce9e08
Center macOS text within an explicit line height
natew Oct 23, 2026
4cf05bd
Merge commit '9ce9e088bb' into tm/one-macos-live-assembly
natew Oct 23, 2026
228a4e3
Avoid retaining failed native blob responses
natew Oct 23, 2026
e9bde62
Document native animation callback lock invariant
natew Oct 23, 2026
eeb2614
Preserve native input boundaries and composition
natew Oct 23, 2026
225fd27
Locate native dev module scope by vxrn-owned markers
natew Oct 23, 2026
3779e52
Use a native callable in the prelude event API fixture
natew Oct 23, 2026
5c84f60
Bridge native Mac menu commands to One.macOS.AppCommands
natew Oct 23, 2026
5ebe5b1
wip: Render native Mac linear backgrounds
natew Oct 23, 2026
336583a
Verify native Mac gradient rendering
natew Oct 23, 2026
1235579
Merge approved native Mac commands
natew Oct 23, 2026
e01b304
Fix Mac gradient clear stops and pattern colors
natew Oct 23, 2026
5bd2bef
Keep shared One imports outside Mac suffix resolution
natew Oct 23, 2026
9608ad5
Align generated declarations with the Mac runtime
natew Oct 23, 2026
7e468b9
Merge main into the native Mac release
natew Oct 23, 2026
288bd31
Prepare One 2.10 native Mac release
natew Oct 23, 2026
ea447e7
Preserve native text colors across appearance changes
natew Oct 23, 2026
234e1e1
Record the reviewed macOS runtime candidate
natew Oct 23, 2026
18a68ec
Add native Mac symbol images
natew Oct 23, 2026
85b4d18
Preserve native symbol point size
natew Oct 23, 2026
d84ca0a
Add macOS command toolbars and segmented roles
natew Oct 23, 2026
d6179ae
Isolate Mac toolbars and preserve accessibility roles
natew Oct 23, 2026
0456119
wip: hide native Mac accessibility descendants
natew Oct 23, 2026
f5b1e44
Keep hidden Mac views out of accessibility and focus
natew Oct 23, 2026
947c29c
Add bordered option to the Mac Button
natew Oct 23, 2026
aa1caa5
Clip Mac view children to the rounded outline
natew Oct 24, 2026
74aeaf5
Update native Mac release review
natew Oct 24, 2026
4a80826
Embed Hermes bytecode in Mac release builds
natew Oct 24, 2026
3e522f2
Record Mac release startup measurements
natew Oct 24, 2026
be5dd71
Plan a native Linux target mirroring the Mac host
natew Oct 24, 2026
753c573
Fail visibly when the Mac release bundle is missing
natew Oct 24, 2026
9c6fd74
Record the Mac post-mount startup profile
natew Oct 24, 2026
1ef6302
Serve Hermes bytecode to Mac debug builds
natew Oct 24, 2026
9b92552
Share the React Native core source list between macOS and Linux
natew Oct 24, 2026
600ecfd
Build the React Native core and Hermes for Linux with a headless smok…
natew Oct 24, 2026
4da09c6
Share the plain C++ host runtime between the Mac and Linux hosts
natew Oct 24, 2026
b2ebaff
Open a GTK 4 window that mounts React Native views and Pango text on …
natew Oct 24, 2026
4465f5a
Record the Linux M1 window status and screenshot
natew Oct 24, 2026
6af9445
Answer the Mac color scheme without waiting on the main thread
natew Oct 24, 2026
5538cf4
Seed the Mac color scheme from the root view's appearance
natew Oct 24, 2026
b701e4b
Add linux as a JS platform in vxrn and One
natew Oct 24, 2026
43b2add
Run the Linux host on the real linux bundle with a GTK switch, Nitro,…
natew Oct 24, 2026
947c2f0
Add Linux Networking, fix switch picking, record M1 status
natew Oct 24, 2026
ac7cb86
Point the Mac plan at the renamed desktop resolver
natew Oct 24, 2026
cb79d7c
Record the linux bundle startup breakdown
natew Oct 24, 2026
2721e4c
Feed pointer presses to React Native touch events on Linux
natew Oct 24, 2026
cc2e751
Add ScrollView on GtkScrolledWindow for the Linux host
natew Oct 24, 2026
d75dff0
Add TextInput on GtkText for the Linux host
natew Oct 24, 2026
a602d95
Follow the GTK theme for Appearance on Linux, cache the scheme on Mac
natew Oct 24, 2026
286a1be
Center TextInput text vertically like the placeholder
natew Oct 24, 2026
a444233
Record the Mac scheme check in the plan
natew Oct 24, 2026
9cf2d2c
Add Image on the Linux host
natew Oct 24, 2026
731dfb2
Apply view transforms on the Linux host
natew Oct 24, 2026
75be1a7
Add hover and cursor on the Linux host
natew Oct 24, 2026
f407c6a
Add multiline TextInput on GtkTextView
natew Oct 24, 2026
ed7b385
Record the hover out check in the plan
natew Oct 24, 2026
b5b412e
Hit test through view transforms on the Linux host
natew Oct 24, 2026
07b6ccb
Copy assets on one build --platform linux
natew Oct 24, 2026
fd90f25
Enforce maxLength in the multiline TextInput
natew Oct 24, 2026
02170dc
Add selectionColor and multiline placeholderTextColor on the Linux host
natew Oct 24, 2026
e6c8f16
Plan: measure and propose a smaller iOS link set
natew Oct 24, 2026
8258e84
Fix escaped backticks in the plan
natew Oct 24, 2026
d35f3f2
Report touch and pointer offsets local to the target view on Linux
natew Oct 24, 2026
d778506
Add a Mac pop-up button and a prominent push button
natew Oct 24, 2026
cf5355e
Regenerate types for PopUpButton and Button prominent
natew Oct 24, 2026
598f29b
Backport reviewed audit dependency repair
natew Oct 24, 2026
4d3aded
Compile iOS feature groups out of release builds
natew Oct 24, 2026
ae97142
Gate PhotosUI limited picker in PhotoLibrary
natew Oct 24, 2026
6d44e32
Fix compiled-out component stub include
natew Oct 24, 2026
1b819e5
Import shadow node header in compiled-out stubs
natew Oct 24, 2026
d4a3bac
Move iOS store review to a store group hybrid
natew Oct 24, 2026
55fc7bd
Merge remote-tracking branch 'origin/tm/macos-resume' into tm/macos-p…
natew Oct 24, 2026
86a2e54
Fix the native engine integration test package boundary
natew Oct 24, 2026
7f306cd
Merge remote-tracking branch 'origin/tm/macos-resume' into tm/macos-p…
natew Oct 24, 2026
aa43f5f
Align vxrn project declarations with package output
natew Oct 24, 2026
0bd3408
Merge remote-tracking branch 'origin/tm/macos-resume' into tm/macos-p…
natew Oct 24, 2026
b651963
Detect link set groups through the One namespace
natew Oct 24, 2026
f8d8db7
Record iOS link set results in the plan
natew Oct 24, 2026
163f07c
Merge Mac pop-up and prominent button controls
natew Oct 24, 2026
4045562
Detect link set groups from the production module graph
natew Oct 24, 2026
abd23a2
Add typed search params with Standard Schema
natew Oct 24, 2026
6314681
Read only query keys in useSearchParams(schema), fix item fixture build
natew Oct 24, 2026
f129407
Global search params in a page read the active route
natew Oct 24, 2026
60db28d
Record link set detection, staleness and measurement
natew Oct 24, 2026
ec34509
Regenerate One type declarations for the link set
natew Oct 24, 2026
14fcd50
Carry modifier frameworks only for non-SwiftUI declarations
natew Oct 24, 2026
30c42f2
Prepare iOS linking in the held minor
natew Oct 24, 2026
73fced5
Disable automatic updates in the Linux dev VM
natew Oct 25, 2026
a0de2c3
Send Linux pointer down move and up events
natew Oct 25, 2026
0293a3f
Fix Linux input placeholder and caret colors
natew Oct 25, 2026
8b5b483
Add the first Linux GTK controls
natew Oct 25, 2026
e21aec3
Record Linux VM setup and interaction validation
natew Oct 25, 2026
0d5108c
Measure Linux inline text attachments
natew Oct 25, 2026
2a23b33
Retain Linux surface through host teardown
natew Oct 25, 2026
dc4d91f
Let React Native synthesize Linux hover events
natew Oct 25, 2026
9020aaf
Rename validateSearchParams, validate component schemas before ssr lo…
natew Oct 25, 2026
dc88cc9
Send the page query with ssr loader requests on client navigation
natew Oct 25, 2026
56ebb5a
Validate ssr search params in the Vercel function, show rejected queries
natew Oct 25, 2026
fab944f
docs(one): describe query-aware client loader validation
natew Oct 25, 2026
d21406c
Apply Linux pointer policy to GTK picking
natew Oct 25, 2026
3d7d61f
add DOM component JavaScript runtime
natew Oct 25, 2026
fb750e8
Restore the macOS bottom toolbar error
natew Oct 25, 2026
9be2e8b
add DOM directive browser builds
natew Oct 25, 2026
be87ed7
preserve DOM calls across handle updates
natew Oct 25, 2026
0cdc9d9
Ignore stale Linux image callbacks
natew Oct 25, 2026
8c4815d
Release closed Linux WebSockets
natew Oct 25, 2026
3181777
document experimental DOM components
natew Oct 25, 2026
48dfa7d
Enforce Linux input limits in UTF-16 units
natew Oct 25, 2026
1009698
reject DOM directives in Metro transforms
natew Oct 25, 2026
31243cd
add native OneDOMHost for iOS and Android
natew Oct 25, 2026
099d36c
Add four Linux control counterparts
natew Oct 25, 2026
0b84b02
Measure Linux controls with GTK
natew Oct 25, 2026
bd1854e
Wire DOM host assets and package exports
natew Oct 25, 2026
fe617e0
Complete Linux control callbacks and item values
natew Oct 25, 2026
72b352c
package DOM assets beside native bundles
natew Oct 25, 2026
968b820
Correct progress props and expose control measurements
natew Oct 25, 2026
424cc44
record real DOM browser runtime proof
natew Oct 25, 2026
258a23b
keep WebKit out of One-Swift.h and owned host variants off the network
natew Oct 25, 2026
2ca74c0
Repair DOM fixture asset and isolate its router
natew Oct 25, 2026
91d0145
Respect GTK control measurement timing
natew Oct 25, 2026
631b297
report DOM host errors without throwing
natew Oct 25, 2026
7fafb77
report DOM page errors before subscribe on iOS
natew Oct 25, 2026
0019d5f
label native and DOM fixture builds
natew Oct 25, 2026
c43c6fc
Generate Linux control declarations
natew Oct 25, 2026
7fe12ef
Wait for hydration and the committed url in the search params loader …
natew Oct 25, 2026
dba04ff
Record Linux M3 interaction proof
natew Oct 25, 2026
b68064b
Read embedded DOM assets from the host context
natew Oct 25, 2026
ea0074d
Clarify DOM navigation and startup errors
natew Oct 25, 2026
de7edd4
Align Linux Stepper with native API
natew Oct 25, 2026
549b2ac
report DOM page errors before subscribe on Android
natew Oct 25, 2026
fb1efbe
add update controls to DOM proof app
natew Oct 25, 2026
a5d3f2e
Batch Linux control measurements before paint
natew Oct 25, 2026
cd88232
Scope Linux pointer events to their surface
natew Oct 25, 2026
d6d0498
Clip Linux controls to their RN frames
natew Oct 25, 2026
7ab07b2
Pair Linux Slider cancellation callbacks
natew Oct 25, 2026
6134f35
Pair Linux pointer releases and hover exits
natew Oct 25, 2026
9dadf4f
Fold Linux Switch into shared controls
natew Oct 25, 2026
0df8377
Fix production JSX in DOM assets
natew Oct 25, 2026
e8897e0
Remove controlled state from Linux progress
natew Oct 25, 2026
bc97c3a
Share desktop control wrapper types
natew Oct 25, 2026
c4383c4
Keep Linux control behavior by widget kind
natew Oct 25, 2026
3e399cb
Share Mac and Linux control wrappers
natew Oct 25, 2026
e51a646
Record Android DOM host validation
natew Oct 25, 2026
35dfb21
Add Linux app shell and native routing
natew Oct 25, 2026
2e96618
Trim shared command type whitespace
natew Oct 25, 2026
2a2a4ce
Resubmit Linux measurements after stale props
natew Oct 25, 2026
17bcb3e
Record Mac check after shared wrappers
natew Oct 25, 2026
36210a6
Pass navigation insets through Fabric state
natew Oct 25, 2026
1e4ee61
Own worklet animation frames per module
natew Oct 25, 2026
8d53df8
Match shifted and cmd bindings, keep menu underscores
natew Oct 25, 2026
9311bdd
Record review 3 fixes
natew Oct 25, 2026
2d3c2c2
Add prebuilt core and .deb packaging for Linux
natew Oct 25, 2026
8d7ff06
Package Flatpak, ship ICU with it, list ICU in .deb deps
natew Oct 25, 2026
38109a2
Merge the macOS minor batch 7fe12ef4c8 into the Linux branch
natew Oct 25, 2026
736922c
Fix duplicate appearance ivar from the Mac merge, add prominent and P…
natew Oct 25, 2026
382d3ea
Record combined Mac and Linux check
natew Oct 25, 2026
39e4946
docs: record DOM app validation
natew Oct 25, 2026
7bdf1d5
Merge held minor with DOM packaging
natew Oct 25, 2026
9cd108e
Reject unsupported desktop DOM imports
natew Oct 25, 2026
10a738b
Build Linux native hosts in CI with static ICU
natew Oct 25, 2026
d8a5dc3
Commit generated Metro DOM declaration
natew Oct 25, 2026
0c96f74
Commit the DOM Metro guard declaration
natew Oct 25, 2026
fec466b
Merge the original DOM declaration repair
natew Oct 25, 2026
eeadcc0
Build PIC ICU archives for shared Hermes
natew Oct 25, 2026
000dc37
Link the Linux core with the atomic runtime
natew Oct 25, 2026
d06fc83
Record passing Linux CI on both architectures
natew Oct 25, 2026
2f42358
Run the Linux native workflow only on main, v2-beta and pull requests
natew Oct 25, 2026
fcc3b64
Assert native plugin command contexts
natew Oct 25, 2026
509107d
Keep DOM proof outside default Metro routes
natew Oct 25, 2026
ecd025b
Reject missing debug view identifiers
natew Oct 25, 2026
5b13539
Integrate portable Linux builds and CI
natew Oct 25, 2026
3127f17
Merge current main into the native minor
natew Oct 25, 2026
f7e06a3
Prepare the native feature batch for One 2.11
natew Oct 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
110 changes: 110 additions & 0 deletions .github/workflows/test-native-linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Linux Native Build

on:
push:
branches:
- main
- v2-beta
paths:
- '.github/actions/install/**'
- '.github/workflows/test-native-linux.yml'
- 'bun.lock'
- 'package.json'
- 'patches/**'
- 'packages/one/**'
- 'packages/vxrn/**'
- 'packages/vite-plugin-metro/**'
- 'tests/linux-basic/**'
pull_request:
paths:
- '.github/actions/install/**'
- '.github/workflows/test-native-linux.yml'
- 'bun.lock'
- 'package.json'
- 'patches/**'
- 'packages/one/**'
- 'packages/vxrn/**'
- 'packages/vite-plugin-metro/**'
- 'tests/linux-basic/**'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

jobs:
build-linux-native:
name: Compile and launch One Native Linux (${{ matrix.arch }})
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-24.04
- arch: aarch64
runner: ubuntu-24.04-arm
env:
CC: clang-18
CXX: clang++-18
ONE_LINUX_CORE_FROM_SOURCE: '1'
steps:
- uses: actions/checkout@v6
- name: Install Linux build and headless display dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang-18 cmake ninja-build pkg-config libgtk-4-dev \
libsoup-3.0-dev libsqlite3-dev sway grim dbus-x11 fonts-dejavu-core
- uses: ./.github/actions/install
with:
install-playwright: 'false'
workspace-focus: one
- name: Locate the installed React Native
run: echo "RN_ROOT=$(realpath node_modules/react-native)" >> "$GITHUB_ENV"
- name: Cache Linux native dependencies
uses: actions/cache@v5
with:
path: |
~/.cache/ReactNative/linux/src
~/.cache/ReactNative/linux/downloads
~/.cache/ReactNative/linux/third-party
~/.cache/ReactNative/linux/hermes-*
~/.cache/ReactNative/linux/icu-*
~/.cache/ReactNative/linux/deps-*
key: linux-native-${{ matrix.arch }}-${{ hashFiles('bun.lock', 'packages/one/linux/scripts/prepare-hermes.sh', 'packages/one/linux/scripts/prepare-icu.sh', 'packages/one/linux/scripts/prepare-deps.sh', 'packages/one/linux/cpp/deps/**') }}
- name: Build the Linux core and GTK host
run: packages/one/linux/scripts/prepare-core.sh "$RUNNER_TEMP/linux-app" release
- name: Verify Hermes has no dynamic ICU dependency
run: |
for binary in "$RUNNER_TEMP/linux-app/libhermesvm.so" "$RUNNER_TEMP/linux-app/hermesc"; do
readelf -d "$binary" | tee "$binary.dynamic.txt"
if grep -q 'Shared library: \[libicu' "$binary.dynamic.txt"; then
echo "::error::$binary depends on the build host's ICU"
exit 1
fi
done
- name: Bundle the Linux Basic consumer as Hermes bytecode
run: |
packages/one/linux/scripts/bundle-js.sh js tests/linux-basic "$RUNNER_TEMP/linux-app/main.js"
packages/one/linux/scripts/bundle-js.sh bytecode "$RUNNER_TEMP/linux-app/hermesc" \
"$RUNNER_TEMP/linux-app/main.js" "$RUNNER_TEMP/linux-app/main.jsbundle"
cp -R tests/linux-basic/dist/assets "$RUNNER_TEMP/linux-app/assets"
- name: Prove first content paint under headless Wayland
env:
G_DEBUG: fatal-criticals
run: |
dbus-run-session -- packages/one/linux/scripts/screenshot.sh \
"$RUNNER_TEMP/linux-app/one-linux" "$RUNNER_TEMP/linux-first-paint.png"
- name: Upload Linux launch evidence
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: one-native-linux-${{ matrix.arch }}
path: |
${{ runner.temp }}/linux-first-paint.png*
${{ runner.temp }}/linux-app/*.dynamic.txt
if-no-files-found: warn
2 changes: 1 addition & 1 deletion apps/one-tray/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "one-tray",
"version": "2.9.0",
"version": "2.11.0",
"private": true,
"scripts": {
"build": "[ \"$(uname)\" = \"Darwin\" ] && make debug || true",
Expand Down
14 changes: 14 additions & 0 deletions apps/onestack.dev/data/docs/components-Link.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,19 @@ export interface LinkProps<T extends string | object = string>
* <Link href="/photos/5/modal" mask="/photos/5">View Photo</Link>
*/
mask?: Href

/**
* Search params to add to `href`. Keys replace the same keys already in `href`; the
* path, other keys and the hash stay. Strings, numbers, booleans and arrays of those
* are written (arrays as repeated keys), `null` and `undefined` remove a key. The `params`
* prop still joins an array with commas, so an array there is one string.
*
* When the destination route reads its query with `useSearchParams(schema)`, the keys
* and values are type checked against that schema. The server validates the same schemas before an `ssr` route's loader runs. See [useSearchParams](/docs/hooks-useSearchParams).
*
* @example
* <Link href="/products" searchParams={{ page: 2 }}>Page 2</Link>
*/
searchParams?: Record<string, string | number | boolean | readonly (string | number | boolean)[] | null | undefined>
}
```
2 changes: 1 addition & 1 deletion apps/onestack.dev/data/docs/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ With render modes, you can choose SSG, SSR, or SPA on a per-page basis - Expo Ro

One also adds [dev tools](/docs/dev-tools) (Alt+Space) with SEO preview, route debugging, loader timing, error tracking, and a source inspector. Plus [middleware](/docs/routing-middlewares) for request interception and auth, and [typed loaders](/docs/routing-loader) that run on the server and tree-shake out of client bundles.

Expo Router does have features One lacks, like `use dom` and RSC support. We encourage you to evaluate both and choose based on your needs.
One has an experimental, unreleased [DOM components guide](/docs/guides-dom-components) for its `use dom` feature branch; native integration is still being validated. Expo Router offers RSC support, which One does not. We encourage you to evaluate both and choose based on your needs.

### Will you support RSC?

Expand Down
174 changes: 174 additions & 0 deletions apps/onestack.dev/data/docs/guides-dom-components.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
title: DOM components (experimental)
description: Use a browser React component inside a native screen, with data props and asynchronous actions.
---

DOM components let a native screen host browser React markup, CSS and browser libraries. On the web, the same import renders the original React component inline.

<Notice>
This feature is experimental and unreleased on the feature branch. Build and JavaScript integration probes have passed. An integrated iOS 27 simulator app has exercised native actions and refs, refresh, packaged offline loading, update staging, activation and rollback with matching native and DOM versions. Android 17 emulator proof covers the native host; integrated Android app and Updates behavior remain unvalidated. The current app targets are iOS 17+ and Android API 24+ through React Native 0.88. These are not claims of testing on those minimum versions or complete native support. Android also needs a modern, updated System WebView: Vite's current browser baseline includes Chrome 111 and iOS 16.4, so the Android OS API alone does not establish browser compatibility.
</Notice>

Use One's default Vite/Rolldown pipeline. Metro, native desktop, Expo Go and Expo Updates support are deferred. Your native binary must include `OneDOMHost`, so adding this feature requires a native rebuild; JavaScript refresh alone cannot add it. See [Build or Run iOS](/docs/guides-ios-native) and [Native Setup](/docs/native-setup). No separate WebView package or Expo compiler is required.

## Create a component

Put `'use dom'` in the directive prologue, before imports, in a component file **outside `app/`**. Export one default component. Type exports are allowed, but named runtime exports and export-star declarations are rejected. Direct DOM route files, layouts, API routes, loaders and server modules are unsupported. A normal route can import the component.

Create `components/NoteEditor.tsx`:

```tsx
'use dom'

import { useState, type Ref } from 'react'
import { useDOMImperativeHandle, type DOMProps } from 'one/dom'

export type EditorHandle = {
read: () => Promise<string>
clear: () => Promise<void>
}

type Props = {
initialText: string
onSave: (text: string) => Promise<string>
onNavigate: () => Promise<void>
ref?: Ref<EditorHandle>
dom?: DOMProps
}

export default function NoteEditor({ initialText, onSave, onNavigate, ref }: Props) {
const [text, setText] = useState(initialText)
const [message, setMessage] = useState('')
const report = (error: unknown) =>
setMessage(error instanceof Error ? error.message : String(error))

useDOMImperativeHandle(ref, () => ({
async read() {
if (!text.trim()) throw new Error('Enter some text')
return text
},
async clear() {
setText('')
},
}), [text])

return (
<section style={{ padding: 16 }}>
<textarea value={text} onChange={(event) => setText(event.currentTarget.value)} />
<button onClick={() => void onSave(text).then(setMessage, report)}>Save</button>
<button onClick={() => void onNavigate().catch(report)}>Library</button>
<p role="status">{message}</p>
</section>
)
}
```

`dom` configures the native container and is removed before data reaches the hosted component. Accept it in the component's type, but do not spread it onto browser elements. The component above uses React 19's `ref` prop.

## Pass data and actions from the screen

For example, `app/index.tsx` can supply data and asynchronous callbacks:

```tsx
import { useRef, useState } from 'react'
import { Button, Text, View } from 'react-native'
import { useRouter } from 'one'
import NoteEditor, { type EditorHandle } from '../components/NoteEditor'

export default function Screen() {
const router = useRouter()
const editor = useRef<EditorHandle>(null)
const [status, setStatus] = useState('')

async function readAndClear() {
const handle = editor.current
if (!handle) {
setStatus('Editor is not ready')
return
}
try {
const text = await handle.read()
await handle.clear()
setStatus(`Read: ${text}`)
} catch (error) {
setStatus(error instanceof Error ? error.message : String(error))
}
}

return (
<View>
<NoteEditor
ref={editor}
initialText="Hello"
onSave={async (text) => {
setStatus(`Saved: ${text}`)
return 'Saved'
}}
onNavigate={async () => { router.push('/library') }}
dom={{
style: { height: 240 },
scrollEnabled: true,
onError: (error) => setStatus(error.message),
}}
/>
<Button title="Read and clear" onPress={() => void readAndClear()} />
<Text>{status}</Text>
</View>
)
}
```

Replace `/library` with a route in your app. Navigation is an explicit action owned by the parent. In the native host, links that leave the owned page are blocked, and `window.open` opens no window. Use an action such as `onNavigate` to request navigation. Native router state, providers, native modules and React context do not cross into the browser root. Pass data and actions rather than `children`, React elements or native objects. Browser events stay in the component; pass their data, such as the text string, to an action.

The example demonstrates all three handle outcomes: `read()` resolves to a string, `clear()` resolves with no value, and reading an empty editor rejects with an error. Actions and imperative methods always return promises, including on ordinary web renders. Errors preserve `name`, `message` and an optional `code`; stacks are included only in development. Do not depend on a custom error class surviving the boundary.

`useDOMImperativeHandle(ref, factory, dependencies)` exposes one handle per hosted component. Keep dependencies current. A dependency change replaces the committed methods without rejecting calls already running. New calls through retained handles use the latest committed methods; calling a removed method rejects. The name `then` is reserved. A ref becomes available when the browser hook commits; `dom.onLoad` does not promise that the ref is ready.

## Container options

Pass these options through the optional `dom` prop. They apply to the native host, not the inline web component.

| Option | Behavior |
| --- | --- |
| `style` | React Native container style. Give the host space, for example a fixed height. |
| `scrollEnabled` | Enables browser scrolling; defaults to `true`. |
| `matchContents` | Uses the measured browser content height at the native container's width. Use this instead of a fixed height when content should size the host. |
| `onLoad` | Receives `{ entryId, epoch }` when the host document completes loading. |
| `onError` | Receives `{ name, message, code?, stack?, entryId, epoch? }` for host and page errors, including startup failures. |

Page errors include a module evaluation failure, an unhandled rejection and a failed entry script load. When `onError` is omitted, errors are logged.

There is no synchronous bridge, raw script evaluation, arbitrary page source or underlying WebView ref API.

## Data rules

Data props, action arguments and returned values support strings, booleans, finite numbers, `null`, arrays and plain objects. Only top-level function props become actions. Functions inside objects are rejected.

Undefined object fields are omitted recursively, including optional top-level props. Undefined array entries and array holes are rejected. For example, an undefined first item reports a path such as `props["items"][0]`; a nested callback reports `props["options"]["onSave"]`. Class instances, `Date`, `Error` as data, symbols, BigInt, nonfinite numbers and cycles are also rejected with paths. Convert them to supported data first. Throwing an error from an action is supported and rejects the caller's promise.

Prop changes update the mounted component without replacing its document. Local browser state follows normal React rules: updating `initialText` does not reinitialize the example's `useState`. Native ordinary props never supply HTML or JavaScript source.

## Styles, assets and web rendering

Use browser markup and styles inside the component. Import the CSS and assets it owns, for example after creating `editor.css` and `illustration.svg` beside it:

```tsx
import './editor.css'
import illustration from './illustration.svg'

function Illustration() {
return <img src={illustration} alt="Notebook" />
}
```

Imported CSS, fonts and images use standard Vite transformations and relative packaged URLs. Unrelated web `public/` files are not copied. Root-relative public URLs such as `/logo.png` are unsupported in packaged DOM components; import the asset instead. Ordinary network requests follow browser CORS rules. Production page origins are `one-dom://app` on iOS and `https://appassets.androidplatform.net` on Android; development uses the Vite server origin. Verify the request headers on your target WebView when configuring server CORS. The iOS custom scheme probe establishes the page origin but has not measured the HTTP `Origin` header.

On web, One retains the original component and the route's existing [SSG, SSR or SPA rules](/docs/render-modes). The directive does not disable server rendering. Keep browser-only globals out of module evaluation and server renders; access them in effects or event handlers where appropriate. Prefer static asset imports as above over `new URL(..., import.meta.url)` patterns whose meaning differs during SSR.

## Refresh and document lifetime

Development uses the existing reachable Vite server, with browser React Refresh, CSS updates, imported assets and the error overlay. Compatible React Refresh edits can preserve local state, including edits to transitive browser dependencies. A full reload or document replacement starts fresh browser state.

Each hosted document has a separate request lifetime. Unmount, disposal or document failure rejects pending bridge calls; replies from an old document cannot resolve calls in its replacement. Already started native actions may still finish their side effects, so rejection is not cancellation. A replacement document receives a fresh committed prop snapshot and later prop updates reconcile normally.

Integrated app layout and keyboard behavior, minimum platform coverage and Updates activation still need validation. Focused host, build and JavaScript probes do not establish those app guarantees.
1 change: 1 addition & 0 deletions apps/onestack.dev/data/docs/guides.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Guides to common patterns are here. If you'd like to contribute a Guide, please
<Card href="/docs/guides-dark-mode" title="Light and Dark mode" category="UI" />
<Card href="/docs/guides-tamagui" title="Setting up Tamagui" category="UI" />
<Card href="/docs/guides-ios-native" title="Build or Run the Native iOS App" category="Native" />
<Card href="/docs/guides-dom-components" title="DOM components (experimental)" category="Native" />
<Card href="/docs/guides-ota-updates" title="Over-the-air Updates" category="Native" />
<Card href="/docs/guides-migrating-create-react-app-cra-to-vite-with-one" title="Migrate from Create React App to One" category="Migrating" />
<Card href="https://github.com/onejs/skills" title="AI Agent Skills" category="AI" />
Expand Down
Loading
Loading