@nextlyhq/plugin-form-builder 0.0.2-alpha.5 → 0.0.2-alpha.50

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.
Files changed (38) hide show
  1. package/README.md +12 -5
  2. package/dist/admin/index.d.ts +123 -331
  3. package/dist/admin/index.js +3809 -3419
  4. package/dist/admin/index.js.map +1 -1
  5. package/dist/chunk-WVI7N3QO.js +559 -0
  6. package/dist/chunk-WVI7N3QO.js.map +1 -0
  7. package/dist/index.d.ts +12 -11
  8. package/dist/index.js +579 -663
  9. package/dist/index.js.map +1 -1
  10. package/dist/{index-C0kBvYjm.d.ts → types-r8uBeB0u.d.ts} +126 -125
  11. package/package.json +28 -30
  12. package/dist/CheckboxFieldEditor-K4T6QX52.js +0 -121
  13. package/dist/CheckboxFieldEditor-K4T6QX52.js.map +0 -1
  14. package/dist/DateFieldEditor-JFJFAVOH.js +0 -187
  15. package/dist/DateFieldEditor-JFJFAVOH.js.map +0 -1
  16. package/dist/EmailFieldEditor-MMOXXL7P.js +0 -138
  17. package/dist/EmailFieldEditor-MMOXXL7P.js.map +0 -1
  18. package/dist/NumberFieldEditor-UISAYR6Z.js +0 -175
  19. package/dist/NumberFieldEditor-UISAYR6Z.js.map +0 -1
  20. package/dist/RadioFieldEditor-6UQFH4WT.js +0 -165
  21. package/dist/RadioFieldEditor-6UQFH4WT.js.map +0 -1
  22. package/dist/SelectFieldEditor-PSO4KHV4.js +0 -213
  23. package/dist/SelectFieldEditor-PSO4KHV4.js.map +0 -1
  24. package/dist/TextFieldEditor-5EU64EA5.js +0 -187
  25. package/dist/TextFieldEditor-5EU64EA5.js.map +0 -1
  26. package/dist/TextareaFieldEditor-773G3LNM.js +0 -190
  27. package/dist/TextareaFieldEditor-773G3LNM.js.map +0 -1
  28. package/dist/admin/index.css +0 -934
  29. package/dist/admin/index.css.map +0 -1
  30. package/dist/chunk-ABNZFTQK.js +0 -586
  31. package/dist/chunk-ABNZFTQK.js.map +0 -1
  32. package/dist/chunk-XTCEPJ7B.js +0 -256
  33. package/dist/chunk-XTCEPJ7B.js.map +0 -1
  34. package/dist/components/index.d.ts +0 -3
  35. package/dist/components/index.js +0 -9
  36. package/dist/components/index.js.map +0 -1
  37. package/dist/styles/form-builder.css +0 -1150
  38. package/dist/styles/submissions-filter.css +0 -75
