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

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 (546) hide show
  1. package/CHANGELOG.md +293 -0
  2. package/README.md +6 -4
  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 +55 -0
  10. package/dist/actions/body/serializeBody.js +78 -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/textOfBody.d.ts +13 -0
  15. package/dist/actions/body/textOfBody.js +35 -0
  16. package/dist/actions/body/textOfBody.js.map +1 -0
  17. package/dist/actions/body/wildcards.d.ts +10 -0
  18. package/dist/actions/body/wildcards.js +33 -0
  19. package/dist/actions/body/wildcards.js.map +1 -0
  20. package/dist/actions/buildActionBlocks.js +12 -9
  21. package/dist/actions/buildActionBlocks.js.map +1 -1
  22. package/dist/actions/builtin/confirmation.js +46 -43
  23. package/dist/actions/builtin/confirmation.js.map +1 -1
  24. package/dist/actions/builtin/emailAction.d.ts +17 -0
  25. package/dist/actions/builtin/emailAction.js +83 -0
  26. package/dist/actions/builtin/emailAction.js.map +1 -0
  27. package/dist/actions/builtin/emailTeam.js +14 -38
  28. package/dist/actions/builtin/emailTeam.js.map +1 -1
  29. package/dist/actions/builtin/index.d.ts +16 -1
  30. package/dist/actions/builtin/index.js +21 -7
  31. package/dist/actions/builtin/index.js.map +1 -1
  32. package/dist/actions/builtin/signedWebhook.js +6 -2
  33. package/dist/actions/builtin/signedWebhook.js.map +1 -1
  34. package/dist/actions/defineAction.d.ts +5 -4
  35. package/dist/actions/defineAction.js.map +1 -1
  36. package/dist/actions/dispatch.js +2 -1
  37. package/dist/actions/dispatch.js.map +1 -1
  38. package/dist/actions/emailRecipients.d.ts +12 -0
  39. package/dist/actions/emailRecipients.js +116 -0
  40. package/dist/actions/emailRecipients.js.map +1 -0
  41. package/dist/actions/fromAddresses.d.ts +21 -0
  42. package/dist/actions/fromAddresses.js +74 -0
  43. package/dist/actions/fromAddresses.js.map +1 -0
  44. package/dist/actions/registry.d.ts +2 -1
  45. package/dist/actions/registry.js +2 -6
  46. package/dist/actions/registry.js.map +1 -1
  47. package/dist/actions/runActions.js +10 -1
  48. package/dist/actions/runActions.js.map +1 -1
  49. package/dist/actions/task.js +20 -15
  50. package/dist/actions/task.js.map +1 -1
  51. package/dist/aggregation/aggregateResponses.d.ts +9 -0
  52. package/dist/aggregation/aggregateResponses.js +8 -14
  53. package/dist/aggregation/aggregateResponses.js.map +1 -1
  54. package/dist/aggregation/resolveResultsRequest.d.ts +35 -6
  55. package/dist/aggregation/resolveResultsRequest.js +68 -11
  56. package/dist/aggregation/resolveResultsRequest.js.map +1 -1
  57. package/dist/calc/computeCalcFields.js +2 -1
  58. package/dist/calc/computeCalcFields.js.map +1 -1
  59. package/dist/calc/evaluate.js +1 -2
  60. package/dist/calc/evaluate.js.map +1 -1
  61. package/dist/calc/normalizeCalc.js +6 -19
  62. package/dist/calc/normalizeCalc.js.map +1 -1
  63. package/dist/calc/types.d.ts +8 -2
  64. package/dist/calc/types.js +22 -0
  65. package/dist/calc/types.js.map +1 -0
  66. package/dist/client/ByteSizeField.d.ts +29 -0
  67. package/dist/client/ByteSizeField.js +58 -0
  68. package/dist/client/ByteSizeField.js.map +1 -0
  69. package/dist/client/ClosePollButton.d.ts +15 -0
  70. package/dist/client/ClosePollButton.js +80 -0
  71. package/dist/client/ClosePollButton.js.map +1 -0
  72. package/dist/client/CondensedArray.d.ts +15 -0
  73. package/dist/client/CondensedArray.js +97 -0
  74. package/dist/client/CondensedArray.js.map +1 -0
  75. package/dist/client/ConditionBuilder.js +2 -1
  76. package/dist/client/ConditionBuilder.js.map +1 -1
  77. package/dist/client/ConsentBlockLabel.d.ts +15 -0
  78. package/dist/client/ConsentBlockLabel.js +71 -0
  79. package/dist/client/ConsentBlockLabel.js.map +1 -0
  80. package/dist/client/ConsentSourceRowLabel.d.ts +9 -0
  81. package/dist/client/ConsentSourceRowLabel.js +21 -0
  82. package/dist/client/ConsentSourceRowLabel.js.map +1 -0
  83. package/dist/client/EndpointOptionsSelect.d.ts +46 -0
  84. package/dist/client/EndpointOptionsSelect.js +106 -0
  85. package/dist/client/EndpointOptionsSelect.js.map +1 -0
  86. package/dist/client/FieldBlockLabel.d.ts +18 -0
  87. package/dist/client/FieldBlockLabel.js +34 -0
  88. package/dist/client/FieldBlockLabel.js.map +1 -0
  89. package/dist/client/FieldNameSelect.d.ts +37 -0
  90. package/dist/client/FieldNameSelect.js +72 -0
  91. package/dist/client/FieldNameSelect.js.map +1 -0
  92. package/dist/client/FlowBuilder.d.ts +2 -2
  93. package/dist/client/FlowBuilder.js +137 -88
  94. package/dist/client/FlowBuilder.js.map +1 -1
  95. package/dist/client/FormConditionField.js +1 -4
  96. package/dist/client/FormConditionField.js.map +1 -1
  97. package/dist/client/RecipientsSelect.d.ts +31 -0
  98. package/dist/client/RecipientsSelect.js +174 -0
  99. package/dist/client/RecipientsSelect.js.map +1 -0
  100. package/dist/client/RuleDescription.d.ts +21 -0
  101. package/dist/client/RuleDescription.js +19 -0
  102. package/dist/client/RuleDescription.js.map +1 -0
  103. package/dist/client/admin.css +275 -0
  104. package/dist/client/endpointOptions.js +29 -0
  105. package/dist/client/endpointOptions.js.map +1 -0
  106. package/dist/client/flowAuthoring.js +142 -0
  107. package/dist/client/flowAuthoring.js.map +1 -0
  108. package/dist/client/synthesizeClientField.js +21 -10
  109. package/dist/client/synthesizeClientField.js.map +1 -1
  110. package/dist/client/toStaticLabel.js +13 -0
  111. package/dist/client/toStaticLabel.js.map +1 -0
  112. package/dist/collections/buttonFields.d.ts +34 -0
  113. package/dist/collections/buttonFields.js +35 -0
  114. package/dist/collections/buttonFields.js.map +1 -0
  115. package/dist/collections/cells/FieldCountCell.d.ts +15 -0
  116. package/dist/collections/cells/FieldCountCell.js +18 -0
  117. package/dist/collections/cells/FieldCountCell.js.map +1 -0
  118. package/dist/collections/cells/FlowStepsCell.d.ts +14 -0
  119. package/dist/collections/cells/FlowStepsCell.js +17 -0
  120. package/dist/collections/cells/FlowStepsCell.js.map +1 -0
  121. package/dist/collections/formSubmissions.js +108 -42
  122. package/dist/collections/formSubmissions.js.map +1 -1
  123. package/dist/collections/forms.js +409 -114
  124. package/dist/collections/forms.js.map +1 -1
  125. package/dist/collections/formsEndpoints.js +101 -0
  126. package/dist/collections/formsEndpoints.js.map +1 -0
  127. package/dist/collections/redirectFields.d.ts +29 -0
  128. package/dist/conditions/conditionType.js +9 -2
  129. package/dist/conditions/conditionType.js.map +1 -1
  130. package/dist/conditions/evaluate.js +1 -1
  131. package/dist/conditions/evaluate.js.map +1 -1
  132. package/dist/conditions/fieldTypes.d.ts +3 -1
  133. package/dist/conditions/fieldTypes.js +4 -1
  134. package/dist/conditions/fieldTypes.js.map +1 -1
  135. package/dist/conditions/normalizeConditions.js +20 -6
  136. package/dist/conditions/normalizeConditions.js.map +1 -1
  137. package/dist/consent/applyConsentStatements.d.ts +14 -0
  138. package/dist/consent/applyConsentStatements.js +17 -0
  139. package/dist/consent/applyConsentStatements.js.map +1 -0
  140. package/dist/consent/captureConsent.d.ts +38 -11
  141. package/dist/consent/captureConsent.js +60 -13
  142. package/dist/consent/captureConsent.js.map +1 -1
  143. package/dist/consent/consentSourcesField.d.ts +66 -0
  144. package/dist/consent/consentSourcesField.js +90 -0
  145. package/dist/consent/consentSourcesField.js.map +1 -0
  146. package/dist/consent/resolveConsentEntries.d.ts +24 -0
  147. package/dist/consent/resolveConsentEntries.js +40 -0
  148. package/dist/consent/resolveConsentEntries.js.map +1 -0
  149. package/dist/consent/resolveConsentSourcesRequest.d.ts +37 -0
  150. package/dist/consent/resolveConsentSourcesRequest.js +54 -0
  151. package/dist/consent/resolveConsentSourcesRequest.js.map +1 -0
  152. package/dist/consent/resolveConsentStatements.d.ts +45 -0
  153. package/dist/consent/resolveConsentStatements.js +44 -0
  154. package/dist/consent/resolveConsentStatements.js.map +1 -0
  155. package/dist/consent/resolvePublishedVersionRef.d.ts +17 -11
  156. package/dist/consent/resolvePublishedVersionRef.js +13 -10
  157. package/dist/consent/resolvePublishedVersionRef.js.map +1 -1
  158. package/dist/consent/types.d.ts +61 -0
  159. package/dist/email/departments.d.ts +59 -0
  160. package/dist/email/departments.js +87 -0
  161. package/dist/email/departments.js.map +1 -0
  162. package/dist/email/departmentsField.d.ts +53 -0
  163. package/dist/email/departmentsField.js +73 -0
  164. package/dist/email/departmentsField.js.map +1 -0
  165. package/dist/exports/client.d.ts +13 -1
  166. package/dist/exports/client.js +13 -1
  167. package/dist/exports/i18n.d.ts +5 -2
  168. package/dist/exports/i18n.js +5 -2
  169. package/dist/exports/react.d.ts +26 -8
  170. package/dist/exports/react.js +19 -3
  171. package/dist/exports/rsc.d.ts +8 -1
  172. package/dist/exports/rsc.js +8 -1
  173. package/dist/exports/types.d.ts +19 -10
  174. package/dist/fields/buildFieldBlocks.js +53 -19
  175. package/dist/fields/buildFieldBlocks.js.map +1 -1
  176. package/dist/fields/builtin/calculation.js +122 -2
  177. package/dist/fields/builtin/calculation.js.map +1 -1
  178. package/dist/fields/builtin/checkbox.js +8 -0
  179. package/dist/fields/builtin/checkbox.js.map +1 -1
  180. package/dist/fields/builtin/consent.js +30 -15
  181. package/dist/fields/builtin/consent.js.map +1 -1
  182. package/dist/fields/builtin/country.d.ts +13 -0
  183. package/dist/fields/builtin/country.js +30 -0
  184. package/dist/fields/builtin/country.js.map +1 -0
  185. package/dist/fields/builtin/date.js +31 -0
  186. package/dist/fields/builtin/date.js.map +1 -0
  187. package/dist/fields/builtin/email.js +1 -1
  188. package/dist/fields/builtin/email.js.map +1 -1
  189. package/dist/fields/builtin/file.d.ts +15 -0
  190. package/dist/fields/builtin/file.js +95 -8
  191. package/dist/fields/builtin/file.js.map +1 -1
  192. package/dist/fields/builtin/index.d.ts +26 -0
  193. package/dist/fields/builtin/index.js +30 -6
  194. package/dist/fields/builtin/index.js.map +1 -1
  195. package/dist/fields/builtin/message.js +30 -0
  196. package/dist/fields/builtin/message.js.map +1 -0
  197. package/dist/fields/builtin/repeater.js +49 -0
  198. package/dist/fields/builtin/repeater.js.map +1 -0
  199. package/dist/fields/builtin/select.js +8 -3
  200. package/dist/fields/builtin/select.js.map +1 -1
  201. package/dist/fields/builtin/state.d.ts +13 -0
  202. package/dist/fields/builtin/state.js +30 -0
  203. package/dist/fields/builtin/state.js.map +1 -0
  204. package/dist/fields/data/regions.d.ts +21 -0
  205. package/dist/fields/data/regions.js +1238 -0
  206. package/dist/fields/data/regions.js.map +1 -0
  207. package/dist/fields/fieldKey.d.ts +15 -0
  208. package/dist/fields/fieldKey.js +16 -0
  209. package/dist/fields/fieldKey.js.map +1 -0
  210. package/dist/fields/fieldNamesOfType.js +30 -0
  211. package/dist/fields/fieldNamesOfType.js.map +1 -0
  212. package/dist/fields/instanceOptions.js +20 -0
  213. package/dist/fields/instanceOptions.js.map +1 -0
  214. package/dist/fields/localizedIf.d.ts +13 -0
  215. package/dist/fields/localizedIf.js +12 -0
  216. package/dist/fields/localizedIf.js.map +1 -0
  217. package/dist/fields/registry.d.ts +3 -1
  218. package/dist/fields/registry.js +23 -8
  219. package/dist/fields/registry.js.map +1 -1
  220. package/dist/fields/sharedConfig.js +120 -58
  221. package/dist/fields/sharedConfig.js.map +1 -1
  222. package/dist/fields/types.d.ts +71 -7
  223. package/dist/flow/engine.d.ts +6 -4
  224. package/dist/flow/engine.js +11 -6
  225. package/dist/flow/engine.js.map +1 -1
  226. package/dist/flow/normalizeFlow.js +28 -9
  227. package/dist/flow/normalizeFlow.js.map +1 -1
  228. package/dist/flow/stepLabel.js +15 -0
  229. package/dist/flow/stepLabel.js.map +1 -0
  230. package/dist/flow/types.d.ts +12 -3
  231. package/dist/flow/types.js +11 -0
  232. package/dist/flow/types.js.map +1 -0
  233. package/dist/form/pollState.d.ts +22 -0
  234. package/dist/form/pollState.js +17 -0
  235. package/dist/form/pollState.js.map +1 -0
  236. package/dist/form/toFormDocument.d.ts +102 -0
  237. package/dist/form/toFormDocument.js +87 -0
  238. package/dist/form/toFormDocument.js.map +1 -0
  239. package/dist/form/types.d.ts +65 -0
  240. package/dist/index.d.ts +53 -39
  241. package/dist/index.js +85 -23
  242. package/dist/index.js.map +1 -1
  243. package/dist/options.d.ts +229 -0
  244. package/dist/plugin/applyRegistryConfig.d.ts +11 -0
  245. package/dist/plugin/applyRegistryConfig.js +20 -0
  246. package/dist/plugin/applyRegistryConfig.js.map +1 -0
  247. package/dist/plugin/collectionOverrides.d.ts +22 -0
  248. package/dist/plugin/customState.js +26 -0
  249. package/dist/plugin/customState.js.map +1 -0
  250. package/dist/plugin/registerCollections.js +40 -20
  251. package/dist/plugin/registerCollections.js.map +1 -1
  252. package/dist/plugin/uploadsCollection.d.ts +16 -0
  253. package/dist/plugin/uploadsCollection.js +53 -0
  254. package/dist/plugin/uploadsCollection.js.map +1 -0
  255. package/dist/poll/applyPollOptions.js +18 -0
  256. package/dist/poll/applyPollOptions.js.map +1 -0
  257. package/dist/poll/buildPollOptionSourceFields.js +50 -0
  258. package/dist/poll/buildPollOptionSourceFields.js.map +1 -0
  259. package/dist/poll/closeJob.d.ts +52 -0
  260. package/dist/poll/closeJob.js +119 -0
  261. package/dist/poll/closeJob.js.map +1 -0
  262. package/dist/poll/definePollOptionSource.d.ts +44 -0
  263. package/dist/poll/definePollOptionSource.js +6 -0
  264. package/dist/poll/definePollOptionSource.js.map +1 -0
  265. package/dist/poll/definePollType.d.ts +34 -0
  266. package/dist/poll/definePollType.js +6 -0
  267. package/dist/poll/definePollType.js.map +1 -0
  268. package/dist/poll/effectivePollOptions.d.ts +38 -0
  269. package/dist/poll/effectivePollOptions.js +64 -0
  270. package/dist/poll/effectivePollOptions.js.map +1 -0
  271. package/dist/poll/mostVoted.d.ts +21 -0
  272. package/dist/poll/mostVoted.js +32 -0
  273. package/dist/poll/mostVoted.js.map +1 -0
  274. package/dist/poll/outcomeBeforeChange.js +91 -0
  275. package/dist/poll/outcomeBeforeChange.js.map +1 -0
  276. package/dist/poll/outcomeFields.d.ts +38 -0
  277. package/dist/poll/outcomeFields.js +52 -0
  278. package/dist/poll/outcomeFields.js.map +1 -0
  279. package/dist/poll/pollTypeRegistry.d.ts +34 -0
  280. package/dist/poll/pollTypeRegistry.js +69 -0
  281. package/dist/poll/pollTypeRegistry.js.map +1 -0
  282. package/dist/poll/registry.d.ts +17 -0
  283. package/dist/poll/registry.js +12 -0
  284. package/dist/poll/registry.js.map +1 -0
  285. package/dist/poll/resolvePollCloseRequest.js +105 -0
  286. package/dist/poll/resolvePollCloseRequest.js.map +1 -0
  287. package/dist/poll/resolvePollOptions.d.ts +29 -0
  288. package/dist/poll/resolvePollOptions.js +52 -0
  289. package/dist/poll/resolvePollOptions.js.map +1 -0
  290. package/dist/poll/resolvePollOptionsRequest.js +50 -0
  291. package/dist/poll/resolvePollOptionsRequest.js.map +1 -0
  292. package/dist/poll/resolvePollOutcome.d.ts +34 -0
  293. package/dist/poll/resolvePollOutcome.js +76 -0
  294. package/dist/poll/resolvePollOutcome.js.map +1 -0
  295. package/dist/poll/resultsField.js +21 -0
  296. package/dist/poll/resultsField.js.map +1 -0
  297. package/dist/prefill/valuesFromSearchParams.js +5 -9
  298. package/dist/prefill/valuesFromSearchParams.js.map +1 -1
  299. package/dist/presentations/types.d.ts +3 -2
  300. package/dist/react/Form.d.ts +66 -19
  301. package/dist/react/Form.js +342 -180
  302. package/dist/react/Form.js.map +1 -1
  303. package/dist/react/FormContext.d.ts +44 -1
  304. package/dist/react/FormContext.js.map +1 -1
  305. package/dist/react/FormControls.d.ts +55 -0
  306. package/dist/react/FormControls.js +56 -0
  307. package/dist/react/FormControls.js.map +1 -0
  308. package/dist/react/FormFields.d.ts +18 -0
  309. package/dist/react/FormFields.js +114 -0
  310. package/dist/react/FormFields.js.map +1 -0
  311. package/dist/react/FormLayout.d.ts +4 -2
  312. package/dist/react/FormLayout.js +3 -2
  313. package/dist/react/FormLayout.js.map +1 -1
  314. package/dist/react/FormResults.d.ts +6 -3
  315. package/dist/react/FormResults.js +37 -29
  316. package/dist/react/FormResults.js.map +1 -1
  317. package/dist/react/FormSteps.d.ts +17 -0
  318. package/dist/react/FormSteps.js +35 -0
  319. package/dist/react/FormSteps.js.map +1 -0
  320. package/dist/react/Poll.d.ts +17 -6
  321. package/dist/react/Poll.js +79 -21
  322. package/dist/react/Poll.js.map +1 -1
  323. package/dist/react/captcha/HcaptchaCaptcha.d.ts +28 -0
  324. package/dist/react/captcha/HcaptchaCaptcha.js +53 -0
  325. package/dist/react/captcha/HcaptchaCaptcha.js.map +1 -0
  326. package/dist/react/captcha/RecaptchaCaptcha.d.ts +41 -0
  327. package/dist/react/captcha/RecaptchaCaptcha.js +93 -0
  328. package/dist/react/captcha/RecaptchaCaptcha.js.map +1 -0
  329. package/dist/react/captcha/TurnstileCaptcha.d.ts +28 -0
  330. package/dist/react/captcha/TurnstileCaptcha.js +53 -0
  331. package/dist/react/captcha/TurnstileCaptcha.js.map +1 -0
  332. package/dist/react/captcha/types.d.ts +8 -0
  333. package/dist/react/captcha/useCaptchaScript.js +45 -0
  334. package/dist/react/captcha/useCaptchaScript.js.map +1 -0
  335. package/dist/react/captcha/vendors.js +8 -0
  336. package/dist/react/captcha/vendors.js.map +1 -0
  337. package/dist/react/contract.d.ts +2 -3
  338. package/dist/react/contract.js.map +1 -1
  339. package/dist/react/fetchResults.d.ts +1 -1
  340. package/dist/react/fetchResults.js +1 -1
  341. package/dist/react/fetchResults.js.map +1 -1
  342. package/dist/react/presentation/DialogSurface.js +1 -4
  343. package/dist/react/presentation/DialogSurface.js.map +1 -1
  344. package/dist/react/primitives/Checkbox.d.ts +4 -2
  345. package/dist/react/primitives/Checkbox.js +2 -1
  346. package/dist/react/primitives/Checkbox.js.map +1 -1
  347. package/dist/react/primitives/FieldShell.d.ts +2 -4
  348. package/dist/react/primitives/FieldShell.js +12 -19
  349. package/dist/react/primitives/FieldShell.js.map +1 -1
  350. package/dist/react/primitives/Input.d.ts +1 -1
  351. package/dist/react/primitives/Input.js.map +1 -1
  352. package/dist/react/renderers/calculation.js +1 -4
  353. package/dist/react/renderers/calculation.js.map +1 -1
  354. package/dist/react/renderers/checkbox.js +1 -4
  355. package/dist/react/renderers/checkbox.js.map +1 -1
  356. package/dist/react/renderers/consent.js +78 -35
  357. package/dist/react/renderers/consent.js.map +1 -1
  358. package/dist/react/renderers/date.js +33 -0
  359. package/dist/react/renderers/date.js.map +1 -0
  360. package/dist/react/renderers/email.js +1 -4
  361. package/dist/react/renderers/email.js.map +1 -1
  362. package/dist/react/renderers/file.js +29 -14
  363. package/dist/react/renderers/file.js.map +1 -1
  364. package/dist/react/renderers/index.js +9 -0
  365. package/dist/react/renderers/index.js.map +1 -1
  366. package/dist/react/renderers/message.js +41 -0
  367. package/dist/react/renderers/message.js.map +1 -0
  368. package/dist/react/renderers/number.js +1 -4
  369. package/dist/react/renderers/number.js.map +1 -1
  370. package/dist/react/renderers/region.js +43 -0
  371. package/dist/react/renderers/region.js.map +1 -0
  372. package/dist/react/renderers/repeater.js +131 -0
  373. package/dist/react/renderers/repeater.js.map +1 -0
  374. package/dist/react/renderers/select.js +1 -4
  375. package/dist/react/renderers/select.js.map +1 -1
  376. package/dist/react/renderers/text.js +1 -4
  377. package/dist/react/renderers/text.js.map +1 -1
  378. package/dist/react/renderers/textarea.js +1 -4
  379. package/dist/react/renderers/textarea.js.map +1 -1
  380. package/dist/react/state.d.ts +40 -3
  381. package/dist/react/state.js +64 -9
  382. package/dist/react/state.js.map +1 -1
  383. package/dist/react/uploadFile.d.ts +2 -2
  384. package/dist/react/uploadFile.js +1 -1
  385. package/dist/react/uploadFile.js.map +1 -1
  386. package/dist/react/useField.d.ts +0 -1
  387. package/dist/react/useField.js +6 -6
  388. package/dist/react/useField.js.map +1 -1
  389. package/dist/react/useFormState.d.ts +1 -1
  390. package/dist/react/useFormState.js +1 -1
  391. package/dist/react/useFormState.js.map +1 -1
  392. package/dist/react/validateField.js +3 -6
  393. package/dist/react/validateField.js.map +1 -1
  394. package/dist/recall/interpolate.d.ts +4 -3
  395. package/dist/recall/interpolate.js +5 -4
  396. package/dist/recall/interpolate.js.map +1 -1
  397. package/dist/recall/resolver.d.ts +1 -1
  398. package/dist/recall/resolver.js +14 -2
  399. package/dist/recall/resolver.js.map +1 -1
  400. package/dist/spam/captcha.d.ts +4 -3
  401. package/dist/spam/captcha.js +4 -3
  402. package/dist/spam/captcha.js.map +1 -1
  403. package/dist/spam/clientIp.js +9 -0
  404. package/dist/spam/clientIp.js.map +1 -0
  405. package/dist/spam/constants.js +7 -1
  406. package/dist/spam/constants.js.map +1 -1
  407. package/dist/spam/identify.js +3 -6
  408. package/dist/spam/identify.js.map +1 -1
  409. package/dist/spam/providers/hcaptcha.d.ts +17 -0
  410. package/dist/spam/providers/hcaptcha.js +18 -0
  411. package/dist/spam/providers/hcaptcha.js.map +1 -0
  412. package/dist/spam/providers/recaptcha.d.ts +23 -0
  413. package/dist/spam/providers/recaptcha.js +23 -0
  414. package/dist/spam/providers/recaptcha.js.map +1 -0
  415. package/dist/spam/providers/siteverify.js +34 -0
  416. package/dist/spam/providers/siteverify.js.map +1 -0
  417. package/dist/spam/providers/turnstile.d.ts +17 -0
  418. package/dist/spam/providers/turnstile.js +18 -0
  419. package/dist/spam/providers/turnstile.js.map +1 -0
  420. package/dist/spam/resolveSpam.js +2 -1
  421. package/dist/spam/resolveSpam.js.map +1 -1
  422. package/dist/spam/spamGuard.js +23 -10
  423. package/dist/spam/spamGuard.js.map +1 -1
  424. package/dist/spam/types.d.ts +19 -4
  425. package/dist/submissions/SubmissionAnswers.d.ts +2 -4
  426. package/dist/submissions/SubmissionAnswers.js +114 -34
  427. package/dist/submissions/SubmissionAnswers.js.map +1 -1
  428. package/dist/submissions/SubmissionAnswersClient.js +178 -0
  429. package/dist/submissions/SubmissionAnswersClient.js.map +1 -0
  430. package/dist/submissions/coerceBoolean.js +14 -0
  431. package/dist/submissions/coerceBoolean.js.map +1 -0
  432. package/dist/submissions/createSubmission.d.ts +36 -0
  433. package/dist/submissions/createSubmission.js +26 -0
  434. package/dist/submissions/createSubmission.js.map +1 -0
  435. package/dist/submissions/runSubmission.d.ts +10 -0
  436. package/dist/submissions/runSubmission.js +128 -27
  437. package/dist/submissions/runSubmission.js.map +1 -1
  438. package/dist/submissions/types.d.ts +12 -4
  439. package/dist/submissions/validateSubmission.js +62 -11
  440. package/dist/submissions/validateSubmission.js.map +1 -1
  441. package/dist/submissions/votedCookie.d.ts +13 -0
  442. package/dist/submissions/votedCookie.js +27 -0
  443. package/dist/submissions/votedCookie.js.map +1 -0
  444. package/dist/translations/clientRuntimeKeys.d.ts +17 -0
  445. package/dist/translations/clientRuntimeKeys.js +46 -0
  446. package/dist/translations/clientRuntimeKeys.js.map +1 -0
  447. package/dist/translations/de.d.ts +12 -0
  448. package/dist/translations/de.js +309 -0
  449. package/dist/translations/de.js.map +1 -0
  450. package/dist/translations/en.js +203 -27
  451. package/dist/translations/en.js.map +1 -1
  452. package/dist/translations/index.d.ts +14 -5
  453. package/dist/translations/index.js +14 -3
  454. package/dist/translations/index.js.map +1 -1
  455. package/dist/translations/keys.d.ts +199 -23
  456. package/dist/translations/keys.js +200 -24
  457. package/dist/translations/keys.js.map +1 -1
  458. package/dist/translations/makeTranslate.d.ts +7 -3
  459. package/dist/translations/makeTranslate.js +12 -3
  460. package/dist/translations/makeTranslate.js.map +1 -1
  461. package/dist/translations/server.js +8 -1
  462. package/dist/translations/server.js.map +1 -1
  463. package/dist/uploads/captureFileRef.d.ts +10 -3
  464. package/dist/uploads/captureFileRef.js +18 -9
  465. package/dist/uploads/captureFileRef.js.map +1 -1
  466. package/dist/uploads/formatBytes.d.ts +9 -0
  467. package/dist/uploads/formatBytes.js +25 -0
  468. package/dist/uploads/formatBytes.js.map +1 -0
  469. package/dist/uploads/resolveFileRef.js +3 -2
  470. package/dist/uploads/resolveFileRef.js.map +1 -1
  471. package/dist/uploads/types.d.ts +1 -2
  472. package/dist/validation/buildRuleBlocks.js +18 -17
  473. package/dist/validation/buildRuleBlocks.js.map +1 -1
  474. package/dist/validation/builtin/email.js +2 -1
  475. package/dist/validation/builtin/email.js.map +1 -1
  476. package/dist/validation/builtin/index.d.ts +14 -0
  477. package/dist/validation/builtin/index.js +12 -1
  478. package/dist/validation/builtin/index.js.map +1 -1
  479. package/dist/validation/builtin/matchesField.js +3 -7
  480. package/dist/validation/builtin/matchesField.js.map +1 -1
  481. package/dist/validation/builtin/max.js +1 -0
  482. package/dist/validation/builtin/max.js.map +1 -1
  483. package/dist/validation/builtin/maxDate.js +24 -0
  484. package/dist/validation/builtin/maxDate.js.map +1 -0
  485. package/dist/validation/builtin/maxLength.js +1 -0
  486. package/dist/validation/builtin/maxLength.js.map +1 -1
  487. package/dist/validation/builtin/min.js +1 -0
  488. package/dist/validation/builtin/min.js.map +1 -1
  489. package/dist/validation/builtin/minDate.js +24 -0
  490. package/dist/validation/builtin/minDate.js.map +1 -0
  491. package/dist/validation/builtin/minLength.js +1 -0
  492. package/dist/validation/builtin/minLength.js.map +1 -1
  493. package/dist/validation/builtin/notAlreadySubmitted.js +2 -0
  494. package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -1
  495. package/dist/validation/builtin/oneOf.js +1 -0
  496. package/dist/validation/builtin/oneOf.js.map +1 -1
  497. package/dist/validation/builtin/pattern.js +11 -2
  498. package/dist/validation/builtin/pattern.js.map +1 -1
  499. package/dist/validation/builtin/url.js +1 -0
  500. package/dist/validation/builtin/url.js.map +1 -1
  501. package/dist/validation/builtin/validateDateBound.js +18 -0
  502. package/dist/validation/builtin/validateDateBound.js.map +1 -0
  503. package/dist/validation/builtin/validateRegexParams.js +44 -0
  504. package/dist/validation/builtin/validateRegexParams.js.map +1 -0
  505. package/dist/validation/emailPattern.js +10 -0
  506. package/dist/validation/emailPattern.js.map +1 -0
  507. package/dist/validation/fieldTargetParam.d.ts +22 -0
  508. package/dist/validation/fieldTargetParam.js +38 -0
  509. package/dist/validation/fieldTargetParam.js.map +1 -0
  510. package/dist/validation/registry.d.ts +2 -1
  511. package/dist/validation/registry.js +2 -9
  512. package/dist/validation/registry.js.map +1 -1
  513. package/dist/validation/runValidation.js +9 -30
  514. package/dist/validation/runValidation.js.map +1 -1
  515. package/dist/validation/types.d.ts +5 -11
  516. package/dist/validation/validateUrl.js +22 -0
  517. package/dist/validation/validateUrl.js.map +1 -0
  518. package/package.json +7 -5
  519. package/styles/form-builder.css +10 -190
  520. package/dist/collections/uploads.d.ts +0 -29
  521. package/dist/collections/uploads.js +0 -46
  522. package/dist/collections/uploads.js.map +0 -1
  523. package/dist/consent/buildConsentSourceConfig.js +0 -49
  524. package/dist/consent/buildConsentSourceConfig.js.map +0 -1
  525. package/dist/consent/builtin/index.d.ts +0 -7
  526. package/dist/consent/builtin/index.js +0 -11
  527. package/dist/consent/builtin/index.js.map +0 -1
  528. package/dist/consent/builtin/pageReference.js +0 -75
  529. package/dist/consent/builtin/pageReference.js.map +0 -1
  530. package/dist/consent/builtin/static.js +0 -44
  531. package/dist/consent/builtin/static.js.map +0 -1
  532. package/dist/consent/defineConsentSource.d.ts +0 -35
  533. package/dist/consent/defineConsentSource.js +0 -6
  534. package/dist/consent/defineConsentSource.js.map +0 -1
  535. package/dist/consent/registry.d.ts +0 -16
  536. package/dist/consent/registry.js +0 -16
  537. package/dist/consent/registry.js.map +0 -1
  538. package/dist/consent/resolveConsentLinks.d.ts +0 -19
  539. package/dist/consent/resolveConsentLinks.js +0 -26
  540. package/dist/consent/resolveConsentLinks.js.map +0 -1
  541. package/dist/presentations/registry.d.ts +0 -15
  542. package/dist/presentations/registry.js +0 -15
  543. package/dist/presentations/registry.js.map +0 -1
  544. package/dist/react/toFormDocument.d.ts +0 -24
  545. package/dist/react/toFormDocument.js +0 -22
  546. package/dist/react/toFormDocument.js.map +0 -1
