@page "/components/tag-input"

<PageTitle>TagInput — Lumeo</PageTitle>

<PageHeader Title="TagInput" Description="An input field for creating and managing tags with optional suggestions and limits." />

<div class="mt-10 space-y-3">
    <Heading Id="when-to-use" Level="2" Class="scroll-mt-20">When to Use</Heading>
    <ul class="list-disc list-inside space-y-1 text-muted-foreground text-sm">
        <li>Tagging content with categories, labels, or keywords</li>
        <li>Multi-value text entry such as email recipient lists</li>
        <li>Filter or search inputs where users add multiple terms</li>
        <li>Any field where users create a dynamic list of short text values</li>
    </ul>
</div>

<Stack Gap="8" Class="mt-8">
    <ComponentDemo Title="Basic TagInput" Code="@_basicCode">
        <TagInput @bind-Tags="_tags1" Placeholder="Add tags..." Class="max-w-md" />
    </ComponentDemo>

    <ComponentDemo Title="With Suggestions" Code="@_suggestionsCode">
        <Stack Gap="2" Class="max-w-md">
            <TagInput @bind-Tags="_tags2" Suggestions="@_suggestions" Placeholder="Type to search..." />
            <Lumeo.Text Size="sm" Color="muted">Tags: @string.Join(", ", _tags2)</Lumeo.Text>
        </Stack>
    </ComponentDemo>

    <ComponentDemo Title="Max Tags" Code="@_maxCode">
        <TagInput @bind-Tags="_tags3" MaxTags="3" Placeholder="Max 3 tags..." Class="max-w-md" />
    </ComponentDemo>

    <ComponentDemo Title="Generic TItem — User picker" Code="@_genericCode">
        <Stack Gap="2" Class="max-w-md">
            <TagInput TItem="UserOption"
                      @bind-Tags="_userTags"
                      Suggestions="@_userSuggestions"
                      GetTagText="@(u => u.Name)"
                      GetSuggestionText="@(u => $"{u.Name} {u.Email}")"
                      CreateTag="@CreateUserFromText"
                      Separators="@(new[] { ",", ";", " " })"
                      Placeholder="Search users…">
                <TagTemplate Context="user">
                    <span class="inline-flex items-center gap-2 rounded-md border border-border/40 bg-secondary pl-1 pr-2 py-0.5 text-xs font-medium text-secondary-foreground">
                        <span class="inline-flex h-5 w-5 items-center justify-center rounded-full bg-primary text-[10px] font-semibold text-primary-foreground">
                            @user.Name.Substring(0, 1)
                        </span>
                        @user.Name
                    </span>
                </TagTemplate>
                <SuggestionTemplate Context="user">
                    <div class="flex flex-row items-center gap-2 w-full">
                        <span class="inline-flex h-6 w-6 items-center justify-center rounded-full bg-primary text-xs font-semibold text-primary-foreground">
                            @user.Name.Substring(0, 1)
                        </span>
                        <Stack Gap="0">
                            <Lumeo.Text Size="sm">@user.Name</Lumeo.Text>
                            <Lumeo.Text Size="xs" Color="muted">@user.Email</Lumeo.Text>
                        </Stack>
                    </div>
                </SuggestionTemplate>
            </TagInput>
            <Lumeo.Text Size="sm" Color="muted">Selected: @string.Join(", ", _userTags.Select(u => u.Name))</Lumeo.Text>
        </Stack>
    </ComponentDemo>
</Stack>

