react-native-smooth-clip-view 0.2.8 → 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.
- package/README.md +86 -21
- package/android/CMakeLists.txt +7 -0
- package/android/build.gradle +14 -2
- package/android/proguard-rules.pro +3 -3
- package/android/src/main/cpp/SmoothClipAndroid.h +10 -0
- package/android/src/main/cpp/SmoothClipBindings.cpp +896 -6
- package/android/src/main/cpp/SmoothClipRegistry.cpp +1067 -46
- package/android/src/main/cpp/SmoothClipTrace.h +25 -0
- package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +265 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +21 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +283 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +385 -24
- package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +138 -24
- package/cpp/SmoothClipAnimationCurve.h +151 -122
- package/cpp/SmoothClipRegistry.h +102 -4
- package/cpp/SmoothClipSharedGeometry.h +146 -7
- package/cpp/SmoothClipVelocityTracker.h +13 -9
- package/ios/SmoothClipGeometry.h +184 -6
- package/ios/SmoothClipRegistry.mm +1033 -25
- package/ios/SmoothClipRegistrySnapshot.h +13 -0
- package/ios/SmoothClipTurboModule.cpp +857 -2
- package/ios/SmoothClipTurboModule.h +310 -0
- package/ios/SmoothClipView.mm +714 -183
- package/ios/SmoothClipViewRegistry.h +1 -0
- package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/lib/module/NativeSmoothClipModule.js.map +1 -1
- package/lib/module/SmoothClipView.ios.js +22 -6
- package/lib/module/SmoothClipView.ios.js.map +1 -1
- package/lib/module/SmoothClipView.js +1 -46
- package/lib/module/SmoothClipView.js.map +1 -1
- package/lib/module/SmoothClipViewNativeComponent.ts +27 -1
- package/lib/module/capabilities.js +4 -0
- package/lib/module/capabilities.js.map +1 -0
- package/lib/module/capabilities.native.js +36 -0
- package/lib/module/capabilities.native.js.map +1 -0
- package/lib/module/capabilityTypes.js +11 -0
- package/lib/module/capabilityTypes.js.map +1 -0
- package/lib/module/driverState.js +0 -28
- package/lib/module/driverState.js.map +1 -1
- package/lib/module/drivers.js +1 -281
- package/lib/module/drivers.js.map +1 -1
- package/lib/module/drivers.native.js +340 -75
- package/lib/module/drivers.native.js.map +1 -1
- package/lib/module/geometry.js +147 -17
- package/lib/module/geometry.js.map +1 -1
- package/lib/module/groupDriverTypes.js +4 -0
- package/lib/module/groupDriverTypes.js.map +1 -0
- package/lib/module/groupDrivers.android.js +4 -0
- package/lib/module/groupDrivers.android.js.map +1 -0
- package/lib/module/groupDrivers.ios.js +4 -0
- package/lib/module/groupDrivers.ios.js.map +1 -0
- package/lib/module/groupDrivers.js +4 -0
- package/lib/module/groupDrivers.js.map +1 -0
- package/lib/module/groupDrivers.native.js +799 -0
- package/lib/module/groupDrivers.native.js.map +1 -0
- package/lib/module/index.js +3 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/presentationProtocol.js +15 -0
- package/lib/module/presentationProtocol.js.map +1 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts +25 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipView.d.ts +2 -10
- package/lib/typescript/src/SmoothClipView.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipView.ios.d.ts +133 -2
- package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +8 -0
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/capabilities.d.ts +3 -0
- package/lib/typescript/src/capabilities.d.ts.map +1 -0
- package/lib/typescript/src/capabilities.native.d.ts +3 -0
- package/lib/typescript/src/capabilities.native.d.ts.map +1 -0
- package/lib/typescript/src/capabilityTypes.d.ts +10 -0
- package/lib/typescript/src/capabilityTypes.d.ts.map +1 -0
- package/lib/typescript/src/driverState.d.ts +1 -6
- package/lib/typescript/src/driverState.d.ts.map +1 -1
- package/lib/typescript/src/driverTypes.d.ts +39 -11
- package/lib/typescript/src/driverTypes.d.ts.map +1 -1
- package/lib/typescript/src/drivers.d.ts +2 -4
- package/lib/typescript/src/drivers.d.ts.map +1 -1
- package/lib/typescript/src/drivers.native.d.ts.map +1 -1
- package/lib/typescript/src/geometry.d.ts +36 -2
- package/lib/typescript/src/geometry.d.ts.map +1 -1
- package/lib/typescript/src/groupDriverTypes.d.ts +66 -0
- package/lib/typescript/src/groupDriverTypes.d.ts.map +1 -0
- package/lib/typescript/src/groupDrivers.android.d.ts +2 -0
- package/lib/typescript/src/groupDrivers.android.d.ts.map +1 -0
- package/lib/typescript/src/groupDrivers.d.ts +2 -0
- package/lib/typescript/src/groupDrivers.d.ts.map +1 -0
- package/lib/typescript/src/groupDrivers.ios.d.ts +2 -0
- package/lib/typescript/src/groupDrivers.ios.d.ts.map +1 -0
- package/lib/typescript/src/groupDrivers.native.d.ts +4 -0
- package/lib/typescript/src/groupDrivers.native.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +6 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/presentationProtocol.d.ts +4 -0
- package/lib/typescript/src/presentationProtocol.d.ts.map +1 -0
- package/package.json +10 -11
- package/src/NativeSmoothClipModule.ts +275 -0
- package/src/SmoothClipView.ios.tsx +30 -11
- package/src/SmoothClipView.tsx +2 -76
- package/src/SmoothClipViewNativeComponent.ts +27 -1
- package/src/capabilities.native.ts +69 -0
- package/src/capabilities.ts +2 -0
- package/src/capabilityTypes.ts +17 -0
- package/src/driverState.ts +1 -41
- package/src/driverTypes.ts +56 -11
- package/src/drivers.native.ts +921 -151
- package/src/drivers.ts +2 -423
- package/src/geometry.ts +231 -27
- package/src/groupDriverTypes.ts +117 -0
- package/src/groupDrivers.android.ts +1 -0
- package/src/groupDrivers.ios.ts +1 -0
- package/src/groupDrivers.native.ts +1189 -0
- package/src/groupDrivers.ts +1 -0
- package/src/index.ts +30 -2
- package/src/presentationProtocol.ts +28 -0
- package/lib/module/SmoothClipView.web.js +0 -54
- package/lib/module/SmoothClipView.web.js.map +0 -1
- package/lib/module/index.web.js +0 -8
- package/lib/module/index.web.js.map +0 -1
- package/lib/module/webClipPath.js +0 -25
- package/lib/module/webClipPath.js.map +0 -1
- package/lib/typescript/src/SmoothClipView.web.d.ts +0 -10
- package/lib/typescript/src/SmoothClipView.web.d.ts.map +0 -1
- package/lib/typescript/src/index.web.d.ts +0 -9
- package/lib/typescript/src/index.web.d.ts.map +0 -1
- package/lib/typescript/src/webClipPath.d.ts +0 -7
- package/lib/typescript/src/webClipPath.d.ts.map +0 -1
- package/src/SmoothClipView.web.tsx +0 -66
- package/src/index.web.ts +0 -23
- package/src/webClipPath.ts +0 -30
package/src/geometry.ts
CHANGED
|
@@ -1,9 +1,31 @@
|
|
|
1
|
+
export type ClipCurve = 'circular' | 'continuous';
|
|
2
|
+
|
|
1
3
|
export type ClipGeometry = Readonly<{
|
|
2
4
|
x: number;
|
|
3
5
|
y: number;
|
|
4
6
|
width: number;
|
|
5
7
|
height: number;
|
|
8
|
+
/** Default for every corner without an explicit override. */
|
|
6
9
|
radius: number;
|
|
10
|
+
topLeftRadius?: number;
|
|
11
|
+
topRightRadius?: number;
|
|
12
|
+
bottomRightRadius?: number;
|
|
13
|
+
bottomLeftRadius?: number;
|
|
14
|
+
curve?: ClipCurve;
|
|
15
|
+
}>;
|
|
16
|
+
|
|
17
|
+
export type CanonicalClipGeometry = Readonly<{
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
/** Normalized legacy all-corners value retained for V1 compatibility. */
|
|
23
|
+
radius: number;
|
|
24
|
+
topLeftRadius: number;
|
|
25
|
+
topRightRadius: number;
|
|
26
|
+
bottomRightRadius: number;
|
|
27
|
+
bottomLeftRadius: number;
|
|
28
|
+
curve: ClipCurve;
|
|
7
29
|
}>;
|
|
8
30
|
|
|
9
31
|
export type ClipBounds = Readonly<{
|
|
@@ -15,15 +37,25 @@ export type SmoothClipPresentation = Readonly<{
|
|
|
15
37
|
clip: ClipGeometry;
|
|
16
38
|
contentTranslateX: number;
|
|
17
39
|
contentTranslateY: number;
|
|
40
|
+
/** Defaults to 1 when omitted. */
|
|
41
|
+
contentScale?: number;
|
|
18
42
|
}>;
|
|
19
43
|
|
|
20
|
-
export
|
|
21
|
-
clip:
|
|
22
|
-
contentTranslateX
|
|
23
|
-
contentTranslateY
|
|
24
|
-
|
|
44
|
+
export type CanonicalSmoothClipPresentation = Readonly<{
|
|
45
|
+
clip: CanonicalClipGeometry;
|
|
46
|
+
contentTranslateX: number;
|
|
47
|
+
contentTranslateY: number;
|
|
48
|
+
contentScale: number;
|
|
49
|
+
}>;
|
|
50
|
+
|
|
51
|
+
function isClipCurve(curve: ClipCurve | undefined): boolean {
|
|
25
52
|
'worklet';
|
|
26
|
-
return
|
|
53
|
+
return curve === undefined || curve === 'circular' || curve === 'continuous';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isFiniteOptionalNumber(value: number | undefined): boolean {
|
|
57
|
+
'worklet';
|
|
58
|
+
return value === undefined || Number.isFinite(value);
|
|
27
59
|
}
|
|
28
60
|
|
|
29
61
|
export function isFiniteClipGeometry(geometry: ClipGeometry): boolean {
|
|
@@ -33,10 +65,40 @@ export function isFiniteClipGeometry(geometry: ClipGeometry): boolean {
|
|
|
33
65
|
Number.isFinite(geometry.y) &&
|
|
34
66
|
Number.isFinite(geometry.width) &&
|
|
35
67
|
Number.isFinite(geometry.height) &&
|
|
36
|
-
Number.isFinite(geometry.radius)
|
|
68
|
+
Number.isFinite(geometry.radius) &&
|
|
69
|
+
isFiniteOptionalNumber(geometry.topLeftRadius) &&
|
|
70
|
+
isFiniteOptionalNumber(geometry.topRightRadius) &&
|
|
71
|
+
isFiniteOptionalNumber(geometry.bottomRightRadius) &&
|
|
72
|
+
isFiniteOptionalNumber(geometry.bottomLeftRadius) &&
|
|
73
|
+
isClipCurve(geometry.curve)
|
|
37
74
|
);
|
|
38
75
|
}
|
|
39
76
|
|
|
77
|
+
function resolvedTopLeftRadius(geometry: ClipGeometry): number {
|
|
78
|
+
'worklet';
|
|
79
|
+
return geometry.topLeftRadius ?? geometry.radius;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function resolvedTopRightRadius(geometry: ClipGeometry): number {
|
|
83
|
+
'worklet';
|
|
84
|
+
return geometry.topRightRadius ?? geometry.radius;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function resolvedBottomRightRadius(geometry: ClipGeometry): number {
|
|
88
|
+
'worklet';
|
|
89
|
+
return geometry.bottomRightRadius ?? geometry.radius;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function resolvedBottomLeftRadius(geometry: ClipGeometry): number {
|
|
93
|
+
'worklet';
|
|
94
|
+
return geometry.bottomLeftRadius ?? geometry.radius;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function resolvedCurve(geometry: ClipGeometry): ClipCurve {
|
|
98
|
+
'worklet';
|
|
99
|
+
return geometry.curve ?? 'circular';
|
|
100
|
+
}
|
|
101
|
+
|
|
40
102
|
export function clipGeometryEquals(
|
|
41
103
|
first: ClipGeometry | null,
|
|
42
104
|
second: ClipGeometry
|
|
@@ -48,18 +110,31 @@ export function clipGeometryEquals(
|
|
|
48
110
|
first.y === second.y &&
|
|
49
111
|
first.width === second.width &&
|
|
50
112
|
first.height === second.height &&
|
|
51
|
-
first.radius === second.radius
|
|
113
|
+
first.radius === second.radius &&
|
|
114
|
+
resolvedTopLeftRadius(first) === resolvedTopLeftRadius(second) &&
|
|
115
|
+
resolvedTopRightRadius(first) === resolvedTopRightRadius(second) &&
|
|
116
|
+
resolvedBottomRightRadius(first) === resolvedBottomRightRadius(second) &&
|
|
117
|
+
resolvedBottomLeftRadius(first) === resolvedBottomLeftRadius(second) &&
|
|
118
|
+
resolvedCurve(first) === resolvedCurve(second)
|
|
52
119
|
);
|
|
53
120
|
}
|
|
54
121
|
|
|
122
|
+
function resolvedContentScale(presentation: SmoothClipPresentation): number {
|
|
123
|
+
'worklet';
|
|
124
|
+
return presentation.contentScale ?? 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
55
127
|
export function isFiniteClipPresentation(
|
|
56
128
|
presentation: SmoothClipPresentation
|
|
57
129
|
): boolean {
|
|
58
130
|
'worklet';
|
|
131
|
+
const contentScale = resolvedContentScale(presentation);
|
|
59
132
|
return (
|
|
60
133
|
isFiniteClipGeometry(presentation.clip) &&
|
|
61
134
|
Number.isFinite(presentation.contentTranslateX) &&
|
|
62
|
-
Number.isFinite(presentation.contentTranslateY)
|
|
135
|
+
Number.isFinite(presentation.contentTranslateY) &&
|
|
136
|
+
Number.isFinite(contentScale) &&
|
|
137
|
+
contentScale > 0
|
|
63
138
|
);
|
|
64
139
|
}
|
|
65
140
|
|
|
@@ -72,10 +147,131 @@ export function clipPresentationEquals(
|
|
|
72
147
|
first !== null &&
|
|
73
148
|
clipGeometryEquals(first.clip, second.clip) &&
|
|
74
149
|
first.contentTranslateX === second.contentTranslateX &&
|
|
75
|
-
first.contentTranslateY === second.contentTranslateY
|
|
150
|
+
first.contentTranslateY === second.contentTranslateY &&
|
|
151
|
+
resolvedContentScale(first) === resolvedContentScale(second)
|
|
76
152
|
);
|
|
77
153
|
}
|
|
78
154
|
|
|
155
|
+
function createCanonicalClipGeometry(
|
|
156
|
+
geometry: ClipGeometry,
|
|
157
|
+
x: number,
|
|
158
|
+
y: number,
|
|
159
|
+
width: number,
|
|
160
|
+
height: number
|
|
161
|
+
): CanonicalClipGeometry {
|
|
162
|
+
'worklet';
|
|
163
|
+
const topLeftRadius = Math.max(0, resolvedTopLeftRadius(geometry));
|
|
164
|
+
const topRightRadius = Math.max(0, resolvedTopRightRadius(geometry));
|
|
165
|
+
const bottomRightRadius = Math.max(0, resolvedBottomRightRadius(geometry));
|
|
166
|
+
const bottomLeftRadius = Math.max(0, resolvedBottomLeftRadius(geometry));
|
|
167
|
+
|
|
168
|
+
// CSS corner-overlap reduction uses one common factor so all four corners
|
|
169
|
+
// retain their proportions when either pair exceeds the available edge.
|
|
170
|
+
let scale = 1;
|
|
171
|
+
const top = topLeftRadius + topRightRadius;
|
|
172
|
+
const right = topRightRadius + bottomRightRadius;
|
|
173
|
+
const bottom = bottomLeftRadius + bottomRightRadius;
|
|
174
|
+
const left = topLeftRadius + bottomLeftRadius;
|
|
175
|
+
|
|
176
|
+
if (top > 0) scale = Math.min(scale, width / top);
|
|
177
|
+
if (right > 0) scale = Math.min(scale, height / right);
|
|
178
|
+
if (bottom > 0) scale = Math.min(scale, width / bottom);
|
|
179
|
+
if (left > 0) scale = Math.min(scale, height / left);
|
|
180
|
+
scale = Math.max(0, Math.min(1, scale));
|
|
181
|
+
|
|
182
|
+
const normalizedTopLeftRadius = topLeftRadius * scale;
|
|
183
|
+
const normalizedTopRightRadius = topRightRadius * scale;
|
|
184
|
+
const normalizedBottomRightRadius = bottomRightRadius * scale;
|
|
185
|
+
const normalizedBottomLeftRadius = bottomLeftRadius * scale;
|
|
186
|
+
const radius =
|
|
187
|
+
normalizedTopLeftRadius === normalizedTopRightRadius &&
|
|
188
|
+
normalizedTopRightRadius === normalizedBottomRightRadius &&
|
|
189
|
+
normalizedBottomRightRadius === normalizedBottomLeftRadius
|
|
190
|
+
? normalizedTopLeftRadius
|
|
191
|
+
: 0;
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
x,
|
|
195
|
+
y,
|
|
196
|
+
width,
|
|
197
|
+
height,
|
|
198
|
+
radius,
|
|
199
|
+
topLeftRadius: normalizedTopLeftRadius,
|
|
200
|
+
topRightRadius: normalizedTopRightRadius,
|
|
201
|
+
bottomRightRadius: normalizedBottomRightRadius,
|
|
202
|
+
bottomLeftRadius: normalizedBottomLeftRadius,
|
|
203
|
+
curve: resolvedCurve(geometry),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Expands presentation defaults and applies CSS proportional corner scaling.
|
|
209
|
+
*/
|
|
210
|
+
export function canonicalizeClipGeometry(
|
|
211
|
+
geometry: ClipGeometry
|
|
212
|
+
): CanonicalClipGeometry | null {
|
|
213
|
+
'worklet';
|
|
214
|
+
if (!isFiniteClipGeometry(geometry)) return null;
|
|
215
|
+
|
|
216
|
+
const width = Math.max(0, geometry.width);
|
|
217
|
+
const height = Math.max(0, geometry.height);
|
|
218
|
+
return createCanonicalClipGeometry(
|
|
219
|
+
geometry,
|
|
220
|
+
geometry.x,
|
|
221
|
+
geometry.y,
|
|
222
|
+
width,
|
|
223
|
+
height
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function canonicalizeClipPresentation(
|
|
228
|
+
presentation: SmoothClipPresentation
|
|
229
|
+
): CanonicalSmoothClipPresentation | null {
|
|
230
|
+
'worklet';
|
|
231
|
+
if (!isFiniteClipPresentation(presentation)) return null;
|
|
232
|
+
|
|
233
|
+
const clip = canonicalizeClipGeometry(presentation.clip);
|
|
234
|
+
if (clip === null) return null;
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
clip,
|
|
238
|
+
contentTranslateX: presentation.contentTranslateX,
|
|
239
|
+
contentTranslateY: presentation.contentTranslateY,
|
|
240
|
+
contentScale: resolvedContentScale(presentation),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Keep this below the canonicalization helpers so the worklet never closes
|
|
245
|
+
// over a helper declared later in this module.
|
|
246
|
+
export function createClipPresentation(
|
|
247
|
+
clip: ClipGeometry,
|
|
248
|
+
contentTranslateX = 0,
|
|
249
|
+
contentTranslateY = 0,
|
|
250
|
+
contentScale = 1
|
|
251
|
+
): CanonicalSmoothClipPresentation {
|
|
252
|
+
'worklet';
|
|
253
|
+
const canonicalClip = canonicalizeClipGeometry(clip);
|
|
254
|
+
return {
|
|
255
|
+
// Keep invalid input observably invalid so downstream validation remains
|
|
256
|
+
// atomic instead of accidentally sanitizing a required scalar.
|
|
257
|
+
clip: canonicalClip ?? {
|
|
258
|
+
x: clip.x,
|
|
259
|
+
y: clip.y,
|
|
260
|
+
width: clip.width,
|
|
261
|
+
height: clip.height,
|
|
262
|
+
radius: clip.radius,
|
|
263
|
+
topLeftRadius: resolvedTopLeftRadius(clip),
|
|
264
|
+
topRightRadius: resolvedTopRightRadius(clip),
|
|
265
|
+
bottomRightRadius: resolvedBottomRightRadius(clip),
|
|
266
|
+
bottomLeftRadius: resolvedBottomLeftRadius(clip),
|
|
267
|
+
curve: resolvedCurve(clip),
|
|
268
|
+
},
|
|
269
|
+
contentTranslateX,
|
|
270
|
+
contentTranslateY,
|
|
271
|
+
contentScale,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
79
275
|
/**
|
|
80
276
|
* Mirrors the native geometry contract for tests and non-native fallbacks.
|
|
81
277
|
* Native remains authoritative because its bounds are the actual rendered size.
|
|
@@ -83,19 +279,15 @@ export function clipPresentationEquals(
|
|
|
83
279
|
export function normalizeClipGeometry(
|
|
84
280
|
geometry: ClipGeometry,
|
|
85
281
|
bounds: ClipBounds
|
|
86
|
-
):
|
|
282
|
+
): CanonicalClipGeometry | null {
|
|
87
283
|
'worklet';
|
|
88
|
-
|
|
89
|
-
geometry
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
bounds.height,
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
if (!values.every(Number.isFinite)) return null;
|
|
284
|
+
if (
|
|
285
|
+
!isFiniteClipGeometry(geometry) ||
|
|
286
|
+
!Number.isFinite(bounds.width) ||
|
|
287
|
+
!Number.isFinite(bounds.height)
|
|
288
|
+
) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
99
291
|
|
|
100
292
|
const boundsWidth = Math.max(0, bounds.width);
|
|
101
293
|
const boundsHeight = Math.max(0, bounds.height);
|
|
@@ -112,11 +304,23 @@ export function normalizeClipGeometry(
|
|
|
112
304
|
const width = Math.max(0, right - left);
|
|
113
305
|
const height = Math.max(0, bottom - top);
|
|
114
306
|
|
|
307
|
+
return createCanonicalClipGeometry(geometry, left, top, width, height);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function normalizeClipPresentation(
|
|
311
|
+
presentation: SmoothClipPresentation,
|
|
312
|
+
bounds: ClipBounds
|
|
313
|
+
): CanonicalSmoothClipPresentation | null {
|
|
314
|
+
'worklet';
|
|
315
|
+
if (!isFiniteClipPresentation(presentation)) return null;
|
|
316
|
+
|
|
317
|
+
const clip = normalizeClipGeometry(presentation.clip, bounds);
|
|
318
|
+
if (clip === null) return null;
|
|
319
|
+
|
|
115
320
|
return {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
radius: Math.min(Math.max(0, geometry.radius), Math.min(width, height) / 2),
|
|
321
|
+
clip,
|
|
322
|
+
contentTranslateX: presentation.contentTranslateX,
|
|
323
|
+
contentTranslateY: presentation.contentTranslateY,
|
|
324
|
+
contentScale: resolvedContentScale(presentation),
|
|
121
325
|
};
|
|
122
326
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ClipReduceMotion,
|
|
3
|
+
SmoothClipDriver,
|
|
4
|
+
SpringClipAnimation,
|
|
5
|
+
TimingClipAnimation,
|
|
6
|
+
} from './driverTypes';
|
|
7
|
+
import type {
|
|
8
|
+
CanonicalSmoothClipPresentation,
|
|
9
|
+
SmoothClipPresentation,
|
|
10
|
+
} from './geometry';
|
|
11
|
+
|
|
12
|
+
export type SmoothClipGroupAnimationResult = Readonly<{
|
|
13
|
+
groupId: number;
|
|
14
|
+
finished: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
|
|
17
|
+
export type SmoothClipGroupSnapshot = Readonly<{
|
|
18
|
+
driver: SmoothClipDriver;
|
|
19
|
+
presentation: CanonicalSmoothClipPresentation;
|
|
20
|
+
ready: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
|
|
23
|
+
export type SmoothClipBatchEntry = Readonly<{
|
|
24
|
+
driver: SmoothClipDriver;
|
|
25
|
+
presentation: SmoothClipPresentation;
|
|
26
|
+
}>;
|
|
27
|
+
|
|
28
|
+
export type SmoothClipGroupMotionEntry = Readonly<{
|
|
29
|
+
driver: SmoothClipDriver;
|
|
30
|
+
target: SmoothClipPresentation;
|
|
31
|
+
from?: SmoothClipPresentation;
|
|
32
|
+
}>;
|
|
33
|
+
|
|
34
|
+
export type SmoothClipGroupKeyframeEntry = SmoothClipGroupMotionEntry &
|
|
35
|
+
Readonly<{
|
|
36
|
+
frames: readonly Readonly<{
|
|
37
|
+
offset: number;
|
|
38
|
+
presentation: SmoothClipPresentation;
|
|
39
|
+
}>[];
|
|
40
|
+
}>;
|
|
41
|
+
|
|
42
|
+
export type SmoothClipGroupSuspensionPolicy = 'pause' | 'finish';
|
|
43
|
+
export type SmoothClipGroupCancelBehavior = 'freeze' | 'finish';
|
|
44
|
+
|
|
45
|
+
type SmoothClipGroupAnimationBase = Readonly<{
|
|
46
|
+
suspensionPolicy?: SmoothClipGroupSuspensionPolicy;
|
|
47
|
+
}>;
|
|
48
|
+
|
|
49
|
+
export type SmoothClipGroupTimingAnimation = Omit<TimingClipAnimation, 'from'> &
|
|
50
|
+
SmoothClipGroupAnimationBase;
|
|
51
|
+
|
|
52
|
+
export type SmoothClipGroupSpringAnimation = Omit<SpringClipAnimation, 'from'> &
|
|
53
|
+
SmoothClipGroupAnimationBase;
|
|
54
|
+
|
|
55
|
+
export type SmoothClipGroupKeyframeAnimation = Readonly<{
|
|
56
|
+
type: 'keyframes';
|
|
57
|
+
duration: number;
|
|
58
|
+
suspensionPolicy?: SmoothClipGroupSuspensionPolicy;
|
|
59
|
+
}>;
|
|
60
|
+
|
|
61
|
+
export type SmoothClipGroupMotionAnimation =
|
|
62
|
+
SmoothClipGroupTimingAnimation | SmoothClipGroupSpringAnimation;
|
|
63
|
+
|
|
64
|
+
export type SmoothClipGroupDriverOptions = Readonly<{
|
|
65
|
+
reduceMotion?: ClipReduceMotion;
|
|
66
|
+
onAnimationComplete?: (result: SmoothClipGroupAnimationResult) => void;
|
|
67
|
+
}>;
|
|
68
|
+
|
|
69
|
+
export interface SmoothClipGroupUIControls {
|
|
70
|
+
beginInteraction(
|
|
71
|
+
drivers: readonly SmoothClipDriver[]
|
|
72
|
+
): readonly SmoothClipGroupSnapshot[];
|
|
73
|
+
snapshotCurrent(
|
|
74
|
+
drivers: readonly SmoothClipDriver[]
|
|
75
|
+
): readonly SmoothClipGroupSnapshot[];
|
|
76
|
+
setBatch(entries: readonly SmoothClipBatchEntry[]): void;
|
|
77
|
+
animateTo(
|
|
78
|
+
entries: readonly SmoothClipGroupMotionEntry[],
|
|
79
|
+
animation: SmoothClipGroupMotionAnimation
|
|
80
|
+
): number;
|
|
81
|
+
animateTo(
|
|
82
|
+
entries: readonly SmoothClipGroupKeyframeEntry[],
|
|
83
|
+
animation: SmoothClipGroupKeyframeAnimation
|
|
84
|
+
): number;
|
|
85
|
+
cancel(
|
|
86
|
+
groupId: number,
|
|
87
|
+
behavior?: SmoothClipGroupCancelBehavior
|
|
88
|
+
): readonly SmoothClipGroupSnapshot[];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface SmoothClipGroupReactControls {
|
|
92
|
+
beginInteraction(
|
|
93
|
+
drivers: readonly SmoothClipDriver[]
|
|
94
|
+
): Promise<readonly SmoothClipGroupSnapshot[]>;
|
|
95
|
+
snapshotCurrent(
|
|
96
|
+
drivers: readonly SmoothClipDriver[]
|
|
97
|
+
): Promise<readonly SmoothClipGroupSnapshot[]>;
|
|
98
|
+
setBatch(entries: readonly SmoothClipBatchEntry[]): Promise<void>;
|
|
99
|
+
animateTo(
|
|
100
|
+
entries: readonly SmoothClipGroupMotionEntry[],
|
|
101
|
+
animation: SmoothClipGroupMotionAnimation
|
|
102
|
+
): Promise<number>;
|
|
103
|
+
animateTo(
|
|
104
|
+
entries: readonly SmoothClipGroupKeyframeEntry[],
|
|
105
|
+
animation: SmoothClipGroupKeyframeAnimation
|
|
106
|
+
): Promise<number>;
|
|
107
|
+
cancel(
|
|
108
|
+
groupId: number,
|
|
109
|
+
behavior?: SmoothClipGroupCancelBehavior
|
|
110
|
+
): Promise<readonly SmoothClipGroupSnapshot[]>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export type SmoothClipGroupDriver = Readonly<{
|
|
114
|
+
kind: 'group';
|
|
115
|
+
ui: SmoothClipGroupUIControls;
|
|
116
|
+
react: SmoothClipGroupReactControls;
|
|
117
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSmoothClipGroupDriver } from './groupDrivers.native';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSmoothClipGroupDriver } from './groupDrivers.native';
|