@10x-media/form-builder 0.1.0-beta.2 → 0.1.0-beta.3

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.
Files changed (156) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +2 -2
  3. package/dist/actions/body/converters.d.ts +20 -0
  4. package/dist/actions/body/converters.js +57 -0
  5. package/dist/actions/body/converters.js.map +1 -0
  6. package/dist/actions/body/escapeHtml.d.ts +6 -0
  7. package/dist/actions/body/escapeHtml.js +14 -0
  8. package/dist/actions/body/escapeHtml.js.map +1 -0
  9. package/dist/actions/body/serializeBody.d.ts +35 -0
  10. package/dist/actions/body/serializeBody.js +76 -0
  11. package/dist/actions/body/serializeBody.js.map +1 -0
  12. package/dist/actions/body/serializeSlate.js +31 -0
  13. package/dist/actions/body/serializeSlate.js.map +1 -0
  14. package/dist/actions/body/wildcards.d.ts +10 -0
  15. package/dist/actions/body/wildcards.js +33 -0
  16. package/dist/actions/body/wildcards.js.map +1 -0
  17. package/dist/actions/builtin/confirmation.js +28 -12
  18. package/dist/actions/builtin/confirmation.js.map +1 -1
  19. package/dist/actions/builtin/emailTeam.js +7 -9
  20. package/dist/actions/builtin/emailTeam.js.map +1 -1
  21. package/dist/actions/builtin/signedWebhook.js +21 -3
  22. package/dist/actions/builtin/signedWebhook.js.map +1 -1
  23. package/dist/actions/defineAction.d.ts +2 -1
  24. package/dist/actions/defineAction.js.map +1 -1
  25. package/dist/actions/dispatch.js +2 -1
  26. package/dist/actions/dispatch.js.map +1 -1
  27. package/dist/actions/runActions.js +8 -1
  28. package/dist/actions/runActions.js.map +1 -1
  29. package/dist/actions/task.js +7 -5
  30. package/dist/actions/task.js.map +1 -1
  31. package/dist/calc/normalizeCalc.js +5 -17
  32. package/dist/calc/normalizeCalc.js.map +1 -1
  33. package/dist/calc/types.d.ts +8 -2
  34. package/dist/calc/types.js +22 -0
  35. package/dist/calc/types.js.map +1 -0
  36. package/dist/client/ByteSizeField.d.ts +21 -0
  37. package/dist/client/ByteSizeField.js +56 -0
  38. package/dist/client/ByteSizeField.js.map +1 -0
  39. package/dist/client/ConditionBuilder.js +2 -1
  40. package/dist/client/ConditionBuilder.js.map +1 -1
  41. package/dist/client/FieldNameSelect.d.ts +20 -0
  42. package/dist/client/FieldNameSelect.js +58 -0
  43. package/dist/client/FieldNameSelect.js.map +1 -0
  44. package/dist/client/FlowBuilder.d.ts +0 -1
  45. package/dist/client/FlowBuilder.js +4 -6
  46. package/dist/client/FlowBuilder.js.map +1 -1
  47. package/dist/client/FormConditionField.js +1 -4
  48. package/dist/client/FormConditionField.js.map +1 -1
  49. package/dist/client/admin.css +192 -0
  50. package/dist/client/toStaticLabel.js +13 -0
  51. package/dist/client/toStaticLabel.js.map +1 -0
  52. package/dist/collections/formSubmissions.js +5 -3
  53. package/dist/collections/formSubmissions.js.map +1 -1
  54. package/dist/collections/forms.js +74 -57
  55. package/dist/collections/forms.js.map +1 -1
  56. package/dist/exports/client.d.ts +3 -1
  57. package/dist/exports/client.js +3 -1
  58. package/dist/exports/react.d.ts +6 -1
  59. package/dist/exports/react.js +5 -1
  60. package/dist/fields/buildFieldBlocks.js +14 -18
  61. package/dist/fields/buildFieldBlocks.js.map +1 -1
  62. package/dist/fields/builtin/calculation.js +115 -2
  63. package/dist/fields/builtin/calculation.js.map +1 -1
  64. package/dist/fields/builtin/date.js +29 -0
  65. package/dist/fields/builtin/date.js.map +1 -0
  66. package/dist/fields/builtin/file.d.ts +15 -0
  67. package/dist/fields/builtin/file.js +79 -3
  68. package/dist/fields/builtin/file.js.map +1 -1
  69. package/dist/fields/builtin/index.d.ts +14 -0
  70. package/dist/fields/builtin/index.js +11 -2
  71. package/dist/fields/builtin/index.js.map +1 -1
  72. package/dist/fields/fieldNamesOfType.js +25 -0
  73. package/dist/fields/fieldNamesOfType.js.map +1 -0
  74. package/dist/fields/sharedConfig.js +30 -18
  75. package/dist/fields/sharedConfig.js.map +1 -1
  76. package/dist/index.d.ts +19 -2
  77. package/dist/index.js +14 -4
  78. package/dist/index.js.map +1 -1
  79. package/dist/plugin/registerCollections.js +3 -2
  80. package/dist/plugin/registerCollections.js.map +1 -1
  81. package/dist/react/Form.js +3 -3
  82. package/dist/react/Form.js.map +1 -1
  83. package/dist/react/Poll.js +1 -1
  84. package/dist/react/captcha/HcaptchaCaptcha.d.ts +28 -0
  85. package/dist/react/captcha/HcaptchaCaptcha.js +53 -0
  86. package/dist/react/captcha/HcaptchaCaptcha.js.map +1 -0
  87. package/dist/react/captcha/RecaptchaCaptcha.d.ts +41 -0
  88. package/dist/react/captcha/RecaptchaCaptcha.js +93 -0
  89. package/dist/react/captcha/RecaptchaCaptcha.js.map +1 -0
  90. package/dist/react/captcha/TurnstileCaptcha.d.ts +28 -0
  91. package/dist/react/captcha/TurnstileCaptcha.js +53 -0
  92. package/dist/react/captcha/TurnstileCaptcha.js.map +1 -0
  93. package/dist/react/captcha/types.d.ts +8 -0
  94. package/dist/react/captcha/useCaptchaScript.js +45 -0
  95. package/dist/react/captcha/useCaptchaScript.js.map +1 -0
  96. package/dist/react/captcha/vendors.js +8 -0
  97. package/dist/react/captcha/vendors.js.map +1 -0
  98. package/dist/react/primitives/Input.d.ts +1 -1
  99. package/dist/react/primitives/Input.js.map +1 -1
  100. package/dist/react/renderers/calculation.js +1 -1
  101. package/dist/react/renderers/checkbox.js +1 -1
  102. package/dist/react/renderers/consent.js +1 -1
  103. package/dist/react/renderers/date.js +37 -0
  104. package/dist/react/renderers/date.js.map +1 -0
  105. package/dist/react/renderers/email.js +1 -1
  106. package/dist/react/renderers/file.js +20 -7
  107. package/dist/react/renderers/file.js.map +1 -1
  108. package/dist/react/renderers/index.js +2 -0
  109. package/dist/react/renderers/index.js.map +1 -1
  110. package/dist/react/renderers/number.js +1 -1
  111. package/dist/react/renderers/repeater.js +1 -1
  112. package/dist/react/renderers/select.js +1 -1
  113. package/dist/react/renderers/text.js +1 -1
  114. package/dist/react/renderers/textarea.js +1 -1
  115. package/dist/spam/captcha.d.ts +3 -2
  116. package/dist/spam/captcha.js +3 -2
  117. package/dist/spam/captcha.js.map +1 -1
  118. package/dist/spam/clientIp.js +9 -0
  119. package/dist/spam/clientIp.js.map +1 -0
  120. package/dist/spam/identify.js +3 -6
  121. package/dist/spam/identify.js.map +1 -1
  122. package/dist/spam/providers/hcaptcha.d.ts +17 -0
  123. package/dist/spam/providers/hcaptcha.js +18 -0
  124. package/dist/spam/providers/hcaptcha.js.map +1 -0
  125. package/dist/spam/providers/recaptcha.d.ts +23 -0
  126. package/dist/spam/providers/recaptcha.js +23 -0
  127. package/dist/spam/providers/recaptcha.js.map +1 -0
  128. package/dist/spam/providers/siteverify.js +34 -0
  129. package/dist/spam/providers/siteverify.js.map +1 -0
  130. package/dist/spam/providers/turnstile.d.ts +17 -0
  131. package/dist/spam/providers/turnstile.js +18 -0
  132. package/dist/spam/providers/turnstile.js.map +1 -0
  133. package/dist/spam/spamGuard.js +2 -5
  134. package/dist/spam/spamGuard.js.map +1 -1
  135. package/dist/spam/types.d.ts +2 -2
  136. package/dist/translations/en.js +26 -4
  137. package/dist/translations/en.js.map +1 -1
  138. package/dist/translations/keys.d.ts +26 -4
  139. package/dist/translations/keys.js +26 -4
  140. package/dist/translations/keys.js.map +1 -1
  141. package/dist/uploads/formatBytes.d.ts +9 -0
  142. package/dist/uploads/formatBytes.js +25 -0
  143. package/dist/uploads/formatBytes.js.map +1 -0
  144. package/dist/uploads/resolveFileRef.js +1 -1
  145. package/dist/uploads/resolveFileRef.js.map +1 -1
  146. package/dist/validation/builtin/index.d.ts +14 -0
  147. package/dist/validation/builtin/index.js +12 -1
  148. package/dist/validation/builtin/index.js.map +1 -1
  149. package/dist/validation/builtin/maxDate.js +23 -0
  150. package/dist/validation/builtin/maxDate.js.map +1 -0
  151. package/dist/validation/builtin/minDate.js +23 -0
  152. package/dist/validation/builtin/minDate.js.map +1 -0
  153. package/dist/validation/builtin/validateDateBound.js +18 -0
  154. package/dist/validation/builtin/validateDateBound.js.map +1 -0
  155. package/package.json +3 -2
  156. package/styles/form-builder.css +0 -190
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldNamesOfType.js","names":[],"sources":["../../src/fields/fieldNamesOfType.ts"],"sourcesContent":["/**\n * Names of form `fields` blocks whose `blockType` is in `types`, trimmed and non-empty.\n * Server-safe and defensive: `fields` may be missing, non-array, or contain garbled rows\n * mid-edit. The single source of truth for which field names are selectable and valid as\n * a field reference (e.g. the confirmation action's `toField`), so client options and\n * server validation cannot drift apart.\n */\nexport const fieldNamesOfType = (fields: unknown, types: readonly string[]): string[] => {\n\tif (!Array.isArray(fields)) {\n\t\treturn []\n\t}\n\tconst names: string[] = []\n\tfor (const row of fields) {\n\t\tif (!row || typeof row !== 'object') {\n\t\t\tcontinue\n\t\t}\n\t\tconst { blockType, name } = row as { blockType?: unknown; name?: unknown }\n\t\tif (typeof blockType !== 'string' || !types.includes(blockType)) {\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof name !== 'string') {\n\t\t\tcontinue\n\t\t}\n\t\tconst trimmed = name.trim()\n\t\tif (trimmed.length > 0) {\n\t\t\tnames.push(trimmed)\n\t\t}\n\t}\n\treturn names\n}\n"],"mappings":";;;;;;;;AAOA,MAAa,oBAAoB,QAAiB,UAAuC;CACxF,IAAI,CAAC,MAAM,QAAQ,MAAM,GACxB,OAAO,CAAC;CAET,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,OAAO,QAAQ;EACzB,IAAI,CAAC,OAAO,OAAO,QAAQ,UAC1B;EAED,MAAM,EAAE,WAAW,SAAS;EAC5B,IAAI,OAAO,cAAc,YAAY,CAAC,MAAM,SAAS,SAAS,GAC7D;EAED,IAAI,OAAO,SAAS,UACnB;EAED,MAAM,UAAU,KAAK,KAAK;EAC1B,IAAI,QAAQ,SAAS,GACpB,MAAM,KAAK,OAAO;CAEpB;CACA,OAAO;AACR"}
@@ -13,11 +13,10 @@ const conditionField = (name, labelKey, conditionTypes) => ({
13
13
  });
14
14
  /**
15
15
  * Config every field instance carries regardless of type. `name` is the machine key written into
16
- * submissions; `width` is stored for the layout grid. `visibleWhen`/`validateWhen` store a
17
- * canonical Payload `Where`, edited by the native condition builder. Field types add their own `config`
18
- * after these.
16
+ * submissions; `width` is stored for the layout grid. Field types add their own `config` after
17
+ * these inside the Field tab (see `fieldBlockTabs`).
19
18
  */
20
- const sharedFieldConfig = (conditionTypes) => [
19
+ const sharedFieldConfig = () => [
21
20
  {
22
21
  name: "name",
23
22
  type: "text",
@@ -67,23 +66,36 @@ const sharedFieldConfig = (conditionTypes) => [
67
66
  name: "description",
68
67
  type: "textarea",
69
68
  label: labelFor(keys.configDescription)
70
- },
71
- {
72
- type: "collapsible",
73
- label: labelFor(keys.configAdvanced),
74
- admin: { initCollapsed: true },
75
- fields: [
76
- conditionField("visibleWhen", keys.configVisibleWhen, conditionTypes),
77
- conditionField("validateWhen", keys.configValidateWhen, conditionTypes),
78
- {
69
+ }
70
+ ];
71
+ /**
72
+ * The single field of every field block: unnamed tabs (presentational only, data paths stay flat).
73
+ * Field tab holds the shared basics plus the type's own config; Validation holds the rule blocks and
74
+ * `validateWhen`; Advanced holds `visibleWhen` and `hidden`. `visibleWhen`/`validateWhen` store a
75
+ * canonical Payload `Where`, edited by the native condition builder.
76
+ */
77
+ const fieldBlockTabs = (conditionTypes, typeConfig, validations) => ({
78
+ type: "tabs",
79
+ tabs: [
80
+ {
81
+ label: labelFor(keys.tabField),
82
+ fields: [...sharedFieldConfig(), ...typeConfig]
83
+ },
84
+ {
85
+ label: labelFor(keys.tabValidation),
86
+ fields: [validations, conditionField("validateWhen", keys.configValidateWhen, conditionTypes)]
87
+ },
88
+ {
89
+ label: labelFor(keys.tabAdvanced),
90
+ fields: [conditionField("visibleWhen", keys.configVisibleWhen, conditionTypes), {
79
91
  name: "hidden",
80
92
  type: "checkbox",
81
93
  label: labelFor(keys.configHidden)
82
- }
83
- ]
84
- }
85
- ];
94
+ }]
95
+ }
96
+ ]
97
+ });
86
98
  //#endregion
87
- export { sharedFieldConfig };
99
+ export { fieldBlockTabs };
88
100
 
89
101
  //# sourceMappingURL=sharedConfig.js.map
