defmodule SimpleshopTheme.Theme.Presets do @moduledoc """ Defines the 9 curated theme presets for SimpleShop. """ @presets %{ gallery: %{ mood: "warm", typography: "editorial", shape: "soft", density: "spacious", grid_columns: "3", header_layout: "centered", accent_color: "#e85d04" }, studio: %{ mood: "neutral", typography: "clean", shape: "soft", density: "balanced", grid_columns: "4", header_layout: "standard", accent_color: "#3b82f6" }, boutique: %{ mood: "warm", typography: "classic", shape: "soft", density: "balanced", grid_columns: "3", header_layout: "centered", accent_color: "#b45309" }, bold: %{ mood: "neutral", typography: "modern", shape: "sharp", density: "compact", grid_columns: "4", header_layout: "standard", accent_color: "#dc2626" }, playful: %{ mood: "neutral", typography: "friendly", shape: "pill", density: "balanced", grid_columns: "4", header_layout: "standard", accent_color: "#8b5cf6" }, minimal: %{ mood: "cool", typography: "minimal", shape: "sharp", density: "spacious", grid_columns: "2", header_layout: "minimal", accent_color: "#171717" }, night: %{ mood: "dark", typography: "modern", shape: "soft", density: "balanced", grid_columns: "4", header_layout: "standard", accent_color: "#f97316" }, classic: %{ mood: "warm", typography: "classic", shape: "soft", density: "spacious", grid_columns: "3", header_layout: "standard", accent_color: "#166534" }, impulse: %{ mood: "neutral", typography: "impulse", shape: "sharp", density: "spacious", grid_columns: "3", header_layout: "centered", accent_color: "#000000", font_size: "medium", heading_weight: "regular", layout_width: "full", button_style: "filled", card_shadow: "none", product_text_align: "center" } } @descriptions %{ gallery: "Elegant & editorial", studio: "Clean & professional", boutique: "Warm & sophisticated", bold: "High contrast, strong", playful: "Fun & approachable", minimal: "Understated & modern", night: "Dark & dramatic", classic: "Traditional & refined", impulse: "Light & airy" } # Core keys used to match presets (excludes branding-specific settings) @core_keys ~w(mood typography shape density grid_columns header_layout accent_color)a @doc """ Returns all available presets. ## Examples iex> all() %{gallery: %{...}, studio: %{...}, ...} """ def all, do: @presets @doc """ Gets a preset by name. ## Examples iex> get(:gallery) %{mood: "warm", typography: "editorial", ...} iex> get(:nonexistent) nil """ def get(preset_name) when is_atom(preset_name) do Map.get(@presets, preset_name) end @doc """ Lists all preset names. ## Examples iex> list_names() [:gallery, :studio, :boutique, :bold, :playful, :minimal, :night, :classic, :impulse] """ def list_names do Map.keys(@presets) end @doc """ Gets the description for a preset. ## Examples iex> get_description(:gallery) "Elegant & editorial" """ def get_description(preset_name) when is_atom(preset_name) do Map.get(@descriptions, preset_name, "") end @doc """ Returns all presets with their descriptions. ## Examples iex> all_with_descriptions() [{:bold, "High contrast, strong"}, ...] """ def all_with_descriptions do @presets |> Map.keys() |> Enum.sort() |> Enum.map(fn name -> {name, Map.get(@descriptions, name, "")} end) end @doc """ Detects which preset matches the current theme settings, if any. Only compares core theme keys, ignoring branding-specific settings. ## Examples iex> detect_preset(%ThemeSettings{mood: "warm", typography: "editorial", ...}) :gallery iex> detect_preset(%ThemeSettings{...customized...}) nil """ def detect_preset(theme_settings) do current_core = extract_core_values(theme_settings) Enum.find_value(@presets, fn {name, preset} -> preset_core = Map.take(preset, @core_keys) if maps_match?(current_core, preset_core) do name else nil end end) end defp extract_core_values(theme_settings) do theme_settings |> Map.from_struct() |> Map.take(@core_keys) end defp maps_match?(map1, map2) do Enum.all?(@core_keys, fn key -> Map.get(map1, key) == Map.get(map2, key) end) end end