@unrulysystems/native-motion 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +55 -0
  4. package/android/build.gradle +24 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/java/com/unrulysystems/nativemotion/GestureExclusionModule.kt +55 -0
  7. package/android/src/main/java/com/unrulysystems/nativemotion/NativeMotionPackage.kt +27 -0
  8. package/package.json +57 -0
  9. package/react-native.config.js +14 -0
  10. package/src/native/driver/instantWindow.ts +31 -0
  11. package/src/native/driver/strictModeReplay.ts +20 -0
  12. package/src/native/driver/uiLayoutEngine.ts +845 -0
  13. package/src/native/driver/uiLayoutGraph.ts +338 -0
  14. package/src/native/driver/uiValueChannel.ts +4640 -0
  15. package/src/native/driver/workletDriver.ts +3860 -0
  16. package/src/native/motion/AnimatePresence.tsx +1605 -0
  17. package/src/native/motion/LayoutGroup.tsx +163 -0
  18. package/src/native/motion/MotionConfig.tsx +400 -0
  19. package/src/native/motion/MotionRoot.tsx +250 -0
  20. package/src/native/motion/MotionView.tsx +6761 -0
  21. package/src/native/motion/addScaleCorrector.ts +97 -0
  22. package/src/native/motion/colorEndpointUiFeed.ts +32 -0
  23. package/src/native/motion/colorProjection.ts +39 -0
  24. package/src/native/motion/composeTransform.ts +271 -0
  25. package/src/native/motion/constraintMeasure.ts +157 -0
  26. package/src/native/motion/deferredPendingSnapshots.ts +25 -0
  27. package/src/native/motion/discreteProjection.ts +36 -0
  28. package/src/native/motion/dragAncestorPanContext.ts +28 -0
  29. package/src/native/motion/dragControls.ts +152 -0
  30. package/src/native/motion/dragGestureWiring.ts +1168 -0
  31. package/src/native/motion/dragHandoffBinding.ts +179 -0
  32. package/src/native/motion/dragHubStream.ts +756 -0
  33. package/src/native/motion/dragPropagationLock.ts +57 -0
  34. package/src/native/motion/driverValueChannel.ts +3288 -0
  35. package/src/native/motion/externalDragDriver.ts +214 -0
  36. package/src/native/motion/frameData.ts +31 -0
  37. package/src/native/motion/gestureBinding.ts +107 -0
  38. package/src/native/motion/gestureStateGate.ts +563 -0
  39. package/src/native/motion/gestureStateResolver.ts +286 -0
  40. package/src/native/motion/identityValueChannelControllerAdapter.ts +2043 -0
  41. package/src/native/motion/identityValueChannelControllerReconciliation.ts +176 -0
  42. package/src/native/motion/identityValueChannelLaneMarker.ts +14 -0
  43. package/src/native/motion/imperativeAnimate.ts +816 -0
  44. package/src/native/motion/keyframeTiming.ts +7 -0
  45. package/src/native/motion/layoutIdBinding.ts +261 -0
  46. package/src/native/motion/layoutIdFlightConfig.ts +51 -0
  47. package/src/native/motion/layoutProjection.ts +89 -0
  48. package/src/native/motion/layoutScroll.ts +204 -0
  49. package/src/native/motion/layoutTransition.ts +1302 -0
  50. package/src/native/motion/lengthLayoutContext.tsx +100 -0
  51. package/src/native/motion/lengthLayoutHost.ts +44 -0
  52. package/src/native/motion/mappedKeys.ts +184 -0
  53. package/src/native/motion/motionViewController.ts +3180 -0
  54. package/src/native/motion/nativeHostMarker.ts +22 -0
  55. package/src/native/motion/panSessionWiring.ts +127 -0
  56. package/src/native/motion/pathTransition.ts +101 -0
  57. package/src/native/motion/popLayout.ts +176 -0
  58. package/src/native/motion/presenceBinding.ts +382 -0
  59. package/src/native/motion/scaleCorrectorRegistry.ts +123 -0
  60. package/src/native/motion/scrollValues.ts +260 -0
  61. package/src/native/motion/serializablePayload.ts +151 -0
  62. package/src/native/motion/severity.ts +16 -0
  63. package/src/native/motion/shippedSurface.ts +843 -0
  64. package/src/native/motion/staticLengthGate.ts +86 -0
  65. package/src/native/motion/styleBaseGate.ts +72 -0
  66. package/src/native/motion/styleValueBinding.ts +657 -0
  67. package/src/native/motion/systemGestureExclusion.ts +61 -0
  68. package/src/native/motion/tapGestureWiring.ts +215 -0
  69. package/src/native/motion/transformOrder.ts +38 -0
  70. package/src/native/motion/transformStringBinding.ts +200 -0
  71. package/src/native/motion/transformTemplateGate.ts +45 -0
  72. package/src/native/motion/transitionGate.ts +435 -0
  73. package/src/native/motion/useAnimate.ts +52 -0
  74. package/src/native/motion/useCycle.ts +44 -0
  75. package/src/native/motion/useInstantTransition.ts +68 -0
  76. package/src/native/motion/useReducedMotion.ts +58 -0
  77. package/src/native/motion/useScroll.ts +162 -0
  78. package/src/native/motion/useViewportScroll.ts +29 -0
  79. package/src/native/motion/valueChannel.ts +7121 -0
  80. package/src/native/motion/valueHooks.ts +901 -0
  81. package/src/native/motion/variantChildRegistry.ts +67 -0
  82. package/src/native/motion/variantContext.tsx +172 -0
  83. package/src/native/motion/variantProps.ts +598 -0
  84. package/src/native.ts +159 -0
  85. package/src/verification/harnessMetrics.ts +78 -0
  86. package/src/verification/probe/LayoutIdentityWorkletProbe.tsx +251 -0
  87. package/src/verification/probe/WorkletParityProbe.tsx +162 -0
  88. package/src/verification/probe/layoutIdentityProbeEngine.ts +429 -0
  89. package/src/verification/screens/ArcPathChecksScreen.tsx +273 -0
  90. package/src/verification/screens/BooleanAnimateChecksScreen.tsx +358 -0
  91. package/src/verification/screens/ChoreographyGalleryScreen.tsx +1010 -0
  92. package/src/verification/screens/ColorBindingChecksScreen.tsx +568 -0
  93. package/src/verification/screens/CompletionChecksScreen.tsx +294 -0
  94. package/src/verification/screens/ConformanceScreen.tsx +573 -0
  95. package/src/verification/screens/ContentionProbeScreen.tsx +224 -0
  96. package/src/verification/screens/DriverSmokeScreen.tsx +99 -0
  97. package/src/verification/screens/DurationOnlyTweenChecksScreen.tsx +294 -0
  98. package/src/verification/screens/DynamicDragConfigChecksScreen.tsx +237 -0
  99. package/src/verification/screens/FrameDataChecksScreen.tsx +252 -0
  100. package/src/verification/screens/GestureChecksScreen.tsx +685 -0
  101. package/src/verification/screens/InstantTransitionChecksScreen.tsx +839 -0
  102. package/src/verification/screens/LayoutAnimationStartChecksScreen.tsx +648 -0
  103. package/src/verification/screens/LayoutChecksScreen.tsx +822 -0
  104. package/src/verification/screens/LayoutCommitSpikeScreen.tsx +142 -0
  105. package/src/verification/screens/MotionViewChecksScreen.tsx +930 -0
  106. package/src/verification/screens/PresenceChecksScreen.tsx +614 -0
  107. package/src/verification/screens/ReducedMotionChecksScreen.tsx +614 -0
  108. package/src/verification/screens/RestThresholdChecksScreen.tsx +634 -0
  109. package/src/verification/screens/ScaleCorrectorChecksScreen.tsx +425 -0
  110. package/src/verification/screens/SharedLayoutContinuityChecksScreen.tsx +338 -0
  111. package/src/verification/screens/SharedLayoutCrossfadeChecksScreen.tsx +425 -0
  112. package/src/verification/screens/TransitionDefaultSelectionChecksScreen.tsx +514 -0
  113. package/src/verification/screens/ViewportScrollAliasChecksScreen.tsx +303 -0
  114. package/src/verification/screens/conformanceBanner.ts +21 -0
  115. package/src/verification/screens/proofConsoleTap.ts +18 -0
  116. package/src/verification.ts +47 -0
  117. package/src/web.ts +98 -0
