react-native-smooth-clip-view 0.2.9 → 0.3.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 (130) hide show
  1. package/README.md +60 -21
  2. package/android/build.gradle +6 -2
  3. package/android/proguard-rules.pro +3 -3
  4. package/android/src/main/cpp/SmoothClipAndroid.h +10 -0
  5. package/android/src/main/cpp/SmoothClipBindings.cpp +890 -4
  6. package/android/src/main/cpp/SmoothClipRegistry.cpp +1056 -44
  7. package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +265 -0
  8. package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +21 -0
  9. package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +283 -0
  10. package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +371 -18
  11. package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +138 -24
  12. package/cpp/SmoothClipAnimationCurve.h +151 -122
  13. package/cpp/SmoothClipRegistry.h +95 -3
  14. package/cpp/SmoothClipSharedGeometry.h +146 -7
  15. package/cpp/SmoothClipVelocityTracker.h +13 -9
  16. package/ios/SmoothClipGeometry.h +184 -6
  17. package/ios/SmoothClipRegistry.mm +1028 -22
  18. package/ios/SmoothClipRegistrySnapshot.h +13 -0
  19. package/ios/SmoothClipTurboModule.cpp +857 -2
  20. package/ios/SmoothClipTurboModule.h +310 -0
  21. package/ios/SmoothClipView.mm +714 -183
  22. package/ios/SmoothClipViewRegistry.h +1 -0
  23. package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  24. package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  25. package/lib/module/NativeSmoothClipModule.js.map +1 -1
  26. package/lib/module/SmoothClipView.ios.js +22 -6
  27. package/lib/module/SmoothClipView.ios.js.map +1 -1
  28. package/lib/module/SmoothClipView.js +1 -46
  29. package/lib/module/SmoothClipView.js.map +1 -1
  30. package/lib/module/SmoothClipViewNativeComponent.ts +27 -1
  31. package/lib/module/capabilities.js +4 -0
  32. package/lib/module/capabilities.js.map +1 -0
  33. package/lib/module/capabilities.native.js +36 -0
  34. package/lib/module/capabilities.native.js.map +1 -0
  35. package/lib/module/capabilityTypes.js +11 -0
  36. package/lib/module/capabilityTypes.js.map +1 -0
  37. package/lib/module/driverState.js +0 -28
  38. package/lib/module/driverState.js.map +1 -1
  39. package/lib/module/drivers.js +1 -281
  40. package/lib/module/drivers.js.map +1 -1
  41. package/lib/module/drivers.native.js +263 -63
  42. package/lib/module/drivers.native.js.map +1 -1
  43. package/lib/module/geometry.js +147 -17
  44. package/lib/module/geometry.js.map +1 -1
  45. package/lib/module/groupDriverTypes.js +4 -0
  46. package/lib/module/groupDriverTypes.js.map +1 -0
  47. package/lib/module/groupDrivers.android.js +4 -0
  48. package/lib/module/groupDrivers.android.js.map +1 -0
  49. package/lib/module/groupDrivers.ios.js +4 -0
  50. package/lib/module/groupDrivers.ios.js.map +1 -0
  51. package/lib/module/groupDrivers.js +4 -0
  52. package/lib/module/groupDrivers.js.map +1 -0
  53. package/lib/module/groupDrivers.native.js +799 -0
  54. package/lib/module/groupDrivers.native.js.map +1 -0
  55. package/lib/module/index.js +3 -2
  56. package/lib/module/index.js.map +1 -1
  57. package/lib/module/presentationProtocol.js +15 -0
  58. package/lib/module/presentationProtocol.js.map +1 -0
  59. package/lib/typescript/src/NativeSmoothClipModule.d.ts +25 -0
  60. package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -1
  61. package/lib/typescript/src/SmoothClipView.d.ts +2 -10
  62. package/lib/typescript/src/SmoothClipView.d.ts.map +1 -1
  63. package/lib/typescript/src/SmoothClipView.ios.d.ts +133 -2
  64. package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -1
  65. package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +8 -0
  66. package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
  67. package/lib/typescript/src/capabilities.d.ts +3 -0
  68. package/lib/typescript/src/capabilities.d.ts.map +1 -0
  69. package/lib/typescript/src/capabilities.native.d.ts +3 -0
  70. package/lib/typescript/src/capabilities.native.d.ts.map +1 -0
  71. package/lib/typescript/src/capabilityTypes.d.ts +10 -0
  72. package/lib/typescript/src/capabilityTypes.d.ts.map +1 -0
  73. package/lib/typescript/src/driverState.d.ts +1 -6
  74. package/lib/typescript/src/driverState.d.ts.map +1 -1
  75. package/lib/typescript/src/driverTypes.d.ts +25 -11
  76. package/lib/typescript/src/driverTypes.d.ts.map +1 -1
  77. package/lib/typescript/src/drivers.d.ts +2 -4
  78. package/lib/typescript/src/drivers.d.ts.map +1 -1
  79. package/lib/typescript/src/drivers.native.d.ts.map +1 -1
  80. package/lib/typescript/src/geometry.d.ts +36 -2
  81. package/lib/typescript/src/geometry.d.ts.map +1 -1
  82. package/lib/typescript/src/groupDriverTypes.d.ts +66 -0
  83. package/lib/typescript/src/groupDriverTypes.d.ts.map +1 -0
  84. package/lib/typescript/src/groupDrivers.android.d.ts +2 -0
  85. package/lib/typescript/src/groupDrivers.android.d.ts.map +1 -0
  86. package/lib/typescript/src/groupDrivers.d.ts +2 -0
  87. package/lib/typescript/src/groupDrivers.d.ts.map +1 -0
  88. package/lib/typescript/src/groupDrivers.ios.d.ts +2 -0
  89. package/lib/typescript/src/groupDrivers.ios.d.ts.map +1 -0
  90. package/lib/typescript/src/groupDrivers.native.d.ts +4 -0
  91. package/lib/typescript/src/groupDrivers.native.d.ts.map +1 -0
  92. package/lib/typescript/src/index.d.ts +6 -3
  93. package/lib/typescript/src/index.d.ts.map +1 -1
  94. package/lib/typescript/src/presentationProtocol.d.ts +4 -0
  95. package/lib/typescript/src/presentationProtocol.d.ts.map +1 -0
  96. package/package.json +10 -11
  97. package/src/NativeSmoothClipModule.ts +275 -0
  98. package/src/SmoothClipView.ios.tsx +30 -11
  99. package/src/SmoothClipView.tsx +2 -76
  100. package/src/SmoothClipViewNativeComponent.ts +27 -1
  101. package/src/capabilities.native.ts +69 -0
  102. package/src/capabilities.ts +2 -0
  103. package/src/capabilityTypes.ts +17 -0
  104. package/src/driverState.ts +1 -41
  105. package/src/driverTypes.ts +42 -11
  106. package/src/drivers.native.ts +824 -124
  107. package/src/drivers.ts +2 -423
  108. package/src/geometry.ts +231 -27
  109. package/src/groupDriverTypes.ts +117 -0
  110. package/src/groupDrivers.android.ts +1 -0
  111. package/src/groupDrivers.ios.ts +1 -0
  112. package/src/groupDrivers.native.ts +1189 -0
  113. package/src/groupDrivers.ts +1 -0
  114. package/src/index.ts +30 -2
  115. package/src/presentationProtocol.ts +28 -0
  116. package/lib/module/SmoothClipView.web.js +0 -54
  117. package/lib/module/SmoothClipView.web.js.map +0 -1
  118. package/lib/module/index.web.js +0 -8
  119. package/lib/module/index.web.js.map +0 -1
  120. package/lib/module/webClipPath.js +0 -25
  121. package/lib/module/webClipPath.js.map +0 -1
  122. package/lib/typescript/src/SmoothClipView.web.d.ts +0 -10
  123. package/lib/typescript/src/SmoothClipView.web.d.ts.map +0 -1
  124. package/lib/typescript/src/index.web.d.ts +0 -9
  125. package/lib/typescript/src/index.web.d.ts.map +0 -1
  126. package/lib/typescript/src/webClipPath.d.ts +0 -7
  127. package/lib/typescript/src/webClipPath.d.ts.map +0 -1
  128. package/src/SmoothClipView.web.tsx +0 -66
  129. package/src/index.web.ts +0 -23
  130. package/src/webClipPath.ts +0 -30
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useRef","cancelAnimation","cancelReanimatedAnimation","Easing","ReduceMotion","useAnimatedReaction","useSharedValue","withSpring","withTiming","scheduleOnRN","scheduleOnUI","allocateDriverId","attachDriverState","createDriverState","deliverDriverCompletion","detachDriverState","finishDriverAnimation","getDriverState","setDriverState","snapshotDriverViews","createClipPresentation","clipPresentationEquals","isFiniteClipPresentation","createReactRequest","rejectDriverRequests","resolveReactRequest","toReanimatedReduceMotion","value","Always","Never","System","animationIsFinite","animation","from","undefined","type","Number","isFinite","duration","controlPoints","every","mass","stiffness","damping","initialVelocity","previousOffset","frames","length","frame","offset","presentation","interpolatePresentation","to","progress","mix","start","end","clip","x","y","width","height","radius","contentTranslateX","contentTranslateY","finishFallback","driverId","animationId","finished","useSmoothClipDriver","initialValue","options","initialPresentation","activeAnimationId","nextAnimationId","latestTarget","animationStart","animationProgress","keyframes","callbackRef","onAnimationComplete","driverRef","current","upperIndex","lower","upper","span","localProgress","Math","min","max","reduceMotion","beginOnUI","setOnUI","next","animateOnUI","onComplete","x1","y1","x2","y2","easing","bezier","configuredVelocity","velocity","linear","cancelOnUI","behavior","setScalarsOnUI","driver","kind","ui","beginInteraction","set","setScalars","animateTo","cancel","react","requestId","promise","result","currentDriver","state"],"sourceRoot":"../../src","sources":["drivers.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useSmoothClipDriver"],"sourceRoot":"../../src","sources":["drivers.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAAQ,qBAAkB","ignoreList":[]}
@@ -1,18 +1,18 @@
1
1
  "use strict";
