@rafaelaugusto/jolt 0.1.0-beta.4 → 0.1.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +134 -4
- package/dist/animate.d.ts +7 -4
- package/dist/animate.d.ts.map +1 -1
- package/dist/animate.js +58 -13
- package/dist/animate.js.map +1 -1
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +34 -0
- package/dist/config.js.map +1 -0
- package/dist/decoration.d.ts +18 -0
- package/dist/decoration.d.ts.map +1 -0
- package/dist/decoration.js +155 -0
- package/dist/decoration.js.map +1 -0
- package/dist/driver/android-color.d.ts +3 -0
- package/dist/driver/android-color.d.ts.map +1 -1
- package/dist/driver/android-color.js +20 -18
- package/dist/driver/android-color.js.map +1 -1
- package/dist/driver/android-decoration.d.ts +22 -0
- package/dist/driver/android-decoration.d.ts.map +1 -0
- package/dist/driver/android-decoration.js +139 -0
- package/dist/driver/android-decoration.js.map +1 -0
- package/dist/driver/android-playback.d.ts +13 -0
- package/dist/driver/android-playback.d.ts.map +1 -0
- package/dist/driver/android-playback.js +141 -0
- package/dist/driver/android-playback.js.map +1 -0
- package/dist/driver/android.d.ts.map +1 -1
- package/dist/driver/android.js +30 -36
- package/dist/driver/android.js.map +1 -1
- package/dist/driver/index.d.ts +9 -0
- package/dist/driver/index.d.ts.map +1 -1
- package/dist/driver/index.js.map +1 -1
- package/dist/driver/ios-color.d.ts +2 -0
- package/dist/driver/ios-color.d.ts.map +1 -1
- package/dist/driver/ios-color.js +19 -8
- package/dist/driver/ios-color.js.map +1 -1
- package/dist/driver/ios-decoration.d.ts +17 -0
- package/dist/driver/ios-decoration.d.ts.map +1 -0
- package/dist/driver/ios-decoration.js +271 -0
- package/dist/driver/ios-decoration.js.map +1 -0
- package/dist/driver/ios-playback.d.ts +10 -0
- package/dist/driver/ios-playback.d.ts.map +1 -0
- package/dist/driver/ios-playback.js +47 -0
- package/dist/driver/ios-playback.js.map +1 -0
- package/dist/driver/ios-shadow.d.ts +6 -0
- package/dist/driver/ios-shadow.d.ts.map +1 -0
- package/dist/driver/ios-shadow.js +52 -0
- package/dist/driver/ios-shadow.js.map +1 -0
- package/dist/driver/ios.d.ts.map +1 -1
- package/dist/driver/ios.js +76 -40
- package/dist/driver/ios.js.map +1 -1
- package/dist/engine.d.ts +64 -3
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +243 -19
- package/dist/engine.js.map +1 -1
- package/dist/haptics.d.ts +4 -1
- package/dist/haptics.d.ts.map +1 -1
- package/dist/haptics.js +27 -3
- package/dist/haptics.js.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/items.d.ts +20 -0
- package/dist/items.d.ts.map +1 -0
- package/dist/items.js +109 -0
- package/dist/items.js.map +1 -0
- package/dist/keyboard.d.ts +17 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +116 -0
- package/dist/keyboard.js.map +1 -0
- package/dist/label.d.ts +7 -0
- package/dist/label.d.ts.map +1 -0
- package/dist/label.js +60 -0
- package/dist/label.js.map +1 -0
- package/dist/liquid.d.ts.map +1 -1
- package/dist/liquid.js +2 -1
- package/dist/liquid.js.map +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +2 -1
- package/dist/loader.js.map +1 -1
- package/dist/particles.d.ts.map +1 -1
- package/dist/particles.js +4 -3
- package/dist/particles.js.map +1 -1
- package/dist/path.d.ts +12 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +90 -0
- package/dist/path.js.map +1 -0
- package/dist/playback-group.d.ts +6 -0
- package/dist/playback-group.d.ts.map +1 -0
- package/dist/playback-group.js +141 -0
- package/dist/playback-group.js.map +1 -0
- package/dist/playback.d.ts +25 -0
- package/dist/playback.d.ts.map +1 -0
- package/dist/playback.js +35 -0
- package/dist/playback.js.map +1 -0
- package/dist/press.d.ts.map +1 -1
- package/dist/press.js +3 -3
- package/dist/press.js.map +1 -1
- package/dist/properties.d.ts +2 -1
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +14 -1
- package/dist/properties.js.map +1 -1
- package/dist/reveal.d.ts.map +1 -1
- package/dist/reveal.js +3 -2
- package/dist/reveal.js.map +1 -1
- package/dist/roll-diff.d.ts +22 -0
- package/dist/roll-diff.d.ts.map +1 -0
- package/dist/roll-diff.js +36 -0
- package/dist/roll-diff.js.map +1 -0
- package/dist/roll.d.ts +29 -0
- package/dist/roll.d.ts.map +1 -0
- package/dist/roll.js +442 -0
- package/dist/roll.js.map +1 -0
- package/dist/scroll-linked.d.ts +10 -0
- package/dist/scroll-linked.d.ts.map +1 -0
- package/dist/scroll-linked.js +58 -0
- package/dist/scroll-linked.js.map +1 -0
- package/dist/sequence.d.ts +10 -5
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +208 -14
- package/dist/sequence.js.map +1 -1
- package/dist/shimmer.d.ts.map +1 -1
- package/dist/shimmer.js +2 -1
- package/dist/shimmer.js.map +1 -1
- package/dist/svg-path.d.ts +14 -0
- package/dist/svg-path.d.ts.map +1 -0
- package/dist/svg-path.js +281 -0
- package/dist/svg-path.js.map +1 -0
- package/dist/symbol-effect.d.ts.map +1 -1
- package/dist/symbol-effect.js +4 -3
- package/dist/symbol-effect.js.map +1 -1
- package/dist/text-layout.d.ts +8 -0
- package/dist/text-layout.d.ts.map +1 -1
- package/dist/text-layout.js +8 -2
- package/dist/text-layout.js.map +1 -1
- package/dist/text.d.ts +1 -1
- package/dist/text.d.ts.map +1 -1
- package/dist/text.js +60 -64
- package/dist/text.js.map +1 -1
- package/dist/track.d.ts +2 -0
- package/dist/track.d.ts.map +1 -1
- package/dist/track.js +72 -16
- package/dist/track.js.map +1 -1
- package/dist/transition.d.ts.map +1 -1
- package/dist/transition.js +4 -1
- package/dist/transition.js.map +1 -1
- package/dist/types.d.ts +22 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vue/index.d.ts +89 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +134 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +15 -3
- package/platforms/android/java/org/rafaelaugusto/jolt/ColorTarget.java +2 -2
- package/platforms/android/java/org/rafaelaugusto/jolt/DecorationTarget.java +154 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFollower.java +91 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/NumberRoll.java +190 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/TextReveal.java +180 -0
- package/platforms/android/proguard-rules.pro +7 -0
- package/src/android-plugin.d.ts +64 -0
- package/src/animate.ts +96 -33
- package/src/config.ts +46 -0
- package/src/decoration.ts +180 -0
- package/src/driver/android-color.ts +22 -20
- package/src/driver/android-decoration.ts +182 -0
- package/src/driver/android-playback.ts +157 -0
- package/src/driver/android.ts +57 -43
- package/src/driver/index.ts +15 -0
- package/src/driver/ios-color.ts +19 -10
- package/src/driver/ios-decoration.ts +332 -0
- package/src/driver/ios-playback.ts +51 -0
- package/src/driver/ios-shadow.ts +50 -0
- package/src/driver/ios.ts +87 -46
- package/src/engine.ts +267 -22
- package/src/haptics.ts +25 -2
- package/src/index.ts +12 -1
- package/src/items.ts +140 -0
- package/src/keyboard.ts +132 -0
- package/src/label.ts +76 -0
- package/src/liquid.ts +2 -1
- package/src/loader.ts +2 -1
- package/src/particles.ts +4 -4
- package/src/path.ts +124 -0
- package/src/playback-group.ts +143 -0
- package/src/playback.ts +62 -0
- package/src/press.ts +3 -5
- package/src/properties.ts +18 -2
- package/src/reveal.ts +3 -3
- package/src/roll-diff.ts +57 -0
- package/src/roll.ts +515 -0
- package/src/scroll-linked.ts +73 -0
- package/src/sequence.ts +204 -14
- package/src/shimmer.ts +2 -1
- package/src/svg-path.ts +355 -0
- package/src/symbol-effect.ts +4 -3
- package/src/text-layout.ts +14 -2
- package/src/text.ts +62 -81
- package/src/track.ts +98 -25
- package/src/transition.ts +4 -1
- package/src/types.ts +23 -1
- package/src/vue/index.ts +189 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { type App, type BaseTransitionProps, type NSVElement, type ObjectDirective, type PropType } from 'nativescript-vue';
|
|
2
|
+
import { type AnimateOptions, type Keyframes, type PresetName, type SpringName } from '../index.js';
|
|
3
|
+
type Host = NSVElement;
|
|
4
|
+
type Options = AnimateOptions | SpringName;
|
|
5
|
+
/** A preset name or keyframes, alone or paired with a transition. */
|
|
6
|
+
export type AnimateValue = PresetName | Keyframes | readonly [animation: PresetName | Keyframes, options?: Options];
|
|
7
|
+
/** The pressed keyframes, alone or paired with a transition. */
|
|
8
|
+
export type PressValue = Keyframes | readonly [pressed: Keyframes, options?: Options];
|
|
9
|
+
export interface TransitionProps {
|
|
10
|
+
/** Played when the child is inserted. */
|
|
11
|
+
enter?: AnimateValue;
|
|
12
|
+
/** Played before the child is removed. */
|
|
13
|
+
leave?: AnimateValue;
|
|
14
|
+
/** Also play `enter` on the first render. */
|
|
15
|
+
appear?: boolean;
|
|
16
|
+
mode?: 'in-out' | 'out-in' | 'default';
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Plays an animation when the element mounts, and again whenever the value changes.
|
|
20
|
+
*
|
|
21
|
+
* ```vue
|
|
22
|
+
* <Label v-animate="'fadeInUp'" />
|
|
23
|
+
* <Label v-animate="['popIn', { delay: 200 }]" />
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare const vAnimate: ObjectDirective<Host, AnimateValue>;
|
|
27
|
+
/**
|
|
28
|
+
* Press feedback while a finger is on the element.
|
|
29
|
+
*
|
|
30
|
+
* ```vue
|
|
31
|
+
* <GridLayout v-press />
|
|
32
|
+
* <GridLayout v-press="{ scale: 0.95 }" />
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const vPress: ObjectDirective<Host, PressValue | undefined>;
|
|
36
|
+
/** The hooks `JoltTransition` hands to Vue's `BaseTransition`. */
|
|
37
|
+
export declare function transitionHooks(props: TransitionProps): BaseTransitionProps<Host>;
|
|
38
|
+
/**
|
|
39
|
+
* Animates a child in and out. Vue keeps the element until the leave animation settles.
|
|
40
|
+
*
|
|
41
|
+
* ```vue
|
|
42
|
+
* <JoltTransition enter="popIn" leave="fadeOut">
|
|
43
|
+
* <Label v-if="visible" text="Saved" />
|
|
44
|
+
* </JoltTransition>
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare const JoltTransition: import("nativescript-vue").DefineComponent<import("nativescript-vue").ExtractPropTypes<{
|
|
48
|
+
enter: {
|
|
49
|
+
type: PropType<AnimateValue>;
|
|
50
|
+
default: undefined;
|
|
51
|
+
};
|
|
52
|
+
leave: {
|
|
53
|
+
type: PropType<AnimateValue>;
|
|
54
|
+
default: undefined;
|
|
55
|
+
};
|
|
56
|
+
appear: BooleanConstructor;
|
|
57
|
+
mode: {
|
|
58
|
+
type: PropType<TransitionProps['mode']>;
|
|
59
|
+
default: undefined;
|
|
60
|
+
};
|
|
61
|
+
}>, () => import("nativescript-vue").VNode<import("nativescript-vue").RendererNode, import("nativescript-vue").RendererElement, {
|
|
62
|
+
[key: string]: any;
|
|
63
|
+
}>, {}, {}, {}, import("nativescript-vue").ComponentOptionsMixin, import("nativescript-vue").ComponentOptionsMixin, {}, string, import("nativescript-vue").PublicProps, Readonly<import("nativescript-vue").ExtractPropTypes<{
|
|
64
|
+
enter: {
|
|
65
|
+
type: PropType<AnimateValue>;
|
|
66
|
+
default: undefined;
|
|
67
|
+
};
|
|
68
|
+
leave: {
|
|
69
|
+
type: PropType<AnimateValue>;
|
|
70
|
+
default: undefined;
|
|
71
|
+
};
|
|
72
|
+
appear: BooleanConstructor;
|
|
73
|
+
mode: {
|
|
74
|
+
type: PropType<TransitionProps['mode']>;
|
|
75
|
+
default: undefined;
|
|
76
|
+
};
|
|
77
|
+
}>> & Readonly<{}>, {
|
|
78
|
+
enter: AnimateValue;
|
|
79
|
+
leave: AnimateValue;
|
|
80
|
+
appear: boolean;
|
|
81
|
+
mode: "default" | "in-out" | "out-in" | undefined;
|
|
82
|
+
}, {}, {}, {}, string, import("nativescript-vue").ComponentProvideOptions, true, {}, any>;
|
|
83
|
+
/** Registers `v-animate`, `v-press` and `JoltTransition` on the app. */
|
|
84
|
+
export declare function install(app: App): void;
|
|
85
|
+
declare const _default: {
|
|
86
|
+
install: typeof install;
|
|
87
|
+
};
|
|
88
|
+
export default _default;
|
|
89
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,GAAG,EACR,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,SAAS,EAEd,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,aAAa,CAAA;AAEpB,KAAK,IAAI,GAAG,UAAU,CAAA;AACtB,KAAK,OAAO,GAAG,cAAc,GAAG,UAAU,CAAA;AAE1C,qEAAqE;AACrE,MAAM,MAAM,YAAY,GACtB,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC,SAAS,EAAE,UAAU,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAA;AAE1F,gEAAgE;AAChE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAA;AAErF,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;CACvC;AA4CD;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,eAAe,CAAC,IAAI,EAAE,YAAY,CAQxD,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAahE,CAAA;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAuBjF;AAOD;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;;cAbQ,QAAQ,CAAC,YAAY,CAAC;;;;;;;;;QAmB7C,IAAI,EAAY,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;yFAUpE,CAAA;AAEF,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,QAI/B"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { BaseTransition, defineComponent, h, } from 'nativescript-vue';
|
|
2
|
+
import { animate, press, } from '../index.js';
|
|
3
|
+
const animations = new WeakMap();
|
|
4
|
+
const removers = new WeakMap();
|
|
5
|
+
function split(value) {
|
|
6
|
+
return Array.isArray(value)
|
|
7
|
+
? [value[0], value[1]]
|
|
8
|
+
: [value, undefined];
|
|
9
|
+
}
|
|
10
|
+
function same(a, b) {
|
|
11
|
+
if (Object.is(a, b))
|
|
12
|
+
return true;
|
|
13
|
+
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
|
|
14
|
+
return false;
|
|
15
|
+
if (Array.isArray(a) !== Array.isArray(b))
|
|
16
|
+
return false;
|
|
17
|
+
const keys = Object.keys(a);
|
|
18
|
+
return (keys.length === Object.keys(b).length &&
|
|
19
|
+
keys.every((key) => same(a[key], b[key])));
|
|
20
|
+
}
|
|
21
|
+
function play(el, value) {
|
|
22
|
+
const [animation, options] = split(value);
|
|
23
|
+
const handle = animate(el, animation, options);
|
|
24
|
+
animations.set(el, handle);
|
|
25
|
+
return handle;
|
|
26
|
+
}
|
|
27
|
+
function cancel(el) {
|
|
28
|
+
animations.get(el)?.stop();
|
|
29
|
+
animations.delete(el);
|
|
30
|
+
}
|
|
31
|
+
function attach(el, value) {
|
|
32
|
+
const [pressed, options] = value === undefined ? [] : split(value);
|
|
33
|
+
removers.set(el, press(el, pressed, options));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Plays an animation when the element mounts, and again whenever the value changes.
|
|
37
|
+
*
|
|
38
|
+
* ```vue
|
|
39
|
+
* <Label v-animate="'fadeInUp'" />
|
|
40
|
+
* <Label v-animate="['popIn', { delay: 200 }]" />
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export const vAnimate = {
|
|
44
|
+
mounted(el, { value }) {
|
|
45
|
+
play(el, value);
|
|
46
|
+
},
|
|
47
|
+
updated(el, { value, oldValue }) {
|
|
48
|
+
if (!same(value, oldValue))
|
|
49
|
+
play(el, value);
|
|
50
|
+
},
|
|
51
|
+
unmounted: cancel,
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Press feedback while a finger is on the element.
|
|
55
|
+
*
|
|
56
|
+
* ```vue
|
|
57
|
+
* <GridLayout v-press />
|
|
58
|
+
* <GridLayout v-press="{ scale: 0.95 }" />
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export const vPress = {
|
|
62
|
+
mounted(el, { value }) {
|
|
63
|
+
attach(el, value);
|
|
64
|
+
},
|
|
65
|
+
updated(el, { value, oldValue }) {
|
|
66
|
+
if (same(value, oldValue))
|
|
67
|
+
return;
|
|
68
|
+
removers.get(el)?.();
|
|
69
|
+
attach(el, value);
|
|
70
|
+
},
|
|
71
|
+
unmounted(el) {
|
|
72
|
+
removers.get(el)?.();
|
|
73
|
+
removers.delete(el);
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
/** The hooks `JoltTransition` hands to Vue's `BaseTransition`. */
|
|
77
|
+
export function transitionHooks(props) {
|
|
78
|
+
const run = (value) => (el, done) => {
|
|
79
|
+
if (value === undefined) {
|
|
80
|
+
done();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const handle = play(el, value);
|
|
84
|
+
void handle.finished.then(() => {
|
|
85
|
+
if (animations.get(el) === handle)
|
|
86
|
+
animations.delete(el);
|
|
87
|
+
done();
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
const hooks = {
|
|
91
|
+
onEnter: run(props.enter),
|
|
92
|
+
onEnterCancelled: cancel,
|
|
93
|
+
onLeave: run(props.leave),
|
|
94
|
+
onLeaveCancelled: cancel,
|
|
95
|
+
};
|
|
96
|
+
if (props.appear) {
|
|
97
|
+
hooks.onAppear = hooks.onEnter;
|
|
98
|
+
hooks.onAppearCancelled = cancel;
|
|
99
|
+
}
|
|
100
|
+
return hooks;
|
|
101
|
+
}
|
|
102
|
+
const value = {
|
|
103
|
+
type: [String, Object, Array],
|
|
104
|
+
default: undefined,
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Animates a child in and out. Vue keeps the element until the leave animation settles.
|
|
108
|
+
*
|
|
109
|
+
* ```vue
|
|
110
|
+
* <JoltTransition enter="popIn" leave="fadeOut">
|
|
111
|
+
* <Label v-if="visible" text="Saved" />
|
|
112
|
+
* </JoltTransition>
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export const JoltTransition = defineComponent({
|
|
116
|
+
name: 'JoltTransition',
|
|
117
|
+
props: {
|
|
118
|
+
enter: value,
|
|
119
|
+
leave: value,
|
|
120
|
+
appear: Boolean,
|
|
121
|
+
mode: { type: String, default: undefined },
|
|
122
|
+
},
|
|
123
|
+
setup(props, { slots }) {
|
|
124
|
+
return () => h(BaseTransition, { ...transitionHooks(props), mode: props.mode, appear: props.appear }, slots);
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
/** Registers `v-animate`, `v-press` and `JoltTransition` on the app. */
|
|
128
|
+
export function install(app) {
|
|
129
|
+
app.directive('animate', vAnimate);
|
|
130
|
+
app.directive('press', vPress);
|
|
131
|
+
app.component('JoltTransition', JoltTransition);
|
|
132
|
+
}
|
|
133
|
+
export default { install };
|
|
134
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rafaelaugusto/jolt",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.6",
|
|
4
4
|
"description": "Native animations for NativeScript: presets, springs, keyframes and stagger in one call.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nativescript",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"spring",
|
|
11
11
|
"keyframes",
|
|
12
12
|
"ios",
|
|
13
|
-
"android"
|
|
13
|
+
"android",
|
|
14
|
+
"vue"
|
|
14
15
|
],
|
|
15
16
|
"author": "Rafael Augusto",
|
|
16
17
|
"license": "MIT",
|
|
@@ -28,6 +29,10 @@
|
|
|
28
29
|
"types": "./dist/index.d.ts",
|
|
29
30
|
"default": "./dist/index.js"
|
|
30
31
|
},
|
|
32
|
+
"./vue": {
|
|
33
|
+
"types": "./dist/vue/index.d.ts",
|
|
34
|
+
"default": "./dist/vue/index.js"
|
|
35
|
+
},
|
|
31
36
|
"./package.json": "./package.json"
|
|
32
37
|
},
|
|
33
38
|
"files": [
|
|
@@ -53,12 +58,19 @@
|
|
|
53
58
|
"prepack": "npm run build"
|
|
54
59
|
},
|
|
55
60
|
"peerDependencies": {
|
|
56
|
-
"@nativescript/core": ">=8.9.0"
|
|
61
|
+
"@nativescript/core": ">=8.9.0",
|
|
62
|
+
"nativescript-vue": ">=3.0.0"
|
|
63
|
+
},
|
|
64
|
+
"peerDependenciesMeta": {
|
|
65
|
+
"nativescript-vue": {
|
|
66
|
+
"optional": true
|
|
67
|
+
}
|
|
57
68
|
},
|
|
58
69
|
"devDependencies": {
|
|
59
70
|
"@nativescript/core": "^9.1.3",
|
|
60
71
|
"@nativescript/types-android": "^9.1.1",
|
|
61
72
|
"@nativescript/types-ios": "^9.1.3",
|
|
73
|
+
"nativescript-vue": "3.1.2",
|
|
62
74
|
"prettier": "^3.9.10",
|
|
63
75
|
"typescript": "^7.0.2",
|
|
64
76
|
"vitepress": "^1.6.4",
|
|
@@ -12,7 +12,7 @@ import java.lang.reflect.Method;
|
|
|
12
12
|
/** ObjectAnimator target. All frame updates stay in native code. */
|
|
13
13
|
public final class ColorTarget {
|
|
14
14
|
private static final String BORDER = "org.nativescript.widgets.BorderDrawable";
|
|
15
|
-
|
|
15
|
+
static final Field[] FIELDS = fields();
|
|
16
16
|
private static final String SHADOW = "org.nativescript.widgets.BoxShadowDrawable";
|
|
17
17
|
private static final Method UNWRAP = unwrapMethod();
|
|
18
18
|
private final WeakReference<View> view;
|
|
@@ -49,7 +49,7 @@ public final class ColorTarget {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
static Drawable background(View nativeView) {
|
|
53
53
|
Drawable drawable = nativeView.getBackground();
|
|
54
54
|
// Avoid reflective method lookups and exceptions in the frame loop.
|
|
55
55
|
if (drawable != null && drawable.getClass().getName().equals(SHADOW) && UNWRAP != null) {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
package org.rafaelaugusto.jolt;
|
|
2
|
+
|
|
3
|
+
import android.animation.StateListAnimator;
|
|
4
|
+
import android.graphics.drawable.Drawable;
|
|
5
|
+
import android.graphics.drawable.ColorDrawable;
|
|
6
|
+
import android.view.View;
|
|
7
|
+
import java.lang.ref.WeakReference;
|
|
8
|
+
import java.lang.reflect.Constructor;
|
|
9
|
+
import java.lang.reflect.Field;
|
|
10
|
+
import java.util.WeakHashMap;
|
|
11
|
+
|
|
12
|
+
/** ObjectAnimator's float target. No JavaScript enters the native frame loop. */
|
|
13
|
+
public final class DecorationTarget {
|
|
14
|
+
private static final String BORDER = "org.nativescript.widgets.BorderDrawable";
|
|
15
|
+
private static final Field[][] FIELDS = fields();
|
|
16
|
+
private static final Constructor<?> CONSTRUCTOR = constructor();
|
|
17
|
+
private static final WeakHashMap<View, BackgroundLease> BACKGROUNDS = new WeakHashMap<>();
|
|
18
|
+
private static final WeakHashMap<View, Lease> LEASES = new WeakHashMap<>();
|
|
19
|
+
private final WeakReference<View> view;
|
|
20
|
+
private final int property;
|
|
21
|
+
private final int borderColor;
|
|
22
|
+
private float value;
|
|
23
|
+
private boolean acquired;
|
|
24
|
+
|
|
25
|
+
// 0 = uniform radius, 1 = uniform width, 2 = elevation, 3 = translationZ.
|
|
26
|
+
public DecorationTarget(View view, int property, float value, int borderColor) {
|
|
27
|
+
this.view = new WeakReference<>(view);
|
|
28
|
+
this.property = property;
|
|
29
|
+
this.value = value;
|
|
30
|
+
this.borderColor = borderColor;
|
|
31
|
+
}
|
|
32
|
+
private static Field[][] fields() {
|
|
33
|
+
try {
|
|
34
|
+
Class<?> type = Class.forName(BORDER);
|
|
35
|
+
String[][] names = {
|
|
36
|
+
{"borderTopLeftRadius", "borderTopRightRadius", "borderBottomRightRadius", "borderBottomLeftRadius"},
|
|
37
|
+
{"borderTopWidth", "borderRightWidth", "borderBottomWidth", "borderLeftWidth"}
|
|
38
|
+
};
|
|
39
|
+
Field[][] result = new Field[2][4];
|
|
40
|
+
for (int i = 0; i < 2; i++) for (int j = 0; j < 4; j++) {
|
|
41
|
+
result[i][j] = type.getDeclaredField(names[i][j]);
|
|
42
|
+
result[i][j].setAccessible(true);
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
} catch (ReflectiveOperationException | SecurityException exception) { return null; }
|
|
46
|
+
}
|
|
47
|
+
private static Constructor<?> constructor() {
|
|
48
|
+
try { return Class.forName(BORDER).getConstructor(float.class); }
|
|
49
|
+
catch (ReflectiveOperationException | SecurityException exception) { return null; }
|
|
50
|
+
}
|
|
51
|
+
public boolean isSupported() {
|
|
52
|
+
View nativeView = view.get();
|
|
53
|
+
if (nativeView == null) return false;
|
|
54
|
+
if (property >= 2) return true;
|
|
55
|
+
Drawable drawable = ColorTarget.background(nativeView);
|
|
56
|
+
return FIELDS != null && ((drawable != null && drawable.getClass().getName().equals(BORDER)) ||
|
|
57
|
+
((drawable == null || drawable.getClass() == ColorDrawable.class) && CONSTRUCTOR != null && ColorTarget.FIELDS != null));
|
|
58
|
+
}
|
|
59
|
+
public float getValue() { return value; }
|
|
60
|
+
public void setValue(float next) {
|
|
61
|
+
View nativeView = view.get();
|
|
62
|
+
if (nativeView == null) return;
|
|
63
|
+
value = next;
|
|
64
|
+
if (property >= 2) suspendStateAnimator(nativeView);
|
|
65
|
+
if (property == 2) { nativeView.setElevation(next); return; }
|
|
66
|
+
if (property == 3) { nativeView.setTranslationZ(next); return; }
|
|
67
|
+
ensureBackground(nativeView);
|
|
68
|
+
Drawable drawable = ColorTarget.background(nativeView);
|
|
69
|
+
if (drawable == null || !drawable.getClass().getName().equals(BORDER) || FIELDS == null) return;
|
|
70
|
+
try {
|
|
71
|
+
// Core rebuilds the paths from these fields in draw() and getOutline().
|
|
72
|
+
// Keep its bitmap, gradient, color and all other state on the same drawable.
|
|
73
|
+
for (Field field : FIELDS[property]) field.setFloat(drawable, next);
|
|
74
|
+
drawable.invalidateSelf();
|
|
75
|
+
nativeView.invalidateOutline();
|
|
76
|
+
} catch (IllegalAccessException exception) { /* Keep Core's final model. */ }
|
|
77
|
+
}
|
|
78
|
+
public void acquire() {
|
|
79
|
+
View nativeView = view.get();
|
|
80
|
+
if (nativeView == null || acquired) return;
|
|
81
|
+
acquired = true;
|
|
82
|
+
if (property < 2) {
|
|
83
|
+
BackgroundLease lease = BACKGROUNDS.get(nativeView);
|
|
84
|
+
if (lease == null) { lease = new BackgroundLease(); BACKGROUNDS.put(nativeView, lease); }
|
|
85
|
+
lease.count++;
|
|
86
|
+
ensureBackground(nativeView);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
Lease lease = LEASES.get(nativeView);
|
|
90
|
+
if (lease == null) {
|
|
91
|
+
lease = new Lease(nativeView.getStateListAnimator());
|
|
92
|
+
LEASES.put(nativeView, lease);
|
|
93
|
+
nativeView.setStateListAnimator(null);
|
|
94
|
+
}
|
|
95
|
+
lease.count++;
|
|
96
|
+
suspendStateAnimator(nativeView);
|
|
97
|
+
}
|
|
98
|
+
public void release() {
|
|
99
|
+
View nativeView = view.get();
|
|
100
|
+
if (!acquired || nativeView == null) return;
|
|
101
|
+
acquired = false;
|
|
102
|
+
if (property < 2) {
|
|
103
|
+
BackgroundLease lease = BACKGROUNDS.get(nativeView);
|
|
104
|
+
if (lease != null && --lease.count == 0) {
|
|
105
|
+
BACKGROUNDS.remove(nativeView);
|
|
106
|
+
if (lease.drawable != null && nativeView.getBackground() == lease.drawable) nativeView.setBackground(lease.original);
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
suspendStateAnimator(nativeView);
|
|
111
|
+
Lease lease = LEASES.get(nativeView);
|
|
112
|
+
if (lease != null && --lease.count == 0) {
|
|
113
|
+
LEASES.remove(nativeView);
|
|
114
|
+
if (nativeView.getStateListAnimator() == null) {
|
|
115
|
+
float elevation = nativeView.getElevation(), z = nativeView.getTranslationZ();
|
|
116
|
+
nativeView.setStateListAnimator(lease.animator);
|
|
117
|
+
if (lease.animator != null) lease.animator.jumpToCurrentState();
|
|
118
|
+
nativeView.setElevation(elevation);
|
|
119
|
+
nativeView.setTranslationZ(z);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
private void ensureBackground(View nativeView) {
|
|
124
|
+
BackgroundLease lease = BACKGROUNDS.get(nativeView);
|
|
125
|
+
Drawable original = nativeView.getBackground();
|
|
126
|
+
if (lease == null || (original != null && original.getClass() != ColorDrawable.class) || CONSTRUCTOR == null || ColorTarget.FIELDS == null) return;
|
|
127
|
+
try {
|
|
128
|
+
Drawable drawable = (Drawable) CONSTRUCTOR.newInstance(nativeView.getResources().getDisplayMetrics().density);
|
|
129
|
+
ColorTarget.FIELDS[0].setInt(drawable, original == null ? 0 : ((ColorDrawable) original).getColor());
|
|
130
|
+
for (int i = 1; i < ColorTarget.FIELDS.length; i++) ColorTarget.FIELDS[i].setInt(drawable, borderColor);
|
|
131
|
+
lease.original = original;
|
|
132
|
+
lease.drawable = drawable;
|
|
133
|
+
nativeView.setBackground(drawable);
|
|
134
|
+
} catch (ReflectiveOperationException exception) { /* Unsupported Core. */ }
|
|
135
|
+
}
|
|
136
|
+
private static final class BackgroundLease {
|
|
137
|
+
Drawable original, drawable;
|
|
138
|
+
int count;
|
|
139
|
+
}
|
|
140
|
+
private static void suspendStateAnimator(View view) {
|
|
141
|
+
Lease lease = LEASES.get(view);
|
|
142
|
+
StateListAnimator current = view.getStateListAnimator();
|
|
143
|
+
if (lease != null && current != null) {
|
|
144
|
+
// A Core model write may have installed an updated state animator.
|
|
145
|
+
lease.animator = current;
|
|
146
|
+
view.setStateListAnimator(null);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
private static final class Lease {
|
|
150
|
+
StateListAnimator animator;
|
|
151
|
+
int count;
|
|
152
|
+
Lease(StateListAnimator animator) { this.animator = animator; }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
package org.rafaelaugusto.jolt;
|
|
2
|
+
|
|
3
|
+
import android.view.View;
|
|
4
|
+
import android.view.WindowInsets;
|
|
5
|
+
import android.view.WindowInsetsAnimation;
|
|
6
|
+
import java.util.List;
|
|
7
|
+
|
|
8
|
+
/** Keeps a view above the keyboard while the IME animates. All frame updates stay in native code. */
|
|
9
|
+
public final class KeyboardFollower extends WindowInsetsAnimation.Callback {
|
|
10
|
+
public interface Listener {
|
|
11
|
+
void onStart();
|
|
12
|
+
void onSettled(float translation);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private final View view;
|
|
16
|
+
private final float offset;
|
|
17
|
+
private final Listener listener;
|
|
18
|
+
private float visualBottom;
|
|
19
|
+
private float from;
|
|
20
|
+
private float to;
|
|
21
|
+
private boolean tracking;
|
|
22
|
+
|
|
23
|
+
public KeyboardFollower(View view, float offset, Listener listener) {
|
|
24
|
+
super(DISPATCH_MODE_CONTINUE_ON_SUBTREE);
|
|
25
|
+
this.view = view;
|
|
26
|
+
this.offset = offset;
|
|
27
|
+
this.listener = listener;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public void attach() {
|
|
31
|
+
view.setWindowInsetsAnimationCallback(this);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public void detach() {
|
|
35
|
+
tracking = false;
|
|
36
|
+
view.setWindowInsetsAnimationCallback(null);
|
|
37
|
+
view.setTranslationY(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private static boolean keyboard(WindowInsetsAnimation animation) {
|
|
41
|
+
return (animation.getTypeMask() & WindowInsets.Type.ime()) != 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private float bottom() {
|
|
45
|
+
int[] location = new int[2];
|
|
46
|
+
view.getLocationInWindow(location);
|
|
47
|
+
return location[1] + view.getHeight();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@Override
|
|
51
|
+
public void onPrepare(WindowInsetsAnimation animation) {
|
|
52
|
+
if (!keyboard(animation)) return;
|
|
53
|
+
visualBottom = bottom();
|
|
54
|
+
tracking = true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Override
|
|
58
|
+
public WindowInsetsAnimation.Bounds onStart(WindowInsetsAnimation animation, WindowInsetsAnimation.Bounds bounds) {
|
|
59
|
+
if (!keyboard(animation) || !tracking) return bounds;
|
|
60
|
+
listener.onStart();
|
|
61
|
+
// The end state is laid out now; the view may already have moved with the layout.
|
|
62
|
+
float untranslated = bottom() - view.getTranslationY();
|
|
63
|
+
WindowInsets insets = view.getRootWindowInsets();
|
|
64
|
+
int height = insets == null ? 0 : insets.getInsets(WindowInsets.Type.ime()).bottom;
|
|
65
|
+
float top = view.getRootView().getHeight() - height;
|
|
66
|
+
to = -Math.max(0, untranslated + offset - top);
|
|
67
|
+
from = visualBottom - untranslated;
|
|
68
|
+
view.setTranslationY(from);
|
|
69
|
+
return bounds;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@Override
|
|
73
|
+
public WindowInsets onProgress(WindowInsets insets, List<WindowInsetsAnimation> running) {
|
|
74
|
+
if (!tracking) return insets;
|
|
75
|
+
for (WindowInsetsAnimation animation : running) {
|
|
76
|
+
if (keyboard(animation)) {
|
|
77
|
+
view.setTranslationY(from + (to - from) * animation.getInterpolatedFraction());
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return insets;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@Override
|
|
85
|
+
public void onEnd(WindowInsetsAnimation animation) {
|
|
86
|
+
if (!keyboard(animation) || !tracking) return;
|
|
87
|
+
tracking = false;
|
|
88
|
+
view.setTranslationY(to);
|
|
89
|
+
listener.onSettled(to);
|
|
90
|
+
}
|
|
91
|
+
}
|