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
@@ -1,76 +1,6 @@
1
- import type React from 'react';
2
- import { type ReactNode, useEffect } from 'react';
3
- import { type ViewProps } from 'react-native';
4
- import Animated, {
5
- dispatchCommand,
6
- useAnimatedReaction,
7
- useAnimatedRef,
8
- } from 'react-native-reanimated';
9
- import type { SmoothClipDriver } from './driverTypes';
10
- import { getDriverState, registerDriverView } from './driverState';
11
- import { clipPresentationEquals, isFiniteClipPresentation } from './geometry';
12
- import NativeSmoothClipView, {
13
- type NativeProps,
14
- } from './SmoothClipViewNativeComponent';
15
-
16
- const AnimatedNativeSmoothClipView =
17
- Animated.createAnimatedComponent(NativeSmoothClipView);
18
-
19
- export type SmoothClipViewProps = ViewProps & {
20
- driver: SmoothClipDriver;
21
- children?: ReactNode;
22
- };
23
-
24
- /** Android fallback. iOS resolves SmoothClipView.ios.tsx instead. */
25
- export function SmoothClipView({
26
- driver,
27
- children,
28
- ...viewProps
29
- }: SmoothClipViewProps) {
30
- const { driverId, initialPresentation, source } = getDriverState(driver);
31
- const { clip } = initialPresentation;
32
- useEffect(() => registerDriverView(driver), [driver]);
33
- const nativeRef =
34
- useAnimatedRef<React.ComponentRef<typeof NativeSmoothClipView>>();
35
-
36
- useAnimatedReaction(
37
- () => source.value,
38
- (presentation, previousPresentation) => {
39
- if (
40
- !isFiniteClipPresentation(presentation) ||
41
- clipPresentationEquals(previousPresentation, presentation)
42
- ) {
43
- return;
44
- }
45
-
46
- dispatchCommand(nativeRef, 'setClipPresentation', [
47
- presentation.clip.x,
48
- presentation.clip.y,
49
- presentation.clip.width,
50
- presentation.clip.height,
51
- presentation.clip.radius,
52
- presentation.contentTranslateX,
53
- presentation.contentTranslateY,
54
- ]);
55
- },
56
- [nativeRef, source]
57
- );
58
-
59
- const nativeProps: NativeProps = {
60
- ...viewProps,
61
- driverId,
62
- initialClipX: clip.x,
63
- initialClipY: clip.y,
64
- initialClipWidth: clip.width,
65
- initialClipHeight: clip.height,
66
- initialClipRadius: clip.radius,
67
- initialContentTranslateX: initialPresentation.contentTranslateX,
68
- initialContentTranslateY: initialPresentation.contentTranslateY,
69
- };
70
-
71
- return (
72
- <AnimatedNativeSmoothClipView ref={nativeRef} {...nativeProps}>
73
- {children}
74
- </AnimatedNativeSmoothClipView>
75
- );
76
- }
1
+ export {
2
+ renderSmoothClipView,
3
+ sanitizeSmoothClipStyle,
4
+ SmoothClipView,
5
+ } from './SmoothClipView.ios';
6
+ export type { SmoothClipViewProps } from './SmoothClipView.ios';
@@ -12,34 +12,54 @@ export interface NativeProps extends ViewProps {
12
12
  initialClipY: CodegenTypes.Double;
13
13
  initialClipWidth: CodegenTypes.Double;
14
14
  initialClipHeight: CodegenTypes.Double;
15
- initialClipRadius: CodegenTypes.Double;
15
+ initialClipTopLeftRadius: CodegenTypes.Double;
16
+ initialClipTopRightRadius: CodegenTypes.Double;
17
+ initialClipBottomRightRadius: CodegenTypes.Double;
18
+ initialClipBottomLeftRadius: CodegenTypes.Double;
19
+ initialClipCurve: CodegenTypes.Int32;
16
20
  initialContentTranslateX: CodegenTypes.Double;
17
21
  initialContentTranslateY: CodegenTypes.Double;
22
+ initialContentScale: CodegenTypes.Double;
23
+ initialClipBoxShadowEnabled: boolean;
24
+ initialClipBoxShadowRed: CodegenTypes.Double;
25
+ initialClipBoxShadowGreen: CodegenTypes.Double;
26
+ initialClipBoxShadowBlue: CodegenTypes.Double;
27
+ initialClipBoxShadowAlpha: CodegenTypes.Double;
28
+ initialClipBoxShadowOffsetX: CodegenTypes.Double;
29
+ initialClipBoxShadowOffsetY: CodegenTypes.Double;
30
+ initialClipBoxShadowBlurRadius: CodegenTypes.Double;
31
+ initialClipBoxShadowSpreadDistance: CodegenTypes.Double;
18
32
  }
