import React, { useState } from 'react' import { Pencil } from 'lucide-react' import { useFormStore } from '../store/useFormStore' import ConditionalLogicToggle from './ConditionalLogicToggle' import ImageFieldEditor from './field-editors/ImageFieldEditor' import StaticContentEditor from './field-editors/StaticContentEditor' import UtilityFieldSettings from './field-editors/UtilityFieldSettings' import FieldIconControl from './field-editors/FieldIconControl' import OptionsEditor from './property/OptionsEditor' import FieldStylePicker from './property/FieldStylePicker' import { FieldColors, hasFieldColors, DefaultValueEditor, SubfieldsEditor, DateSettings, TimeSettings, PhoneSettings, RichTextToggle, ImageStyleSettings, GridSettings, } from './property/TypeSettings' import { getFieldType, Slot, useRegistryVersion } from '../extensions/registry' import { BUILTIN_FIELD_TYPES } from './FormField' import InfoTip from './property/InfoTip' import { SettingLabel, AccordionSection } from './property/PanelParts' // Human-readable field type for the storefront-style "Edit : [Type]" chip. const FIELD_TYPE_LABELS = { select: 'Dropdown', tel: 'Phone', url: 'Website', textarea: 'Paragraph Text', text: 'Text', checkbox: 'Checkbox', radio: 'Radio', 'static-content': 'Static Content', html: 'HTML', captcha: 'CAPTCHA', } export function getFieldTypeDisplay(type) { if (!type) return 'Unknown Field Type' if (FIELD_TYPE_LABELS[type]) return FIELD_TYPE_LABELS[type] const registered = getFieldType(type) if (registered && (registered.typeLabel || registered.label)) return registered.typeLabel || registered.label return type.split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ') } export default function PropertyEditor() { useRegistryVersion() const activeFieldId = useFormStore((state) => state.activeFieldId) const fields = useFormStore((state) => state.fields) const updateField = useFormStore((state) => state.updateField) const setIsLogicSidebarOpen = useFormStore((state) => state.setIsLogicSidebarOpen) // Fields inside container columns are editable too (a `columns` array holds column definitions). const findField = (list) => { for (const f of list || []) { if (f.id === activeFieldId) return f if (f.columns && !Array.isArray(f.columns) && typeof f.columns === 'object') { for (const col of Object.values(f.columns)) { const found = Array.isArray(col) ? findField(col) : null if (found) return found } } } return null } const activeField = findField(fields) // the reference builder accordion: one section open at a time, General open by default. const [openSection, setOpenSection] = useState('General') const setActiveFieldId = useFormStore((state) => state.setActiveFieldId) if (!activeField) { return (
Select a field on the canvas to configure its settings.
) } const field = activeField const onUpdate = (updates) => { updateField(activeField.id, updates) } const t = activeField.type const typeDef = getFieldType(t) const flag = (key, fallback) => (typeDef && typeDef[key] !== undefined ? Boolean(typeDef[key]) : fallback) const hasOptions = flag('hasOptions', ['select', 'checkbox', 'radio'].includes(t)) && (!typeDef || typeDef.hasOptions !== 'array' || Array.isArray(activeField.options)) // the reference builder hides these per type (F:15555 Required, F:18213 Visibility, F:17510 Advanced, F:18280 logic). const showRequired = flag('showRequired', !['submit', 'hidden', 'html', 'section', 'static-content', 'image', 'grid', 'promo-banner', 'trust-badges', 'faq-accordion', 'countdown-banner'].includes(t)) const showVisibility = !['submit', 'hidden'].includes(t) const showAdvanced = t !== 'submit' const showLogic = t !== 'hidden' const showIcon = flag('showIcon', ['text', 'email', 'tel', 'url', 'number', 'password', 'date', 'time', 'select', 'dropdown'].includes(t)) const isUnsupported = !typeDef && !BUILTIN_FIELD_TYPES.includes(t) if (isUnsupported) { return (

Unsupported field type: {String(t || 'unknown')}

This field type can't be edited here. The field and its settings are kept when you save the form.

) } const typeDisplay = getFieldTypeDisplay(field.type) const isOpen = (section) => openSection === section const toggleSection = (section) => setOpenSection(openSection === section ? null : section) const inputCls = 'w-full text-sm border border-gray-200 rounded-md px-3 py-2 focus:outline-none focus:ring-1 focus:ring-gray-900 focus:border-gray-900 text-gray-900' return (
{/* Edit header — the reference builder "Edit : [Type]" chip with ✕ close */}
{/* ── General ─────────────────────────────────────────── */} toggleSection('General')}>
{/* Field Label */}
Label onUpdate({ label: e.target.value })} className={inputCls} placeholder="Field label" />
{/* Field Description */}
Description