@nextlyhq/plugin-form-builder 0.0.2-alpha.73 → 0.0.2-alpha.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -66,7 +66,8 @@ import "@nextlyhq/plugin-form-builder/admin";
66
66
  - **Admin routes:** `/admin/collections/forms` and `/admin/collections/form-submissions`
67
67
  - **Collections:** `forms`, `form-submissions`
68
68
  - **Form lifecycle states:** Draft, Published, Closed
69
- - **Optional integrations:** email notifications, a `form.submission.created` webhook through Nextly's own webhooks, spam protection (honeypot, rate limit, reCAPTCHA v3)
69
+ - **One response per person:** by email address, browser or network address, refused atomically by a keyed digest (the browser mode needs your form's script to send a token; see the docs)
70
+ - **Optional integrations:** email notifications, a `form.submission.created` webhook through Nextly's own webhooks, spam protection (honeypot, rate limit, and a reCAPTCHA v3 or Cloudflare Turnstile bot check verified on the server)
70
71
 
71
72
  ### Submission privacy
72
73
 
@@ -1,7 +1,7 @@
1
- import { O as FormSettings, S as FormFieldTypeId, T as FormNotification, b as FormField, i as AnyFormField, r as NewSubmissionsData } from "../new-submissions-CzlhVGhH.js";
2
- import { ComponentPath, DocumentLockGates } from "@nextlyhq/plugin-sdk/admin";
1
+ import { O as FormSettings, S as FormFieldTypeId, T as FormNotification, b as FormField, i as AnyFormField, r as NewSubmissionsData } from "../new-submissions-DGiIhdBF.js";
2
+ import { ComponentPath, DocumentLockGates, FieldPickerChoice } from "@nextlyhq/plugin-sdk/admin";
3
3
  import React, { JSX, ReactNode } from "react";
4
- import { FieldTypeCatalogEntry, FormFieldCatalogType } from "nextly/field-catalog";
4
+ import { FormFieldCatalogType } from "nextly/field-catalog";
5
5
  interface FormBuilderViewProps {
6
6
  id?: string;
7
7
  entryId?: string;
@@ -14,13 +14,27 @@ interface FormBuilderViewProps {
14
14
  slug?: string;
15
15
  description?: string;
16
16
  status?: "draft" | "published" | "closed";
17
+ /** When the form first went live: what fixes its ID. */
18
+ wentLiveAt?: string | null;
17
19
  closedMessage?: string;
18
20
  fields?: unknown[];
19
21
  settings?: Record<string, unknown>;
20
22
  notifications?: unknown[];
23
+ /**
24
+ * The form's version as read, which a save sends back so one made from an
25
+ * older version is refused rather than replacing what someone saved since.
26
+ */
27
+ _rev?: string;
21
28
  };
22
- onSave?: (data: unknown) => void;
29
+ /**
30
+ * Saves the form in the host's own way, in place of the builder's request.
31
+ * The builder counts the form saved once this returns, or once the promise
32
+ * it may return settles without failing.
33
+ */
34
+ onSave?: (data: unknown) => void | Promise<void>;
23
35
  onSuccess?: (entry?: Record<string, unknown>) => void;
36
+ /** Called once the form has been deleted from the editor's More menu. */
37
+ onDelete?: () => void;
24
38
  onCancel?: () => void;
25
39
  /**
26
40
  * What a colleague's claim on this form withholds, handed over by the admin
@@ -32,8 +46,14 @@ interface FormBuilderViewProps {
32
46
  * it too.
33
47
  */
34
48
  documentLock?: DocumentLockGates;
49
+ /**
50
+ * The page of the editor the address names (`"settings"` at
51
+ * `/admin/collections/forms/<id>/settings`); absent on the form's edit
52
+ * address, which opens Builder.
53
+ */
54
+ view?: string;
35
55
  }
36
- export declare function FormBuilderView({ id, entryId, collection, collectionSlug, isCreating, initialData, onSave, onSuccess, onCancel, documentLock }: FormBuilderViewProps): JSX.Element;
56
+ export declare function FormBuilderView({ id, entryId, collection, collectionSlug, isCreating, initialData, onSave, onSuccess, onDelete, documentLock, view }: FormBuilderViewProps): JSX.Element;
37
57
  interface SubmissionRow {
38
58
  id: string;
39
59
  form: string | {
@@ -49,6 +69,8 @@ interface SubmissionRow {
49
69
  submittedAt?: string | null;
50
70
  editedAt?: string | null;
51
71
  editedBy?: string | null;
72
+ /** The submission's version as the list read it; see `submissionPatch`. */
73
+ _rev?: string;
52
74
  }
53
75
  interface FormOption {
54
76
  id: string;
@@ -57,8 +79,13 @@ interface FormOption {
57
79
  }
58
80
  interface SubmissionsViewProps {
59
81
  collectionSlug?: string;
82
+ /**
83
+ * Show only this form's submissions, with no choice of form: the list as a
84
+ * form's own Submissions tab draws it.
85
+ */
86
+ formId?: string;
60
87
  }
61
- export declare function SubmissionsView({ collectionSlug }: SubmissionsViewProps): JSX.Element;
88
+ export declare function SubmissionsView({ collectionSlug, formId }: SubmissionsViewProps): JSX.Element;
62
89
  interface SubmissionSheetProps {
63
90
  submission: SubmissionRow;
64
91
  form: FormOption;
@@ -69,17 +96,18 @@ interface SubmissionSheetProps {
69
96
  onSave: (changes: Record<string, unknown>) => Promise<void>;
70
97
  }
71
98
  export declare function SubmissionSheet({ submission, form, canUpdate, onClose, onPrev, onNext, onSave }: SubmissionSheetProps): JSX.Element;
72
- /** The card's rows, as many as its size holds. */
73
- export declare function NewSubmissionsCard({ data }: {
99
+ /** The card's rows: its reader's "Number of entries", the rows its `load` read. */
100
+ export declare function NewSubmissionsCard({ data, settings }: {
74
101
  data: NewSubmissionsData;
102
+ /** The card's settings as its `load` read them; `limit` is its "Number of entries". */
103
+ settings?: Record<string, unknown>;
75
104
  }): JSX.Element;
76
105
  interface FieldCardsProps {
77
106
  /**
78
107
  * Form-surface types the host has NOT excluded (the plugin's field
79
108
  * enable/disable option). `null` while the host configuration is still
80
- * loading — the Add dialog waits rather than flashing the unfiltered set.
81
- * Types outside this set stay renderable on existing fields but cannot be
82
- * added.
109
+ * loading: Add field waits rather than offering the unfiltered set. Types
110
+ * outside this set stay editable on existing fields but cannot be added.
83
111
  */
84
112
  enabledTypes: readonly FormFieldCatalogType[] | null;
85
113
  /**
@@ -88,52 +116,23 @@ interface FieldCardsProps {
88
116
  * contributed types.
89
117
  */
90
118
  disabledFieldTypes?: ReadonlySet<string>;
91
- /** Creates a field of the given type and returns it (context helper). */
92
- onAddField: (type: FormFieldTypeId) => void;
93
- }
94
- export declare function FieldCards({ enabledTypes, disabledFieldTypes, onAddField }: FieldCardsProps): JSX.Element;
95
- interface AddFieldDialogProps {
96
- open: boolean;
97
- onOpenChange: (open: boolean) => void;
98
119
  /**
99
- * The form surface's catalog — built-ins already filtered by the host's
100
- * excludes plus any plugin field types that opted into the forms surface;
101
- * `null` while the host configuration is still loading. `type` is the open
102
- * `FormFieldTypeId` so a plugin entry shares this shape with the built-ins.
120
+ * Creates and selects a field of the chosen type. The picker's whole choice
121
+ * comes second (the label the person typed and the name it gives), so a host
122
+ * written for the type alone keeps working and one that wants the label
123
+ * reads it there. The third is where in the list it goes, when it was added
124
+ * between two rows or below one; absent for the end.
103
125
  */
104
- entries: readonly FieldTypeCatalogEntry<FormFieldTypeId>[] | null;
105
- /** Called with the chosen type; the parent creates and selects the field. */
106
- onAdd: (type: FormFieldTypeId) => void;
107
- }
108
- export declare function AddFieldDialog({ open, onOpenChange, entries, onAdd }: AddFieldDialogProps): JSX.Element;
109
- interface FieldEditorProps {
110
- /** The field being edited (built-in or plugin-contributed). */
111
- field: AnyFormField;
112
- /** All fields in the form (for conditional logic references) */
113
- allFields: AnyFormField[];
114
- /** Callback when field is updated */
115
- onUpdate: (updates: Partial<AnyFormField>) => void;
126
+ onAddField: (type: FormFieldTypeId, choice?: FieldPickerChoice, index?: number) => void;
127
+ /**
128
+ * Where the selected field's settings dock from 1024px: `"beside"` the list
129
+ * (the default, for a list drawn on its own), or by the `"host"` page,
130
+ * which draws `FieldInspector` against the window's edge itself. Below
131
+ * 1024px they open under the row either way.
132
+ */
133
+ dockedSettings?: "beside" | "host";
116
134
  }
117
- /**
118
- * FieldEditor - Field properties configuration panel
119
- *
120
- * Provides a tabbed interface for editing field properties:
121
- * - General: name, label, placeholder, help text, required, width, type-specific options
122
- * - Validation: error messages, min/max length, patterns, etc.
123
- * - Conditional: show/hide logic based on other field values
124
- *
125
- * @example
126
- * ```tsx
127
- * <FieldEditor
128
- * field={selectedField}
129
- * allFields={allFields}
130
- * onUpdate={handleUpdate}
131
- * onDelete={handleDelete}
132
- * onDuplicate={handleDuplicate}
133
- * />
134
- * ```
135
- */
136
- export declare function FieldEditor({ field, allFields, onUpdate }: FieldEditorProps): JSX.Element;
135
+ export declare function FieldCards({ enabledTypes, disabledFieldTypes, onAddField, dockedSettings }: FieldCardsProps): JSX.Element;
137
136
  interface FormPreviewProps {
138
137
  /** Array of form fields to preview (built-in or plugin-contributed). */
139
138
  fields: AnyFormField[];
@@ -145,12 +144,23 @@ interface FormPreviewProps {
145
144
  };
146
145
  }
147
146
  export declare function FormPreview({ fields, formData }: FormPreviewProps): JSX.Element;
147
+ /**
148
+ * Generate a readable unique field name: the type itself for the first
149
+ * field of that type, then a numeric suffix (`email`, `email_2`, ...).
150
+ * Names key submission data, so they should read like keys a developer
151
+ * would have chosen, not timestamps.
152
+ */
153
+ export declare function generateFieldName(type: FormFieldTypeId, existingNames?: readonly string[]): string;
148
154
  interface FormBuilderState {
149
155
  /** Form fields array */
150
156
  fields: AnyFormField[];
151
157
  /** Currently selected field ID (name) */
152
158
  selectedFieldId: string | null;
153
- /** Active tab: builder, preview, settings, or notifications */
159
+ /**
160
+ * Active tab: builder, preview, settings, or notifications.
161
+ * @deprecated The editor shows the page its address names; this is no
162
+ * longer what it shows, and is kept for hosts that read it.
163
+ */
154
164
  activeTab: "builder" | "preview" | "settings" | "notifications";
155
165
  /** Whether form has unsaved changes */
156
166
  isDirty: boolean;
@@ -184,7 +194,10 @@ interface FormBuilderActions {
184
194
  duplicateField: (fieldName: string) => void;
185
195
  /** Select a field */
186
196
  selectField: (fieldName: string | null) => void;
187
- /** Set active tab */
197
+ /**
198
+ * Set active tab.
199
+ * @deprecated The editor's tabs are links to each page's address.
200
+ */
188
201
  setActiveTab: (tab: "builder" | "preview" | "settings" | "notifications") => void;
189
202
  /** Update form metadata */
190
203
  updateFormData: (updates: Partial<FormBuilderState["formData"]>) => void;
@@ -212,6 +225,8 @@ interface FormBuilderProviderProps {
212
225
  slug?: string;
213
226
  description?: string;
214
227
  status?: "draft" | "published" | "closed";
228
+ /** When the form first went live, as the server stamped it. */
229
+ wentLiveAt?: string | null;
215
230
  closedMessage?: string;
216
231
  fields?: AnyFormField[];
217
232
  settings?: Partial<FormSettings>;
@@ -235,13 +250,6 @@ interface FormBuilderProviderProps {
235
250
  export declare const DEFAULT_SETTINGS: FormSettings;
236
251
  /** Create a new notification rule with default values */
237
252
  export declare function createNotification(): FormNotification;
238
- /**
239
- * Generate a readable unique field name: the type itself for the first
240
- * field of that type, then a numeric suffix (`email`, `email_2`, ...).
241
- * Names key submission data, so they should read like keys a developer
242
- * would have chosen, not timestamps.
243
- */
244
- export declare function generateFieldName(type: FormFieldTypeId, existingNames?: readonly string[]): string;
245
253
  /**
246
254
  * Generate a human-readable label from field type, using the shared catalog
247
255
  * so a new field's default label matches what the picker called the type. A
@@ -303,7 +311,22 @@ export declare function useFormBuilder(): FormBuilderContextValue;
303
311
  * @returns Form builder context value or null
304
312
  */
305
313
  export declare function useOptionalFormBuilder(): FormBuilderContextValue | null;
306
- interface SpamDefaults {
314
+ type BotProvider = "recaptcha" | "turnstile";
315
+ /** What the plugin's options say about bot checks and the rate limit. */
316
+ interface BotCheckSiteDefaults {
317
+ /** The provider "Site default" resolves to, or null for none. */
318
+ botCheckDefault?: BotProvider | null;
319
+ /** Which providers have their keys set. */
320
+ botChecks?: Record<BotProvider, {
321
+ secret: boolean;
322
+ siteKey: boolean;
323
+ }>;
324
+ rateLimit?: {
325
+ maxSubmissions: number;
326
+ windowMs: number;
327
+ } | null;
328
+ }
329
+ interface SpamDefaults extends BotCheckSiteDefaults {
307
330
  honeypot?: boolean;
308
331
  recaptchaEnabled?: boolean;
309
332
  }
@@ -344,5 +367,5 @@ export declare function FormNotificationsTab({ defaults }: FormNotificationsTabP
344
367
  export declare const FORM_BUILDER_VIEW_PATH: ComponentPath;
345
368
  /** Component path for SubmissionsView */
346
369
  export declare const SUBMISSIONS_VIEW_PATH: ComponentPath;
347
- export type { AddFieldDialogProps, FieldCardsProps, FieldEditorProps, FormBuilderActions, FormBuilderContextValue, FormBuilderProviderProps, FormBuilderState, FormBuilderViewProps, FormNotification, FormPreviewProps, FormSettings };
370
+ export type { FieldCardsProps, FormBuilderActions, FormBuilderContextValue, FormBuilderProviderProps, FormBuilderState, FormBuilderViewProps, FormNotification, FormPreviewProps, FormSettings };
348
371
  //# sourceMappingURL=index.d.ts.map