-module(glaze@basecoat@theme). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/glaze/basecoat/theme.gleam"). -export([from_list/1, default_theme/0, dark_theme/0, to_list/1, get/2, set/3, set_many/2, tailwind_bridge_style_tag/0, style_tag/1, style_tag_light_dark/2]). -export_type([token/0, theme/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( " Theme tokens and \\ generation for Basecoat UI.\n" "\n" " Basecoat uses shadcn/ui compatible CSS variables for theming.\n" " This module provides typed tokens and helpers to generate theme styles.\n" "\n" " ### Example\n" "\n" " ```gleam\n" " import glaze/basecoat\n" " import glaze/basecoat/theme\n" "\n" " let my_theme =\n" " theme.default_theme()\n" " |> theme.set(theme.Primary, \"oklch(0.205 0 0)\")\n" " |> theme.set(theme.Radius, \"0.5rem\")\n" "\n" " html.head([], [\n" " basecoat.register(basecoat.version),\n" " theme.style_tag(my_theme),\n" " ])\n" " ```\n" "\n" " ## Theming\n" "\n" " You can use any shadcn/ui theme. Visit [ui.shadcn.com/themes](https://ui.shadcn.com/themes)\n" " to browse available themes and copy their CSS variables.\n" "\n" ). -type token() :: background | foreground | card | card_foreground | popover | popover_foreground | primary | primary_foreground | secondary | secondary_foreground | muted | muted_foreground | accent | accent_foreground | destructive | destructive_foreground | border | input | ring | radius | chart1 | chart2 | chart3 | chart4 | chart5 | sidebar | sidebar_foreground | sidebar_primary | sidebar_primary_foreground | sidebar_accent | sidebar_accent_foreground | sidebar_border | sidebar_ring. -opaque theme() :: {theme, gleam@dict:dict(token(), binary())}. -file("src/glaze/basecoat/theme.gleam", 183). ?DOC( " Construct a `Theme` from a list of token-value pairs.\n" "\n" " If the same token appears multiple times, the last value overrides previous ones.\n" "\n" " ### Example\n" "\n" " ```gleam\n" " let t = theme.from_list([\n" " #(theme.Primary, \"oklch(0.205 0 0)\"),\n" " #(theme.PrimaryForeground, \"oklch(0.985 0 0)\"),\n" " ])\n" " ```\n" ). -spec from_list(list({token(), binary()})) -> theme(). from_list(Tokens) -> Values = gleam@list:fold( Tokens, maps:new(), fun(Acc, Cur) -> {Token, Value} = Cur, gleam@dict:insert(Acc, Token, Value) end ), {theme, Values}. -file("src/glaze/basecoat/theme.gleam", 88). ?DOC( " Returns Basecoat's default theme (shadcn/ui default theme).\n" "\n" " This includes the default color palette and border radius.\n" " Start with this and customize as needed.\n" ). -spec default_theme() -> theme(). default_theme() -> _pipe = [{background, <<"oklch(1 0 0)"/utf8>>}, {foreground, <<"oklch(0.145 0 0)"/utf8>>}, {card, <<"oklch(1 0 0)"/utf8>>}, {card_foreground, <<"oklch(0.145 0 0)"/utf8>>}, {popover, <<"oklch(1 0 0)"/utf8>>}, {popover_foreground, <<"oklch(0.145 0 0)"/utf8>>}, {primary, <<"oklch(0.205 0 0)"/utf8>>}, {primary_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {secondary, <<"oklch(0.97 0 0)"/utf8>>}, {secondary_foreground, <<"oklch(0.205 0 0)"/utf8>>}, {muted, <<"oklch(0.97 0 0)"/utf8>>}, {muted_foreground, <<"oklch(0.556 0 0)"/utf8>>}, {accent, <<"oklch(0.97 0 0)"/utf8>>}, {accent_foreground, <<"oklch(0.205 0 0)"/utf8>>}, {destructive, <<"oklch(0.577 0.245 27.325)"/utf8>>}, {destructive_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {border, <<"oklch(0.922 0 0)"/utf8>>}, {input, <<"oklch(0.922 0 0)"/utf8>>}, {ring, <<"oklch(0.708 0 0)"/utf8>>}, {radius, <<"0.5rem"/utf8>>}, {chart1, <<"oklch(0.646 0.222 41.116)"/utf8>>}, {chart2, <<"oklch(0.6 0.118 184.704)"/utf8>>}, {chart3, <<"oklch(0.398 0.07 227.392)"/utf8>>}, {chart4, <<"oklch(0.828 0.189 84.429)"/utf8>>}, {chart5, <<"oklch(0.769 0.188 70.08)"/utf8>>}, {sidebar, <<"oklch(0.985 0 0)"/utf8>>}, {sidebar_foreground, <<"oklch(0.145 0 0)"/utf8>>}, {sidebar_primary, <<"oklch(0.205 0 0)"/utf8>>}, {sidebar_primary_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {sidebar_accent, <<"oklch(0.97 0 0)"/utf8>>}, {sidebar_accent_foreground, <<"oklch(0.205 0 0)"/utf8>>}, {sidebar_border, <<"oklch(0.922 0 0)"/utf8>>}, {sidebar_ring, <<"oklch(0.708 0 0)"/utf8>>}], from_list(_pipe). -file("src/glaze/basecoat/theme.gleam", 131). ?DOC( " Returns the dark theme variant.\n" "\n" " Use this for dark mode or combine with `default_theme()` using `light-dark()`.\n" ). -spec dark_theme() -> theme(). dark_theme() -> _pipe = [{background, <<"oklch(0.145 0 0)"/utf8>>}, {foreground, <<"oklch(0.985 0 0)"/utf8>>}, {card, <<"oklch(0.205 0 0)"/utf8>>}, {card_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {popover, <<"oklch(0.269 0 0)"/utf8>>}, {popover_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {primary, <<"oklch(0.922 0 0)"/utf8>>}, {primary_foreground, <<"oklch(0.205 0 0)"/utf8>>}, {secondary, <<"oklch(0.269 0 0)"/utf8>>}, {secondary_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {muted, <<"oklch(0.269 0 0)"/utf8>>}, {muted_foreground, <<"oklch(0.708 0 0)"/utf8>>}, {accent, <<"oklch(0.371 0 0)"/utf8>>}, {accent_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {destructive, <<"oklch(0.704 0.191 22.216)"/utf8>>}, {destructive_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {border, <<"oklch(1 0 0 / 10%)"/utf8>>}, {input, <<"oklch(1 0 0 / 15%)"/utf8>>}, {ring, <<"oklch(0.556 0 0)"/utf8>>}, {radius, <<"0.5rem"/utf8>>}, {chart1, <<"oklch(0.488 0.243 264.376)"/utf8>>}, {chart2, <<"oklch(0.696 0.17 162.48)"/utf8>>}, {chart3, <<"oklch(0.769 0.188 70.08)"/utf8>>}, {chart4, <<"oklch(0.627 0.265 303.9)"/utf8>>}, {chart5, <<"oklch(0.645 0.246 16.439)"/utf8>>}, {sidebar, <<"oklch(0.205 0 0)"/utf8>>}, {sidebar_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {sidebar_primary, <<"oklch(0.488 0.243 264.376)"/utf8>>}, {sidebar_primary_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {sidebar_accent, <<"oklch(0.269 0 0)"/utf8>>}, {sidebar_accent_foreground, <<"oklch(0.985 0 0)"/utf8>>}, {sidebar_border, <<"oklch(1 0 0 / 10%)"/utf8>>}, {sidebar_ring, <<"oklch(0.439 0 0)"/utf8>>}], from_list(_pipe). -file("src/glaze/basecoat/theme.gleam", 194). ?DOC(" Convert a `Theme` into token-value pairs.\n"). -spec to_list(theme()) -> list({token(), binary()}). to_list(Theme) -> {theme, Values} = Theme, maps:to_list(Values). -file("src/glaze/basecoat/theme.gleam", 201). ?DOC(" Get a token value from a theme.\n"). -spec get(theme(), token()) -> binary(). get(Theme, Token) -> {theme, Values} = Theme, case gleam_stdlib:map_get(Values, Token) of {ok, Value} -> Value; {error, _} -> <<""/utf8>> end. -file("src/glaze/basecoat/theme.gleam", 211). ?DOC(" Set a token value in a theme.\n"). -spec set(theme(), token(), binary()) -> theme(). set(Theme, Token, Value) -> {theme, Values} = Theme, {theme, gleam@dict:insert(Values, Token, Value)}. -file("src/glaze/basecoat/theme.gleam", 218). ?DOC(" Set multiple token values in a theme.\n"). -spec set_many(theme(), list({token(), binary()})) -> theme(). set_many(Theme, Updates) -> gleam@list:fold( Updates, Theme, fun(Acc, Cur) -> {Token, Value} = Cur, set(Acc, Token, Value) end ). -file("src/glaze/basecoat/theme.gleam", 257). ?DOC( " Render a `