import React, { useEffect, useMemo, useRef, useState } from 'react' import { Braces, Search } from 'lucide-react' import { mergeTagOptions } from './mergeTags' /** * "Insert tag" button with a searchable list of merge tags (form tags + every field, grid columns included). * `onInsert(tag)` receives the tag text, e.g. "{field_email}". */ export default function MergeTagPicker({ fields, onInsert, allFields = true, label = 'Insert tag', testId, align = 'right' }) { const [open, setOpen] = useState(false) const [query, setQuery] = useState('') const ref = useRef(null) const options = useMemo(() => mergeTagOptions(fields, { allFields }), [fields, allFields]) useEffect(() => { if (!open) return undefined const onDown = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false) } const onKey = (e) => { if (e.key === 'Escape') { e.stopPropagation(); setOpen(false) } } document.addEventListener('mousedown', onDown) document.addEventListener('keydown', onKey, true) return () => { document.removeEventListener('mousedown', onDown) document.removeEventListener('keydown', onKey, true) } }, [open]) const q = query.trim().toLowerCase() const shown = q ? options.filter((o) => o.label.toLowerCase().includes(q) || o.tag.toLowerCase().includes(q)) : options const groups = ['Form', 'Fields'].map((g) => [g, shown.filter((o) => o.group === g)]).filter(([, list]) => list.length) return (
No matching tags
} {groups.map(([group, list]) => (