Programming Phoenix LiveView B8.0 ch4: live_modal vs .modal inconsistencies

Hello I’m not sure if this has been caught yet, but in chapter 4 (pdf p101), there are big inconsistencies in the code printed and the code in the generated app.

Eg here is what is printed:

<%= if @live_action in [:new, :edit] do %>
<%= live_modal PentoWeb.ProductLive.FormComponent,
id: @product.id || :new,
title: @page_title,
action: @live_action,
product: @product,
return_to: Routes.product_index_path(@socket, :index) %>
<% end %>

and here is what is in the app:

<%= if @live_action in [:new, :edit] do %>
  <.modal return_to={Routes.product_index_path(@socket, :index)}>
    <.live_component
      module={PentoWeb.ProductLive.FormComponent}
      id={@product.id || :new}
      title={@page_title}
      action={@live_action}
      product={@product}
      return_to={Routes.product_index_path(@socket, :index)}
    />
  </.modal>
<% end %>

and printed p103:

# generate_web/pento/lib/pento_web/live/live_helpers.ex
def live_modal(component, opts) do
path = Keyword.fetch!(opts, :return_to)
modal_opts = [id: :modal, return_to: path, component: component, opts: opts] live_component(PentoWeb.ModalComponent, modal_opts)
end

whereas my app has:

def modal(assigns) do
    assigns = assign_new(assigns, :return_to, fn -> nil end)

    ~H"""
    <div id="modal" class="phx-modal fade-in" phx-remove={hide_modal()}>
      <div
        id="modal-content"
        class="phx-modal-content fade-in-scale"
        phx-click-away={JS.dispatch("click", to: "#close")}
        phx-window-keydown={JS.dispatch("click", to: "#close")}
        phx-key="escape"
      >
        <%= if @return_to do %>
          <%= live_patch "✖",
            to: @return_to,
            id: "close",
            class: "phx-modal-close",
            phx_click: hide_modal()
          %>
        <% else %>
          <a id="close" href="#" class="phx-modal-close" phx-click={hide_modal()}>✖</a>
        <% end %>

        <%= render_slot(@inner_block) %>
      </div>
    </div>
    """
  end

at first it is possible to stitch one and two together, but then “Render the Modal Component” (pdf p104) starts referring to files my app doesn’t even have:

printed p104:

Crack open the lib/pento_web/live/modal_component.ex file, and let’s read it from the top down. This overview will give us a basic sense of the responsibilities of the modal component. Then, in the following sections we’ll dive further into how it all works.
First, you can see that the Modal.Component module uses the PentoWeb, :live_compo- nent behaviour. More on this in a bit.
generate_web/pento/lib/pento_web/live/modal_component.ex
use PentoWeb, :live_component
You’ll also notice that, rather than using a template, the generated component uses an explicitly defined render/1 function to return the markup that will be sent down to the client:
generate_web/pento/lib/pento_web/live/modal_component.ex
@impl true
def render(assigns) do
~H""" <div
    id={@id}
    class="phx-modal"
    phx-capture-click="close"
    phx-window-keydown="close"
    phx-key="escape"
    phx-target={@myself}
    phx-page-loading>
    <div class="phx-modal-content">
      <%= live_patch raw("&times;"), to: @return_to, class: "phx-modal-close" %>
      <%= live_component @component, @opts %>
    </div>
  </div>
"""
end

this file lib/pento_web/live/modal_component.ex does not exist in my app at all. I’m starting to get lost here and wondering if I failed to generate some files (though it looks like this code is now at least partially in lib/pento_web/live/live_helpers.ex? Help…