Packages

🎨 Gleam UI lustre library by @gleam-br

Current section

Files

Jump to
gbr_ui src gbr@ui.erl
Raw

src/gbr@ui.erl

-module(gbr@ui).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src\\gbr\\ui.gleam").
-export([loader/1, primary_with_breadcrumb/4, primary/3, partial/2, horizontal/1, grid/3, box/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
"\n"
" 🎨 Gleam UI library by @gleam-br\n"
"\n"
" Loader:\n"
"\n"
" ```gleam\n"
" fn view(model: Model) -> Element(ModelEvent) {\n"
" let Model(loading:) = model\n"
"\n"
" loading\n"
" |> ui.loader()\n"
" }\n"
" ```\n"
"\n"
" Horizontal:\n"
"\n"
" ```gleam\n"
" pub fn render(in: Login) -> Element(LoginEvent) {\n"
" let Login(basic:, logo:) = in\n"
"\n"
" [basic, logo]\n"
" |> ui.horizontal()\n"
" }\n"
" ```\n"
"\n"
" Main:\n"
"\n"
" ```gleam\n"
" pub fn render(in: AdminHome) -> Element(AdminEvent) {\n"
" let AdminHome(sidebar:, header:, content:, breadcrumb:) = in\n"
"\n"
" ui.primary(header:, sidebar:, content:, breadcrumb:)\n"
" }\n"
" ```\n"
"\n"
).
-file("src\\gbr\\ui.gleam", 89).
?DOC(
" UI loader layout with ui screen full blur and a center spin loader.\n"
"\n"
" Better choice to work with [gbr_js](https://github.com/gleam-br/gbr_js) and `gbr/js/global.{dom_content_loaded}`.\n"
"\n"
" Supose on dom loaded dispatch OnLoading(False) when:\n"
" - init: Model(loading: True)\n"
" - after: Model(loading: False):\n"
"\n"
" ```gleam\n"
" fn on_dom_loaded(runtime) {\n"
" use _ <- function.tap(runtime)\n"
" use _ <- global.dom_content_loaded()\n"
"\n"
" AdminEventOnLoading(False)\n"
" |> lustre.dispatch()\n"
" |> lustre.send(runtime, _)\n"
" }\n"
"\n"
" fn view(model: Model) -> Element(ModelEvent) {\n"
" let Model(loading:) = model\n"
"\n"
" loading\n"
" |> ui.loader()\n"
" }\n"
" ```\n"
"\n"
" ### Fn desc: Trasform one `1 -> 1`\n"
"\n"
" Bool type to loader element layout\n"
"\n"
" - `True`: Render loader\n"
" - `False`: Render `lustre/element.{none}`\n"
).
-spec loader(boolean()) -> lustre@vdom@vnode:element(any()).
loader(Loading) ->
gleam@bool:guard(
not Loading,
lustre@element:none(),
fun() ->
lustre@element@html:'div'(
[lustre@attribute:class(
<<"fixed left-0 top-0 z-999999 flex h-screen w-screen items-center justify-center bg-white dark:bg-black"/utf8>>
)],
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"h-16 w-16 animate-spin rounded-full border-4 border-solid border-brand-500 border-t-transparent"/utf8>>
)],
[]
)]
)
end
).
-file("src\\gbr\\ui.gleam", 212).
?DOC(
" Same of `gbr/ui.primary` with optional breadcrumb element.\n"
"\n"
" TODO: WIP\n"
).
-spec primary_with_breadcrumb(
lustre@vdom@vnode:element(OHI),
lustre@vdom@vnode:element(OHI),
gleam@option:option(lustre@vdom@vnode:element(OHI)),
gleam@option:option(lustre@vdom@vnode:element(OHI))
) -> lustre@vdom@vnode:element(OHI).
primary_with_breadcrumb(Header, Sidebar, Content, Breadcrumb) ->
Breadcrumb@1 = gleam@option:unwrap(Breadcrumb, lustre@element:none()),
Content@1 = gleam@option:unwrap(Content, lustre@element:none()),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"flex h-screen overflow-hidden bg-gray-100 dark:bg-gray-900"/utf8>>
)],
[Sidebar,
lustre@element@html:'div'(
[lustre@attribute:class(
<<"relative flex flex-1 flex-col overflow-x-hidden overflow-y-auto"/utf8>>
)],
[Header,
lustre@element@html:main(
[],
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"mx-auto max-w-(--breakpoint-2xl) p-4 md:p-6"/utf8>>
)],
[Breadcrumb@1, Content@1]
)]
)]
)]
).
-file("src\\gbr\\ui.gleam", 156).
?DOC(
" UI primary layout with header, sidebar, breadcrumb and content.\n"
"\n"
" Excelent layout to admin home page.\n"
"\n"
" Better choise to work with [gbr_ui_router](https://github.com/gleam-br/gbr_ui_router) links in sidebar to update content element.\n"
"\n"
" Supose admin home render function:\n"
"\n"
" ```gleam\n"
" pub fn render(in: AdminHome) -> Element(AdminEvent) {\n"
" let AdminHome(sidebar:, header:, content:, breadcrumb:) = in\n"
"\n"
" ui.primary(header:, sidebar:, content:, breadcrumb:)\n"
" }\n"
" ```\n"
"\n"
" ### Fn desc: Transform three `3 -> 1`\n"
"\n"
" Three elements to one element with primary layout.\n"
).
-spec primary(
lustre@vdom@vnode:element(OGU),
lustre@vdom@vnode:element(OGU),
gleam@option:option(lustre@vdom@vnode:element(OGU))
) -> lustre@vdom@vnode:element(OGU).
primary(Header, Sidebar, Content) ->
primary_with_breadcrumb(Header, Sidebar, Content, none).
-file("src\\gbr\\ui.gleam", 129).
?DOC(
" UI layout partial with header and sidebar only.\n"
"\n"
" Better choise when you need only partial primary layout.\n"
"\n"
" ### Fn desc: Transform two `2 -> 1`\n"
"\n"
" Two elements to one element with partial primary layout ui.\n"
).
-spec partial(lustre@vdom@vnode:element(OGQ), lustre@vdom@vnode:element(OGQ)) -> lustre@vdom@vnode:element(OGQ).
partial(Header, Sidebar) ->
primary(Header, Sidebar, none).
-file("src\\gbr\\ui.gleam", 115).
?DOC(
" UI layout with horizontal inner elements.\n"
"\n"
" Better choise to work with `gbr/ui/login.{basic}`.\n"
"\n"
" Supose login render function:\n"
"\n"
" ```gleam\n"
" pub fn render(in: Login) -> Element(LoginEvent) {\n"
" let Login(basic:, logo:) = in\n"
"\n"
" [basic, logo]\n"
" |> ui.horizontal()\n"
" }\n"
" ```\n"
" ### Fn desc: Reduce `* -> 1`\n"
"\n"
" List of elements to one element with horizontal layout inner elements.\n"
).
-spec horizontal(list(lustre@vdom@vnode:element(OGN))) -> lustre@vdom@vnode:element(OGN).
horizontal(Inner) ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"relative p-6 sm:p-0"/utf8>>)],
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"relative flex flex-col justify-center w-full h-screen bg-white dark:bg-gray-900 sm:p-0 lg:flex-row"/utf8>>
)],
Inner
)]
).
-file("src\\gbr\\ui.gleam", 185).
?DOC(
" UI grid layout with left, right, inner elements.\n"
"\n"
" Excelent layout to one page message from errors, e.g. 404 or page to payment success message.\n"
"\n"
" Supose page 404 with grid img background render function:\n"
"\n"
" ```gleam\n"
" pub fn render() -> Element(Msg) {\n"
" let img = html.img([src(\"/assets/grid-01.svg\"), alt(\"Grid\")])\n"
" let inner = [\n"
" html.h1([], [html.text(\"404: Not found\")])\n"
" ]\n"
"\n"
" ui.grid(left: img, right: img, inner:)\n"
" }\n"
" ```\n"
"\n"
" ### Fn desc: Transform three `3 -> 1`\n"
"\n"
" Three elements to one element with grid layout.\n"
).
-spec grid(
list(lustre@vdom@vnode:element(OGZ)),
list(lustre@vdom@vnode:element(OGZ)),
list(lustre@vdom@vnode:element(OGZ))
) -> lustre@vdom@vnode:element(OGZ).
grid(Left, Right, Inner) ->
lustre@element@html:'div'(
[lustre@attribute:class(
<<"relative items-center hidden w-full h-full bg-brand-950 dark:bg-white/5 lg:grid lg:w-1/2"/utf8>>
)],
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"flex items-center justify-center z-1"/utf8>>
)],
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"absolute right-0 top-0 -z-1 w-full max-w-[250px] xl:max-w-[450px]"/utf8>>
)],
Left
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"absolute bottom-0 left-0 -z-1 w-full max-w-[250px] rotate-180 xl:max-w-[450px]"/utf8>>
)],
Right
) |
Inner]
)]
).
-file("src\\gbr\\ui.gleam", 245).
-spec box_inner(list(gbr@ui@core@model:u_i_box(OJW))) -> list(lustre@vdom@vnode:element(OJW)).
box_inner(In) ->
gleam@list:map(
lists:reverse(In),
fun(Box) ->
{u_i_box, Title, Content, Footer, Attrs} = Box,
lustre@element@html:'div'(
Attrs,
[lustre@element@html:h3(
[lustre@attribute:class(
<<"mb-2 font-semibold text-gray-900 dark:text-white"/utf8>>
)],
[Title]
),
lustre@element@html:p(
[lustre@attribute:class(
<<"mb-4 text-theme-sm text-gray-500 dark:text-gray-400"/utf8>>
)],
[Content]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"flex items-center justify-center rounded-lg bg-brand-500 p-3 text-theme-sm font-medium text-white hover:bg-brand-600"/utf8>>
)],
[Footer]
)]
)
end
).
-file("src\\gbr\\ui.gleam", 201).
?DOC(" UI boxes layout\n").
-spec box(
list(gbr@ui@core@model:u_i_box(OHE)),
list(lustre@vdom@vattr:attribute(OHE))
) -> lustre@vdom@vnode:element(OHE).
box(In, Attrs) ->
Attrs@1 = [lustre@attribute:class(
<<"mx-auto mb-10 w-full max-w-60 rounded-2xl bg-gray-50 px-4 py-5 text-center dark:bg-white/[0.03]"/utf8>>
) |
Attrs],
Inner = box_inner(In),
lustre@element@html:'div'(Attrs@1, Inner).