Skip to content

Commit d1a21b0

Browse files
authored
feat(view): default slot content (#1300)
1 parent 957f9c8 commit d1a21b0

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

packages/view/src/Elements/ViewComponentElement.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,19 +158,33 @@ public function compile(): string
158158
)
159159
// Compile slots
160160
->replaceRegex(
161-
regex: '/<x-slot\s*(name="(?<name>[\w-]+)")?((\s*\/>)|><\/x-slot>)/',
161+
regex: '/<x-slot\s*(name="(?<name>[\w-]+)")?((\s*\/>)|>(?<default>(.|\n)*?)<\/x-slot>)/',
162162
replace: function ($matches) {
163163
$name = $matches['name'] ?: 'slot';
164164

165165
$slot = $this->getSlot($name);
166166

167+
$default = $matches['default'] ?? null;
168+
167169
if ($slot === null) {
170+
if ($default) {
171+
// There's no slot, but there's a default value in the view component
172+
return $default;
173+
}
174+
168175
// A slot doesn't have any content, so we'll comment it out.
169176
// This is to prevent DOM parsing errors (slots in <head> tags is one example, see #937)
170177
return $this->environment->isProduction() ? '' : ('<!--' . $matches[0] . '-->');
171178
}
172179

173-
return $slot->compile();
180+
$compiled = $slot->compile();
181+
182+
// There's no default slot content, but there's a default value in the view component
183+
if (trim($compiled) === '') {
184+
return $default;
185+
}
186+
187+
return $compiled;
174188
},
175189
);
176190

tests/Integration/View/ViewComponentTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,4 +897,44 @@ public function test_escape_expression_attribute_in_view_components(): void
897897

898898
$this->assertSnippetsMatch('<div class="foo" :escaped="foo"></div>', $html);
899899
}
900+
901+
public function test_default_slot_value(): void
902+
{
903+
$this->registerViewComponent('x-test', <<<'HTML'
904+
<x-slot>Default</x-slot>
905+
<x-slot name="a">Default A</x-slot>
906+
<x-slot name="b">Default B</x-slot>
907+
HTML);
908+
909+
$this->assertSnippetsMatch(
910+
<<<'HTML'
911+
Overwritten
912+
Overwritten A
913+
Overwritten B
914+
HTML,
915+
$this->render('<x-test>
916+
Overwritten
917+
<x-slot name="a">Overwritten A</x-slot>
918+
<x-slot name="b">Overwritten B</x-slot>
919+
</x-test>'),
920+
);
921+
922+
$this->assertSnippetsMatch(
923+
<<<'HTML'
924+
Overwritten
925+
Default A
926+
Overwritten B
927+
HTML,
928+
$this->render('<x-test>
929+
Overwritten
930+
<x-slot name="b">Overwritten B</x-slot>
931+
</x-test>'),
932+
);
933+
934+
$this->assertSnippetsMatch(<<<'HTML'
935+
Default
936+
Default A
937+
Default B
938+
HTML, $this->render('<x-test></x-test>'));
939+
}
900940
}

0 commit comments

Comments
 (0)