@tamagui/animations-react-native 2.0.0-rc.4 → 2.0.0-rc.40
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/dist/cjs/createAnimations.cjs +385 -220
- package/dist/cjs/createAnimations.native.js +451 -273
- package/dist/cjs/createAnimations.native.js.map +1 -1
- package/dist/cjs/index.cjs +7 -5
- package/dist/cjs/index.native.js +7 -5
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/polyfill.cjs +3 -1
- package/dist/cjs/polyfill.native.js +3 -1
- package/dist/cjs/polyfill.native.js.map +1 -1
- package/dist/esm/createAnimations.mjs +355 -193
- package/dist/esm/createAnimations.mjs.map +1 -1
- package/dist/esm/createAnimations.native.js +421 -246
- package/dist/esm/createAnimations.native.js.map +1 -1
- package/dist/esm/index.js +1 -2
- package/dist/esm/index.js.map +1 -6
- package/dist/esm/polyfill.mjs +3 -1
- package/dist/esm/polyfill.mjs.map +1 -1
- package/dist/esm/polyfill.native.js +3 -1
- package/dist/esm/polyfill.native.js.map +1 -1
- package/package.json +10 -13
- package/src/createAnimations.tsx +187 -25
- package/types/createAnimations.d.ts +5 -1
- package/types/createAnimations.d.ts.map +5 -10
- package/types/index.d.ts.map +2 -2
- package/types/polyfill.d.ts.map +2 -2
- package/dist/cjs/createAnimations.js +0 -297
- package/dist/cjs/createAnimations.js.map +0 -6
- package/dist/cjs/index.js +0 -16
- package/dist/cjs/index.js.map +0 -6
- package/dist/cjs/polyfill.js +0 -2
- package/dist/cjs/polyfill.js.map +0 -6
- package/dist/esm/createAnimations.js +0 -278
- package/dist/esm/createAnimations.js.map +0 -6
- package/dist/esm/polyfill.js +0 -2
- package/dist/esm/polyfill.js.map +0 -6
|
@@ -1,56 +1,66 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getEffectiveAnimation, normalizeTransition } from "@tamagui/animation-helpers";
|
|
2
2
|
import { isWeb, useIsomorphicLayoutEffect } from "@tamagui/constants";
|
|
3
3
|
import { ResetPresence, usePresence } from "@tamagui/use-presence";
|
|
4
4
|
import { useEvent, useThemeWithState } from "@tamagui/web";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { Animated } from "react-native-web";
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
7
|
+
const isFabric = !isWeb && typeof global !== "undefined" && !!global.__nativeFabricUIManager;
|
|
8
|
+
const resolveDynamicValue = (value, isDark) => {
|
|
9
|
+
if (value && typeof value === "object" && "dynamic" in value) {
|
|
10
|
+
const dynamicValue = isDark ? value.dynamic.dark : value.dynamic.light;
|
|
11
|
+
return dynamicValue;
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
15
|
+
const animatedStyleKey = {
|
|
16
|
+
transform: true,
|
|
17
|
+
opacity: true
|
|
18
|
+
};
|
|
19
|
+
const colorStyleKey = {
|
|
20
|
+
backgroundColor: true,
|
|
21
|
+
color: true,
|
|
22
|
+
borderColor: true,
|
|
23
|
+
borderLeftColor: true,
|
|
24
|
+
borderRightColor: true,
|
|
25
|
+
borderTopColor: true,
|
|
26
|
+
borderBottomColor: true
|
|
27
|
+
};
|
|
28
|
+
const costlyToAnimateStyleKey = {
|
|
29
|
+
borderRadius: true,
|
|
30
|
+
borderTopLeftRadius: true,
|
|
31
|
+
borderTopRightRadius: true,
|
|
32
|
+
borderBottomLeftRadius: true,
|
|
33
|
+
borderBottomRightRadius: true,
|
|
34
|
+
borderWidth: true,
|
|
35
|
+
borderLeftWidth: true,
|
|
36
|
+
borderRightWidth: true,
|
|
37
|
+
borderTopWidth: true,
|
|
38
|
+
borderBottomWidth: true,
|
|
39
|
+
...colorStyleKey
|
|
40
|
+
};
|
|
41
|
+
const AnimatedView = Animated.View;
|
|
42
|
+
const AnimatedText = Animated.Text;
|
|
37
43
|
function useAnimatedNumber(initial) {
|
|
38
44
|
const state = React.useRef(null);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
if (!state.current) {
|
|
46
|
+
state.current = {
|
|
47
|
+
composite: null,
|
|
48
|
+
val: new Animated.Value(initial),
|
|
49
|
+
strategy: {
|
|
50
|
+
type: "spring"
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
46
55
|
getInstance() {
|
|
47
56
|
return state.current.val;
|
|
48
57
|
},
|
|
49
58
|
getValue() {
|
|
50
|
-
return state.current.val
|
|
59
|
+
return state.current.val["_value"];
|
|
51
60
|
},
|
|
52
61
|
stop() {
|
|
53
|
-
state.current.composite?.stop()
|
|
62
|
+
state.current.composite?.stop();
|
|
63
|
+
state.current.composite = null;
|
|
54
64
|
},
|
|
55
65
|
setValue(next, {
|
|
56
66
|
type,
|
|
@@ -58,55 +68,68 @@ function useAnimatedNumber(initial) {
|
|
|
58
68
|
} = {
|
|
59
69
|
type: "spring"
|
|
60
70
|
}, onFinish) {
|
|
61
|
-
const val = state.current.val
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (type === "direct")
|
|
71
|
+
const val = state.current.val;
|
|
72
|
+
const handleFinish = onFinish ? ({
|
|
73
|
+
finished
|
|
74
|
+
}) => finished ? onFinish() : null : void 0;
|
|
75
|
+
if (type === "direct") {
|
|
76
|
+
val.setValue(next);
|
|
77
|
+
} else if (type === "spring") {
|
|
66
78
|
state.current.composite?.stop();
|
|
67
79
|
const composite = Animated.spring(val, {
|
|
68
80
|
...config,
|
|
69
81
|
toValue: next,
|
|
70
|
-
useNativeDriver:
|
|
82
|
+
useNativeDriver: isFabric
|
|
71
83
|
});
|
|
72
|
-
composite.start(handleFinish)
|
|
84
|
+
composite.start(handleFinish);
|
|
85
|
+
state.current.composite = composite;
|
|
73
86
|
} else {
|
|
74
87
|
state.current.composite?.stop();
|
|
75
88
|
const composite = Animated.timing(val, {
|
|
76
89
|
...config,
|
|
77
90
|
toValue: next,
|
|
78
|
-
useNativeDriver:
|
|
91
|
+
useNativeDriver: isFabric
|
|
79
92
|
});
|
|
80
|
-
composite.start(handleFinish)
|
|
93
|
+
composite.start(handleFinish);
|
|
94
|
+
state.current.composite = composite;
|
|
81
95
|
}
|
|
82
96
|
}
|
|
83
97
|
};
|
|
84
98
|
}
|
|
85
99
|
const useAnimatedNumberReaction = ({
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
value
|
|
101
|
+
}, onValue) => {
|
|
102
|
+
const onChange = useEvent(current => {
|
|
103
|
+
onValue(current.value);
|
|
104
|
+
});
|
|
105
|
+
React.useEffect(() => {
|
|
106
|
+
const id = value.getInstance().addListener(onChange);
|
|
107
|
+
return () => {
|
|
108
|
+
value.getInstance().removeListener(id);
|
|
109
|
+
};
|
|
110
|
+
}, [value, onChange]);
|
|
111
|
+
};
|
|
112
|
+
const useAnimatedNumberStyle = (value, getStyle) => {
|
|
113
|
+
return getStyle(value.getInstance());
|
|
114
|
+
};
|
|
115
|
+
const useAnimatedNumbersStyle = (vals, getStyle) => {
|
|
116
|
+
return getStyle(...vals.map(v => v.getInstance()));
|
|
117
|
+
};
|
|
118
|
+
function createAnimations(animations, options) {
|
|
119
|
+
const nativeDriver = options?.useNativeDriver ?? isFabric;
|
|
100
120
|
return {
|
|
101
|
-
isReactNative:
|
|
121
|
+
isReactNative: true,
|
|
102
122
|
inputStyle: "value",
|
|
103
123
|
outputStyle: "inline",
|
|
124
|
+
avoidReRenders: true,
|
|
104
125
|
animations,
|
|
126
|
+
needsCustomComponent: true,
|
|
105
127
|
View: AnimatedView,
|
|
106
128
|
Text: AnimatedText,
|
|
107
129
|
useAnimatedNumber,
|
|
108
130
|
useAnimatedNumberReaction,
|
|
109
131
|
useAnimatedNumberStyle,
|
|
132
|
+
useAnimatedNumbersStyle,
|
|
110
133
|
usePresence,
|
|
111
134
|
ResetPresence,
|
|
112
135
|
useAnimations: ({
|
|
@@ -114,163 +137,300 @@ function createAnimations(animations) {
|
|
|
114
137
|
onDidAnimate,
|
|
115
138
|
style,
|
|
116
139
|
componentState,
|
|
117
|
-
presence
|
|
140
|
+
presence,
|
|
141
|
+
useStyleEmitter
|
|
118
142
|
}) => {
|
|
119
|
-
const isDisabled = isWeb && componentState.unmounted ===
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
const isDisabled = isWeb && componentState.unmounted === true;
|
|
144
|
+
const isExiting = presence?.[0] === false;
|
|
145
|
+
const sendExitComplete = presence?.[1];
|
|
146
|
+
const [, themeState] = useThemeWithState({});
|
|
147
|
+
const isDark = themeState?.scheme === "dark" || themeState?.name?.startsWith("dark");
|
|
148
|
+
const animateStyles = React.useRef({});
|
|
149
|
+
const animatedTranforms = React.useRef([]);
|
|
150
|
+
const animationsState = React.useRef(/* @__PURE__ */new WeakMap());
|
|
151
|
+
const exitCycleIdRef = React.useRef(0);
|
|
152
|
+
const exitCompletedRef = React.useRef(false);
|
|
153
|
+
const wasExitingRef = React.useRef(false);
|
|
154
|
+
const justStartedExiting = isExiting && !wasExitingRef.current;
|
|
155
|
+
const justStoppedExiting = !isExiting && wasExitingRef.current;
|
|
156
|
+
if (justStartedExiting) {
|
|
157
|
+
exitCycleIdRef.current++;
|
|
158
|
+
exitCompletedRef.current = false;
|
|
159
|
+
}
|
|
160
|
+
if (justStoppedExiting) {
|
|
161
|
+
exitCycleIdRef.current++;
|
|
162
|
+
}
|
|
163
|
+
const animateOnly = props.animateOnly || [];
|
|
164
|
+
const hasTransitionOnly = !!props.animateOnly;
|
|
165
|
+
const isEntering = !!componentState.unmounted;
|
|
166
|
+
const wasEnteringRef = React.useRef(isEntering);
|
|
167
|
+
const justFinishedEntering = wasEnteringRef.current && !isEntering;
|
|
132
168
|
React.useEffect(() => {
|
|
133
169
|
wasEnteringRef.current = isEntering;
|
|
134
170
|
});
|
|
135
|
-
const args = [JSON.stringify(style), componentState, isExiting, !!onDidAnimate, isDark, justFinishedEntering]
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
nonAnimatedStyle[key] = val;
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
if (hasTransitionOnly && !animateOnly.includes(key)) {
|
|
151
|
-
nonAnimatedStyle[key] = val;
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
if (key !== "transform") {
|
|
155
|
-
animateStyles.current[key] = update(key, animateStyles.current[key], val);
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
if (val) {
|
|
159
|
-
if (typeof val == "string") {
|
|
160
|
-
console.warn("Warning: Tamagui can't animate string transforms yet!");
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
for (const [index, transform] of val.entries()) {
|
|
164
|
-
if (!transform) continue;
|
|
165
|
-
const tkey = Object.keys(transform)[0],
|
|
166
|
-
currentTransform = animatedTranforms.current[index]?.[tkey];
|
|
167
|
-
animatedTranforms.current[index] = {
|
|
168
|
-
[tkey]: update(tkey, currentTransform, transform[tkey])
|
|
169
|
-
}, animatedTranforms.current = [...animatedTranforms.current];
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
171
|
+
const args = [JSON.stringify(style), componentState, isExiting, !!onDidAnimate, isDark, justFinishedEntering, hasTransitionOnly];
|
|
172
|
+
const res = React.useMemo(() => {
|
|
173
|
+
const runners = [];
|
|
174
|
+
const completions = [];
|
|
175
|
+
const animationState = isExiting ? "exit" : isEntering || justFinishedEntering ? "enter" : "default";
|
|
176
|
+
const nonAnimatedStyle = {};
|
|
177
|
+
for (const key in style) {
|
|
178
|
+
const rawVal = style[key];
|
|
179
|
+
const val = resolveDynamicValue(rawVal, isDark);
|
|
180
|
+
if (val === void 0) continue;
|
|
181
|
+
if (isDisabled) {
|
|
182
|
+
continue;
|
|
173
183
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
184
|
+
if (animatedStyleKey[key] == null && !costlyToAnimateStyleKey[key]) {
|
|
185
|
+
nonAnimatedStyle[key] = val;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (hasTransitionOnly && !animateOnly.includes(key)) {
|
|
189
|
+
nonAnimatedStyle[key] = val;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (key !== "transform") {
|
|
193
|
+
animateStyles.current[key] = update(key, animateStyles.current[key], val);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (!val) continue;
|
|
197
|
+
if (typeof val === "string") {
|
|
198
|
+
console.warn(`Warning: Tamagui can't animate string transforms yet!`);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
for (const [index, transform] of val.entries()) {
|
|
202
|
+
if (!transform) continue;
|
|
203
|
+
const tkey = Object.keys(transform)[0];
|
|
204
|
+
const currentTransform = animatedTranforms.current[index]?.[tkey];
|
|
205
|
+
animatedTranforms.current[index] = {
|
|
206
|
+
[tkey]: update(tkey, currentTransform, transform[tkey])
|
|
207
|
+
};
|
|
208
|
+
animatedTranforms.current = [...animatedTranforms.current];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const animatedTransformStyle = animatedTranforms.current.length > 0 ? {
|
|
212
|
+
transform: animatedTranforms.current.map(r => {
|
|
213
|
+
const key = Object.keys(r)[0];
|
|
214
|
+
const val = animationsState.current.get(r[key])?.interpolation || r[key];
|
|
215
|
+
return {
|
|
216
|
+
[key]: val
|
|
217
|
+
};
|
|
218
|
+
})
|
|
219
|
+
} : {};
|
|
220
|
+
const animatedStyle = {
|
|
221
|
+
...Object.fromEntries(Object.entries(animateStyles.current).map(([k, v]) => [k, animationsState.current.get(v)?.interpolation || v])),
|
|
222
|
+
...animatedTransformStyle
|
|
223
|
+
};
|
|
224
|
+
return {
|
|
225
|
+
runners,
|
|
226
|
+
completions,
|
|
227
|
+
style: [nonAnimatedStyle, animatedStyle]
|
|
228
|
+
};
|
|
229
|
+
function update(key, animated, valIn) {
|
|
230
|
+
const isColorStyleKey = colorStyleKey[key];
|
|
231
|
+
const [val, type] = isColorStyleKey ? [0, void 0] : getValue(valIn);
|
|
232
|
+
let animateToValue = val;
|
|
233
|
+
const value = animated || new Animated.Value(val);
|
|
234
|
+
const curInterpolation = animationsState.current.get(value);
|
|
235
|
+
let interpolateArgs;
|
|
236
|
+
if (type) {
|
|
237
|
+
interpolateArgs = getInterpolated(curInterpolation?.current ?? value["_value"], val, type);
|
|
238
|
+
animationsState.current.set(value, {
|
|
197
239
|
interpolation: value.interpolate(interpolateArgs),
|
|
198
240
|
current: val
|
|
199
|
-
})
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
if (isColorStyleKey) {
|
|
244
|
+
animateToValue = curInterpolation?.animateToValue ? 0 : 1;
|
|
245
|
+
interpolateArgs = getColorInterpolated(curInterpolation?.current,
|
|
200
246
|
// valIn is the next color
|
|
201
|
-
valIn, animateToValue)
|
|
247
|
+
valIn, animateToValue);
|
|
248
|
+
animationsState.current.set(value, {
|
|
202
249
|
current: valIn,
|
|
203
250
|
interpolation: value.interpolate(interpolateArgs),
|
|
204
251
|
animateToValue: curInterpolation?.animateToValue ? 0 : 1
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
finished
|
|
222
|
-
}) => {
|
|
223
|
-
finished && resolve();
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
if (value) {
|
|
255
|
+
const animationConfig = getAnimationConfig(key, animations, props.transition, animationState);
|
|
256
|
+
let resolve;
|
|
257
|
+
const promise = new Promise(res2 => {
|
|
258
|
+
resolve = res2;
|
|
259
|
+
});
|
|
260
|
+
completions.push(promise);
|
|
261
|
+
runners.push(() => {
|
|
262
|
+
value.stopAnimation();
|
|
263
|
+
function getAnimation() {
|
|
264
|
+
return Animated[animationConfig.type || "spring"](value, {
|
|
265
|
+
toValue: animateToValue,
|
|
266
|
+
useNativeDriver: nativeDriver,
|
|
267
|
+
...animationConfig
|
|
224
268
|
});
|
|
269
|
+
}
|
|
270
|
+
const animation = animationConfig.delay ? Animated.sequence([Animated.delay(animationConfig.delay), getAnimation()]) : getAnimation();
|
|
271
|
+
animation.start(({
|
|
272
|
+
finished
|
|
273
|
+
}) => {
|
|
274
|
+
if (finished || isExiting) {
|
|
275
|
+
resolve();
|
|
276
|
+
}
|
|
225
277
|
});
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
if (process.env.NODE_ENV === "development") {
|
|
281
|
+
if (props["debug"] === "verbose") {
|
|
282
|
+
console.info(" \u{1F4A0} animate", key, `from (${value["_value"]}) to`, valIn, `(${val})`, "type", type, "interpolate", interpolateArgs);
|
|
226
283
|
}
|
|
227
|
-
return process.env.NODE_ENV === "development" && props.debug === "verbose" && console.info(" \u{1F4A0} animate", key, `from (${value._value}) to`, valIn, `(${val})`, "type", type, "interpolate", interpolateArgs), value;
|
|
228
284
|
}
|
|
229
|
-
|
|
230
|
-
|
|
285
|
+
return value;
|
|
286
|
+
}
|
|
287
|
+
}, args);
|
|
288
|
+
React.useEffect(() => {
|
|
289
|
+
wasExitingRef.current = isExiting;
|
|
290
|
+
});
|
|
291
|
+
useIsomorphicLayoutEffect(() => {
|
|
231
292
|
res.runners.forEach(r => r());
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
293
|
+
const cycleId = exitCycleIdRef.current;
|
|
294
|
+
if (res.completions.length === 0) {
|
|
295
|
+
onDidAnimate?.();
|
|
296
|
+
if (isExiting && !exitCompletedRef.current) {
|
|
297
|
+
exitCompletedRef.current = true;
|
|
298
|
+
sendExitComplete?.();
|
|
299
|
+
}
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
let cancel = false;
|
|
303
|
+
Promise.all(res.completions).then(() => {
|
|
304
|
+
if (cancel) return;
|
|
305
|
+
if (isExiting && cycleId !== exitCycleIdRef.current) return;
|
|
306
|
+
if (isExiting && exitCompletedRef.current) return;
|
|
307
|
+
onDidAnimate?.();
|
|
308
|
+
if (isExiting) {
|
|
309
|
+
exitCompletedRef.current = true;
|
|
310
|
+
sendExitComplete?.();
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
return () => {
|
|
314
|
+
cancel = true;
|
|
237
315
|
};
|
|
238
|
-
}, args)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
316
|
+
}, args);
|
|
317
|
+
useStyleEmitter?.(nextStyle => {
|
|
318
|
+
for (const key in nextStyle) {
|
|
319
|
+
const rawVal = nextStyle[key];
|
|
320
|
+
const val = resolveDynamicValue(rawVal, isDark);
|
|
321
|
+
if (val === void 0) continue;
|
|
322
|
+
if (key === "transform" && Array.isArray(val)) {
|
|
323
|
+
for (const [index, transform] of val.entries()) {
|
|
324
|
+
if (!transform) continue;
|
|
325
|
+
const tkey = Object.keys(transform)[0];
|
|
326
|
+
const currentTransform = animatedTranforms.current[index]?.[tkey];
|
|
327
|
+
animatedTranforms.current[index] = {
|
|
328
|
+
[tkey]: update(tkey, currentTransform, transform[tkey])
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
} else if (animatedStyleKey[key] != null || costlyToAnimateStyleKey[key]) {
|
|
332
|
+
animateStyles.current[key] = update(key, animateStyles.current[key], val);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
res.runners.forEach(r => r());
|
|
336
|
+
function update(key, animated, valIn) {
|
|
337
|
+
const isColor = colorStyleKey[key];
|
|
338
|
+
const [numVal, type] = isColor ? [0, void 0] : getValue(valIn);
|
|
339
|
+
let animateToValue = numVal;
|
|
340
|
+
const value = animated || new Animated.Value(numVal);
|
|
341
|
+
const curInterpolation = animationsState.current.get(value);
|
|
342
|
+
if (type) {
|
|
343
|
+
animationsState.current.set(value, {
|
|
344
|
+
interpolation: value.interpolate(getInterpolated(curInterpolation?.current ?? value["_value"], numVal, type)),
|
|
345
|
+
current: numVal
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
if (isColor) {
|
|
349
|
+
animateToValue = curInterpolation?.animateToValue ? 0 : 1;
|
|
350
|
+
animationsState.current.set(value, {
|
|
351
|
+
current: valIn,
|
|
352
|
+
interpolation: value.interpolate(getColorInterpolated(curInterpolation?.current, valIn, animateToValue)),
|
|
353
|
+
animateToValue: curInterpolation?.animateToValue ? 0 : 1
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
const animationConfig = getAnimationConfig(key, animations, props.transition, "default");
|
|
357
|
+
res.runners.push(() => {
|
|
358
|
+
value.stopAnimation();
|
|
359
|
+
const anim = Animated[animationConfig.type || "spring"](value, {
|
|
360
|
+
toValue: animateToValue,
|
|
361
|
+
useNativeDriver: nativeDriver,
|
|
362
|
+
...animationConfig
|
|
363
|
+
});
|
|
364
|
+
(animationConfig.delay ? Animated.sequence([Animated.delay(animationConfig.delay), anim]) : anim).start();
|
|
365
|
+
});
|
|
366
|
+
return value;
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
if (process.env.NODE_ENV === "development") {
|
|
370
|
+
if (props["debug"] === "verbose") {
|
|
371
|
+
console.info(`Animated`, {
|
|
372
|
+
response: res,
|
|
373
|
+
inputStyle: style,
|
|
374
|
+
isExiting
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return res;
|
|
243
379
|
}
|
|
244
380
|
};
|
|
245
381
|
}
|
|
246
382
|
function getColorInterpolated(currentColor, nextColor, animateToValue) {
|
|
247
|
-
const inputRange = [0, 1]
|
|
248
|
-
|
|
249
|
-
|
|
383
|
+
const inputRange = [0, 1];
|
|
384
|
+
const outputRange = [currentColor ? currentColor : nextColor, nextColor];
|
|
385
|
+
if (animateToValue === 0) {
|
|
386
|
+
outputRange.reverse();
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
250
389
|
inputRange,
|
|
251
390
|
outputRange
|
|
252
391
|
};
|
|
253
392
|
}
|
|
254
393
|
function getInterpolated(current, next, postfix = "deg") {
|
|
255
|
-
next === current
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
394
|
+
if (next === current) {
|
|
395
|
+
current = next - 1e-9;
|
|
396
|
+
}
|
|
397
|
+
const inputRange = [current, next];
|
|
398
|
+
const outputRange = [`${current}${postfix}`, `${next}${postfix}`];
|
|
399
|
+
if (next < current) {
|
|
400
|
+
inputRange.reverse();
|
|
401
|
+
outputRange.reverse();
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
259
404
|
inputRange,
|
|
260
405
|
outputRange
|
|
261
406
|
};
|
|
262
407
|
}
|
|
263
408
|
function getAnimationConfig(key, animations, transition, animationState = "default") {
|
|
264
|
-
const normalized = normalizeTransition(transition)
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
let animationType = null
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
409
|
+
const normalized = normalizeTransition(transition);
|
|
410
|
+
const shortKey = transformShorthands[key];
|
|
411
|
+
const propAnimation = normalized.properties[key] ?? normalized.properties[shortKey];
|
|
412
|
+
let animationType = null;
|
|
413
|
+
let extraConf = {};
|
|
414
|
+
if (typeof propAnimation === "string") {
|
|
415
|
+
animationType = propAnimation;
|
|
416
|
+
} else if (propAnimation && typeof propAnimation === "object") {
|
|
417
|
+
animationType = propAnimation.type || getEffectiveAnimation(normalized, animationState);
|
|
418
|
+
extraConf = propAnimation;
|
|
419
|
+
} else {
|
|
420
|
+
animationType = getEffectiveAnimation(normalized, animationState);
|
|
421
|
+
}
|
|
422
|
+
if (normalized.delay && !extraConf.delay) {
|
|
423
|
+
extraConf = {
|
|
424
|
+
...extraConf,
|
|
425
|
+
delay: normalized.delay
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
const found = animationType ? animations[animationType] : {};
|
|
429
|
+
return {
|
|
430
|
+
...found,
|
|
431
|
+
// Apply global spring config overrides (from transition={['bouncy', { stiffness: 1000 }]})
|
|
432
|
+
...normalized.config,
|
|
433
|
+
// Property-specific config takes highest precedence
|
|
274
434
|
...extraConf
|
|
275
435
|
};
|
|
276
436
|
}
|
|
@@ -280,10 +440,12 @@ const transformShorthands = {
|
|
|
280
440
|
translateX: "x",
|
|
281
441
|
translateY: "y"
|
|
282
442
|
};
|
|
283
|
-
function getValue(input, isColor =
|
|
284
|
-
if (typeof input
|
|
443
|
+
function getValue(input, isColor = false) {
|
|
444
|
+
if (typeof input !== "string") {
|
|
445
|
+
return [input];
|
|
446
|
+
}
|
|
285
447
|
const [_, number, after] = input.match(/([-0-9]+)(deg|%|px)/) ?? [];
|
|
286
448
|
return [+number, after];
|
|
287
449
|
}
|
|
288
|
-
export { AnimatedText, AnimatedView, createAnimations, useAnimatedNumber, useAnimatedNumberReaction, useAnimatedNumberStyle };
|
|
450
|
+
export { AnimatedText, AnimatedView, createAnimations, useAnimatedNumber, useAnimatedNumberReaction, useAnimatedNumberStyle, useAnimatedNumbersStyle };
|
|
289
451
|
//# sourceMappingURL=createAnimations.mjs.map
|