@@ -1,90 +1,95 @@
1
1
  "use client";
2
+ import { keys } from "../translations/keys.js";
2
3
  import { interpolate } from "../recall/interpolate.js";
4
+ import { serializeBody } from "../actions/body/serializeBody.js";
3
5
  import { noopEventSink } from "../events/noopSink.js";
4
- import { CAPTCHA_TOKEN_KEY } from "../spam/constants.js";
5
- import { defaultPresentationDescriptors } from "../presentations/defaults.js";
6
+ import { CAPTCHA_TOKEN_KEY, HONEYPOT_VALUE_KEY } from "../spam/constants.js";
7
+ import { fieldKey, isNamedField } from "../fields/fieldKey.js";
6
8
  import { calcExpressionOf, computeCalcFields } from "../calc/computeCalcFields.js";
7
9
  import { evaluateCondition } from "../conditions/evaluate.js";
10
+ import { resolveMessage } from "../validation/message.js";
8
11
  import { en } from "../translations/en.js";
9
- import { buildRecallResolver } from "../recall/resolver.js";
12
+ import { defaultPresentationDescriptors } from "../presentations/defaults.js";
13
+ import { buildRecallResolver, descriptorsFor } from "../recall/resolver.js";
10
14
  import { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames } from "../flow/engine.js";
