Skip to content

Commit 93909cf

Browse files
committed
chore: temp demo app
1 parent 50a9bd5 commit 93909cf

File tree

7 files changed

+398
-4
lines changed

7 files changed

+398
-4
lines changed

demo-snippets/vue3/Card.vue

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<script lang="ts" setup>
2+
import { PropType } from "nativescript-vue";
3+
import { Card } from "./types";
4+
5+
const props = defineProps({
6+
data: {
7+
type: Object as PropType<Card>,
8+
required: true
9+
}
10+
})
11+
</script>
12+
13+
<template>
14+
<GridLayout padding="4">
15+
<FlexboxLayout borderRadius="16" boxShadow="0 0 3 3 rgba(0,0,0,.12)" :style="{ 'background': props.data.bg }" class="flex-col p-3 justify-between rounded-lg h-full">
16+
<FlexboxLayout class="justify-between">
17+
<Label text="Credit" class="text-xl font-bold text-white"></Label>
18+
<!-- <Image :src="props.data.imgType" height="45"></Image> -->
19+
</FlexboxLayout>
20+
<FlexboxLayout class="flex-col">
21+
<Label :text="data.name" class="text-xl text-white"></Label>
22+
<Label :text="data.number" class="text-lg text-white"></Label>
23+
</FlexboxLayout>
24+
</FlexboxLayout>
25+
</GridLayout>
26+
</template>

