@nextlyhq/plugin-form-builder 0.0.2-alpha.5 → 0.0.2-alpha.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -5
- package/dist/admin/index.d.ts +123 -331
- package/dist/admin/index.js +3824 -3420
- package/dist/admin/index.js.map +1 -1
- package/dist/chunk-WVI7N3QO.js +559 -0
- package/dist/chunk-WVI7N3QO.js.map +1 -0
- package/dist/index.d.ts +12 -11
- package/dist/index.js +592 -664
- package/dist/index.js.map +1 -1
- package/dist/{index-C0kBvYjm.d.ts → types-r8uBeB0u.d.ts} +126 -125
- package/package.json +32 -30
- package/dist/CheckboxFieldEditor-K4T6QX52.js +0 -121
- package/dist/CheckboxFieldEditor-K4T6QX52.js.map +0 -1
- package/dist/DateFieldEditor-JFJFAVOH.js +0 -187
- package/dist/DateFieldEditor-JFJFAVOH.js.map +0 -1
- package/dist/EmailFieldEditor-MMOXXL7P.js +0 -138
- package/dist/EmailFieldEditor-MMOXXL7P.js.map +0 -1
- package/dist/NumberFieldEditor-UISAYR6Z.js +0 -175
- package/dist/NumberFieldEditor-UISAYR6Z.js.map +0 -1
- package/dist/RadioFieldEditor-6UQFH4WT.js +0 -165
- package/dist/RadioFieldEditor-6UQFH4WT.js.map +0 -1
- package/dist/SelectFieldEditor-PSO4KHV4.js +0 -213
- package/dist/SelectFieldEditor-PSO4KHV4.js.map +0 -1
- package/dist/TextFieldEditor-5EU64EA5.js +0 -187
- package/dist/TextFieldEditor-5EU64EA5.js.map +0 -1
- package/dist/TextareaFieldEditor-773G3LNM.js +0 -190
- package/dist/TextareaFieldEditor-773G3LNM.js.map +0 -1
- package/dist/admin/index.css +0 -934
- package/dist/admin/index.css.map +0 -1
- package/dist/chunk-ABNZFTQK.js +0 -586
- package/dist/chunk-ABNZFTQK.js.map +0 -1
- package/dist/chunk-XTCEPJ7B.js +0 -256
- package/dist/chunk-XTCEPJ7B.js.map +0 -1
- package/dist/components/index.d.ts +0 -3
- package/dist/components/index.js +0 -9
- package/dist/components/index.js.map +0 -1
- package/dist/styles/form-builder.css +0 -1150
- package/dist/styles/submissions-filter.css +0 -75
package/dist/admin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/admin/index.ts","../../src/admin/components/SubmissionsFilter.tsx","../../src/admin/FormBuilderView.tsx","../../src/admin/components/builder/FieldEditor.tsx","../../src/admin/components/builder/ConditionalLogicEditor.tsx","../../src/admin/components/builder/FieldLibrary.tsx","../../src/admin/context/FormBuilderContext.tsx","../../src/admin/components/builder/FormCanvas.tsx","../../src/admin/components/builder/FormNotificationsTab.tsx","../../src/admin/components/builder/FormPreview.tsx","../../src/admin/components/builder/FormSettingsTab.tsx","../../src/admin/components/FormFieldList.tsx","../../src/admin/components/SortableFieldRow.tsx","../../src/admin/fields/index.ts","../../src/admin/components/AddFieldButton.tsx","../../src/admin/components/FieldEditorPanel.tsx"],"sourcesContent":["/**\n * Form Builder Admin Components\n *\n * Entry point for admin UI components used by the Nextly admin panel.\n * These components are referenced via component paths in collection configs.\n *\n * Component paths use the format: \"@nextlyhq/plugin-form-builder/admin#ExportName\"\n *\n * ## Auto-Registration\n *\n * This module automatically registers its components with the admin panel\n * when imported. No manual registration is required - just add the plugin\n * to your Nextly config and the admin will detect and load the components.\n *\n * @module admin\n * @since 0.1.0\n */\n\n// ============================================================================\n// Main View Components\n// ============================================================================\n\n// ============================================================================\n// Component Registration\n// ============================================================================\n\nimport {\n registerComponents,\n registerKnownPlugin,\n type ComponentPath,\n} from \"@nextlyhq/admin/lib/component-registry\";\n\nimport { SubmissionsFilter } from \"./components/SubmissionsFilter\";\nimport { FormBuilderView } from \"./FormBuilderView\";\n\nexport { FormBuilderView, type FormBuilderViewProps } from \"./FormBuilderView\";\nexport {\n SubmissionsFilter,\n type SubmissionsFilterProps,\n} from \"./components/SubmissionsFilter\";\n\n// ============================================================================\n// Builder Sub-Components\n// ============================================================================\n\nexport {\n FieldLibrary,\n FormCanvas,\n FieldEditor,\n FormPreview,\n type FormCanvasProps,\n type FieldEditorProps,\n type FormPreviewProps,\n} from \"./components/builder\";\n\n// ============================================================================\n// New Components\n// ============================================================================\n\nexport {\n FormFieldList,\n type FormFieldListProps,\n SortableFieldRow,\n type SortableFieldRowProps,\n AddFieldButton,\n type AddFieldButtonProps,\n FieldEditorPanel,\n type FieldEditorPanelProps,\n} from \"./components\";\n\n// ============================================================================\n// Context & Hooks\n// ============================================================================\n\nexport {\n FormBuilderProvider,\n useFormBuilder,\n useOptionalFormBuilder,\n createFieldFromType,\n createNotification,\n generateFieldName,\n generateFieldLabel,\n DEFAULT_SETTINGS,\n type FormBuilderState,\n type FormBuilderActions,\n type FormBuilderContextValue,\n type FormBuilderProviderProps,\n type FormSettings,\n type FormNotification,\n} from \"./context/FormBuilderContext\";\n\n// ============================================================================\n// Tab Components\n// ============================================================================\n\nexport { FormSettingsTab } from \"./components/builder/FormSettingsTab\";\nexport { FormNotificationsTab } from \"./components/builder/FormNotificationsTab\";\n\n// ============================================================================\n// Submission Components\n// ============================================================================\n\nexport {\n SubmissionList,\n SubmissionDetail,\n type SubmissionListProps,\n type SubmissionDetailProps,\n} from \"../components/submissions\";\n\n/** Component path for FormBuilderView */\nexport const FORM_BUILDER_VIEW_PATH: ComponentPath =\n \"@nextlyhq/plugin-form-builder/admin#FormBuilderView\";\n\n/** Component path for SubmissionsFilter */\nexport const SUBMISSIONS_FILTER_PATH: ComponentPath =\n \"@nextlyhq/plugin-form-builder/admin#SubmissionsFilter\";\n\n/**\n * Register Form Builder admin components with the Nextly admin panel.\n *\n * @deprecated This function is no longer needed. Components are auto-registered\n * when the admin detects the Form Builder plugin's component paths in collection configs.\n *\n * @example\n * ```typescript\n * // No manual registration needed! Just add the plugin to your config:\n * export default defineConfig({\n * plugins: [formBuilderPlugin.plugin],\n * });\n * ```\n */\nexport function registerFormBuilderAdminComponents(): void {\n registerComponents({\n [FORM_BUILDER_VIEW_PATH]: FormBuilderView,\n });\n}\n\n// ============================================================================\n// Auto-Registration with Admin\n// ============================================================================\n\n/**\n * Eagerly register components at module load time.\n *\n * This ensures components are available immediately when the admin\n * tries to resolve them, without needing to wait for async registration.\n */\nregisterComponents({\n [FORM_BUILDER_VIEW_PATH]: FormBuilderView,\n [SUBMISSIONS_FILTER_PATH]: SubmissionsFilter,\n});\n\n/**\n * Also register with the known plugin system for consistency.\n *\n * This supports the auto-registration flow where the admin detects\n * component paths and triggers registration. Since we eagerly register\n * above, this callback is effectively a no-op but keeps the plugin\n * compatible with both eager and lazy registration patterns.\n */\nregisterKnownPlugin(\n \"@nextlyhq/plugin-form-builder\",\n // eslint-disable-next-line @typescript-eslint/require-await -- registerKnownPlugin's second arg is typed `() => Promise<void>` (strict, not a union); body is synchronous\n async () => {\n // Components already registered above, but re-register for safety\n registerComponents({\n [FORM_BUILDER_VIEW_PATH]: FormBuilderView,\n [SUBMISSIONS_FILTER_PATH]: SubmissionsFilter,\n });\n }\n);\n","\"use client\";\n\n/**\n * Submissions Filter Component\n *\n * A filter component that appears above the form-submissions list table.\n * Allows users to filter submissions by selecting a specific form.\n *\n * @module admin/components/SubmissionsFilter\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { useRouter, useSearchParams } from \"next/navigation\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n// Import styles - uses aliased path that resolves to dist/styles in consuming apps\nimport \"@nextlyhq/plugin-form-builder/styles/submissions-filter.css\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface Form {\n id: string;\n name: string;\n slug: string;\n}\n\nexport interface SubmissionsFilterProps {\n /** Collection slug (should be \"form-submissions\") */\n collectionSlug: string;\n /** Collection configuration */\n collection: Record<string, unknown>;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * SubmissionsFilter - Filter submissions by form\n *\n * Displays a dropdown of all forms. When a form is selected,\n * updates the URL query params to filter the submissions list.\n */\nexport function SubmissionsFilter({\n collectionSlug,\n}: SubmissionsFilterProps): React.ReactElement | null {\n const router = useRouter();\n const searchParams = useSearchParams();\n const [forms, setForms] = useState<Form[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [selectedFormId, setSelectedFormId] = useState<string>(\"\");\n\n // Get current filter from URL\n useEffect(() => {\n const whereParam = searchParams.get(\"where\");\n if (whereParam) {\n try {\n const where = JSON.parse(whereParam);\n if (where.form?.equals) {\n setSelectedFormId(where.form.equals);\n }\n } catch {\n // Invalid JSON, ignore\n }\n }\n }, [searchParams]);\n\n // Fetch all forms\n useEffect(() => {\n async function fetchForms() {\n try {\n const response = await fetch(\"/admin/api/collections/forms/entries\");\n if (response.ok) {\n const data = (await response.json()) as { items?: Form[] };\n setForms(data.items ?? []);\n }\n } catch (error) {\n console.error(\"Failed to fetch forms:\", error);\n } finally {\n setIsLoading(false);\n }\n }\n\n void fetchForms();\n }, []);\n\n // Handle form selection\n const handleFormChange = useCallback(\n (formId: string) => {\n setSelectedFormId(formId);\n\n // Build new URL with filter\n const params = new URLSearchParams(searchParams.toString());\n\n if (formId) {\n // Set the where parameter to filter by form\n const where = JSON.stringify({ form: { equals: formId } });\n params.set(\"where\", where);\n } else {\n // Clear the filter\n params.delete(\"where\");\n }\n\n // Reset to page 1 when filter changes\n params.delete(\"page\");\n\n // Navigate with new params (route is /admin/collections/ singular)\n router.push(`/admin/collections/${collectionSlug}?${params.toString()}`);\n },\n [router, searchParams, collectionSlug]\n );\n\n // Don't render if not on form-submissions collection\n if (collectionSlug !== \"form-submissions\") {\n return null;\n }\n\n return (\n <div className=\"submissions-filter\">\n <div className=\"submissions-filter-container\">\n <label htmlFor=\"form-filter\" className=\"submissions-filter-label\">\n Filter by Form:\n </label>\n <select\n id=\"form-filter\"\n value={selectedFormId}\n onChange={e => handleFormChange(e.target.value)}\n className=\"submissions-filter-select\"\n disabled={isLoading}\n >\n <option value=\"\">All Forms</option>\n {forms.map(form => (\n <option key={form.id} value={form.id}>\n {form.name}\n </option>\n ))}\n </select>\n {selectedFormId && (\n <button\n type=\"button\"\n onClick={() => handleFormChange(\"\")}\n className=\"submissions-filter-clear\"\n title=\"Clear filter\"\n >\n Clear\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport default SubmissionsFilter;\n","\"use client\";\n\n/**\n * Form Builder View\n *\n * Custom admin view that provides a visual drag-and-drop form builder.\n * Layout mirrors the Collection Builder for visual consistency.\n *\n * @module admin/FormBuilderView\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport \"../styles/form-builder.css\";\n\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport {\n Button,\n Input,\n toast,\n Tabs,\n TabsList,\n TabsTrigger,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n} from \"@nextlyhq/ui\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { useCallback, useState } from \"react\";\n\nimport type { FormField, FormFieldType } from \"../types\";\n\nimport { FieldEditor } from \"./components/builder/FieldEditor\";\nimport { FieldLibrary } from \"./components/builder/FieldLibrary\";\nimport { FormCanvas } from \"./components/builder/FormCanvas\";\nimport { FormNotificationsTab } from \"./components/builder/FormNotificationsTab\";\nimport { FormPreview } from \"./components/builder/FormPreview\";\nimport { FormSettingsTab } from \"./components/builder/FormSettingsTab\";\nimport {\n FormBuilderProvider,\n useFormBuilder,\n createFieldFromType,\n type FormNotification,\n} from \"./context/FormBuilderContext\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FormBuilderViewProps {\n id?: string;\n entryId?: string;\n collection?: string;\n collectionSlug?: string;\n isCreating?: boolean;\n initialData?: {\n id?: string;\n name?: string;\n slug?: string;\n description?: string;\n status?: \"draft\" | \"published\" | \"closed\";\n fields?: unknown[];\n settings?: Record<string, unknown>;\n notifications?: unknown[];\n };\n onSave?: (data: unknown) => void;\n onSuccess?: (entry?: Record<string, unknown>) => void;\n onCancel?: () => void;\n}\n\n// ============================================================================\n// Helper\n// ============================================================================\n\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, \"\")\n .replace(/[\\s_-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\n// ============================================================================\n// Sliders / Spinner inline SVG\n// ============================================================================\n\nfunction SlidersIcon() {\n return (\n <svg\n className=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"4\" y1=\"21\" x2=\"4\" y2=\"14\" />\n <line x1=\"4\" y1=\"10\" x2=\"4\" y2=\"3\" />\n <line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"3\" />\n <line x1=\"20\" y1=\"21\" x2=\"20\" y2=\"16\" />\n <line x1=\"20\" y1=\"12\" x2=\"20\" y2=\"3\" />\n <line x1=\"1\" y1=\"14\" x2=\"7\" y2=\"14\" />\n <line x1=\"9\" y1=\"8\" x2=\"15\" y2=\"8\" />\n <line x1=\"17\" y1=\"16\" x2=\"23\" y2=\"16\" />\n </svg>\n );\n}\n\n// ============================================================================\n// Inner Component (uses context)\n// ============================================================================\n\nfunction FormBuilderViewInner({\n isCreating = false,\n collectionSlug = \"forms\",\n entryId,\n onSave,\n onSuccess,\n onCancel,\n}: Pick<\n FormBuilderViewProps,\n | \"isCreating\"\n | \"collectionSlug\"\n | \"entryId\"\n | \"onSave\"\n | \"onSuccess\"\n | \"onCancel\"\n>) {\n const {\n fields,\n selectedFieldId,\n activeTab,\n isDirty,\n formData,\n settings,\n notifications,\n setActiveTab,\n addField,\n moveField,\n selectField,\n deleteField,\n updateField,\n duplicateField,\n updateFormData,\n markAsSaved,\n } = useFormBuilder();\n\n const queryClient = useQueryClient();\n\n const [sidebarTab, setSidebarTab] = useState<\"add\" | \"properties\">(\"add\");\n const [isSaving, setIsSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // ── DnD ──────────────────────────────────────────────────────────────────\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 8 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })\n );\n\n const handleDragEnd = useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n if (!over) return;\n\n const isFromLibrary = active.data.current?.isLibraryItem;\n\n if (isFromLibrary) {\n const fieldType = active.data.current?.fieldType as FormFieldType;\n if (fieldType) {\n const newField = createFieldFromType(fieldType);\n if (over.id === \"canvas-drop-zone\") {\n addField(newField);\n } else {\n const overIndex = fields.findIndex(f => f.name === over.id);\n addField(newField, overIndex !== -1 ? overIndex + 1 : undefined);\n }\n }\n } else {\n if (active.id !== over.id) {\n const oldIndex = fields.findIndex(f => f.name === active.id);\n const newIndex = fields.findIndex(f => f.name === over.id);\n if (oldIndex !== -1 && newIndex !== -1) {\n moveField(oldIndex, newIndex);\n }\n }\n }\n },\n [fields, addField, moveField]\n );\n\n // ── Save / Cancel ─────────────────────────────────────────────────────────\n const handleSave = useCallback(async () => {\n // Check if there are fields\n if (fields.length === 0) {\n toast.error(\"Please add at least one field to the form\");\n return;\n }\n\n const { id: _id, ...formDataWithoutId } = formData;\n const saveData = {\n ...formDataWithoutId,\n title: formDataWithoutId.name,\n fields,\n settings,\n notifications,\n };\n\n if (onSave) {\n onSave(saveData);\n return;\n }\n\n setIsSaving(true);\n setSaveError(null);\n try {\n const url = isCreating\n ? `/admin/api/collections/${collectionSlug}/entries`\n : `/admin/api/collections/${collectionSlug}/entries/${entryId}`;\n const response = await fetch(url, {\n method: isCreating ? \"POST\" : \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n credentials: \"include\",\n body: JSON.stringify(saveData),\n });\n if (!response.ok) {\n const err = (await response.json().catch(() => ({}))) as {\n error?: { message?: string };\n };\n throw new Error(\n err.error?.message ?? `Failed to save form: ${response.statusText}`\n );\n }\n\n const result = (await response.json()) as {\n message?: string;\n item?: Record<string, unknown>;\n } & Record<string, unknown>;\n const savedEntry: Record<string, unknown> = result.item ?? result;\n void queryClient.invalidateQueries({\n queryKey: [\"entries\", \"list\", collectionSlug],\n });\n void queryClient.invalidateQueries({ queryKey: [\"entries\", \"count\"] });\n if (!isCreating && entryId) {\n void queryClient.invalidateQueries({\n queryKey: [\"entries\", \"detail\", collectionSlug, entryId],\n });\n }\n markAsSaved();\n toast.success(\n isCreating ? \"Form created successfully\" : \"Form updated successfully\"\n );\n if (onSuccess) onSuccess(savedEntry);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Failed to save form\";\n setSaveError(message);\n toast.error(message);\n } finally {\n setIsSaving(false);\n }\n }, [\n formData,\n fields,\n settings,\n notifications,\n onSave,\n onSuccess,\n isCreating,\n collectionSlug,\n entryId,\n queryClient,\n markAsSaved,\n ]);\n\n const handleCancel = useCallback(() => {\n if (onCancel) onCancel();\n else if (typeof window !== \"undefined\") window.history.back();\n }, [onCancel]);\n\n const handleFieldSelect = useCallback(\n (fieldName: string | null) => {\n selectField(fieldName);\n if (fieldName) setSidebarTab(\"properties\");\n },\n [selectField]\n );\n\n const handleNameChange = useCallback(\n (name: string) => {\n updateFormData({ name });\n if (!formData.slug || formData.slug === slugify(formData.name)) {\n updateFormData({ slug: slugify(name) });\n }\n },\n [formData.name, formData.slug, updateFormData]\n );\n\n const selectedField = fields.find(f => f.name === selectedFieldId);\n const hasSelectedField = !!selectedFieldId;\n\n // Main tabs\n const mainTabs = [\n {\n value: \"builder\" as const,\n label: \"Builder\",\n count: fields.length > 0 ? fields.length : null,\n },\n {\n value: \"preview\" as const,\n label: \"Preview\",\n count: null,\n },\n { value: \"settings\" as const, label: \"Settings\", count: null },\n {\n value: \"notifications\" as const,\n label: \"Notifications\",\n count: notifications.length > 0 ? notifications.length : null,\n },\n ];\n\n // ── Render ────────────────────────────────────────────────────────────────\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n {/* ── Page header (Outside the white card) ── */}\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4 mb-6 px-1\">\n <div>\n <h1 className=\"text-2xl font-semibold text-foreground tracking-tight\">\n {isCreating ? \"Create Form\" : \"Edit Form\"}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {isCreating\n ? \"Design a new form with drag-and-drop fields.\"\n : \"Modify your form fields and settings.\"}\n </p>\n </div>\n\n {/* Action buttons — same variant/size as Collection Builder */}\n <div className=\"flex items-center gap-2 shrink-0\">\n {isDirty && (\n <span className=\"text-xs font-medium text-amber-600 bg-amber-50 border border-amber-200 px-2.5 py-1 rounded-none whitespace-nowrap\">\n Unsaved changes\n </span>\n )}\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={isSaving}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => {\n void handleSave();\n }}\n disabled={isSaving}\n className=\"flex items-center gap-1.5\"\n >\n {isSaving ? (\n <>\n <svg\n className=\"animate-spin h-3.5 w-3.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n Saving…\n </>\n ) : isCreating ? (\n \"Create\"\n ) : (\n \"Save Changes\"\n )}\n </Button>\n </div>\n </div>\n\n {/*\n Outer shell — white card with rounded-none border (no shadow).\n Fills available height in the admin page container.\n */}\n <div\n className=\"flex border border-primary/5 bg-background overflow-hidden\"\n style={{\n borderRadius: \"0.5rem\",\n }}\n >\n {/* =================================================================\n LEFT — scrollable main content\n ================================================================= */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"w-full px-8 pt-8 pb-12 space-y-6\">\n {/* ── Fixed Metadata & Tab Navigation ── */}\n <div className=\"bg-background -mx-8 border-b border-primary/5 space-y-4\">\n <div className=\"flex flex-wrap gap-4\">\n {/* Form Name */}\n <div className=\"flex-1 min-w-[200px] max-w-sm space-y-1.5\">\n <label\n htmlFor=\"form-name\"\n className=\"text-sm font-medium text-foreground\"\n >\n Form Name\n </label>\n <Input\n id=\"form-name\"\n type=\"text\"\n value={formData.name || \"\"}\n onChange={e => handleNameChange(e.target.value)}\n placeholder=\"e.g., Contact Form\"\n className=\"bg-transparent\"\n />\n </div>\n\n {/* Slug */}\n <div className=\"flex-1 min-w-[160px] max-w-xs space-y-1.5\">\n <label\n htmlFor=\"form-slug\"\n className=\"text-sm font-medium text-foreground\"\n >\n Slug\n </label>\n <Input\n id=\"form-slug\"\n type=\"text\"\n value={formData.slug || \"\"}\n onChange={e => updateFormData({ slug: e.target.value })}\n placeholder=\"e.g., contact-form\"\n className=\"bg-transparent placeholder:text-muted-foreground/50\"\n />\n </div>\n\n {/* Status */}\n <div className=\"w-36 space-y-1.5\">\n <label\n htmlFor=\"form-status\"\n className=\"text-sm font-medium text-foreground\"\n >\n Status\n </label>\n <Select\n value={formData.status || \"draft\"}\n onValueChange={value =>\n updateFormData({\n status: value as \"draft\" | \"published\" | \"closed\",\n })\n }\n >\n <SelectTrigger id=\"form-status\" className=\"bg-transparent\">\n <SelectValue placeholder=\"Status\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"draft\">Draft</SelectItem>\n <SelectItem value=\"published\">Published</SelectItem>\n <SelectItem value=\"closed\">Closed</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {/* ── Main tab navigation ── */}\n <Tabs\n value={activeTab}\n onValueChange={v => setActiveTab(v as typeof activeTab)}\n >\n <TabsList className=\"bg-transparent justify-start gap-0 -mb-px border-b-0\">\n {mainTabs.map(tab => (\n <TabsTrigger\n key={tab.value}\n value={tab.value}\n style={{\n borderBottomColor:\n activeTab === tab.value\n ? \"hsl(var(--primary))\"\n : \"transparent\",\n }}\n className=\"border-b-2 relative -mb-0.5 data-[state=active]:text-primary data-[state=inactive]:text-muted-foreground hover:text-primary hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n >\n {tab.label}\n {tab.count !== null && (\n <span\n className={`inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 text-[10px] font-semibold rounded-none ml-2 transition-colors ${\n activeTab === tab.value\n ? \"bg-primary/5 text-primary\"\n : \"bg-primary/5 text-muted-foreground\"\n }`}\n >\n {tab.count}\n </span>\n )}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n </div>\n\n {/* ── Tab content ── */}\n\n {/* Builder tab */}\n {activeTab === \"builder\" && (\n <div>\n <SortableContext\n items={fields.map(f => f.name)}\n strategy={verticalListSortingStrategy}\n >\n <FormCanvas\n fields={fields}\n selectedFieldId={selectedFieldId}\n onFieldSelect={handleFieldSelect}\n onFieldDelete={deleteField}\n />\n </SortableContext>\n </div>\n )}\n\n {/* Preview tab */}\n {activeTab === \"preview\" && (\n <FormPreview fields={fields} formData={formData} />\n )}\n\n {/* Settings tab */}\n {activeTab === \"settings\" && (\n <div className=\"w-full\">\n <FormSettingsTab />\n </div>\n )}\n\n {/* Notifications tab */}\n {activeTab === \"notifications\" && (\n <div className=\"w-full\">\n <FormNotificationsTab />\n </div>\n )}\n\n {/* Save error */}\n {saveError && (\n <div className=\"p-3 text-sm text-destructive bg-destructive/10 border border-destructive/20 rounded-none\">\n {saveError}\n </div>\n )}\n </div>\n </div>\n\n {/* =================================================================\n RIGHT SIDEBAR — 360px, white bg, left border divider\n Only shown in Builder tab.\n ================================================================= */}\n {activeTab === \"builder\" && (\n <div\n className=\"shrink-0 border-l border-primary/5 bg-background flex flex-col\"\n style={{ width: \"360px\" }}\n >\n {/* Sidebar tab bar */}\n <div\n className=\"shrink-0 grid grid-cols-2 gap-1.5 px-3 py-2.5 border-b border-primary/5\"\n style={{ minHeight: \"52px\" }}\n >\n {(\n [\n {\n value: \"add\" as const,\n label: \"Add Fields\",\n disabled: false,\n icon: (\n <svg\n className=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n ),\n },\n {\n value: \"properties\" as const,\n label: \"Properties\",\n disabled: !hasSelectedField,\n icon: <SlidersIcon />,\n },\n ] as const\n ).map(tab => {\n const isActive = sidebarTab === tab.value;\n return (\n <button\n key={tab.value}\n type=\"button\"\n disabled={tab.disabled}\n onClick={() => !tab.disabled && setSidebarTab(tab.value)}\n className={[\n \"flex items-center justify-center gap-1.5 w-full text-[13px] font-medium transition-all duration-150 border rounded-none select-none\",\n \"disabled:opacity-40 disabled:cursor-not-allowed\",\n isActive\n ? \"bg-primary/5 text-primary border-primary/30 cursor-pointer\"\n : \"bg-transparent border-primary/5 text-muted-foreground hover:text-foreground hover:bg-primary/5/50 cursor-pointer\",\n ].join(\" \")}\n style={{ padding: \"8px 12px\" }}\n >\n {tab.icon}\n {tab.label}\n </button>\n );\n })}\n </div>\n\n {/* Sidebar body */}\n <div className=\"flex-1 flex flex-col min-h-0\">\n {/* Add Fields panel */}\n {sidebarTab === \"add\" && (\n <div className=\"flex-1 flex flex-col\">\n <FieldLibrary />\n </div>\n )}\n\n {/* Properties panel */}\n {sidebarTab === \"properties\" && (\n <div className=\"flex-1 flex flex-col relative\">\n {selectedField ? (\n <FieldEditor\n field={selectedField}\n allFields={fields}\n onUpdate={updates =>\n updateField(selectedField.name, updates)\n }\n onDelete={() => {\n deleteField(selectedField.name);\n setSidebarTab(\"add\");\n }}\n onDuplicate={() => duplicateField(selectedField.name)}\n />\n ) : (\n <div className=\"flex flex-col items-center justify-center h-full px-6 py-16 text-center\">\n <div className=\"flex items-center justify-center w-11 h-11 rounded-none bg-primary/5 border border-primary/5 mb-4\">\n <SlidersIcon />\n </div>\n <p className=\"text-sm font-medium text-foreground\">\n No field selected\n </p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n Click a field in the canvas to edit its properties\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n </DndContext>\n );\n}\n\n// ============================================================================\n// Main Component (provides context)\n// ============================================================================\n\nexport function FormBuilderView({\n id,\n entryId,\n collection,\n collectionSlug,\n isCreating,\n initialData,\n onSave,\n onSuccess,\n onCancel,\n}: FormBuilderViewProps) {\n const resolvedEntryId = entryId || id || initialData?.id;\n const resolvedCollectionSlug = collectionSlug || collection || \"forms\";\n const resolvedIsCreating = isCreating ?? !resolvedEntryId;\n const providerKey = resolvedEntryId || \"new\";\n\n return (\n <FormBuilderProvider\n key={providerKey}\n initialData={{\n id: resolvedEntryId,\n name: initialData?.name,\n slug: initialData?.slug,\n description: initialData?.description,\n status: initialData?.status,\n fields: initialData?.fields as FormField[],\n settings: initialData?.settings as Record<string, unknown>,\n notifications: initialData?.notifications as FormNotification[],\n }}\n >\n <FormBuilderViewInner\n isCreating={resolvedIsCreating}\n collectionSlug={resolvedCollectionSlug}\n entryId={resolvedEntryId}\n onSave={onSave}\n onSuccess={onSuccess}\n onCancel={onCancel}\n />\n </FormBuilderProvider>\n );\n}\n\nexport default FormBuilderView;\n","\"use client\";\n\n/**\n * Field Editor\n *\n * Properties panel for editing the selected field's configuration.\n * Provides tabbed interface for General, Validation, and Conditional settings.\n *\n * @module admin/components/builder/FieldEditor\n * @since 0.1.0\n */\n\n\"use client\";\nimport { FormLabelWithTooltip } from \"@nextlyhq/admin\";\nimport {\n Input,\n Button,\n Checkbox,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@nextlyhq/ui\";\nimport { useState, useCallback, useMemo } from \"react\";\n\nimport type {\n FormField,\n TextFormField,\n SelectFormField,\n RadioFormField,\n} from \"../../../types\";\n\nimport { ConditionalLogicEditor } from \"./ConditionalLogicEditor\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FieldEditorProps {\n /** The field being edited */\n field: FormField;\n /** All fields in the form (for conditional logic references) */\n allFields: FormField[];\n /** Callback when field is updated */\n onUpdate: (updates: Partial<FormField>) => void;\n /** Callback when field is deleted */\n onDelete: () => void;\n /** Callback when field is duplicated */\n onDuplicate?: () => void;\n}\n\n// ============================================================================\n// Helper Components\n// ============================================================================\n\n/**\n * General properties tab - common field settings\n */\nfunction GeneralTab({\n field,\n allFields,\n onUpdate,\n}: {\n field: FormField;\n allFields: FormField[];\n onUpdate: (updates: Partial<FormField>) => void;\n}) {\n // Check if other fields have conditional logic referencing this field\n const hasConditionalReferences = useMemo(() => {\n return allFields.some(f => {\n if (f.name === field.name || !f.conditionalLogic?.enabled) return false;\n return f.conditionalLogic.conditions.some(c => c.field === field.name);\n });\n }, [allFields, field.name]);\n\n return (\n <div className=\"space-y-6 py-4\">\n {/* Field Name */}\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Field Name (ID)\"\n htmlFor=\"field-name\"\n description=\"Used as the key in submission data. Should be unique and contain no spaces.\"\n />\n <Input\n id=\"field-name\"\n type=\"text\"\n value={field.name}\n onChange={e => onUpdate({ name: e.target.value })}\n pattern=\"^[a-zA-Z][a-zA-Z0-9_]*$\"\n className=\"bg-transparent\"\n />\n {hasConditionalReferences && (\n <p className=\"text-[11px] text-amber-500 font-medium\">\n ⚠️ Changing this may break conditional logic referencing this field\n </p>\n )}\n </div>\n\n {/* Label - not shown for hidden fields */}\n {field.type !== \"hidden\" && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Label\"\n htmlFor=\"field-label\"\n description=\"The text displayed above the field in the form.\"\n />\n <Input\n id=\"field-label\"\n type=\"text\"\n value={field.label}\n onChange={e => onUpdate({ label: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* Placeholder - for text-like fields */}\n {(field.type === \"text\" ||\n field.type === \"email\" ||\n field.type === \"phone\" ||\n field.type === \"url\" ||\n field.type === \"number\" ||\n field.type === \"textarea\") && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Placeholder\"\n htmlFor=\"field-placeholder\"\n description=\"The faint text shown inside the field when empty.\"\n />\n <Input\n id=\"field-placeholder\"\n type=\"text\"\n value={field.placeholder || \"\"}\n onChange={e => onUpdate({ placeholder: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* Help Text - not shown for hidden fields */}\n {field.type !== \"hidden\" && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Help Text\"\n htmlFor=\"field-help\"\n description=\"Additional instructions displayed below the field.\"\n />\n <Input\n id=\"field-help\"\n type=\"text\"\n value={field.helpText || \"\"}\n onChange={e => onUpdate({ helpText: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* Required - not shown for hidden or checkbox fields */}\n {field.type !== \"hidden\" && field.type !== \"checkbox\" && (\n <div className=\"flex items-center gap-3 pt-1\">\n <Checkbox\n id=\"field-required\"\n checked={field.required || false}\n onCheckedChange={checked =>\n onUpdate({ required: checked === true })\n }\n />\n <FormLabelWithTooltip\n label=\"Required field\"\n htmlFor=\"field-required\"\n description=\"Forces the user to fill this field before submitting.\"\n />\n </div>\n )}\n\n {/* Width */}\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Width\"\n htmlFor=\"field-width\"\n description=\"How much space this field takes in a horizontal row.\"\n />\n <Select\n value={field.admin?.width || \"100%\"}\n onValueChange={value =>\n onUpdate({\n admin: {\n ...field.admin,\n width: value as \"25%\" | \"33%\" | \"50%\" | \"66%\" | \"75%\" | \"100%\",\n },\n })\n }\n >\n <SelectTrigger className=\"w-full bg-transparent border-input dark:bg-slate-900/50\">\n <SelectValue placeholder=\"Select width\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"100%\">Full Width (100%)</SelectItem>\n <SelectItem value=\"75%\">Three Quarters (75%)</SelectItem>\n <SelectItem value=\"66%\">Two Thirds (66%)</SelectItem>\n <SelectItem value=\"50%\">Half (50%)</SelectItem>\n <SelectItem value=\"33%\">One Third (33%)</SelectItem>\n <SelectItem value=\"25%\">One Quarter (25%)</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Type-specific options */}\n <TypeSpecificOptions field={field} onUpdate={onUpdate} />\n </div>\n );\n}\n\n/**\n * Type-specific field options\n */\nfunction TypeSpecificOptions({\n field,\n onUpdate,\n}: {\n field: FormField;\n onUpdate: (updates: Partial<FormField>) => void;\n}) {\n switch (field.type) {\n case \"select\":\n case \"radio\":\n return <OptionsEditor field={field} onUpdate={onUpdate} />;\n\n case \"textarea\": {\n const textareaField = field;\n return (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Rows\"\n htmlFor=\"field-rows\"\n description=\"Height of the textarea in text lines.\"\n />\n <Input\n id=\"field-rows\"\n type=\"number\"\n min={2}\n max={20}\n value={textareaField.rows || 4}\n onChange={e => onUpdate({ rows: parseInt(e.target.value) || 4 })}\n className=\"w-24 bg-transparent\"\n />\n </div>\n );\n }\n\n case \"file\": {\n const fileField = field;\n return (\n <>\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Accepted File Types\"\n htmlFor=\"field-accept\"\n description=\"Comma-separated MIME types (e.g., image/*, application/pdf).\"\n />\n <Input\n id=\"field-accept\"\n type=\"text\"\n value={fileField.accept || \"\"}\n onChange={e => onUpdate({ accept: e.target.value })}\n placeholder=\"image/*,application/pdf\"\n className=\"bg-transparent\"\n />\n </div>\n <div className=\"flex items-center gap-3 pt-1\">\n <Checkbox\n id=\"field-multiple\"\n checked={fileField.multiple || false}\n onCheckedChange={checked =>\n onUpdate({ multiple: checked === true })\n }\n />\n <FormLabelWithTooltip\n label=\"Allow multiple files\"\n htmlFor=\"field-multiple\"\n description=\"Users can upload more than one file at once.\"\n />\n </div>\n <div className=\"flex items-center gap-3 pt-1\">\n <Checkbox\n id=\"field-attach-to-email\"\n checked={fileField.attachToEmail || false}\n onCheckedChange={checked =>\n onUpdate({ attachToEmail: checked === true })\n }\n />\n <FormLabelWithTooltip\n label=\"Attach to notification emails\"\n htmlFor=\"field-attach-to-email\"\n description=\"Uploaded files will be attached to all notification emails for this form.\"\n />\n </div>\n </>\n );\n }\n\n case \"hidden\": {\n const hiddenField = field;\n return (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Default Value\"\n htmlFor=\"field-default\"\n description=\"This value will be submitted silently with the form.\"\n />\n <Input\n id=\"field-default\"\n type=\"text\"\n value={hiddenField.defaultValue || \"\"}\n onChange={e => onUpdate({ defaultValue: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n );\n }\n\n case \"date\": {\n const dateField = field;\n return (\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Minimum Date\"\n htmlFor=\"min-date\"\n description=\"Lower bound for date selection.\"\n />\n <Input\n id=\"min-date\"\n type=\"date\"\n value={dateField.min || \"\"}\n onChange={e => onUpdate({ min: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Maximum Date\"\n htmlFor=\"max-date\"\n description=\"Upper bound for date selection.\"\n />\n <Input\n id=\"max-date\"\n type=\"date\"\n value={dateField.max || \"\"}\n onChange={e => onUpdate({ max: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n </div>\n );\n }\n\n case \"number\": {\n const numField = field;\n return (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Step\"\n htmlFor=\"field-step\"\n description=\"Increment/decrement step (e.g., 0.01 for decimals).\"\n />\n <Input\n id=\"field-step\"\n type=\"number\"\n value={numField.validation?.step || \"\"}\n onChange={e =>\n onUpdate({\n validation: {\n ...numField.validation,\n step: parseFloat(e.target.value) || undefined,\n },\n })\n }\n placeholder=\"1\"\n className=\"w-24 bg-transparent\"\n />\n </div>\n );\n }\n\n default:\n return null;\n }\n}\n\n/**\n * Options editor for select/radio/checkbox-group fields\n */\nfunction OptionsEditor({\n field,\n onUpdate,\n}: {\n field: FormField;\n onUpdate: (updates: Partial<FormField>) => void;\n}) {\n const optionsField = field as SelectFormField | RadioFormField;\n const options = useMemo(\n () => optionsField.options || [],\n [optionsField.options]\n );\n\n const addOption = useCallback(() => {\n const newOptions = [\n ...options,\n {\n label: `Option ${options.length + 1}`,\n value: `option_${options.length + 1}`,\n },\n ];\n onUpdate({ options: newOptions });\n }, [options, onUpdate]);\n\n const updateOption = useCallback(\n (index: number, key: \"label\" | \"value\", value: string) => {\n const newOptions = options.map((opt, i: number) =>\n i === index ? { ...opt, [key]: value } : opt\n );\n onUpdate({ options: newOptions });\n },\n [options, onUpdate]\n );\n\n const removeOption = useCallback(\n (index: number) => {\n const newOptions = options.filter((_, i: number) => i !== index);\n onUpdate({ options: newOptions });\n },\n [options, onUpdate]\n );\n\n return (\n <div className=\"space-y-3 pt-6\">\n <FormLabelWithTooltip\n label=\"Options\"\n description=\"List of choices available for this field.\"\n />\n\n {options.length === 0 ? (\n <div className=\"p-4 bg-primary/5/30 rounded-none border border-dashed border-primary/5 text-center text-xs text-muted-foreground\">\n No options defined. Add an option to get started.\n </div>\n ) : (\n <div className=\"space-y-2\">\n {options.map((opt, index) => (\n <div key={index} className=\"flex items-center gap-2 group\">\n <Input\n type=\"text\"\n value={opt.label}\n onChange={e => updateOption(index, \"label\", e.target.value)}\n placeholder=\"Label\"\n className=\"flex-1 h-9 bg-transparent\"\n />\n <Input\n type=\"text\"\n value={opt.value}\n onChange={e => updateOption(index, \"value\", e.target.value)}\n placeholder=\"Value\"\n className=\"flex-1 h-9 bg-transparent\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => removeOption(index)}\n className=\"h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10\"\n title=\"Remove option\"\n >\n ×\n </Button>\n </div>\n ))}\n </div>\n )}\n\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={addOption}\n className=\"w-full border-dashed text-xs h-8\"\n >\n + Add Option\n </Button>\n </div>\n );\n}\n\n/**\n * Validation tab - field validation settings\n */\nfunction ValidationTab({\n field,\n onUpdate,\n}: {\n field: FormField;\n onUpdate: (updates: Partial<FormField>) => void;\n}) {\n const validation = useMemo(() => field.validation || {}, [field.validation]);\n\n const updateValidation = useCallback(\n (key: string, value: string | number | undefined) => {\n onUpdate({\n validation: { ...validation, [key]: value },\n });\n },\n [validation, onUpdate]\n );\n\n return (\n <div className=\"space-y-6 pt-2\">\n {/* Custom error message */}\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Custom Error Message\"\n htmlFor=\"error-message\"\n description=\"Override the default browser validation message.\"\n />\n <Input\n id=\"error-message\"\n type=\"text\"\n value={validation.errorMessage || \"\"}\n onChange={e => updateValidation(\"errorMessage\", e.target.value)}\n placeholder=\"This field is required\"\n className=\"bg-transparent\"\n />\n </div>\n\n {/* Text/Textarea length validation */}\n {(field.type === \"text\" || field.type === \"textarea\") && (\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Min Length\"\n htmlFor=\"min-len\"\n description=\"Minimum characters required.\"\n />\n <Input\n id=\"min-len\"\n type=\"number\"\n min={0}\n value={(field as TextFormField).validation?.minLength ?? \"\"}\n onChange={e =>\n updateValidation(\n \"minLength\",\n e.target.value ? parseInt(e.target.value) : undefined\n )\n }\n className=\"bg-transparent\"\n />\n </div>\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Max Length\"\n htmlFor=\"max-len\"\n description=\"Maximum characters allowed.\"\n />\n <Input\n id=\"max-len\"\n type=\"number\"\n min={0}\n value={(field as TextFormField).validation?.maxLength ?? \"\"}\n onChange={e =>\n updateValidation(\n \"maxLength\",\n e.target.value ? parseInt(e.target.value) : undefined\n )\n }\n className=\"bg-transparent\"\n />\n </div>\n </div>\n )}\n\n {/* Number min/max validation */}\n {field.type === \"number\" && (\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Min Value\"\n htmlFor=\"min-val\"\n description=\"Minimum numerical value.\"\n />\n <Input\n id=\"min-val\"\n type=\"number\"\n value={field.validation?.min ?? \"\"}\n onChange={e =>\n updateValidation(\n \"min\",\n e.target.value ? parseFloat(e.target.value) : undefined\n )\n }\n className=\"bg-transparent\"\n />\n </div>\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Max Value\"\n htmlFor=\"max-val\"\n description=\"Maximum numerical value.\"\n />\n <Input\n id=\"max-val\"\n type=\"number\"\n value={field.validation?.max ?? \"\"}\n onChange={e =>\n updateValidation(\n \"max\",\n e.target.value ? parseFloat(e.target.value) : undefined\n )\n }\n className=\"bg-transparent\"\n />\n </div>\n </div>\n )}\n\n {/* Pattern validation for text fields */}\n {(field.type === \"text\" ||\n field.type === \"email\" ||\n field.type === \"phone\" ||\n field.type === \"url\") && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Pattern (Regex)\"\n htmlFor=\"val-pattern\"\n description=\"Regular expression for advanced validation.\"\n />\n <Input\n id=\"val-pattern\"\n type=\"text\"\n value={(field as TextFormField).validation?.pattern || \"\"}\n onChange={e => updateValidation(\"pattern\", e.target.value)}\n placeholder=\"^[A-Za-z]+$\"\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* File size validation */}\n {field.type === \"file\" && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Max File Size (bytes)\"\n htmlFor=\"max-file-size\"\n description=\"Maximum allowed size in bytes (10MB ≈ 10485760).\"\n />\n <Input\n id=\"max-file-size\"\n type=\"number\"\n min={0}\n value={field.maxFileSize ?? \"\"}\n onChange={e =>\n onUpdate({\n maxFileSize: e.target.value\n ? parseInt(e.target.value)\n : undefined,\n })\n }\n placeholder=\"10485760\"\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* Info for fields without validation options */}\n {(field.type === \"checkbox\" || field.type === \"hidden\") && (\n <div className=\"p-3 bg-primary/5/30 rounded-none text-xs text-muted-foreground text-center border border-dashed border-primary/5\">\n No additional validation options for this field type.\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * FieldEditor - Field properties configuration panel\n *\n * Provides a tabbed interface for editing field properties:\n * - General: name, label, placeholder, help text, required, width, type-specific options\n * - Validation: error messages, min/max length, patterns, etc.\n * - Conditional: show/hide logic based on other field values\n *\n * @example\n * ```tsx\n * <FieldEditor\n * field={selectedField}\n * allFields={allFields}\n * onUpdate={handleUpdate}\n * onDelete={handleDelete}\n * onDuplicate={handleDuplicate}\n * />\n * ```\n */\nexport function FieldEditor({\n field,\n allFields,\n onUpdate,\n onDelete,\n onDuplicate,\n}: FieldEditorProps) {\n const [activeTab, setActiveTab] = useState<string>(\"general\");\n\n // Get human-readable type label\n const getTypeLabel = (type: string): string => {\n const labels: Record<string, string> = {\n text: \"Text\",\n email: \"Email\",\n number: \"Number\",\n phone: \"Phone\",\n url: \"URL\",\n textarea: \"Textarea\",\n select: \"Select\",\n checkbox: \"Checkbox\",\n radio: \"Radio\",\n file: \"File\",\n date: \"Date\",\n time: \"Time\",\n hidden: \"Hidden\",\n };\n return labels[type] || type;\n };\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Header */}\n <div className=\"p-4 border-b border-primary/5\">\n <h3 className=\"text-sm font-semibold text-foreground flex items-center gap-2\">\n Field Properties\n <span className=\"text-[10px] uppercase tracking-wider px-1.5 py-0.5 rounded-full bg-primary/5 text-primary font-bold dark:bg-primary/20 dark:text-primary-foreground/90\">\n {getTypeLabel(field.type)}\n </span>\n </h3>\n </div>\n\n {/* Tabs */}\n <Tabs\n value={activeTab}\n onValueChange={setActiveTab}\n className=\"flex-1 flex flex-col\"\n >\n <div className=\"border-b bg-primary/5/10 border-primary/5\">\n <TabsList className=\"w-full justify-start gap-0\">\n <TabsTrigger\n value=\"general\"\n className=\"w-full rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-background/50 transition-all\"\n >\n General\n </TabsTrigger>\n <TabsTrigger\n value=\"validation\"\n className=\"w-full rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-background/50 transition-all\"\n >\n Validation\n </TabsTrigger>\n <TabsTrigger\n value=\"conditional\"\n className=\"w-full rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-background/50 transition-all\"\n >\n Conditional\n </TabsTrigger>\n </TabsList>\n </div>\n\n {/* Scrollable Content */}\n <div className=\"flex-1 overflow-y-auto p-4 pb-20\">\n <TabsContent value=\"general\" className=\"mt-0\">\n <GeneralTab\n field={field}\n allFields={allFields}\n onUpdate={onUpdate}\n />\n </TabsContent>\n\n <TabsContent value=\"validation\" className=\"mt-0\">\n <ValidationTab field={field} onUpdate={onUpdate} />\n </TabsContent>\n\n <TabsContent value=\"conditional\" className=\"mt-0\">\n <ConditionalLogicEditor\n field={field}\n allFields={allFields}\n onUpdate={onUpdate}\n />\n </TabsContent>\n </div>\n </Tabs>\n\n {/* Sticky Footer with actions */}\n <div className=\"p-4 bg-background border-t border-primary/5 flex gap-2 shrink-0\">\n {onDuplicate && (\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"flex-1 h-9\"\n onClick={onDuplicate}\n >\n Duplicate\n </Button>\n )}\n <Button\n type=\"button\"\n variant=\"destructive\"\n className=\"flex-1 h-9\"\n onClick={onDelete}\n >\n Delete Field\n </Button>\n </div>\n </div>\n );\n}\n\nexport default FieldEditor;\n","\"use client\";\n\n/**\n * Conditional Logic Editor\n *\n * Component for configuring conditional show/hide logic for form fields.\n * Allows users to define conditions based on other field values.\n *\n * @module admin/components/builder/ConditionalLogicEditor\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { FormLabelWithTooltip } from \"@nextlyhq/admin\";\nimport {\n Input,\n Button,\n Checkbox,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@nextlyhq/ui\";\nimport { useCallback, useMemo } from \"react\";\n\nimport type {\n FormField,\n ConditionalLogic,\n ConditionalLogicCondition,\n} from \"../../../types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ConditionalLogicEditorProps {\n /** The field being edited */\n field: FormField;\n /** All fields in the form (for field references) */\n allFields: FormField[];\n /** Callback when conditional logic is updated */\n onUpdate: (updates: Partial<FormField>) => void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst COMPARISON_OPERATORS: Array<{\n value: ConditionalLogicCondition[\"comparison\"];\n label: string;\n}> = [\n { value: \"equals\", label: \"Equals\" },\n { value: \"notEquals\", label: \"Does not equal\" },\n { value: \"contains\", label: \"Contains\" },\n { value: \"isEmpty\", label: \"Is empty\" },\n { value: \"isNotEmpty\", label: \"Is not empty\" },\n { value: \"greaterThan\", label: \"Greater than\" },\n { value: \"lessThan\", label: \"Less than\" },\n];\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Coerce a condition's `value` (stored as `unknown`) into a string\n * suitable for the controlled `<Input>`. Objects are JSON-stringified\n * so we never render `[object Object]`.\n */\nfunction conditionValueToString(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n // eslint-disable-next-line @typescript-eslint/no-base-to-string -- value narrowed to primitive above; rule doesn't follow control flow on unknown\n return String(value);\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * ConditionalLogicEditor - Configure conditional show/hide logic\n *\n * Allows users to define when a field should be shown or hidden\n * based on the values of other fields in the form.\n *\n * @example\n * ```tsx\n * <ConditionalLogicEditor\n * field={selectedField}\n * allFields={allFields}\n * onUpdate={handleUpdate}\n * />\n * ```\n */\nexport function ConditionalLogicEditor({\n field,\n allFields,\n onUpdate,\n}: ConditionalLogicEditorProps) {\n // Get current conditional logic or create default.\n // Wrapped in useMemo so dependent useCallbacks don't re-create on every render.\n const logic: ConditionalLogic = useMemo(\n () =>\n field.conditionalLogic || {\n enabled: false,\n action: \"show\",\n operator: \"AND\",\n conditions: [],\n },\n [field.conditionalLogic]\n );\n\n // Get other fields that can be referenced (exclude current field)\n const availableFields = allFields.filter(f => f.name !== field.name);\n\n // Update the entire conditional logic object\n const updateLogic = useCallback(\n (updates: Partial<ConditionalLogic>) => {\n onUpdate({\n conditionalLogic: { ...logic, ...updates },\n });\n },\n [logic, onUpdate]\n );\n\n // Toggle enabled state\n const handleToggleEnabled = useCallback(() => {\n updateLogic({ enabled: !logic.enabled });\n }, [logic.enabled, updateLogic]);\n\n // Add a new condition\n const handleAddCondition = useCallback(() => {\n const firstField = availableFields[0];\n if (!firstField) return;\n\n const newCondition: ConditionalLogicCondition = {\n field: firstField.name,\n comparison: \"equals\",\n value: \"\",\n };\n\n updateLogic({\n conditions: [...logic.conditions, newCondition],\n });\n }, [availableFields, logic.conditions, updateLogic]);\n\n // Update a specific condition\n const handleUpdateCondition = useCallback(\n (index: number, updates: Partial<ConditionalLogicCondition>) => {\n const newConditions = logic.conditions.map((c, i) =>\n i === index ? { ...c, ...updates } : c\n );\n updateLogic({ conditions: newConditions });\n },\n [logic.conditions, updateLogic]\n );\n\n // Remove a condition\n const handleRemoveCondition = useCallback(\n (index: number) => {\n const newConditions = logic.conditions.filter((_, i) => i !== index);\n updateLogic({ conditions: newConditions });\n },\n [logic.conditions, updateLogic]\n );\n\n // Check if comparison needs a value input\n const needsValue = (comparison: ConditionalLogicCondition[\"comparison\"]) => {\n return comparison !== \"isEmpty\" && comparison !== \"isNotEmpty\";\n };\n\n return (\n <div className=\"space-y-6 pt-2\">\n {/* Enable toggle */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Checkbox\n id=\"logic-enabled\"\n checked={logic.enabled}\n onCheckedChange={handleToggleEnabled}\n />\n <FormLabelWithTooltip\n label=\"Enable conditional logic\"\n htmlFor=\"logic-enabled\"\n description=\"Show or hide this field based on other field values.\"\n />\n </div>\n </div>\n\n {logic.enabled && (\n <div className=\"space-y-4 pt-4 border-t border-primary/5\">\n {/* Action and operator row */}\n <div className=\"flex flex-wrap items-center gap-2 text-sm text-muted-foreground\">\n <Select\n value={logic.action}\n onValueChange={value =>\n updateLogic({ action: value as \"show\" | \"hide\" })\n }\n >\n <SelectTrigger className=\"w-[100px] h-9 bg-transparent border-input dark:bg-slate-900/50\">\n <SelectValue placeholder=\"Show/Hide\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"show\">Show</SelectItem>\n <SelectItem value=\"hide\">Hide</SelectItem>\n </SelectContent>\n </Select>\n <span>this field when</span>\n <Select\n value={logic.operator}\n onValueChange={value =>\n updateLogic({ operator: value as \"AND\" | \"OR\" })\n }\n >\n <SelectTrigger className=\"w-[80px] h-9 bg-transparent border-input dark:bg-slate-900/50\">\n <SelectValue placeholder=\"All/Any\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"AND\">All</SelectItem>\n <SelectItem value=\"OR\">Any</SelectItem>\n </SelectContent>\n </Select>\n <span>of the following conditions are met:</span>\n </div>\n\n {/* Conditions list */}\n <div className=\"space-y-3 pt-4\">\n {logic.conditions.length === 0 ? (\n <div className=\"p-4 bg-primary/5/30 rounded-none border border-dashed border-primary/5 text-center text-xs text-muted-foreground\">\n No conditions defined. Add a condition to get started.\n </div>\n ) : (\n logic.conditions.map((condition, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 p-3 rounded-none bg-primary/5/20 border border-primary/5 relative group\"\n >\n <div className=\"grid grid-cols-1 gap-2\">\n {/* Field selector */}\n <Select\n value={condition.field}\n onValueChange={value =>\n handleUpdateCondition(index, { field: value })\n }\n >\n <SelectTrigger className=\"w-full bg-transparent border-input dark:bg-slate-900/50\">\n <SelectValue placeholder=\"Select field\" />\n </SelectTrigger>\n <SelectContent>\n {availableFields.map(f => (\n <SelectItem key={f.name} value={f.name}>\n {f.label || f.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <div className=\"flex gap-2\">\n {/* Comparison operator */}\n <Select\n value={condition.comparison}\n onValueChange={value =>\n handleUpdateCondition(index, {\n comparison:\n value as ConditionalLogicCondition[\"comparison\"],\n })\n }\n >\n <SelectTrigger className=\"flex-1 h-9 bg-transparent border-input dark:bg-slate-900/50\">\n <SelectValue placeholder=\"Compare operator\" />\n </SelectTrigger>\n <SelectContent>\n {COMPARISON_OPERATORS.map(op => (\n <SelectItem key={op.value} value={op.value}>\n {op.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {/* Value input (if needed) */}\n {needsValue(condition.comparison) && (\n <Input\n type=\"text\"\n value={conditionValueToString(condition.value)}\n onChange={e =>\n handleUpdateCondition(index, {\n value: e.target.value,\n })\n }\n placeholder=\"Value\"\n className=\"flex-1 h-9 bg-transparent\"\n />\n )}\n </div>\n </div>\n\n {/* Remove button */}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleRemoveCondition(index)}\n className=\"absolute -top-2 -right-2 h-6 w-6 rounded-full bg-background border border-primary/5 opacity-0 group-hover:opacity-100 transition-opacity\"\n title=\"Remove condition\"\n >\n <span className=\"text-xs\">×</span>\n </Button>\n </div>\n ))\n )}\n </div>\n\n {/* Add condition button */}\n {availableFields.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleAddCondition}\n className=\"w-full mt-4 border-dashed\"\n >\n + Add Condition\n </Button>\n ) : (\n <p className=\"mt-4 text-center text-xs text-amber-500 font-medium bg-amber-500/10 p-2 rounded-none border border-amber-500/20\">\n Add more fields to the form to create conditions.\n </p>\n )}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Field Library\n *\n * Displays available field types that can be dragged onto the form canvas.\n * Styled to match the Collection Builder's FieldPalette:\n * - Search input at the top\n * - Accordion category sections (Basic / Advanced)\n * - Blue icon boxes with label + description rows\n * - Drag-to-add and click-to-add support\n *\n * @module admin/components/builder/FieldLibrary\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { useDraggable } from \"@dnd-kit/core\";\nimport { useMemo, useState } from \"react\";\n\nimport type { FormFieldType } from \"../../../types\";\nimport {\n useFormBuilder,\n createFieldFromType,\n} from \"../../context/FormBuilderContext\";\n\n// ============================================================================\n// Field Type Definitions\n// ============================================================================\n\ninterface FieldTypeConfig {\n type: FormFieldType;\n label: string;\n description: string;\n /** Lucide-compatible SVG path data for the icon */\n iconPath: string;\n category: \"basic\" | \"advanced\";\n}\n\nconst FIELD_TYPES: FieldTypeConfig[] = [\n // -------------------------------------------------------------------------\n // Basic\n // -------------------------------------------------------------------------\n {\n type: \"text\",\n label: \"Text\",\n description: \"Single line text input\",\n iconPath: \"M4 7h16M4 12h16M4 17h10\",\n category: \"basic\",\n },\n {\n type: \"email\",\n label: \"Email\",\n description: \"Email address with validation\",\n iconPath:\n \"M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\",\n category: \"basic\",\n },\n {\n type: \"number\",\n label: \"Number\",\n description: \"Numeric input\",\n iconPath: \"M7 20l4-16m2 16l4-16M6 9h14M4 15h14\",\n category: \"basic\",\n },\n {\n type: \"phone\",\n label: \"Phone\",\n description: \"Phone number input\",\n iconPath:\n \"M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498A1 1 0 0121 15.72V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z\",\n category: \"basic\",\n },\n {\n type: \"url\",\n label: \"URL\",\n description: \"Website URL input\",\n iconPath:\n \"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1\",\n category: \"basic\",\n },\n {\n type: \"textarea\",\n label: \"Textarea\",\n description: \"Multi-line text input\",\n iconPath: \"M4 6h16M4 12h16M4 18h7\",\n category: \"basic\",\n },\n {\n type: \"select\",\n label: \"Dropdown\",\n description: \"Dropdown select menu\",\n iconPath: \"M8 9l4-4 4 4m0 6l-4 4-4-4\",\n category: \"basic\",\n },\n {\n type: \"checkbox\",\n label: \"Checkbox\",\n description: \"Single checkbox\",\n iconPath: \"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\",\n category: \"basic\",\n },\n {\n type: \"radio\",\n label: \"Radio\",\n description: \"Radio button group\",\n iconPath:\n \"M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-6a4 4 0 100-8 4 4 0 000 8z\",\n category: \"basic\",\n },\n // -------------------------------------------------------------------------\n // Advanced\n // -------------------------------------------------------------------------\n {\n type: \"file\",\n label: \"File Upload\",\n description: \"File attachment\",\n iconPath:\n \"M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13\",\n category: \"advanced\",\n },\n {\n type: \"date\",\n label: \"Date\",\n description: \"Date picker\",\n iconPath:\n \"M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z\",\n category: \"advanced\",\n },\n {\n type: \"time\",\n label: \"Time\",\n description: \"Time picker\",\n iconPath: \"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\",\n category: \"advanced\",\n },\n {\n type: \"hidden\",\n label: \"Hidden\",\n description: \"Hidden field with static value\",\n iconPath:\n \"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\",\n category: \"advanced\",\n },\n];\n\nconst CATEGORIES = [\n { key: \"basic\" as const, label: \"Basic\" },\n { key: \"advanced\" as const, label: \"Advanced\" },\n];\n\n// ============================================================================\n// Draggable Item\n// ============================================================================\n\nfunction DraggableFieldItem({\n type,\n label,\n description,\n iconPath,\n onAdd,\n}: FieldTypeConfig & { onAdd: (type: FormFieldType) => void }) {\n const { attributes, listeners, setNodeRef, isDragging } = useDraggable({\n id: `library-${type}`,\n data: {\n isLibraryItem: true,\n fieldType: type,\n },\n });\n\n return (\n <button\n ref={setNodeRef}\n type=\"button\"\n onClick={() => onAdd(type)}\n title={description}\n className={`flex items-center gap-3 w-full px-2 py-2 rounded-none text-left group hover:bg-primary/5/50 transition-all duration-150 cursor-grab active:cursor-grabbing active:scale-[0.98] ${\n isDragging ? \"opacity-50 bg-primary/5\" : \"\"\n }`}\n {...attributes}\n {...listeners}\n >\n {/* Blue icon box — same as Collection Builder FieldPalette */}\n <div\n className=\"shrink-0 flex items-center justify-center w-9 h-9 bg-primary/5 text-primary dark:bg-primary/20 dark:text-primary-foreground/80\"\n style={{\n borderRadius: \"6px\",\n border: \"1px solid hsl(var(--primary) / 0.25)\",\n }}\n >\n <svg\n className=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d={iconPath} />\n </svg>\n </div>\n\n {/* Label + description */}\n <div className=\"flex flex-col min-w-0\">\n <span className=\"text-[13px] font-semibold text-foreground leading-snug\">\n {label}\n </span>\n <span className=\"text-[11px] text-muted-foreground/80 leading-snug truncate\">\n {description}\n </span>\n </div>\n </button>\n );\n}\n\n// ============================================================================\n// Category Section (accordion)\n// ============================================================================\n\nfunction CategorySection({\n name,\n types,\n isOpen,\n onToggle,\n onAdd,\n}: {\n name: string;\n types: FieldTypeConfig[];\n isOpen: boolean;\n onToggle: () => void;\n onAdd: (type: FormFieldType) => void;\n}) {\n return (\n <div>\n {/* Accordion trigger */}\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"flex items-center gap-1.5 w-full py-2 px-1 text-left select-none cursor-pointer\"\n >\n {/* Chevron */}\n <svg\n className={`h-3 w-3 transition-transform duration-200 shrink-0 ${\n isOpen ? \"rotate-0\" : \"-rotate-90\"\n }`}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#9ca3af\"\n strokeWidth=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n\n {/* Category name */}\n <span\n className=\"text-[13px] font-semibold tracking-widest uppercase\"\n style={{ color: \"#9ca3af\" }}\n >\n {name}\n </span>\n\n {/* Count badge */}\n <span\n className=\"ml-auto text-[10px] font-medium leading-none\"\n style={{\n background: \"#f3f4f6\",\n color: \"#9ca3af\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n }}\n >\n {types.length}\n </span>\n </button>\n\n {/* Expanded items with vertical left line */}\n {isOpen && (\n <div\n className=\"mb-1 space-y-0.5\"\n style={{\n marginLeft: \"10px\",\n paddingLeft: \"10px\",\n borderLeft: \"1px solid #e5e7eb\",\n }}\n >\n {types.map(field => (\n <DraggableFieldItem key={field.type} {...field} onAdd={onAdd} />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// FieldLibrary Component\n// ============================================================================\n\n/**\n * FieldLibrary — Right-sidebar field type palette\n *\n * Mirrors the Collection Builder's FieldPalette:\n * - Search bar at top\n * - Accordion categories (Basic / Advanced)\n * - Blue icon boxes with draggable rows\n * - Click or drag to add a field\n */\nexport function FieldLibrary() {\n const { addField } = useFormBuilder();\n\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [openSection, setOpenSection] = useState<string>(\"Basic\");\n\n const handleAdd = (type: FormFieldType) => {\n const newField = createFieldFromType(type);\n addField(newField);\n };\n\n const toggleSection = (name: string) => {\n setOpenSection(prev => (prev === name ? \"\" : name));\n };\n\n const isSearching = searchQuery.trim().length > 0;\n\n const filteredCategories = useMemo(() => {\n const byCategory: Record<\"basic\" | \"advanced\", FieldTypeConfig[]> = {\n basic: [],\n advanced: [],\n };\n\n for (const field of FIELD_TYPES) {\n byCategory[field.category].push(field);\n }\n\n return CATEGORIES.map(cat => ({\n ...cat,\n types: byCategory[cat.key].filter(f => {\n if (!isSearching) return true;\n const q = searchQuery.toLowerCase();\n return (\n f.label.toLowerCase().includes(q) ||\n f.type.toLowerCase().includes(q) ||\n f.description.toLowerCase().includes(q)\n );\n }),\n })).filter(c => c.types.length > 0);\n }, [searchQuery, isSearching]);\n\n const activeFieldCount = filteredCategories.reduce(\n (acc, cat) => acc + cat.types.length,\n 0\n );\n\n return (\n <div className=\"h-full flex flex-col bg-background\">\n {/* Search */}\n <div className=\"px-3 py-3 border-b border-primary/5\">\n <div className=\"relative\">\n <svg\n className=\"absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/50\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n <input\n type=\"search\"\n placeholder={`Search ${activeFieldCount} field types...`}\n value={searchQuery}\n onChange={e => setSearchQuery(e.target.value)}\n className=\"text-[13px] pl-9 flex h-9 w-full rounded-none border border-input bg-primary/5/20 px-3 py-1 text-sm shadow-none transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n style={{ borderRadius: \"6px\", height: \"38px\" }}\n />\n </div>\n </div>\n\n {/* Accordion list */}\n <div\n className=\"flex-1 overflow-y-auto px-3 py-3 space-y-3\"\n style={{\n scrollbarWidth: \"none\",\n msOverflowStyle: \"none\",\n }}\n >\n {filteredCategories.map(category => (\n <CategorySection\n key={category.key}\n name={category.label}\n types={category.types}\n isOpen={isSearching ? true : openSection === category.label}\n onToggle={() => toggleSection(category.label)}\n onAdd={handleAdd}\n />\n ))}\n\n {filteredCategories.length === 0 && (\n <div className=\"text-center py-12\">\n <svg\n className=\"h-7 w-7 text-muted-foreground/20 mx-auto mb-2\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n <p className=\"text-sm text-muted-foreground\">No fields found</p>\n </div>\n )}\n </div>\n\n {/* Footer hint */}\n <div className=\"px-3 py-2.5 border-t border-primary/5\">\n <p className=\"text-[11px] text-muted-foreground/50 text-center\">\n Drag fields to the canvas to add them\n </p>\n </div>\n </div>\n );\n}\n\nexport default FieldLibrary;\n","\"use client\";\n\n/**\n * Form Builder Context\n *\n * Provides state management for the Form Builder UI.\n * Manages form fields, selection state, and form metadata.\n *\n * @module admin/context/FormBuilderContext\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport {\n createContext,\n useContext,\n useCallback,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport type { FormField, FormFieldType } from \"../../types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Form settings configuration */\nexport interface FormSettings {\n /** Submit button text */\n submitButtonText: string;\n /** Show reset button */\n showResetButton: boolean;\n /** Reset button text */\n resetButtonText: string;\n /** Success message after submission */\n confirmationMessage: string;\n /** Redirect URL after submission (optional) */\n redirectUrl?: string;\n /** Enable honeypot spam protection */\n honeypotEnabled: boolean;\n /** Enable CAPTCHA */\n captchaEnabled: boolean;\n /** Store submissions in database */\n storeSubmissions: boolean;\n /** Limit submissions per user/IP */\n submissionLimit?: number;\n}\n\n/** Email notification configuration */\nexport interface FormNotification {\n /** Unique ID for this notification */\n id: string;\n /** Notification name */\n name: string;\n /** Whether this notification is enabled */\n enabled: boolean;\n /** ID of the email provider to use; undefined = system default */\n providerId?: string;\n /** Sender email override; undefined = use provider's configured address */\n senderEmail?: string;\n /** How the recipient address is determined */\n recipientType: \"static\" | \"field\";\n /** Recipient address: static email or a {{fieldName}} reference */\n to: string;\n /** CC email addresses */\n cc: string[];\n /** BCC email addresses */\n bcc: string[];\n /** Slug of the email template to use */\n templateSlug?: string;\n}\n\nexport interface FormBuilderState {\n /** Form fields array */\n fields: FormField[];\n /** Currently selected field ID (name) */\n selectedFieldId: string | null;\n /** Active tab: builder, preview, settings, or notifications */\n activeTab: \"builder\" | \"preview\" | \"settings\" | \"notifications\";\n /** Whether form has unsaved changes */\n isDirty: boolean;\n /** Form metadata */\n formData: {\n id?: string;\n name: string;\n slug: string;\n description?: string;\n status: \"draft\" | \"published\" | \"closed\";\n };\n /** Form settings */\n settings: FormSettings;\n /** Email notifications */\n notifications: FormNotification[];\n}\n\nexport interface FormBuilderActions {\n /** Set all fields */\n setFields: (fields: FormField[]) => void;\n /** Add a new field */\n addField: (field: FormField, index?: number) => void;\n /** Update a field by name */\n updateField: (fieldName: string, updates: Partial<FormField>) => void;\n /** Delete a field by name */\n deleteField: (fieldName: string) => void;\n /** Move a field from one index to another */\n moveField: (fromIndex: number, toIndex: number) => void;\n /** Duplicate a field */\n duplicateField: (fieldName: string) => void;\n /** Select a field */\n selectField: (fieldName: string | null) => void;\n /** Set active tab */\n setActiveTab: (\n tab: \"builder\" | \"preview\" | \"settings\" | \"notifications\"\n ) => void;\n /** Update form metadata */\n updateFormData: (updates: Partial<FormBuilderState[\"formData\"]>) => void;\n /** Update form settings */\n updateSettings: (updates: Partial<FormSettings>) => void;\n /** Add a notification */\n addNotification: (notification: FormNotification) => void;\n /** Update a notification */\n updateNotification: (id: string, updates: Partial<FormNotification>) => void;\n /** Delete a notification */\n deleteNotification: (id: string) => void;\n /** Mark form as saved (clears dirty flag) */\n markAsSaved: () => void;\n}\n\nexport interface FormBuilderContextValue\n extends FormBuilderState,\n FormBuilderActions {}\n\nexport interface FormBuilderProviderProps {\n /** Initial form data (for editing existing forms) */\n initialData?: {\n id?: string;\n name?: string;\n slug?: string;\n description?: string;\n status?: \"draft\" | \"published\" | \"closed\";\n fields?: FormField[];\n settings?: Partial<FormSettings>;\n notifications?: FormNotification[];\n };\n /** Child components */\n children: ReactNode;\n}\n\n/** Default form settings */\nexport const DEFAULT_SETTINGS: FormSettings = {\n submitButtonText: \"Submit\",\n showResetButton: false,\n resetButtonText: \"Reset\",\n confirmationMessage: \"Thank you for your submission!\",\n redirectUrl: undefined,\n honeypotEnabled: true,\n captchaEnabled: false,\n storeSubmissions: true,\n submissionLimit: undefined,\n};\n\n/** Create a new email integration with default values */\nexport function createNotification(): FormNotification {\n const id = `notif_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 6)}`;\n return {\n id,\n name: \"Email Notification\",\n enabled: true,\n recipientType: \"static\",\n to: \"\",\n cc: [],\n bcc: [],\n };\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst FormBuilderContext = createContext<FormBuilderContextValue | null>(null);\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Generate a unique field name based on type and timestamp.\n */\nexport function generateFieldName(type: FormFieldType): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 6);\n return `${type}_${timestamp}_${random}`;\n}\n\n/**\n * Generate a human-readable label from field type.\n */\nexport function generateFieldLabel(type: FormFieldType): string {\n const labels: Record<FormFieldType, string> = {\n text: \"Text Field\",\n email: \"Email Address\",\n number: \"Number\",\n phone: \"Phone Number\",\n url: \"Website URL\",\n textarea: \"Text Area\",\n select: \"Dropdown\",\n checkbox: \"Checkbox\",\n radio: \"Radio Buttons\",\n file: \"File Upload\",\n date: \"Date\",\n time: \"Time\",\n hidden: \"Hidden Field\",\n };\n return labels[type] || \"New Field\";\n}\n\n/**\n * Create a new field from a field type with default values.\n */\nexport function createFieldFromType(type: FormFieldType): FormField {\n const name = generateFieldName(type);\n const label = generateFieldLabel(type);\n\n const baseField = {\n name,\n label,\n required: false,\n };\n\n switch (type) {\n case \"text\":\n return { ...baseField, type: \"text\" };\n\n case \"email\":\n return { ...baseField, type: \"email\", label: \"Email Address\" };\n\n case \"number\":\n return { ...baseField, type: \"number\" };\n\n case \"phone\":\n return { ...baseField, type: \"phone\", label: \"Phone Number\" };\n\n case \"url\":\n return { ...baseField, type: \"url\", label: \"Website\" };\n\n case \"textarea\":\n return { ...baseField, type: \"textarea\", rows: 4 };\n\n case \"select\":\n return {\n ...baseField,\n type: \"select\",\n options: [\n { label: \"Option 1\", value: \"option_1\" },\n { label: \"Option 2\", value: \"option_2\" },\n ],\n };\n\n case \"checkbox\":\n return { ...baseField, type: \"checkbox\" };\n\n case \"radio\":\n return {\n ...baseField,\n type: \"radio\",\n options: [\n { label: \"Option 1\", value: \"option_1\" },\n { label: \"Option 2\", value: \"option_2\" },\n ],\n };\n\n case \"file\":\n return { ...baseField, type: \"file\" };\n\n case \"date\":\n return { ...baseField, type: \"date\" };\n\n case \"time\":\n return { ...baseField, type: \"time\" };\n\n case \"hidden\":\n return { ...baseField, type: \"hidden\", label: \"Hidden Field\" };\n\n default:\n return { ...baseField, type: \"text\" };\n }\n}\n\n// ============================================================================\n// Provider\n// ============================================================================\n\n/**\n * FormBuilderProvider - Provides form builder state to child components\n *\n * Wraps the form builder UI to provide centralized state management\n * for fields, selection, and form metadata.\n *\n * @example\n * ```tsx\n * <FormBuilderProvider initialData={existingForm}>\n * <FormBuilderView />\n * </FormBuilderProvider>\n * ```\n */\nexport function FormBuilderProvider({\n initialData,\n children,\n}: FormBuilderProviderProps) {\n // State\n const [fields, setFieldsState] = useState<FormField[]>(\n initialData?.fields || []\n );\n const [selectedFieldId, setSelectedFieldId] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState<\n \"builder\" | \"preview\" | \"settings\" | \"notifications\"\n >(\"builder\");\n const [isDirty, setIsDirty] = useState(false);\n const [formData, setFormData] = useState<FormBuilderState[\"formData\"]>({\n id: initialData?.id,\n name: initialData?.name || \"\",\n slug: initialData?.slug || \"\",\n description: initialData?.description,\n status: initialData?.status || \"draft\",\n });\n const [settings, setSettings] = useState<FormSettings>({\n ...DEFAULT_SETTINGS,\n ...initialData?.settings,\n });\n const [notifications, setNotifications] = useState<FormNotification[]>(\n initialData?.notifications || []\n );\n\n // Actions\n const setFields = useCallback((newFields: FormField[]) => {\n setFieldsState(newFields);\n setIsDirty(true);\n }, []);\n\n const addField = useCallback((field: FormField, index?: number) => {\n setFieldsState(prev => {\n if (index !== undefined && index >= 0 && index <= prev.length) {\n const newFields = [...prev];\n newFields.splice(index, 0, field);\n return newFields;\n }\n return [...prev, field];\n });\n setSelectedFieldId(field.name);\n setIsDirty(true);\n }, []);\n\n const updateField = useCallback(\n (fieldName: string, updates: Partial<FormField>) => {\n setFieldsState(prev =>\n prev.map(f =>\n f.name === fieldName ? ({ ...f, ...updates } as FormField) : f\n )\n );\n // If the field name is being changed, also update selectedFieldId\n // This prevents the sidebar from disappearing when renaming a field\n if (updates.name && updates.name !== fieldName) {\n setSelectedFieldId(updates.name);\n }\n setIsDirty(true);\n },\n []\n );\n\n const deleteField = useCallback(\n (fieldName: string) => {\n setFieldsState(prev => prev.filter(f => f.name !== fieldName));\n if (selectedFieldId === fieldName) {\n setSelectedFieldId(null);\n }\n setIsDirty(true);\n },\n [selectedFieldId]\n );\n\n const moveField = useCallback((fromIndex: number, toIndex: number) => {\n setFieldsState(prev => {\n if (\n fromIndex < 0 ||\n fromIndex >= prev.length ||\n toIndex < 0 ||\n toIndex >= prev.length\n ) {\n return prev;\n }\n const newFields = [...prev];\n const [removed] = newFields.splice(fromIndex, 1);\n newFields.splice(toIndex, 0, removed);\n return newFields;\n });\n setIsDirty(true);\n }, []);\n\n const duplicateField = useCallback((fieldName: string) => {\n let newFieldName: string | null = null;\n\n setFieldsState(prev => {\n const fieldIndex = prev.findIndex(f => f.name === fieldName);\n if (fieldIndex === -1) return prev;\n\n const field = prev[fieldIndex];\n newFieldName = generateFieldName(field.type);\n const newField: FormField = {\n ...field,\n name: newFieldName,\n label: `${field.label} (Copy)`,\n };\n\n const newFields = [...prev];\n newFields.splice(fieldIndex + 1, 0, newField);\n return newFields;\n });\n\n // Select the duplicated field so it appears in the editor panel\n if (newFieldName) {\n setSelectedFieldId(newFieldName);\n }\n setIsDirty(true);\n }, []);\n\n const selectField = useCallback((fieldName: string | null) => {\n setSelectedFieldId(fieldName);\n }, []);\n\n const updateFormData = useCallback(\n (updates: Partial<FormBuilderState[\"formData\"]>) => {\n setFormData(prev => ({ ...prev, ...updates }));\n setIsDirty(true);\n },\n []\n );\n\n const updateSettings = useCallback((updates: Partial<FormSettings>) => {\n setSettings(prev => ({ ...prev, ...updates }));\n setIsDirty(true);\n }, []);\n\n const addNotification = useCallback((notification: FormNotification) => {\n setNotifications(prev => [...prev, notification]);\n setIsDirty(true);\n }, []);\n\n const updateNotification = useCallback(\n (id: string, updates: Partial<FormNotification>) => {\n setNotifications(prev =>\n prev.map(n => (n.id === id ? { ...n, ...updates } : n))\n );\n setIsDirty(true);\n },\n []\n );\n\n const deleteNotification = useCallback((id: string) => {\n setNotifications(prev => prev.filter(n => n.id !== id));\n setIsDirty(true);\n }, []);\n\n const markAsSaved = useCallback(() => {\n setIsDirty(false);\n }, []);\n\n // Memoized context value\n const value = useMemo<FormBuilderContextValue>(\n () => ({\n // State\n fields,\n selectedFieldId,\n activeTab,\n isDirty,\n formData,\n settings,\n notifications,\n // Actions\n setFields,\n addField,\n updateField,\n deleteField,\n moveField,\n duplicateField,\n selectField,\n setActiveTab,\n updateFormData,\n updateSettings,\n addNotification,\n updateNotification,\n deleteNotification,\n markAsSaved,\n }),\n [\n fields,\n selectedFieldId,\n activeTab,\n isDirty,\n formData,\n settings,\n notifications,\n setFields,\n addField,\n updateField,\n deleteField,\n moveField,\n duplicateField,\n selectField,\n updateFormData,\n updateSettings,\n addNotification,\n updateNotification,\n deleteNotification,\n markAsSaved,\n ]\n );\n\n return (\n <FormBuilderContext.Provider value={value}>\n {children}\n </FormBuilderContext.Provider>\n );\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * useFormBuilder - Access form builder context\n *\n * Hook to access form builder state and actions from within the builder UI.\n * Must be used within a FormBuilderProvider.\n *\n * @returns Form builder context value\n * @throws Error if used outside of FormBuilderProvider\n *\n * @example\n * ```tsx\n * function FieldList() {\n * const { fields, selectField, deleteField } = useFormBuilder();\n *\n * return (\n * <ul>\n * {fields.map(field => (\n * <li key={field.name} onClick={() => selectField(field.name)}>\n * {field.label}\n * <button onClick={() => deleteField(field.name)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useFormBuilder(): FormBuilderContextValue {\n const context = useContext(FormBuilderContext);\n\n if (!context) {\n throw new Error(\"useFormBuilder must be used within a FormBuilderProvider\");\n }\n\n return context;\n}\n\n/**\n * useOptionalFormBuilder - Access form builder context safely\n *\n * Like useFormBuilder but returns null if not within a provider.\n * Useful for components that may be rendered outside of the form builder.\n *\n * @returns Form builder context value or null\n */\nexport function useOptionalFormBuilder(): FormBuilderContextValue | null {\n return useContext(FormBuilderContext);\n}\n","/**\n * Form Canvas\n *\n * Drop zone where form fields are arranged and can be reordered.\n * Styled to match the Collection Builder's FieldList:\n * - Full-width horizontal rows\n * - Blue icon boxes (matching FieldPalette items)\n * - GripVertical drag handle on the left\n * - Type badge + Required badge on the right\n * - Dashed-border empty state\n *\n * @module admin/components/builder/FormCanvas\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { useDroppable } from \"@dnd-kit/core\";\nimport { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\n\nimport type { FormField } from \"../../../types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FormCanvasProps {\n fields: FormField[];\n selectedFieldId: string | null;\n onFieldSelect: (fieldName: string | null) => void;\n onFieldDelete: (fieldName: string) => void;\n}\n\n// ============================================================================\n// Field Type Icon SVG paths (inline Lucide-compatible)\n// ============================================================================\n\nconst FIELD_ICON_PATHS: Record<string, string> = {\n text: \"M4 7h16M4 12h16M4 17h10\",\n email:\n \"M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\",\n number: \"M7 20l4-16m2 16l4-16M6 9h14M4 15h14\",\n phone:\n \"M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498A1 1 0 0121 15.72V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z\",\n url: \"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1\",\n textarea: \"M4 6h16M4 12h16M4 18h7\",\n select: \"M8 9l4-4 4 4m0 6l-4 4-4-4\",\n checkbox: \"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\",\n radio:\n \"M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-6a4 4 0 100-8 4 4 0 000 8z\",\n file: \"M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13\",\n date: \"M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z\",\n time: \"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\",\n hidden:\n \"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\",\n};\n\nconst DEFAULT_ICON_PATH = \"M4 7h16M4 12h16M4 17h10\";\n\nconst FIELD_TYPE_LABELS: Record<string, string> = {\n text: \"Text\",\n email: \"Email\",\n number: \"Number\",\n phone: \"Phone\",\n url: \"URL\",\n textarea: \"Textarea\",\n select: \"Dropdown\",\n checkbox: \"Checkbox\",\n radio: \"Radio\",\n file: \"File Upload\",\n date: \"Date\",\n time: \"Time\",\n hidden: \"Hidden\",\n};\n\n// ============================================================================\n// SortableFieldItem — Full-width horizontal row (mirrors FieldList)\n// ============================================================================\n\nfunction SortableFieldItem({\n field,\n isSelected,\n onSelect,\n onDelete,\n}: {\n field: FormField;\n isSelected: boolean;\n onSelect: () => void;\n onDelete: () => void;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: field.name });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n const iconPath = FIELD_ICON_PATHS[field.type] || DEFAULT_ICON_PATH;\n const typeLabel = FIELD_TYPE_LABELS[field.type] || field.type;\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n onClick={onSelect}\n role=\"button\"\n tabIndex={0}\n onKeyDown={e => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onSelect();\n }\n }}\n className={`flex items-center gap-3 py-3 px-4 border border-solid rounded-none cursor-pointer transition-all duration-150 group outline-none focus:outline-none focus:ring-0 ${\n isSelected\n ? \"bg-transparent dark:bg-transparent shadow-none ring-0\"\n : \"border-primary/5 dark:border-primary/5 dark:bg-transparent dark:hover:bg-transparent\"\n } ${isDragging ? \"opacity-50\" : \"\"}`}\n >\n {/* Drag Handle — GripVertical */}\n <button\n type=\"button\"\n className=\"p-1 shrink-0 cursor-grab active:cursor-grabbing text-muted-foreground/30 hover:text-muted-foreground transition-colors\"\n aria-label={`Drag to reorder ${field.label || field.name}`}\n onClick={e => e.stopPropagation()}\n {...attributes}\n {...listeners}\n >\n <svg\n className=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n {/* GripVertical dots */}\n <circle cx=\"9\" cy=\"5\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"9\" cy=\"12\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"9\" cy=\"19\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"5\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"12\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"19\" r=\"1\" fill=\"currentColor\" />\n </svg>\n </button>\n\n {/* Field type icon box — blue, matches FieldPalette */}\n <div\n className=\"shrink-0 flex items-center justify-center w-9 h-9 bg-primary/5 text-primary dark:bg-primary/20 dark:text-white mr-1\"\n style={{\n borderRadius: \"6px\",\n border: \"1px solid hsl(var(--primary) / 0.25)\",\n }}\n >\n <svg\n className=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d={iconPath} />\n </svg>\n </div>\n\n {/* Field info */}\n <div className=\"flex-1 flex items-center gap-2 min-w-0 flex-wrap\">\n <span className=\"text-sm font-medium text-foreground truncate\">\n {field.label || field.name || \"Unnamed Field\"}\n </span>\n <span className=\"text-muted-foreground/40 text-xs shrink-0\">•</span>\n <span className=\"text-[10px] font-medium shrink-0 px-2 py-0 leading-5 rounded-full border border-primary/5 bg-primary/5 text-muted-foreground capitalize\">\n {typeLabel}\n </span>\n {field.required && (\n <span className=\"text-[10px] px-2 py-0 leading-5 bg-red-50 text-red-600 dark:bg-red-500/20 dark:text-red-400 font-normal rounded-full border border-red-200 dark:border-red-500/30 shrink-0\">\n Required\n </span>\n )}\n </div>\n\n {/* Delete button — visible on hover */}\n <button\n type=\"button\"\n onClick={e => {\n e.stopPropagation();\n onDelete();\n }}\n title={`Delete ${field.label || field.name}`}\n aria-label={`Delete ${field.label || field.name}`}\n className=\"shrink-0 flex items-center justify-center w-7 h-7 rounded-none text-muted-foreground/40 hover:text-destructive hover:bg-destructive/10 transition-all duration-150 opacity-0 group-hover:opacity-100\"\n >\n <svg\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a1 1 0 011-1h4a1 1 0 011 1v2\" />\n </svg>\n </button>\n </div>\n );\n}\n\n// ============================================================================\n// FormCanvas Component\n// ============================================================================\n\nexport function FormCanvas({\n fields,\n selectedFieldId,\n onFieldSelect,\n onFieldDelete,\n}: FormCanvasProps) {\n const { setNodeRef, isOver } = useDroppable({\n id: \"canvas-drop-zone\",\n });\n\n // Empty state — dashed border, centred icon + text (mirrors Collection Builder)\n if (fields.length === 0) {\n return (\n <div\n ref={setNodeRef}\n id=\"canvas-drop-zone\"\n className={`min-h-[320px] flex flex-col items-center justify-center border-2 border-dashed rounded-none transition-all duration-200 ${\n isOver ? \"border-primary bg-primary/5\" : \"border-primary/5 bg-primary/5/20\"\n }`}\n >\n <div className=\"text-center px-6 py-12\">\n {/* Arrow-down icon */}\n <div\n className={`mx-auto mb-4 flex items-center justify-center w-12 h-12 rounded-none border transition-colors ${\n isOver\n ? \"border-primary/30 bg-primary/5 text-primary\"\n : \"border-primary/5 bg-primary/5 text-muted-foreground/40\"\n }`}\n >\n <svg\n className=\"h-5 w-5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <polyline points=\"19 12 12 19 5 12\" />\n </svg>\n </div>\n <p\n className={`text-sm font-medium mb-1 ${\n isOver ? \"text-primary\" : \"text-foreground\"\n }`}\n >\n {isOver ? \"Release to add field\" : \"No fields yet\"}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {isOver\n ? \"Drop the field here\"\n : \"Drag a field from the panel on the right to add it here\"}\n </p>\n </div>\n </div>\n );\n }\n\n // Fields present\n return (\n <div\n ref={setNodeRef}\n className={`min-h-[120px] transition-all duration-200 ${\n isOver ? \"bg-primary/5 rounded-none\" : \"\"\n }`}\n >\n {/* Field rows */}\n <div className=\"space-y-2\">\n {fields.map(field => (\n <SortableFieldItem\n key={field.name}\n field={field}\n isSelected={selectedFieldId === field.name}\n onSelect={() => onFieldSelect(field.name)}\n onDelete={() => onFieldDelete(field.name)}\n />\n ))}\n </div>\n\n {/* Drop-here strip at bottom when dragging */}\n {isOver && (\n <div className=\"mt-2 flex items-center justify-center py-3 rounded-none border-2 border-dashed border-primary bg-primary/5\">\n <p className=\"text-xs font-medium text-primary\">\n Release to add field here\n </p>\n </div>\n )}\n </div>\n );\n}\n\nexport default FormCanvas;\n","\"use client\";\n\n/**\n * Form Notifications Tab\n *\n * Email integration configuration panel for form submissions.\n * Allows selecting existing email providers and templates for notifications.\n *\n * @module admin/components/builder/FormNotificationsTab\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { Button, Input } from \"@nextlyhq/ui\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport {\n useFormBuilder,\n createNotification,\n type FormNotification,\n} from \"../../context/FormBuilderContext\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface ProviderOption {\n id: string;\n name: string;\n type: string;\n isDefault: boolean;\n}\n\ninterface TemplateOption {\n id: string;\n name: string;\n slug: string;\n isActive: boolean;\n}\n\n// ============================================================================\n// API helpers\n// ============================================================================\n\nasync function fetchProviders(): Promise<ProviderOption[]> {\n try {\n const res = await fetch(\"/admin/api/email-providers?pageSize=100&page=1\", {\n credentials: \"include\",\n });\n if (!res.ok) return [];\n const json = (await res.json()) as { providers?: ProviderOption[] };\n return json.providers ?? [];\n } catch {\n return [];\n }\n}\n\nasync function fetchTemplates(): Promise<TemplateOption[]> {\n try {\n const res = await fetch(\"/admin/api/email-templates\", {\n credentials: \"include\",\n });\n if (!res.ok) return [];\n const json = (await res.json()) as { templates?: TemplateOption[] };\n return json.templates ?? [];\n } catch {\n return [];\n }\n}\n\n// ============================================================================\n// Integration Card\n// ============================================================================\n\ninterface IntegrationCardProps {\n notification: FormNotification;\n providerName: string;\n onEdit: () => void;\n onDelete: () => void;\n}\n\nfunction IntegrationCard({\n notification,\n providerName,\n onEdit,\n onDelete,\n}: IntegrationCardProps) {\n return (\n <div\n className={`form-integration-card ${!notification.enabled ? \"form-integration-card--disabled\" : \"\"}`}\n >\n <div className=\"form-integration-card-left\">\n <div className=\"form-integration-card-info\">\n <span className=\"form-integration-card-name\">\n {notification.name}\n </span>\n <span className=\"form-integration-provider-badge\">\n Provider: {providerName}\n </span>\n </div>\n </div>\n <div className=\"form-integration-card-actions\">\n <button\n type=\"button\"\n className=\"form-integration-btn form-integration-btn--edit\"\n onClick={onEdit}\n >\n Edit\n </button>\n <button\n type=\"button\"\n className=\"form-integration-btn form-integration-btn--delete\"\n onClick={onDelete}\n >\n Delete\n </button>\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// Integration Modal\n// ============================================================================\n\ninterface IntegrationModalProps {\n initial: FormNotification;\n providers: ProviderOption[];\n templates: TemplateOption[];\n fields: { name: string; label: string }[];\n isEditing: boolean;\n onSave: (notification: FormNotification) => void;\n onCancel: () => void;\n}\n\nfunction IntegrationModal({\n initial,\n providers,\n templates,\n fields,\n isEditing,\n onSave,\n onCancel,\n}: IntegrationModalProps) {\n const [form, setForm] = useState<FormNotification>(initial);\n const [newCc, setNewCc] = useState(\"\");\n const [newBcc, setNewBcc] = useState(\"\");\n const overlayRef = useRef<HTMLDivElement>(null);\n\n const update = useCallback(\n <K extends keyof FormNotification>(key: K, value: FormNotification[K]) => {\n setForm(prev => ({ ...prev, [key]: value }));\n },\n []\n );\n\n const addCc = useCallback(() => {\n const email = newCc.trim();\n if (!email) return;\n setForm(prev => ({ ...prev, cc: [...prev.cc, email] }));\n setNewCc(\"\");\n }, [newCc]);\n\n const removeCc = useCallback((index: number) => {\n setForm(prev => ({ ...prev, cc: prev.cc.filter((_, i) => i !== index) }));\n }, []);\n\n const addBcc = useCallback(() => {\n const email = newBcc.trim();\n if (!email) return;\n setForm(prev => ({ ...prev, bcc: [...prev.bcc, email] }));\n setNewBcc(\"\");\n }, [newBcc]);\n\n const removeBcc = useCallback((index: number) => {\n setForm(prev => ({ ...prev, bcc: prev.bcc.filter((_, i) => i !== index) }));\n }, []);\n\n const handleSubmit = useCallback(() => {\n onSave(form);\n }, [form, onSave]);\n\n const handleOverlayClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === overlayRef.current) {\n onCancel();\n }\n },\n [onCancel]\n );\n\n const defaultProvider = providers.find(p => p.isDefault);\n const defaultLabel = defaultProvider\n ? `System Default (${defaultProvider.name})`\n : \"System Default\";\n\n return (\n <div\n className=\"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm flex items-center justify-center p-4 sm:p-6\"\n ref={overlayRef}\n onClick={handleOverlayClick}\n >\n <div className=\"bg-background rounded-none border border-primary/5 shadow-md w-full max-w-lg overflow-hidden flex flex-col max-h-[90vh]\">\n <div className=\"px-6 py-5 border-b border-primary/5 flex items-center justify-between sticky top-0 bg-background z-10\">\n <h3 className=\"text-lg font-semibold text-foreground\">\n {isEditing ? \"Edit Email Integration\" : \"Add Email Integration\"}\n </h3>\n <button\n onClick={onCancel}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n </div>\n\n <div className=\"p-6 overflow-y-auto space-y-6\">\n {/* Integration Name */}\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n Integration Name\n </label>\n <Input\n type=\"text\"\n value={form.name}\n onChange={e => update(\"name\", e.target.value)}\n placeholder=\"e.g. Admin Notification\"\n />\n </div>\n\n {/* Email Provider & Template */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n Email Provider\n </label>\n <select\n className=\"flex h-9 w-full rounded-none border border-input bg-transparent px-3 py-1 text-sm shadow-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={form.providerId ?? \"\"}\n onChange={e =>\n update(\"providerId\", e.target.value || undefined)\n }\n >\n <option value=\"\">{defaultLabel}</option>\n {providers.map(p => (\n <option key={p.id} value={p.id}>\n {p.name}\n {p.isDefault ? \" (Default)\" : \"\"}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n Email Template\n </label>\n <select\n className=\"flex h-9 w-full rounded-none border border-input bg-transparent px-3 py-1 text-sm shadow-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={form.templateSlug ?? \"\"}\n onChange={e =>\n update(\"templateSlug\", e.target.value || undefined)\n }\n >\n <option value=\"\">Select an email template</option>\n {templates\n .filter(t => t.isActive)\n .map(t => (\n <option key={t.id} value={t.slug}>\n {t.name}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n {/* Sender Email */}\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n Sender Email\n </label>\n <Input\n type=\"email\"\n value={form.senderEmail ?? \"\"}\n onChange={e => update(\"senderEmail\", e.target.value || undefined)}\n placeholder=\"noreply@example.com\"\n />\n <p className=\"text-xs text-muted-foreground\">\n Leave blank to use the provider's default configured address.\n </p>\n </div>\n\n {/* Recipient Configuration */}\n <div className=\"space-y-4 pt-4 border-t border-primary/5\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n Recipient Type\n </label>\n <select\n className=\"flex h-9 w-full rounded-none border border-input bg-transparent px-3 py-1 text-sm shadow-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={form.recipientType}\n onChange={e =>\n update(\n \"recipientType\",\n e.target.value as \"static\" | \"field\"\n )\n }\n >\n <option value=\"static\">Static Email Address</option>\n <option value=\"field\">Email from Form Field</option>\n </select>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n {form.recipientType === \"field\"\n ? \"Target Email Field\"\n : \"Recipient Email\"}\n </label>\n {form.recipientType === \"field\" ? (\n <select\n className=\"flex h-9 w-full rounded-none border border-input bg-transparent px-3 py-1 text-sm shadow-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={form.to}\n onChange={e => update(\"to\", e.target.value)}\n >\n <option value=\"\">Select a field</option>\n {fields.map(f => (\n <option key={f.name} value={`{{${f.name}}}`}>\n {f.label} ({`{{${f.name}}}`})\n </option>\n ))}\n </select>\n ) : (\n <Input\n type=\"email\"\n value={form.to}\n onChange={e => update(\"to\", e.target.value)}\n placeholder=\"admin@example.com\"\n />\n )}\n </div>\n </div>\n\n {/* CC Recipients */}\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n CC Recipients (Optional)\n </label>\n {form.cc.length > 0 && (\n <div className=\"flex flex-wrap gap-2 mb-2\">\n {form.cc.map((email, i) => (\n <div\n key={i}\n className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-primary/5 text-xs font-medium border border-primary/5\"\n >\n <span>{email}</span>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground hover:bg-background rounded-full p-0.5\"\n onClick={() => removeCc(i)}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n </div>\n ))}\n </div>\n )}\n <div className=\"flex items-center gap-2\">\n <Input\n type=\"email\"\n value={newCc}\n onChange={e => setNewCc(e.target.value)}\n onKeyDown={e => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n addCc();\n }\n }}\n placeholder=\"cc@example.com\"\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={addCc}\n className=\"shrink-0 px-3\"\n >\n Add CC\n </Button>\n </div>\n </div>\n\n {/* BCC Recipients */}\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n BCC Recipients (Optional)\n </label>\n {form.bcc.length > 0 && (\n <div className=\"flex flex-wrap gap-2 mb-2\">\n {form.bcc.map((email, i) => (\n <div\n key={i}\n className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-primary/5 text-xs font-medium border border-primary/5\"\n >\n <span>{email}</span>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground hover:bg-background rounded-full p-0.5\"\n onClick={() => removeBcc(i)}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n </div>\n ))}\n </div>\n )}\n <div className=\"flex items-center gap-2\">\n <Input\n type=\"email\"\n value={newBcc}\n onChange={e => setNewBcc(e.target.value)}\n onKeyDown={e => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n addBcc();\n }\n }}\n placeholder=\"bcc@example.com\"\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={addBcc}\n className=\"shrink-0 px-3\"\n >\n Add BCC\n </Button>\n </div>\n </div>\n </div>\n\n <div className=\"pt-4 border-t border-primary/5 flex items-center justify-between\">\n <div>\n <label className=\"text-sm font-medium text-foreground\">\n Enable Integration\n </label>\n <p className=\"text-xs text-muted-foreground\">\n Toggle to turn on/off without removing.\n </p>\n </div>\n <label className=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n className=\"sr-only peer\"\n checked={form.enabled}\n onChange={e => update(\"enabled\", e.target.checked)}\n />\n <div className=\"w-9 h-5 bg-primary/5 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-primary/20 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-primary/5 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-primary border border-primary/5\"></div>\n </label>\n </div>\n </div>\n\n <div className=\"px-6 py-4 border-t border-primary/5 bg-primary/5/20 flex items-center justify-end gap-3 rounded-b-xl\">\n <Button type=\"button\" variant=\"outline\" onClick={onCancel}>\n Cancel\n </Button>\n <Button type=\"button\" onClick={handleSubmit}>\n {isEditing ? \"Save Changes\" : \"Add Integration\"}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * FormNotificationsTab - Email integrations configuration\n *\n * Allows users to configure email integrations that trigger when a form is\n * submitted. Each integration references an existing email provider and\n * template rather than duplicating provider credentials.\n */\nexport function FormNotificationsTab() {\n const {\n notifications,\n fields,\n addNotification,\n updateNotification,\n deleteNotification,\n } = useFormBuilder();\n\n const [providers, setProviders] = useState<ProviderOption[]>([]);\n const [templates, setTemplates] = useState<TemplateOption[]>([]);\n const [modalState, setModalState] = useState<{\n open: boolean;\n editing: FormNotification | null;\n }>({ open: false, editing: null });\n\n useEffect(() => {\n void fetchProviders().then(setProviders);\n void fetchTemplates().then(setTemplates);\n }, []);\n\n const fieldList = fields.map(f => ({ name: f.name, label: f.label }));\n\n const openAddModal = useCallback(() => {\n setModalState({ open: true, editing: null });\n }, []);\n\n const openEditModal = useCallback((notification: FormNotification) => {\n setModalState({ open: true, editing: notification });\n }, []);\n\n const closeModal = useCallback(() => {\n setModalState({ open: false, editing: null });\n }, []);\n\n const handleSave = useCallback(\n (notification: FormNotification) => {\n if (modalState.editing) {\n updateNotification(notification.id, notification);\n } else {\n addNotification(notification);\n }\n closeModal();\n },\n [modalState.editing, addNotification, updateNotification, closeModal]\n );\n\n const getProviderName = useCallback(\n (providerId?: string) => {\n if (!providerId) {\n const def = providers.find(p => p.isDefault);\n return def ? `${def.name} (Default)` : \"System Default\";\n }\n return providers.find(p => p.id === providerId)?.name ?? \"Unknown\";\n },\n [providers]\n );\n\n const initialNotification = modalState.editing ?? createNotification();\n\n return (\n <div className=\"form-notifications-tab\">\n <div className=\"flex items-center justify-between mb-8 pb-4 border-b border-primary/5\">\n <div>\n <h3 className=\"text-xl font-semibold text-foreground\">\n Email Integrations\n </h3>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Configure email notifications sent when someone submits this form.\n </p>\n </div>\n <Button type=\"button\" onClick={openAddModal}>\n + Add Integration\n </Button>\n </div>\n\n {/* List */}\n {notifications.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center p-12 mt-6 border-2 border-dashed border-primary/5 rounded-none bg-primary/5/20\">\n <div className=\"flex items-center justify-center w-12 h-12 rounded-none border border-primary/5 bg-background mb-4 text-primary\">\n <svg\n className=\"h-6 w-6\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" />\n <path d=\"Mm22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n </div>\n <p className=\"text-base font-medium text-foreground mb-1\">\n No email integrations yet\n </p>\n <p className=\"text-sm text-muted-foreground mb-6 text-center max-w-sm\">\n Add an email integration to notify recipients when someone submits\n this form.\n </p>\n <Button type=\"button\" onClick={openAddModal}>\n + Add Integration\n </Button>\n </div>\n ) : (\n <div className=\"form-notifications-list\">\n {notifications.map(notification => (\n <IntegrationCard\n key={notification.id}\n notification={notification}\n providerName={getProviderName(notification.providerId)}\n onEdit={() => openEditModal(notification)}\n onDelete={() => deleteNotification(notification.id)}\n />\n ))}\n </div>\n )}\n\n {/* Modal */}\n {modalState.open && (\n <IntegrationModal\n initial={initialNotification}\n providers={providers}\n templates={templates}\n fields={fieldList}\n isEditing={!!modalState.editing}\n onSave={handleSave}\n onCancel={closeModal}\n />\n )}\n </div>\n );\n}\n\nexport default FormNotificationsTab;\n","/**\n * Form Preview\n *\n * Renders a preview of how the form will appear to end users.\n * Shows the form layout with input fields rendered in a disabled\n * (read-only) state so submissions cannot be made from the preview.\n *\n * @module admin/components/builder/FormPreview\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { Input, Button } from \"@nextlyhq/ui\";\nimport type React from \"react\";\n\nimport type { FormField } from \"../../../types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FormPreviewProps {\n /** Array of form fields to preview */\n fields: FormField[];\n /** Form metadata */\n formData?: {\n name?: string;\n slug?: string;\n description?: string;\n status?: string;\n };\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * FormPreview - Visual form preview\n *\n * This is a stub component that shows a preview of the form.\n * The full implementation will include:\n * - Rendered form fields with proper styling\n * - Responsive preview modes (desktop, tablet, mobile)\n * - Theme preview options\n * - Conditional logic simulation\n *\n * @example\n * ```tsx\n * <FormPreview fields={fields} formData={formData} />\n * ```\n */\nexport function FormPreview({ fields, formData }: FormPreviewProps) {\n if (fields.length === 0) {\n return (\n <div className=\"flex flex-col items-center justify-center p-12 bg-primary/5/20 rounded-none border-2 border-dashed border-primary/5 text-center\">\n <div className=\"text-4xl mb-3\">📝</div>\n <p className=\"text-sm font-medium text-muted-foreground\">\n Add some fields to preview your form\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"bg-background max-w-2xl mt-8\">\n <div className=\"mb-8\">\n <h2 className=\"text-2xl font-bold text-foreground\">\n {formData?.name || \"Untitled Form\"}\n </h2>\n {formData?.description && (\n <p className=\"text-sm text-muted-foreground mt-2\">\n {formData.description}\n </p>\n )}\n </div>\n\n <div className=\"space-y-6\">\n {fields.map(field => (\n <div key={field.name} className=\"flex flex-col gap-1.5\">\n <label className=\"text-sm font-medium text-foreground\">\n {field.label}\n {field.required && (\n <span className=\"text-destructive ml-1\">*</span>\n )}\n </label>\n\n {renderFieldPreview(field)}\n\n {field.helpText && (\n <p className=\"text-xs text-muted-foreground mt-1\">\n {field.helpText}\n </p>\n )}\n </div>\n ))}\n </div>\n\n <div className=\"mt-8 pt-6 border-t border-primary/5 flex items-center gap-4\">\n <Button type=\"button\" disabled>\n Submit\n </Button>\n <p className=\"text-xs text-muted-foreground\">\n This is a preview. Submissions are disabled.\n </p>\n </div>\n </div>\n );\n}\n\n/**\n * Render a preview of a field based on its type\n */\nfunction renderFieldPreview(field: FormField): React.ReactNode {\n switch (field.type) {\n case \"text\":\n case \"email\":\n case \"phone\":\n case \"url\":\n return (\n <Input\n type={field.type === \"email\" ? \"email\" : \"text\"}\n placeholder={\n field.placeholder || `Enter ${field.label.toLowerCase()}`\n }\n disabled\n />\n );\n\n case \"number\":\n return (\n <Input\n type=\"number\"\n placeholder={field.placeholder || \"Enter a number\"}\n disabled\n />\n );\n\n case \"textarea\":\n return (\n <textarea\n className=\"flex w-full rounded-none border border-input bg-transparent px-3 py-2 text-sm shadow-none placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n placeholder={\n field.placeholder || `Enter ${field.label.toLowerCase()}`\n }\n rows={field.rows || 4}\n disabled\n />\n );\n\n case \"select\":\n return (\n <select\n className=\"flex h-9 w-full items-center justify-between rounded-none border border-input bg-transparent px-3 py-2 text-sm shadow-none focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n disabled\n >\n <option value=\"\">Select an option</option>\n {field.options?.map(opt => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n );\n\n case \"checkbox\":\n return (\n <div className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n className=\"h-4 w-4 rounded border-input text-primary focus:ring-primary\"\n disabled\n />\n <span className=\"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\">\n {field.label}\n </span>\n </div>\n );\n\n case \"radio\":\n return (\n <div className=\"flex flex-col space-y-2\">\n {field.options?.map(opt => (\n <div key={opt.value} className=\"flex items-center space-x-2\">\n <input\n type=\"radio\"\n name={field.name}\n className=\"h-4 w-4 rounded-full border border-input text-primary focus:ring-primary\"\n disabled\n />\n <span className=\"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\">\n {opt.label}\n </span>\n </div>\n ))}\n </div>\n );\n\n case \"file\":\n return (\n <div className=\"flex items-center\">\n <Input type=\"file\" disabled />\n </div>\n );\n\n case \"date\":\n return <Input type=\"date\" disabled />;\n\n case \"time\":\n return <Input type=\"time\" disabled />;\n\n case \"hidden\":\n return (\n <div className=\"flex items-center gap-2 p-3 text-sm text-muted-foreground bg-primary/5/20 border-2 border-dashed border-primary/5 rounded-none\">\n <span className=\"text-lg\">👁️</span>\n <span>Hidden field</span>\n </div>\n );\n\n default:\n return <Input type=\"text\" placeholder=\"Unknown field type\" disabled />;\n }\n}\n\nexport default FormPreview;\n","\"use client\";\n\nimport {\n Input,\n Textarea,\n Tabs,\n TabsList,\n TabsTrigger,\n Switch,\n} from \"@nextlyhq/ui\";\nimport type React from \"react\";\n\nimport { useFormBuilder } from \"../../context/FormBuilderContext\";\n\n// ============================================================================\n// Helper Components\n// ============================================================================\n\n/**\n * SettingRow - A layout component for a single setting with label and description on the left,\n * and the control/input on the right.\n */\nfunction SettingRow({\n label,\n description,\n children,\n className = \"\",\n}: {\n label: string;\n description?: string;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div\n className={`flex flex-col sm:flex-row sm:items-center justify-between gap-6 py-2 ${className}`}\n >\n <div className=\"space-y-1 max-w-xl\">\n <h4 className=\"text-[13px] font-semibold text-foreground tracking-tight\">\n {label}\n </h4>\n {description && (\n <p className=\"text-[12px] text-muted-foreground leading-relaxed\">\n {description}\n </p>\n )}\n </div>\n <div className=\"flex-shrink-0 flex items-center justify-end min-w-[100px]\">\n {children}\n </div>\n </div>\n );\n}\n\n/**\n * FormSettingsTab - Form settings configuration panel\n *\n * Refined for Antigravity standard:\n * - Two-column layout for better space utilization.\n * - Title Case headings with improved hierarchy.\n * - Robust state management for action tabs.\n */\nexport function FormSettingsTab() {\n const { settings, updateSettings } = useFormBuilder();\n\n // Handle tab switch for After Submission\n // We check for undefined specifically so empty strings \"\" are treated as \"redirect\"\n const currentActionTab =\n settings.redirectUrl !== undefined ? \"redirect\" : \"message\";\n\n return (\n <div className=\"w-full flex flex-row gap-8\">\n {/* Left Column: Submission & After Submission */}\n <div className=\"w-full flex flex-col gap-8\">\n {/* Submission Settings */}\n <section className=\"mb-12\">\n <div className=\"border-b border-primary/5 pb-3\">\n <h3 className=\"text-[16px] font-bold text-foreground tracking-tight\">\n Submission Settings\n </h3>\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <SettingRow\n label=\"Submit Button Text\"\n description=\"Label on the primary action button\"\n >\n <Input\n type=\"text\"\n value={settings.submitButtonText}\n onChange={e =>\n updateSettings({ submitButtonText: e.target.value })\n }\n placeholder=\"Submit\"\n className=\"bg-transparent h-8 w-40 text-right pr-2 focus-visible:ring-1 border-primary/5 text-[13px]\"\n />\n </SettingRow>\n\n <SettingRow\n label=\"Show Reset Button\"\n description=\"Lets users clear all fields at once\"\n >\n <Switch\n checked={settings.showResetButton}\n onCheckedChange={(checked: boolean) =>\n updateSettings({ showResetButton: checked })\n }\n />\n </SettingRow>\n\n {settings.showResetButton && (\n <SettingRow\n label=\"Reset Button Text\"\n description=\"Label on the secondary action button\"\n className=\"animate-in fade-in slide-in-from-top-2 duration-300\"\n >\n <Input\n type=\"text\"\n value={settings.resetButtonText}\n onChange={e =>\n updateSettings({ resetButtonText: e.target.value })\n }\n placeholder=\"Reset\"\n className=\"bg-transparent h-8 w-40 text-right pr-2 focus-visible:ring-1 border-primary/5 text-[13px]\"\n />\n </SettingRow>\n )}\n </div>\n </section>\n\n {/* After Submission */}\n <section className=\"mb-12\">\n <div className=\"border-b border-primary/5 pb-3\">\n <h3 className=\"text-[16px] font-bold text-foreground tracking-tight\">\n After Submission\n </h3>\n </div>\n\n <div className=\"flex flex-col gap-4\">\n <SettingRow\n label=\"Action\"\n description=\"What happens after the form is submitted\"\n >\n <Tabs\n value={currentActionTab}\n onValueChange={v => {\n if (v === \"message\") {\n updateSettings({ redirectUrl: undefined });\n } else if (v === \"redirect\") {\n updateSettings({ redirectUrl: \"\" });\n }\n }}\n >\n <TabsList className=\"bg-primary/5 p-1 h-8\">\n <TabsTrigger\n value=\"message\"\n className=\"px-4 py-1 text-[11px] font-medium data-[state=active]:bg-background data-[state=active]:shadow-sm\"\n >\n Message\n </TabsTrigger>\n <TabsTrigger\n value=\"redirect\"\n className=\"px-4 py-1 text-[11px] font-medium data-[state=active]:bg-background data-[state=active]:shadow-sm\"\n >\n Redirect\n </TabsTrigger>\n </TabsList>\n </Tabs>\n </SettingRow>\n\n {currentActionTab === \"message\" ? (\n <div className=\"pt-2 animate-in fade-in duration-300\">\n <div className=\"space-y-1.5 mb-4\">\n <h4 className=\"text-[13px] font-semibold text-foreground tracking-tight\">\n Confirmation Message\n </h4>\n <p className=\"text-[12px] text-muted-foreground leading-relaxed\">\n Message shown to user after successful submission\n </p>\n </div>\n <Textarea\n id=\"confirmationMessage\"\n value={settings.confirmationMessage}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n updateSettings({ confirmationMessage: e.target.value })\n }\n placeholder=\"Thank you for your submission!\"\n rows={4}\n className=\"bg-transparent text-[13px] leading-relaxed w-full border-primary/5 focus-visible:ring-1\"\n />\n </div>\n ) : (\n <div className=\"pt-2 animate-in fade-in duration-300\">\n <SettingRow\n label=\"Redirect URL\"\n description=\"User will be redirected to this URL after submission\"\n >\n <Input\n type=\"url\"\n value={settings.redirectUrl || \"\"}\n onChange={e =>\n updateSettings({ redirectUrl: e.target.value })\n }\n placeholder=\"https://example.com/thank-you\"\n className=\"bg-transparent h-8 w-56 text-right pr-2 focus-visible:ring-1 border-primary/5 text-[13px]\"\n />\n </SettingRow>\n </div>\n )}\n </div>\n </section>\n </div>\n\n {/* Right Column: Spam Protection & Data Storage */}\n <div className=\"w-full flex flex-col gap-8\">\n {/* Spam Protection */}\n <section>\n <div className=\"border-b border-primary/5 pb-3\">\n <h3 className=\"text-[16px] font-bold text-foreground tracking-tight\">\n Spam Protection\n </h3>\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <SettingRow\n label=\"Honeypot Field\"\n description=\"Hidden field that silently catches bots\"\n >\n <Switch\n checked={settings.honeypotEnabled}\n onCheckedChange={(checkedValue: boolean) =>\n updateSettings({ honeypotEnabled: checkedValue })\n }\n />\n </SettingRow>\n\n <SettingRow\n label=\"CAPTCHA Challenge\"\n description=\"Human verification before submitting\"\n >\n <Switch\n checked={settings.captchaEnabled}\n onCheckedChange={(checkedValue: boolean) =>\n updateSettings({ captchaEnabled: checkedValue })\n }\n />\n </SettingRow>\n </div>\n </section>\n\n {/* Data Storage */}\n <section>\n <div className=\"border-b border-primary/5 pb-3\">\n <h3 className=\"text-[16px] font-bold text-foreground tracking-tight\">\n Data Storage\n </h3>\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <SettingRow\n label=\"Store Submissions\"\n description=\"Save responses to the database\"\n >\n <Switch\n checked={settings.storeSubmissions}\n onCheckedChange={(checkedValue: boolean) =>\n updateSettings({ storeSubmissions: checkedValue })\n }\n />\n </SettingRow>\n\n <SettingRow\n label=\"Submission Limit\"\n description=\"Max number of entries to store\"\n >\n <div className=\"flex items-center gap-3\">\n <Input\n type=\"number\"\n value={settings.submissionLimit || \"\"}\n onChange={e =>\n updateSettings({\n submissionLimit: e.target.value\n ? parseInt(e.target.value, 10)\n : undefined,\n })\n }\n placeholder=\"Unlimited\"\n min={1}\n className=\"bg-transparent h-8 w-28 text-right pr-2 focus-visible:ring-1 border-primary/5 text-[13px]\"\n />\n <span className=\"text-[12px] text-muted-foreground font-medium\">\n Entries\n </span>\n </div>\n </SettingRow>\n </div>\n </section>\n </div>\n </div>\n );\n}\n\nexport default FormSettingsTab;\n","\"use client\";\n\n/**\n * Form Field List Component\n *\n * A sortable list container for form fields with drag-and-drop reordering.\n * Uses @dnd-kit for accessible drag-and-drop functionality.\n *\n * Features:\n * - Drag-and-drop reordering via @dnd-kit\n * - Keyboard-accessible drag operations (Arrow keys)\n * - PointerSensor with 8px activation distance (prevents accidental drags)\n * - Empty state display when no fields exist\n * - Visual feedback during drag operations\n *\n * This component provides the DndContext and SortableContext wrappers.\n * Individual field rows are rendered using SortableFieldRow which uses\n * the useSortable hook for drag-and-drop functionality.\n *\n * @module admin/components/FormFieldList\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { useCallback } from \"react\";\n\nimport type { FormField } from \"../../types\";\n\nimport { SortableFieldRow } from \"./SortableFieldRow\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FormFieldListProps {\n /**\n * Array of form fields to display.\n */\n fields: FormField[];\n\n /**\n * Callback when fields are reordered via drag-and-drop.\n * Receives the new array with fields in updated order.\n */\n onFieldsChange: (fields: FormField[]) => void;\n\n /**\n * Callback when a field is selected for editing.\n * Receives the field name (unique identifier).\n */\n onEditField: (fieldName: string) => void;\n\n /**\n * Callback when a field should be deleted.\n * Receives the field name (unique identifier).\n */\n onDeleteField: (fieldName: string) => void;\n\n /**\n * Currently selected field name for highlighting.\n */\n selectedFieldName?: string | null;\n\n /**\n * Whether the list is disabled (no interactions allowed).\n * @default false\n */\n disabled?: boolean;\n}\n\n// ============================================================================\n// FormFieldList Component\n// ============================================================================\n\n/**\n * FormFieldList provides a drag-and-drop sortable container for form fields.\n *\n * This component wraps fields with DndContext and SortableContext from @dnd-kit,\n * enabling drag-and-drop reordering with full keyboard accessibility.\n *\n * The component follows the pattern established by ArrayInput.tsx in the\n * Nextly admin package:\n * - PointerSensor with 8px activation distance (prevents accidental drags)\n * - KeyboardSensor with sortableKeyboardCoordinates (arrow key navigation)\n * - closestCenter collision detection\n * - verticalListSortingStrategy for vertical lists\n *\n * @example\n * ```tsx\n * <FormFieldList\n * fields={formFields}\n * onFieldsChange={setFormFields}\n * onEditField={(name) => setSelectedField(name)}\n * onDeleteField={(name) => handleDeleteField(name)}\n * selectedFieldName={selectedField}\n * />\n * ```\n */\nexport function FormFieldList({\n fields,\n onFieldsChange,\n onEditField,\n onDeleteField,\n selectedFieldName,\n disabled = false,\n}: FormFieldListProps) {\n // ---------------------------------------------------------------------------\n // Sensor Setup\n // ---------------------------------------------------------------------------\n\n // PointerSensor: mouse/touch with 8px activation distance to prevent accidental drags\n // KeyboardSensor: Arrow keys for accessibility (WCAG 2.2 compliance)\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 8,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // ---------------------------------------------------------------------------\n // Drag Handlers\n // ---------------------------------------------------------------------------\n\n /**\n * Handle drag end - reorder fields using arrayMove.\n */\n const handleDragEnd = useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = fields.findIndex(f => f.name === active.id);\n const newIndex = fields.findIndex(f => f.name === over.id);\n\n if (oldIndex !== -1 && newIndex !== -1) {\n const newFields = arrayMove(fields, oldIndex, newIndex);\n onFieldsChange(newFields);\n }\n }\n },\n [fields, onFieldsChange]\n );\n\n // ---------------------------------------------------------------------------\n // Empty State\n // ---------------------------------------------------------------------------\n\n if (fields.length === 0) {\n return (\n <div className=\"form-field-list form-field-list--empty\">\n <div className=\"form-field-list__empty-state\">\n <div className=\"form-field-list__empty-icon\" aria-hidden=\"true\">\n 📋\n </div>\n <p className=\"form-field-list__empty-title\">No fields yet</p>\n <p className=\"form-field-list__empty-hint\">\n Click "Add Field" to get started\n </p>\n </div>\n </div>\n );\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n return (\n <div className=\"form-field-list\">\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext\n items={fields.map(f => f.name)}\n strategy={verticalListSortingStrategy}\n disabled={disabled}\n >\n <div className=\"form-field-list__fields\" role=\"list\">\n {fields.map(field => (\n <SortableFieldRow\n key={field.name}\n field={field}\n isSelected={selectedFieldName === field.name}\n onSelect={() => onEditField(field.name)}\n onDelete={() => onDeleteField(field.name)}\n disabled={disabled}\n />\n ))}\n </div>\n </SortableContext>\n </DndContext>\n\n {/* Footer hint */}\n <div className=\"form-field-list__footer\">\n <p className=\"form-field-list__footer-text\">\n {fields.length} field{fields.length !== 1 ? \"s\" : \"\"} • Drag to\n reorder • Click to edit\n </p>\n </div>\n </div>\n );\n}\n\nexport default FormFieldList;\n","\"use client\";\n\n/**\n * Sortable Field Row Component\n *\n * A draggable row component for form fields in the Visual Form Builder.\n * Uses @dnd-kit's useSortable hook for drag-and-drop reordering.\n *\n * Features:\n * - Drag handle with GripVertical icon for reordering\n * - Visual feedback during drag operations (opacity, ring, shadow)\n * - Field type icon and label display\n * - Required field indicator\n * - Delete button with keyboard accessibility\n * - WCAG 2.2 compliant with proper ARIA attributes\n *\n * This component follows the pattern established by ArrayRow.tsx in the\n * Nextly admin package for consistency across the codebase.\n *\n * @module admin/components/SortableFieldRow\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { GripVertical, Trash2 } from \"lucide-react\";\nimport { useCallback } from \"react\";\n\nimport type { FormField } from \"../../types\";\nimport {\n getFieldTypeIcon,\n getFieldTypeLabel,\n resolveFieldIcon,\n} from \"../fields\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SortableFieldRowProps {\n /**\n * The form field to display.\n */\n field: FormField;\n\n /**\n * Whether this row is currently selected for editing.\n */\n isSelected: boolean;\n\n /**\n * Callback when the row is clicked/selected.\n */\n onSelect: () => void;\n\n /**\n * Callback when the delete button is clicked.\n */\n onDelete: () => void;\n\n /**\n * Whether the row is disabled (no interactions allowed).\n * @default false\n */\n disabled?: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * SortableFieldRow renders a single draggable field row in the form builder.\n *\n * Uses @dnd-kit's useSortable hook to enable drag-and-drop reordering.\n * The component displays:\n * - A drag handle (GripVertical icon) for reordering\n * - The field type icon\n * - The field label (or name as fallback) with required indicator\n * - The field type badge\n * - A delete button\n *\n * Visual feedback is provided during drag operations:\n * - Reduced opacity (50%)\n * - Primary color ring (2px)\n * - Elevated shadow\n * - Higher z-index\n *\n * @example\n * ```tsx\n * <SortableFieldRow\n * field={field}\n * isSelected={selectedFieldName === field.name}\n * onSelect={() => setSelectedFieldName(field.name)}\n * onDelete={() => handleDeleteField(field.name)}\n * />\n * ```\n */\nexport function SortableFieldRow({\n field,\n isSelected,\n onSelect,\n onDelete,\n disabled = false,\n}: SortableFieldRowProps) {\n // ---------------------------------------------------------------------------\n // @dnd-kit Sortable Hook\n // ---------------------------------------------------------------------------\n\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({\n id: field.name,\n disabled,\n });\n\n // Apply CSS transform for drag animation\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n // ---------------------------------------------------------------------------\n // Field Type Info\n // ---------------------------------------------------------------------------\n\n const iconName = getFieldTypeIcon(field.type);\n const typeLabel = getFieldTypeLabel(field.type);\n const IconComponent = resolveFieldIcon(iconName);\n\n // ---------------------------------------------------------------------------\n // Event Handlers\n // ---------------------------------------------------------------------------\n\n /**\n * Handle delete button click.\n * Stops propagation to prevent row selection.\n */\n const handleDelete = useCallback(\n (e: React.MouseEvent | React.KeyboardEvent) => {\n e.stopPropagation();\n onDelete();\n },\n [onDelete]\n );\n\n /**\n * Handle keyboard navigation on the row.\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onSelect();\n }\n },\n [onSelect]\n );\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n // Build class names based on state\n const rowClassName = [\n \"form-field-row\",\n isSelected && \"form-field-row--selected\",\n isDragging && \"form-field-row--dragging\",\n disabled && \"form-field-row--disabled\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={rowClassName}\n onClick={onSelect}\n onKeyDown={handleKeyDown}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-label={`${field.label || field.name} field, type: ${typeLabel}${isSelected ? \", selected\" : \"\"}`}\n aria-pressed={isSelected}\n aria-disabled={disabled}\n >\n {/* Drag Handle */}\n {!disabled && (\n <button\n type=\"button\"\n className=\"form-field-row__drag-handle\"\n aria-label={`Drag to reorder ${field.label || field.name}`}\n {...attributes}\n {...listeners}\n >\n <GripVertical className=\"form-field-row__drag-icon\" />\n </button>\n )}\n\n {/* Spacer when drag handle is hidden */}\n {disabled && <div className=\"form-field-row__drag-handle-spacer\" />}\n\n {/* Field Type Icon */}\n <span className=\"form-field-row__type-icon\" aria-hidden=\"true\">\n <IconComponent className=\"form-field-row__icon\" />\n </span>\n\n {/* Field Content */}\n <div className=\"form-field-row__content\">\n <span className=\"form-field-row__label\">\n {field.label || field.name}\n {field.required && (\n <span className=\"form-field-row__required\" aria-label=\"Required\">\n *\n </span>\n )}\n </span>\n <span className=\"form-field-row__type-badge\">{typeLabel}</span>\n </div>\n\n {/* Actions */}\n <div className=\"form-field-row__actions\">\n <button\n type=\"button\"\n className=\"form-field-row__action form-field-row__action--delete\"\n onClick={handleDelete}\n onKeyDown={e => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleDelete(e);\n }\n }}\n disabled={disabled}\n aria-label={`Delete ${field.label || field.name}`}\n title=\"Delete field\"\n >\n <Trash2 className=\"form-field-row__action-icon\" />\n </button>\n </div>\n </div>\n );\n}\n\nexport default SortableFieldRow;\n","/**\n * Form Field Type Registry\n *\n * Central registry for all supported field types in the Visual Form Builder.\n * Used by AddFieldModal to display available field types grouped by category.\n *\n * Supported Field Types:\n * - Core Fields (8): text, textarea, email, number, checkbox, select, radio, date\n *\n * @module admin/fields\n * @since 0.1.0\n */\n\nimport {\n AlignLeft,\n Calendar,\n CheckSquare,\n ChevronDown,\n Circle,\n FileText,\n Hash,\n Mail,\n Type,\n type LucideIcon,\n} from \"lucide-react\";\nimport type { ComponentType } from \"react\";\n\nimport type { FormField, FormFieldType } from \"../../types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Props for field editor components.\n *\n * Each field type has a dedicated editor component that receives these props.\n */\nexport interface FieldEditorProps<T extends FormField = FormField> {\n /** The field being edited */\n field: T;\n /** All fields in the form (for references, e.g., state -> country linking) */\n allFields: FormField[];\n /** Callback to update field properties */\n onUpdate: (updates: Partial<T>) => void;\n}\n\n/**\n * Field type configuration for the admin UI.\n *\n * Defines metadata and components for each supported field type.\n */\nexport interface FieldTypeConfig {\n /** Field type identifier (matches FormFieldType) */\n type: FormFieldType;\n /** Display name in field selector */\n label: string;\n /** Lucide icon name */\n icon: string;\n /** Short description shown in field selector */\n description: string;\n /** Category for grouping in the Add Field modal */\n category: \"core\";\n /**\n * Editor component for configuring field properties.\n * Lazy-loaded for code splitting.\n *\n * Note: Uses `any` for the component type to allow field-specific editors.\n * The actual editor component will receive the correctly typed field.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n EditorComponent: () => Promise<{ default: ComponentType<any> }>;\n /** Default field configuration when added to form */\n defaultConfig: Partial<FormField> & { type: FormFieldType };\n}\n\n/**\n * Field type category configuration.\n */\nexport interface FieldCategory {\n /** Category key */\n key: \"core\";\n /** Display label */\n label: string;\n /** Description of the category */\n description: string;\n}\n\n// ============================================================================\n// Category Definitions\n// ============================================================================\n\n/**\n * Field type categories for organizing the Add Field modal.\n */\nexport const FIELD_CATEGORIES: FieldCategory[] = [\n {\n key: \"core\",\n label: \"Core Fields\",\n description: \"Essential form input fields\",\n },\n];\n\n// ============================================================================\n// Field Type Definitions\n// ============================================================================\n\n/**\n * Supported field types.\n *\n * This registry defines 8 field types that cover the most common form use cases:\n * - Contact forms\n * - Registration forms\n * - Surveys and feedback\n *\n * Additional field types (phone, url, file, time, hidden)\n * can be added in future iterations.\n */\nexport const FIELD_TYPES: FieldTypeConfig[] = [\n // ---------------------------------------------------------------------------\n // Core Fields (7 types)\n // ---------------------------------------------------------------------------\n {\n type: \"text\",\n label: \"Text\",\n icon: \"Type\",\n description: \"Single-line text input\",\n category: \"core\",\n EditorComponent: () => import(\"./TextFieldEditor\"),\n defaultConfig: {\n type: \"text\",\n label: \"Text Field\",\n placeholder: \"\",\n required: false,\n },\n },\n {\n type: \"textarea\",\n label: \"Textarea\",\n icon: \"AlignLeft\",\n description: \"Multi-line text input\",\n category: \"core\",\n EditorComponent: () => import(\"./TextareaFieldEditor\"),\n defaultConfig: {\n type: \"textarea\",\n label: \"Message\",\n placeholder: \"\",\n required: false,\n rows: 4,\n },\n },\n {\n type: \"email\",\n label: \"Email\",\n icon: \"Mail\",\n description: \"Email address with validation\",\n category: \"core\",\n EditorComponent: () => import(\"./EmailFieldEditor\"),\n defaultConfig: {\n type: \"email\",\n label: \"Email\",\n placeholder: \"email@example.com\",\n required: false,\n },\n },\n {\n type: \"number\",\n label: \"Number\",\n icon: \"Hash\",\n description: \"Numeric input with min/max\",\n category: \"core\",\n EditorComponent: () => import(\"./NumberFieldEditor\"),\n defaultConfig: {\n type: \"number\",\n label: \"Number\",\n placeholder: \"0\",\n required: false,\n },\n },\n {\n type: \"checkbox\",\n label: \"Checkbox\",\n icon: \"CheckSquare\",\n description: \"Single checkbox (yes/no)\",\n category: \"core\",\n EditorComponent: () => import(\"./CheckboxFieldEditor\"),\n defaultConfig: {\n type: \"checkbox\",\n label: \"I agree to the terms\",\n required: false,\n defaultValue: false,\n },\n },\n {\n type: \"select\",\n label: \"Dropdown\",\n icon: \"ChevronDown\",\n description: \"Dropdown select menu\",\n category: \"core\",\n EditorComponent: () => import(\"./SelectFieldEditor\"),\n defaultConfig: {\n type: \"select\",\n label: \"Select an option\",\n placeholder: \"Choose...\",\n required: false,\n options: [\n { label: \"Option 1\", value: \"option1\" },\n { label: \"Option 2\", value: \"option2\" },\n ],\n },\n },\n {\n type: \"radio\",\n label: \"Radio\",\n icon: \"Circle\",\n description: \"Radio button group\",\n category: \"core\",\n EditorComponent: () => import(\"./RadioFieldEditor\"),\n defaultConfig: {\n type: \"radio\",\n label: \"Choose one\",\n required: false,\n options: [\n { label: \"Option 1\", value: \"option1\" },\n { label: \"Option 2\", value: \"option2\" },\n ],\n },\n },\n\n // ---------------------------------------------------------------------------\n // Date Fields\n // ---------------------------------------------------------------------------\n {\n type: \"date\",\n label: \"Date\",\n icon: \"Calendar\",\n description: \"Date picker\",\n category: \"core\",\n EditorComponent: () => import(\"./DateFieldEditor\"),\n defaultConfig: {\n type: \"date\",\n label: \"Date\",\n required: false,\n },\n },\n];\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Get field types grouped by category.\n *\n * @returns Object with category keys mapping to arrays of field configs\n *\n * @example\n * ```typescript\n * const grouped = getFieldTypesByCategory();\n * // { core: [...], location: [...] }\n * ```\n */\nexport function getFieldTypesByCategory(): Record<string, FieldTypeConfig[]> {\n return FIELD_TYPES.reduce(\n (acc, field) => {\n if (!acc[field.category]) {\n acc[field.category] = [];\n }\n acc[field.category].push(field);\n return acc;\n },\n {} as Record<string, FieldTypeConfig[]>\n );\n}\n\n/**\n * Get field type configuration by type identifier.\n *\n * @param type - The field type to look up\n * @returns The field type config or undefined if not found\n *\n * @example\n * ```typescript\n * const config = getFieldTypeConfig('text');\n * console.log(config?.label); // \"Text\"\n * ```\n */\nexport function getFieldTypeConfig(\n type: FormFieldType\n): FieldTypeConfig | undefined {\n return FIELD_TYPES.find(f => f.type === type);\n}\n\n/**\n * Check if a field type is supported by the registry.\n *\n * @param type - The field type to check\n * @returns True if the field type is supported\n */\nexport function isFieldTypeSupported(type: string): type is FormFieldType {\n return FIELD_TYPES.some(f => f.type === type);\n}\n\n/**\n * Create a new field instance from a field type.\n *\n * Generates a unique field name and applies default configuration.\n *\n * @param type - The field type to create\n * @returns A new FormField instance\n * @throws Error if the field type is unknown\n *\n * @example\n * ```typescript\n * const field = createFieldFromType('email');\n * // { type: 'email', name: 'email_abc123', label: 'Email', ... }\n * ```\n */\nexport function createFieldFromType(type: FormFieldType): FormField {\n const config = getFieldTypeConfig(type);\n\n if (!config) {\n throw new Error(`Unknown field type: ${type}`);\n }\n\n // Generate unique field name\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 6);\n const name = `${type}_${timestamp}_${random}`;\n\n return {\n name,\n ...config.defaultConfig,\n } as FormField;\n}\n\n/**\n * Get the Lucide icon name for a field type.\n *\n * @param type - The field type\n * @returns The Lucide icon name or \"FileText\" as fallback\n */\nexport function getFieldTypeIcon(type: FormFieldType): string {\n return getFieldTypeConfig(type)?.icon ?? \"FileText\";\n}\n\n/**\n * Get the display label for a field type.\n *\n * @param type - The field type\n * @returns The display label or the type itself as fallback\n */\nexport function getFieldTypeLabel(type: FormFieldType): string {\n return getFieldTypeConfig(type)?.label ?? type;\n}\n\n/**\n * Get all supported field types as an array of type identifiers.\n *\n * @returns Array of supported FormFieldType values\n */\nexport function getSupportedFieldTypes(): FormFieldType[] {\n return FIELD_TYPES.map(f => f.type);\n}\n\n// ============================================================================\n// Icon Resolution\n// ============================================================================\n\n/**\n * Mapping of Lucide icon names to their component implementations.\n *\n * This map is used by `resolveFieldIcon()` to convert icon name strings\n * (stored in FIELD_TYPES) to actual React components for rendering.\n *\n * When adding new field types, ensure the corresponding icon is added here.\n */\nconst ICON_MAP: Record<string, LucideIcon> = {\n Type,\n AlignLeft,\n Mail,\n Hash,\n CheckSquare,\n ChevronDown,\n Circle,\n Calendar,\n FileText, // Fallback icon\n};\n\n/**\n * Resolve a Lucide icon name to its component implementation.\n *\n * This function converts icon name strings (e.g., \"Type\", \"Mail\") to actual\n * Lucide React components that can be rendered. Used by SortableFieldRow\n * and other components that display field type icons.\n *\n * @param iconName - The Lucide icon name (from getFieldTypeIcon or FIELD_TYPES)\n * @returns The Lucide icon component, or FileText as fallback\n *\n * @example\n * ```tsx\n * const iconName = getFieldTypeIcon('email'); // \"Mail\"\n * const IconComponent = resolveFieldIcon(iconName);\n * return <IconComponent className=\"h-4 w-4\" />;\n * ```\n */\nexport function resolveFieldIcon(iconName: string): LucideIcon {\n return ICON_MAP[iconName] ?? FileText;\n}\n\n// Re-export LucideIcon type for consumers\nexport type { LucideIcon };\n","\"use client\";\n\n/**\n * Add Field Button Component\n *\n * A button that opens a modal dialog for selecting field types to add to a form.\n * Displays fields grouped by category (Core, Location) with icons and descriptions.\n *\n * Features:\n * - Modal dialog with field type selection\n * - Fields grouped by category\n * - Icon, label, and description for each field type\n * - Keyboard accessible\n * - Auto-closes on selection\n *\n * @module admin/components/AddFieldButton\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"@nextlyhq/ui\";\nimport { Plus } from \"lucide-react\";\nimport { useCallback, useState } from \"react\";\n\nimport type { FormField, FormFieldType } from \"../../types\";\nimport {\n createFieldFromType,\n FIELD_CATEGORIES,\n getFieldTypesByCategory,\n resolveFieldIcon,\n type FieldTypeConfig,\n} from \"../fields\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AddFieldButtonProps {\n /**\n * Callback when a new field is created.\n * Receives the newly created FormField instance.\n */\n onAddField: (field: FormField) => void;\n\n /**\n * Whether the button is disabled.\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Additional CSS class names for the button.\n */\n className?: string;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * AddFieldButton renders a button that opens a modal for selecting field types.\n *\n * When a field type is selected, a new field instance is created with default\n * configuration and passed to the onAddField callback. The modal automatically\n * closes after selection.\n *\n * @example\n * ```tsx\n * <AddFieldButton\n * onAddField={(field) => {\n * setFields([...fields, field]);\n * }}\n * />\n * ```\n */\nexport function AddFieldButton({\n onAddField,\n disabled = false,\n className,\n}: AddFieldButtonProps) {\n const [isOpen, setIsOpen] = useState(false);\n\n // Get fields grouped by category\n const fieldsByCategory = getFieldTypesByCategory();\n\n /**\n * Handle field type selection.\n * Creates a new field and calls the callback.\n */\n const handleSelectField = useCallback(\n (type: FormFieldType) => {\n const newField = createFieldFromType(type);\n onAddField(newField);\n setIsOpen(false);\n },\n [onAddField]\n );\n\n // Build button class names\n const buttonClassName = [\n \"add-field-button\",\n disabled && \"add-field-button--disabled\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <>\n {/* Trigger Button */}\n <button\n type=\"button\"\n className={buttonClassName}\n onClick={() => setIsOpen(true)}\n disabled={disabled}\n aria-label=\"Add a new field to the form\"\n >\n <Plus className=\"add-field-button__icon\" aria-hidden=\"true\" />\n <span className=\"add-field-button__label\">Add Field</span>\n </button>\n\n {/* Field Selection Modal */}\n <Dialog open={isOpen} onOpenChange={setIsOpen}>\n <DialogContent size=\"md\" className=\"add-field-modal\">\n <DialogHeader>\n <DialogTitle>Add Field</DialogTitle>\n <DialogDescription>\n Select a field type to add to your form.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"add-field-modal__content\">\n {FIELD_CATEGORIES.map(category => {\n const fields = fieldsByCategory[category.key] || [];\n if (fields.length === 0) return null;\n\n return (\n <div key={category.key} className=\"add-field-modal__category\">\n <h4 className=\"add-field-modal__category-title\">\n {category.label}\n </h4>\n <p className=\"add-field-modal__category-description\">\n {category.description}\n </p>\n\n <div className=\"add-field-modal__field-grid\">\n {fields.map(fieldConfig => (\n <FieldTypeButton\n key={fieldConfig.type}\n config={fieldConfig}\n onClick={() => handleSelectField(fieldConfig.type)}\n />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n\n// ============================================================================\n// Field Type Button (Internal)\n// ============================================================================\n\ninterface FieldTypeButtonProps {\n config: FieldTypeConfig;\n onClick: () => void;\n}\n\n/**\n * Individual field type button displayed in the modal.\n * Shows icon, label, and description.\n */\nfunction FieldTypeButton({ config, onClick }: FieldTypeButtonProps) {\n const IconComponent = resolveFieldIcon(config.icon);\n\n return (\n <button\n type=\"button\"\n className=\"add-field-modal__field-button\"\n onClick={onClick}\n aria-label={`Add ${config.label} field`}\n >\n <span className=\"add-field-modal__field-icon\" aria-hidden=\"true\">\n <IconComponent className=\"add-field-modal__icon\" />\n </span>\n <span className=\"add-field-modal__field-info\">\n <span className=\"add-field-modal__field-label\">{config.label}</span>\n <span className=\"add-field-modal__field-description\">\n {config.description}\n </span>\n </span>\n </button>\n );\n}\n\nexport default AddFieldButton;\n","\"use client\";\n\n/**\n * Field Editor Panel Component\n *\n * Right-side panel for editing field properties. Dynamically loads the\n * appropriate field editor component based on field type using React.lazy().\n *\n * Features:\n * - Lazy-loaded field editors for code splitting\n * - Loading skeleton during editor load\n * - Graceful handling of unknown field types\n * - Header with field type icon and label\n * - Close button to dismiss the panel\n *\n * @module admin/components/FieldEditorPanel\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { X } from \"lucide-react\";\nimport React, { Suspense, useMemo } from \"react\";\n\nimport type { FormField } from \"../../types\";\nimport {\n getFieldTypeConfig,\n getFieldTypeLabel,\n resolveFieldIcon,\n} from \"../fields\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FieldEditorPanelProps {\n /**\n * The field being edited.\n */\n field: FormField;\n\n /**\n * All fields in the form (for references, e.g., conditional logic).\n */\n allFields: FormField[];\n\n /**\n * Callback when field properties are updated.\n * Receives partial updates to merge with current field.\n */\n onUpdate: (updates: Partial<FormField>) => void;\n\n /**\n * Callback when the panel should be closed.\n */\n onClose: () => void;\n}\n\n// ============================================================================\n// Loading Skeleton\n// ============================================================================\n\n/**\n * Loading skeleton displayed while field editor is being lazy-loaded.\n * Provides visual feedback during the brief loading period.\n */\nfunction EditorSkeleton() {\n return (\n <div className=\"field-editor-panel__skeleton\">\n {/* Label skeleton */}\n <div className=\"field-editor-panel__skeleton-row\">\n <div className=\"field-editor-panel__skeleton-label\" />\n <div className=\"field-editor-panel__skeleton-input\" />\n </div>\n {/* Field name skeleton */}\n <div className=\"field-editor-panel__skeleton-row\">\n <div className=\"field-editor-panel__skeleton-label\" />\n <div className=\"field-editor-panel__skeleton-input\" />\n </div>\n {/* Placeholder skeleton */}\n <div className=\"field-editor-panel__skeleton-row\">\n <div className=\"field-editor-panel__skeleton-label\" />\n <div className=\"field-editor-panel__skeleton-input\" />\n </div>\n {/* Checkbox skeleton */}\n <div className=\"field-editor-panel__skeleton-row\">\n <div className=\"field-editor-panel__skeleton-checkbox\" />\n <div className=\"field-editor-panel__skeleton-label--short\" />\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// Unknown Field Type Fallback\n// ============================================================================\n\n/**\n * Fallback displayed when field type is not recognized.\n * This should rarely happen in practice, but provides a graceful degradation.\n */\nfunction UnknownFieldType({ type }: { type: string }) {\n return (\n <div className=\"field-editor-panel__unknown\">\n <p className=\"field-editor-panel__unknown-title\">Unknown Field Type</p>\n <p className=\"field-editor-panel__unknown-message\">\n The field type <code>{type}</code> is not supported by this version of\n the form builder.\n </p>\n </div>\n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * FieldEditorPanel - Right-side panel for editing field properties\n *\n * This component dynamically loads the appropriate field editor based on\n * the field type. Each field type has its own editor component that handles\n * the specific configuration options for that type.\n *\n * The panel displays:\n * - Header with field type icon, type label, and field label\n * - Close button to dismiss the panel\n * - Lazy-loaded editor content with loading skeleton\n *\n * @example\n * ```tsx\n * <FieldEditorPanel\n * field={selectedField}\n * allFields={allFields}\n * onUpdate={(updates) => updateField(selectedField.name, updates)}\n * onClose={() => setSelectedField(null)}\n * />\n * ```\n */\nexport function FieldEditorPanel({\n field,\n allFields,\n onUpdate,\n onClose,\n}: FieldEditorPanelProps) {\n // Get field type configuration from registry\n const fieldConfig = getFieldTypeConfig(field.type);\n\n // Lazily load the editor component based on field type\n // useMemo ensures we don't recreate the lazy component on every render\n const EditorComponent = useMemo(() => {\n if (!fieldConfig) return null;\n return React.lazy(fieldConfig.EditorComponent);\n }, [fieldConfig]);\n\n // Handle unknown field type\n if (!fieldConfig || !EditorComponent) {\n return (\n <div className=\"field-editor-panel\">\n <div className=\"field-editor-panel__header\">\n <div className=\"field-editor-panel__title\">\n <span className=\"field-editor-panel__title-text\">Edit Field</span>\n </div>\n <button\n type=\"button\"\n className=\"field-editor-panel__close\"\n onClick={onClose}\n aria-label=\"Close editor panel\"\n >\n <X className=\"field-editor-panel__close-icon\" />\n </button>\n </div>\n <div className=\"field-editor-panel__content\">\n <UnknownFieldType type={field.type} />\n </div>\n </div>\n );\n }\n\n // Resolve the icon component for this field type\n const IconComponent = resolveFieldIcon(fieldConfig.icon);\n\n // Get display label for field type\n const typeLabel = getFieldTypeLabel(field.type);\n\n return (\n <div className=\"field-editor-panel\">\n {/* Header */}\n <div className=\"field-editor-panel__header\">\n <div className=\"field-editor-panel__title\">\n <IconComponent\n className=\"field-editor-panel__title-icon\"\n aria-hidden=\"true\"\n />\n <span className=\"field-editor-panel__title-text\">\n Edit {typeLabel} Field\n {field.label && (\n <span className=\"field-editor-panel__title-label\">\n {\" \"}\n — {field.label}\n </span>\n )}\n </span>\n </div>\n <button\n type=\"button\"\n className=\"field-editor-panel__close\"\n onClick={onClose}\n aria-label=\"Close editor panel\"\n >\n <X className=\"field-editor-panel__close-icon\" />\n </button>\n </div>\n\n {/* Editor Content */}\n <div className=\"field-editor-panel__content\">\n <Suspense fallback={<EditorSkeleton />}>\n <EditorComponent\n field={field}\n allFields={allFields}\n onUpdate={onUpdate}\n />\n </Suspense>\n </div>\n </div>\n );\n}\n\nexport default FieldEditorPanel;\n"],"mappings":"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","names":["Button","Input","Tabs","TabsList","TabsTrigger","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","useCallback","useState","FormLabelWithTooltip","Input","Button","Checkbox","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","useState","useCallback","useMemo","useCallback","jsx","jsxs","jsx","jsxs","useMemo","FormLabelWithTooltip","Input","Checkbox","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","useCallback","Button","useState","useMemo","useState","useCallback","useMemo","useState","jsx","jsx","jsxs","useState","useMemo","jsx","jsxs","Button","Input","useCallback","useEffect","useState","jsx","jsxs","useState","useCallback","Input","Button","useEffect","Input","Button","jsx","jsxs","Input","Tabs","TabsList","TabsTrigger","jsx","jsxs","Input","Tabs","TabsList","TabsTrigger","Fragment","jsx","jsxs","useState","useCallback","Button","Input","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Tabs","TabsList","TabsTrigger","DndContext","closestCenter","KeyboardSensor","PointerSensor","useSensor","useSensors","SortableContext","sortableKeyboardCoordinates","verticalListSortingStrategy","useCallback","useSortable","CSS","useCallback","FIELD_TYPES","createFieldFromType","jsx","jsxs","useSortable","CSS","useCallback","jsx","jsxs","useSensors","useSensor","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","useCallback","DndContext","closestCenter","SortableContext","verticalListSortingStrategy","useCallback","useState","Fragment","jsx","jsxs","useState","useCallback","createFieldFromType","useMemo","jsx","jsxs","useMemo"]}
|
|
1
|
+
{"version":3,"sources":["../../src/admin/index.ts","../../src/admin/components/submissions/SubmissionsView.tsx","../../src/admin/components/submissions/SubmissionSheet.tsx","../../src/admin/FormBuilderView.tsx","../../src/admin/components/builder/FieldCards.tsx","../../src/utils/field-references.ts","../../src/admin/context/FormBuilderContext.tsx","../../src/admin/components/builder/AddFieldDialog.tsx","../../src/admin/components/builder/FieldEditor.tsx","../../src/admin/components/builder/ConditionalLogicEditor.tsx","../../src/admin/components/builder/FormNotificationsTab.tsx","../../src/admin/components/builder/FormPreview.tsx","../../src/admin/components/builder/FormSettingsTab.tsx"],"sourcesContent":["/**\n * Form Builder Admin Components\n *\n * Entry point for admin UI components used by the Nextly admin panel.\n * These components are referenced via component paths in collection configs.\n *\n * Component paths use the format: \"@nextlyhq/plugin-form-builder/admin#ExportName\"\n *\n * ## Auto-Registration\n *\n * This module automatically registers its components with the admin panel\n * when imported. No manual registration is required - just add the plugin\n * to your Nextly config and the admin will detect and load the components.\n *\n * @module admin\n * @since 0.1.0\n */\n\n// ============================================================================\n// Main View Components\n// ============================================================================\n\n// ============================================================================\n// Component Registration\n// ============================================================================\n\nimport {\n registerComponents,\n registerKnownPlugin,\n type ComponentPath,\n} from \"@nextlyhq/plugin-sdk/admin\";\n\nimport { SubmissionsView } from \"./components/submissions/SubmissionsView\";\nimport { FormBuilderView } from \"./FormBuilderView\";\n\nexport { FormBuilderView, type FormBuilderViewProps } from \"./FormBuilderView\";\nexport { SubmissionsView } from \"./components/submissions/SubmissionsView\";\nexport { SubmissionSheet } from \"./components/submissions/SubmissionSheet\";\n\n// ============================================================================\n// Builder Sub-Components\n// ============================================================================\n\nexport {\n FieldCards,\n AddFieldDialog,\n FieldEditor,\n FormPreview,\n type FieldCardsProps,\n type AddFieldDialogProps,\n type FieldEditorProps,\n type FormPreviewProps,\n} from \"./components/builder\";\n\n// ============================================================================\n// Context & Hooks\n// ============================================================================\n\nexport {\n FormBuilderProvider,\n useFormBuilder,\n useOptionalFormBuilder,\n createFieldFromType,\n createNotification,\n generateFieldName,\n generateFieldLabel,\n DEFAULT_SETTINGS,\n type FormBuilderState,\n type FormBuilderActions,\n type FormBuilderContextValue,\n type FormBuilderProviderProps,\n type FormSettings,\n type FormNotification,\n} from \"./context/FormBuilderContext\";\n\n// ============================================================================\n// Tab Components\n// ============================================================================\n\nexport { FormSettingsTab } from \"./components/builder/FormSettingsTab\";\nexport { FormNotificationsTab } from \"./components/builder/FormNotificationsTab\";\n\n/** Component path for FormBuilderView */\nexport const FORM_BUILDER_VIEW_PATH: ComponentPath =\n \"@nextlyhq/plugin-form-builder/admin#FormBuilderView\";\n\n/** Component path for SubmissionsView */\nexport const SUBMISSIONS_VIEW_PATH: ComponentPath =\n \"@nextlyhq/plugin-form-builder/admin#SubmissionsView\";\n\n// ============================================================================\n// Auto-Registration with Admin\n// ============================================================================\n\n/**\n * Eagerly register components at module load time.\n *\n * This ensures components are available immediately when the admin\n * tries to resolve them, without needing to wait for async registration.\n */\nregisterComponents({\n [FORM_BUILDER_VIEW_PATH]: FormBuilderView,\n [SUBMISSIONS_VIEW_PATH]: SubmissionsView,\n});\n\n/**\n * Also register with the known plugin system for consistency.\n *\n * This supports the auto-registration flow where the admin detects\n * component paths and triggers registration. Since we eagerly register\n * above, this callback is effectively a no-op but keeps the plugin\n * compatible with both eager and lazy registration patterns.\n */\nregisterKnownPlugin(\n \"@nextlyhq/plugin-form-builder\",\n // eslint-disable-next-line @typescript-eslint/require-await -- registerKnownPlugin's second arg is typed `() => Promise<void>` (strict, not a union); body is synchronous\n async () => {\n // Components already registered above, but re-register for safety\n registerComponents({\n [FORM_BUILDER_VIEW_PATH]: FormBuilderView,\n [SUBMISSIONS_VIEW_PATH]: SubmissionsView,\n });\n }\n);\n","\"use client\";\n\n/**\n * Submissions View\n *\n * The submissions list, replacing the generic collection table via the\n * List-view override. Submission data is stored keyed by field name, so\n * when one form is selected the table shows real per-field columns; across\n * all forms (where fields differ) it falls back to generic columns with a\n * data summary. Spam is a first-class status tab — flagged submissions are\n * reviewable and recoverable, never invisible.\n *\n * @module admin/components/submissions/SubmissionsView\n */\n\nimport {\n DataTableView,\n type NextlyColumn,\n type RowAction,\n} from \"@nextlyhq/plugin-sdk/admin\";\nimport {\n Badge,\n Button,\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tabs,\n TabsList,\n TabsTrigger,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@nextlyhq/ui\";\nimport { ChevronLeft, ChevronRight, Columns3, Download } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type { FormField } from \"../../../types\";\nimport { formatExportValue } from \"../../../utils/export-formats\";\n\nimport { SubmissionSheet } from \"./SubmissionSheet\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SubmissionRow {\n id: string;\n form: string | { id: string; name?: string };\n data: Record<string, unknown>;\n status: string;\n spamReason?: string | null;\n notes?: string | null;\n ipAddress?: string | null;\n userAgent?: string | null;\n submittedAt?: string | null;\n editedAt?: string | null;\n editedBy?: string | null;\n}\n\nexport interface FormOption {\n id: string;\n name: string;\n fields: FormField[];\n}\n\ninterface SubmissionsViewProps {\n collectionSlug?: string;\n}\n\ntype StatusTab = \"all\" | \"new\" | \"read\" | \"archived\" | \"spam\";\n\nconst STATUS_TABS: Array<{ value: StatusTab; label: string }> = [\n { value: \"all\", label: \"All\" },\n { value: \"new\", label: \"New\" },\n { value: \"read\", label: \"Read\" },\n { value: \"archived\", label: \"Archived\" },\n { value: \"spam\", label: \"Spam\" },\n];\n\nconst PAGE_SIZE = 25;\n\n/** How many per-field columns are visible before the rest hide behind the selector. */\nconst VISIBLE_FIELD_COLUMNS = 4;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formIdOf(row: SubmissionRow): string {\n return typeof row.form === \"object\" ? row.form.id : row.form;\n}\n\nfunction formatDate(value: string | null | undefined): string {\n if (!value) return \"\";\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return \"\";\n return date.toLocaleString(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n });\n}\n\n/** Status → badge styling. Tokens only; spam reads as a warning state. */\nfunction StatusBadge({ status }: { status: string }) {\n const label = status.charAt(0).toUpperCase() + status.slice(1);\n return (\n <Badge\n variant=\"outline\"\n className={`rounded-none px-1.5 py-0 text-[10px] font-semibold uppercase tracking-wider ${\n // Full-strength status borders (destructive/primary) so each badge boundary is perceivable; the default falls back to border-border, keeping the states distinct.\n status === \"spam\"\n ? \"border-destructive text-destructive\"\n : status === \"new\"\n ? \"border-primary text-primary\"\n : \"border-border text-muted-foreground\"\n }`}\n >\n {label}\n </Badge>\n );\n}\n\n/** Compact \"key: value\" preview of a submission for the all-forms table. */\nfunction summarizeData(data: Record<string, unknown>): string {\n return Object.entries(data)\n .slice(0, 3)\n .map(([key, value]) => `${key}: ${formatExportValue(value)}`)\n .join(\" · \");\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function SubmissionsView({ collectionSlug }: SubmissionsViewProps) {\n const [slugs, setSlugs] = useState<{ forms: string; submissions: string }>();\n const [forms, setForms] = useState<FormOption[]>([]);\n const [selectedFormId, setSelectedFormId] = useState<string>(() => {\n // Deep links (?form=<id>) preselect the form filter.\n if (typeof window === \"undefined\") return \"\";\n return new URLSearchParams(window.location.search).get(\"form\") ?? \"\";\n });\n const [statusTab, setStatusTab] = useState<StatusTab>(\"all\");\n const [rows, setRows] = useState<SubmissionRow[]>([]);\n const [total, setTotal] = useState(0);\n const [page, setPage] = useState(1);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [openId, setOpenId] = useState<string | null>(null);\n const [canUpdate, setCanUpdate] = useState(false);\n const [canDelete, setCanDelete] = useState(false);\n\n const submissionsSlug =\n slugs?.submissions ?? collectionSlug ?? \"form-submissions\";\n\n // --- bootstrap: resolved slugs, the forms list, and the user's rights ----\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n try {\n const configRes = await fetch(\n \"/admin/api/plugins/@nextlyhq/plugin-form-builder/builder-config\",\n { credentials: \"include\" }\n );\n const config = configRes.ok\n ? ((await configRes.json()) as {\n slugs?: { forms: string; submissions: string };\n })\n : null;\n const resolved = config?.slugs ?? {\n forms: \"forms\",\n submissions: \"form-submissions\",\n };\n if (cancelled) return;\n setSlugs(resolved);\n\n // Page through ALL forms — a capped single fetch would silently\n // drop forms from the filter and the per-field column lookup.\n const allForms: FormOption[] = [];\n const formsPageSize = 200;\n for (let formsPage = 1; ; formsPage += 1) {\n const formsRes = await fetch(\n `/admin/api/collections/${resolved.forms}/entries?pageSize=${formsPageSize}&page=${formsPage}`,\n { credentials: \"include\" }\n );\n if (!formsRes.ok) break;\n const json = (await formsRes.json()) as {\n items?: Array<{ id: string; name?: string; fields?: FormField[] }>;\n };\n const items = json.items ?? [];\n allForms.push(\n ...items.map(item => ({\n id: item.id,\n name: item.name ?? item.id,\n fields: Array.isArray(item.fields) ? item.fields : [],\n }))\n );\n if (items.length < formsPageSize) break;\n }\n if (!cancelled) setForms(allForms);\n\n const permsRes = await fetch(\"/admin/api/me/permissions\", {\n credentials: \"include\",\n });\n if (permsRes.ok) {\n const perms = (await permsRes.json()) as {\n permissions?: string[];\n isSuperAdmin?: boolean;\n };\n const has = (slug: string) =>\n Boolean(perms.isSuperAdmin) ||\n (perms.permissions ?? []).includes(slug);\n if (!cancelled) {\n setCanUpdate(has(`update-${resolved.submissions}`));\n setCanDelete(has(`delete-${resolved.submissions}`));\n }\n }\n } catch {\n // Bootstrap failures degrade to the default slugs — without them\n // the list fetch would wait forever and the loading state never end.\n if (!cancelled) {\n setSlugs(\n current =>\n current ?? { forms: \"forms\", submissions: \"form-submissions\" }\n );\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, []);\n\n // --- the list fetch ------------------------------------------------------\n // Monotonic request sequence: rapid filter changes overlap fetches, and\n // only the LATEST request may commit rows — an older response finishing\n // last must never overwrite the current filter's data.\n const fetchSeqRef = useRef(0);\n const fetchRows = useCallback(async () => {\n if (!slugs) return;\n const seq = ++fetchSeqRef.current;\n setLoading(true);\n setError(null);\n try {\n const where: Record<string, unknown> = {};\n if (selectedFormId) where.form = { equals: selectedFormId };\n // \"All\" means every human status; spam only shows when asked for —\n // the same default the export route applies.\n if (statusTab === \"all\") where.status = { not_equals: \"spam\" };\n else where.status = { equals: statusTab };\n\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n sortBy: \"submittedAt\",\n sortOrder: \"desc\",\n where: JSON.stringify(where),\n });\n const res = await fetch(\n `/admin/api/collections/${slugs.submissions}/entries?${params}`,\n { credentials: \"include\" }\n );\n if (!res.ok)\n throw new Error(`Failed to load submissions (${res.status})`);\n const json = (await res.json()) as {\n items?: SubmissionRow[];\n meta?: { total?: number };\n };\n if (seq !== fetchSeqRef.current) return;\n setRows(json.items ?? []);\n setTotal(json.meta?.total ?? (json.items ?? []).length);\n } catch (err) {\n if (seq !== fetchSeqRef.current) return;\n setError(\n err instanceof Error ? err.message : \"Failed to load submissions\"\n );\n } finally {\n if (seq === fetchSeqRef.current) setLoading(false);\n }\n }, [slugs, selectedFormId, statusTab, page]);\n\n useEffect(() => {\n void fetchRows();\n }, [fetchRows]);\n\n const selectedForm = useMemo(\n () => forms.find(form => form.id === selectedFormId),\n [forms, selectedFormId]\n );\n\n const formNameById = useMemo(\n () => new Map(forms.map(form => [form.id, form.name])),\n [forms]\n );\n\n // --- columns --------------------------------------------------------------\n // Hidden field columns, per form. Wide forms start with everything past\n // the first few hidden; the toolbar's Columns menu toggles the rest in.\n const [hiddenFieldColumns, setHiddenFieldColumns] = useState<Set<string>>(\n new Set()\n );\n useEffect(() => {\n setHiddenFieldColumns(\n new Set(\n (selectedForm?.fields ?? [])\n .slice(VISIBLE_FIELD_COLUMNS)\n .map(field => field.name)\n )\n );\n }, [selectedForm]);\n\n const columns = useMemo<NextlyColumn<SubmissionRow>[]>(() => {\n if (selectedForm) {\n // One form selected: real per-field columns.\n const fieldColumns = selectedForm.fields\n .filter(field => !hiddenFieldColumns.has(field.name))\n .map<NextlyColumn<SubmissionRow>>(field => ({\n name: `data.${field.name}`,\n header: field.label || field.name,\n accessor: row => formatExportValue(row.data?.[field.name], field),\n }));\n return [\n ...fieldColumns,\n {\n name: \"status\",\n header: \"Status\",\n accessor: row => row.status,\n cell: ({ row }) => <StatusBadge status={row.status} />,\n },\n {\n name: \"submittedAt\",\n header: \"Submitted\",\n accessor: row => formatDate(row.submittedAt),\n },\n ];\n }\n return [\n {\n name: \"form\",\n header: \"Form\",\n accessor: row => formNameById.get(formIdOf(row)) ?? formIdOf(row),\n },\n {\n name: \"data\",\n header: \"Submission\",\n accessor: row => summarizeData(row.data ?? {}),\n },\n {\n name: \"status\",\n header: \"Status\",\n accessor: row => row.status,\n cell: ({ row }) => <StatusBadge status={row.status} />,\n },\n {\n name: \"submittedAt\",\n header: \"Submitted\",\n accessor: row => formatDate(row.submittedAt),\n },\n ];\n }, [selectedForm, formNameById, hiddenFieldColumns]);\n\n // --- actions ---------------------------------------------------------------\n const patchSubmission = useCallback(\n async (id: string, body: Record<string, unknown>) => {\n const res = await fetch(\n `/admin/api/collections/${submissionsSlug}/entries/${id}`,\n {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n credentials: \"include\",\n body: JSON.stringify(body),\n }\n );\n if (!res.ok) throw new Error(`Update failed (${res.status})`);\n await fetchRows();\n },\n [submissionsSlug, fetchRows]\n );\n\n const deleteSubmission = useCallback(\n async (id: string) => {\n const res = await fetch(\n `/admin/api/collections/${submissionsSlug}/entries/${id}`,\n { method: \"DELETE\", credentials: \"include\" }\n );\n if (!res.ok) throw new Error(`Delete failed (${res.status})`);\n setOpenId(null);\n await fetchRows();\n },\n [submissionsSlug, fetchRows]\n );\n\n const rowActions = useCallback(\n (row: SubmissionRow): RowAction<SubmissionRow>[] => {\n const actions: RowAction<SubmissionRow>[] = [];\n if (row.status === \"spam\" && canUpdate) {\n actions.push({\n id: \"not-spam\",\n label: \"Not spam\",\n onSelect: target =>\n void patchSubmission(target.id, {\n status: \"new\",\n spamReason: null,\n }),\n });\n }\n if (canDelete) {\n actions.push({\n id: \"delete\",\n label: \"Delete\",\n destructive: true,\n onSelect: target => void deleteSubmission(target.id),\n });\n }\n return actions;\n },\n [canUpdate, canDelete, patchSubmission, deleteSubmission]\n );\n\n // --- export ----------------------------------------------------------------\n const exportHref = useCallback(\n (format: \"csv\" | \"json\") => {\n const params = new URLSearchParams({ format });\n if (selectedFormId) params.set(\"form\", selectedFormId);\n if (statusTab !== \"all\") params.set(\"status\", statusTab);\n return `/admin/api/plugins/@nextlyhq/plugin-form-builder/submissions/export?${params}`;\n },\n [selectedFormId, statusTab]\n );\n\n const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));\n // The open record is tracked by ID: after a save refetch the row may\n // move or leave the filtered view entirely — index tracking would silently\n // show a different submission, while a missing ID just closes the drawer.\n const openIndex = openId ? rows.findIndex(row => row.id === openId) : -1;\n const openRow = openIndex === -1 ? null : rows[openIndex];\n\n return (\n <div className=\"space-y-4\">\n {/* Toolbar: form filter, status tabs, export */}\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\n <Select\n value={selectedFormId || \"__all\"}\n onValueChange={value => {\n setSelectedFormId(value === \"__all\" ? \"\" : value);\n setPage(1);\n setOpenId(null);\n }}\n >\n <SelectTrigger\n aria-label=\"Filter by form\"\n className=\"w-full sm:w-56 bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__all\">All forms</SelectItem>\n {forms.map(form => (\n <SelectItem key={form.id} value={form.id}>\n {form.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Tabs\n value={statusTab}\n onValueChange={value => {\n setStatusTab(value as StatusTab);\n setPage(1);\n setOpenId(null);\n }}\n >\n <TabsList className=\"rounded-none\">\n {STATUS_TABS.map(tab => (\n <TabsTrigger\n key={tab.value}\n value={tab.value}\n className=\"rounded-none\"\n >\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n </div>\n\n <div className=\"flex items-center gap-2\">\n {selectedForm && selectedForm.fields.length > 0 && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button type=\"button\" variant=\"outline\">\n <Columns3 className=\"h-4 w-4\" aria-hidden=\"true\" />\n Columns\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n className=\"shadow-none border-border\"\n >\n {selectedForm.fields.map(field => (\n <DropdownMenuCheckboxItem\n key={field.name}\n checked={!hiddenFieldColumns.has(field.name)}\n onCheckedChange={checked =>\n setHiddenFieldColumns(prev => {\n const next = new Set(prev);\n if (checked) next.delete(field.name);\n else next.add(field.name);\n return next;\n })\n }\n // Keep the menu open while toggling several columns.\n onSelect={event => event.preventDefault()}\n >\n {field.label || field.name}\n </DropdownMenuCheckboxItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button type=\"button\" variant=\"outline\">\n <Download className=\"h-4 w-4\" aria-hidden=\"true\" />\n Export\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n className=\"shadow-none border-border\"\n >\n {selectedFormId ? (\n <DropdownMenuItem asChild className=\"cursor-pointer\">\n <a href={exportHref(\"csv\")} download>\n CSV\n </a>\n </DropdownMenuItem>\n ) : (\n <Tooltip>\n <TooltipTrigger asChild>\n {/* CSV columns come from one form's fields, so it needs a\n form selected; the tooltip says so instead of hiding it. */}\n <DropdownMenuItem\n disabled\n onSelect={event => event.preventDefault()}\n >\n CSV\n </DropdownMenuItem>\n </TooltipTrigger>\n <TooltipContent side=\"left\">\n Select a form first — CSV columns come from its fields.\n </TooltipContent>\n </Tooltip>\n )}\n <DropdownMenuItem asChild className=\"cursor-pointer\">\n <a href={exportHref(\"json\")} download>\n JSON\n </a>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n\n <DataTableView<SubmissionRow>\n columns={columns}\n rows={rows}\n loading={loading}\n error={error}\n emptyMessage={\n statusTab === \"spam\"\n ? \"No spam — nothing has been flagged.\"\n : \"No submissions yet.\"\n }\n ariaLabel=\"Submissions\"\n onRowClick={row => setOpenId(row.id)}\n rowActions={rowActions}\n />\n\n {/* Pagination */}\n <div className=\"flex items-center justify-between text-sm text-muted-foreground\">\n <span role=\"status\">\n {total === 0\n ? \"0 submissions\"\n : `${(page - 1) * PAGE_SIZE + 1}–${Math.min(page * PAGE_SIZE, total)} of ${total}`}\n </span>\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n className=\"h-8 w-8 rounded-none\"\n disabled={page <= 1}\n onClick={() => setPage(current => current - 1)}\n aria-label=\"Previous page\"\n >\n <ChevronLeft className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n <span>\n Page {page} of {totalPages}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n className=\"h-8 w-8 rounded-none\"\n disabled={page >= totalPages}\n onClick={() => setPage(current => current + 1)}\n aria-label=\"Next page\"\n >\n <ChevronRight className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n </div>\n\n {/* Detail drawer with prev/next over the current page */}\n {openRow && (\n <SubmissionSheet\n submission={openRow}\n form={\n forms.find(form => form.id === formIdOf(openRow)) ?? {\n id: formIdOf(openRow),\n name: formNameById.get(formIdOf(openRow)) ?? \"Form\",\n fields: [],\n }\n }\n canUpdate={canUpdate}\n onClose={() => setOpenId(null)}\n onPrev={\n openIndex > 0 ? () => setOpenId(rows[openIndex - 1].id) : undefined\n }\n onNext={\n openIndex < rows.length - 1\n ? () => setOpenId(rows[openIndex + 1].id)\n : undefined\n }\n onSave={async changes => {\n await patchSubmission(openRow.id, changes);\n }}\n />\n )}\n </div>\n );\n}\n\nexport default SubmissionsView;\n","\"use client\";\n\n/**\n * Submission Sheet\n *\n * Drawer detail for one submission: the submitted values in field order,\n * metadata, status + internal notes, and — behind the update permission —\n * inline editing of the submitted data. Prev/next walks the current table\n * page without losing filter context.\n *\n * @module admin/components/submissions/SubmissionSheet\n */\n\nimport {\n Badge,\n Button,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Switch,\n Textarea,\n} from \"@nextlyhq/ui\";\nimport { ChevronLeft, ChevronRight, Pencil, TriangleAlert } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\nimport type { FormField } from \"../../../types\";\nimport { formatExportValue } from \"../../../utils/export-formats\";\n\nimport type { FormOption, SubmissionRow } from \"./SubmissionsView\";\n\ninterface SubmissionSheetProps {\n submission: SubmissionRow;\n form: FormOption;\n canUpdate: boolean;\n onClose: () => void;\n onPrev?: () => void;\n onNext?: () => void;\n onSave: (changes: Record<string, unknown>) => Promise<void>;\n}\n\nfunction formatDate(value: string | null | undefined): string {\n if (!value) return \"\";\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return \"\";\n return date.toLocaleString(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n });\n}\n\n/** One editable input per field type; unsupported types render read-only. */\nfunction FieldValueInput({\n field,\n value,\n onChange,\n}: {\n field: FormField;\n value: unknown;\n onChange: (value: unknown) => void;\n}) {\n const id = `submission-field-${field.name}`;\n switch (field.type) {\n case \"textarea\":\n return (\n <Textarea\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={e => onChange(e.target.value)}\n rows={3}\n />\n );\n case \"checkbox\":\n return (\n <Switch\n id={id}\n checked={Boolean(value)}\n onCheckedChange={checked => onChange(checked)}\n />\n );\n case \"select\":\n case \"radio\": {\n const options = \"options\" in field ? (field.options ?? []) : [];\n return (\n <Select\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={onChange}\n >\n <SelectTrigger\n id={id}\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {options.map(option => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n }\n case \"number\":\n return (\n <Input\n id={id}\n type=\"number\"\n value={\n typeof value === \"number\" || typeof value === \"string\"\n ? String(value)\n : \"\"\n }\n onChange={e =>\n onChange(e.target.value === \"\" ? \"\" : Number(e.target.value))\n }\n />\n );\n case \"date\":\n case \"time\":\n return (\n <Input\n id={id}\n type={field.type}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={e => onChange(e.target.value)}\n />\n );\n case \"text\":\n case \"email\":\n case \"url\":\n case \"phone\":\n return (\n <Input\n id={id}\n type={field.type === \"email\" ? \"email\" : \"text\"}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={e => onChange(e.target.value)}\n />\n );\n case \"file\":\n case \"hidden\":\n default:\n // Files are media references, hidden fields are machine values, and\n // unknown types may hold structured data — coercing any of them\n // through a text input would corrupt them, so they stay read-only.\n return (\n <p className=\"text-sm text-muted-foreground\">\n {formatExportValue(value, field) || \"—\"}\n </p>\n );\n }\n}\n\nexport function SubmissionSheet({\n submission,\n form,\n canUpdate,\n onClose,\n onPrev,\n onNext,\n onSave,\n}: SubmissionSheetProps) {\n const [editing, setEditing] = useState(false);\n const [draftData, setDraftData] = useState<Record<string, unknown>>({});\n const [status, setStatus] = useState(submission.status);\n const [notes, setNotes] = useState(submission.notes ?? \"\");\n const [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // Prev/next swaps the submission while the sheet stays open — every piece\n // of local state must follow the record it belongs to.\n useEffect(() => {\n setEditing(false);\n setDraftData(submission.data ?? {});\n setStatus(submission.status);\n setNotes(submission.notes ?? \"\");\n setSaveError(null);\n }, [submission]);\n\n const fieldNames = new Set(form.fields.map(field => field.name));\n // Forms evolve after submissions exist: keys no longer on the form are\n // shown honestly instead of silently dropped.\n const orphanedEntries = Object.entries(submission.data ?? {}).filter(\n ([key]) => !fieldNames.has(key)\n );\n\n // Only a real value difference counts as a data edit — entering edit mode\n // and saving untouched values must not write `data` or earn an edit stamp.\n const dataChanged =\n editing &&\n form.fields.some(field => {\n const before = (submission.data ?? {})[field.name];\n const after = draftData[field.name];\n return JSON.stringify(before ?? null) !== JSON.stringify(after ?? null);\n });\n\n const dirty =\n dataChanged ||\n status !== submission.status ||\n notes !== (submission.notes ?? \"\");\n\n const handleSave = async () => {\n if (!canUpdate) return;\n setSaving(true);\n setSaveError(null);\n try {\n const changes: Record<string, unknown> = {};\n if (status !== submission.status) {\n changes.status = status;\n // Recovering from spam clears the stale detection reason.\n if (submission.status === \"spam\" && status !== \"spam\") {\n changes.spamReason = null;\n }\n }\n if (notes !== (submission.notes ?? \"\")) changes.notes = notes;\n if (dataChanged) changes.data = draftData;\n if (Object.keys(changes).length > 0) await onSave(changes);\n setEditing(false);\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : \"Save failed\");\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Sheet\n open\n onOpenChange={open => {\n if (!open) onClose();\n }}\n >\n <SheetContent\n side=\"right\"\n className=\"w-[560px] sm:max-w-[560px] p-0 flex flex-col\"\n >\n <SheetHeader className=\"p-4 border-b border-border\">\n <div className=\"flex items-center justify-between gap-2\">\n <SheetTitle className=\"min-w-0 truncate\">\n Submission — {form.name}\n </SheetTitle>\n <div className=\"flex shrink-0 items-center gap-1 mr-6\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 rounded-none\"\n disabled={!onPrev}\n onClick={onPrev}\n aria-label=\"Previous submission\"\n >\n <ChevronLeft className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 rounded-none\"\n disabled={!onNext}\n onClick={onNext}\n aria-label=\"Next submission\"\n >\n <ChevronRight className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n </div>\n <SheetDescription>\n Submitted {formatDate(submission.submittedAt)}\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"flex-1 overflow-y-auto p-4 space-y-6\">\n {/* Spam banner */}\n {submission.status === \"spam\" && (\n // Full-strength destructive border so the spam banner boundary is perceivable over its tinted fill.\n <div className=\"flex items-center gap-2 border border-destructive bg-destructive/5 p-3 text-sm text-destructive\">\n <TriangleAlert className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n Flagged as spam\n {submission.spamReason ? ` (${submission.spamReason})` : \"\"}. Set\n the status to New to recover it.\n </div>\n )}\n\n {/* Submitted values */}\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm font-medium text-foreground\">\n Submitted values\n </p>\n {canUpdate && !editing && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setEditing(true)}\n >\n <Pencil className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Edit\n </Button>\n )}\n </div>\n\n <div className=\"space-y-3 border border-border p-3\">\n {form.fields.length === 0 && (\n <p className=\"text-sm text-muted-foreground\">\n The form's fields are unavailable.\n </p>\n )}\n {form.fields.map(field => (\n <div key={field.name} className=\"space-y-1\">\n <Label htmlFor={`submission-field-${field.name}`}>\n {field.label || field.name}\n </Label>\n {editing ? (\n <FieldValueInput\n field={field}\n value={draftData[field.name]}\n onChange={value =>\n setDraftData(prev => ({\n ...prev,\n [field.name]: value,\n }))\n }\n />\n ) : (\n <p className=\"text-sm text-foreground wrap-break-word\">\n {formatExportValue(\n (submission.data ?? {})[field.name],\n field\n ) || <span className=\"text-muted-foreground\">—</span>}\n </p>\n )}\n </div>\n ))}\n </div>\n\n {orphanedEntries.length > 0 && (\n <div className=\"space-y-2 border border-border bg-muted/40 p-3\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n No longer on the form\n </p>\n {orphanedEntries.map(([key, value]) => (\n <p key={key} className=\"text-sm text-muted-foreground\">\n <span className=\"font-mono\">{key}</span>:{\" \"}\n {formatExportValue(value)}\n </p>\n ))}\n </div>\n )}\n\n {submission.editedAt && (\n <p className=\"text-xs text-muted-foreground\">\n Edited {formatDate(submission.editedAt)}\n {submission.editedBy ? ` by ${submission.editedBy}` : \"\"} — the\n values above are not necessarily what the visitor sent.\n </p>\n )}\n </div>\n\n {/* Status + notes */}\n <div className=\"grid grid-cols-1 gap-4 border-t border-border pt-4 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"submission-status\">Status</Label>\n {/* Status/notes writes go through the same update permission\n as data edits — without it, everything here is read-only. */}\n <Select\n value={status}\n onValueChange={setStatus}\n disabled={!canUpdate}\n >\n <SelectTrigger\n id=\"submission-status\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"new\">New</SelectItem>\n <SelectItem value=\"read\">Read</SelectItem>\n <SelectItem value=\"archived\">Archived</SelectItem>\n <SelectItem value=\"spam\">Spam</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5 sm:col-span-2\">\n <Label htmlFor=\"submission-notes\">Internal notes</Label>\n <Textarea\n id=\"submission-notes\"\n value={notes}\n onChange={e => setNotes(e.target.value)}\n rows={3}\n placeholder=\"Visible to admins only\"\n disabled={!canUpdate}\n />\n </div>\n </div>\n\n {/* Metadata */}\n <div className=\"space-y-1 border-t border-border pt-4 text-xs text-muted-foreground\">\n <p>\n IP: {submission.ipAddress || \"—\"}\n <span className=\"mx-1.5 text-muted-foreground\">·</span>\n ID: <span className=\"font-mono\">{submission.id}</span>\n </p>\n {submission.userAgent && (\n <p className=\"break-all\">Agent: {submission.userAgent}</p>\n )}\n {submission.spamReason && submission.status !== \"spam\" && (\n <p>\n Previously flagged:{\" \"}\n <Badge\n variant=\"outline\"\n className=\"rounded-none border-border px-1 py-0 text-[10px]\"\n >\n {submission.spamReason}\n </Badge>\n </p>\n )}\n </div>\n </div>\n\n <div className=\"flex items-center justify-between gap-3 border-t border-border bg-muted p-4\">\n {saveError ? (\n <p className=\"text-xs text-destructive\">{saveError}</p>\n ) : (\n <span />\n )}\n <div className=\"flex items-center gap-3\">\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n Close\n </Button>\n <Button\n type=\"button\"\n onClick={() => void handleSave()}\n disabled={!canUpdate || !dirty || saving}\n >\n {saving ? \"Saving…\" : \"Save\"}\n </Button>\n </div>\n </div>\n </SheetContent>\n </Sheet>\n );\n}\n\nexport default SubmissionSheet;\n","\"use client\";\n\n/**\n * Form Builder View\n *\n * Custom admin view that provides a visual drag-and-drop form builder.\n * Layout mirrors the Collection Builder for visual consistency.\n *\n * @module admin/FormBuilderView\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport {\n Button,\n Input,\n toast,\n Tabs,\n TabsList,\n TabsTrigger,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n} from \"@nextlyhq/ui\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { FormFieldCatalogType } from \"nextly/field-catalog\";\nimport { FORM_FIELD_TYPE_CATALOG } from \"nextly/field-catalog\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport type { FormField, FormFieldTypeId } from \"../types\";\n\nimport { FieldCards } from \"./components/builder/FieldCards\";\nimport {\n FormNotificationsTab,\n type NotificationDefaults,\n} from \"./components/builder/FormNotificationsTab\";\nimport { FormPreview } from \"./components/builder/FormPreview\";\nimport {\n FormSettingsTab,\n type SpamDefaults,\n} from \"./components/builder/FormSettingsTab\";\nimport {\n FormBuilderProvider,\n useFormBuilder,\n createFieldFromType,\n createNotification,\n type FormNotification,\n} from \"./context/FormBuilderContext\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FormBuilderViewProps {\n id?: string;\n entryId?: string;\n collection?: string;\n collectionSlug?: string;\n isCreating?: boolean;\n initialData?: {\n id?: string;\n name?: string;\n slug?: string;\n description?: string;\n status?: \"draft\" | \"published\" | \"closed\";\n fields?: unknown[];\n settings?: Record<string, unknown>;\n notifications?: unknown[];\n };\n onSave?: (data: unknown) => void;\n onSuccess?: (entry?: Record<string, unknown>) => void;\n onCancel?: () => void;\n}\n\n// ============================================================================\n// Helper\n// ============================================================================\n\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, \"\")\n .replace(/[\\s_-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\n// ============================================================================\n// Inner Component (uses context)\n// ============================================================================\n\nfunction FormBuilderViewInner({\n isCreating = false,\n collectionSlug = \"forms\",\n entryId,\n onSave,\n onSuccess,\n onCancel,\n}: Pick<\n FormBuilderViewProps,\n | \"isCreating\"\n | \"collectionSlug\"\n | \"entryId\"\n | \"onSave\"\n | \"onSuccess\"\n | \"onCancel\"\n>) {\n const {\n fields,\n activeTab,\n isDirty,\n formData,\n settings,\n notifications,\n setActiveTab,\n addField,\n selectField,\n seedNotifications,\n updateFormData,\n markAsSaved,\n } = useFormBuilder();\n\n const queryClient = useQueryClient();\n\n const [isSaving, setIsSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // The host's resolved field enable/disable map. `null` until the config\n // request settles, so the Add dialog never flashes the unfiltered set. If\n // the request errors, every type is offered: the exclude list is an\n // authoring preference (the server accepts any field type in the form's\n // JSON regardless), so hiding all types on a transient failure would cost\n // more than a temporarily unfiltered picker.\n const [enabledTypes, setEnabledTypes] = useState<\n FormFieldCatalogType[] | null\n >(null);\n\n // Type ids the host explicitly disabled (`config.fields[type] === false`),\n // including plugin type ids — so the host exclude layer applies to\n // contributed field types too, not just built-ins.\n const [disabledFieldTypes, setDisabledFieldTypes] = useState<Set<string>>(\n () => new Set()\n );\n\n // The host's notification defaults (plugin options). `null` until the\n // config request settles; `{}` when the request failed or nothing is\n // configured, so consumers can distinguish \"loading\" from \"no defaults\".\n const [notificationDefaults, setNotificationDefaults] =\n useState<NotificationDefaults | null>(null);\n\n // Plugin-level spam defaults, so the Settings tab can show what\n // \"inherit\" resolves to. `null` while the config request settles.\n const [spamDefaults, setSpamDefaults] = useState<SpamDefaults | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n const allTypes = FORM_FIELD_TYPE_CATALOG.map(entry => entry.type);\n void fetch(\n \"/admin/api/plugins/@nextlyhq/plugin-form-builder/builder-config\",\n { credentials: \"include\" }\n )\n .then(response => (response.ok ? response.json() : null))\n .then(\n (\n config: {\n fields?: Record<string, boolean>;\n notifications?: NotificationDefaults;\n spamProtection?: SpamDefaults;\n } | null\n ) => {\n if (cancelled) return;\n setEnabledTypes(\n config?.fields\n ? allTypes.filter(type => config.fields?.[type] !== false)\n : allTypes\n );\n setDisabledFieldTypes(\n new Set(\n Object.entries(config?.fields ?? {})\n .filter(([, enabled]) => enabled === false)\n .map(([type]) => type)\n )\n );\n setNotificationDefaults(config?.notifications ?? {});\n setSpamDefaults(config?.spamProtection ?? {});\n }\n )\n .catch(() => {\n if (cancelled) return;\n setEnabledTypes(allTypes);\n setNotificationDefaults({});\n setSpamDefaults({});\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n // Seed a new form with the default admin-notification rule once the host\n // defaults are known. Guarded by a ref so deleting the seeded rule is\n // final — the effect must never re-seed a list the user emptied.\n const seededRef = useRef(false);\n useEffect(() => {\n if (!isCreating || notificationDefaults === null || seededRef.current) {\n return;\n }\n seededRef.current = true;\n seedNotifications([\n {\n ...createNotification(),\n name: \"Admin notification\",\n to: notificationDefaults.defaultToEmail ?? \"\",\n },\n ]);\n }, [isCreating, notificationDefaults, seedNotifications]);\n\n const handleAddField = useCallback(\n (type: FormFieldTypeId) => {\n const newField = createFieldFromType(\n type,\n fields.map(f => f.name)\n );\n addField(newField);\n selectField(newField.name);\n },\n [fields, addField, selectField]\n );\n\n // ── Save / Cancel ─────────────────────────────────────────────────────────\n const handleSave = useCallback(async () => {\n // Check if there are fields\n if (fields.length === 0) {\n toast.error(\"Please add at least one field to the form\");\n return;\n }\n\n const { id: _id, ...formDataWithoutId } = formData;\n const saveData = {\n ...formDataWithoutId,\n fields,\n settings,\n notifications,\n };\n\n if (onSave) {\n onSave(saveData);\n return;\n }\n\n setIsSaving(true);\n setSaveError(null);\n try {\n const url = isCreating\n ? `/admin/api/collections/${collectionSlug}/entries`\n : `/admin/api/collections/${collectionSlug}/entries/${entryId}`;\n const response = await fetch(url, {\n method: isCreating ? \"POST\" : \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n credentials: \"include\",\n body: JSON.stringify(saveData),\n });\n if (!response.ok) {\n const err = (await response.json().catch(() => ({}))) as {\n error?: { message?: string };\n };\n throw new Error(\n err.error?.message ?? `Failed to save form: ${response.statusText}`\n );\n }\n\n const result = (await response.json()) as {\n message?: string;\n item?: Record<string, unknown>;\n } & Record<string, unknown>;\n const savedEntry: Record<string, unknown> = result.item ?? result;\n void queryClient.invalidateQueries({\n queryKey: [\"entries\", \"list\", collectionSlug],\n });\n void queryClient.invalidateQueries({ queryKey: [\"entries\", \"count\"] });\n if (!isCreating && entryId) {\n void queryClient.invalidateQueries({\n queryKey: [\"entries\", \"detail\", collectionSlug, entryId],\n });\n }\n markAsSaved();\n toast.success(\n isCreating ? \"Form created successfully\" : \"Form updated successfully\"\n );\n if (onSuccess) onSuccess(savedEntry);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Failed to save form\";\n setSaveError(message);\n toast.error(message);\n } finally {\n setIsSaving(false);\n }\n }, [\n formData,\n fields,\n settings,\n notifications,\n onSave,\n onSuccess,\n isCreating,\n collectionSlug,\n entryId,\n queryClient,\n markAsSaved,\n ]);\n\n const handleCancel = useCallback(() => {\n if (onCancel) onCancel();\n else if (typeof window !== \"undefined\") window.history.back();\n }, [onCancel]);\n\n const handleNameChange = useCallback(\n (name: string) => {\n updateFormData({ name });\n if (!formData.slug || formData.slug === slugify(formData.name)) {\n updateFormData({ slug: slugify(name) });\n }\n },\n [formData.name, formData.slug, updateFormData]\n );\n\n // Main tabs\n const mainTabs = [\n {\n value: \"builder\" as const,\n label: \"Builder\",\n count: fields.length > 0 ? fields.length : null,\n },\n {\n value: \"preview\" as const,\n label: \"Preview\",\n count: null,\n },\n { value: \"settings\" as const, label: \"Settings\", count: null },\n {\n value: \"notifications\" as const,\n label: \"Notifications\",\n count: notifications.length > 0 ? notifications.length : null,\n },\n ];\n\n // ── Render ────────────────────────────────────────────────────────────────\n return (\n <>\n {/* ── Page header (Outside the white card) ── */}\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4 mb-6 px-1\">\n <div>\n <h1 className=\"text-2xl font-semibold text-foreground tracking-tight\">\n {isCreating ? \"Create Form\" : \"Edit Form\"}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {isCreating\n ? \"Design a new form with drag-and-drop fields.\"\n : \"Modify your form fields and settings.\"}\n </p>\n </div>\n\n {/* Action buttons — same variant/size as Collection Builder */}\n <div className=\"flex items-center gap-2 shrink-0\">\n {isDirty && (\n // Full-strength warning border so the unsaved-changes badge boundary is perceivable over its tinted fill.\n <span className=\"text-xs font-medium bg-warning-100 text-warning-700 dark:bg-warning-900 dark:text-warning-100 border border-warning px-2.5 py-1 rounded-none whitespace-nowrap\">\n Unsaved changes\n </span>\n )}\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={isSaving}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => {\n void handleSave();\n }}\n disabled={isSaving}\n className=\"flex items-center gap-1.5\"\n >\n {isSaving ? (\n <>\n <svg\n className=\"animate-spin h-3.5 w-3.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n Saving…\n </>\n ) : isCreating ? (\n \"Create\"\n ) : (\n \"Save Changes\"\n )}\n </Button>\n </div>\n </div>\n\n {/*\n Outer shell — white card with rounded-none border (no shadow).\n Fills available height in the admin page container.\n */}\n <div className=\"flex border border-border bg-background overflow-hidden\">\n {/* =================================================================\n LEFT — scrollable main content\n ================================================================= */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"w-full px-8 pt-8 pb-12 space-y-6\">\n {/* ── Fixed Metadata & Tab Navigation ── */}\n {/* -mx-8 + px-8: full-width divider, inset content. */}\n <div className=\"bg-background -mx-8 px-8 border-b border-border space-y-4\">\n <div className=\"flex flex-wrap gap-4\">\n {/* Form Name */}\n <div className=\"flex-1 min-w-[200px] max-w-sm space-y-1.5\">\n <label\n htmlFor=\"form-name\"\n className=\"text-sm font-medium text-foreground\"\n >\n Form Name\n </label>\n <Input\n id=\"form-name\"\n type=\"text\"\n value={formData.name || \"\"}\n onChange={e => handleNameChange(e.target.value)}\n placeholder=\"e.g., Contact Form\"\n className=\"bg-transparent\"\n />\n </div>\n\n {/* Slug */}\n <div className=\"flex-1 min-w-[160px] max-w-xs space-y-1.5\">\n <label\n htmlFor=\"form-slug\"\n className=\"text-sm font-medium text-foreground\"\n >\n Slug\n </label>\n <Input\n id=\"form-slug\"\n type=\"text\"\n value={formData.slug || \"\"}\n onChange={e => updateFormData({ slug: e.target.value })}\n placeholder=\"e.g., contact-form\"\n className=\"bg-transparent placeholder:text-muted-foreground\"\n />\n </div>\n\n {/* Status */}\n <div className=\"w-36 space-y-1.5\">\n <label\n htmlFor=\"form-status\"\n className=\"text-sm font-medium text-foreground\"\n >\n Status\n </label>\n <Select\n value={formData.status || \"draft\"}\n onValueChange={value =>\n updateFormData({\n status: value as \"draft\" | \"published\" | \"closed\",\n })\n }\n >\n <SelectTrigger id=\"form-status\" className=\"bg-transparent\">\n <SelectValue placeholder=\"Status\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"draft\">Draft</SelectItem>\n <SelectItem value=\"published\">Published</SelectItem>\n <SelectItem value=\"closed\">Closed</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {/* ── Main tab navigation ── */}\n <Tabs\n value={activeTab}\n onValueChange={v => setActiveTab(v as typeof activeTab)}\n >\n <TabsList className=\"bg-transparent justify-start gap-0 -mb-px border-b-0 max-w-full overflow-x-auto\">\n {mainTabs.map(tab => (\n <TabsTrigger\n key={tab.value}\n value={tab.value}\n style={{\n borderBottomColor:\n activeTab === tab.value\n ? \"var(--nx-primary)\"\n : \"transparent\",\n }}\n className=\"shrink-0 whitespace-nowrap border-b-2 relative -mb-0.5 data-[state=active]:text-primary data-[state=inactive]:text-muted-foreground hover:text-primary hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n >\n {tab.label}\n {tab.count !== null && (\n <span\n className={`inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 text-[10px] font-semibold rounded-none ml-2 transition-colors ${\n activeTab === tab.value\n ? \"bg-primary/5 text-primary\"\n : \"bg-primary/5 text-muted-foreground\"\n }`}\n >\n {tab.count}\n </span>\n )}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n </div>\n\n {/* ── Tab content ── */}\n\n {/* Builder tab */}\n {activeTab === \"builder\" && (\n <FieldCards\n enabledTypes={enabledTypes}\n disabledFieldTypes={disabledFieldTypes}\n onAddField={handleAddField}\n />\n )}\n\n {/* Preview tab */}\n {activeTab === \"preview\" && (\n <FormPreview fields={fields} formData={formData} />\n )}\n\n {/* Settings tab */}\n {activeTab === \"settings\" && (\n <div className=\"w-full\">\n <FormSettingsTab spamDefaults={spamDefaults} />\n </div>\n )}\n\n {/* Notifications tab */}\n {activeTab === \"notifications\" && (\n <div className=\"w-full\">\n <FormNotificationsTab defaults={notificationDefaults} />\n </div>\n )}\n\n {/* Save error */}\n {saveError && (\n // Full-strength destructive border so the error box boundary is perceivable over its tinted fill.\n <div className=\"p-3 text-sm text-destructive bg-destructive/10 border border-destructive rounded-none\">\n {saveError}\n </div>\n )}\n </div>\n </div>\n </div>\n </>\n );\n}\n\n// ============================================================================\n// Main Component (provides context)\n// ============================================================================\n\nexport function FormBuilderView({\n id,\n entryId,\n collection,\n collectionSlug,\n isCreating,\n initialData,\n onSave,\n onSuccess,\n onCancel,\n}: FormBuilderViewProps) {\n const resolvedEntryId = entryId || id || initialData?.id;\n const resolvedCollectionSlug = collectionSlug || collection || \"forms\";\n const resolvedIsCreating = isCreating ?? !resolvedEntryId;\n const providerKey = resolvedEntryId || \"new\";\n\n return (\n <FormBuilderProvider\n key={providerKey}\n initialData={{\n id: resolvedEntryId,\n name: initialData?.name,\n slug: initialData?.slug,\n description: initialData?.description,\n status: initialData?.status,\n fields: initialData?.fields as FormField[],\n settings: initialData?.settings as Record<string, unknown>,\n notifications: initialData?.notifications as FormNotification[],\n }}\n >\n <FormBuilderViewInner\n isCreating={resolvedIsCreating}\n collectionSlug={resolvedCollectionSlug}\n entryId={resolvedEntryId}\n onSave={onSave}\n onSuccess={onSuccess}\n onCancel={onCancel}\n />\n </FormBuilderProvider>\n );\n}\n\nexport default FormBuilderView;\n","\"use client\";\n\n/**\n * Field Cards\n *\n * The form builder's field list: one collapsible card per field, edited\n * inline. This is the whole field-editing surface — there is no separate\n * palette or properties sidebar.\n *\n * Reordering is triple-redundant on purpose: drag handles (pointer), the\n * same handle with Space + arrow keys (dnd-kit keyboard sensor), and\n * explicit Move up / Move down menu items. Deleting a field that another\n * field's condition or a notification references is blocked with the list\n * of referrers instead of silently breaking them.\n *\n * @module admin/components/builder/FieldCards\n */\n\nimport {\n closestCenter,\n DndContext,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { usePluginFieldTypeEntries } from \"@nextlyhq/plugin-sdk/admin\";\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@nextlyhq/ui\";\nimport * as Lucide from \"lucide-react\";\nimport type {\n FieldTypeCatalogEntry,\n FormFieldCatalogType,\n} from \"nextly/field-catalog\";\nimport { FORM_FIELD_TYPE_CATALOG } from \"nextly/field-catalog\";\nimport { useCallback, useMemo, useState } from \"react\";\n\nimport type { AnyFormField, FormFieldTypeId } from \"../../../types\";\nimport { buildFieldReferenceMap } from \"../../../utils/field-references\";\nimport { useFormBuilder } from \"../../context/FormBuilderContext\";\n\nimport { AddFieldDialog } from \"./AddFieldDialog\";\nimport { FieldEditor } from \"./FieldEditor\";\n\n// ---------------------------------------------------------------------------\n// Catalog helpers\n// ---------------------------------------------------------------------------\n\nconst CATALOG_BY_TYPE = new Map<\n string,\n FieldTypeCatalogEntry<FormFieldCatalogType>\n>(FORM_FIELD_TYPE_CATALOG.map(entry => [entry.type, entry]));\n\n/** Resolve a catalog icon name against lucide; unknown names fall back. */\nfunction CatalogIcon({\n name,\n className,\n}: {\n name: string | undefined;\n className?: string;\n}) {\n const icons = Lucide as unknown as Record<string, React.ElementType>;\n const Icon = (name && icons[name]) || Lucide.Type;\n return <Icon className={className} aria-hidden=\"true\" />;\n}\n\n// ---------------------------------------------------------------------------\n// One field card\n// ---------------------------------------------------------------------------\n\ninterface FieldCardProps {\n field: AnyFormField;\n index: number;\n total: number;\n expanded: boolean;\n onToggle: () => void;\n allFields: AnyFormField[];\n deleteBlockers: string[];\n onUpdate: (updates: Partial<AnyFormField>) => void;\n onDuplicate: () => void;\n onDelete: () => void;\n onMove: (direction: -1 | 1) => void;\n}\n\nfunction FieldCard({\n field,\n index,\n total,\n expanded,\n onToggle,\n allFields,\n deleteBlockers,\n onUpdate,\n onDuplicate,\n onDelete,\n onMove,\n}: FieldCardProps) {\n const {\n attributes,\n listeners,\n setNodeRef,\n setActivatorNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: field.name });\n\n const entry = CATALOG_BY_TYPE.get(field.type);\n const headerId = `field-card-header-${field.name}`;\n const bodyId = `field-card-body-${field.name}`;\n const deleteBlocked = deleteBlockers.length > 0;\n\n return (\n <div\n ref={setNodeRef}\n style={{ transform: CSS.Transform.toString(transform), transition }}\n className={\n // Dragging uses full-strength border-primary so the lifted card stands out; the resting state uses border-border, keeping the two distinct.\n isDragging\n ? \"border border-primary bg-card opacity-80 relative z-10\"\n : \"border border-border bg-card\"\n }\n >\n {/* Header row: every control is a real, separate interactive element —\n no nested-button markup. */}\n <div className=\"flex items-center gap-2 px-3 py-2.5\">\n <button\n type=\"button\"\n ref={setActivatorNodeRef}\n {...attributes}\n {...listeners}\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-none text-muted-foreground hover:text-foreground hover:bg-primary/5 cursor-grab active:cursor-grabbing focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n aria-label={`Reorder ${field.label || field.name}. Press Space to lift, arrow keys to move, Space to drop.`}\n >\n <Lucide.GripVertical className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={expanded}\n aria-controls={bodyId}\n id={headerId}\n className=\"flex min-w-0 flex-1 items-center gap-3 rounded-none py-1 text-left cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n >\n <span className=\"flex h-7 w-7 shrink-0 items-center justify-center bg-primary/5 text-primary\">\n <CatalogIcon name={entry?.icon} className=\"h-3.5 w-3.5\" />\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium text-foreground\">\n {field.label || field.name}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground\">\n {entry?.label ?? field.type}\n <span className=\"mx-1.5 text-muted-foreground\">·</span>\n <span className=\"font-mono\">{field.name}</span>\n </span>\n </span>\n {field.required && (\n <span className=\"shrink-0 border border-border bg-primary/5 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-primary\">\n Required\n </span>\n )}\n <Lucide.ChevronDown\n className={`h-4 w-4 shrink-0 text-muted-foreground transition-transform ${expanded ? \"rotate-180\" : \"\"}`}\n aria-hidden=\"true\"\n />\n </button>\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"h-8 w-8 shrink-0 rounded-none text-muted-foreground hover:text-foreground\"\n aria-label={`Actions for ${field.label || field.name}`}\n >\n <Lucide.MoreHorizontal className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n className=\"w-56 shadow-none border-border\"\n >\n <DropdownMenuItem\n disabled={index === 0}\n onClick={() => onMove(-1)}\n className=\"gap-2 cursor-pointer\"\n >\n <Lucide.ArrowUp className=\"h-4 w-4 text-muted-foreground\" />\n Move up\n </DropdownMenuItem>\n <DropdownMenuItem\n disabled={index === total - 1}\n onClick={() => onMove(1)}\n className=\"gap-2 cursor-pointer\"\n >\n <Lucide.ArrowDown className=\"h-4 w-4 text-muted-foreground\" />\n Move down\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={onDuplicate}\n className=\"gap-2 cursor-pointer\"\n >\n <Lucide.Copy className=\"h-4 w-4 text-muted-foreground\" />\n Duplicate\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n {deleteBlocked ? (\n <Tooltip delayDuration={0}>\n <TooltipTrigger asChild>\n <div>\n <DropdownMenuItem\n disabled\n className=\"gap-2 text-muted-foreground\"\n >\n <Lucide.Trash2 className=\"h-4 w-4\" />\n Delete\n </DropdownMenuItem>\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"left\" className=\"max-w-64\">\n Used by {deleteBlockers.join(\", \")}. Remove those references\n first.\n </TooltipContent>\n </Tooltip>\n ) : (\n <DropdownMenuItem\n onClick={onDelete}\n className=\"gap-2 cursor-pointer text-destructive focus:text-destructive\"\n >\n <Lucide.Trash2 className=\"h-4 w-4\" />\n Delete\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Inline properties: the card IS the properties panel. */}\n {expanded && (\n <div\n id={bodyId}\n role=\"region\"\n aria-labelledby={headerId}\n className=\"border-t border-border\"\n >\n <FieldEditor\n field={field}\n allFields={allFields}\n onUpdate={onUpdate}\n />\n </div>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// The list\n// ---------------------------------------------------------------------------\n\nexport interface FieldCardsProps {\n /**\n * Form-surface types the host has NOT excluded (the plugin's field\n * enable/disable option). `null` while the host configuration is still\n * loading — the Add dialog waits rather than flashing the unfiltered set.\n * Types outside this set stay renderable on existing fields but cannot be\n * added.\n */\n enabledTypes: readonly FormFieldCatalogType[] | null;\n /**\n * Type ids the host disabled (`config.fields[type] === false`). Applied to\n * plugin field types too, so the host exclude layer is not bypassed for\n * contributed types.\n */\n disabledFieldTypes?: ReadonlySet<string>;\n /** Creates a field of the given type and returns it (context helper). */\n onAddField: (type: FormFieldTypeId) => void;\n}\n\nexport function FieldCards({\n enabledTypes,\n disabledFieldTypes,\n onAddField,\n}: FieldCardsProps) {\n const {\n fields,\n notifications,\n selectedFieldId,\n selectField,\n updateField,\n deleteField,\n duplicateField,\n moveField,\n } = useFormBuilder();\n\n const [isAddOpen, setIsAddOpen] = useState(false);\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })\n );\n\n // Plugin field types that opted into the forms surface, offered alongside the\n // enabled built-ins. A plugin reusing a built-in id never shadows it.\n const pluginEntries = usePluginFieldTypeEntries(\"forms\");\n\n const entries = useMemo(() => {\n if (enabledTypes === null) return null;\n const allowed = new Set<string>(enabledTypes);\n const builtinTypes = new Set<string>(\n FORM_FIELD_TYPE_CATALOG.map(entry => entry.type)\n );\n const builtins: FieldTypeCatalogEntry<FormFieldTypeId>[] =\n FORM_FIELD_TYPE_CATALOG.filter(entry => allowed.has(entry.type));\n return [\n ...builtins,\n // A plugin type a built-in shadows, or one the host disabled, is excluded.\n ...pluginEntries.filter(\n entry =>\n !builtinTypes.has(entry.type) && !disabledFieldTypes?.has(entry.type)\n ),\n ];\n }, [enabledTypes, pluginEntries, disabledFieldTypes]);\n\n // One O(N^2) pass per fields/notifications change; each card then looks\n // its blockers up in O(1) instead of re-walking everything per render.\n const referenceMap = useMemo(\n () => buildFieldReferenceMap(fields, notifications),\n [fields, notifications]\n );\n\n const handleDragEnd = useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n if (!over || active.id === over.id) return;\n const from = fields.findIndex(f => f.name === active.id);\n const to = fields.findIndex(f => f.name === over.id);\n if (from !== -1 && to !== -1) moveField(from, to);\n },\n [fields, moveField]\n );\n\n return (\n <div className=\"space-y-3\">\n {fields.length === 0 ? (\n <div className=\"flex flex-col items-center gap-3 border border-dashed border-border bg-card px-6 py-14 text-center\">\n <span className=\"flex h-10 w-10 items-center justify-center bg-primary/10 text-primary\">\n <Lucide.ListPlus className=\"h-5 w-5\" aria-hidden=\"true\" />\n </span>\n <div>\n <p className=\"text-sm font-medium text-foreground\">No fields yet</p>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n Add the first field to start building this form.\n </p>\n </div>\n <Button type=\"button\" size=\"sm\" onClick={() => setIsAddOpen(true)}>\n Add field\n </Button>\n </div>\n ) : (\n <>\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext\n items={fields.map(f => f.name)}\n strategy={verticalListSortingStrategy}\n >\n <ul className=\"space-y-2\" aria-label=\"Form fields\">\n {fields.map((field, index) => (\n <li key={field.name}>\n <FieldCard\n field={field}\n index={index}\n total={fields.length}\n expanded={selectedFieldId === field.name}\n onToggle={() =>\n selectField(\n selectedFieldId === field.name ? null : field.name\n )\n }\n allFields={fields}\n deleteBlockers={(referenceMap.get(field.name) ?? []).map(\n ref => ref.label\n )}\n onUpdate={updates => updateField(field.name, updates)}\n onDuplicate={() => duplicateField(field.name)}\n onDelete={() => deleteField(field.name)}\n onMove={direction => moveField(index, index + direction)}\n />\n </li>\n ))}\n </ul>\n </SortableContext>\n </DndContext>\n\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setIsAddOpen(true)}\n className=\"w-full border-dashed\"\n >\n <Lucide.Plus className=\"h-4 w-4\" aria-hidden=\"true\" />\n Add field\n </Button>\n </>\n )}\n\n <AddFieldDialog\n open={isAddOpen}\n onOpenChange={setIsAddOpen}\n entries={entries}\n onAdd={onAddField}\n />\n </div>\n );\n}\n","/**\n * Find what references a form field by name, so destructive actions can be\n * guarded: a field that another field's conditional logic or a notification's\n * recipient/reply-to interpolation points at must not be silently deletable.\n */\n\nimport type { AnyFormField, FormNotification } from \"../types\";\n\nexport interface FieldReference {\n /** What kind of thing holds the reference. */\n kind: \"condition\" | \"notification\";\n /** Human label of the referrer (field label or notification name). */\n label: string;\n}\n\n/**\n * Match `{{ fieldName }}` interpolations (whitespace-tolerant), the syntax the\n * notification send path resolves recipients and reply-to values with.\n */\nfunction referencesInTemplate(template: string, fieldName: string): boolean {\n const pattern = new RegExp(\n `\\\\{\\\\{\\\\s*${fieldName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}\\\\s*\\\\}\\\\}`\n );\n return pattern.test(template);\n}\n\n/** All references to `fieldName` across the form's fields and notifications. */\nexport function findFieldReferences(\n fieldName: string,\n fields: readonly AnyFormField[],\n notifications: readonly FormNotification[]\n): FieldReference[] {\n const references: FieldReference[] = [];\n\n for (const field of fields) {\n if (field.name === fieldName) continue;\n // Disabled conditional logic has no runtime effect, so it must not block\n // deletion; the dormant condition just goes stale.\n if (!field.conditionalLogic?.enabled) continue;\n const conditions = field.conditionalLogic.conditions ?? [];\n if (conditions.some(condition => condition.field === fieldName)) {\n references.push({ kind: \"condition\", label: field.label || field.name });\n }\n }\n\n for (const notification of notifications) {\n // A disabled rule has no runtime effect — like disabled conditional\n // logic above, it must not block deletion; its stale reference just\n // needs re-pointing if the rule is ever re-enabled.\n if (!notification.enabled) continue;\n // Field-sourced recipients and reply-to always carry the {{fieldName}}\n // syntax (the send path's resolveFieldRef only matches that form), so\n // one template check covers to/cc/bcc/replyTo uniformly.\n const templates = [\n notification.to,\n ...(notification.cc ?? []),\n ...(notification.bcc ?? []),\n notification.replyTo,\n ].filter((value): value is string => typeof value === \"string\");\n const referencedByTemplate = templates.some(template =>\n referencesInTemplate(template, fieldName)\n );\n // Send-conditions name the field directly (no interpolation syntax).\n const referencedByCondition = notification.condition?.field === fieldName;\n if (referencedByTemplate || referencedByCondition) {\n references.push({\n kind: \"notification\",\n label: notification.name || \"Notification\",\n });\n }\n }\n\n return references;\n}\n\n/**\n * Reference lists for every field in one pass, keyed by field name, so a\n * per-card lookup is O(1) instead of re-walking fields and notifications for\n * each card on every render.\n */\nexport function buildFieldReferenceMap(\n fields: readonly AnyFormField[],\n notifications: readonly FormNotification[]\n): Map<string, FieldReference[]> {\n const map = new Map<string, FieldReference[]>();\n for (const field of fields) {\n map.set(field.name, findFieldReferences(field.name, fields, notifications));\n }\n return map;\n}\n","\"use client\";\n\n/**\n * Form Builder Context\n *\n * Provides state management for the Form Builder UI.\n * Manages form fields, selection state, and form metadata.\n *\n * @module admin/context/FormBuilderContext\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { FORM_FIELD_TYPE_CATALOG } from \"nextly/field-catalog\";\nimport {\n createContext,\n useContext,\n useCallback,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport type {\n AnyFormField,\n FormFieldTypeId,\n FormNotification,\n FormSettings,\n} from \"../../types\";\nimport {\n DEFAULT_FORM_SETTINGS,\n normalizeFormSettings,\n} from \"../../utils/form-settings\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * The canonical settings shape lives in `types.ts` (the same shape the\n * collection group declares and the submit handler consumes); re-exported\n * here so admin components keep one import site.\n */\nexport type { FormSettings } from \"../../types\";\n\n/**\n * The notification rule type lives in `types.ts` (the same shape the send\n * path consumes); re-exported here so admin components keep one import site.\n */\nexport type { FormNotification } from \"../../types\";\n\nexport interface FormBuilderState {\n /** Form fields array */\n fields: AnyFormField[];\n /** Currently selected field ID (name) */\n selectedFieldId: string | null;\n /** Active tab: builder, preview, settings, or notifications */\n activeTab: \"builder\" | \"preview\" | \"settings\" | \"notifications\";\n /** Whether form has unsaved changes */\n isDirty: boolean;\n /** Form metadata */\n formData: {\n id?: string;\n name: string;\n slug: string;\n description?: string;\n status: \"draft\" | \"published\" | \"closed\";\n };\n /** Form settings */\n settings: FormSettings;\n /** Email notifications */\n notifications: FormNotification[];\n}\n\nexport interface FormBuilderActions {\n /** Set all fields */\n setFields: (fields: AnyFormField[]) => void;\n /** Add a new field */\n addField: (field: AnyFormField, index?: number) => void;\n /** Update a field by name */\n updateField: (fieldName: string, updates: Partial<AnyFormField>) => void;\n /** Delete a field by name */\n deleteField: (fieldName: string) => void;\n /** Move a field from one index to another */\n moveField: (fromIndex: number, toIndex: number) => void;\n /** Duplicate a field */\n duplicateField: (fieldName: string) => void;\n /** Select a field */\n selectField: (fieldName: string | null) => void;\n /** Set active tab */\n setActiveTab: (\n tab: \"builder\" | \"preview\" | \"settings\" | \"notifications\"\n ) => void;\n /** Update form metadata */\n updateFormData: (updates: Partial<FormBuilderState[\"formData\"]>) => void;\n /** Update form settings */\n updateSettings: (updates: Partial<FormSettings>) => void;\n /** Add a notification */\n addNotification: (notification: FormNotification) => void;\n /** Duplicate a notification (the copy starts disabled) */\n duplicateNotification: (id: string) => void;\n /** Update a notification */\n updateNotification: (id: string, updates: Partial<FormNotification>) => void;\n /** Delete a notification */\n deleteNotification: (id: string) => void;\n /** Seed default notifications into an empty list without dirtying the form */\n seedNotifications: (rules: FormNotification[]) => void;\n /** Mark form as saved (clears dirty flag) */\n markAsSaved: () => void;\n}\n\nexport interface FormBuilderContextValue\n extends FormBuilderState,\n FormBuilderActions {}\n\nexport interface FormBuilderProviderProps {\n /** Initial form data (for editing existing forms) */\n initialData?: {\n id?: string;\n name?: string;\n slug?: string;\n description?: string;\n status?: \"draft\" | \"published\" | \"closed\";\n fields?: AnyFormField[];\n settings?: Partial<FormSettings>;\n notifications?: FormNotification[];\n };\n /** Child components */\n children: ReactNode;\n}\n\n/** Default form settings (the canonical defaults from the settings reader) */\nexport const DEFAULT_SETTINGS: FormSettings = DEFAULT_FORM_SETTINGS;\n\n/** Create a new notification rule with default values */\nexport function createNotification(): FormNotification {\n const id = `notif_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 6)}`;\n return {\n id,\n name: \"New notification\",\n enabled: true,\n recipientType: \"static\",\n to: \"\",\n cc: [],\n bcc: [],\n };\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst FormBuilderContext = createContext<FormBuilderContextValue | null>(null);\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Generate a readable unique field name: the type itself for the first\n * field of that type, then a numeric suffix (`email`, `email_2`, ...).\n * Names key submission data, so they should read like keys a developer\n * would have chosen, not timestamps.\n */\nexport function generateFieldName(\n type: FormFieldTypeId,\n existingNames: readonly string[] = []\n): string {\n // A plugin type id can be hyphenated (`star-rating`) or start with a digit,\n // but a field name must match ^[a-zA-Z][a-zA-Z0-9_]*$ (it keys submission\n // data). Normalize to a safe key; built-in type ids are already valid and\n // pass through unchanged.\n const base =\n type\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .replace(/^_+/, \"\")\n .replace(/^([0-9])/, \"field_$1\")\n .replace(/_+$/, \"\") || \"field\";\n const taken = new Set(existingNames);\n if (!taken.has(base)) return base;\n let suffix = 2;\n while (taken.has(`${base}_${suffix}`)) suffix += 1;\n return `${base}_${suffix}`;\n}\n\n/**\n * Generate a human-readable label from field type, using the shared catalog\n * so a new field's default label matches what the picker called the type. A\n * plugin type not in the built-in catalog falls back to a title-cased id.\n */\nexport function generateFieldLabel(type: FormFieldTypeId): string {\n const entry = FORM_FIELD_TYPE_CATALOG.find(row => row.type === type);\n if (entry) return entry.label;\n const titleCased = type\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n return titleCased || \"New Field\";\n}\n\n/**\n * Create a new field from a field type with default values.\n */\nexport function createFieldFromType(\n type: FormFieldTypeId,\n existingNames: readonly string[] = []\n): AnyFormField {\n const name = generateFieldName(type, existingNames);\n const label = generateFieldLabel(type);\n\n const baseField = {\n name,\n label,\n required: false,\n };\n\n switch (type) {\n case \"text\":\n return { ...baseField, type: \"text\" };\n\n case \"email\":\n return { ...baseField, type: \"email\" };\n\n case \"number\":\n return { ...baseField, type: \"number\" };\n\n case \"phone\":\n return { ...baseField, type: \"phone\" };\n\n case \"url\":\n return { ...baseField, type: \"url\" };\n\n case \"textarea\":\n return { ...baseField, type: \"textarea\", rows: 4 };\n\n case \"select\":\n return {\n ...baseField,\n type: \"select\",\n options: [\n { label: \"Option 1\", value: \"option_1\" },\n { label: \"Option 2\", value: \"option_2\" },\n ],\n };\n\n case \"checkbox\":\n return { ...baseField, type: \"checkbox\" };\n\n case \"radio\":\n return {\n ...baseField,\n type: \"radio\",\n options: [\n { label: \"Option 1\", value: \"option_1\" },\n { label: \"Option 2\", value: \"option_2\" },\n ],\n };\n\n case \"file\":\n return { ...baseField, type: \"file\" };\n\n case \"date\":\n return { ...baseField, type: \"date\" };\n\n case \"time\":\n return { ...baseField, type: \"time\" };\n\n case \"hidden\":\n return { ...baseField, type: \"hidden\" };\n\n default:\n // A plugin-contributed type keeps its own id; the plugin owns the editor\n // component and value semantics, so no built-in defaults are seeded.\n return { ...baseField, type };\n }\n}\n\n// ============================================================================\n// Provider\n// ============================================================================\n\n/**\n * FormBuilderProvider - Provides form builder state to child components\n *\n * Wraps the form builder UI to provide centralized state management\n * for fields, selection, and form metadata.\n *\n * @example\n * ```tsx\n * <FormBuilderProvider initialData={existingForm}>\n * <FormBuilderView />\n * </FormBuilderProvider>\n * ```\n */\nexport function FormBuilderProvider({\n initialData,\n children,\n}: FormBuilderProviderProps) {\n // State\n const [fields, setFieldsState] = useState<AnyFormField[]>(\n initialData?.fields || []\n );\n const [selectedFieldId, setSelectedFieldId] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState<\n \"builder\" | \"preview\" | \"settings\" | \"notifications\"\n >(\"builder\");\n const [isDirty, setIsDirty] = useState(false);\n const [formData, setFormData] = useState<FormBuilderState[\"formData\"]>({\n id: initialData?.id,\n name: initialData?.name || \"\",\n slug: initialData?.slug || \"\",\n description: initialData?.description,\n status: initialData?.status || \"draft\",\n });\n // Stored settings may carry legacy keys from earlier builder versions —\n // the normalizer migrates them on read (nothing rewrites until save).\n const [settings, setSettings] = useState<FormSettings>(() =>\n normalizeFormSettings(initialData?.settings)\n );\n const [notifications, setNotifications] = useState<FormNotification[]>(\n initialData?.notifications || []\n );\n\n // Actions\n const setFields = useCallback((newFields: AnyFormField[]) => {\n setFieldsState(newFields);\n setIsDirty(true);\n }, []);\n\n const addField = useCallback((field: AnyFormField, index?: number) => {\n setFieldsState(prev => {\n if (index !== undefined && index >= 0 && index <= prev.length) {\n const newFields = [...prev];\n newFields.splice(index, 0, field);\n return newFields;\n }\n return [...prev, field];\n });\n setSelectedFieldId(field.name);\n setIsDirty(true);\n }, []);\n\n const updateField = useCallback(\n (fieldName: string, updates: Partial<AnyFormField>) => {\n setFieldsState(prev =>\n prev.map(f => (f.name === fieldName ? { ...f, ...updates } : f))\n );\n // If the field name is being changed, also update selectedFieldId\n // This prevents the sidebar from disappearing when renaming a field\n if (updates.name && updates.name !== fieldName) {\n setSelectedFieldId(updates.name);\n }\n setIsDirty(true);\n },\n []\n );\n\n const deleteField = useCallback(\n (fieldName: string) => {\n setFieldsState(prev => prev.filter(f => f.name !== fieldName));\n if (selectedFieldId === fieldName) {\n setSelectedFieldId(null);\n }\n setIsDirty(true);\n },\n [selectedFieldId]\n );\n\n const moveField = useCallback((fromIndex: number, toIndex: number) => {\n setFieldsState(prev => {\n if (\n fromIndex < 0 ||\n fromIndex >= prev.length ||\n toIndex < 0 ||\n toIndex >= prev.length\n ) {\n return prev;\n }\n const newFields = [...prev];\n const [removed] = newFields.splice(fromIndex, 1);\n newFields.splice(toIndex, 0, removed);\n return newFields;\n });\n setIsDirty(true);\n }, []);\n\n const duplicateField = useCallback(\n (fieldName: string) => {\n // Computed from the current fields (not inside the state updater):\n // updaters must stay pure, and the selection below needs the new name\n // deterministically.\n const fieldIndex = fields.findIndex(f => f.name === fieldName);\n if (fieldIndex === -1) return;\n\n const field = fields[fieldIndex];\n const newFieldName = generateFieldName(\n field.type,\n fields.map(f => f.name)\n );\n const newField: AnyFormField = {\n ...field,\n name: newFieldName,\n label: `${field.label} (Copy)`,\n };\n\n const newFields = [...fields];\n newFields.splice(fieldIndex + 1, 0, newField);\n setFieldsState(newFields);\n\n // Select the duplicated field so its card expands\n setSelectedFieldId(newFieldName);\n setIsDirty(true);\n },\n [fields]\n );\n\n const selectField = useCallback((fieldName: string | null) => {\n setSelectedFieldId(fieldName);\n }, []);\n\n const updateFormData = useCallback(\n (updates: Partial<FormBuilderState[\"formData\"]>) => {\n setFormData(prev => ({ ...prev, ...updates }));\n setIsDirty(true);\n },\n []\n );\n\n const updateSettings = useCallback((updates: Partial<FormSettings>) => {\n setSettings(prev => ({ ...prev, ...updates }));\n setIsDirty(true);\n }, []);\n\n const addNotification = useCallback((notification: FormNotification) => {\n setNotifications(prev => [...prev, notification]);\n setIsDirty(true);\n }, []);\n\n const duplicateNotification = useCallback((id: string) => {\n // The non-deterministic id is generated outside the updater (updaters\n // must stay pure and may re-run); the copy itself derives from `prev`\n // so rapid duplications never work from a stale snapshot.\n const copyId = `notif_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 6)}`;\n setNotifications(prev => {\n const index = prev.findIndex(n => n.id === id);\n if (index === -1) return prev;\n const source = prev[index];\n const copy: FormNotification = {\n ...source,\n id: copyId,\n name: `${source.name} (Copy)`,\n // Copies start disabled so duplicating never doubles the emails a\n // live rule sends until the copy is deliberately turned on.\n enabled: false,\n };\n const next = [...prev];\n next.splice(index + 1, 0, copy);\n return next;\n });\n setIsDirty(true);\n }, []);\n\n const seedNotifications = useCallback((rules: FormNotification[]) => {\n // Only fills an empty list, and does not mark the form dirty: the seed\n // is a starting point the user hasn't authored, not an unsaved edit.\n setNotifications(prev => (prev.length > 0 ? prev : rules));\n }, []);\n\n const updateNotification = useCallback(\n (id: string, updates: Partial<FormNotification>) => {\n setNotifications(prev =>\n prev.map(n => (n.id === id ? { ...n, ...updates } : n))\n );\n setIsDirty(true);\n },\n []\n );\n\n const deleteNotification = useCallback((id: string) => {\n setNotifications(prev => prev.filter(n => n.id !== id));\n setIsDirty(true);\n }, []);\n\n const markAsSaved = useCallback(() => {\n setIsDirty(false);\n }, []);\n\n // Memoized context value\n const value = useMemo<FormBuilderContextValue>(\n () => ({\n // State\n fields,\n selectedFieldId,\n activeTab,\n isDirty,\n formData,\n settings,\n notifications,\n // Actions\n setFields,\n addField,\n updateField,\n deleteField,\n moveField,\n duplicateField,\n selectField,\n setActiveTab,\n updateFormData,\n updateSettings,\n addNotification,\n duplicateNotification,\n updateNotification,\n deleteNotification,\n seedNotifications,\n markAsSaved,\n }),\n [\n fields,\n selectedFieldId,\n activeTab,\n isDirty,\n formData,\n settings,\n notifications,\n setFields,\n addField,\n updateField,\n deleteField,\n moveField,\n duplicateField,\n selectField,\n updateFormData,\n updateSettings,\n addNotification,\n duplicateNotification,\n updateNotification,\n deleteNotification,\n seedNotifications,\n markAsSaved,\n ]\n );\n\n return (\n <FormBuilderContext.Provider value={value}>\n {children}\n </FormBuilderContext.Provider>\n );\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * useFormBuilder - Access form builder context\n *\n * Hook to access form builder state and actions from within the builder UI.\n * Must be used within a FormBuilderProvider.\n *\n * @returns Form builder context value\n * @throws Error if used outside of FormBuilderProvider\n *\n * @example\n * ```tsx\n * function FieldList() {\n * const { fields, selectField, deleteField } = useFormBuilder();\n *\n * return (\n * <ul>\n * {fields.map(field => (\n * <li key={field.name} onClick={() => selectField(field.name)}>\n * {field.label}\n * <button onClick={() => deleteField(field.name)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useFormBuilder(): FormBuilderContextValue {\n const context = useContext(FormBuilderContext);\n\n if (!context) {\n throw new Error(\"useFormBuilder must be used within a FormBuilderProvider\");\n }\n\n return context;\n}\n\n/**\n * useOptionalFormBuilder - Access form builder context safely\n *\n * Like useFormBuilder but returns null if not within a provider.\n * Useful for components that may be rendered outside of the form builder.\n *\n * @returns Form builder context value or null\n */\nexport function useOptionalFormBuilder(): FormBuilderContextValue | null {\n return useContext(FormBuilderContext);\n}\n","\"use client\";\n\n/**\n * Add Field Dialog\n *\n * Type selection for new form fields, rendered from the shared field-type\n * catalog via the SDK's FieldTypePicker so the form surface shows the same\n * labels, icons, and hints as every other field picker in the admin.\n *\n * @module admin/components/builder/AddFieldDialog\n */\n\nimport { FieldTypePicker } from \"@nextlyhq/plugin-sdk/admin\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@nextlyhq/ui\";\nimport type { FieldTypeCatalogEntry } from \"nextly/field-catalog\";\nimport { useState } from \"react\";\n\nimport type { FormFieldTypeId } from \"../../../types\";\n\nexport interface AddFieldDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /**\n * The form surface's catalog — built-ins already filtered by the host's\n * excludes plus any plugin field types that opted into the forms surface;\n * `null` while the host configuration is still loading. `type` is the open\n * `FormFieldTypeId` so a plugin entry shares this shape with the built-ins.\n */\n entries: readonly FieldTypeCatalogEntry<FormFieldTypeId>[] | null;\n /** Called with the chosen type; the parent creates and selects the field. */\n onAdd: (type: FormFieldTypeId) => void;\n}\n\nexport function AddFieldDialog({\n open,\n onOpenChange,\n entries,\n onAdd,\n}: AddFieldDialogProps) {\n const [selected, setSelected] = useState<FormFieldTypeId>(\"text\");\n\n const selectable = entries?.some(entry => entry.type === selected)\n ? selected\n : entries?.[0]?.type;\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-2xl\">\n <DialogHeader>\n <DialogTitle>Add field</DialogTitle>\n <DialogDescription>\n Pick the field type. Everything else is edited on the field card.\n </DialogDescription>\n </DialogHeader>\n\n {entries === null ? (\n <p className=\"text-sm text-muted-foreground\" role=\"status\">\n Loading the available field types…\n </p>\n ) : entries.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n All field types are disabled by this site's form-builder\n configuration.\n </p>\n ) : (\n <FieldTypePicker\n entries={entries}\n value={selectable ?? \"text\"}\n onChange={setSelected}\n columns={3}\n ariaLabel=\"Field type\"\n />\n )}\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n disabled={!selectable}\n onClick={() => {\n if (selectable) onAdd(selectable);\n onOpenChange(false);\n }}\n >\n Add field\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\";\n\n/**\n * Field Editor\n *\n * Properties panel for editing the selected field's configuration.\n * Provides tabbed interface for General, Validation, and Conditional settings.\n *\n * @module admin/components/builder/FieldEditor\n * @since 0.1.0\n */\n\n\"use client\";\nimport {\n FieldOptionsEditor,\n withOptionIds,\n type FieldOptionsEditorProps,\n} from \"@nextlyhq/plugin-sdk/admin\";\nimport {\n FormLabelWithTooltip,\n Input,\n Checkbox,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@nextlyhq/ui\";\nimport { useState, useCallback, useMemo } from \"react\";\n\nimport type {\n AnyFormField,\n FormField,\n TextFormField,\n SelectFormField,\n RadioFormField,\n} from \"../../../types\";\nimport { isKnownFormField } from \"../../../types\";\n\nimport { ConditionalLogicEditor } from \"./ConditionalLogicEditor\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FieldEditorProps {\n /** The field being edited (built-in or plugin-contributed). */\n field: AnyFormField;\n /** All fields in the form (for conditional logic references) */\n allFields: AnyFormField[];\n /** Callback when field is updated */\n onUpdate: (updates: Partial<AnyFormField>) => void;\n}\n\n// ============================================================================\n// Helper Components\n// ============================================================================\n\n/**\n * General properties tab - common field settings\n */\nfunction GeneralTab({\n field,\n allFields,\n onUpdate,\n}: {\n field: AnyFormField;\n allFields: AnyFormField[];\n onUpdate: (updates: Partial<AnyFormField>) => void;\n}) {\n // Check if other fields have conditional logic referencing this field\n const hasConditionalReferences = useMemo(() => {\n return allFields.some(f => {\n if (f.name === field.name || !f.conditionalLogic?.enabled) return false;\n return f.conditionalLogic.conditions.some(c => c.field === field.name);\n });\n }, [allFields, field.name]);\n\n return (\n <div className=\"space-y-6 py-4\">\n {/* Field Name */}\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Field Name (ID)\"\n htmlFor=\"field-name\"\n description=\"Used as the key in submission data. Should be unique and contain no spaces.\"\n />\n <Input\n id=\"field-name\"\n type=\"text\"\n value={field.name}\n onChange={e => onUpdate({ name: e.target.value })}\n pattern=\"^[a-zA-Z][a-zA-Z0-9_]*$\"\n className=\"bg-transparent\"\n />\n {hasConditionalReferences && (\n <p className=\"text-[11px] text-warning font-medium\">\n ⚠️ Changing this may break conditional logic referencing this field\n </p>\n )}\n </div>\n\n {/* Label - not shown for hidden fields */}\n {field.type !== \"hidden\" && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Label\"\n htmlFor=\"field-label\"\n description=\"The text displayed above the field in the form.\"\n />\n <Input\n id=\"field-label\"\n type=\"text\"\n value={field.label}\n onChange={e => onUpdate({ label: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* Placeholder - for text-like fields */}\n {(field.type === \"text\" ||\n field.type === \"email\" ||\n field.type === \"phone\" ||\n field.type === \"url\" ||\n field.type === \"number\" ||\n field.type === \"textarea\") && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Placeholder\"\n htmlFor=\"field-placeholder\"\n description=\"The faint text shown inside the field when empty.\"\n />\n <Input\n id=\"field-placeholder\"\n type=\"text\"\n value={field.placeholder || \"\"}\n onChange={e => onUpdate({ placeholder: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* Help Text - not shown for hidden fields */}\n {field.type !== \"hidden\" && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Help Text\"\n htmlFor=\"field-help\"\n description=\"Additional instructions displayed below the field.\"\n />\n <Input\n id=\"field-help\"\n type=\"text\"\n value={field.helpText || \"\"}\n onChange={e => onUpdate({ helpText: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* Required - not shown for hidden or checkbox fields */}\n {field.type !== \"hidden\" && field.type !== \"checkbox\" && (\n <div className=\"flex items-center gap-3 pt-1\">\n <Checkbox\n id=\"field-required\"\n checked={field.required || false}\n onCheckedChange={checked =>\n onUpdate({ required: checked === true })\n }\n />\n <FormLabelWithTooltip\n label=\"Required field\"\n htmlFor=\"field-required\"\n description=\"Forces the user to fill this field before submitting.\"\n />\n </div>\n )}\n\n {/* Width */}\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Width\"\n htmlFor=\"field-width\"\n description=\"How much space this field takes in a horizontal row.\"\n />\n <Select\n value={field.admin?.width || \"100%\"}\n onValueChange={value =>\n onUpdate({\n admin: {\n ...field.admin,\n width: value as \"25%\" | \"33%\" | \"50%\" | \"66%\" | \"75%\" | \"100%\",\n },\n })\n }\n >\n <SelectTrigger className=\"w-full bg-transparent border-input dark:bg-muted/50\">\n <SelectValue placeholder=\"Select width\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"100%\">Full Width (100%)</SelectItem>\n <SelectItem value=\"75%\">Three Quarters (75%)</SelectItem>\n <SelectItem value=\"66%\">Two Thirds (66%)</SelectItem>\n <SelectItem value=\"50%\">Half (50%)</SelectItem>\n <SelectItem value=\"33%\">One Third (33%)</SelectItem>\n <SelectItem value=\"25%\">One Quarter (25%)</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Type-specific options — built-ins only; a plugin field owns its own\n editor component and carries no built-in type-specific settings. */}\n {isKnownFormField(field) && (\n <TypeSpecificOptions field={field} onUpdate={onUpdate} />\n )}\n </div>\n );\n}\n\n/**\n * Type-specific field options\n */\nfunction TypeSpecificOptions({\n field,\n onUpdate,\n}: {\n field: FormField;\n onUpdate: (updates: Partial<FormField>) => void;\n}) {\n switch (field.type) {\n case \"select\":\n case \"radio\":\n return <OptionsEditor field={field} onUpdate={onUpdate} />;\n\n case \"textarea\": {\n const textareaField = field;\n return (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Rows\"\n htmlFor=\"field-rows\"\n description=\"Height of the textarea in text lines.\"\n />\n <Input\n id=\"field-rows\"\n type=\"number\"\n min={2}\n max={20}\n value={textareaField.rows || 4}\n onChange={e => onUpdate({ rows: parseInt(e.target.value) || 4 })}\n className=\"w-24 bg-transparent\"\n />\n </div>\n );\n }\n\n case \"file\": {\n const fileField = field;\n return (\n <>\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Accepted File Types\"\n htmlFor=\"field-accept\"\n description=\"Comma-separated MIME types (e.g., image/*, application/pdf).\"\n />\n <Input\n id=\"field-accept\"\n type=\"text\"\n value={fileField.accept || \"\"}\n onChange={e => onUpdate({ accept: e.target.value })}\n placeholder=\"image/*,application/pdf\"\n className=\"bg-transparent\"\n />\n </div>\n <div className=\"flex items-center gap-3 pt-1\">\n <Checkbox\n id=\"field-multiple\"\n checked={fileField.multiple || false}\n onCheckedChange={checked =>\n onUpdate({ multiple: checked === true })\n }\n />\n <FormLabelWithTooltip\n label=\"Allow multiple files\"\n htmlFor=\"field-multiple\"\n description=\"Users can upload more than one file at once.\"\n />\n </div>\n <div className=\"flex items-center gap-3 pt-1\">\n <Checkbox\n id=\"field-attach-to-email\"\n checked={fileField.attachToEmail || false}\n onCheckedChange={checked =>\n onUpdate({ attachToEmail: checked === true })\n }\n />\n <FormLabelWithTooltip\n label=\"Attach to notification emails\"\n htmlFor=\"field-attach-to-email\"\n description=\"Uploaded files will be attached to all notification emails for this form.\"\n />\n </div>\n </>\n );\n }\n\n case \"hidden\": {\n const hiddenField = field;\n return (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Default Value\"\n htmlFor=\"field-default\"\n description=\"This value will be submitted silently with the form.\"\n />\n <Input\n id=\"field-default\"\n type=\"text\"\n value={hiddenField.defaultValue || \"\"}\n onChange={e => onUpdate({ defaultValue: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n );\n }\n\n case \"date\": {\n const dateField = field;\n return (\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Minimum Date\"\n htmlFor=\"min-date\"\n description=\"Lower bound for date selection.\"\n />\n <Input\n id=\"min-date\"\n type=\"date\"\n value={dateField.min || \"\"}\n onChange={e => onUpdate({ min: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Maximum Date\"\n htmlFor=\"max-date\"\n description=\"Upper bound for date selection.\"\n />\n <Input\n id=\"max-date\"\n type=\"date\"\n value={dateField.max || \"\"}\n onChange={e => onUpdate({ max: e.target.value })}\n className=\"bg-transparent\"\n />\n </div>\n </div>\n );\n }\n\n case \"number\": {\n const numField = field;\n return (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Step\"\n htmlFor=\"field-step\"\n description=\"Increment/decrement step (e.g., 0.01 for decimals).\"\n />\n <Input\n id=\"field-step\"\n type=\"number\"\n value={numField.validation?.step || \"\"}\n onChange={e =>\n onUpdate({\n validation: {\n ...numField.validation,\n step: parseFloat(e.target.value) || undefined,\n },\n })\n }\n placeholder=\"1\"\n className=\"w-24 bg-transparent\"\n />\n </div>\n );\n }\n\n default:\n return null;\n }\n}\n\ntype KitOption = FieldOptionsEditorProps[\"options\"][number];\n\n/**\n * Options editor for select/radio fields, delegating to the SDK's\n * FieldOptionsEditor (drag reorder, auto-generated values, CSV/JSON import,\n * duplicate-value reporting). The kit works on id-carrying rows for\n * drag-and-drop; the form stores plain {label, value} pairs, so ids live in\n * local state and are stripped before every write.\n */\nfunction OptionsEditor({\n field,\n onUpdate,\n}: {\n field: FormField;\n onUpdate: (updates: Partial<FormField>) => void;\n}) {\n const optionsField = field as SelectFormField | RadioFormField;\n\n const [kitOptions, setKitOptions] = useState<KitOption[]>(() =>\n withOptionIds(optionsField.options || [])\n );\n\n const handleOptionsChange = useCallback(\n (next: KitOption[]) => {\n setKitOptions(next);\n onUpdate({\n options: next.map(({ label, value }) => ({ label, value })),\n });\n },\n [onUpdate]\n );\n\n return (\n <div className=\"space-y-3 pt-6\">\n <FormLabelWithTooltip\n label=\"Options\"\n description=\"List of choices available for this field.\"\n />\n <FieldOptionsEditor\n options={kitOptions}\n onOptionsChange={handleOptionsChange}\n />\n </div>\n );\n}\n\n/**\n * Validation tab - field validation settings\n */\nfunction ValidationTab({\n field,\n onUpdate,\n}: {\n field: FormField;\n onUpdate: (updates: Partial<FormField>) => void;\n}) {\n const validation = useMemo(() => field.validation || {}, [field.validation]);\n\n const updateValidation = useCallback(\n (key: string, value: string | number | undefined) => {\n onUpdate({\n validation: { ...validation, [key]: value },\n });\n },\n [validation, onUpdate]\n );\n\n return (\n <div className=\"space-y-6 pt-2\">\n {/* Custom error message */}\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Custom Error Message\"\n htmlFor=\"error-message\"\n description=\"Override the default browser validation message.\"\n />\n <Input\n id=\"error-message\"\n type=\"text\"\n value={validation.errorMessage || \"\"}\n onChange={e => updateValidation(\"errorMessage\", e.target.value)}\n placeholder=\"This field is required\"\n className=\"bg-transparent\"\n />\n </div>\n\n {/* Text/Textarea length validation */}\n {(field.type === \"text\" || field.type === \"textarea\") && (\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Min Length\"\n htmlFor=\"min-len\"\n description=\"Minimum characters required.\"\n />\n <Input\n id=\"min-len\"\n type=\"number\"\n min={0}\n value={(field as TextFormField).validation?.minLength ?? \"\"}\n onChange={e =>\n updateValidation(\n \"minLength\",\n e.target.value ? parseInt(e.target.value) : undefined\n )\n }\n className=\"bg-transparent\"\n />\n </div>\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Max Length\"\n htmlFor=\"max-len\"\n description=\"Maximum characters allowed.\"\n />\n <Input\n id=\"max-len\"\n type=\"number\"\n min={0}\n value={(field as TextFormField).validation?.maxLength ?? \"\"}\n onChange={e =>\n updateValidation(\n \"maxLength\",\n e.target.value ? parseInt(e.target.value) : undefined\n )\n }\n className=\"bg-transparent\"\n />\n </div>\n </div>\n )}\n\n {/* Number min/max validation */}\n {field.type === \"number\" && (\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Min Value\"\n htmlFor=\"min-val\"\n description=\"Minimum numerical value.\"\n />\n <Input\n id=\"min-val\"\n type=\"number\"\n value={field.validation?.min ?? \"\"}\n onChange={e =>\n updateValidation(\n \"min\",\n e.target.value ? parseFloat(e.target.value) : undefined\n )\n }\n className=\"bg-transparent\"\n />\n </div>\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Max Value\"\n htmlFor=\"max-val\"\n description=\"Maximum numerical value.\"\n />\n <Input\n id=\"max-val\"\n type=\"number\"\n value={field.validation?.max ?? \"\"}\n onChange={e =>\n updateValidation(\n \"max\",\n e.target.value ? parseFloat(e.target.value) : undefined\n )\n }\n className=\"bg-transparent\"\n />\n </div>\n </div>\n )}\n\n {/* Pattern validation for text fields */}\n {(field.type === \"text\" ||\n field.type === \"email\" ||\n field.type === \"phone\" ||\n field.type === \"url\") && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Pattern (Regex)\"\n htmlFor=\"val-pattern\"\n description=\"Regular expression for advanced validation.\"\n />\n <Input\n id=\"val-pattern\"\n type=\"text\"\n value={(field as TextFormField).validation?.pattern || \"\"}\n onChange={e => updateValidation(\"pattern\", e.target.value)}\n placeholder=\"^[A-Za-z]+$\"\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* File size validation */}\n {field.type === \"file\" && (\n <div className=\"space-y-2\">\n <FormLabelWithTooltip\n label=\"Max File Size (bytes)\"\n htmlFor=\"max-file-size\"\n description=\"Maximum allowed size in bytes (10MB ≈ 10485760).\"\n />\n <Input\n id=\"max-file-size\"\n type=\"number\"\n min={0}\n value={field.maxFileSize ?? \"\"}\n onChange={e =>\n onUpdate({\n maxFileSize: e.target.value\n ? parseInt(e.target.value)\n : undefined,\n })\n }\n placeholder=\"10485760\"\n className=\"bg-transparent\"\n />\n </div>\n )}\n\n {/* Info for fields without validation options */}\n {(field.type === \"checkbox\" || field.type === \"hidden\") && (\n // Semantic border token so this info-box boundary is visible at the 3:1 UI minimum.\n <div className=\"p-3 bg-muted rounded-none text-xs text-muted-foreground text-center border border-dashed border-border\">\n No additional validation options for this field type.\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * FieldEditor - Field properties configuration panel\n *\n * Provides a tabbed interface for editing field properties:\n * - General: name, label, placeholder, help text, required, width, type-specific options\n * - Validation: error messages, min/max length, patterns, etc.\n * - Conditional: show/hide logic based on other field values\n *\n * @example\n * ```tsx\n * <FieldEditor\n * field={selectedField}\n * allFields={allFields}\n * onUpdate={handleUpdate}\n * onDelete={handleDelete}\n * onDuplicate={handleDuplicate}\n * />\n * ```\n */\nexport function FieldEditor({ field, allFields, onUpdate }: FieldEditorProps) {\n const [activeTab, setActiveTab] = useState<string>(\"general\");\n\n return (\n <div className=\"flex flex-col\">\n {/* Tabs */}\n <Tabs\n value={activeTab}\n onValueChange={setActiveTab}\n className=\"flex-1 flex flex-col\"\n >\n {/* Semantic border token so the tab-bar bottom edge is visible at the 3:1 UI minimum. */}\n <div className=\"border-b bg-muted border-border\">\n <TabsList className=\"w-full justify-start gap-0\">\n <TabsTrigger\n value=\"general\"\n className=\"w-full rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-background/50 transition-all\"\n >\n General\n </TabsTrigger>\n <TabsTrigger\n value=\"validation\"\n className=\"w-full rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-background/50 transition-all\"\n >\n Validation\n </TabsTrigger>\n <TabsTrigger\n value=\"conditional\"\n className=\"w-full rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-background/50 transition-all\"\n >\n Conditional\n </TabsTrigger>\n </TabsList>\n </div>\n\n {/* Content */}\n <div className=\"p-4\">\n <TabsContent value=\"general\" className=\"mt-0\">\n <GeneralTab\n field={field}\n allFields={allFields}\n onUpdate={onUpdate}\n />\n </TabsContent>\n\n <TabsContent value=\"validation\" className=\"mt-0\">\n {isKnownFormField(field) ? (\n <ValidationTab field={field} onUpdate={onUpdate} />\n ) : (\n <p className=\"py-4 text-sm text-muted-foreground\">\n This field type manages its own validation.\n </p>\n )}\n </TabsContent>\n\n <TabsContent value=\"conditional\" className=\"mt-0\">\n <ConditionalLogicEditor\n field={field}\n allFields={allFields}\n onUpdate={onUpdate}\n />\n </TabsContent>\n </div>\n </Tabs>\n </div>\n );\n}\n\nexport default FieldEditor;\n","\"use client\";\n\n/**\n * Conditional Logic Editor\n *\n * Component for configuring conditional show/hide logic for form fields.\n * Allows users to define conditions based on other field values.\n *\n * @module admin/components/builder/ConditionalLogicEditor\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport {\n ConditionRow,\n type ConditionOperatorName,\n type ConditionSource,\n} from \"@nextlyhq/plugin-sdk/admin\";\nimport {\n FormLabelWithTooltip,\n Button,\n Checkbox,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@nextlyhq/ui\";\nimport { useCallback, useMemo } from \"react\";\n\nimport type {\n AnyFormField,\n ConditionalLogic,\n ConditionalLogicCondition,\n} from \"../../../types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ConditionalLogicEditorProps {\n /** The field being edited (built-in or plugin-contributed). */\n field: AnyFormField;\n /** All fields in the form (for field references) */\n allFields: AnyFormField[];\n /** Callback when conditional logic is updated */\n onUpdate: (updates: Partial<AnyFormField>) => void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * The comparisons `evaluateConditions` implements.\n *\n * The shared row offers seventeen operators, and this runtime understands\n * seven of them. Every operator offered has to be one this evaluator can\n * answer: a field configured with `isTrue` would store fine, render fine, and\n * then never match at form time, with nothing anywhere to say why. So the\n * vocabulary is pinned here rather than taken from the row's default.\n *\n * Typed as the shared row's operator names AND as this module's stored\n * comparisons, so the day either list moves the other stops compiling.\n */\nconst SUPPORTED_COMPARISONS = [\n \"equals\",\n \"notEquals\",\n \"contains\",\n \"isEmpty\",\n \"isNotEmpty\",\n \"greaterThan\",\n \"lessThan\",\n] as const satisfies readonly ConditionOperatorName[] &\n readonly ConditionalLogicCondition[\"comparison\"][];\n\nconst SUPPORTED_SET: ReadonlySet<string> = new Set(SUPPORTED_COMPARISONS);\n\n/**\n * Whether an operator the row reported is one this runtime can evaluate.\n *\n * `operatorsFor` already narrows what the row offers, so this should always\n * hold; it is a guard rather than an assertion so that if the two ever drift,\n * the condition is left as it was instead of stored in a shape the evaluator\n * will not understand.\n */\nfunction isSupportedComparison(\n operator: string\n): operator is ConditionalLogicCondition[\"comparison\"] {\n return SUPPORTED_SET.has(operator);\n}\n\n// The field types whose values are text, named as `FormFieldType` spells them.\n// `tel` and `password` were guesses and match nothing; the builder's telephone\n// field is `phone`, so it was falling through to the full comparison set and\n// offering \"greater than\" for a phone number.\nconst TEXT_TYPES = new Set([\n \"text\",\n \"textarea\",\n \"email\",\n \"url\",\n \"phone\",\n \"hidden\",\n]);\n\n/**\n * The comparisons worth offering for a source type, within what the evaluator\n * supports.\n *\n * Narrower than the full seven where the type makes some of them meaningless:\n * \"contains\" on a number compares substrings of a formatted value, which is\n * not what anyone building that condition means.\n */\nfunction comparisonsForType(\n sourceType: string | undefined\n): ConditionOperatorName[] {\n if (sourceType === \"checkbox\") return [\"equals\", \"notEquals\"];\n if (sourceType === \"number\") {\n return [\"equals\", \"notEquals\", \"greaterThan\", \"lessThan\"];\n }\n if (sourceType !== undefined && TEXT_TYPES.has(sourceType)) {\n return [\"equals\", \"notEquals\", \"contains\", \"isEmpty\", \"isNotEmpty\"];\n }\n return [...SUPPORTED_COMPARISONS];\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * A form field as the shared row needs to see it.\n *\n * Choice fields hand over their options so the value editor becomes a dropdown\n * of exactly those, rather than a text box in which an option can be misspelled\n * into a condition that never matches.\n */\nfunction toSource(field: AnyFormField): ConditionSource {\n // Only the choice field types carry an option list, and `AnyFormField` is a\n // union over every type, so the property has to be probed rather than read.\n // An option with an empty value is dropped: a Select cannot render one, and\n // it is a placeholder row in the editor rather than a value to compare with.\n const options =\n \"options\" in field && Array.isArray(field.options)\n ? field.options\n .filter(option => option.value !== \"\")\n .map(option => ({ value: option.value, label: option.label }))\n : undefined;\n return {\n name: field.name,\n label: field.label || field.name,\n type: field.type,\n options,\n };\n}\n\n/**\n * A stored condition's value as the row edits it.\n *\n * Storage types this `unknown`, and the row edits scalars. An object that got\n * in some other way is shown as nothing rather than as `[object Object]`,\n * which is not a value anyone typed and not one the evaluator can use.\n */\nfunction toRowValue(value: unknown): string | number | boolean | undefined {\n if (value === null || value === undefined) return undefined;\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return value;\n }\n return undefined;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * ConditionalLogicEditor - Configure conditional show/hide logic\n *\n * Allows users to define when a field should be shown or hidden\n * based on the values of other fields in the form.\n *\n * @example\n * ```tsx\n * <ConditionalLogicEditor\n * field={selectedField}\n * allFields={allFields}\n * onUpdate={handleUpdate}\n * />\n * ```\n */\nexport function ConditionalLogicEditor({\n field,\n allFields,\n onUpdate,\n}: ConditionalLogicEditorProps) {\n // Get current conditional logic or create default.\n // Wrapped in useMemo so dependent useCallbacks don't re-create on every render.\n const logic: ConditionalLogic = useMemo(\n () =>\n field.conditionalLogic || {\n enabled: false,\n action: \"show\",\n operator: \"AND\",\n conditions: [],\n },\n [field.conditionalLogic]\n );\n\n // Get other fields that can be referenced (exclude current field)\n const availableFields = allFields.filter(f => f.name !== field.name);\n\n // Update the entire conditional logic object\n const updateLogic = useCallback(\n (updates: Partial<ConditionalLogic>) => {\n onUpdate({\n conditionalLogic: { ...logic, ...updates },\n });\n },\n [logic, onUpdate]\n );\n\n // Toggle enabled state\n const handleToggleEnabled = useCallback(() => {\n updateLogic({ enabled: !logic.enabled });\n }, [logic.enabled, updateLogic]);\n\n // Add a new condition\n const handleAddCondition = useCallback(() => {\n const firstField = availableFields[0];\n if (!firstField) return;\n\n const newCondition: ConditionalLogicCondition = {\n field: firstField.name,\n comparison: \"equals\",\n value: \"\",\n };\n\n updateLogic({\n conditions: [...logic.conditions, newCondition],\n });\n }, [availableFields, logic.conditions, updateLogic]);\n\n // Update a specific condition\n const handleUpdateCondition = useCallback(\n (index: number, updates: Partial<ConditionalLogicCondition>) => {\n const newConditions = logic.conditions.map((c, i) =>\n i === index ? { ...c, ...updates } : c\n );\n updateLogic({ conditions: newConditions });\n },\n [logic.conditions, updateLogic]\n );\n\n // Remove a condition\n const handleRemoveCondition = useCallback(\n (index: number) => {\n const newConditions = logic.conditions.filter((_, i) => i !== index);\n updateLogic({ conditions: newConditions });\n },\n [logic.conditions, updateLogic]\n );\n\n return (\n <div className=\"space-y-6 pt-2\">\n {/* Enable toggle */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Checkbox\n id=\"logic-enabled\"\n checked={logic.enabled}\n onCheckedChange={handleToggleEnabled}\n />\n <FormLabelWithTooltip\n label=\"Enable conditional logic\"\n htmlFor=\"logic-enabled\"\n description=\"Show or hide this field based on other field values.\"\n />\n </div>\n </div>\n\n {logic.enabled && (\n // Semantic border token so this top divider is visible at the 3:1 UI minimum.\n <div className=\"space-y-4 pt-4 border-t border-border\">\n {/* Action and operator row */}\n <div className=\"flex flex-wrap items-center gap-2 text-sm text-muted-foreground\">\n <Select\n value={logic.action}\n onValueChange={value =>\n updateLogic({ action: value as \"show\" | \"hide\" })\n }\n >\n <SelectTrigger className=\"w-[100px] h-9 bg-transparent border-input dark:bg-muted/50\">\n <SelectValue placeholder=\"Show/Hide\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"show\">Show</SelectItem>\n <SelectItem value=\"hide\">Hide</SelectItem>\n </SelectContent>\n </Select>\n <span>this field when</span>\n <Select\n value={logic.operator}\n onValueChange={value =>\n updateLogic({ operator: value as \"AND\" | \"OR\" })\n }\n >\n <SelectTrigger className=\"w-[80px] h-9 bg-transparent border-input dark:bg-muted/50\">\n <SelectValue placeholder=\"All/Any\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"AND\">All</SelectItem>\n <SelectItem value=\"OR\">Any</SelectItem>\n </SelectContent>\n </Select>\n <span>of the following conditions are met:</span>\n </div>\n\n {/* Conditions list */}\n <div className=\"space-y-3 pt-4\">\n {logic.conditions.length === 0 ? (\n // Semantic border token so this empty-state boundary is visible at the 3:1 UI minimum.\n <div className=\"p-4 bg-muted rounded-none border border-dashed border-border text-center text-xs text-muted-foreground\">\n No conditions defined. Add a condition to get started.\n </div>\n ) : (\n logic.conditions.map((condition, index) => (\n // Semantic border token so this condition card boundary is visible at the 3:1 UI minimum.\n <div\n key={index}\n className=\"flex flex-col gap-2 p-3 rounded-none bg-muted border border-border relative group\"\n >\n {/* Source, comparison and value, shared with the schema\n builder. Stacked rather than in three columns: this card\n sits in a builder sidebar, where three columns leave each\n control too narrow to read its own selection. */}\n <ConditionRow\n className=\"grid grid-cols-1 gap-2\"\n condition={{\n field: condition.field,\n operator: condition.comparison,\n value: toRowValue(condition.value),\n }}\n sources={availableFields.map(toSource)}\n operatorsFor={comparisonsForType}\n onChange={next => {\n if (!next || !isSupportedComparison(next.operator))\n return;\n handleUpdateCondition(index, {\n field: next.field,\n comparison: next.operator,\n value: toRowValue(next.value),\n });\n }}\n />\n\n {/* Remove button */}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleRemoveCondition(index)}\n // Semantic border token so the remove button's boundary is visible at the 3:1 UI minimum.\n className=\"absolute -top-2 -right-2 h-6 w-6 rounded-full bg-background border border-border opacity-0 group-hover:opacity-100 transition-opacity\"\n title=\"Remove condition\"\n >\n <span className=\"text-xs\">×</span>\n </Button>\n </div>\n ))\n )}\n </div>\n\n {/* Add condition button */}\n {availableFields.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleAddCondition}\n className=\"w-full mt-4 border-dashed\"\n >\n + Add Condition\n </Button>\n ) : (\n // Full-strength warning border so this notice boundary is perceivable over its tinted fill.\n <p className=\"mt-4 text-center text-xs text-warning font-medium bg-warning/10 p-2 rounded-none border border-warning\">\n Add more fields to the form to create conditions.\n </p>\n )}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Form Notifications Tab\n *\n * Per-form email notification rules: a list of cards, each editing in a\n * side sheet. A rule targets a static address or the visitor (via one of\n * the form's email fields), can set Reply-To from a field so replies reach\n * the visitor, and can carry a single send-condition evaluated against the\n * submitted data. An autoresponder is just a rule whose recipient is the\n * visitor — there is no separate feature.\n *\n * @module admin/components/builder/FormNotificationsTab\n */\n\nimport {\n Badge,\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Switch,\n} from \"@nextlyhq/ui\";\nimport {\n Copy,\n Filter,\n Mail,\n MoreHorizontal,\n Pencil,\n Plus,\n Trash2,\n TriangleAlert,\n X,\n} from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\n\nimport type { ConditionalLogicCondition } from \"../../../types\";\nimport {\n useFormBuilder,\n createNotification,\n type FormNotification,\n} from \"../../context/FormBuilderContext\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Host-level notification defaults surfaced by the builder-config route. */\nexport interface NotificationDefaults {\n defaultFrom?: string;\n defaultToEmail?: string;\n}\n\ninterface FormNotificationsTabProps {\n /** `null` while the builder-config request is still settling. */\n defaults: NotificationDefaults | null;\n}\n\ninterface ProviderOption {\n id: string;\n name: string;\n type: string;\n isDefault: boolean;\n}\n\ninterface TemplateOption {\n id: string;\n name: string;\n slug: string;\n isActive: boolean;\n /** \"template\" or \"layout\" — layouts wrap templates and cannot be sent. */\n kind?: string;\n}\n\ninterface FieldOption {\n name: string;\n label: string;\n type: string;\n}\n\n// ============================================================================\n// API helpers\n// ============================================================================\n\nasync function fetchProviders(): Promise<ProviderOption[]> {\n try {\n const res = await fetch(\"/admin/api/email-providers?pageSize=100&page=1\", {\n credentials: \"include\",\n });\n if (!res.ok) return [];\n const json = (await res.json()) as { providers?: ProviderOption[] };\n return json.providers ?? [];\n } catch {\n return [];\n }\n}\n\nasync function fetchTemplates(): Promise<TemplateOption[]> {\n try {\n const res = await fetch(\"/admin/api/email-templates\", {\n credentials: \"include\",\n });\n if (!res.ok) return [];\n const json = (await res.json()) as { templates?: TemplateOption[] };\n return json.templates ?? [];\n } catch {\n return [];\n }\n}\n\n// ============================================================================\n// Field-reference helpers\n// ============================================================================\n\n/** The `{{fieldName}}` shape the send path resolves against submissions. */\nconst FIELD_REF_PATTERN = /^\\{\\{(\\w+)\\}\\}$/;\n\nfunction toFieldRef(fieldName: string): string {\n return `{{${fieldName}}}`;\n}\n\nfunction parseFieldRef(value: string | undefined): string | null {\n if (!value) return null;\n const match = value.match(FIELD_REF_PATTERN);\n return match ? match[1] : null;\n}\n\n/**\n * Options for address dropdowns: the form's email fields, plus the\n * currently-referenced field even when it is not an email type, so a legacy\n * value keeps displaying instead of silently vanishing from the select.\n */\nfunction buildEmailFieldOptions(\n fields: readonly FieldOption[],\n currentRef: string | null\n): FieldOption[] {\n const emailFields = fields.filter(field => field.type === \"email\");\n if (currentRef && !emailFields.some(field => field.name === currentRef)) {\n const current = fields.find(field => field.name === currentRef);\n if (current) return [...emailFields, current];\n }\n return emailFields;\n}\n\n/**\n * Deliberately loose email shape check (something@something.tld): the goal\n * is catching typos before they fail at delivery, not RFC 5322 conformance.\n */\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\nfunction isValidEmail(value: string): boolean {\n return EMAIL_PATTERN.test(value.trim());\n}\n\n// ============================================================================\n// Condition labels\n// ============================================================================\n\nconst COMPARISON_LABELS: Record<\n ConditionalLogicCondition[\"comparison\"],\n string\n> = {\n equals: \"Equals\",\n notEquals: \"Does not equal\",\n contains: \"Contains\",\n isEmpty: \"Is empty\",\n isNotEmpty: \"Is not empty\",\n greaterThan: \"Greater than\",\n lessThan: \"Less than\",\n};\n\nconst VALUELESS_COMPARISONS: ReadonlySet<\n ConditionalLogicCondition[\"comparison\"]\n> = new Set([\"isEmpty\", \"isNotEmpty\"]);\n\n// ============================================================================\n// Notification Card\n// ============================================================================\n\ninterface NotificationCardProps {\n notification: FormNotification;\n providerName: string;\n fields: readonly FieldOption[];\n onEdit: () => void;\n onDuplicate: () => void;\n onDelete: () => void;\n onToggleEnabled: (enabled: boolean) => void;\n}\n\nfunction describeRecipient(\n notification: FormNotification,\n fields: readonly FieldOption[]\n): { text: string; missing: boolean } {\n if (notification.recipientType === \"field\") {\n const ref = parseFieldRef(notification.to);\n if (!ref) return { text: \"No recipient field selected\", missing: true };\n const field = fields.find(f => f.name === ref);\n if (!field) {\n // The referenced field was deleted (allowed while the rule was\n // disabled) — say so instead of presenting the dead name as valid.\n return {\n text: `Recipient field \"${ref}\" no longer exists`,\n missing: true,\n };\n }\n return {\n text: `To the visitor (${field.label})`,\n missing: false,\n };\n }\n if (!notification.to.trim()) {\n return { text: \"No recipient address\", missing: true };\n }\n return { text: `To ${notification.to}`, missing: false };\n}\n\nfunction NotificationCard({\n notification,\n providerName,\n fields,\n onEdit,\n onDuplicate,\n onDelete,\n onToggleEnabled,\n}: NotificationCardProps) {\n const recipient = describeRecipient(notification, fields);\n const ccCount =\n (notification.cc?.length ?? 0) + (notification.bcc?.length ?? 0);\n\n // Deleting a referenced field is only blocked for enabled rules, so a\n // disabled rule can legitimately hold references to fields that no longer\n // exist — surface that on the card instead of sending broken email later.\n const fieldNames = new Set(fields.map(f => f.name));\n const replyToRef = parseFieldRef(notification.replyTo);\n const hasStaleReference =\n (replyToRef !== null && !fieldNames.has(replyToRef)) ||\n (notification.condition !== undefined &&\n !fieldNames.has(notification.condition.field));\n\n const warnings: string[] = [];\n if (!notification.templateSlug) {\n warnings.push(\"No template — will not send\");\n }\n if (hasStaleReference) {\n warnings.push(\"References a deleted field — edit to repair\");\n }\n\n return (\n <div\n className={`border border-border bg-background ${notification.enabled ? \"\" : \"opacity-60\"}`}\n >\n <div className=\"flex items-center gap-2 px-3 py-2.5\">\n <span className=\"flex h-7 w-7 shrink-0 items-center justify-center bg-primary/5 text-primary\">\n <Mail className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </span>\n\n <button\n type=\"button\"\n onClick={onEdit}\n className=\"flex min-w-0 flex-1 items-center gap-3 rounded-none py-1 text-left cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n aria-label={`Edit notification ${notification.name}`}\n >\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-medium text-foreground\">\n {notification.name}\n </span>\n {notification.condition && (\n <Badge\n variant=\"outline\"\n className=\"shrink-0 gap-1 rounded-none border-border px-1.5 py-0 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n <Filter className=\"h-2.5 w-2.5\" aria-hidden=\"true\" />\n Conditional\n </Badge>\n )}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground\">\n <span className={recipient.missing ? \"text-destructive\" : \"\"}>\n {recipient.text}\n </span>\n {ccCount > 0 && (\n <span>\n <span className=\"mx-1.5 text-muted-foreground\">·</span>+\n {ccCount} cc/bcc\n </span>\n )}\n <span className=\"mx-1.5 text-muted-foreground\">·</span>\n {providerName}\n </span>\n </span>\n {warnings.length > 0 && (\n <span className=\"flex shrink-0 flex-col items-end gap-0.5\">\n {warnings.map(warning => (\n <span\n key={warning}\n className=\"flex items-center gap-1 text-xs font-medium text-destructive\"\n >\n <TriangleAlert className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n {warning}\n </span>\n ))}\n </span>\n )}\n </button>\n\n <Switch\n checked={notification.enabled}\n onCheckedChange={onToggleEnabled}\n aria-label={`${notification.enabled ? \"Disable\" : \"Enable\"} notification ${notification.name}`}\n />\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0 rounded-none text-muted-foreground hover:text-foreground\"\n aria-label={`Notification actions for ${notification.name}`}\n >\n <MoreHorizontal className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n className=\"w-56 shadow-none border-border\"\n >\n <DropdownMenuItem onClick={onEdit} className=\"gap-2 cursor-pointer\">\n <Pencil className=\"h-4 w-4 text-muted-foreground\" />\n Edit\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={onDuplicate}\n className=\"gap-2 cursor-pointer\"\n >\n <Copy className=\"h-4 w-4 text-muted-foreground\" />\n Duplicate\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={onDelete}\n className=\"gap-2 cursor-pointer text-destructive focus:text-destructive\"\n >\n <Trash2 className=\"h-4 w-4\" />\n Delete\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// Recipient chip list (cc / bcc)\n// ============================================================================\n\ninterface AddressChipListProps {\n id: string;\n label: string;\n addresses: string[];\n placeholder: string;\n onChange: (addresses: string[]) => void;\n}\n\nfunction AddressChipList({\n id,\n label,\n addresses,\n placeholder,\n onChange,\n}: AddressChipListProps) {\n const [draft, setDraft] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n\n const add = useCallback(() => {\n const email = draft.trim();\n if (!email) return;\n // Nothing here goes through form submission, so constraint validation\n // never runs — reject malformed addresses before they can be persisted\n // and fail at delivery.\n if (!isValidEmail(email)) {\n setError(\"Enter a valid email address.\");\n return;\n }\n onChange([...addresses, email]);\n setDraft(\"\");\n setError(null);\n }, [draft, addresses, onChange]);\n\n return (\n <div className=\"space-y-1.5\">\n <Label htmlFor={id}>{label}</Label>\n {addresses.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {addresses.map((email, index) => (\n <Badge\n key={`${email}-${index}`}\n variant=\"outline\"\n className=\"gap-1.5 rounded-none border-border bg-primary/5 px-2 py-0.5 text-xs font-medium\"\n >\n <span>{email}</span>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary\"\n onClick={() =>\n onChange(addresses.filter((_, i) => i !== index))\n }\n aria-label={`Remove ${email}`}\n >\n <X className=\"h-3 w-3\" aria-hidden=\"true\" />\n </button>\n </Badge>\n ))}\n </div>\n )}\n <div className=\"flex items-center gap-2\">\n <Input\n id={id}\n type=\"email\"\n value={draft}\n onChange={e => {\n setDraft(e.target.value);\n setError(null);\n }}\n onKeyDown={e => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n add();\n }\n }}\n placeholder={placeholder}\n aria-invalid={error ? true : undefined}\n aria-describedby={error ? `${id}-error` : undefined}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={add}\n className=\"shrink-0 px-3\"\n >\n Add\n </Button>\n </div>\n {error && (\n <p id={`${id}-error`} className=\"text-xs text-destructive\">\n {error}\n </p>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// Notification Sheet\n// ============================================================================\n\ntype ReplyToMode = \"none\" | \"field\" | \"custom\";\n\ninterface NotificationSheetProps {\n initial: FormNotification;\n isEditing: boolean;\n providers: ProviderOption[];\n templates: TemplateOption[];\n fields: readonly FieldOption[];\n defaults: NotificationDefaults | null;\n onSave: (notification: FormNotification) => void;\n onClose: () => void;\n}\n\nfunction initialReplyToMode(replyTo: string | undefined): ReplyToMode {\n if (!replyTo) return \"none\";\n return parseFieldRef(replyTo) ? \"field\" : \"custom\";\n}\n\nfunction NotificationSheet({\n initial,\n isEditing,\n providers,\n templates,\n fields,\n defaults,\n onSave,\n onClose,\n}: NotificationSheetProps) {\n const [form, setForm] = useState<FormNotification>(initial);\n const [replyToMode, setReplyToMode] = useState<ReplyToMode>(\n initialReplyToMode(initial.replyTo)\n );\n // Save-time address errors, keyed by field. Nothing here goes through\n // form submission (every control is a type=\"button\" callback), so\n // constraint validation never runs — this is its replacement.\n const [addressErrors, setAddressErrors] = useState<\n Partial<Record<\"senderEmail\" | \"to\" | \"replyTo\", string>>\n >({});\n\n const update = useCallback(\n <K extends keyof FormNotification>(key: K, value: FormNotification[K]) => {\n setForm(prev => ({ ...prev, [key]: value }));\n setAddressErrors(prev =>\n key in prev ? { ...prev, [key]: undefined } : prev\n );\n },\n []\n );\n\n const handleSave = useCallback(() => {\n const errors: typeof addressErrors = {};\n const invalid = (value: string | undefined) =>\n Boolean(value?.trim()) && !isValidEmail(value as string);\n if (invalid(form.senderEmail)) {\n errors.senderEmail = \"Enter a valid email address.\";\n }\n if (form.recipientType === \"static\" && invalid(form.to)) {\n errors.to = \"Enter a valid email address.\";\n }\n // Only literal reply-to addresses are validated; {{field}} references\n // resolve against each submission at send time.\n if (!parseFieldRef(form.replyTo) && invalid(form.replyTo)) {\n errors.replyTo = \"Enter a valid email address.\";\n }\n if (Object.values(errors).some(Boolean)) {\n setAddressErrors(errors);\n return;\n }\n onSave(form);\n }, [form, onSave]);\n\n const defaultProvider = providers.find(p => p.isDefault);\n const defaultProviderLabel = defaultProvider\n ? `System default (${defaultProvider.name})`\n : \"System default\";\n\n const toRef = parseFieldRef(form.to);\n const toFieldOptions = buildEmailFieldOptions(\n fields,\n form.recipientType === \"field\" ? toRef : null\n );\n const replyToRef = parseFieldRef(form.replyTo);\n const replyToFieldOptions = buildEmailFieldOptions(fields, replyToRef);\n\n const senderPlaceholder = defaults?.defaultFrom || \"Provider default\";\n const senderHelp = defaults?.defaultFrom\n ? `Leave blank to send from ${defaults.defaultFrom} (the configured default).`\n : \"Leave blank to use the template or provider default address.\";\n\n const condition = form.condition;\n\n return (\n <Sheet\n open\n onOpenChange={open => {\n if (!open) onClose();\n }}\n >\n <SheetContent\n side=\"right\"\n className=\"w-[560px] sm:max-w-[560px] p-0 flex flex-col\"\n >\n <SheetHeader className=\"p-4 border-b border-border\">\n <SheetTitle>\n {isEditing ? \"Edit notification\" : \"New notification\"}\n </SheetTitle>\n <SheetDescription>\n Sent when someone submits this form.\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"flex-1 overflow-y-auto p-4 space-y-6\">\n {/* Name */}\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-name\">Name</Label>\n <Input\n id=\"notification-name\"\n type=\"text\"\n value={form.name}\n onChange={e => update(\"name\", e.target.value)}\n placeholder=\"e.g. Admin notification\"\n />\n </div>\n\n {/* Provider & Template */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-provider\">Email provider</Label>\n <Select\n value={form.providerId ?? \"__default\"}\n onValueChange={value =>\n update(\n \"providerId\",\n value === \"__default\" ? undefined : value\n )\n }\n >\n <SelectTrigger\n id=\"notification-provider\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__default\">\n {defaultProviderLabel}\n </SelectItem>\n {providers.map(p => (\n <SelectItem key={p.id} value={p.id}>\n {p.name}\n {p.isDefault ? \" (Default)\" : \"\"}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-template\">Email template</Label>\n <Select\n value={form.templateSlug ?? \"__none\"}\n onValueChange={value =>\n update(\"templateSlug\", value === \"__none\" ? undefined : value)\n }\n >\n <SelectTrigger\n id=\"notification-template\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none\">Select a template</SelectItem>\n {templates\n .filter(t => t.isActive && t.kind !== \"layout\")\n .map(t => (\n <SelectItem key={t.id} value={t.slug}>\n {t.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {!form.templateSlug && (\n <p className=\"flex items-center gap-1 text-xs text-destructive\">\n <TriangleAlert className=\"h-3 w-3\" aria-hidden=\"true\" />\n Required — a notification without a template is never sent.\n </p>\n )}\n </div>\n </div>\n\n {/* Sender */}\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-sender\">Sender email</Label>\n <Input\n id=\"notification-sender\"\n type=\"email\"\n value={form.senderEmail ?? \"\"}\n onChange={e => update(\"senderEmail\", e.target.value || undefined)}\n placeholder={senderPlaceholder}\n aria-invalid={addressErrors.senderEmail ? true : undefined}\n />\n {addressErrors.senderEmail ? (\n <p className=\"text-xs text-destructive\">\n {addressErrors.senderEmail}\n </p>\n ) : (\n <p className=\"text-xs text-muted-foreground\">{senderHelp}</p>\n )}\n </div>\n\n {/* Recipients */}\n <div className=\"space-y-4 pt-4 border-t border-border\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-recipient-type\">Send to</Label>\n <Select\n value={form.recipientType}\n onValueChange={value => {\n // Switching target kinds invalidates the previous `to`\n // value shape, so it resets rather than leaking a\n // {{ref}} into the static input (or vice versa).\n setForm(prev => ({\n ...prev,\n recipientType: value as \"static\" | \"field\",\n to: \"\",\n }));\n }}\n >\n <SelectTrigger\n id=\"notification-recipient-type\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"static\">A specific address</SelectItem>\n <SelectItem value=\"field\">\n The visitor (email field)\n </SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-to\">\n {form.recipientType === \"field\"\n ? \"Visitor email field\"\n : \"Recipient address\"}\n </Label>\n {form.recipientType === \"field\" ? (\n <Select\n value={toRef ?? \"__none\"}\n onValueChange={value =>\n update(\"to\", value === \"__none\" ? \"\" : toFieldRef(value))\n }\n >\n <SelectTrigger\n id=\"notification-to\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none\">Select a field</SelectItem>\n {toFieldOptions.map(f => (\n <SelectItem key={f.name} value={f.name}>\n {f.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <Input\n id=\"notification-to\"\n type=\"email\"\n value={form.to}\n onChange={e => update(\"to\", e.target.value)}\n placeholder={\n defaults?.defaultToEmail || \"admin@example.com\"\n }\n aria-invalid={addressErrors.to ? true : undefined}\n />\n )}\n {addressErrors.to && (\n <p className=\"text-xs text-destructive\">{addressErrors.to}</p>\n )}\n {form.recipientType === \"field\" &&\n toFieldOptions.length === 0 && (\n <p className=\"text-xs text-muted-foreground\">\n Add an email field to the form first.\n </p>\n )}\n </div>\n </div>\n\n {/* Reply-To */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-replyto-mode\">Reply-To</Label>\n <Select\n value={replyToMode}\n onValueChange={value => {\n const mode = value as ReplyToMode;\n setReplyToMode(mode);\n // A mode change always clears the stored value (the old\n // shape can't be represented in the new mode); it stays\n // absent — not an empty string — until the user picks a\n // field or types an address.\n update(\"replyTo\", undefined);\n }}\n >\n <SelectTrigger\n id=\"notification-replyto-mode\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"none\">None</SelectItem>\n <SelectItem value=\"field\">\n The visitor (email field)\n </SelectItem>\n <SelectItem value=\"custom\">A custom address</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {replyToMode === \"field\" && (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-replyto\">\n Visitor email field\n </Label>\n <Select\n value={replyToRef ?? \"__none\"}\n onValueChange={value =>\n update(\n \"replyTo\",\n value === \"__none\" ? undefined : toFieldRef(value)\n )\n }\n >\n <SelectTrigger\n id=\"notification-replyto\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none\">Select a field</SelectItem>\n {replyToFieldOptions.map(f => (\n <SelectItem key={f.name} value={f.name}>\n {f.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n {replyToMode === \"custom\" && (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"notification-replyto\">Reply-To address</Label>\n <Input\n id=\"notification-replyto\"\n type=\"email\"\n value={form.replyTo ?? \"\"}\n onChange={e =>\n update(\"replyTo\", e.target.value || undefined)\n }\n placeholder=\"replies@example.com\"\n aria-invalid={addressErrors.replyTo ? true : undefined}\n />\n {addressErrors.replyTo && (\n <p className=\"text-xs text-destructive\">\n {addressErrors.replyTo}\n </p>\n )}\n </div>\n )}\n </div>\n {replyToMode === \"field\" && (\n <p className=\"text-xs text-muted-foreground -mt-2\">\n Replying to this email answers the person who submitted the\n form.\n </p>\n )}\n\n <AddressChipList\n id=\"notification-cc\"\n label=\"CC (optional)\"\n addresses={form.cc}\n placeholder=\"cc@example.com\"\n onChange={cc => update(\"cc\", cc)}\n />\n <AddressChipList\n id=\"notification-bcc\"\n label=\"BCC (optional)\"\n addresses={form.bcc}\n placeholder=\"bcc@example.com\"\n onChange={bcc => update(\"bcc\", bcc)}\n />\n </div>\n\n {/* Send condition */}\n <div className=\"space-y-3 pt-4 border-t border-border\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm font-medium text-foreground\">\n Send condition\n </p>\n <p className=\"text-xs text-muted-foreground\">\n Only send this notification when a submitted value matches.\n </p>\n </div>\n {!condition && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n update(\"condition\", {\n field: fields[0]?.name ?? \"\",\n comparison: \"equals\",\n value: \"\",\n })\n }\n disabled={fields.length === 0}\n >\n <Plus className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Add condition\n </Button>\n )}\n </div>\n\n {condition && (\n <div className=\"flex flex-wrap items-end gap-2 border border-border bg-muted/40 p-3\">\n <div className=\"min-w-36 flex-1 space-y-1.5\">\n <Label htmlFor=\"notification-condition-field\">Field</Label>\n <Select\n value={condition.field || \"__none\"}\n onValueChange={value =>\n update(\"condition\", {\n ...condition,\n field: value === \"__none\" ? \"\" : value,\n })\n }\n >\n <SelectTrigger\n id=\"notification-condition-field\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none\">Select a field</SelectItem>\n {fields.map(f => (\n <SelectItem key={f.name} value={f.name}>\n {f.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"min-w-36 flex-1 space-y-1.5\">\n <Label htmlFor=\"notification-condition-comparison\">\n Comparison\n </Label>\n <Select\n value={condition.comparison}\n onValueChange={value =>\n update(\"condition\", {\n ...condition,\n comparison:\n value as ConditionalLogicCondition[\"comparison\"],\n })\n }\n >\n <SelectTrigger\n id=\"notification-condition-comparison\"\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {Object.entries(COMPARISON_LABELS).map(\n ([value, label]) => (\n <SelectItem key={value} value={value}>\n {label}\n </SelectItem>\n )\n )}\n </SelectContent>\n </Select>\n </div>\n\n {!VALUELESS_COMPARISONS.has(condition.comparison) && (\n <div className=\"min-w-36 flex-1 space-y-1.5\">\n <Label htmlFor=\"notification-condition-value\">Value</Label>\n <Input\n id=\"notification-condition-value\"\n type=\"text\"\n value={\n typeof condition.value === \"string\" ||\n typeof condition.value === \"number\"\n ? String(condition.value)\n : \"\"\n }\n onChange={e =>\n update(\"condition\", {\n ...condition,\n value: e.target.value,\n })\n }\n />\n </div>\n )}\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 rounded-none text-muted-foreground hover:text-destructive\"\n onClick={() => update(\"condition\", undefined)}\n aria-label=\"Remove send condition\"\n >\n <Trash2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n )}\n </div>\n\n {/* Enabled */}\n <div className=\"flex items-center justify-between pt-4 border-t border-border\">\n <div>\n <Label htmlFor=\"notification-enabled\">Enabled</Label>\n <p className=\"text-xs text-muted-foreground\">\n Turn off to keep the rule without sending.\n </p>\n </div>\n <Switch\n id=\"notification-enabled\"\n checked={form.enabled}\n onCheckedChange={checked => update(\"enabled\", checked)}\n />\n </div>\n </div>\n\n <div className=\"flex items-center justify-end gap-3 border-t border-border bg-muted p-4\">\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n Cancel\n </Button>\n <Button\n type=\"button\"\n onClick={handleSave}\n disabled={!form.name.trim()}\n >\n {isEditing ? \"Save changes\" : \"Add notification\"}\n </Button>\n </div>\n </SheetContent>\n </Sheet>\n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * FormNotificationsTab - the form's notification rules.\n *\n * Each rule references an existing email provider and template rather than\n * duplicating provider credentials or embedding a second template editor.\n */\nexport function FormNotificationsTab({ defaults }: FormNotificationsTabProps) {\n const {\n notifications,\n fields,\n addNotification,\n duplicateNotification,\n updateNotification,\n deleteNotification,\n } = useFormBuilder();\n\n const [providers, setProviders] = useState<ProviderOption[]>([]);\n const [templates, setTemplates] = useState<TemplateOption[]>([]);\n const [sheetState, setSheetState] = useState<{\n open: boolean;\n editing: FormNotification | null;\n }>({ open: false, editing: null });\n\n useEffect(() => {\n void fetchProviders().then(setProviders);\n void fetchTemplates().then(setTemplates);\n }, []);\n\n const fieldList = useMemo<FieldOption[]>(\n () => fields.map(f => ({ name: f.name, label: f.label, type: f.type })),\n [fields]\n );\n\n const openAddSheet = useCallback(() => {\n setSheetState({ open: true, editing: null });\n }, []);\n\n const openEditSheet = useCallback((notification: FormNotification) => {\n setSheetState({ open: true, editing: notification });\n }, []);\n\n const closeSheet = useCallback(() => {\n setSheetState({ open: false, editing: null });\n }, []);\n\n const handleSave = useCallback(\n (notification: FormNotification) => {\n if (sheetState.editing) {\n updateNotification(notification.id, notification);\n } else {\n addNotification(notification);\n }\n closeSheet();\n },\n [sheetState.editing, addNotification, updateNotification, closeSheet]\n );\n\n const getProviderName = useCallback(\n (providerId?: string) => {\n if (!providerId) {\n const def = providers.find(p => p.isDefault);\n return def ? `${def.name} (default)` : \"System default\";\n }\n return providers.find(p => p.id === providerId)?.name ?? \"Unknown\";\n },\n [providers]\n );\n\n const initialNotification = sheetState.editing ?? createNotification();\n\n return (\n <div className=\"max-w-200\">\n <div className=\"flex items-center justify-between mb-8 pb-4 border-b border-border\">\n <div>\n <h3 className=\"text-xl font-semibold text-foreground\">\n Notifications\n </h3>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Emails sent when someone submits this form.\n </p>\n </div>\n <Button type=\"button\" onClick={openAddSheet}>\n <Plus className=\"h-4 w-4\" aria-hidden=\"true\" />\n Add notification\n </Button>\n </div>\n\n {/* List */}\n {notifications.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center p-12 mt-6 border-2 border-dashed border-border rounded-none bg-muted\">\n <div className=\"flex items-center justify-center w-12 h-12 rounded-none border border-border bg-background mb-4 text-primary\">\n <Mail className=\"h-6 w-6\" aria-hidden=\"true\" />\n </div>\n <p className=\"text-base font-medium text-foreground mb-1\">\n No notifications yet\n </p>\n <p className=\"text-sm text-muted-foreground mb-6 text-center max-w-sm\">\n Add a notification to email someone when this form is submitted.\n </p>\n <Button type=\"button\" onClick={openAddSheet}>\n <Plus className=\"h-4 w-4\" aria-hidden=\"true\" />\n Add notification\n </Button>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {notifications.map(notification => (\n <NotificationCard\n key={notification.id}\n notification={notification}\n providerName={getProviderName(notification.providerId)}\n fields={fieldList}\n onEdit={() => openEditSheet(notification)}\n onDuplicate={() => duplicateNotification(notification.id)}\n onDelete={() => deleteNotification(notification.id)}\n onToggleEnabled={enabled =>\n updateNotification(notification.id, { enabled })\n }\n />\n ))}\n </div>\n )}\n\n {/* Editor sheet */}\n {sheetState.open && (\n <NotificationSheet\n initial={initialNotification}\n isEditing={!!sheetState.editing}\n providers={providers}\n templates={templates}\n fields={fieldList}\n defaults={defaults}\n onSave={handleSave}\n onClose={closeSheet}\n />\n )}\n </div>\n );\n}\n\nexport default FormNotificationsTab;\n","\"use client\";\n\n/**\n * Form Preview\n *\n * An interactive simulation of the form: real enabled inputs, conditional\n * logic evaluated live against what you type (the same evaluator the\n * runtime uses), the form's actual settings (button text, confirmation\n * behavior), and a device-width toggle. It is honest about what it is —\n * a faithful simulation inside the admin, not the published form; nothing\n * here submits anywhere.\n *\n * @module admin/components/builder/FormPreview\n */\n\nimport {\n Badge,\n Button,\n Checkbox,\n Input,\n Label,\n RadioGroup,\n RadioGroupItem,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tabs,\n TabsList,\n TabsTrigger,\n Textarea,\n} from \"@nextlyhq/ui\";\nimport { Eye, Monitor, Paperclip, RotateCcw, Smartphone } from \"lucide-react\";\nimport { useMemo, useState } from \"react\";\n\nimport type { AnyFormField, CustomFormField, FormField } from \"../../../types\";\nimport { isKnownFormField } from \"../../../types\";\nimport { evaluateConditions } from \"../../../utils/evaluate-conditions\";\nimport { useFormBuilder } from \"../../context/FormBuilderContext\";\n\n// ---------------------------------------------------------------------------\n// Field rendering\n// ---------------------------------------------------------------------------\n\nfunction PreviewFieldInput({\n field,\n value,\n onChange,\n}: {\n field: FormField;\n value: unknown;\n onChange: (value: unknown) => void;\n}) {\n const id = `preview-${field.name}`;\n switch (field.type) {\n case \"textarea\":\n return (\n <Textarea\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={e => onChange(e.target.value)}\n rows={\"rows\" in field ? (field.rows ?? 4) : 4}\n placeholder={field.placeholder}\n />\n );\n case \"checkbox\":\n // A real checkbox, not a toggle switch — the preview should look like\n // what a frontend form renders for this type.\n return (\n <Checkbox\n id={id}\n checked={Boolean(value)}\n onCheckedChange={checked => onChange(checked === true)}\n />\n );\n case \"select\": {\n const options = \"options\" in field ? (field.options ?? []) : [];\n return (\n <Select\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={onChange}\n >\n <SelectTrigger\n id={id}\n className=\"w-full bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue placeholder={field.placeholder ?? \"Select…\"} />\n </SelectTrigger>\n <SelectContent>\n {options.map(option => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n }\n case \"radio\": {\n const options = \"options\" in field ? (field.options ?? []) : [];\n return (\n <RadioGroup\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={onChange}\n className=\"flex flex-col gap-2\"\n >\n {options.map(option => (\n <div key={option.value} className=\"flex items-center gap-2\">\n <RadioGroupItem\n value={option.value}\n id={`${id}-${option.value}`}\n />\n <Label htmlFor={`${id}-${option.value}`} className=\"font-normal\">\n {option.label}\n </Label>\n </div>\n ))}\n </RadioGroup>\n );\n }\n case \"number\":\n return (\n <Input\n id={id}\n type=\"number\"\n value={\n typeof value === \"number\" || typeof value === \"string\"\n ? String(value)\n : \"\"\n }\n onChange={e =>\n onChange(e.target.value === \"\" ? \"\" : Number(e.target.value))\n }\n placeholder={field.placeholder}\n />\n );\n case \"date\":\n case \"time\":\n return (\n <Input\n id={id}\n type={field.type}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={e => onChange(e.target.value)}\n />\n );\n case \"file\":\n // Nothing uploads from a preview; the affordance is shown, disabled.\n return (\n <div className=\"flex items-center gap-2 border border-dashed border-border bg-muted/40 px-3 py-2 text-sm text-muted-foreground\">\n <Paperclip className=\"h-4 w-4\" aria-hidden=\"true\" />\n File upload (disabled in preview)\n </div>\n );\n default:\n return (\n <Input\n id={id}\n type={\n field.type === \"email\"\n ? \"email\"\n : field.type === \"url\"\n ? \"url\"\n : field.type === \"phone\"\n ? \"tel\"\n : \"text\"\n }\n value={typeof value === \"string\" ? value : \"\"}\n onChange={e => onChange(e.target.value)}\n placeholder={field.placeholder}\n />\n );\n }\n}\n\n/**\n * Preview for a plugin-contributed field. The plugin owns the real input, which\n * renders from its own component in the live form; the builder preview shows a\n * labeled placeholder so the field's presence and order stay visible.\n */\nfunction PluginFieldPreview({ field }: { field: CustomFormField }) {\n return (\n <div className=\"space-y-1.5\">\n <Label htmlFor={`preview-${field.name}`}>\n {field.label || field.name}\n {field.required && <span className=\"ml-1 text-destructive\">*</span>}\n </Label>\n <div className=\"flex items-center gap-2 border border-dashed border-border bg-muted/40 px-3 py-2 text-sm text-muted-foreground\">\n Custom field ({field.type}) — renders from its plugin component in the\n live form.\n </div>\n {field.helpText && (\n <p className=\"text-xs text-muted-foreground\">{field.helpText}</p>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport interface FormPreviewProps {\n /** Array of form fields to preview (built-in or plugin-contributed). */\n fields: AnyFormField[];\n /** Form metadata */\n formData?: {\n name?: string;\n slug?: string;\n description?: string;\n };\n}\n\nexport function FormPreview({ fields, formData }: FormPreviewProps) {\n const { settings } = useFormBuilder();\n const [values, setValues] = useState<Record<string, unknown>>({});\n const [device, setDevice] = useState<\"desktop\" | \"mobile\">(\"desktop\");\n const [confirmed, setConfirmed] = useState(false);\n const [missingRequired, setMissingRequired] = useState<Set<string>>(\n new Set()\n );\n\n // Conditional logic runs against the live values with the SAME evaluator\n // the runtime uses — typing into the preview shows/hides fields for real.\n // Visibility is computed in field order against the values of fields that\n // are themselves visible: a hidden field's leftover value must not keep\n // satisfying a downstream condition (chained show/hide would misbehave).\n const visibleFields = useMemo(() => {\n const effectiveValues: Record<string, unknown> = {};\n const visible: AnyFormField[] = [];\n for (const field of fields) {\n if (field.type === \"hidden\") continue;\n const isVisible =\n !field.conditionalLogic?.enabled ||\n evaluateConditions(field.conditionalLogic, effectiveValues);\n if (isVisible) {\n visible.push(field);\n if (field.name in values) {\n effectiveValues[field.name] = values[field.name];\n }\n }\n }\n return visible;\n }, [fields, values]);\n\n const hiddenCount = fields.filter(field => field.type === \"hidden\").length;\n\n const reset = () => {\n setValues({});\n setConfirmed(false);\n setMissingRequired(new Set());\n };\n\n // The real form would refuse an empty required field, so the simulation\n // does too — an admin previewing required fields sees the requirement.\n const simulateSubmit = () => {\n const missing = new Set(\n visibleFields\n .filter(field => {\n // A plugin field renders a non-interactive placeholder in the preview\n // (its real input lives in the plugin's component in the live form),\n // so it can never be filled here — excluded like `file`, otherwise the\n // simulated submit would block forever with no way to satisfy it.\n if (!field.required || field.type === \"file\") return false;\n if (!isKnownFormField(field)) return false;\n const value = values[field.name];\n return value === undefined || value === \"\" || value === false;\n })\n .map(field => field.name)\n );\n setMissingRequired(missing);\n if (missing.size === 0) setConfirmed(true);\n };\n\n return (\n <div className=\"space-y-4\">\n {/* Preview chrome: honest framing + device toggle + reset */}\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Eye className=\"h-4 w-4\" aria-hidden=\"true\" />\n Preview — a simulation of this form. Nothing here submits anywhere.\n </div>\n <div className=\"flex items-center gap-2\">\n <Tabs\n value={device}\n onValueChange={value => setDevice(value as \"desktop\" | \"mobile\")}\n >\n <TabsList className=\"rounded-none\">\n <TabsTrigger value=\"desktop\" className=\"rounded-none gap-1.5\">\n <Monitor className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Desktop\n </TabsTrigger>\n <TabsTrigger value=\"mobile\" className=\"rounded-none gap-1.5\">\n <Smartphone className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Mobile\n </TabsTrigger>\n </TabsList>\n </Tabs>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={reset}>\n <RotateCcw className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Reset\n </Button>\n </div>\n </div>\n\n {/* The simulated form */}\n <div className=\"flex justify-center border border-border bg-muted/30 p-6\">\n <div\n className={`w-full space-y-5 border border-border bg-background p-6 ${\n device === \"mobile\" ? \"max-w-95\" : \"max-w-2xl\"\n }`}\n >\n <div>\n <h3 className=\"text-lg font-semibold text-foreground\">\n {formData?.name || \"Untitled form\"}\n </h3>\n {formData?.description && (\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {formData.description}\n </p>\n )}\n </div>\n\n {confirmed ? (\n <div className=\"space-y-4\">\n {settings.confirmationType === \"redirect\" ? (\n <p className=\"border border-border bg-muted/40 p-4 text-sm text-foreground\">\n The visitor would now be redirected to{\" \"}\n <span className=\"font-mono\">\n {settings.redirectUrl || \"(no redirect URL set)\"}\n </span>\n .\n </p>\n ) : (\n <p className=\"border border-border bg-muted/40 p-4 text-sm text-foreground\">\n {settings.successMessage || \"Thank you for your submission!\"}\n </p>\n )}\n <Button type=\"button\" variant=\"outline\" onClick={reset}>\n Fill again\n </Button>\n </div>\n ) : (\n <>\n {visibleFields.length === 0 && (\n <p className=\"text-sm text-muted-foreground\">\n No visible fields — add fields in the Builder tab.\n </p>\n )}\n {visibleFields.map(field =>\n !isKnownFormField(field) ? (\n <PluginFieldPreview key={field.name} field={field} />\n ) : (\n <div key={field.name} className=\"space-y-1.5\">\n {field.type !== \"checkbox\" && (\n <Label htmlFor={`preview-${field.name}`}>\n {field.label || field.name}\n {field.required && (\n <span className=\"ml-1 text-destructive\">*</span>\n )}\n </Label>\n )}\n {field.type === \"checkbox\" ? (\n <div className=\"flex items-center gap-2\">\n <PreviewFieldInput\n field={field}\n value={values[field.name]}\n onChange={value =>\n setValues(prev => ({\n ...prev,\n [field.name]: value,\n }))\n }\n />\n <Label htmlFor={`preview-${field.name}`}>\n {field.label || field.name}\n {field.required && (\n <span className=\"ml-1 text-destructive\">*</span>\n )}\n </Label>\n </div>\n ) : (\n <PreviewFieldInput\n field={field}\n value={values[field.name]}\n onChange={value =>\n setValues(prev => ({ ...prev, [field.name]: value }))\n }\n />\n )}\n {field.helpText && (\n <p className=\"text-xs text-muted-foreground\">\n {field.helpText}\n </p>\n )}\n {missingRequired.has(field.name) && (\n <p className=\"text-xs text-destructive\">\n This field is required.\n </p>\n )}\n </div>\n )\n )}\n\n <Button\n type=\"button\"\n onClick={simulateSubmit}\n disabled={visibleFields.length === 0}\n >\n {settings.submitButtonText || \"Submit\"}\n </Button>\n </>\n )}\n\n {hiddenCount > 0 && !confirmed && (\n <p className=\"text-xs text-muted-foreground\">\n <Badge\n variant=\"outline\"\n className=\"mr-1.5 rounded-none border-border px-1 py-0 text-[10px]\"\n >\n {hiddenCount}\n </Badge>\n hidden {hiddenCount === 1 ? \"field\" : \"fields\"} will be submitted\n invisibly.\n </p>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport default FormPreview;\n","\"use client\";\n\n/**\n * Form Settings Tab\n *\n * Per-form behavior on the canonical settings shape: every control here is\n * consumed somewhere (the submit handler or the confirmation flow) — a\n * setting that does nothing does not get a toggle. Spam controls are\n * per-form OVERRIDES of the plugin's global config: blank means inherit,\n * and the inherited value is shown rather than hidden.\n *\n * @module admin/components/builder/FormSettingsTab\n */\n\nimport {\n Input,\n Label,\n RadioGroup,\n RadioGroupItem,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n Textarea,\n} from \"@nextlyhq/ui\";\nimport type React from \"react\";\n\nimport { useFormBuilder } from \"../../context/FormBuilderContext\";\n\n// ---------------------------------------------------------------------------\n// Layout helpers\n// ---------------------------------------------------------------------------\n\nfunction SettingRow({\n label,\n description,\n htmlFor,\n children,\n}: {\n label: string;\n description?: string;\n htmlFor?: string;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-6 py-2\">\n <div className=\"space-y-1 max-w-xl\">\n <Label\n htmlFor={htmlFor}\n className=\"text-[13px] font-semibold text-foreground tracking-tight\"\n >\n {label}\n </Label>\n {description && (\n <p className=\"text-[12px] text-muted-foreground leading-relaxed\">\n {description}\n </p>\n )}\n </div>\n <div className=\"shrink-0 flex items-center justify-end min-w-25\">\n {children}\n </div>\n </div>\n );\n}\n\nfunction SectionHeading({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"border-b border-border pb-3\">\n <h3 className=\"text-[16px] font-bold text-foreground tracking-tight\">\n {children}\n </h3>\n </div>\n );\n}\n\n/**\n * Tri-state override select: inherit from the plugin config (showing the\n * effective value), or force on/off for this form.\n */\nfunction InheritToggle({\n id,\n value,\n inherited,\n onChange,\n}: {\n id: string;\n value: boolean | undefined;\n inherited: boolean | undefined;\n onChange: (value: boolean | undefined) => void;\n}) {\n const inheritedLabel =\n inherited === undefined\n ? \"Inherit\"\n : `Inherit (${inherited ? \"on\" : \"off\"})`;\n return (\n <Select\n value={value === undefined ? \"inherit\" : value ? \"on\" : \"off\"}\n onValueChange={selected =>\n onChange(selected === \"inherit\" ? undefined : selected === \"on\")\n }\n >\n <SelectTrigger\n id={id}\n className=\"w-40 bg-transparent border-input dark:bg-muted/50\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"inherit\">{inheritedLabel}</SelectItem>\n <SelectItem value=\"on\">On</SelectItem>\n <SelectItem value=\"off\">Off</SelectItem>\n </SelectContent>\n </Select>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport interface SpamDefaults {\n honeypot?: boolean;\n recaptchaEnabled?: boolean;\n}\n\ninterface FormSettingsTabProps {\n /** Plugin-level spam defaults (from builder-config); null while loading. */\n spamDefaults: SpamDefaults | null;\n}\n\nexport function FormSettingsTab({ spamDefaults }: FormSettingsTabProps) {\n const { settings, updateSettings } = useFormBuilder();\n\n return (\n <div className=\"w-full max-w-3xl flex flex-col gap-10\">\n {/* Submission */}\n <section>\n <SectionHeading>Submission</SectionHeading>\n <div className=\"flex flex-col gap-1 pt-2\">\n <SettingRow\n label=\"Submit button text\"\n description=\"Label on the form's primary action button\"\n htmlFor=\"settings-submit-text\"\n >\n <Input\n id=\"settings-submit-text\"\n type=\"text\"\n className=\"w-56\"\n value={settings.submitButtonText ?? \"\"}\n onChange={e =>\n updateSettings({ submitButtonText: e.target.value })\n }\n />\n </SettingRow>\n\n <SettingRow\n label=\"Allow multiple submissions\"\n description=\"When off, the same visitor (by IP) can submit this form only once. Best-effort: IP-based, so shared networks count as one visitor.\"\n htmlFor=\"settings-multiple\"\n >\n <Switch\n id=\"settings-multiple\"\n checked={settings.allowMultipleSubmissions ?? true}\n onCheckedChange={checked =>\n updateSettings({ allowMultipleSubmissions: checked })\n }\n />\n </SettingRow>\n </div>\n </section>\n\n {/* After submission */}\n <section>\n <SectionHeading>After submission</SectionHeading>\n <div className=\"flex flex-col gap-4 pt-4\">\n {settings.confirmationType === \"relationship\" && (\n <p className=\"border border-border bg-muted/40 p-3 text-sm text-muted-foreground\">\n This form redirects to a linked page (configured via the API).\n Picking an option below replaces that behavior.\n </p>\n )}\n <RadioGroup\n value={settings.confirmationType ?? \"message\"}\n onValueChange={value =>\n updateSettings({\n confirmationType: value as \"message\" | \"redirect\",\n })\n }\n className=\"flex flex-col gap-3\"\n >\n <div className=\"flex items-start gap-3\">\n <RadioGroupItem\n value=\"message\"\n id=\"settings-confirm-message\"\n className=\"mt-0.5\"\n />\n <div className=\"w-full space-y-2\">\n <Label htmlFor=\"settings-confirm-message\">Show a message</Label>\n {(settings.confirmationType ?? \"message\") === \"message\" && (\n <Textarea\n aria-label=\"Success message\"\n value={settings.successMessage ?? \"\"}\n onChange={e =>\n updateSettings({ successMessage: e.target.value })\n }\n rows={3}\n placeholder=\"Thank you for your submission!\"\n />\n )}\n </div>\n </div>\n <div className=\"flex items-start gap-3\">\n <RadioGroupItem\n value=\"redirect\"\n id=\"settings-confirm-redirect\"\n className=\"mt-0.5\"\n />\n <div className=\"w-full space-y-2\">\n <Label htmlFor=\"settings-confirm-redirect\">\n Redirect to a URL\n </Label>\n {settings.confirmationType === \"redirect\" && (\n <Input\n aria-label=\"Redirect URL\"\n type=\"url\"\n value={settings.redirectUrl ?? \"\"}\n onChange={e =>\n updateSettings({\n redirectUrl: e.target.value || undefined,\n })\n }\n placeholder=\"https://example.com/thanks\"\n />\n )}\n </div>\n </div>\n </RadioGroup>\n </div>\n </section>\n\n {/* Spam protection */}\n <section>\n <SectionHeading>Spam protection</SectionHeading>\n <div className=\"flex flex-col gap-1 pt-2\">\n <SettingRow\n label=\"Honeypot\"\n description=\"Invisible trap field for bots. Inherits the plugin default unless overridden here.\"\n htmlFor=\"settings-honeypot\"\n >\n <InheritToggle\n id=\"settings-honeypot\"\n value={settings.honeypotEnabled}\n inherited={spamDefaults?.honeypot}\n onChange={honeypotEnabled => updateSettings({ honeypotEnabled })}\n />\n </SettingRow>\n\n <SettingRow\n label=\"reCAPTCHA\"\n description=\"Challenge-based bot check. Inherits the plugin default unless overridden here.\"\n htmlFor=\"settings-captcha\"\n >\n <InheritToggle\n id=\"settings-captcha\"\n value={settings.captchaEnabled}\n inherited={spamDefaults?.recaptchaEnabled}\n onChange={captchaEnabled => updateSettings({ captchaEnabled })}\n />\n </SettingRow>\n\n {settings.captchaEnabled === true && (\n <SettingRow\n label=\"reCAPTCHA site key\"\n description=\"The client-facing site key for this form\"\n htmlFor=\"settings-captcha-key\"\n >\n <Input\n id=\"settings-captcha-key\"\n type=\"text\"\n className=\"w-72 font-mono\"\n value={settings.captchaSiteKey ?? \"\"}\n onChange={e =>\n updateSettings({\n captchaSiteKey: e.target.value || undefined,\n })\n }\n />\n </SettingRow>\n )}\n </div>\n </section>\n </div>\n );\n}\n\nexport default FormSettingsTab;\n"],"mappings":"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","names":["Badge","Button","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","ChevronLeft","ChevronRight","useEffect","useState","jsx","jsxs","formatDate","Badge","useState","useEffect","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Button","ChevronLeft","ChevronRight","Button","Input","Tabs","TabsList","TabsTrigger","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","FORM_FIELD_TYPE_CATALOG","useCallback","useEffect","useRef","useState","Button","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuTrigger","Tooltip","TooltipContent","TooltipTrigger","FORM_FIELD_TYPE_CATALOG","useCallback","useMemo","useState","useCallback","useMemo","useState","jsx","useState","useCallback","useMemo","Button","useState","jsx","jsxs","FormLabelWithTooltip","Input","Checkbox","Tabs","TabsList","TabsTrigger","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","useState","useCallback","useMemo","Button","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","useCallback","useMemo","jsx","jsxs","jsx","jsxs","useMemo","FormLabelWithTooltip","Input","Checkbox","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","useState","useCallback","Tabs","TabsList","TabsTrigger","Fragment","jsx","jsxs","FORM_FIELD_TYPE_CATALOG","DropdownMenu","DropdownMenuTrigger","Button","DropdownMenuContent","DropdownMenuItem","Tooltip","TooltipTrigger","TooltipContent","useState","useMemo","useCallback","Badge","Button","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuSeparator","DropdownMenuTrigger","Input","Label","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","Sheet","SheetContent","SheetDescription","SheetHeader","SheetTitle","Switch","Copy","MoreHorizontal","Pencil","Plus","Trash2","TriangleAlert","useCallback","useEffect","useMemo","useState","jsx","jsxs","Badge","TriangleAlert","Switch","DropdownMenu","DropdownMenuTrigger","Button","MoreHorizontal","DropdownMenuContent","DropdownMenuItem","Pencil","Copy","DropdownMenuSeparator","Trash2","useState","useCallback","Label","Input","Sheet","SheetContent","SheetHeader","SheetTitle","SheetDescription","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Plus","useEffect","useMemo","Badge","Button","Checkbox","Input","Label","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","Tabs","TabsList","TabsTrigger","Textarea","useMemo","useState","Fragment","jsx","jsxs","Textarea","Checkbox","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Label","Input","useState","useMemo","Tabs","TabsList","TabsTrigger","Button","Badge","Input","Label","RadioGroup","RadioGroupItem","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","Switch","Textarea","jsx","jsxs","Label","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Input","Switch","RadioGroup","RadioGroupItem","Textarea","Fragment","jsx","jsxs","useState","useEffect","FORM_FIELD_TYPE_CATALOG","useRef","useCallback","Button","Input","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Tabs","TabsList","TabsTrigger"]}
|