@nextlyhq/plugin-form-builder 0.0.2-alpha.56 → 0.0.2-alpha.58
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/dist/admin/index.js +10 -21
- package/dist/admin/index.js.map +1 -1
- package/package.json +11 -11
package/dist/admin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
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 {/* No corner override: square is the primitive's guarantee, not\n this view's decision. */}\n <TabsList>\n {STATUS_TABS.map(tab => (\n <TabsTrigger key={tab.value} value={tab.value}>\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 {/* Layout only. The underline, the active and hover colours, the\n focus ring and the disabled state all come from the shared\n primitive; restating them here is how two copies of one\n appearance start drifting. `gap-0` and the scroll behaviour\n are genuinely local: this strip can overflow its container.\n `-mb-px` is too: the header above draws its own 1px bottom\n divider, and pulling the strip down over it lets the active\n tab's underline REPLACE that divider rather than stack a\n 2px mark on top of a 1px one. */}\n <TabsList className=\"bg-transparent justify-start gap-0 -mb-px max-w-full overflow-x-auto\">\n {mainTabs.map(tab => (\n <TabsTrigger\n key={tab.value}\n value={tab.value}\n className=\"shrink-0 whitespace-nowrap\"\n >\n {tab.label}\n {/* `rounded-sm`, the adornment step, matching the shared\n Badge and the identically sized notification count.\n Square is the TAB's corner and it exists so the\n underline runs flush to the trigger's edges; a chip\n inside the label inherits none of that reasoning, and\n carrying it made the count read as a second tab. */}\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-sm 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 {/* Layout only. The underline, its colours and the square corner come\n from the shared primitive; `w-full` spreads the triggers evenly and\n the active tint is this panel's own surface treatment. */}\n <TabsList className=\"w-full justify-start gap-0\">\n <TabsTrigger\n value=\"general\"\n className=\"w-full data-[state=active]:bg-background/50\"\n >\n General\n </TabsTrigger>\n <TabsTrigger\n value=\"validation\"\n className=\"w-full data-[state=active]:bg-background/50\"\n >\n Validation\n </TabsTrigger>\n <TabsTrigger\n value=\"conditional\"\n className=\"w-full data-[state=active]:bg-background/50\"\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 {/* No corner override: the primitive already guarantees square,\n and a call site restating it is how the guarantee gets forked. */}\n <TabsList>\n <TabsTrigger value=\"desktop\" className=\"gap-1.5\">\n <Monitor className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Desktop\n </TabsTrigger>\n <TabsTrigger value=\"mobile\" className=\"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"]}
|