demo-snippets/vue3/CardHome.vue

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<script lang="ts" setup>
2+
import { ref, $navigateTo, $showModal } from 'nativescript-vue';
3+
import { HEIGH_CARD, dataCards } from './carddata';
4+
import { isAndroid, ObservableArray, PageTransition, SharedTransition, View, ModalTransition, Screen } from '@nativescript/core';
5+
import { animateView, configHomeSharedTransition } from './animation';
6+
import Card from './Card.vue';
7+
// import Details from "./Details.vue";
8+
9+
const isOpen = ref(false);
10+
const refShowBtn = ref();
11+
const refAddBtn = ref();
12+
const refTextHeader = ref();
13+
14+
const items = new ObservableArray(dataCards);
15+
16+
const transaleY = 70;
17+
const viewCards: View[] = [];
18+
19+
function loadedCard(args: any, index: number) {
20+
const card: View = args.object;
21+
if (!isOpen.value && viewCards.length < dataCards.length) {
22+
viewCards.push(card);
23+
card.translateY = -(HEIGH_CARD - transaleY) * index;
24+
}
25+
}
26+
27+
function toggleStatus() {
28+
const showBtn: View = refShowBtn.value.nativeView;
29+
const addBtn: View = refAddBtn.value.nativeView;
30+
const addWalletBtn: View = addBtn.getViewById('icon-add');
31+
const textHeader: View = refTextHeader.value.nativeView;
32+
33+
if (isOpen.value) {
34+
viewCards.forEach((cardView, index) => index == 0 || close(cardView, index));
35+
animateView(addBtn, { translate: { y: 0, x: 0 }, alpha: 1, rotation: 0 });
36+
animateView(addWalletBtn, { rotation: 0 });
37+
animateView(showBtn, { rotation: 90, alpha: 0 });
38+
animateView(textHeader, { translate: { x: 0, y: 0 } });
39+
} else {
40+
viewCards.forEach((cardView) => open(cardView));
41+
animateView(addBtn, { translate: { y: 50, x: 0 }, alpha: 0 });
42+
animateView(addWalletBtn, { rotation: 180 });
43+
animateView(showBtn, { rotation: 0, alpha: 1 });
44+
animateView(textHeader, { translate: { x: -(Screen.mainScreen.widthDIPs / 2) + textHeader.getActualSize().width / 2 + 10, y: 0 } });
45+
}
46+
isOpen.value = !isOpen.value;
47+
}
48+
49+
function open(cardView: View) {
50+
animateView(cardView, { translate: { x: 0, y: 0 } });
51+
}
52+
53+
function close(cardView: View, index: number) {
54+
animateView(cardView, { translate: { x: 0, y: -(HEIGH_CARD - transaleY) * index } });
55+
}
56+
57+
function openOrGoToDetails(index: number) {
58+
// if (isOpen.value) {
59+
// if (isAndroid) {
60+
// $navigateTo(Details, {
61+
// transition: SharedTransition.custom(new PageTransition(), configHomeSharedTransition),
62+
// props: { index, card: dataCards[index] }
63+
// });
64+
// } else {
65+
// $showModal(Details, {
66+
// transition: SharedTransition.custom(new ModalTransition(), configHomeSharedTransition),
67+
// props: { index, card: dataCards[index] }
68+
// });
69+
// }
70+
// } else {
71+
toggleStatus();
72+
// }
73+
}
74+
let currentToggledIndex = -1;
75+
function toggleItemHeight(item) {
76+
const index = items.findIndex((i) => i.id === item.id);
77+
if (index >= 0) {
78+
if (!item.expanded && currentToggledIndex !== -1) {
79+
const currentItem = items.getItem(currentToggledIndex);
80+
currentItem.expanded = false;
81+
items.setItem(currentToggledIndex, currentItem);
82+
}
83+
item.expanded = !!!item.expanded;
84+
currentToggledIndex = item.expanded ? index : -1;
85+
items.setItem(index, item);
86+
}
87+
}
88+
</script>
89+
90+
<template>
91+
<Page actionBarHidden="true" androidStatusBarBackground="transparent" class="bg-white">
92+
<GridLayout rows="auto,*,auto">
93+
<GridLayout height="50" android:marginop="3">
94+
<Label ref="refTextHeader" text="Wallet" class="text-3xl font-bold text-black" horizontalAlignment="center"></Label>
95+
<Label ref="refShowBtn" text="close" style="font-size: 24;" height="45" width="45" rotate="90" class="m-icon-round bg-[#0666eb] rounded-full text-white text-center opacity-0 mr-2" horizontalAlignment="right" @tap="toggleStatus"></Label>
96+
</GridLayout>
97+
<CollectionView row="1" height="100%" :items="items" itemIdGenerator="index" :itemOverlap="`-${HEIGH_CARD - 60} 0 0 0`">
98+
<template #default="{ item }">
99+
<GridLayout :height="item.expanded ? 2*HEIGH_CARD - 60 : HEIGH_CARD">
100+
<Card :height="HEIGH_CARD" :data="item" :sharedTransitionTag="`card_${item.id}`" @tap="toggleItemHeight(item)" verticalAlignment="top">
101+
</Card>
102+
</GridLayout>
103+
</template>
104+
</CollectionView>
105+
<!-- <FlexboxLayout height="100%" marginTop="2" flexDirection="column">
106+
<Card v-for="(card, index) in dataCards" :key="index" :style="{ 'height': HEIGH_CARD }" :data="card" :sharedTransitionTag="`card_${index}`" @loaded="loadedCard($event, index)" @tap="openOrGoToDetails(index)">
107+
</Card>
108+
</FlexboxLayout> -->
109+
<FlexboxLayout ref="refAddBtn" verticalAlignment="bottom" class="justify-center items-center" height="100">
110+
<Label id="icon-add" text="add" height="60" width="60" class="m-icon-round bg-[#0666eb] text-center text-white rounded-xl"></Label>
111+
</FlexboxLayout>
112+
</GridLayout>
113+
</Page>
114+
</template>

demo-snippets/vue3/SimpleTemplates.vue

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@
1717
</GridLayout>
1818
</template>
1919
<template #heading="{ item }">
20-
<GridLayout rows="*, auto" :backgroundColor="item.color" verticalAlignment="middle" padding="25">
21-
<Label :text="item.name" textTransform="uppercase" color="white" fontSize="20"
22-
fontWeight="bold"></Label>
23-
</GridLayout>
20+
<Label :text="item.name" :backgroundColor="item.color" textTransform="uppercase" color="white" fontSize="20"
21+
fontWeight="bold" padding="25"></Label>
2422
</template>
2523
</CollectionView>
2624
</GridLayout>

