Pass "Blocks" to LiveComponent Children

I’d like to be able to make a macro for use in my widget library.

    <%= live_component @socket, CardComponent, id: :card1, footers: ["Save Item": "card-1-save"] do %>
      <%= case @item do %>
        <% :header -> %>
        <% :image -> %>
        <% :content -> %>
        <% :content_item -> %>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit.
          <a href="#">#css</a> <a href="#">#responsive</a>
          <br>
          <time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
        <% :footer -> %>
      <% end %>
    <% end %>

Into something more like this:

    <%= widget CardComponent, :card1, footers: ["Save Item": "card-1-save"] do %>
        <% :header -> %>
          <p class="card-header-title">
            Example Card
          </p>
          <a href="#" class="card-header-icon" aria-label="more options">
            <span class="icon">
              <i class="fa fa-angle-down" aria-hidden="true"></i>
            </span>
          </a>
        <% :content_item -> %>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit.
          <a href="#">#css</a> <a href="#">#responsive</a>
          <br>
          <time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
        <% :footer -> %>
      <% end %>
    <% end %>

However, I’m not sure how to make the macro work with “embedded” EEx templates. Actually it’s surprising to me that the first example works at all given it’s passing only a portion of the EEx to the live_component render function (somehow)!

Does anyone have suggestions on how to create a function that’d handle the EEx templates? Previously I tried doing some like unquote(do_block) or other forms but kept getting errors I didn’t understand. Am I missing something simple?

Looks like this works:


  defmacro widget(socket, module, id, [do: block]) do
    quote do
      Phoenix.LiveView.Helpers.live_component(
        unquote(socket),
        unquote(module),
        id: unquote(id),
        inner_content: fn assigns ->
          case assigns[:item] do
            unquote(block)
          end
      end)
    end
  end

But it doesn’t feel quite right. That and I can’t get the @socket to be injected in the macro. It’d be nice to make it so I don’t need to use the inner_content in this way as an anonymous function.