2
2
 
3
- // The shared NATIVE driver: iOS and Android both execute this file, via the
3
+ // The shared native driver: iOS and Android both execute this file, via the
4
4
  // one-line re-exports in drivers.ios.ts / drivers.android.ts that Metro's
5
5
  // platform resolution picks up from index.ts's `./drivers` import. Only the
6
- // `./smoothClipNative` import below is platform-split. drivers.ts (no
7
- // suffix) is the web/Reanimated fallback, not this driver's sibling.
6
+ // `./smoothClipNative` import below is platform-split.
8
7
  import { useEffect, useRef } from 'react';
9
8
  import { Platform } from 'react-native';
10
9
  import { useSharedValue } from 'react-native-reanimated';
11
10
  import { isRNRuntime, scheduleOnRN, scheduleOnUI } from 'react-native-worklets';
12
11
  import NativeSmoothClipModule from './smoothClipNative';
12
+ import { getSmoothClipCapabilities } from './capabilities';
13
13
  import { allocateDriverId, attachDriverState, createDriverState, detachDriverState, getDriverState, setDriverState } from "./driverState.js";
14
14
  import { completeNativeAnimation, synchronizeNativeCompletion } from "./nativeCompletion.js";
15
- import { clipPresentationEquals, createClipPresentation, isFiniteClipPresentation } from "./geometry.js";
15
+ import { canonicalizeClipPresentation, clipPresentationEquals, createClipPresentation, isFiniteClipPresentation } from "./geometry.js";
16
16
  import { createReactRequest, rejectDriverRequests, resolveReactRequest } from "./reactRequests.js";
17
17
  const INTERACTIVE = 0;
18
18
  const NATIVE = 1;
@@ -23,6 +23,8 @@ const NATIVE = 1;
23
23
  // stamp there is a wasted native _getAnimationTimestamp() call per animateTo.
24
24
  // Resolved once at module scope; the worklet captures the primitive.
25
25
  const NEEDS_START_STAMP = Platform.OS === 'android';
26
+ const PRESENTATION_PROTOCOL_VERSION = getSmoothClipCapabilities().presentationProtocolVersion;
27
+ const NativeSmoothClipModuleV2 = NativeSmoothClipModule;
26
28
 
27
29
  // Widened like the animate* functions below: one trailing argument beyond the
28
30
  // TurboModule spec — whether this write should record an `'inherit'` velocity
@@ -46,15 +48,27 @@ const animateKeyframesHostFunction = NativeSmoothClipModule.animateKeyframes;
46
48
  const rejectAnimationHostFunction = NativeSmoothClipModule.rejectAnimation;
47
49
  const cancelAnimationHostFunction = NativeSmoothClipModule.cancelAnimation;