<!-- API Reference -->
<Stack Gap="6" Class="mt-12">
    <Heading Level="2">API Reference</Heading>
    <Stack Gap="8" Class="mt-8">
        <Stack Gap="3">
            <Heading Level="3">TagInput</Heading>
            <Stack Class="rounded-lg border border-border/40 overflow-x-auto">
                <table class="w-full min-w-[600px] text-sm">
                    <thead>
                        <tr class="border-b border-border/40 bg-muted/40">
                            <th class="text-left p-3 font-medium text-foreground">Property</th>
                            <th class="text-left p-3 font-medium text-foreground">Type</th>
                            <th class="text-left p-3 font-medium text-foreground">Default</th>
                            <th class="text-left p-3 font-medium text-foreground">Description</th>
                        </tr>
                    </thead>
                    <tbody class="divide-y divide-border/40">
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Tags</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">List&lt;string&gt;</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">The list of tags. Supports two-way binding.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Suggestions</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">List&lt;string&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">Autocomplete suggestions shown when typing.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">MaxTags</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">int?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">Maximum number of tags allowed.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">AllowDuplicates</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">false</td>
                            <td class="p-3 text-muted-foreground">Allow duplicate tag values.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Placeholder</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">Placeholder text shown when empty.</td>
                        </tr>
                                            <tr>
                            <td class="p-3 font-mono text-xs text-primary">TagsChanged</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">EventCallback&lt;List&lt;string&gt;&gt;</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">Two-way binding callback for the tags list.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Disabled</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">false</td>
                            <td class="p-3 text-muted-foreground">Disables user interaction.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">TItem</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">@@typeparam</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string</td>
                            <td class="p-3 text-muted-foreground">Item type. Use a custom record/class for non-string tags (e.g. user picker).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">GetTagText</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">Func&lt;TItem, string&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">ToString()</td>
                            <td class="p-3 text-muted-foreground">Maps an item to its tag display text. Required for non-string TItem when not using TagTemplate.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">GetSuggestionText</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">Func&lt;TItem, string&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">GetTagText</td>
                            <td class="p-3 text-muted-foreground">Maps an item to its searchable suggestion text. Falls back to GetTagText, then ToString().</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">TagTemplate</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">RenderFragment&lt;TItem&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">Custom render fragment for each tag (e.g. avatar + name).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">SuggestionTemplate</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">RenderFragment&lt;TItem&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">Custom render fragment for each suggestion row in the popup.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Separators</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string[]</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">[","]</td>
                            <td class="p-3 text-muted-foreground">Strings that split typed/pasted input into multiple tags. Pass {",", ";", "\n", "\t"} for richer paste support.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ValidateInput</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">Func&lt;string, string?&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">Synchronous validation. Return null to accept, or an error string to block + display inline.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ValidateInputAsync</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">Func&lt;string, Task&lt;string?&gt;&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">—</td>
                            <td class="p-3 text-muted-foreground">Async validation (e.g. server-side uniqueness check).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">CreateTag</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">Func&lt;string, TItem?&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">cast for string</td>
                            <td class="p-3 text-muted-foreground">Converts free-text input to a TItem when no suggestion matches. Required for non-string TItem.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">MaxTagsHelperText</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">localized</td>
                            <td class="p-3 text-muted-foreground">Helper text shown below the field once MaxTags is reached.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Required</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">false</td>
                            <td class="p-3 text-muted-foreground">Marks the field as required. Syncs with a parent FormField.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Invalid</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">false</td>
                            <td class="p-3 text-muted-foreground">Applies error styling. Syncs with a parent FormField.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ErrorText</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Error message displayed below the field when Invalid is true.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">HelperText</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Helper text shown below the field when not invalid.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Label</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Label rendered above the field (standalone, without FormField).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Name</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">HTML name attribute for form submission.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">FormField</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">FormField.FormFieldContext?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Cascaded context from a parent FormField; wires label, validation, and required state automatically.</td>
                        </tr>
</tbody>
                </table>
            </Stack>
        </Stack>
    </Stack>
</Stack>

<div class="mt-12">
    <Heading Id="related" Level="2" Class="scroll-mt-20">Related Components</Heading>
    <ul class="mt-4 space-y-2 text-sm">
        <li><a href="/components/combobox" class="text-primary hover:underline">Combobox</a> — Searchable dropdown for selecting from predefined options</li>
        <li><a href="/components/badge" class="text-primary hover:underline">Badge</a> — Display tags or labels as styled badges</li>
        <li><a href="/components/input" class="text-primary hover:underline">Input</a> — Single-value text input for simpler fields</li>
    </ul>
</div>

@code {
    private List<string> _tags1 = new() { "Blazor", "C#" };
    private List<string> _tags2 = new() { "React" };
    private List<string> _tags3 = new() { "Alpha", "Beta" };

    private List<string> _suggestions = new()
    {
        "JavaScript", "TypeScript", "Python", "Rust", "Go", "Java", "Swift", "Kotlin"
    };

    public record UserOption(string Name, string Email);

    private UserOption? CreateUserFromText(string text) => new UserOption(text, text);

    private List<UserOption> _userTags = new() { new("Ada Lovelace", "ada@lumeo.dev") };

    private List<UserOption> _userSuggestions = new()
    {
        new("Ada Lovelace",  "ada@lumeo.dev"),
        new("Alan Turing",   "alan@lumeo.dev"),
        new("Grace Hopper",  "grace@lumeo.dev"),
        new("Linus Torvalds","linus@lumeo.dev"),
        new("Margaret Hamilton","margaret@lumeo.dev"),
    };

    private string _basicCode = @"<TagInput @bind-Tags=""_tags"" Placeholder=""Add tags..."" />";
    private string _suggestionsCode = @"<TagInput @bind-Tags=""_tags"" Suggestions=""@_suggestions"" />";
    private string _maxCode = @"<TagInput @bind-Tags=""_tags"" MaxTags=""3"" />";

    private string _genericCode = @"public record UserOption(string Name, string Email);

private List<UserOption> _users = new();
private List<UserOption> _suggestions = new() { /* … */ };

<TagInput TItem=""UserOption""
          @bind-Tags=""_users""
          Suggestions=""@_suggestions""
          GetTagText=""@(u => u.Name)""
          GetSuggestionText=""@(u => $""{u.Name} {u.Email}"")""
          CreateTag=""@(text => new UserOption(text, text))""
          Separators=""@(new[] { "","", "";"", "" "" })"">
    <TagTemplate Context=""user"">
        <span class=""chip"">
            <Avatar Initial=""@user.Name[0]"" />
            @user.Name
        </span>
    </TagTemplate>
    <SuggestionTemplate Context=""user"">
        <Stack Direction=""Row"" Gap=""2"">
            <Avatar Initial=""@user.Name[0]"" />
            <Stack Gap=""0"">
                <Text>@user.Name</Text>
                <Text Color=""muted"">@user.Email</Text>
            </Stack>
        </Stack>
    </SuggestionTemplate>
</TagInput>";
}
