-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 ``. 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 `.(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).