@10x-media/form-builder 0.1.0-beta.11 → 0.1.0-beta.13
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 +24 -0
- package/dist/aggregation/resolveResultsRequest.d.ts +6 -0
- package/dist/aggregation/resolveResultsRequest.js +32 -3
- package/dist/aggregation/resolveResultsRequest.js.map +1 -1
- package/dist/calc/computeCalcFields.d.ts +5 -3
- package/dist/calc/computeCalcFields.js +4 -3
- package/dist/calc/computeCalcFields.js.map +1 -1
- package/dist/calc/evaluate.d.ts +26 -3
- package/dist/calc/evaluate.js +33 -11
- package/dist/calc/evaluate.js.map +1 -1
- package/dist/calc/formatCalc.d.ts +11 -0
- package/dist/calc/formatCalc.js +35 -0
- package/dist/calc/formatCalc.js.map +1 -0
- package/dist/calc/formatCalcValue.d.ts +17 -0
- package/dist/calc/formatCalcValue.js +17 -0
- package/dist/calc/formatCalcValue.js.map +1 -0
- package/dist/calc/normalizeCalc.d.ts +17 -3
- package/dist/calc/normalizeCalc.js +39 -17
- package/dist/calc/normalizeCalc.js.map +1 -1
- package/dist/calc/registry.d.ts +43 -0
- package/dist/calc/registry.js +27 -0
- package/dist/calc/registry.js.map +1 -0
- package/dist/calc/resolveCalcContext.d.ts +36 -0
- package/dist/calc/resolveCalcContext.js +87 -0
- package/dist/calc/resolveCalcContext.js.map +1 -0
- package/dist/calc/types.d.ts +18 -3
- package/dist/calc/types.js +2 -1
- package/dist/calc/types.js.map +1 -1
- package/dist/client/CalcExpressionBuilder.d.ts +20 -0
- package/dist/client/CalcExpressionBuilder.js +890 -0
- package/dist/client/CalcExpressionBuilder.js.map +1 -0
- package/dist/client/admin.css +282 -0
- package/dist/collections/formSubmissions.js +7 -9
- package/dist/collections/formSubmissions.js.map +1 -1
- package/dist/collections/forms.js +59 -34
- package/dist/collections/forms.js.map +1 -1
- package/dist/collections/formsEndpoints.js +4 -2
- package/dist/collections/formsEndpoints.js.map +1 -1
- package/dist/collections/settingsFields.d.ts +31 -0
- package/dist/collections/settingsFields.js +45 -0
- package/dist/collections/settingsFields.js.map +1 -0
- package/dist/exports/client.d.ts +2 -1
- package/dist/exports/client.js +2 -1
- package/dist/exports/react.d.ts +7 -3
- package/dist/exports/react.js +6 -2
- package/dist/exports/rsc.js +1 -1
- package/dist/exports/types.d.ts +1 -1
- package/dist/fields/buildFieldBlocks.js +2 -1
- package/dist/fields/buildFieldBlocks.js.map +1 -1
- package/dist/fields/builtin/calculation.d.ts +17 -0
- package/dist/fields/builtin/calculation.js +170 -115
- package/dist/fields/builtin/calculation.js.map +1 -1
- package/dist/fields/builtin/checkbox.js +15 -0
- package/dist/fields/builtin/checkbox.js.map +1 -1
- package/dist/fields/builtin/email.js +7 -0
- package/dist/fields/builtin/email.js.map +1 -1
- package/dist/fields/builtin/index.d.ts +6 -2
- package/dist/fields/builtin/index.js +9 -4
- package/dist/fields/builtin/index.js.map +1 -1
- package/dist/fields/builtin/select.js +20 -1
- package/dist/fields/builtin/select.js.map +1 -1
- package/dist/fields/builtin/text.js +7 -0
- package/dist/fields/builtin/text.js.map +1 -1
- package/dist/fields/instanceOptions.js +1 -1
- package/dist/fields/instanceOptions.js.map +1 -1
- package/dist/fields/sharedConfig.js +15 -11
- package/dist/fields/sharedConfig.js.map +1 -1
- package/dist/fields/types.d.ts +8 -2
- package/dist/form/toFormDocument.d.ts +7 -0
- package/dist/form/toFormDocument.js +2 -1
- package/dist/form/toFormDocument.js.map +1 -1
- package/dist/form/types.d.ts +7 -0
- package/dist/index.d.ts +12 -4
- package/dist/index.js +35 -8
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +35 -0
- package/dist/plugin/registerCollections.js +29 -19
- package/dist/plugin/registerCollections.js.map +1 -1
- package/dist/poll/closeJob.d.ts +4 -3
- package/dist/poll/closeJob.js +6 -4
- package/dist/poll/closeJob.js.map +1 -1
- package/dist/poll/pollTypeRegistry.js +1 -1
- package/dist/poll/resolvePollCloseRequest.js +2 -1
- package/dist/poll/resolvePollCloseRequest.js.map +1 -1
- package/dist/poll/resolvePollOutcome.d.ts +6 -0
- package/dist/poll/resolvePollOutcome.js +17 -3
- package/dist/poll/resolvePollOutcome.js.map +1 -1
- package/dist/poll/votes/aggregateFromVotes.d.ts +27 -0
- package/dist/poll/votes/aggregateFromVotes.js +53 -0
- package/dist/poll/votes/aggregateFromVotes.js.map +1 -0
- package/dist/poll/votes/bumpPollVote.js +88 -0
- package/dist/poll/votes/bumpPollVote.js.map +1 -0
- package/dist/poll/votes/recountPollVotes.d.ts +20 -0
- package/dist/poll/votes/recountPollVotes.js +63 -0
- package/dist/poll/votes/recountPollVotes.js.map +1 -0
- package/dist/poll/votes/voteTallyHook.js +58 -0
- package/dist/poll/votes/voteTallyHook.js.map +1 -0
- package/dist/poll/votes/votesCollection.d.ts +19 -0
- package/dist/poll/votes/votesCollection.js +89 -0
- package/dist/poll/votes/votesCollection.js.map +1 -0
- package/dist/react/Form.d.ts +7 -0
- package/dist/react/Form.js +20 -3
- package/dist/react/Form.js.map +1 -1
- package/dist/react/FormContext.d.ts +8 -1
- package/dist/react/FormContext.js.map +1 -1
- package/dist/react/primitives/Checkbox.d.ts +4 -2
- package/dist/react/primitives/Checkbox.js +3 -2
- package/dist/react/primitives/Checkbox.js.map +1 -1
- package/dist/react/primitives/ChoiceGroup.d.ts +40 -0
- package/dist/react/primitives/ChoiceGroup.js +33 -0
- package/dist/react/primitives/ChoiceGroup.js.map +1 -0
- package/dist/react/primitives/FieldShell.d.ts +11 -1
- package/dist/react/primitives/FieldShell.js +43 -33
- package/dist/react/primitives/FieldShell.js.map +1 -1
- package/dist/react/primitives/Input.d.ts +3 -1
- package/dist/react/primitives/Input.js +2 -1
- package/dist/react/primitives/Input.js.map +1 -1
- package/dist/react/renderers/calculation.js +6 -1
- package/dist/react/renderers/calculation.js.map +1 -1
- package/dist/react/renderers/checkbox.js +2 -1
- package/dist/react/renderers/checkbox.js.map +1 -1
- package/dist/react/renderers/email.js +3 -1
- package/dist/react/renderers/email.js.map +1 -1
- package/dist/react/renderers/select.js +20 -2
- package/dist/react/renderers/select.js.map +1 -1
- package/dist/react/renderers/text.js +3 -1
- package/dist/react/renderers/text.js.map +1 -1
- package/dist/react/useCalcValues.d.ts +10 -0
- package/dist/react/useCalcValues.js +13 -0
- package/dist/react/useCalcValues.js.map +1 -0
- package/dist/recall/resolver.js +1 -1
- package/dist/recall/resolver.js.map +1 -1
- package/dist/submissions/formIdOf.js +13 -0
- package/dist/submissions/formIdOf.js.map +1 -0
- package/dist/submissions/runSubmission.js +3 -3
- package/dist/submissions/runSubmission.js.map +1 -1
- package/dist/submissions/validateSubmission.js +26 -2
- package/dist/submissions/validateSubmission.js.map +1 -1
- package/dist/translations/de.js +58 -3
- package/dist/translations/de.js.map +1 -1
- package/dist/translations/en.js +58 -3
- package/dist/translations/en.js.map +1 -1
- package/dist/translations/keys.d.ts +56 -1
- package/dist/translations/keys.js +56 -1
- package/dist/translations/keys.js.map +1 -1
- package/dist/validation/builtin/index.js +2 -0
- package/dist/validation/builtin/index.js.map +1 -1
- package/dist/validation/builtin/integer.js +15 -0
- package/dist/validation/builtin/integer.js.map +1 -0
- package/package.json +10 -4
- package/styles/form-builder.css +84 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildCalculationField } from "./calculation.js";
|
|
2
2
|
import { checkboxField } from "./checkbox.js";
|
|
3
3
|
import { consentField } from "./consent.js";
|
|
4
4
|
import { dateField } from "./date.js";
|
|
@@ -17,16 +17,21 @@ import { textareaField } from "./textarea.js";
|
|
|
17
17
|
* richText editor on the message content field (from the plugin's `richText.editor` option). Field
|
|
18
18
|
* types without content config are shared static definitions. Definitions are authored with precise
|
|
19
19
|
* value/config generics; the registry stores them erased (config is re-narrowed per matched type at
|
|
20
|
-
* execution), hence one cast per built-in, no `any`.
|
|
20
|
+
* execution), hence one cast per built-in, no `any`. `calcAllowed` threads the registered calc
|
|
21
|
+
* extension names into the calculation field's expression validate and editor schema;
|
|
22
|
+
* `calcSources` carries the serializable source metadata the builder UI renders from.
|
|
21
23
|
*/
|
|
22
|
-
const buildDefaultFieldDefinitions = (localize, editor, uploadMimeTypes) => [
|
|
24
|
+
const buildDefaultFieldDefinitions = (localize, editor, uploadMimeTypes, calcAllowed, calcSources) => [
|
|
23
25
|
textField,
|
|
24
26
|
textareaField,
|
|
25
27
|
emailField,
|
|
26
28
|
numberField,
|
|
27
29
|
buildSelectField(localize),
|
|
28
30
|
checkboxField,
|
|
29
|
-
|
|
31
|
+
buildCalculationField(calcAllowed, {
|
|
32
|
+
localize,
|
|
33
|
+
sources: calcSources
|
|
34
|
+
}),
|
|
30
35
|
consentField,
|
|
31
36
|
buildFileField(uploadMimeTypes),
|
|
32
37
|
buildRepeaterField(localize),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/fields/builtin/index.ts"],"sourcesContent":["import type { RichTextField } from 'payload'\nimport type { AnyFormFieldDefinition } from '../types'\nimport {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/fields/builtin/index.ts"],"sourcesContent":["import type { RichTextField } from 'payload'\nimport type { CalcAllowed } from '../../calc/normalizeCalc'\nimport type { AnyFormFieldDefinition } from '../types'\nimport { buildCalculationField, type CalcSourceClientMeta } from './calculation'\nimport { checkboxField } from './checkbox'\nimport { consentField } from './consent'\nimport { dateField } from './date'\nimport { emailField } from './email'\nimport { buildFileField } from './file'\nimport { buildMessageField } from './message'\nimport { numberField } from './number'\nimport { buildRepeaterField } from './repeater'\nimport { buildSelectField } from './select'\nimport { textField } from './text'\nimport { textareaField } from './textarea'\n\n/**\n * Built-in field definitions with content-bearing config fields (select option labels, repeater add\n * label) carrying `localized: true` when `localize` is true. `editor`, when given, overrides the\n * richText editor on the message content field (from the plugin's `richText.editor` option). Field\n * types without content config are shared static definitions. Definitions are authored with precise\n * value/config generics; the registry stores them erased (config is re-narrowed per matched type at\n * execution), hence one cast per built-in, no `any`. `calcAllowed` threads the registered calc\n * extension names into the calculation field's expression validate and editor schema;\n * `calcSources` carries the serializable source metadata the builder UI renders from.\n */\n// biome-ignore lint/complexity/useMaxParams: the documented positional surface (localize, editor, uploadMimeTypes) plus the calc allowed sets and source metadata; an options object would break existing callers\nexport const buildDefaultFieldDefinitions = (\n\tlocalize: boolean,\n\teditor?: RichTextField['editor'],\n\tuploadMimeTypes?: string[],\n\tcalcAllowed?: CalcAllowed,\n\tcalcSources?: CalcSourceClientMeta[]\n): AnyFormFieldDefinition[] => [\n\ttextField as AnyFormFieldDefinition,\n\ttextareaField as AnyFormFieldDefinition,\n\temailField as AnyFormFieldDefinition,\n\tnumberField as AnyFormFieldDefinition,\n\tbuildSelectField(localize) as AnyFormFieldDefinition,\n\tcheckboxField as AnyFormFieldDefinition,\n\tbuildCalculationField(calcAllowed, { localize, sources: calcSources }) as AnyFormFieldDefinition,\n\tconsentField as AnyFormFieldDefinition,\n\tbuildFileField(uploadMimeTypes) as AnyFormFieldDefinition,\n\tbuildRepeaterField(localize) as AnyFormFieldDefinition,\n\tdateField as AnyFormFieldDefinition,\n\tbuildMessageField(localize, editor) as AnyFormFieldDefinition,\n]\n\nexport const defaultFieldDefinitions: AnyFormFieldDefinition[] = buildDefaultFieldDefinitions(true)\n\n/**\n * `defaultFieldDefinitions` indexed by `type`, so a single built-in can be spread and tweaked\n * without hand-rolling a `.find()`, e.g.\n * `fields: { text: { ...defaultFieldDefinitionsByType.text, validate: myValidate } }`. The\n * `fields` plugin option replaces a built-in of the same `type`; `false` removes it, `true` keeps it.\n * Prebuilt with content localization on; with `localizeContent: false`, derive overrides from\n * `buildDefaultFieldDefinitions(false)` instead so the spread does not reintroduce `localized`.\n */\nexport const defaultFieldDefinitionsByType: Record<string, AnyFormFieldDefinition> =\n\tObject.fromEntries(defaultFieldDefinitions.map((definition) => [definition.type, definition]))\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA2BA,MAAa,gCACZ,UACA,QACA,iBACA,aACA,gBAC8B;CAC9B;CACA;CACA;CACA;CACA,iBAAiB,QAAQ;CACzB;CACA,sBAAsB,aAAa;EAAE;EAAU,SAAS;CAAY,CAAC;CACrE;CACA,eAAe,eAAe;CAC9B,mBAAmB,QAAQ;CAC3B;CACA,kBAAkB,UAAU,MAAM;AACnC;AAEA,MAAa,0BAAoD,6BAA6B,IAAI;;;;;;;;;AAUlG,MAAa,gCACZ,OAAO,YAAY,wBAAwB,KAAK,eAAe,CAAC,WAAW,MAAM,UAAU,CAAC,CAAC"}
|
|
@@ -21,7 +21,6 @@ const buildSelectField = (localize) => defineFormField({
|
|
|
21
21
|
fields: [{
|
|
22
22
|
name: "label",
|
|
23
23
|
type: "text",
|
|
24
|
-
required: true,
|
|
25
24
|
label: labelFor(keys.configOptionLabel),
|
|
26
25
|
...localizedIf(localize)
|
|
27
26
|
}, {
|
|
@@ -30,6 +29,26 @@ const buildSelectField = (localize) => defineFormField({
|
|
|
30
29
|
required: true,
|
|
31
30
|
label: labelFor(keys.configOptionValue)
|
|
32
31
|
}]
|
|
32
|
+
}, {
|
|
33
|
+
name: "display",
|
|
34
|
+
type: "select",
|
|
35
|
+
defaultValue: "dropdown",
|
|
36
|
+
label: labelFor(keys.configSelectDisplay),
|
|
37
|
+
admin: { isClearable: false },
|
|
38
|
+
options: [
|
|
39
|
+
{
|
|
40
|
+
label: labelFor(keys.selectDisplayDropdown),
|
|
41
|
+
value: "dropdown"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
label: labelFor(keys.selectDisplayRadio),
|
|
45
|
+
value: "radio"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
label: labelFor(keys.selectDisplayButtons),
|
|
49
|
+
value: "buttons"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
33
52
|
}],
|
|
34
53
|
validate: ({ value, config, t }) => {
|
|
35
54
|
if (value == null || value === "") return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","names":[],"sources":["../../../src/fields/builtin/select.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\nimport { localizedIf } from '../localizedIf'\n\ntype SelectOption = { label
|
|
1
|
+
{"version":3,"file":"select.js","names":[],"sources":["../../../src/fields/builtin/select.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\nimport { localizedIf } from '../localizedIf'\n\ntype SelectOption = { label?: string; value: string }\ntype SelectConfig = { options?: SelectOption[]; display?: 'dropdown' | 'radio' | 'buttons' }\n\n/** Option `label` is author-facing content and follows `localize`; `value` is an identifier and never does. */\nexport const buildSelectField = (localize: boolean) =>\n\tdefineFormField<'text', SelectConfig>({\n\t\ttype: 'select',\n\t\tlabel: keys.fieldTypeSelect,\n\t\tvalue: 'text',\n\t\tconditionType: 'select',\n\t\tpollEligible: true,\n\t\tconfig: [\n\t\t\t{\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'array',\n\t\t\t\tlabel: labelFor(keys.configOptions),\n\t\t\t\tlabels: { singular: labelFor(keys.configOption), plural: labelFor(keys.configOptions) },\n\t\t\t\tfields: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'label',\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\tlabel: labelFor(keys.configOptionLabel),\n\t\t\t\t\t\t...localizedIf(localize),\n\t\t\t\t\t},\n\t\t\t\t\t{ name: 'value', type: 'text', required: true, label: labelFor(keys.configOptionValue) },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'display',\n\t\t\t\ttype: 'select',\n\t\t\t\tdefaultValue: 'dropdown',\n\t\t\t\tlabel: labelFor(keys.configSelectDisplay),\n\t\t\t\tadmin: { isClearable: false },\n\t\t\t\toptions: [\n\t\t\t\t\t{ label: labelFor(keys.selectDisplayDropdown), value: 'dropdown' },\n\t\t\t\t\t{ label: labelFor(keys.selectDisplayRadio), value: 'radio' },\n\t\t\t\t\t{ label: labelFor(keys.selectDisplayButtons), value: 'buttons' },\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t\tvalidate: ({ value, config, t }) => {\n\t\t\tif (value == null || value === '') {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tconst options = config.options ?? []\n\t\t\tif (options.length === 0) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn options.some((option) => option.value === value) ? true : t(keys.validationSelect)\n\t\t},\n\t\tformat: ({ value, optionLabels }) => {\n\t\t\tif (value == null || value === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn optionLabels?.[value] ?? String(value)\n\t\t},\n\t})\n\nexport const selectField = buildSelectField(true)\n"],"mappings":";;;;;;AASA,MAAa,oBAAoB,aAChC,gBAAsC;CACrC,MAAM;CACN,OAAO,KAAK;CACZ,OAAO;CACP,eAAe;CACf,cAAc;CACd,QAAQ,CACP;EACC,MAAM;EACN,MAAM;EACN,OAAO,SAAS,KAAK,aAAa;EAClC,QAAQ;GAAE,UAAU,SAAS,KAAK,YAAY;GAAG,QAAQ,SAAS,KAAK,aAAa;EAAE;EACtF,QAAQ,CACP;GACC,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,iBAAiB;GACtC,GAAG,YAAY,QAAQ;EACxB,GACA;GAAE,MAAM;GAAS,MAAM;GAAQ,UAAU;GAAM,OAAO,SAAS,KAAK,iBAAiB;EAAE,CACxF;CACD,GACA;EACC,MAAM;EACN,MAAM;EACN,cAAc;EACd,OAAO,SAAS,KAAK,mBAAmB;EACxC,OAAO,EAAE,aAAa,MAAM;EAC5B,SAAS;GACR;IAAE,OAAO,SAAS,KAAK,qBAAqB;IAAG,OAAO;GAAW;GACjE;IAAE,OAAO,SAAS,KAAK,kBAAkB;IAAG,OAAO;GAAQ;GAC3D;IAAE,OAAO,SAAS,KAAK,oBAAoB;IAAG,OAAO;GAAU;EAChE;CACD,CACD;CACA,WAAW,EAAE,OAAO,QAAQ,QAAQ;EACnC,IAAI,SAAS,QAAQ,UAAU,IAC9B,OAAO;EAER,MAAM,UAAU,OAAO,WAAW,CAAC;EACnC,IAAI,QAAQ,WAAW,GACtB,OAAO;EAER,OAAO,QAAQ,MAAM,WAAW,OAAO,UAAU,KAAK,IAAI,OAAO,EAAE,KAAK,gBAAgB;CACzF;CACA,SAAS,EAAE,OAAO,mBAAmB;EACpC,IAAI,SAAS,QAAQ,UAAU,IAC9B,OAAO;EAER,OAAO,eAAe,UAAU,OAAO,KAAK;CAC7C;AACD,CAAC;AAEyB,iBAAiB,IAAI"}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { keys } from "../../translations/keys.js";
|
|
2
|
+
import { labelFor } from "../../translations/server.js";
|
|
2
3
|
import { defineFormField } from "../defineFormField.js";
|
|
3
4
|
//#region src/fields/builtin/text.ts
|
|
4
5
|
const textField = defineFormField({
|
|
5
6
|
type: "text",
|
|
6
7
|
label: keys.fieldTypeText,
|
|
7
8
|
value: "text",
|
|
9
|
+
advancedConfig: [{
|
|
10
|
+
name: "autocomplete",
|
|
11
|
+
type: "text",
|
|
12
|
+
label: labelFor(keys.configAutocomplete),
|
|
13
|
+
admin: { description: labelFor(keys.configAutocompleteDescription) }
|
|
14
|
+
}],
|
|
8
15
|
format: ({ value }) => value == null ? "" : String(value)
|
|
9
16
|
});
|
|
10
17
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","names":[],"sources":["../../../src/fields/builtin/text.ts"],"sourcesContent":["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"],"mappings":"
|
|
1
|
+
{"version":3,"file":"text.js","names":[],"sources":["../../../src/fields/builtin/text.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\n\nexport const textField = defineFormField<'text'>({\n\ttype: 'text',\n\tlabel: keys.fieldTypeText,\n\tvalue: 'text',\n\tadvancedConfig: [\n\t\t{\n\t\t\tname: 'autocomplete',\n\t\t\ttype: 'text',\n\t\t\tlabel: labelFor(keys.configAutocomplete),\n\t\t\tadmin: { description: labelFor(keys.configAutocompleteDescription) },\n\t\t},\n\t],\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n"],"mappings":";;;;AAIA,MAAa,YAAY,gBAAwB;CAChD,MAAM;CACN,OAAO,KAAK;CACZ,OAAO;CACP,gBAAgB,CACf;EACC,MAAM;EACN,MAAM;EACN,OAAO,SAAS,KAAK,kBAAkB;EACvC,OAAO,EAAE,aAAa,SAAS,KAAK,6BAA6B,EAAE;CACpE,CACD;CACA,SAAS,EAAE,YAAa,SAAS,OAAO,KAAK,OAAO,KAAK;AAC1D,CAAC"}
|
|
@@ -10,7 +10,7 @@ const instanceOptionsOf = (field) => {
|
|
|
10
10
|
if (!Array.isArray(field.options)) return;
|
|
11
11
|
const options = field.options.filter((option) => typeof option?.value === "string").map((option) => ({
|
|
12
12
|
value: String(option.value),
|
|
13
|
-
label: option.label
|
|
13
|
+
label: option.label?.trim() ? option.label : String(option.value)
|
|
14
14
|
}));
|
|
15
15
|
return options.length > 0 ? options : void 0;
|
|
16
16
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instanceOptions.js","names":[],"sources":["../../src/fields/instanceOptions.ts"],"sourcesContent":["import type { FormFieldInstance } from '../submissions/types'\n\n/**\n * Normalize a field instance's authored options to `{ value, label }` pairs, dropping entries\n * without a string value and falling back to the value as label. Returns `undefined` when the\n * instance declares no usable options, so callers can distinguish \"not a choice field\" from an\n * empty choice set. Shared by response aggregation and poll outcome resolution so both read the\n * same choice set from a form document.\n */\nexport const instanceOptionsOf = (\n\tfield: FormFieldInstance\n): { value: string; label: string }[] | undefined => {\n\tif (!Array.isArray(field.options)) {\n\t\treturn undefined\n\t}\n\tconst options = (field.options as Array<{ label?: string; value?: string }>)\n\t\t.filter((option) => typeof option?.value === 'string')\n\t\t.map((option) => ({
|
|
1
|
+
{"version":3,"file":"instanceOptions.js","names":[],"sources":["../../src/fields/instanceOptions.ts"],"sourcesContent":["import type { FormFieldInstance } from '../submissions/types'\n\n/**\n * Normalize a field instance's authored options to `{ value, label }` pairs, dropping entries\n * without a string value and falling back to the value as label. Returns `undefined` when the\n * instance declares no usable options, so callers can distinguish \"not a choice field\" from an\n * empty choice set. Shared by response aggregation and poll outcome resolution so both read the\n * same choice set from a form document.\n */\nexport const instanceOptionsOf = (\n\tfield: FormFieldInstance\n): { value: string; label: string }[] | undefined => {\n\tif (!Array.isArray(field.options)) {\n\t\treturn undefined\n\t}\n\tconst options = (field.options as Array<{ label?: string; value?: string }>)\n\t\t.filter((option) => typeof option?.value === 'string')\n\t\t.map((option) => ({\n\t\t\tvalue: String(option.value),\n\t\t\tlabel: option.label?.trim() ? option.label : String(option.value),\n\t\t}))\n\treturn options.length > 0 ? options : undefined\n}\n"],"mappings":";;;;;;;;AASA,MAAa,qBACZ,UACoD;CACpD,IAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,GAC/B;CAED,MAAM,UAAW,MAAM,QACrB,QAAQ,WAAW,OAAO,QAAQ,UAAU,QAAQ,EACpD,KAAK,YAAY;EACjB,OAAO,OAAO,OAAO,KAAK;EAC1B,OAAO,OAAO,OAAO,KAAK,IAAI,OAAO,QAAQ,OAAO,OAAO,KAAK;CACjE,EAAE;CACH,OAAO,QAAQ,SAAS,IAAI,UAAU,KAAA;AACvC"}
|
|
@@ -65,7 +65,6 @@ const baseSharedFieldConfig = (localize) => [
|
|
|
65
65
|
fields: [{
|
|
66
66
|
name: "width",
|
|
67
67
|
type: "select",
|
|
68
|
-
required: true,
|
|
69
68
|
defaultValue: "full",
|
|
70
69
|
label: labelFor(keys.configWidth),
|
|
71
70
|
admin: {
|
|
@@ -74,19 +73,19 @@ const baseSharedFieldConfig = (localize) => [
|
|
|
74
73
|
},
|
|
75
74
|
options: [
|
|
76
75
|
{
|
|
77
|
-
label:
|
|
76
|
+
label: labelFor(keys.widthFull),
|
|
78
77
|
value: "full"
|
|
79
78
|
},
|
|
80
79
|
{
|
|
81
|
-
label:
|
|
80
|
+
label: labelFor(keys.widthHalf),
|
|
82
81
|
value: "half"
|
|
83
82
|
},
|
|
84
83
|
{
|
|
85
|
-
label:
|
|
84
|
+
label: labelFor(keys.widthThird),
|
|
86
85
|
value: "third"
|
|
87
86
|
},
|
|
88
87
|
{
|
|
89
|
-
label:
|
|
88
|
+
label: labelFor(keys.widthTwoThirds),
|
|
90
89
|
value: "twoThirds"
|
|
91
90
|
}
|
|
92
91
|
]
|
|
@@ -124,7 +123,7 @@ const sharedFieldConfig = (localize = true, omitShared = []) => {
|
|
|
124
123
|
omit.delete("name");
|
|
125
124
|
return applyOmissions(baseSharedFieldConfig(localize), omit);
|
|
126
125
|
};
|
|
127
|
-
const fieldBlockTabs = ({ conditionTypes, typeConfig, validations, localize = true, omitShared }) => ({
|
|
126
|
+
const fieldBlockTabs = ({ conditionTypes, typeConfig, validations, localize = true, omitShared, advancedConfig }) => ({
|
|
128
127
|
type: "tabs",
|
|
129
128
|
tabs: [
|
|
130
129
|
{
|
|
@@ -137,11 +136,16 @@ const fieldBlockTabs = ({ conditionTypes, typeConfig, validations, localize = tr
|
|
|
137
136
|
},
|
|
138
137
|
{
|
|
139
138
|
label: labelFor(keys.tabAdvanced),
|
|
140
|
-
fields: [
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
fields: [
|
|
140
|
+
conditionField("visibleWhen", keys.configVisibleWhen, conditionTypes),
|
|
141
|
+
{
|
|
142
|
+
name: "hidden",
|
|
143
|
+
type: "checkbox",
|
|
144
|
+
label: labelFor(keys.configHidden),
|
|
145
|
+
admin: { description: labelFor(keys.configHiddenDescription) }
|
|
146
|
+
},
|
|
147
|
+
...advancedConfig ?? []
|
|
148
|
+
]
|
|
145
149
|
}
|
|
146
150
|
]
|
|
147
151
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sharedConfig.js","names":[],"sources":["../../src/fields/sharedConfig.ts"],"sourcesContent":["import type { Field } from 'payload'\nimport type { ConditionFieldType } from '../conditions/fieldTypes'\nimport { keys } from '../translations/keys'\nimport { labelFor } from '../translations/server'\nimport { localizedIf } from './localizedIf'\nimport type { OmittableSharedField } from './types'\n\nconst CONDITION_FIELD_REF = '@10x-media/form-builder/client#FormConditionField'\n\nconst conditionField = (\n\tname: 'visibleWhen' | 'validateWhen',\n\tlabelKey: string,\n\tconditionTypes: Record<string, ConditionFieldType>\n): Field => ({\n\tname,\n\ttype: 'json',\n\tlabel: labelFor(labelKey),\n\tadmin: {\n\t\tcomponents: {\n\t\t\tField: { path: CONDITION_FIELD_REF, clientProps: { conditionTypes } },\n\t\t},\n\t},\n})\n\n/**\n * Let a lone row survivor span its row: Payload styles a row child with no `admin.width` as\n * `flex: 1 1 auto` (see `mergeFieldStyles`), so dropping the key is the \"fill the row\" signal.\n * Without this, omitting one half of a 50/50 row would strand the other half at 50%.\n */\nconst spanRow = <T extends Field>(field: T): T => {\n\tif (field.admin?.width === undefined) {\n\t\treturn field\n\t}\n\tconst { width: _width, ...admin } = field.admin\n\treturn { ...field, admin }\n}\n\n/**\n * Drop the shared fields a type never uses, descending into the presentational rows so a nested\n * field is reachable. An emptied row is dropped whole; a row pruned down to one field lets that\n * field span it. A row that lost nothing is left exactly as authored, single-child rows included.\n */\nconst applyOmissions = (fields: Field[], omit: ReadonlySet<string>): Field[] =>\n\tfields.flatMap((field): Field[] => {\n\t\tif (field.type === 'row') {\n\t\t\tconst kept = applyOmissions(field.fields, omit)\n\t\t\tif (kept.length === 0) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst strandsSurvivor = kept.length === 1 && kept.length < field.fields.length\n\t\t\treturn [{ ...field, fields: strandsSurvivor ? kept.map(spanRow) : kept }]\n\t\t}\n\t\treturn 'name' in field && omit.has(field.name) ? [] : [field]\n\t})\n\n/** The full shared config, before a type's `omitShared` prunes it. See `sharedFieldConfig`. */\nconst baseSharedFieldConfig = (localize: boolean): Field[] => [\n\t{\n\t\ttype: 'row',\n\t\tfields: [\n\t\t\t{\n\t\t\t\tname: 'name',\n\t\t\t\ttype: 'text',\n\t\t\t\trequired: true,\n\t\t\t\tlabel: labelFor(keys.configName),\n\t\t\t\tadmin: { width: '50%' },\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'label',\n\t\t\t\ttype: 'text',\n\t\t\t\tlabel: labelFor(keys.configLabel),\n\t\t\t\tadmin: { width: '50%' },\n\t\t\t\t...localizedIf(localize),\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\ttype: 'row',\n\t\tfields: [\n\t\t\t{\n\t\t\t\tname: 'width',\n\t\t\t\ttype: 'select',\n\t\t\t\
|
|
1
|
+
{"version":3,"file":"sharedConfig.js","names":[],"sources":["../../src/fields/sharedConfig.ts"],"sourcesContent":["import type { Field } from 'payload'\nimport type { ConditionFieldType } from '../conditions/fieldTypes'\nimport { keys } from '../translations/keys'\nimport { labelFor } from '../translations/server'\nimport { localizedIf } from './localizedIf'\nimport type { OmittableSharedField } from './types'\n\nconst CONDITION_FIELD_REF = '@10x-media/form-builder/client#FormConditionField'\n\nconst conditionField = (\n\tname: 'visibleWhen' | 'validateWhen',\n\tlabelKey: string,\n\tconditionTypes: Record<string, ConditionFieldType>\n): Field => ({\n\tname,\n\ttype: 'json',\n\tlabel: labelFor(labelKey),\n\tadmin: {\n\t\tcomponents: {\n\t\t\tField: { path: CONDITION_FIELD_REF, clientProps: { conditionTypes } },\n\t\t},\n\t},\n})\n\n/**\n * Let a lone row survivor span its row: Payload styles a row child with no `admin.width` as\n * `flex: 1 1 auto` (see `mergeFieldStyles`), so dropping the key is the \"fill the row\" signal.\n * Without this, omitting one half of a 50/50 row would strand the other half at 50%.\n */\nconst spanRow = <T extends Field>(field: T): T => {\n\tif (field.admin?.width === undefined) {\n\t\treturn field\n\t}\n\tconst { width: _width, ...admin } = field.admin\n\treturn { ...field, admin }\n}\n\n/**\n * Drop the shared fields a type never uses, descending into the presentational rows so a nested\n * field is reachable. An emptied row is dropped whole; a row pruned down to one field lets that\n * field span it. A row that lost nothing is left exactly as authored, single-child rows included.\n */\nconst applyOmissions = (fields: Field[], omit: ReadonlySet<string>): Field[] =>\n\tfields.flatMap((field): Field[] => {\n\t\tif (field.type === 'row') {\n\t\t\tconst kept = applyOmissions(field.fields, omit)\n\t\t\tif (kept.length === 0) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst strandsSurvivor = kept.length === 1 && kept.length < field.fields.length\n\t\t\treturn [{ ...field, fields: strandsSurvivor ? kept.map(spanRow) : kept }]\n\t\t}\n\t\treturn 'name' in field && omit.has(field.name) ? [] : [field]\n\t})\n\n/** The full shared config, before a type's `omitShared` prunes it. See `sharedFieldConfig`. */\nconst baseSharedFieldConfig = (localize: boolean): Field[] => [\n\t{\n\t\ttype: 'row',\n\t\tfields: [\n\t\t\t{\n\t\t\t\tname: 'name',\n\t\t\t\ttype: 'text',\n\t\t\t\trequired: true,\n\t\t\t\tlabel: labelFor(keys.configName),\n\t\t\t\tadmin: { width: '50%' },\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'label',\n\t\t\t\ttype: 'text',\n\t\t\t\tlabel: labelFor(keys.configLabel),\n\t\t\t\tadmin: { width: '50%' },\n\t\t\t\t...localizedIf(localize),\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\ttype: 'row',\n\t\tfields: [\n\t\t\t{\n\t\t\t\tname: 'width',\n\t\t\t\ttype: 'select',\n\t\t\t\tdefaultValue: 'full',\n\t\t\t\tlabel: labelFor(keys.configWidth),\n\t\t\t\tadmin: { width: '50%', isClearable: false },\n\t\t\t\toptions: [\n\t\t\t\t\t{ label: labelFor(keys.widthFull), value: 'full' },\n\t\t\t\t\t{ label: labelFor(keys.widthHalf), value: 'half' },\n\t\t\t\t\t{ label: labelFor(keys.widthThird), value: 'third' },\n\t\t\t\t\t{ label: labelFor(keys.widthTwoThirds), value: 'twoThirds' },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'placeholder',\n\t\t\t\ttype: 'text',\n\t\t\t\tlabel: labelFor(keys.configPlaceholder),\n\t\t\t\tadmin: { width: '50%' },\n\t\t\t\t...localizedIf(localize),\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: 'description',\n\t\ttype: 'textarea',\n\t\tlabel: labelFor(keys.configDescription),\n\t\t...localizedIf(localize),\n\t},\n\t{ name: 'required', type: 'checkbox', label: labelFor(keys.configRequired) },\n]\n\n/**\n * Config every field instance carries regardless of type. `name` is the machine key written into\n * submissions; `width` is stored for the layout grid. Field types add their own `config` after\n * these inside the Field tab (see `fieldBlockTabs`) and drop the ones they never read via\n * `omitShared`, so an author is never offered a setting the renderer ignores. Content-bearing\n * fields (`label`, `placeholder`, `description`) are localized unless `localize` is false;\n * identifiers and behavior flags never are. The rows are presentational only (unnamed, data paths\n * stay flat); `required` sits last, under `description`, per the admin layout.\n */\nexport const sharedFieldConfig = (\n\tlocalize = true,\n\tomitShared: readonly OmittableSharedField[] = []\n): Field[] => {\n\tconst omit = new Set<string>(omitShared)\n\t// `name` is the storage key every read and write path gates on (`isNamedField`). The type\n\t// already excludes it; dropping it here too keeps an untyped caller from breaking storage.\n\tomit.delete('name')\n\treturn applyOmissions(baseSharedFieldConfig(localize), omit)\n}\n\n/**\n * The single field of every field block: unnamed tabs (presentational only, data paths stay flat).\n * Field tab holds the shared basics plus the type's own config; Validation holds the rule blocks and\n * `validateWhen`; Advanced holds `visibleWhen` and `hidden`. `visibleWhen`/`validateWhen` store a\n * canonical Payload `Where`, edited by the native condition builder.\n */\ntype FieldBlockTabsArgs = {\n\tconditionTypes: Record<string, ConditionFieldType>\n\ttypeConfig: Field[]\n\tvalidations: Field\n\tlocalize?: boolean\n\t/** See `FormFieldDefinition.omitShared`: shared basics this type never uses, left unauthored. */\n\tomitShared?: readonly OmittableSharedField[]\n\t/** See `FormFieldDefinition.advancedConfig`: extra fields appended to the Advanced tab. */\n\tadvancedConfig?: Field[]\n}\n\nexport const fieldBlockTabs = ({\n\tconditionTypes,\n\ttypeConfig,\n\tvalidations,\n\tlocalize = true,\n\tomitShared,\n\tadvancedConfig,\n}: FieldBlockTabsArgs): Field => ({\n\ttype: 'tabs',\n\ttabs: [\n\t\t{\n\t\t\tlabel: labelFor(keys.tabField),\n\t\t\tfields: [...sharedFieldConfig(localize, omitShared), ...typeConfig],\n\t\t},\n\t\t{\n\t\t\tlabel: labelFor(keys.tabValidation),\n\t\t\tfields: [\n\t\t\t\tvalidations,\n\t\t\t\tconditionField('validateWhen', keys.configValidateWhen, conditionTypes),\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tlabel: labelFor(keys.tabAdvanced),\n\t\t\tfields: [\n\t\t\t\tconditionField('visibleWhen', keys.configVisibleWhen, conditionTypes),\n\t\t\t\t{\n\t\t\t\t\tname: 'hidden',\n\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\tlabel: labelFor(keys.configHidden),\n\t\t\t\t\tadmin: { description: labelFor(keys.configHiddenDescription) },\n\t\t\t\t},\n\t\t\t\t...(advancedConfig ?? []),\n\t\t\t],\n\t\t},\n\t],\n})\n"],"mappings":";;;;AAOA,MAAM,sBAAsB;AAE5B,MAAM,kBACL,MACA,UACA,oBACY;CACZ;CACA,MAAM;CACN,OAAO,SAAS,QAAQ;CACxB,OAAO,EACN,YAAY,EACX,OAAO;EAAE,MAAM;EAAqB,aAAa,EAAE,eAAe;CAAE,EACrE,EACD;AACD;;;;;;AAOA,MAAM,WAA4B,UAAgB;CACjD,IAAI,MAAM,OAAO,UAAU,KAAA,GAC1B,OAAO;CAER,MAAM,EAAE,OAAO,QAAQ,GAAG,UAAU,MAAM;CAC1C,OAAO;EAAE,GAAG;EAAO;CAAM;AAC1B;;;;;;AAOA,MAAM,kBAAkB,QAAiB,SACxC,OAAO,SAAS,UAAmB;CAClC,IAAI,MAAM,SAAS,OAAO;EACzB,MAAM,OAAO,eAAe,MAAM,QAAQ,IAAI;EAC9C,IAAI,KAAK,WAAW,GACnB,OAAO,CAAC;EAET,MAAM,kBAAkB,KAAK,WAAW,KAAK,KAAK,SAAS,MAAM,OAAO;EACxE,OAAO,CAAC;GAAE,GAAG;GAAO,QAAQ,kBAAkB,KAAK,IAAI,OAAO,IAAI;EAAK,CAAC;CACzE;CACA,OAAO,UAAU,SAAS,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK;AAC7D,CAAC;;AAGF,MAAM,yBAAyB,aAA+B;CAC7D;EACC,MAAM;EACN,QAAQ,CACP;GACC,MAAM;GACN,MAAM;GACN,UAAU;GACV,OAAO,SAAS,KAAK,UAAU;GAC/B,OAAO,EAAE,OAAO,MAAM;EACvB,GACA;GACC,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,WAAW;GAChC,OAAO,EAAE,OAAO,MAAM;GACtB,GAAG,YAAY,QAAQ;EACxB,CACD;CACD;CACA;EACC,MAAM;EACN,QAAQ,CACP;GACC,MAAM;GACN,MAAM;GACN,cAAc;GACd,OAAO,SAAS,KAAK,WAAW;GAChC,OAAO;IAAE,OAAO;IAAO,aAAa;GAAM;GAC1C,SAAS;IACR;KAAE,OAAO,SAAS,KAAK,SAAS;KAAG,OAAO;IAAO;IACjD;KAAE,OAAO,SAAS,KAAK,SAAS;KAAG,OAAO;IAAO;IACjD;KAAE,OAAO,SAAS,KAAK,UAAU;KAAG,OAAO;IAAQ;IACnD;KAAE,OAAO,SAAS,KAAK,cAAc;KAAG,OAAO;IAAY;GAC5D;EACD,GACA;GACC,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,iBAAiB;GACtC,OAAO,EAAE,OAAO,MAAM;GACtB,GAAG,YAAY,QAAQ;EACxB,CACD;CACD;CACA;EACC,MAAM;EACN,MAAM;EACN,OAAO,SAAS,KAAK,iBAAiB;EACtC,GAAG,YAAY,QAAQ;CACxB;CACA;EAAE,MAAM;EAAY,MAAM;EAAY,OAAO,SAAS,KAAK,cAAc;CAAE;AAC5E;;;;;;;;;;AAWA,MAAa,qBACZ,WAAW,MACX,aAA8C,CAAC,MAClC;CACb,MAAM,OAAO,IAAI,IAAY,UAAU;CAGvC,KAAK,OAAO,MAAM;CAClB,OAAO,eAAe,sBAAsB,QAAQ,GAAG,IAAI;AAC5D;AAmBA,MAAa,kBAAkB,EAC9B,gBACA,YACA,aACA,WAAW,MACX,YACA,sBACiC;CACjC,MAAM;CACN,MAAM;EACL;GACC,OAAO,SAAS,KAAK,QAAQ;GAC7B,QAAQ,CAAC,GAAG,kBAAkB,UAAU,UAAU,GAAG,GAAG,UAAU;EACnE;EACA;GACC,OAAO,SAAS,KAAK,aAAa;GAClC,QAAQ,CACP,aACA,eAAe,gBAAgB,KAAK,oBAAoB,cAAc,CACvE;EACD;EACA;GACC,OAAO,SAAS,KAAK,WAAW;GAChC,QAAQ;IACP,eAAe,eAAe,KAAK,mBAAmB,cAAc;IACpE;KACC,MAAM;KACN,MAAM;KACN,OAAO,SAAS,KAAK,YAAY;KACjC,OAAO,EAAE,aAAa,SAAS,KAAK,uBAAuB,EAAE;IAC9D;IACA,GAAI,kBAAkB,CAAC;GACxB;EACD;CACD;AACD"}
|
package/dist/fields/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { ConditionFieldType } from "../conditions/fieldTypes.js";
|
|
1
2
|
import { PollOption } from "../poll/definePollOptionSource.js";
|
|
2
3
|
import { FormFieldInstance } from "../submissions/types.js";
|
|
3
4
|
import { FileRef } from "../uploads/types.js";
|
|
4
|
-
import { ConditionFieldType } from "../conditions/fieldTypes.js";
|
|
5
5
|
import { Field, Payload, PayloadRequest } from "payload";
|
|
6
6
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
7
7
|
|
|
@@ -70,6 +70,11 @@ type FormFieldDefinition<K extends FormFieldValueKind = FormFieldValueKind, TCon
|
|
|
70
70
|
label: string;
|
|
71
71
|
value: K;
|
|
72
72
|
config?: Field[];
|
|
73
|
+
/**
|
|
74
|
+
* Extra per-type fields for the Advanced tab, after `visibleWhen`/`hidden`. Lets a type add
|
|
75
|
+
* behavior settings (e.g. `autocomplete`) without crowding the Field tab.
|
|
76
|
+
*/
|
|
77
|
+
advancedConfig?: Field[];
|
|
73
78
|
validate?: FormFieldValidate<K, TConfig>;
|
|
74
79
|
format?: FormFieldFormat<K, TConfig>;
|
|
75
80
|
Field?: string;
|
|
@@ -133,7 +138,8 @@ type AnyFormFieldDefinition = {
|
|
|
133
138
|
type: string;
|
|
134
139
|
label: string;
|
|
135
140
|
value: FormFieldValueKind;
|
|
136
|
-
config?: Field[];
|
|
141
|
+
config?: Field[]; /** See `FormFieldDefinition.advancedConfig`: extra per-type fields for the Advanced tab. */
|
|
142
|
+
advancedConfig?: Field[];
|
|
137
143
|
validate?: AnyFormFieldValidate;
|
|
138
144
|
format?: AnyFormFieldFormat;
|
|
139
145
|
Field?: string; /** See `FormFieldDefinition.blockLabel`: import-map ref for a custom block row Label. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PollOption } from "../poll/definePollOptionSource.js";
|
|
2
|
+
import { CalcResolved } from "../calc/evaluate.js";
|
|
2
3
|
import { ConsentStatements } from "../consent/resolveConsentStatements.js";
|
|
3
4
|
import { FormDocument } from "./types.js";
|
|
4
5
|
|
|
@@ -96,6 +97,12 @@ declare function toFormDocument(form: {
|
|
|
96
97
|
* An explicit `options.consentStatements` takes precedence when both are present.
|
|
97
98
|
*/
|
|
98
99
|
consentStatements?: ConsentStatements;
|
|
100
|
+
/**
|
|
101
|
+
* Calc source values resolved onto the doc by the plugin's forms `afterRead` hook (when calc
|
|
102
|
+
* sources are registered and used); passed through so the client's live preview computes with
|
|
103
|
+
* real values. `functions` can never ride a document, hence the Pick.
|
|
104
|
+
*/
|
|
105
|
+
calcResolved?: Pick<CalcResolved, 'sources' | 'weights'>;
|
|
99
106
|
}, options?: ToFormDocumentOptions): FormDocument;
|
|
100
107
|
//#endregion
|
|
101
108
|
export { ToFormDocumentOptions, toFormDocument };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toFormDocument.js","names":[],"sources":["../../src/form/toFormDocument.ts"],"sourcesContent":["import { applyConsentStatements } from '../consent/applyConsentStatements'\nimport type { ConsentStatements } from '../consent/resolveConsentStatements'\nimport type { FormFlow } from '../flow/types'\nimport { applyPollOptions } from '../poll/applyPollOptions'\nimport type { PollOption } from '../poll/definePollOptionSource'\nimport type { FormFieldInstance } from '../submissions/types'\nimport type { FormButtonSettings, FormDocument, FormResponseSettings } from './types'\n\nexport type ToFormDocumentOptions = {\n\t/**\n\t * Source-resolved poll options (from `resolvePollOptions`), injected as the options of the\n\t * field instance named by the form's `poll.resultsField` so the client renders the host's\n\t * current choices instead of hand-authored ones.\n\t */\n\tpollOptions?: PollOption[]\n\t/**\n\t * Source-resolved consent statements (from `resolveConsentStatements`), injected into the\n\t * consent field instances they name. A form stores only a source id, so without these its\n\t * consent fields render with no statement at all.\n\t */\n\tconsentStatements?: ConsentStatements\n\t/**\n\t * Resolve an internal redirect `reference` to a same-site URL. Called only when\n\t * `response.type === 'redirect'`, a `reference` is present, and no `redirect.url` is set. Keep it\n\t * sync: operate on the already-loaded (populated) reference, since resolving a Doc to a URL is host\n\t * routing knowledge the plugin cannot supply. The result is written to `redirect.url`, so `<Form>`\n\t * navigates with no client change.\n\t */\n\tresolveRedirect?: (reference: {\n\t\trelationTo: string\n\t\tvalue: number | string | object\n\t}) => string | null | undefined\n}\n\n/**\n * Reassemble the client button labels from the document's top-level `submitLabel`/`prevLabel`/\n * `nextLabel` fields, keeping only non-empty strings (mirroring the client's own `storedLabel`\n * fallback). Returns `undefined` when the author set no label, so the client uses its defaults.\n */\nconst buttonSettingsOf = (form: {\n\tsubmitLabel?: string | null\n\tprevLabel?: string | null\n\tnextLabel?: string | null\n}): FormButtonSettings | undefined => {\n\tconst label = (value: unknown): string | undefined =>\n\t\ttypeof value === 'string' && value.length > 0 ? value : undefined\n\tconst settings: FormButtonSettings = {}\n\tconst submitLabel = label(form.submitLabel)\n\tconst prevLabel = label(form.prevLabel)\n\tconst nextLabel = label(form.nextLabel)\n\tif (submitLabel !== undefined) settings.submitLabel = submitLabel\n\tif (prevLabel !== undefined) settings.prevLabel = prevLabel\n\tif (nextLabel !== undefined) settings.nextLabel = nextLabel\n\treturn Object.keys(settings).length > 0 ? settings : undefined\n}\n\n/**\n * Narrows a Payload-generated form document (from `getPayload().findByID()` or `fetch`) to\n * `FormDocument` without an unsafe `as` cast. Handles the small structural mismatches between\n * the auto-generated collection types and what `<Form>` expects:\n * - `fields` may be a typed blocks-union array or null; normalized to `FormFieldInstance[]`\n * (nameless bare rows, e.g. message blocks, pass through with their row `id` intact)\n * - `flow` is stored as opaque JSON; typed as `FormFlow | undefined`\n * - `response` may be null; coerced to `undefined`, otherwise passed through wholesale, which\n * includes `response.redirect.reference` (present only when the plugin's `redirectRelationships`\n * option is set): `value` may be a bare id (`depth: 0`) or a populated document, and the host\n * resolves it to a URL either by writing `redirect.url` or by passing `options.resolveRedirect`\n * - the button labels (`submitLabel`/`prevLabel`/`nextLabel`) live at the document root now (there\n * is no `buttons` group); the non-empty ones are reassembled into `FormDocument.buttons`\n * - `title` may be null; coerced to `undefined`\n * - `multistep`/`pollEnabled` are the two top-level form-type flags, coerced to strict booleans\n * - `poll` may be null; coerced to `undefined` (`resultsField`, `optionSource`, and\n * `sourceConfig` are dropped: server-side only; `outcome` passes through `winningValues` only)\n *\n * Unknown keys survive on `response` but not on `poll`, which is deliberate rather than incidental.\n * `response` is a visitor-facing group a host is meant to extend (`overrides.forms.fields`) and read\n * back off `FormDocument` in custom chrome, so it is cast wholesale. `poll` is plugin-owned config\n * that is split between\n * client-safe lifecycle state and server-only members, so it is rebuilt from an allowlist: a\n * passthrough would ship whatever a host put in `sourceConfig` (domain config, ids, credentials)\n * to every anonymous visitor. Adding a client-visible poll member means naming it here.\n *\n * Pure and framework-agnostic (no 'use client'): safe to call from a Server Component or any\n * other server-side code before handing the result to the client `<Form>`.\n */\nexport function toFormDocument(\n\tform: {\n\t\tid: number | string\n\t\tfields?: { blockType: string; name?: string; [key: string]: unknown }[] | null\n\t\tflow?: unknown\n\t\tresponse?: {\n\t\t\ttype?: string | null\n\t\t\tmessage?: unknown\n\t\t\tredirect?: {\n\t\t\t\turl?: string | null\n\t\t\t\treference?: { relationTo?: string | null; value?: number | string | object | null } | null\n\t\t\t} | null\n\t\t} | null\n\t\tsubmitLabel?: string | null\n\t\tprevLabel?: string | null\n\t\tnextLabel?: string | null\n\t\ttitle?: string | null\n\t\tmultistep?: boolean | null\n\t\tpollEnabled?: boolean | null\n\t\tpoll?: {\n\t\t\tresultsField?: string | null\n\t\t\tresultsVisibility?: string | null\n\t\t\tclosesAt?: string | null\n\t\t\toutcome?: { winningValues?: (string | null)[] | null } | null\n\t\t} | null\n\t\t/**\n\t\t * Consent statements resolved onto the doc by the plugin's forms `afterRead` hook (when\n\t\t * `consent.sources` is set), so consent renders on any fetch path (modal/client, not just RSC).\n\t\t * An explicit `options.consentStatements` takes precedence when both are present.\n\t\t */\n\t\tconsentStatements?: ConsentStatements\n\t},\n\toptions?: ToFormDocumentOptions\n): FormDocument {\n\tconst rawWinningValues = form.poll?.outcome?.winningValues\n\tconst winningValues = Array.isArray(rawWinningValues)\n\t\t? rawWinningValues.filter(\n\t\t\t\t(value): value is string => typeof value === 'string' && value.length > 0\n\t\t\t)\n\t\t: []\n\tconst poll = form.poll\n\t\t? {\n\t\t\t\tresultsVisibility: (form.poll.resultsVisibility ?? undefined) as\n\t\t\t\t\t| 'afterVote'\n\t\t\t\t\t| 'afterClose'\n\t\t\t\t\t| undefined,\n\t\t\t\tclosesAt: form.poll.closesAt ?? undefined,\n\t\t\t\t...(winningValues.length > 0 ? { outcome: { winningValues } } : {}),\n\t\t\t}\n\t\t: undefined\n\tlet fields = (form.fields ?? []) as FormFieldInstance[]\n\tif (options?.pollOptions) {\n\t\tfields = applyPollOptions(fields, form.poll?.resultsField, options.pollOptions)\n\t}\n\tconst consentStatements = options?.consentStatements ?? form.consentStatements\n\tif (consentStatements) {\n\t\tfields = applyConsentStatements(fields, consentStatements)\n\t}\n\tlet response = (form.response as FormResponseSettings | null | undefined) ?? undefined\n\t// A host that passes `resolveRedirect` gets internal references turned into `redirect.url` (all\n\t// `<Form>` navigates by), but only when the author set no explicit url. Non-mutating: clone the group.\n\tif (\n\t\toptions?.resolveRedirect &&\n\t\tresponse?.type === 'redirect' &&\n\t\tresponse.redirect?.reference &&\n\t\t!response.redirect.url\n\t) {\n\t\tconst url = options.resolveRedirect(response.redirect.reference)\n\t\tif (url) {\n\t\t\tresponse = { ...response, redirect: { ...response.redirect, url } }\n\t\t}\n\t}\n\treturn {\n\t\tid: form.id,\n\t\tfields,\n\t\tflow: form.flow as FormFlow | undefined,\n\t\tresponse,\n\t\tbuttons: buttonSettingsOf(form),\n\t\ttitle: form.title ?? undefined,\n\t\tmultistep: form.multistep === true,\n\t\tpollEnabled: form.pollEnabled === true,\n\t\tpoll,\n\t}\n}\n"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"toFormDocument.js","names":[],"sources":["../../src/form/toFormDocument.ts"],"sourcesContent":["import type { CalcResolved } from '../calc/evaluate'\nimport { applyConsentStatements } from '../consent/applyConsentStatements'\nimport type { ConsentStatements } from '../consent/resolveConsentStatements'\nimport type { FormFlow } from '../flow/types'\nimport { applyPollOptions } from '../poll/applyPollOptions'\nimport type { PollOption } from '../poll/definePollOptionSource'\nimport type { FormFieldInstance } from '../submissions/types'\nimport type { FormButtonSettings, FormDocument, FormResponseSettings } from './types'\n\nexport type ToFormDocumentOptions = {\n\t/**\n\t * Source-resolved poll options (from `resolvePollOptions`), injected as the options of the\n\t * field instance named by the form's `poll.resultsField` so the client renders the host's\n\t * current choices instead of hand-authored ones.\n\t */\n\tpollOptions?: PollOption[]\n\t/**\n\t * Source-resolved consent statements (from `resolveConsentStatements`), injected into the\n\t * consent field instances they name. A form stores only a source id, so without these its\n\t * consent fields render with no statement at all.\n\t */\n\tconsentStatements?: ConsentStatements\n\t/**\n\t * Resolve an internal redirect `reference` to a same-site URL. Called only when\n\t * `response.type === 'redirect'`, a `reference` is present, and no `redirect.url` is set. Keep it\n\t * sync: operate on the already-loaded (populated) reference, since resolving a Doc to a URL is host\n\t * routing knowledge the plugin cannot supply. The result is written to `redirect.url`, so `<Form>`\n\t * navigates with no client change.\n\t */\n\tresolveRedirect?: (reference: {\n\t\trelationTo: string\n\t\tvalue: number | string | object\n\t}) => string | null | undefined\n}\n\n/**\n * Reassemble the client button labels from the document's top-level `submitLabel`/`prevLabel`/\n * `nextLabel` fields, keeping only non-empty strings (mirroring the client's own `storedLabel`\n * fallback). Returns `undefined` when the author set no label, so the client uses its defaults.\n */\nconst buttonSettingsOf = (form: {\n\tsubmitLabel?: string | null\n\tprevLabel?: string | null\n\tnextLabel?: string | null\n}): FormButtonSettings | undefined => {\n\tconst label = (value: unknown): string | undefined =>\n\t\ttypeof value === 'string' && value.length > 0 ? value : undefined\n\tconst settings: FormButtonSettings = {}\n\tconst submitLabel = label(form.submitLabel)\n\tconst prevLabel = label(form.prevLabel)\n\tconst nextLabel = label(form.nextLabel)\n\tif (submitLabel !== undefined) settings.submitLabel = submitLabel\n\tif (prevLabel !== undefined) settings.prevLabel = prevLabel\n\tif (nextLabel !== undefined) settings.nextLabel = nextLabel\n\treturn Object.keys(settings).length > 0 ? settings : undefined\n}\n\n/**\n * Narrows a Payload-generated form document (from `getPayload().findByID()` or `fetch`) to\n * `FormDocument` without an unsafe `as` cast. Handles the small structural mismatches between\n * the auto-generated collection types and what `<Form>` expects:\n * - `fields` may be a typed blocks-union array or null; normalized to `FormFieldInstance[]`\n * (nameless bare rows, e.g. message blocks, pass through with their row `id` intact)\n * - `flow` is stored as opaque JSON; typed as `FormFlow | undefined`\n * - `response` may be null; coerced to `undefined`, otherwise passed through wholesale, which\n * includes `response.redirect.reference` (present only when the plugin's `redirectRelationships`\n * option is set): `value` may be a bare id (`depth: 0`) or a populated document, and the host\n * resolves it to a URL either by writing `redirect.url` or by passing `options.resolveRedirect`\n * - the button labels (`submitLabel`/`prevLabel`/`nextLabel`) live at the document root now (there\n * is no `buttons` group); the non-empty ones are reassembled into `FormDocument.buttons`\n * - `title` may be null; coerced to `undefined`\n * - `multistep`/`pollEnabled` are the two top-level form-type flags, coerced to strict booleans\n * - `poll` may be null; coerced to `undefined` (`resultsField`, `optionSource`, and\n * `sourceConfig` are dropped: server-side only; `outcome` passes through `winningValues` only)\n *\n * Unknown keys survive on `response` but not on `poll`, which is deliberate rather than incidental.\n * `response` is a visitor-facing group a host is meant to extend (`overrides.forms.fields`) and read\n * back off `FormDocument` in custom chrome, so it is cast wholesale. `poll` is plugin-owned config\n * that is split between\n * client-safe lifecycle state and server-only members, so it is rebuilt from an allowlist: a\n * passthrough would ship whatever a host put in `sourceConfig` (domain config, ids, credentials)\n * to every anonymous visitor. Adding a client-visible poll member means naming it here.\n *\n * Pure and framework-agnostic (no 'use client'): safe to call from a Server Component or any\n * other server-side code before handing the result to the client `<Form>`.\n */\nexport function toFormDocument(\n\tform: {\n\t\tid: number | string\n\t\tfields?: { blockType: string; name?: string; [key: string]: unknown }[] | null\n\t\tflow?: unknown\n\t\tresponse?: {\n\t\t\ttype?: string | null\n\t\t\tmessage?: unknown\n\t\t\tredirect?: {\n\t\t\t\turl?: string | null\n\t\t\t\treference?: { relationTo?: string | null; value?: number | string | object | null } | null\n\t\t\t} | null\n\t\t} | null\n\t\tsubmitLabel?: string | null\n\t\tprevLabel?: string | null\n\t\tnextLabel?: string | null\n\t\ttitle?: string | null\n\t\tmultistep?: boolean | null\n\t\tpollEnabled?: boolean | null\n\t\tpoll?: {\n\t\t\tresultsField?: string | null\n\t\t\tresultsVisibility?: string | null\n\t\t\tclosesAt?: string | null\n\t\t\toutcome?: { winningValues?: (string | null)[] | null } | null\n\t\t} | null\n\t\t/**\n\t\t * Consent statements resolved onto the doc by the plugin's forms `afterRead` hook (when\n\t\t * `consent.sources` is set), so consent renders on any fetch path (modal/client, not just RSC).\n\t\t * An explicit `options.consentStatements` takes precedence when both are present.\n\t\t */\n\t\tconsentStatements?: ConsentStatements\n\t\t/**\n\t\t * Calc source values resolved onto the doc by the plugin's forms `afterRead` hook (when calc\n\t\t * sources are registered and used); passed through so the client's live preview computes with\n\t\t * real values. `functions` can never ride a document, hence the Pick.\n\t\t */\n\t\tcalcResolved?: Pick<CalcResolved, 'sources' | 'weights'>\n\t},\n\toptions?: ToFormDocumentOptions\n): FormDocument {\n\tconst rawWinningValues = form.poll?.outcome?.winningValues\n\tconst winningValues = Array.isArray(rawWinningValues)\n\t\t? rawWinningValues.filter(\n\t\t\t\t(value): value is string => typeof value === 'string' && value.length > 0\n\t\t\t)\n\t\t: []\n\tconst poll = form.poll\n\t\t? {\n\t\t\t\tresultsVisibility: (form.poll.resultsVisibility ?? undefined) as\n\t\t\t\t\t| 'afterVote'\n\t\t\t\t\t| 'afterClose'\n\t\t\t\t\t| undefined,\n\t\t\t\tclosesAt: form.poll.closesAt ?? undefined,\n\t\t\t\t...(winningValues.length > 0 ? { outcome: { winningValues } } : {}),\n\t\t\t}\n\t\t: undefined\n\tlet fields = (form.fields ?? []) as FormFieldInstance[]\n\tif (options?.pollOptions) {\n\t\tfields = applyPollOptions(fields, form.poll?.resultsField, options.pollOptions)\n\t}\n\tconst consentStatements = options?.consentStatements ?? form.consentStatements\n\tif (consentStatements) {\n\t\tfields = applyConsentStatements(fields, consentStatements)\n\t}\n\tlet response = (form.response as FormResponseSettings | null | undefined) ?? undefined\n\t// A host that passes `resolveRedirect` gets internal references turned into `redirect.url` (all\n\t// `<Form>` navigates by), but only when the author set no explicit url. Non-mutating: clone the group.\n\tif (\n\t\toptions?.resolveRedirect &&\n\t\tresponse?.type === 'redirect' &&\n\t\tresponse.redirect?.reference &&\n\t\t!response.redirect.url\n\t) {\n\t\tconst url = options.resolveRedirect(response.redirect.reference)\n\t\tif (url) {\n\t\t\tresponse = { ...response, redirect: { ...response.redirect, url } }\n\t\t}\n\t}\n\treturn {\n\t\tid: form.id,\n\t\tfields,\n\t\tflow: form.flow as FormFlow | undefined,\n\t\tresponse,\n\t\tbuttons: buttonSettingsOf(form),\n\t\ttitle: form.title ?? undefined,\n\t\tmultistep: form.multistep === true,\n\t\tpollEnabled: form.pollEnabled === true,\n\t\tpoll,\n\t\tcalcResolved: form.calcResolved,\n\t}\n}\n"],"mappings":";;;;;;;;AAwCA,MAAM,oBAAoB,SAIY;CACrC,MAAM,SAAS,UACd,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;CACzD,MAAM,WAA+B,CAAC;CACtC,MAAM,cAAc,MAAM,KAAK,WAAW;CAC1C,MAAM,YAAY,MAAM,KAAK,SAAS;CACtC,MAAM,YAAY,MAAM,KAAK,SAAS;CACtC,IAAI,gBAAgB,KAAA,GAAW,SAAS,cAAc;CACtD,IAAI,cAAc,KAAA,GAAW,SAAS,YAAY;CAClD,IAAI,cAAc,KAAA,GAAW,SAAS,YAAY;CAClD,OAAO,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAI,WAAW,KAAA;AACtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,eACf,MAqCA,SACe;CACf,MAAM,mBAAmB,KAAK,MAAM,SAAS;CAC7C,MAAM,gBAAgB,MAAM,QAAQ,gBAAgB,IACjD,iBAAiB,QAChB,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CACzE,IACC,CAAC;CACJ,MAAM,OAAO,KAAK,OACf;EACA,mBAAoB,KAAK,KAAK,qBAAqB,KAAA;EAInD,UAAU,KAAK,KAAK,YAAY,KAAA;EAChC,GAAI,cAAc,SAAS,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,CAAC;CAClE,IACC,KAAA;CACH,IAAI,SAAU,KAAK,UAAU,CAAC;CAC9B,IAAI,SAAS,aACZ,SAAS,iBAAiB,QAAQ,KAAK,MAAM,cAAc,QAAQ,WAAW;CAE/E,MAAM,oBAAoB,SAAS,qBAAqB,KAAK;CAC7D,IAAI,mBACH,SAAS,uBAAuB,QAAQ,iBAAiB;CAE1D,IAAI,WAAY,KAAK,YAAwD,KAAA;CAG7E,IACC,SAAS,mBACT,UAAU,SAAS,cACnB,SAAS,UAAU,aACnB,CAAC,SAAS,SAAS,KAClB;EACD,MAAM,MAAM,QAAQ,gBAAgB,SAAS,SAAS,SAAS;EAC/D,IAAI,KACH,WAAW;GAAE,GAAG;GAAU,UAAU;IAAE,GAAG,SAAS;IAAU;GAAI;EAAE;CAEpE;CACA,OAAO;EACN,IAAI,KAAK;EACT;EACA,MAAM,KAAK;EACX;EACA,SAAS,iBAAiB,IAAI;EAC9B,OAAO,KAAK,SAAS,KAAA;EACrB,WAAW,KAAK,cAAc;EAC9B,aAAa,KAAK,gBAAgB;EAClC;EACA,cAAc,KAAK;CACpB;AACD"}
|
package/dist/form/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FormFieldInstance } from "../submissions/types.js";
|
|
2
|
+
import { CalcResolved } from "../calc/evaluate.js";
|
|
2
3
|
import { FormFlow } from "../flow/types.js";
|
|
3
4
|
|
|
4
5
|
//#region src/form/types.d.ts
|
|
@@ -59,6 +60,12 @@ type FormDocument = {
|
|
|
59
60
|
multistep: boolean; /** Whether this form is a poll. Gates poll rendering and results; the poll config lives under `poll`. */
|
|
60
61
|
pollEnabled: boolean;
|
|
61
62
|
poll?: FormPollSettings;
|
|
63
|
+
/**
|
|
64
|
+
* Server-resolved calc source values, stamped by the plugin's forms afterRead hook when calc
|
|
65
|
+
* sources are registered and the form's expressions use them. Only `sources`/`weights` can ride
|
|
66
|
+
* the document, hence the Pick (`functions` cannot serialize; the client supplies those itself).
|
|
67
|
+
*/
|
|
68
|
+
calcResolved?: Pick<CalcResolved, 'sources' | 'weights'>;
|
|
62
69
|
};
|
|
63
70
|
//#endregion
|
|
64
71
|
export { FormButtonSettings, FormDocument, FormPollSettings, FormResponseSettings };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import { CalcExpression } from "./calc/types.js";
|
|
1
2
|
import { AnyPollOptionSource, PollOption, PollOptionResolveArgs, PollOptionSource, definePollOptionSource } from "./poll/definePollOptionSource.js";
|
|
2
3
|
import { FileFieldConfig, FileRef, FileRefError } from "./uploads/types.js";
|
|
3
4
|
import { AnyFormFieldDefinition, FormFieldDefinition, FormFieldFormat, FormFieldValidate, FormFieldValueKind, OmittableSharedField, ResolveFieldOptionsArgs } from "./fields/types.js";
|
|
5
|
+
import { CalcAllowed, normalizeCalc } from "./calc/normalizeCalc.js";
|
|
4
6
|
import { BodyConverter, BodyConverterArgs, BodyRender, defaultBodyConverters, sanitizeUrl } from "./actions/body/converters.js";
|
|
5
7
|
import { BodyContext, RichTextBodyOption, SerializeBodyArgs, serializeBody } from "./actions/body/serializeBody.js";
|
|
6
8
|
import { textOfBody } from "./actions/body/textOfBody.js";
|
|
7
9
|
import { AggregationBucket, AggregationRow, FieldAggregation, FieldMeta, SubmissionStatusFilter } from "./aggregation/types.js";
|
|
8
|
-
import {
|
|
10
|
+
import { CalcResolved, calcWeightKey, evaluateCalc } from "./calc/evaluate.js";
|
|
9
11
|
import { calcExpressionOf, computeCalcFields } from "./calc/computeCalcFields.js";
|
|
10
|
-
import {
|
|
12
|
+
import { formatCalc } from "./calc/formatCalc.js";
|
|
13
|
+
import { CalcDisplayConfig, formatCalcValue } from "./calc/formatCalcValue.js";
|
|
11
14
|
import { evaluateCondition } from "./conditions/evaluate.js";
|
|
12
15
|
import { ConsentSourceEntry, ConsentSourcePage, ConsentSourcesResolver } from "./consent/types.js";
|
|
13
16
|
import { ConsentStatement, ConsentStatements, ResolveConsentStatementsArgs, resolveConsentStatements } from "./consent/resolveConsentStatements.js";
|
|
@@ -44,7 +47,9 @@ import { ConsentSourceOption, ResolveConsentSourcesRequestArgs, ResolveConsentSo
|
|
|
44
47
|
import { ResolvePublishedVersionRefArgs, resolvePublishedVersionRef } from "./consent/resolvePublishedVersionRef.js";
|
|
45
48
|
import { DepartmentEmailsResolver, DepartmentOption, ResolveDepartmentOptionsArgs, ResolveDepartmentsRequestArgs, ResolveDepartmentsRequestResult, resolveDepartmentOptions } from "./email/departments.js";
|
|
46
49
|
import { RecipientResolveArgs, RecipientSource, RecipientSourceRegistry } from "./actions/recipientSources.js";
|
|
50
|
+
import { CalcFunction, CalcSource, CalcSourceResolveArgs, CalcWeightResolveArgs, defineCalcFunction, defineCalcSource } from "./calc/registry.js";
|
|
47
51
|
import { RedirectFieldsOverride, RedirectOption, ResponseOption } from "./collections/redirectFields.js";
|
|
52
|
+
import { DefaultSettingsFields, SettingsFieldsOverride, SettingsOption, buildDefaultSettingsFields } from "./collections/settingsFields.js";
|
|
48
53
|
import { CaptchaProvider, CaptchaVerifyArgs, IdentifyFn, RateLimitCheckArgs, RateLimitConfig, RateLimitResult, RateLimiter, SpamConfig, SpamMetadataConfig, SpamOption } from "./spam/types.js";
|
|
49
54
|
import { UploadsOption } from "./plugin/uploadsCollection.js";
|
|
50
55
|
import { DefaultOutcomeFields, OutcomeFieldsOverride, buildDefaultOutcomeFields, buildResolvedAtField, buildWinningValuesField } from "./poll/outcomeFields.js";
|
|
@@ -57,7 +62,7 @@ import { renderAllValues, renderAllValuesTable } from "./actions/body/wildcards.
|
|
|
57
62
|
import { buildDefaultActionDefinitions, defaultActionDefinitions } from "./actions/builtin/index.js";
|
|
58
63
|
import { SIGNATURE_HEADER, signPayload } from "./actions/sign.js";
|
|
59
64
|
import { aggregateRowForField, aggregateRowsForFields } from "./aggregation/aggregateRows.js";
|
|
60
|
-
import {
|
|
65
|
+
import { ResolveCalcContextArgs, calcUsesSources, resolveCalcContext } from "./calc/resolveCalcContext.js";
|
|
61
66
|
import { applyConsentStatements } from "./consent/applyConsentStatements.js";
|
|
62
67
|
import { DepartmentsFieldOptions, departmentsField } from "./email/departmentsField.js";
|
|
63
68
|
import { buildDefaultFieldDefinitions, defaultFieldDefinitions, defaultFieldDefinitionsByType } from "./fields/builtin/index.js";
|
|
@@ -68,6 +73,9 @@ import { defineFormField } from "./fields/defineFormField.js";
|
|
|
68
73
|
import { localizedIf } from "./fields/localizedIf.js";
|
|
69
74
|
import { POLL_CLOSE_TASK_SLUG, PollCloseTaskInput, buildPollCloseTask, enqueuePollClose, registerPollCloseTask, runPollClose, shouldAutoResolvePoll } from "./poll/closeJob.js";
|
|
70
75
|
import { mostVotedStrategy, topBucketValues } from "./poll/mostVoted.js";
|
|
76
|
+
import { aggregateFromVotes } from "./poll/votes/aggregateFromVotes.js";
|
|
77
|
+
import { recountPollVotes } from "./poll/votes/recountPollVotes.js";
|
|
78
|
+
import { POLL_VOTES_SLUG, RESPONDENTS_VALUE, VOTE_SHARDS } from "./poll/votes/votesCollection.js";
|
|
71
79
|
import { DEFAULT_PRESENTATION_NAME, defaultPresentationDescriptors } from "./presentations/defaults.js";
|
|
72
80
|
import { defineCaptchaProvider } from "./spam/captcha.js";
|
|
73
81
|
import { defaultIdentify } from "./spam/identify.js";
|
|
@@ -86,5 +94,5 @@ import { FieldTargetParamOptions, fieldTargetParam } from "./validation/fieldTar
|
|
|
86
94
|
//#region src/index.d.ts
|
|
87
95
|
declare const formBuilder: (options: FormBuilderPluginOptions) => import("payload").Plugin;
|
|
88
96
|
//#endregion
|
|
89
|
-
export { type ActionDefinition, type ActionOption, type ActionRegistry, type ActionResult, type ActionRunArgs, type ActionsConfig, type AggregateFieldResponsesArgs, type AggregateFormResponsesArgs, type AggregationBucket, type AggregationRow, type AnyActionDefinition, type AnyFormFieldDefinition, type AnyPollOptionSource, type AnyValidationRuleDefinition, type BodyContext, type BodyConverter, type BodyConverterArgs, type BodyRender, type ButtonFieldsOverride, type ButtonsOption, CAPTCHA_TOKEN_KEY, type CalcExpression, type CaptchaProvider, type CaptchaVerifyArgs, type ConsentProof, type ConsentSnapshotMode, type ConsentSourceEntry, type ConsentSourceOption, type ConsentSourcePage, type ConsentSourcesFieldOptions, type ConsentSourcesResolver, type ConsentStatement, type ConsentStatements, type CreateSubmissionArgs, type CreatedSubmission, DEFAULT_HONEYPOT_FIELD, DEFAULT_PRESENTATION_NAME, type DefaultButtonFields, type DefaultOutcomeFields, type DepartmentEmailsResolver, type DepartmentOption, type DepartmentsFieldOptions, type FieldAggregation, type FieldCondition, type FieldMeta, type FieldTargetParamOptions, type FieldTypeOption, type FieldTypeRegistry, type FieldTypesConfig, type FileFieldConfig, type FileRef, type FileRefError, type FormBuilderPluginOptions, type FormButtonSettings, type FormContextReference, type FormDocument, type FormFieldDefinition, type FormFieldFormat, type FormFieldValidate, type FormFieldValueKind, type FormPollSettings, type FormResponseSettings, type FormResultsAccess, type FormResultsAccessArgs, type FromAddressOption, type FromAddressesResolver, type HcaptchaProviderOptions, type IdentifyFn, type OmittableSharedField, type OutcomeFieldsOverride, POLL_CLOSE_TASK_SLUG, type FormBuilderPluginOptions as PluginOptions, type PollCloseTaskInput, type PollOption, type PollOptionResolveArgs, type PollOptionSource, type PollOptionSourceOption, type PollOptionSourceRegistry, type PollOptionSourcesConfig, type PollOutcomeStrategy, type PollOutcomeStrategyArgs, type PollTypeRegistry, type PollTypesConfig, type PrefillOptions, type PresentationDensity, type PresentationDescriptor, type PresentationSurface, type RateLimitCheckArgs, type RateLimitConfig, type RateLimitResult, type RateLimiter, type RecallResolver, type RecaptchaProviderOptions, type RecipientResolveArgs, type RecipientSource, type RecipientSourceRegistry, type RedirectFieldsOverride, type RedirectOption, type ResolveConsentEntriesArgs, type ResolveConsentSourcesRequestArgs, type ResolveConsentSourcesRequestResult, type ResolveConsentStatementsArgs, type ResolveDepartmentOptionsArgs, type ResolveDepartmentsRequestArgs, type ResolveDepartmentsRequestResult, type ResolveEffectivePollOptionsArgs, type ResolveFieldOptionsArgs, type ResolvePollOptionsArgs, type ResolvePollOutcomeArgs, type ResolvePublishedVersionRefArgs, type ResolveResultsRequestArgs, type ResolveResultsRequestResult, type ResponseOption, type RichTextBodyOption, SIGNATURE_HEADER, type SerializeBodyArgs, type SpamConfig, type SpamMetadataConfig, type SpamOption, type SubmissionStatusFilter, type ToFormDocumentOptions, type TurnstileProviderOptions, type UploadsOption, type ValidationRuleDefinition, type ValidationRuleOption, type ValidationRuleRegistry, type ValidationRuleResult, type ValidationRulesConfig, aggregateFieldResponses, aggregateFormResponses, aggregateRowForField, aggregateRowsForFields, applyConsentStatements, buildDefaultActionDefinitions, buildDefaultButtonFields, buildDefaultFieldDefinitions, buildDefaultOutcomeFields, buildNextLabelField, buildPollCloseTask, buildPrevLabelField, buildRecallResolver, buildResolvedAtField, buildSubmitLabelField, buildWinningValuesField, calcExpressionOf, captureConsent, captureFileRef, computeCalcFields, consentSourcesField, countryField, createKvRateLimiter, createSubmission, defaultActionDefinitions, defaultBodyConverters, defaultFieldDefinitions, defaultFieldDefinitionsByType, defaultIdentify, defaultPresentationDescriptors, defaultValidationRules, defaultValidationRulesByType, defineAction, defineCaptchaProvider, defineFormField, definePollOptionSource, definePollType, defineValidationRule, departmentsField, enqueuePollClose, escapeHtml, evaluateCalc, evaluateCondition, fieldHasOptions, fieldKey, fieldTargetParam, fileMimeTypeOptions, formBuilder, formatBytes, hasVotedCookie, hcaptchaProvider, interpolate, isPollClosed, localizedIf, manualStrategy, mostVotedStrategy, normalizeCalc, optionLabelsFor, pollTypesOf, recaptchaProvider, registerPollCloseTask, renderAllValues, renderAllValuesTable, resolveActions, resolveConsentEntries, resolveConsentSourcesRequest, resolveConsentStatements, resolveDepartmentOptions, resolveEffectivePollOptions, resolveFileRef, resolveFormResultsRequest, resolvePollOptionSources, resolvePollOptions, resolvePollOutcome, resolvePollTypes, resolvePublishedVersionRef, resolveSpamConfig, runPollClose, sanitizeUrl, serializeBody, shouldAutoResolvePoll, signFormContext, signPayload, sourceStrategy, stashPollTypes, stateField, textOfBody, toFormDocument, topBucketValues, turnstileProvider, valuesFromSearchParams, verifyFormContext, votedCookieName };
|
|
97
|
+
export { type ActionDefinition, type ActionOption, type ActionRegistry, type ActionResult, type ActionRunArgs, type ActionsConfig, type AggregateFieldResponsesArgs, type AggregateFormResponsesArgs, type AggregationBucket, type AggregationRow, type AnyActionDefinition, type AnyFormFieldDefinition, type AnyPollOptionSource, type AnyValidationRuleDefinition, type BodyContext, type BodyConverter, type BodyConverterArgs, type BodyRender, type ButtonFieldsOverride, type ButtonsOption, CAPTCHA_TOKEN_KEY, type CalcAllowed, type CalcDisplayConfig, type CalcExpression, type CalcFunction, type CalcResolved, type CalcSource, type CalcSourceResolveArgs, type CalcWeightResolveArgs, type CaptchaProvider, type CaptchaVerifyArgs, type ConsentProof, type ConsentSnapshotMode, type ConsentSourceEntry, type ConsentSourceOption, type ConsentSourcePage, type ConsentSourcesFieldOptions, type ConsentSourcesResolver, type ConsentStatement, type ConsentStatements, type CreateSubmissionArgs, type CreatedSubmission, DEFAULT_HONEYPOT_FIELD, DEFAULT_PRESENTATION_NAME, type DefaultButtonFields, type DefaultOutcomeFields, type DefaultSettingsFields, type DepartmentEmailsResolver, type DepartmentOption, type DepartmentsFieldOptions, type FieldAggregation, type FieldCondition, type FieldMeta, type FieldTargetParamOptions, type FieldTypeOption, type FieldTypeRegistry, type FieldTypesConfig, type FileFieldConfig, type FileRef, type FileRefError, type FormBuilderPluginOptions, type FormButtonSettings, type FormContextReference, type FormDocument, type FormFieldDefinition, type FormFieldFormat, type FormFieldValidate, type FormFieldValueKind, type FormPollSettings, type FormResponseSettings, type FormResultsAccess, type FormResultsAccessArgs, type FromAddressOption, type FromAddressesResolver, type HcaptchaProviderOptions, type IdentifyFn, type OmittableSharedField, type OutcomeFieldsOverride, POLL_CLOSE_TASK_SLUG, POLL_VOTES_SLUG, type FormBuilderPluginOptions as PluginOptions, type PollCloseTaskInput, type PollOption, type PollOptionResolveArgs, type PollOptionSource, type PollOptionSourceOption, type PollOptionSourceRegistry, type PollOptionSourcesConfig, type PollOutcomeStrategy, type PollOutcomeStrategyArgs, type PollTypeRegistry, type PollTypesConfig, type PrefillOptions, type PresentationDensity, type PresentationDescriptor, type PresentationSurface, RESPONDENTS_VALUE, type RateLimitCheckArgs, type RateLimitConfig, type RateLimitResult, type RateLimiter, type RecallResolver, type RecaptchaProviderOptions, type RecipientResolveArgs, type RecipientSource, type RecipientSourceRegistry, type RedirectFieldsOverride, type RedirectOption, type ResolveCalcContextArgs, type ResolveConsentEntriesArgs, type ResolveConsentSourcesRequestArgs, type ResolveConsentSourcesRequestResult, type ResolveConsentStatementsArgs, type ResolveDepartmentOptionsArgs, type ResolveDepartmentsRequestArgs, type ResolveDepartmentsRequestResult, type ResolveEffectivePollOptionsArgs, type ResolveFieldOptionsArgs, type ResolvePollOptionsArgs, type ResolvePollOutcomeArgs, type ResolvePublishedVersionRefArgs, type ResolveResultsRequestArgs, type ResolveResultsRequestResult, type ResponseOption, type RichTextBodyOption, SIGNATURE_HEADER, type SerializeBodyArgs, type SettingsFieldsOverride, type SettingsOption, type SpamConfig, type SpamMetadataConfig, type SpamOption, type SubmissionStatusFilter, type ToFormDocumentOptions, type TurnstileProviderOptions, type UploadsOption, VOTE_SHARDS, type ValidationRuleDefinition, type ValidationRuleOption, type ValidationRuleRegistry, type ValidationRuleResult, type ValidationRulesConfig, aggregateFieldResponses, aggregateFormResponses, aggregateFromVotes, aggregateRowForField, aggregateRowsForFields, applyConsentStatements, buildDefaultActionDefinitions, buildDefaultButtonFields, buildDefaultFieldDefinitions, buildDefaultOutcomeFields, buildDefaultSettingsFields, buildNextLabelField, buildPollCloseTask, buildPrevLabelField, buildRecallResolver, buildResolvedAtField, buildSubmitLabelField, buildWinningValuesField, calcExpressionOf, calcUsesSources, calcWeightKey, captureConsent, captureFileRef, computeCalcFields, consentSourcesField, countryField, createKvRateLimiter, createSubmission, defaultActionDefinitions, defaultBodyConverters, defaultFieldDefinitions, defaultFieldDefinitionsByType, defaultIdentify, defaultPresentationDescriptors, defaultValidationRules, defaultValidationRulesByType, defineAction, defineCalcFunction, defineCalcSource, defineCaptchaProvider, defineFormField, definePollOptionSource, definePollType, defineValidationRule, departmentsField, enqueuePollClose, escapeHtml, evaluateCalc, evaluateCondition, fieldHasOptions, fieldKey, fieldTargetParam, fileMimeTypeOptions, formBuilder, formatBytes, formatCalc, formatCalcValue, hasVotedCookie, hcaptchaProvider, interpolate, isPollClosed, localizedIf, manualStrategy, mostVotedStrategy, normalizeCalc, optionLabelsFor, pollTypesOf, recaptchaProvider, recountPollVotes, registerPollCloseTask, renderAllValues, renderAllValuesTable, resolveActions, resolveCalcContext, resolveConsentEntries, resolveConsentSourcesRequest, resolveConsentStatements, resolveDepartmentOptions, resolveEffectivePollOptions, resolveFileRef, resolveFormResultsRequest, resolvePollOptionSources, resolvePollOptions, resolvePollOutcome, resolvePollTypes, resolvePublishedVersionRef, resolveSpamConfig, runPollClose, sanitizeUrl, serializeBody, shouldAutoResolvePoll, signFormContext, signPayload, sourceStrategy, stashPollTypes, stateField, textOfBody, toFormDocument, topBucketValues, turnstileProvider, valuesFromSearchParams, verifyFormContext, votedCookieName };
|
|
90
98
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -9,33 +9,39 @@ import { defineAction } from "./actions/defineAction.js";
|
|
|
9
9
|
import { SIGNATURE_HEADER, signPayload } from "./actions/sign.js";
|
|
10
10
|
import { buildDefaultActionDefinitions, defaultActionDefinitions } from "./actions/builtin/index.js";
|
|
11
11
|
import { resolveActions } from "./actions/registry.js";
|
|
12
|
+
import { assertNoCalcFunctionCollision, assertValidCalcSourceKeys, defineCalcFunction, defineCalcSource } from "./calc/registry.js";
|
|
12
13
|
import { resolveConsentEntries, stashConsentSources } from "./consent/resolveConsentEntries.js";
|
|
14
|
+
import { formatCalcValue } from "./calc/formatCalcValue.js";
|
|
13
15
|
import { normalizeCalc } from "./calc/normalizeCalc.js";
|
|
14
16
|
import { defineFormField } from "./fields/defineFormField.js";
|
|
15
17
|
import { resolveFileRef } from "./uploads/resolveFileRef.js";
|
|
16
18
|
import { fileMimeTypeOptions } from "./fields/builtin/file.js";
|
|
17
19
|
import { buildDefaultFieldDefinitions, defaultFieldDefinitions, defaultFieldDefinitionsByType } from "./fields/builtin/index.js";
|
|
18
20
|
import { resolveFieldTypes, stashFieldTypes } from "./fields/registry.js";
|
|
19
|
-
import {
|
|
21
|
+
import { fieldKey } from "./fields/fieldKey.js";
|
|
22
|
+
import { calcWeightKey, evaluateCalc } from "./calc/evaluate.js";
|
|
23
|
+
import { calcExpressionOf, computeCalcFields } from "./calc/computeCalcFields.js";
|
|
24
|
+
import { calcUsesSources, resolveCalcContext } from "./calc/resolveCalcContext.js";
|
|
20
25
|
import { resolveConsentStatements } from "./consent/resolveConsentStatements.js";
|
|
21
26
|
import { isPollClosed } from "./form/pollState.js";
|
|
22
|
-
import { fieldKey } from "./fields/fieldKey.js";
|
|
23
27
|
import { aggregateRowForField, aggregateRowsForFields } from "./aggregation/aggregateRows.js";
|
|
24
28
|
import { aggregateFieldResponses, aggregateFormResponses, fieldHasOptions } from "./aggregation/aggregateResponses.js";
|
|
29
|
+
import { resolvePollOptions, stashPollOptionSources } from "./poll/resolvePollOptions.js";
|
|
30
|
+
import { resolveEffectivePollOptions } from "./poll/effectivePollOptions.js";
|
|
25
31
|
import { definePollType } from "./poll/definePollType.js";
|
|
26
32
|
import { mostVotedStrategy, topBucketValues } from "./poll/mostVoted.js";
|
|
27
|
-
import { resolvePollOptions, stashPollOptionSources } from "./poll/resolvePollOptions.js";
|
|
28
33
|
import { manualStrategy, pollTypesOf, resolvePollTypes, sourceStrategy, stashPollTypes } from "./poll/pollTypeRegistry.js";
|
|
34
|
+
import { POLL_VOTES_SLUG, RESPONDENTS_VALUE, VOTE_SHARDS } from "./poll/votes/votesCollection.js";
|
|
35
|
+
import { aggregateFromVotes } from "./poll/votes/aggregateFromVotes.js";
|
|
29
36
|
import { resolvePollOutcome } from "./poll/resolvePollOutcome.js";
|
|
30
37
|
import { POLL_CLOSE_TASK_SLUG, buildPollCloseTask, enqueuePollClose, registerPollCloseTask, runPollClose, shouldAutoResolvePoll } from "./poll/closeJob.js";
|
|
31
|
-
import { resolveEffectivePollOptions } from "./poll/effectivePollOptions.js";
|
|
32
38
|
import { buildDefaultOutcomeFields, buildResolvedAtField, buildWinningValuesField } from "./poll/outcomeFields.js";
|
|
33
39
|
import { buildDefaultButtonFields, buildNextLabelField, buildPrevLabelField, buildSubmitLabelField } from "./collections/buttonFields.js";
|
|
34
40
|
import { resolveFormResultsRequest } from "./aggregation/resolveResultsRequest.js";
|
|
35
41
|
import { resolveConsentSourcesRequest } from "./consent/resolveConsentSourcesRequest.js";
|
|
36
42
|
import { resolveDepartmentOptions } from "./email/departments.js";
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
43
|
+
import { buildDefaultSettingsFields } from "./collections/settingsFields.js";
|
|
44
|
+
import { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from "./spam/constants.js";
|
|
39
45
|
import { evaluateCondition } from "./conditions/evaluate.js";
|
|
40
46
|
import { textOfBody } from "./actions/body/textOfBody.js";
|
|
41
47
|
import { resolvePublishedVersionRef } from "./consent/resolvePublishedVersionRef.js";
|
|
@@ -54,6 +60,7 @@ import { defineValidationRule } from "./validation/defineValidationRule.js";
|
|
|
54
60
|
import { fieldTargetParam } from "./validation/fieldTargetParam.js";
|
|
55
61
|
import { defaultValidationRules, defaultValidationRulesByType } from "./validation/builtin/index.js";
|
|
56
62
|
import { resolveValidationRules } from "./validation/registry.js";
|
|
63
|
+
import { formatCalc } from "./calc/formatCalc.js";
|
|
57
64
|
import { applyConsentStatements } from "./consent/applyConsentStatements.js";
|
|
58
65
|
import { consentSourcesField } from "./consent/consentSourcesField.js";
|
|
59
66
|
import { departmentsField } from "./email/departmentsField.js";
|
|
@@ -61,6 +68,7 @@ import { countryField } from "./fields/builtin/country.js";
|
|
|
61
68
|
import { stateField } from "./fields/builtin/state.js";
|
|
62
69
|
import { toFormDocument } from "./form/toFormDocument.js";
|
|
63
70
|
import { definePollOptionSource } from "./poll/definePollOptionSource.js";
|
|
71
|
+
import { recountPollVotes } from "./poll/votes/recountPollVotes.js";
|
|
64
72
|
import { valuesFromSearchParams } from "./prefill/valuesFromSearchParams.js";
|
|
65
73
|
import { DEFAULT_PRESENTATION_NAME, defaultPresentationDescriptors } from "./presentations/defaults.js";
|
|
66
74
|
import { buildRecallResolver, optionLabelsFor } from "./recall/resolver.js";
|
|
@@ -79,9 +87,23 @@ const formBuilder = definePlugin({
|
|
|
79
87
|
if (options.disabled === true) return config;
|
|
80
88
|
const localizeContent = options.localizeContent !== false;
|
|
81
89
|
const uploads = options.uploads ?? false;
|
|
90
|
+
const calcSources = options.calc?.sources ?? {};
|
|
91
|
+
const calcFunctions = options.calc?.functions ?? {};
|
|
92
|
+
assertNoCalcFunctionCollision(calcFunctions);
|
|
93
|
+
assertValidCalcSourceKeys(calcSources);
|
|
94
|
+
const calcAllowed = {
|
|
95
|
+
sources: new Set(Object.keys(calcSources)),
|
|
96
|
+
functions: new Set(Object.keys(calcFunctions))
|
|
97
|
+
};
|
|
98
|
+
const calcSourceMeta = Object.entries(calcSources).map(([key, source]) => ({
|
|
99
|
+
key,
|
|
100
|
+
label: source.label,
|
|
101
|
+
scalar: typeof source.resolve === "function",
|
|
102
|
+
weights: typeof source.resolveWeights === "function"
|
|
103
|
+
}));
|
|
82
104
|
const uploadMimeTypes = uploads === false ? void 0 : uploads.mimeTypes ?? readUploadCollectionMimeTypes(config, uploads.collection);
|
|
83
105
|
const consentSources = options.consent?.sources;
|
|
84
|
-
const registry = resolveFieldTypes(buildDefaultFieldDefinitions(localizeContent, options.richText?.editor, uploadMimeTypes).filter((definition) => (uploads !== false || definition.type !== "file") && (consentSources !== void 0 || definition.type !== "consent")), options.fields);
|
|
106
|
+
const registry = resolveFieldTypes(buildDefaultFieldDefinitions(localizeContent, options.richText?.editor, uploadMimeTypes, calcAllowed, calcSourceMeta).filter((definition) => (uploads !== false || definition.type !== "file") && (consentSources !== void 0 || definition.type !== "consent")), options.fields);
|
|
85
107
|
const ruleRegistry = resolveValidationRules(defaultValidationRules, options.rules);
|
|
86
108
|
const fromAddresses = options.email?.fromAddresses;
|
|
87
109
|
const departments = options.email?.departments;
|
|
@@ -106,6 +128,9 @@ const formBuilder = definePlugin({
|
|
|
106
128
|
config,
|
|
107
129
|
registry,
|
|
108
130
|
ruleRegistry,
|
|
131
|
+
calcAllowed,
|
|
132
|
+
calcSources,
|
|
133
|
+
calcFunctions,
|
|
109
134
|
consentSources,
|
|
110
135
|
consentSnapshot: options.consent?.snapshot ?? "both",
|
|
111
136
|
consentResolveOnRead: options.consent?.resolveOnRead,
|
|
@@ -122,7 +147,9 @@ const formBuilder = definePlugin({
|
|
|
122
147
|
pollSourceRegistry,
|
|
123
148
|
pollTypeRegistry,
|
|
124
149
|
outcomeFields: options.poll?.outcomeFields,
|
|
150
|
+
pollVotes: options.poll?.votes === false ? false : options.poll?.votes ?? {},
|
|
125
151
|
buttons: options.buttons,
|
|
152
|
+
settings: options.settings,
|
|
126
153
|
response: options.response,
|
|
127
154
|
fromAddresses,
|
|
128
155
|
departments,
|
|
@@ -133,6 +160,6 @@ const formBuilder = definePlugin({
|
|
|
133
160
|
}
|
|
134
161
|
});
|
|
135
162
|
//#endregion
|
|
136
|
-
export { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD, DEFAULT_PRESENTATION_NAME, POLL_CLOSE_TASK_SLUG, SIGNATURE_HEADER, aggregateFieldResponses, aggregateFormResponses, aggregateRowForField, aggregateRowsForFields, applyConsentStatements, buildDefaultActionDefinitions, buildDefaultButtonFields, buildDefaultFieldDefinitions, buildDefaultOutcomeFields, buildNextLabelField, buildPollCloseTask, buildPrevLabelField, buildRecallResolver, buildResolvedAtField, buildSubmitLabelField, buildWinningValuesField, calcExpressionOf, captureConsent, captureFileRef, computeCalcFields, consentSourcesField, countryField, createKvRateLimiter, createSubmission, defaultActionDefinitions, defaultBodyConverters, defaultFieldDefinitions, defaultFieldDefinitionsByType, defaultIdentify, defaultPresentationDescriptors, defaultValidationRules, defaultValidationRulesByType, defineAction, defineCaptchaProvider, defineFormField, definePollOptionSource, definePollType, defineValidationRule, departmentsField, enqueuePollClose, escapeHtml, evaluateCalc, evaluateCondition, fieldHasOptions, fieldKey, fieldTargetParam, fileMimeTypeOptions, formBuilder, formatBytes, hasVotedCookie, hcaptchaProvider, interpolate, isPollClosed, localizedIf, manualStrategy, mostVotedStrategy, normalizeCalc, optionLabelsFor, pollTypesOf, recaptchaProvider, registerPollCloseTask, renderAllValues, renderAllValuesTable, resolveActions, resolveConsentEntries, resolveConsentSourcesRequest, resolveConsentStatements, resolveDepartmentOptions, resolveEffectivePollOptions, resolveFileRef, resolveFormResultsRequest, resolvePollOptionSources, resolvePollOptions, resolvePollOutcome, resolvePollTypes, resolvePublishedVersionRef, resolveSpamConfig, runPollClose, sanitizeUrl, serializeBody, shouldAutoResolvePoll, signFormContext, signPayload, sourceStrategy, stashPollTypes, stateField, textOfBody, toFormDocument, topBucketValues, turnstileProvider, valuesFromSearchParams, verifyFormContext, votedCookieName };
|
|
163
|
+
export { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD, DEFAULT_PRESENTATION_NAME, POLL_CLOSE_TASK_SLUG, POLL_VOTES_SLUG, RESPONDENTS_VALUE, SIGNATURE_HEADER, VOTE_SHARDS, aggregateFieldResponses, aggregateFormResponses, aggregateFromVotes, aggregateRowForField, aggregateRowsForFields, applyConsentStatements, buildDefaultActionDefinitions, buildDefaultButtonFields, buildDefaultFieldDefinitions, buildDefaultOutcomeFields, buildDefaultSettingsFields, buildNextLabelField, buildPollCloseTask, buildPrevLabelField, buildRecallResolver, buildResolvedAtField, buildSubmitLabelField, buildWinningValuesField, calcExpressionOf, calcUsesSources, calcWeightKey, captureConsent, captureFileRef, computeCalcFields, consentSourcesField, countryField, createKvRateLimiter, createSubmission, defaultActionDefinitions, defaultBodyConverters, defaultFieldDefinitions, defaultFieldDefinitionsByType, defaultIdentify, defaultPresentationDescriptors, defaultValidationRules, defaultValidationRulesByType, defineAction, defineCalcFunction, defineCalcSource, defineCaptchaProvider, defineFormField, definePollOptionSource, definePollType, defineValidationRule, departmentsField, enqueuePollClose, escapeHtml, evaluateCalc, evaluateCondition, fieldHasOptions, fieldKey, fieldTargetParam, fileMimeTypeOptions, formBuilder, formatBytes, formatCalc, formatCalcValue, hasVotedCookie, hcaptchaProvider, interpolate, isPollClosed, localizedIf, manualStrategy, mostVotedStrategy, normalizeCalc, optionLabelsFor, pollTypesOf, recaptchaProvider, recountPollVotes, registerPollCloseTask, renderAllValues, renderAllValuesTable, resolveActions, resolveCalcContext, resolveConsentEntries, resolveConsentSourcesRequest, resolveConsentStatements, resolveDepartmentOptions, resolveEffectivePollOptions, resolveFileRef, resolveFormResultsRequest, resolvePollOptionSources, resolvePollOptions, resolvePollOutcome, resolvePollTypes, resolvePublishedVersionRef, resolveSpamConfig, runPollClose, sanitizeUrl, serializeBody, shouldAutoResolvePoll, signFormContext, signPayload, sourceStrategy, stashPollTypes, stateField, textOfBody, toFormDocument, topBucketValues, turnstileProvider, valuesFromSearchParams, verifyFormContext, votedCookieName };
|
|
137
164
|
|
|
138
165
|
//# sourceMappingURL=index.js.map
|