demo-snippets/vue3/animation.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { Screen, SharedTransitionConfig, Utils, View, isAndroid } from '@nativescript/core';
2+
import { isNumber } from '@nativescript/core/utils/types';
3+
import { AnimateOptions } from './types';
4+
5+
export const configHomeSharedTransition: SharedTransitionConfig = {
6+
interactive: {
7+
dismiss: {
8+
finishThreshold: 0.5
9+
}
10+
},
11+
pageStart: {
12+
opacity: 1,
13+
x: 0,
14+
y: isAndroid ? Screen.mainScreen.heightPixels : undefined
15+
},
16+
pageEnd: {
17+
spring: { tension: 70, friction: 9, mass: 1 }
18+
},
19+
pageReturn: {
20+
opacity: 1,
21+
spring: { tension: 70, friction: 9, mass: 2 }
22+
}
23+
};
24+
25+
export const animateView = (view: View, options: AnimateOptions) => {
26+
if (__ANDROID__) {
27+
animateAndroid(view, options);
28+
} else {
29+
animateIOS(view, options);
30+
}
31+
};
32+
33+
function animateAndroid(view: View, animation: AnimateOptions) {
34+
// if ((global as any).isAppRunInPreview) {
35+
// view.animate({
36+
// translate: { x: animation.translate?.x ?? view.translateX, y: animation.translate?.y ?? view.translateY },
37+
// rotate: animation.rotation ?? view.rotate,
38+
// opacity: animation.alpha ?? view.opacity,
39+
// curve: CoreTypes.AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1),
40+
// duration: 250
41+
// });
42+
// } else {
43+
if (isNumber(animation.translate?.x)) {
44+
const springAnim = new androidx.dynamicanimation.animation.SpringAnimation(
45+
view.android,
46+
androidx.dynamicanimation.animation.DynamicAnimation.TRANSLATION_X,
47+
Utils.layout.toDevicePixels(animation.translate?.x)
48+
);
49+
springAnim.getSpring().setStiffness(150);
50+
springAnim.getSpring().setDampingRatio(0.6);
51+
springAnim.start();
52+
}
53+
if (isNumber(animation.translate?.y)) {
54+
const springAnim = new androidx.dynamicanimation.animation.SpringAnimation(
55+
view.android,
56+
androidx.dynamicanimation.animation.DynamicAnimation.TRANSLATION_Y,
57+
Utils.layout.toDevicePixels(animation.translate?.y)
58+
);
59+
springAnim.getSpring().setStiffness(150);
60+
springAnim.getSpring().setDampingRatio(0.6);
61+
springAnim.start();
62+
}
63+
if (isNumber(animation.rotation)) {
64+
const springAnim = new androidx.dynamicanimation.animation.SpringAnimation(view.android, androidx.dynamicanimation.animation.DynamicAnimation.ROTATION, animation.rotation);
65+
springAnim.getSpring().setStiffness(150);
66+
springAnim.start();
67+
}
68+
if (isNumber(animation.alpha)) {
69+
const springAnim = new androidx.dynamicanimation.animation.SpringAnimation(view.android, androidx.dynamicanimation.animation.DynamicAnimation.ALPHA, animation.alpha);
70+
springAnim.getSpring().setStiffness(150);
71+
springAnim.start();
72+
}
73+
// }
74+
}
75+
76+
function animateIOS(view: View, animation: AnimateOptions) {
77+
Utils.ios.animateWithSpring({
78+
animations: () => {
79+
const uiView = view.ios as UIView;
80+
if (isNumber(animation.translate?.x) || isNumber(animation.translate?.y)) {
81+
uiView.transform = CGAffineTransformMakeTranslation(getNumber(animation.translate?.x, view.translateX), getNumber(animation.translate?.y, view.translateY));
82+
}
83+
if (animation.rotation || animation.rotation === 0) {
84+
uiView.transform = CGAffineTransformMakeRotation((animation.rotation * 3.1416) / 180);
85+
}
86+
if (animation.alpha || animation.alpha === 0) {
87+
uiView.layer.opacity = animation.alpha;
88+
}
89+
}
90+
});
91+
}
92+
93+
const getNumber = (number: number | undefined, defaultValue: number) => (number || number === 0 ? number : defaultValue);

