Skip to content

feat: React Native (Expo) support - #8

Merged
khaledalam merged 3 commits into
mainfrom
feat/react-native-support
Jul 15, 2026
Merged

feat: React Native (Expo) support#8
khaledalam merged 3 commits into
mainfrom
feat/react-native-support

Conversation

@khaledalam

Copy link
Copy Markdown
Owner

Summary

Adds React Native (Expo) support to avatoon without changing web behaviour. The same <Avatoon> component now renders on web (DOM <canvas> + HTMLAudioElement) and on React Native (@react-three/fiber/native via expo-gl + expo-av), selected automatically by a react-native package export condition — consumers import from 'avatoon' on both.

How it works

A platform split keeps the component tree platform-agnostic:

  • src/platform/ — renderer seam. index.ts (web) re-exports Canvas/hooks/controls from @react-three/fiber + @react-three/drei; index.native.tsx re-exports from the /native entries. All components now import these from ../platform.
  • src/audio/ — audio seam. An AudioClock interface with a web impl (HTMLAudioElement) and a native impl (expo-av: base64 WAV → temp file via expo-file-system, positionMillis interpolated into a smooth per-frame clock). AvatoonModel talks only to this interface.
  • Buildvite.native.config.mjs emits a separate lib/native/index.es.js, resolving .native.* first and externalizing all native peers. package.json exports adds the react-native condition; expo peers are optional peer deps and react-dom is now optional.
  • Type shims (src/types/native-modules.d.ts) let it typecheck without installing Expo.

Examples & docs

  • examples/native/App.tsx — audio-synced lip-sync driven via ref.
  • examples/native/GoalsExample.tsx — goal-based gestures (Normal / Muscle / Sleep).
  • README gains a "📱 React Native (Expo)" section with a platform-difference table.

Tests / coverage

  • Coverage 80% → 96% lines (92.9% statements); 51 tests (was 33).
  • New expoAudioClock.spec.ts unit-tests the native audio clock via manual expo-av / expo-file-system mocks (wired through jest.config.js).
  • Added web coverage for the imperative ref handle + play button, the camera fov frame loop, and the audio/viseme-driving path.

Verification

  • ✅ lint, typecheck, tests, and web + native build all green.
  • ⚠️ Verified it compiles, bundles, and resolves to the correct platform code (native bundle references @react-three/fiber/native + expo-av; web bundle unchanged). Not yet run on a real device/simulator — an Expo device test is recommended before release.
  • Note: @react-three/drei/native's HDR Environment is more limited than web; R3F's native entry is most proven on the v8 line (React 18 / Expo 51), which the example pins.

Release note

Touches src/, so merging to main will publish. Suggest landing as a minor (1.10.0) — new feature, no breaking changes to the web API.

@khaledalam
khaledalam merged commit 4adfe3a into main Jul 15, 2026
8 checks passed
@khaledalam
khaledalam deleted the feat/react-native-support branch July 15, 2026 15:15
@khaledalam

Copy link
Copy Markdown
Owner Author

🎉 This PR is included in version 1.10.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant