@unrulysystems/native-motion
v0.1.0-alpha.0
Published
The single public import (REQ-UNIVERSAL-001): one specifier resolving to two engine entries — AND, since the dogfood extraction (`specs/DOGFOOD-MIGRATION-BUILD-PACKET.md`), the home of the native runtime itself.
Readme
@unrulysystems/native-motion
The single public import (REQ-UNIVERSAL-001): one specifier resolving to two engine entries —
AND, since the dogfood extraction (specs/DOGFOOD-MIGRATION-BUILD-PACKET.md), the home of the
native runtime itself.
src/web.ts—'use client', an EXPLICIT re-export of the universal surface from the web engine (@unrulysystems/native-motion-web); web-internal helpers stay out of the namespace.src/native.ts— the native runtime entry: the universal surface (View,ViewProps,Text,TextProps,Image,ImageProps,AnimatePresence(+ pin-catalogonRestalias ofonExitComplete),usePresence,useIsPresent,MotionRoot,MotionRootProps,MotionLengthLayoutProvider(parent/viewport geometry for measure-resolved%/calc),LayoutScrollOffsetProvider+recordLayoutScrollOffsetFromEvent/createLayoutScrollOffsetRef(REQ-LAYOUT-022(c) live container-scroll feed),DragInfo+ the canonical core types) over the engine insrc/native/{driver,motion}(the worklet driver, the bindings, the UI-thread layout-identity engine).View,Text, andImageshare the FLAG 5a drag family (drag('x' | 'y' | true— both-axes ships at R15 D1, REQ-API-041),dragConstraints,dragElastic,dragSnapPoints,dragPropagation(Motion's nested-drag lock, R15 D1),onDragStart/onDrag/onDragEnd), the FLAG 5b layout family (layout,layoutId,layoutScroll), and distinct property/layout lifecycle callbacks (onAnimationComplete,onLayoutAnimationStart,onLayoutAnimationComplete);Textaccepts ordinary React Native text children whileImageis childless and requires a validsource. Text's universalas="p" | "span"selector is validated on native (nested Text accepts onlyspan, preventing a divergent invalid text tree) even though RN has no DOM display-mode split; the web entry uses it to preserve a catalog paragraph/inline choice.MotionRootowns the gesture recognizer root (a gesture-carrying host outside it fails loud). Capabilities the native surface has not pulled yet are absent — premature use is a build error, never a stub. The host element set is CLOSED at these three RN leaf primitives (ratified 2026-07-22, BRIEF Decisions): container classes adjudicate toView, controls animate through aViewwrapper, andmotion.createstays internal-only.src/verification.ts— the engine's intrinsic verification harness (probes, deterministic check screens, the choreography gallery). SHELL-ONLY by law: the proof-harness app shell mounts it; it is never part of a consumer example (REQ-EXHARNESS-010).
Dual skew-checked resolution (the ratified architecture)
The manifest ships BOTH resolution mechanisms — the exports react-native condition (newer
Metro) AND the top-level react-native field (older Metro floor) — and two guards keep them
from ever disagreeing:
scripts/check-resolution-skew.mjs(wired intonub run check): asserts the condition and the field point at the same file, thatbrowser/import/defaultagree and differ from the native entry, and that both entries exist on disk.src/resolution.test.ts: resolves the export map withresolve.exports— react-native → native, browser/import/default → web, no engine-mixing fall-through.
Type identity across entries is a COMPILE-TIME gate: src/type-identity.keys.ts fails
nub run typecheck if a native value export is absent on web while allowing intentional pinned
Motion additions to the web namespace. src/type-identity.assert.ts fails if the universal View-,
Text-, and Image-prop subsets (initial/animate/exit/transition/onAnimationComplete/
onLayoutAnimationStart/onLayoutAnimationComplete/layout/layoutId) or the pinned
AnimatePresence props stop being
structurally identical, or if the presence-hook signatures drift from the pinned motion/react
shapes (portable across test runners because it is not a test at all).
