66
77use Tempest \View \Element ;
88use Tempest \View \Renderers \TempestViewCompiler ;
9+ use Tempest \View \Slot ;
910use Tempest \View \ViewComponent ;
11+ use function Tempest \Support \arr ;
1012use function Tempest \Support \str ;
1113
1214final class ViewComponentElement implements Element
@@ -17,7 +19,8 @@ public function __construct(
1719 private readonly TempestViewCompiler $ compiler ,
1820 private readonly ViewComponent $ viewComponent ,
1921 array $ attributes ,
20- ) {
22+ )
23+ {
2124 $ this ->attributes = $ attributes ;
2225 }
2326
@@ -26,6 +29,22 @@ public function getViewComponent(): ViewComponent
2629 return $ this ->viewComponent ;
2730 }
2831
32+ /** @return Element[] */
33+ public function getSlots (): array
34+ {
35+ $ slots = [];
36+
37+ foreach ($ this ->getChildren () as $ child ) {
38+ if (! $ child instanceof SlotElement) {
39+ continue ;
40+ }
41+
42+ $ slots [] = $ child ;
43+ }
44+
45+ return $ slots ;
46+ }
47+
2948 public function getSlot (string $ name = 'slot ' ): ?Element
3049 {
3150 foreach ($ this ->getChildren () as $ child ) {
@@ -57,7 +76,25 @@ public function getSlot(string $name = 'slot'): ?Element
5776
5877 public function compile (): string
5978 {
79+ /** @var Slot[] $slots */
80+ $ slots = arr ($ this ->getSlots ())
81+ ->mapWithKeys (fn (SlotElement $ element ) => yield $ element ->name => Slot::fromElement ($ element ))
82+ ->toArray ();
83+
6084 $ compiled = str ($ this ->viewComponent ->compile ($ this ))
85+ // Add dynamic slots to the current scope
86+ ->prepend (
87+ '<?php $_previousSlots = $slots ?? null; ?> ' , // Store previous slots in temporary variable to keep scope
88+ sprintf ('<?php $slots = %s; ?> ' , var_export ($ slots , true )), // Set the new value of $slots for this view component
89+ )
90+
91+ // Cleanup slots after the view component and restore slots from previous scope
92+ ->append (
93+ '<?php unset($slots); ?> ' , // Unset current $slots
94+ '<?php $slots = $_previousSlots ?? null; ?> ' , // Restore previous $slots
95+ '<?php unset($_previousSlots); ?> ' , // Cleanup temporary $_previousSlots
96+ )
97+
6198 // Compile slots
6299 ->replaceRegex (
63100 regex: '/<x-slot\s*(name="(?<name>\w+)")?((\s*\/>)|><\/x-slot>)/ ' ,
0 commit comments