MishkaCmsCore. Runtime. PageBuilder. IconLibrary behaviour
(Mishka CMS Core v0.0.1)
Copy Markdown
View Source
What an icon set has to answer so the inspector can offer it.
Why a behaviour rather than one hardcoded set
An icon attribute's value is a class name — hero-check, and tomorrow lucide-check or
tabler-check. The class already carries its own namespace, so several sets can coexist in one
document without colliding; what was missing was anywhere for the editor to learn about the second
one. MishkaCmsCore.Runtime.PageBuilder.Icons is now a facade over every registered set, and
MishkaCmsCore.Runtime.PageBuilder.Icons.Heroicons is simply the first.
Registering one
config :mishka_cms_core, :icon_libraries, [
MishkaCmsCore.Runtime.PageBuilder.Icons.Heroicons,
MyApp.Icons.Lucide
]The list is read at runtime, but each library's own catalogue must be built at COMPILE time. That
is not a style preference: deps/ is a build artefact that a release does not ship, while the
class names a release renders are baked into its CSS. A library that walks deps/ at runtime works
in dev and returns an empty picker in production.
What a library owes the editor
Two things the panel cannot do for itself. svg/2 draws the glyph in the picker — the picker
cannot render <span class="hero-check"> and hope, because that class comes from a Tailwind plugin
that runs over the SITE's pages and the admin chrome has no reason to carry it. And css/1 emits
the rule for a class the canvas is about to render, for the same reason: a component's default
icon appears in no page's HTML, so the site stylesheet never learned it.
Prefixes
The facade routes by LONGEST matching prefix, so two libraries claiming hero- and hero-solid-
resolve unambiguously — the more specific one wins. Use the prefix the set's own Tailwind plugin
emits.
Summary
Callbacks
Every class this set ships, sorted.
How many match, uncapped — the picker's counter cannot be derived from a capped list.
CSS rules for these classes, mirroring what the set's own Tailwind plugin emits.
What to call the set in the picker when more than one is installed — "Heroicons".
The class-name prefixes this library owns — ["hero-"].
The classes matching a query in one variant, capped by :limit.
One icon as inline SVG at size pixels, or nil when this set does not ship it.
The weight variants, as {suffix, label} — {"", "Outline"}, {"-solid", "Solid"}.
Callbacks
@callback all() :: [String.t()]
Every class this set ships, sorted.
@callback count(String.t() | nil, String.t()) :: non_neg_integer()
How many match, uncapped — the picker's counter cannot be derived from a capped list.
CSS rules for these classes, mirroring what the set's own Tailwind plugin emits.
Bare rules: MishkaCmsCore.Runtime.PageBuilder.Icons.css/1 puts them in the components layer.
@callback label() :: String.t()
What to call the set in the picker when more than one is installed — "Heroicons".
@callback prefixes() :: [String.t()]
The class-name prefixes this library owns — ["hero-"].
A LIST because one module may serve several sets: MishkaCmsCore.Runtime.PageBuilder.Icons.Bundled
answers for every set that arrived inside an installed kit, and there is no reason for each of those
to need a module of its own.
The classes matching a query in one variant, capped by :limit.
@callback svg(String.t(), pos_integer()) :: {:safe, iodata()} | nil
One icon as inline SVG at size pixels, or nil when this set does not ship it.
The weight variants, as {suffix, label} — {"", "Outline"}, {"-solid", "Solid"}.
A set with one weight answers [{"", "All"}].