payload-dynamic-forms 0.0.0-stage → 0.2.0
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/LICENSE +21 -0
- package/README.md +461 -2
- package/dist/access.d.ts +7 -0
- package/dist/access.js +10 -0
- package/dist/access.js.map +1 -0
- package/dist/collections/attachments.d.ts +6 -0
- package/dist/collections/attachments.js +67 -0
- package/dist/collections/attachments.js.map +1 -0
- package/dist/collections/blocks.d.ts +27 -0
- package/dist/collections/blocks.js +495 -0
- package/dist/collections/blocks.js.map +1 -0
- package/dist/collections/forms.d.ts +3 -0
- package/dist/collections/forms.js +558 -0
- package/dist/collections/forms.js.map +1 -0
- package/dist/collections/overrides.d.ts +7 -0
- package/dist/collections/overrides.js +49 -0
- package/dist/collections/overrides.js.map +1 -0
- package/dist/collections/ruleFields.d.ts +6 -0
- package/dist/collections/ruleFields.js +97 -0
- package/dist/collections/ruleFields.js.map +1 -0
- package/dist/collections/submissions.d.ts +7 -0
- package/dist/collections/submissions.js +225 -0
- package/dist/collections/submissions.js.map +1 -0
- package/dist/delivery/run.d.ts +37 -0
- package/dist/delivery/run.js +234 -0
- package/dist/delivery/run.js.map +1 -0
- package/dist/delivery/webhook.d.ts +41 -0
- package/dist/delivery/webhook.js +120 -0
- package/dist/delivery/webhook.js.map +1 -0
- package/dist/endpoints/public.d.ts +4 -0
- package/dist/endpoints/public.js +27 -0
- package/dist/endpoints/public.js.map +1 -0
- package/dist/endpoints/resend.d.ts +4 -0
- package/dist/endpoints/resend.js +58 -0
- package/dist/endpoints/resend.js.map +1 -0
- package/dist/endpoints/submit.d.ts +4 -0
- package/dist/endpoints/submit.js +320 -0
- package/dist/endpoints/submit.js.map +1 -0
- package/dist/exports/shared.d.ts +13 -0
- package/dist/exports/shared.js +13 -0
- package/dist/exports/shared.js.map +1 -0
- package/dist/formBlock.d.ts +13 -0
- package/dist/formBlock.js +25 -0
- package/dist/formBlock.js.map +1 -0
- package/dist/hooks/resendTick.d.ts +8 -0
- package/dist/hooks/resendTick.js +55 -0
- package/dist/hooks/resendTick.js.map +1 -0
- package/dist/hooks/validateForm.d.ts +8 -0
- package/dist/hooks/validateForm.js +251 -0
- package/dist/hooks/validateForm.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +130 -0
- package/dist/index.js.map +1 -0
- package/dist/security/crypto.d.ts +9 -0
- package/dist/security/crypto.js +54 -0
- package/dist/security/crypto.js.map +1 -0
- package/dist/security/rateLimit.d.ts +13 -0
- package/dist/security/rateLimit.js +28 -0
- package/dist/security/rateLimit.js.map +1 -0
- package/dist/security/request.d.ts +3 -0
- package/dist/security/request.js +13 -0
- package/dist/security/request.js.map +1 -0
- package/dist/security/turnstile.d.ts +28 -0
- package/dist/security/turnstile.js +56 -0
- package/dist/security/turnstile.js.map +1 -0
- package/dist/server/forms.d.ts +73 -0
- package/dist/server/forms.js +215 -0
- package/dist/server/forms.js.map +1 -0
- package/dist/server/resend.d.ts +27 -0
- package/dist/server/resend.js +84 -0
- package/dist/server/resend.js.map +1 -0
- package/dist/shared/answers.d.ts +47 -0
- package/dist/shared/answers.js +282 -0
- package/dist/shared/answers.js.map +1 -0
- package/dist/shared/operators.d.ts +41 -0
- package/dist/shared/operators.js +54 -0
- package/dist/shared/operators.js.map +1 -0
- package/dist/shared/rules.d.ts +58 -0
- package/dist/shared/rules.js +324 -0
- package/dist/shared/rules.js.map +1 -0
- package/dist/shared/steps.d.ts +28 -0
- package/dist/shared/steps.js +109 -0
- package/dist/shared/steps.js.map +1 -0
- package/dist/shared/tokens.d.ts +25 -0
- package/dist/shared/tokens.js +96 -0
- package/dist/shared/tokens.js.map +1 -0
- package/dist/shared/types.d.ts +181 -0
- package/dist/shared/types.js +5 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/shared/whatsapp.d.ts +20 -0
- package/dist/shared/whatsapp.js +26 -0
- package/dist/shared/whatsapp.js.map +1 -0
- package/dist/shared/words.d.ts +9 -0
- package/dist/shared/words.js +41 -0
- package/dist/shared/words.js.map +1 -0
- package/dist/types.d.ts +182 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +114 -4
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import { ruleGroupField } from './ruleFields.js';
|
|
2
|
+
const DATE_TEXT = /^\d{4}-\d{2}-\d{2}$/;
|
|
3
|
+
function dateLimit(name, label) {
|
|
4
|
+
return {
|
|
5
|
+
name,
|
|
6
|
+
type: 'text',
|
|
7
|
+
admin: {
|
|
8
|
+
description: 'YYYY-MM-DD',
|
|
9
|
+
width: '50%'
|
|
10
|
+
},
|
|
11
|
+
label,
|
|
12
|
+
validate: (value)=>!value || typeof value === 'string' && DATE_TEXT.test(value) ? true : 'Use YYYY-MM-DD.'
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** Every word one question shows, grouped and localized. */ export function fieldWordsField() {
|
|
16
|
+
return {
|
|
17
|
+
type: 'collapsible',
|
|
18
|
+
admin: {
|
|
19
|
+
initCollapsed: false
|
|
20
|
+
},
|
|
21
|
+
fields: [
|
|
22
|
+
{
|
|
23
|
+
name: 'words',
|
|
24
|
+
type: 'group',
|
|
25
|
+
fields: [
|
|
26
|
+
{
|
|
27
|
+
name: 'label',
|
|
28
|
+
type: 'text',
|
|
29
|
+
localized: true,
|
|
30
|
+
required: true
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'hint',
|
|
34
|
+
type: 'textarea',
|
|
35
|
+
localized: true
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'placeholder',
|
|
39
|
+
type: 'text',
|
|
40
|
+
localized: true
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'row',
|
|
44
|
+
fields: [
|
|
45
|
+
{
|
|
46
|
+
name: 'errorEmpty',
|
|
47
|
+
type: 'text',
|
|
48
|
+
admin: {
|
|
49
|
+
description: 'Shown when a required answer is missing. Empty: the form\'s "required" words.',
|
|
50
|
+
width: '50%'
|
|
51
|
+
},
|
|
52
|
+
localized: true
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'errorInvalid',
|
|
56
|
+
type: 'text',
|
|
57
|
+
admin: {
|
|
58
|
+
description: 'Shown when the answer is not valid. Empty: the form\'s "invalid" words.',
|
|
59
|
+
width: '50%'
|
|
60
|
+
},
|
|
61
|
+
localized: true
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'rowLabel',
|
|
67
|
+
type: 'text',
|
|
68
|
+
admin: {
|
|
69
|
+
description: 'Label of this answer in messages. Empty: the label.'
|
|
70
|
+
},
|
|
71
|
+
localized: true
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
label: false
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
label: 'Words'
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** Fields every input block has: key, width, required, words, default, link parameter, rules. */ export function baseInputFields(defaultValue = {
|
|
81
|
+
name: 'defaultValue',
|
|
82
|
+
type: 'text',
|
|
83
|
+
localized: true
|
|
84
|
+
}) {
|
|
85
|
+
return [
|
|
86
|
+
{
|
|
87
|
+
type: 'row',
|
|
88
|
+
fields: [
|
|
89
|
+
{
|
|
90
|
+
name: 'fieldKey',
|
|
91
|
+
type: 'text',
|
|
92
|
+
admin: {
|
|
93
|
+
description: 'Stored as lower-case kebab-case. Used in rules and {{tokens}}.',
|
|
94
|
+
width: '50%'
|
|
95
|
+
},
|
|
96
|
+
label: 'Key',
|
|
97
|
+
required: true
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'width',
|
|
101
|
+
type: 'select',
|
|
102
|
+
admin: {
|
|
103
|
+
width: '25%'
|
|
104
|
+
},
|
|
105
|
+
dbName: 'w',
|
|
106
|
+
defaultValue: 'full',
|
|
107
|
+
options: [
|
|
108
|
+
{
|
|
109
|
+
label: 'Full',
|
|
110
|
+
value: 'full'
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
label: 'Half',
|
|
114
|
+
value: 'half'
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'required',
|
|
120
|
+
type: 'checkbox',
|
|
121
|
+
admin: {
|
|
122
|
+
width: '25%'
|
|
123
|
+
},
|
|
124
|
+
defaultValue: false
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
fieldWordsField(),
|
|
129
|
+
{
|
|
130
|
+
type: 'row',
|
|
131
|
+
fields: [
|
|
132
|
+
{
|
|
133
|
+
...defaultValue,
|
|
134
|
+
admin: {
|
|
135
|
+
...defaultValue.admin,
|
|
136
|
+
width: '50%'
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'prefillParam',
|
|
141
|
+
type: 'text',
|
|
142
|
+
admin: {
|
|
143
|
+
description: 'Link parameter that prefills this answer, e.g. need for ?need=…',
|
|
144
|
+
width: '50%'
|
|
145
|
+
},
|
|
146
|
+
label: 'Prefill from link parameter'
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
ruleGroupField()
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
function lengthLimits() {
|
|
154
|
+
return {
|
|
155
|
+
type: 'row',
|
|
156
|
+
fields: [
|
|
157
|
+
{
|
|
158
|
+
name: 'minLength',
|
|
159
|
+
type: 'number',
|
|
160
|
+
admin: {
|
|
161
|
+
width: '50%'
|
|
162
|
+
},
|
|
163
|
+
min: 0
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'maxLength',
|
|
167
|
+
type: 'number',
|
|
168
|
+
admin: {
|
|
169
|
+
width: '50%'
|
|
170
|
+
},
|
|
171
|
+
min: 0
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function choiceFields(sources) {
|
|
177
|
+
const sourceKeys = Object.keys(sources);
|
|
178
|
+
const typedOptions = {
|
|
179
|
+
name: 'options',
|
|
180
|
+
type: 'array',
|
|
181
|
+
admin: sourceKeys.length ? {
|
|
182
|
+
condition: (_data, sibling)=>!sibling?.optionsFrom || sibling.optionsFrom === 'typed'
|
|
183
|
+
} : {},
|
|
184
|
+
fields: [
|
|
185
|
+
{
|
|
186
|
+
type: 'row',
|
|
187
|
+
fields: [
|
|
188
|
+
{
|
|
189
|
+
name: 'label',
|
|
190
|
+
type: 'text',
|
|
191
|
+
admin: {
|
|
192
|
+
width: '50%'
|
|
193
|
+
},
|
|
194
|
+
localized: true,
|
|
195
|
+
required: true
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: 'value',
|
|
199
|
+
type: 'text',
|
|
200
|
+
admin: {
|
|
201
|
+
width: '50%'
|
|
202
|
+
},
|
|
203
|
+
required: true
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
};
|
|
209
|
+
if (!sourceKeys.length) {
|
|
210
|
+
return [
|
|
211
|
+
typedOptions
|
|
212
|
+
];
|
|
213
|
+
}
|
|
214
|
+
const collections = [
|
|
215
|
+
...new Set(sourceKeys.map((key)=>String(sources[key].collection)))
|
|
216
|
+
];
|
|
217
|
+
return [
|
|
218
|
+
{
|
|
219
|
+
name: 'optionsFrom',
|
|
220
|
+
type: 'select',
|
|
221
|
+
dbName: 'of',
|
|
222
|
+
defaultValue: 'typed',
|
|
223
|
+
label: 'Choices from',
|
|
224
|
+
options: [
|
|
225
|
+
{
|
|
226
|
+
label: 'Typed here',
|
|
227
|
+
value: 'typed'
|
|
228
|
+
},
|
|
229
|
+
...sourceKeys.map((key)=>({
|
|
230
|
+
label: key,
|
|
231
|
+
value: key
|
|
232
|
+
}))
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
typedOptions,
|
|
236
|
+
{
|
|
237
|
+
name: 'sourceItems',
|
|
238
|
+
type: 'relationship',
|
|
239
|
+
admin: {
|
|
240
|
+
condition: (_data, sibling)=>Boolean(sibling?.optionsFrom && sibling.optionsFrom !== 'typed'),
|
|
241
|
+
description: 'Pick and order the items. Empty: every published item, in the collection\'s default order.',
|
|
242
|
+
isSortable: true
|
|
243
|
+
},
|
|
244
|
+
filterOptions: ({ relationTo, siblingData })=>{
|
|
245
|
+
const key = siblingData?.optionsFrom;
|
|
246
|
+
const source = key ? sources[key] : undefined;
|
|
247
|
+
return Boolean(source && String(source.collection) === relationTo);
|
|
248
|
+
},
|
|
249
|
+
hasMany: true,
|
|
250
|
+
relationTo: collections
|
|
251
|
+
}
|
|
252
|
+
];
|
|
253
|
+
}
|
|
254
|
+
/** The built-in field blocks, in their admin order. */ export function builtInBlocks(ctx) {
|
|
255
|
+
const input = (slug, singular, extra, defaultValue)=>({
|
|
256
|
+
slug,
|
|
257
|
+
fields: [
|
|
258
|
+
...baseInputFields(defaultValue),
|
|
259
|
+
...extra
|
|
260
|
+
],
|
|
261
|
+
labels: {
|
|
262
|
+
plural: `${singular} fields`,
|
|
263
|
+
singular
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
return {
|
|
267
|
+
checkbox: input('checkbox', 'Checkbox', [], {
|
|
268
|
+
name: 'defaultValue',
|
|
269
|
+
type: 'checkbox',
|
|
270
|
+
defaultValue: false
|
|
271
|
+
}),
|
|
272
|
+
checkboxGroup: input('checkboxGroup', 'Checkbox group', choiceFields(ctx.sources), {
|
|
273
|
+
name: 'defaultValue',
|
|
274
|
+
type: 'text',
|
|
275
|
+
admin: {
|
|
276
|
+
description: 'Values, separated by commas.'
|
|
277
|
+
}
|
|
278
|
+
}),
|
|
279
|
+
date: input('date', 'Date', [
|
|
280
|
+
{
|
|
281
|
+
type: 'row',
|
|
282
|
+
fields: [
|
|
283
|
+
dateLimit('minDate', 'Earliest'),
|
|
284
|
+
dateLimit('maxDate', 'Latest')
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
]),
|
|
288
|
+
email: input('email', 'Email', []),
|
|
289
|
+
fileUpload: input('fileUpload', 'File upload', [
|
|
290
|
+
{
|
|
291
|
+
type: 'row',
|
|
292
|
+
fields: [
|
|
293
|
+
{
|
|
294
|
+
name: 'maxFiles',
|
|
295
|
+
type: 'number',
|
|
296
|
+
admin: {
|
|
297
|
+
width: '50%'
|
|
298
|
+
},
|
|
299
|
+
defaultValue: 1,
|
|
300
|
+
max: 10,
|
|
301
|
+
min: 1
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: 'maxFileSizeMB',
|
|
305
|
+
type: 'number',
|
|
306
|
+
admin: {
|
|
307
|
+
description: 'Empty: the plugin limit.',
|
|
308
|
+
width: '50%'
|
|
309
|
+
},
|
|
310
|
+
min: 0
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
name: 'mimeTypes',
|
|
316
|
+
type: 'select',
|
|
317
|
+
admin: {
|
|
318
|
+
description: 'Empty: every type the plugin allows.'
|
|
319
|
+
},
|
|
320
|
+
dbName: 'mime',
|
|
321
|
+
hasMany: true,
|
|
322
|
+
options: ctx.mimeTypes.map((type)=>({
|
|
323
|
+
label: type,
|
|
324
|
+
value: type
|
|
325
|
+
}))
|
|
326
|
+
}
|
|
327
|
+
], {
|
|
328
|
+
name: 'defaultValue',
|
|
329
|
+
type: 'text',
|
|
330
|
+
admin: {
|
|
331
|
+
hidden: true
|
|
332
|
+
}
|
|
333
|
+
}),
|
|
334
|
+
heading: {
|
|
335
|
+
slug: 'heading',
|
|
336
|
+
fields: [
|
|
337
|
+
{
|
|
338
|
+
name: 'heading',
|
|
339
|
+
type: 'text',
|
|
340
|
+
localized: true,
|
|
341
|
+
required: true
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
name: 'level',
|
|
345
|
+
type: 'select',
|
|
346
|
+
dbName: 'lvl',
|
|
347
|
+
defaultValue: 'h3',
|
|
348
|
+
options: [
|
|
349
|
+
'h2',
|
|
350
|
+
'h3',
|
|
351
|
+
'h4'
|
|
352
|
+
]
|
|
353
|
+
}
|
|
354
|
+
],
|
|
355
|
+
labels: {
|
|
356
|
+
plural: 'Headings',
|
|
357
|
+
singular: 'Heading'
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
helpText: {
|
|
361
|
+
slug: 'helpText',
|
|
362
|
+
fields: [
|
|
363
|
+
{
|
|
364
|
+
name: 'body',
|
|
365
|
+
type: 'textarea',
|
|
366
|
+
localized: true,
|
|
367
|
+
required: true
|
|
368
|
+
}
|
|
369
|
+
],
|
|
370
|
+
labels: {
|
|
371
|
+
plural: 'Help texts',
|
|
372
|
+
singular: 'Help text'
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
number: input('number', 'Number', [
|
|
376
|
+
{
|
|
377
|
+
type: 'row',
|
|
378
|
+
fields: [
|
|
379
|
+
{
|
|
380
|
+
name: 'min',
|
|
381
|
+
type: 'number',
|
|
382
|
+
admin: {
|
|
383
|
+
width: '50%'
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
name: 'max',
|
|
388
|
+
type: 'number',
|
|
389
|
+
admin: {
|
|
390
|
+
width: '50%'
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
]),
|
|
396
|
+
radio: input('radio', 'Radio', choiceFields(ctx.sources)),
|
|
397
|
+
select: input('select', 'Select', choiceFields(ctx.sources)),
|
|
398
|
+
text: input('text', 'Text', [
|
|
399
|
+
lengthLimits()
|
|
400
|
+
]),
|
|
401
|
+
textarea: input('textarea', 'Long text', [
|
|
402
|
+
lengthLimits()
|
|
403
|
+
])
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
export const BUILT_IN_TYPES = [
|
|
407
|
+
'heading',
|
|
408
|
+
'helpText',
|
|
409
|
+
'text',
|
|
410
|
+
'email',
|
|
411
|
+
'textarea',
|
|
412
|
+
'number',
|
|
413
|
+
'date',
|
|
414
|
+
'select',
|
|
415
|
+
'radio',
|
|
416
|
+
'checkbox',
|
|
417
|
+
'checkboxGroup',
|
|
418
|
+
'fileUpload'
|
|
419
|
+
];
|
|
420
|
+
function isPlainObject(value) {
|
|
421
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
422
|
+
}
|
|
423
|
+
/** Deep-merges plain objects; arrays and other values from `patch` replace. */ export function deepMerge(base, patch) {
|
|
424
|
+
if (!isPlainObject(base) || !isPlainObject(patch)) {
|
|
425
|
+
return patch === undefined ? base : patch;
|
|
426
|
+
}
|
|
427
|
+
const out = {
|
|
428
|
+
...base
|
|
429
|
+
};
|
|
430
|
+
for (const [key, value] of Object.entries(patch)){
|
|
431
|
+
out[key] = isPlainObject(out[key]) && isPlainObject(value) ? deepMerge(out[key], value) : value;
|
|
432
|
+
}
|
|
433
|
+
return out;
|
|
434
|
+
}
|
|
435
|
+
function isDefinition(value) {
|
|
436
|
+
return isPlainObject(value) && isPlainObject(value.block) && typeof value.block.slug === 'string';
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Applies the `fields` registry: built-ins on/off (fileUpload off by default), partial blocks
|
|
440
|
+
* merged, new types added with the common input fields. Returns the blocks and the checks for
|
|
441
|
+
* app-defined types.
|
|
442
|
+
*/ export function buildFieldBlocks(registry = {}, ctx) {
|
|
443
|
+
const builtIns = builtInBlocks(ctx);
|
|
444
|
+
const blocks = [];
|
|
445
|
+
const fieldTypes = {};
|
|
446
|
+
for (const type of BUILT_IN_TYPES){
|
|
447
|
+
const entry = registry[type];
|
|
448
|
+
const on = entry === undefined ? type !== 'fileUpload' : entry !== false;
|
|
449
|
+
if (!on) {
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (type === 'fileUpload' && !ctx.attachmentsOn) {
|
|
453
|
+
throw new Error('formsPlugin: the fileUpload field type needs attachments (attachments is false).');
|
|
454
|
+
}
|
|
455
|
+
if (isDefinition(entry)) {
|
|
456
|
+
blocks.push(entry.block);
|
|
457
|
+
fieldTypes[type] = {
|
|
458
|
+
normalize: entry.normalize,
|
|
459
|
+
toText: entry.toText,
|
|
460
|
+
validate: entry.validate
|
|
461
|
+
};
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
blocks.push(isPlainObject(entry) ? deepMerge(builtIns[type], entry) : builtIns[type]);
|
|
465
|
+
}
|
|
466
|
+
for (const [type, entry] of Object.entries(registry)){
|
|
467
|
+
if (BUILT_IN_TYPES.includes(type) || entry === false || entry === true) {
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
if (!isDefinition(entry)) {
|
|
471
|
+
throw new Error(`formsPlugin: field type "${type}" is not built in and needs { block, validate? }.`);
|
|
472
|
+
}
|
|
473
|
+
const own = new Set(entry.block.fields.map((f)=>'name' in f ? f.name : '').filter(Boolean));
|
|
474
|
+
const base = baseInputFields().filter((f)=>!('name' in f) || !own.has(f.name));
|
|
475
|
+
blocks.push({
|
|
476
|
+
...entry.block,
|
|
477
|
+
slug: entry.block.slug || type,
|
|
478
|
+
fields: [
|
|
479
|
+
...base,
|
|
480
|
+
...entry.block.fields
|
|
481
|
+
]
|
|
482
|
+
});
|
|
483
|
+
fieldTypes[entry.block.slug || type] = {
|
|
484
|
+
normalize: entry.normalize,
|
|
485
|
+
toText: entry.toText,
|
|
486
|
+
validate: entry.validate
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
return {
|
|
490
|
+
blocks,
|
|
491
|
+
fieldTypes
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
//# sourceMappingURL=blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/collections/blocks.ts"],"sourcesContent":["import type { Block, Field } from 'payload'\n\nimport type { FieldTypeChecks } from '../shared/types.js'\nimport type { FieldTypeDefinition, FormsPluginOptions, OptionSource } from '../types.js'\n\nimport { ruleGroupField } from './ruleFields.js'\n\nconst DATE_TEXT = /^\\d{4}-\\d{2}-\\d{2}$/\n\nfunction dateLimit(name: string, label: string): Field {\n return {\n name,\n type: 'text',\n admin: { description: 'YYYY-MM-DD', width: '50%' },\n label,\n validate: (value: unknown) =>\n !value || (typeof value === 'string' && DATE_TEXT.test(value)) ? true : 'Use YYYY-MM-DD.',\n }\n}\n\n/** Every word one question shows, grouped and localized. */\nexport function fieldWordsField(): Field {\n return {\n type: 'collapsible',\n admin: { initCollapsed: false },\n fields: [\n {\n name: 'words',\n type: 'group',\n fields: [\n { name: 'label', type: 'text', localized: true, required: true },\n { name: 'hint', type: 'textarea', localized: true },\n { name: 'placeholder', type: 'text', localized: true },\n {\n type: 'row',\n fields: [\n { name: 'errorEmpty', type: 'text', admin: { description: 'Shown when a required answer is missing. Empty: the form\\'s \"required\" words.', width: '50%' }, localized: true },\n { name: 'errorInvalid', type: 'text', admin: { description: 'Shown when the answer is not valid. Empty: the form\\'s \"invalid\" words.', width: '50%' }, localized: true },\n ],\n },\n { name: 'rowLabel', type: 'text', admin: { description: 'Label of this answer in messages. Empty: the label.' }, localized: true },\n ],\n label: false,\n },\n ],\n label: 'Words',\n }\n}\n\n/** Fields every input block has: key, width, required, words, default, link parameter, rules. */\nexport function baseInputFields(defaultValue: Field = { name: 'defaultValue', type: 'text', localized: true }): Field[] {\n return [\n {\n type: 'row',\n fields: [\n {\n name: 'fieldKey',\n type: 'text',\n admin: { description: 'Stored as lower-case kebab-case. Used in rules and {{tokens}}.', width: '50%' },\n label: 'Key',\n required: true,\n },\n {\n name: 'width',\n type: 'select',\n admin: { width: '25%' },\n dbName: 'w',\n defaultValue: 'full',\n options: [\n { label: 'Full', value: 'full' },\n { label: 'Half', value: 'half' },\n ],\n },\n {\n name: 'required',\n type: 'checkbox',\n admin: { width: '25%' },\n defaultValue: false,\n },\n ],\n },\n fieldWordsField(),\n {\n type: 'row',\n fields: [\n { ...defaultValue, admin: { ...(defaultValue.admin as object), width: '50%' } } as Field,\n {\n name: 'prefillParam',\n type: 'text',\n admin: { description: 'Link parameter that prefills this answer, e.g. need for ?need=…', width: '50%' },\n label: 'Prefill from link parameter',\n },\n ],\n },\n ruleGroupField(),\n ]\n}\n\nfunction lengthLimits(): Field {\n return {\n type: 'row',\n fields: [\n { name: 'minLength', type: 'number', admin: { width: '50%' }, min: 0 },\n { name: 'maxLength', type: 'number', admin: { width: '50%' }, min: 0 },\n ],\n }\n}\n\nfunction choiceFields(sources: Record<string, OptionSource>): Field[] {\n const sourceKeys = Object.keys(sources)\n const typedOptions: Field = {\n name: 'options',\n type: 'array',\n admin: sourceKeys.length\n ? { condition: (_data, sibling) => !sibling?.optionsFrom || sibling.optionsFrom === 'typed' }\n : {},\n fields: [\n {\n type: 'row',\n fields: [\n { name: 'label', type: 'text', admin: { width: '50%' }, localized: true, required: true },\n { name: 'value', type: 'text', admin: { width: '50%' }, required: true },\n ],\n },\n ],\n }\n if (!sourceKeys.length) {\n return [typedOptions]\n }\n const collections = [...new Set(sourceKeys.map((key) => String(sources[key].collection)))]\n return [\n {\n name: 'optionsFrom',\n type: 'select',\n dbName: 'of',\n defaultValue: 'typed',\n label: 'Choices from',\n options: [\n { label: 'Typed here', value: 'typed' },\n ...sourceKeys.map((key) => ({ label: key, value: key })),\n ],\n },\n typedOptions,\n {\n name: 'sourceItems',\n type: 'relationship',\n admin: {\n condition: (_data, sibling) => Boolean(sibling?.optionsFrom && sibling.optionsFrom !== 'typed'),\n description: 'Pick and order the items. Empty: every published item, in the collection\\'s default order.',\n isSortable: true,\n },\n filterOptions: ({ relationTo, siblingData }) => {\n const key = (siblingData as { optionsFrom?: string } | undefined)?.optionsFrom\n const source = key ? sources[key] : undefined\n return Boolean(source && String(source.collection) === relationTo)\n },\n hasMany: true,\n relationTo: collections as never,\n },\n ]\n}\n\nexport type BlockContext = {\n mimeTypes: string[]\n sources: Record<string, OptionSource>\n}\n\n/** The built-in field blocks, in their admin order. */\nexport function builtInBlocks(ctx: BlockContext): Record<string, Block> {\n const input = (slug: string, singular: string, extra: Field[], defaultValue?: Field): Block => ({\n slug,\n fields: [...baseInputFields(defaultValue), ...extra],\n labels: { plural: `${singular} fields`, singular },\n })\n return {\n checkbox: input('checkbox', 'Checkbox', [], { name: 'defaultValue', type: 'checkbox', defaultValue: false }),\n checkboxGroup: input('checkboxGroup', 'Checkbox group', choiceFields(ctx.sources), {\n name: 'defaultValue',\n type: 'text',\n admin: { description: 'Values, separated by commas.' },\n }),\n date: input('date', 'Date', [{ type: 'row', fields: [dateLimit('minDate', 'Earliest'), dateLimit('maxDate', 'Latest')] }]),\n email: input('email', 'Email', []),\n fileUpload: input(\n 'fileUpload',\n 'File upload',\n [\n {\n type: 'row',\n fields: [\n { name: 'maxFiles', type: 'number', admin: { width: '50%' }, defaultValue: 1, max: 10, min: 1 },\n { name: 'maxFileSizeMB', type: 'number', admin: { description: 'Empty: the plugin limit.', width: '50%' }, min: 0 },\n ],\n },\n {\n name: 'mimeTypes',\n type: 'select',\n admin: { description: 'Empty: every type the plugin allows.' },\n dbName: 'mime',\n hasMany: true,\n options: ctx.mimeTypes.map((type) => ({ label: type, value: type })),\n },\n ],\n { name: 'defaultValue', type: 'text', admin: { hidden: true } },\n ),\n heading: {\n slug: 'heading',\n fields: [\n { name: 'heading', type: 'text', localized: true, required: true },\n {\n name: 'level',\n type: 'select',\n dbName: 'lvl',\n defaultValue: 'h3',\n options: ['h2', 'h3', 'h4'],\n },\n ],\n labels: { plural: 'Headings', singular: 'Heading' },\n },\n helpText: {\n slug: 'helpText',\n fields: [{ name: 'body', type: 'textarea', localized: true, required: true }],\n labels: { plural: 'Help texts', singular: 'Help text' },\n },\n number: input('number', 'Number', [\n {\n type: 'row',\n fields: [\n { name: 'min', type: 'number', admin: { width: '50%' } },\n { name: 'max', type: 'number', admin: { width: '50%' } },\n ],\n },\n ]),\n radio: input('radio', 'Radio', choiceFields(ctx.sources)),\n select: input('select', 'Select', choiceFields(ctx.sources)),\n text: input('text', 'Text', [lengthLimits()]),\n textarea: input('textarea', 'Long text', [lengthLimits()]),\n }\n}\n\nexport const BUILT_IN_TYPES = [\n 'heading',\n 'helpText',\n 'text',\n 'email',\n 'textarea',\n 'number',\n 'date',\n 'select',\n 'radio',\n 'checkbox',\n 'checkboxGroup',\n 'fileUpload',\n] as const\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype\n}\n\n/** Deep-merges plain objects; arrays and other values from `patch` replace. */\nexport function deepMerge<T>(base: T, patch: unknown): T {\n if (!isPlainObject(base) || !isPlainObject(patch)) {\n return (patch === undefined ? base : patch) as T\n }\n const out: Record<string, unknown> = { ...base }\n for (const [key, value] of Object.entries(patch)) {\n out[key] = isPlainObject(out[key]) && isPlainObject(value) ? deepMerge(out[key], value) : value\n }\n return out as T\n}\n\nfunction isDefinition(value: unknown): value is FieldTypeDefinition {\n return isPlainObject(value) && isPlainObject(value.block) && typeof value.block.slug === 'string'\n}\n\n/**\n * Applies the `fields` registry: built-ins on/off (fileUpload off by default), partial blocks\n * merged, new types added with the common input fields. Returns the blocks and the checks for\n * app-defined types.\n */\nexport function buildFieldBlocks(\n registry: FormsPluginOptions['fields'] = {},\n ctx: { attachmentsOn: boolean } & BlockContext,\n): { blocks: Block[]; fieldTypes: Record<string, FieldTypeChecks> } {\n const builtIns = builtInBlocks(ctx)\n const blocks: Block[] = []\n const fieldTypes: Record<string, FieldTypeChecks> = {}\n\n for (const type of BUILT_IN_TYPES) {\n const entry = registry[type]\n const on = entry === undefined ? type !== 'fileUpload' : entry !== false\n if (!on) {\n continue\n }\n if (type === 'fileUpload' && !ctx.attachmentsOn) {\n throw new Error('formsPlugin: the fileUpload field type needs attachments (attachments is false).')\n }\n if (isDefinition(entry)) {\n blocks.push(entry.block)\n fieldTypes[type] = { normalize: entry.normalize, toText: entry.toText, validate: entry.validate }\n continue\n }\n blocks.push(isPlainObject(entry) ? deepMerge(builtIns[type], entry) : builtIns[type])\n }\n\n for (const [type, entry] of Object.entries(registry)) {\n if ((BUILT_IN_TYPES as readonly string[]).includes(type) || entry === false || entry === true) {\n continue\n }\n if (!isDefinition(entry)) {\n throw new Error(`formsPlugin: field type \"${type}\" is not built in and needs { block, validate? }.`)\n }\n const own = new Set(entry.block.fields.map((f) => ('name' in f ? f.name : '')).filter(Boolean))\n const base = baseInputFields().filter((f) => !('name' in f) || !own.has(f.name))\n blocks.push({ ...entry.block, slug: entry.block.slug || type, fields: [...base, ...entry.block.fields] })\n fieldTypes[entry.block.slug || type] = {\n normalize: entry.normalize,\n toText: entry.toText,\n validate: entry.validate,\n }\n }\n return { blocks, fieldTypes }\n}\n"],"names":["ruleGroupField","DATE_TEXT","dateLimit","name","label","type","admin","description","width","validate","value","test","fieldWordsField","initCollapsed","fields","localized","required","baseInputFields","defaultValue","dbName","options","lengthLimits","min","choiceFields","sources","sourceKeys","Object","keys","typedOptions","length","condition","_data","sibling","optionsFrom","collections","Set","map","key","String","collection","Boolean","isSortable","filterOptions","relationTo","siblingData","source","undefined","hasMany","builtInBlocks","ctx","input","slug","singular","extra","labels","plural","checkbox","checkboxGroup","date","email","fileUpload","max","mimeTypes","hidden","heading","helpText","number","radio","select","text","textarea","BUILT_IN_TYPES","isPlainObject","Array","isArray","getPrototypeOf","prototype","deepMerge","base","patch","out","entries","isDefinition","block","buildFieldBlocks","registry","builtIns","blocks","fieldTypes","entry","on","attachmentsOn","Error","push","normalize","toText","includes","own","f","filter","has"],"mappings":"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"}
|