@@ -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'\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 * Config every field instance carries regardless of type. `name` is the machine key written into\n * submissions; `width` is stored for the layout grid. `visibleWhen`/`validateWhen` store a\n * canonical Payload `Where`, edited by the native condition builder. Field types add their own `config`\n * after these.\n */\nexport const sharedFieldConfig = (conditionTypes: Record<string, ConditionFieldType>): Field[] => [\n\t{ name: 'name', type: 'text', required: true, label: labelFor(keys.configName) },\n\t{ name: 'label', type: 'text', label: labelFor(keys.configLabel) },\n\t{ name: 'required', type: 'checkbox', label: labelFor(keys.configRequired) },\n\t{\n\t\tname: 'width',\n\t\ttype: 'select',\n\t\tdefaultValue: 'full',\n\t\tlabel: labelFor(keys.configWidth),\n\t\toptions: [\n\t\t\t{ label: 'Full', value: 'full' },\n\t\t\t{ label: 'Half', value: 'half' },\n\t\t\t{ label: 'Third', value: 'third' },\n\t\t\t{ label: 'Two thirds', value: 'twoThirds' },\n\t\t],\n\t},\n\t{ name: 'placeholder', type: 'text', label: labelFor(keys.configPlaceholder) },\n\t{ name: 'description', type: 'textarea', label: labelFor(keys.configDescription) },\n\t{\n\t\ttype: 'collapsible',\n\t\tlabel: labelFor(keys.configAdvanced),\n\t\tadmin: { initCollapsed: true },\n\t\tfields: [\n\t\t\tconditionField('visibleWhen', keys.configVisibleWhen, conditionTypes),\n\t\t\tconditionField('validateWhen', keys.configValidateWhen, conditionTypes),\n\t\t\t{ name: 'hidden', type: 'checkbox', label: labelFor(keys.configHidden) },\n\t\t],\n\t},\n]\n"],"mappings":";;;AAKA,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;;;;;;;AAQA,MAAa,qBAAqB,mBAAgE;CACjG;EAAE,MAAM;EAAQ,MAAM;EAAQ,UAAU;EAAM,OAAO,SAAS,KAAK,UAAU;CAAE;CAC/E;EAAE,MAAM;EAAS,MAAM;EAAQ,OAAO,SAAS,KAAK,WAAW;CAAE;CACjE;EAAE,MAAM;EAAY,MAAM;EAAY,OAAO,SAAS,KAAK,cAAc;CAAE;CAC3E;EACC,MAAM;EACN,MAAM;EACN,cAAc;EACd,OAAO,SAAS,KAAK,WAAW;EAChC,SAAS;GACR;IAAE,OAAO;IAAQ,OAAO;GAAO;GAC/B;IAAE,OAAO;IAAQ,OAAO;GAAO;GAC/B;IAAE,OAAO;IAAS,OAAO;GAAQ;GACjC;IAAE,OAAO;IAAc,OAAO;GAAY;EAC3C;CACD;CACA;EAAE,MAAM;EAAe,MAAM;EAAQ,OAAO,SAAS,KAAK,iBAAiB;CAAE;CAC7E;EAAE,MAAM;EAAe,MAAM;EAAY,OAAO,SAAS,KAAK,iBAAiB;CAAE;CACjF;EACC,MAAM;EACN,OAAO,SAAS,KAAK,cAAc;EACnC,OAAO,EAAE,eAAe,KAAK;EAC7B,QAAQ;GACP,eAAe,eAAe,KAAK,mBAAmB,cAAc;GACpE,eAAe,gBAAgB,KAAK,oBAAoB,cAAc;GACtE;IAAE,MAAM;IAAU,MAAM;IAAY,OAAO,SAAS,KAAK,YAAY;GAAE;EACxE;CACD;AACD"}
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'\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 * 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`).\n */\nexport const sharedFieldConfig = (): Field[] => [\n\t{ name: 'name', type: 'text', required: true, label: labelFor(keys.configName) },\n\t{ name: 'label', type: 'text', label: labelFor(keys.configLabel) },\n\t{ name: 'required', type: 'checkbox', label: labelFor(keys.configRequired) },\n\t{\n\t\tname: 'width',\n\t\ttype: 'select',\n\t\tdefaultValue: 'full',\n\t\tlabel: labelFor(keys.configWidth),\n\t\toptions: [\n\t\t\t{ label: 'Full', value: 'full' },\n\t\t\t{ label: 'Half', value: 'half' },\n\t\t\t{ label: 'Third', value: 'third' },\n\t\t\t{ label: 'Two thirds', value: 'twoThirds' },\n\t\t],\n\t},\n\t{ name: 'placeholder', type: 'text', label: labelFor(keys.configPlaceholder) },\n\t{ name: 'description', type: 'textarea', label: labelFor(keys.configDescription) },\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 */\nexport const fieldBlockTabs = (\n\tconditionTypes: Record<string, ConditionFieldType>,\n\ttypeConfig: Field[],\n\tvalidations: Field\n): Field => ({\n\ttype: 'tabs',\n\ttabs: [\n\t\t{\n\t\t\tlabel: labelFor(keys.tabField),\n\t\t\tfields: [...sharedFieldConfig(), ...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{ name: 'hidden', type: 'checkbox', label: labelFor(keys.configHidden) },\n\t\t\t],\n\t\t},\n\t],\n})\n"],"mappings":";;;AAKA,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,MAAa,0BAAmC;CAC/C;EAAE,MAAM;EAAQ,MAAM;EAAQ,UAAU;EAAM,OAAO,SAAS,KAAK,UAAU;CAAE;CAC/E;EAAE,MAAM;EAAS,MAAM;EAAQ,OAAO,SAAS,KAAK,WAAW;CAAE;CACjE;EAAE,MAAM;EAAY,MAAM;EAAY,OAAO,SAAS,KAAK,cAAc;CAAE;CAC3E;EACC,MAAM;EACN,MAAM;EACN,cAAc;EACd,OAAO,SAAS,KAAK,WAAW;EAChC,SAAS;GACR;IAAE,OAAO;IAAQ,OAAO;GAAO;GAC/B;IAAE,OAAO;IAAQ,OAAO;GAAO;GAC/B;IAAE,OAAO;IAAS,OAAO;GAAQ;GACjC;IAAE,OAAO;IAAc,OAAO;GAAY;EAC3C;CACD;CACA;EAAE,MAAM;EAAe,MAAM;EAAQ,OAAO,SAAS,KAAK,iBAAiB;CAAE;CAC7E;EAAE,MAAM;EAAe,MAAM;EAAY,OAAO,SAAS,KAAK,iBAAiB;CAAE;AAClF;;;;;;;AAQA,MAAa,kBACZ,gBACA,YACA,iBACY;CACZ,MAAM;CACN,MAAM;EACL;GACC,OAAO,SAAS,KAAK,QAAQ;GAC7B,QAAQ,CAAC,GAAG,kBAAkB,GAAG,GAAG,UAAU;EAC/C;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,CACP,eAAe,eAAe,KAAK,mBAAmB,cAAc,GACpE;IAAE,MAAM;IAAU,MAAM;IAAY,OAAO,SAAS,KAAK,YAAY;GAAE,CACxE;EACD;CACD;AACD"}
package/dist/index.d.ts CHANGED
@@ -14,8 +14,11 @@ import { PresentationDensity, PresentationDescriptor, PresentationSurface } from
14
14
  import { interpolate } from "./recall/interpolate.js";
15
15
  import { RecallResolver, buildRecallResolver, optionLabelsFor } from "./recall/resolver.js";
