Skip to content

Commit f2045ab

Browse files
committed
feat: improved types for createNativeView, $showModal and $navigateTo
1 parent 9c26e6f commit f2045ab

File tree

8 files changed

+101
-56
lines changed

8 files changed

+101
-56
lines changed

demo/src/app.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ StackLayout {
55
Label {
66
/* background-color: rgb(0, 255, 0, 0.2); */
77
}
8+
9+
.modal {
10+
background-color: rgb(0, 0, 255, 0.2);
11+
}

demo/src/components/Home.vue

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ import { ListItem, onMounted, onUnmounted } from 'nativescript-vue';
33
import { goHome } from '../composables/goHome';
44
import Test from './Test.vue';
55
6-
defineProps({
7-
depth: {
8-
type: Number,
9-
default: 0,
6+
withDefaults(
7+
defineProps<{
8+
depth?: number;
9+
title?: string;
10+
items?: (string | number)[];
11+
enabled?: boolean;
12+
}>(),
13+
{
14+
depth: 0,
1015
},
11-
});
16+
);
1217
1318
const message = 'Hello World!!';
1419
@@ -46,7 +51,10 @@ onUnmounted(() => {
4651
<Label class="info" :text="message + ' ' + depth" />
4752
<Button text="Go home" @tap="goHome(depth + 1)" />
4853
<Button text="Go home Modal" @tap="goHome(depth + 1, true)" />
49-
<Button text="Close Modal" @tap="$modal?.close({ depth, foo: 'bar' })" />
54+
<Button
55+
text="Close Modal"
56+
@tap="$modal?.close({ depth, foo: 'bar' }, 'arg1', 'arg2')"
57+
/>
5058

5159
<Test />
5260

@@ -62,6 +70,7 @@ onUnmounted(() => {
6270
)}\n\nindex: ${index} even: ${even} odd: ${odd}`"
6371
textWrap="true"
6472
padding="16"
73+
@tap="$emit('customEvent', { item, index, even, odd })"
6574
/>
6675
</template>
6776

@@ -73,6 +82,7 @@ onUnmounted(() => {
7382
)}\n\nindex: ${index} even: ${even} odd: ${odd}`"
7483
textWrap="true"
7584
padding="16"
85+
@tap="$emit('customEvent', { item, index, even, odd })"
7686
/>
7787
</template>
7888
</ListView>

demo/src/composables/goHome.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
1-
import { $navigateTo, $showModal } from 'nativescript-vue';
1+
import { $navigateTo, $showModal, createNativeView, h } from 'nativescript-vue';
22
import Home from '../components/Home.vue';
33

4+
function test() {
5+
const home: typeof Home = Home;
6+
7+
createNativeView(Home, {});
8+
}
9+
410
export function goHome(depth = 0, modal = false) {
511
if (modal) {
6-
return $showModal(Home, {
12+
return $showModal<{
13+
strongTypeReturn: string;
14+
}>(Home, {
715
props: {
16+
onVnodeMounted(vnode) {
17+
// console.log('MODAL VNODE MOUNTED', vnode);
18+
},
19+
onCustomEvent(e) {
20+
console.log('MODAL CUSTOM EVENT', e);
21+
},
22+
class: 'modal',
823
depth,
924
},
10-
}).then((res) => {
11-
console.log('MODAL CLOSED', res);
25+
closeCallback(data, ...args) {
26+
console.log('MODAL CLOSE CALLBACK', data, ...args);
27+
},
28+
}).then((data) => {
29+
console.log('MODAL CLOSED DATA', data);
1230
});
1331
}
14-
$navigateTo(Home, {
32+
return $navigateTo(Home, {
1533
// clearHistory: true,
1634
props: {
1735
depth,

demo/types/shims.vue.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
declare module '*.vue' {
22
import type { DefineComponent } from 'nativescript-vue';
3-
const component: DefineComponent<{}, {}, any>;
3+
const component: DefineComponent;
44
export default component;
55
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export const createApp = ((...args) => {
7878

7979
app.registerElement = registerElement;
8080

81-
app.mount = (...args) => {
81+
app.mount = (...args: Parameters<typeof mount>) => {
8282
if (!args.length) {
8383
return mount(new NSVRoot(), false, false);
8484
}

src/plugins/modals.ts

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { Application, ShowModalOptions, View } from '@nativescript/core';
1+
import {
2+
Application,
3+
ShowModalOptions as CoreShowModalOptions,
4+
View,
5+
} from '@nativescript/core';
26
import {
37
App,
48
Component,
@@ -7,32 +11,32 @@ import {
711
unref,
812
warn,
913
} from '@vue/runtime-core';
10-
import { NSVElement, NSVRoot } from '../dom';
11-
import { createNativeView } from '../runtimeHelpers';
1214
import { isObject } from '@vue/shared';
15+
import { NSVElement, NSVRoot } from '../dom';
16+
import { CreateNativeViewProps, createNativeView } from '../runtimeHelpers';
1317

1418
declare module '@vue/runtime-core' {
1519
export interface ComponentCustomProperties {
16-
/**
17-
* todo: update docblock
18-
*/
19-
$showModal: <T = any>(
20-
component: Component,
21-
options?: ModalOptions,
20+
$showModal: <T = any, P = any>(
21+
component: Component<P>,
22+
options?: ShowModalOptions<P, T>,
2223
) => Promise<T | false | undefined>;
23-
$closeModal: (arg: any) => void;
24+
$closeModal: <T = any>(data: T, ...args: any[]) => void;
2425
$modal: {
25-
close: (arg: any) => void;
26+
close: <T = any>(data: T, ...args: any[]) => void;
2627
};
2728
}
2829
}
2930

3031
type ResolvableModalTarget = ComponentPublicInstance | NSVElement | View;
3132

32-
export interface ModalOptions extends Partial<ShowModalOptions> {
33-
props?: Record<string, any>;
33+
export type ShowModalOptions<P = any, T = any> = Partial<
34+
Omit<CoreShowModalOptions, 'closeCallback'>
35+
> & {
36+
closeCallback?: (data?: T, ...args: any[]) => void;
37+
props?: CreateNativeViewProps<P>;
3438
target?: ResolvableModalTarget;
35-
}
39+
};
3640

3741
/**
3842
* @internal
@@ -57,9 +61,9 @@ function resolveModalTarget(
5761
return false;
5862
}
5963

60-
export async function $showModal<T = any>(
61-
component: Component,
62-
options: ModalOptions = {},
64+
export async function $showModal<T = any, P = any>(
65+
component: Component<P>,
66+
options: ShowModalOptions<P, T> = {},
6367
): Promise<T | false | undefined> {
6468
const modalTarget = resolveModalTarget(
6569
options.target ?? Application.getRootView(),
@@ -87,7 +91,7 @@ export async function $showModal<T = any>(
8791
reload: reloadModal,
8892
});
8993

90-
const closeCallback = (data?: T) => {
94+
const closeCallback = (data?: T, ...args: any) => {
9195
if (isResolved) return;
9296

9397
if (isReloading) {
@@ -107,6 +111,10 @@ export async function $showModal<T = any>(
107111
view.unmount();
108112
view = null;
109113

114+
// call the closeCallback if it exists with all arguments
115+
options.closeCallback?.(data, ...args);
116+
117+
// resolve the promise with the first argument, since Promise.resolve() expects only one argument
110118
resolve(data);
111119
};
112120

@@ -118,7 +126,9 @@ export async function $showModal<T = any>(
118126
...additionalOptions,
119127
});
120128
};
121-
const closeModal = (...args: any[]) => view.nativeView?.closeModal(...args);
129+
const closeModal = (...args: any[]) => {
130+
view.nativeView?.closeModal(...args);
131+
};
122132

123133
view.context.config.globalProperties.$closeModal = closeModal;
124134
view.context.config.globalProperties.$modal = { close: closeModal };

src/plugins/navigation.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Frame, NavigationEntry, Page } from '@nativescript/core';
22
import { App, Component, Ref, nextTick, unref } from '@vue/runtime-core';
33
import { NSVElement, NSVRoot } from '../dom';
4-
import { createNativeView } from '../runtimeHelpers';
4+
import { CreateNativeViewProps, createNativeView } from '../runtimeHelpers';
55

66
declare module '@vue/runtime-core' {
77
export interface ComponentCustomProperties {
@@ -13,21 +13,24 @@ declare module '@vue/runtime-core' {
1313
* @param target
1414
* @param options
1515
*/
16-
$navigateTo: (target: Component, options?: NavigationOptions) => Page;
17-
$navigateBack: (options?: NavigationOptions) => void;
16+
$navigateTo: <P = any>(
17+
target: Component<P>,
18+
options?: NavigateToOptions<P>,
19+
) => Page;
20+
$navigateBack: (options?: NavigateBackOptions) => void;
1821
}
1922
}
2023

2124
type ResolvableFrame = string | Ref | NSVElement | Frame | undefined;
2225

23-
export interface NavigationOptions extends NavigationEntry {
24-
props?: Record<string, any>;
26+
export type NavigateToOptions<P = any> = NavigationEntry & {
27+
props?: CreateNativeViewProps<P>;
2528
frame?: ResolvableFrame;
26-
}
29+
};
2730

28-
export interface BackNavigationOptions {
31+
export type NavigateBackOptions = {
2932
frame?: ResolvableFrame;
30-
}
33+
};
3134

3235
/**
3336
* @internal
@@ -58,9 +61,9 @@ function resolveFrame(frame?: ResolvableFrame): Frame {
5861
return Frame.getFrameById(ob);
5962
}
6063

61-
export function $navigateTo(
62-
target: Component,
63-
options?: NavigationOptions,
64+
export function $navigateTo<P = any>(
65+
target: Component<P>,
66+
options?: NavigateToOptions<P>,
6467
): Page {
6568
try {
6669
const frame = resolveFrame(options?.frame);
@@ -145,7 +148,7 @@ export function $navigateTo(
145148
}
146149
}
147150

148-
export async function $navigateBack(options?: BackNavigationOptions) {
151+
export async function $navigateBack(options?: NavigateBackOptions) {
149152
const frame = resolveFrame(options?.frame);
150153

151154
if (!frame) {

src/runtimeHelpers.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,26 @@ import {
66
RendererElement,
77
RendererNode,
88
VNode,
9+
VNodeProps,
910
} from '@vue/runtime-core';
1011
import { NSVNode, NSVRoot } from './dom';
1112
import { renderer } from './renderer';
1213

13-
type Props = Record<string, unknown>;
14-
15-
const __DEV__ = true;
16-
1714
let rootApp: App = null;
18-
1915
export const setRootApp = (app: App) => {
2016
rootApp = app;
2117
};
2218

23-
export const createNativeView = <T = View>(
24-
component: Component,
25-
props?: Props,
26-
contextOverrides?: { reload?(): void },
27-
) => {
19+
export type ContextOverrides = { reload?(): void };
20+
export type CreateNativeViewProps<P> = Partial<
21+
P & VNodeProps & Record<string, any>
22+
>;
23+
24+
export function createNativeView<T = View, P = any>(
25+
component: Component<P>,
26+
props?: CreateNativeViewProps<P>,
27+
contextOverrides?: ContextOverrides,
28+
) {
2829
let isMounted = false;
2930
let vm: ComponentPublicInstance | null;
3031
const newApp = renderer.createApp(component, props);
@@ -33,7 +34,6 @@ export const createNativeView = <T = View>(
3334
const context = { ...rootContext, ...contextOverrides };
3435

3536
type M = VNode<RendererNode, RendererElement, { nativeView: T }>;
36-
3737
return {
3838
context,
3939
get vnode() {
@@ -66,7 +66,7 @@ export const createNativeView = <T = View>(
6666
isMounted = false;
6767
},
6868
};
69-
};
69+
}
7070

7171
export const ELEMENT_REF = Symbol(__DEV__ ? `elementRef` : ``);
7272

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy