@tamagui/animations-react-native 1.0.1-beta.141 → 1.0.1-beta.142
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 +92 -17
- package/dist/cjs/createAnimations.js.map +2 -2
- package/dist/esm/createAnimations.js +92 -18
- package/dist/esm/createAnimations.js.map +2 -2
- package/dist/jsx/createAnimations.js +90 -18
- package/dist/jsx/createAnimations.js.map +2 -2
- package/package.json +7 -5
- package/src/createAnimations.tsx +107 -19
- package/types/createAnimations.d.ts +6 -1
|
@@ -18,7 +18,12 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var createAnimations_exports = {};
|
|
20
20
|
__export(createAnimations_exports, {
|
|
21
|
-
|
|
21
|
+
AnimatedText: () => AnimatedText,
|
|
22
|
+
AnimatedView: () => AnimatedView,
|
|
23
|
+
createAnimations: () => createAnimations,
|
|
24
|
+
useAnimatedNumber: () => useAnimatedNumber,
|
|
25
|
+
useAnimatedNumberReaction: () => useAnimatedNumberReaction,
|
|
26
|
+
useAnimatedNumberStyle: () => useAnimatedNumberStyle
|
|
22
27
|
});
|
|
23
28
|
module.exports = __toCommonJS(createAnimations_exports);
|
|
24
29
|
var import_animate_presence = require("@tamagui/animate-presence");
|
|
@@ -29,9 +34,71 @@ const animatedStyleKey = {
|
|
|
29
34
|
transform: true,
|
|
30
35
|
opacity: true
|
|
31
36
|
};
|
|
37
|
+
const AnimatedView = import_react_native.Animated.View;
|
|
38
|
+
const AnimatedText = import_react_native.Animated.Text;
|
|
39
|
+
function useAnimatedNumber(initial) {
|
|
40
|
+
const state = (0, import_react.useRef)(null);
|
|
41
|
+
if (!state.current) {
|
|
42
|
+
state.current = {
|
|
43
|
+
composite: null,
|
|
44
|
+
val: new import_react_native.Animated.Value(initial),
|
|
45
|
+
strategy: { type: "spring" }
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
getInstance() {
|
|
50
|
+
return state.current.val;
|
|
51
|
+
},
|
|
52
|
+
getValue() {
|
|
53
|
+
return state.current.val["_value"];
|
|
54
|
+
},
|
|
55
|
+
stop() {
|
|
56
|
+
var _a;
|
|
57
|
+
(_a = state.current.composite) == null ? void 0 : _a.stop();
|
|
58
|
+
state.current.composite = null;
|
|
59
|
+
},
|
|
60
|
+
setValue(next, { type, ...config } = { type: "spring" }) {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
const val = state.current.val;
|
|
63
|
+
if (type === "direct") {
|
|
64
|
+
val.setValue(next);
|
|
65
|
+
} else if (type === "spring") {
|
|
66
|
+
(_a = state.current.composite) == null ? void 0 : _a.stop();
|
|
67
|
+
const composite = import_react_native.Animated.spring(val, {
|
|
68
|
+
...config,
|
|
69
|
+
toValue: next,
|
|
70
|
+
useNativeDriver: !import_core.isWeb
|
|
71
|
+
});
|
|
72
|
+
composite.start();
|
|
73
|
+
state.current.composite = composite;
|
|
74
|
+
} else {
|
|
75
|
+
(_b = state.current.composite) == null ? void 0 : _b.stop();
|
|
76
|
+
const composite = import_react_native.Animated.timing(val, {
|
|
77
|
+
...config,
|
|
78
|
+
toValue: next,
|
|
79
|
+
useNativeDriver: !import_core.isWeb
|
|
80
|
+
});
|
|
81
|
+
composite.start();
|
|
82
|
+
state.current.composite = composite;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function useAnimatedNumberReaction(value, cb) {
|
|
88
|
+
const onChange = (0, import_core.useEvent)((current) => {
|
|
89
|
+
cb(current.value);
|
|
90
|
+
});
|
|
91
|
+
(0, import_react.useEffect)(() => {
|
|
92
|
+
const id = value.getInstance().addListener(onChange);
|
|
93
|
+
return () => {
|
|
94
|
+
value.getInstance().removeListener(id);
|
|
95
|
+
};
|
|
96
|
+
}, [value, onChange]);
|
|
97
|
+
}
|
|
98
|
+
function useAnimatedNumberStyle(value, getStyle) {
|
|
99
|
+
return getStyle(value.getInstance());
|
|
100
|
+
}
|
|
32
101
|
function createAnimations(animations) {
|
|
33
|
-
const AnimatedView = import_react_native.Animated.View;
|
|
34
|
-
const AnimatedText = import_react_native.Animated.Text;
|
|
35
102
|
AnimatedView["displayName"] = "AnimatedView";
|
|
36
103
|
AnimatedText["displayName"] = "AnimatedText";
|
|
37
104
|
return {
|
|
@@ -39,6 +106,9 @@ function createAnimations(animations) {
|
|
|
39
106
|
animations,
|
|
40
107
|
View: AnimatedView,
|
|
41
108
|
Text: AnimatedText,
|
|
109
|
+
useAnimatedNumber,
|
|
110
|
+
useAnimatedNumberReaction,
|
|
111
|
+
useAnimatedNumberStyle,
|
|
42
112
|
useAnimations: (props, helpers) => {
|
|
43
113
|
var _a;
|
|
44
114
|
const { onDidAnimate, delay, getStyle, state } = helpers;
|
|
@@ -94,19 +164,6 @@ function createAnimations(animations) {
|
|
|
94
164
|
const [_, number, after] = input.match(/([-0-9]+)(deg|%)/) ?? [];
|
|
95
165
|
return [+number * (neg ? -1 : 1), after];
|
|
96
166
|
}
|
|
97
|
-
function getInterpolated(val, postfix, next) {
|
|
98
|
-
const cur = val["_value"];
|
|
99
|
-
const inputRange = [cur, next];
|
|
100
|
-
const outputRange = [`${cur}deg`, `${next}deg`];
|
|
101
|
-
if (next < cur) {
|
|
102
|
-
inputRange.reverse();
|
|
103
|
-
outputRange.reverse();
|
|
104
|
-
}
|
|
105
|
-
return val.interpolate({
|
|
106
|
-
inputRange,
|
|
107
|
-
outputRange
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
167
|
const nonAnimatedStyle = {};
|
|
111
168
|
for (const key in all) {
|
|
112
169
|
const val = all[key];
|
|
@@ -171,6 +228,19 @@ function createAnimations(animations) {
|
|
|
171
228
|
}
|
|
172
229
|
};
|
|
173
230
|
}
|
|
231
|
+
function getInterpolated(val, postfix, next) {
|
|
232
|
+
const cur = val["_value"];
|
|
233
|
+
const inputRange = [cur, next];
|
|
234
|
+
const outputRange = [`${cur}deg`, `${next}deg`];
|
|
235
|
+
if (next < cur) {
|
|
236
|
+
inputRange.reverse();
|
|
237
|
+
outputRange.reverse();
|
|
238
|
+
}
|
|
239
|
+
return val.interpolate({
|
|
240
|
+
inputRange,
|
|
241
|
+
outputRange
|
|
242
|
+
});
|
|
243
|
+
}
|
|
174
244
|
function getAnimationConfig(key, animations, animation) {
|
|
175
245
|
if (typeof animation === "string") {
|
|
176
246
|
return animations[animation];
|
|
@@ -204,6 +274,11 @@ function getAnimationConfig(key, animations, animation) {
|
|
|
204
274
|
}
|
|
205
275
|
// Annotate the CommonJS export names for ESM import in node:
|
|
206
276
|
0 && (module.exports = {
|
|
207
|
-
|
|
277
|
+
AnimatedText,
|
|
278
|
+
AnimatedView,
|
|
279
|
+
createAnimations,
|
|
280
|
+
useAnimatedNumber,
|
|
281
|
+
useAnimatedNumberReaction,
|
|
282
|
+
useAnimatedNumberStyle
|
|
208
283
|
});
|
|
209
284
|
//# sourceMappingURL=createAnimations.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/createAnimations.tsx"],
|
|
4
|
-
"sourcesContent": ["import { PresenceContext, usePresence } from '@tamagui/animate-presence'\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAA6C;AAC7C,
|
|
4
|
+
"sourcesContent": ["import { PresenceContext, usePresence } from '@tamagui/animate-presence'\nimport {\n AnimatedNumberStrategy,\n AnimationDriver,\n AnimationProp,\n UniversalAnimatedNumber,\n isWeb,\n useEvent,\n useIsomorphicLayoutEffect,\n} from '@tamagui/core'\nimport { useContext, useEffect, useMemo, useRef } from 'react'\nimport { Animated } from 'react-native'\n\ntype AnimationsConfig<A extends Object = any> = {\n [Key in keyof A]: AnimationConfig\n}\n\ntype AnimationConfig = Partial<\n Pick<\n Animated.SpringAnimationConfig,\n | 'delay'\n | 'bounciness'\n | 'damping'\n | 'friction'\n | 'mass'\n | 'overshootClamping'\n | 'speed'\n | 'stiffness'\n | 'tension'\n | 'velocity'\n >\n>\n\nconst animatedStyleKey = {\n transform: true,\n opacity: true,\n}\n\nexport const AnimatedView = Animated.View\nexport const AnimatedText = Animated.Text\n\nexport function useAnimatedNumber(initial: number): UniversalAnimatedNumber<Animated.Value> {\n const state = useRef(\n null as any as {\n val: Animated.Value\n composite: Animated.CompositeAnimation | null\n strategy: AnimatedNumberStrategy\n }\n )\n if (!state.current) {\n state.current = {\n composite: null,\n val: new Animated.Value(initial),\n strategy: { type: 'spring' },\n }\n }\n\n return {\n getInstance() {\n return state.current.val\n },\n getValue() {\n return state.current.val['_value']\n },\n stop() {\n state.current.composite?.stop()\n state.current.composite = null\n },\n setValue(next: number, { type, ...config } = { type: 'spring' }) {\n const val = state.current.val\n if (type === 'direct') {\n val.setValue(next)\n } else if (type === 'spring') {\n state.current.composite?.stop()\n const composite = Animated.spring(val, {\n ...config,\n toValue: next,\n useNativeDriver: !isWeb,\n })\n composite.start()\n state.current.composite = composite\n } else {\n state.current.composite?.stop()\n const composite = Animated.timing(val, {\n ...config,\n toValue: next,\n useNativeDriver: !isWeb,\n })\n composite.start()\n state.current.composite = composite\n }\n },\n }\n}\n\nexport function useAnimatedNumberReaction(\n value: UniversalAnimatedNumber<Animated.Value>,\n cb: (current: number) => void\n) {\n const onChange = useEvent((current) => {\n cb(current.value)\n })\n\n useEffect(() => {\n const id = value.getInstance().addListener(onChange)\n return () => {\n value.getInstance().removeListener(id)\n }\n }, [value, onChange])\n}\n\nexport function useAnimatedNumberStyle<V extends UniversalAnimatedNumber<Animated.Value>>(\n value: V,\n getStyle: (value: any) => any\n) {\n return getStyle(value.getInstance())\n}\n\nexport function createAnimations<A extends AnimationsConfig>(animations: A): AnimationDriver<A> {\n AnimatedView['displayName'] = 'AnimatedView'\n AnimatedText['displayName'] = 'AnimatedText'\n\n return {\n avoidClasses: true,\n animations,\n View: AnimatedView,\n Text: AnimatedText,\n useAnimatedNumber,\n useAnimatedNumberReaction,\n useAnimatedNumberStyle,\n useAnimations: (props, helpers) => {\n const { onDidAnimate, delay, getStyle, state } = helpers\n const [isPresent, sendExitComplete] = usePresence()\n const presence = useContext(PresenceContext)\n\n // const exitStyle = presence?.exitVariant\n // ? staticConfig.variantsParsed?.[presence.exitVariant]?.true || pseudos.exitStyle\n // : pseudos.exitStyle\n\n const isExiting = isPresent === false\n const isEntering = !state.mounted\n\n const all = getStyle({\n isExiting,\n isEntering,\n exitVariant: presence?.exitVariant,\n enterVariant: presence?.enterVariant,\n })\n\n const animateStyles = useRef<Record<string, Animated.Value>>({})\n const animatedTranforms = useRef<{ [key: string]: Animated.Value }[]>([])\n const interpolations = useRef(new WeakMap<Animated.Value, Animated.AnimatedInterpolation>())\n\n // TODO loop and create values, run them if they change\n\n const runners: Function[] = []\n const completions: Promise<void>[] = []\n\n function update(key: string, animated: Animated.Value | undefined, valIn: string | number) {\n const [val, type] = getValue(valIn)\n const value = animated || new Animated.Value(val)\n if (type) {\n interpolations.current.set(value, getInterpolated(value, type, val))\n }\n if (animated) {\n const animationConfig = getAnimationConfig(key, animations, props.animation)\n\n let resolve\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n completions.push(promise)\n\n runners.push(() => {\n Animated.spring(animated, {\n toValue: val,\n useNativeDriver: !isWeb,\n ...animationConfig,\n }).start(({ finished }) => {\n if (finished) {\n resolve()\n }\n })\n })\n }\n return value\n }\n\n function getValue(input: number | string) {\n if (typeof input !== 'string') {\n return [input] as const\n }\n const neg = input[0] === '-'\n if (neg) input = input.slice(1)\n const [_, number, after] = input.match(/([-0-9]+)(deg|%)/) ?? []\n return [+number * (neg ? -1 : 1), after] as const\n }\n\n const nonAnimatedStyle = {}\n for (const key in all) {\n const val = all[key]\n if (animatedStyleKey[key]) {\n if (key === 'transform') {\n // for now just support one transform key\n if (val) {\n for (const [index, transform] of val.entries()) {\n if (!transform) continue\n const tkey = Object.keys(transform)[0]\n animatedTranforms.current[index] = {\n [tkey]: update(tkey, animatedTranforms.current[index]?.[tkey], transform[tkey]),\n }\n }\n }\n } else {\n animateStyles.current[key] = update(key, animateStyles.current[key], val)\n }\n } else {\n nonAnimatedStyle[key] = val\n }\n }\n\n const animatedStyle = {\n ...Object.fromEntries(\n Object.entries({\n ...animateStyles.current,\n }).map(([k, v]) => [k, interpolations.current.get(v) || v])\n ),\n transform: animatedTranforms.current.map((r) => {\n const key = Object.keys(r)[0]\n const val = interpolations.current.get(r[key]) || r[key]\n return { [key]: val }\n }),\n }\n\n const args = [\n JSON.stringify(all),\n state.mounted,\n state.hover,\n state.press,\n state.pressIn,\n state.focus,\n delay,\n isPresent,\n onDidAnimate,\n presence?.exitVariant,\n presence?.enterVariant,\n ]\n\n useIsomorphicLayoutEffect(() => {\n //\n for (const runner of runners) {\n runner()\n }\n Promise.all(completions).then(() => {\n onDidAnimate?.()\n if (isExiting) {\n sendExitComplete?.()\n }\n })\n }, args)\n\n return useMemo(() => {\n return {\n style: [nonAnimatedStyle, animatedStyle],\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, args)\n },\n }\n}\n\nfunction getInterpolated(val: Animated.Value, postfix: string, next: number) {\n const cur = val['_value'] as number\n const inputRange = [cur, next]\n const outputRange = [`${cur}deg`, `${next}deg`]\n if (next < cur) {\n inputRange.reverse()\n outputRange.reverse()\n }\n return val.interpolate({\n inputRange,\n outputRange,\n })\n}\n\nfunction getAnimationConfig(key: string, animations: AnimationsConfig, animation?: AnimationProp) {\n if (typeof animation === 'string') {\n return animations[animation]\n }\n let type = ''\n let extraConf: any\n if (Array.isArray(animation)) {\n type = animation[0] as string\n const conf = animation[1] && animation[1][key]\n if (conf) {\n if (typeof conf === 'string') {\n type = conf\n } else {\n type = (conf as any).type || type\n extraConf = conf\n }\n }\n } else {\n const val = animation?.[key]\n type = val?.type\n extraConf = val\n }\n const found = animations[type]\n if (!found) {\n throw new Error(`No animation of type \"${type}\" for key \"${key}\"`)\n }\n return {\n ...found,\n ...extraConf,\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAA6C;AAC7C,kBAQO;AACP,mBAAuD;AACvD,0BAAyB;AAsBzB,MAAM,mBAAmB;AAAA,EACvB,WAAW;AAAA,EACX,SAAS;AACX;AAEO,MAAM,eAAe,6BAAS;AAC9B,MAAM,eAAe,6BAAS;AAE9B,2BAA2B,SAA0D;AAC1F,QAAM,QAAQ,yBACZ,IAKF;AACA,MAAI,CAAC,MAAM,SAAS;AAClB,UAAM,UAAU;AAAA,MACd,WAAW;AAAA,MACX,KAAK,IAAI,6BAAS,MAAM,OAAO;AAAA,MAC/B,UAAU,EAAE,MAAM,SAAS;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,cAAc;AACZ,aAAO,MAAM,QAAQ;AAAA,IACvB;AAAA,IACA,WAAW;AACT,aAAO,MAAM,QAAQ,IAAI;AAAA,IAC3B;AAAA,IACA,OAAO;AAhEX;AAiEM,kBAAM,QAAQ,cAAd,mBAAyB;AACzB,YAAM,QAAQ,YAAY;AAAA,IAC5B;AAAA,IACA,SAAS,MAAc,EAAE,SAAS,WAAW,EAAE,MAAM,SAAS,GAAG;AApErE;AAqEM,YAAM,MAAM,MAAM,QAAQ;AAC1B,UAAI,SAAS,UAAU;AACrB,YAAI,SAAS,IAAI;AAAA,MACnB,WAAW,SAAS,UAAU;AAC5B,oBAAM,QAAQ,cAAd,mBAAyB;AACzB,cAAM,YAAY,6BAAS,OAAO,KAAK;AAAA,UACrC,GAAG;AAAA,UACH,SAAS;AAAA,UACT,iBAAiB,CAAC;AAAA,QACpB,CAAC;AACD,kBAAU,MAAM;AAChB,cAAM,QAAQ,YAAY;AAAA,MAC5B,OAAO;AACL,oBAAM,QAAQ,cAAd,mBAAyB;AACzB,cAAM,YAAY,6BAAS,OAAO,KAAK;AAAA,UACrC,GAAG;AAAA,UACH,SAAS;AAAA,UACT,iBAAiB,CAAC;AAAA,QACpB,CAAC;AACD,kBAAU,MAAM;AAChB,cAAM,QAAQ,YAAY;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AACF;AAEO,mCACL,OACA,IACA;AACA,QAAM,WAAW,0BAAS,CAAC,YAAY;AACrC,OAAG,QAAQ,KAAK;AAAA,EAClB,CAAC;AAED,8BAAU,MAAM;AACd,UAAM,KAAK,MAAM,YAAY,EAAE,YAAY,QAAQ;AACnD,WAAO,MAAM;AACX,YAAM,YAAY,EAAE,eAAe,EAAE;AAAA,IACvC;AAAA,EACF,GAAG,CAAC,OAAO,QAAQ,CAAC;AACtB;AAEO,gCACL,OACA,UACA;AACA,SAAO,SAAS,MAAM,YAAY,CAAC;AACrC;AAEO,0BAAsD,YAAmC;AAC9F,eAAa,iBAAiB;AAC9B,eAAa,iBAAiB;AAE9B,SAAO;AAAA,IACL,cAAc;AAAA,IACd;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,CAAC,OAAO,YAAY;AAlIvC;AAmIM,YAAM,EAAE,cAAc,OAAO,UAAU,UAAU;AACjD,YAAM,CAAC,WAAW,oBAAoB,yCAAY;AAClD,YAAM,WAAW,6BAAW,uCAAe;AAM3C,YAAM,YAAY,cAAc;AAChC,YAAM,aAAa,CAAC,MAAM;AAE1B,YAAM,MAAM,SAAS;AAAA,QACnB;AAAA,QACA;AAAA,QACA,aAAa,qCAAU;AAAA,QACvB,cAAc,qCAAU;AAAA,MAC1B,CAAC;AAED,YAAM,gBAAgB,yBAAuC,CAAC,CAAC;AAC/D,YAAM,oBAAoB,yBAA4C,CAAC,CAAC;AACxE,YAAM,iBAAiB,yBAAO,oBAAI,QAAwD,CAAC;AAI3F,YAAM,UAAsB,CAAC;AAC7B,YAAM,cAA+B,CAAC;AAEtC,sBAAgB,KAAa,UAAsC,OAAwB;AACzF,cAAM,CAAC,KAAK,QAAQ,SAAS,KAAK;AAClC,cAAM,QAAQ,YAAY,IAAI,6BAAS,MAAM,GAAG;AAChD,YAAI,MAAM;AACR,yBAAe,QAAQ,IAAI,OAAO,gBAAgB,OAAO,MAAM,GAAG,CAAC;AAAA,QACrE;AACA,YAAI,UAAU;AACZ,gBAAM,kBAAkB,mBAAmB,KAAK,YAAY,MAAM,SAAS;AAE3E,cAAI;AACJ,gBAAM,UAAU,IAAI,QAAc,CAAC,QAAQ;AACzC,sBAAU;AAAA,UACZ,CAAC;AACD,sBAAY,KAAK,OAAO;AAExB,kBAAQ,KAAK,MAAM;AACjB,yCAAS,OAAO,UAAU;AAAA,cACxB,SAAS;AAAA,cACT,iBAAiB,CAAC;AAAA,cAClB,GAAG;AAAA,YACL,CAAC,EAAE,MAAM,CAAC,EAAE,eAAe;AACzB,kBAAI,UAAU;AACZ,wBAAQ;AAAA,cACV;AAAA,YACF,CAAC;AAAA,UACH,CAAC;AAAA,QACH;AACA,eAAO;AAAA,MACT;AAEA,wBAAkB,OAAwB;AACxC,YAAI,OAAO,UAAU,UAAU;AAC7B,iBAAO,CAAC,KAAK;AAAA,QACf;AACA,cAAM,MAAM,MAAM,OAAO;AACzB,YAAI;AAAK,kBAAQ,MAAM,MAAM,CAAC;AAC9B,cAAM,CAAC,GAAG,QAAQ,SAAS,MAAM,MAAM,kBAAkB,KAAK,CAAC;AAC/D,eAAO,CAAC,CAAC,SAAU,OAAM,KAAK,IAAI,KAAK;AAAA,MACzC;AAEA,YAAM,mBAAmB,CAAC;AAC1B,iBAAW,OAAO,KAAK;AACrB,cAAM,MAAM,IAAI;AAChB,YAAI,iBAAiB,MAAM;AACzB,cAAI,QAAQ,aAAa;AAEvB,gBAAI,KAAK;AACP,yBAAW,CAAC,OAAO,cAAc,IAAI,QAAQ,GAAG;AAC9C,oBAAI,CAAC;AAAW;AAChB,sBAAM,OAAO,OAAO,KAAK,SAAS,EAAE;AACpC,kCAAkB,QAAQ,SAAS;AAAA,kBACjC,CAAC,OAAO,OAAO,MAAM,wBAAkB,QAAQ,WAA1B,mBAAmC,OAAO,UAAU,KAAK;AAAA,gBAChF;AAAA,cACF;AAAA,YACF;AAAA,UACF,OAAO;AACL,0BAAc,QAAQ,OAAO,OAAO,KAAK,cAAc,QAAQ,MAAM,GAAG;AAAA,UAC1E;AAAA,QACF,OAAO;AACL,2BAAiB,OAAO;AAAA,QAC1B;AAAA,MACF;AAEA,YAAM,gBAAgB;AAAA,QACpB,GAAG,OAAO,YACR,OAAO,QAAQ;AAAA,UACb,GAAG,cAAc;AAAA,QACnB,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,eAAe,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,CAC5D;AAAA,QACA,WAAW,kBAAkB,QAAQ,IAAI,CAAC,MAAM;AAC9C,gBAAM,MAAM,OAAO,KAAK,CAAC,EAAE;AAC3B,gBAAM,MAAM,eAAe,QAAQ,IAAI,EAAE,IAAI,KAAK,EAAE;AACpD,iBAAO,EAAE,CAAC,MAAM,IAAI;AAAA,QACtB,CAAC;AAAA,MACH;AAEA,YAAM,OAAO;AAAA,QACX,KAAK,UAAU,GAAG;AAAA,QAClB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,qCAAU;AAAA,QACV,qCAAU;AAAA,MACZ;AAEA,iDAA0B,MAAM;AAE9B,mBAAW,UAAU,SAAS;AAC5B,iBAAO;AAAA,QACT;AACA,gBAAQ,IAAI,WAAW,EAAE,KAAK,MAAM;AAClC;AACA,cAAI,WAAW;AACb;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,GAAG,IAAI;AAEP,aAAO,0BAAQ,MAAM;AACnB,eAAO;AAAA,UACL,OAAO,CAAC,kBAAkB,aAAa;AAAA,QACzC;AAAA,MAEF,GAAG,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAEA,yBAAyB,KAAqB,SAAiB,MAAc;AAC3E,QAAM,MAAM,IAAI;AAChB,QAAM,aAAa,CAAC,KAAK,IAAI;AAC7B,QAAM,cAAc,CAAC,GAAG,UAAU,GAAG,SAAS;AAC9C,MAAI,OAAO,KAAK;AACd,eAAW,QAAQ;AACnB,gBAAY,QAAQ;AAAA,EACtB;AACA,SAAO,IAAI,YAAY;AAAA,IACrB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,4BAA4B,KAAa,YAA8B,WAA2B;AAChG,MAAI,OAAO,cAAc,UAAU;AACjC,WAAO,WAAW;AAAA,EACpB;AACA,MAAI,OAAO;AACX,MAAI;AACJ,MAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,WAAO,UAAU;AACjB,UAAM,OAAO,UAAU,MAAM,UAAU,GAAG;AAC1C,QAAI,MAAM;AACR,UAAI,OAAO,SAAS,UAAU;AAC5B,eAAO;AAAA,MACT,OAAO;AACL,eAAQ,KAAa,QAAQ;AAC7B,oBAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM,MAAM,uCAAY;AACxB,WAAO,2BAAK;AACZ,gBAAY;AAAA,EACd;AACA,QAAM,QAAQ,WAAW;AACzB,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,yBAAyB,kBAAkB,MAAM;AAAA,EACnE;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,14 +1,80 @@
|
|
|
1
1
|
import { PresenceContext, usePresence } from "@tamagui/animate-presence";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
isWeb,
|
|
4
|
+
useEvent,
|
|
5
|
+
useIsomorphicLayoutEffect
|
|
6
|
+
} from "@tamagui/core";
|
|
7
|
+
import { useContext, useEffect, useMemo, useRef } from "react";
|
|
4
8
|
import { Animated } from "react-native";
|
|
5
9
|
const animatedStyleKey = {
|
|
6
10
|
transform: true,
|
|
7
11
|
opacity: true
|
|
8
12
|
};
|
|
13
|
+
const AnimatedView = Animated.View;
|
|
14
|
+
const AnimatedText = Animated.Text;
|
|
15
|
+
function useAnimatedNumber(initial) {
|
|
16
|
+
const state = useRef(null);
|
|
17
|
+
if (!state.current) {
|
|
18
|
+
state.current = {
|
|
19
|
+
composite: null,
|
|
20
|
+
val: new Animated.Value(initial),
|
|
21
|
+
strategy: { type: "spring" }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
getInstance() {
|
|
26
|
+
return state.current.val;
|
|
27
|
+
},
|
|
28
|
+
getValue() {
|
|
29
|
+
return state.current.val["_value"];
|
|
30
|
+
},
|
|
31
|
+
stop() {
|
|
32
|
+
var _a;
|
|
33
|
+
(_a = state.current.composite) == null ? void 0 : _a.stop();
|
|
34
|
+
state.current.composite = null;
|
|
35
|
+
},
|
|
36
|
+
setValue(next, { type, ...config } = { type: "spring" }) {
|
|
37
|
+
var _a, _b;
|
|
38
|
+
const val = state.current.val;
|
|
39
|
+
if (type === "direct") {
|
|
40
|
+
val.setValue(next);
|
|
41
|
+
} else if (type === "spring") {
|
|
42
|
+
(_a = state.current.composite) == null ? void 0 : _a.stop();
|
|
43
|
+
const composite = Animated.spring(val, {
|
|
44
|
+
...config,
|
|
45
|
+
toValue: next,
|
|
46
|
+
useNativeDriver: !isWeb
|
|
47
|
+
});
|
|
48
|
+
composite.start();
|
|
49
|
+
state.current.composite = composite;
|
|
50
|
+
} else {
|
|
51
|
+
(_b = state.current.composite) == null ? void 0 : _b.stop();
|
|
52
|
+
const composite = Animated.timing(val, {
|
|
53
|
+
...config,
|
|
54
|
+
toValue: next,
|
|
55
|
+
useNativeDriver: !isWeb
|
|
56
|
+
});
|
|
57
|
+
composite.start();
|
|
58
|
+
state.current.composite = composite;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function useAnimatedNumberReaction(value, cb) {
|
|
64
|
+
const onChange = useEvent((current) => {
|
|
65
|
+
cb(current.value);
|
|
66
|
+
});
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const id = value.getInstance().addListener(onChange);
|
|
69
|
+
return () => {
|
|
70
|
+
value.getInstance().removeListener(id);
|
|
71
|
+
};
|
|
72
|
+
}, [value, onChange]);
|
|
73
|
+
}
|
|
74
|
+
function useAnimatedNumberStyle(value, getStyle) {
|
|
75
|
+
return getStyle(value.getInstance());
|
|
76
|
+
}
|
|
9
77
|
function createAnimations(animations) {
|
|
10
|
-
const AnimatedView = Animated.View;
|
|
11
|
-
const AnimatedText = Animated.Text;
|
|
12
78
|
AnimatedView["displayName"] = "AnimatedView";
|
|
13
79
|
AnimatedText["displayName"] = "AnimatedText";
|
|
14
80
|
return {
|
|
@@ -16,6 +82,9 @@ function createAnimations(animations) {
|
|
|
16
82
|
animations,
|
|
17
83
|
View: AnimatedView,
|
|
18
84
|
Text: AnimatedText,
|
|
85
|
+
useAnimatedNumber,
|
|
86
|
+
useAnimatedNumberReaction,
|
|
87
|
+
useAnimatedNumberStyle,
|
|
19
88
|
useAnimations: (props, helpers) => {
|
|
20
89
|
var _a;
|
|
21
90
|
const { onDidAnimate, delay, getStyle, state } = helpers;
|
|
@@ -71,19 +140,6 @@ function createAnimations(animations) {
|
|
|
71
140
|
const [_, number, after] = input.match(/([-0-9]+)(deg|%)/) ?? [];
|
|
72
141
|
return [+number * (neg ? -1 : 1), after];
|
|
73
142
|
}
|
|
74
|
-
function getInterpolated(val, postfix, next) {
|
|
75
|
-
const cur = val["_value"];
|
|
76
|
-
const inputRange = [cur, next];
|
|
77
|
-
const outputRange = [`${cur}deg`, `${next}deg`];
|
|
78
|
-
if (next < cur) {
|
|
79
|
-
inputRange.reverse();
|
|
80
|
-
outputRange.reverse();
|
|
81
|
-
}
|
|
82
|
-
return val.interpolate({
|
|
83
|
-
inputRange,
|
|
84
|
-
outputRange
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
143
|
const nonAnimatedStyle = {};
|
|
88
144
|
for (const key in all) {
|
|
89
145
|
const val = all[key];
|
|
@@ -148,6 +204,19 @@ function createAnimations(animations) {
|
|
|
148
204
|
}
|
|
149
205
|
};
|
|
150
206
|
}
|
|
207
|
+
function getInterpolated(val, postfix, next) {
|
|
208
|
+
const cur = val["_value"];
|
|
209
|
+
const inputRange = [cur, next];
|
|
210
|
+
const outputRange = [`${cur}deg`, `${next}deg`];
|
|
211
|
+
if (next < cur) {
|
|
212
|
+
inputRange.reverse();
|
|
213
|
+
outputRange.reverse();
|
|
214
|
+
}
|
|
215
|
+
return val.interpolate({
|
|
216
|
+
inputRange,
|
|
217
|
+
outputRange
|
|
218
|
+
});
|
|
219
|
+
}
|
|
151
220
|
function getAnimationConfig(key, animations, animation) {
|
|
152
221
|
if (typeof animation === "string") {
|
|
153
222
|
return animations[animation];
|
|
@@ -180,6 +249,11 @@ function getAnimationConfig(key, animations, animation) {
|
|
|
180
249
|
};
|
|
181
250
|
}
|
|
182
251
|
export {
|
|
183
|
-
|
|
252
|
+
AnimatedText,
|
|
253
|
+
AnimatedView,
|
|
254
|
+
createAnimations,
|
|
255
|
+
useAnimatedNumber,
|
|
256
|
+
useAnimatedNumberReaction,
|
|
257
|
+
useAnimatedNumberStyle
|
|
184
258
|
};
|
|
185
259
|
//# sourceMappingURL=createAnimations.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/createAnimations.tsx"],
|
|
4
|
-
"sourcesContent": ["import { PresenceContext, usePresence } from '@tamagui/animate-presence'\nimport {
|
|
5
|
-
"mappings": "AAAA;AACA;
|
|
4
|
+
"sourcesContent": ["import { PresenceContext, usePresence } from '@tamagui/animate-presence'\nimport {\n AnimatedNumberStrategy,\n AnimationDriver,\n AnimationProp,\n UniversalAnimatedNumber,\n isWeb,\n useEvent,\n useIsomorphicLayoutEffect,\n} from '@tamagui/core'\nimport { useContext, useEffect, useMemo, useRef } from 'react'\nimport { Animated } from 'react-native'\n\ntype AnimationsConfig<A extends Object = any> = {\n [Key in keyof A]: AnimationConfig\n}\n\ntype AnimationConfig = Partial<\n Pick<\n Animated.SpringAnimationConfig,\n | 'delay'\n | 'bounciness'\n | 'damping'\n | 'friction'\n | 'mass'\n | 'overshootClamping'\n | 'speed'\n | 'stiffness'\n | 'tension'\n | 'velocity'\n >\n>\n\nconst animatedStyleKey = {\n transform: true,\n opacity: true,\n}\n\nexport const AnimatedView = Animated.View\nexport const AnimatedText = Animated.Text\n\nexport function useAnimatedNumber(initial: number): UniversalAnimatedNumber<Animated.Value> {\n const state = useRef(\n null as any as {\n val: Animated.Value\n composite: Animated.CompositeAnimation | null\n strategy: AnimatedNumberStrategy\n }\n )\n if (!state.current) {\n state.current = {\n composite: null,\n val: new Animated.Value(initial),\n strategy: { type: 'spring' },\n }\n }\n\n return {\n getInstance() {\n return state.current.val\n },\n getValue() {\n return state.current.val['_value']\n },\n stop() {\n state.current.composite?.stop()\n state.current.composite = null\n },\n setValue(next: number, { type, ...config } = { type: 'spring' }) {\n const val = state.current.val\n if (type === 'direct') {\n val.setValue(next)\n } else if (type === 'spring') {\n state.current.composite?.stop()\n const composite = Animated.spring(val, {\n ...config,\n toValue: next,\n useNativeDriver: !isWeb,\n })\n composite.start()\n state.current.composite = composite\n } else {\n state.current.composite?.stop()\n const composite = Animated.timing(val, {\n ...config,\n toValue: next,\n useNativeDriver: !isWeb,\n })\n composite.start()\n state.current.composite = composite\n }\n },\n }\n}\n\nexport function useAnimatedNumberReaction(\n value: UniversalAnimatedNumber<Animated.Value>,\n cb: (current: number) => void\n) {\n const onChange = useEvent((current) => {\n cb(current.value)\n })\n\n useEffect(() => {\n const id = value.getInstance().addListener(onChange)\n return () => {\n value.getInstance().removeListener(id)\n }\n }, [value, onChange])\n}\n\nexport function useAnimatedNumberStyle<V extends UniversalAnimatedNumber<Animated.Value>>(\n value: V,\n getStyle: (value: any) => any\n) {\n return getStyle(value.getInstance())\n}\n\nexport function createAnimations<A extends AnimationsConfig>(animations: A): AnimationDriver<A> {\n AnimatedView['displayName'] = 'AnimatedView'\n AnimatedText['displayName'] = 'AnimatedText'\n\n return {\n avoidClasses: true,\n animations,\n View: AnimatedView,\n Text: AnimatedText,\n useAnimatedNumber,\n useAnimatedNumberReaction,\n useAnimatedNumberStyle,\n useAnimations: (props, helpers) => {\n const { onDidAnimate, delay, getStyle, state } = helpers\n const [isPresent, sendExitComplete] = usePresence()\n const presence = useContext(PresenceContext)\n\n // const exitStyle = presence?.exitVariant\n // ? staticConfig.variantsParsed?.[presence.exitVariant]?.true || pseudos.exitStyle\n // : pseudos.exitStyle\n\n const isExiting = isPresent === false\n const isEntering = !state.mounted\n\n const all = getStyle({\n isExiting,\n isEntering,\n exitVariant: presence?.exitVariant,\n enterVariant: presence?.enterVariant,\n })\n\n const animateStyles = useRef<Record<string, Animated.Value>>({})\n const animatedTranforms = useRef<{ [key: string]: Animated.Value }[]>([])\n const interpolations = useRef(new WeakMap<Animated.Value, Animated.AnimatedInterpolation>())\n\n // TODO loop and create values, run them if they change\n\n const runners: Function[] = []\n const completions: Promise<void>[] = []\n\n function update(key: string, animated: Animated.Value | undefined, valIn: string | number) {\n const [val, type] = getValue(valIn)\n const value = animated || new Animated.Value(val)\n if (type) {\n interpolations.current.set(value, getInterpolated(value, type, val))\n }\n if (animated) {\n const animationConfig = getAnimationConfig(key, animations, props.animation)\n\n let resolve\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n completions.push(promise)\n\n runners.push(() => {\n Animated.spring(animated, {\n toValue: val,\n useNativeDriver: !isWeb,\n ...animationConfig,\n }).start(({ finished }) => {\n if (finished) {\n resolve()\n }\n })\n })\n }\n return value\n }\n\n function getValue(input: number | string) {\n if (typeof input !== 'string') {\n return [input] as const\n }\n const neg = input[0] === '-'\n if (neg) input = input.slice(1)\n const [_, number, after] = input.match(/([-0-9]+)(deg|%)/) ?? []\n return [+number * (neg ? -1 : 1), after] as const\n }\n\n const nonAnimatedStyle = {}\n for (const key in all) {\n const val = all[key]\n if (animatedStyleKey[key]) {\n if (key === 'transform') {\n // for now just support one transform key\n if (val) {\n for (const [index, transform] of val.entries()) {\n if (!transform) continue\n const tkey = Object.keys(transform)[0]\n animatedTranforms.current[index] = {\n [tkey]: update(tkey, animatedTranforms.current[index]?.[tkey], transform[tkey]),\n }\n }\n }\n } else {\n animateStyles.current[key] = update(key, animateStyles.current[key], val)\n }\n } else {\n nonAnimatedStyle[key] = val\n }\n }\n\n const animatedStyle = {\n ...Object.fromEntries(\n Object.entries({\n ...animateStyles.current,\n }).map(([k, v]) => [k, interpolations.current.get(v) || v])\n ),\n transform: animatedTranforms.current.map((r) => {\n const key = Object.keys(r)[0]\n const val = interpolations.current.get(r[key]) || r[key]\n return { [key]: val }\n }),\n }\n\n const args = [\n JSON.stringify(all),\n state.mounted,\n state.hover,\n state.press,\n state.pressIn,\n state.focus,\n delay,\n isPresent,\n onDidAnimate,\n presence?.exitVariant,\n presence?.enterVariant,\n ]\n\n useIsomorphicLayoutEffect(() => {\n //\n for (const runner of runners) {\n runner()\n }\n Promise.all(completions).then(() => {\n onDidAnimate?.()\n if (isExiting) {\n sendExitComplete?.()\n }\n })\n }, args)\n\n return useMemo(() => {\n return {\n style: [nonAnimatedStyle, animatedStyle],\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, args)\n },\n }\n}\n\nfunction getInterpolated(val: Animated.Value, postfix: string, next: number) {\n const cur = val['_value'] as number\n const inputRange = [cur, next]\n const outputRange = [`${cur}deg`, `${next}deg`]\n if (next < cur) {\n inputRange.reverse()\n outputRange.reverse()\n }\n return val.interpolate({\n inputRange,\n outputRange,\n })\n}\n\nfunction getAnimationConfig(key: string, animations: AnimationsConfig, animation?: AnimationProp) {\n if (typeof animation === 'string') {\n return animations[animation]\n }\n let type = ''\n let extraConf: any\n if (Array.isArray(animation)) {\n type = animation[0] as string\n const conf = animation[1] && animation[1][key]\n if (conf) {\n if (typeof conf === 'string') {\n type = conf\n } else {\n type = (conf as any).type || type\n extraConf = conf\n }\n }\n } else {\n const val = animation?.[key]\n type = val?.type\n extraConf = val\n }\n const found = animations[type]\n if (!found) {\n throw new Error(`No animation of type \"${type}\" for key \"${key}\"`)\n }\n return {\n ...found,\n ...extraConf,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,14 +1,78 @@
|
|
|
1
1
|
import { PresenceContext, usePresence } from "@tamagui/animate-presence";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
isWeb,
|
|
4
|
+
useEvent,
|
|
5
|
+
useIsomorphicLayoutEffect
|
|
6
|
+
} from "@tamagui/core";
|
|
7
|
+
import { useContext, useEffect, useMemo, useRef } from "react";
|
|
4
8
|
import { Animated } from "react-native";
|
|
5
9
|
const animatedStyleKey = {
|
|
6
10
|
transform: true,
|
|
7
11
|
opacity: true
|
|
8
12
|
};
|
|
13
|
+
const AnimatedView = Animated.View;
|
|
14
|
+
const AnimatedText = Animated.Text;
|
|
15
|
+
function useAnimatedNumber(initial) {
|
|
16
|
+
const state = useRef(null);
|
|
17
|
+
if (!state.current) {
|
|
18
|
+
state.current = {
|
|
19
|
+
composite: null,
|
|
20
|
+
val: new Animated.Value(initial),
|
|
21
|
+
strategy: { type: "spring" }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
getInstance() {
|
|
26
|
+
return state.current.val;
|
|
27
|
+
},
|
|
28
|
+
getValue() {
|
|
29
|
+
return state.current.val["_value"];
|
|
30
|
+
},
|
|
31
|
+
stop() {
|
|
32
|
+
state.current.composite?.stop();
|
|
33
|
+
state.current.composite = null;
|
|
34
|
+
},
|
|
35
|
+
setValue(next, { type, ...config } = { type: "spring" }) {
|
|
36
|
+
const val = state.current.val;
|
|
37
|
+
if (type === "direct") {
|
|
38
|
+
val.setValue(next);
|
|
39
|
+
} else if (type === "spring") {
|
|
40
|
+
state.current.composite?.stop();
|
|
41
|
+
const composite = Animated.spring(val, {
|
|
42
|
+
...config,
|
|
43
|
+
toValue: next,
|
|
44
|
+
useNativeDriver: !isWeb
|
|
45
|
+
});
|
|
46
|
+
composite.start();
|
|
47
|
+
state.current.composite = composite;
|
|
48
|
+
} else {
|
|
49
|
+
state.current.composite?.stop();
|
|
50
|
+
const composite = Animated.timing(val, {
|
|
51
|
+
...config,
|
|
52
|
+
toValue: next,
|
|
53
|
+
useNativeDriver: !isWeb
|
|
54
|
+
});
|
|
55
|
+
composite.start();
|
|
56
|
+
state.current.composite = composite;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function useAnimatedNumberReaction(value, cb) {
|
|
62
|
+
const onChange = useEvent((current) => {
|
|
63
|
+
cb(current.value);
|
|
64
|
+
});
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const id = value.getInstance().addListener(onChange);
|
|
67
|
+
return () => {
|
|
68
|
+
value.getInstance().removeListener(id);
|
|
69
|
+
};
|
|
70
|
+
}, [value, onChange]);
|
|
71
|
+
}
|
|
72
|
+
function useAnimatedNumberStyle(value, getStyle) {
|
|
73
|
+
return getStyle(value.getInstance());
|
|
74
|
+
}
|
|
9
75
|
function createAnimations(animations) {
|
|
10
|
-
const AnimatedView = Animated.View;
|
|
11
|
-
const AnimatedText = Animated.Text;
|
|
12
76
|
AnimatedView["displayName"] = "AnimatedView";
|
|
13
77
|
AnimatedText["displayName"] = "AnimatedText";
|
|
14
78
|
return {
|
|
@@ -16,6 +80,9 @@ function createAnimations(animations) {
|
|
|
16
80
|
animations,
|
|
17
81
|
View: AnimatedView,
|
|
18
82
|
Text: AnimatedText,
|
|
83
|
+
useAnimatedNumber,
|
|
84
|
+
useAnimatedNumberReaction,
|
|
85
|
+
useAnimatedNumberStyle,
|
|
19
86
|
useAnimations: (props, helpers) => {
|
|
20
87
|
const { onDidAnimate, delay, getStyle, state } = helpers;
|
|
21
88
|
const [isPresent, sendExitComplete] = usePresence();
|
|
@@ -70,19 +137,6 @@ function createAnimations(animations) {
|
|
|
70
137
|
const [_, number, after] = input.match(/([-0-9]+)(deg|%)/) ?? [];
|
|
71
138
|
return [+number * (neg ? -1 : 1), after];
|
|
72
139
|
}
|
|
73
|
-
function getInterpolated(val, postfix, next) {
|
|
74
|
-
const cur = val["_value"];
|
|
75
|
-
const inputRange = [cur, next];
|
|
76
|
-
const outputRange = [`${cur}deg`, `${next}deg`];
|
|
77
|
-
if (next < cur) {
|
|
78
|
-
inputRange.reverse();
|
|
79
|
-
outputRange.reverse();
|
|
80
|
-
}
|
|
81
|
-
return val.interpolate({
|
|
82
|
-
inputRange,
|
|
83
|
-
outputRange
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
140
|
const nonAnimatedStyle = {};
|
|
87
141
|
for (const key in all) {
|
|
88
142
|
const val = all[key];
|
|
@@ -147,6 +201,19 @@ function createAnimations(animations) {
|
|
|
147
201
|
}
|
|
148
202
|
};
|
|
149
203
|
}
|
|
204
|
+
function getInterpolated(val, postfix, next) {
|
|
205
|
+
const cur = val["_value"];
|
|
206
|
+
const inputRange = [cur, next];
|
|
207
|
+
const outputRange = [`${cur}deg`, `${next}deg`];
|
|
208
|
+
if (next < cur) {
|
|
209
|
+
inputRange.reverse();
|
|
210
|
+
outputRange.reverse();
|
|
211
|
+
}
|
|
212
|
+
return val.interpolate({
|
|
213
|
+
inputRange,
|
|
214
|
+
outputRange
|
|
215
|
+
});
|
|
216
|
+
}
|
|
150
217
|
function getAnimationConfig(key, animations, animation) {
|
|
151
218
|
if (typeof animation === "string") {
|
|
152
219
|
return animations[animation];
|
|
@@ -179,6 +246,11 @@ function getAnimationConfig(key, animations, animation) {
|
|
|
179
246
|
};
|
|
180
247
|
}
|
|
181
248
|
export {
|
|
182
|
-
|
|
249
|
+
AnimatedText,
|
|
250
|
+
AnimatedView,
|
|
251
|
+
createAnimations,
|
|
252
|
+
useAnimatedNumber,
|
|
253
|
+
useAnimatedNumberReaction,
|
|
254
|
+
useAnimatedNumberStyle
|
|
183
255
|
};
|
|
184
256
|
//# sourceMappingURL=createAnimations.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/createAnimations.tsx"],
|
|
4
|
-
"sourcesContent": ["import { PresenceContext, usePresence } from '@tamagui/animate-presence'\nimport {
|
|
5
|
-
"mappings": "AAAA;AACA;
|
|
4
|
+
"sourcesContent": ["import { PresenceContext, usePresence } from '@tamagui/animate-presence'\nimport {\n AnimatedNumberStrategy,\n AnimationDriver,\n AnimationProp,\n UniversalAnimatedNumber,\n isWeb,\n useEvent,\n useIsomorphicLayoutEffect,\n} from '@tamagui/core'\nimport { useContext, useEffect, useMemo, useRef } from 'react'\nimport { Animated } from 'react-native'\n\ntype AnimationsConfig<A extends Object = any> = {\n [Key in keyof A]: AnimationConfig\n}\n\ntype AnimationConfig = Partial<\n Pick<\n Animated.SpringAnimationConfig,\n | 'delay'\n | 'bounciness'\n | 'damping'\n | 'friction'\n | 'mass'\n | 'overshootClamping'\n | 'speed'\n | 'stiffness'\n | 'tension'\n | 'velocity'\n >\n>\n\nconst animatedStyleKey = {\n transform: true,\n opacity: true,\n}\n\nexport const AnimatedView = Animated.View\nexport const AnimatedText = Animated.Text\n\nexport function useAnimatedNumber(initial: number): UniversalAnimatedNumber<Animated.Value> {\n const state = useRef(\n null as any as {\n val: Animated.Value\n composite: Animated.CompositeAnimation | null\n strategy: AnimatedNumberStrategy\n }\n )\n if (!state.current) {\n state.current = {\n composite: null,\n val: new Animated.Value(initial),\n strategy: { type: 'spring' },\n }\n }\n\n return {\n getInstance() {\n return state.current.val\n },\n getValue() {\n return state.current.val['_value']\n },\n stop() {\n state.current.composite?.stop()\n state.current.composite = null\n },\n setValue(next: number, { type, ...config } = { type: 'spring' }) {\n const val = state.current.val\n if (type === 'direct') {\n val.setValue(next)\n } else if (type === 'spring') {\n state.current.composite?.stop()\n const composite = Animated.spring(val, {\n ...config,\n toValue: next,\n useNativeDriver: !isWeb,\n })\n composite.start()\n state.current.composite = composite\n } else {\n state.current.composite?.stop()\n const composite = Animated.timing(val, {\n ...config,\n toValue: next,\n useNativeDriver: !isWeb,\n })\n composite.start()\n state.current.composite = composite\n }\n },\n }\n}\n\nexport function useAnimatedNumberReaction(\n value: UniversalAnimatedNumber<Animated.Value>,\n cb: (current: number) => void\n) {\n const onChange = useEvent((current) => {\n cb(current.value)\n })\n\n useEffect(() => {\n const id = value.getInstance().addListener(onChange)\n return () => {\n value.getInstance().removeListener(id)\n }\n }, [value, onChange])\n}\n\nexport function useAnimatedNumberStyle<V extends UniversalAnimatedNumber<Animated.Value>>(\n value: V,\n getStyle: (value: any) => any\n) {\n return getStyle(value.getInstance())\n}\n\nexport function createAnimations<A extends AnimationsConfig>(animations: A): AnimationDriver<A> {\n AnimatedView['displayName'] = 'AnimatedView'\n AnimatedText['displayName'] = 'AnimatedText'\n\n return {\n avoidClasses: true,\n animations,\n View: AnimatedView,\n Text: AnimatedText,\n useAnimatedNumber,\n useAnimatedNumberReaction,\n useAnimatedNumberStyle,\n useAnimations: (props, helpers) => {\n const { onDidAnimate, delay, getStyle, state } = helpers\n const [isPresent, sendExitComplete] = usePresence()\n const presence = useContext(PresenceContext)\n\n // const exitStyle = presence?.exitVariant\n // ? staticConfig.variantsParsed?.[presence.exitVariant]?.true || pseudos.exitStyle\n // : pseudos.exitStyle\n\n const isExiting = isPresent === false\n const isEntering = !state.mounted\n\n const all = getStyle({\n isExiting,\n isEntering,\n exitVariant: presence?.exitVariant,\n enterVariant: presence?.enterVariant,\n })\n\n const animateStyles = useRef<Record<string, Animated.Value>>({})\n const animatedTranforms = useRef<{ [key: string]: Animated.Value }[]>([])\n const interpolations = useRef(new WeakMap<Animated.Value, Animated.AnimatedInterpolation>())\n\n // TODO loop and create values, run them if they change\n\n const runners: Function[] = []\n const completions: Promise<void>[] = []\n\n function update(key: string, animated: Animated.Value | undefined, valIn: string | number) {\n const [val, type] = getValue(valIn)\n const value = animated || new Animated.Value(val)\n if (type) {\n interpolations.current.set(value, getInterpolated(value, type, val))\n }\n if (animated) {\n const animationConfig = getAnimationConfig(key, animations, props.animation)\n\n let resolve\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n completions.push(promise)\n\n runners.push(() => {\n Animated.spring(animated, {\n toValue: val,\n useNativeDriver: !isWeb,\n ...animationConfig,\n }).start(({ finished }) => {\n if (finished) {\n resolve()\n }\n })\n })\n }\n return value\n }\n\n function getValue(input: number | string) {\n if (typeof input !== 'string') {\n return [input] as const\n }\n const neg = input[0] === '-'\n if (neg) input = input.slice(1)\n const [_, number, after] = input.match(/([-0-9]+)(deg|%)/) ?? []\n return [+number * (neg ? -1 : 1), after] as const\n }\n\n const nonAnimatedStyle = {}\n for (const key in all) {\n const val = all[key]\n if (animatedStyleKey[key]) {\n if (key === 'transform') {\n // for now just support one transform key\n if (val) {\n for (const [index, transform] of val.entries()) {\n if (!transform) continue\n const tkey = Object.keys(transform)[0]\n animatedTranforms.current[index] = {\n [tkey]: update(tkey, animatedTranforms.current[index]?.[tkey], transform[tkey]),\n }\n }\n }\n } else {\n animateStyles.current[key] = update(key, animateStyles.current[key], val)\n }\n } else {\n nonAnimatedStyle[key] = val\n }\n }\n\n const animatedStyle = {\n ...Object.fromEntries(\n Object.entries({\n ...animateStyles.current,\n }).map(([k, v]) => [k, interpolations.current.get(v) || v])\n ),\n transform: animatedTranforms.current.map((r) => {\n const key = Object.keys(r)[0]\n const val = interpolations.current.get(r[key]) || r[key]\n return { [key]: val }\n }),\n }\n\n const args = [\n JSON.stringify(all),\n state.mounted,\n state.hover,\n state.press,\n state.pressIn,\n state.focus,\n delay,\n isPresent,\n onDidAnimate,\n presence?.exitVariant,\n presence?.enterVariant,\n ]\n\n useIsomorphicLayoutEffect(() => {\n //\n for (const runner of runners) {\n runner()\n }\n Promise.all(completions).then(() => {\n onDidAnimate?.()\n if (isExiting) {\n sendExitComplete?.()\n }\n })\n }, args)\n\n return useMemo(() => {\n return {\n style: [nonAnimatedStyle, animatedStyle],\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, args)\n },\n }\n}\n\nfunction getInterpolated(val: Animated.Value, postfix: string, next: number) {\n const cur = val['_value'] as number\n const inputRange = [cur, next]\n const outputRange = [`${cur}deg`, `${next}deg`]\n if (next < cur) {\n inputRange.reverse()\n outputRange.reverse()\n }\n return val.interpolate({\n inputRange,\n outputRange,\n })\n}\n\nfunction getAnimationConfig(key: string, animations: AnimationsConfig, animation?: AnimationProp) {\n if (typeof animation === 'string') {\n return animations[animation]\n }\n let type = ''\n let extraConf: any\n if (Array.isArray(animation)) {\n type = animation[0] as string\n const conf = animation[1] && animation[1][key]\n if (conf) {\n if (typeof conf === 'string') {\n type = conf\n } else {\n type = (conf as any).type || type\n extraConf = conf\n }\n }\n } else {\n const val = animation?.[key]\n type = val?.type\n extraConf = val\n }\n const found = animations[type]\n if (!found) {\n throw new Error(`No animation of type \"${type}\" for key \"${key}\"`)\n }\n return {\n ...found,\n ...extraConf,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/animations-react-native",
|
|
3
|
-
"version": "1.0.1-beta.
|
|
3
|
+
"version": "1.0.1-beta.142",
|
|
4
4
|
"source": "src/index.ts",
|
|
5
|
-
"sideEffects":
|
|
5
|
+
"sideEffects": [
|
|
6
|
+
"./polyfill.js"
|
|
7
|
+
],
|
|
6
8
|
"license": "MIT",
|
|
7
9
|
"types": "./types/index.d.ts",
|
|
8
10
|
"main": "dist/cjs",
|
|
@@ -14,11 +16,11 @@
|
|
|
14
16
|
"dist"
|
|
15
17
|
],
|
|
16
18
|
"dependencies": {
|
|
17
|
-
"@tamagui/animate-presence": "^1.0.1-beta.
|
|
18
|
-
"@tamagui/core": "^1.0.1-beta.
|
|
19
|
+
"@tamagui/animate-presence": "^1.0.1-beta.142",
|
|
20
|
+
"@tamagui/core": "^1.0.1-beta.142"
|
|
19
21
|
},
|
|
20
22
|
"devDependencies": {
|
|
21
|
-
"@tamagui/build": "^1.0.1-beta.
|
|
23
|
+
"@tamagui/build": "^1.0.1-beta.142",
|
|
22
24
|
"react": "*",
|
|
23
25
|
"react-dom": "*",
|
|
24
26
|
"react-native": "*"
|
package/src/createAnimations.tsx
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { PresenceContext, usePresence } from '@tamagui/animate-presence'
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
AnimatedNumberStrategy,
|
|
4
|
+
AnimationDriver,
|
|
5
|
+
AnimationProp,
|
|
6
|
+
UniversalAnimatedNumber,
|
|
7
|
+
isWeb,
|
|
8
|
+
useEvent,
|
|
9
|
+
useIsomorphicLayoutEffect,
|
|
10
|
+
} from '@tamagui/core'
|
|
11
|
+
import { useContext, useEffect, useMemo, useRef } from 'react'
|
|
4
12
|
import { Animated } from 'react-native'
|
|
5
13
|
|
|
6
14
|
type AnimationsConfig<A extends Object = any> = {
|
|
@@ -28,10 +36,87 @@ const animatedStyleKey = {
|
|
|
28
36
|
opacity: true,
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
export
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
export const AnimatedView = Animated.View
|
|
40
|
+
export const AnimatedText = Animated.Text
|
|
41
|
+
|
|
42
|
+
export function useAnimatedNumber(initial: number): UniversalAnimatedNumber<Animated.Value> {
|
|
43
|
+
const state = useRef(
|
|
44
|
+
null as any as {
|
|
45
|
+
val: Animated.Value
|
|
46
|
+
composite: Animated.CompositeAnimation | null
|
|
47
|
+
strategy: AnimatedNumberStrategy
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
if (!state.current) {
|
|
51
|
+
state.current = {
|
|
52
|
+
composite: null,
|
|
53
|
+
val: new Animated.Value(initial),
|
|
54
|
+
strategy: { type: 'spring' },
|
|
55
|
+
}
|
|
56
|
+
}
|
|
34
57
|
|
|
58
|
+
return {
|
|
59
|
+
getInstance() {
|
|
60
|
+
return state.current.val
|
|
61
|
+
},
|
|
62
|
+
getValue() {
|
|
63
|
+
return state.current.val['_value']
|
|
64
|
+
},
|
|
65
|
+
stop() {
|
|
66
|
+
state.current.composite?.stop()
|
|
67
|
+
state.current.composite = null
|
|
68
|
+
},
|
|
69
|
+
setValue(next: number, { type, ...config } = { type: 'spring' }) {
|
|
70
|
+
const val = state.current.val
|
|
71
|
+
if (type === 'direct') {
|
|
72
|
+
val.setValue(next)
|
|
73
|
+
} else if (type === 'spring') {
|
|
74
|
+
state.current.composite?.stop()
|
|
75
|
+
const composite = Animated.spring(val, {
|
|
76
|
+
...config,
|
|
77
|
+
toValue: next,
|
|
78
|
+
useNativeDriver: !isWeb,
|
|
79
|
+
})
|
|
80
|
+
composite.start()
|
|
81
|
+
state.current.composite = composite
|
|
82
|
+
} else {
|
|
83
|
+
state.current.composite?.stop()
|
|
84
|
+
const composite = Animated.timing(val, {
|
|
85
|
+
...config,
|
|
86
|
+
toValue: next,
|
|
87
|
+
useNativeDriver: !isWeb,
|
|
88
|
+
})
|
|
89
|
+
composite.start()
|
|
90
|
+
state.current.composite = composite
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function useAnimatedNumberReaction(
|
|
97
|
+
value: UniversalAnimatedNumber<Animated.Value>,
|
|
98
|
+
cb: (current: number) => void
|
|
99
|
+
) {
|
|
100
|
+
const onChange = useEvent((current) => {
|
|
101
|
+
cb(current.value)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
const id = value.getInstance().addListener(onChange)
|
|
106
|
+
return () => {
|
|
107
|
+
value.getInstance().removeListener(id)
|
|
108
|
+
}
|
|
109
|
+
}, [value, onChange])
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function useAnimatedNumberStyle<V extends UniversalAnimatedNumber<Animated.Value>>(
|
|
113
|
+
value: V,
|
|
114
|
+
getStyle: (value: any) => any
|
|
115
|
+
) {
|
|
116
|
+
return getStyle(value.getInstance())
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function createAnimations<A extends AnimationsConfig>(animations: A): AnimationDriver<A> {
|
|
35
120
|
AnimatedView['displayName'] = 'AnimatedView'
|
|
36
121
|
AnimatedText['displayName'] = 'AnimatedText'
|
|
37
122
|
|
|
@@ -40,6 +125,9 @@ export function createAnimations<A extends AnimationsConfig>(animations: A): Ani
|
|
|
40
125
|
animations,
|
|
41
126
|
View: AnimatedView,
|
|
42
127
|
Text: AnimatedText,
|
|
128
|
+
useAnimatedNumber,
|
|
129
|
+
useAnimatedNumberReaction,
|
|
130
|
+
useAnimatedNumberStyle,
|
|
43
131
|
useAnimations: (props, helpers) => {
|
|
44
132
|
const { onDidAnimate, delay, getStyle, state } = helpers
|
|
45
133
|
const [isPresent, sendExitComplete] = usePresence()
|
|
@@ -108,20 +196,6 @@ export function createAnimations<A extends AnimationsConfig>(animations: A): Ani
|
|
|
108
196
|
return [+number * (neg ? -1 : 1), after] as const
|
|
109
197
|
}
|
|
110
198
|
|
|
111
|
-
function getInterpolated(val: Animated.Value, postfix: string, next: number) {
|
|
112
|
-
const cur = val['_value'] as number
|
|
113
|
-
const inputRange = [cur, next]
|
|
114
|
-
const outputRange = [`${cur}deg`, `${next}deg`]
|
|
115
|
-
if (next < cur) {
|
|
116
|
-
inputRange.reverse()
|
|
117
|
-
outputRange.reverse()
|
|
118
|
-
}
|
|
119
|
-
return val.interpolate({
|
|
120
|
-
inputRange,
|
|
121
|
-
outputRange,
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
|
|
125
199
|
const nonAnimatedStyle = {}
|
|
126
200
|
for (const key in all) {
|
|
127
201
|
const val = all[key]
|
|
@@ -195,6 +269,20 @@ export function createAnimations<A extends AnimationsConfig>(animations: A): Ani
|
|
|
195
269
|
}
|
|
196
270
|
}
|
|
197
271
|
|
|
272
|
+
function getInterpolated(val: Animated.Value, postfix: string, next: number) {
|
|
273
|
+
const cur = val['_value'] as number
|
|
274
|
+
const inputRange = [cur, next]
|
|
275
|
+
const outputRange = [`${cur}deg`, `${next}deg`]
|
|
276
|
+
if (next < cur) {
|
|
277
|
+
inputRange.reverse()
|
|
278
|
+
outputRange.reverse()
|
|
279
|
+
}
|
|
280
|
+
return val.interpolate({
|
|
281
|
+
inputRange,
|
|
282
|
+
outputRange,
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
|
|
198
286
|
function getAnimationConfig(key: string, animations: AnimationsConfig, animation?: AnimationProp) {
|
|
199
287
|
if (typeof animation === 'string') {
|
|
200
288
|
return animations[animation]
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { AnimationDriver } from '@tamagui/core';
|
|
1
|
+
import { AnimationDriver, UniversalAnimatedNumber } from '@tamagui/core';
|
|
2
2
|
import { Animated } from 'react-native';
|
|
3
3
|
declare type AnimationsConfig<A extends Object = any> = {
|
|
4
4
|
[Key in keyof A]: AnimationConfig;
|
|
5
5
|
};
|
|
6
6
|
declare type AnimationConfig = Partial<Pick<Animated.SpringAnimationConfig, 'delay' | 'bounciness' | 'damping' | 'friction' | 'mass' | 'overshootClamping' | 'speed' | 'stiffness' | 'tension' | 'velocity'>>;
|
|
7
|
+
export declare const AnimatedView: Animated.AnimatedComponent<typeof import("react-native").View>;
|
|
8
|
+
export declare const AnimatedText: Animated.AnimatedComponent<typeof import("react-native").Text>;
|
|
9
|
+
export declare function useAnimatedNumber(initial: number): UniversalAnimatedNumber<Animated.Value>;
|
|
10
|
+
export declare function useAnimatedNumberReaction(value: UniversalAnimatedNumber<Animated.Value>, cb: (current: number) => void): void;
|
|
11
|
+
export declare function useAnimatedNumberStyle<V extends UniversalAnimatedNumber<Animated.Value>>(value: V, getStyle: (value: any) => any): any;
|
|
7
12
|
export declare function createAnimations<A extends AnimationsConfig>(animations: A): AnimationDriver<A>;
|
|
8
13
|
export {};
|
|
9
14
|
//# sourceMappingURL=createAnimations.d.ts.map
|