19
33
 
20
34
  interface NativeCommands {
21
- setClipGeometry: (
22
- viewRef: React.ElementRef<HostComponent<NativeProps>>,
23
- x: CodegenTypes.Double,
24
- y: CodegenTypes.Double,
25
- width: CodegenTypes.Double,
26
- height: CodegenTypes.Double,
27
- radius: CodegenTypes.Double
28
- ) => void;
29
35
  setClipPresentation: (
30
36
  viewRef: React.ElementRef<HostComponent<NativeProps>>,
31
37
  x: CodegenTypes.Double,
32
38
  y: CodegenTypes.Double,
33
39
  width: CodegenTypes.Double,
34
40
  height: CodegenTypes.Double,
35
- radius: CodegenTypes.Double,
41
+ topLeftRadius: CodegenTypes.Double,
42
+ topRightRadius: CodegenTypes.Double,
43
+ bottomRightRadius: CodegenTypes.Double,
44
+ bottomLeftRadius: CodegenTypes.Double,
45
+ curveCode: CodegenTypes.Int32,
36
46
  contentTranslateX: CodegenTypes.Double,
37
- contentTranslateY: CodegenTypes.Double
47
+ contentTranslateY: CodegenTypes.Double,
48
+ contentScale: CodegenTypes.Double,
49
+ shadowEnabled: boolean,
50
+ shadowRed: CodegenTypes.Double,
51
+ shadowGreen: CodegenTypes.Double,
52
+ shadowBlue: CodegenTypes.Double,
53
+ shadowAlpha: CodegenTypes.Double,
54
+ shadowOffsetX: CodegenTypes.Double,
55
+ shadowOffsetY: CodegenTypes.Double,
56
+ shadowBlurRadius: CodegenTypes.Double,
57
+ shadowSpreadDistance: CodegenTypes.Double
38
58
  ) => void;
39
59
  }
40
60
 
41
61
  export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
42
- supportedCommands: ['setClipGeometry', 'setClipPresentation'],
62
+ supportedCommands: ['setClipPresentation'],
43
63
  });
44
64
 