11
15
  import { cn } from "./cn.js";
12
16
  import { makeTranslate } from "../translations/makeTranslate.js";
13
17
  import { emitFormEvent } from "./events.js";
14
18
  import { FormContext } from "./FormContext.js";
15
- import { FormLayout, widthProps } from "./FormLayout.js";
19
+ import { FormControls } from "./FormControls.js";
20
+ import { DEFAULT_STEP_ID, formReducer, initialFormState, seedFieldValues } from "./state.js";
21
+ import { FormFields } from "./FormFields.js";
16
22
  import { Honeypot } from "./Honeypot.js";
17
23
  import { defaultPresentations } from "./presentation/presentations.js";
18
24
  import { resolvePresentations } from "./presentation/registry.js";
19
- import { applyRecall } from "./recall.js";
20
25
  import { resolveRenderers } from "./registry.js";
21
26
  import { defaultRenderers } from "./renderers/index.js";
22
27
  import { buildFieldTypeRegistry, buildValidationRuleRegistry, visibleFields } from "./resolveForm.js";
23
- import { formReducer, initialFormState } from "./state.js";
24
28
  import { submitForm } from "./submitForm.js";
25
- import { useField } from "./useField.js";
26
29
  import { validateFieldValue } from "./validateField.js";
27
- import { createElement, useCallback, useEffect, useId, useMemo, useReducer, useRef, useState } from "react";
28
- import { jsx, jsxs } from "react/jsx-runtime";
30
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
31
+ import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
29
32
  //#region src/react/Form.tsx
