react-native-smooth-clip-view 0.2.9 → 0.4.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 (193) hide show
  1. package/README.md +132 -349
  2. package/android/build.gradle +8 -4
  3. package/android/proguard-rules.pro +3 -3
  4. package/android/src/main/cpp/SmoothClipAndroid.h +13 -6
  5. package/android/src/main/cpp/SmoothClipBindings.cpp +605 -123
  6. package/android/src/main/cpp/SmoothClipRegistry.cpp +975 -209
  7. package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +192 -118
  8. package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +22 -4
  9. package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +81 -56
  10. package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +449 -240
  11. package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +150 -38
  12. package/cpp/SmoothClipAnimationCurve.h +317 -397
  13. package/cpp/SmoothClipRegistry.h +84 -20
  14. package/cpp/SmoothClipSharedGeometry.h +131 -22
  15. package/cpp/SmoothClipVelocityTracker.h +16 -12
  16. package/ios/SmoothClipGeometry.h +188 -21
  17. package/ios/SmoothClipRegistry.mm +869 -368
  18. package/ios/SmoothClipRegistrySnapshot.h +13 -0
  19. package/ios/SmoothClipTurboModule.cpp +513 -156
  20. package/ios/SmoothClipTurboModule.h +123 -56
  21. package/ios/SmoothClipView.mm +1074 -449
  22. package/ios/SmoothClipViewRegistry.h +3 -7
  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 +94 -11
  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 +32 -12
  31. package/lib/module/capabilities.js +4 -0
  32. package/lib/module/capabilities.js.map +1 -0
  33. package/lib/module/capabilities.native.js +18 -0
  34. package/lib/module/capabilities.native.js.map +1 -0
  35. package/lib/module/capabilityTypes.js +2 -0
  36. package/lib/module/capabilityTypes.js.map +1 -0
  37. package/lib/module/controllerInternals.js +28 -0
  38. package/lib/module/controllerInternals.js.map +1 -0
  39. package/lib/module/controllerLifecycle.js +9 -0
  40. package/lib/module/controllerLifecycle.js.map +1 -0
  41. package/lib/module/controllerTypes.js +4 -0
  42. package/lib/module/controllerTypes.js.map +1 -0
  43. package/lib/module/controllers.android.js +4 -0
  44. package/lib/module/controllers.android.js.map +1 -0
  45. package/lib/module/controllers.ios.js +4 -0
  46. package/lib/module/controllers.ios.js.map +1 -0
  47. package/lib/module/controllers.js +4 -0
  48. package/lib/module/controllers.js.map +1 -0
  49. package/lib/module/controllers.native.js +89 -0
  50. package/lib/module/controllers.native.js.map +1 -0
  51. package/lib/module/geometry.js +180 -30
  52. package/lib/module/geometry.js.map +1 -1
  53. package/lib/module/groupTypes.js +4 -0
  54. package/lib/module/groupTypes.js.map +1 -0
  55. package/lib/module/groups.android.js +4 -0
  56. package/lib/module/groups.android.js.map +1 -0
  57. package/lib/module/groups.ios.js +4 -0
  58. package/lib/module/groups.ios.js.map +1 -0
  59. package/lib/module/groups.js +4 -0
  60. package/lib/module/groups.js.map +1 -0
  61. package/lib/module/groups.native.js +399 -0
  62. package/lib/module/groups.native.js.map +1 -0
  63. package/lib/module/ids.js +8 -0
  64. package/lib/module/ids.js.map +1 -0
  65. package/lib/module/index.js +4 -3
  66. package/lib/module/index.js.map +1 -1
  67. package/lib/module/nativeCompletion.js +37 -16
  68. package/lib/module/nativeCompletion.js.map +1 -1
  69. package/lib/module/presentationCodec.js +81 -0
  70. package/lib/module/presentationCodec.js.map +1 -0
  71. package/lib/typescript/src/NativeSmoothClipModule.d.ts +20 -4
  72. package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -1
  73. package/lib/typescript/src/SmoothClipView.d.ts +2 -10
  74. package/lib/typescript/src/SmoothClipView.d.ts.map +1 -1
  75. package/lib/typescript/src/SmoothClipView.ios.d.ts +139 -4
  76. package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -1
  77. package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +16 -3
  78. package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
  79. package/lib/typescript/src/capabilities.d.ts +3 -0
  80. package/lib/typescript/src/capabilities.d.ts.map +1 -0
  81. package/lib/typescript/src/capabilities.native.d.ts +3 -0
  82. package/lib/typescript/src/capabilities.native.d.ts.map +1 -0
  83. package/lib/typescript/src/capabilityTypes.d.ts +4 -0
  84. package/lib/typescript/src/capabilityTypes.d.ts.map +1 -0
  85. package/lib/typescript/src/controllerInternals.d.ts +14 -0
  86. package/lib/typescript/src/controllerInternals.d.ts.map +1 -0
  87. package/lib/typescript/src/controllerLifecycle.d.ts +3 -0
  88. package/lib/typescript/src/controllerLifecycle.d.ts.map +1 -0
  89. package/lib/typescript/src/controllerTypes.d.ts +62 -0
  90. package/lib/typescript/src/controllerTypes.d.ts.map +1 -0
  91. package/lib/typescript/src/controllers.android.d.ts +2 -0
  92. package/lib/typescript/src/controllers.android.d.ts.map +1 -0
  93. package/lib/typescript/src/controllers.d.ts +2 -0
  94. package/lib/typescript/src/controllers.d.ts.map +1 -0
  95. package/lib/typescript/src/controllers.ios.d.ts +2 -0
  96. package/lib/typescript/src/controllers.ios.d.ts.map +1 -0
  97. package/lib/typescript/src/controllers.native.d.ts +3 -0
  98. package/lib/typescript/src/controllers.native.d.ts.map +1 -0
  99. package/lib/typescript/src/geometry.d.ts +49 -5
  100. package/lib/typescript/src/geometry.d.ts.map +1 -1
  101. package/lib/typescript/src/groupTypes.d.ts +31 -0
  102. package/lib/typescript/src/groupTypes.d.ts.map +1 -0
  103. package/lib/typescript/src/groups.android.d.ts +2 -0
  104. package/lib/typescript/src/groups.android.d.ts.map +1 -0
  105. package/lib/typescript/src/groups.d.ts +2 -0
  106. package/lib/typescript/src/groups.d.ts.map +1 -0
  107. package/lib/typescript/src/groups.ios.d.ts +2 -0
  108. package/lib/typescript/src/groups.ios.d.ts.map +1 -0
  109. package/lib/typescript/src/groups.native.d.ts +3 -0
  110. package/lib/typescript/src/groups.native.d.ts.map +1 -0
  111. package/lib/typescript/src/ids.d.ts +2 -0
  112. package/lib/typescript/src/ids.d.ts.map +1 -0
  113. package/lib/typescript/src/index.d.ts +8 -5
  114. package/lib/typescript/src/index.d.ts.map +1 -1
  115. package/lib/typescript/src/nativeCompletion.d.ts +16 -6
  116. package/lib/typescript/src/nativeCompletion.d.ts.map +1 -1
  117. package/lib/typescript/src/presentationCodec.d.ts +10 -0
  118. package/lib/typescript/src/presentationCodec.d.ts.map +1 -0
  119. package/package.json +17 -13
  120. package/src/NativeSmoothClipModule.ts +80 -56
  121. package/src/SmoothClipView.ios.tsx +142 -16
  122. package/src/SmoothClipView.tsx +6 -76
  123. package/src/SmoothClipViewNativeComponent.ts +32 -12
  124. package/src/capabilities.native.ts +19 -0
  125. package/src/capabilities.ts +2 -0
  126. package/src/capabilityTypes.ts +3 -0
  127. package/src/controllerInternals.ts +52 -0
  128. package/src/controllerLifecycle.ts +6 -0
  129. package/src/controllerTypes.ts +87 -0
  130. package/src/controllers.android.ts +1 -0
  131. package/src/controllers.ios.ts +1 -0
  132. package/src/controllers.native.ts +104 -0
  133. package/src/controllers.ts +1 -0
  134. package/src/geometry.ts +293 -45
  135. package/src/groupTypes.ts +53 -0
  136. package/src/groups.android.ts +1 -0
  137. package/src/groups.ios.ts +1 -0
  138. package/src/groups.native.ts +604 -0
  139. package/src/groups.ts +1 -0
  140. package/src/ids.ts +6 -0
  141. package/src/index.ts +32 -12
  142. package/src/nativeCompletion.ts +67 -32
  143. package/src/presentationCodec.ts +134 -0
  144. package/lib/module/SmoothClipView.web.js +0 -54
  145. package/lib/module/SmoothClipView.web.js.map +0 -1
  146. package/lib/module/driverState.js +0 -110
  147. package/lib/module/driverState.js.map +0 -1
  148. package/lib/module/driverTypes.js +0 -4
  149. package/lib/module/driverTypes.js.map +0 -1
  150. package/lib/module/drivers.android.js +0 -6
  151. package/lib/module/drivers.android.js.map +0 -1
  152. package/lib/module/drivers.ios.js +0 -6
  153. package/lib/module/drivers.ios.js.map +0 -1
  154. package/lib/module/drivers.js +0 -284
  155. package/lib/module/drivers.js.map +0 -1
  156. package/lib/module/drivers.native.js +0 -556
  157. package/lib/module/drivers.native.js.map +0 -1
  158. package/lib/module/index.web.js +0 -8
  159. package/lib/module/index.web.js.map +0 -1
  160. package/lib/module/reactRequests.js +0 -56
  161. package/lib/module/reactRequests.js.map +0 -1
  162. package/lib/module/webClipPath.js +0 -25
  163. package/lib/module/webClipPath.js.map +0 -1
  164. package/lib/typescript/src/SmoothClipView.web.d.ts +0 -10
  165. package/lib/typescript/src/SmoothClipView.web.d.ts.map +0 -1
  166. package/lib/typescript/src/driverState.d.ts +0 -31
  167. package/lib/typescript/src/driverState.d.ts.map +0 -1
  168. package/lib/typescript/src/driverTypes.d.ts +0 -107
  169. package/lib/typescript/src/driverTypes.d.ts.map +0 -1
  170. package/lib/typescript/src/drivers.android.d.ts +0 -3
  171. package/lib/typescript/src/drivers.android.d.ts.map +0 -1
  172. package/lib/typescript/src/drivers.d.ts +0 -5
  173. package/lib/typescript/src/drivers.d.ts.map +0 -1
  174. package/lib/typescript/src/drivers.ios.d.ts +0 -3
  175. package/lib/typescript/src/drivers.ios.d.ts.map +0 -1
  176. package/lib/typescript/src/drivers.native.d.ts +0 -5
  177. package/lib/typescript/src/drivers.native.d.ts.map +0 -1
  178. package/lib/typescript/src/index.web.d.ts +0 -9
  179. package/lib/typescript/src/index.web.d.ts.map +0 -1
  180. package/lib/typescript/src/reactRequests.d.ts +0 -9
  181. package/lib/typescript/src/reactRequests.d.ts.map +0 -1
  182. package/lib/typescript/src/webClipPath.d.ts +0 -7
  183. package/lib/typescript/src/webClipPath.d.ts.map +0 -1
  184. package/src/SmoothClipView.web.tsx +0 -66
  185. package/src/driverState.ts +0 -158
  186. package/src/driverTypes.ts +0 -140
  187. package/src/drivers.android.ts +0 -8
  188. package/src/drivers.ios.ts +0 -8
  189. package/src/drivers.native.ts +0 -899
  190. package/src/drivers.ts +0 -427
  191. package/src/index.web.ts +0 -23
  192. package/src/reactRequests.ts +0 -76
  193. package/src/webClipPath.ts +0 -30