45
65
  export default codegenNativeComponent<NativeProps>(
@@ -0,0 +1,19 @@
1
+ import NativeSmoothClipModule from './smoothClipNative';
2
+ import type { SmoothClipCapabilities } from './capabilityTypes';
3
+
4
+ let cached: SmoothClipCapabilities | undefined;
5
+
6
+ export function getSmoothClipCapabilities(): SmoothClipCapabilities {
7
+ if (cached) return cached;
8
+ let autonomousComplexPathAnimation = false;
9
+ try {
10
+ autonomousComplexPathAnimation =
11
+ NativeSmoothClipModule.supportsAutonomousComplexPathAnimation() === true;
12
+ } catch {
13
+ autonomousComplexPathAnimation = false;
14
+ }
15
+ cached = {
16
+ autonomousComplexPathAnimation,
17
+ };
18
+ return cached;
19
+ }
@@ -0,0 +1,2 @@
1
+ export { getSmoothClipCapabilities } from './capabilities.native';
2
+ export type { SmoothClipCapabilities } from './capabilityTypes';
@@ -0,0 +1,3 @@
1
+ export type SmoothClipCapabilities = Readonly<{
2
+ autonomousComplexPathAnimation: boolean;
3
+ }>;
@@ -0,0 +1,52 @@
1
+ import type { SmoothClipController, SmoothClipRef } from './controllerTypes';
2
+ import type { CanonicalSmoothClipPresentation } from './geometry';
3
+
4
+ export type InternalSmoothClipController = Readonly<{
5
+ ref: SmoothClipRef;
6
+ initialFrame: CanonicalSmoothClipPresentation;
7
+ }>;
8
+
9
+ export type InternalSmoothClipRef = SmoothClipRef & Readonly<{ id: number }>;
10
+
11
+ const controllers = new WeakMap<
12
+ SmoothClipController,
13
+ InternalSmoothClipController
14
+ >();
15
+
16
+ export function setControllerRef(
17
+ controller: SmoothClipController,
18
+ value: InternalSmoothClipController
19
+ ): void {
20
+ controllers.set(controller, value);
21
+ }
22
+
23
+ export function getControllerRef(
24
+ controller: SmoothClipController
25
+ ): InternalSmoothClipController {
26
+ const value = controllers.get(controller);
27
+ if (!value) {
28
+ throw new Error(
29
+ '[SmoothClipView] Controllers must be created by useSmoothClipController.'
30
+ );
31
+ }
32
+ return value;
33
+ }
34
+
35
+ export function unwrapSmoothClipRef(
36
+ ref: SmoothClipRef | undefined
37
+ ): InternalSmoothClipRef | undefined {
38
+ 'worklet';
39
+ const internal = ref as InternalSmoothClipRef | undefined;
40
+ if (
41
+ internal === undefined ||
42
+ !Number.isSafeInteger(internal.id) ||
43
+ internal.id <= 0
44
+ ) {
45
+ return undefined;
46
+ }
47
+ return internal;
48
+ }
49
+
50
+ export function createSmoothClipRef(id: number): SmoothClipRef {
51
+ return { id } as InternalSmoothClipRef;
52
+ }
@@ -0,0 +1,6 @@
1
+ import NativeSmoothClipModule from './NativeSmoothClipModule';
2
+
3
+ /** Destroy from the React Native runtime; native forwards to the UI thread. */
4
+ export function destroyController(controllerId: number): void {
5
+ NativeSmoothClipModule.destroyDriver(controllerId);
6
+ }
@@ -0,0 +1,87 @@
1
+ import type {
2
+ CanonicalSmoothClipPresentation,
3
+ ClipGeometry,
4
+ SmoothClipPresentation,
5
+ } from './geometry';
6
+
7
+ export type ClipReduceMotion = 'system' | 'always' | 'never';
8
+
9
+ type SmoothClipAnimationBase = Readonly<{
10
+ /** Resolved per transaction; it is never retained by the controller. */
11
+ reduceMotion?: ClipReduceMotion;
12
+ }>;
13
+
14
+ export type TimingClipAnimation = SmoothClipAnimationBase &
15
+ Readonly<{
16
+ type: 'timing';
17
+ duration: number;
18
+ controlPoints: readonly [number, number, number, number];
19
+ }>;
20
+
21
+ export type SpringClipAnimation = SmoothClipAnimationBase &
22
+ Readonly<{
23
+ type: 'spring';
24
+ mass?: number;
25
+ stiffness?: number;
26
+ damping?: number;
27
+ /** Normalized progress velocity in inverse seconds. */
28
+ velocity?: number;
29
+ /** Relative mechanical energy used to determine settlement. */
30
+ energyThreshold?: number;
31
+ }>;
32
+
33
+ export type SmoothClipAnimation = TimingClipAnimation | SpringClipAnimation;
34
+
35
+ declare const smoothClipRefBrand: unique symbol;
36
+ /** Opaque, worklet-safe identity for one mounted clip host. */
37
+ export type SmoothClipRef = Readonly<{
38
+ readonly [smoothClipRefBrand]: true;
39
+ }>;
40
+
41
+ declare const smoothClipRunBrand: unique symbol;
42
+ /** Opaque identity for a native transaction started on the UI runtime. */
43
+ export type SmoothClipRunHandle = Readonly<{
44
+ readonly [smoothClipRunBrand]: true;
45
+ }>;
46
+
47
+ export type SmoothClipCompletion = Readonly<{
48
+ finished: boolean;
49
+ /** Present only when supplied by the UI-runtime caller. */
50
+ completionTag?: number;
51
+ }>;
52
+
53
+ export type SmoothClipReactRun = Readonly<{
54
+ finished: Promise<boolean>;
55
+ cancel(): void;
56
+ }>;
57
+
58
+ export type SmoothClipControllerOptions = Readonly<{
59
+ /** Stable React-runtime callback for UI- and React-runtime transactions. */
60
+ onAnimationComplete?: (result: SmoothClipCompletion) => void;
61
+ }>;
62
+
63
+ export type SmoothClipControllerUI = Readonly<{
64
+ beginInteraction(): CanonicalSmoothClipPresentation;
65
+ setFrame(frame: SmoothClipPresentation): void;
66
+ animateTo(
67
+ target: SmoothClipPresentation,
68
+ animation: SmoothClipAnimation,
69
+ completionTag?: number
70
+ ): SmoothClipRunHandle | null;
71
+ cancel(run: SmoothClipRunHandle): CanonicalSmoothClipPresentation;
72
+ }>;
73
+
74
+ export type SmoothClipControllerReact = Readonly<{
75
+ animateTo(
76
+ target: SmoothClipPresentation,
77
+ animation: SmoothClipAnimation
78
+ ): SmoothClipReactRun;
79
+ }>;
80
+
81
+ export type SmoothClipController = Readonly<{
82
+ ref: SmoothClipRef;
83
+ ui: SmoothClipControllerUI;
84
+ react: SmoothClipControllerReact;
85
+ }>;
86
+
87
+ export type SmoothClipInitialFrame = ClipGeometry | SmoothClipPresentation;
@@ -0,0 +1 @@
1
+ export { useSmoothClipController } from './controllers.native';
@@ -0,0 +1 @@
1
+ export { useSmoothClipController } from './controllers.native';
@@ -0,0 +1,104 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { scheduleOnUI } from 'react-native-worklets';
3
+ import type {
4
+ SmoothClipController,
5
+ SmoothClipControllerOptions,
6
+ SmoothClipInitialFrame,
7
+ } from './controllerTypes';
8
+ import { createSmoothClipRef, setControllerRef } from './controllerInternals';
9
+ import { destroyController } from './controllerLifecycle';
10
+ import { allocateSmoothClipId } from './ids';
11
+ import {
12
+ canonicalizeClipPresentation,
13
+ createClipPresentation,
14
+ type CanonicalSmoothClipPresentation,
15
+ } from './geometry';
16
+ import { useSmoothClipGroup } from './groups.native';
17
+ import { presentationPacket } from './presentationCodec';
18
+ import NativeSmoothClipModule from './smoothClipNative';
19
+
20
+ const setClipPresentationHostFunction =
21
+ NativeSmoothClipModule.setClipPresentation;
22
+
23
+ export function useSmoothClipController(
24
+ initialValue: SmoothClipInitialFrame,
25
+ options: SmoothClipControllerOptions = {}
26
+ ): SmoothClipController {
27
+ // A controller is intentionally a one-member transaction group. This keeps
28
+ // validation, native dispatch, cancellation, completion, and lifecycle races
29
+ // on the same path as multi-member transitions.
30
+ const group = useSmoothClipGroup(options);
31
+ const initialRequested =
32
+ 'clip' in initialValue
33
+ ? initialValue
34
+ : createClipPresentation(initialValue);
35
+ const canonicalInitial = canonicalizeClipPresentation(initialRequested);
36
+ if (canonicalInitial === null) {
37
+ throw new Error('[SmoothClipView] Initial presentation must be finite.');
38
+ }
39
+ const initialFrameRef = useRef<CanonicalSmoothClipPresentation | null>(null);
40
+ initialFrameRef.current ??= canonicalInitial;
41
+ const initialFrame = initialFrameRef.current;
42
+
43
+ const idRef = useRef(0);
44
+ const controllerRef = useRef<SmoothClipController | null>(null);
45
+ if (idRef.current === 0) idRef.current = allocateSmoothClipId();
46
+ const controllerId = idRef.current;
47
+
48
+ if (controllerRef.current === null) {
49
+ const ref = createSmoothClipRef(controllerId);
50
+ const controller: SmoothClipController = {
51
+ ref,
52
+ ui: {
53
+ beginInteraction() {
54
+ 'worklet';
55
+ return group.ui.beginInteraction([ref])[0]?.frame ?? initialFrame;
56
+ },
57
+ setFrame(frame) {
58
+ 'worklet';
59
+ group.ui.setFrames([{ clip: ref, frame }]);
60
+ },
61
+ animateTo(target, animation, completionTag = 0) {
62
+ 'worklet';
63
+ return group.ui.animateTo(
64
+ [{ clip: ref, target }],
65
+ animation,
66
+ completionTag
67
+ );
68
+ },
69
+ cancel(run) {
70
+ 'worklet';
71
+ return group.ui.cancel(run)[0]?.frame ?? initialFrame;
72
+ },
73
+ },
74
+ react: {
75
+ animateTo(target, animation) {
76
+ return group.react.animateTo([{ clip: ref, target }], animation);
77
+ },
78
+ },
79
+ };
80
+ setControllerRef(controller, { ref, initialFrame });
81
+ controllerRef.current = controller;
82
+ }
83
+
84
+ useEffect(() => {
85
+ scheduleOnUI(
86
+ (id: number, frame: CanonicalSmoothClipPresentation) => {
87
+ 'worklet';
88
+ setClipPresentationHostFunction(
89
+ id,
90
+ presentationPacket(frame),
91
+ true,
92
+ false
93
+ );
94
+ },
95
+ controllerId,
96
+ initialFrame
97
+ );
98
+ return () => {
99
+ destroyController(controllerId);
100
+ };
101
+ }, [controllerId, initialFrame]);
102
+
103
+ return controllerRef.current;
104
+ }
@@ -0,0 +1 @@
1
+ export { useSmoothClipController } from './controllers.native';