import classnames from 'classnames'; import { useEffect, useState } from 'react'; import { IconButton } from './IconButton'; import { Input } from './Input'; import { VStack } from './Stacks'; interface Props { pairs: Pair[]; onChange: (pairs: Pair[]) => void; className?: string; } interface Pair { name: string; value: string; } interface PairContainer { pair: Pair; id: string; } export function PairEditor({ pairs: originalPairs, className, onChange }: Props) { const newPairContainer = (): PairContainer => { return { pair: { name: '', value: '' }, id: Math.random().toString() }; }; const [pairs, setPairs] = useState(() => { // Remove empty headers on initial render const nonEmpty = originalPairs.filter((h) => !(h.name === '' && h.value === '')); const pairs = nonEmpty.map((h) => ({ pair: h, id: Math.random().toString() })); return [...pairs, newPairContainer()]; }); const setPairsAndSave = (fn: (pairs: PairContainer[]) => PairContainer[]) => { setPairs((oldPairs) => { const pairs = fn(oldPairs).map((p) => p.pair); onChange(pairs); return fn(oldPairs); }); }; const handleChangeHeader = (pair: PairContainer) => { setPairsAndSave((pairs) => pairs.map((p) => (pair.id !== p.id ? p : pair))); }; // Ensure there's always at least one pair useEffect(() => { if (pairs.length === 0) { setPairs((pairs) => [...pairs, newPairContainer()]); } }, [pairs]); const handleDelete = (pair: PairContainer) => { setPairsAndSave((oldPairs) => oldPairs.filter((p) => p.id !== pair.id)); }; return (
{pairs.map((p, i) => { const isLast = i === pairs.length - 1; return ( { if (isLast) { setPairs((pairs) => [...pairs, newPairContainer()]); } }} onDelete={isLast ? undefined : handleDelete} /> ); })}
); } function FormRow({ pairContainer, onChange, onDelete, onFocus, isLast, }: { pairContainer: PairContainer; onChange: (pair: PairContainer) => void; onDelete?: (pair: PairContainer) => void; onFocus?: () => void; isLast?: boolean; }) { const { id } = pairContainer; return (
onChange({ id, pair: { name, value: pairContainer.pair.value } })} onFocus={onFocus} placeholder={isLast ? 'new name' : 'name'} useEditor={{ useTemplating: true }} /> onChange({ id, pair: { name: pairContainer.pair.name, value } })} onFocus={onFocus} placeholder={isLast ? 'new value' : 'value'} useEditor={{ useTemplating: true }} /> {onDelete && ( onDelete(pairContainer)} tabIndex={-1} className={classnames('opacity-0 group-hover:opacity-100')} /> )}
); }