48
50
  const destroyDriverHostFunction = NativeSmoothClipModule.destroyDriver;
51
+ const setPresentationV2HostFunction = NativeSmoothClipModuleV2.setClipPresentationV2;
52
+ const beginInteractionV2HostFunction = NativeSmoothClipModuleV2.beginInteractionV2;
53
+ const snapshotCurrentV2HostFunction = NativeSmoothClipModuleV2.snapshotCurrentV2;
54
+ const animateTimingV2HostFunction = NativeSmoothClipModuleV2.animateTimingV2;
55
+ const animateSpringV2HostFunction = NativeSmoothClipModuleV2.animateSpringV2;
56
+ const animateKeyframesV2HostFunction = NativeSmoothClipModuleV2.animateKeyframesV2;
57
+ const animateTimingFromV2HostFunction = NativeSmoothClipModuleV2.animateTimingFromV2;
58
+ const animateSpringFromV2HostFunction = NativeSmoothClipModuleV2.animateSpringFromV2;
59
+ const animateKeyframesFromV2HostFunction = NativeSmoothClipModuleV2.animateKeyframesFromV2;
60
+ const cancelAnimationV2HostFunction = NativeSmoothClipModuleV2.cancelAnimationV2;
49
61
 
50
- // Workaround for react-native-worklets 0.10: the RN-side serialization cache
62
+ // Workaround for react-native-worklets 0.10.0 (fixed upstream in >=0.10.1,
63
+ // which drops the registry/proxy design; kept while the peer range still
64
+ // allows 0.10.0 consumers): the RN-side serialization cache
51
65
  // hands out one remote-function registry id per function forever, but the
52
66
  // registry entry is deleted as soon as any transient UI-side proxy of that
53
67
  // function is garbage collected. A later scheduleOnRN for the same function
54
68
  // then reads `undefined` from the registry and aborts in Value::getObject.
55
69
  // Pinning one UI-side reference for the app lifetime keeps the proxy — and
