@@ -4,6 +4,7 @@ import Renderer from '../../Renderer';
4
4
import Block from '../../Block' ;
5
5
import InlineComponent from '../../../nodes/InlineComponent' ;
6
6
import FragmentWrapper from '../Fragment' ;
7
+ import SlotTemplateWrapper from '../SlotTemplate' ;
7
8
import { sanitize } from '../../../../utils/names' ;
8
9
import add_to_set from '../../../utils/add_to_set' ;
9
10
import { b , x , p } from 'code-red' ;
@@ -18,11 +19,15 @@ import EventHandler from '../Element/EventHandler';
18
19
import { extract_names } from 'periscopic' ;
19
20
import mark_each_block_bindings from '../shared/mark_each_block_bindings' ;
20
21
22
+ type SlotDefinition = { block : Block ; scope : TemplateScope ; get_context ?: Node ; get_changes ?: Node } ;
23
+
21
24
export default class InlineComponentWrapper extends Wrapper {
22
25
var : Identifier ;
23
- slots : Map < string , { block : Block ; scope : TemplateScope ; get_context ?: Node ; get_changes ?: Node } > = new Map ( ) ;
26
+ slots : Map < string , SlotDefinition > = new Map ( ) ;
24
27
node : InlineComponent ;
25
28
fragment : FragmentWrapper ;
29
+ children : Array < Wrapper | FragmentWrapper > = [ ] ;
30
+ default_slot_block : Block ;
26
31
27
32
constructor (
28
33
renderer : Renderer ,
@@ -75,16 +80,35 @@ export default class InlineComponentWrapper extends Wrapper {
75
80
} ) ;
76
81
} ) ;
77
82
83
+ const children = this . node . children . slice ( ) ;
84
+ for ( let i = children . length - 1 ; i >= 0 ; ) {
85
+ const child = children [ i ] ;
86
+ if ( child . type === 'SlotTemplate' || ( child . type === 'Element' && child . attributes . find ( attribute => attribute . name === 'slot' ) ) ) {
87
+ const slot_template = new SlotTemplateWrapper ( renderer , block , this , child , strip_whitespace , next_sibling ) ;
88
+ this . children . push ( slot_template ) ;
89
+ children . splice ( i , 1 ) ;
90
+ continue ;
91
+ }
92
+
93
+ i -- ;
94
+ }
95
+
96
+ if ( this . slots . has ( 'default' ) && children . filter ( node => ! ( node . type === 'Text' && node . data . trim ( ) === '' ) ) ) {
97
+ throw new Error ( 'Found elements without slot attribute when using slot="default"' ) ;
98
+ }
99
+
78
100
const default_slot = block . child ( {
79
101
comment : create_debugging_comment ( node , renderer . component ) ,
80
102
name : renderer . component . get_unique_name ( `create_default_slot` ) ,
81
103
type : 'slot'
82
104
} ) ;
83
105
84
106
this . renderer . blocks . push ( default_slot ) ;
107
+ this . default_slot_block = default_slot ;
85
108
86
109
this . slots . set ( 'default' , get_slot_definition ( default_slot , this . node . scope , this . node . lets ) ) ;
87
- this . fragment = new FragmentWrapper ( renderer , default_slot , node . children , this , strip_whitespace , next_sibling ) ;
110
+ const fragment = new FragmentWrapper ( renderer , default_slot , children , this , strip_whitespace , next_sibling ) ;
111
+ this . children . push ( fragment ) ;
88
112
89
113
const dependencies : Set < string > = new Set ( ) ;
90
114
@@ -101,6 +125,13 @@ export default class InlineComponentWrapper extends Wrapper {
101
125
block . add_outro ( ) ;
102
126
}
103
127
128
+ set_slot ( name : string , slot_definition : SlotDefinition ) {
129
+ if ( this . slots . has ( name ) ) {
130
+ throw new Error ( `Duplicate slot name "${ name } " in <${ this . node . name } >` ) ;
131
+ }
132
+ this . slots . set ( name , slot_definition ) ;
133
+ }
134
+
104
135
warn_if_reactive ( ) {
105
136
const { name } = this . node ;
106
137
const variable = this . renderer . component . var_lookup . get ( name ) ;
@@ -134,14 +165,10 @@ export default class InlineComponentWrapper extends Wrapper {
134
165
const statements : Array < Node | Node [ ] > = [ ] ;
135
166
const updates : Array < Node | Node [ ] > = [ ] ;
136
167
137
- if ( this . fragment ) {
168
+ this . children . forEach ( ( child ) => {
138
169
this . renderer . add_to_context ( '$$scope' , true ) ;
139
- const default_slot = this . slots . get ( 'default' ) ;
140
-
141
- this . fragment . nodes . forEach ( ( child ) => {
142
- child . render ( default_slot . block , null , x `#nodes` as unknown as Identifier ) ;
143
- } ) ;
144
- }
170
+ child . render ( this . default_slot_block , null , x `#nodes` as Identifier ) ;
171
+ } ) ;
145
172
146
173
let props ;
147
174
const name_changes = block . get_unique_name ( `${ name . name } _changes` ) ;
@@ -193,7 +220,7 @@ export default class InlineComponentWrapper extends Wrapper {
193
220
component_opts . properties . push ( p `$$inline: true` ) ;
194
221
}
195
222
196
- const fragment_dependencies = new Set ( this . fragment ? [ '$$scope' ] : [ ] ) ;
223
+ const fragment_dependencies = new Set ( this . slots . size ? [ '$$scope' ] : [ ] ) ;
197
224
this . slots . forEach ( slot => {
198
225
slot . block . dependencies . forEach ( name => {
199
226
const is_let = slot . scope . is_let ( name ) ;
0 commit comments