"use client"; import { useEffect, useState } from "react"; import { useSortable } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import { GripVertical, Trash2 } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { cn } from "@/lib/utils"; type FormField = { id: string; label: string; type: string; required: boolean; placeholder?: string; helpText?: string; options?: { label: string; value: string }[]; defaultValue?: unknown; mappedProperty: string | null; validation?: { min?: number; max?: number; pattern?: string; maxLength?: number; }; conditionals?: { fieldId: string; operator: string; value: unknown; action: string; }[]; }; function formatTypeLabel(type: string) { return type .split("_") .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) .join(" "); } export function FormFieldCard({ field, isSelected, onSelect, onChange, onDelete, }: { field: FormField; isSelected: boolean; onSelect: () => void; onChange: (patch: Partial) => void; onDelete: () => void; }) { const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id: field.id }); const style = { transform: CSS.Transform.toString(transform), transition, }; const [editingLabel, setEditingLabel] = useState(false); const [labelDraft, setLabelDraft] = useState(field.label); useEffect(() => { setLabelDraft(field.label); }, [field.label]); return (
{ if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onSelect(); } }} > {editingLabel ? ( setLabelDraft(e.target.value)} onBlur={() => { setEditingLabel(false); if (labelDraft.trim() !== field.label) { onChange({ label: labelDraft.trim() || "Untitled" }); } }} onKeyDown={(e) => { if (e.key === "Enter") (e.target as HTMLInputElement).blur(); e.stopPropagation(); }} className="h-8" onClick={(e) => e.stopPropagation()} /> ) : ( )}
{formatTypeLabel(field.type)} {field.required ? ( Required ) : null}
); }