@tamagui/animations-react-native 1.0.1-beta.192 → 1.0.1-beta.194
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.js +117 -97
- package/dist/cjs/createAnimations.js.map +3 -3
- package/dist/esm/createAnimations.js +118 -97
- package/dist/esm/createAnimations.js.map +3 -3
- package/dist/jsx/createAnimations.js +113 -96
- package/dist/jsx/createAnimations.js.map +3 -3
- package/package.json +4 -4
- package/src/createAnimations.tsx +122 -103
package/src/createAnimations.tsx
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { PresenceContext, usePresence } from '@tamagui/animate-presence'
|
|
2
1
|
import {
|
|
3
2
|
AnimatedNumberStrategy,
|
|
4
3
|
AnimationDriver,
|
|
@@ -7,7 +6,9 @@ import {
|
|
|
7
6
|
isWeb,
|
|
8
7
|
useEvent,
|
|
9
8
|
useIsomorphicLayoutEffect,
|
|
9
|
+
useSafeRef,
|
|
10
10
|
} from '@tamagui/core'
|
|
11
|
+
import { PresenceContext, usePresence } from '@tamagui/use-presence'
|
|
11
12
|
import { useContext, useEffect, useMemo, useRef } from 'react'
|
|
12
13
|
import { Animated } from 'react-native'
|
|
13
14
|
|
|
@@ -40,7 +41,7 @@ export const AnimatedView = Animated.View
|
|
|
40
41
|
export const AnimatedText = Animated.Text
|
|
41
42
|
|
|
42
43
|
export function useAnimatedNumber(initial: number): UniversalAnimatedNumber<Animated.Value> {
|
|
43
|
-
const state =
|
|
44
|
+
const state = useSafeRef(
|
|
44
45
|
null as any as {
|
|
45
46
|
val: Animated.Value
|
|
46
47
|
composite: Animated.CompositeAnimation | null
|
|
@@ -121,7 +122,7 @@ export function createAnimations<A extends AnimationsConfig>(animations: A): Ani
|
|
|
121
122
|
AnimatedText['displayName'] = 'AnimatedText'
|
|
122
123
|
|
|
123
124
|
return {
|
|
124
|
-
|
|
125
|
+
isReactNativeWeb: true,
|
|
125
126
|
animations,
|
|
126
127
|
View: AnimatedView,
|
|
127
128
|
Text: AnimatedText,
|
|
@@ -147,113 +148,124 @@ export function createAnimations<A extends AnimationsConfig>(animations: A): Ani
|
|
|
147
148
|
enterVariant: presence?.enterVariant,
|
|
148
149
|
})
|
|
149
150
|
|
|
150
|
-
const animateStyles =
|
|
151
|
-
const animatedTranforms =
|
|
152
|
-
const interpolations =
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
const animateStyles = useSafeRef<Record<string, Animated.Value>>({})
|
|
152
|
+
const animatedTranforms = useSafeRef<{ [key: string]: Animated.Value }[]>([])
|
|
153
|
+
const interpolations = useSafeRef(
|
|
154
|
+
new WeakMap<
|
|
155
|
+
Animated.Value,
|
|
156
|
+
{ interopolation: Animated.AnimatedInterpolation; current?: number }
|
|
157
|
+
>()
|
|
158
|
+
)
|
|
155
159
|
|
|
156
160
|
const runners: Function[] = []
|
|
157
161
|
const completions: Promise<void>[] = []
|
|
158
162
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
const args = [
|
|
164
|
+
JSON.stringify(all),
|
|
165
|
+
state.mounted,
|
|
166
|
+
state.hover,
|
|
167
|
+
state.press,
|
|
168
|
+
state.pressIn,
|
|
169
|
+
state.focus,
|
|
170
|
+
delay,
|
|
171
|
+
isPresent,
|
|
172
|
+
onDidAnimate,
|
|
173
|
+
presence?.exitVariant,
|
|
174
|
+
presence?.enterVariant,
|
|
175
|
+
]
|
|
167
176
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
177
|
+
const res = useMemo(() => {
|
|
178
|
+
function update(key: string, animated: Animated.Value | undefined, valIn: string | number) {
|
|
179
|
+
const [val, type] = getValue(valIn)
|
|
180
|
+
const value = animated || new Animated.Value(val)
|
|
181
|
+
let interpolateArgs: any
|
|
182
|
+
if (type) {
|
|
183
|
+
const curInterpolation = interpolations.current.get(value)
|
|
184
|
+
interpolateArgs = getInterpolated(
|
|
185
|
+
curInterpolation?.current ?? value['_value'],
|
|
186
|
+
val,
|
|
187
|
+
type
|
|
188
|
+
)
|
|
189
|
+
interpolations.current!.set(value, {
|
|
190
|
+
interopolation: value.interpolate(interpolateArgs),
|
|
191
|
+
current: val,
|
|
192
|
+
})
|
|
193
|
+
}
|
|
194
|
+
if (animated) {
|
|
195
|
+
const animationConfig = getAnimationConfig(key, animations, props.animation)
|
|
173
196
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
resolve
|
|
177
|
-
// avoid update when its the same
|
|
178
|
-
return
|
|
179
|
-
}
|
|
180
|
-
animated.stopAnimation()
|
|
181
|
-
Animated.spring(animated, {
|
|
182
|
-
toValue: val,
|
|
183
|
-
useNativeDriver: !isWeb,
|
|
184
|
-
...animationConfig,
|
|
185
|
-
}).start(({ finished }) => {
|
|
186
|
-
if (finished) {
|
|
187
|
-
resolve()
|
|
188
|
-
}
|
|
197
|
+
let resolve
|
|
198
|
+
const promise = new Promise<void>((res) => {
|
|
199
|
+
resolve = res
|
|
189
200
|
})
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
return value
|
|
193
|
-
}
|
|
201
|
+
completions.push(promise)
|
|
194
202
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
203
|
+
runners.push(() => {
|
|
204
|
+
animated.stopAnimation()
|
|
205
|
+
Animated.spring(animated, {
|
|
206
|
+
toValue: val,
|
|
207
|
+
useNativeDriver: !isWeb,
|
|
208
|
+
...animationConfig,
|
|
209
|
+
}).start(({ finished }) => {
|
|
210
|
+
if (finished) {
|
|
211
|
+
resolve()
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
if (process.env.NODE_ENV === 'development') {
|
|
217
|
+
if (props['debug']) {
|
|
218
|
+
// prettier-ignore
|
|
219
|
+
// eslint-disable-next-line no-console
|
|
220
|
+
console.log('AnimatedValue', key, 'mapped value', valIn, 'of type', type, 'to', val, 'interpolated', interpolateArgs, '- current Animated.Value', value['_value'])
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return value
|
|
198
224
|
}
|
|
199
|
-
const neg = input[0] === '-'
|
|
200
|
-
if (neg) input = input.slice(1)
|
|
201
|
-
const [_, number, after] = input.match(/([-0-9]+)(deg|%)/) ?? []
|
|
202
|
-
return [+number * (neg ? -1 : 1), after] as const
|
|
203
|
-
}
|
|
204
225
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
226
|
+
const nonAnimatedStyle = {}
|
|
227
|
+
for (const key in all) {
|
|
228
|
+
const val = all[key]
|
|
229
|
+
if (animatedStyleKey[key]) {
|
|
230
|
+
if (key === 'transform') {
|
|
231
|
+
// for now just support one transform key
|
|
232
|
+
if (val) {
|
|
233
|
+
for (const [index, transform] of val.entries()) {
|
|
234
|
+
if (!transform) continue
|
|
235
|
+
const tkey = Object.keys(transform)[0]
|
|
236
|
+
animatedTranforms.current[index] = {
|
|
237
|
+
[tkey]: update(tkey, animatedTranforms.current[index]?.[tkey], transform[tkey]),
|
|
238
|
+
}
|
|
217
239
|
}
|
|
218
240
|
}
|
|
241
|
+
} else {
|
|
242
|
+
animateStyles.current[key] = update(key, animateStyles.current[key], val)
|
|
219
243
|
}
|
|
220
244
|
} else {
|
|
221
|
-
|
|
245
|
+
nonAnimatedStyle[key] = val
|
|
222
246
|
}
|
|
223
|
-
} else {
|
|
224
|
-
nonAnimatedStyle[key] = val
|
|
225
247
|
}
|
|
226
|
-
}
|
|
227
248
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
249
|
+
const animatedStyle = {
|
|
250
|
+
...Object.fromEntries(
|
|
251
|
+
Object.entries({
|
|
252
|
+
...animateStyles.current,
|
|
253
|
+
}).map(([k, v]) => [k, interpolations.current!.get(v)?.interopolation || v])
|
|
254
|
+
),
|
|
255
|
+
transform: animatedTranforms.current.map((r) => {
|
|
256
|
+
const key = Object.keys(r)[0]
|
|
257
|
+
const val = interpolations.current!.get(r[key])?.interopolation || r[key]
|
|
258
|
+
return { [key]: val }
|
|
259
|
+
}),
|
|
260
|
+
}
|
|
240
261
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
state.pressIn,
|
|
247
|
-
state.focus,
|
|
248
|
-
delay,
|
|
249
|
-
isPresent,
|
|
250
|
-
onDidAnimate,
|
|
251
|
-
presence?.exitVariant,
|
|
252
|
-
presence?.enterVariant,
|
|
253
|
-
]
|
|
262
|
+
return {
|
|
263
|
+
style: [nonAnimatedStyle, animatedStyle],
|
|
264
|
+
}
|
|
265
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
266
|
+
}, args)
|
|
254
267
|
|
|
255
268
|
useIsomorphicLayoutEffect(() => {
|
|
256
|
-
//
|
|
257
269
|
for (const runner of runners) {
|
|
258
270
|
runner()
|
|
259
271
|
}
|
|
@@ -265,28 +277,25 @@ export function createAnimations<A extends AnimationsConfig>(animations: A): Ani
|
|
|
265
277
|
})
|
|
266
278
|
}, args)
|
|
267
279
|
|
|
268
|
-
return
|
|
269
|
-
return {
|
|
270
|
-
style: [nonAnimatedStyle, animatedStyle],
|
|
271
|
-
}
|
|
272
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
273
|
-
}, args)
|
|
280
|
+
return res
|
|
274
281
|
},
|
|
275
282
|
}
|
|
276
283
|
}
|
|
277
284
|
|
|
278
|
-
function getInterpolated(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
285
|
+
function getInterpolated(current: number, next: number, postfix = 'deg') {
|
|
286
|
+
if (next === current) {
|
|
287
|
+
current = next - 0.000000001
|
|
288
|
+
}
|
|
289
|
+
const inputRange = [current, next]
|
|
290
|
+
const outputRange = [`${current}${postfix}`, `${next}${postfix}`]
|
|
291
|
+
if (next < current) {
|
|
283
292
|
inputRange.reverse()
|
|
284
293
|
outputRange.reverse()
|
|
285
294
|
}
|
|
286
|
-
return
|
|
295
|
+
return {
|
|
287
296
|
inputRange,
|
|
288
297
|
outputRange,
|
|
289
|
-
}
|
|
298
|
+
}
|
|
290
299
|
}
|
|
291
300
|
|
|
292
301
|
function getAnimationConfig(key: string, animations: AnimationsConfig, animation?: AnimationProp) {
|
|
@@ -320,3 +329,13 @@ function getAnimationConfig(key: string, animations: AnimationsConfig, animation
|
|
|
320
329
|
...extraConf,
|
|
321
330
|
}
|
|
322
331
|
}
|
|
332
|
+
|
|
333
|
+
function getValue(input: number | string) {
|
|
334
|
+
if (typeof input !== 'string') {
|
|
335
|
+
return [input] as const
|
|
336
|
+
}
|
|
337
|
+
const neg = input[0] === '-'
|
|
338
|
+
if (neg) input = input.slice(1)
|
|
339
|
+
const [_, number, after] = input.match(/([-0-9]+)(deg|%)/) ?? []
|
|
340
|
+
return [+number * (neg ? -1 : 1), after] as const
|
|
341
|
+
}
|