1 | 'use strict';
|
2 | import type {
|
3 | ILayoutAnimationBuilder,
|
4 | LayoutAnimationsValues,
|
5 | LayoutAnimationFunction,
|
6 | StylePropsWithArrayTransform,
|
7 | } from '../animationBuilder/commonTypes';
|
8 | import { BaseAnimationBuilder } from '../animationBuilder';
|
9 | import { withSequence, withTiming } from '../../animation';
|
10 | import { FadeIn, FadeOut } from '../defaultAnimations/Fade';
|
11 | import type { AnimatableValue, AnimationObject } from '../../commonTypes';
|
12 | import type { TransformArrayItem } from '../../helperTypes';
|
13 |
|
14 | export class EntryExitTransition
|
15 | extends BaseAnimationBuilder
|
16 | implements ILayoutAnimationBuilder
|
17 | {
|
18 | enteringV: BaseAnimationBuilder | typeof BaseAnimationBuilder = FadeIn;
|
19 |
|
20 | exitingV: BaseAnimationBuilder | typeof BaseAnimationBuilder = FadeOut;
|
21 |
|
22 | static createInstance<T extends typeof BaseAnimationBuilder>(
|
23 | this: T
|
24 | ): InstanceType<T> {
|
25 | return new EntryExitTransition() as InstanceType<T>;
|
26 | }
|
27 |
|
28 | static entering(
|
29 | animation: BaseAnimationBuilder | typeof BaseAnimationBuilder
|
30 | ): EntryExitTransition {
|
31 | const instance = this.createInstance();
|
32 | return instance.entering(animation);
|
33 | }
|
34 |
|
35 | entering(
|
36 | animation: BaseAnimationBuilder | typeof BaseAnimationBuilder
|
37 | ): EntryExitTransition {
|
38 | this.enteringV = animation;
|
39 | return this;
|
40 | }
|
41 |
|
42 | static exiting(
|
43 | animation: BaseAnimationBuilder | typeof BaseAnimationBuilder
|
44 | ): EntryExitTransition {
|
45 | const instance = this.createInstance();
|
46 | return instance.exiting(animation);
|
47 | }
|
48 |
|
49 | exiting(
|
50 | animation: BaseAnimationBuilder | typeof BaseAnimationBuilder
|
51 | ): EntryExitTransition {
|
52 | this.exitingV = animation;
|
53 | return this;
|
54 | }
|
55 |
|
56 | build = (): LayoutAnimationFunction => {
|
57 | const delayFunction = this.getDelayFunction();
|
58 | const callback = this.callbackV;
|
59 | const delay = this.getDelay();
|
60 |
|
61 | const enteringAnimation = this.enteringV.build();
|
62 |
|
63 | const exitingAnimation = this.exitingV.build();
|
64 | const exitingDuration = this.exitingV.getDuration();
|
65 |
|
66 | return (values) => {
|
67 | 'worklet';
|
68 | const enteringValues = enteringAnimation(values);
|
69 | const exitingValues = exitingAnimation(values);
|
70 | const animations: StylePropsWithArrayTransform = {
|
71 | transform: [],
|
72 | };
|
73 |
|
74 | for (const prop of Object.keys(exitingValues.animations)) {
|
75 | if (prop === 'transform') {
|
76 | if (!Array.isArray(exitingValues.animations.transform)) {
|
77 | continue;
|
78 | }
|
79 | exitingValues.animations.transform.forEach((value, index) => {
|
80 | for (const transformProp of Object.keys(value)) {
|
81 | animations.transform!.push({
|
82 | [transformProp]: delayFunction(
|
83 | delay,
|
84 | withSequence(
|
85 | value[transformProp as keyof TransformArrayItem],
|
86 | withTiming(
|
87 | exitingValues.initialValues.transform
|
88 | ?
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 | exitingValues.initialValues.transform[index][
|
97 | transformProp
|
98 | ]
|
99 | : 0,
|
100 | { duration: 0 }
|
101 | )
|
102 | )
|
103 | ),
|
104 | } as TransformArrayItem);
|
105 | }
|
106 | });
|
107 | } else {
|
108 | const sequence =
|
109 | enteringValues.animations[prop] !== undefined
|
110 | ? [
|
111 | exitingValues.animations[prop],
|
112 | withTiming(enteringValues.initialValues[prop], {
|
113 | duration: 0,
|
114 | }),
|
115 | enteringValues.animations[prop],
|
116 | ]
|
117 | : [
|
118 | exitingValues.animations[prop],
|
119 | withTiming(
|
120 | Object.keys(values).includes(prop)
|
121 | ? values[prop as keyof LayoutAnimationsValues]
|
122 | : exitingValues.initialValues[prop],
|
123 | { duration: 0 }
|
124 | ),
|
125 | ];
|
126 |
|
127 | animations[prop] = delayFunction(delay, withSequence(...sequence));
|
128 | }
|
129 | }
|
130 | for (const prop of Object.keys(enteringValues.animations)) {
|
131 | if (prop === 'transform') {
|
132 | if (!Array.isArray(enteringValues.animations.transform)) {
|
133 | continue;
|
134 | }
|
135 | enteringValues.animations.transform.forEach((value, index) => {
|
136 | for (const transformProp of Object.keys(value)) {
|
137 | animations.transform!.push({
|
138 | [transformProp]: delayFunction(
|
139 | delay + exitingDuration,
|
140 | withSequence(
|
141 | withTiming(
|
142 | enteringValues.initialValues.transform
|
143 | ? ((
|
144 | enteringValues.initialValues
|
145 | .transform as TransformArrayItem[]
|
146 | )[index][
|
147 | transformProp as keyof TransformArrayItem
|
148 | ] as AnimatableValue)
|
149 | : 0,
|
150 | { duration: exitingDuration }
|
151 | ),
|
152 | value[
|
153 | transformProp as keyof TransformArrayItem
|
154 | ] as AnimatableValue
|
155 | )
|
156 | ),
|
157 | } as TransformArrayItem);
|
158 | }
|
159 | });
|
160 | } else if (animations[prop] !== undefined) {
|
161 |
|
162 | continue;
|
163 | } else {
|
164 | animations[prop] = delayFunction(
|
165 | delay,
|
166 | withSequence(
|
167 | withTiming(enteringValues.initialValues[prop], { duration: 0 }),
|
168 | enteringValues.animations[prop]
|
169 | )
|
170 | );
|
171 | }
|
172 | }
|
173 |
|
174 | const mergedTransform = (
|
175 | Array.isArray(exitingValues.initialValues.transform)
|
176 | ? exitingValues.initialValues.transform
|
177 | : []
|
178 | ).concat(
|
179 | (Array.isArray(enteringValues.animations.transform)
|
180 | ? enteringValues.animations.transform
|
181 | : []
|
182 | ).map((value) => {
|
183 | const objectKeys = Object.keys(value);
|
184 | if (objectKeys?.length < 1) {
|
185 | console.error(
|
186 | `[Reanimated]: \${value} is not a valid Transform object`
|
187 | );
|
188 | return value;
|
189 | }
|
190 |
|
191 | const transformProp = objectKeys[0];
|
192 | const current =
|
193 |
|
194 |
|
195 | (value[transformProp] as AnimationObject).current;
|
196 | if (typeof current === 'string') {
|
197 | if (current.includes('deg')) {
|
198 | return {
|
199 | [transformProp]: '0deg',
|
200 | } as unknown as TransformArrayItem;
|
201 | } else {
|
202 | return {
|
203 | [transformProp]: '0',
|
204 | } as unknown as TransformArrayItem;
|
205 | }
|
206 | } else if (transformProp.includes('translate')) {
|
207 | return { [transformProp]: 0 } as unknown as TransformArrayItem;
|
208 | } else {
|
209 | return { [transformProp]: 1 } as unknown as TransformArrayItem;
|
210 | }
|
211 | })
|
212 | );
|
213 |
|
214 | return {
|
215 | initialValues: {
|
216 | ...exitingValues.initialValues,
|
217 | originX: values.currentOriginX,
|
218 | originY: values.currentOriginY,
|
219 | width: values.currentWidth,
|
220 | height: values.currentHeight,
|
221 | transform: mergedTransform,
|
222 | },
|
223 | animations: {
|
224 | originX: delayFunction(
|
225 | delay + exitingDuration,
|
226 | withTiming(values.targetOriginX, { duration: exitingDuration })
|
227 | ),
|
228 | originY: delayFunction(
|
229 | delay + exitingDuration,
|
230 | withTiming(values.targetOriginY, { duration: exitingDuration })
|
231 | ),
|
232 | width: delayFunction(
|
233 | delay + exitingDuration,
|
234 | withTiming(values.targetWidth, { duration: exitingDuration })
|
235 | ),
|
236 | height: delayFunction(
|
237 | delay + exitingDuration,
|
238 | withTiming(values.targetHeight, { duration: exitingDuration })
|
239 | ),
|
240 | ...animations,
|
241 | },
|
242 | callback,
|
243 | };
|
244 | };
|
245 | };
|
246 | }
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 | export function combineTransition(
|
257 | exiting: BaseAnimationBuilder | typeof BaseAnimationBuilder,
|
258 | entering: BaseAnimationBuilder | typeof BaseAnimationBuilder
|
259 | ): EntryExitTransition {
|
260 | return EntryExitTransition.entering(entering).exiting(exiting);
|
261 | }
|