56
- // with it the registry entry — alive. Remove once worklets decouples registry
57
- // cleanup from proxy lifetime.
70
+ // with it the registry entry — alive. Remove once the peer range requires
71
+ // worklets >=0.10.1.
58
72
  scheduleOnUI(resolver => {
59
73
  'worklet';
60
74
 
@@ -70,7 +84,7 @@ function reduceMotionCode(value) {
70
84
  return 0;
71
85
  }
72
86
  }
73
- function animationIsFinite(animation) {
87
+ function animationIsFinite(animation, strictV2) {
74
88
  'worklet';
75
89
 
76
90
  if (animation.from !== undefined && !isFiniteClipPresentation(animation.from)) {
@@ -80,29 +94,53 @@ function animationIsFinite(animation) {
80
94
  }
81
95
  if (animation.type === 'timing') {
82
96
  const [x1,, x2] = animation.controlPoints;
83
- return Number.isFinite(animation.duration) && animation.controlPoints.every(Number.isFinite) &&
97
+ return Number.isFinite(animation.duration) && (!strictV2 || animation.duration >= 0) && animation.controlPoints.every(Number.isFinite) && (
84
98
  // A cubic-bezier easing is only defined for x within [0,1] (the CSS /
85
99
  // CoreAnimation / Reanimated Easing.bezier contract). Out-of-range x
86
100
  // makes the Android parameter solve meaningless while CoreAnimation
87
101
  // silently clamps — reject like any other invalid input instead of
88
102
  // diverging per platform.
89
- x1 >= 0 && x1 <= 1 && x2 >= 0 && x2 <= 1;
103
+ !strictV2 || x1 >= 0 && x1 <= 1 && x2 >= 0 && x2 <= 1);
90
104
  }
91
105
  if (animation.type === 'spring') {
92
- return [animation.mass ?? 1, animation.stiffness ?? 100, animation.damping ?? 10, animation.initialVelocity === 'inherit' ? 0 : animation.initialVelocity ?? 0].every(Number.isFinite);
106
+ const mass = animation.mass ?? 1;
107
+ const stiffness = animation.stiffness ?? 100;
108
+ const damping = animation.damping ?? 10;
109
+ const initialVelocity = animation.initialVelocity === 'inherit' ? 0 : animation.initialVelocity ?? 0;
110
+ return [mass, stiffness, damping, initialVelocity].every(Number.isFinite) && (!strictV2 || mass > 0 && stiffness > 0 && damping >= 0);
93
111
  }
94
112
  // Keyframe frames validate inside flattenFiniteKeyframes — one traversal
95
113
  // both checks and flattens, instead of walking every frame twice. The type
96
114
  // check is statically always-true for the TS union but load-bearing for JS
97
115
  // callers: an unrecognized type must reject here, or it would skip the
98
116
  // keyframe gate entirely and hand native a null frames array.
99
- return animation.type === 'keyframes';
117
+ return animation.type === 'keyframes' && (!strictV2 || animation.duration >= 0);
100
118
  }
101
119
  function presentationFromNative(values, fallback, offset = 0) {
102
120
  'worklet';
103
121
 
122
+ if (values.length >= offset + 12) {
123
+ const presentation = canonicalizeClipPresentation({
124
+ clip: {
125
+ x: values[offset],
126
+ y: values[offset + 1],
127
+ width: values[offset + 2],
128
+ height: values[offset + 3],
129
+ radius: 0,
130
+ topLeftRadius: values[offset + 4],
131
+ topRightRadius: values[offset + 5],
132
+ bottomRightRadius: values[offset + 6],
133
+ bottomLeftRadius: values[offset + 7],
134
+ curve: values[offset + 8] === 1 ? 'continuous' : 'circular'
135
+ },
136
+ contentTranslateX: values[offset + 9],
137
+ contentTranslateY: values[offset + 10],
138
+ contentScale: values[offset + 11]
139
+ });
140
+ return presentation ?? fallback;
141
+ }
104
142
  if (values.length < offset + 7) return fallback;
105
- const presentation = {
143
+ const presentation = canonicalizeClipPresentation({
106
144
  clip: {
107
145
  x: values[offset],
108
146
  y: values[offset + 1],
@@ -112,8 +150,33 @@ function presentationFromNative(values, fallback, offset = 0) {
112
150
  },
113
151
  contentTranslateX: values[offset + 5],
114
152
  contentTranslateY: values[offset + 6]
115
- };
116
- return isFiniteClipPresentation(presentation) ? presentation : fallback;
153
+ });
154
+ return presentation ?? fallback;
155
+ }
156
+ function curveCode(presentation) {
157
+ 'worklet';
158
+
159
+ return presentation.clip.curve === 'continuous' ? 1 : 0;
160
+ }
161
+ function isV1Compatible(presentation) {
162
+ 'worklet';
163
+
164
+ const clip = presentation.clip;
165
+ return clip.curve === 'circular' && clip.topLeftRadius === clip.radius && clip.topRightRadius === clip.radius && clip.bottomRightRadius === clip.radius && clip.bottomLeftRadius === clip.radius && presentation.contentScale === 1;
166
+ }
167
+ function springScaleIsProvablyPositive(start, target, animation) {
168
+ 'worklet';
169
+
170
+ if (start.contentScale === target.contentScale) return true;
171
+
172
+ // A zero-velocity critically/over-damped step is monotonic, so its sampled
173
+ // scale remains between two already-positive endpoints. Inherited or
174
+ // under-damped configurations can overshoot; callers must compile those
175
+ // plans to exact keyframes instead of risking a non-positive transform.
176
+ const mass = animation.mass ?? 1;
177
+ const stiffness = animation.stiffness ?? 100;
178
+ const damping = animation.damping ?? 10;
179
+ return animation.initialVelocity === 0 && damping * damping >= 4 * mass * stiffness;
117
180
  }
118
181
 
119
182
  // Validates and flattens the keyframe list in one traversal (the flat number
@@ -127,26 +190,44 @@ function flattenFiniteKeyframes(target, animation) {
127
190
  return null;
128
191
  }
129
192
  const values = [];
193
+ const canonicalFrames = [];
130
194
  let previousOffset = -1;
131
195
  for (const frame of animation.frames) {
132
196
  const {
133
- offset,
134
- presentation
197
+ offset
135
198
  } = frame;
136
- if (!Number.isFinite(offset) || offset < 0 || offset > 1 || offset <= previousOffset || !isFiniteClipPresentation(presentation)) {
199
+ const presentation = canonicalizeClipPresentation(frame.presentation);
200
+ if (!Number.isFinite(offset) || offset < 0 || offset > 1 || offset <= previousOffset || presentation === null || presentation.clip.curve !== target.clip.curve) {
137
201
  return null;
138
202
  }
139
203
  previousOffset = offset;
204
+ canonicalFrames.push(presentation);
140
205
  const {
141
206
  clip,
142
207
  contentTranslateX,
143
- contentTranslateY
208
+ contentTranslateY,
209
+ contentScale
144
210
  } = presentation;
145
- values.push(offset, clip.x, clip.y, clip.width, clip.height, clip.radius, contentTranslateX, contentTranslateY);
211
+ values.push(offset, clip.x, clip.y, clip.width, clip.height, clip.topLeftRadius, clip.topRightRadius, clip.bottomRightRadius, clip.bottomLeftRadius, curveCode(presentation), contentTranslateX, contentTranslateY, contentScale);
146
212
  }
147
- if (animation.frames[0]?.offset !== 0 || previousOffset !== 1 || !clipPresentationEquals(animation.frames[animation.frames.length - 1]?.presentation ?? null, target)) {
213
+ if (animation.frames[0]?.offset !== 0 || previousOffset !== 1 || !clipPresentationEquals(canonicalFrames[canonicalFrames.length - 1] ?? null, target)) {
148
214
  return null;
149
215
  }
216
+ return {
217
+ frames: values,
218
+ canonicalFrames
219
+ };
220
+ }
221
+ function flattenV1Keyframes(frames, offsets) {
222
+ 'worklet';
223
+
224
+ const values = [];
225
+ for (let index = 0; index < frames.length; index += 1) {
226
+ const presentation = frames[index];
227
+ const offset = offsets[index];
228
+ if (presentation === undefined || offset === undefined) continue;
229
+ values.push(offset, presentation.clip.x, presentation.clip.y, presentation.clip.width, presentation.clip.height, presentation.clip.radius, presentation.contentTranslateX, presentation.contentTranslateY);
230
+ }
150
231
  return values;
151
232
  }
152
233
  function uiOnly() {
@@ -155,7 +236,11 @@ function uiOnly() {
155
236
  throw new Error('[SmoothClipView] driver.ui methods must run on the UI runtime. Use driver.react from React code.');
156
237
  }
157
238
  export function useSmoothClipDriver(initialValue, options = {}) {
158
- const initialPresentation = 'clip' in initialValue ? initialValue : createClipPresentation(initialValue);
239
+ const requestedInitialPresentation = 'clip' in initialValue ? initialValue : createClipPresentation(initialValue);
240
+ const initialPresentation = canonicalizeClipPresentation(requestedInitialPresentation);
241
+ if (initialPresentation === null) {
242
+ throw new Error('[SmoothClipView] Initial presentation must be finite.');
243
+ }
159
244
  const presentation = useSharedValue(initialPresentation);
160
245
  const ownership = useSharedValue(INTERACTIVE);
161
246
  const suppressDeliveries = useSharedValue(0);
@@ -200,8 +285,9 @@ export function useSmoothClipDriver(initialValue, options = {}) {
200
285
  const beginOnUI = () => {
201
286
  'worklet';
202
287
 
203
- if (disposed.value !== 0) return presentation.value;
204
- const current = presentationFromNative(beginInteractionHostFunction(driverId), presentation.value);
288
+ const fallback = canonicalizeClipPresentation(presentation.value) ?? initialPresentation;
289
+ if (disposed.value !== 0) return fallback;
290
+ const current = presentationFromNative(PRESENTATION_PROTOCOL_VERSION === 2 && beginInteractionV2HostFunction ? beginInteractionV2HostFunction(driverId) : beginInteractionHostFunction(driverId), fallback);
205
291
  activeAnimationId.value = 0;
206
292
  ownership.value = INTERACTIVE;
207
293
  scalarsStale.value = 0;
@@ -211,20 +297,28 @@ export function useSmoothClipDriver(initialValue, options = {}) {
211
297
  const setOnUI = next => {
212
298
  'worklet';
213
299
 
214
- if (disposed.value !== 0 || !isFiniteClipPresentation(next)) return;
300
+ const canonical = canonicalizeClipPresentation(next);
301
+ if (disposed.value !== 0 || canonical === null) return;
215
302
  activeAnimationId.value = 0;
216
303
  ownership.value = INTERACTIVE;
217
304
  scalarsStale.value = 0;
218
305
  const {
219
306
  clip,
220
307
  contentTranslateX,
221
- contentTranslateY
222
- } = next;
308
+ contentTranslateY,
309
+ contentScale
310
+ } = canonical;
223
311
  // Always records: only the per-frame setScalars hot path is gated by
224
312
  // velocityTracking. set() already pays full validation and a SharedValue
225
313
  // seed per call, so the sample recording is noise here.
226
- setPresentationHostFunction(driverId, clip.x, clip.y, clip.width, clip.height, clip.radius, contentTranslateX, contentTranslateY, true, false);
227
- seedPresentation(next);
314
+ if (PRESENTATION_PROTOCOL_VERSION === 2 && setPresentationV2HostFunction) {
315
+ setPresentationV2HostFunction(driverId, clip.x, clip.y, clip.width, clip.height, clip.topLeftRadius, clip.topRightRadius, clip.bottomRightRadius, clip.bottomLeftRadius, curveCode(canonical), contentTranslateX, contentTranslateY, contentScale, true, false, true);
316
+ } else if (isV1Compatible(canonical)) {
317
+ setPresentationHostFunction(driverId, clip.x, clip.y, clip.width, clip.height, clip.radius, contentTranslateX, contentTranslateY, true, false);
318
+ } else {
319
+ return;
320
+ }
321
+ seedPresentation(canonical);
228
322
  };
229
323
  const setScalarsOnUI = (x, y, width, height, radius, contentTranslateX, contentTranslateY, overridePendingAnimation = false, forceRecordVelocity = false) => {
230
324
  'worklet';
@@ -251,6 +345,25 @@ export function useSmoothClipDriver(initialValue, options = {}) {
251
345
  if (scalarsStale.value === 0) scalarsStale.value = 1;
252
346
  setPresentationHostFunction(driverId, x, y, width, height, radius, contentTranslateX, contentTranslateY, true, overridePendingAnimation, recordVelocity);
253
347
  };
348
+ const setPresentationScalarsOnUI = (x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius, nextCurveCode, contentTranslateX, contentTranslateY, contentScale, overridePendingAnimation = false, forceRecordVelocity = false) => {
349
+ 'worklet';
350
+
351
+ const values = [x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius, nextCurveCode, contentTranslateX, contentTranslateY, contentScale];
352
+ if (disposed.value !== 0 || !values.every(Number.isFinite) || nextCurveCode !== 0 && nextCurveCode !== 1 || contentScale <= 0) {
353
+ return;
354
+ }
355
+ const recordVelocity = forceRecordVelocity || velocityTracking;
356
+ if (PRESENTATION_PROTOCOL_VERSION !== 2 || !setPresentationV2HostFunction) {
357
+ if (nextCurveCode === 0 && contentScale === 1 && topLeftRadius === topRightRadius && topLeftRadius === bottomRightRadius && topLeftRadius === bottomLeftRadius) {
358
+ setScalarsOnUI(x, y, width, height, topLeftRadius, contentTranslateX, contentTranslateY, overridePendingAnimation, forceRecordVelocity);
359
+ }
360
+ return;
361
+ }
362
+ if (activeAnimationId.value !== 0) activeAnimationId.value = 0;
363
+ if (ownership.value !== INTERACTIVE) ownership.value = INTERACTIVE;
364
+ if (scalarsStale.value === 0) scalarsStale.value = 1;
365
+ setPresentationV2HostFunction(driverId, x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius, nextCurveCode, contentTranslateX, contentTranslateY, contentScale, true, overridePendingAnimation, recordVelocity);
366
+ };
254
367
  const animateOnUI = (target, animation) => {
255
368
  'worklet';
256
369
 
@@ -258,8 +371,43 @@ export function useSmoothClipDriver(initialValue, options = {}) {
258
371
  // invalid stale call cannot mint a native rejection id/completion against
259
372
  // a driver whose listener and registry entry are already gone.
260
373
  if (disposed.value !== 0) return 0;
261
- const keyframeValues = animation.type === 'keyframes' ? flattenFiniteKeyframes(target, animation) : null;
262
- if (!isFiniteClipPresentation(target) || !animationIsFinite(animation) || animation.type === 'keyframes' && keyframeValues === null) {
374
+ const canonicalTarget = canonicalizeClipPresentation(target);
375
+ const canonicalFrom = animation.from === undefined ? undefined : canonicalizeClipPresentation(animation.from);
376
+ const keyframeResult = animation.type === 'keyframes' ? canonicalTarget === null ? null : flattenFiniteKeyframes(canonicalTarget, animation) : null;
377
+ if (canonicalTarget === null || animation.from !== undefined && canonicalFrom === null || animation.type === 'keyframes' && keyframeResult === null) {
378
+ return rejectAnimationHostFunction(driverId);
379
+ }
380
+ const resolvedFrom = canonicalFrom ?? undefined;
381
+ const v1Compatible = isV1Compatible(canonicalTarget) && (resolvedFrom === undefined || isV1Compatible(resolvedFrom)) && (animation.type !== 'keyframes' || (keyframeResult?.canonicalFrames.every(isV1Compatible) ?? false));
382
+ // V1-representable plans deliberately stay on the original seven-scalar
383
+ // bridge even when V2 is installed. Besides preserving bridge shape,
384
+ // this retains V1's finite-value/clamping and host-normalization rules.
385
+ const useV2 = !v1Compatible;
386
+ if (!animationIsFinite(animation, useV2)) {
387
+ return rejectAnimationHostFunction(driverId);
388
+ }
389
+ const hasV2Protocol = PRESENTATION_PROTOCOL_VERSION === 2 && snapshotCurrentV2HostFunction !== undefined && animateTimingV2HostFunction !== undefined && animateSpringV2HostFunction !== undefined && animateKeyframesV2HostFunction !== undefined;
390
+ const hasAtomicFromMethod = resolvedFrom === undefined || (animation.type === 'timing' ? animateTimingFromV2HostFunction !== undefined : animation.type === 'spring' ? animateSpringFromV2HostFunction !== undefined : animateKeyframesFromV2HostFunction !== undefined);
391
+ // This is intentionally before sampling or any ownership/group/
392
+ // presentation mutation. New JS against old native must fail closed,
393
+ // and an explicit V2 start must never degrade to set()+animate().
394
+ if (useV2 && (!hasV2Protocol || !hasAtomicFromMethod)) {
395
+ return rejectAnimationHostFunction(driverId);
396
+ }
397
+ if (useV2 && resolvedFrom !== undefined && animation.type === 'keyframes' && !clipPresentationEquals(keyframeResult?.canonicalFrames[0] ?? null, resolvedFrom)) {
398
+ return rejectAnimationHostFunction(driverId);
399
+ }
400
+ const currentPresentation = canonicalizeClipPresentation(presentation.value) ?? initialPresentation;
401
+ const sampledStart = resolvedFrom ?? (useV2 ? presentationFromNative(snapshotCurrentV2HostFunction(driverId), currentPresentation) : currentPresentation);
402
+ // setPresentationScalars intentionally leaves the public SharedValue
403
+ // stale to keep the hot path allocation-free. Validate an implicit
404
+ // retarget against the sampled native-visible start, not that stale JS
405
+ // value; otherwise a streamed curve transition cannot settle natively on
406
+ // its new (now stable) curve.
407
+ if (canonicalTarget.clip.curve !== sampledStart.clip.curve) {
408
+ return rejectAnimationHostFunction(driverId);
409
+ }
410
+ if (useV2 && animation.type === 'spring' && !springScaleIsProvablyPositive(sampledStart, canonicalTarget, animation)) {
263
411
  return rejectAnimationHostFunction(driverId);
264
412
  }
265
413
  // Past the hook's cleanup the native entry is gone for good, and an
@@ -268,8 +416,8 @@ export function useSmoothClipDriver(initialValue, options = {}) {
268
416
  // rejectAnimation, which would mint an id and a completion for a driver
269
417
  // whose JS state is already detached. This is the "unsupported dispatch"
270
418
  // arm of the documented 0 contract.
271
- const from = animation.from;
272
- if (from !== undefined) {
419
+ const from = resolvedFrom;
420
+ if (from !== undefined && !useV2) {
273
421
  // Fused hot write: exactly setScalars(from…) issued immediately
274
422
  // before the handoff, so native's latest value — the animation
275
423
  // start below — is the caller's explicit presentation. Also
@@ -289,12 +437,17 @@ export function useSmoothClipDriver(initialValue, options = {}) {
289
437
  // latest value instead.
290
438
  const scalarsWereStale = scalarsStale.value !== 0;
291
439
  const hasInteractiveStart = ownership.value === INTERACTIVE && !scalarsWereStale;
292
- const start = presentation.value;
293
- ownership.value = NATIVE;
294
- presentation.value = target;
295
- scalarsStale.value = 0;
296
- const startClip = start.clip;
297
- const targetClip = target.clip;
440
+ const start = canonicalizeClipPresentation(presentation.value) ?? initialPresentation;
441
+ // V1 preserves the old optimistic SharedValue ownership transition.
442
+ // V2 commits it only after native has atomically accepted the plan.
443
+ if (!useV2) {
444
+ ownership.value = NATIVE;
445
+ presentation.value = canonicalTarget;
446
+ scalarsStale.value = 0;
447
+ }
448
+ const dispatchStart = useV2 && from !== undefined ? from : start;
449
+ const startClip = dispatchStart.clip;
450
+ const targetClip = canonicalTarget.clip;
298
451
  // Reanimated stamps a parallel animation's t0 on this same runtime as
299
452
  // `__frameTimestamp || _getAnimationTimestamp()` (valueSetter.ts).
300
453
  // Capturing the identical value here and handing it to the integrator
@@ -311,17 +464,30 @@ export function useSmoothClipDriver(initialValue, options = {}) {
311
464
  const workletGlobal = globalThis;
312
465
  const startedAtMs = !NEEDS_START_STAMP ? Number.NaN : workletGlobal.__frameTimestamp || (typeof workletGlobal._getAnimationTimestamp === 'function' ? workletGlobal._getAnimationTimestamp() : Number.NaN);
313
466
  let animationId;
314
- if (animation.type === 'timing') {
467
+ if (animation.type === 'timing' && useV2) {
315
468
  const [x1, y1, x2, y2] = animation.controlPoints;
316
- animationId = animateTimingHostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.radius, start.contentTranslateX, start.contentTranslateY, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.radius, target.contentTranslateX, target.contentTranslateY, Math.max(0, animation.duration), x1, y1, x2, y2, reduceMotion, startedAtMs);
469
+ animationId = from !== undefined ? animateTimingFromV2HostFunction(driverId, startClip.x, startClip.y, startClip.width, startClip.height, startClip.topLeftRadius, startClip.topRightRadius, startClip.bottomRightRadius, startClip.bottomLeftRadius, curveCode(dispatchStart), dispatchStart.contentTranslateX, dispatchStart.contentTranslateY, dispatchStart.contentScale, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.topLeftRadius, targetClip.topRightRadius, targetClip.bottomRightRadius, targetClip.bottomLeftRadius, curveCode(canonicalTarget), canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, canonicalTarget.contentScale, animation.duration, x1, y1, x2, y2, reduceMotion, startedAtMs) : animateTimingV2HostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.topLeftRadius, startClip.topRightRadius, startClip.bottomRightRadius, startClip.bottomLeftRadius, curveCode(dispatchStart), dispatchStart.contentTranslateX, dispatchStart.contentTranslateY, dispatchStart.contentScale, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.topLeftRadius, targetClip.topRightRadius, targetClip.bottomRightRadius, targetClip.bottomLeftRadius, curveCode(canonicalTarget), canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, canonicalTarget.contentScale, animation.duration, x1, y1, x2, y2, reduceMotion, startedAtMs);
470
+ } else if (animation.type === 'timing') {
471
+ const [x1, y1, x2, y2] = animation.controlPoints;
472
+ animationId = animateTimingHostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.radius, start.contentTranslateX, start.contentTranslateY, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.radius, canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, Math.max(0, animation.duration), x1, y1, x2, y2, reduceMotion, startedAtMs);
473
+ } else if (animation.type === 'spring' && useV2) {
474
+ const inheritVelocity = animation.initialVelocity === undefined || animation.initialVelocity === 'inherit';
475
+ const mass = animation.mass ?? 1;
476
+ const stiffness = animation.stiffness ?? 100;
477
+ const damping = animation.damping ?? 10;
478
+ const initialVelocity = inheritVelocity ? 0 : animation.initialVelocity;
479
+ animationId = from !== undefined ? animateSpringFromV2HostFunction(driverId, startClip.x, startClip.y, startClip.width, startClip.height, startClip.topLeftRadius, startClip.topRightRadius, startClip.bottomRightRadius, startClip.bottomLeftRadius, curveCode(dispatchStart), dispatchStart.contentTranslateX, dispatchStart.contentTranslateY, dispatchStart.contentScale, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.topLeftRadius, targetClip.topRightRadius, targetClip.bottomRightRadius, targetClip.bottomLeftRadius, curveCode(canonicalTarget), canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, canonicalTarget.contentScale, mass, stiffness, damping, initialVelocity, inheritVelocity, reduceMotion, startedAtMs) : animateSpringV2HostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.topLeftRadius, startClip.topRightRadius, startClip.bottomRightRadius, startClip.bottomLeftRadius, curveCode(dispatchStart), dispatchStart.contentTranslateX, dispatchStart.contentTranslateY, dispatchStart.contentScale, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.topLeftRadius, targetClip.topRightRadius, targetClip.bottomRightRadius, targetClip.bottomLeftRadius, curveCode(canonicalTarget), canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, canonicalTarget.contentScale, mass, stiffness, damping, initialVelocity, inheritVelocity, reduceMotion, startedAtMs);
317
480
  } else if (animation.type === 'spring') {
318
481
  const inheritVelocity = animation.initialVelocity === undefined || animation.initialVelocity === 'inherit';
319
- animationId = animateSpringHostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.radius, start.contentTranslateX, start.contentTranslateY, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.radius, target.contentTranslateX, target.contentTranslateY, Math.max(0.0001, animation.mass ?? 1), Math.max(0.0001, animation.stiffness ?? 100), Math.max(0, animation.damping ?? 10), inheritVelocity ? 0 : animation.initialVelocity, inheritVelocity, reduceMotion, startedAtMs);
482
+ animationId = animateSpringHostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.radius, start.contentTranslateX, start.contentTranslateY, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.radius, canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, Math.max(0.0001, animation.mass ?? 1), Math.max(0.0001, animation.stiffness ?? 100), Math.max(0, animation.damping ?? 10), inheritVelocity ? 0 : animation.initialVelocity, inheritVelocity, reduceMotion, startedAtMs);
483
+ } else if (useV2) {
484
+ const frames = keyframeResult.frames;
485
+ animationId = from !== undefined ? animateKeyframesFromV2HostFunction(driverId, startClip.x, startClip.y, startClip.width, startClip.height, startClip.topLeftRadius, startClip.topRightRadius, startClip.bottomRightRadius, startClip.bottomLeftRadius, curveCode(dispatchStart), dispatchStart.contentTranslateX, dispatchStart.contentTranslateY, dispatchStart.contentScale, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.topLeftRadius, targetClip.topRightRadius, targetClip.bottomRightRadius, targetClip.bottomLeftRadius, curveCode(canonicalTarget), canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, canonicalTarget.contentScale, animation.duration, frames, reduceMotion, startedAtMs) : animateKeyframesV2HostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.topLeftRadius, startClip.topRightRadius, startClip.bottomRightRadius, startClip.bottomLeftRadius, curveCode(dispatchStart), dispatchStart.contentTranslateX, dispatchStart.contentTranslateY, dispatchStart.contentScale, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.topLeftRadius, targetClip.topRightRadius, targetClip.bottomRightRadius, targetClip.bottomLeftRadius, curveCode(canonicalTarget), canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, canonicalTarget.contentScale, animation.duration, frames, reduceMotion, startedAtMs);
320
486
  } else {
321
- animationId = animateKeyframesHostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.radius, start.contentTranslateX, start.contentTranslateY, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.radius, target.contentTranslateX, target.contentTranslateY, Math.max(0, animation.duration),
487
+ animationId = animateKeyframesHostFunction(driverId, hasInteractiveStart, startClip.x, startClip.y, startClip.width, startClip.height, startClip.radius, start.contentTranslateX, start.contentTranslateY, targetClip.x, targetClip.y, targetClip.width, targetClip.height, targetClip.radius, canonicalTarget.contentTranslateX, canonicalTarget.contentTranslateY, Math.max(0, animation.duration),
322
488
  // Non-null here: the validation gate above rejected null before any
323
489
  // side effect.
324
- keyframeValues, reduceMotion, startedAtMs);
490
+ flattenV1Keyframes(keyframeResult.canonicalFrames, animation.frames.map(frame => frame.offset)), reduceMotion, startedAtMs);
325
491
  }
326
492
  if (animationId === 0) {
327
493
  // The 0 sentinel: off-main, invalid-id, or otherwise unsupported
@@ -332,12 +498,19 @@ export function useSmoothClipDriver(initialValue, options = {}) {
332
498
  // effect, with a fresh id and one finished:false completion once the
333
499
  // native entry exists — in the pre-seed window rejectAnimation has no
334
500
  // entry and returns the bare 0 sentinel with no completion instead.
335
- ownership.value = INTERACTIVE;
336
- presentation.value = start;
337
- if (scalarsWereStale) scalarsStale.value = 1;
338
- activeAnimationId.value = 0;
501
+ if (!useV2) {
502
+ ownership.value = INTERACTIVE;
503
+ presentation.value = start;
504
+ if (scalarsWereStale) scalarsStale.value = 1;
505
+ activeAnimationId.value = 0;
506
+ }
339
507
  return rejectAnimationHostFunction(driverId);
340
508
  }
509
+ if (useV2) {
510
+ ownership.value = NATIVE;
511
+ presentation.value = canonicalTarget;
512
+ scalarsStale.value = 0;
513
+ }
341
514
  activeAnimationId.value = animationId;
342
515
  return animationId;
343
516
  };
@@ -347,10 +520,11 @@ export function useSmoothClipDriver(initialValue, options = {}) {
347
520
  // Past the hook's cleanup the native entry is gone; the call would fail
348
521
  // defined (handled=false) but it is the last driver.ui path that still
349
522
  // crosses into native after the tombstone. Guard it like the rest.
350
- if (disposed.value !== 0) return presentation.value;
351
- const values = cancelAnimationHostFunction(driverId, animationId, behavior === 'target' ? 1 : 0);
352
- if (values.length < 8 || values[0] !== 1) return presentation.value;
353
- const current = presentationFromNative(values, presentation.value, 1);
523
+ const fallback = canonicalizeClipPresentation(presentation.value) ?? initialPresentation;
524
+ if (disposed.value !== 0) return fallback;
525
+ const values = PRESENTATION_PROTOCOL_VERSION === 2 && cancelAnimationV2HostFunction ? cancelAnimationV2HostFunction(driverId, animationId, behavior === 'target' ? 1 : 0) : cancelAnimationHostFunction(driverId, animationId, behavior === 'target' ? 1 : 0);
526
+ if (values.length < 8 || values[0] !== 1) return fallback;
527
+ const current = presentationFromNative(values, fallback, 1);
354
528
  activeAnimationId.value = 0;
355
529
  ownership.value = INTERACTIVE;
356
530
  scalarsStale.value = 0;
@@ -379,6 +553,12 @@ export function useSmoothClipDriver(initialValue, options = {}) {
379
553
  if (isRNRuntime()) return uiOnly();
380
554
  setScalarsOnUI(x, y, width, height, radius, contentTranslateX, contentTranslateY);
381
555
  },
556
+ setPresentationScalars(x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius, nextCurveCode, contentTranslateX, contentTranslateY, contentScale) {
557
+ 'worklet';
558
+
559
+ if (isRNRuntime()) return uiOnly();
560
+ setPresentationScalarsOnUI(x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius, nextCurveCode, contentTranslateX, contentTranslateY, contentScale);
561
+ },
382
562
  animateTo(target, animation) {
383
563
  'worklet';
384
564
 
@@ -454,6 +634,13 @@ export function useSmoothClipDriver(initialValue, options = {}) {
454
634
  });
455
635
  return promise;
456
636
  }
637
+ },
638
+ __smoothClipHandle: {
639
+ driverId,
640
+ presentation,
641
+ ownership,
642
+ activeAnimationId,
643
+ disposed
457
644
  }
458
645
  };
459
646
  setDriverState(driver, createDriverState(driverId, initialPresentation, presentation, callbackRef, activeAnimationId, ownership));
@@ -476,7 +663,7 @@ export function useSmoothClipDriver(initialValue, options = {}) {
476
663
  synchronizeNativeCompletion(activeAnimationId, ownership, result.animationId, result.finished);
477
664
  completeNativeAnimation(driverId, result.animationId, result.finished);
478
665
  });
479
- scheduleOnUI((source, listenerId, nativeDriverId, owner, suppressed, active, stale, gone, setter) => {
666
+ scheduleOnUI((source, listenerId, nativeDriverId, owner, suppressed, active, stale, gone, setter, setterV2, protocolVersion) => {
480
667
  'worklet';
481
668
 
482
669
  // First, before the listener or the seed: this effect run owns the
@@ -485,7 +672,8 @@ export function useSmoothClipDriver(initialValue, options = {}) {
485
672
  gone.value = 0;
486
673
  let last = null;
487
674
  const deliver = next => {
488
- if (!isFiniteClipPresentation(next) || clipPresentationEquals(last, next)) {
675
+ const canonical = canonicalizeClipPresentation(next);
676
+ if (canonical === null || clipPresentationEquals(last, canonical)) {
489
677
  return;
490
678
  }
491
679
  // Record `last` only for values native has actually observed:
@@ -494,19 +682,27 @@ export function useSmoothClipDriver(initialValue, options = {}) {
494
682
  if (owner.value !== INTERACTIVE) return;
495
683
  if (suppressed.value > 0) {
496
684
  suppressed.value -= 1;
497
- last = next;
685
+ last = canonical;
498
686
  return;
499
687
  }
500
- last = next;
688
+ if (protocolVersion !== 2 && !isV1Compatible(canonical)) {
689
+ return;
690
+ }
691
+ last = canonical;
501
692
  if (stale.value !== 0) stale.value = 0;
502
693
  const {
503
694
  clip,
504
695
  contentTranslateX,
505
- contentTranslateY
506
- } = next;
696
+ contentTranslateY,
697
+ contentScale
698
+ } = canonical;
507
699
  // Declarative deliveries always record velocity samples — only the
508
700
  // setScalars hot path is gated by the velocityTracking option.
509
- setter(nativeDriverId, clip.x, clip.y, clip.width, clip.height, clip.radius, contentTranslateX, contentTranslateY, false, false);
701
+ if (protocolVersion === 2 && setterV2) {
702
+ setterV2(nativeDriverId, clip.x, clip.y, clip.width, clip.height, clip.topLeftRadius, clip.topRightRadius, clip.bottomRightRadius, clip.bottomLeftRadius, curveCode(canonical), contentTranslateX, contentTranslateY, contentScale, false, false, true);
703
+ } else {
704
+ setter(nativeDriverId, clip.x, clip.y, clip.width, clip.height, clip.radius, contentTranslateX, contentTranslateY, false, false);
705
+ }
510
706
  };
511
707
  source.addListener(listenerId, deliver);
512
708
  // Authoritative take-ownership seed. Creates the native entry before
@@ -515,15 +711,19 @@ export function useSmoothClipDriver(initialValue, options = {}) {
515
711
  // An animation worklet can win the scheduling race and create a latch
516
712
  // first; Native ownership then marks that intent as newer, so this
517
713
  // passive seed must not clear its active id or replay the target value.
518
- const current = source.value;
519
- if (owner.value === INTERACTIVE && isFiniteClipPresentation(current)) {
714
+ const current = canonicalizeClipPresentation(source.value);
715
+ if (owner.value === INTERACTIVE && current !== null) {
520
716
  active.value = 0;
521
717
  owner.value = INTERACTIVE;
522
718
  stale.value = 0;
523
719
  last = current;
524
- setter(nativeDriverId, current.clip.x, current.clip.y, current.clip.width, current.clip.height, current.clip.radius, current.contentTranslateX, current.contentTranslateY, true, false);
720
+ if (protocolVersion === 2 && setterV2) {
721
+ setterV2(nativeDriverId, current.clip.x, current.clip.y, current.clip.width, current.clip.height, current.clip.topLeftRadius, current.clip.topRightRadius, current.clip.bottomRightRadius, current.clip.bottomLeftRadius, curveCode(current), current.contentTranslateX, current.contentTranslateY, current.contentScale, true, false, true);
722
+ } else if (isV1Compatible(current)) {
723
+ setter(nativeDriverId, current.clip.x, current.clip.y, current.clip.width, current.clip.height, current.clip.radius, current.contentTranslateX, current.contentTranslateY, true, false);
724
+ }
525
725
  }
526
- }, presentation, driverId, driverId, ownership, suppressDeliveries, activeAnimationId, scalarsStale, disposed, setPresentationHostFunction);
726
+ }, presentation, driverId, driverId, ownership, suppressDeliveries, activeAnimationId, scalarsStale, disposed, setPresentationHostFunction, setPresentationV2HostFunction, PRESENTATION_PROTOCOL_VERSION);
527
727
  return () => {
528
728
  subscription.remove();
529
729
  rejectDriverRequests(driverId);