30
33
  const isEmpty = (value) => value == null || value === "" || Array.isArray(value) && value.length === 0;
31
- const FIELD_WIDTHS = new Set([
32
- "full",
33
- "half",
34
- "third",
35
- "twoThirds"
36
- ]);
37
- const FieldHost = ({ field, renderer, locale, t }) => {
38
- const id = useId();
39
- const { value, errors, warnings, setValue, onBlur } = useField(field.name);
40
- return createElement(renderer, {
41
- field,
42
- id,
43
- name: field.name,
44
- value,
45
- onChange: setValue,
46
- onBlur,
47
- errors,
48
- warnings,
49
- required: Boolean(field.required),
50
- locale,
51
- t
52
- });
34
+ /** Visually hidden but screen-reader-announced, for the "Step X of Y" live region (no host CSS required). */
35
+ const SR_ONLY = {
36
+ position: "absolute",
37
+ width: 1,
38
+ height: 1,
39
+ padding: 0,
40
+ margin: -1,
41
+ overflow: "hidden",
42
+ clip: "rect(0, 0, 0, 0)",
43
+ whiteSpace: "nowrap",
44
+ border: 0
53
45
  };
54
- /** Hosts a derived (calc) field: read-only, value supplied from `effectiveValues`, never bound via `useField`. */
55
- const CalcFieldHost = ({ field, renderer, value, locale, t }) => {
56
- return createElement(renderer, {
57
- field,
58
- id: useId(),
59
- name: field.name,
60
- value,
61
- onChange: () => {},
62
- onBlur: () => {},
63
- errors: [],
64
- warnings: [],
65
- required: false,
66
- disabled: true,
67
- locale,
68
- t
69
- });
46
+ /** The base field name of an error key: the part before a repeater composite suffix (`name[0].sub`). */
47
+ const baseFieldKey = (key) => {
48
+ const bracket = key.indexOf("[");
49
+ return bracket === -1 ? key : key.slice(0, bracket);
50
+ };
51
+ /** The id of the first flow step (in order) that owns an errored field, or undefined when none does. */
52
+ const firstStepWithError = (flow, errors) => {
53
+ const errored = new Set(Object.keys(errors).map(baseFieldKey));
54
+ return flow.steps.find((flowStep) => flowStep.fields.some((key) => errored.has(key)))?.id;
55
+ };
56
+ /** The first focusable element under `root` that a step transition should land on (skips hidden/honeypot). */
57
+ const focusFirstIn = (root, selector) => {
58
+ (root?.querySelector(selector))?.focus();
70
59
  };
60
+ /** A stored button label counts only when it is a non-empty string; anything else falls through. */
61
+ const storedLabel = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
71
62
  /** The headless form controller: state, progressive client validation, conditional visibility, submission, events. */
72
- const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSuccess, onError, events, t, locale = "en", layout, submitLabel = "Submit", nextLabel = "Next", backLabel = "Back", closeLabel = "Close", successMessage = "Thank you.", presentation, presentations, onClose, title, initialValues, honeypot, captchaToken, children, className }) => {
63
+ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSuccess, onError, converters, successBehavior = "replace", events, t, locale = "en", layout, submitLabel, nextLabel, prevLabel, closeLabel, successMessage, presentation, presentations, onClose, title, initialValues, honeypot, captchaToken, children, header, className, renderSubmit, renderNext, renderBack, submitButtonClassName, nextButtonClassName, backButtonClassName }) => {
73
64
  const honeypotName = honeypot === false ? null : honeypot?.name ?? "website";
74
65
  const honeypotRef = useRef(null);
75
66
  const registry = useMemo(() => buildFieldTypeRegistry(fieldTypes), [fieldTypes]);
76
67
  const ruleRegistry = useMemo(() => buildValidationRuleRegistry(rules), [rules]);
77
68
  const rendererRegistry = useMemo(() => resolveRenderers(defaultRenderers, renderers), [renderers]);
78
69
  const presentationRegistry = useMemo(() => resolvePresentations(defaultPresentations, presentations), [presentations]);
79
- const activePresentation = typeof presentation === "object" ? presentation : presentationRegistry.get(presentation ?? form.defaultPresentation ?? "page") ?? presentationRegistry.get("page") ?? defaultPresentationDescriptors.page;
80
- const fieldsByName = useMemo(() => new Map(form.fields.map((field) => [field.name, field])), [form.fields]);
70
+ const activePresentation = typeof presentation === "object" ? presentation : presentationRegistry.get(presentation ?? "page") ?? presentationRegistry.get("page") ?? defaultPresentationDescriptors.page;
71
+ const fieldsByName = useMemo(() => new Map(form.fields.filter(isNamedField).map((field) => [field.name, field])), [form.fields]);
81
72
  const translate = useMemo(() => t ?? makeTranslate(en), [t]);
73
+ const resolvedCloseLabel = closeLabel ?? translate(keys.formClose);
74
+ const resolvedSuccessMessage = successMessage ?? translate(keys.formSuccess);
75
+ const docButtons = form.buttons;
76
+ const labels = useMemo(() => ({
77
+ prev: prevLabel ?? storedLabel(docButtons?.prevLabel) ?? translate(keys.formBack),
78
+ next: nextLabel ?? storedLabel(docButtons?.nextLabel) ?? translate(keys.formNext),
79
+ submit: submitLabel ?? storedLabel(docButtons?.submitLabel) ?? translate(keys.formSubmit)
80
+ }), [
81
+ prevLabel,
82
+ nextLabel,
83
+ submitLabel,
84
+ docButtons,
85
+ translate
86
+ ]);
82
87
  const sinkRef = useRef(noopEventSink);
83
88
  sinkRef.current = events ?? noopEventSink;
84
89
  const formIdRef = useRef("");
85
90
  formIdRef.current = String(form.id);
86
91
  const [state, rawDispatch] = useReducer(formReducer, form.fields, (fields) => initialFormState({
87
- ...Object.fromEntries(fields.map((field) => [field.name, void 0])),
92
+ ...seedFieldValues(fields),
88
93
  ...initialValues ?? {}
89
94
  }));
90
95
  const effectiveValues = useMemo(() => computeCalcFields(form.fields, state.values), [form.fields, state.values]);
@@ -101,14 +106,28 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
101
106
  locale,
102
107
  translate
103
108
  ]);