demo-snippets/vue3/carddata.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { isAndroid } from '@nativescript/core';
2+
import { Card, Transaction } from './types';
3+
4+
export const HEIGH_CARD = 220;
5+
6+
export const dataCards: Card[] = [
7+
{
8+
id: 1,
9+
name: 'Justine',
10+
number: '***** **** 0978',
11+
bg: 'linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(245,144,2,1) 100%)',
12+
imgType: '~/assets/master-card.png'
13+
},
14+
{
15+
id: 2,
16+
name: 'Jenna',
17+
number: '***** **** 5782',
18+
bg: 'linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgba(0,212,255,1) 100%)',
19+
imgType: '~/assets/visa-card.png'
20+
},
21+
{
22+
id: 3,
23+
name: 'Jessica',
24+
number: '***** **** 1093',
25+
bg: 'linear-gradient(0deg, rgba(34,193,195,1) 0%, rgba(253,187,45,1) 100%)',
26+
imgType: '~/assets/master-card.png'
27+
},
28+
{
29+
id: 4,
30+
name: 'Justine',
31+
number: '***** **** 0978',
32+
bg: 'linear-gradient(90deg, rgba(0,58,180,1) 0%, rgba(0,29,29,1) 50%, rgba(0,144,2,1) 100%)',
33+
imgType: '~/assets/master-card.png'
34+
},
35+
{
36+
id: 5,
37+
name: 'Jenna',
38+
number: '***** **** 5782',
39+
bg: 'linear-gradient(90deg, rgba(2,100,36,1) 0%, rgba(9,109,121,1) 35%, rgba(0,212,255,1) 100%)',
40+
imgType: '~/assets/visa-card.png'
41+
},
42+
{
43+
id: 6,
44+
name: 'Jessica',
45+
number: '***** **** 1093',
46+
bg: 'linear-gradient(0deg, rgba(134,193,195,1) 0%, rgba(253,187,145,1) 100%)',
47+
imgType: '~/assets/master-card.png'
48+
}
49+
];
50+
51+
export const transactions: Transaction[] = [
52+
{
53+
id: 1,
54+
title: 'Amazon',
55+
subTitle: 'Groceries',
56+
date: new Date(),
57+
image: '~/assets/list/amazon.png',
58+
price: 100
59+
},
60+
{
61+
id: 2,
62+
title: 'Apple',
63+
subTitle: 'Electronics',
64+
date: new Date(),
65+
image: '~/assets/list/apple.png',
66+
price: 200
67+
},
68+
{
69+
id: 3,
70+
title: 'Dribbble',
71+
subTitle: 'Design',
72+
date: new Date(),
73+
image: '~/assets/list/dribble.png',
74+
price: 50
75+
},
76+
{
77+
id: 4,
78+
title: 'GitHub',
79+
subTitle: 'Code',
80+
date: new Date(),
81+
image: '~/assets/list/github.png',
82+
price: 75
83+
},
84+
{
85+
id: 5,
86+
title: 'Instagram',
87+
subTitle: 'Social Media',
88+
date: new Date(),
89+
image: '~/assets/list/instagram.png',
90+
price: 150
91+
},
92+
{
93+
id: 6,
94+
title: 'Figma',
95+
subTitle: 'Design Tool',
96+
date: new Date(),
97+
image: '~/assets/list/figma.png',
98+
price: 120
99+
},
100+
{
101+
id: 7,
102+
title: 'Twitter',
103+
subTitle: 'Social Media',
104+
date: new Date(),
105+
image: '~/assets/list/twitter.png',
106+
price: 90
107+
},
108+
{
109+
id: 8,
110+
title: 'Spotify',
111+
subTitle: 'Music Streaming',
112+
date: new Date(),
113+
image: '~/assets/list/spotify.png',
114+
price: 60
115+
},
116+
{
117+
id: 9,
118+
title: 'Netflix',
119+
subTitle: 'Video Streaming',
120+
date: new Date(),
121+
image: '~/assets/list/netflix.png',
122+
price: 80
123+
},
124+
{
125+
id: 10,
126+
title: 'Dropbox',
127+
subTitle: 'Cloud Storage',
128+
date: new Date(),
129+
image: '~/assets/list/dropbox.png',
130+
price: 55
131+
}
132+
];

demo-snippets/vue3/install.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Reorder from './Reorder.vue';
1212
import SwipeMenu from './SwipeMenu.vue';
1313
import ResizeCell from './ResizeCell.vue';
1414
import SimpleGridsScrollToIndex from './SimpleGridsScrollToIndex.vue';
15+
import CardHome from './CardHome.vue';
1516

1617
export function installPlugin(app: any) {
1718
app.use(CollectionView);
@@ -20,6 +21,7 @@ export function installPlugin(app: any) {
2021
}
2122

2223
export const demos = [
24+
{ name: 'Card', path: 'card', component: CardHome },
2325
{ name: 'Simple Grid', path: 'simple-grid', component: SimpleGrid },
2426
{ name: 'Horizontal Grid', path: 'horizontal-grid', component: HorizontalGrid },
2527
{ name: 'Simple Waterfall', path: 'simple-waterfall', component: SimpleWaterfall },

0 commit comments

Comments
 (0)