-module(gg_icon@icon).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gg_icon/icon.gleam").
-export([size/1, svg/4, fallback_box/1, placeholder/3]).
-export_type([size/0]).
-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(
" gg_icon — the set-agnostic icon interface every `gg_icons_*` package builds\n"
" on. It holds the size scale, the shared `svg` wrapper (generic over `viewBox`\n"
" + per-variant defaults, so it serves stroke *and* fill variants), and the\n"
" authoring `placeholder`. It never imports a concrete icon set and ships no\n"
" Tailwind — keeping it a lean, dual-target foundation.\n"
"\n"
" See `dev-docs/icons.md` in the gg_ui repo for the full design.\n"
).
-type size() :: sm | md | lg.
-file("src/gg_icon/icon.gleam", 33).
-spec size_class(size()) -> binary().
size_class(Size) ->
case Size of
sm ->
<<"cn-icon-size-sm"/utf8>>;
md ->
<<"cn-icon-size-md"/utf8>>;
lg ->
<<"cn-icon-size-lg"/utf8>>
end.
-file("src/gg_icon/icon.gleam", 29).
?DOC(
" A class attribute selecting a named size. Pass it in an icon's `attrs`:\n"
" `lucide.star([icon.size(icon.Lg)])`. For a one-off, pass a raw\n"
" `attribute.class(\"size-[18px]\")` instead — it wins by source order.\n"
).
-spec size(size()) -> lustre@vdom@vattr:attribute(any()).
size(Size) ->
lustre@attribute:class(size_class(Size)).
-file("src/gg_icon/icon.gleam", 49).
?DOC(
" Build an icon `<svg>`. Generated icon functions call this with their\n"
" variant's `view_box` + `defaults` (e.g. `fill=none stroke=currentColor` for\n"
" an outline variant, `fill=currentColor` for a filled one). `attrs` is\n"
" appended **last** so caller overrides win by source order. Everything stays\n"
" `currentColor`, so `color` / `text-*` drive the colour and `size` /\n"
" `size-*` drive the size.\n"
).
-spec svg(
binary(),
list({binary(), binary()}),
list(lustre@vdom@vattr:attribute(PBL)),
list(lustre@vdom@vnode:element(PBL))
) -> lustre@vdom@vnode:element(PBL).
svg(View_box, Defaults, Attrs, Children) ->
lustre@element@svg:svg(
lists:append(
[[lustre@attribute:class(<<"cn-icon"/utf8>>),
lustre@attribute:attribute(<<"viewBox"/utf8>>, View_box),
lustre@attribute:attribute(
<<"data-slot"/utf8>>,
<<"icon"/utf8>>
),
lustre@attribute:attribute(
<<"aria-hidden"/utf8>>,
<<"true"/utf8>>
)],
gleam@list:map(
Defaults,
fun(D) ->
lustre@attribute:attribute(
erlang:element(1, D),
erlang:element(2, D)
)
end
),
Attrs]
),
Children
).
-file("src/gg_icon/icon.gleam", 90).
?DOC(
" A neutral rounded square — the placeholder's no-resolver fallback, and a\n"
" visible \"icon would go here\" marker in un-transformed previews.\n"
).
-spec fallback_box(list(lustre@vdom@vattr:attribute(PBV))) -> lustre@vdom@vnode:element(PBV).
fallback_box(Attrs) ->
svg(
<<"0 0 24 24"/utf8>>,
[{<<"fill"/utf8>>, <<"none"/utf8>>},
{<<"stroke"/utf8>>, <<"currentColor"/utf8>>},
{<<"stroke-width"/utf8>>, <<"2"/utf8>>},
{<<"stroke-linecap"/utf8>>, <<"round"/utf8>>},
{<<"stroke-linejoin"/utf8>>, <<"round"/utf8>>}],
Attrs,
[lustre@element@svg:path(
[lustre@attribute:attribute(
<<"d"/utf8>>,
<<"M4 4h16v16H4z"/utf8>>
)]
)]
).
-file("src/gg_icon/icon.gleam", 80).
?DOC(
" Authoring placeholder used in registry source. The (future) CLI transformer\n"
" replaces each call with a direct `<shard>.<icon>(attrs)` for the user's\n"
" chosen set/variant, so this never reaches a shipped bundle. Until then — and\n"
" in any non-transformed runtime — it renders a neutral fallback box.\n"
"\n"
" Storybook's live preview will inject a resolver here so embedded icons\n"
" (a dialog-close `x`) switch with the toolbar; that wiring lands with the\n"
" `apps/storybook` demo catalog and keeps `gg_icon` set-agnostic.\n"
).
-spec placeholder(binary(), binary(), list(lustre@vdom@vattr:attribute(PBR))) -> lustre@vdom@vnode:element(PBR).
placeholder(_, _, Attrs) ->
fallback_box(Attrs).