@@ -15,6 +15,25 @@ export function register(components) {
15
15
registry . set ( name , value ) ;
16
16
}
17
17
18
+ /**
19
+ * @param {ChildNode } webComponent
20
+ */
21
+ function updateProps ( webComponent , props = { } ) {
22
+ for ( const [ key , value ] of Object . entries ( props ) )
23
+ webComponent [ key ] = value ;
24
+ }
25
+
26
+ /**
27
+ * @param {ChildNode } webComponent
28
+ */
29
+ function updateEvents ( webComponent , events = { } ) {
30
+ for ( const [ key , listener ] of Object . entries ( events ) ) {
31
+ webComponent . addEventListener ( key , event =>
32
+ listener ( /** @type {CustomEvent } */ ( event ) . detail )
33
+ ) ;
34
+ }
35
+ }
36
+
18
37
/**
19
38
* @param {string } html
20
39
* @return {DocumentFragment }
@@ -24,16 +43,38 @@ function stringToHtml(html) {
24
43
}
25
44
26
45
/**
27
- * @param {string | string[] } slot
46
+ * @param {ChildNode } webComponent
28
47
*/
29
- function createSlots ( slot ) {
30
- if ( typeof slot === 'string' )
31
- return [ stringToHtml ( slot ) ] ;
32
-
33
- if ( Array . isArray ( slot ) )
34
- return slot . map ( stringToHtml ) ;
48
+ function updateSlots ( webComponent , slots = { } ) {
49
+ for ( const [ key , value ] of Object . entries ( slots ) ) {
50
+ let slotElements ;
51
+ if ( typeof value === 'string' )
52
+ slotElements = [ stringToHtml ( value ) ] ;
53
+
54
+ if ( Array . isArray ( value ) )
55
+ slotElements = value . map ( stringToHtml ) ;
56
+
57
+ if ( ! slotElements )
58
+ throw new Error ( `Invalid slot with the name: \`${ key } \` supplied to \`mount()\`` ) ;
59
+
60
+ slotElements . forEach ( ( fragment ) => {
61
+ const slotElement = fragment . firstChild ;
62
+ if ( ! slotElement )
63
+ throw new Error ( `Invalid slot with the name: \`${ key } \` supplied to \`mount()\`` ) ;
64
+
65
+ if ( key === 'default' )
66
+ return webComponent . appendChild ( slotElement ) ;
67
+
68
+ if ( slotElement ?. nodeName === '#text' ) {
69
+ throw new Error (
70
+ `Invalid slot with the name: \`${ key } \` supplied to \`mount()\`, expected an HTMLElement but received a text node.`
71
+ ) ;
72
+ }
35
73
36
- throw Error ( `Invalid slot received.` ) ;
74
+ slotElement [ 'slot' ] = key ;
75
+ webComponent . appendChild ( fragment . firstChild ) ;
76
+ } ) ;
77
+ }
37
78
}
38
79
39
80
/**
@@ -62,53 +103,37 @@ function createComponent(component) {
62
103
throw new Error ( 'JSX mount notation is not supported' ) ;
63
104
64
105
const webComponent = new Component ( ) ;
65
-
66
- for ( const [ key , value ] of Object . entries ( component . options ?. props || { } ) )
67
- webComponent [ key ] = value ;
68
-
69
- for ( const [ key , listener ] of Object . entries ( component . options ?. on || { } ) )
70
- webComponent . addEventListener ( key , event => listener ( /** @type {CustomEvent } */ ( event ) . detail ) ) ;
71
-
72
- for ( const [ key , value ] of Object . entries ( component . options ?. slots || { } ) ) {
73
- if ( key !== 'default' )
74
- throw new Error ( 'named slots are not yet supported' ) ;
75
-
76
- createSlots ( value ) . forEach ( slot => {
77
- webComponent . appendChild ( slot ) ;
78
- } )
79
- }
80
-
106
+ updateProps ( webComponent , component . options ?. props ) ;
107
+ updateSlots ( webComponent , component . options ?. slots ) ;
108
+ updateEvents ( webComponent , component . options ?. on ) ;
81
109
return webComponent ;
82
110
}
83
111
84
112
window . playwrightUpdate = async ( rootElement , component ) => {
85
113
if ( component . kind === 'jsx' )
86
114
throw new Error ( 'JSX mount notation is not supported' ) ;
87
115
88
- if ( component . options ?. slots )
89
- throw new Error ( 'slots in component.update() is not yet supported ' ) ;
116
+ const webComponent = rootElement . firstChild ;
117
+ if ( ! webComponent ) throw new Error ( 'Component was not mounted ' ) ;
90
118
91
- const wrapper = rootElement . firstChild ;
92
- if ( ! wrapper )
93
- throw new Error ( 'Component was not mounted' ) ;
94
-
95
- for ( const [ key , value ] of Object . entries ( component . options ?. props || { } ) )
96
- wrapper [ key ] = value ;
119
+ if ( component . options ?. slots )
120
+ throw new Error ( 'Slots in component.update() is not yet supported' ) ;
97
121
98
- for ( const [ key , listener ] of Object . entries ( component . options ?. on || { } ) )
99
- wrapper . addEventListener ( key , event => listener ( /** @type {CustomEvent } */ ( event ) . detail ) ) ;
122
+ updateProps ( webComponent , component . options ?. props ) ;
123
+ updateSlots ( webComponent , component . options ?. slots ) ;
124
+ updateEvents ( webComponent , component . options ?. on ) ;
100
125
} ;
101
126
102
127
window . playwrightUnmount = async ( rootElement ) => {
103
128
rootElement . replaceChildren ( ) ;
104
129
} ;
105
130
106
131
window . playwrightMount = async ( component , rootElement , hooksConfig ) => {
107
- for ( const hook of /** @type { any } */ ( window ) . __pw_hooks_before_mount || [ ] )
132
+ for ( const hook of window [ ' __pw_hooks_before_mount' ] || [ ] )
108
133
await hook ( { hooksConfig } ) ;
109
134
110
135
rootElement . appendChild ( createComponent ( component ) ) ;
111
136
112
- for ( const hook of /** @type { any } */ ( window ) . __pw_hooks_after_mount || [ ] )
137
+ for ( const hook of window [ ' __pw_hooks_after_mount' ] || [ ] )
113
138
await hook ( { hooksConfig } ) ;
114
139
} ;
0 commit comments