1
- import { transformVNodeArgs , h , createVNode } from 'vue'
1
+ import {
2
+ transformVNodeArgs ,
3
+ h ,
4
+ ComponentPublicInstance ,
5
+ Slots ,
6
+ ComponentOptions ,
7
+ defineComponent ,
8
+ VNodeProps ,
9
+ VNodeTypes
10
+ } from 'vue'
2
11
import { hyphenate } from './utils/vueShared'
3
12
import { MOUNT_COMPONENT_REF , MOUNT_PARENT_NAME } from './constants'
4
13
import { config } from './config'
5
14
import { matchName } from './utils/matchName'
6
15
7
- interface IStubOptions {
16
+ interface StubOptions {
8
17
name ?: string
9
18
props : any
10
19
}
11
20
12
- type VNodeArgs = Parameters < typeof createVNode >
13
-
14
- function getSlots ( ctx ) {
21
+ function getSlots ( ctx : ComponentPublicInstance ) : Slots | undefined {
15
22
return ! config . renderStubDefaultSlot ? undefined : ctx . $slots
16
23
}
17
24
18
- const createStub = ( { name, props } : IStubOptions ) => {
25
+ const createStub = ( { name, props } : StubOptions ) : ComponentOptions => {
19
26
const anonName = 'anonymous-stub'
20
27
const tag = name ? `${ hyphenate ( name ) } -stub` : anonName
21
28
22
- const render = ( ctx ) => {
23
- return h ( tag , { } , getSlots ( ctx ) )
29
+ const render = ( ctx : ComponentPublicInstance ) => {
30
+ // TS is not happy with this signature, so we cast the Slots as any
31
+ return h ( tag , { } , getSlots ( ctx ) as any )
24
32
}
25
33
26
- return { name : name || anonName , render, props }
34
+ return defineComponent ( { name : name || anonName , render, props } )
27
35
}
28
36
29
37
const resolveComponentStubByName = (
@@ -45,41 +53,45 @@ const resolveComponentStubByName = (
45
53
}
46
54
}
47
55
48
- const isHTMLElement = ( args : VNodeArgs ) => typeof args [ 0 ] === 'string'
56
+ const isHTMLElement = ( type : VNodeTypes ) => typeof type === 'string'
49
57
50
- const isCommentOrFragment = ( args : VNodeArgs ) => typeof args [ 0 ] === 'symbol'
58
+ const isCommentOrFragment = ( type : VNodeTypes ) => typeof type === 'symbol'
51
59
52
- const isParent = ( args : VNodeArgs ) =>
53
- isComponent ( args ) && args [ 0 ] [ 'name' ] === MOUNT_PARENT_NAME
60
+ const isParent = ( type : VNodeTypes ) =>
61
+ isComponent ( type ) && type [ 'name' ] === MOUNT_PARENT_NAME
54
62
55
- const isMountedComponent = ( args : VNodeArgs ) =>
56
- isComponent ( args ) && args [ 1 ] && args [ 1 ] [ 'ref' ] === MOUNT_COMPONENT_REF
63
+ const isMountedComponent = (
64
+ type : VNodeTypes ,
65
+ props : ( { [ key : string ] : unknown } & VNodeProps ) | null | undefined
66
+ ) => isComponent ( type ) && props && props [ 'ref' ] === MOUNT_COMPONENT_REF
57
67
58
- const isComponent = ( args : VNodeArgs ) => typeof args [ 0 ] === 'object'
68
+ const isComponent = ( type : VNodeTypes ) : type is ComponentOptions =>
69
+ typeof type === 'object'
59
70
60
- const isFunctionalComponent = ( [ type ] : VNodeArgs ) =>
71
+ const isFunctionalComponent = ( type : VNodeTypes ) : type is ComponentOptions =>
61
72
typeof type === 'function' && ( 'name' in type || 'displayName' in type )
62
73
63
74
export function stubComponents (
64
75
stubs : Record < any , any > = { } ,
65
76
shallow : boolean = false
66
77
) {
67
78
transformVNodeArgs ( ( args ) => {
79
+ const [ nodeType , props , children , patchFlag , dynamicProps ] = args
80
+ const type = nodeType as VNodeTypes
68
81
// args[0] can either be:
69
82
// 1. a HTML tag (div, span...)
70
83
// 2. An object of component options, such as { name: 'foo', render: [Function], props: {...} }
71
84
// Depending what it is, we do different things.
72
85
if (
73
- isHTMLElement ( args ) ||
74
- isCommentOrFragment ( args ) ||
75
- isParent ( args ) ||
76
- isMountedComponent ( args )
86
+ isHTMLElement ( type ) ||
87
+ isCommentOrFragment ( type ) ||
88
+ isParent ( type ) ||
89
+ isMountedComponent ( type , props )
77
90
) {
78
91
return args
79
92
}
80
93
81
- if ( isComponent ( args ) || isFunctionalComponent ( args ) ) {
82
- const [ type , props , children , patchFlag , dynamicProps ] = args
94
+ if ( isComponent ( type ) || isFunctionalComponent ( type ) ) {
83
95
const name = type [ 'name' ] || type [ 'displayName' ]
84
96
if ( ! name && ! shallow ) {
85
97
return args
@@ -97,7 +109,6 @@ export function stubComponents(
97
109
// where the signature is h(Component, props, slots)
98
110
// case 1: default stub
99
111
if ( stub === true || shallow ) {
100
- // @ts -ignore
101
112
const propsDeclaration = type ?. props || { }
102
113
return [
103
114
createStub ( { name, props : propsDeclaration } ) ,
0 commit comments