16
16
  import { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from "./spam/constants.js";
17
+ import { formatBytes } from "./uploads/formatBytes.js";
17
18
  import { ActionDefinition, ActionRunArgs, AnyActionDefinition, defineAction } from "./actions/defineAction.js";
18
19
  import { ActionOption, ActionRegistry, ActionsConfig, resolveActions } from "./actions/registry.js";
20
+ import { BodyConverter, BodyConverterArgs, BodyRender, defaultBodyConverters, sanitizeUrl } from "./actions/body/converters.js";
21
+ import { BodyContext, RichTextBodyOption, SerializeBodyArgs, serializeBody } from "./actions/body/serializeBody.js";
19
22
  import { ActionResult } from "./actions/runActions.js";
20
23
  import { AggregateFieldResponsesArgs, AggregateFormResponsesArgs, aggregateFieldResponses, aggregateFormResponses, fieldHasOptions } from "./aggregation/aggregateResponses.js";
21
24
  import { ResolveResultsRequestArgs, ResolveResultsRequestResult, resolveFormResultsRequest } from "./aggregation/resolveResultsRequest.js";
@@ -28,6 +31,8 @@ import { ConsentProof, captureConsent } from "./consent/captureConsent.js";
28
31
  import { PresentationDescriptorOption, PresentationDescriptorRegistry, PresentationsDescriptorConfig, resolvePresentationDescriptors } from "./presentations/registry.js";
29
32
  import { CaptchaProvider, CaptchaVerifyArgs, IdentifyFn, RateLimitCheckArgs, RateLimitConfig, RateLimitResult, RateLimiter, SpamConfig, SpamMetadataConfig, SpamOption } from "./spam/types.js";
30
33
  import { ValidationRuleOption, ValidationRuleRegistry, ValidationRulesConfig } from "./validation/registry.js";
34
+ import { escapeHtml } from "./actions/body/escapeHtml.js";
35
+ import { renderAllValues, renderAllValuesTable } from "./actions/body/wildcards.js";
31
36
  import { defaultActionDefinitions } from "./actions/builtin/index.js";
32
37
  import { SIGNATURE_HEADER, signPayload } from "./actions/sign.js";
33
38
  import { aggregateRowForField, aggregateRowsForFields } from "./aggregation/aggregateRows.js";
@@ -35,14 +40,20 @@ import { normalizeCalc } from "./calc/normalizeCalc.js";
35
40
  import { defaultConsentSources } from "./consent/builtin/index.js";
36
41
  import { resolveConsentLinks } from "./consent/resolveConsentLinks.js";
37
42
  import { resolvePublishedVersionRef } from "./consent/resolvePublishedVersionRef.js";
43
+ import { defaultFieldDefinitions, defaultFieldDefinitionsByType } from "./fields/builtin/index.js";
44
+ import { fileMimeTypeOptions } from "./fields/builtin/file.js";
38
45
  import { defineFormField } from "./fields/defineFormField.js";
39
46
  import { DEFAULT_PRESENTATION_NAME, defaultPresentationDescriptors } from "./presentations/defaults.js";
40
47
  import { defineCaptchaProvider } from "./spam/captcha.js";
41
48
  import { defaultIdentify } from "./spam/identify.js";
49
+ import { HcaptchaProviderOptions, hcaptchaProvider } from "./spam/providers/hcaptcha.js";
50
+ import { RecaptchaProviderOptions, recaptchaProvider } from "./spam/providers/recaptcha.js";
51
+ import { TurnstileProviderOptions, turnstileProvider } from "./spam/providers/turnstile.js";
42
52
  import { createKvRateLimiter } from "./spam/rateLimiter.js";
43
53
  import { resolveSpamConfig } from "./spam/resolveSpam.js";
44
54
  import { resolveFileRef } from "./uploads/resolveFileRef.js";
45
55
  import { captureFileRef } from "./uploads/captureFileRef.js";
56
+ import { defaultValidationRules, defaultValidationRulesByType } from "./validation/builtin/index.js";
46
57
  import { defineValidationRule } from "./validation/defineValidationRule.js";
47
58
 
48
59
  //#region src/index.d.ts
@@ -59,7 +70,13 @@ type FormBuilderPluginOptions = {
59
70
  fields?: FieldTypesConfig; /** Add, override, or remove presentations. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */
60
71
  presentations?: PresentationsDescriptorConfig; /** Add, override, or remove validation rule types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */
61
72
  rules?: ValidationRulesConfig; /** Add, override, or remove post-submit action types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */
62
- actions?: ActionsConfig; /** Add, override, or remove consent source types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */
73
+ actions?: ActionsConfig;
74
+ /**
75
+ * Customize how rich text action bodies are rendered. `converters` spread over the default
76
+ * Lexical node converters; `serialize` replaces the whole pipeline (e.g. to target chat or
77
+ * plain-text channels instead of email HTML).
78
+ */
79
+ richText?: RichTextBodyOption; /** Add, override, or remove consent source types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */
63
80
  consentSources?: ConsentSourcesConfig; /** The built-in `form-uploads` collection backing file fields. `false` disables it (bring your own); an object overrides slug/upload/access/fields. */
64
81
  uploads?: UploadsOption; /** Honeypot + rate-limiting (on by default) + a captcha adapter seam + upload-ownership scoping. `false` disables the whole subsystem. */
65
82
  spam?: SpamOption;
@@ -89,5 +106,5 @@ declare module 'payload' {
89
106
  }
90
107
  declare const formBuilder: (options: FormBuilderPluginOptions) => import("payload").Plugin;
91
108
  //#endregion
92
- export { type ActionDefinition, type ActionOption, type ActionRegistry, type ActionResult, type ActionRunArgs, type ActionsConfig, type AggregateFieldResponsesArgs, type AggregateFormResponsesArgs, type AggregationBucket, type AggregationRow, type AnyActionDefinition, type AnyConsentSource, type AnyFormFieldDefinition, type AnyValidationRuleDefinition, CAPTCHA_TOKEN_KEY, type CalcExpression, type CaptchaProvider, type CaptchaVerifyArgs, type ConsentLink, type ConsentProof, type ConsentResolveArgs, type ConsentResolved, type ConsentSource, type ConsentSourceOption, type ConsentSourceRegistry, type ConsentSourcesConfig, DEFAULT_HONEYPOT_FIELD, DEFAULT_PRESENTATION_NAME, FORM_UPLOADS_SLUG, type FieldAggregation, type FieldCondition, type FieldMeta, type FieldTypeOption, type FieldTypeRegistry, type FieldTypesConfig, type FileFieldConfig, type FileRef, type FileRefError, FormBuilderPluginOptions, type FormBuilderPluginOptions as PluginOptions, type FormFieldDefinition, type FormFieldFormat, type FormFieldValidate, type FormFieldValueKind, type IdentifyFn, type PrefillOptions, type PresentationDensity, type PresentationDescriptor, type PresentationDescriptorOption, type PresentationDescriptorRegistry, type PresentationSurface, type PresentationsDescriptorConfig, type RateLimitCheckArgs, type RateLimitConfig, type RateLimitResult, type RateLimiter, type RecallResolver, type ResolveResultsRequestArgs, type ResolveResultsRequestResult, SIGNATURE_HEADER, type SpamConfig, type SpamMetadataConfig, type SpamOption, type SubmissionStatusFilter, type UploadsCollectionConfig, type UploadsOption, type ValidationRuleDefinition, type ValidationRuleOption, type ValidationRuleRegistry, type ValidationRuleResult, type ValidationRulesConfig, type ValidationSeverity, aggregateFieldResponses, aggregateFormResponses, aggregateRowForField, aggregateRowsForFields, buildRecallResolver, buildUploadsCollection, calcExpressionOf, captureConsent, captureFileRef, computeCalcFields, createKvRateLimiter, defaultActionDefinitions, defaultConsentSources, defaultIdentify, defaultPresentationDescriptors, defineAction, defineCaptchaProvider, defineConsentSource, defineFormField, defineValidationRule, evaluateCalc, evaluateCondition, fieldHasOptions, formBuilder, interpolate, normalizeCalc, optionLabelsFor, resolveActions, resolveConsentLinks, resolveConsentSources, resolveFileRef, resolveFormResultsRequest, resolvePresentationDescriptors, resolvePublishedVersionRef, resolveSpamConfig, resolveUploads, signPayload, valuesFromSearchParams };
109
+ export { type ActionDefinition, type ActionOption, type ActionRegistry, type ActionResult, type ActionRunArgs, type ActionsConfig, type AggregateFieldResponsesArgs, type AggregateFormResponsesArgs, type AggregationBucket, type AggregationRow, type AnyActionDefinition, type AnyConsentSource, type AnyFormFieldDefinition, type AnyValidationRuleDefinition, type BodyContext, type BodyConverter, type BodyConverterArgs, type BodyRender, CAPTCHA_TOKEN_KEY, type CalcExpression, type CaptchaProvider, type CaptchaVerifyArgs, type ConsentLink, type ConsentProof, type ConsentResolveArgs, type ConsentResolved, type ConsentSource, type ConsentSourceOption, type ConsentSourceRegistry, type ConsentSourcesConfig, DEFAULT_HONEYPOT_FIELD, DEFAULT_PRESENTATION_NAME, FORM_UPLOADS_SLUG, type FieldAggregation, type FieldCondition, type FieldMeta, type FieldTypeOption, type FieldTypeRegistry, type FieldTypesConfig, type FileFieldConfig, type FileRef, type FileRefError, FormBuilderPluginOptions, type FormBuilderPluginOptions as PluginOptions, type FormFieldDefinition, type FormFieldFormat, type FormFieldValidate, type FormFieldValueKind, type HcaptchaProviderOptions, type IdentifyFn, type PrefillOptions, type PresentationDensity, type PresentationDescriptor, type PresentationDescriptorOption, type PresentationDescriptorRegistry, type PresentationSurface, type PresentationsDescriptorConfig, type RateLimitCheckArgs, type RateLimitConfig, type RateLimitResult, type RateLimiter, type RecallResolver, type RecaptchaProviderOptions, type ResolveResultsRequestArgs, type ResolveResultsRequestResult, type RichTextBodyOption, SIGNATURE_HEADER, type SerializeBodyArgs, type SpamConfig, type SpamMetadataConfig, type SpamOption, type SubmissionStatusFilter, type TurnstileProviderOptions, type UploadsCollectionConfig, type UploadsOption, type ValidationRuleDefinition, type ValidationRuleOption, type ValidationRuleRegistry, type ValidationRuleResult, type ValidationRulesConfig, type ValidationSeverity, aggregateFieldResponses, aggregateFormResponses, aggregateRowForField, aggregateRowsForFields, buildRecallResolver, buildUploadsCollection, calcExpressionOf, captureConsent, captureFileRef, computeCalcFields, createKvRateLimiter, defaultActionDefinitions, defaultBodyConverters, defaultConsentSources, defaultFieldDefinitions, defaultFieldDefinitionsByType, defaultIdentify, defaultPresentationDescriptors, defaultValidationRules, defaultValidationRulesByType, defineAction, defineCaptchaProvider, defineConsentSource, defineFormField, defineValidationRule, escapeHtml, evaluateCalc, evaluateCondition, fieldHasOptions, fileMimeTypeOptions, formBuilder, formatBytes, hcaptchaProvider, interpolate, normalizeCalc, optionLabelsFor, recaptchaProvider, renderAllValues, renderAllValuesTable, resolveActions, resolveConsentLinks, resolveConsentSources, resolveFileRef, resolveFormResultsRequest, resolvePresentationDescriptors, resolvePublishedVersionRef, resolveSpamConfig, resolveUploads, sanitizeUrl, serializeBody, signPayload, turnstileProvider, valuesFromSearchParams };
93
110
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
1
  import { interpolate } from "./recall/interpolate.js";
2
+ import { escapeHtml } from "./actions/body/escapeHtml.js";
3
+ import { defaultBodyConverters, sanitizeUrl } from "./actions/body/converters.js";
4
+ import { renderAllValues, renderAllValuesTable } from "./actions/body/wildcards.js";
5
+ import { serializeBody } from "./actions/body/serializeBody.js";
2
6
  import { defineAction } from "./actions/defineAction.js";
3
7
  import { SIGNATURE_HEADER, signPayload } from "./actions/sign.js";
4
8
  import { defaultActionDefinitions } from "./actions/builtin/index.js";
@@ -8,14 +12,15 @@ import { defineConsentSource } from "./consent/defineConsentSource.js";
8
12
  import { resolvePublishedVersionRef } from "./consent/resolvePublishedVersionRef.js";
9
13
  import { defaultConsentSources } from "./consent/builtin/index.js";
10
14
  import { resolveConsentSources } from "./consent/registry.js";
15
+ import { normalizeCalc } from "./calc/normalizeCalc.js";
11
16
  import { defineFormField } from "./fields/defineFormField.js";
12
- import { defaultFieldDefinitions } from "./fields/builtin/index.js";
17
+ import { fileMimeTypeOptions } from "./fields/builtin/file.js";
18
+ import { defaultFieldDefinitions, defaultFieldDefinitionsByType } from "./fields/builtin/index.js";
13
19
  import { resolveFieldTypes } from "./fields/registry.js";
14
20
  import { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from "./spam/constants.js";
15
21
  import { aggregateRowForField, aggregateRowsForFields } from "./aggregation/aggregateRows.js";
16
22
  import { aggregateFieldResponses, aggregateFormResponses, fieldHasOptions } from "./aggregation/aggregateResponses.js";
17
23
  import { resolveFormResultsRequest } from "./aggregation/resolveResultsRequest.js";
18
- import { normalizeCalc } from "./calc/normalizeCalc.js";
19
24
  import { DEFAULT_PRESENTATION_NAME, defaultPresentationDescriptors } from "./presentations/defaults.js";
20
25
  import { evaluateCalc } from "./calc/evaluate.js";
21
26
  import { calcExpressionOf, computeCalcFields } from "./calc/computeCalcFields.js";
@@ -31,11 +36,15 @@ import { defaultIdentify } from "./spam/identify.js";
31
36
  import { createKvRateLimiter } from "./spam/rateLimiter.js";
32
37
  import { resolveSpamConfig } from "./spam/resolveSpam.js";
33
38
  import { defineValidationRule } from "./validation/defineValidationRule.js";
34
- import { defaultValidationRules } from "./validation/builtin/index.js";
39
+ import { defaultValidationRules, defaultValidationRulesByType } from "./validation/builtin/index.js";
35
40
  import { resolveValidationRules } from "./validation/registry.js";
36
41
  import { valuesFromSearchParams } from "./prefill/valuesFromSearchParams.js";
37
42
  import { buildRecallResolver, optionLabelsFor } from "./recall/resolver.js";
38
43
  import { defineCaptchaProvider } from "./spam/captcha.js";
44
+ import { hcaptchaProvider } from "./spam/providers/hcaptcha.js";
45
+ import { recaptchaProvider } from "./spam/providers/recaptcha.js";
46
+ import { turnstileProvider } from "./spam/providers/turnstile.js";
47
+ import { formatBytes } from "./uploads/formatBytes.js";
39
48
  import { definePlugin } from "payload";
40
49
  //#region src/index.ts
41
50
  const formBuilder = definePlugin({
@@ -58,6 +67,7 @@ const formBuilder = definePlugin({
58
67
  consentRegistry,
59
68
  presentationRegistry,
60
69
  actionRegistry,
70
+ richText: options.richText,
61
71
  hasJobsPlugin: Boolean(plugins["@10x-media/jobs"]),
62
72
  events: options.events,
63
73
  uploads,
@@ -69,6 +79,6 @@ const formBuilder = definePlugin({
69
79
  }
70
80
  });
71
81
  //#endregion
72
- export { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD, DEFAULT_PRESENTATION_NAME, FORM_UPLOADS_SLUG, SIGNATURE_HEADER, aggregateFieldResponses, aggregateFormResponses, aggregateRowForField, aggregateRowsForFields, buildRecallResolver, buildUploadsCollection, calcExpressionOf, captureConsent, captureFileRef, computeCalcFields, createKvRateLimiter, defaultActionDefinitions, defaultConsentSources, defaultIdentify, defaultPresentationDescriptors, defineAction, defineCaptchaProvider, defineConsentSource, defineFormField, defineValidationRule, evaluateCalc, evaluateCondition, fieldHasOptions, formBuilder, interpolate, normalizeCalc, optionLabelsFor, resolveActions, resolveConsentLinks, resolveConsentSources, resolveFileRef, resolveFormResultsRequest, resolvePresentationDescriptors, resolvePublishedVersionRef, resolveSpamConfig, resolveUploads, signPayload, valuesFromSearchParams };
82
+ export { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD, DEFAULT_PRESENTATION_NAME, FORM_UPLOADS_SLUG, SIGNATURE_HEADER, aggregateFieldResponses, aggregateFormResponses, aggregateRowForField, aggregateRowsForFields, buildRecallResolver, buildUploadsCollection, calcExpressionOf, captureConsent, captureFileRef, computeCalcFields, createKvRateLimiter, defaultActionDefinitions, defaultBodyConverters, defaultConsentSources, defaultFieldDefinitions, defaultFieldDefinitionsByType, defaultIdentify, defaultPresentationDescriptors, defaultValidationRules, defaultValidationRulesByType, defineAction, defineCaptchaProvider, defineConsentSource, defineFormField, defineValidationRule, escapeHtml, evaluateCalc, evaluateCondition, fieldHasOptions, fileMimeTypeOptions, formBuilder, formatBytes, hcaptchaProvider, interpolate, normalizeCalc, optionLabelsFor, recaptchaProvider, renderAllValues, renderAllValuesTable, resolveActions, resolveConsentLinks, resolveConsentSources, resolveFileRef, resolveFormResultsRequest, resolvePresentationDescriptors, resolvePublishedVersionRef, resolveSpamConfig, resolveUploads, sanitizeUrl, serializeBody, signPayload, turnstileProvider, valuesFromSearchParams };
73
83
 
74
84
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { type Config, definePlugin } from 'payload'\nimport { defaultActionDefinitions } from './actions/builtin'\nimport type { ActionsConfig } from './actions/registry'\nimport { resolveActions } from './actions/registry'\nimport { resolveUploads, type UploadsOption } from './collections/uploads'\nimport { defaultConsentSources } from './consent/builtin'\nimport type { ConsentSourcesConfig } from './consent/registry'\nimport { resolveConsentSources } from './consent/registry'\nimport type { FormEventSink } from './events/types'\nimport { defaultFieldDefinitions } from './fields/builtin'\nimport { type FieldTypesConfig, resolveFieldTypes } from './fields/registry'\nimport type { CollectionOverrides } from './plugin/collectionOverrides'\nimport { registerCollections } from './plugin/registerCollections'\nimport { registerTranslations } from './plugin/registerTranslations'\nimport { defaultPresentationDescriptors } from './presentations/defaults'\nimport type { PresentationsDescriptorConfig } from './presentations/registry'\nimport { resolvePresentationDescriptors } from './presentations/registry'\nimport { resolveSpamConfig } from './spam/resolveSpam'\nimport type { SpamOption } from './spam/types'\nimport type { TranslationsOption } from './translations'\nimport { defaultValidationRules } from './validation/builtin'\nimport { resolveValidationRules, type ValidationRulesConfig } from './validation/registry'\n\nexport type FormBuilderPluginOptions = {\n\tdisabled?: boolean\n\t/**\n\t * Per-locale overrides for this plugin's UI strings, keyed by the typed\n\t * translation keys exported from `@10x-media/form-builder/i18n`. Values win\n\t * over the built-in locales key-by-key; locales the plugin does not ship are\n\t * added whole. App-level `i18n.translations` still wins over both.\n\t */\n\ttranslations?: TranslationsOption\n\t/** Pluggable sink for form lifecycle events. Defaults to a no-op; analytics adapters or a future analytics plugin subscribe here. */\n\tevents?: FormEventSink\n\t/** Add, override, or remove field types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\tfields?: FieldTypesConfig\n\t/** Add, override, or remove presentations. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\tpresentations?: PresentationsDescriptorConfig\n\t/** Add, override, or remove validation rule types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\trules?: ValidationRulesConfig\n\t/** Add, override, or remove post-submit action types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\tactions?: ActionsConfig\n\t/** Add, override, or remove consent source types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\tconsentSources?: ConsentSourcesConfig\n\t/** The built-in `form-uploads` collection backing file fields. `false` disables it (bring your own); an object overrides slug/upload/access/fields. */\n\tuploads?: UploadsOption\n\t/** Honeypot + rate-limiting (on by default) + a captcha adapter seam + upload-ownership scoping. `false` disables the whole subsystem. */\n\tspam?: SpamOption\n\t/**\n\t * When `true`, the raw `values`, `descriptors`, and `consent` JSON fields are visible in the\n\t * submission admin view. Default `false` — those fields are fully represented by the\n\t * `SubmissionAnswers` UI component and are noisy when shown alongside it.\n\t */\n\tshowSubmissionRawFields?: boolean\n\t/**\n\t * Override individual plugin-managed collections using explicit spreads. Each key accepts a\n\t * `CollectionOverrides` object: top-level keys are spread with the plugin's defaults (spread\n\t * order per key determines who wins), hooks are appended after the plugin's own hooks, and\n\t * `fields` is a function that receives the default fields and returns the final array so\n\t * additions/removals are always intentional.\n\t */\n\toverrides?: {\n\t\tforms?: CollectionOverrides\n\t\tformSubmissions?: CollectionOverrides\n\t\tuploads?: CollectionOverrides\n\t}\n}\n\ndeclare module 'payload' {\n\tinterface RegisteredPlugins {\n\t\t'@10x-media/form-builder': FormBuilderPluginOptions\n\t}\n}\n\nexport const formBuilder = definePlugin<FormBuilderPluginOptions>({\n\tslug: '@10x-media/form-builder',\n\torder: 50,\n\tplugin: ({ config, plugins, ...options }): Config => {\n\t\tif (options.disabled === true) {\n\t\t\treturn config\n\t\t}\n\t\tconst registry = resolveFieldTypes(defaultFieldDefinitions, options.fields)\n\t\tconst ruleRegistry = resolveValidationRules(defaultValidationRules, options.rules)\n\t\tconst consentRegistry = resolveConsentSources(defaultConsentSources, options.consentSources)\n\t\tconst presentationRegistry = resolvePresentationDescriptors(\n\t\t\tdefaultPresentationDescriptors,\n\t\t\toptions.presentations\n\t\t)\n\t\tconst actionRegistry = resolveActions(defaultActionDefinitions, options.actions)\n\t\tconst uploads = resolveUploads(options.uploads)\n\t\tconst spam = resolveSpamConfig(options.spam)\n\t\tregisterTranslations(config, options.translations)\n\t\tregisterCollections({\n\t\t\tconfig,\n\t\t\tregistry,\n\t\t\truleRegistry,\n\t\t\tconsentRegistry,\n\t\t\tpresentationRegistry,\n\t\t\tactionRegistry,\n\t\t\thasJobsPlugin: Boolean(plugins['@10x-media/jobs']),\n\t\t\tevents: options.events,\n\t\t\tuploads,\n\t\t\tspam,\n\t\t\tshowSubmissionRawFields: options.showSubmissionRawFields ?? false,\n\t\t\toverrides: options.overrides,\n\t\t})\n\t\treturn config\n\t},\n})\n\nexport { defaultActionDefinitions } from './actions/builtin'\nexport type { ActionDefinition, ActionRunArgs, AnyActionDefinition } from './actions/defineAction'\nexport { defineAction } from './actions/defineAction'\nexport type { ActionOption, ActionRegistry, ActionsConfig } from './actions/registry'\nexport { resolveActions } from './actions/registry'\nexport type { ActionResult } from './actions/runActions'\nexport { SIGNATURE_HEADER, signPayload } from './actions/sign'\nexport type {\n\tAggregateFieldResponsesArgs,\n\tAggregateFormResponsesArgs,\n} from './aggregation/aggregateResponses'\nexport {\n\taggregateFieldResponses,\n\taggregateFormResponses,\n\tfieldHasOptions,\n} from './aggregation/aggregateResponses'\nexport { aggregateRowForField, aggregateRowsForFields } from './aggregation/aggregateRows'\nexport type {\n\tResolveResultsRequestArgs,\n\tResolveResultsRequestResult,\n} from './aggregation/resolveResultsRequest'\nexport { resolveFormResultsRequest } from './aggregation/resolveResultsRequest'\nexport type {\n\tAggregationBucket,\n\tAggregationRow,\n\tFieldAggregation,\n\tFieldMeta,\n\tSubmissionStatusFilter,\n} from './aggregation/types'\nexport { calcExpressionOf, computeCalcFields } from './calc/computeCalcFields'\nexport { evaluateCalc } from './calc/evaluate'\nexport { normalizeCalc } from './calc/normalizeCalc'\nexport type { CalcExpression } from './calc/types'\nexport type { UploadsCollectionConfig, UploadsOption } from './collections/uploads'\nexport { buildUploadsCollection, FORM_UPLOADS_SLUG, resolveUploads } from './collections/uploads'\nexport { evaluateCondition } from './conditions/evaluate'\nexport type { FieldCondition } from './conditions/types'\nexport { defaultConsentSources } from './consent/builtin'\nexport type { ConsentProof } from './consent/captureConsent'\nexport { captureConsent } from './consent/captureConsent'\nexport type {\n\tAnyConsentSource,\n\tConsentLink,\n\tConsentResolveArgs,\n\tConsentResolved,\n\tConsentSource,\n} from './consent/defineConsentSource'\nexport { defineConsentSource } from './consent/defineConsentSource'\nexport type {\n\tConsentSourceOption,\n\tConsentSourceRegistry,\n\tConsentSourcesConfig,\n} from './consent/registry'\nexport { resolveConsentSources } from './consent/registry'\nexport { resolveConsentLinks } from './consent/resolveConsentLinks'\nexport { resolvePublishedVersionRef } from './consent/resolvePublishedVersionRef'\nexport { defineFormField } from './fields/defineFormField'\nexport type { FieldTypeOption, FieldTypeRegistry, FieldTypesConfig } from './fields/registry'\nexport type {\n\tAnyFormFieldDefinition,\n\tFormFieldDefinition,\n\tFormFieldFormat,\n\tFormFieldValidate,\n\tFormFieldValueKind,\n} from './fields/types'\nexport type { PrefillOptions } from './prefill/valuesFromSearchParams'\nexport { valuesFromSearchParams } from './prefill/valuesFromSearchParams'\nexport { DEFAULT_PRESENTATION_NAME, defaultPresentationDescriptors } from './presentations/defaults'\nexport type {\n\tPresentationDescriptorOption,\n\tPresentationDescriptorRegistry,\n\tPresentationsDescriptorConfig,\n} from './presentations/registry'\nexport { resolvePresentationDescriptors } from './presentations/registry'\nexport type {\n\tPresentationDensity,\n\tPresentationDescriptor,\n\tPresentationSurface,\n} from './presentations/types'\nexport { interpolate } from './recall/interpolate'\nexport type { RecallResolver } from './recall/resolver'\nexport { buildRecallResolver, optionLabelsFor } from './recall/resolver'\nexport { defineCaptchaProvider } from './spam/captcha'\nexport { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from './spam/constants'\nexport { defaultIdentify } from './spam/identify'\nexport { createKvRateLimiter } from './spam/rateLimiter'\nexport { resolveSpamConfig } from './spam/resolveSpam'\nexport type {\n\tCaptchaProvider,\n\tCaptchaVerifyArgs,\n\tIdentifyFn,\n\tRateLimitCheckArgs,\n\tRateLimitConfig,\n\tRateLimiter,\n\tRateLimitResult,\n\tSpamConfig,\n\tSpamMetadataConfig,\n\tSpamOption,\n} from './spam/types'\nexport { captureFileRef } from './uploads/captureFileRef'\nexport { resolveFileRef } from './uploads/resolveFileRef'\nexport type { FileFieldConfig, FileRef, FileRefError } from './uploads/types'\nexport { defineValidationRule } from './validation/defineValidationRule'\nexport type {\n\tValidationRuleOption,\n\tValidationRuleRegistry,\n\tValidationRulesConfig,\n} from './validation/registry'\nexport type {\n\tAnyValidationRuleDefinition,\n\tValidationRuleDefinition,\n\tValidationRuleResult,\n\tValidationSeverity,\n} from './validation/types'\nexport type { FormBuilderPluginOptions as PluginOptions }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0EA,MAAa,cAAc,aAAuC;CACjE,MAAM;CACN,OAAO;CACP,SAAS,EAAE,QAAQ,SAAS,GAAG,cAAsB;EACpD,IAAI,QAAQ,aAAa,MACxB,OAAO;EAER,MAAM,WAAW,kBAAkB,yBAAyB,QAAQ,MAAM;EAC1E,MAAM,eAAe,uBAAuB,wBAAwB,QAAQ,KAAK;EACjF,MAAM,kBAAkB,sBAAsB,uBAAuB,QAAQ,cAAc;EAC3F,MAAM,uBAAuB,+BAC5B,gCACA,QAAQ,aACT;EACA,MAAM,iBAAiB,eAAe,0BAA0B,QAAQ,OAAO;EAC/E,MAAM,UAAU,eAAe,QAAQ,OAAO;EAC9C,MAAM,OAAO,kBAAkB,QAAQ,IAAI;EAC3C,qBAAqB,QAAQ,QAAQ,YAAY;EACjD,oBAAoB;GACnB;GACA;GACA;GACA;GACA;GACA;GACA,eAAe,QAAQ,QAAQ,kBAAkB;GACjD,QAAQ,QAAQ;GAChB;GACA;GACA,yBAAyB,QAAQ,2BAA2B;GAC5D,WAAW,QAAQ;EACpB,CAAC;EACD,OAAO;CACR;AACD,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { type Config, definePlugin } from 'payload'\nimport type { RichTextBodyOption } from './actions/body/serializeBody'\nimport { defaultActionDefinitions } from './actions/builtin'\nimport type { ActionsConfig } from './actions/registry'\nimport { resolveActions } from './actions/registry'\nimport { resolveUploads, type UploadsOption } from './collections/uploads'\nimport { defaultConsentSources } from './consent/builtin'\nimport type { ConsentSourcesConfig } from './consent/registry'\nimport { resolveConsentSources } from './consent/registry'\nimport type { FormEventSink } from './events/types'\nimport { defaultFieldDefinitions } from './fields/builtin'\nimport { type FieldTypesConfig, resolveFieldTypes } from './fields/registry'\nimport type { CollectionOverrides } from './plugin/collectionOverrides'\nimport { registerCollections } from './plugin/registerCollections'\nimport { registerTranslations } from './plugin/registerTranslations'\nimport { defaultPresentationDescriptors } from './presentations/defaults'\nimport type { PresentationsDescriptorConfig } from './presentations/registry'\nimport { resolvePresentationDescriptors } from './presentations/registry'\nimport { resolveSpamConfig } from './spam/resolveSpam'\nimport type { SpamOption } from './spam/types'\nimport type { TranslationsOption } from './translations'\nimport { defaultValidationRules } from './validation/builtin'\nimport { resolveValidationRules, type ValidationRulesConfig } from './validation/registry'\n\nexport type FormBuilderPluginOptions = {\n\tdisabled?: boolean\n\t/**\n\t * Per-locale overrides for this plugin's UI strings, keyed by the typed\n\t * translation keys exported from `@10x-media/form-builder/i18n`. Values win\n\t * over the built-in locales key-by-key; locales the plugin does not ship are\n\t * added whole. App-level `i18n.translations` still wins over both.\n\t */\n\ttranslations?: TranslationsOption\n\t/** Pluggable sink for form lifecycle events. Defaults to a no-op; analytics adapters or a future analytics plugin subscribe here. */\n\tevents?: FormEventSink\n\t/** Add, override, or remove field types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\tfields?: FieldTypesConfig\n\t/** Add, override, or remove presentations. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\tpresentations?: PresentationsDescriptorConfig\n\t/** Add, override, or remove validation rule types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\trules?: ValidationRulesConfig\n\t/** Add, override, or remove post-submit action types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\tactions?: ActionsConfig\n\t/**\n\t * Customize how rich text action bodies are rendered. `converters` spread over the default\n\t * Lexical node converters; `serialize` replaces the whole pipeline (e.g. to target chat or\n\t * plain-text channels instead of email HTML).\n\t */\n\trichText?: RichTextBodyOption\n\t/** Add, override, or remove consent source types. `false` removes a built-in, `true` keeps it, an object adds or replaces one. */\n\tconsentSources?: ConsentSourcesConfig\n\t/** The built-in `form-uploads` collection backing file fields. `false` disables it (bring your own); an object overrides slug/upload/access/fields. */\n\tuploads?: UploadsOption\n\t/** Honeypot + rate-limiting (on by default) + a captcha adapter seam + upload-ownership scoping. `false` disables the whole subsystem. */\n\tspam?: SpamOption\n\t/**\n\t * When `true`, the raw `values`, `descriptors`, and `consent` JSON fields are visible in the\n\t * submission admin view. Default `false` — those fields are fully represented by the\n\t * `SubmissionAnswers` UI component and are noisy when shown alongside it.\n\t */\n\tshowSubmissionRawFields?: boolean\n\t/**\n\t * Override individual plugin-managed collections using explicit spreads. Each key accepts a\n\t * `CollectionOverrides` object: top-level keys are spread with the plugin's defaults (spread\n\t * order per key determines who wins), hooks are appended after the plugin's own hooks, and\n\t * `fields` is a function that receives the default fields and returns the final array so\n\t * additions/removals are always intentional.\n\t */\n\toverrides?: {\n\t\tforms?: CollectionOverrides\n\t\tformSubmissions?: CollectionOverrides\n\t\tuploads?: CollectionOverrides\n\t}\n}\n\ndeclare module 'payload' {\n\tinterface RegisteredPlugins {\n\t\t'@10x-media/form-builder': FormBuilderPluginOptions\n\t}\n}\n\nexport const formBuilder = definePlugin<FormBuilderPluginOptions>({\n\tslug: '@10x-media/form-builder',\n\torder: 50,\n\tplugin: ({ config, plugins, ...options }): Config => {\n\t\tif (options.disabled === true) {\n\t\t\treturn config\n\t\t}\n\t\tconst registry = resolveFieldTypes(defaultFieldDefinitions, options.fields)\n\t\tconst ruleRegistry = resolveValidationRules(defaultValidationRules, options.rules)\n\t\tconst consentRegistry = resolveConsentSources(defaultConsentSources, options.consentSources)\n\t\tconst presentationRegistry = resolvePresentationDescriptors(\n\t\t\tdefaultPresentationDescriptors,\n\t\t\toptions.presentations\n\t\t)\n\t\tconst actionRegistry = resolveActions(defaultActionDefinitions, options.actions)\n\t\tconst uploads = resolveUploads(options.uploads)\n\t\tconst spam = resolveSpamConfig(options.spam)\n\t\tregisterTranslations(config, options.translations)\n\t\tregisterCollections({\n\t\t\tconfig,\n\t\t\tregistry,\n\t\t\truleRegistry,\n\t\t\tconsentRegistry,\n\t\t\tpresentationRegistry,\n\t\t\tactionRegistry,\n\t\t\trichText: options.richText,\n\t\t\thasJobsPlugin: Boolean(plugins['@10x-media/jobs']),\n\t\t\tevents: options.events,\n\t\t\tuploads,\n\t\t\tspam,\n\t\t\tshowSubmissionRawFields: options.showSubmissionRawFields ?? false,\n\t\t\toverrides: options.overrides,\n\t\t})\n\t\treturn config\n\t},\n})\n\nexport type {\n\tBodyConverter,\n\tBodyConverterArgs,\n\tBodyRender,\n} from './actions/body/converters'\nexport { defaultBodyConverters, sanitizeUrl } from './actions/body/converters'\nexport { escapeHtml } from './actions/body/escapeHtml'\nexport type {\n\tBodyContext,\n\tRichTextBodyOption,\n\tSerializeBodyArgs,\n} from './actions/body/serializeBody'\nexport { serializeBody } from './actions/body/serializeBody'\nexport { renderAllValues, renderAllValuesTable } from './actions/body/wildcards'\nexport { defaultActionDefinitions } from './actions/builtin'\nexport type { ActionDefinition, ActionRunArgs, AnyActionDefinition } from './actions/defineAction'\nexport { defineAction } from './actions/defineAction'\nexport type { ActionOption, ActionRegistry, ActionsConfig } from './actions/registry'\nexport { resolveActions } from './actions/registry'\nexport type { ActionResult } from './actions/runActions'\nexport { SIGNATURE_HEADER, signPayload } from './actions/sign'\nexport type {\n\tAggregateFieldResponsesArgs,\n\tAggregateFormResponsesArgs,\n} from './aggregation/aggregateResponses'\nexport {\n\taggregateFieldResponses,\n\taggregateFormResponses,\n\tfieldHasOptions,\n} from './aggregation/aggregateResponses'\nexport { aggregateRowForField, aggregateRowsForFields } from './aggregation/aggregateRows'\nexport type {\n\tResolveResultsRequestArgs,\n\tResolveResultsRequestResult,\n} from './aggregation/resolveResultsRequest'\nexport { resolveFormResultsRequest } from './aggregation/resolveResultsRequest'\nexport type {\n\tAggregationBucket,\n\tAggregationRow,\n\tFieldAggregation,\n\tFieldMeta,\n\tSubmissionStatusFilter,\n} from './aggregation/types'\nexport { calcExpressionOf, computeCalcFields } from './calc/computeCalcFields'\nexport { evaluateCalc } from './calc/evaluate'\nexport { normalizeCalc } from './calc/normalizeCalc'\nexport type { CalcExpression } from './calc/types'\nexport type { UploadsCollectionConfig, UploadsOption } from './collections/uploads'\nexport { buildUploadsCollection, FORM_UPLOADS_SLUG, resolveUploads } from './collections/uploads'\nexport { evaluateCondition } from './conditions/evaluate'\nexport type { FieldCondition } from './conditions/types'\nexport { defaultConsentSources } from './consent/builtin'\nexport type { ConsentProof } from './consent/captureConsent'\nexport { captureConsent } from './consent/captureConsent'\nexport type {\n\tAnyConsentSource,\n\tConsentLink,\n\tConsentResolveArgs,\n\tConsentResolved,\n\tConsentSource,\n} from './consent/defineConsentSource'\nexport { defineConsentSource } from './consent/defineConsentSource'\nexport type {\n\tConsentSourceOption,\n\tConsentSourceRegistry,\n\tConsentSourcesConfig,\n} from './consent/registry'\nexport { resolveConsentSources } from './consent/registry'\nexport { resolveConsentLinks } from './consent/resolveConsentLinks'\nexport { resolvePublishedVersionRef } from './consent/resolvePublishedVersionRef'\nexport { defaultFieldDefinitions, defaultFieldDefinitionsByType } from './fields/builtin'\nexport { fileMimeTypeOptions } from './fields/builtin/file'\nexport { defineFormField } from './fields/defineFormField'\nexport type { FieldTypeOption, FieldTypeRegistry, FieldTypesConfig } from './fields/registry'\nexport type {\n\tAnyFormFieldDefinition,\n\tFormFieldDefinition,\n\tFormFieldFormat,\n\tFormFieldValidate,\n\tFormFieldValueKind,\n} from './fields/types'\nexport type { PrefillOptions } from './prefill/valuesFromSearchParams'\nexport { valuesFromSearchParams } from './prefill/valuesFromSearchParams'\nexport { DEFAULT_PRESENTATION_NAME, defaultPresentationDescriptors } from './presentations/defaults'\nexport type {\n\tPresentationDescriptorOption,\n\tPresentationDescriptorRegistry,\n\tPresentationsDescriptorConfig,\n} from './presentations/registry'\nexport { resolvePresentationDescriptors } from './presentations/registry'\nexport type {\n\tPresentationDensity,\n\tPresentationDescriptor,\n\tPresentationSurface,\n} from './presentations/types'\nexport { interpolate } from './recall/interpolate'\nexport type { RecallResolver } from './recall/resolver'\nexport { buildRecallResolver, optionLabelsFor } from './recall/resolver'\nexport { defineCaptchaProvider } from './spam/captcha'\nexport { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from './spam/constants'\nexport { defaultIdentify } from './spam/identify'\nexport type { HcaptchaProviderOptions } from './spam/providers/hcaptcha'\nexport { hcaptchaProvider } from './spam/providers/hcaptcha'\nexport type { RecaptchaProviderOptions } from './spam/providers/recaptcha'\nexport { recaptchaProvider } from './spam/providers/recaptcha'\nexport type { TurnstileProviderOptions } from './spam/providers/turnstile'\nexport { turnstileProvider } from './spam/providers/turnstile'\nexport { createKvRateLimiter } from './spam/rateLimiter'\nexport { resolveSpamConfig } from './spam/resolveSpam'\nexport type {\n\tCaptchaProvider,\n\tCaptchaVerifyArgs,\n\tIdentifyFn,\n\tRateLimitCheckArgs,\n\tRateLimitConfig,\n\tRateLimiter,\n\tRateLimitResult,\n\tSpamConfig,\n\tSpamMetadataConfig,\n\tSpamOption,\n} from './spam/types'\nexport { captureFileRef } from './uploads/captureFileRef'\nexport { formatBytes } from './uploads/formatBytes'\nexport { resolveFileRef } from './uploads/resolveFileRef'\nexport type { FileFieldConfig, FileRef, FileRefError } from './uploads/types'\nexport { defaultValidationRules, defaultValidationRulesByType } from './validation/builtin'\nexport { defineValidationRule } from './validation/defineValidationRule'\nexport type {\n\tValidationRuleOption,\n\tValidationRuleRegistry,\n\tValidationRulesConfig,\n} from './validation/registry'\nexport type {\n\tAnyValidationRuleDefinition,\n\tValidationRuleDefinition,\n\tValidationRuleResult,\n\tValidationSeverity,\n} from './validation/types'\nexport type { FormBuilderPluginOptions as PluginOptions }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFA,MAAa,cAAc,aAAuC;CACjE,MAAM;CACN,OAAO;CACP,SAAS,EAAE,QAAQ,SAAS,GAAG,cAAsB;EACpD,IAAI,QAAQ,aAAa,MACxB,OAAO;EAER,MAAM,WAAW,kBAAkB,yBAAyB,QAAQ,MAAM;EAC1E,MAAM,eAAe,uBAAuB,wBAAwB,QAAQ,KAAK;EACjF,MAAM,kBAAkB,sBAAsB,uBAAuB,QAAQ,cAAc;EAC3F,MAAM,uBAAuB,+BAC5B,gCACA,QAAQ,aACT;EACA,MAAM,iBAAiB,eAAe,0BAA0B,QAAQ,OAAO;EAC/E,MAAM,UAAU,eAAe,QAAQ,OAAO;EAC9C,MAAM,OAAO,kBAAkB,QAAQ,IAAI;EAC3C,qBAAqB,QAAQ,QAAQ,YAAY;EACjD,oBAAoB;GACnB;GACA;GACA;GACA;GACA;GACA;GACA,UAAU,QAAQ;GAClB,eAAe,QAAQ,QAAQ,kBAAkB;GACjD,QAAQ,QAAQ;GAChB;GACA;GACA,yBAAyB,QAAQ,2BAA2B;GAC5D,WAAW,QAAQ;EACpB,CAAC;EACD,OAAO;CACR;AACD,CAAC"}
@@ -3,8 +3,8 @@ import { buildSubmissionsCollection } from "../collections/formSubmissions.js";
3
3
  import { registerActionsTask } from "../actions/task.js";
4
4
  import { buildUploadOwnerStamp, buildUploadRateLimit } from "../spam/uploadHooks.js";
5
5
  //#region src/plugin/registerCollections.ts
6
- const registerCollections = ({ config, registry, ruleRegistry, consentRegistry, presentationRegistry, actionRegistry, hasJobsPlugin, events, uploads, spam, showSubmissionRawFields, overrides }) => {
7
- registerActionsTask(config, actionRegistry);
6
+ const registerCollections = ({ config, registry, ruleRegistry, consentRegistry, presentationRegistry, actionRegistry, richText, hasJobsPlugin, events, uploads, spam, showSubmissionRawFields, overrides }) => {
7
+ registerActionsTask(config, actionRegistry, richText);
8
8
  const hasRunner = Boolean(config.jobs?.autoRun) || hasJobsPlugin;
9
9
  let uploadsCollection = null;
10
10
  if (uploads.enabled && uploads.collection) {
@@ -53,6 +53,7 @@ const registerCollections = ({ config, registry, ruleRegistry, consentRegistry,
53
53
  ruleRegistry,
54
54
  consentRegistry,
55
55
  actionRegistry,
56
+ richText,
56
57
  events,
57
58
  hasRunner,
58
59
  uploadSlug: uploads.slug,
@@ -1 +1 @@
1
- {"version":3,"file":"registerCollections.js","names":[],"sources":["../../src/plugin/registerCollections.ts"],"sourcesContent":["import type { CollectionConfig, Config, Field } from 'payload'\nimport type { ActionRegistry } from '../actions/registry'\nimport { registerActionsTask } from '../actions/task'\nimport { buildSubmissionsCollection } from '../collections/formSubmissions'\nimport { buildFormsCollection } from '../collections/forms'\nimport type { ConsentSourceRegistry } from '../consent/registry'\nimport type { FormEventSink } from '../events/types'\nimport type { FieldTypeRegistry } from '../fields/registry'\nimport type { PresentationDescriptorRegistry } from '../presentations/registry'\nimport type { ResolvedSpamConfig } from '../spam/types'\nimport { buildUploadOwnerStamp, buildUploadRateLimit } from '../spam/uploadHooks'\nimport type { ValidationRuleRegistry } from '../validation/registry'\nimport type { CollectionOverrides } from './collectionOverrides'\n\ntype RegisterCollectionsArgs = {\n\tconfig: Config\n\tregistry: FieldTypeRegistry\n\truleRegistry: ValidationRuleRegistry\n\tconsentRegistry: ConsentSourceRegistry\n\tpresentationRegistry: PresentationDescriptorRegistry\n\tactionRegistry: ActionRegistry\n\thasJobsPlugin: boolean\n\tevents?: FormEventSink\n\tuploads: { enabled: boolean; slug: string; collection?: CollectionConfig }\n\tspam: ResolvedSpamConfig | false\n\tshowSubmissionRawFields: boolean\n\toverrides?: {\n\t\tforms?: CollectionOverrides\n\t\tformSubmissions?: CollectionOverrides\n\t\tuploads?: CollectionOverrides\n\t}\n}\n\nexport const registerCollections = ({\n\tconfig,\n\tregistry,\n\truleRegistry,\n\tconsentRegistry,\n\tpresentationRegistry,\n\tactionRegistry,\n\thasJobsPlugin,\n\tevents,\n\tuploads,\n\tspam,\n\tshowSubmissionRawFields,\n\toverrides,\n}: RegisterCollectionsArgs): void => {\n\tregisterActionsTask(config, actionRegistry)\n\tconst hasRunner = Boolean(config.jobs?.autoRun) || hasJobsPlugin\n\n\tlet uploadsCollection: CollectionConfig | null = null\n\tif (uploads.enabled && uploads.collection) {\n\t\tconst col = uploads.collection\n\n\t\t// Spam hooks are added first (plugin-owned invariant)\n\t\tif (spam) {\n\t\t\tcol.hooks = col.hooks ?? {}\n\t\t\tcol.hooks.beforeOperation = [...(col.hooks.beforeOperation ?? []), buildUploadRateLimit(spam)]\n\t\t\tcol.hooks.beforeValidate = [...(col.hooks.beforeValidate ?? []), buildUploadOwnerStamp(spam)]\n\t\t}\n\n\t\t// Apply CollectionOverrides using explicit spreads after spam hooks are in place.\n\t\t// ...col first so the plugin defaults are the base, ...(ov ?? {}) second so the consumer\n\t\t// wins for any top-level key not explicitly re-set below (consistent with forms/formSubmissions).\n\t\t// The locked keys (hooks array ordering, fields function) are spread last.\n\t\tconst ov = overrides?.uploads\n\t\tif (ov) {\n\t\t\tconst defaultFields = (col.fields ?? []) as Field[]\n\t\t\tuploadsCollection = {\n\t\t\t\t...col,\n\t\t\t\t...(ov ?? {}),\n\t\t\t\taccess: { ...(col.access ?? {}), ...(ov.access ?? {}) },\n\t\t\t\tadmin: { ...(col.admin ?? {}), ...(ov.admin ?? {}) },\n\t\t\t\thooks: {\n\t\t\t\t\t...(ov.hooks ?? {}),\n\t\t\t\t\t// Spam hooks stay first in each array; consumer hooks appended\n\t\t\t\t\tbeforeOperation: [\n\t\t\t\t\t\t...(col.hooks?.beforeOperation ?? []),\n\t\t\t\t\t\t...(ov.hooks?.beforeOperation ?? []),\n\t\t\t\t\t],\n\t\t\t\t\tbeforeValidate: [\n\t\t\t\t\t\t...(col.hooks?.beforeValidate ?? []),\n\t\t\t\t\t\t...(ov.hooks?.beforeValidate ?? []),\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tfields: ov.fields ? ov.fields({ defaultFields }) : defaultFields,\n\t\t\t}\n\t\t} else {\n\t\t\tuploadsCollection = col\n\t\t}\n\t}\n\n\tconfig.collections = [\n\t\t...(config.collections ?? []),\n\t\t...(uploadsCollection ? [uploadsCollection] : []),\n\t\tbuildFormsCollection({\n\t\t\tregistry,\n\t\t\truleRegistry,\n\t\t\tconsentRegistry,\n\t\t\tpresentationRegistry,\n\t\t\tactionRegistry,\n\t\t\toverrides: overrides?.forms,\n\t\t}),\n\t\tbuildSubmissionsCollection({\n\t\t\tregistry,\n\t\t\truleRegistry,\n\t\t\tconsentRegistry,\n\t\t\tactionRegistry,\n\t\t\tevents,\n\t\t\thasRunner,\n\t\t\tuploadSlug: uploads.slug,\n\t\t\tspam,\n\t\t\tshowRawFields: showSubmissionRawFields,\n\t\t\toverrides: overrides?.formSubmissions,\n\t\t}),\n\t]\n}\n"],"mappings":";;;;;AAiCA,MAAa,uBAAuB,EACnC,QACA,UACA,cACA,iBACA,sBACA,gBACA,eACA,QACA,SACA,MACA,yBACA,gBACoC;CACpC,oBAAoB,QAAQ,cAAc;CAC1C,MAAM,YAAY,QAAQ,OAAO,MAAM,OAAO,KAAK;CAEnD,IAAI,oBAA6C;CACjD,IAAI,QAAQ,WAAW,QAAQ,YAAY;EAC1C,MAAM,MAAM,QAAQ;EAGpB,IAAI,MAAM;GACT,IAAI,QAAQ,IAAI,SAAS,CAAC;GAC1B,IAAI,MAAM,kBAAkB,CAAC,GAAI,IAAI,MAAM,mBAAmB,CAAC,GAAI,qBAAqB,IAAI,CAAC;GAC7F,IAAI,MAAM,iBAAiB,CAAC,GAAI,IAAI,MAAM,kBAAkB,CAAC,GAAI,sBAAsB,IAAI,CAAC;EAC7F;EAMA,MAAM,KAAK,WAAW;EACtB,IAAI,IAAI;GACP,MAAM,gBAAiB,IAAI,UAAU,CAAC;GACtC,oBAAoB;IACnB,GAAG;IACH,GAAI,MAAM,CAAC;IACX,QAAQ;KAAE,GAAI,IAAI,UAAU,CAAC;KAAI,GAAI,GAAG,UAAU,CAAC;IAAG;IACtD,OAAO;KAAE,GAAI,IAAI,SAAS,CAAC;KAAI,GAAI,GAAG,SAAS,CAAC;IAAG;IACnD,OAAO;KACN,GAAI,GAAG,SAAS,CAAC;KAEjB,iBAAiB,CAChB,GAAI,IAAI,OAAO,mBAAmB,CAAC,GACnC,GAAI,GAAG,OAAO,mBAAmB,CAAC,CACnC;KACA,gBAAgB,CACf,GAAI,IAAI,OAAO,kBAAkB,CAAC,GAClC,GAAI,GAAG,OAAO,kBAAkB,CAAC,CAClC;IACD;IACA,QAAQ,GAAG,SAAS,GAAG,OAAO,EAAE,cAAc,CAAC,IAAI;GACpD;EACD,OACC,oBAAoB;CAEtB;CAEA,OAAO,cAAc;EACpB,GAAI,OAAO,eAAe,CAAC;EAC3B,GAAI,oBAAoB,CAAC,iBAAiB,IAAI,CAAC;EAC/C,qBAAqB;GACpB;GACA;GACA;GACA;GACA;GACA,WAAW,WAAW;EACvB,CAAC;EACD,2BAA2B;GAC1B;GACA;GACA;GACA;GACA;GACA;GACA,YAAY,QAAQ;GACpB;GACA,eAAe;GACf,WAAW,WAAW;EACvB,CAAC;CACF;AACD"}
1
+ {"version":3,"file":"registerCollections.js","names":[],"sources":["../../src/plugin/registerCollections.ts"],"sourcesContent":["import type { CollectionConfig, Config, Field } from 'payload'\nimport type { RichTextBodyOption } from '../actions/body/serializeBody'\nimport type { ActionRegistry } from '../actions/registry'\nimport { registerActionsTask } from '../actions/task'\nimport { buildSubmissionsCollection } from '../collections/formSubmissions'\nimport { buildFormsCollection } from '../collections/forms'\nimport type { ConsentSourceRegistry } from '../consent/registry'\nimport type { FormEventSink } from '../events/types'\nimport type { FieldTypeRegistry } from '../fields/registry'\nimport type { PresentationDescriptorRegistry } from '../presentations/registry'\nimport type { ResolvedSpamConfig } from '../spam/types'\nimport { buildUploadOwnerStamp, buildUploadRateLimit } from '../spam/uploadHooks'\nimport type { ValidationRuleRegistry } from '../validation/registry'\nimport type { CollectionOverrides } from './collectionOverrides'\n\ntype RegisterCollectionsArgs = {\n\tconfig: Config\n\tregistry: FieldTypeRegistry\n\truleRegistry: ValidationRuleRegistry\n\tconsentRegistry: ConsentSourceRegistry\n\tpresentationRegistry: PresentationDescriptorRegistry\n\tactionRegistry: ActionRegistry\n\trichText?: RichTextBodyOption\n\thasJobsPlugin: boolean\n\tevents?: FormEventSink\n\tuploads: { enabled: boolean; slug: string; collection?: CollectionConfig }\n\tspam: ResolvedSpamConfig | false\n\tshowSubmissionRawFields: boolean\n\toverrides?: {\n\t\tforms?: CollectionOverrides\n\t\tformSubmissions?: CollectionOverrides\n\t\tuploads?: CollectionOverrides\n\t}\n}\n\nexport const registerCollections = ({\n\tconfig,\n\tregistry,\n\truleRegistry,\n\tconsentRegistry,\n\tpresentationRegistry,\n\tactionRegistry,\n\trichText,\n\thasJobsPlugin,\n\tevents,\n\tuploads,\n\tspam,\n\tshowSubmissionRawFields,\n\toverrides,\n}: RegisterCollectionsArgs): void => {\n\tregisterActionsTask(config, actionRegistry, richText)\n\tconst hasRunner = Boolean(config.jobs?.autoRun) || hasJobsPlugin\n\n\tlet uploadsCollection: CollectionConfig | null = null\n\tif (uploads.enabled && uploads.collection) {\n\t\tconst col = uploads.collection\n\n\t\t// Spam hooks are added first (plugin-owned invariant)\n\t\tif (spam) {\n\t\t\tcol.hooks = col.hooks ?? {}\n\t\t\tcol.hooks.beforeOperation = [...(col.hooks.beforeOperation ?? []), buildUploadRateLimit(spam)]\n\t\t\tcol.hooks.beforeValidate = [...(col.hooks.beforeValidate ?? []), buildUploadOwnerStamp(spam)]\n\t\t}\n\n\t\t// Apply CollectionOverrides using explicit spreads after spam hooks are in place.\n\t\t// ...col first so the plugin defaults are the base, ...(ov ?? {}) second so the consumer\n\t\t// wins for any top-level key not explicitly re-set below (consistent with forms/formSubmissions).\n\t\t// The locked keys (hooks array ordering, fields function) are spread last.\n\t\tconst ov = overrides?.uploads\n\t\tif (ov) {\n\t\t\tconst defaultFields = (col.fields ?? []) as Field[]\n\t\t\tuploadsCollection = {\n\t\t\t\t...col,\n\t\t\t\t...(ov ?? {}),\n\t\t\t\taccess: { ...(col.access ?? {}), ...(ov.access ?? {}) },\n\t\t\t\tadmin: { ...(col.admin ?? {}), ...(ov.admin ?? {}) },\n\t\t\t\thooks: {\n\t\t\t\t\t...(ov.hooks ?? {}),\n\t\t\t\t\t// Spam hooks stay first in each array; consumer hooks appended\n\t\t\t\t\tbeforeOperation: [\n\t\t\t\t\t\t...(col.hooks?.beforeOperation ?? []),\n\t\t\t\t\t\t...(ov.hooks?.beforeOperation ?? []),\n\t\t\t\t\t],\n\t\t\t\t\tbeforeValidate: [\n\t\t\t\t\t\t...(col.hooks?.beforeValidate ?? []),\n\t\t\t\t\t\t...(ov.hooks?.beforeValidate ?? []),\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tfields: ov.fields ? ov.fields({ defaultFields }) : defaultFields,\n\t\t\t}\n\t\t} else {\n\t\t\tuploadsCollection = col\n\t\t}\n\t}\n\n\tconfig.collections = [\n\t\t...(config.collections ?? []),\n\t\t...(uploadsCollection ? [uploadsCollection] : []),\n\t\tbuildFormsCollection({\n\t\t\tregistry,\n\t\t\truleRegistry,\n\t\t\tconsentRegistry,\n\t\t\tpresentationRegistry,\n\t\t\tactionRegistry,\n\t\t\toverrides: overrides?.forms,\n\t\t}),\n\t\tbuildSubmissionsCollection({\n\t\t\tregistry,\n\t\t\truleRegistry,\n\t\t\tconsentRegistry,\n\t\t\tactionRegistry,\n\t\t\trichText,\n\t\t\tevents,\n\t\t\thasRunner,\n\t\t\tuploadSlug: uploads.slug,\n\t\t\tspam,\n\t\t\tshowRawFields: showSubmissionRawFields,\n\t\t\toverrides: overrides?.formSubmissions,\n\t\t}),\n\t]\n}\n"],"mappings":";;;;;AAmCA,MAAa,uBAAuB,EACnC,QACA,UACA,cACA,iBACA,sBACA,gBACA,UACA,eACA,QACA,SACA,MACA,yBACA,gBACoC;CACpC,oBAAoB,QAAQ,gBAAgB,QAAQ;CACpD,MAAM,YAAY,QAAQ,OAAO,MAAM,OAAO,KAAK;CAEnD,IAAI,oBAA6C;CACjD,IAAI,QAAQ,WAAW,QAAQ,YAAY;EAC1C,MAAM,MAAM,QAAQ;EAGpB,IAAI,MAAM;GACT,IAAI,QAAQ,IAAI,SAAS,CAAC;GAC1B,IAAI,MAAM,kBAAkB,CAAC,GAAI,IAAI,MAAM,mBAAmB,CAAC,GAAI,qBAAqB,IAAI,CAAC;GAC7F,IAAI,MAAM,iBAAiB,CAAC,GAAI,IAAI,MAAM,kBAAkB,CAAC,GAAI,sBAAsB,IAAI,CAAC;EAC7F;EAMA,MAAM,KAAK,WAAW;EACtB,IAAI,IAAI;GACP,MAAM,gBAAiB,IAAI,UAAU,CAAC;GACtC,oBAAoB;IACnB,GAAG;IACH,GAAI,MAAM,CAAC;IACX,QAAQ;KAAE,GAAI,IAAI,UAAU,CAAC;KAAI,GAAI,GAAG,UAAU,CAAC;IAAG;IACtD,OAAO;KAAE,GAAI,IAAI,SAAS,CAAC;KAAI,GAAI,GAAG,SAAS,CAAC;IAAG;IACnD,OAAO;KACN,GAAI,GAAG,SAAS,CAAC;KAEjB,iBAAiB,CAChB,GAAI,IAAI,OAAO,mBAAmB,CAAC,GACnC,GAAI,GAAG,OAAO,mBAAmB,CAAC,CACnC;KACA,gBAAgB,CACf,GAAI,IAAI,OAAO,kBAAkB,CAAC,GAClC,GAAI,GAAG,OAAO,kBAAkB,CAAC,CAClC;IACD;IACA,QAAQ,GAAG,SAAS,GAAG,OAAO,EAAE,cAAc,CAAC,IAAI;GACpD;EACD,OACC,oBAAoB;CAEtB;CAEA,OAAO,cAAc;EACpB,GAAI,OAAO,eAAe,CAAC;EAC3B,GAAI,oBAAoB,CAAC,iBAAiB,IAAI,CAAC;EAC/C,qBAAqB;GACpB;GACA;GACA;GACA;GACA;GACA,WAAW,WAAW;EACvB,CAAC;EACD,2BAA2B;GAC1B;GACA;GACA;GACA;GACA;GACA;GACA;GACA,YAAY,QAAQ;GACpB;GACA,eAAe;GACf,WAAW,WAAW;EACvB,CAAC;CACF;AACD"}
@@ -24,8 +24,8 @@ import { buildFieldTypeRegistry, buildValidationRuleRegistry, visibleFields } fr
24
24
  import { formReducer, initialFormState } from "./state.js";
25
25
  import { submitForm } from "./submitForm.js";
26
26
  import { validateFieldValue } from "./validateField.js";
27
- import { createElement, useCallback, useEffect, useId, useMemo, useReducer, useRef, useState } from "react";
28
27
  import { jsx, jsxs } from "react/jsx-runtime";
28
+ import { createElement, useCallback, useEffect, useId, useMemo, useReducer, useRef, useState } from "react";
29
29
  //#region src/react/Form.tsx
30
30
  const isEmpty = (value) => value == null || value === "" || Array.isArray(value) && value.length === 0;
31
31
  const FIELD_WIDTHS = new Set([
@@ -193,7 +193,7 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
193
193
  if (result.errors.length > 0) hasError = true;
194
194
  }
195
195
  if (hasError) return;
196
- const next = resolveNextStepId(flow, currentStepId, state.values);
196
+ const next = resolveNextStepId(flow, currentStepId, effectiveValues);
197
197
  if (!next) return;
198
198
  emitFormEvent(sinkRef.current, formIdRef.current, {
199
199
  type: "step.completed",
@@ -350,7 +350,7 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
350
350
  stepIndex: flow.steps.findIndex((s) => s.id === currentStepId),
351
351
  stepCount: flow.steps.length,
352
352
  isFirst: history.length === 0,
353
- isTerminal: currentStepId ? isTerminalStepId(flow, currentStepId, state.values) : true,
353
+ isTerminal: currentStepId ? isTerminalStepId(flow, currentStepId, effectiveValues) : true,
354
354
  goNext: () => {
355
355
  goNext();
356
356
  },
@@ -1 +1 @@
1
- {"version":3,"file":"Form.js","names":[],"sources":["../../src/react/Form.tsx"],"sourcesContent":["'use client'\n\nimport {\n\tcreateElement,\n\ttype FormEvent as ReactFormEvent,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseMemo,\n\tuseReducer,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport { calcExpressionOf, computeCalcFields } from '../calc/computeCalcFields'\nimport { evaluateCondition } from '../conditions/evaluate'\nimport { noopEventSink } from '../events/noopSink'\nimport type { FormEventSink } from '../events/types'\nimport type { AnyFormFieldDefinition } from '../fields/types'\nimport { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames } from '../flow/engine'\nimport type { FormFlow } from '../flow/types'\nimport { defaultPresentationDescriptors } from '../presentations/defaults'\nimport { interpolate } from '../recall/interpolate'\nimport { buildRecallResolver } from '../recall/resolver'\nimport { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from '../spam/constants'\nimport type { FormFieldInstance, SubmissionValue } from '../submissions/types'\nimport { en } from '../translations/en'\nimport { makeTranslate } from '../translations/makeTranslate'\nimport type { AnyValidationRuleDefinition } from '../validation/types'\nimport { cn } from './cn'\nimport type { FieldRenderer, RendererTranslate } from './contract'\nimport { emitFormEvent } from './events'\nimport { FormContext, type FormStepInfo } from './FormContext'\nimport { type FieldWidth, FormLayout, widthProps } from './FormLayout'\nimport { Honeypot } from './Honeypot'\nimport { defaultPresentations } from './presentation/presentations'\nimport { type PresentationsConfig, resolvePresentations } from './presentation/registry'\nimport type { FormPresentation } from './presentation/types'\nimport { applyRecall } from './recall'\nimport { type RenderersConfig, resolveRenderers } from './registry'\nimport { defaultRenderers } from './renderers'\nimport { buildFieldTypeRegistry, buildValidationRuleRegistry, visibleFields } from './resolveForm'\nimport { type FieldErrors, type FormAction, formReducer, initialFormState } from './state'\nimport { type SubmitFormResult, type SubmitHandler, submitForm } from './submitForm'\nimport { useField } from './useField'\nimport { validateFieldValue } from './validateField'\n\nexport type FormDocument = {\n\tid: number | string\n\tfields: FormFieldInstance[]\n\tflow?: FormFlow\n\t/** Stored presentation name; overridden by the `presentation` prop. */\n\tdefaultPresentation?: string\n}\n\n/** Props passed to `renderSubmit`. */\nexport type SubmitButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n}\n\n/** Props passed to `renderNext`. */\nexport type NextButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n\tonClick: () => void\n}\n\n/** Props passed to `renderBack`. */\nexport type BackButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n\tonClick: () => void\n}\n\nexport type FormProps = {\n\tform: FormDocument\n\tfieldTypes?: AnyFormFieldDefinition[]\n\trules?: AnyValidationRuleDefinition[]\n\trenderers?: RenderersConfig\n\tapiRoute?: string\n\tonSubmit?: SubmitHandler\n\tonSuccess?: (submissionId?: string) => void\n\tonError?: (message: string) => void\n\tevents?: FormEventSink\n\tt?: RendererTranslate\n\tlocale?: string\n\tlayout?: boolean\n\tsubmitLabel?: string\n\tnextLabel?: string\n\tbackLabel?: string\n\t/** Label for the overlay close control (modal/drawer). */\n\tcloseLabel?: string\n\tsuccessMessage?: string\n\t/** Active presentation: a name into the registry or an inline presentation. Overrides the form's stored default. */\n\tpresentation?: string | FormPresentation\n\t/** Per-render presentation overrides merged onto the defaults (add, replace, or `false` to remove). */\n\tpresentations?: PresentationsConfig\n\t/** Invoked when an overlay presentation dismisses (close button, Escape, outside click, or `dismissOnSuccess`). */\n\tonClose?: () => void\n\t/** Accessible name for an overlay surface. */\n\ttitle?: string\n\t/** Seed initial field values (e.g. from `valuesFromSearchParams`). Still validated on submit. */\n\tinitialValues?: Record<string, unknown>\n\t/** Honeypot decoy (on by default). `false` removes it; `{ name }` matches a customized server `spam.honeypot.fieldName`. */\n\thoneypot?: false | { name?: string }\n\t/** A token from your captcha widget; verified server-side when a captcha provider is configured. */\n\tcaptchaToken?: string\n\t/** Custom layout: render fields with `useField`/`useFormState` instead of the auto-rendered field loop. */\n\tchildren?: ReactNode\n\t/** Additional CSS class names applied to the root `<form>` element (and the success node). */\n\tclassName?: string\n\t/** Replace the default submit button entirely. Receives the resolved label and submitting state. */\n\trenderSubmit?: (props: SubmitButtonRenderProps) => ReactNode\n\t/** Replace the default \"Next\" button in multi-step forms. */\n\trenderNext?: (props: NextButtonRenderProps) => ReactNode\n\t/** Replace the default \"Back\" button in multi-step forms. */\n\trenderBack?: (props: BackButtonRenderProps) => ReactNode\n\t/** CSS class forwarded to the default submit `<button>`. Ignored when `renderSubmit` is provided. */\n\tsubmitButtonClassName?: string\n\t/** CSS class forwarded to the default \"Next\" `<button>`. Ignored when `renderNext` is provided. */\n\tnextButtonClassName?: string\n\t/** CSS class forwarded to the default \"Back\" `<button>`. Ignored when `renderBack` is provided. */\n\tbackButtonClassName?: string\n}\n\nconst isEmpty = (value: unknown): boolean =>\n\tvalue == null || value === '' || (Array.isArray(value) && value.length === 0)\n\nconst FIELD_WIDTHS = new Set<string>(['full', 'half', 'third', 'twoThirds'])\n\ntype FieldHostProps = {\n\tfield: FormFieldInstance\n\trenderer: FieldRenderer\n\tlocale: string\n\tt: RendererTranslate\n}\n\nconst FieldHost = ({ field, renderer, locale, t }: FieldHostProps) => {\n\tconst id = useId()\n\tconst { value, errors, warnings, setValue, onBlur } = useField(field.name)\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: field.name,\n\t\tvalue,\n\t\tonChange: setValue,\n\t\tonBlur,\n\t\terrors,\n\t\twarnings,\n\t\trequired: Boolean(field.required),\n\t\tlocale,\n\t\tt,\n\t})\n}\n\ntype CalcFieldHostProps = FieldHostProps & { value: unknown }\n\n/** Hosts a derived (calc) field: read-only, value supplied from `effectiveValues`, never bound via `useField`. */\nconst CalcFieldHost = ({ field, renderer, value, locale, t }: CalcFieldHostProps) => {\n\tconst id = useId()\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: field.name,\n\t\tvalue,\n\t\tonChange: () => {},\n\t\tonBlur: () => {},\n\t\terrors: [],\n\t\twarnings: [],\n\t\trequired: false,\n\t\tdisabled: true,\n\t\tlocale,\n\t\tt,\n\t})\n}\n\n/** The headless form controller: state, progressive client validation, conditional visibility, submission, events. */\nexport const Form = ({\n\tform,\n\tfieldTypes,\n\trules,\n\trenderers,\n\tapiRoute,\n\tonSubmit,\n\tonSuccess,\n\tonError,\n\tevents,\n\tt,\n\tlocale = 'en',\n\tlayout,\n\tsubmitLabel = 'Submit',\n\tnextLabel = 'Next',\n\tbackLabel = 'Back',\n\tcloseLabel = 'Close',\n\tsuccessMessage = 'Thank you.',\n\tpresentation,\n\tpresentations,\n\tonClose,\n\ttitle,\n\tinitialValues,\n\thoneypot,\n\tcaptchaToken,\n\tchildren,\n\tclassName,\n\trenderSubmit,\n\trenderNext,\n\trenderBack,\n\tsubmitButtonClassName,\n\tnextButtonClassName,\n\tbackButtonClassName,\n}: FormProps) => {\n\tconst honeypotName = honeypot === false ? null : (honeypot?.name ?? DEFAULT_HONEYPOT_FIELD)\n\tconst honeypotRef = useRef<HTMLInputElement>(null)\n\tconst registry = useMemo(() => buildFieldTypeRegistry(fieldTypes), [fieldTypes])\n\tconst ruleRegistry = useMemo(() => buildValidationRuleRegistry(rules), [rules])\n\tconst rendererRegistry = useMemo(() => resolveRenderers(defaultRenderers, renderers), [renderers])\n\tconst presentationRegistry = useMemo(\n\t\t() => resolvePresentations(defaultPresentations, presentations),\n\t\t[presentations]\n\t)\n\tconst activePresentation: FormPresentation =\n\t\ttypeof presentation === 'object'\n\t\t\t? presentation\n\t\t\t: (presentationRegistry.get(presentation ?? form.defaultPresentation ?? 'page') ??\n\t\t\t\tpresentationRegistry.get('page') ??\n\t\t\t\tdefaultPresentationDescriptors.page)\n\tconst fieldsByName = useMemo(\n\t\t() => new Map(form.fields.map((field) => [field.name, field])),\n\t\t[form.fields]\n\t)\n\tconst translate = useMemo<RendererTranslate>(() => t ?? makeTranslate(en), [t])\n\n\t// Latest-value refs so event emission and the mount/unmount effect tolerate an inline `events` prop or a changing form id.\n\tconst sinkRef = useRef<FormEventSink>(noopEventSink)\n\tsinkRef.current = events ?? noopEventSink\n\tconst formIdRef = useRef('')\n\tformIdRef.current = String(form.id)\n\n\tconst [state, rawDispatch] = useReducer(formReducer, form.fields, (fields) =>\n\t\tinitialFormState({\n\t\t\t...Object.fromEntries(fields.map((field) => [field.name, undefined])),\n\t\t\t...(initialValues ?? {}),\n\t\t})\n\t)\n\n\t// Authoritative values for derived (calc) fields, recomputed from user answers on every change. The\n\t// server recomputes these too at submit; the client copy drives the live calc renderer, recall, and submit.\n\tconst effectiveValues = useMemo(\n\t\t() => computeCalcFields(form.fields, state.values),\n\t\t[form.fields, state.values]\n\t)\n\n\tconst recall = useMemo(\n\t\t() =>\n\t\t\tbuildRecallResolver({\n\t\t\t\tfields: form.fields,\n\t\t\t\tvalues: effectiveValues,\n\t\t\t\tregistry,\n\t\t\t\tlocale,\n\t\t\t\tt: translate,\n\t\t\t}),\n\t\t[form.fields, effectiveValues, registry, locale, translate]\n\t)\n\n\t// Multi-step is active only when a flow declares two or more steps; otherwise this is an ordinary single-step form.\n\tconst flow = form.flow && form.flow.steps.length >= 2 ? form.flow : undefined\n\tconst [currentStepId, setCurrentStepId] = useState<string | undefined>(() =>\n\t\tflow ? firstStepId(flow) : undefined\n\t)\n\tconst [history, setHistory] = useState<string[]>([])\n\n\tconst startedRef = useRef(false)\n\tconst submittedRef = useRef(false)\n\tconst submittingRef = useRef(false)\n\tconst flowRef = useRef(flow)\n\tflowRef.current = flow\n\n\tconst dispatch = useCallback((action: FormAction) => {\n\t\tif (action.type === 'SET_VALUE' && !startedRef.current) {\n\t\t\tstartedRef.current = true\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.started' })\n\t\t}\n\t\trawDispatch(action)\n\t}, [])\n\n\tconst validateField = useCallback(\n\t\t(name: string, value: unknown) => {\n\t\t\tconst field = fieldsByName.get(name)\n\t\t\tif (!field) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst answers = { ...effectiveValues, [name]: value }\n\t\t\t// Mirror the server: a field whose `validateWhen` is unmet is not validated; clear any stale error.\n\t\t\tif (!evaluateCondition(field.validateWhen, answers)) {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name, errors: [], warnings: [] })\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvoid validateFieldValue({\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tregistry,\n\t\t\t\truleRegistry,\n\t\t\t\tanswers,\n\t\t\t\tlocale,\n\t\t\t\tt: translate,\n\t\t\t}).then(({ errors, warnings }) => {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name, errors, warnings })\n\t\t\t\tconst [firstError] = errors\n\t\t\t\tif (firstError !== undefined) {\n\t\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\t\t\ttype: 'field.errored',\n\t\t\t\t\t\tfield: name,\n\t\t\t\t\t\tmessage: firstError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[fieldsByName, effectiveValues, registry, ruleRegistry, locale, translate]\n\t)\n\n\tconst visible = visibleFields(form.fields, effectiveValues)\n\tconst stepNames = flow && currentStepId ? stepFieldNames(flow, currentStepId) : []\n\tconst stepVisible: FormFieldInstance[] = stepNames\n\t\t.map((name) => visible.find((field) => field.name === name))\n\t\t.filter((field): field is FormFieldInstance => Boolean(field))\n\n\tconst goNext = async () => {\n\t\tif (!flow || !currentStepId) {\n\t\t\treturn\n\t\t}\n\t\tconst results = await Promise.all(\n\t\t\tstepVisible\n\t\t\t\t.filter((field) => !calcExpressionOf(field))\n\t\t\t\t.filter((field) => evaluateCondition(field.validateWhen, effectiveValues))\n\t\t\t\t.map(async (field) => ({\n\t\t\t\t\tfield,\n\t\t\t\t\t...(await validateFieldValue({\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tvalue: effectiveValues[field.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: effectiveValues,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})),\n\t\t\t\t}))\n\t\t)\n\t\tlet hasError = false\n\t\tfor (const result of results) {\n\t\t\trawDispatch({ type: 'TOUCH', name: result.field.name })\n\t\t\trawDispatch({\n\t\t\t\ttype: 'SET_FIELD_ISSUES',\n\t\t\t\tname: result.field.name,\n\t\t\t\terrors: result.errors,\n\t\t\t\twarnings: result.warnings,\n\t\t\t})\n\t\t\tif (result.errors.length > 0) {\n\t\t\t\thasError = true\n\t\t\t}\n\t\t}\n\t\tif (hasError) {\n\t\t\treturn\n\t\t}\n\t\tconst next = resolveNextStepId(flow, currentStepId, state.values)\n\t\tif (!next) {\n\t\t\treturn\n\t\t}\n\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\ttype: 'step.completed',\n\t\t\tstepId: currentStepId,\n\t\t})\n\t\tsetHistory((prev) => [...prev, currentStepId])\n\t\tsetCurrentStepId(next)\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: next })\n\t}\n\n\tconst goBack = () => {\n\t\tconst prev = history[history.length - 1]\n\t\tif (prev === undefined) {\n\t\t\treturn\n\t\t}\n\t\tsetHistory((entries) => entries.slice(0, -1))\n\t\tsetCurrentStepId(prev)\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: prev })\n\t}\n\n\tuseEffect(() => {\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.viewed' })\n\t\tconst mountFlow = flowRef.current\n\t\tif (mountFlow) {\n\t\t\tconst first = firstStepId(mountFlow)\n\t\t\tif (first) {\n\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: first })\n\t\t\t}\n\t\t}\n\t\treturn () => {\n\t\t\tif (!submittedRef.current && !submittingRef.current) {\n\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.abandoned' })\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst handleClose = useCallback(() => {\n\t\tonClose?.()\n\t}, [onClose])\n\n\tconst handleSubmit = async (event: ReactFormEvent<HTMLFormElement>) => {\n\t\tevent.preventDefault()\n\t\t// Re-entrancy guard: claim the in-flight slot before the async validation window so a fast second\n\t\t// activation (double-click, Enter + click) cannot reach the transport and POST the submission twice.\n\t\tif (submittingRef.current) {\n\t\t\treturn\n\t\t}\n\t\tsubmittingRef.current = true\n\t\tconst visible = visibleFields(form.fields, effectiveValues)\n\t\tconst results = await Promise.all(\n\t\t\t// Calc fields carry no rules and have no input; they are always satisfied, so skip validating them.\n\t\t\t// A field whose `validateWhen` is unmet is skipped too, mirroring the server (no client/server divergence).\n\t\t\tvisible\n\t\t\t\t.filter((field) => !calcExpressionOf(field))\n\t\t\t\t.filter((field) => evaluateCondition(field.validateWhen, effectiveValues))\n\t\t\t\t.map(async (field) => ({\n\t\t\t\t\tfield,\n\t\t\t\t\t...(await validateFieldValue({\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tvalue: effectiveValues[field.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: effectiveValues,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})),\n\t\t\t\t}))\n\t\t)\n\t\tconst errors: FieldErrors = {}\n\t\tconst warnings: FieldErrors = {}\n\t\tfor (const result of results) {\n\t\t\tif (result.errors.length > 0) {\n\t\t\t\terrors[result.field.name] = result.errors\n\t\t\t\tconst [firstError] = result.errors\n\t\t\t\tif (firstError !== undefined) {\n\t\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\t\t\ttype: 'field.errored',\n\t\t\t\t\t\tfield: result.field.name,\n\t\t\t\t\t\tmessage: firstError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.warnings.length > 0) {\n\t\t\t\twarnings[result.field.name] = result.warnings\n\t\t\t}\n\t\t}\n\n\t\t// Validate sub-fields within each visible repeater, mirroring the server's per-row pass.\n\t\t// Errors are stored under the composite key `fieldName[rowIndex].subFieldName` so the\n\t\t// repeater renderer can look them up from form state and display them inline.\n\t\tfor (const field of visible.filter((f) => f.blockType === 'repeater')) {\n\t\t\tconst rows = Array.isArray(effectiveValues[field.name])\n\t\t\t\t? (effectiveValues[field.name] as Array<Record<string, unknown>>)\n\t\t\t\t: []\n\t\t\tconst subFields = Array.isArray(field.subFields)\n\t\t\t\t? (field.subFields as FormFieldInstance[])\n\t\t\t\t: []\n\t\t\tfor (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n\t\t\t\tconst row = rows[rowIndex] ?? {}\n\t\t\t\tfor (const subField of subFields) {\n\t\t\t\t\tif (!evaluateCondition(subField.visibleWhen, row)) continue\n\t\t\t\t\tif (!evaluateCondition(subField.validateWhen, row)) continue\n\t\t\t\t\tconst subResult = await validateFieldValue({\n\t\t\t\t\t\tfield: subField,\n\t\t\t\t\t\tvalue: row[subField.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: row,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})\n\t\t\t\t\tconst compositeKey = `${field.name}[${rowIndex}].${subField.name}`\n\t\t\t\t\tif (subResult.errors.length > 0) errors[compositeKey] = subResult.errors\n\t\t\t\t\tif (subResult.warnings.length > 0) warnings[compositeKey] = subResult.warnings\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trawDispatch({ type: 'SET_ALL_ISSUES', errors, warnings })\n\t\tif (Object.keys(errors).length > 0) {\n\t\t\tsubmittingRef.current = false\n\t\t\treturn\n\t\t}\n\t\trawDispatch({ type: 'SUBMIT_START' })\n\t\tconst values: SubmissionValue[] = visible\n\t\t\t.filter((field) => !isEmpty(effectiveValues[field.name]))\n\t\t\t.map((field) => ({ field: field.name, value: effectiveValues[field.name] }))\n\t\tif (honeypotName) {\n\t\t\tconst decoy = honeypotRef.current?.value ?? ''\n\t\t\tif (decoy !== '') {\n\t\t\t\tvalues.push({ field: honeypotName, value: decoy })\n\t\t\t}\n\t\t}\n\t\tif (captchaToken) {\n\t\t\tvalues.push({ field: CAPTCHA_TOKEN_KEY, value: captchaToken })\n\t\t}\n\t\tconst result: SubmitFormResult = onSubmit\n\t\t\t? await onSubmit({ formId: form.id, values })\n\t\t\t: await submitForm({ formId: form.id, values, apiRoute })\n\t\tsubmittingRef.current = false\n\t\tif (result.ok) {\n\t\t\tsubmittedRef.current = true\n\t\t\trawDispatch({ type: 'SUBMIT_SUCCESS' })\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\ttype: 'submission.created',\n\t\t\t\tsubmissionId: result.submissionId,\n\t\t\t})\n\t\t\tonSuccess?.(result.submissionId)\n\t\t\tif (activePresentation.dismissOnSuccess) {\n\t\t\t\thandleClose()\n\t\t\t}\n\t\t} else {\n\t\t\tif (result.fieldErrors) {\n\t\t\t\trawDispatch({ type: 'SET_ALL_ISSUES', errors: result.fieldErrors, warnings: {} })\n\t\t\t}\n\t\t\tconst message = result.message ?? 'Submission failed'\n\t\t\trawDispatch({ type: 'SUBMIT_ERROR', message })\n\t\t\tonError?.(message)\n\t\t}\n\t}\n\n\tconst step: FormStepInfo = flow\n\t\t? {\n\t\t\t\tflow,\n\t\t\t\tcurrentStepId,\n\t\t\t\tstepIndex: flow.steps.findIndex((s) => s.id === currentStepId),\n\t\t\t\tstepCount: flow.steps.length,\n\t\t\t\tisFirst: history.length === 0,\n\t\t\t\tisTerminal: currentStepId ? isTerminalStepId(flow, currentStepId, state.values) : true,\n\t\t\t\tgoNext: () => {\n\t\t\t\t\tvoid goNext()\n\t\t\t\t},\n\t\t\t\tgoBack,\n\t\t\t}\n\t\t: {\n\t\t\t\tstepIndex: 0,\n\t\t\t\tstepCount: 1,\n\t\t\t\tisFirst: true,\n\t\t\t\tisTerminal: true,\n\t\t\t\tgoNext: () => {},\n\t\t\t\tgoBack: () => {},\n\t\t\t}\n\n\tconst contextValue = { state, dispatch, validateField, locale, step, rendererRegistry }\n\n\tconst PresentationWrapper = activePresentation.Wrapper\n\tconst wrap = (content: ReactNode): ReactNode =>\n\t\tPresentationWrapper ? (\n\t\t\t<PresentationWrapper\n\t\t\t\tpresentation={activePresentation}\n\t\t\t\topen\n\t\t\t\tonClose={handleClose}\n\t\t\t\ttitle={title}\n\t\t\t\tcloseLabel={closeLabel}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t</PresentationWrapper>\n\t\t) : (\n\t\t\tcontent\n\t\t)\n\n\tif (children !== undefined) {\n\t\treturn (\n\t\t\t<FormContext.Provider value={contextValue}>\n\t\t\t\t{wrap(\n\t\t\t\t\t<form\n\t\t\t\t\t\tclassName={cn('fb-form-root', className)}\n\t\t\t\t\t\tnoValidate\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t\t>\n\t\t\t\t\t\t{honeypotName ? <Honeypot name={honeypotName} inputRef={honeypotRef} /> : null}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</form>\n\t\t\t\t)}\n\t\t\t</FormContext.Provider>\n\t\t)\n\t}\n\n\tif (state.submitted) {\n\t\treturn (\n\t\t\t<FormContext.Provider value={contextValue}>\n\t\t\t\t{wrap(\n\t\t\t\t\t<p\n\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\tclassName={cn('fb-form__success', className)}\n\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t\t>\n\t\t\t\t\t\t{interpolate(successMessage, recall)}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</FormContext.Provider>\n\t\t)\n\t}\n\n\tconst rendered = (flow ? stepVisible : visible).filter(\n\t\t(field) => field.hidden !== true && field.calcDisplay !== false\n\t)\n\n\treturn (\n\t\t<FormContext.Provider value={contextValue}>\n\t\t\t{wrap(\n\t\t\t\t<form\n\t\t\t\t\tclassName={cn('fb-form-root', className)}\n\t\t\t\t\tnoValidate\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t>\n\t\t\t\t\t{honeypotName ? <Honeypot name={honeypotName} inputRef={honeypotRef} /> : null}\n\t\t\t\t\t<FormLayout enabled={layout !== false}>\n\t\t\t\t\t\t{rendered.map((field) => {\n\t\t\t\t\t\t\tconst renderer = rendererRegistry.get(field.blockType)\n\t\t\t\t\t\t\tif (!renderer) {\n\t\t\t\t\t\t\t\treturn null\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst width: FieldWidth | undefined =\n\t\t\t\t\t\t\t\ttypeof field.width === 'string' && FIELD_WIDTHS.has(field.width)\n\t\t\t\t\t\t\t\t\t? (field.width as FieldWidth)\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\tconst recalledField = applyRecall(field, recall)\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div key={field.name} {...widthProps(width)}>\n\t\t\t\t\t\t\t\t\t{calcExpressionOf(field) ? (\n\t\t\t\t\t\t\t\t\t\t<CalcFieldHost\n\t\t\t\t\t\t\t\t\t\t\tfield={recalledField}\n\t\t\t\t\t\t\t\t\t\t\trenderer={renderer}\n\t\t\t\t\t\t\t\t\t\t\tvalue={effectiveValues[field.name]}\n\t\t\t\t\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\t\t\t\t\tt={translate}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<FieldHost\n\t\t\t\t\t\t\t\t\t\t\tfield={recalledField}\n\t\t\t\t\t\t\t\t\t\t\trenderer={renderer}\n\t\t\t\t\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\t\t\t\t\tt={translate}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\n\t\t\t\t\t</FormLayout>\n\t\t\t\t\t{state.submitError ? (\n\t\t\t\t\t\t<p role=\"alert\" className=\"fb-form__submit-error\">\n\t\t\t\t\t\t\t{state.submitError}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{flow ? (\n\t\t\t\t\t\t<div className=\"fb-form__controls\">\n\t\t\t\t\t\t\t{!step.isFirst ? (\n\t\t\t\t\t\t\t\trenderBack ? (\n\t\t\t\t\t\t\t\t\trenderBack({ label: backLabel, submitting: state.submitting, onClick: goBack })\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName={backButtonClassName}\n\t\t\t\t\t\t\t\t\t\tonClick={goBack}\n\t\t\t\t\t\t\t\t\t\tdisabled={state.submitting}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{backLabel}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t{step.isTerminal ? (\n\t\t\t\t\t\t\t\trenderSubmit ? (\n\t\t\t\t\t\t\t\t\trenderSubmit({ label: submitLabel, submitting: state.submitting })\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\t\tclassName={submitButtonClassName}\n\t\t\t\t\t\t\t\t\t\tdisabled={state.submitting}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{submitLabel}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) : renderNext ? (\n\t\t\t\t\t\t\t\trenderNext({\n\t\t\t\t\t\t\t\t\tlabel: nextLabel,\n\t\t\t\t\t\t\t\t\tsubmitting: state.submitting,\n\t\t\t\t\t\t\t\t\tonClick: () => void goNext(),\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName={nextButtonClassName}\n\t\t\t\t\t\t\t\t\tdisabled={state.submitting}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tvoid goNext()\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{nextLabel}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : renderSubmit ? (\n\t\t\t\t\t\trenderSubmit({ label: submitLabel, submitting: state.submitting })\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<button type=\"submit\" className={submitButtonClassName} disabled={state.submitting}>\n\t\t\t\t\t\t\t{submitLabel}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</form>\n\t\t\t)}\n\t\t</FormContext.Provider>\n\t)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Form.js","names":[],"sources":["../../src/react/Form.tsx"],"sourcesContent":["'use client'\n\nimport {\n\tcreateElement,\n\ttype FormEvent as ReactFormEvent,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseMemo,\n\tuseReducer,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport { calcExpressionOf, computeCalcFields } from '../calc/computeCalcFields'\nimport { evaluateCondition } from '../conditions/evaluate'\nimport { noopEventSink } from '../events/noopSink'\nimport type { FormEventSink } from '../events/types'\nimport type { AnyFormFieldDefinition } from '../fields/types'\nimport { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames } from '../flow/engine'\nimport type { FormFlow } from '../flow/types'\nimport { defaultPresentationDescriptors } from '../presentations/defaults'\nimport { interpolate } from '../recall/interpolate'\nimport { buildRecallResolver } from '../recall/resolver'\nimport { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from '../spam/constants'\nimport type { FormFieldInstance, SubmissionValue } from '../submissions/types'\nimport { en } from '../translations/en'\nimport { makeTranslate } from '../translations/makeTranslate'\nimport type { AnyValidationRuleDefinition } from '../validation/types'\nimport { cn } from './cn'\nimport type { FieldRenderer, RendererTranslate } from './contract'\nimport { emitFormEvent } from './events'\nimport { FormContext, type FormStepInfo } from './FormContext'\nimport { type FieldWidth, FormLayout, widthProps } from './FormLayout'\nimport { Honeypot } from './Honeypot'\nimport { defaultPresentations } from './presentation/presentations'\nimport { type PresentationsConfig, resolvePresentations } from './presentation/registry'\nimport type { FormPresentation } from './presentation/types'\nimport { applyRecall } from './recall'\nimport { type RenderersConfig, resolveRenderers } from './registry'\nimport { defaultRenderers } from './renderers'\nimport { buildFieldTypeRegistry, buildValidationRuleRegistry, visibleFields } from './resolveForm'\nimport { type FieldErrors, type FormAction, formReducer, initialFormState } from './state'\nimport { type SubmitFormResult, type SubmitHandler, submitForm } from './submitForm'\nimport { useField } from './useField'\nimport { validateFieldValue } from './validateField'\n\nexport type FormDocument = {\n\tid: number | string\n\tfields: FormFieldInstance[]\n\tflow?: FormFlow\n\t/** Stored presentation name; overridden by the `presentation` prop. */\n\tdefaultPresentation?: string\n}\n\n/** Props passed to `renderSubmit`. */\nexport type SubmitButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n}\n\n/** Props passed to `renderNext`. */\nexport type NextButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n\tonClick: () => void\n}\n\n/** Props passed to `renderBack`. */\nexport type BackButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n\tonClick: () => void\n}\n\nexport type FormProps = {\n\tform: FormDocument\n\tfieldTypes?: AnyFormFieldDefinition[]\n\trules?: AnyValidationRuleDefinition[]\n\trenderers?: RenderersConfig\n\tapiRoute?: string\n\tonSubmit?: SubmitHandler\n\tonSuccess?: (submissionId?: string) => void\n\tonError?: (message: string) => void\n\tevents?: FormEventSink\n\tt?: RendererTranslate\n\tlocale?: string\n\tlayout?: boolean\n\tsubmitLabel?: string\n\tnextLabel?: string\n\tbackLabel?: string\n\t/** Label for the overlay close control (modal/drawer). */\n\tcloseLabel?: string\n\tsuccessMessage?: string\n\t/** Active presentation: a name into the registry or an inline presentation. Overrides the form's stored default. */\n\tpresentation?: string | FormPresentation\n\t/** Per-render presentation overrides merged onto the defaults (add, replace, or `false` to remove). */\n\tpresentations?: PresentationsConfig\n\t/** Invoked when an overlay presentation dismisses (close button, Escape, outside click, or `dismissOnSuccess`). */\n\tonClose?: () => void\n\t/** Accessible name for an overlay surface. */\n\ttitle?: string\n\t/** Seed initial field values (e.g. from `valuesFromSearchParams`). Still validated on submit. */\n\tinitialValues?: Record<string, unknown>\n\t/** Honeypot decoy (on by default). `false` removes it; `{ name }` matches a customized server `spam.honeypot.fieldName`. */\n\thoneypot?: false | { name?: string }\n\t/** A token from your captcha widget; verified server-side when a captcha provider is configured. */\n\tcaptchaToken?: string\n\t/** Custom layout: render fields with `useField`/`useFormState` instead of the auto-rendered field loop. */\n\tchildren?: ReactNode\n\t/** Additional CSS class names applied to the root `<form>` element (and the success node). */\n\tclassName?: string\n\t/** Replace the default submit button entirely. Receives the resolved label and submitting state. */\n\trenderSubmit?: (props: SubmitButtonRenderProps) => ReactNode\n\t/** Replace the default \"Next\" button in multi-step forms. */\n\trenderNext?: (props: NextButtonRenderProps) => ReactNode\n\t/** Replace the default \"Back\" button in multi-step forms. */\n\trenderBack?: (props: BackButtonRenderProps) => ReactNode\n\t/** CSS class forwarded to the default submit `<button>`. Ignored when `renderSubmit` is provided. */\n\tsubmitButtonClassName?: string\n\t/** CSS class forwarded to the default \"Next\" `<button>`. Ignored when `renderNext` is provided. */\n\tnextButtonClassName?: string\n\t/** CSS class forwarded to the default \"Back\" `<button>`. Ignored when `renderBack` is provided. */\n\tbackButtonClassName?: string\n}\n\nconst isEmpty = (value: unknown): boolean =>\n\tvalue == null || value === '' || (Array.isArray(value) && value.length === 0)\n\nconst FIELD_WIDTHS = new Set<string>(['full', 'half', 'third', 'twoThirds'])\n\ntype FieldHostProps = {\n\tfield: FormFieldInstance\n\trenderer: FieldRenderer\n\tlocale: string\n\tt: RendererTranslate\n}\n\nconst FieldHost = ({ field, renderer, locale, t }: FieldHostProps) => {\n\tconst id = useId()\n\tconst { value, errors, warnings, setValue, onBlur } = useField(field.name)\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: field.name,\n\t\tvalue,\n\t\tonChange: setValue,\n\t\tonBlur,\n\t\terrors,\n\t\twarnings,\n\t\trequired: Boolean(field.required),\n\t\tlocale,\n\t\tt,\n\t})\n}\n\ntype CalcFieldHostProps = FieldHostProps & { value: unknown }\n\n/** Hosts a derived (calc) field: read-only, value supplied from `effectiveValues`, never bound via `useField`. */\nconst CalcFieldHost = ({ field, renderer, value, locale, t }: CalcFieldHostProps) => {\n\tconst id = useId()\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: field.name,\n\t\tvalue,\n\t\tonChange: () => {},\n\t\tonBlur: () => {},\n\t\terrors: [],\n\t\twarnings: [],\n\t\trequired: false,\n\t\tdisabled: true,\n\t\tlocale,\n\t\tt,\n\t})\n}\n\n/** The headless form controller: state, progressive client validation, conditional visibility, submission, events. */\nexport const Form = ({\n\tform,\n\tfieldTypes,\n\trules,\n\trenderers,\n\tapiRoute,\n\tonSubmit,\n\tonSuccess,\n\tonError,\n\tevents,\n\tt,\n\tlocale = 'en',\n\tlayout,\n\tsubmitLabel = 'Submit',\n\tnextLabel = 'Next',\n\tbackLabel = 'Back',\n\tcloseLabel = 'Close',\n\tsuccessMessage = 'Thank you.',\n\tpresentation,\n\tpresentations,\n\tonClose,\n\ttitle,\n\tinitialValues,\n\thoneypot,\n\tcaptchaToken,\n\tchildren,\n\tclassName,\n\trenderSubmit,\n\trenderNext,\n\trenderBack,\n\tsubmitButtonClassName,\n\tnextButtonClassName,\n\tbackButtonClassName,\n}: FormProps) => {\n\tconst honeypotName = honeypot === false ? null : (honeypot?.name ?? DEFAULT_HONEYPOT_FIELD)\n\tconst honeypotRef = useRef<HTMLInputElement>(null)\n\tconst registry = useMemo(() => buildFieldTypeRegistry(fieldTypes), [fieldTypes])\n\tconst ruleRegistry = useMemo(() => buildValidationRuleRegistry(rules), [rules])\n\tconst rendererRegistry = useMemo(() => resolveRenderers(defaultRenderers, renderers), [renderers])\n\tconst presentationRegistry = useMemo(\n\t\t() => resolvePresentations(defaultPresentations, presentations),\n\t\t[presentations]\n\t)\n\tconst activePresentation: FormPresentation =\n\t\ttypeof presentation === 'object'\n\t\t\t? presentation\n\t\t\t: (presentationRegistry.get(presentation ?? form.defaultPresentation ?? 'page') ??\n\t\t\t\tpresentationRegistry.get('page') ??\n\t\t\t\tdefaultPresentationDescriptors.page)\n\tconst fieldsByName = useMemo(\n\t\t() => new Map(form.fields.map((field) => [field.name, field])),\n\t\t[form.fields]\n\t)\n\tconst translate = useMemo<RendererTranslate>(() => t ?? makeTranslate(en), [t])\n\n\t// Latest-value refs so event emission and the mount/unmount effect tolerate an inline `events` prop or a changing form id.\n\tconst sinkRef = useRef<FormEventSink>(noopEventSink)\n\tsinkRef.current = events ?? noopEventSink\n\tconst formIdRef = useRef('')\n\tformIdRef.current = String(form.id)\n\n\tconst [state, rawDispatch] = useReducer(formReducer, form.fields, (fields) =>\n\t\tinitialFormState({\n\t\t\t...Object.fromEntries(fields.map((field) => [field.name, undefined])),\n\t\t\t...(initialValues ?? {}),\n\t\t})\n\t)\n\n\t// Authoritative values for derived (calc) fields, recomputed from user answers on every change. The\n\t// server recomputes these too at submit; the client copy drives the live calc renderer, recall, and submit.\n\tconst effectiveValues = useMemo(\n\t\t() => computeCalcFields(form.fields, state.values),\n\t\t[form.fields, state.values]\n\t)\n\n\tconst recall = useMemo(\n\t\t() =>\n\t\t\tbuildRecallResolver({\n\t\t\t\tfields: form.fields,\n\t\t\t\tvalues: effectiveValues,\n\t\t\t\tregistry,\n\t\t\t\tlocale,\n\t\t\t\tt: translate,\n\t\t\t}),\n\t\t[form.fields, effectiveValues, registry, locale, translate]\n\t)\n\n\t// Multi-step is active only when a flow declares two or more steps; otherwise this is an ordinary single-step form.\n\tconst flow = form.flow && form.flow.steps.length >= 2 ? form.flow : undefined\n\tconst [currentStepId, setCurrentStepId] = useState<string | undefined>(() =>\n\t\tflow ? firstStepId(flow) : undefined\n\t)\n\tconst [history, setHistory] = useState<string[]>([])\n\n\tconst startedRef = useRef(false)\n\tconst submittedRef = useRef(false)\n\tconst submittingRef = useRef(false)\n\tconst flowRef = useRef(flow)\n\tflowRef.current = flow\n\n\tconst dispatch = useCallback((action: FormAction) => {\n\t\tif (action.type === 'SET_VALUE' && !startedRef.current) {\n\t\t\tstartedRef.current = true\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.started' })\n\t\t}\n\t\trawDispatch(action)\n\t}, [])\n\n\tconst validateField = useCallback(\n\t\t(name: string, value: unknown) => {\n\t\t\tconst field = fieldsByName.get(name)\n\t\t\tif (!field) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst answers = { ...effectiveValues, [name]: value }\n\t\t\t// Mirror the server: a field whose `validateWhen` is unmet is not validated; clear any stale error.\n\t\t\tif (!evaluateCondition(field.validateWhen, answers)) {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name, errors: [], warnings: [] })\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvoid validateFieldValue({\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tregistry,\n\t\t\t\truleRegistry,\n\t\t\t\tanswers,\n\t\t\t\tlocale,\n\t\t\t\tt: translate,\n\t\t\t}).then(({ errors, warnings }) => {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name, errors, warnings })\n\t\t\t\tconst [firstError] = errors\n\t\t\t\tif (firstError !== undefined) {\n\t\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\t\t\ttype: 'field.errored',\n\t\t\t\t\t\tfield: name,\n\t\t\t\t\t\tmessage: firstError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[fieldsByName, effectiveValues, registry, ruleRegistry, locale, translate]\n\t)\n\n\tconst visible = visibleFields(form.fields, effectiveValues)\n\tconst stepNames = flow && currentStepId ? stepFieldNames(flow, currentStepId) : []\n\tconst stepVisible: FormFieldInstance[] = stepNames\n\t\t.map((name) => visible.find((field) => field.name === name))\n\t\t.filter((field): field is FormFieldInstance => Boolean(field))\n\n\tconst goNext = async () => {\n\t\tif (!flow || !currentStepId) {\n\t\t\treturn\n\t\t}\n\t\tconst results = await Promise.all(\n\t\t\tstepVisible\n\t\t\t\t.filter((field) => !calcExpressionOf(field))\n\t\t\t\t.filter((field) => evaluateCondition(field.validateWhen, effectiveValues))\n\t\t\t\t.map(async (field) => ({\n\t\t\t\t\tfield,\n\t\t\t\t\t...(await validateFieldValue({\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tvalue: effectiveValues[field.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: effectiveValues,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})),\n\t\t\t\t}))\n\t\t)\n\t\tlet hasError = false\n\t\tfor (const result of results) {\n\t\t\trawDispatch({ type: 'TOUCH', name: result.field.name })\n\t\t\trawDispatch({\n\t\t\t\ttype: 'SET_FIELD_ISSUES',\n\t\t\t\tname: result.field.name,\n\t\t\t\terrors: result.errors,\n\t\t\t\twarnings: result.warnings,\n\t\t\t})\n\t\t\tif (result.errors.length > 0) {\n\t\t\t\thasError = true\n\t\t\t}\n\t\t}\n\t\tif (hasError) {\n\t\t\treturn\n\t\t}\n\t\tconst next = resolveNextStepId(flow, currentStepId, effectiveValues)\n\t\tif (!next) {\n\t\t\treturn\n\t\t}\n\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\ttype: 'step.completed',\n\t\t\tstepId: currentStepId,\n\t\t})\n\t\tsetHistory((prev) => [...prev, currentStepId])\n\t\tsetCurrentStepId(next)\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: next })\n\t}\n\n\tconst goBack = () => {\n\t\tconst prev = history[history.length - 1]\n\t\tif (prev === undefined) {\n\t\t\treturn\n\t\t}\n\t\tsetHistory((entries) => entries.slice(0, -1))\n\t\tsetCurrentStepId(prev)\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: prev })\n\t}\n\n\tuseEffect(() => {\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.viewed' })\n\t\tconst mountFlow = flowRef.current\n\t\tif (mountFlow) {\n\t\t\tconst first = firstStepId(mountFlow)\n\t\t\tif (first) {\n\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: first })\n\t\t\t}\n\t\t}\n\t\treturn () => {\n\t\t\tif (!submittedRef.current && !submittingRef.current) {\n\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.abandoned' })\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst handleClose = useCallback(() => {\n\t\tonClose?.()\n\t}, [onClose])\n\n\tconst handleSubmit = async (event: ReactFormEvent<HTMLFormElement>) => {\n\t\tevent.preventDefault()\n\t\t// Re-entrancy guard: claim the in-flight slot before the async validation window so a fast second\n\t\t// activation (double-click, Enter + click) cannot reach the transport and POST the submission twice.\n\t\tif (submittingRef.current) {\n\t\t\treturn\n\t\t}\n\t\tsubmittingRef.current = true\n\t\tconst visible = visibleFields(form.fields, effectiveValues)\n\t\tconst results = await Promise.all(\n\t\t\t// Calc fields carry no rules and have no input; they are always satisfied, so skip validating them.\n\t\t\t// A field whose `validateWhen` is unmet is skipped too, mirroring the server (no client/server divergence).\n\t\t\tvisible\n\t\t\t\t.filter((field) => !calcExpressionOf(field))\n\t\t\t\t.filter((field) => evaluateCondition(field.validateWhen, effectiveValues))\n\t\t\t\t.map(async (field) => ({\n\t\t\t\t\tfield,\n\t\t\t\t\t...(await validateFieldValue({\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tvalue: effectiveValues[field.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: effectiveValues,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})),\n\t\t\t\t}))\n\t\t)\n\t\tconst errors: FieldErrors = {}\n\t\tconst warnings: FieldErrors = {}\n\t\tfor (const result of results) {\n\t\t\tif (result.errors.length > 0) {\n\t\t\t\terrors[result.field.name] = result.errors\n\t\t\t\tconst [firstError] = result.errors\n\t\t\t\tif (firstError !== undefined) {\n\t\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\t\t\ttype: 'field.errored',\n\t\t\t\t\t\tfield: result.field.name,\n\t\t\t\t\t\tmessage: firstError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.warnings.length > 0) {\n\t\t\t\twarnings[result.field.name] = result.warnings\n\t\t\t}\n\t\t}\n\n\t\t// Validate sub-fields within each visible repeater, mirroring the server's per-row pass.\n\t\t// Errors are stored under the composite key `fieldName[rowIndex].subFieldName` so the\n\t\t// repeater renderer can look them up from form state and display them inline.\n\t\tfor (const field of visible.filter((f) => f.blockType === 'repeater')) {\n\t\t\tconst rows = Array.isArray(effectiveValues[field.name])\n\t\t\t\t? (effectiveValues[field.name] as Array<Record<string, unknown>>)\n\t\t\t\t: []\n\t\t\tconst subFields = Array.isArray(field.subFields)\n\t\t\t\t? (field.subFields as FormFieldInstance[])\n\t\t\t\t: []\n\t\t\tfor (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n\t\t\t\tconst row = rows[rowIndex] ?? {}\n\t\t\t\tfor (const subField of subFields) {\n\t\t\t\t\tif (!evaluateCondition(subField.visibleWhen, row)) continue\n\t\t\t\t\tif (!evaluateCondition(subField.validateWhen, row)) continue\n\t\t\t\t\tconst subResult = await validateFieldValue({\n\t\t\t\t\t\tfield: subField,\n\t\t\t\t\t\tvalue: row[subField.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: row,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})\n\t\t\t\t\tconst compositeKey = `${field.name}[${rowIndex}].${subField.name}`\n\t\t\t\t\tif (subResult.errors.length > 0) errors[compositeKey] = subResult.errors\n\t\t\t\t\tif (subResult.warnings.length > 0) warnings[compositeKey] = subResult.warnings\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trawDispatch({ type: 'SET_ALL_ISSUES', errors, warnings })\n\t\tif (Object.keys(errors).length > 0) {\n\t\t\tsubmittingRef.current = false\n\t\t\treturn\n\t\t}\n\t\trawDispatch({ type: 'SUBMIT_START' })\n\t\tconst values: SubmissionValue[] = visible\n\t\t\t.filter((field) => !isEmpty(effectiveValues[field.name]))\n\t\t\t.map((field) => ({ field: field.name, value: effectiveValues[field.name] }))\n\t\tif (honeypotName) {\n\t\t\tconst decoy = honeypotRef.current?.value ?? ''\n\t\t\tif (decoy !== '') {\n\t\t\t\tvalues.push({ field: honeypotName, value: decoy })\n\t\t\t}\n\t\t}\n\t\tif (captchaToken) {\n\t\t\tvalues.push({ field: CAPTCHA_TOKEN_KEY, value: captchaToken })\n\t\t}\n\t\tconst result: SubmitFormResult = onSubmit\n\t\t\t? await onSubmit({ formId: form.id, values })\n\t\t\t: await submitForm({ formId: form.id, values, apiRoute })\n\t\tsubmittingRef.current = false\n\t\tif (result.ok) {\n\t\t\tsubmittedRef.current = true\n\t\t\trawDispatch({ type: 'SUBMIT_SUCCESS' })\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\ttype: 'submission.created',\n\t\t\t\tsubmissionId: result.submissionId,\n\t\t\t})\n\t\t\tonSuccess?.(result.submissionId)\n\t\t\tif (activePresentation.dismissOnSuccess) {\n\t\t\t\thandleClose()\n\t\t\t}\n\t\t} else {\n\t\t\tif (result.fieldErrors) {\n\t\t\t\trawDispatch({ type: 'SET_ALL_ISSUES', errors: result.fieldErrors, warnings: {} })\n\t\t\t}\n\t\t\tconst message = result.message ?? 'Submission failed'\n\t\t\trawDispatch({ type: 'SUBMIT_ERROR', message })\n\t\t\tonError?.(message)\n\t\t}\n\t}\n\n\tconst step: FormStepInfo = flow\n\t\t? {\n\t\t\t\tflow,\n\t\t\t\tcurrentStepId,\n\t\t\t\tstepIndex: flow.steps.findIndex((s) => s.id === currentStepId),\n\t\t\t\tstepCount: flow.steps.length,\n\t\t\t\tisFirst: history.length === 0,\n\t\t\t\tisTerminal: currentStepId ? isTerminalStepId(flow, currentStepId, effectiveValues) : true,\n\t\t\t\tgoNext: () => {\n\t\t\t\t\tvoid goNext()\n\t\t\t\t},\n\t\t\t\tgoBack,\n\t\t\t}\n\t\t: {\n\t\t\t\tstepIndex: 0,\n\t\t\t\tstepCount: 1,\n\t\t\t\tisFirst: true,\n\t\t\t\tisTerminal: true,\n\t\t\t\tgoNext: () => {},\n\t\t\t\tgoBack: () => {},\n\t\t\t}\n\n\tconst contextValue = { state, dispatch, validateField, locale, step, rendererRegistry }\n\n\tconst PresentationWrapper = activePresentation.Wrapper\n\tconst wrap = (content: ReactNode): ReactNode =>\n\t\tPresentationWrapper ? (\n\t\t\t<PresentationWrapper\n\t\t\t\tpresentation={activePresentation}\n\t\t\t\topen\n\t\t\t\tonClose={handleClose}\n\t\t\t\ttitle={title}\n\t\t\t\tcloseLabel={closeLabel}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t</PresentationWrapper>\n\t\t) : (\n\t\t\tcontent\n\t\t)\n\n\tif (children !== undefined) {\n\t\treturn (\n\t\t\t<FormContext.Provider value={contextValue}>\n\t\t\t\t{wrap(\n\t\t\t\t\t<form\n\t\t\t\t\t\tclassName={cn('fb-form-root', className)}\n\t\t\t\t\t\tnoValidate\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t\t>\n\t\t\t\t\t\t{honeypotName ? <Honeypot name={honeypotName} inputRef={honeypotRef} /> : null}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</form>\n\t\t\t\t)}\n\t\t\t</FormContext.Provider>\n\t\t)\n\t}\n\n\tif (state.submitted) {\n\t\treturn (\n\t\t\t<FormContext.Provider value={contextValue}>\n\t\t\t\t{wrap(\n\t\t\t\t\t<p\n\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\tclassName={cn('fb-form__success', className)}\n\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t\t>\n\t\t\t\t\t\t{interpolate(successMessage, recall)}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</FormContext.Provider>\n\t\t)\n\t}\n\n\tconst rendered = (flow ? stepVisible : visible).filter(\n\t\t(field) => field.hidden !== true && field.calcDisplay !== false\n\t)\n\n\treturn (\n\t\t<FormContext.Provider value={contextValue}>\n\t\t\t{wrap(\n\t\t\t\t<form\n\t\t\t\t\tclassName={cn('fb-form-root', className)}\n\t\t\t\t\tnoValidate\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t>\n\t\t\t\t\t{honeypotName ? <Honeypot name={honeypotName} inputRef={honeypotRef} /> : null}\n\t\t\t\t\t<FormLayout enabled={layout !== false}>\n\t\t\t\t\t\t{rendered.map((field) => {\n\t\t\t\t\t\t\tconst renderer = rendererRegistry.get(field.blockType)\n\t\t\t\t\t\t\tif (!renderer) {\n\t\t\t\t\t\t\t\treturn null\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst width: FieldWidth | undefined =\n\t\t\t\t\t\t\t\ttypeof field.width === 'string' && FIELD_WIDTHS.has(field.width)\n\t\t\t\t\t\t\t\t\t? (field.width as FieldWidth)\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\tconst recalledField = applyRecall(field, recall)\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div key={field.name} {...widthProps(width)}>\n\t\t\t\t\t\t\t\t\t{calcExpressionOf(field) ? (\n\t\t\t\t\t\t\t\t\t\t<CalcFieldHost\n\t\t\t\t\t\t\t\t\t\t\tfield={recalledField}\n\t\t\t\t\t\t\t\t\t\t\trenderer={renderer}\n\t\t\t\t\t\t\t\t\t\t\tvalue={effectiveValues[field.name]}\n\t\t\t\t\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\t\t\t\t\tt={translate}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<FieldHost\n\t\t\t\t\t\t\t\t\t\t\tfield={recalledField}\n\t\t\t\t\t\t\t\t\t\t\trenderer={renderer}\n\t\t\t\t\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\t\t\t\t\tt={translate}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\n\t\t\t\t\t</FormLayout>\n\t\t\t\t\t{state.submitError ? (\n\t\t\t\t\t\t<p role=\"alert\" className=\"fb-form__submit-error\">\n\t\t\t\t\t\t\t{state.submitError}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{flow ? (\n\t\t\t\t\t\t<div className=\"fb-form__controls\">\n\t\t\t\t\t\t\t{!step.isFirst ? (\n\t\t\t\t\t\t\t\trenderBack ? (\n\t\t\t\t\t\t\t\t\trenderBack({ label: backLabel, submitting: state.submitting, onClick: goBack })\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName={backButtonClassName}\n\t\t\t\t\t\t\t\t\t\tonClick={goBack}\n\t\t\t\t\t\t\t\t\t\tdisabled={state.submitting}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{backLabel}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t{step.isTerminal ? (\n\t\t\t\t\t\t\t\trenderSubmit ? (\n\t\t\t\t\t\t\t\t\trenderSubmit({ label: submitLabel, submitting: state.submitting })\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\t\tclassName={submitButtonClassName}\n\t\t\t\t\t\t\t\t\t\tdisabled={state.submitting}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{submitLabel}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) : renderNext ? (\n\t\t\t\t\t\t\t\trenderNext({\n\t\t\t\t\t\t\t\t\tlabel: nextLabel,\n\t\t\t\t\t\t\t\t\tsubmitting: state.submitting,\n\t\t\t\t\t\t\t\t\tonClick: () => void goNext(),\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName={nextButtonClassName}\n\t\t\t\t\t\t\t\t\tdisabled={state.submitting}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tvoid goNext()\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{nextLabel}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : renderSubmit ? (\n\t\t\t\t\t\trenderSubmit({ label: submitLabel, submitting: state.submitting })\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<button type=\"submit\" className={submitButtonClassName} disabled={state.submitting}>\n\t\t\t\t\t\t\t{submitLabel}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</form>\n\t\t\t)}\n\t\t</FormContext.Provider>\n\t)\n}\n"],"mappings":"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"}
@@ -2,8 +2,8 @@
2
2
  import { Form } from "./Form.js";
3
3
  import { FormResults } from "./FormResults.js";
4
4
  import { fetchFormResults } from "./fetchResults.js";
5
- import { useCallback, useEffect, useState } from "react";
6
5
  import { jsx } from "react/jsx-runtime";
6
+ import { useCallback, useEffect, useState } from "react";
7
7
  //#region src/react/Poll.tsx
8
8
  const readVoted = (key) => {
9
9
  try {
@@ -0,0 +1,28 @@
1
+ import { CaptchaWidgetHandle } from "./types.js";
2
+ import { Ref } from "react";
3
+
4
+ //#region src/react/captcha/HcaptchaCaptcha.d.ts
5
+ declare const HCAPTCHA_SCRIPT_URL = "https://js.hcaptcha.com/1/api.js?render=explicit";
6
+ type HcaptchaCaptchaProps = {
7
+ /** hCaptcha site key (public). */siteKey: string; /** Receives each fresh token, and null when the token expires or errors. */
8
+ onToken: (token: string | null) => void; /** Extra vendor render params (theme, size, ...). */
9
+ options?: Record<string, unknown>;
10
+ className?: string; /** Override the vendor script URL. */
11
+ scriptSrc?: string;
12
+ ref?: Ref<CaptchaWidgetHandle>;
13
+ };
14
+ /**
15
+ * Headless hCaptcha widget: loads the vendor script once, renders the widget into a bare div,
16
+ * and reports tokens through `onToken`. Pass the latest token to `<Form captchaToken>`.
17
+ */
18
+ declare const HcaptchaCaptcha: ({
19
+ siteKey,
20
+ onToken,
21
+ options,
22
+ className,
23
+ scriptSrc,
24
+ ref
25
+ }: HcaptchaCaptchaProps) => import("react/jsx-runtime").JSX.Element;
26
+ //#endregion
27
+ export { HCAPTCHA_SCRIPT_URL, HcaptchaCaptcha, HcaptchaCaptchaProps };
28
+ //# sourceMappingURL=HcaptchaCaptcha.d.ts.map