WIP: trying to figure out flickering

This commit is contained in:
Zach Daniel 2022-03-28 18:05:19 -04:00
parent 068a03efa2
commit c6c05c0fa1
15 changed files with 507 additions and 157 deletions

View file

@ -4,7 +4,6 @@
@import "tailwindcss/utilities"; @import "tailwindcss/utilities";
@import "syntax.css"; @import "syntax.css";
@import "markdown.css";
.search-hit { .search-hit {
color: #fb923c color: #fb923c

View file

@ -71,10 +71,23 @@ let liveSocket = new LiveSocket("/live", Socket, {
} }
}); });
// Show progress bar on live navigation and form submits // Show progress bar on live navigation and form submits. Only displays if still
// loading after 120 msec
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
window.addEventListener("phx:page-loading-start", info => topbar.show())
window.addEventListener("phx:page-loading-stop", info => topbar.hide()) let topBarScheduled = undefined;
window.addEventListener("phx:page-loading-start", () => {
if(!topBarScheduled) {
topBarScheduled = setTimeout(() => topbar.show(), 120);
};
});
window.addEventListener("phx:page-loading-stop", () => {
clearTimeout(topBarScheduled);
topBarScheduled = undefined;
topbar.hide();
});
window.addEventListener("js:focus", e => e.target.focus()) window.addEventListener("js:focus", e => e.target.focus())
window.addEventListener("js:noscroll-main", e => { window.addEventListener("js:noscroll-main", e => {
if(e.target.style.display === "none") { if(e.target.style.display === "none") {

View file

@ -2,7 +2,7 @@ const colors = require('tailwindcss/colors')
module.exports = { module.exports = {
mode: "jit", mode: "jit",
purge: ["./js/**/*.js", "../lib/*_web/**/*.*ex"], content: ["./js/**/*.js", "../lib/*_web/**/*.*ex"],
darkMode: "class", darkMode: "class",
theme: { theme: {
extend: { extend: {

View file

@ -17,6 +17,7 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Changes.RenderMarkdown do
) )
{:ok, html_doc, _} -> {:ok, html_doc, _} ->
html_doc = AshHq.Docs.Extensions.RenderMarkdown.Highlighter.highlight(html_doc)
Ash.Changeset.force_change_attribute(changeset, opts[:destination], html_doc) Ash.Changeset.force_change_attribute(changeset, opts[:destination], html_doc)
end end
else else

View file

@ -0,0 +1,55 @@
defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
@moduledoc false
# Copied *directly* from nimble_publisher
# https://github.com/dashbitco/nimble_publisher/blob/v0.1.2/lib/nimble_publisher/highlighter.ex
@doc """
Highlights all code block in an already generated HTML document.
"""
def highlight(html) do
Regex.replace(
~r/<pre><code(?:\s+class="(\w*)")?>([^<]*)<\/code><\/pre>/,
html,
&highlight_code_block(&1, &2, &3)
)
end
defp highlight_code_block(full_block, lang, code) do
case pick_language_and_lexer(lang) do
{_language, nil, _opts} -> full_block
{language, lexer, opts} -> render_code(language, lexer, opts, code)
end
end
defp pick_language_and_lexer(""), do: {"text", nil, []}
defp pick_language_and_lexer(lang) do
case Makeup.Registry.fetch_lexer_by_name(lang) do
{:ok, {lexer, opts}} -> {lang, lexer, opts}
:error -> {lang, nil, []}
end
end
defp render_code(lang, lexer, lexer_opts, code) do
highlighted =
code
|> unescape_html()
|> IO.iodata_to_binary()
|> Makeup.highlight_inner_html(
lexer: lexer,
lexer_options: lexer_opts,
formatter_options: [highlight_tag: "span"]
)
~s(<pre><code class="makeup #{lang}">#{highlighted}</code></pre>)
end
entities = [{"&amp;", ?&}, {"&lt;", ?<}, {"&gt;", ?>}, {"&quot;", ?"}, {"&#39;", ?'}]
for {encoded, decoded} <- entities do
defp unescape_html(unquote(encoded) <> rest), do: [unquote(decoded) | unescape_html(rest)]
end
defp unescape_html(<<c, rest::binary>>), do: [c | unescape_html(rest)]
defp unescape_html(<<>>), do: []
end

View file

@ -1,6 +1,15 @@
defmodule AshHq.Docs.Extension do defmodule AshHq.Docs.Extension do
use AshHq.Resource, use AshHq.Resource,
data_layer: AshPostgres.DataLayer data_layer: AshPostgres.DataLayer,
extensions: [AshHq.Docs.Extensions.Search, AshHq.Docs.Extensions.RenderMarkdown]
render_markdown do
render_attributes doc: :html_doc
end
# search :load_for_search do
# end
postgres do postgres do
table "extensions" table "extensions"
@ -50,6 +59,13 @@ defmodule AshHq.Docs.Extension do
attribute :doc, :string do attribute :doc, :string do
allow_nil? false allow_nil? false
constraints trim?: false, allow_empty?: true
default ""
end
attribute :doc_html, :string do
constraints trim?: false, allow_empty?: true
writable? false
end end
attribute :type, :string do attribute :type, :string do

View file

@ -0,0 +1,148 @@
defmodule AshHqWeb.Components.DocSidebar do
use Surface.Component
alias AshHqWeb.Routes
alias Surface.Components.LiveRedirect
prop class, :css_class, default: ""
prop libraries, :list, required: true
prop extension, :any, default: nil
prop guide, :any, default: nil
prop library, :any, default: nil
prop library_version, :any, default: nil
prop selected_versions, :map, default: %{}
prop id, :string, required: true
def render(assigns) do
~F"""
<aside id={@id} class={"w-64 h-full block", @class} aria-label="Sidebar">
<div class="overflow-y-auto py-4 px-3">
<ul class="space-y-2">
{#for library <- @libraries}
<li>
<LiveRedirect
to={Routes.library_link(library, selected_version_name(library, @selected_versions))}
class={
"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700",
"dark:bg-gray-600": !@extension && @library && library.id == @library.id
}
>
<Heroicons.Outline.CollectionIcon class="w-6 h-6" />
<span class="ml-3 mr-2">{library.display_name}</span>
<span class="font-light text-gray-500">{selected_version_name(library, @selected_versions)}</span>
</LiveRedirect>
{#if @library && @library_version && library.id == @library.id}
{#if !Enum.empty?(@library_version.guides)}
<div class="ml-2 text-gray-500">
Guides
</div>
{/if}
{#for guide <- @library_version.guides}
<li class="ml-3">
<LiveRedirect
to={Routes.guide_link(
library,
selected_version_name(library, @selected_versions),
guide.url_safe_name
)}
class={
"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
"dark:bg-gray-600": @guide && @guide.id == guide.id
}
>
<Heroicons.Outline.BookOpenIcon class="h-4 w-4" />
<span class="ml-3 mr-2">{guide.name}</span>
</LiveRedirect>
</li>
{/for}
{#if !Enum.empty?(@library_version.guides)}
<div class="ml-2 text-gray-500">
Extensions
</div>
{/if}
{#for extension <- get_extensions(library, @selected_versions)}
<li class="ml-3">
<LiveRedirect
to={Routes.extension_link(library, selected_version_name(library, @selected_versions), extension.name)}
class={
"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
"dark:bg-gray-600": @extension && @extension.id == extension.id
}
>
{render_icon(assigns, extension.type)}
<span class="ml-3 mr-2">{extension.name}</span>
</LiveRedirect>
</li>
{/for}
{/if}
</li>
{/for}
</ul>
</div>
</aside>
"""
end
def render_icon(assigns, "Resource") do
~F"""
<Heroicons.Outline.ServerIcon class="h-4 w-4" />
"""
end
def render_icon(assigns, "Api") do
~F"""
<Heroicons.Outline.SwitchHorizontalIcon class="h-4 w-4" />
"""
end
def render_icon(assigns, "DataLayer") do
~F"""
<Heroicons.Outline.DatabaseIcon class="h-4 w-4" />
"""
end
def render_icon(assigns, "Flow") do
~F"""
<Heroicons.Outline.MapIcon class="h-4 w-4" />
"""
end
def render_icon(assigns, "Notifier") do
~F"""
<Heroicons.Outline.MailIcon class="h-4 w-4" />
"""
end
def render_icon(assigns, "Registry") do
~F"""
<Heroicons.Outline.ViewListIcon class="h-4 w-4" />
"""
end
def render_icon(assigns, _) do
~F"""
<Heroicons.Outline.PuzzleIcon class="h-4 w-4" />
"""
end
defp selected_version_name(library, selected_versions) do
case Enum.find(library.versions, &(&1.id == selected_versions[library.id])) do
nil ->
nil
version ->
version.version
end
end
defp get_extensions(library, selected_versions) do
case Enum.find(library.versions, &(&1.id == selected_versions[library.id])) do
nil ->
[]
version ->
version.extensions
end
end
end

View file

@ -23,7 +23,7 @@ defmodule AshHqWeb.Components.Search do
<div <div
id={@id} id={@id}
style="display: none;" style="display: none;"
class="transition absolute flex justify-center align-middle w-screen h-screen backdrop-blur-sm pb-8 bg-white bg-opacity-10" class="absolute flex justify-center align-middle w-screen h-screen backdrop-blur-sm pb-8 bg-white bg-opacity-10"
phx-hook="CmdK" phx-hook="CmdK"
> >
<div <div
@ -126,7 +126,8 @@ defmodule AshHqWeb.Components.Search do
"bg-gray-800": @selected_item.id != item.id "bg-gray-800": @selected_item.id != item.id
} }
> >
{#if item.__struct__ != AshHq.Docs.LibraryVersion && item.name != List.last(Map.get(results, :path, []))} {#if item.__struct__ != AshHq.Docs.LibraryVersion &&
item.name != List.last(Map.get(results, :path, []))}
{item.name} {item.name}
{/if} {/if}
{#if item.__struct__ == AshHq.Docs.LibraryVersion} {#if item.__struct__ == AshHq.Docs.LibraryVersion}

View file

@ -1,8 +1,8 @@
defmodule AshHqWeb.Pages.Docs do defmodule AshHqWeb.Pages.Docs do
use Surface.LiveComponent use Surface.LiveComponent
alias AshHqWeb.Routes alias Phoenix.LiveView.JS
alias Surface.Components.LiveRedirect alias AshHqWeb.Components.DocSidebar
prop params, :map, required: true prop params, :map, required: true
prop change_versions, :event, required: true prop change_versions, :event, required: true
@ -14,112 +14,75 @@ defmodule AshHqWeb.Pages.Docs do
data docs, :any data docs, :any
data library_version, :any data library_version, :any
data guide, :any data guide, :any
data doc_path, :list, default: []
@spec render(any) :: Phoenix.LiveView.Rendered.t() @spec render(any) :: Phoenix.LiveView.Rendered.t()
def render(assigns) do def render(assigns) do
~F""" ~F"""
<div class="flex flex-row h-full dark:bg-dark-grid justify-center"> <div class="h-full w-full flex flex-col bg-light-grid dark:bg-dark-grid">
<aside class="w-64 h-full" aria-label="Sidebar"> <div class="md:hidden flex flex-row justify-start space-x-12 mt-2 items-center border-b border-t border-gray-600 py-3 mb-10">
<div class="overflow-y-auto py-4 px-3"> <button class="dark:hover:text-gray-600" phx-click={show_sidebar()}>
<ul class="space-y-2"> <Heroicons.Outline.MenuIcon class="w-8 h-8 ml-4" />
{#for library <- @libraries} </button>
<li> {#if @doc_path && @doc_path != []}
<LiveRedirect <div class="flex flex-row space-x-1 items-center">
to={Routes.library_link(library, selected_version_name(library, @selected_versions))} {#case @doc_path}
class={"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700", "dark:bg-gray-600": !@extension && @library && library.id == @library.id} {#match [item]}
> <div class="dark:text-white">
<Heroicons.Outline.CollectionIcon class="w-6 h-6" /> {item}
<span class="ml-3 mr-2">{library.display_name}</span> </div>
<span class="font-light text-gray-500">{selected_version_name(library, @selected_versions)}</span> {#match path}
</LiveRedirect> {#for item <- :lists.droplast(path)}
{#if @library && @library_version && library.id == @library.id} <span class="text-gray-500">
{#if !Enum.empty?(@library_version.guides)} {item}</span>
<div class="ml-2 text-gray-500"> <Heroicons.Outline.ChevronRightIcon class="w-3 h-3" />
Guides {/for}
<span class="dark:text-white" />
{/case}
</div> </div>
{/if} {/if}
{#for guide <- @library_version.guides}
<li class="ml-3">
<LiveRedirect
to={Routes.guide_link(library, selected_version_name(library, @selected_versions), guide.url_safe_name)}
class={"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700", "dark:bg-gray-600": @guide && @guide.id == guide.id}
>
<Heroicons.Outline.BookOpenIcon class="h-4 w-4"/>
<span class="ml-3 mr-2">{guide.name}</span>
</LiveRedirect>
</li>
{/for}
{#if !Enum.empty?(@library_version.guides)}
<div class="ml-2 text-gray-500">
Extensions
</div> </div>
{/if} <div id="mobile-sidebar-container" class="hidden md:hidden relative w-screen h-full backdrop-blur-lg transition">
{#for extension <- get_extensions(library, @selected_versions)} <div>
<li class="ml-3"> <DocSidebar
<LiveRedirect id="mobile-sidebar"
to={Routes.extension_link(library, selected_version_name(library, @selected_versions), extension.name)} class="absolute left-0 top-0"
class={"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700", "dark:bg-gray-600": @extension && @extension.id == extension.id} libraries={@libraries}
> extension={@extension}
{render_icon(assigns, extension.type)} guide={@guide}
<span class="ml-3 mr-2">{extension.name}</span> library={@library}
</LiveRedirect> library_version={@library_version}
</li> selected_versions={@selected_versions}
/>
{/for}
{/if}
</li>
{/for}
</ul>
</div> </div>
</aside> </div>
<div class="grow flex flex-row h-full justify-center space-x-12">
<DocSidebar
id="sidebar"
class="hidden md:block"
libraries={@libraries}
extension={@extension}
guide={@guide}
library={@library}
library_version={@library_version}
selected_versions={@selected_versions}
/>
<div class="grow w-full prose prose-zinc md:prose-lg lg:prose-xl dark:prose-invert"> <div class="grow w-full prose prose-zinc md:prose-lg lg:prose-xl dark:prose-invert">
{raw(@docs)} {raw(@docs)}
</div> </div>
</div> </div>
</div>
""" """
end end
def render_icon(assigns, "Resource") do def show_sidebar() do
~F""" %JS{}
<Heroicons.Outline.ServerIcon class="h-4 w-4"/> |> JS.toggle(
""" to: "#mobile-sidebar-container",
end in: {"fade-in duration-100 transition", "hidden", "block"},
out: {"fade-out duration-100 transition", "block", "hidden"},
def render_icon(assigns, "Api") do time: 100
~F""" )
<Heroicons.Outline.SwitchHorizontalIcon class="h-4 w-4"/>
"""
end
def render_icon(assigns, "DataLayer") do
~F"""
<Heroicons.Outline.DatabaseIcon class="h-4 w-4"/>
"""
end
def render_icon(assigns, "Flow") do
~F"""
<Heroicons.Outline.MapIcon class="h-4 w-4"/>
"""
end
def render_icon(assigns, "Notifier") do
~F"""
<Heroicons.Outline.MailIcon class="h-4 w-4"/>
"""
end
def render_icon(assigns, "Registry") do
~F"""
<Heroicons.Outline.ViewListIcon class="h-4 w-4"/>
"""
end
def render_icon(assigns, _) do
~F"""
<Heroicons.Outline.PuzzleIcon class="h-4 w-4"/>
"""
end end
def update(assigns, socket) do def update(assigns, socket) do
@ -131,16 +94,6 @@ defmodule AshHqWeb.Pages.Docs do
|> assign_docs()} |> assign_docs()}
end end
defp selected_version_name(library, selected_versions) do
case Enum.find(library.versions, &(&1.id == selected_versions[library.id])) do
nil ->
nil
version ->
version.version
end
end
defp assign_guide(socket) do defp assign_guide(socket) do
guide = guide =
if socket.assigns[:params]["guide"] && socket.assigns.library_version do if socket.assigns[:params]["guide"] && socket.assigns.library_version do
@ -155,16 +108,25 @@ defmodule AshHqWeb.Pages.Docs do
defp assign_docs(socket) do defp assign_docs(socket) do
cond do cond do
socket.assigns.extension -> socket.assigns.extension ->
assign(socket, :docs, Earmark.as_html!(socket.assigns.extension.doc)) assign(socket,
docs: Earmark.as_html!(socket.assigns.extension.doc),
doc_path: [socket.assigns.library.name, socket.assigns.extension.name]
)
socket.assigns.guide -> socket.assigns.guide ->
assign(socket, :docs, Earmark.as_html!(socket.assigns.guide.text)) assign(socket,
docs: Earmark.as_html!(socket.assigns.guide.text),
doc_path: [socket.assigns.library.name, socket.assigns.guide.name]
)
socket.assigns.library_version -> socket.assigns.library_version ->
assign(socket, :docs, Earmark.as_html!(socket.assigns.library_version.doc)) assign(socket,
docs: Earmark.as_html!(socket.assigns.library_version.doc),
doc_path: [socket.assigns.library.name]
)
true -> true ->
assign(socket, :docs, "") assign(socket, docs: "", doc_path: [])
end end
end end
@ -207,25 +169,6 @@ defmodule AshHqWeb.Pages.Docs do
end end
end end
# defp render_sub_item_nav(assigns, library, path \\ []) do
# ~F"""
# <ul class="space-y-2">
# {#for %{path: ^path, name: name} = dsl <- library.dsls}
# <li class="ml-2">
# <LiveRedirect
# to={Routes.doc_link(dsl)}
# class="flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700"
# >
# <Heroicons.Outline.CollectionIcon class="w-6 h-6" />
# <span class="ml-3 mr-2">{library.display_name}</span>
# <span class="font-light text-gray-500">{selected_version_name(library, @selected_versions)}</span>
# </LiveRedirect>
# </li>
# {/for}
# </ul>
# """
# end
defp assign_library(socket) do defp assign_library(socket) do
if !socket.assigns[:library] || if !socket.assigns[:library] ||
socket.assigns.params["library"] != socket.assigns.library.name do socket.assigns.params["library"] != socket.assigns.library.name do

View file

@ -26,11 +26,7 @@ defmodule AshHqWeb.AppViewLive do
change_versions="change-versions" change_versions="change-versions"
selected_versions={@selected_versions} selected_versions={@selected_versions}
/> />
<button <button id="search-button" class="hidden" phx-click={AshHqWeb.AppViewLive.toggle_search()} />
id="search-button"
class="hidden"
phx-click={AshHqWeb.AppViewLive.toggle_search()}
/>
<div <div
id="main-container" id="main-container"
class="h-full bg-white dark:bg-primary-black dark:text-silver-phoenix overflow-x-hidden" class="h-full bg-white dark:bg-primary-black dark:text-silver-phoenix overflow-x-hidden"
@ -43,12 +39,19 @@ defmodule AshHqWeb.AppViewLive do
</a> </a>
</div> </div>
<div class="flex flex-row align-middle items-center space-x-2"> <div class="flex flex-row align-middle items-center space-x-2">
<a href="/docs/guides/ash/main/Getting-Started" class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600">Get Started</a> <a
href="/docs/guides/ash/main/Getting-Started"
class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600"
>Get Started</a>
<div>|</div> <div>|</div>
<a href="/docs" class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600">Docs</a> <a href="/docs" class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600">Docs</a>
<div>|</div> <div>|</div>
<a href="https://github.com/ash-project"> <a href="https://github.com/ash-project">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 dark:fill-gray-400 dark:hover:fill-gray-200 hover:fill-gray-600" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg> <svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6 dark:fill-gray-400 dark:hover:fill-gray-200 hover:fill-gray-600"
viewBox="0 0 24 24"
><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /></svg>
</a> </a>
<button phx-click="toggle_theme"> <button phx-click="toggle_theme">
{#case @configured_theme} {#case @configured_theme}
@ -64,7 +67,13 @@ defmodule AshHqWeb.AppViewLive do
{#match :home} {#match :home}
<Home id="home" /> <Home id="home" />
{#match :docs_dsl} {#match :docs_dsl}
<Docs id="docs" params={@params} change_versions="change-versions" selected_versions={@selected_versions} libraries={@libraries} /> <Docs
id="docs"
params={@params}
change_versions="change-versions"
selected_versions={@selected_versions}
libraries={@libraries}
/>
{/case} {/case}
</div> </div>
</div> </div>
@ -189,10 +198,9 @@ defmodule AshHqWeb.AppViewLive do
js js
|> JS.dispatch("js:noscroll-main", to: "#search-box") |> JS.dispatch("js:noscroll-main", to: "#search-box")
|> JS.toggle( |> JS.toggle(
in: "fade-in duration-100", in: "fade-in transition",
out: "fade-out duration-100", out: "fade-out transition",
to: "#search-box", to: "#search-box"
time: 100
) )
|> JS.dispatch("js:focus", to: "#search-input") |> JS.dispatch("js:focus", to: "#search-input")
end end
@ -201,9 +209,8 @@ defmodule AshHqWeb.AppViewLive do
js js
|> JS.dispatch("js:noscroll-main", to: "#search-box") |> JS.dispatch("js:noscroll-main", to: "#search-box")
|> JS.hide( |> JS.hide(
transition: "fade-out duration-100", transition: "fade-out",
to: "#search-box", to: "#search-box"
time: 100
) )
|> JS.dispatch("js:focus", to: "#search-input") |> JS.dispatch("js:focus", to: "#search-input")
end end

View file

@ -42,8 +42,15 @@ defmodule AshHq.MixProject do
{:ecto, git: "https://github.com/elixir-ecto/ecto.git", override: true}, {:ecto, git: "https://github.com/elixir-ecto/ecto.git", override: true},
{:surface, "~> 0.7.3"}, {:surface, "~> 0.7.3"},
{:surface_heroicons, "~> 0.6.0"}, {:surface_heroicons, "~> 0.6.0"},
# Syntax Highlighting
{:makeup, "~> 1.1"}, {:makeup, "~> 1.1"},
{:makeup_elixir, "~> 0.16.0"}, {:makeup_elixir, "~> 0.16.0"},
{:makeup_graphql, "~> 0.1.2"},
{:makeup_erlang, "~> 0.1.1"},
{:makeup_eex, "~> 0.1.1"},
{:makeup_js, "~> 0.1.0"},
{:makeup_sql, "~> 0.1.0"},
# Phoenix/Core dependencies
{:phoenix, "~> 1.6.6"}, {:phoenix, "~> 1.6.6"},
{:phoenix_ecto, "~> 4.4"}, {:phoenix_ecto, "~> 4.4"},
{:ecto_sql, "~> 3.6"}, {:ecto_sql, "~> 3.6"},

View file

@ -30,7 +30,13 @@
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"makeup_eex": {:hex, :makeup_eex, "0.1.1", "89352d5da318d97ae27bbcc87201f274504d2b71ede58ca366af6a5fbed9508d", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.16", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_html, "~> 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d111a0994eaaab09ef1a4b3b313ef806513bb4652152c26c0d7ca2be8402a964"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"makeup_graphql": {:hex, :makeup_graphql, "0.1.2", "81e2939aab6d2b81d39ee5d9e13fae02599e9ca6e1152e0eeed737a98a5f96aa", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "3390ab04ba388d52a94bbe64ef62aa4d7923ceaffac43ec948f58f631440e8fb"},
"makeup_html": {:hex, :makeup_html, "0.1.0", "b0228fda985e311d8f0d25bed58f8280826633a38d7448cabdd723e116165bcf", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "0ca44e7dcb8d933e010740324470dd8ec947243b51304bd34b8165ef3281edc2"},
"makeup_js": {:hex, :makeup_js, "0.1.0", "ffa8ce9db95d14dcd09045334539d5992d540d63598c592d4805b7674bdd6675", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "3f0c1a5eb52c9737b1679c926574e83bb260ccdedf08b58ee96cca7c685dea75"},
"makeup_sql": {:hex, :makeup_sql, "0.1.0", "197a8a0a38e83885f73767530739bb8f990aecf7fd1597d3141608c14f5f233e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "556e23ff88ad2fb8c44e393467cfba0c4f980cbe90316deaf48a1362f58cd118"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"}, "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},

View file

@ -5,7 +5,8 @@ defmodule AshHq.Repo.Migrations.AddTsvectorIndices do
guides: {:name, :text}, guides: {:name, :text},
library_versions: {:version, :doc}, library_versions: {:version, :doc},
options: {:name, :doc}, options: {:name, :doc},
dsls: {:name, :doc} dsls: {:name, :doc},
extensions: {:name, :doc}
} }
def change do def change do

View file

@ -0,0 +1,23 @@
defmodule AshHq.Repo.Migrations.MigrateResources9 do
@moduledoc """
Updates resources based on their most recent snapshots.
This file was autogenerated with `mix ash_postgres.generate_migrations`
"""
use Ecto.Migration
def up do
alter table(:extensions) do
modify :doc, :text, default: ""
add :doc_html, :text
end
end
def down do
alter table(:extensions) do
remove :doc_html
modify :doc, :text, default: nil
end
end
end

View file

@ -0,0 +1,130 @@
{
"attributes": [
{
"allow_nil?": false,
"default": "fragment(\"uuid_generate_v4()\")",
"generated?": false,
"primary_key?": true,
"references": null,
"size": null,
"source": "id",
"type": "uuid"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "name",
"type": "text"
},
{
"allow_nil?": true,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "target",
"type": "text"
},
{
"allow_nil?": true,
"default": "false",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "default_for_target",
"type": "boolean"
},
{
"allow_nil?": false,
"default": "\"\"",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "doc",
"type": "text"
},
{
"allow_nil?": true,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "doc_html",
"type": "text"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "type",
"type": "text"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "order",
"type": "bigint"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": {
"destination_field": "id",
"destination_field_default": null,
"destination_field_generated": null,
"multitenancy": {
"attribute": null,
"global": null,
"strategy": null
},
"name": "extensions_library_version_id_fkey",
"on_delete": null,
"on_update": null,
"table": "library_versions"
},
"size": null,
"source": "library_version_id",
"type": "uuid"
}
],
"base_filter": null,
"check_constraints": [],
"custom_indexes": [],
"has_create_action": true,
"hash": "322D1B960153C08465157BE952943969D68A7D05D823B1CA076473CC2FF47772",
"identities": [
{
"base_filter": null,
"index_name": "extensions_unique_name_by_library_version_index",
"keys": [
"library_version_id",
"name"
],
"name": "unique_name_by_library_version"
}
],
"multitenancy": {
"attribute": null,
"global": null,
"strategy": null
},
"repo": "Elixir.AshHq.Repo",
"table": "extensions"
}