defmodule Moon.Components.ToastStack do
@moduledoc false
use Moon.StatefulComponent
alias Moon.Components.Toast
alias Moon.Components.Toast.Message
@default_duration 4000
data(toasts, :keyword, default: Keyword.new())
def render(assigns) do
~F"""
"""
end
def show(toast = %Message{}, id) do
toast =
if toast.id do
toast
else
%{toast | id: generate_id()}
end
send_update(__MODULE__, id: id, toast: toast)
end
def show(toasts, id) when is_list(toasts) do
Enum.each(toasts, fn toast -> show(toast, id) end)
end
def hide_toast(toast_id, stack_id) do
send_update(__MODULE__, id: stack_id, toast_to_hide: toast_id)
end
def update(%{toast: toast}, socket) do
Process.send_after(self(), {:hide_toast, toast.id}, @default_duration)
{:ok, assign(socket, toasts: socket.assigns.toasts ++ [{toast.id, toast}])}
end
def update(%{toast_to_hide: toast_id}, socket) do
{
:ok,
assign(socket, toasts: Keyword.delete(socket.assigns.toasts, toast_id))
}
end
def update(_assigns, socket), do: {:ok, socket}
def handle_event("hide_toast", %{"id" => id}, socket) do
toasts = Keyword.delete(socket.assigns.toasts, String.to_existing_atom(id))
{:noreply, assign(socket, toasts: toasts)}
end
defp generate_id do
12
|> :crypto.strong_rand_bytes()
|> Base.url_encode64()
|> binary_part(0, 12)
|> String.to_atom()
end
end