@@ -0,0 +1,303 @@
1
+ // U7i useViewportScroll device checks: catalog useTransform-with-useLayoutEffect on the
2
+ // public path. iOS has no tap injection, so the screen self-drives. Discriminators (Decision
3
+ // 86 analog of 77/82): the alias is exported and a container-less call refuses with the
4
+ // named viewport message (F1 — shipping the name is not a viewport). The catalog observable
5
+ // (scrollY → opacity) uses the standing named-container substitution (useScroll({ container })
6
+ // + useTransform). Host window-scroll is the web e2e.
7
+
8
+ import { useCallback, useEffect, useRef, useState } from 'react'
9
+ import { StyleSheet, Text, View } from 'react-native'
10
+ import Animated, { scrollTo, useAnimatedRef } from 'react-native-reanimated'
11
+ import { scheduleOnUI } from 'react-native-worklets'
12
+ import { MotionRoot } from '../../native/motion/MotionRoot'
13
+ import { MotionView } from '../../native/motion/MotionView'
14
+ import { ambientNativeSeverity } from '../../native/motion/severity'
15
+ import { useScroll } from '../../native/motion/useScroll'
16
+ import { useViewportScroll } from '../../native/motion/useViewportScroll'
17
+ import { useMotionValueEvent, useTransform } from '../../native/motion/valueHooks'
18
+ import { armProofConsoleTap } from './proofConsoleTap'
19
+
20
+ const ROW_ALIAS = 'container-less useViewportScroll refuses with the named viewport message'
21
+ const ROW_TRACK = 'named-container useScroll + useTransform: opacity drops on scroll'
22
+ const ROW_CLEAN = 'clean run: only the expected viewport refusal'
23
+ const ROWS = [ROW_ALIAS, ROW_TRACK, ROW_CLEAN] as const
24
+
25
+ const T_ALIAS = 400
26
+ const T_SCROLL = 900
27
+ const T_SAMPLE = 2200
28
+ const T_CLEAN = 2600
29
+ const SCROLL_Y = 180
30
+ const OPACITY_RANGE = [0, 200] as const
31
+
32
+ type ScrollHost = {
33
+ readonly scrollTo?: (args: { readonly y: number; readonly animated?: boolean }) => void
34
+ }
35
+
36
+ function driveNamedContainerScroll(
37
+ ref: ReturnType<typeof useAnimatedRef<Animated.ScrollView>>,
38
+ y: number,
39
+ ): void {
40
+ // Reanimated scrollTo(animated=false) and Android programmatic scrollTo without
41
+ // animation skip onScroll, so useScroll never sees the offset. Host
42
+ // scrollTo({ animated: true }) emits the native events the UI handler is bound
43
+ // to. iOS has no tap injection — this is the self-drive (Decision 86 analog).
44
+ const host = ref.current as ScrollHost | number | null | undefined
45
+ if (
46
+ host !== null &&
47
+ host !== undefined &&
48
+ typeof host === 'object' &&
49
+ typeof host.scrollTo === 'function'
50
+ ) {
51
+ host.scrollTo({ y, animated: true })
52
+ return
53
+ }
54
+ scheduleOnUI(() => {
55
+ 'worklet'
56
+ scrollTo(ref, 0, y, true)
57
+ })
58
+ }
59
+
60
+ interface RowResult {
61
+ readonly pass: boolean
62
+ readonly detail: string
63
+ }
64
+
65
+ function isViewportRefusal(message: string): boolean {
66
+ return /no window viewport analog|requires a container ref to a scrollable source/i.test(message)
67
+ }
68
+
69
+ function AliasRefusalProbe(): null {
70
+ useViewportScroll()
71
+ return null
72
+ }
73
+
74
+ function ScrollOpacityStage(props: {
75
+ readonly onOpacity: (value: number) => void
76
+ readonly onScroll: (value: number) => void
77
+ readonly scrollRef: ReturnType<typeof useAnimatedRef<Animated.ScrollView>>
78
+ }) {
79
+ const { scrollY } = useScroll({ container: props.scrollRef })
80
+ const opacity = useTransform(scrollY, [OPACITY_RANGE[0], OPACITY_RANGE[1]], [1, 0])
81
+ useMotionValueEvent(opacity, 'change', (value: number) => {
82
+ props.onOpacity(value)
83
+ })
84
+ useMotionValueEvent(scrollY, 'change', (value: number) => {
85
+ props.onScroll(value)
86
+ })
87
+ return (
88
+ <Animated.ScrollView
89
+ ref={props.scrollRef}
90
+ style={styles.scroller}
91
+ scrollEventThrottle={16}
92
+ accessibilityLabel="u7i-viewport-scroll-scroller"
93
+ >
94
+ <View style={styles.scrollContent}>
95
+ <MotionView
96
+ style={[styles.box, { opacity }]}
97
+ accessibilityLabel="u7i-viewport-scroll-box"
98
+ />
99
+ </View>
100
+ </Animated.ScrollView>
101
+ )
102
+ }
103
+
104
+ export function ViewportScrollAliasChecksScreen() {
105
+ const severity = ambientNativeSeverity()
106
+ const scrollRef = useAnimatedRef<Animated.ScrollView>()
107
+ const [stage, setStage] = useState('boot')
108
+ const [rows, setRows] = useState<Partial<Record<(typeof ROWS)[number], RowResult>>>({})
109
+ const [opacityNow, setOpacityNow] = useState(1)
110
+ const [scrollNow, setScrollNow] = useState(0)
111
+ const [probeOn, setProbeOn] = useState(true)
112
+
113
+ const reportsRef = useRef<string[]>([])
114
+ const opacityRef = useRef(1)
115
+ const scrollYRef = useRef(0)
116
+ const restoreTapRef = useRef<null | (() => void)>(null)
117
+ if (restoreTapRef.current === null) {
118
+ restoreTapRef.current = armProofConsoleTap(reportsRef.current, (message) =>
119
+ /motion|useScroll|viewport|container|animate/i.test(message),
120
+ )
121
+ }
122
+
123
+ const finalize = (id: (typeof ROWS)[number], pass: boolean, detail: string): void => {
124
+ setRows((previous) => ({ ...previous, [id]: { pass, detail } }))
125
+ }
126
+
127
+ const onOpacity = useCallback((value: number): void => {
128
+ opacityRef.current = value
129
+ setOpacityNow(value)
130
+ }, [])
131
+ const onScroll = useCallback((value: number): void => {
132
+ scrollYRef.current = value
133
+ setScrollNow(value)
134
+ }, [])
135
+
136
+ useEffect(() => {
137
+ const timers: ReturnType<typeof setTimeout>[] = []
138
+ const at = (ms: number, run: () => void): void => {
139
+ timers.push(setTimeout(run, ms))
140
+ }
141
+
142
+ at(T_ALIAS, () => {
143
+ const hit = reportsRef.current.some(isViewportRefusal)
144
+ finalize(
145
+ ROW_ALIAS,
146
+ hit,
147
+ hit
148
+ ? 'container-less alias reported the named viewport refusal'
149
+ : `no viewport refusal (reports=${reportsRef.current.length})`,
150
+ )
151
+ setProbeOn(false)
152
+ setStage('alias refusal sampled')
153
+ })
154
+
155
+ at(T_SCROLL, () => {
156
+ driveNamedContainerScroll(scrollRef, SCROLL_Y)
157
+ setStage(`scrolled to y=${SCROLL_Y}`)
158
+ })
159
+
160
+ at(T_SAMPLE, () => {
161
+ const opacity = opacityRef.current
162
+ const y = scrollYRef.current
163
+ const pass = y >= 80 && opacity < 0.75
164
+ finalize(
165
+ ROW_TRACK,
166
+ pass,
167
+ pass
168
+ ? `scrollY=${y.toFixed(1)} opacity=${opacity.toFixed(3)} (named container)`
169
+ : `scrollY=${y.toFixed(1)} opacity=${opacity.toFixed(3)} — expected scroll≥80 and opacity<0.75`,
170
+ )
171
+ setStage(pass ? 'track row finalized' : 'track row finalized (FAIL)')
172
+ })
173
+
174
+ at(T_CLEAN, () => {
175
+ const unexpected = reportsRef.current.filter((message) => !isViewportRefusal(message))
176
+ const expected = reportsRef.current.filter(isViewportRefusal)
177
+ finalize(
178
+ ROW_CLEAN,
179
+ unexpected.length === 0,
180
+ unexpected.length === 0
181
+ ? `0 unexpected; ${expected.length} expected viewport refusal(s)`
182
+ : `${unexpected.length} unexpected: ${unexpected.map((message) => message.slice(0, 80)).join(' | ')}`,
183
+ )
184
+ setStage('done')
185
+ })
186
+
187
+ return () => {
188
+ for (const timer of timers) clearTimeout(timer)
189
+ restoreTapRef.current?.()
190
+ restoreTapRef.current = null
191
+ }
192
+ }, [scrollRef])
193
+
194
+ const done = ROWS.every((id) => rows[id] !== undefined)
195
+ const failing = ROWS.filter((id) => rows[id] !== undefined && !rows[id]!.pass)
196
+ const verdict = !done ? 'RUNNING' : failing.length === 0 ? 'PASS' : 'FAIL'
197
+ const passed = Object.keys(rows).length - failing.length
198
+
199
+ return (
200
+ <MotionRoot>
201
+ <View style={styles.scroll}>
202
+ <View style={styles.container}>
203
+ <Text style={styles.title}>U7i viewport-scroll alias checks</Text>
204
+ <Text style={styles.subtitle}>
205
+ catalog scrollY→opacity + named-container substitution ({severity} severity)
206
+ </Text>
207
+ <View
208
+ style={[
209
+ styles.banner,
210
+ verdict === 'PASS' ? styles.pass : verdict === 'FAIL' ? styles.fail : styles.running,
211
+ ]}
212
+ >
213
+ <Text style={styles.bannerText}>{verdict}</Text>
214
+ </View>
215
+ <Text style={styles.tally}>
216
+ {done
217
+ ? `${passed} PASS / ${failing.length} FAIL of ${ROWS.length} rows`
218
+ : `${Object.keys(rows).length}/${ROWS.length} rows complete — RUNNING`}
219
+ </Text>
220
+ <Text style={styles.tallyDetail}>
221
+ {done
222
+ ? failing.length === 0
223
+ ? 'no failing rows'
224
+ : `FAILING: ${failing.join(' | ')}`
225
+ : `stage: ${stage}`}
226
+ </Text>
227
+ <Text style={styles.status}>
228
+ y={scrollNow.toFixed(1)} · opacity={opacityNow.toFixed(3)} · {severity}
229
+ </Text>
230
+
231
+ {probeOn ? <AliasRefusalProbe /> : null}
232
+ <ScrollOpacityStage scrollRef={scrollRef} onOpacity={onOpacity} onScroll={onScroll} />
233
+
234
+ {ROWS.map((id) => {
235
+ const row = rows[id]
236
+ return (
237
+ <View key={id} style={styles.row}>
238
+ <Text
239
+ style={[
240
+ styles.verdict,
241
+ row === undefined ? styles.pending : row.pass ? styles.ok : styles.bad,
242
+ ]}
243
+ >
244
+ {row === undefined ? '…' : row.pass ? 'PASS' : 'FAIL'}
245
+ </Text>
246
+ <View style={styles.rowBody}>
247
+ <Text style={styles.rowId}>{id}</Text>
248
+ <Text style={styles.rowDetail} numberOfLines={3}>
249
+ {row === undefined ? 'pending' : row.detail}
250
+ </Text>
251
+ </View>
252
+ </View>
253
+ )
254
+ })}
255
+ </View>
256
+ </View>
257
+ </MotionRoot>
258
+ )
259
+ }
260
+
261
+ const styles = StyleSheet.create({
262
+ scroll: { flex: 1, backgroundColor: '#0b0b12' },
263
+ container: { paddingVertical: 72, paddingHorizontal: 8 },
264
+ title: { color: '#fff', fontSize: 22, fontWeight: '700', textAlign: 'center' },
265
+ subtitle: { color: '#8a8aa0', fontSize: 12, marginTop: 6, textAlign: 'center' },
266
+ banner: {
267
+ alignSelf: 'center',
268
+ paddingHorizontal: 36,
269
+ paddingVertical: 10,
270
+ borderRadius: 10,
271
+ marginTop: 18,
272
+ marginBottom: 10,
273
+ },
274
+ pass: { backgroundColor: '#1d7a3e' },
275
+ fail: { backgroundColor: '#a32633' },
276
+ running: { backgroundColor: '#7a641d' },
277
+ bannerText: { color: '#fff', fontSize: 22, fontWeight: '800', letterSpacing: 2 },
278
+ tally: { color: '#e6e6f0', fontSize: 14, fontWeight: '700', textAlign: 'center' },
279
+ tallyDetail: { color: '#f87171', fontSize: 11, marginTop: 3, textAlign: 'center' },
280
+ status: {
281
+ color: '#c9c9d8',
282
+ fontSize: 11,
283
+ marginTop: 8,
284
+ textAlign: 'center',
285
+ fontFamily: 'Menlo',
286
+ },
287
+ scroller: { height: 160, marginTop: 14, backgroundColor: '#1a1a24', borderRadius: 12 },
288
+ scrollContent: { height: 520, padding: 12 },
289
+ box: {
290
+ width: 120,
291
+ height: 120,
292
+ backgroundColor: '#f9cb29',
293
+ borderRadius: 8,
294
+ },
295
+ row: { flexDirection: 'row', marginTop: 10 },
296
+ verdict: { width: 52, fontSize: 12, fontWeight: '800', paddingTop: 1 },
297
+ ok: { color: '#4ade80' },
298
+ bad: { color: '#f87171' },
299
+ pending: { color: '#8a8aa0' },
300
+ rowBody: { flex: 1 },
301
+ rowId: { color: '#e6e6f0', fontSize: 13, fontWeight: '600' },
302
+ rowDetail: { color: '#6f6f85', fontSize: 11, marginTop: 2 },
303
+ })
@@ -0,0 +1,21 @@
1
+ // The device conformance banner's VERDICT law (REQ-CONFORM-011; M2 r5 major 6e730d4c1a82):
2
+ // unassertable never counts as pass — any routed obligation makes the overall verdict FAIL,
3
+ // UNCONDITIONALLY. This holds even when parity is owned at another altitude:
4
+ // CMP-R7-cross-engine-parity is discharged by the web e2e + device proofs, but that parity does
5
+ // not execute in this suite, so it stays routed and still fails the banner. Styling may
6
+ // distinguish "failed assertion" from "routed obligation", but the VERDICT — what a proof
7
+ // screenshot claims — admits no qualified pass.
8
+
9
+ export type ConformanceBannerVerdict = 'PASS' | 'FAIL' | 'RUNNING'
10
+
11
+ export function conformanceBannerVerdict(state: {
12
+ readonly allDone: boolean
13
+ readonly rowsPass: boolean
14
+ readonly suitesClean: boolean
15
+ readonly routed: number
16
+ }): ConformanceBannerVerdict {
17
+ if (!state.allDone) return 'RUNNING'
18
+ if (!state.rowsPass || !state.suitesClean) return 'FAIL'
19
+ if (state.routed > 0) return 'FAIL'
20
+ return 'PASS'
21
+ }
@@ -0,0 +1,18 @@
1
+ // Proof-only console tap. Production MotionView reports typed refusals synchronously
2
+ // during render (resolveAnimateProp → consoleReporter). A parent useEffect tap is too
3
+ // late: children have already rendered. Arm during the parent's render body, before
4
+ // returning children.
5
+
6
+ export function armProofConsoleTap(sink: string[], keep: (message: string) => boolean): () => void {
7
+ const original = console.error
8
+ console.error = (...args: unknown[]) => {
9
+ for (const arg of args) {
10
+ const message = arg instanceof Error ? arg.message : typeof arg === 'string' ? arg : null
11
+ if (message !== null && keep(message)) sink.push(message)
12
+ }
13
+ original.apply(console, args)
14
+ }
15
+ return () => {
16
+ console.error = original
17
+ }
18
+ }
@@ -0,0 +1,47 @@
1
+ // Engine-intrinsic verification surface (REQ-EXHARNESS-010,
2
+ // specs/DOGFOOD-MIGRATION-BUILD-PACKET.md FLAG 1): the probes and deterministic check screens
3
+ // that prove the engine ON DEVICE live with the engine — they are engine code, exempt from the
4
+ // consumer-isolation ban only because they live here, never because an app path is allowlisted.
5
+ // This entry exists for the proof-harness app shell to mount them; it is NOT the product surface
6
+ // and nothing here may appear in a consumer example (that is the escape hatch the dogfood law
7
+ // forbids). Native-only by design: verification drives the worklet runtime, so there is no web
8
+ // route for this subpath.
9
+
10
+ export { ChoreographyGalleryScreen } from './verification/screens/ChoreographyGalleryScreen'
11
+ export { ColorBindingChecksScreen } from './verification/screens/ColorBindingChecksScreen'
12
+ export { ConformanceScreen } from './verification/screens/ConformanceScreen'
13
+ export { ContentionProbeScreen } from './verification/screens/ContentionProbeScreen'
14
+ export { DriverSmokeScreen } from './verification/screens/DriverSmokeScreen'
15
+ export { BooleanAnimateChecksScreen } from './verification/screens/BooleanAnimateChecksScreen'
16
+ export { DynamicDragConfigChecksScreen } from './verification/screens/DynamicDragConfigChecksScreen'
17
+ export { GestureChecksScreen } from './verification/screens/GestureChecksScreen'
18
+ export { InstantTransitionChecksScreen } from './verification/screens/InstantTransitionChecksScreen'
19
+ export { LayoutAnimationStartChecksScreen } from './verification/screens/LayoutAnimationStartChecksScreen'
20
+ export { LayoutChecksScreen } from './verification/screens/LayoutChecksScreen'
21
+ export { LayoutCommitSpikeScreen } from './verification/screens/LayoutCommitSpikeScreen'
22
+ export { MotionViewChecksScreen } from './verification/screens/MotionViewChecksScreen'
23
+ export { PresenceChecksScreen } from './verification/screens/PresenceChecksScreen'
24
+ export { ReducedMotionChecksScreen } from './verification/screens/ReducedMotionChecksScreen'
25
+ export { RestThresholdChecksScreen } from './verification/screens/RestThresholdChecksScreen'
26
+ export { ScaleCorrectorChecksScreen } from './verification/screens/ScaleCorrectorChecksScreen'
27
+ export { ViewportScrollAliasChecksScreen } from './verification/screens/ViewportScrollAliasChecksScreen'
28
+ export { FrameDataChecksScreen } from './verification/screens/FrameDataChecksScreen'
29
+ export { ArcPathChecksScreen } from './verification/screens/ArcPathChecksScreen'
30
+ export { DurationOnlyTweenChecksScreen } from './verification/screens/DurationOnlyTweenChecksScreen'
31
+ export { CompletionChecksScreen } from './verification/screens/CompletionChecksScreen'
32
+ export { TransitionDefaultSelectionChecksScreen } from './verification/screens/TransitionDefaultSelectionChecksScreen'
33
+ export { SharedLayoutContinuityChecksScreen } from './verification/screens/SharedLayoutContinuityChecksScreen'
34
+ export { SharedLayoutCrossfadeChecksScreen } from './verification/screens/SharedLayoutCrossfadeChecksScreen'
35
+ export { LayoutIdentityWorkletProbe } from './verification/probe/LayoutIdentityWorkletProbe'
36
+ export { WorkletParityProbe } from './verification/probe/WorkletParityProbe'
37
+ // Seal-r16 F2: proof-only settle/layout-callback witnesses — NOT on the consumer-facing package
38
+ // root (BRIEF Motion-shaped public-API law). The dogfood purity ban still forbids this subpath
39
+ // inside apps/mobile/src/**; the proof gallery reads JS-side last-pushed cells instead, and
40
+ // isolation/verification screens may import these readers here.
41
+ export {
42
+ armUiProofWitnesses,
43
+ lastPushedProofLayoutCallbackWitness,
44
+ lastPushedProofSettleEmissionCount,
45
+ uiProofLayoutCallbackWitness,
46
+ uiProofSettleEmissionCount,
47
+ } from './native/driver/workletDriver'
package/src/web.ts ADDED
@@ -0,0 +1,98 @@
1
+ 'use client'
2
+ // Web route of the single public import (REQ-UNIVERSAL-001/REQ-WEB-010): re-export the web
3
+ // driver-peer. Web bundlers land here via the `browser`/`import`/`default` exports conditions;
4
+ // the shim (not this file) owns normalization and the motion/react binding.
5
+ //
6
+ // Explicit Native Motion exports below exclude shim-only helpers such as `createView`. Web remains
7
+ // a superset while the native namespace gate still requires every portable native name. Pinned
8
+ // additions are re-exported explicitly by the web driver so each one remains census-classified.
9
+
10
+ export type {
11
+ DragControlOptions,
12
+ DragControlsHandle,
13
+ DragInfo,
14
+ TapCallback,
15
+ TapInfo,
16
+ MotionTargetProps,
17
+ Target,
18
+ TransformProperties,
19
+ TransformTemplate,
20
+ Transition,
21
+ TransitionType,
22
+ } from '@unrulysystems/native-motion-core'
23
+ // Product dual-authority release helpers — key parity with the native entry.
24
+ export { absoluteDragOrigin, selectReleaseTarget } from '@unrulysystems/native-motion-core'
25
+ export {
26
+ AnimatePresence,
27
+ AnimateSharedLayout,
28
+ Image,
29
+ LazyMotion,
30
+ LayoutGroup,
31
+ LayoutScrollOffsetProvider,
32
+ createLayoutScrollOffsetRef,
33
+ recordLayoutScrollOffsetFromEvent,
34
+ MotionConfig,
35
+ MotionLengthLayoutProvider,
36
+ MotionRoot,
37
+ MotionValue,
38
+ Reorder,
39
+ disableInstantTransitions,
40
+ domAnimation,
41
+ domMax,
42
+ motion,
43
+ m,
44
+ mix,
45
+ addScaleCorrector,
46
+ useIsPresent,
47
+ useMotionValue,
48
+ useMotionValueEvent,
49
+ usePresence,
50
+ usePresenceData,
51
+ animate,
52
+ useAnimate,
53
+ useAnimateMini,
54
+ useAnimationControls,
55
+ useCycle,
56
+ type Cycle,
57
+ type CycleState,
58
+ type AnimateFn,
59
+ type AnimationPlaybackControls,
60
+ type AnimationScope,
61
+ useDragControls,
62
+ DragControls,
63
+ useInView,
64
+ useInstantTransition,
65
+ useMotionTemplate,
66
+ useReducedMotion,
67
+ useScroll,
68
+ useViewportScroll,
69
+ useSpring,
70
+ useTransform,
71
+ useTime,
72
+ useVelocity,
73
+ frameData,
74
+ arc,
75
+ stagger,
76
+ Text,
77
+ View,
78
+ wrap,
79
+ type ImageProps,
80
+ type LayoutGroupInherit,
81
+ type LayoutGroupProps,
82
+ type LayoutScrollOffset,
83
+ type LayoutScrollOffsetProviderProps,
84
+ type LayoutScrollOffsetRef,
85
+ type MotionConfigProps,
86
+ type MotionConfigTransition,
87
+ type MotionLengthLayoutProviderProps,
88
+ type MotionRootProps,
89
+ type ReducedMotionConfig,
90
+ type ScrollMotionValues,
91
+ type SpringValueOptions,
92
+ type TextProps,
93
+ type TransformOptions,
94
+ type UseScrollOptions,
95
+ type ViewProps,
96
+ type FrameData,
97
+ type ArcOptions,
98
+ } from '@unrulysystems/native-motion-web'