{
  "name": "ThemeSwitcher",
  "category": "Utility",
  "subcategory": null,
  "description": "Color-scheme picker that writes to ThemeService.",
  "thumbnail": "/preview-cards/theme-switcher.png",
  "hasDocsPage": true,
  "nugetPackage": "Lumeo",
  "files": [
    "UI/ThemeSwitcher/ThemeSwitcher.razor"
  ],
  "dependencies": [],
  "packageDependencies": [
    "Blazicons.Lucide"
  ],
  "cssVars": [
    "--color-background",
    "--color-border",
    "--color-foreground",
    "--color-muted",
    "--color-muted-foreground",
    "--color-primary",
    "--radius"
  ],
  "api": {
    "name": "ThemeSwitcher",
    "category": "Utility",
    "subcategory": null,
    "description": "Color-scheme picker that writes to ThemeService.",
    "nugetPackage": "Lumeo",
    "files": [
      "UI/ThemeSwitcher/ThemeSwitcher.razor"
    ],
    "namespace": "Lumeo",
    "inheritsFrom": null,
    "implements": [
      "IDisposable"
    ],
    "parameters": [
      {
        "name": "Class",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AdditionalAttributes",
        "type": "Dictionary<string, object>?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": true
      }
    ],
    "events": [],
    "enums": [],
    "records": [],
    "cssVars": [
      "--color-background",
      "--color-border",
      "--color-foreground",
      "--color-muted",
      "--color-muted-foreground",
      "--color-primary",
      "--radius"
    ],
    "examples": [
      {
        "title": "Default",
        "code": "<ThemeSwitcher />"
      },
      {
        "title": "In a Card",
        "code": "<Card>\n    <CardHeader>\n        <Heading Level=\"3\">Appearance</Heading>\n        <Lumeo.Text Size=\"sm\" Color=\"muted\">Customize the look and feel.</Lumeo.Text>\n    </CardHeader>\n    <CardContent>\n        <ThemeSwitcher />\n    </CardContent>\n</Card>"
      },
      {
        "title": "Settings Row",
        "code": "<Stack Gap=\"1\" Class=\"rounded-lg border bg-card p-1\">\n    <Flex Align=\"center\" Justify=\"between\" Class=\"rounded-md px-3 py-2\">\n        <Stack Gap=\"0\">\n            <Lumeo.Text Size=\"sm\" Weight=\"medium\">Appearance</Lumeo.Text>\n            <Lumeo.Text Size=\"xs\" Color=\"muted\">Choose your color scheme and mode</Lumeo.Text>\n        </Stack>\n    </Flex>\n    <Separator />\n    <Stack Class=\"px-3 py-3\">\n        <ThemeSwitcher />\n    </Stack>\n</Stack>"
      }
    ],
    "subComponents": {},
    "parseFailed": false,
    "parseError": null
  },
  "$schema": "https://lumeo.nativ.sh/registry-component-schema.json",
  "key": "theme-switcher",
  "docsUrl": "https://lumeo.nativ.sh/components/theme-switcher",
  "sourceUrl": [
    {
      "file": "UI/ThemeSwitcher/ThemeSwitcher.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/ThemeSwitcher/ThemeSwitcher.razor"
    }
  ],
  "source": [
    {
      "path": "UI/ThemeSwitcher/ThemeSwitcher.razor",
      "content": "@namespace Lumeo\n@using Lumeo.Services\n@using Blazicons\n@implements IDisposable\n@inject ThemeService Theme\n\n<div class=\"@CssClass\" @attributes=\"AdditionalAttributes\">\n    <!-- Color scheme swatches -->\n    <div>\n        <p class=\"mb-2 text-xs font-medium text-muted-foreground\">Color</p>\n        <div class=\"flex flex-wrap gap-2\">\n            @foreach (var scheme in ThemeService.AvailableSchemes)\n            {\n                <button class=\"@GetSwatchClass(scheme.Id)\"\n                        style=\"background-color: @scheme.PreviewColor;\"\n                        title=\"@scheme.DisplayName\"\n                        @onclick=\"() => SetScheme(scheme.Id)\">\n                    @if (scheme.Id == _currentScheme)\n                    {\n                        <Blazicon Svg=\"Lucide.Check\" class=\"h-3 w-3 text-white\" />\n                    }\n                </button>\n            }\n        </div>\n    </div>\n\n    <!-- Mode toggle -->\n    <div>\n        <p class=\"mb-2 text-xs font-medium text-muted-foreground\">Mode</p>\n        <div class=\"inline-flex items-center gap-1 rounded-lg border border-border/50 bg-muted p-1\">\n            <button class=\"@GetModeButtonClass(ThemeMode.Light)\"\n                    title=\"Light\"\n                    @onclick=\"() => SetMode(ThemeMode.Light)\">\n                <Blazicon Svg=\"Lucide.Sun\" class=\"h-3.5 w-3.5\" />\n            </button>\n            <button class=\"@GetModeButtonClass(ThemeMode.Dark)\"\n                    title=\"Dark\"\n                    @onclick=\"() => SetMode(ThemeMode.Dark)\">\n                <Blazicon Svg=\"Lucide.Moon\" class=\"h-3.5 w-3.5\" />\n            </button>\n            <button class=\"@GetModeButtonClass(ThemeMode.System)\"\n                    title=\"System\"\n                    @onclick=\"() => SetMode(ThemeMode.System)\">\n                <Blazicon Svg=\"Lucide.Monitor\" class=\"h-3.5 w-3.5\" />\n            </button>\n        </div>\n    </div>\n</div>\n\n@code {\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    // Bug F — these are overwritten in OnInitializedAsync; the field initializers are intentionally\n    // neutral placeholders. OnInitializedAsync reads the real values from ThemeService before the\n    // first render, so the UI is correct from the very first paint (no stale-default flash).\n    private string _currentScheme = \"zinc\";\n    private ThemeMode _currentMode = ThemeMode.System;\n\n    private string CssClass => $\"space-y-4 {Class}\".Trim();\n\n    protected override async Task OnInitializedAsync()\n    {\n        // Read scheme and mode synchronously from ThemeService before first render.\n        // ThemeService.CurrentScheme / CurrentMode are populated during DI startup\n        // or by a prior InitializeAsync call; reading them here avoids a stale first paint.\n        _currentScheme = Theme.CurrentScheme;\n        _currentMode = Theme.CurrentMode;\n        Theme.OnThemeChanged += OnThemeChanged;\n        await base.OnInitializedAsync();\n    }\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (firstRender)\n        {\n            // JS interop must run after render; re-sync in case the JS-side state\n            // differs from the server-side defaults (e.g. persisted user preference).\n            await Theme.InitializeAsync();\n            _currentScheme = Theme.CurrentScheme;\n            _currentMode = Theme.CurrentMode;\n            StateHasChanged();\n        }\n    }\n\n    private async Task SetScheme(string scheme)\n    {\n        _currentScheme = scheme;\n        await Theme.SetSchemeAsync(scheme);\n    }\n\n    private async Task SetMode(ThemeMode mode)\n    {\n        _currentMode = mode;\n        await Theme.SetModeAsync(mode);\n    }\n\n    private void OnThemeChanged()\n    {\n        _currentScheme = Theme.CurrentScheme;\n        _currentMode = Theme.CurrentMode;\n        InvokeAsync(StateHasChanged);\n    }\n\n    private string GetSwatchClass(string schemeId)\n    {\n        var baseClass = \"flex h-8 w-8 items-center justify-center rounded-full border border-primary transition-all\";\n        return schemeId == _currentScheme\n            ? $\"{baseClass} border-foreground scale-110\"\n            : $\"{baseClass} border-transparent hover:scale-105\";\n    }\n\n    private string GetModeButtonClass(ThemeMode mode)\n    {\n        var baseClass = \"inline-flex items-center justify-center rounded-md px-2.5 py-1.5 text-sm transition-colors\";\n        return mode == _currentMode\n            ? $\"{baseClass} bg-background text-foreground shadow-sm\"\n            : $\"{baseClass} text-muted-foreground hover:text-foreground\";\n    }\n\n    public void Dispose()\n    {\n        Theme.OnThemeChanged -= OnThemeChanged;\n    }\n}\n"
    }
  ],
  "slots": [],
  "serviceDependencies": [
    {
      "service": "ThemeService",
      "namespace": ""
    }
  ],
  "cascadingDependencies": [],
  "relatedComponents": [],
  "keyboardInteractions": [],
  "tests": [
    "tests/Lumeo.Tests/Components/ThemeSwitcher/ThemeSwitcherTests.cs"
  ],
  "mdSummary": "# ThemeSwitcher\n\nColor-scheme picker that writes to ThemeService.\n\n**Package:** `Lumeo` · **Category:** Utility\n**Docs:** https://lumeo.nativ.sh/components/theme-switcher\n\n## Parameters\n| Owner | Name | Type | Default | Description |\n|---|---|---|---|---|\n| ThemeSwitcher | Class | `string?` | `` |  |\n| ThemeSwitcher | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n\n## Slots\n- (none)\n\n## Events\n- (none)\n\n## Sub-components\n- (none)\n\n## Cascading values it expects\n- (none)\n\n## Services it injects\n- `ThemeService` ()\n\n## Keyboard\n—\n\n## Example\n```razor\n<ThemeSwitcher />\n```\n\n## CSS variables\n`--color-background`, `--color-border`, `--color-foreground`, `--color-muted`, `--color-muted-foreground`, `--color-primary`, `--radius`\n\n## Files\n- `UI/ThemeSwitcher/ThemeSwitcher.razor`\n"
}