const TagsInput = ({ tags, onChange, placeholder = "Add tags..." }) => { const [inputValue, setInputValue] = React.useState(''); const [error, setError] = React.useState(''); // Ensure tags is always an array const tagArray = Array.isArray(tags) ? tags : []; const addTag = (tagText) => { const cleaned = tagText.trim(); if (!cleaned) return; // Validate: no special characters that could break JSON if (/[<>"'`{}[\]]/.test(cleaned)) { setError('Tags cannot contain: < > " \' ` { } [ ]'); return; } // Dedupe: case-insensitive, and when adding multiple from comma-separated const existingLower = tagArray.map(t => String(t).toLowerCase()); const toAdd = cleaned.split(',').map(t => t.trim()).filter(Boolean).filter(t => !existingLower.includes(t.toLowerCase())); toAdd.forEach(t => existingLower.push(t.toLowerCase())); if (toAdd.length === 0) { setInputValue(''); return; } setError(''); onChange([...tagArray, ...toAdd]); setInputValue(''); }; const removeTag = (index) => { const newTags = tagArray.filter((_, i) => i !== index); onChange(newTags); }; const handleKeyDown = (e) => { if (e.key === 'Enter' || e.key === ',' || e.key === 'Tab') { e.preventDefault(); addTag(inputValue); } else if (e.key === 'Backspace' && !inputValue && tagArray.length > 0) { removeTag(tagArray.length - 1); } else if (e.key === 'Escape') { setInputValue(''); setError(''); } }; return (