react-native-smooth-clip-view 0.1.0 → 0.2.1
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.
- package/README.md +171 -43
- package/SmoothClipView.podspec +8 -2
- package/android/CMakeLists.txt +39 -0
- package/android/build.gradle +69 -2
- package/android/proguard-rules.pro +6 -0
- package/android/src/main/cpp/SmoothClipAndroid.h +59 -0
- package/android/src/main/cpp/SmoothClipBindings.cpp +428 -0
- package/android/src/main/cpp/SmoothClipRegistry.cpp +945 -0
- package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +25 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +55 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +128 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +164 -30
- package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +107 -10
- package/android/src/main/java/com/smoothclipview/SmoothClipViewPackage.kt +18 -2
- package/cpp/SmoothClipRegistry.h +93 -0
- package/cpp/SmoothClipSharedGeometry.h +50 -0
- package/ios/SmoothClipModuleProvider.h +9 -0
- package/ios/SmoothClipModuleProvider.mm +16 -0
- package/ios/SmoothClipRegistry.mm +754 -0
- package/ios/SmoothClipTurboModule.cpp +290 -0
- package/ios/SmoothClipTurboModule.h +132 -0
- package/ios/SmoothClipView.mm +976 -85
- package/ios/SmoothClipViewRegistry.h +27 -0
- package/lib/module/NativeSmoothClipModule.js +5 -0
- package/lib/module/NativeSmoothClipModule.js.map +1 -0
- package/lib/module/SmoothClipView.android.js +4 -0
- package/lib/module/SmoothClipView.android.js.map +1 -0
- package/lib/module/SmoothClipView.ios.js +34 -0
- package/lib/module/SmoothClipView.ios.js.map +1 -0
- package/lib/module/SmoothClipView.js +26 -12
- package/lib/module/SmoothClipView.js.map +1 -1
- package/lib/module/SmoothClipView.web.js +28 -12
- package/lib/module/SmoothClipView.web.js.map +1 -1
- package/lib/module/SmoothClipViewNativeComponent.ts +14 -1
- package/lib/module/driverState.js +102 -0
- package/lib/module/driverState.js.map +1 -0
- package/lib/module/driverTypes.js +4 -0
- package/lib/module/driverTypes.js.map +1 -0
- package/lib/module/drivers.android.js +4 -0
- package/lib/module/drivers.android.js.map +1 -0
- package/lib/module/drivers.ios.js +380 -0
- package/lib/module/drivers.ios.js.map +1 -0
- package/lib/module/drivers.js +276 -0
- package/lib/module/drivers.js.map +1 -0
- package/lib/module/geometry.js +19 -0
- package/lib/module/geometry.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +2 -0
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/nativeCompletion.js +21 -0
- package/lib/module/nativeCompletion.js.map +1 -0
- package/lib/module/reactRequests.js +50 -0
- package/lib/module/reactRequests.js.map +1 -0
- package/lib/module/smoothClipNative.android.js +15 -0
- package/lib/module/smoothClipNative.android.js.map +1 -0
- package/lib/module/smoothClipNative.js +8 -0
- package/lib/module/smoothClipNative.js.map +1 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts +19 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -0
- package/lib/typescript/src/SmoothClipView.android.d.ts +3 -0
- package/lib/typescript/src/SmoothClipView.android.d.ts.map +1 -0
- package/lib/typescript/src/SmoothClipView.d.ts +5 -6
- package/lib/typescript/src/SmoothClipView.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipView.ios.d.ts +9 -0
- package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -0
- package/lib/typescript/src/SmoothClipView.web.d.ts +5 -7
- package/lib/typescript/src/SmoothClipView.web.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +4 -0
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/driverState.d.ts +31 -0
- package/lib/typescript/src/driverState.d.ts.map +1 -0
- package/lib/typescript/src/driverTypes.d.ts +61 -0
- package/lib/typescript/src/driverTypes.d.ts.map +1 -0
- package/lib/typescript/src/drivers.android.d.ts +3 -0
- package/lib/typescript/src/drivers.android.d.ts.map +1 -0
- package/lib/typescript/src/drivers.d.ts +5 -0
- package/lib/typescript/src/drivers.d.ts.map +1 -0
- package/lib/typescript/src/drivers.ios.d.ts +5 -0
- package/lib/typescript/src/drivers.ios.d.ts.map +1 -0
- package/lib/typescript/src/geometry.d.ts +8 -0
- package/lib/typescript/src/geometry.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +4 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +4 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/nativeCompletion.d.ts +7 -0
- package/lib/typescript/src/nativeCompletion.d.ts.map +1 -0
- package/lib/typescript/src/reactRequests.d.ts +7 -0
- package/lib/typescript/src/reactRequests.d.ts.map +1 -0
- package/lib/typescript/src/smoothClipNative.android.d.ts +4 -0
- package/lib/typescript/src/smoothClipNative.android.d.ts.map +1 -0
- package/lib/typescript/src/smoothClipNative.d.ts +3 -0
- package/lib/typescript/src/smoothClipNative.d.ts.map +1 -0
- package/package.json +12 -7
- package/src/NativeSmoothClipModule.ts +104 -0
- package/src/SmoothClipView.android.tsx +2 -0
- package/src/SmoothClipView.ios.tsx +36 -0
- package/src/SmoothClipView.tsx +31 -27
- package/src/SmoothClipView.web.tsx +26 -22
- package/src/SmoothClipViewNativeComponent.ts +14 -1
- package/src/driverState.ts +150 -0
- package/src/driverTypes.ts +91 -0
- package/src/drivers.android.ts +6 -0
- package/src/drivers.ios.ts +665 -0
- package/src/drivers.ts +416 -0
- package/src/geometry.ts +39 -0
- package/src/index.ts +19 -1
- package/src/index.web.ts +19 -1
- package/src/nativeCompletion.ts +37 -0
- package/src/reactRequests.ts +64 -0
- package/src/smoothClipNative.android.ts +20 -0
- package/src/smoothClipNative.ts +5 -0
|
@@ -1,62 +1,66 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ReactNode, useEffect } from 'react';
|
|
2
2
|
import { type ViewProps, type ViewStyle } from 'react-native';
|
|
3
3
|
import Animated, {
|
|
4
4
|
useAnimatedReaction,
|
|
5
5
|
useAnimatedStyle,
|
|
6
6
|
useSharedValue,
|
|
7
|
-
type SharedValue,
|
|
8
7
|
} from 'react-native-reanimated';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
type ClipGeometry,
|
|
13
|
-
} from './geometry';
|
|
8
|
+
import type { SmoothClipDriver } from './driverTypes';
|
|
9
|
+
import { getDriverState, registerDriverView } from './driverState';
|
|
10
|
+
import { clipPresentationEquals, isFiniteClipPresentation } from './geometry';
|
|
14
11
|
import { createWebClipPath } from './webClipPath';
|
|
15
12
|
|
|
16
13
|
export type SmoothClipViewProps = ViewProps & {
|
|
17
|
-
|
|
18
|
-
animatedClip: SharedValue<ClipGeometry>;
|
|
14
|
+
driver: SmoothClipDriver;
|
|
19
15
|
children?: ReactNode;
|
|
20
16
|
};
|
|
21
17
|
|
|
22
|
-
/**
|
|
18
|
+
/** Fixed-layout CSS fallback. */
|
|
23
19
|
export function SmoothClipView({
|
|
24
|
-
|
|
25
|
-
animatedClip,
|
|
20
|
+
driver,
|
|
26
21
|
children,
|
|
27
22
|
style,
|
|
28
23
|
...viewProps
|
|
29
24
|
}: SmoothClipViewProps) {
|
|
30
|
-
const
|
|
25
|
+
const { initialPresentation, source } = getDriverState(driver);
|
|
26
|
+
useEffect(() => registerDriverView(driver), [driver]);
|
|
27
|
+
const acceptedPresentation = useSharedValue(initialPresentation);
|
|
31
28
|
const initialClipStyle = {
|
|
32
|
-
clipPath: createWebClipPath(
|
|
29
|
+
clipPath: createWebClipPath(initialPresentation.clip),
|
|
33
30
|
overflow: 'hidden',
|
|
34
31
|
} as unknown as ViewStyle;
|
|
35
32
|
|
|
36
33
|
useAnimatedReaction(
|
|
37
|
-
() =>
|
|
38
|
-
(
|
|
34
|
+
() => source.value,
|
|
35
|
+
(presentation, previousPresentation) => {
|
|
39
36
|
if (
|
|
40
|
-
|
|
41
|
-
!
|
|
37
|
+
isFiniteClipPresentation(presentation) &&
|
|
38
|
+
!clipPresentationEquals(previousPresentation, presentation)
|
|
42
39
|
) {
|
|
43
|
-
|
|
40
|
+
acceptedPresentation.value = presentation;
|
|
44
41
|
}
|
|
45
42
|
},
|
|
46
|
-
[
|
|
43
|
+
[source, acceptedPresentation]
|
|
47
44
|
);
|
|
48
45
|
|
|
49
46
|
const clipStyle = useAnimatedStyle(() => {
|
|
50
|
-
const clip =
|
|
47
|
+
const clip = acceptedPresentation.value.clip;
|
|
51
48
|
return {
|
|
52
49
|
clipPath: createWebClipPath(clip),
|
|
53
50
|
overflow: 'hidden',
|
|
54
51
|
};
|
|
55
52
|
});
|
|
56
53
|
|
|
54
|
+
const contentStyle = useAnimatedStyle(() => ({
|
|
55
|
+
transform: [
|
|
56
|
+
{ translateX: acceptedPresentation.value.contentTranslateX },
|
|
57
|
+
{ translateY: acceptedPresentation.value.contentTranslateY },
|
|
58
|
+
],
|
|
59
|
+
}));
|
|
60
|
+
|
|
57
61
|
return (
|
|
58
62
|
<Animated.View {...viewProps} style={[style, initialClipStyle, clipStyle]}>
|
|
59
|
-
{children}
|
|
63
|
+
<Animated.View style={contentStyle}>{children}</Animated.View>
|
|
60
64
|
</Animated.View>
|
|
61
65
|
);
|
|
62
66
|
}
|
|
@@ -7,11 +7,14 @@ import {
|
|
|
7
7
|
} from 'react-native';
|
|
8
8
|
|
|
9
9
|
export interface NativeProps extends ViewProps {
|
|
10
|
+
driverId: CodegenTypes.Double;
|
|
10
11
|
initialClipX: CodegenTypes.Double;
|
|
11
12
|
initialClipY: CodegenTypes.Double;
|
|
12
13
|
initialClipWidth: CodegenTypes.Double;
|
|
13
14
|
initialClipHeight: CodegenTypes.Double;
|
|
14
15
|
initialClipRadius: CodegenTypes.Double;
|
|
16
|
+
initialContentTranslateX: CodegenTypes.Double;
|
|
17
|
+
initialContentTranslateY: CodegenTypes.Double;
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
interface NativeCommands {
|
|
@@ -23,10 +26,20 @@ interface NativeCommands {
|
|
|
23
26
|
height: CodegenTypes.Double,
|
|
24
27
|
radius: CodegenTypes.Double
|
|
25
28
|
) => void;
|
|
29
|
+
setClipPresentation: (
|
|
30
|
+
viewRef: React.ElementRef<HostComponent<NativeProps>>,
|
|
31
|
+
x: CodegenTypes.Double,
|
|
32
|
+
y: CodegenTypes.Double,
|
|
33
|
+
width: CodegenTypes.Double,
|
|
34
|
+
height: CodegenTypes.Double,
|
|
35
|
+
radius: CodegenTypes.Double,
|
|
36
|
+
contentTranslateX: CodegenTypes.Double,
|
|
37
|
+
contentTranslateY: CodegenTypes.Double
|
|
38
|
+
) => void;
|
|
26
39
|
}
|
|
27
40
|
|
|
28
41
|
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
|
29
|
-
supportedCommands: ['setClipGeometry'],
|
|
42
|
+
supportedCommands: ['setClipGeometry', 'setClipPresentation'],
|
|
30
43
|
});
|
|
31
44
|
|
|
32
45
|
export default codegenNativeComponent<NativeProps>(
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
2
|
+
import type { ClipAnimationResult, SmoothClipDriver } from './driverTypes';
|
|
3
|
+
import type { SmoothClipPresentation } from './geometry';
|
|
4
|
+
|
|
5
|
+
export type DriverState = {
|
|
6
|
+
driverId: number;
|
|
7
|
+
initialPresentation: SmoothClipPresentation;
|
|
8
|
+
source: SharedValue<SmoothClipPresentation>;
|
|
9
|
+
activeAnimationId?: SharedValue<number>;
|
|
10
|
+
ownership?: SharedValue<number>;
|
|
11
|
+
onAnimationComplete: {
|
|
12
|
+
current: ((result: ClipAnimationResult) => void) | undefined;
|
|
13
|
+
};
|
|
14
|
+
mountedViews: Set<object>;
|
|
15
|
+
animationParticipants: Map<number, Set<object>>;
|
|
16
|
+
failedAnimations: Set<number>;
|
|
17
|
+
completionDeferrals: number;
|
|
18
|
+
deferredCompletions: ClipAnimationResult[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const states = new WeakMap<SmoothClipDriver, DriverState>();
|
|
22
|
+
const statesById = new Map<number, DriverState>();
|
|
23
|
+
let nextDriverId = Date.now() * 1024;
|
|
24
|
+
|
|
25
|
+
export function allocateDriverId(): number {
|
|
26
|
+
nextDriverId += 1;
|
|
27
|
+
if (!Number.isSafeInteger(nextDriverId)) nextDriverId = 1;
|
|
28
|
+
return nextDriverId;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function setDriverState(
|
|
32
|
+
driver: SmoothClipDriver,
|
|
33
|
+
state: DriverState
|
|
34
|
+
): void {
|
|
35
|
+
// WeakMap-only: safe to call from render (discarded renders leave nothing
|
|
36
|
+
// reachable) and survives effect replays so getDriverState keeps working.
|
|
37
|
+
states.set(driver, state);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// The strong by-id index is attached in the driver hook's effect and detached
|
|
41
|
+
// in its cleanup, so discarded renders never leak entries and StrictMode /
|
|
42
|
+
// <Activity> effect replays can re-attach the same state.
|
|
43
|
+
export function attachDriverState(state: DriverState): void {
|
|
44
|
+
statesById.set(state.driverId, state);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function detachDriverState(state: DriverState): void {
|
|
48
|
+
if (statesById.get(state.driverId) === state) {
|
|
49
|
+
statesById.delete(state.driverId);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function createDriverState(
|
|
54
|
+
driverId: number,
|
|
55
|
+
initialPresentation: SmoothClipPresentation,
|
|
56
|
+
source: SharedValue<SmoothClipPresentation>,
|
|
57
|
+
onAnimationComplete: DriverState['onAnimationComplete'],
|
|
58
|
+
activeAnimationId?: SharedValue<number>,
|
|
59
|
+
ownership?: SharedValue<number>
|
|
60
|
+
): DriverState {
|
|
61
|
+
return {
|
|
62
|
+
driverId,
|
|
63
|
+
initialPresentation,
|
|
64
|
+
source,
|
|
65
|
+
activeAnimationId,
|
|
66
|
+
ownership,
|
|
67
|
+
onAnimationComplete,
|
|
68
|
+
mountedViews: new Set(),
|
|
69
|
+
animationParticipants: new Map(),
|
|
70
|
+
failedAnimations: new Set(),
|
|
71
|
+
completionDeferrals: 0,
|
|
72
|
+
deferredCompletions: [],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function registerDriverView(driver: SmoothClipDriver): () => void {
|
|
77
|
+
const state = getDriverState(driver);
|
|
78
|
+
const token = {};
|
|
79
|
+
state.mountedViews.add(token);
|
|
80
|
+
return () => {
|
|
81
|
+
state.mountedViews.delete(token);
|
|
82
|
+
for (const [animationId, participants] of state.animationParticipants) {
|
|
83
|
+
if (participants.has(token)) state.failedAnimations.add(animationId);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function snapshotDriverViews(
|
|
89
|
+
driverId: number,
|
|
90
|
+
animationId: number
|
|
91
|
+
): void {
|
|
92
|
+
const state = statesById.get(driverId);
|
|
93
|
+
if (state) {
|
|
94
|
+
state.animationParticipants.set(animationId, new Set(state.mountedViews));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function finishDriverAnimation(
|
|
99
|
+
driverId: number,
|
|
100
|
+
animationId: number,
|
|
101
|
+
finished: boolean
|
|
102
|
+
): boolean {
|
|
103
|
+
const state = statesById.get(driverId);
|
|
104
|
+
if (!state) return finished;
|
|
105
|
+
const result = finished && !state.failedAnimations.has(animationId);
|
|
106
|
+
state.animationParticipants.delete(animationId);
|
|
107
|
+
state.failedAnimations.delete(animationId);
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function deliverDriverCompletion(
|
|
112
|
+
driverId: number,
|
|
113
|
+
animationId: number,
|
|
114
|
+
finished: boolean
|
|
115
|
+
): void {
|
|
116
|
+
const state = statesById.get(driverId);
|
|
117
|
+
if (!state) return;
|
|
118
|
+
const result = { animationId, finished };
|
|
119
|
+
if (state.completionDeferrals > 0) {
|
|
120
|
+
state.deferredCompletions.push(result);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
state.onAnimationComplete.current?.(result);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function deferDriverCompletions(driverId: number): void {
|
|
127
|
+
const state = statesById.get(driverId);
|
|
128
|
+
if (state) state.completionDeferrals += 1;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function releaseDriverCompletions(driverId: number): void {
|
|
132
|
+
const state = statesById.get(driverId);
|
|
133
|
+
if (!state || state.completionDeferrals === 0) return;
|
|
134
|
+
state.completionDeferrals -= 1;
|
|
135
|
+
if (state.completionDeferrals !== 0) return;
|
|
136
|
+
const deferred = state.deferredCompletions.splice(0);
|
|
137
|
+
for (const result of deferred) {
|
|
138
|
+
state.onAnimationComplete.current?.(result);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function getDriverState(driver: SmoothClipDriver): DriverState {
|
|
143
|
+
const state = states.get(driver);
|
|
144
|
+
if (!state) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
'[SmoothClipView] Drivers must be created by useSmoothClipDriver.'
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return state;
|
|
150
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
2
|
+
import type { SmoothClipPresentation } from './geometry';
|
|
3
|
+
|
|
4
|
+
export type ClipReduceMotion = 'system' | 'always' | 'never';
|
|
5
|
+
|
|
6
|
+
export type TimingClipAnimation = Readonly<{
|
|
7
|
+
type: 'timing';
|
|
8
|
+
duration: number;
|
|
9
|
+
controlPoints: readonly [number, number, number, number];
|
|
10
|
+
}>;
|
|
11
|
+
|
|
12
|
+
export type SpringClipAnimation = Readonly<{
|
|
13
|
+
type: 'spring';
|
|
14
|
+
mass?: number;
|
|
15
|
+
stiffness?: number;
|
|
16
|
+
damping?: number;
|
|
17
|
+
initialVelocity?: number | 'inherit';
|
|
18
|
+
}>;
|
|
19
|
+
|
|
20
|
+
export type KeyframedClipAnimation = Readonly<{
|
|
21
|
+
type: 'keyframes';
|
|
22
|
+
duration: number;
|
|
23
|
+
frames: readonly Readonly<{
|
|
24
|
+
offset: number;
|
|
25
|
+
presentation: SmoothClipPresentation;
|
|
26
|
+
}>[];
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
export type SmoothClipAnimation =
|
|
30
|
+
TimingClipAnimation | SpringClipAnimation | KeyframedClipAnimation;
|
|
31
|
+
|
|
32
|
+
export type ClipAnimationResult = Readonly<{
|
|
33
|
+
animationId: number;
|
|
34
|
+
finished: boolean;
|
|
35
|
+
}>;
|
|
36
|
+
|
|
37
|
+
export type SmoothClipDriverOptions = Readonly<{
|
|
38
|
+
reduceMotion?: ClipReduceMotion;
|
|
39
|
+
onAnimationComplete?: (result: ClipAnimationResult) => void;
|
|
40
|
+
}>;
|
|
41
|
+
|
|
42
|
+
export type SmoothClipUIControls = Readonly<{
|
|
43
|
+
beginInteraction(): SmoothClipPresentation;
|
|
44
|
+
set(presentation: SmoothClipPresentation): void;
|
|
45
|
+
/**
|
|
46
|
+
* Per-frame hot path: writes geometry straight to native without touching
|
|
47
|
+
* `driver.presentation`. Skips SharedValue bookkeeping (dirty marking, RN
|
|
48
|
+
* mirror sync, listener dispatch) for high-frequency streams such as
|
|
49
|
+
* gestures. `driver.presentation.value` is stale after hot writes by design;
|
|
50
|
+
* `beginInteraction()` remains the source of truth for visible geometry.
|
|
51
|
+
* Do not interleave with `presentation.value` writes on the same driver —
|
|
52
|
+
* the listener's duplicate suppression may skip a later equal value.
|
|
53
|
+
*/
|
|
54
|
+
setScalars(
|
|
55
|
+
x: number,
|
|
56
|
+
y: number,
|
|
57
|
+
width: number,
|
|
58
|
+
height: number,
|
|
59
|
+
radius: number,
|
|
60
|
+
contentTranslateX: number,
|
|
61
|
+
contentTranslateY: number
|
|
62
|
+
): void;
|
|
63
|
+
animateTo(
|
|
64
|
+
presentation: SmoothClipPresentation,
|
|
65
|
+
animation: SmoothClipAnimation
|
|
66
|
+
): number;
|
|
67
|
+
cancel(
|
|
68
|
+
animationId?: number,
|
|
69
|
+
behavior?: 'current' | 'target'
|
|
70
|
+
): SmoothClipPresentation;
|
|
71
|
+
}>;
|
|
72
|
+
|
|
73
|
+
export type SmoothClipReactControls = Readonly<{
|
|
74
|
+
beginInteraction(): Promise<SmoothClipPresentation>;
|
|
75
|
+
set(presentation: SmoothClipPresentation): Promise<void>;
|
|
76
|
+
animateTo(
|
|
77
|
+
presentation: SmoothClipPresentation,
|
|
78
|
+
animation: SmoothClipAnimation
|
|
79
|
+
): Promise<number>;
|
|
80
|
+
cancel(
|
|
81
|
+
animationId?: number,
|
|
82
|
+
behavior?: 'current' | 'target'
|
|
83
|
+
): Promise<SmoothClipPresentation>;
|
|
84
|
+
}>;
|
|
85
|
+
|
|
86
|
+
export type SmoothClipDriver = Readonly<{
|
|
87
|
+
kind: 'hybrid';
|
|
88
|
+
presentation: SharedValue<SmoothClipPresentation>;
|
|
89
|
+
ui: SmoothClipUIControls;
|
|
90
|
+
react: SmoothClipReactControls;
|
|
91
|
+
}>;
|