{
	"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
	"name": "tag-input",
	"title": "Tag Input",
	"type": "registry:ui",
	"description": "An input field for entering multiple values, displayed as chips.",
	"dependencies": [
		"@lucide/svelte@^0.554.0"
	],
	"devDependencies": [
		"@lucide/svelte@^0.544.0"
	],
	"files": [
		{
			"content": "<script lang=\"ts\">\r\n\timport { cn } from '$UTILS$';\r\n\timport * as Chip from '$lib/components/ui/chip';\r\n\timport { X } from '@lucide/svelte';\r\n\r\n\tlet {\r\n\t\ttags = $bindable([]),\r\n\t\tplaceholder = 'Add tag...',\r\n\t\tdisabled = false,\r\n\t\tmaxTags,\r\n\t\tclass: className,\r\n\t\tchipVariant = 'secondary',\r\n\t\tvalidate,\r\n\t\tonadd,\r\n\t\tonremove\r\n\t}: {\r\n\t\ttags: string[];\r\n\t\tplaceholder?: string;\r\n\t\tdisabled?: boolean;\r\n\t\tmaxTags?: number;\r\n\t\tclass?: string;\r\n\t\tchipVariant?: 'default' | 'secondary' | 'outline' | 'ghost';\r\n\t\tvalidate?: (tag: string) => boolean;\r\n\t\tonadd?: (tag: string) => void;\r\n\t\tonremove?: (tag: string) => void;\r\n\t} = $props();\r\n\r\n\tlet inputValue = $state('');\r\n\tlet inputRef: HTMLInputElement | undefined = $state();\r\n\r\n\tfunction addTag(text: string) {\r\n\t\tconst trimmed = text.trim();\r\n\r\n\t\tif (!trimmed) return;\r\n\t\tif (tags.includes(trimmed)) return;\r\n\t\tif (maxTags && tags.length >= maxTags) return;\r\n\t\tif (validate && !validate(trimmed)) return;\r\n\r\n\t\ttags = [...tags, trimmed];\r\n\t\tinputValue = '';\r\n\t\tonadd?.(trimmed);\r\n\t}\r\n\r\n\tfunction removeTag(index: number) {\r\n\t\tconst removed = tags[index];\r\n\t\ttags = tags.filter((_, i) => i !== index);\r\n\t\tonremove?.(removed);\r\n\t}\r\n\r\n\tfunction handleKeydown(e: KeyboardEvent) {\r\n\t\tif (e.key === 'Enter' || e.key === ',') {\r\n\t\t\te.preventDefault();\r\n\t\t\taddTag(inputValue);\r\n\t\t} else if (e.key === 'Backspace' && inputValue === '' && tags.length > 0) {\r\n\t\t\tremoveTag(tags.length - 1);\r\n\t\t}\r\n\t}\r\n\r\n\tfunction handleContainerClick() {\r\n\t\tinputRef?.focus();\r\n\t}\r\n</script>\r\n\r\n<div\r\n\tclass={cn(\r\n\t\t'flex min-h-10 w-full flex-wrap items-center gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background',\r\n\t\t'focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',\r\n\t\tdisabled && 'cursor-not-allowed opacity-50',\r\n\t\tclassName\r\n\t)}\r\n\tonclick={handleContainerClick}\r\n\trole=\"textbox\"\r\n\ttabindex=\"-1\"\r\n\tonkeydown={() => {}}\r\n>\r\n\t{#each tags as tag, i}\r\n\t\t<Chip.Root\r\n\t\t\tvariant={chipVariant}\r\n\t\t\tsize=\"sm\"\r\n\t\t\tremovable={!disabled}\r\n\t\t\tonremove={() => removeTag(i)}\r\n\t\t\t{disabled}\r\n\t\t\tclass=\"animate-in zoom-in-50 fade-in-0 duration-200\"\r\n\t\t>\r\n\t\t\t{tag}\r\n\t\t</Chip.Root>\r\n\t{/each}\r\n\r\n\t<input\r\n\t\tbind:this={inputRef}\r\n\t\tbind:value={inputValue}\r\n\t\t{disabled}\r\n\t\t{placeholder}\r\n\t\tonkeydown={handleKeydown}\r\n\t\tonblur={() => {}}\r\n\t\tclass=\"flex-1 bg-transparent outline-none placeholder:text-muted-foreground min-w-[120px]\"\r\n\t/>\r\n</div>\r\n",
			"type": "registry:ui",
			"target": "tag-input/tag-input.svelte"
		},
		{
			"content": "import TagInput from './tag-input.svelte';\n\nexport { TagInput };\n",
			"type": "registry:ui",
			"target": "tag-input/index.ts"
		}
	]
}