@nextlyhq/plugin-form-builder 0.0.2-alpha.7 → 0.0.2-alpha.71
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 +29 -17
- package/dist/admin/index.d.ts +251 -454
- package/dist/admin/index.js +4782 -3985
- package/dist/admin/index.js.map +1 -1
- package/dist/field-references-BshlgMcn.js +1048 -0
- package/dist/field-references-BshlgMcn.js.map +1 -0
- package/dist/index.d.ts +341 -615
- package/dist/index.js +3893 -2406
- package/dist/index.js.map +1 -1
- package/dist/types-BHReIA0j.d.ts +986 -0
- package/package.json +40 -39
- package/dist/CheckboxFieldEditor-K4T6QX52.js +0 -121
- package/dist/CheckboxFieldEditor-K4T6QX52.js.map +0 -1
- package/dist/DateFieldEditor-JFJFAVOH.js +0 -187
- package/dist/DateFieldEditor-JFJFAVOH.js.map +0 -1
- package/dist/EmailFieldEditor-MMOXXL7P.js +0 -138
- package/dist/EmailFieldEditor-MMOXXL7P.js.map +0 -1
- package/dist/NumberFieldEditor-UISAYR6Z.js +0 -175
- package/dist/NumberFieldEditor-UISAYR6Z.js.map +0 -1
- package/dist/RadioFieldEditor-6UQFH4WT.js +0 -165
- package/dist/RadioFieldEditor-6UQFH4WT.js.map +0 -1
- package/dist/SelectFieldEditor-PSO4KHV4.js +0 -213
- package/dist/SelectFieldEditor-PSO4KHV4.js.map +0 -1
- package/dist/TextFieldEditor-5EU64EA5.js +0 -187
- package/dist/TextFieldEditor-5EU64EA5.js.map +0 -1
- package/dist/TextareaFieldEditor-773G3LNM.js +0 -190
- package/dist/TextareaFieldEditor-773G3LNM.js.map +0 -1
- package/dist/admin/index.css +0 -934
- package/dist/admin/index.css.map +0 -1
- package/dist/chunk-ABNZFTQK.js +0 -586
- package/dist/chunk-ABNZFTQK.js.map +0 -1
- package/dist/chunk-XTCEPJ7B.js +0 -256
- package/dist/chunk-XTCEPJ7B.js.map +0 -1
- package/dist/components/index.d.ts +0 -3
- package/dist/components/index.js +0 -9
- package/dist/components/index.js.map +0 -1
- package/dist/index-C0kBvYjm.d.ts +0 -1012
- package/dist/styles/form-builder.css +0 -1150
- package/dist/styles/submissions-filter.css +0 -75
package/dist/admin/index.d.ts
CHANGED
|
@@ -1,76 +1,114 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { ReactNode } from 'react';
|
|
6
|
-
import 'nextly';
|
|
7
|
-
|
|
1
|
+
import { S as FormNotification, T as FormSettings, _ as FormField, t as AnyFormField, y as FormFieldTypeId } from "../types-BHReIA0j.js";
|
|
2
|
+
import { ComponentPath, DocumentLockGates } from "@nextlyhq/plugin-sdk/admin";
|
|
3
|
+
import React, { JSX, ReactNode } from "react";
|
|
4
|
+
import { FieldTypeCatalogEntry, FormFieldCatalogType } from "nextly/field-catalog";
|
|
8
5
|
interface FormBuilderViewProps {
|
|
6
|
+
id?: string;
|
|
7
|
+
entryId?: string;
|
|
8
|
+
collection?: string;
|
|
9
|
+
collectionSlug?: string;
|
|
10
|
+
isCreating?: boolean;
|
|
11
|
+
initialData?: {
|
|
9
12
|
id?: string;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
name?: string;
|
|
14
|
+
slug?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
status?: "draft" | "published" | "closed";
|
|
17
|
+
closedMessage?: string;
|
|
18
|
+
fields?: unknown[];
|
|
19
|
+
settings?: Record<string, unknown>;
|
|
20
|
+
notifications?: unknown[];
|
|
21
|
+
};
|
|
22
|
+
onSave?: (data: unknown) => void;
|
|
23
|
+
onSuccess?: (entry?: Record<string, unknown>) => void;
|
|
24
|
+
onCancel?: () => void;
|
|
25
|
+
/**
|
|
26
|
+
* What a colleague's claim on this form withholds, handed over by the admin
|
|
27
|
+
* page that renders this view.
|
|
28
|
+
*
|
|
29
|
+
* The strip above this builder says in words that unsaved changes cannot be
|
|
30
|
+
* saved while someone else holds the document. Committing anyway would make
|
|
31
|
+
* that sentence false and would overwrite the holder's row, so the save reads
|
|
32
|
+
* it too.
|
|
33
|
+
*/
|
|
34
|
+
documentLock?: DocumentLockGates;
|
|
27
35
|
}
|
|
28
|
-
declare function FormBuilderView({ id, entryId, collection, collectionSlug, isCreating, initialData, onSave, onSuccess, onCancel, }: FormBuilderViewProps):
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
export declare function FormBuilderView({ id, entryId, collection, collectionSlug, isCreating, initialData, onSave, onSuccess, onCancel, documentLock }: FormBuilderViewProps): JSX.Element;
|
|
37
|
+
interface SubmissionRow {
|
|
38
|
+
id: string;
|
|
39
|
+
form: string | {
|
|
40
|
+
id: string;
|
|
41
|
+
name?: string;
|
|
42
|
+
};
|
|
43
|
+
data: Record<string, unknown>;
|
|
44
|
+
status: string;
|
|
45
|
+
spamReason?: string | null;
|
|
46
|
+
notes?: string | null;
|
|
47
|
+
ipAddress?: string | null;
|
|
48
|
+
userAgent?: string | null;
|
|
49
|
+
submittedAt?: string | null;
|
|
50
|
+
editedAt?: string | null;
|
|
51
|
+
editedBy?: string | null;
|
|
35
52
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
interface
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
interface FormOption {
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
fields: FormField[];
|
|
57
|
+
}
|
|
58
|
+
interface SubmissionsViewProps {
|
|
59
|
+
collectionSlug?: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function SubmissionsView({ collectionSlug }: SubmissionsViewProps): JSX.Element;
|
|
62
|
+
interface SubmissionSheetProps {
|
|
63
|
+
submission: SubmissionRow;
|
|
64
|
+
form: FormOption;
|
|
65
|
+
canUpdate: boolean;
|
|
66
|
+
onClose: () => void;
|
|
67
|
+
onPrev?: () => void;
|
|
68
|
+
onNext?: () => void;
|
|
69
|
+
onSave: (changes: Record<string, unknown>) => Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
export declare function SubmissionSheet({ submission, form, canUpdate, onClose, onPrev, onNext, onSave }: SubmissionSheetProps): JSX.Element;
|
|
72
|
+
interface FieldCardsProps {
|
|
73
|
+
/**
|
|
74
|
+
* Form-surface types the host has NOT excluded (the plugin's field
|
|
75
|
+
* enable/disable option). `null` while the host configuration is still
|
|
76
|
+
* loading — the Add dialog waits rather than flashing the unfiltered set.
|
|
77
|
+
* Types outside this set stay renderable on existing fields but cannot be
|
|
78
|
+
* added.
|
|
79
|
+
*/
|
|
80
|
+
enabledTypes: readonly FormFieldCatalogType[] | null;
|
|
81
|
+
/**
|
|
82
|
+
* Type ids the host disabled (`config.fields[type] === false`). Applied to
|
|
83
|
+
* plugin field types too, so the host exclude layer is not bypassed for
|
|
84
|
+
* contributed types.
|
|
85
|
+
*/
|
|
86
|
+
disabledFieldTypes?: ReadonlySet<string>;
|
|
87
|
+
/** Creates a field of the given type and returns it (context helper). */
|
|
88
|
+
onAddField: (type: FormFieldTypeId) => void;
|
|
89
|
+
}
|
|
90
|
+
export declare function FieldCards({ enabledTypes, disabledFieldTypes, onAddField }: FieldCardsProps): JSX.Element;
|
|
91
|
+
interface AddFieldDialogProps {
|
|
92
|
+
open: boolean;
|
|
93
|
+
onOpenChange: (open: boolean) => void;
|
|
94
|
+
/**
|
|
95
|
+
* The form surface's catalog — built-ins already filtered by the host's
|
|
96
|
+
* excludes plus any plugin field types that opted into the forms surface;
|
|
97
|
+
* `null` while the host configuration is still loading. `type` is the open
|
|
98
|
+
* `FormFieldTypeId` so a plugin entry shares this shape with the built-ins.
|
|
99
|
+
*/
|
|
100
|
+
entries: readonly FieldTypeCatalogEntry<FormFieldTypeId>[] | null;
|
|
101
|
+
/** Called with the chosen type; the parent creates and selects the field. */
|
|
102
|
+
onAdd: (type: FormFieldTypeId) => void;
|
|
60
103
|
}
|
|
61
|
-
declare function
|
|
62
|
-
|
|
104
|
+
export declare function AddFieldDialog({ open, onOpenChange, entries, onAdd }: AddFieldDialogProps): JSX.Element;
|
|
63
105
|
interface FieldEditorProps {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/** Callback when field is deleted */
|
|
71
|
-
onDelete: () => void;
|
|
72
|
-
/** Callback when field is duplicated */
|
|
73
|
-
onDuplicate?: () => void;
|
|
106
|
+
/** The field being edited (built-in or plugin-contributed). */
|
|
107
|
+
field: AnyFormField;
|
|
108
|
+
/** All fields in the form (for conditional logic references) */
|
|
109
|
+
allFields: AnyFormField[];
|
|
110
|
+
/** Callback when field is updated */
|
|
111
|
+
onUpdate: (updates: Partial<AnyFormField>) => void;
|
|
74
112
|
}
|
|
75
113
|
/**
|
|
76
114
|
* FieldEditor - Field properties configuration panel
|
|
@@ -91,350 +129,125 @@ interface FieldEditorProps {
|
|
|
91
129
|
* />
|
|
92
130
|
* ```
|
|
93
131
|
*/
|
|
94
|
-
declare function FieldEditor({ field, allFields, onUpdate
|
|
95
|
-
|
|
132
|
+
export declare function FieldEditor({ field, allFields, onUpdate }: FieldEditorProps): JSX.Element;
|
|
96
133
|
interface FormPreviewProps {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
};
|
|
106
|
-
}
|
|
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
|
-
declare function FormPreview({ fields, formData }: FormPreviewProps): react_jsx_runtime.JSX.Element;
|
|
123
|
-
|
|
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;
|
|
134
|
+
/** Array of form fields to preview (built-in or plugin-contributed). */
|
|
135
|
+
fields: AnyFormField[];
|
|
136
|
+
/** Form metadata */
|
|
137
|
+
formData?: {
|
|
138
|
+
name?: string;
|
|
139
|
+
slug?: string;
|
|
140
|
+
description?: string;
|
|
141
|
+
};
|
|
352
142
|
}
|
|
143
|
+
export declare function FormPreview({ fields, formData }: FormPreviewProps): JSX.Element;
|
|
353
144
|
interface FormBuilderState {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
145
|
+
/** Form fields array */
|
|
146
|
+
fields: AnyFormField[];
|
|
147
|
+
/** Currently selected field ID (name) */
|
|
148
|
+
selectedFieldId: string | null;
|
|
149
|
+
/** Active tab: builder, preview, settings, or notifications */
|
|
150
|
+
activeTab: "builder" | "preview" | "settings" | "notifications";
|
|
151
|
+
/** Whether form has unsaved changes */
|
|
152
|
+
isDirty: boolean;
|
|
153
|
+
/** Form metadata */
|
|
154
|
+
formData: {
|
|
155
|
+
id?: string;
|
|
156
|
+
name: string;
|
|
157
|
+
slug: string;
|
|
158
|
+
description?: string;
|
|
159
|
+
status: "draft" | "published" | "closed";
|
|
160
|
+
/** What a closed form tells a visitor who reaches it. */
|
|
161
|
+
closedMessage?: string;
|
|
162
|
+
};
|
|
163
|
+
/** Form settings */
|
|
164
|
+
settings: FormSettings;
|
|
165
|
+
/** Email notifications */
|
|
166
|
+
notifications: FormNotification[];
|
|
374
167
|
}
|
|
375
168
|
interface FormBuilderActions {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
169
|
+
/** Set all fields */
|
|
170
|
+
setFields: (fields: AnyFormField[]) => void;
|
|
171
|
+
/** Add a new field */
|
|
172
|
+
addField: (field: AnyFormField, index?: number) => void;
|
|
173
|
+
/** Update a field by name */
|
|
174
|
+
updateField: (fieldName: string, updates: Partial<AnyFormField>) => void;
|
|
175
|
+
/** Delete a field by name */
|
|
176
|
+
deleteField: (fieldName: string) => void;
|
|
177
|
+
/** Move a field from one index to another */
|
|
178
|
+
moveField: (fromIndex: number, toIndex: number) => void;
|
|
179
|
+
/** Duplicate a field */
|
|
180
|
+
duplicateField: (fieldName: string) => void;
|
|
181
|
+
/** Select a field */
|
|
182
|
+
selectField: (fieldName: string | null) => void;
|
|
183
|
+
/** Set active tab */
|
|
184
|
+
setActiveTab: (tab: "builder" | "preview" | "settings" | "notifications") => void;
|
|
185
|
+
/** Update form metadata */
|
|
186
|
+
updateFormData: (updates: Partial<FormBuilderState["formData"]>) => void;
|
|
187
|
+
/** Update form settings */
|
|
188
|
+
updateSettings: (updates: Partial<FormSettings>) => void;
|
|
189
|
+
/** Add a notification */
|
|
190
|
+
addNotification: (notification: FormNotification) => void;
|
|
191
|
+
/** Duplicate a notification (the copy starts disabled) */
|
|
192
|
+
duplicateNotification: (id: string) => void;
|
|
193
|
+
/** Update a notification */
|
|
194
|
+
updateNotification: (id: string, updates: Partial<FormNotification>) => void;
|
|
195
|
+
/** Delete a notification */
|
|
196
|
+
deleteNotification: (id: string) => void;
|
|
197
|
+
/** Seed default notifications into an empty list without dirtying the form */
|
|
198
|
+
seedNotifications: (rules: FormNotification[]) => void;
|
|
199
|
+
/** Mark form as saved (clears dirty flag) */
|
|
200
|
+
markAsSaved: () => void;
|
|
406
201
|
}
|
|
202
|
+
interface FormBuilderContextValue extends FormBuilderState, FormBuilderActions {}
|
|
407
203
|
interface FormBuilderProviderProps {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
204
|
+
/** Initial form data (for editing existing forms) */
|
|
205
|
+
initialData?: {
|
|
206
|
+
id?: string;
|
|
207
|
+
name?: string;
|
|
208
|
+
slug?: string;
|
|
209
|
+
description?: string;
|
|
210
|
+
status?: "draft" | "published" | "closed";
|
|
211
|
+
closedMessage?: string;
|
|
212
|
+
fields?: AnyFormField[];
|
|
213
|
+
settings?: Partial<FormSettings>;
|
|
214
|
+
notifications?: FormNotification[];
|
|
215
|
+
};
|
|
216
|
+
/** Child components */
|
|
217
|
+
children: ReactNode;
|
|
218
|
+
/**
|
|
219
|
+
* The document belongs to someone else right now, so nothing here may change
|
|
220
|
+
* it.
|
|
221
|
+
*
|
|
222
|
+
* Held here rather than at each control because the builder has dozens of
|
|
223
|
+
* them across four tabs, and a rule spelled at every one is a rule one new
|
|
224
|
+
* control forgets. Reading is untouched: the editor still browses fields,
|
|
225
|
+
* switches tabs and opens settings, which is exactly what the strip above
|
|
226
|
+
* offers them.
|
|
227
|
+
*/
|
|
228
|
+
readOnly?: boolean;
|
|
421
229
|
}
|
|
422
|
-
/** Default form settings */
|
|
423
|
-
declare const DEFAULT_SETTINGS: FormSettings;
|
|
424
|
-
/** Create a new
|
|
425
|
-
declare function createNotification(): FormNotification;
|
|
230
|
+
/** Default form settings (the canonical defaults from the settings reader) */
|
|
231
|
+
export declare const DEFAULT_SETTINGS: FormSettings;
|
|
232
|
+
/** Create a new notification rule with default values */
|
|
233
|
+
export declare function createNotification(): FormNotification;
|
|
426
234
|
/**
|
|
427
|
-
* Generate a unique field name
|
|
235
|
+
* Generate a readable unique field name: the type itself for the first
|
|
236
|
+
* field of that type, then a numeric suffix (`email`, `email_2`, ...).
|
|
237
|
+
* Names key submission data, so they should read like keys a developer
|
|
238
|
+
* would have chosen, not timestamps.
|
|
428
239
|
*/
|
|
429
|
-
declare function generateFieldName(type:
|
|
240
|
+
export declare function generateFieldName(type: FormFieldTypeId, existingNames?: readonly string[]): string;
|
|
430
241
|
/**
|
|
431
|
-
* Generate a human-readable label from field type
|
|
242
|
+
* Generate a human-readable label from field type, using the shared catalog
|
|
243
|
+
* so a new field's default label matches what the picker called the type. A
|
|
244
|
+
* plugin type not in the built-in catalog falls back to a title-cased id.
|
|
432
245
|
*/
|
|
433
|
-
declare function generateFieldLabel(type:
|
|
246
|
+
export declare function generateFieldLabel(type: FormFieldTypeId): string;
|
|
434
247
|
/**
|
|
435
248
|
* Create a new field from a field type with default values.
|
|
436
249
|
*/
|
|
437
|
-
declare function createFieldFromType(type:
|
|
250
|
+
export declare function createFieldFromType(type: FormFieldTypeId, existingNames?: readonly string[]): AnyFormField;
|
|
438
251
|
/**
|
|
439
252
|
* FormBuilderProvider - Provides form builder state to child components
|
|
440
253
|
*
|
|
@@ -448,7 +261,7 @@ declare function createFieldFromType(type: FormFieldType): FormField;
|
|
|
448
261
|
* </FormBuilderProvider>
|
|
449
262
|
* ```
|
|
450
263
|
*/
|
|
451
|
-
declare function FormBuilderProvider({ initialData, children, }: FormBuilderProviderProps):
|
|
264
|
+
export declare function FormBuilderProvider({ initialData, children, readOnly }: FormBuilderProviderProps): JSX.Element;
|
|
452
265
|
/**
|
|
453
266
|
* useFormBuilder - Access form builder context
|
|
454
267
|
*
|
|
@@ -476,7 +289,7 @@ declare function FormBuilderProvider({ initialData, children, }: FormBuilderProv
|
|
|
476
289
|
* }
|
|
477
290
|
* ```
|
|
478
291
|
*/
|
|
479
|
-
declare function useFormBuilder(): FormBuilderContextValue;
|
|
292
|
+
export declare function useFormBuilder(): FormBuilderContextValue;
|
|
480
293
|
/**
|
|
481
294
|
* useOptionalFormBuilder - Access form builder context safely
|
|
482
295
|
*
|
|
@@ -485,63 +298,47 @@ declare function useFormBuilder(): FormBuilderContextValue;
|
|
|
485
298
|
*
|
|
486
299
|
* @returns Form builder context value or null
|
|
487
300
|
*/
|
|
488
|
-
declare function useOptionalFormBuilder(): FormBuilderContextValue | null;
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
301
|
+
export declare function useOptionalFormBuilder(): FormBuilderContextValue | null;
|
|
302
|
+
interface SpamDefaults {
|
|
303
|
+
honeypot?: boolean;
|
|
304
|
+
recaptchaEnabled?: boolean;
|
|
305
|
+
}
|
|
306
|
+
interface FormSettingsTabProps {
|
|
307
|
+
/** Plugin-level spam defaults (from builder-config); null while loading. */
|
|
308
|
+
spamDefaults: SpamDefaults | null;
|
|
309
|
+
/**
|
|
310
|
+
* Collections a form may redirect to (from builder-config); null while
|
|
311
|
+
* loading. Empty means the site configured none, and the option is not
|
|
312
|
+
* offered — choosing it could only ever produce a form with no destination.
|
|
313
|
+
*/
|
|
314
|
+
redirectCollections: string[] | null;
|
|
315
|
+
/**
|
|
316
|
+
* The configuration request failed, as distinct from returning nothing. An
|
|
317
|
+
* empty list is a valid answer; a failure is not an answer at all, and
|
|
318
|
+
* saying "no collection is configured" on a 403 states something false.
|
|
319
|
+
*/
|
|
320
|
+
redirectConfigFailed: boolean;
|
|
321
|
+
}
|
|
322
|
+
export declare function FormSettingsTab({ spamDefaults, redirectCollections, redirectConfigFailed }: FormSettingsTabProps): React.JSX.Element;
|
|
323
|
+
/** Host-level notification defaults surfaced by the builder-config route. */
|
|
324
|
+
interface NotificationDefaults {
|
|
325
|
+
defaultFrom?: string;
|
|
326
|
+
defaultToEmail?: string;
|
|
327
|
+
}
|
|
328
|
+
interface FormNotificationsTabProps {
|
|
329
|
+
/** `null` while the builder-config request is still settling. */
|
|
330
|
+
defaults: NotificationDefaults | null;
|
|
331
|
+
}
|
|
500
332
|
/**
|
|
501
|
-
* FormNotificationsTab -
|
|
333
|
+
* FormNotificationsTab - the form's notification rules.
|
|
502
334
|
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
* template rather than duplicating provider credentials.
|
|
335
|
+
* Each rule references an existing email provider and template rather than
|
|
336
|
+
* duplicating provider credentials or embedding a second template editor.
|
|
506
337
|
*/
|
|
507
|
-
declare function FormNotificationsTab():
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Form Builder Admin Components
|
|
511
|
-
*
|
|
512
|
-
* Entry point for admin UI components used by the Nextly admin panel.
|
|
513
|
-
* These components are referenced via component paths in collection configs.
|
|
514
|
-
*
|
|
515
|
-
* Component paths use the format: "@nextlyhq/plugin-form-builder/admin#ExportName"
|
|
516
|
-
*
|
|
517
|
-
* ## Auto-Registration
|
|
518
|
-
*
|
|
519
|
-
* This module automatically registers its components with the admin panel
|
|
520
|
-
* when imported. No manual registration is required - just add the plugin
|
|
521
|
-
* to your Nextly config and the admin will detect and load the components.
|
|
522
|
-
*
|
|
523
|
-
* @module admin
|
|
524
|
-
* @since 0.1.0
|
|
525
|
-
*/
|
|
526
|
-
|
|
338
|
+
export declare function FormNotificationsTab({ defaults }: FormNotificationsTabProps): JSX.Element;
|
|
527
339
|
/** Component path for FormBuilderView */
|
|
528
|
-
declare const FORM_BUILDER_VIEW_PATH: ComponentPath;
|
|
529
|
-
/** Component path for
|
|
530
|
-
declare const
|
|
531
|
-
|
|
532
|
-
|
|
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;
|
|
546
|
-
|
|
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 };
|
|
340
|
+
export declare const FORM_BUILDER_VIEW_PATH: ComponentPath;
|
|
341
|
+
/** Component path for SubmissionsView */
|
|
342
|
+
export declare const SUBMISSIONS_VIEW_PATH: ComponentPath;
|
|
343
|
+
export type { AddFieldDialogProps, FieldCardsProps, FieldEditorProps, FormBuilderActions, FormBuilderContextValue, FormBuilderProviderProps, FormBuilderState, FormBuilderViewProps, FormNotification, FormPreviewProps, FormSettings };
|
|
344
|
+
//# sourceMappingURL=index.d.ts.map
|