package/src/drivers.ts DELETED
@@ -1,427 +0,0 @@
1
- import { useEffect, useRef } from 'react';
2
- import {
3
- cancelAnimation as cancelReanimatedAnimation,
4
- Easing,
5
- ReduceMotion,
6
- useAnimatedReaction,
7
- useSharedValue,
8
- withSpring,
9
- withTiming,
10
- } from 'react-native-reanimated';
11
- import { scheduleOnRN, scheduleOnUI } from 'react-native-worklets';
12
- import type {
13
- ClipReduceMotion,
14
- KeyframedClipAnimation,
15
- SmoothClipAnimation,
16
- SmoothClipDriver,
17
- SmoothClipDriverOptions,
18
- SpringClipAnimation,
19
- TimingClipAnimation,
20
- } from './driverTypes';
21
- import {
22
- allocateDriverId,
23
- attachDriverState,
24
- createDriverState,
25
- deliverDriverCompletion,
26
- detachDriverState,
27
- finishDriverAnimation,
28
- getDriverState,
29
- setDriverState,
30
- snapshotDriverViews,
31
- } from './driverState';
32
- import {
33
- createClipPresentation,
34
- clipPresentationEquals,
35
- isFiniteClipPresentation,
36
- type ClipGeometry,
37
- type SmoothClipPresentation,
38
- } from './geometry';
39
- import {
40
- createReactRequest,
41
- rejectDriverRequests,
42
- resolveReactRequest,
43
- } from './reactRequests';
44
-
45
- function toReanimatedReduceMotion(value: ClipReduceMotion): ReduceMotion {
46
- switch (value) {
47
- case 'always':
48
- return ReduceMotion.Always;
49
- case 'never':
50
- return ReduceMotion.Never;
51
- default:
52
- return ReduceMotion.System;
53
- }
54
- }
55
-
56
- function animationIsFinite(animation: SmoothClipAnimation): boolean {
57
- 'worklet';
58
- if (
59
- animation.from !== undefined &&
60
- !isFiniteClipPresentation(animation.from)
61
- ) {
62
- return false;
63
- }
64
- if (animation.type === 'timing') {
65
- return (
66
- Number.isFinite(animation.duration) &&
67
- animation.controlPoints.every(Number.isFinite)
68
- );
69
- }
70
- if (animation.type === 'spring') {
71
- return [
72
- animation.mass ?? 1,
73
- animation.stiffness ?? 100,
74
- animation.damping ?? 10,
75
- animation.initialVelocity === 'inherit'
76
- ? 0
77
- : (animation.initialVelocity ?? 0),
78
- ].every(Number.isFinite);
79
- }
80
- let previousOffset = -1;
81
- if (!Number.isFinite(animation.duration) || animation.frames.length < 2) {
82
- return false;
83
- }
84
- for (const frame of animation.frames) {
85
- if (
86
- !Number.isFinite(frame.offset) ||
87
- frame.offset < 0 ||
88
- frame.offset > 1 ||
89
- frame.offset <= previousOffset ||
90
- !isFiniteClipPresentation(frame.presentation)
91
- ) {
92
- return false;
93
- }
94
- previousOffset = frame.offset;
95
- }
96
- return animation.frames[0]?.offset === 0 && previousOffset === 1;
97
- }
98
-
99
- function interpolatePresentation(
100
- from: SmoothClipPresentation,
101
- to: SmoothClipPresentation,
102
- progress: number
103
- ): SmoothClipPresentation {
104
- 'worklet';
105
- const mix = (start: number, end: number) => start + (end - start) * progress;
106
- return {
107
- clip: {
108
- x: mix(from.clip.x, to.clip.x),
109
- y: mix(from.clip.y, to.clip.y),
110
- width: mix(from.clip.width, to.clip.width),
111
- height: mix(from.clip.height, to.clip.height),
112
- radius: mix(from.clip.radius, to.clip.radius),
113
- },
114
- contentTranslateX: mix(from.contentTranslateX, to.contentTranslateX),
115
- contentTranslateY: mix(from.contentTranslateY, to.contentTranslateY),
116
- };
117
- }
118
-
119
- function finishFallback(
120
- driverId: number,
121
- animationId: number,
122
- finished: boolean
123
- ): void {
124
- deliverDriverCompletion(
125
- driverId,
126
- animationId,
127
- finishDriverAnimation(driverId, animationId, finished)
128
- );
129
- }
130
-
131
- export function useSmoothClipDriver(
132
- initialValue: ClipGeometry | SmoothClipPresentation,
133
- options: SmoothClipDriverOptions = {}
134
- ): SmoothClipDriver {
135
- const initialPresentation =
136
- 'clip' in initialValue
137
- ? initialValue
138
- : createClipPresentation(initialValue);
139
- const presentation = useSharedValue(initialPresentation);
140
- const activeAnimationId = useSharedValue(0);
141
- const nextAnimationId = useSharedValue(0);
142
- const latestTarget = useSharedValue(initialPresentation);
143
- const animationStart = useSharedValue(initialPresentation);
144
- const animationProgress = useSharedValue(0);
145
- const keyframes = useSharedValue<
146
- readonly Readonly<{
147
- offset: number;
148
- presentation: SmoothClipPresentation;
149
- }>[]
150
- >([]);
151
- const callbackRef = useRef(options.onAnimationComplete);
152
- const driverRef = useRef<SmoothClipDriver | null>(null);
153
- callbackRef.current = options.onAnimationComplete;
154
-
155
- useAnimatedReaction(
156
- () => animationProgress.value,
157
- (progress) => {
158
- const frames = keyframes.value;
159
- if (frames.length >= 2) {
160
- let upperIndex = 1;
161
- while (
162
- upperIndex < frames.length - 1 &&
163
- progress > (frames[upperIndex]?.offset ?? 1)
164
- ) {
165
- upperIndex += 1;
166
- }
167
- const lower = frames[upperIndex - 1];
168
- const upper = frames[upperIndex];
169
- if (!lower || !upper) return;
170
- const span = upper.offset - lower.offset;
171
- const localProgress = span <= 0 ? 1 : (progress - lower.offset) / span;
172
- presentation.value = interpolatePresentation(
173
- lower.presentation,
174
- upper.presentation,
175
- Math.min(1, Math.max(0, localProgress))
176
- );
177
- return;
178
- }
179
- presentation.value = interpolatePresentation(
180
- animationStart.value,
181
- latestTarget.value,
182
- progress
183
- );
184
- },
185
- [animationProgress, animationStart, keyframes, latestTarget, presentation]
186
- );
187
-
188
- if (driverRef.current === null) {
189
- const driverId = allocateDriverId();
190
- const reduceMotion = toReanimatedReduceMotion(
191
- options.reduceMotion ?? 'system'
192
- );
193
-
194
- const beginOnUI = (): SmoothClipPresentation => {
195
- 'worklet';
196
- cancelReanimatedAnimation(animationProgress);
197
- activeAnimationId.value = 0;
198
- return presentation.value;
199
- };
200
-
201
- const setOnUI = (next: SmoothClipPresentation): void => {
202
- 'worklet';
203
- if (!isFiniteClipPresentation(next)) return;
204
- cancelReanimatedAnimation(animationProgress);
205
- activeAnimationId.value = 0;
206
- latestTarget.value = next;
207
- presentation.value = next;
208
- };
209
-
210
- const animateOnUI = (
211
- next: SmoothClipPresentation,
212
- animation: SmoothClipAnimation
213
- ): number => {
214
- 'worklet';
215
- nextAnimationId.value = (nextAnimationId.value % 0x7ffffffe) + 1;
216
- const animationId = nextAnimationId.value;
217
- if (!isFiniteClipPresentation(next) || !animationIsFinite(animation)) {
218
- scheduleOnRN(finishFallback, driverId, animationId, false);
219
- return animationId;
220
- }
221
-
222
- if (animation.from !== undefined) {
223
- // Fused explicit start: on the fallback driver the setScalars hot
224
- // path is a plain presentation write, so the desugar is the same.
225
- presentation.value = animation.from;
226
- }
227
- activeAnimationId.value = animationId;
228
- animationStart.value = presentation.value;
229
- latestTarget.value = next;
230
- keyframes.value = [];
231
- animationProgress.value = 0;
232
- scheduleOnRN(snapshotDriverViews, driverId, animationId);
233
- const onComplete = (finished?: boolean) => {
234
- 'worklet';
235
- if (activeAnimationId.value === animationId) {
236
- activeAnimationId.value = 0;
237
- }
238
- scheduleOnRN(finishFallback, driverId, animationId, finished === true);
239
- };
240
-
241
- if (animation.type === 'timing') {
242
- const [x1, y1, x2, y2] = animation.controlPoints;
243
- animationProgress.value = withTiming(
244
- 1,
245
- {
246
- duration: Math.max(0, animation.duration),
247
- easing: Easing.bezier(x1, y1, x2, y2),
248
- reduceMotion,
249
- },
250
- onComplete
251
- );
252
- } else if (animation.type === 'spring') {
253
- const configuredVelocity = animation.initialVelocity;
254
- animationProgress.value = withSpring(
255
- 1,
256
- {
257
- damping: animation.damping ?? 10,
258
- mass: animation.mass ?? 1,
259
- reduceMotion,
260
- stiffness: animation.stiffness ?? 100,
261
- // The fallback driver cannot sample native presentation motion,
262
- // so 'inherit' (and undefined) degrade to zero launch velocity.
263
- velocity:
264
- typeof configuredVelocity === 'number' ? configuredVelocity : 0,
265
- },
266
- onComplete
267
- );
268
- } else {
269
- if (
270
- !clipPresentationEquals(
271
- animation.frames[animation.frames.length - 1]?.presentation ?? null,
272
- next
273
- )
274
- ) {
275
- scheduleOnRN(finishFallback, driverId, animationId, false);
276
- activeAnimationId.value = 0;
277
- return animationId;
278
- }
279
- keyframes.value = animation.frames;
280
- animationProgress.value = withTiming(
281
- 1,
282
- {
283
- duration: Math.max(0, animation.duration),
284
- easing: Easing.linear,
285
- reduceMotion,
286
- },
287
- onComplete
288
- );
289
- }
290
- return animationId;
291
- };
292
-
293
- const cancelOnUI = (
294
- animationId = 0,
295
- behavior: 'current' | 'target' = 'current'
296
- ): SmoothClipPresentation => {
297
- 'worklet';
298
- if (animationId !== 0 && animationId !== activeAnimationId.value) {
299
- return presentation.value;
300
- }
301
- cancelReanimatedAnimation(animationProgress);
302
- activeAnimationId.value = 0;
303
- if (behavior === 'target') presentation.value = latestTarget.value;
304
- return presentation.value;
305
- };
306
-
307
- const setScalarsOnUI = (
308
- x: number,
309
- y: number,
310
- width: number,
311
- height: number,
312
- radius: number,
313
- contentTranslateX: number,
314
- contentTranslateY: number
315
- ): void => {
316
- 'worklet';
317
- setOnUI({
318
- clip: { x, y, width, height, radius },
319
- contentTranslateX,
320
- contentTranslateY,
321
- });
322
- };
323
-
324
- const driver: SmoothClipDriver = {
325
- kind: 'hybrid',
326
- presentation,
327
- // Every worklet here shares the single JS runtime, so unlike the native
328
- // driver there is no runtime guard on `ui`: calling it from React code
329
- // is harmless in this fallback.
330
- ui: {
331
- beginInteraction: beginOnUI,
332
- set: setOnUI,
333
- setScalars: setScalarsOnUI,
334
- animateTo: animateOnUI,
335
- cancel: cancelOnUI,
336
- },
337
- react: {
338
- beginInteraction() {
339
- const { requestId, promise } =
340
- createReactRequest<SmoothClipPresentation>(driverId);
341
- scheduleOnUI(() => {
342
- 'worklet';
343
- const result = beginOnUI();
344
- scheduleOnRN(resolveReactRequest, driverId, requestId, result);
345
- });
346
- return promise;
347
- },
348
- set(next) {
349
- const { requestId, promise } = createReactRequest<void>(driverId);
350
- scheduleOnUI(() => {
351
- 'worklet';
352
- setOnUI(next);
353
- scheduleOnRN(resolveReactRequest, driverId, requestId, undefined);
354
- });
355
- return promise;
356
- },
357
- animateTo(next, animation) {
358
- const { requestId, promise } = createReactRequest<number>(
359
- driverId,
360
- true
361
- );
362
- scheduleOnUI(() => {
363
- 'worklet';
364
- const result = animateOnUI(next, animation);
365
- scheduleOnRN(
366
- resolveReactRequest,
367
- driverId,
368
- requestId,
369
- result,
370
- true
371
- );
372
- });
373
- return promise;
374
- },
375
- cancel(animationId = 0, behavior = 'current') {
376
- const { requestId, promise } =
377
- createReactRequest<SmoothClipPresentation>(driverId, true);
378
- scheduleOnUI(() => {
379
- 'worklet';
380
- const result = cancelOnUI(animationId, behavior);
381
- scheduleOnRN(
382
- resolveReactRequest,
383
- driverId,
384
- requestId,
385
- result,
386
- true
387
- );
388
- });
389
- return promise;
390
- },
391
- },
392
- };
393
- setDriverState(
394
- driver,
395
- createDriverState(
396
- driverId,
397
- initialPresentation,
398
- presentation,
399
- callbackRef,
400
- activeAnimationId
401
- )
402
- );
403
- driverRef.current = driver;
404
- }
405
-
406
- const driver = driverRef.current;
407
- useEffect(() => {
408
- const currentDriver = driverRef.current;
409
- if (!currentDriver) return undefined;
410
- const state = getDriverState(currentDriver);
411
- // Re-attach on effect replays (StrictMode/<Activity>) after a cleanup
412
- // detached this state.
413
- attachDriverState(state);
414
- return () => {
415
- cancelReanimatedAnimation(animationProgress);
416
- rejectDriverRequests(state.driverId);
417
- detachDriverState(state);
418
- };
419
- }, [animationProgress]);
420
- return driver;
421
- }
422
-
423
- export type {
424
- KeyframedClipAnimation,
425
- SpringClipAnimation,
426
- TimingClipAnimation,
427
- };
package/src/index.web.ts DELETED
@@ -1,23 +0,0 @@
1
- export { SmoothClipView } from './SmoothClipView.web';
2
- export type { SmoothClipViewProps } from './SmoothClipView.web';
3
- export { useSmoothClipDriver } from './drivers';
4
- export type {
5
- ClipAnimationResult,
6
- ClipReduceMotion,
7
- KeyframedClipAnimation,
8
- SmoothClipDriver,
9
- SmoothClipDriverOptions,
10
- SmoothClipReactControls,
11
- SmoothClipUIControls,
12
- SmoothClipAnimation,
13
- SpringClipAnimation,
14
- TimingClipAnimation,
15
- } from './driverTypes';
16
- export { ClipEasings } from './easings';
17
- export { normalizeClipGeometry } from './geometry';
18
- export { createClipPresentation } from './geometry';
19
- export type {
20
- ClipBounds,
21
- ClipGeometry,
22
- SmoothClipPresentation,
23
- } from './geometry';
@@ -1,76 +0,0 @@
1
- import {
2
- deferDriverCompletions,
3
- releaseDriverCompletions,
4
- } from './driverState';
5
-
6
- type PendingRequest = {
7
- resolve(value: unknown): void;
8
- reject(error: Error): void;
9
- // Set for calls whose documented usage is fire-and-forget (`void
10
- // driver.react.animateTo(...)`): teardown resolves them with this benign
11
- // sentinel instead of rejecting, so a discarded promise cannot surface as
12
- // an unhandled rejection during ordinary unmount.
13
- teardownResolution?: { value: unknown };
14
- };
15
-
16
- const requests = new Map<number, PendingRequest>();
17
- const requestsByDriver = new Map<number, Set<number>>();
18
- let nextRequestId = 0;
19
-
20
- export function createReactRequest<T>(
21
- driverId: number,
22
- deferCompletions = false,
23
- teardownResolution?: { value: unknown }
24
- ): { requestId: number; promise: Promise<T> } {
25
- nextRequestId = (nextRequestId % 0x7ffffffe) + 1;
26
- const requestId = nextRequestId;
27
- let resolveRequest!: (value: T) => void;
28
- let rejectRequest!: (error: Error) => void;
29
- const promise = new Promise<T>((resolve, reject) => {
30
- resolveRequest = resolve;
31
- rejectRequest = reject;
32
- });
33
- requests.set(requestId, {
34
- resolve: resolveRequest as (value: unknown) => void,
35
- reject: rejectRequest,
36
- teardownResolution,
37
- });
38
- const driverRequests = requestsByDriver.get(driverId) ?? new Set<number>();
39
- driverRequests.add(requestId);
40
- requestsByDriver.set(driverId, driverRequests);
41
- if (deferCompletions) deferDriverCompletions(driverId);
42
- return { requestId, promise };
43
- }
44
-
45
- export function resolveReactRequest(
46
- driverId: number,
47
- requestId: number,
48
- value: unknown,
49
- releaseCompletions = false
50
- ): void {
51
- const request = requests.get(requestId);
52
- requests.delete(requestId);
53
- const driverRequests = requestsByDriver.get(driverId);
54
- driverRequests?.delete(requestId);
55
- if (driverRequests?.size === 0) requestsByDriver.delete(driverId);
56
- request?.resolve(value);
57
- if (releaseCompletions) {
58
- queueMicrotask(() => releaseDriverCompletions(driverId));
59
- }
60
- }
61
-
62
- export function rejectDriverRequests(driverId: number): void {
63
- const driverRequests = requestsByDriver.get(driverId);
64
- if (!driverRequests) return;
65
- for (const requestId of driverRequests) {
66
- const request = requests.get(requestId);
67
- requests.delete(requestId);
68
- if (!request) continue;
69
- if (request.teardownResolution) {
70
- request.resolve(request.teardownResolution.value);
71
- } else {
72
- request.reject(new Error('[SmoothClipView] Driver was destroyed.'));
73
- }
74
- }
75
- requestsByDriver.delete(driverId);
76
- }
@@ -1,30 +0,0 @@
1
- import type { ClipGeometry } from './geometry';
2
-
3
- function px(value: number): string {
4
- 'worklet';
5
- return `${value}px`;
6
- }
7
-
8
- /**
9
- * Creates a fixed-host CSS clip. Percentage/right/bottom anchored descendants
10
- * continue resolving against the host because this never changes its layout.
11
- */
12
- export function createWebClipPath(geometry: ClipGeometry): string {
13
- 'worklet';
14
- const width = Math.max(0, geometry.width);
15
- const height = Math.max(0, geometry.height);
16
- const left = Math.max(0, geometry.x);
17
- const top = Math.max(0, geometry.y);
18
- const rightEdge = Math.max(0, geometry.x + width);
19
- const bottomEdge = Math.max(0, geometry.y + height);
20
- const radius = Math.min(
21
- Math.max(0, geometry.radius),
22
- Math.min(width, height) / 2
23
- );
24
-
25
- return `inset(${px(top)} max(0px, calc(100% - ${px(
26
- rightEdge
27
- )})) max(0px, calc(100% - ${px(bottomEdge)})) ${px(
28
- left
29
- )} round ${px(radius)})`;
30
- }