@10x-media/form-builder 0.1.0-beta.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/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README.md +1434 -0
- package/dist/constants-B-BUfetP.d.ts +288 -0
- package/dist/exports/client.d.ts +21 -0
- package/dist/exports/client.js +320 -0
- package/dist/exports/client.js.map +1 -0
- package/dist/exports/i18n.d.ts +138 -0
- package/dist/exports/i18n.js +3 -0
- package/dist/exports/react.d.ts +550 -0
- package/dist/exports/react.js +1564 -0
- package/dist/exports/react.js.map +1 -0
- package/dist/exports/rsc.d.ts +16 -0
- package/dist/exports/rsc.js +55 -0
- package/dist/exports/rsc.js.map +1 -0
- package/dist/exports/types.d.ts +5 -0
- package/dist/exports/types.js +1 -0
- package/dist/fieldTypes-B8jkNRob.d.ts +188 -0
- package/dist/fieldTypes-CzhhJXjg.js +88 -0
- package/dist/fieldTypes-CzhhJXjg.js.map +1 -0
- package/dist/index-DfFYGbVF.d.ts +481 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1921 -0
- package/dist/index.js.map +1 -0
- package/dist/keys-N5xGiUsh.js +132 -0
- package/dist/keys-N5xGiUsh.js.map +1 -0
- package/dist/registry-CoCyhtvB.js +282 -0
- package/dist/registry-CoCyhtvB.js.map +1 -0
- package/dist/resolver-OeQyVH2N.js +665 -0
- package/dist/resolver-OeQyVH2N.js.map +1 -0
- package/dist/translations-edMqq_2e.js +152 -0
- package/dist/translations-edMqq_2e.js.map +1 -0
- package/dist/types-DsJ_6kGJ.d.ts +23 -0
- package/package.json +125 -0
- package/styles/form-builder.css +108 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { t as keys } from "./keys-N5xGiUsh.js";
|
|
2
|
+
//#region src/translations/server.ts
|
|
3
|
+
/**
|
|
4
|
+
* Adapt a Payload request `t` (typed to core keys only) so it also accepts this
|
|
5
|
+
* plugin's keys. They are registered at config time and resolve at runtime; the
|
|
6
|
+
* cast only widens the compile-time key domain.
|
|
7
|
+
*/
|
|
8
|
+
const asTranslate = (t) => t;
|
|
9
|
+
/**
|
|
10
|
+
* Adapt a Payload request `t` to the engine-facing `Translate` the submission core and field-type
|
|
11
|
+
* `format`/`validate` speak (any key string). Same runtime function as `asTranslate`; this widening
|
|
12
|
+
* accepts arbitrary keys because the engine resolves both this plugin's and a host's registered keys.
|
|
13
|
+
*/
|
|
14
|
+
const asFieldTranslate = (t) => t;
|
|
15
|
+
/** A field `label`/`description` backed by a typed key, resolved per request. */
|
|
16
|
+
const labelForKey = (key) => ({ t }) => asTranslate(t)(key);
|
|
17
|
+
/**
|
|
18
|
+
* A `label`/`description` from an arbitrary key string (a field-type-supplied label, which may be a
|
|
19
|
+
* host-registered key or a literal; Payload's `t` returns the input unchanged when unknown). Distinct
|
|
20
|
+
* from `labelForKey`, which constrains to this plugin's typed keys.
|
|
21
|
+
*/
|
|
22
|
+
const labelFor = (key) => ({ t }) => asTranslate(t)(key);
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/fields/defineFormField.ts
|
|
25
|
+
/**
|
|
26
|
+
* Define a form field type once and get every facet from one object: a Payload `Field[]` for
|
|
27
|
+
* authoring, an isomorphic `validate`, a localized `format`, and a renderer ref. Built-ins use
|
|
28
|
+
* this same primitive, so custom field types are never second-class. The `value` kind drives the
|
|
29
|
+
* typed value threaded into `validate`/`format`; the optional second generic types the config.
|
|
30
|
+
*/
|
|
31
|
+
const defineFormField = (definition) => definition;
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/fields/builtin/calculation.ts
|
|
34
|
+
const calculationField = defineFormField({
|
|
35
|
+
type: "calculation",
|
|
36
|
+
label: keys.fieldTypeCalculation,
|
|
37
|
+
value: "number",
|
|
38
|
+
config: [{
|
|
39
|
+
name: "expression",
|
|
40
|
+
type: "json",
|
|
41
|
+
label: labelFor(keys.configExpression)
|
|
42
|
+
}, {
|
|
43
|
+
name: "calcDisplay",
|
|
44
|
+
type: "checkbox",
|
|
45
|
+
defaultValue: true,
|
|
46
|
+
label: labelFor(keys.configCalcDisplay)
|
|
47
|
+
}],
|
|
48
|
+
format: ({ value }) => value == null ? "" : String(value)
|
|
49
|
+
});
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/fields/builtin/checkbox.ts
|
|
52
|
+
const checkboxField = defineFormField({
|
|
53
|
+
type: "checkbox",
|
|
54
|
+
label: keys.fieldTypeCheckbox,
|
|
55
|
+
value: "boolean",
|
|
56
|
+
format: ({ value, t }) => value ? t(keys.formatYes) : t(keys.formatNo)
|
|
57
|
+
});
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/fields/builtin/consent.ts
|
|
60
|
+
const consentField = defineFormField({
|
|
61
|
+
type: "consent",
|
|
62
|
+
label: keys.fieldTypeConsent,
|
|
63
|
+
value: "boolean",
|
|
64
|
+
config: [
|
|
65
|
+
{
|
|
66
|
+
name: "statement",
|
|
67
|
+
type: "text",
|
|
68
|
+
label: labelFor(keys.consentConfigStatement)
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "source",
|
|
72
|
+
type: "select",
|
|
73
|
+
defaultValue: "static",
|
|
74
|
+
label: labelFor(keys.consentConfigSource),
|
|
75
|
+
options: [{
|
|
76
|
+
label: labelFor(keys.consentSourceStatic),
|
|
77
|
+
value: "static"
|
|
78
|
+
}, {
|
|
79
|
+
label: labelFor(keys.consentSourcePageReference),
|
|
80
|
+
value: "pageReference"
|
|
81
|
+
}]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "sourceConfig",
|
|
85
|
+
type: "group",
|
|
86
|
+
label: labelFor(keys.consentConfigSourceConfig),
|
|
87
|
+
fields: [
|
|
88
|
+
{
|
|
89
|
+
name: "label",
|
|
90
|
+
type: "text",
|
|
91
|
+
label: labelFor(keys.consentConfigLabel)
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "url",
|
|
95
|
+
type: "text",
|
|
96
|
+
label: labelFor(keys.consentConfigUrl)
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "version",
|
|
100
|
+
type: "text",
|
|
101
|
+
label: labelFor(keys.consentConfigVersion)
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "relationTo",
|
|
105
|
+
type: "text",
|
|
106
|
+
label: labelFor(keys.consentConfigRelationTo)
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "docId",
|
|
110
|
+
type: "text",
|
|
111
|
+
label: labelFor(keys.consentConfigDocId)
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "urlField",
|
|
115
|
+
type: "text",
|
|
116
|
+
defaultValue: "slug",
|
|
117
|
+
label: labelFor(keys.consentConfigUrlField)
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "captureVersion",
|
|
121
|
+
type: "checkbox",
|
|
122
|
+
label: labelFor(keys.consentConfigCaptureVersion)
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "optional",
|
|
128
|
+
type: "checkbox",
|
|
129
|
+
label: labelFor(keys.consentConfigOptional)
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
validate: ({ value, config, t }) => {
|
|
133
|
+
if (!(config.optional === true) && value !== true) return t(keys.validationRequired);
|
|
134
|
+
return true;
|
|
135
|
+
},
|
|
136
|
+
format: ({ value, t }) => t(value === true ? keys.formatYes : keys.formatNo)
|
|
137
|
+
});
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/fields/builtin/email.ts
|
|
140
|
+
const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
141
|
+
const emailField = defineFormField({
|
|
142
|
+
type: "email",
|
|
143
|
+
label: keys.fieldTypeEmail,
|
|
144
|
+
value: "text",
|
|
145
|
+
validate: ({ value, t }) => {
|
|
146
|
+
if (value == null || value === "") return true;
|
|
147
|
+
return EMAIL_PATTERN.test(value) ? true : t(keys.validationEmail);
|
|
148
|
+
},
|
|
149
|
+
format: ({ value }) => value == null ? "" : String(value)
|
|
150
|
+
});
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/fields/builtin/file.ts
|
|
153
|
+
const isFileRef = (value) => typeof value === "object" && value !== null && "filename" in value;
|
|
154
|
+
/**
|
|
155
|
+
* The `file` field type. Its stored value is a server-captured {@link FileRef}; the client only ever submits
|
|
156
|
+
* the upload id, and `runSubmission` re-reads filename/mimeType/filesize from the upload doc at the trust
|
|
157
|
+
* boundary (see `captureFileRef`). The intrinsic validator is intentionally a no-op: MIME/size/existence are
|
|
158
|
+
* enforced authoritatively server-side against the stored doc, never against client metadata. `relationTo`,
|
|
159
|
+
* `mimeTypes`, and `maxSize` persist on the block so the capture can enforce them.
|
|
160
|
+
*/
|
|
161
|
+
const fileField = defineFormField({
|
|
162
|
+
type: "file",
|
|
163
|
+
label: keys.fieldTypeFile,
|
|
164
|
+
value: "file",
|
|
165
|
+
config: [
|
|
166
|
+
{
|
|
167
|
+
name: "relationTo",
|
|
168
|
+
type: "text",
|
|
169
|
+
label: labelFor(keys.fileConfigRelationTo)
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "mimeTypes",
|
|
173
|
+
type: "text",
|
|
174
|
+
hasMany: true,
|
|
175
|
+
label: labelFor(keys.fileConfigMimeTypes)
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "maxSize",
|
|
179
|
+
type: "number",
|
|
180
|
+
label: labelFor(keys.fileConfigMaxSize)
|
|
181
|
+
}
|
|
182
|
+
],
|
|
183
|
+
format: ({ value }) => isFileRef(value) ? value.filename : ""
|
|
184
|
+
});
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/fields/builtin/number.ts
|
|
187
|
+
const numberField = defineFormField({
|
|
188
|
+
type: "number",
|
|
189
|
+
label: keys.fieldTypeNumber,
|
|
190
|
+
value: "number",
|
|
191
|
+
validate: ({ value, t }) => {
|
|
192
|
+
if (value == null) return true;
|
|
193
|
+
return Number.isFinite(value) ? true : t(keys.validationNumber);
|
|
194
|
+
},
|
|
195
|
+
format: ({ value }) => value == null ? "" : String(value)
|
|
196
|
+
});
|
|
197
|
+
//#endregion
|
|
198
|
+
//#region src/fields/builtin/select.ts
|
|
199
|
+
const selectField = defineFormField({
|
|
200
|
+
type: "select",
|
|
201
|
+
label: keys.fieldTypeSelect,
|
|
202
|
+
value: "text",
|
|
203
|
+
conditionType: "select",
|
|
204
|
+
config: [{
|
|
205
|
+
name: "options",
|
|
206
|
+
type: "array",
|
|
207
|
+
label: labelFor(keys.configOptions),
|
|
208
|
+
labels: {
|
|
209
|
+
singular: labelFor(keys.configOption),
|
|
210
|
+
plural: labelFor(keys.configOptions)
|
|
211
|
+
},
|
|
212
|
+
fields: [{
|
|
213
|
+
name: "label",
|
|
214
|
+
type: "text",
|
|
215
|
+
required: true,
|
|
216
|
+
label: labelFor(keys.configOptionLabel)
|
|
217
|
+
}, {
|
|
218
|
+
name: "value",
|
|
219
|
+
type: "text",
|
|
220
|
+
required: true,
|
|
221
|
+
label: labelFor(keys.configOptionValue)
|
|
222
|
+
}]
|
|
223
|
+
}],
|
|
224
|
+
validate: ({ value, config, t }) => {
|
|
225
|
+
if (value == null || value === "") return true;
|
|
226
|
+
const options = config.options ?? [];
|
|
227
|
+
if (options.length === 0) return true;
|
|
228
|
+
return options.some((option) => option.value === value) ? true : t(keys.validationSelect);
|
|
229
|
+
},
|
|
230
|
+
format: ({ value, optionLabels }) => {
|
|
231
|
+
if (value == null || value === "") return "";
|
|
232
|
+
return optionLabels?.[value] ?? String(value);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region src/fields/builtin/index.ts
|
|
237
|
+
const defaultFieldDefinitions = [
|
|
238
|
+
defineFormField({
|
|
239
|
+
type: "text",
|
|
240
|
+
label: keys.fieldTypeText,
|
|
241
|
+
value: "text",
|
|
242
|
+
format: ({ value }) => value == null ? "" : String(value)
|
|
243
|
+
}),
|
|
244
|
+
defineFormField({
|
|
245
|
+
type: "textarea",
|
|
246
|
+
label: keys.fieldTypeTextarea,
|
|
247
|
+
value: "text",
|
|
248
|
+
format: ({ value }) => value == null ? "" : String(value)
|
|
249
|
+
}),
|
|
250
|
+
emailField,
|
|
251
|
+
numberField,
|
|
252
|
+
selectField,
|
|
253
|
+
checkboxField,
|
|
254
|
+
calculationField,
|
|
255
|
+
consentField,
|
|
256
|
+
fileField
|
|
257
|
+
];
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/fields/registry.ts
|
|
260
|
+
const buildRegistry = (definitions) => {
|
|
261
|
+
const registry = /* @__PURE__ */ new Map();
|
|
262
|
+
for (const definition of definitions) registry.set(definition.type, definition);
|
|
263
|
+
return registry;
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* Resolve the active field-type registry from the built-in defaults and the plugin `fields` option.
|
|
267
|
+
* `false` removes a type, `true` keeps the default, an object adds a new type or replaces an existing
|
|
268
|
+
* one (its `type` is forced to the config key so an override cannot rename the slot).
|
|
269
|
+
*/
|
|
270
|
+
const resolveFieldTypes = (defaults, config = {}) => {
|
|
271
|
+
const registry = buildRegistry(defaults);
|
|
272
|
+
for (const [type, option] of Object.entries(config)) if (option === false) registry.delete(type);
|
|
273
|
+
else if (option === true) {} else registry.set(type, {
|
|
274
|
+
...option,
|
|
275
|
+
type
|
|
276
|
+
});
|
|
277
|
+
return registry;
|
|
278
|
+
};
|
|
279
|
+
//#endregion
|
|
280
|
+
export { asFieldTranslate as a, labelForKey as c, defineFormField as i, resolveFieldTypes as n, asTranslate as o, defaultFieldDefinitions as r, labelFor as s, buildRegistry as t };
|
|
281
|
+
|
|
282
|
+
//# sourceMappingURL=registry-CoCyhtvB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-CoCyhtvB.js","names":[],"sources":["../src/translations/server.ts","../src/fields/defineFormField.ts","../src/fields/builtin/calculation.ts","../src/fields/builtin/checkbox.ts","../src/fields/builtin/consent.ts","../src/fields/builtin/email.ts","../src/fields/builtin/file.ts","../src/fields/builtin/number.ts","../src/fields/builtin/select.ts","../src/fields/builtin/text.ts","../src/fields/builtin/textarea.ts","../src/fields/builtin/index.ts","../src/fields/registry.ts"],"sourcesContent":["import type { LabelFunction } from 'payload'\n\nimport type { Translate as FieldTranslate } from '../fields/types'\nimport type { TranslationKey } from './keys'\n\n/** A `t`-like function narrowed to this plugin's typed keys. */\ntype Translate = (key: TranslationKey) => string\n\n/**\n * Adapt a Payload request `t` (typed to core keys only) so it also accepts this\n * plugin's keys. They are registered at config time and resolve at runtime; the\n * cast only widens the compile-time key domain.\n */\nexport const asTranslate = (t: unknown): Translate => t as Translate\n\n/**\n * Adapt a Payload request `t` to the engine-facing `Translate` the submission core and field-type\n * `format`/`validate` speak (any key string). Same runtime function as `asTranslate`; this widening\n * accepts arbitrary keys because the engine resolves both this plugin's and a host's registered keys.\n */\nexport const asFieldTranslate = (t: unknown): FieldTranslate => t as FieldTranslate\n\n/** A field `label`/`description` backed by a typed key, resolved per request. */\nexport const labelForKey =\n\t(key: TranslationKey): LabelFunction =>\n\t({ t }) =>\n\t\tasTranslate(t)(key)\n\n/**\n * A `label`/`description` from an arbitrary key string (a field-type-supplied label, which may be a\n * host-registered key or a literal; Payload's `t` returns the input unchanged when unknown). Distinct\n * from `labelForKey`, which constrains to this plugin's typed keys.\n */\nexport const labelFor =\n\t(key: string): LabelFunction =>\n\t({ t }) =>\n\t\tasTranslate(t)(key as TranslationKey)\n","import type { FormFieldConfigValues, FormFieldDefinition, FormFieldValueKind } from './types'\n\n/**\n * Define a form field type once and get every facet from one object: a Payload `Field[]` for\n * authoring, an isomorphic `validate`, a localized `format`, and a renderer ref. Built-ins use\n * this same primitive, so custom field types are never second-class. The `value` kind drives the\n * typed value threaded into `validate`/`format`; the optional second generic types the config.\n */\nexport const defineFormField = <\n\tK extends FormFieldValueKind,\n\tTConfig extends FormFieldConfigValues = FormFieldConfigValues,\n>(\n\tdefinition: FormFieldDefinition<K, TConfig>\n): FormFieldDefinition<K, TConfig> => definition\n","import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\n\nexport const calculationField = defineFormField<'number'>({\n\ttype: 'calculation',\n\tlabel: keys.fieldTypeCalculation,\n\tvalue: 'number',\n\tconfig: [\n\t\t{ name: 'expression', type: 'json', label: labelFor(keys.configExpression) },\n\t\t{\n\t\t\tname: 'calcDisplay',\n\t\t\ttype: 'checkbox',\n\t\t\tdefaultValue: true,\n\t\t\tlabel: labelFor(keys.configCalcDisplay),\n\t\t},\n\t],\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n","import { keys } from '../../translations/keys'\nimport { defineFormField } from '../defineFormField'\n\nexport const checkboxField = defineFormField<'boolean'>({\n\ttype: 'checkbox',\n\tlabel: keys.fieldTypeCheckbox,\n\tvalue: 'boolean',\n\tformat: ({ value, t }) => (value ? t(keys.formatYes) : t(keys.formatNo)),\n})\n","import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\n\ntype ConsentConfig = {\n\tstatement?: string\n\tsource?: string\n\tsourceConfig?: {\n\t\tlabel?: string\n\t\turl?: string\n\t\tversion?: string\n\t\trelationTo?: string\n\t\tdocId?: string\n\t\turlField?: string\n\t\tcaptureVersion?: boolean\n\t}\n\toptional?: boolean\n}\n\nexport const consentField = defineFormField<'boolean', ConsentConfig>({\n\ttype: 'consent',\n\tlabel: keys.fieldTypeConsent,\n\tvalue: 'boolean',\n\tconfig: [\n\t\t{ name: 'statement', type: 'text', label: labelFor(keys.consentConfigStatement) },\n\t\t{\n\t\t\tname: 'source',\n\t\t\ttype: 'select',\n\t\t\tdefaultValue: 'static',\n\t\t\tlabel: labelFor(keys.consentConfigSource),\n\t\t\toptions: [\n\t\t\t\t{ label: labelFor(keys.consentSourceStatic), value: 'static' },\n\t\t\t\t{ label: labelFor(keys.consentSourcePageReference), value: 'pageReference' },\n\t\t\t],\n\t\t},\n\t\t// The source params are nested so their names (label/url/...) cannot collide with the shared field config (name/label/required/...) that buildFieldBlocks prepends. The source's `resolve` receives this group object as its config.\n\t\t{\n\t\t\tname: 'sourceConfig',\n\t\t\ttype: 'group',\n\t\t\tlabel: labelFor(keys.consentConfigSourceConfig),\n\t\t\tfields: [\n\t\t\t\t{ name: 'label', type: 'text', label: labelFor(keys.consentConfigLabel) },\n\t\t\t\t{ name: 'url', type: 'text', label: labelFor(keys.consentConfigUrl) },\n\t\t\t\t{ name: 'version', type: 'text', label: labelFor(keys.consentConfigVersion) },\n\t\t\t\t{ name: 'relationTo', type: 'text', label: labelFor(keys.consentConfigRelationTo) },\n\t\t\t\t{ name: 'docId', type: 'text', label: labelFor(keys.consentConfigDocId) },\n\t\t\t\t{\n\t\t\t\t\tname: 'urlField',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tdefaultValue: 'slug',\n\t\t\t\t\tlabel: labelFor(keys.consentConfigUrlField),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'captureVersion',\n\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\tlabel: labelFor(keys.consentConfigCaptureVersion),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t// Consent is required-to-submit by default (compliance); check `optional` for marketing-style opt-ins.\n\t\t{ name: 'optional', type: 'checkbox', label: labelFor(keys.consentConfigOptional) },\n\t],\n\tvalidate: ({ value, config, t }) => {\n\t\tconst optional = (config as ConsentConfig).optional === true\n\t\tif (!optional && value !== true) {\n\t\t\treturn t(keys.validationRequired)\n\t\t}\n\t\treturn true\n\t},\n\tformat: ({ value, t }) => t(value === true ? keys.formatYes : keys.formatNo),\n})\n","import { keys } from '../../translations/keys'\nimport { defineFormField } from '../defineFormField'\n\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\nexport const emailField = defineFormField<'text'>({\n\ttype: 'email',\n\tlabel: keys.fieldTypeEmail,\n\tvalue: 'text',\n\tvalidate: ({ value, t }) => {\n\t\tif (value == null || value === '') {\n\t\t\treturn true\n\t\t}\n\t\treturn EMAIL_PATTERN.test(value) ? true : t(keys.validationEmail)\n\t},\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n","import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport type { FileRef } from '../../uploads/types'\nimport { defineFormField } from '../defineFormField'\n\ntype FileConfig = {\n\trelationTo?: string\n\tmimeTypes?: string[]\n\tmaxSize?: number\n}\n\nconst isFileRef = (value: unknown): value is FileRef =>\n\ttypeof value === 'object' && value !== null && 'filename' in value\n\n/**\n * The `file` field type. Its stored value is a server-captured {@link FileRef}; the client only ever submits\n * the upload id, and `runSubmission` re-reads filename/mimeType/filesize from the upload doc at the trust\n * boundary (see `captureFileRef`). The intrinsic validator is intentionally a no-op: MIME/size/existence are\n * enforced authoritatively server-side against the stored doc, never against client metadata. `relationTo`,\n * `mimeTypes`, and `maxSize` persist on the block so the capture can enforce them.\n */\nexport const fileField = defineFormField<'file', FileConfig>({\n\ttype: 'file',\n\tlabel: keys.fieldTypeFile,\n\tvalue: 'file',\n\tconfig: [\n\t\t{ name: 'relationTo', type: 'text', label: labelFor(keys.fileConfigRelationTo) },\n\t\t{ name: 'mimeTypes', type: 'text', hasMany: true, label: labelFor(keys.fileConfigMimeTypes) },\n\t\t{ name: 'maxSize', type: 'number', label: labelFor(keys.fileConfigMaxSize) },\n\t],\n\tformat: ({ value }) => (isFileRef(value) ? value.filename : ''),\n})\n","import { keys } from '../../translations/keys'\nimport { defineFormField } from '../defineFormField'\n\nexport const numberField = defineFormField<'number'>({\n\ttype: 'number',\n\tlabel: keys.fieldTypeNumber,\n\tvalue: 'number',\n\tvalidate: ({ value, t }) => {\n\t\tif (value == null) {\n\t\t\treturn true\n\t\t}\n\t\treturn Number.isFinite(value) ? true : t(keys.validationNumber)\n\t},\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n","import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\n\ntype SelectOption = { label: string; value: string }\ntype SelectConfig = { options?: SelectOption[] }\n\nexport const selectField = defineFormField<'text', SelectConfig>({\n\ttype: 'select',\n\tlabel: keys.fieldTypeSelect,\n\tvalue: 'text',\n\tconditionType: 'select',\n\tconfig: [\n\t\t{\n\t\t\tname: 'options',\n\t\t\ttype: 'array',\n\t\t\tlabel: labelFor(keys.configOptions),\n\t\t\tlabels: { singular: labelFor(keys.configOption), plural: labelFor(keys.configOptions) },\n\t\t\tfields: [\n\t\t\t\t{ name: 'label', type: 'text', required: true, label: labelFor(keys.configOptionLabel) },\n\t\t\t\t{ name: 'value', type: 'text', required: true, label: labelFor(keys.configOptionValue) },\n\t\t\t],\n\t\t},\n\t],\n\tvalidate: ({ value, config, t }) => {\n\t\tif (value == null || value === '') {\n\t\t\treturn true\n\t\t}\n\t\tconst options = config.options ?? []\n\t\tif (options.length === 0) {\n\t\t\treturn true\n\t\t}\n\t\treturn options.some((option) => option.value === value) ? true : t(keys.validationSelect)\n\t},\n\tformat: ({ value, optionLabels }) => {\n\t\tif (value == null || value === '') {\n\t\t\treturn ''\n\t\t}\n\t\treturn optionLabels?.[value] ?? String(value)\n\t},\n})\n","import { keys } from '../../translations/keys'\nimport { defineFormField } from '../defineFormField'\n\nexport const textField = defineFormField<'text'>({\n\ttype: 'text',\n\tlabel: keys.fieldTypeText,\n\tvalue: 'text',\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n","import { keys } from '../../translations/keys'\nimport { defineFormField } from '../defineFormField'\n\nexport const textareaField = defineFormField<'text'>({\n\ttype: 'textarea',\n\tlabel: keys.fieldTypeTextarea,\n\tvalue: 'text',\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n","import type { AnyFormFieldDefinition } from '../types'\nimport { calculationField } from './calculation'\nimport { checkboxField } from './checkbox'\nimport { consentField } from './consent'\nimport { emailField } from './email'\nimport { fileField } from './file'\nimport { numberField } from './number'\nimport { selectField } from './select'\nimport { textField } from './text'\nimport { textareaField } from './textarea'\n\n// Field types are authored with precise value/config generics; the registry stores them erased\n// (config is re-narrowed per matched type at execution). One cast per built-in, no `any`.\nexport const defaultFieldDefinitions: AnyFormFieldDefinition[] = [\n\ttextField as AnyFormFieldDefinition,\n\ttextareaField as AnyFormFieldDefinition,\n\temailField as AnyFormFieldDefinition,\n\tnumberField as AnyFormFieldDefinition,\n\tselectField as AnyFormFieldDefinition,\n\tcheckboxField as AnyFormFieldDefinition,\n\tcalculationField as AnyFormFieldDefinition,\n\tconsentField as AnyFormFieldDefinition,\n\tfileField as AnyFormFieldDefinition,\n]\n","import type { AnyFormFieldDefinition } from './types'\n\nexport type FieldTypeRegistry = Map<string, AnyFormFieldDefinition>\n\n/** Per-type opt-in: `false` removes a built-in, `true` keeps it, an object adds a new type or replaces one. */\nexport type FieldTypeOption = boolean | AnyFormFieldDefinition\n\nexport type FieldTypesConfig = Record<string, FieldTypeOption>\n\nexport const buildRegistry = (definitions: AnyFormFieldDefinition[]): FieldTypeRegistry => {\n\tconst registry: FieldTypeRegistry = new Map()\n\tfor (const definition of definitions) {\n\t\tregistry.set(definition.type, definition)\n\t}\n\treturn registry\n}\n\n/**\n * Resolve the active field-type registry from the built-in defaults and the plugin `fields` option.\n * `false` removes a type, `true` keeps the default, an object adds a new type or replaces an existing\n * one (its `type` is forced to the config key so an override cannot rename the slot).\n */\nexport const resolveFieldTypes = (\n\tdefaults: AnyFormFieldDefinition[],\n\tconfig: FieldTypesConfig = {}\n): FieldTypeRegistry => {\n\tconst registry = buildRegistry(defaults)\n\tfor (const [type, option] of Object.entries(config)) {\n\t\tif (option === false) {\n\t\t\tregistry.delete(type)\n\t\t} else if (option === true) {\n\t\t\t// keep the default; a no-op when no default exists for this key\n\t\t} else {\n\t\t\tregistry.set(type, { ...option, type })\n\t\t}\n\t}\n\treturn registry\n}\n"],"mappings":"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"}
|