{
  "name": "PasswordInput",
  "category": "Forms",
  "subcategory": "Inputs",
  "description": "Password field with show/hide toggle and strength meter.",
  "thumbnail": "/preview-cards/password-input.png",
  "hasDocsPage": true,
  "nugetPackage": "Lumeo",
  "files": [
    "UI/PasswordInput/PasswordInput.razor"
  ],
  "dependencies": [],
  "packageDependencies": [
    "Blazicons.Lucide"
  ],
  "cssVars": [
    "--color-destructive",
    "--color-foreground",
    "--color-input",
    "--color-muted",
    "--color-muted-foreground",
    "--color-ring",
    "--radius"
  ],
  "api": {
    "name": "PasswordInput",
    "category": "Forms",
    "subcategory": "Inputs",
    "description": "Password field with show/hide toggle and strength meter.",
    "nugetPackage": "Lumeo",
    "files": [
      "UI/PasswordInput/PasswordInput.razor"
    ],
    "namespace": "Lumeo",
    "inheritsFrom": null,
    "implements": [],
    "parameters": [
      {
        "name": "FormField",
        "type": "FormField.FormFieldContext?",
        "default": null,
        "description": null,
        "isCascading": true,
        "captureUnmatched": false
      },
      {
        "name": "Value",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "ValueChanged",
        "type": "EventCallback<string?>",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Placeholder",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "ShowStrength",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "ShowToggle",
        "type": "bool",
        "default": "true",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Disabled",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Required",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Invalid",
        "type": "bool",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "ErrorText",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "HelperText",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Label",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Name",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "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": [
      {
        "name": "ValueChanged",
        "type": "EventCallback<string?>",
        "description": null
      }
    ],
    "enums": [],
    "records": [],
    "cssVars": [
      "--color-destructive",
      "--color-foreground",
      "--color-input",
      "--color-muted",
      "--color-muted-foreground",
      "--color-ring",
      "--radius"
    ],
    "examples": [
      {
        "title": "Basic Password Input",
        "code": "<PasswordInput @bind-Value=\"_password\" />"
      },
      {
        "title": "With Strength Meter",
        "code": "<PasswordInput @bind-Value=\"_password\" ShowStrength=\"true\" />"
      },
      {
        "title": "Without Toggle Button",
        "code": "<PasswordInput @bind-Value=\"_password\" ShowToggle=\"false\" />"
      },
      {
        "title": "With Strength + Custom Placeholder",
        "code": "<PasswordInput @bind-Value=\"_password\"\n               ShowStrength=\"true\"\n               Placeholder=\"Create a strong password\" />"
      }
    ],
    "subComponents": {},
    "parseFailed": false,
    "parseError": null
  },
  "$schema": "https://lumeo.nativ.sh/registry-component-schema.json",
  "key": "password-input",
  "docsUrl": "https://lumeo.nativ.sh/components/password-input",
  "sourceUrl": [
    {
      "file": "UI/PasswordInput/PasswordInput.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/PasswordInput/PasswordInput.razor"
    }
  ],
  "source": [
    {
      "path": "UI/PasswordInput/PasswordInput.razor",
      "content": "@namespace Lumeo\n@inject Lumeo.Services.Localization.ILumeoLocalizer L\n\n@if (Label is not null && !InsideFormField)\n{\n    <label class=\"block text-sm font-medium mb-1.5\">\n        @Label\n        @if (Required)\n        {\n            <span class=\"text-destructive ml-0.5\">*</span>\n        }\n    </label>\n}\n\n<div class=\"@WrapperClass\">\n    <div class=\"@($\"flex h-9 w-full rounded-md border {(EffectiveInvalid ? \"border-destructive\" : \"border-input\")} bg-transparent text-sm overflow-hidden transition-colors {(EffectiveInvalid ? \"focus-within:ring-[1.5px] focus-within:ring-destructive/20\" : \"focus-within:ring-[1.5px] focus-within:ring-ring\")}\")\">\n        <input type=\"@(_showPassword ? \"text\" : \"password\")\"\n               name=\"@Name\"\n               aria-required=\"@Required.ToString().ToLowerInvariant()\"\n               aria-invalid=\"@EffectiveInvalid.ToString().ToLowerInvariant()\"\n               class=\"flex-1 bg-transparent px-3 py-1 placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50\"\n               value=\"@Value\"\n               placeholder=\"@(Placeholder ?? L[\"Password.Placeholder\"])\"\n               disabled=\"@Disabled\"\n               @oninput=\"HandleInput\"\n               @attributes=\"AdditionalAttributes\" />\n        @if (ShowToggle)\n        {\n            <button type=\"button\"\n                    class=\"flex items-center px-3 text-muted-foreground hover:text-foreground transition-colors\"\n                    aria-label=\"@L[\"Password.Toggle\"]\"\n                    @onclick=\"ToggleVisibility\"\n                    tabindex=\"-1\">\n                @if (_showPassword)\n                {\n                    <Blazicon Svg=\"Lucide.EyeOff\" class=\"h-4 w-4\" />\n                }\n                else\n                {\n                    <Blazicon Svg=\"Lucide.Eye\" class=\"h-4 w-4\" />\n                }\n            </button>\n        }\n    </div>\n    @if (ShowStrength && !string.IsNullOrEmpty(Value))\n    {\n        <div class=\"mt-1.5 flex gap-1\">\n            @for (int i = 0; i < 4; i++)\n            {\n                var idx = i;\n                <div class=\"@GetStrengthBarClass(idx) h-1 flex-1 rounded-full transition-colors\"></div>\n            }\n        </div>\n        <p class=\"mt-1 text-xs @StrengthLabelClass\">@StrengthLabel</p>\n    }\n</div>\n\n@if (!InsideFormField)\n{\n    @if (EffectiveInvalid && !string.IsNullOrEmpty(ErrorText))\n    {\n        <p class=\"mt-1 text-xs text-destructive\">@ErrorText</p>\n    }\n    else if (!string.IsNullOrEmpty(HelperText))\n    {\n        <p class=\"mt-1 text-xs text-muted-foreground\">@HelperText</p>\n    }\n}\n\n@code {\n    [CascadingParameter] private FormField.FormFieldContext? FormField { get; set; }\n\n    [Parameter] public string? Value { get; set; }\n    [Parameter] public EventCallback<string?> ValueChanged { get; set; }\n    [Parameter] public string? Placeholder { get; set; }\n    [Parameter] public bool ShowStrength { get; set; }\n    [Parameter] public bool ShowToggle { get; set; } = true;\n    [Parameter] public bool Disabled { get; set; }\n    [Parameter] public bool Required { get; set; }\n    [Parameter] public bool Invalid { get; set; }\n    [Parameter] public string? ErrorText { get; set; }\n    [Parameter] public string? HelperText { get; set; }\n    [Parameter] public string? Label { get; set; }\n    [Parameter] public string? Name { get; set; }\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private bool _showPassword;\n\n    private bool EffectiveInvalid => Invalid || FormField?.HasError == true;\n    private bool InsideFormField => FormField is not null;\n\n    private string WrapperClass => $\"w-full {Class}\".Trim();\n\n    private void ToggleVisibility() => _showPassword = !_showPassword;\n\n    private async Task HandleInput(ChangeEventArgs e)\n    {\n        Value = e.Value?.ToString();\n        await ValueChanged.InvokeAsync(Value);\n    }\n\n    private int StrengthScore\n    {\n        get\n        {\n            if (string.IsNullOrEmpty(Value)) return 0;\n            int score = 0;\n            if (Value.Length >= 8) score++;\n            if (Value.Any(char.IsUpper)) score++;\n            if (Value.Any(char.IsLower)) score++;\n            if (Value.Any(char.IsDigit)) score++;\n            if (Value.Any(c => !char.IsLetterOrDigit(c))) score++;\n            return score;\n        }\n    }\n\n    private int StrengthLevel => StrengthScore switch\n    {\n        0 or 1 => 1,\n        2 => 2,\n        3 => 3,\n        _ => 4\n    };\n\n    private string StrengthLabel => StrengthLevel switch\n    {\n        1 => L[\"Password.Weak\"],\n        2 => L[\"Password.Fair\"],\n        3 => L[\"Password.Good\"],\n        4 => L[\"Password.Strong\"],\n        _ => \"\"\n    };\n\n    private string StrengthLabelClass => StrengthLevel switch\n    {\n        1 => \"text-destructive\",\n        2 => \"text-warning\",\n        3 => \"text-info\",\n        4 => \"text-success\",\n        _ => \"text-muted-foreground\"\n    };\n\n    private string GetStrengthBarClass(int index) =>\n        index < StrengthLevel\n            ? StrengthLevel switch\n            {\n                1 => \"bg-destructive\",\n                2 => \"bg-warning\",\n                3 => \"bg-info\",\n                4 => \"bg-success\",\n                _ => \"bg-muted\"\n            }\n            : \"bg-muted\";\n}\n"
    }
  ],
  "slots": [],
  "serviceDependencies": [
    {
      "service": "ILumeoLocalizer",
      "namespace": "Lumeo.Services.Localization"
    }
  ],
  "cascadingDependencies": [
    {
      "name": "FormField",
      "type": "FormField.FormFieldContext?",
      "required": false
    }
  ],
  "relatedComponents": [],
  "keyboardInteractions": [],
  "tests": [
    "tests/Lumeo.Tests/Components/PasswordInput/PasswordInputTests.cs"
  ],
  "mdSummary": "# PasswordInput\n\nPassword field with show/hide toggle and strength meter.\n\n**Package:** `Lumeo` · **Category:** Forms/Inputs\n**Docs:** https://lumeo.nativ.sh/components/password-input\n\n## Parameters\n| Owner | Name | Type | Default | Description |\n|---|---|---|---|---|\n| PasswordInput | FormField | `FormField.FormFieldContext?` | `` |  |\n| PasswordInput | Value | `string?` | `` |  |\n| PasswordInput | ValueChanged | `EventCallback<string?>` | `` |  |\n| PasswordInput | Placeholder | `string?` | `` |  |\n| PasswordInput | ShowStrength | `bool` | `` |  |\n| PasswordInput | ShowToggle | `bool` | `true` |  |\n| PasswordInput | Disabled | `bool` | `` |  |\n| PasswordInput | Required | `bool` | `` |  |\n| PasswordInput | Invalid | `bool` | `` |  |\n| PasswordInput | ErrorText | `string?` | `` |  |\n| PasswordInput | HelperText | `string?` | `` |  |\n| PasswordInput | Label | `string?` | `` |  |\n| PasswordInput | Name | `string?` | `` |  |\n| PasswordInput | Class | `string?` | `` |  |\n| PasswordInput | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n\n## Slots\n- (none)\n\n## Events\n- `ValueChanged` (`EventCallback<string?>`)\n\n## Sub-components\n- (none)\n\n## Cascading values it expects\n- `FormField` (`FormField.FormFieldContext?`)\n\n## Services it injects\n- `ILumeoLocalizer` (Lumeo.Services.Localization)\n\n## Keyboard\n—\n\n## Example\n```razor\n<PasswordInput />\n```\n\n## CSS variables\n`--color-destructive`, `--color-foreground`, `--color-input`, `--color-muted`, `--color-muted-foreground`, `--color-ring`, `--radius`\n\n## Files\n- `UI/PasswordInput/PasswordInput.razor`\n"
}