104
- const flow = form.flow && form.flow.steps.length >= 2 ? form.flow : void 0;
109
+ const flow = form.multistep === true && form.flow && form.flow.steps.length >= 2 ? form.flow : void 0;
105
110
  const [currentStepId, setCurrentStepId] = useState(() => flow ? firstStepId(flow) : void 0);
106
111
  const [history, setHistory] = useState([]);
107
112
  const startedRef = useRef(false);
108
113
  const submittedRef = useRef(false);
109
114
  const submittingRef = useRef(false);
115
+ const advancingRef = useRef(false);
110
116
  const flowRef = useRef(flow);
111
117
  flowRef.current = flow;
118
+ const stepIdOfField = useMemo(() => {
119
+ const map = /* @__PURE__ */ new Map();
120
+ if (flow) for (const flowStep of flow.steps) for (const key of flowStep.fields) map.set(key, flowStep.id);
121
+ return (fieldKey) => map.get(fieldKey) ?? "__form__";
122
+ }, [flow]);
123
+ const allStepIds = useMemo(() => flow ? flow.steps.map((flowStep) => flowStep.id) : [DEFAULT_STEP_ID], [flow]);
124
+ const formRef = useRef(null);
125
+ const pendingFocusRef = useRef(null);
126
+ const [focusNonce, setFocusNonce] = useState(0);
127
+ const requestFocus = (intent) => {
128
+ pendingFocusRef.current = intent;
129
+ setFocusNonce((nonce) => nonce + 1);
130
+ };
112
131
  const dispatch = useCallback((action) => {
113
132
  if (action.type === "SET_VALUE" && !startedRef.current) {
114
133
  startedRef.current = true;
@@ -127,8 +146,7 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
127
146
  rawDispatch({
128
147
  type: "SET_FIELD_ISSUES",
129
148
  name,
130
- errors: [],
131
- warnings: []
149
+ errors: []
132
150
  });
133
151
  return;
134
152
  }
@@ -140,12 +158,11 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
140
158
  answers,
141
159
  locale,
142
160
  t: translate
143
- }).then(({ errors, warnings }) => {
161
+ }).then(({ errors }) => {
144
162
  rawDispatch({
145
163
  type: "SET_FIELD_ISSUES",
146
164
  name,
147
- errors,
148
- warnings
165
+ errors
149
166
  });
150
167
  const [firstError] = errors;
151
168
  if (firstError !== void 0) emitFormEvent(sinkRef.current, formIdRef.current, {
@@ -163,59 +180,169 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
163
180
  translate
164
181
  ]);
165
182
  const visible = visibleFields(form.fields, effectiveValues);
166
- const stepVisible = (flow && currentStepId ? stepFieldNames(flow, currentStepId) : []).map((name) => visible.find((field) => field.name === name)).filter((field) => Boolean(field));
183
+ /** Visible, answered named fields. Display-only ('none' kind) and nameless (bare) fields never contribute. */
184
+ const answerableFields = () => visibleFields(form.fields, effectiveValues).filter((field) => registry.get(field.blockType)?.value !== "none").filter(isNamedField).filter((field) => !isEmpty(effectiveValues[field.name]));
185
+ /** Answered visible fields as raw submission values, sent to the server on submit. */
186
+ const answeredValues = () => answerableFields().map((field) => ({
187
+ field: field.name,
188
+ value: effectiveValues[field.name]
189
+ }));
190
+ /**
191
+ * Same fields, formatted via `recall` (option labels, Yes/No, localized dates): recall-fidelity
192
+ * values for client-rendered templates, matching what the server gives email-team's body.
193
+ */
194
+ const formattedValues = () => answerableFields().map((field) => ({
195
+ field: field.name,
196
+ value: recall(field.name)
197
+ }));
198
+ /**
199
+ * The recall-resolved success response: a redirect's url, or the response message serialized with
200
+ * the active `converters` (so host blocks survive). Shared by the success screen and the value
201
+ * handed to `onSuccess`, so both stay identical.
202
+ */
203
+ const resolveSuccessResponse = () => {
204
+ const response = form.response;
205
+ if (response?.type === "redirect") return {
206
+ type: "redirect",
207
+ url: response.redirect?.url ?? void 0
208
+ };
209
+ const message = response?.type === "message" || response?.type == null ? response?.message : void 0;
210
+ if (!message) return;
211
+ return {
212
+ type: "message",
213
+ html: serializeBody(message, {
214
+ values: formattedValues(),
215
+ descriptors: descriptorsFor(answerableFields()),
216
+ converters
217
+ })
218
+ };
219
+ };
220
+ const stepKeys = flow && currentStepId ? stepFieldNames(flow, currentStepId) : [];
221
+ const stepKeySet = new Set(stepKeys);
222
+ const stepVisible = visible.filter((field) => stepKeySet.has(fieldKey(field)));
223
+ const validateRepeaterSubFields = async (repeaters) => {
224
+ const errors = {};
225
+ for (const field of repeaters.filter((f) => f.blockType === "repeater" && isNamedField(f))) {
226
+ const rows = Array.isArray(effectiveValues[field.name]) ? effectiveValues[field.name] : [];
227
+ const subFields = (Array.isArray(field.subFields) ? field.subFields : []).filter(isNamedField);
228
+ for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
229
+ const row = rows[rowIndex] ?? {};
230
+ for (const subField of subFields) {
231
+ if (!evaluateCondition(subField.visibleWhen, row)) continue;
232
+ if (!evaluateCondition(subField.validateWhen, row)) continue;
233
+ const subResult = await validateFieldValue({
234
+ field: subField,
235
+ value: row[subField.name],
236
+ registry,
237
+ ruleRegistry,
238
+ answers: row,
239
+ locale,
240
+ t: translate
241
+ });
242
+ const compositeKey = `${field.name}[${rowIndex}].${subField.name}`;
243
+ if (subResult.errors.length > 0) errors[compositeKey] = subResult.errors;
244
+ }
245
+ }
246
+ }
247
+ return errors;
248
+ };
167
249
  const goNext = async () => {
168
- if (!flow || !currentStepId) return;
169
- const results = await Promise.all(stepVisible.filter((field) => !calcExpressionOf(field)).filter((field) => evaluateCondition(field.validateWhen, effectiveValues)).map(async (field) => ({
170
- field,
171
- ...await validateFieldValue({
250
+ if (!flow || !currentStepId || advancingRef.current) return;
251
+ advancingRef.current = true;
252
+ try {
253
+ const results = await Promise.all(stepVisible.filter((field) => !calcExpressionOf(field)).filter((field) => registry.get(field.blockType)?.value !== "none").filter(isNamedField).filter((field) => evaluateCondition(field.validateWhen, effectiveValues)).map(async (field) => ({
172
254
  field,
173
- value: effectiveValues[field.name],
174
- registry,
175
- ruleRegistry,
176
- answers: effectiveValues,
177
- locale,
178
- t: translate
179
- })
180
- })));
181
- let hasError = false;
182
- for (const result of results) {
183
- rawDispatch({
184
- type: "TOUCH",
185
- name: result.field.name
255
+ ...await validateFieldValue({
256
+ field,
257
+ value: effectiveValues[field.name],
258
+ registry,
259
+ ruleRegistry,
260
+ answers: effectiveValues,
261
+ locale,
262
+ t: translate
263
+ })
264
+ })));
265
+ let hasError = false;
266
+ for (const result of results) {
267
+ rawDispatch({
268
+ type: "TOUCH",
269
+ name: result.field.name
270
+ });
271
+ rawDispatch({
272
+ type: "SET_FIELD_ISSUES",
273
+ name: result.field.name,
274
+ errors: result.errors
275
+ });
276
+ if (result.errors.length > 0) hasError = true;
277
+ }
278
+ const repeaterErrors = await validateRepeaterSubFields(stepVisible);
279
+ for (const [compositeKey, errs] of Object.entries(repeaterErrors)) {
280
+ rawDispatch({
281
+ type: "SET_FIELD_ISSUES",
282
+ name: compositeKey,
283
+ errors: errs
284
+ });
285
+ hasError = true;
286
+ }
287
+ if (hasError) {
288
+ rawDispatch({
289
+ type: "MARK_STEP_ATTEMPTED",
290
+ stepId: currentStepId
291
+ });
292
+ requestFocus("firstInvalid");
293
+ return;
294
+ }
295
+ const next = resolveNextStepId(flow, currentStepId, effectiveValues);
296
+ if (!next) return;
297
+ emitFormEvent(sinkRef.current, formIdRef.current, {
298
+ type: "step.completed",
299
+ stepId: currentStepId
186
300
  });
187
- rawDispatch({
188
- type: "SET_FIELD_ISSUES",
189
- name: result.field.name,
190
- errors: result.errors,
191
- warnings: result.warnings
301
+ setHistory((prev) => [...prev, currentStepId]);
302
+ setCurrentStepId(next);
303
+ requestFocus("stepStart");
304
+ emitFormEvent(sinkRef.current, formIdRef.current, {
305
+ type: "step.viewed",
306
+ stepId: next
192
307
  });
193
- if (result.errors.length > 0) hasError = true;
308
+ } finally {
309
+ advancingRef.current = false;
194
310
  }
195
- if (hasError) return;
196
- const next = resolveNextStepId(flow, currentStepId, state.values);
197
- if (!next) return;
198
- emitFormEvent(sinkRef.current, formIdRef.current, {
199
- type: "step.completed",
200
- stepId: currentStepId
201
- });
202
- setHistory((prev) => [...prev, currentStepId]);
203
- setCurrentStepId(next);
204
- emitFormEvent(sinkRef.current, formIdRef.current, {
205
- type: "step.viewed",
206
- stepId: next
207
- });
208
311
  };
209
312
  const goBack = () => {
210
313
  const prev = history[history.length - 1];
211
314
  if (prev === void 0) return;
212
315
  setHistory((entries) => entries.slice(0, -1));
213
316
  setCurrentStepId(prev);
317
+ requestFocus("stepStart");
214
318
  emitFormEvent(sinkRef.current, formIdRef.current, {
215
319
  type: "step.viewed",
216
320
  stepId: prev
217
321
  });
218
322
  };
323
+ const navigateToStep = (stepId) => {
324
+ if (!flow || stepId === currentStepId) return;
325
+ const idx = flow.steps.findIndex((flowStep) => flowStep.id === stepId);
326
+ if (idx < 0) return;
327
+ setHistory(flow.steps.slice(0, idx).map((flowStep) => flowStep.id));
328
+ setCurrentStepId(stepId);
329
+ emitFormEvent(sinkRef.current, formIdRef.current, {
330
+ type: "step.viewed",
331
+ stepId
332
+ });
333
+ };
334
+ useEffect(() => {
335
+ const intent = pendingFocusRef.current;
336
+ if (!intent) return;
337
+ pendingFocusRef.current = null;
338
+ if (intent === "firstInvalid") {
339
+ focusFirstIn(formRef.current, "[aria-invalid=\"true\"]");
340
+ return;
341
+ }
342
+ const region = formRef.current?.querySelector("[data-fb-step-region]");
343
+ if (region) region.focus();
344
+ else focusFirstIn(formRef.current, "input:not([type=\"hidden\"]), select, textarea");
345
+ }, [currentStepId, focusNonce]);
219
346
  useEffect(() => {
220
347
  emitFormEvent(sinkRef.current, formIdRef.current, { type: "form.viewed" });
221
348
  const mountFlow = flowRef.current;
@@ -238,7 +365,7 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
238
365
  if (submittingRef.current) return;
239
366
  submittingRef.current = true;
240
367
  const visible = visibleFields(form.fields, effectiveValues);
241
- const results = await Promise.all(visible.filter((field) => !calcExpressionOf(field)).filter((field) => evaluateCondition(field.validateWhen, effectiveValues)).map(async (field) => ({
368
+ const results = await Promise.all(visible.filter((field) => !calcExpressionOf(field)).filter((field) => registry.get(field.blockType)?.value !== "none").filter(isNamedField).filter((field) => evaluateCondition(field.validateWhen, effectiveValues)).map(async (field) => ({
242
369
  field,
243
370
  ...await validateFieldValue({
244
371
  field,
@@ -251,37 +378,37 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
251
378
  })
252
379
  })));
253
380
  const errors = {};
254
- const warnings = {};
255
- for (const result of results) {
256
- if (result.errors.length > 0) {
257
- errors[result.field.name] = result.errors;
258
- const [firstError] = result.errors;
259
- if (firstError !== void 0) emitFormEvent(sinkRef.current, formIdRef.current, {
260
- type: "field.errored",
261
- field: result.field.name,
262
- message: firstError
263
- });
264
- }
265
- if (result.warnings.length > 0) warnings[result.field.name] = result.warnings;
381
+ for (const result of results) if (result.errors.length > 0) {
382
+ errors[result.field.name] = result.errors;
383
+ const [firstError] = result.errors;
384
+ if (firstError !== void 0) emitFormEvent(sinkRef.current, formIdRef.current, {
385
+ type: "field.errored",
386
+ field: result.field.name,
387
+ message: firstError
388
+ });
266
389
  }
390
+ Object.assign(errors, await validateRepeaterSubFields(visible));
391
+ const hasErrors = Object.keys(errors).length > 0;
267
392
  rawDispatch({
268
393
  type: "SET_ALL_ISSUES",
269
394
  errors,
270
- warnings
395
+ steps: hasErrors ? allStepIds : []
271
396
  });
272
- if (Object.keys(errors).length > 0) {
397
+ if (hasErrors) {
273
398
  submittingRef.current = false;
399
+ if (flow && currentStepId) {
400
+ const target = firstStepWithError(flow, errors);
401
+ if (target) navigateToStep(target);
402
+ }
403
+ requestFocus("firstInvalid");
274
404
  return;
275
405
  }
276
406
  rawDispatch({ type: "SUBMIT_START" });
277
- const values = visible.filter((field) => !isEmpty(effectiveValues[field.name])).map((field) => ({
278
- field: field.name,
279
- value: effectiveValues[field.name]
280
- }));
407
+ const values = answeredValues();
281
408
  if (honeypotName) {
282
409
  const decoy = honeypotRef.current?.value ?? "";
283
410
  if (decoy !== "") values.push({
284
- field: honeypotName,
411
+ field: HONEYPOT_VALUE_KEY,
285
412
  value: decoy
286
413
  });
287
414
  }
@@ -300,20 +427,37 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
300
427
  submittingRef.current = false;
301
428
  if (result.ok) {
302
429
  submittedRef.current = true;
303
- rawDispatch({ type: "SUBMIT_SUCCESS" });
304
430
  emitFormEvent(sinkRef.current, formIdRef.current, {
305
431
  type: "submission.created",
306
432
  submissionId: result.submissionId
307
433
  });
308
- onSuccess?.(result.submissionId);
309
- if (activePresentation.dismissOnSuccess) handleClose();
434
+ onSuccess?.(result.submissionId, { response: resolveSuccessResponse() });
435
+ if (successBehavior === "reset") {
436
+ rawDispatch({
437
+ type: "RESET",
438
+ values: {
439
+ ...seedFieldValues(form.fields),
440
+ ...initialValues ?? {}
441
+ }
442
+ });
443
+ if (flow) {
444
+ setCurrentStepId(firstStepId(flow));
445
+ setHistory([]);
446
+ }
447
+ startedRef.current = false;
448
+ } else {
449
+ rawDispatch({ type: "SUBMIT_SUCCESS" });
450
+ if (activePresentation.dismissOnSuccess) handleClose();
451
+ }
452
+ const redirectUrl = form.response?.type === "redirect" ? form.response.redirect?.url : void 0;
453
+ if (typeof redirectUrl === "string" && redirectUrl.length > 0 && typeof window !== "undefined") window.location.assign(redirectUrl);
310
454
  } else {
311
455
  if (result.fieldErrors) rawDispatch({
312
456
  type: "SET_ALL_ISSUES",
313
457
  errors: result.fieldErrors,
314
- warnings: {}
458
+ steps: allStepIds
315
459
  });
316
- const message = result.message ?? "Submission failed";
460
+ const message = result.message ?? translate(keys.formSubmitFailed);
317
461
  rawDispatch({
318
462
  type: "SUBMIT_ERROR",
319
463
  message
@@ -321,13 +465,24 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
321
465
  onError?.(message);
322
466
  }
323
467
  };
468
+ const isTerminalStep = flow && currentStepId ? isTerminalStepId(flow, currentStepId, effectiveValues) : true;
469
+ const handleKeyDown = (event) => {
470
+ if (!flow || event.key !== "Enter") return;
471
+ const target = event.target;
472
+ if (target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement || target instanceof HTMLButtonElement) return;
473
+ if (target instanceof HTMLInputElement && (target.type === "submit" || target.type === "button")) return;
474
+ if (!isTerminalStep) {
475
+ event.preventDefault();
476
+ goNext();
477
+ }
478
+ };
324
479
  const step = flow ? {
325
480
  flow,
326
481
  currentStepId,
327
482
  stepIndex: flow.steps.findIndex((s) => s.id === currentStepId),
328
483
  stepCount: flow.steps.length,
329
484
  isFirst: history.length === 0,
330
- isTerminal: currentStepId ? isTerminalStepId(flow, currentStepId, state.values) : true,
485
+ isTerminal: isTerminalStep,
331
486
  goNext: () => {
332
487
  goNext();
333
488
  },
@@ -340,12 +495,26 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
340
495
  goNext: () => {},
341
496
  goBack: () => {}
342
497
  };
498
+ const stepStatusText = flow ? resolveMessage(translate(keys.formStepStatus), {
499
+ current: String(step.stepIndex + 1),
500
+ total: String(step.stepCount)
501
+ }) : "";
502
+ const currentStepHasError = flow != null && currentStepId != null && state.attemptedSteps.has(currentStepId) && Object.entries(state.errors).some(([key, errs]) => errs.length > 0 && stepIdOfField(baseFieldKey(key)) === currentStepId);
343
503
  const contextValue = {
504
+ form,
344
505
  state,
345
506
  dispatch,
346
507
  validateField,
347
508
  locale,
348
- step
509
+ step,
510
+ rendererRegistry,
511
+ labels,
512
+ t: translate,
513
+ effectiveValues,
514
+ recall,
515
+ renderedFields: (flow ? stepVisible : visible).filter((field) => field.hidden !== true && field.calcDisplay !== false),
516
+ converters,
517
+ stepIdOfField
349
518
  };
350
519
  const PresentationWrapper = activePresentation.Wrapper;
351
520
  const wrap = (content) => PresentationWrapper ? /* @__PURE__ */ jsx(PresentationWrapper, {
@@ -353,15 +522,17 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
353
522
  open: true,
354
523
  onClose: handleClose,
355
524
  title,
356
- closeLabel,
525
+ closeLabel: resolvedCloseLabel,
357
526
  children: content
358
527
  }) : content;
359
528
  if (children !== void 0) return /* @__PURE__ */ jsx(FormContext.Provider, {
360
529
  value: contextValue,
361
530
  children: wrap(/* @__PURE__ */ jsxs("form", {
531
+ ref: formRef,
362
532
  className: cn("fb-form-root", className),
363
533
  noValidate: true,
364
534
  onSubmit: handleSubmit,
535
+ onKeyDown: handleKeyDown,
365
536
  "data-fb-presentation": activePresentation.name,
366
537
  "data-fb-density": activePresentation.density,
367
538
  children: [honeypotName ? /* @__PURE__ */ jsx(Honeypot, {
@@ -370,23 +541,34 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
370
541
  }) : null, children]
371
542
  }))
372
543
  });
373
- if (state.submitted) return /* @__PURE__ */ jsx(FormContext.Provider, {
374
- value: contextValue,
375
- children: wrap(/* @__PURE__ */ jsx("p", {
376
- role: "status",
377
- className: cn("fb-form__success", className),
378
- "data-fb-presentation": activePresentation.name,
379
- "data-fb-density": activePresentation.density,
380
- children: interpolate(successMessage, recall)
381
- }))
382
- });
383
- const rendered = (flow ? stepVisible : visible).filter((field) => field.hidden !== true && field.calcDisplay !== false);
544
+ if (state.submitted) {
545
+ const successResponse = resolveSuccessResponse();
546
+ const responseHtml = successResponse?.type === "message" ? successResponse.html : void 0;
547
+ return /* @__PURE__ */ jsx(FormContext.Provider, {
548
+ value: contextValue,
549
+ children: wrap(responseHtml ? /* @__PURE__ */ jsx("div", {
550
+ role: "status",
551
+ className: cn("fb-form__success", className),
552
+ "data-fb-presentation": activePresentation.name,
553
+ "data-fb-density": activePresentation.density,
554
+ dangerouslySetInnerHTML: { __html: responseHtml }
555
+ }) : /* @__PURE__ */ jsx("p", {
556
+ role: "status",
557
+ className: cn("fb-form__success", className),
558
+ "data-fb-presentation": activePresentation.name,
559
+ "data-fb-density": activePresentation.density,
560
+ children: interpolate(resolvedSuccessMessage, recall)
561
+ }))
562
+ });
563
+ }
384
564
  return /* @__PURE__ */ jsx(FormContext.Provider, {
385
565
  value: contextValue,
386
566
  children: wrap(/* @__PURE__ */ jsxs("form", {
567
+ ref: formRef,
387
568
  className: cn("fb-form-root", className),
388
569
  noValidate: true,
389
570
  onSubmit: handleSubmit,
571
+ onKeyDown: handleKeyDown,
390
572
  "data-fb-presentation": activePresentation.name,
391
573
  "data-fb-density": activePresentation.density,
392
574
  children: [
@@ -394,58 +576,38 @@ const Form = ({ form, fieldTypes, rules, renderers, apiRoute, onSubmit, onSucces
394
576
  name: honeypotName,
395
577
  inputRef: honeypotRef
396
578
  }) : null,
397
- /* @__PURE__ */ jsx(FormLayout, {
398
- enabled: layout !== false,
399
- children: rendered.map((field) => {
400
- const renderer = rendererRegistry.get(field.blockType);
401
- if (!renderer) return null;
402
- const width = typeof field.width === "string" && FIELD_WIDTHS.has(field.width) ? field.width : void 0;
403
- const recalledField = applyRecall(field, recall);
404
- return /* @__PURE__ */ jsx("div", {
405
- ...widthProps(width),
406
- children: calcExpressionOf(field) ? /* @__PURE__ */ jsx(CalcFieldHost, {
407
- field: recalledField,
408
- renderer,
409
- value: effectiveValues[field.name],
410
- locale,
411
- t: translate
412
- }) : /* @__PURE__ */ jsx(FieldHost, {
413
- field: recalledField,
414
- renderer,
415
- locale,
416
- t: translate
417
- })
418
- }, field.name);
419
- })
420
- }),
579
+ header,
580
+ flow ? /* @__PURE__ */ jsxs(Fragment, { children: [
581
+ /* @__PURE__ */ jsx("div", {
582
+ "aria-live": "polite",
583
+ "aria-atomic": "true",
584
+ style: SR_ONLY,
585
+ children: stepStatusText
586
+ }),
587
+ /* @__PURE__ */ jsx("div", {
588
+ "data-fb-step-region": true,
589
+ tabIndex: -1,
590
+ className: "fb-form__step",
591
+ children: /* @__PURE__ */ jsx(FormFields, { layout })
592
+ }),
593
+ currentStepHasError ? /* @__PURE__ */ jsx("p", {
594
+ role: "alert",
595
+ className: "fb-form__step-error",
596
+ children: translate(keys.formStepInvalid)
597
+ }) : null
598
+ ] }) : /* @__PURE__ */ jsx(FormFields, { layout }),
421
599
  state.submitError ? /* @__PURE__ */ jsx("p", {
422
600
  role: "alert",
423
601
  className: "fb-form__submit-error",
424
602
  children: state.submitError
425
603
  }) : null,
426
- flow ? /* @__PURE__ */ jsxs("div", {
427
- className: "fb-form__controls",
428
- children: [!step.isFirst ? /* @__PURE__ */ jsx("button", {
429
- type: "button",
430
- onClick: goBack,
431
- disabled: state.submitting,
432
- children: backLabel
433
- }) : null, step.isTerminal ? /* @__PURE__ */ jsx("button", {
434
- type: "submit",
435
- disabled: state.submitting,
436
- children: submitLabel
437
- }) : /* @__PURE__ */ jsx("button", {
438
- type: "button",
439
- disabled: state.submitting,
440
- onClick: () => {
441
- goNext();
442
- },
443
- children: nextLabel
444
- })]
445
- }) : /* @__PURE__ */ jsx("button", {
446
- type: "submit",
447
- disabled: state.submitting,
448
- children: submitLabel
604
+ /* @__PURE__ */ jsx(FormControls, {
605
+ backButtonClassName,
606
+ nextButtonClassName,
607
+ submitButtonClassName,
608
+ renderBack,
609
+ renderNext,
610
+ renderSubmit
449
611
  })
450
612
  ]
451
613
  }))