package/README.md CHANGED
@@ -46,15 +46,14 @@ export default defineConfig({
46
46
 
47
47
  > A `formBuilderPlugin` default-instance shortcut is also exported for cases where no customization is needed. See [the plugin docs](https://nextlyhq.com/docs/plugins/form-builder) for the full options reference.
48
48
 
49
- ## Admin styling
49
+ ## Admin components
50
50
 
51
- The plugin's admin UI requires three imports in your admin route page so the builder and submissions filter render correctly:
51
+ The plugin's admin UI needs one import in your admin route page (a side effect
52
+ that registers the builder and submissions views):
52
53
 
53
54
  ```tsx
54
55
  // app/admin/[[...params]]/page.tsx
55
56
  import "@nextlyhq/plugin-form-builder/admin";
56
- import "@nextlyhq/plugin-form-builder/styles/builder.css";
57
- import "@nextlyhq/plugin-form-builder/styles/submissions-filter.css";
58
57
  ```
59
58
 
60
59
  ## What this plugin adds
@@ -64,6 +63,14 @@ import "@nextlyhq/plugin-form-builder/styles/submissions-filter.css";
64
63
  - **Form lifecycle states:** Draft, Published, Closed
65
64
  - **Optional integrations:** email notifications, webhook delivery on submission, spam protection (honeypot, rate limit, reCAPTCHA v3)
66
65
 
66
+ ### Submission privacy
67
+
68
+ Submissions carry visitor-entered answers plus `ipAddress` and `userAgent`, so the `form-submissions` collection suppresses the default `entry.*` events (which would otherwise deliver that content to any endpoint subscribed to `entry.created` or `*`). In their place it emits a curated **`form.submission.created`** event carrying only safe metadata — which form, when, and the submission status — never the answers, IP, or user agent. Subscribe an endpoint to `form.submission.created` to be notified of new submissions without receiving their content.
69
+
70
+ Do **not** override the submissions collection with `webhooks: true`: that would re-enable the raw `entry.*` events and deliver the PII-bearing submission content. Any collection can adopt the same pattern via the `webhooks` option: `{ record: false }` suppresses the default events, and `{ record: false, emit: { event, fields } }` additionally emits a curated event carrying only the allowlisted `fields`. Recording is on by default for everything else.
71
+
72
+ A collection or single created in the **Schema Builder** can be opted out the same way, without touching code: **Settings → Advanced → Webhook recording**. The choice is stored on the entity's registry row, so it holds across restarts. For code-first entities the `webhooks` option in config remains the source of truth and is republished on every boot.
73
+
67
74
  ## Field types
68
75
 
69
76
  The plugin ships 13 field types. All are enabled by default; disable any by setting it to `false` in the `fields` option.
@@ -94,7 +101,7 @@ See the [Field types reference](https://nextlyhq.com/docs/plugins/form-builder#f
94
101
  - Server helpers: `submitForm`, `validateSubmission`, `getFormSubmissionStats`, `createFormConfig`, `validateFormConfig`, `assertValidFormConfig`
95
102
  - Export utilities: `exportToCSV`, `exportToJSON`, `exportAndDownload`, `downloadFile`, `generateExportFilename`
96
103
  - Collections: `formsCollection`, `submissionsCollection`
97
- - Type exports: `FormDocument`, `SubmissionDocument`, `FormSubmission`, `EmailConfig`, `WebhookConfig`, `WebhookEvent`, `FormFieldOption`, `SubmissionListProps`, `SubmissionDetailProps`
104
+ - Type exports: `FormDocument`, `SubmissionDocument`, `FormSubmission`, `FormNotification`, `EmailConfig`, `WebhookConfig`, `WebhookEvent`, `FormFieldOption`
98
105
 
99
106
  ## Compatibility
100
107
 
@@ -1,7 +1,7 @@
1
- import { ComponentPath } from '@nextlyhq/admin/lib/component-registry';
1
+ import { ComponentPath } from '@nextlyhq/plugin-sdk/admin';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import { i as FormField, p as FormFieldType } from '../index-C0kBvYjm.js';
4
- export { J as SubmissionDetail, t as SubmissionDetailProps, K as SubmissionList, u as SubmissionListProps } from '../index-C0kBvYjm.js';
3
+ import { q as FormField, s as FormFieldTypeId, A as AnyFormField, b as FormSettings, v as FormNotification } from '../types-r8uBeB0u.js';
4
+ import { FormFieldCatalogType, FieldTypeCatalogEntry } from 'nextly/field-catalog';
5
5
  import { ReactNode } from 'react';
6
6
  import 'nextly';
7
7
 
@@ -27,50 +27,85 @@ interface FormBuilderViewProps {
27
27
  }
28
28
  declare function FormBuilderView({ id, entryId, collection, collectionSlug, isCreating, initialData, onSave, onSuccess, onCancel, }: FormBuilderViewProps): react_jsx_runtime.JSX.Element;
29
29
 
30
- interface SubmissionsFilterProps {
31
- /** Collection slug (should be "form-submissions") */
32
- collectionSlug: string;
33
- /** Collection configuration */
34
- collection: Record<string, unknown>;
30
+ interface SubmissionRow {
31
+ id: string;
32
+ form: string | {
33
+ id: string;
34
+ name?: string;
35
+ };
36
+ data: Record<string, unknown>;
37
+ status: string;
38
+ spamReason?: string | null;
39
+ notes?: string | null;
40
+ ipAddress?: string | null;
41
+ userAgent?: string | null;
42
+ submittedAt?: string | null;
43
+ editedAt?: string | null;
44
+ editedBy?: string | null;
35
45
  }
36
- /**
37
- * SubmissionsFilter - Filter submissions by form
38
- *
39
- * Displays a dropdown of all forms. When a form is selected,
40
- * updates the URL query params to filter the submissions list.
41
- */
42
- declare function SubmissionsFilter({ collectionSlug, }: SubmissionsFilterProps): React.ReactElement | null;
46
+ interface FormOption {
47
+ id: string;
48
+ name: string;
49
+ fields: FormField[];
50
+ }
51
+ interface SubmissionsViewProps {
52
+ collectionSlug?: string;
53
+ }
54
+ declare function SubmissionsView({ collectionSlug }: SubmissionsViewProps): react_jsx_runtime.JSX.Element;
43
55
 
44
- /**
45
- * FieldLibrary — Right-sidebar field type palette
46
- *
47
- * Mirrors the Collection Builder's FieldPalette:
48
- * - Search bar at top
49
- * - Accordion categories (Basic / Advanced)
50
- * - Blue icon boxes with draggable rows
51
- * - Click or drag to add a field
52
- */
53
- declare function FieldLibrary(): react_jsx_runtime.JSX.Element;
56
+ interface SubmissionSheetProps {
57
+ submission: SubmissionRow;
58
+ form: FormOption;
59
+ canUpdate: boolean;
60
+ onClose: () => void;
61
+ onPrev?: () => void;
62
+ onNext?: () => void;
63
+ onSave: (changes: Record<string, unknown>) => Promise<void>;
64
+ }
65
+ declare function SubmissionSheet({ submission, form, canUpdate, onClose, onPrev, onNext, onSave, }: SubmissionSheetProps): react_jsx_runtime.JSX.Element;
54
66
 
55
- interface FormCanvasProps {
56
- fields: FormField[];
57
- selectedFieldId: string | null;
58
- onFieldSelect: (fieldName: string | null) => void;
59
- onFieldDelete: (fieldName: string) => void;
67
+ interface FieldCardsProps {
68
+ /**
69
+ * Form-surface types the host has NOT excluded (the plugin's field
70
+ * enable/disable option). `null` while the host configuration is still
71
+ * loading — the Add dialog waits rather than flashing the unfiltered set.
72
+ * Types outside this set stay renderable on existing fields but cannot be
73
+ * added.
74
+ */
75
+ enabledTypes: readonly FormFieldCatalogType[] | null;
76
+ /**
77
+ * Type ids the host disabled (`config.fields[type] === false`). Applied to
78
+ * plugin field types too, so the host exclude layer is not bypassed for
79
+ * contributed types.
80
+ */
81
+ disabledFieldTypes?: ReadonlySet<string>;
82
+ /** Creates a field of the given type and returns it (context helper). */
83
+ onAddField: (type: FormFieldTypeId) => void;
60
84
  }
61
- declare function FormCanvas({ fields, selectedFieldId, onFieldSelect, onFieldDelete, }: FormCanvasProps): react_jsx_runtime.JSX.Element;
85
+ declare function FieldCards({ enabledTypes, disabledFieldTypes, onAddField, }: FieldCardsProps): react_jsx_runtime.JSX.Element;
86
+
87
+ interface AddFieldDialogProps {
88
+ open: boolean;
89
+ onOpenChange: (open: boolean) => void;
90
+ /**
91
+ * The form surface's catalog — built-ins already filtered by the host's
92
+ * excludes plus any plugin field types that opted into the forms surface;
93
+ * `null` while the host configuration is still loading. `type` is the open
94
+ * `FormFieldTypeId` so a plugin entry shares this shape with the built-ins.
95
+ */
96
+ entries: readonly FieldTypeCatalogEntry<FormFieldTypeId>[] | null;
97
+ /** Called with the chosen type; the parent creates and selects the field. */
98
+ onAdd: (type: FormFieldTypeId) => void;
99
+ }
100
+ declare function AddFieldDialog({ open, onOpenChange, entries, onAdd, }: AddFieldDialogProps): react_jsx_runtime.JSX.Element;
62
101
 
63
102
  interface FieldEditorProps {
64
- /** The field being edited */
65
- field: FormField;
103
+ /** The field being edited (built-in or plugin-contributed). */
104
+ field: AnyFormField;
66
105
  /** All fields in the form (for conditional logic references) */
67
- allFields: FormField[];
106
+ allFields: AnyFormField[];
68
107
  /** Callback when field is updated */
69
- onUpdate: (updates: Partial<FormField>) => void;
70
- /** Callback when field is deleted */
71
- onDelete: () => void;
72
- /** Callback when field is duplicated */
73
- onDuplicate?: () => void;
108
+ onUpdate: (updates: Partial<AnyFormField>) => void;
74
109
  }
75
110
  /**
76
111
  * FieldEditor - Field properties configuration panel
@@ -91,268 +126,23 @@ interface FieldEditorProps {
91
126
  * />
92
127
  * ```
93
128
  */
94
- declare function FieldEditor({ field, allFields, onUpdate, onDelete, onDuplicate, }: FieldEditorProps): react_jsx_runtime.JSX.Element;
129
+ declare function FieldEditor({ field, allFields, onUpdate }: FieldEditorProps): react_jsx_runtime.JSX.Element;
95
130
 
96
131
  interface FormPreviewProps {
97
- /** Array of form fields to preview */
98
- fields: FormField[];
132
+ /** Array of form fields to preview (built-in or plugin-contributed). */
133
+ fields: AnyFormField[];
99
134
  /** Form metadata */
100
135
  formData?: {
101
136
  name?: string;
102
137
  slug?: string;
103
138
  description?: string;
104
- status?: string;
105
139
  };
106
140
  }
107
- /**
108
- * FormPreview - Visual form preview
109
- *
110
- * This is a stub component that shows a preview of the form.
111
- * The full implementation will include:
112
- * - Rendered form fields with proper styling
113
- * - Responsive preview modes (desktop, tablet, mobile)
114
- * - Theme preview options
115
- * - Conditional logic simulation
116
- *
117
- * @example
118
- * ```tsx
119
- * <FormPreview fields={fields} formData={formData} />
120
- * ```
121
- */
122
141
  declare function FormPreview({ fields, formData }: FormPreviewProps): react_jsx_runtime.JSX.Element;
123
142
 
124
- interface FormFieldListProps {
125
- /**
126
- * Array of form fields to display.
127
- */
128
- fields: FormField[];
129
- /**
130
- * Callback when fields are reordered via drag-and-drop.
131
- * Receives the new array with fields in updated order.
132
- */
133
- onFieldsChange: (fields: FormField[]) => void;
134
- /**
135
- * Callback when a field is selected for editing.
136
- * Receives the field name (unique identifier).
137
- */
138
- onEditField: (fieldName: string) => void;
139
- /**
140
- * Callback when a field should be deleted.
141
- * Receives the field name (unique identifier).
142
- */
143
- onDeleteField: (fieldName: string) => void;
144
- /**
145
- * Currently selected field name for highlighting.
146
- */
147
- selectedFieldName?: string | null;
148
- /**
149
- * Whether the list is disabled (no interactions allowed).
150
- * @default false
151
- */
152
- disabled?: boolean;
153
- }
154
- /**
155
- * FormFieldList provides a drag-and-drop sortable container for form fields.
156
- *
157
- * This component wraps fields with DndContext and SortableContext from @dnd-kit,
158
- * enabling drag-and-drop reordering with full keyboard accessibility.
159
- *
160
- * The component follows the pattern established by ArrayInput.tsx in the
161
- * Nextly admin package:
162
- * - PointerSensor with 8px activation distance (prevents accidental drags)
163
- * - KeyboardSensor with sortableKeyboardCoordinates (arrow key navigation)
164
- * - closestCenter collision detection
165
- * - verticalListSortingStrategy for vertical lists
166
- *
167
- * @example
168
- * ```tsx
169
- * <FormFieldList
170
- * fields={formFields}
171
- * onFieldsChange={setFormFields}
172
- * onEditField={(name) => setSelectedField(name)}
173
- * onDeleteField={(name) => handleDeleteField(name)}
174
- * selectedFieldName={selectedField}
175
- * />
176
- * ```
177
- */
178
- declare function FormFieldList({ fields, onFieldsChange, onEditField, onDeleteField, selectedFieldName, disabled, }: FormFieldListProps): react_jsx_runtime.JSX.Element;
179
-
180
- interface SortableFieldRowProps {
181
- /**
182
- * The form field to display.
183
- */
184
- field: FormField;
185
- /**
186
- * Whether this row is currently selected for editing.
187
- */
188
- isSelected: boolean;
189
- /**
190
- * Callback when the row is clicked/selected.
191
- */
192
- onSelect: () => void;
193
- /**
194
- * Callback when the delete button is clicked.
195
- */
196
- onDelete: () => void;
197
- /**
198
- * Whether the row is disabled (no interactions allowed).
199
- * @default false
200
- */
201
- disabled?: boolean;
202
- }
203
- /**
204
- * SortableFieldRow renders a single draggable field row in the form builder.
205
- *
206
- * Uses @dnd-kit's useSortable hook to enable drag-and-drop reordering.
207
- * The component displays:
208
- * - A drag handle (GripVertical icon) for reordering
209
- * - The field type icon
210
- * - The field label (or name as fallback) with required indicator
211
- * - The field type badge
212
- * - A delete button
213
- *
214
- * Visual feedback is provided during drag operations:
215
- * - Reduced opacity (50%)
216
- * - Primary color ring (2px)
217
- * - Elevated shadow
218
- * - Higher z-index
219
- *
220
- * @example
221
- * ```tsx
222
- * <SortableFieldRow
223
- * field={field}
224
- * isSelected={selectedFieldName === field.name}
225
- * onSelect={() => setSelectedFieldName(field.name)}
226
- * onDelete={() => handleDeleteField(field.name)}
227
- * />
228
- * ```
229
- */
230
- declare function SortableFieldRow({ field, isSelected, onSelect, onDelete, disabled, }: SortableFieldRowProps): react_jsx_runtime.JSX.Element;
231
-
232
- interface AddFieldButtonProps {
233
- /**
234
- * Callback when a new field is created.
235
- * Receives the newly created FormField instance.
236
- */
237
- onAddField: (field: FormField) => void;
238
- /**
239
- * Whether the button is disabled.
240
- * @default false
241
- */
242
- disabled?: boolean;
243
- /**
244
- * Additional CSS class names for the button.
245
- */
246
- className?: string;
247
- }
248
- /**
249
- * AddFieldButton renders a button that opens a modal for selecting field types.
250
- *
251
- * When a field type is selected, a new field instance is created with default
252
- * configuration and passed to the onAddField callback. The modal automatically
253
- * closes after selection.
254
- *
255
- * @example
256
- * ```tsx
257
- * <AddFieldButton
258
- * onAddField={(field) => {
259
- * setFields([...fields, field]);
260
- * }}
261
- * />
262
- * ```
263
- */
264
- declare function AddFieldButton({ onAddField, disabled, className, }: AddFieldButtonProps): react_jsx_runtime.JSX.Element;
265
-
266
- interface FieldEditorPanelProps {
267
- /**
268
- * The field being edited.
269
- */
270
- field: FormField;
271
- /**
272
- * All fields in the form (for references, e.g., conditional logic).
273
- */
274
- allFields: FormField[];
275
- /**
276
- * Callback when field properties are updated.
277
- * Receives partial updates to merge with current field.
278
- */
279
- onUpdate: (updates: Partial<FormField>) => void;
280
- /**
281
- * Callback when the panel should be closed.
282
- */
283
- onClose: () => void;
284
- }
285
- /**
286
- * FieldEditorPanel - Right-side panel for editing field properties
287
- *
288
- * This component dynamically loads the appropriate field editor based on
289
- * the field type. Each field type has its own editor component that handles
290
- * the specific configuration options for that type.
291
- *
292
- * The panel displays:
293
- * - Header with field type icon, type label, and field label
294
- * - Close button to dismiss the panel
295
- * - Lazy-loaded editor content with loading skeleton
296
- *
297
- * @example
298
- * ```tsx
299
- * <FieldEditorPanel
300
- * field={selectedField}
301
- * allFields={allFields}
302
- * onUpdate={(updates) => updateField(selectedField.name, updates)}
303
- * onClose={() => setSelectedField(null)}
304
- * />
305
- * ```
306
- */
307
- declare function FieldEditorPanel({ field, allFields, onUpdate, onClose, }: FieldEditorPanelProps): react_jsx_runtime.JSX.Element;
308
-
309
- /** Form settings configuration */
310
- interface FormSettings {
311
- /** Submit button text */
312
- submitButtonText: string;
313
- /** Show reset button */
314
- showResetButton: boolean;
315
- /** Reset button text */
316
- resetButtonText: string;
317
- /** Success message after submission */
318
- confirmationMessage: string;
319
- /** Redirect URL after submission (optional) */
320
- redirectUrl?: string;
321
- /** Enable honeypot spam protection */
322
- honeypotEnabled: boolean;
323
- /** Enable CAPTCHA */
324
- captchaEnabled: boolean;
325
- /** Store submissions in database */
326
- storeSubmissions: boolean;
327
- /** Limit submissions per user/IP */
328
- submissionLimit?: number;
329
- }
330
- /** Email notification configuration */
331
- interface FormNotification {
332
- /** Unique ID for this notification */
333
- id: string;
334
- /** Notification name */
335
- name: string;
336
- /** Whether this notification is enabled */
337
- enabled: boolean;
338
- /** ID of the email provider to use; undefined = system default */
339
- providerId?: string;
340
- /** Sender email override; undefined = use provider's configured address */
341
- senderEmail?: string;
342
- /** How the recipient address is determined */
343
- recipientType: "static" | "field";
344
- /** Recipient address: static email or a {{fieldName}} reference */
345
- to: string;
346
- /** CC email addresses */
347
- cc: string[];
348
- /** BCC email addresses */
349
- bcc: string[];
350
- /** Slug of the email template to use */
351
- templateSlug?: string;
352
- }
353
143
  interface FormBuilderState {
354
144
  /** Form fields array */
355
- fields: FormField[];
145
+ fields: AnyFormField[];
356
146
  /** Currently selected field ID (name) */
357
147
  selectedFieldId: string | null;
358
148
  /** Active tab: builder, preview, settings, or notifications */
@@ -374,11 +164,11 @@ interface FormBuilderState {
374
164
  }
375
165
  interface FormBuilderActions {
376
166
  /** Set all fields */
377
- setFields: (fields: FormField[]) => void;
167
+ setFields: (fields: AnyFormField[]) => void;
378
168
  /** Add a new field */
379
- addField: (field: FormField, index?: number) => void;
169
+ addField: (field: AnyFormField, index?: number) => void;
380
170
  /** Update a field by name */
381
- updateField: (fieldName: string, updates: Partial<FormField>) => void;
171
+ updateField: (fieldName: string, updates: Partial<AnyFormField>) => void;
382
172
  /** Delete a field by name */
383
173
  deleteField: (fieldName: string) => void;
384
174
  /** Move a field from one index to another */
@@ -395,10 +185,14 @@ interface FormBuilderActions {
395
185
  updateSettings: (updates: Partial<FormSettings>) => void;
396
186
  /** Add a notification */
397
187
  addNotification: (notification: FormNotification) => void;
188
+ /** Duplicate a notification (the copy starts disabled) */
189
+ duplicateNotification: (id: string) => void;
398
190
  /** Update a notification */
399
191
  updateNotification: (id: string, updates: Partial<FormNotification>) => void;
400
192
  /** Delete a notification */
401
193
  deleteNotification: (id: string) => void;
194
+ /** Seed default notifications into an empty list without dirtying the form */
195
+ seedNotifications: (rules: FormNotification[]) => void;
402
196
  /** Mark form as saved (clears dirty flag) */
403
197
  markAsSaved: () => void;
404
198
  }
@@ -412,29 +206,34 @@ interface FormBuilderProviderProps {
412
206
  slug?: string;
413
207
  description?: string;
414
208
  status?: "draft" | "published" | "closed";
415
- fields?: FormField[];
209
+ fields?: AnyFormField[];
416
210
  settings?: Partial<FormSettings>;
417
211
  notifications?: FormNotification[];
418
212
  };
419
213
  /** Child components */
420
214
  children: ReactNode;
421
215
  }
422
- /** Default form settings */
216
+ /** Default form settings (the canonical defaults from the settings reader) */
423
217
  declare const DEFAULT_SETTINGS: FormSettings;
424
- /** Create a new email integration with default values */
218
+ /** Create a new notification rule with default values */
425
219
  declare function createNotification(): FormNotification;
426
220
  /**
427
- * Generate a unique field name based on type and timestamp.
221
+ * Generate a readable unique field name: the type itself for the first
222
+ * field of that type, then a numeric suffix (`email`, `email_2`, ...).
223
+ * Names key submission data, so they should read like keys a developer
224
+ * would have chosen, not timestamps.
428
225
  */
429
- declare function generateFieldName(type: FormFieldType): string;
226
+ declare function generateFieldName(type: FormFieldTypeId, existingNames?: readonly string[]): string;
430
227
  /**
431
- * Generate a human-readable label from field type.
228
+ * Generate a human-readable label from field type, using the shared catalog
229
+ * so a new field's default label matches what the picker called the type. A
230
+ * plugin type not in the built-in catalog falls back to a title-cased id.
432
231
  */
433
- declare function generateFieldLabel(type: FormFieldType): string;
232
+ declare function generateFieldLabel(type: FormFieldTypeId): string;
434
233
  /**
435
234
  * Create a new field from a field type with default values.
436
235
  */
437
- declare function createFieldFromType(type: FormFieldType): FormField;
236
+ declare function createFieldFromType(type: FormFieldTypeId, existingNames?: readonly string[]): AnyFormField;
438
237
  /**
439
238
  * FormBuilderProvider - Provides form builder state to child components
440
239
  *
@@ -487,24 +286,32 @@ declare function useFormBuilder(): FormBuilderContextValue;
487
286
  */
488
287
  declare function useOptionalFormBuilder(): FormBuilderContextValue | null;
489
288
 
490
- /**
491
- * FormSettingsTab - Form settings configuration panel
492
- *
493
- * Refined for Antigravity standard:
494
- * - Two-column layout for better space utilization.
495
- * - Title Case headings with improved hierarchy.
496
- * - Robust state management for action tabs.
497
- */
498
- declare function FormSettingsTab(): react_jsx_runtime.JSX.Element;
289
+ interface SpamDefaults {
290
+ honeypot?: boolean;
291
+ recaptchaEnabled?: boolean;
292
+ }
293
+ interface FormSettingsTabProps {
294
+ /** Plugin-level spam defaults (from builder-config); null while loading. */
295
+ spamDefaults: SpamDefaults | null;
296
+ }
297
+ declare function FormSettingsTab({ spamDefaults }: FormSettingsTabProps): react_jsx_runtime.JSX.Element;
499
298
 
299
+ /** Host-level notification defaults surfaced by the builder-config route. */
300
+ interface NotificationDefaults {
301
+ defaultFrom?: string;
302
+ defaultToEmail?: string;
303
+ }
304
+ interface FormNotificationsTabProps {
305
+ /** `null` while the builder-config request is still settling. */
306
+ defaults: NotificationDefaults | null;
307
+ }
500
308
  /**
501
- * FormNotificationsTab - Email integrations configuration
309
+ * FormNotificationsTab - the form's notification rules.
502
310
  *
503
- * Allows users to configure email integrations that trigger when a form is
504
- * submitted. Each integration references an existing email provider and
505
- * template rather than duplicating provider credentials.
311
+ * Each rule references an existing email provider and template rather than
312
+ * duplicating provider credentials or embedding a second template editor.
506
313
  */
507
- declare function FormNotificationsTab(): react_jsx_runtime.JSX.Element;
314
+ declare function FormNotificationsTab({ defaults }: FormNotificationsTabProps): react_jsx_runtime.JSX.Element;
508
315
 
509
316
  /**
510
317
  * Form Builder Admin Components
@@ -526,22 +333,7 @@ declare function FormNotificationsTab(): react_jsx_runtime.JSX.Element;
526
333
 
527
334
  /** Component path for FormBuilderView */
528
335
  declare const FORM_BUILDER_VIEW_PATH: ComponentPath;
529
- /** Component path for SubmissionsFilter */
530
- declare const SUBMISSIONS_FILTER_PATH: ComponentPath;
531
- /**
532
- * Register Form Builder admin components with the Nextly admin panel.
533
- *
534
- * @deprecated This function is no longer needed. Components are auto-registered
535
- * when the admin detects the Form Builder plugin's component paths in collection configs.
536
- *
537
- * @example
538
- * ```typescript
539
- * // No manual registration needed! Just add the plugin to your config:
540
- * export default defineConfig({
541
- * plugins: [formBuilderPlugin.plugin],
542
- * });
543
- * ```
544
- */
545
- declare function registerFormBuilderAdminComponents(): void;
336
+ /** Component path for SubmissionsView */
337
+ declare const SUBMISSIONS_VIEW_PATH: ComponentPath;
546
338
 
547
- export { AddFieldButton, type AddFieldButtonProps, DEFAULT_SETTINGS, FORM_BUILDER_VIEW_PATH, FieldEditor, FieldEditorPanel, type FieldEditorPanelProps, type FieldEditorProps, FieldLibrary, type FormBuilderActions, type FormBuilderContextValue, FormBuilderProvider, type FormBuilderProviderProps, type FormBuilderState, FormBuilderView, type FormBuilderViewProps, FormCanvas, type FormCanvasProps, FormFieldList, type FormFieldListProps, type FormNotification, FormNotificationsTab, FormPreview, type FormPreviewProps, type FormSettings, FormSettingsTab, SUBMISSIONS_FILTER_PATH, SortableFieldRow, type SortableFieldRowProps, SubmissionsFilter, type SubmissionsFilterProps, createFieldFromType, createNotification, generateFieldLabel, generateFieldName, registerFormBuilderAdminComponents, useFormBuilder, useOptionalFormBuilder };
339
+ export { AddFieldDialog, type AddFieldDialogProps, DEFAULT_SETTINGS, FORM_BUILDER_VIEW_PATH, FieldCards, type FieldCardsProps, FieldEditor, type FieldEditorProps, type FormBuilderActions, type FormBuilderContextValue, FormBuilderProvider, type FormBuilderProviderProps, type FormBuilderState, FormBuilderView, type FormBuilderViewProps, FormNotification, FormNotificationsTab, FormPreview, type FormPreviewProps, FormSettings, FormSettingsTab, SUBMISSIONS_VIEW_PATH, SubmissionSheet, SubmissionsView, createFieldFromType, createNotification, generateFieldLabel, generateFieldName, useFormBuilder, useOptionalFormBuilder };