ash_hq/lib/ash_hq_web/components/code_example.ex

143 lines
4.4 KiB
Elixir
Raw Normal View History

2022-03-26 10:17:01 +13:00
defmodule AshHqWeb.Components.CodeExample do
2024-04-03 09:38:44 +13:00
@moduledoc """
Renders a code example, as seen on the home page
2022-03-26 10:17:01 +13:00
2024-04-03 09:38:44 +13:00
This is so stupid. Why is this a live component
"""
use Phoenix.LiveComponent
import AshHqWeb.Tails
2022-03-26 10:17:01 +13:00
2024-04-03 09:38:44 +13:00
attr :code, :string, required: true
attr :class, :any
attr :title, :string
attr :start_collapsed, :boolean, default: false
attr :collapsible, :boolean, default: false
2022-03-26 10:17:01 +13:00
def render(assigns) do
2024-04-03 09:38:44 +13:00
~H"""
<div class={classes([
"rounded-xl bg-[#f3f4f6] dark:bg-[#22242D] border border-base-light-400 dark:border-base-dark-700 text-sm border-b",
@class
2024-04-03 09:38:44 +13:00
])
}>
2024-04-03 09:38:44 +13:00
<%= if @collapsible do %>
<button
type="button"
2024-04-03 09:38:44 +13:00
phx-click="fold"
phx-target={@myself}
class={
2024-04-03 09:38:44 +13:00
classes([
"flex flex-row rounded-t-xl w-full justify-between py-2 pl-2 pr-8 hover:bg-base-light-500 dark:hover:border-base-dark-600",
"border-base-light-400 dark:border-base-dark-700 border-b": !@collapsed
2024-04-03 09:38:44 +13:00
])
}
>
<div class="flex flex-row justify-start space-x-1">
<div class="w-3 h-3 bg-base-light-600 rounded-full" />
<div class="w-3 h-3 bg-base-light-600 rounded-full" />
<div class="w-3 h-3 bg-base-light-600 rounded-full" />
</div>
2024-04-03 09:38:44 +13:00
<%= if @title do %>
<h3 class="justify-self-end text-base-light-700 dark:text-white"><%= @title %></h3>
<div>
2024-04-03 09:38:44 +13:00
<%= if @collapsible do %>
<%= if @collapsed do %>
<span class="hero-chevron-double-down-solid w-4 h-4"/>
<% else %>
<span class="hero-chevron-double-up-solid w-4 h-4"/>
<% end %>
<% end %>
</div>
2024-04-03 09:38:44 +13:00
<% end %>
</button>
2024-04-03 09:38:44 +13:00
<% else %>
<div class={classes([
"flex flex-row justify-between py-2 pl-2 pr-8",
"border-base-light-400 dark:border-base-dark-700 border-b": !@collapsed
2024-04-03 09:38:44 +13:00
])
}>
2024-04-03 09:38:44 +13:00
<div class="flex flex-row justify-start space-x-1 w-full">
<div class="w-3 h-3 bg-base-light-600 rounded-full" />
<div class="w-3 h-3 bg-base-light-600 rounded-full" />
<div class="w-3 h-3 bg-base-light-600 rounded-full" />
2024-04-03 09:38:44 +13:00
<div class="flex grow justify-center">
<%= if @title do %>
<h3 class="items-center text-base-light-700 dark:text-white"><%= @title %></h3>
<% end %>
</div>
2022-03-26 10:17:01 +13:00
</div>
</div>
2024-04-03 09:38:44 +13:00
<% end %>
<div class={classes(["pl-1 py-2", hidden: @collapsed])}>
2022-10-23 00:51:22 +13:00
<div class="flex flex-row overflow-auto">
<div class="flex flex-col border-r text-base-light-500 dark:text-white border-base-light-400 dark:border-base-dark-700 pr-1">
2024-04-03 09:38:44 +13:00
<%= if !@collapsed do %>
<%= for {_line, no} <- @code do %>
<pre><%= no %></pre>
<% end %>
<% else %>
2022-03-28 10:26:35 +13:00
<div class="invisible h-0">{to_string(List.last(@code) |> elem(0))}</div>
2024-04-03 09:38:44 +13:00
<% end %>
2022-03-28 10:26:35 +13:00
</div>
<div>
2024-04-03 09:38:44 +13:00
<%= for {line, _no} <- @code do %>
<div class={classes(["flex flex-row mr-4", "invisible h-0": @collapsed])}>
<div class="sm:hidden md:block mr-8 text-base-light-600 font-mono" /><%= Phoenix.HTML.raw(line) %>
2022-03-28 10:26:35 +13:00
</div>
2024-04-03 09:38:44 +13:00
<% end %>
2022-03-28 10:26:35 +13:00
</div>
</div>
2022-03-26 10:17:01 +13:00
</div>
</div>
"""
end
def handle_event("fold", _, socket) do
{:noreply, assign(socket, :collapsed, !socket.assigns.collapsed)}
end
def update(assigns, socket) do
2024-04-03 09:38:44 +13:00
if assigns[:start_collapsed] && assigns.collapsible do
2022-03-28 10:26:35 +13:00
{:ok,
socket
|> assign(assigns)
|> assign(:collapsed, true)}
2022-03-26 10:17:01 +13:00
else
2022-03-28 10:26:35 +13:00
{:ok,
socket
|> assign(assigns)
|> assign(:collapsed, false)}
2022-03-26 10:17:01 +13:00
end
end
@doc false
def to_code(text) do
2022-03-26 10:17:01 +13:00
lines =
text
# this is pretty naive, won't handle things like block comments
|> String.split("\n")
|> Enum.reverse()
|> Enum.drop_while(&(&1 in [""]))
|> Enum.reverse()
|> Enum.map(fn
"" ->
"<br>"
line ->
Makeup.highlight(line)
end)
count = Enum.count(lines)
padding = String.length(to_string(count))
lines
|> Enum.with_index()
|> Enum.map(fn {line, index} ->
{line, String.pad_leading(to_string(index + 1), padding, " ")}
end)
end
end