Repository: mhanberg/temple (elixir)

Issue:
Default slot let! directive should work
Currently to pass data to a default slot you have to manually set up the default slot like you'd do a named slot

```elixir
c &component/1 do
  slot :inner_block, let!: foo do
  end
end
```

You should be able to do

```elixir
c &component/1, let!: foo do
end
```

Pull request description:
feat: allow component to declare let! parameter
This allows the user to declare a let parameter for the default slot
without manually defining the `slot :inner_lock, let!: foo do` slot in
the component body.

Closes #239


Patch:
diff --git a/lib/temple/ast/components.ex b/lib/temple/ast/components.ex
index 5e5b682..ed6264e 100644
--- a/lib/temple/ast/components.ex
+++ b/lib/temple/ast/components.ex
@@ -53,6 +53,8 @@ defmodule Temple.Ast.Components do
         {nil, {nil, %{}}}
       end
 
+    {default_slot_parameter, arguments} = Keyword.pop(arguments || [], :let!)
+
     children =
       if default_slot == nil do
         []
@@ -61,6 +63,7 @@ defmodule Temple.Ast.Components do
           Temple.Ast.new(
             Temple.Ast.Slottable,
             name: :inner_block,
+            parameter: default_slot_parameter,
             content: Temple.Parser.parse(default_slot)
           )
         ]


Test patch:
diff --git a/test/support/components.ex b/test/support/components.ex
index adc210f..9956d36 100644
--- a/test/support/components.ex
+++ b/test/support/components.ex
@@ -18,6 +18,14 @@ defmodule Temple.Support.Components do
     end
   end
 
+  def default_slot_with_parameter(assigns) do
+    temple do
+      div do
+        slot @inner_block, %{name: "jimbo"}
+      end
+    end
+  end
+
   def named_slot(assigns) do
     temple do
       div do
diff --git a/test/temple/ast/components_test.exs b/test/temple/ast/components_test.exs
index 09e4109..e440b9e 100644
--- a/test/temple/ast/components_test.exs
+++ b/test/temple/ast/components_test.exs
@@ -216,5 +216,49 @@ defmodule Temple.Ast.ComponentsTest do
                ]
              } = ast
     end
+
+    test "can use let! with default slot without manually declaring it", %{func: func} do
+      raw_ast =
+        quote do
+          c unquote(func), let!: %{form: form}, foo: :bar do
+            "in the #{form} inner block"
+          end
+        end
+
+      ast = Components.run(raw_ast)
+
+      assert %Components{
+               function: ^func,
+               arguments: [foo: :bar],
+               slots: [
+                 %Slottable{
+                   name: :inner_block,
+                   content: [
+                     %Temple.Ast.Default{
+                       elixir_ast:
+                         {:<<>>,
+                          [
+                            end_of_expression: [newlines: 1, line: 224, column: 41],
+                            delimiter: "\""
+                          ],
+                          [
+                            "in the ",
+                            {:"::", [],
+                             [
+                               {{:., [], [Kernel, :to_string]},
+                                [from_interpolation: true, closing: [line: 224, column: 27]],
+                                [{:form, [], Temple.Ast.ComponentsTest}]},
+                               {:binary, [], Temple.Ast.ComponentsTest}
+                             ]},
+                            " inner block"
+                          ]}
+                     }
+                   ],
+                   parameter: {:%{}, _, [form: _]},
+                   attributes: []
+                 }
+               ]
+             } = ast
+    end
   end
 end
diff --git a/test/temple/renderer_test.exs b/test/temple/renderer_test.exs
index 79607c2..7ae5c66 100644
--- a/test/temple/renderer_test.exs
+++ b/test/temple/renderer_test.exs
@@ -408,6 +408,38 @@ defmodule Temple.RendererTest do
       assert_html expected, result
     end
 
+    test "component with a default slot let! parameter" do
+      assigns = %{label: "i'm a slot attribute"}
+
+      result =
+        Renderer.compile do
+          div do
+            c &default_slot_with_parameter/1, let!: %{name: name} do
+              p do
+                "#{name} comes from the component"
+              end
+            end
+          end
+        end
+
+      # heex
+      expected = """
+      <div>
+      <div>
+        <p>
+          jimbo comes from the component
+        </p>
+
+      </div>
+
+
+      </div>
+
+      """
+
+      assert_html expected, result
+    end
+
     test "component with a named slot" do
       assigns = %{label: "i'm a slot attribute"}