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

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 (619) hide show
  1. package/CHANGELOG.md +360 -0
  2. package/README.md +7 -5
  3. package/dist/actions/assertNoBlockCollision.js +18 -0
  4. package/dist/actions/assertNoBlockCollision.js.map +1 -0
  5. package/dist/actions/body/converters.d.ts +20 -0
  6. package/dist/actions/body/converters.js +57 -0
  7. package/dist/actions/body/converters.js.map +1 -0
  8. package/dist/actions/body/escapeHtml.d.ts +6 -0
  9. package/dist/actions/body/escapeHtml.js +14 -0
  10. package/dist/actions/body/escapeHtml.js.map +1 -0
  11. package/dist/actions/body/serializeBody.d.ts +55 -0
  12. package/dist/actions/body/serializeBody.js +78 -0
  13. package/dist/actions/body/serializeBody.js.map +1 -0
  14. package/dist/actions/body/serializeSlate.js +31 -0
  15. package/dist/actions/body/serializeSlate.js.map +1 -0
  16. package/dist/actions/body/textOfBody.d.ts +13 -0
  17. package/dist/actions/body/textOfBody.js +35 -0
  18. package/dist/actions/body/textOfBody.js.map +1 -0
  19. package/dist/actions/body/wildcards.d.ts +10 -0
  20. package/dist/actions/body/wildcards.js +33 -0
  21. package/dist/actions/body/wildcards.js.map +1 -0
  22. package/dist/actions/buildActionBlocks.js +12 -9
  23. package/dist/actions/buildActionBlocks.js.map +1 -1
  24. package/dist/actions/builtin/confirmation.js +47 -43
  25. package/dist/actions/builtin/confirmation.js.map +1 -1
  26. package/dist/actions/builtin/emailAction.d.ts +20 -0
  27. package/dist/actions/builtin/emailAction.js +120 -0
  28. package/dist/actions/builtin/emailAction.js.map +1 -0
  29. package/dist/actions/builtin/emailTeam.js +20 -38
  30. package/dist/actions/builtin/emailTeam.js.map +1 -1
  31. package/dist/actions/builtin/index.d.ts +16 -1
  32. package/dist/actions/builtin/index.js +21 -7
  33. package/dist/actions/builtin/index.js.map +1 -1
  34. package/dist/actions/builtin/signedWebhook.js +6 -2
  35. package/dist/actions/builtin/signedWebhook.js.map +1 -1
  36. package/dist/actions/defineAction.d.ts +17 -5
  37. package/dist/actions/defineAction.js.map +1 -1
  38. package/dist/actions/dispatch.js +51 -6
  39. package/dist/actions/dispatch.js.map +1 -1
  40. package/dist/actions/dispatchContext.js +13 -0
  41. package/dist/actions/dispatchContext.js.map +1 -0
  42. package/dist/actions/emailRecipients.d.ts +12 -0
  43. package/dist/actions/emailRecipients.js +146 -0
  44. package/dist/actions/emailRecipients.js.map +1 -0
  45. package/dist/actions/fromAddresses.d.ts +37 -0
  46. package/dist/actions/fromAddresses.js +131 -0
  47. package/dist/actions/fromAddresses.js.map +1 -0
  48. package/dist/actions/recipientSources.d.ts +34 -0
  49. package/dist/actions/recipientSources.js +11 -0
  50. package/dist/actions/recipientSources.js.map +1 -0
  51. package/dist/actions/registry.d.ts +2 -1
  52. package/dist/actions/registry.js +5 -7
  53. package/dist/actions/registry.js.map +1 -1
  54. package/dist/actions/runActions.js +10 -1
  55. package/dist/actions/runActions.js.map +1 -1
  56. package/dist/actions/task.js +47 -16
  57. package/dist/actions/task.js.map +1 -1
  58. package/dist/aggregation/aggregateResponses.d.ts +9 -0
  59. package/dist/aggregation/aggregateResponses.js +8 -14
  60. package/dist/aggregation/aggregateResponses.js.map +1 -1
  61. package/dist/aggregation/resolveResultsRequest.d.ts +41 -6
  62. package/dist/aggregation/resolveResultsRequest.js +97 -11
  63. package/dist/aggregation/resolveResultsRequest.js.map +1 -1
  64. package/dist/calc/computeCalcFields.d.ts +5 -3
  65. package/dist/calc/computeCalcFields.js +6 -4
  66. package/dist/calc/computeCalcFields.js.map +1 -1
  67. package/dist/calc/evaluate.d.ts +26 -3
  68. package/dist/calc/evaluate.js +34 -13
  69. package/dist/calc/evaluate.js.map +1 -1
  70. package/dist/calc/formatCalc.d.ts +11 -0
  71. package/dist/calc/formatCalc.js +35 -0
  72. package/dist/calc/formatCalc.js.map +1 -0
  73. package/dist/calc/formatCalcValue.d.ts +17 -0
  74. package/dist/calc/formatCalcValue.js +17 -0
  75. package/dist/calc/formatCalcValue.js.map +1 -0
  76. package/dist/calc/normalizeCalc.d.ts +17 -3
  77. package/dist/calc/normalizeCalc.js +42 -33
  78. package/dist/calc/normalizeCalc.js.map +1 -1
  79. package/dist/calc/registry.d.ts +43 -0
  80. package/dist/calc/registry.js +27 -0
  81. package/dist/calc/registry.js.map +1 -0
  82. package/dist/calc/resolveCalcContext.d.ts +36 -0
  83. package/dist/calc/resolveCalcContext.js +87 -0
  84. package/dist/calc/resolveCalcContext.js.map +1 -0
  85. package/dist/calc/types.d.ts +25 -4
  86. package/dist/calc/types.js +23 -0
  87. package/dist/calc/types.js.map +1 -0
  88. package/dist/client/ByteSizeField.d.ts +29 -0
  89. package/dist/client/ByteSizeField.js +58 -0
  90. package/dist/client/ByteSizeField.js.map +1 -0
  91. package/dist/client/CalcExpressionBuilder.d.ts +20 -0
  92. package/dist/client/CalcExpressionBuilder.js +890 -0
  93. package/dist/client/CalcExpressionBuilder.js.map +1 -0
  94. package/dist/client/ClosePollButton.d.ts +15 -0
  95. package/dist/client/ClosePollButton.js +80 -0
  96. package/dist/client/ClosePollButton.js.map +1 -0
  97. package/dist/client/CondensedArray.d.ts +15 -0
  98. package/dist/client/CondensedArray.js +97 -0
  99. package/dist/client/CondensedArray.js.map +1 -0
  100. package/dist/client/ConditionBuilder.js +2 -1
  101. package/dist/client/ConditionBuilder.js.map +1 -1
  102. package/dist/client/ConsentBlockLabel.d.ts +15 -0
  103. package/dist/client/ConsentBlockLabel.js +71 -0
  104. package/dist/client/ConsentBlockLabel.js.map +1 -0
  105. package/dist/client/ConsentSourceRowLabel.d.ts +9 -0
  106. package/dist/client/ConsentSourceRowLabel.js +21 -0
  107. package/dist/client/ConsentSourceRowLabel.js.map +1 -0
  108. package/dist/client/EndpointOptionsSelect.d.ts +55 -0
  109. package/dist/client/EndpointOptionsSelect.js +112 -0
  110. package/dist/client/EndpointOptionsSelect.js.map +1 -0
  111. package/dist/client/FieldBlockLabel.d.ts +18 -0
  112. package/dist/client/FieldBlockLabel.js +34 -0
  113. package/dist/client/FieldBlockLabel.js.map +1 -0
  114. package/dist/client/FieldNameSelect.d.ts +37 -0
  115. package/dist/client/FieldNameSelect.js +72 -0
  116. package/dist/client/FieldNameSelect.js.map +1 -0
  117. package/dist/client/FlowBuilder.d.ts +2 -2
  118. package/dist/client/FlowBuilder.js +137 -88
  119. package/dist/client/FlowBuilder.js.map +1 -1
  120. package/dist/client/FormConditionField.js +1 -4
  121. package/dist/client/FormConditionField.js.map +1 -1
  122. package/dist/client/RecipientsSelect.d.ts +37 -0
  123. package/dist/client/RecipientsSelect.js +197 -0
  124. package/dist/client/RecipientsSelect.js.map +1 -0
  125. package/dist/client/RuleDescription.d.ts +21 -0
  126. package/dist/client/RuleDescription.js +19 -0
  127. package/dist/client/RuleDescription.js.map +1 -0
  128. package/dist/client/admin.css +557 -0
  129. package/dist/client/endpointOptions.d.ts +11 -0
  130. package/dist/client/endpointOptions.js +38 -0
  131. package/dist/client/endpointOptions.js.map +1 -0
  132. package/dist/client/flowAuthoring.js +142 -0
  133. package/dist/client/flowAuthoring.js.map +1 -0
  134. package/dist/client/synthesizeClientField.js +21 -10
  135. package/dist/client/synthesizeClientField.js.map +1 -1
  136. package/dist/client/toStaticLabel.js +13 -0
  137. package/dist/client/toStaticLabel.js.map +1 -0
  138. package/dist/collections/buttonFields.d.ts +34 -0
  139. package/dist/collections/buttonFields.js +35 -0
  140. package/dist/collections/buttonFields.js.map +1 -0
  141. package/dist/collections/cells/FieldCountCell.d.ts +15 -0
  142. package/dist/collections/cells/FieldCountCell.js +18 -0
  143. package/dist/collections/cells/FieldCountCell.js.map +1 -0
  144. package/dist/collections/cells/FlowStepsCell.d.ts +14 -0
  145. package/dist/collections/cells/FlowStepsCell.js +17 -0
  146. package/dist/collections/cells/FlowStepsCell.js.map +1 -0
  147. package/dist/collections/formSubmissions.js +114 -28
  148. package/dist/collections/formSubmissions.js.map +1 -1
  149. package/dist/collections/forms.js +449 -112
  150. package/dist/collections/forms.js.map +1 -1
  151. package/dist/collections/formsEndpoints.js +106 -0
  152. package/dist/collections/formsEndpoints.js.map +1 -0
  153. package/dist/collections/redirectFields.d.ts +29 -0
  154. package/dist/collections/settingsFields.d.ts +31 -0
  155. package/dist/collections/settingsFields.js +45 -0
  156. package/dist/collections/settingsFields.js.map +1 -0
  157. package/dist/conditions/conditionType.js +9 -2
  158. package/dist/conditions/conditionType.js.map +1 -1
  159. package/dist/conditions/evaluate.js +1 -1
  160. package/dist/conditions/evaluate.js.map +1 -1
  161. package/dist/conditions/fieldTypes.d.ts +3 -1
  162. package/dist/conditions/fieldTypes.js +4 -1
  163. package/dist/conditions/fieldTypes.js.map +1 -1
  164. package/dist/conditions/normalizeConditions.js +20 -6
  165. package/dist/conditions/normalizeConditions.js.map +1 -1
  166. package/dist/consent/applyConsentStatements.d.ts +14 -0
  167. package/dist/consent/applyConsentStatements.js +17 -0
  168. package/dist/consent/applyConsentStatements.js.map +1 -0
  169. package/dist/consent/captureConsent.d.ts +39 -11
  170. package/dist/consent/captureConsent.js +63 -13
  171. package/dist/consent/captureConsent.js.map +1 -1
  172. package/dist/consent/consentSourcesField.d.ts +66 -0
  173. package/dist/consent/consentSourcesField.js +98 -0
  174. package/dist/consent/consentSourcesField.js.map +1 -0
  175. package/dist/consent/effectiveStatement.js +16 -0
  176. package/dist/consent/effectiveStatement.js.map +1 -0
  177. package/dist/consent/resolveConsentEntries.d.ts +24 -0
  178. package/dist/consent/resolveConsentEntries.js +40 -0
  179. package/dist/consent/resolveConsentEntries.js.map +1 -0
  180. package/dist/consent/resolveConsentSourcesRequest.d.ts +37 -0
  181. package/dist/consent/resolveConsentSourcesRequest.js +54 -0
  182. package/dist/consent/resolveConsentSourcesRequest.js.map +1 -0
  183. package/dist/consent/resolveConsentStatements.d.ts +45 -0
  184. package/dist/consent/resolveConsentStatements.js +46 -0
  185. package/dist/consent/resolveConsentStatements.js.map +1 -0
  186. package/dist/consent/resolvePublishedVersionRef.d.ts +17 -11
  187. package/dist/consent/resolvePublishedVersionRef.js +13 -10
  188. package/dist/consent/resolvePublishedVersionRef.js.map +1 -1
  189. package/dist/consent/types.d.ts +69 -0
  190. package/dist/context/formContext.d.ts +30 -0
  191. package/dist/context/formContext.js +54 -0
  192. package/dist/context/formContext.js.map +1 -0
  193. package/dist/email/departments.d.ts +59 -0
  194. package/dist/email/departments.js +87 -0
  195. package/dist/email/departments.js.map +1 -0
  196. package/dist/email/departmentsField.d.ts +53 -0
  197. package/dist/email/departmentsField.js +73 -0
  198. package/dist/email/departmentsField.js.map +1 -0
  199. package/dist/exports/client.d.ts +14 -1
  200. package/dist/exports/client.js +14 -1
  201. package/dist/exports/i18n.d.ts +5 -2
  202. package/dist/exports/i18n.js +5 -2
  203. package/dist/exports/react.d.ts +34 -10
  204. package/dist/exports/react.js +24 -4
  205. package/dist/exports/rsc.d.ts +10 -1
  206. package/dist/exports/rsc.js +10 -1
  207. package/dist/exports/types.d.ts +20 -12
  208. package/dist/fields/buildFieldBlocks.js +46 -25
  209. package/dist/fields/buildFieldBlocks.js.map +1 -1
  210. package/dist/fields/builtin/calculation.d.ts +17 -0
  211. package/dist/fields/builtin/calculation.js +193 -18
  212. package/dist/fields/builtin/calculation.js.map +1 -1
  213. package/dist/fields/builtin/checkbox.js +23 -0
  214. package/dist/fields/builtin/checkbox.js.map +1 -1
  215. package/dist/fields/builtin/consent.js +49 -14
  216. package/dist/fields/builtin/consent.js.map +1 -1
  217. package/dist/fields/builtin/country.d.ts +13 -0
  218. package/dist/fields/builtin/country.js +30 -0
  219. package/dist/fields/builtin/country.js.map +1 -0
  220. package/dist/fields/builtin/date.js +31 -0
  221. package/dist/fields/builtin/date.js.map +1 -0
  222. package/dist/fields/builtin/email.js +8 -1
  223. package/dist/fields/builtin/email.js.map +1 -1
  224. package/dist/fields/builtin/file.d.ts +15 -0
  225. package/dist/fields/builtin/file.js +95 -8
  226. package/dist/fields/builtin/file.js.map +1 -1
  227. package/dist/fields/builtin/index.d.ts +30 -0
  228. package/dist/fields/builtin/index.js +37 -10
  229. package/dist/fields/builtin/index.js.map +1 -1
  230. package/dist/fields/builtin/message.js +30 -0
  231. package/dist/fields/builtin/message.js.map +1 -0
  232. package/dist/fields/builtin/repeater.js +8 -3
  233. package/dist/fields/builtin/repeater.js.map +1 -1
  234. package/dist/fields/builtin/select.js +28 -4
  235. package/dist/fields/builtin/select.js.map +1 -1
  236. package/dist/fields/builtin/state.d.ts +13 -0
  237. package/dist/fields/builtin/state.js +30 -0
  238. package/dist/fields/builtin/state.js.map +1 -0
  239. package/dist/fields/builtin/text.js +7 -0
  240. package/dist/fields/builtin/text.js.map +1 -1
  241. package/dist/fields/data/regions.d.ts +21 -0
  242. package/dist/fields/data/regions.js +1238 -0
  243. package/dist/fields/data/regions.js.map +1 -0
  244. package/dist/fields/fieldKey.d.ts +15 -0
  245. package/dist/fields/fieldKey.js +16 -0
  246. package/dist/fields/fieldKey.js.map +1 -0
  247. package/dist/fields/fieldNamesOfType.js +30 -0
  248. package/dist/fields/fieldNamesOfType.js.map +1 -0
  249. package/dist/fields/instanceOptions.js +20 -0
  250. package/dist/fields/instanceOptions.js.map +1 -0
  251. package/dist/fields/localizedIf.d.ts +13 -0
  252. package/dist/fields/localizedIf.js +12 -0
  253. package/dist/fields/localizedIf.js.map +1 -0
  254. package/dist/fields/registry.d.ts +3 -1
  255. package/dist/fields/registry.js +23 -8
  256. package/dist/fields/registry.js.map +1 -1
  257. package/dist/fields/sharedConfig.js +125 -59
  258. package/dist/fields/sharedConfig.js.map +1 -1
  259. package/dist/fields/types.d.ts +78 -9
  260. package/dist/flow/engine.d.ts +6 -4
  261. package/dist/flow/engine.js +11 -6
  262. package/dist/flow/engine.js.map +1 -1
  263. package/dist/flow/normalizeFlow.js +28 -9
  264. package/dist/flow/normalizeFlow.js.map +1 -1
  265. package/dist/flow/stepLabel.js +15 -0
  266. package/dist/flow/stepLabel.js.map +1 -0
  267. package/dist/flow/types.d.ts +12 -3
  268. package/dist/flow/types.js +11 -0
  269. package/dist/flow/types.js.map +1 -0
  270. package/dist/form/pollState.d.ts +23 -0
  271. package/dist/form/pollState.js +17 -0
  272. package/dist/form/pollState.js.map +1 -0
  273. package/dist/form/toFormDocument.d.ts +110 -0
  274. package/dist/form/toFormDocument.js +89 -0
  275. package/dist/form/toFormDocument.js.map +1 -0
  276. package/dist/form/types.d.ts +73 -0
  277. package/dist/index.d.ts +67 -61
  278. package/dist/index.js +120 -25
  279. package/dist/index.js.map +1 -1
  280. package/dist/options.d.ts +281 -0
  281. package/dist/plugin/applyRegistryConfig.d.ts +11 -0
  282. package/dist/plugin/applyRegistryConfig.js +20 -0
  283. package/dist/plugin/applyRegistryConfig.js.map +1 -0
  284. package/dist/plugin/customState.js +26 -0
  285. package/dist/plugin/customState.js.map +1 -0
  286. package/dist/plugin/registerCollections.js +43 -40
  287. package/dist/plugin/registerCollections.js.map +1 -1
  288. package/dist/plugin/uploadsCollection.d.ts +16 -0
  289. package/dist/plugin/uploadsCollection.js +53 -0
  290. package/dist/plugin/uploadsCollection.js.map +1 -0
  291. package/dist/poll/applyPollOptions.js +18 -0
  292. package/dist/poll/applyPollOptions.js.map +1 -0
  293. package/dist/poll/buildPollOptionSourceFields.js +50 -0
  294. package/dist/poll/buildPollOptionSourceFields.js.map +1 -0
  295. package/dist/poll/closeJob.d.ts +53 -0
  296. package/dist/poll/closeJob.js +121 -0
  297. package/dist/poll/closeJob.js.map +1 -0
  298. package/dist/poll/definePollOptionSource.d.ts +44 -0
  299. package/dist/poll/definePollOptionSource.js +6 -0
  300. package/dist/poll/definePollOptionSource.js.map +1 -0
  301. package/dist/poll/definePollType.d.ts +34 -0
  302. package/dist/poll/definePollType.js +6 -0
  303. package/dist/poll/definePollType.js.map +1 -0
  304. package/dist/poll/effectivePollOptions.d.ts +38 -0
  305. package/dist/poll/effectivePollOptions.js +64 -0
  306. package/dist/poll/effectivePollOptions.js.map +1 -0
  307. package/dist/poll/mostVoted.d.ts +21 -0
  308. package/dist/poll/mostVoted.js +32 -0
  309. package/dist/poll/mostVoted.js.map +1 -0
  310. package/dist/poll/outcomeBeforeChange.js +91 -0
  311. package/dist/poll/outcomeBeforeChange.js.map +1 -0
  312. package/dist/poll/outcomeFields.d.ts +38 -0
  313. package/dist/poll/outcomeFields.js +52 -0
  314. package/dist/poll/outcomeFields.js.map +1 -0
  315. package/dist/poll/pollTypeRegistry.d.ts +34 -0
  316. package/dist/poll/pollTypeRegistry.js +69 -0
  317. package/dist/poll/pollTypeRegistry.js.map +1 -0
  318. package/dist/poll/registry.d.ts +17 -0
  319. package/dist/poll/registry.js +12 -0
  320. package/dist/poll/registry.js.map +1 -0
  321. package/dist/poll/resolvePollCloseRequest.js +106 -0
  322. package/dist/poll/resolvePollCloseRequest.js.map +1 -0
  323. package/dist/poll/resolvePollOptions.d.ts +29 -0
  324. package/dist/poll/resolvePollOptions.js +52 -0
  325. package/dist/poll/resolvePollOptions.js.map +1 -0
  326. package/dist/poll/resolvePollOptionsRequest.js +50 -0
  327. package/dist/poll/resolvePollOptionsRequest.js.map +1 -0
  328. package/dist/poll/resolvePollOutcome.d.ts +40 -0
  329. package/dist/poll/resolvePollOutcome.js +90 -0
  330. package/dist/poll/resolvePollOutcome.js.map +1 -0
  331. package/dist/poll/resultsField.js +21 -0
  332. package/dist/poll/resultsField.js.map +1 -0
  333. package/dist/poll/votes/aggregateFromVotes.d.ts +27 -0
  334. package/dist/poll/votes/aggregateFromVotes.js +54 -0
  335. package/dist/poll/votes/aggregateFromVotes.js.map +1 -0
  336. package/dist/poll/votes/answerValues.js +16 -0
  337. package/dist/poll/votes/answerValues.js.map +1 -0
  338. package/dist/poll/votes/bumpPollVote.js +88 -0
  339. package/dist/poll/votes/bumpPollVote.js.map +1 -0
  340. package/dist/poll/votes/recountPollVotes.d.ts +20 -0
  341. package/dist/poll/votes/recountPollVotes.js +63 -0
  342. package/dist/poll/votes/recountPollVotes.js.map +1 -0
  343. package/dist/poll/votes/voteTallyHook.js +76 -0
  344. package/dist/poll/votes/voteTallyHook.js.map +1 -0
  345. package/dist/poll/votes/votesCollection.d.ts +19 -0
  346. package/dist/poll/votes/votesCollection.js +89 -0
  347. package/dist/poll/votes/votesCollection.js.map +1 -0
  348. package/dist/prefill/valuesFromSearchParams.js +5 -9
  349. package/dist/prefill/valuesFromSearchParams.js.map +1 -1
  350. package/dist/presentations/types.d.ts +3 -2
  351. package/dist/react/Form.d.ts +77 -35
  352. package/dist/react/Form.js +368 -222
  353. package/dist/react/Form.js.map +1 -1
  354. package/dist/react/FormContext.d.ts +51 -1
  355. package/dist/react/FormContext.js.map +1 -1
  356. package/dist/react/FormControls.d.ts +55 -0
  357. package/dist/react/FormControls.js +56 -0
  358. package/dist/react/FormControls.js.map +1 -0
  359. package/dist/react/FormFields.d.ts +18 -0
  360. package/dist/react/FormFields.js +114 -0
  361. package/dist/react/FormFields.js.map +1 -0
  362. package/dist/react/FormLayout.d.ts +4 -2
  363. package/dist/react/FormLayout.js +3 -2
  364. package/dist/react/FormLayout.js.map +1 -1
  365. package/dist/react/FormResults.d.ts +8 -3
  366. package/dist/react/FormResults.js +50 -29
  367. package/dist/react/FormResults.js.map +1 -1
  368. package/dist/react/FormSteps.d.ts +17 -0
  369. package/dist/react/FormSteps.js +35 -0
  370. package/dist/react/FormSteps.js.map +1 -0
  371. package/dist/react/Poll.d.ts +40 -6
  372. package/dist/react/Poll.js +137 -33
  373. package/dist/react/Poll.js.map +1 -1
  374. package/dist/react/adapters.d.ts +35 -0
  375. package/dist/react/adapters.js +11 -0
  376. package/dist/react/adapters.js.map +1 -0
  377. package/dist/react/captcha/HcaptchaCaptcha.d.ts +31 -0
  378. package/dist/react/captcha/HcaptchaCaptcha.js +53 -0
  379. package/dist/react/captcha/HcaptchaCaptcha.js.map +1 -0
  380. package/dist/react/captcha/RecaptchaCaptcha.d.ts +44 -0
  381. package/dist/react/captcha/RecaptchaCaptcha.js +93 -0
  382. package/dist/react/captcha/RecaptchaCaptcha.js.map +1 -0
  383. package/dist/react/captcha/TurnstileCaptcha.d.ts +31 -0
  384. package/dist/react/captcha/TurnstileCaptcha.js +53 -0
  385. package/dist/react/captcha/TurnstileCaptcha.js.map +1 -0
  386. package/dist/react/captcha/types.d.ts +8 -0
  387. package/dist/react/captcha/useCaptchaScript.js +63 -0
  388. package/dist/react/captcha/useCaptchaScript.js.map +1 -0
  389. package/dist/react/captcha/vendors.js +8 -0
  390. package/dist/react/captcha/vendors.js.map +1 -0
  391. package/dist/react/contract.d.ts +2 -3
  392. package/dist/react/contract.js.map +1 -1
  393. package/dist/react/fetchResults.d.ts +1 -1
  394. package/dist/react/fetchResults.js +1 -1
  395. package/dist/react/fetchResults.js.map +1 -1
  396. package/dist/react/presentation/DialogSurface.js +1 -4
  397. package/dist/react/presentation/DialogSurface.js.map +1 -1
  398. package/dist/react/primitives/Checkbox.d.ts +6 -2
  399. package/dist/react/primitives/Checkbox.js +4 -2
  400. package/dist/react/primitives/Checkbox.js.map +1 -1
  401. package/dist/react/primitives/ChoiceGroup.d.ts +40 -0
  402. package/dist/react/primitives/ChoiceGroup.js +33 -0
  403. package/dist/react/primitives/ChoiceGroup.js.map +1 -0
  404. package/dist/react/primitives/FieldShell.d.ts +13 -5
  405. package/dist/react/primitives/FieldShell.js +35 -32
  406. package/dist/react/primitives/FieldShell.js.map +1 -1
  407. package/dist/react/primitives/Input.d.ts +4 -2
  408. package/dist/react/primitives/Input.js +2 -1
  409. package/dist/react/primitives/Input.js.map +1 -1
  410. package/dist/react/renderers/calculation.js +7 -5
  411. package/dist/react/renderers/calculation.js.map +1 -1
  412. package/dist/react/renderers/checkbox.js +3 -5
  413. package/dist/react/renderers/checkbox.js.map +1 -1
  414. package/dist/react/renderers/consent.js +84 -36
  415. package/dist/react/renderers/consent.js.map +1 -1
  416. package/dist/react/renderers/date.js +33 -0
  417. package/dist/react/renderers/date.js.map +1 -0
  418. package/dist/react/renderers/email.js +4 -5
  419. package/dist/react/renderers/email.js.map +1 -1
  420. package/dist/react/renderers/file.js +29 -14
  421. package/dist/react/renderers/file.js.map +1 -1
  422. package/dist/react/renderers/index.js +7 -0
  423. package/dist/react/renderers/index.js.map +1 -1
  424. package/dist/react/renderers/message.js +41 -0
  425. package/dist/react/renderers/message.js.map +1 -0
  426. package/dist/react/renderers/number.js +1 -4
  427. package/dist/react/renderers/number.js.map +1 -1
  428. package/dist/react/renderers/region.js +43 -0
  429. package/dist/react/renderers/region.js.map +1 -0
  430. package/dist/react/renderers/repeater.js +32 -14
  431. package/dist/react/renderers/repeater.js.map +1 -1
  432. package/dist/react/renderers/select.js +21 -6
  433. package/dist/react/renderers/select.js.map +1 -1
  434. package/dist/react/renderers/text.js +4 -5
  435. package/dist/react/renderers/text.js.map +1 -1
  436. package/dist/react/renderers/textarea.js +1 -4
  437. package/dist/react/renderers/textarea.js.map +1 -1
  438. package/dist/react/state.d.ts +46 -3
  439. package/dist/react/state.js +73 -10
  440. package/dist/react/state.js.map +1 -1
  441. package/dist/react/submitForm.js +1 -1
  442. package/dist/react/submitForm.js.map +1 -1
  443. package/dist/react/uploadFile.d.ts +2 -2
  444. package/dist/react/uploadFile.js +1 -1
  445. package/dist/react/uploadFile.js.map +1 -1
  446. package/dist/react/useCalcValues.d.ts +10 -0
  447. package/dist/react/useCalcValues.js +13 -0
  448. package/dist/react/useCalcValues.js.map +1 -0
  449. package/dist/react/useField.d.ts +0 -1
  450. package/dist/react/useField.js +7 -6
  451. package/dist/react/useField.js.map +1 -1
  452. package/dist/react/useFormState.d.ts +1 -1
  453. package/dist/react/useFormState.js +1 -1
  454. package/dist/react/useFormState.js.map +1 -1
  455. package/dist/react/validateField.js +3 -6
  456. package/dist/react/validateField.js.map +1 -1
  457. package/dist/recall/interpolate.d.ts +4 -3
  458. package/dist/recall/interpolate.js +5 -4
  459. package/dist/recall/interpolate.js.map +1 -1
  460. package/dist/recall/resolver.d.ts +1 -1
  461. package/dist/recall/resolver.js +15 -3
  462. package/dist/recall/resolver.js.map +1 -1
  463. package/dist/spam/captcha.d.ts +4 -3
  464. package/dist/spam/captcha.js +4 -3
  465. package/dist/spam/captcha.js.map +1 -1
  466. package/dist/spam/clientIp.js +9 -0
  467. package/dist/spam/clientIp.js.map +1 -0
  468. package/dist/spam/constants.js +13 -1
  469. package/dist/spam/constants.js.map +1 -1
  470. package/dist/spam/identify.js +3 -6
  471. package/dist/spam/identify.js.map +1 -1
  472. package/dist/spam/providers/hcaptcha.d.ts +17 -0
  473. package/dist/spam/providers/hcaptcha.js +18 -0
  474. package/dist/spam/providers/hcaptcha.js.map +1 -0
  475. package/dist/spam/providers/recaptcha.d.ts +23 -0
  476. package/dist/spam/providers/recaptcha.js +23 -0
  477. package/dist/spam/providers/recaptcha.js.map +1 -0
  478. package/dist/spam/providers/siteverify.js +34 -0
  479. package/dist/spam/providers/siteverify.js.map +1 -0
  480. package/dist/spam/providers/turnstile.d.ts +17 -0
  481. package/dist/spam/providers/turnstile.js +18 -0
  482. package/dist/spam/providers/turnstile.js.map +1 -0
  483. package/dist/spam/resolveSpam.js +2 -1
  484. package/dist/spam/resolveSpam.js.map +1 -1
  485. package/dist/spam/spamGuard.js +25 -11
  486. package/dist/spam/spamGuard.js.map +1 -1
  487. package/dist/spam/types.d.ts +19 -4
  488. package/dist/submissions/SubmissionAnswers.js +6 -2
  489. package/dist/submissions/SubmissionAnswers.js.map +1 -1
  490. package/dist/submissions/SubmissionAnswersClient.js +100 -64
  491. package/dist/submissions/SubmissionAnswersClient.js.map +1 -1
  492. package/dist/submissions/coerceBoolean.js +14 -0
  493. package/dist/submissions/coerceBoolean.js.map +1 -0
  494. package/dist/submissions/createSubmission.d.ts +36 -0
  495. package/dist/submissions/createSubmission.js +26 -0
  496. package/dist/submissions/createSubmission.js.map +1 -0
  497. package/dist/submissions/formIdOf.js +13 -0
  498. package/dist/submissions/formIdOf.js.map +1 -0
  499. package/dist/submissions/resolveVotedSubmission.d.ts +27 -0
  500. package/dist/submissions/resolveVotedSubmission.js +51 -0
  501. package/dist/submissions/resolveVotedSubmission.js.map +1 -0
  502. package/dist/submissions/runSubmission.d.ts +10 -0
  503. package/dist/submissions/runSubmission.js +104 -54
  504. package/dist/submissions/runSubmission.js.map +1 -1
  505. package/dist/submissions/types.d.ts +11 -4
  506. package/dist/submissions/validateSubmission.js +99 -13
  507. package/dist/submissions/validateSubmission.js.map +1 -1
  508. package/dist/submissions/verifyContext.js +35 -0
  509. package/dist/submissions/verifyContext.js.map +1 -0
  510. package/dist/submissions/voteChangeEndpoint.js +105 -0
  511. package/dist/submissions/voteChangeEndpoint.js.map +1 -0
  512. package/dist/submissions/votedCookie.d.ts +15 -0
  513. package/dist/submissions/votedCookie.js +74 -0
  514. package/dist/submissions/votedCookie.js.map +1 -0
  515. package/dist/translations/clientRuntimeKeys.d.ts +17 -0
  516. package/dist/translations/clientRuntimeKeys.js +48 -0
  517. package/dist/translations/clientRuntimeKeys.js.map +1 -0
  518. package/dist/translations/de.d.ts +12 -0
  519. package/dist/translations/de.js +380 -0
  520. package/dist/translations/de.js.map +1 -0
  521. package/dist/translations/en.js +250 -28
  522. package/dist/translations/en.js.map +1 -1
  523. package/dist/translations/index.d.ts +14 -5
  524. package/dist/translations/index.js +14 -3
  525. package/dist/translations/index.js.map +1 -1
  526. package/dist/translations/keys.d.ts +245 -23
  527. package/dist/translations/keys.js +246 -24
  528. package/dist/translations/keys.js.map +1 -1
  529. package/dist/translations/makeTranslate.d.ts +7 -3
  530. package/dist/translations/makeTranslate.js +12 -3
  531. package/dist/translations/makeTranslate.js.map +1 -1
  532. package/dist/translations/server.js +8 -1
  533. package/dist/translations/server.js.map +1 -1
  534. package/dist/uploads/captureFileRef.d.ts +10 -3
  535. package/dist/uploads/captureFileRef.js +18 -9
  536. package/dist/uploads/captureFileRef.js.map +1 -1
  537. package/dist/uploads/formatBytes.d.ts +9 -0
  538. package/dist/uploads/formatBytes.js +25 -0
  539. package/dist/uploads/formatBytes.js.map +1 -0
  540. package/dist/uploads/resolveFileRef.js +3 -2
  541. package/dist/uploads/resolveFileRef.js.map +1 -1
  542. package/dist/uploads/types.d.ts +1 -2
  543. package/dist/validation/buildRuleBlocks.js +18 -17
  544. package/dist/validation/buildRuleBlocks.js.map +1 -1
  545. package/dist/validation/builtin/email.js +2 -1
  546. package/dist/validation/builtin/email.js.map +1 -1
  547. package/dist/validation/builtin/index.d.ts +14 -0
  548. package/dist/validation/builtin/index.js +14 -1
  549. package/dist/validation/builtin/index.js.map +1 -1
  550. package/dist/validation/builtin/integer.js +15 -0
  551. package/dist/validation/builtin/integer.js.map +1 -0
  552. package/dist/validation/builtin/matchesField.js +3 -7
  553. package/dist/validation/builtin/matchesField.js.map +1 -1
  554. package/dist/validation/builtin/max.js +1 -0
  555. package/dist/validation/builtin/max.js.map +1 -1
  556. package/dist/validation/builtin/maxDate.js +24 -0
  557. package/dist/validation/builtin/maxDate.js.map +1 -0
  558. package/dist/validation/builtin/maxLength.js +1 -0
  559. package/dist/validation/builtin/maxLength.js.map +1 -1
  560. package/dist/validation/builtin/min.js +1 -0
  561. package/dist/validation/builtin/min.js.map +1 -1
  562. package/dist/validation/builtin/minDate.js +24 -0
  563. package/dist/validation/builtin/minDate.js.map +1 -0
  564. package/dist/validation/builtin/minLength.js +1 -0
  565. package/dist/validation/builtin/minLength.js.map +1 -1
  566. package/dist/validation/builtin/notAlreadySubmitted.js +5 -1
  567. package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -1
  568. package/dist/validation/builtin/oneOf.js +1 -0
  569. package/dist/validation/builtin/oneOf.js.map +1 -1
  570. package/dist/validation/builtin/pattern.js +11 -2
  571. package/dist/validation/builtin/pattern.js.map +1 -1
  572. package/dist/validation/builtin/url.js +1 -0
  573. package/dist/validation/builtin/url.js.map +1 -1
  574. package/dist/validation/builtin/validateDateBound.js +18 -0
  575. package/dist/validation/builtin/validateDateBound.js.map +1 -0
  576. package/dist/validation/builtin/validateRegexParams.js +44 -0
  577. package/dist/validation/builtin/validateRegexParams.js.map +1 -0
  578. package/dist/validation/emailPattern.js +10 -0
  579. package/dist/validation/emailPattern.js.map +1 -0
  580. package/dist/validation/fieldTargetParam.d.ts +22 -0
  581. package/dist/validation/fieldTargetParam.js +38 -0
  582. package/dist/validation/fieldTargetParam.js.map +1 -0
  583. package/dist/validation/registry.d.ts +2 -1
  584. package/dist/validation/registry.js +2 -9
  585. package/dist/validation/registry.js.map +1 -1
  586. package/dist/validation/runValidation.js +8 -29
  587. package/dist/validation/runValidation.js.map +1 -1
  588. package/dist/validation/types.d.ts +5 -11
  589. package/dist/validation/validateUrl.js +22 -0
  590. package/dist/validation/validateUrl.js.map +1 -0
  591. package/package.json +14 -6
  592. package/styles/form-builder.css +94 -190
  593. package/dist/collections/uploads.d.ts +0 -30
  594. package/dist/collections/uploads.js +0 -55
  595. package/dist/collections/uploads.js.map +0 -1
  596. package/dist/consent/buildConsentSourceConfig.js +0 -49
  597. package/dist/consent/buildConsentSourceConfig.js.map +0 -1
  598. package/dist/consent/builtin/index.d.ts +0 -7
  599. package/dist/consent/builtin/index.js +0 -11
  600. package/dist/consent/builtin/index.js.map +0 -1
  601. package/dist/consent/builtin/pageReference.js +0 -75
  602. package/dist/consent/builtin/pageReference.js.map +0 -1
  603. package/dist/consent/builtin/static.js +0 -44
  604. package/dist/consent/builtin/static.js.map +0 -1
  605. package/dist/consent/defineConsentSource.d.ts +0 -35
  606. package/dist/consent/defineConsentSource.js +0 -6
  607. package/dist/consent/defineConsentSource.js.map +0 -1
  608. package/dist/consent/registry.d.ts +0 -16
  609. package/dist/consent/registry.js +0 -16
  610. package/dist/consent/registry.js.map +0 -1
  611. package/dist/consent/resolveConsentLinks.d.ts +0 -19
  612. package/dist/consent/resolveConsentLinks.js +0 -26
  613. package/dist/consent/resolveConsentLinks.js.map +0 -1
  614. package/dist/presentations/registry.d.ts +0 -15
  615. package/dist/presentations/registry.js +0 -15
  616. package/dist/presentations/registry.js.map +0 -1
  617. package/dist/react/toFormDocument.d.ts +0 -24
  618. package/dist/react/toFormDocument.js +0 -22
  619. package/dist/react/toFormDocument.js.map +0 -1
@@ -1,11 +1,17 @@
1
- import { FileRef } from "../uploads/types.js";
2
1
  import { ConditionFieldType } from "../conditions/fieldTypes.js";
3
- import { Field } from "payload";
2
+ import { PollOption } from "../poll/definePollOptionSource.js";
3
+ import { FormFieldInstance } from "../submissions/types.js";
4
+ import { FileRef } from "../uploads/types.js";
5
+ import { Field, Payload, PayloadRequest } from "payload";
4
6
  import { StandardSchemaV1 } from "@standard-schema/spec";
5
7
 
6
8
  //#region src/fields/types.d.ts
7
- /** The stored value shapes a field type can declare. Drives `validate`/`format` typing and value coercion. */
8
- type FormFieldValueKind = 'text' | 'number' | 'boolean' | 'date' | 'text[]' | 'file' | 'repeater';
9
+ /**
10
+ * The stored value shapes a field type can declare. Drives `validate`/`format` typing and value
11
+ * coercion. `'none'` marks a display-only type (e.g. `message`): the engine never seeds, validates,
12
+ * or stores a value for it, and a client-sent value under its name is dropped.
13
+ */
14
+ type FormFieldValueKind = 'text' | 'number' | 'boolean' | 'date' | 'text[]' | 'file' | 'repeater' | 'none';
9
15
  type ValueKindTypeMap = {
10
16
  text: string;
11
17
  number: number;
@@ -14,10 +20,17 @@ type ValueKindTypeMap = {
14
20
  'text[]': string[];
15
21
  file: FileRef;
16
22
  repeater: Array<Record<string, unknown>>;
23
+ none: never;
17
24
  };
18
25
  type ValueOfKind<K extends FormFieldValueKind> = ValueKindTypeMap[K];
19
26
  /** Resolved per-instance config values for a field type (loose at the DB boundary, narrowed by the author's generic). */
20
27
  type FormFieldConfigValues = Record<string, unknown>;
28
+ /**
29
+ * The shared config fields a type may drop via {@link FormFieldDefinition.omitShared}. `name` is
30
+ * deliberately absent and can never be dropped: it is the storage key every read and write path
31
+ * gates on (see `isNamedField`), so a named field without it would silently store nothing.
32
+ */
33
+ type OmittableSharedField = 'label' | 'placeholder' | 'description' | 'width' | 'required';
21
34
  /** A `t`-like resolver. The engine supplies one from the request i18n; the renderer will supply the client i18n. */
22
35
  type Translate = (key: string) => string;
23
36
  type FormFieldValidateArgs<K extends FormFieldValueKind, TConfig extends FormFieldConfigValues> = {
@@ -37,6 +50,16 @@ type FormFieldFormatArgs<K extends FormFieldValueKind, TConfig extends FormField
37
50
  t: Translate;
38
51
  };
39
52
  type FormFieldFormat<K extends FormFieldValueKind, TConfig extends FormFieldConfigValues> = (args: FormFieldFormatArgs<K, TConfig>) => string;
53
+ /** Arguments a {@link FormFieldDefinition.resolveOptions} implementation receives. */
54
+ type ResolveFieldOptionsArgs = {
55
+ /** The configured field instance, so the resolver can read the values the author selected. */instance: FormFieldInstance;
56
+ form: {
57
+ id: number | string;
58
+ title?: string;
59
+ };
60
+ payload: Payload;
61
+ req?: PayloadRequest;
62
+ };
40
63
  /**
41
64
  * A field type, authored once. `value` drives typed `validate`/`format`; `config` is a Payload
42
65
  * `Field[]` for the add-field drawer; `Field` is the client renderer import-map ref;
@@ -47,13 +70,53 @@ type FormFieldDefinition<K extends FormFieldValueKind = FormFieldValueKind, TCon
47
70
  label: string;
48
71
  value: K;
49
72
  config?: Field[];
73
+ /**
74
+ * Extra per-type fields for the Advanced tab, after `visibleWhen`/`hidden`. Lets a type add
75
+ * behavior settings (e.g. `autocomplete`) without crowding the Field tab.
76
+ */
77
+ advancedConfig?: Field[];
50
78
  validate?: FormFieldValidate<K, TConfig>;
51
79
  format?: FormFieldFormat<K, TConfig>;
52
- Field?: string; /** Optional Standard Schema validator (Zod/Valibot/etc.), run by the engine after the intrinsic validator. */
80
+ Field?: string;
81
+ /**
82
+ * Import-map ref for a custom block row Label, replacing the default `FieldBlockLabel` for this
83
+ * type's add-field block. Receives the same `{ typeLabelKey }` clientProps. The `consent` type
84
+ * uses this to resolve and show the referenced source's name.
85
+ */
86
+ blockLabel?: string; /** Optional Standard Schema validator (Zod/Valibot/etc.), run by the engine after the intrinsic validator. */
53
87
  schema?: StandardSchemaV1;
54
88
  icon?: string;
55
89
  group?: string; /** How this field appears in the condition builder. Defaults from `value` (see `defaultConditionType`). */
56
90
  conditionType?: ConditionFieldType;
91
+ /**
92
+ * Bare definitions render without the shared chrome: no name/label/width/required/placeholder/
93
+ * description and no validation tabs; the definition's `config` IS the entire block. Instances
94
+ * are nameless (identified by Payload's hidden block row `id`, see `fieldKey`), so bare types
95
+ * must be display-only (`value: 'none'`): with no name there is nothing to validate or store.
96
+ */
97
+ bare?: boolean;
98
+ /**
99
+ * Shared config fields this type never uses, so authors are not offered a setting the renderer
100
+ * ignores (e.g. a placeholder on a checkbox). Unlike `bare`, which drops the shared chrome
101
+ * wholesale, this keeps the rest of it. An emptied layout row collapses and a lone survivor
102
+ * spans the row (see `sharedFieldConfig`).
103
+ */
104
+ omitShared?: OmittableSharedField[];
105
+ /**
106
+ * The type can be chosen as a poll's results field. Its instances must produce enumerable
107
+ * answers: either authored `options` or options resolved from a poll option source.
108
+ */
109
+ pollEligible?: boolean;
110
+ /**
111
+ * Source this `pollEligible` type's poll choices from the field instance itself, instead of
112
+ * authored `options` or a poll `optionSource`. A type that holds enumerable data (for example a
113
+ * `hasMany` relationship to the voteable records) returns one {@link PollOption} per selectable
114
+ * value, read from the live instance the author configured (so it can `payload.find` over the
115
+ * ids it holds). The result backs submission validation, the admin winner select, and results
116
+ * labeling exactly like a source would; it is consulted after an `optionSource` and before the
117
+ * instance's authored `options`.
118
+ */
119
+ resolveOptions?: (args: ResolveFieldOptionsArgs) => PollOption[] | Promise<PollOption[]>;
57
120
  };
58
121
  /** The erased shape stored in the heterogeneous registry. Value is `unknown`; config re-narrows per matched type at execution. */
59
122
  type AnyFormFieldValidate = (args: {
@@ -75,15 +138,21 @@ type AnyFormFieldDefinition = {
75
138
  type: string;
76
139
  label: string;
77
140
  value: FormFieldValueKind;
78
- config?: Field[];
141
+ config?: Field[]; /** See `FormFieldDefinition.advancedConfig`: extra per-type fields for the Advanced tab. */
142
+ advancedConfig?: Field[];
79
143
  validate?: AnyFormFieldValidate;
80
144
  format?: AnyFormFieldFormat;
81
- Field?: string;
145
+ Field?: string; /** See `FormFieldDefinition.blockLabel`: import-map ref for a custom block row Label. */
146
+ blockLabel?: string;
82
147
  schema?: StandardSchemaV1;
83
148
  icon?: string;
84
149
  group?: string; /** How this field appears in the condition builder. Defaults from `value` (see `defaultConditionType`). */
85
- conditionType?: ConditionFieldType;
150
+ conditionType?: ConditionFieldType; /** See `FormFieldDefinition.bare`: the block is the definition's `config` alone, instances are nameless. */
151
+ bare?: boolean; /** See `FormFieldDefinition.omitShared`: shared config fields this type never uses, never authored. */
152
+ omitShared?: OmittableSharedField[]; /** See `FormFieldDefinition.pollEligible`: choosable as a poll's results field. */
153
+ pollEligible?: boolean; /** See `FormFieldDefinition.resolveOptions`: source poll choices from the instance itself. */
154
+ resolveOptions?: (args: ResolveFieldOptionsArgs) => PollOption[] | Promise<PollOption[]>;
86
155
  };
87
156
  //#endregion
88
- export { AnyFormFieldDefinition, FormFieldConfigValues, FormFieldDefinition, FormFieldFormat, FormFieldValidate, FormFieldValueKind, Translate };
157
+ export { AnyFormFieldDefinition, FormFieldConfigValues, FormFieldDefinition, FormFieldFormat, FormFieldValidate, FormFieldValueKind, OmittableSharedField, ResolveFieldOptionsArgs, Translate };
89
158
  //# sourceMappingURL=types.d.ts.map
@@ -3,14 +3,16 @@ import { FormFlow } from "./types.js";
3
3
  //#region src/flow/engine.d.ts
4
4
  /** The entry step id (the first step), or `undefined` for an empty flow. */
5
5
  declare const firstStepId: (flow: FormFlow) => string | undefined;
6
- /** The field machine names a step renders (empty for an unknown step). */
6
+ /** The field keys a step renders (names for named fields, block row ids for bare blocks; empty for an unknown step). */
7
7
  declare const stepFieldNames: (flow: FormFlow, id: string) => string[];
8
8
  /**
9
- * Resolve the next step id from the current step + answers: the first transition whose `when` matches
10
- * (via `evaluateCondition`), else the default `next`, else `undefined` (terminal). Pure + isomorphic.
9
+ * Resolve the next step id from the current step + answers. Precedence: the first transition whose
10
+ * `when` matches (via `evaluateCondition`) wins, else the step's `next` (a step id to jump to, or
11
+ * `null` for an explicit end), else the next step in array order (the last step ends the flow).
12
+ * Returns `undefined` when the flow ends here. Pure + isomorphic.
11
13
  */
12
14
  declare const resolveNextStepId: (flow: FormFlow, currentId: string, answers: Record<string, unknown>) => string | undefined;
13
- /** Whether the current step is terminal (no matching transition + no default next). */
15
+ /** Whether the flow ends at the current step (`resolveNextStepId` finds no step to advance to). */
14
16
  declare const isTerminalStepId: (flow: FormFlow, currentId: string, answers: Record<string, unknown>) => boolean;
15
17
  //#endregion
16
18
  export { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames };
@@ -4,19 +4,24 @@ import { evaluateCondition } from "../conditions/evaluate.js";
4
4
  const firstStepId = (flow) => flow.steps[0]?.id;
5
5
  /** The step with the given id, or `undefined`. */
6
6
  const getStep = (flow, id) => flow.steps.find((step) => step.id === id);
7
- /** The field machine names a step renders (empty for an unknown step). */
7
+ /** The field keys a step renders (names for named fields, block row ids for bare blocks; empty for an unknown step). */
8
8
  const stepFieldNames = (flow, id) => getStep(flow, id)?.fields ?? [];
9
9
  /**
10
- * Resolve the next step id from the current step + answers: the first transition whose `when` matches
11
- * (via `evaluateCondition`), else the default `next`, else `undefined` (terminal). Pure + isomorphic.
10
+ * Resolve the next step id from the current step + answers. Precedence: the first transition whose
11
+ * `when` matches (via `evaluateCondition`) wins, else the step's `next` (a step id to jump to, or
12
+ * `null` for an explicit end), else the next step in array order (the last step ends the flow).
13
+ * Returns `undefined` when the flow ends here. Pure + isomorphic.
12
14
  */
13
15
  const resolveNextStepId = (flow, currentId, answers) => {
14
- const step = getStep(flow, currentId);
16
+ const index = flow.steps.findIndex((step) => step.id === currentId);
17
+ const step = flow.steps[index];
15
18
  if (!step) return;
16
19
  for (const transition of step.transitions ?? []) if (evaluateCondition(transition.when, answers)) return transition.to;
17
- return step.next;
20
+ if (step.next === null) return;
21
+ if (step.next !== void 0) return step.next;
22
+ return flow.steps[index + 1]?.id;
18
23
  };
19
- /** Whether the current step is terminal (no matching transition + no default next). */
24
+ /** Whether the flow ends at the current step (`resolveNextStepId` finds no step to advance to). */
20
25
  const isTerminalStepId = (flow, currentId, answers) => resolveNextStepId(flow, currentId, answers) === void 0;
21
26
  //#endregion
22
27
  export { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames };
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","names":[],"sources":["../../src/flow/engine.ts"],"sourcesContent":["import { evaluateCondition } from '../conditions/evaluate'\nimport type { FlowStep, FormFlow } from './types'\n\n/** The entry step id (the first step), or `undefined` for an empty flow. */\nexport const firstStepId = (flow: FormFlow): string | undefined => flow.steps[0]?.id\n\n/** The step with the given id, or `undefined`. */\nexport const getStep = (flow: FormFlow, id: string): FlowStep | undefined =>\n\tflow.steps.find((step) => step.id === id)\n\n/** The field machine names a step renders (empty for an unknown step). */\nexport const stepFieldNames = (flow: FormFlow, id: string): string[] =>\n\tgetStep(flow, id)?.fields ?? []\n\n/**\n * Resolve the next step id from the current step + answers: the first transition whose `when` matches\n * (via `evaluateCondition`), else the default `next`, else `undefined` (terminal). Pure + isomorphic.\n */\nexport const resolveNextStepId = (\n\tflow: FormFlow,\n\tcurrentId: string,\n\tanswers: Record<string, unknown>\n): string | undefined => {\n\tconst step = getStep(flow, currentId)\n\tif (!step) {\n\t\treturn undefined\n\t}\n\tfor (const transition of step.transitions ?? []) {\n\t\tif (evaluateCondition(transition.when, answers)) {\n\t\t\treturn transition.to\n\t\t}\n\t}\n\treturn step.next\n}\n\n/** Whether the current step is terminal (no matching transition + no default next). */\nexport const isTerminalStepId = (\n\tflow: FormFlow,\n\tcurrentId: string,\n\tanswers: Record<string, unknown>\n): boolean => resolveNextStepId(flow, currentId, answers) === undefined\n"],"mappings":";;;AAIA,MAAa,eAAe,SAAuC,KAAK,MAAM,IAAI;;AAGlF,MAAa,WAAW,MAAgB,OACvC,KAAK,MAAM,MAAM,SAAS,KAAK,OAAO,EAAE;;AAGzC,MAAa,kBAAkB,MAAgB,OAC9C,QAAQ,MAAM,EAAE,GAAG,UAAU,CAAC;;;;;AAM/B,MAAa,qBACZ,MACA,WACA,YACwB;CACxB,MAAM,OAAO,QAAQ,MAAM,SAAS;CACpC,IAAI,CAAC,MACJ;CAED,KAAK,MAAM,cAAc,KAAK,eAAe,CAAC,GAC7C,IAAI,kBAAkB,WAAW,MAAM,OAAO,GAC7C,OAAO,WAAW;CAGpB,OAAO,KAAK;AACb;;AAGA,MAAa,oBACZ,MACA,WACA,YACa,kBAAkB,MAAM,WAAW,OAAO,MAAM,KAAA"}
1
+ {"version":3,"file":"engine.js","names":[],"sources":["../../src/flow/engine.ts"],"sourcesContent":["import { evaluateCondition } from '../conditions/evaluate'\nimport type { FlowStep, FormFlow } from './types'\n\n/** The entry step id (the first step), or `undefined` for an empty flow. */\nexport const firstStepId = (flow: FormFlow): string | undefined => flow.steps[0]?.id\n\n/** The step with the given id, or `undefined`. */\nexport const getStep = (flow: FormFlow, id: string): FlowStep | undefined =>\n\tflow.steps.find((step) => step.id === id)\n\n/** The field keys a step renders (names for named fields, block row ids for bare blocks; empty for an unknown step). */\nexport const stepFieldNames = (flow: FormFlow, id: string): string[] =>\n\tgetStep(flow, id)?.fields ?? []\n\n/**\n * Resolve the next step id from the current step + answers. Precedence: the first transition whose\n * `when` matches (via `evaluateCondition`) wins, else the step's `next` (a step id to jump to, or\n * `null` for an explicit end), else the next step in array order (the last step ends the flow).\n * Returns `undefined` when the flow ends here. Pure + isomorphic.\n */\nexport const resolveNextStepId = (\n\tflow: FormFlow,\n\tcurrentId: string,\n\tanswers: Record<string, unknown>\n): string | undefined => {\n\tconst index = flow.steps.findIndex((step) => step.id === currentId)\n\tconst step = flow.steps[index]\n\tif (!step) {\n\t\treturn undefined\n\t}\n\tfor (const transition of step.transitions ?? []) {\n\t\tif (evaluateCondition(transition.when, answers)) {\n\t\t\treturn transition.to\n\t\t}\n\t}\n\tif (step.next === null) {\n\t\treturn undefined\n\t}\n\tif (step.next !== undefined) {\n\t\treturn step.next\n\t}\n\treturn flow.steps[index + 1]?.id\n}\n\n/** Whether the flow ends at the current step (`resolveNextStepId` finds no step to advance to). */\nexport const isTerminalStepId = (\n\tflow: FormFlow,\n\tcurrentId: string,\n\tanswers: Record<string, unknown>\n): boolean => resolveNextStepId(flow, currentId, answers) === undefined\n"],"mappings":";;;AAIA,MAAa,eAAe,SAAuC,KAAK,MAAM,IAAI;;AAGlF,MAAa,WAAW,MAAgB,OACvC,KAAK,MAAM,MAAM,SAAS,KAAK,OAAO,EAAE;;AAGzC,MAAa,kBAAkB,MAAgB,OAC9C,QAAQ,MAAM,EAAE,GAAG,UAAU,CAAC;;;;;;;AAQ/B,MAAa,qBACZ,MACA,WACA,YACwB;CACxB,MAAM,QAAQ,KAAK,MAAM,WAAW,SAAS,KAAK,OAAO,SAAS;CAClE,MAAM,OAAO,KAAK,MAAM;CACxB,IAAI,CAAC,MACJ;CAED,KAAK,MAAM,cAAc,KAAK,eAAe,CAAC,GAC7C,IAAI,kBAAkB,WAAW,MAAM,OAAO,GAC7C,OAAO,WAAW;CAGpB,IAAI,KAAK,SAAS,MACjB;CAED,IAAI,KAAK,SAAS,KAAA,GACjB,OAAO,KAAK;CAEb,OAAO,KAAK,MAAM,QAAQ,IAAI;AAC/B;;AAGA,MAAa,oBACZ,MACA,WACA,YACa,kBAAkB,MAAM,WAAW,OAAO,MAAM,KAAA"}
@@ -1,24 +1,43 @@
1
1
  //#region src/flow/normalizeFlow.ts
2
2
  const isRecord = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
3
3
  /**
4
- * Pure guard that normalizes a raw (possibly untrusted) flow value against the
5
- * form's current field list. Returns `undefined` when the flow is absent, empty,
6
- * or resolves to fewer than two steps (a single step is an ordinary form).
4
+ * Pure guard that normalizes a raw (possibly untrusted) flow value against the form's current
5
+ * field keys (machine names for named fields, block row ids for bare blocks; see `fieldKey`).
6
+ * Returns `undefined` when the flow is absent, empty, or resolves to fewer than two steps
7
+ * (a single step is an ordinary form). A field assigned to multiple steps keeps only its
8
+ * first occurrence in step order. `next: null` (explicit end of form) is preserved as distinct
9
+ * from an absent `next` (sequential fall-through); a `next` pointing at an unknown step is
10
+ * dropped to absent.
11
+ *
12
+ * A step is kept even when it ends up with no fields, which happens when every field it named was
13
+ * deleted from the form. Dropping it would be wrong twice over: a host can render its own content
14
+ * per step off `useFormStep()`, so an empty step is not necessarily an empty page, and dropping
15
+ * one would strand the `next` and transition targets that point at it. The visitor gets a page with
16
+ * only navigation on it, which is visible to the author in the flow builder and recoverable there.
17
+ *
18
+ * When `normalizeWhen` is provided, each transition's `when` is laundered through it (the same field
19
+ * condition normalization); a transition whose `when` strips to nothing (an operand field was deleted)
20
+ * is dropped rather than kept as an always-true route that would force navigation.
7
21
  */
8
- const normalizeFlow = (raw, fieldNames) => {
22
+ const normalizeFlow = (raw, fieldKeys, normalizeWhen) => {
9
23
  if (!isRecord(raw) || !Array.isArray(raw.steps)) return;
10
- const knownFields = new Set(fieldNames);
24
+ const knownFields = new Set(fieldKeys);
11
25
  const rawSteps = raw.steps.filter((s) => isRecord(s) && typeof s.id === "string");
12
26
  const knownIds = new Set(rawSteps.map((s) => s.id));
13
27
  if (knownIds.size < 2) return;
28
+ const seenFields = /* @__PURE__ */ new Set();
14
29
  return { steps: rawSteps.map((s) => {
15
30
  const id = s.id;
16
- const fields = Array.isArray(s.fields) ? s.fields.filter((f) => typeof f === "string" && knownFields.has(f)) : [];
31
+ const fields = Array.isArray(s.fields) ? s.fields.filter((f) => {
32
+ if (typeof f !== "string" || !knownFields.has(f) || seenFields.has(f)) return false;
33
+ seenFields.add(f);
34
+ return true;
35
+ }) : [];
17
36
  const transitions = (Array.isArray(s.transitions) ? s.transitions : []).filter((t) => isRecord(t) && typeof t.to === "string" && knownIds.has(t.to) && isRecord(t.when)).map((t) => ({
18
- when: t.when,
37
+ when: normalizeWhen ? normalizeWhen(t.when) : t.when,
19
38
  to: t.to
20
- }));
21
- const next = typeof s.next === "string" && knownIds.has(s.next) ? s.next : void 0;
39
+ })).filter((t) => t.when !== void 0);
40
+ const next = s.next === null ? null : typeof s.next === "string" && knownIds.has(s.next) ? s.next : void 0;
22
41
  const step = {
23
42
  id,
24
43
  fields
@@ -1 +1 @@
1
- {"version":3,"file":"normalizeFlow.js","names":[],"sources":["../../src/flow/normalizeFlow.ts"],"sourcesContent":["import type { Where } from 'payload'\nimport type { FlowStep, FormFlow } from './types'\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n\tv !== null && typeof v === 'object' && !Array.isArray(v)\n\n/**\n * Pure guard that normalizes a raw (possibly untrusted) flow value against the\n * form's current field list. Returns `undefined` when the flow is absent, empty,\n * or resolves to fewer than two steps (a single step is an ordinary form).\n */\nexport const normalizeFlow = (raw: unknown, fieldNames: string[]): FormFlow | undefined => {\n\tif (!isRecord(raw) || !Array.isArray(raw.steps)) {\n\t\treturn undefined\n\t}\n\n\tconst knownFields = new Set(fieldNames)\n\n\tconst rawSteps = raw.steps.filter(\n\t\t(s): s is Record<string, unknown> => isRecord(s) && typeof s.id === 'string'\n\t)\n\n\tconst knownIds = new Set(rawSteps.map((s) => s.id as string))\n\n\tif (knownIds.size < 2) {\n\t\treturn undefined\n\t}\n\n\tconst steps: FlowStep[] = rawSteps.map((s) => {\n\t\tconst id = s.id as string\n\n\t\tconst fields = Array.isArray(s.fields)\n\t\t\t? s.fields.filter((f): f is string => typeof f === 'string' && knownFields.has(f))\n\t\t\t: []\n\n\t\tconst rawTransitions = Array.isArray(s.transitions) ? s.transitions : []\n\t\tconst transitions = rawTransitions\n\t\t\t.filter(\n\t\t\t\t(t): t is Record<string, unknown> =>\n\t\t\t\t\tisRecord(t) &&\n\t\t\t\t\ttypeof t.to === 'string' &&\n\t\t\t\t\tknownIds.has(t.to as string) &&\n\t\t\t\t\tisRecord(t.when)\n\t\t\t)\n\t\t\t.map((t) => ({ when: t.when as Where, to: t.to as string }))\n\n\t\tconst next = typeof s.next === 'string' && knownIds.has(s.next) ? (s.next as string) : undefined\n\n\t\tconst step: FlowStep = { id, fields }\n\t\tif (typeof s.title === 'string') step.title = s.title\n\t\tif (transitions.length > 0) step.transitions = transitions\n\t\tif (next !== undefined) step.next = next\n\n\t\treturn step\n\t})\n\n\treturn { steps }\n}\n"],"mappings":";AAGA,MAAM,YAAY,MACjB,MAAM,QAAQ,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC;;;;;;AAOxD,MAAa,iBAAiB,KAAc,eAA+C;CAC1F,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,QAAQ,IAAI,KAAK,GAC7C;CAGD,MAAM,cAAc,IAAI,IAAI,UAAU;CAEtC,MAAM,WAAW,IAAI,MAAM,QACzB,MAAoC,SAAS,CAAC,KAAK,OAAO,EAAE,OAAO,QACrE;CAEA,MAAM,WAAW,IAAI,IAAI,SAAS,KAAK,MAAM,EAAE,EAAY,CAAC;CAE5D,IAAI,SAAS,OAAO,GACnB;CA+BD,OAAO,EAAE,OA5BiB,SAAS,KAAK,MAAM;EAC7C,MAAM,KAAK,EAAE;EAEb,MAAM,SAAS,MAAM,QAAQ,EAAE,MAAM,IAClC,EAAE,OAAO,QAAQ,MAAmB,OAAO,MAAM,YAAY,YAAY,IAAI,CAAC,CAAC,IAC/E,CAAC;EAGJ,MAAM,eADiB,MAAM,QAAQ,EAAE,WAAW,IAAI,EAAE,cAAc,CAAC,GAErE,QACC,MACA,SAAS,CAAC,KACV,OAAO,EAAE,OAAO,YAChB,SAAS,IAAI,EAAE,EAAY,KAC3B,SAAS,EAAE,IAAI,CACjB,EACC,KAAK,OAAO;GAAE,MAAM,EAAE;GAAe,IAAI,EAAE;EAAa,EAAE;EAE5D,MAAM,OAAO,OAAO,EAAE,SAAS,YAAY,SAAS,IAAI,EAAE,IAAI,IAAK,EAAE,OAAkB,KAAA;EAEvF,MAAM,OAAiB;GAAE;GAAI;EAAO;EACpC,IAAI,OAAO,EAAE,UAAU,UAAU,KAAK,QAAQ,EAAE;EAChD,IAAI,YAAY,SAAS,GAAG,KAAK,cAAc;EAC/C,IAAI,SAAS,KAAA,GAAW,KAAK,OAAO;EAEpC,OAAO;CACR,CAEa,EAAE;AAChB"}
1
+ {"version":3,"file":"normalizeFlow.js","names":[],"sources":["../../src/flow/normalizeFlow.ts"],"sourcesContent":["import type { Where } from 'payload'\nimport type { FlowStep, FormFlow } from './types'\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n\tv !== null && typeof v === 'object' && !Array.isArray(v)\n\n/**\n * Pure guard that normalizes a raw (possibly untrusted) flow value against the form's current\n * field keys (machine names for named fields, block row ids for bare blocks; see `fieldKey`).\n * Returns `undefined` when the flow is absent, empty, or resolves to fewer than two steps\n * (a single step is an ordinary form). A field assigned to multiple steps keeps only its\n * first occurrence in step order. `next: null` (explicit end of form) is preserved as distinct\n * from an absent `next` (sequential fall-through); a `next` pointing at an unknown step is\n * dropped to absent.\n *\n * A step is kept even when it ends up with no fields, which happens when every field it named was\n * deleted from the form. Dropping it would be wrong twice over: a host can render its own content\n * per step off `useFormStep()`, so an empty step is not necessarily an empty page, and dropping\n * one would strand the `next` and transition targets that point at it. The visitor gets a page with\n * only navigation on it, which is visible to the author in the flow builder and recoverable there.\n *\n * When `normalizeWhen` is provided, each transition's `when` is laundered through it (the same field\n * condition normalization); a transition whose `when` strips to nothing (an operand field was deleted)\n * is dropped rather than kept as an always-true route that would force navigation.\n */\nexport const normalizeFlow = (\n\traw: unknown,\n\tfieldKeys: string[],\n\tnormalizeWhen?: (raw: unknown) => Where | undefined\n): FormFlow | undefined => {\n\tif (!isRecord(raw) || !Array.isArray(raw.steps)) {\n\t\treturn undefined\n\t}\n\n\tconst knownFields = new Set(fieldKeys)\n\n\tconst rawSteps = raw.steps.filter(\n\t\t(s): s is Record<string, unknown> => isRecord(s) && typeof s.id === 'string'\n\t)\n\n\tconst knownIds = new Set(rawSteps.map((s) => s.id as string))\n\n\tif (knownIds.size < 2) {\n\t\treturn undefined\n\t}\n\n\tconst seenFields = new Set<string>()\n\n\tconst steps: FlowStep[] = rawSteps.map((s) => {\n\t\tconst id = s.id as string\n\n\t\tconst fields = Array.isArray(s.fields)\n\t\t\t? s.fields.filter((f): f is string => {\n\t\t\t\t\tif (typeof f !== 'string' || !knownFields.has(f) || seenFields.has(f)) return false\n\t\t\t\t\tseenFields.add(f)\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t: []\n\n\t\tconst rawTransitions = Array.isArray(s.transitions) ? s.transitions : []\n\t\tconst transitions = rawTransitions\n\t\t\t.filter(\n\t\t\t\t(t): t is Record<string, unknown> =>\n\t\t\t\t\tisRecord(t) &&\n\t\t\t\t\ttypeof t.to === 'string' &&\n\t\t\t\t\tknownIds.has(t.to as string) &&\n\t\t\t\t\tisRecord(t.when)\n\t\t\t)\n\t\t\t.map((t) => ({\n\t\t\t\twhen: normalizeWhen ? normalizeWhen(t.when) : (t.when as Where),\n\t\t\t\tto: t.to as string,\n\t\t\t}))\n\t\t\t.filter((t): t is { when: Where; to: string } => t.when !== undefined)\n\n\t\tconst next =\n\t\t\ts.next === null\n\t\t\t\t? null\n\t\t\t\t: typeof s.next === 'string' && knownIds.has(s.next)\n\t\t\t\t\t? (s.next as string)\n\t\t\t\t\t: undefined\n\n\t\tconst step: FlowStep = { id, fields }\n\t\tif (typeof s.title === 'string') step.title = s.title\n\t\tif (transitions.length > 0) step.transitions = transitions\n\t\tif (next !== undefined) step.next = next\n\n\t\treturn step\n\t})\n\n\treturn { steps }\n}\n"],"mappings":";AAGA,MAAM,YAAY,MACjB,MAAM,QAAQ,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;AAqBxD,MAAa,iBACZ,KACA,WACA,kBAC0B;CAC1B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,QAAQ,IAAI,KAAK,GAC7C;CAGD,MAAM,cAAc,IAAI,IAAI,SAAS;CAErC,MAAM,WAAW,IAAI,MAAM,QACzB,MAAoC,SAAS,CAAC,KAAK,OAAO,EAAE,OAAO,QACrE;CAEA,MAAM,WAAW,IAAI,IAAI,SAAS,KAAK,MAAM,EAAE,EAAY,CAAC;CAE5D,IAAI,SAAS,OAAO,GACnB;CAGD,MAAM,6BAAa,IAAI,IAAY;CA2CnC,OAAO,EAAE,OAzCiB,SAAS,KAAK,MAAM;EAC7C,MAAM,KAAK,EAAE;EAEb,MAAM,SAAS,MAAM,QAAQ,EAAE,MAAM,IAClC,EAAE,OAAO,QAAQ,MAAmB;GACpC,IAAI,OAAO,MAAM,YAAY,CAAC,YAAY,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,GAAG,OAAO;GAC9E,WAAW,IAAI,CAAC;GAChB,OAAO;EACR,CAAC,IACA,CAAC;EAGJ,MAAM,eADiB,MAAM,QAAQ,EAAE,WAAW,IAAI,EAAE,cAAc,CAAC,GAErE,QACC,MACA,SAAS,CAAC,KACV,OAAO,EAAE,OAAO,YAChB,SAAS,IAAI,EAAE,EAAY,KAC3B,SAAS,EAAE,IAAI,CACjB,EACC,KAAK,OAAO;GACZ,MAAM,gBAAgB,cAAc,EAAE,IAAI,IAAK,EAAE;GACjD,IAAI,EAAE;EACP,EAAE,EACD,QAAQ,MAAwC,EAAE,SAAS,KAAA,CAAS;EAEtE,MAAM,OACL,EAAE,SAAS,OACR,OACA,OAAO,EAAE,SAAS,YAAY,SAAS,IAAI,EAAE,IAAI,IAC/C,EAAE,OACH,KAAA;EAEL,MAAM,OAAiB;GAAE;GAAI;EAAO;EACpC,IAAI,OAAO,EAAE,UAAU,UAAU,KAAK,QAAQ,EAAE;EAChD,IAAI,YAAY,SAAS,GAAG,KAAK,cAAc;EAC/C,IAAI,SAAS,KAAA,GAAW,KAAK,OAAO;EAEpC,OAAO;CACR,CAEa,EAAE;AAChB"}
@@ -0,0 +1,15 @@
1
+ //#region src/flow/stepLabel.ts
2
+ /**
3
+ * Display label for a step: its trimmed title, else the fallback template with
4
+ * `{n}` replaced by the 1-based index. Step ids never surface in the UI.
5
+ * Lives with the flow engine (not the admin client module) because the frontend
6
+ * `<FormSteps>` indicator resolves labels with the same semantics.
7
+ */
8
+ const stepLabel = (step, index, fallbackTemplate) => {
9
+ const title = step.title?.trim();
10
+ return title !== void 0 && title.length > 0 ? title : fallbackTemplate.replace("{n}", String(index + 1));
11
+ };
12
+ //#endregion
13
+ export { stepLabel };
14
+
15
+ //# sourceMappingURL=stepLabel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepLabel.js","names":[],"sources":["../../src/flow/stepLabel.ts"],"sourcesContent":["import type { FlowStep } from './types'\n\n/**\n * Display label for a step: its trimmed title, else the fallback template with\n * `{n}` replaced by the 1-based index. Step ids never surface in the UI.\n * Lives with the flow engine (not the admin client module) because the frontend\n * `<FormSteps>` indicator resolves labels with the same semantics.\n */\nexport const stepLabel = (\n\tstep: Pick<FlowStep, 'title'>,\n\tindex: number,\n\tfallbackTemplate: string\n): string => {\n\tconst title = step.title?.trim()\n\treturn title !== undefined && title.length > 0\n\t\t? title\n\t\t: fallbackTemplate.replace('{n}', String(index + 1))\n}\n"],"mappings":";;;;;;;AAQA,MAAa,aACZ,MACA,OACA,qBACY;CACZ,MAAM,QAAQ,KAAK,OAAO,KAAK;CAC/B,OAAO,UAAU,KAAA,KAAa,MAAM,SAAS,IAC1C,QACA,iBAAiB,QAAQ,OAAO,OAAO,QAAQ,CAAC,CAAC;AACrD"}
@@ -9,9 +9,18 @@ type FlowTransition = {
9
9
  /** A flow step: a named group of fields, ordered transitions, and a default next edge. */
10
10
  type FlowStep = {
11
11
  id: string;
12
- title?: string; /** Field machine names rendered in this step (a subset of the form's fields). */
13
- fields: string[]; /** Default next step id when no transition matches. Absent -> this step is terminal. */
14
- next?: string; /** Ordered conditional edges; the first whose `when` matches the answers wins. */
12
+ title?: string;
13
+ /**
14
+ * Field keys rendered in this step (a subset of the form's fields): machine names for named
15
+ * fields, block row ids for bare (nameless) blocks. See `fieldKey`.
16
+ */
17
+ fields: string[];
18
+ /**
19
+ * Default next edge when no transition matches. Absent -> fall through to the next step in
20
+ * array order (the last step ends the form). `null` -> explicit end of form regardless of
21
+ * position. A step id -> jump to that step.
22
+ */
23
+ next?: string | null; /** Ordered conditional edges; the first whose `when` matches the answers wins. */
15
24
  transitions?: FlowTransition[];
16
25
  };
17
26
  /** A serializable multi-step flow layered over the form's flat field list. */
@@ -0,0 +1,11 @@
1
+ //#region src/flow/types.ts
2
+ /**
3
+ * Reserved value the flow builder's next select maps to `next: null` (explicit end of form).
4
+ * Builder-generated step ids are UUIDs (hex digits + dashes) and can never equal it;
5
+ * `validateFlow` rejects API-authored steps claiming it as an id so the mapping stays unambiguous.
6
+ */
7
+ const END_OF_FORM = "__end__";
8
+ //#endregion
9
+ export { END_OF_FORM };
10
+
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/flow/types.ts"],"sourcesContent":["import type { Where } from 'payload'\n\n/** A conditional edge: when `when` matches the answers, route to step `to`. */\nexport type FlowTransition = { when: Where; to: string }\n\n/** A flow step: a named group of fields, ordered transitions, and a default next edge. */\nexport type FlowStep = {\n\tid: string\n\ttitle?: string\n\t/**\n\t * Field keys rendered in this step (a subset of the form's fields): machine names for named\n\t * fields, block row ids for bare (nameless) blocks. See `fieldKey`.\n\t */\n\tfields: string[]\n\t/**\n\t * Default next edge when no transition matches. Absent -> fall through to the next step in\n\t * array order (the last step ends the form). `null` -> explicit end of form regardless of\n\t * position. A step id -> jump to that step.\n\t */\n\tnext?: string | null\n\t/** Ordered conditional edges; the first whose `when` matches the answers wins. */\n\ttransitions?: FlowTransition[]\n}\n\n/** A serializable multi-step flow layered over the form's flat field list. */\nexport type FormFlow = { steps: FlowStep[] }\n\n/**\n * Reserved value the flow builder's next select maps to `next: null` (explicit end of form).\n * Builder-generated step ids are UUIDs (hex digits + dashes) and can never equal it;\n * `validateFlow` rejects API-authored steps claiming it as an id so the mapping stays unambiguous.\n */\nexport const END_OF_FORM = '__end__'\n"],"mappings":";;;;;;AAgCA,MAAa,cAAc"}
@@ -0,0 +1,23 @@
1
+ //#region src/form/pollState.d.ts
2
+ /** Poll settings as loaded from a forms document (server) or a `FormDocument` (client). */
3
+ type PollConfigLike = {
4
+ resultsField?: string | null;
5
+ resultsVisibility?: string | null;
6
+ closesAt?: string | null;
7
+ allowChange?: boolean | null; /** The outcome-resolution strategy slug (`poll.types` registry). Absent is treated as `manual`. */
8
+ type?: string | null;
9
+ optionSource?: string | null;
10
+ sourceConfig?: Record<string, unknown> | null;
11
+ outcome?: {
12
+ winningValues?: (string | null)[] | null;
13
+ resolvedAt?: string | null;
14
+ } | null;
15
+ };
16
+ /**
17
+ * Whether the poll's `closesAt` has passed. An unset or unparseable `closesAt` never closes;
18
+ * framework-agnostic so the server guard, the results gate, and the client `<Poll>` agree.
19
+ */
20
+ declare const isPollClosed: (poll: PollConfigLike | null | undefined, now?: number) => boolean;
21
+ //#endregion
22
+ export { PollConfigLike, isPollClosed };
23
+ //# sourceMappingURL=pollState.d.ts.map
@@ -0,0 +1,17 @@
1
+ //#region src/form/pollState.ts
2
+ /** Narrow a forms document's untyped `poll` member. */
3
+ const pollConfigOf = (poll) => poll != null && typeof poll === "object" ? poll : void 0;
4
+ /**
5
+ * Whether the poll's `closesAt` has passed. An unset or unparseable `closesAt` never closes;
6
+ * framework-agnostic so the server guard, the results gate, and the client `<Poll>` agree.
7
+ */
8
+ const isPollClosed = (poll, now = Date.now()) => {
9
+ const closesAt = poll?.closesAt;
10
+ if (typeof closesAt !== "string" || closesAt.length === 0) return false;
11
+ const ts = Date.parse(closesAt);
12
+ return Number.isFinite(ts) && ts <= now;
13
+ };
14
+ //#endregion
15
+ export { isPollClosed, pollConfigOf };
16
+
17
+ //# sourceMappingURL=pollState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pollState.js","names":[],"sources":["../../src/form/pollState.ts"],"sourcesContent":["/** Poll settings as loaded from a forms document (server) or a `FormDocument` (client). */\nexport type PollConfigLike = {\n\tresultsField?: string | null\n\tresultsVisibility?: string | null\n\tclosesAt?: string | null\n\tallowChange?: boolean | null\n\t/** The outcome-resolution strategy slug (`poll.types` registry). Absent is treated as `manual`. */\n\ttype?: string | null\n\toptionSource?: string | null\n\tsourceConfig?: Record<string, unknown> | null\n\toutcome?: { winningValues?: (string | null)[] | null; resolvedAt?: string | null } | null\n}\n\n/** Narrow a forms document's untyped `poll` member. */\nexport const pollConfigOf = (poll: unknown): PollConfigLike | undefined =>\n\tpoll != null && typeof poll === 'object' ? (poll as PollConfigLike) : undefined\n\n/**\n * Whether the poll's `closesAt` has passed. An unset or unparseable `closesAt` never closes;\n * framework-agnostic so the server guard, the results gate, and the client `<Poll>` agree.\n */\nexport const isPollClosed = (\n\tpoll: PollConfigLike | null | undefined,\n\tnow: number = Date.now()\n): boolean => {\n\tconst closesAt = poll?.closesAt\n\tif (typeof closesAt !== 'string' || closesAt.length === 0) {\n\t\treturn false\n\t}\n\tconst ts = Date.parse(closesAt)\n\treturn Number.isFinite(ts) && ts <= now\n}\n"],"mappings":";;AAcA,MAAa,gBAAgB,SAC5B,QAAQ,QAAQ,OAAO,SAAS,WAAY,OAA0B,KAAA;;;;;AAMvE,MAAa,gBACZ,MACA,MAAc,KAAK,IAAI,MACV;CACb,MAAM,WAAW,MAAM;CACvB,IAAI,OAAO,aAAa,YAAY,SAAS,WAAW,GACvD,OAAO;CAER,MAAM,KAAK,KAAK,MAAM,QAAQ;CAC9B,OAAO,OAAO,SAAS,EAAE,KAAK,MAAM;AACrC"}
@@ -0,0 +1,110 @@
1
+ import { PollOption } from "../poll/definePollOptionSource.js";
2
+ import { CalcResolved } from "../calc/evaluate.js";
3
+ import { ConsentStatements } from "../consent/resolveConsentStatements.js";
4
+ import { FormDocument } from "./types.js";
5
+
6
+ //#region src/form/toFormDocument.d.ts
7
+ type ToFormDocumentOptions = {
8
+ /**
9
+ * Source-resolved poll options (from `resolvePollOptions`), injected as the options of the
10
+ * field instance named by the form's `poll.resultsField` so the client renders the host's
11
+ * current choices instead of hand-authored ones.
12
+ */
13
+ pollOptions?: PollOption[];
14
+ /**
15
+ * Source-resolved consent statements (from `resolveConsentStatements`), injected into the
16
+ * consent field instances they name. A form stores only a source id, so without these its
17
+ * consent fields render with no statement at all.
18
+ */
19
+ consentStatements?: ConsentStatements;
20
+ /**
21
+ * Resolve an internal redirect `reference` to a same-site URL. Called only when
22
+ * `response.type === 'redirect'`, a `reference` is present, and no `redirect.url` is set. Keep it
23
+ * sync: operate on the already-loaded (populated) reference, since resolving a Doc to a URL is host
24
+ * routing knowledge the plugin cannot supply. The result is written to `redirect.url`, so `<Form>`
25
+ * navigates with no client change.
26
+ */
27
+ resolveRedirect?: (reference: {
28
+ relationTo: string;
29
+ value: number | string | object;
30
+ }) => string | null | undefined;
31
+ };
32
+ /**
33
+ * Narrows a Payload-generated form document (from `getPayload().findByID()` or `fetch`) to
34
+ * `FormDocument` without an unsafe `as` cast. Handles the small structural mismatches between
35
+ * the auto-generated collection types and what `<Form>` expects:
36
+ * - `fields` may be a typed blocks-union array or null; normalized to `FormFieldInstance[]`
37
+ * (nameless bare rows, e.g. message blocks, pass through with their row `id` intact)
38
+ * - `flow` is stored as opaque JSON; typed as `FormFlow | undefined`
39
+ * - `response` may be null; coerced to `undefined`, otherwise passed through wholesale, which
40
+ * includes `response.redirect.reference` (present only when the plugin's `redirectRelationships`
41
+ * option is set): `value` may be a bare id (`depth: 0`) or a populated document, and the host
42
+ * resolves it to a URL either by writing `redirect.url` or by passing `options.resolveRedirect`
43
+ * - the button labels (`submitLabel`/`prevLabel`/`nextLabel`) live at the document root now (there
44
+ * is no `buttons` group); the non-empty ones are reassembled into `FormDocument.buttons`
45
+ * - `title` may be null; coerced to `undefined`
46
+ * - `multistep`/`pollEnabled` are the two top-level form-type flags, coerced to strict booleans
47
+ * - `poll` may be null; coerced to `undefined` (`resultsField`, `optionSource`, and
48
+ * `sourceConfig` are dropped: server-side only; `outcome` passes through `winningValues` only)
49
+ *
50
+ * Unknown keys survive on `response` but not on `poll`, which is deliberate rather than incidental.
51
+ * `response` is a visitor-facing group a host is meant to extend (`overrides.forms.fields`) and read
52
+ * back off `FormDocument` in custom chrome, so it is cast wholesale. `poll` is plugin-owned config
53
+ * that is split between
54
+ * client-safe lifecycle state and server-only members, so it is rebuilt from an allowlist: a
55
+ * passthrough would ship whatever a host put in `sourceConfig` (domain config, ids, credentials)
56
+ * to every anonymous visitor. Adding a client-visible poll member means naming it here.
57
+ *
58
+ * Pure and framework-agnostic (no 'use client'): safe to call from a Server Component or any
59
+ * other server-side code before handing the result to the client `<Form>`.
60
+ */
61
+ declare function toFormDocument(form: {
62
+ id: number | string;
63
+ fields?: {
64
+ blockType: string;
65
+ name?: string;
66
+ [key: string]: unknown;
67
+ }[] | null;
68
+ flow?: unknown;
69
+ response?: {
70
+ type?: string | null;
71
+ message?: unknown;
72
+ redirect?: {
73
+ url?: string | null;
74
+ reference?: {
75
+ relationTo?: string | null;
76
+ value?: number | string | object | null;
77
+ } | null;
78
+ } | null;
79
+ } | null;
80
+ submitLabel?: string | null;
81
+ prevLabel?: string | null;
82
+ nextLabel?: string | null;
83
+ title?: string | null;
84
+ multistep?: boolean | null;
85
+ pollEnabled?: boolean | null;
86
+ poll?: {
87
+ resultsField?: string | null;
88
+ resultsVisibility?: string | null;
89
+ closesAt?: string | null;
90
+ allowChange?: boolean | null;
91
+ outcome?: {
92
+ winningValues?: (string | null)[] | null;
93
+ } | null;
94
+ } | null;
95
+ /**
96
+ * Consent statements resolved onto the doc by the plugin's forms `afterRead` hook (when
97
+ * `consent.sources` is set), so consent renders on any fetch path (modal/client, not just RSC).
98
+ * An explicit `options.consentStatements` takes precedence when both are present.
99
+ */
100
+ consentStatements?: ConsentStatements;
101
+ /**
102
+ * Calc source values resolved onto the doc by the plugin's forms `afterRead` hook (when calc
103
+ * sources are registered and used); passed through so the client's live preview computes with
104
+ * real values. `functions` can never ride a document, hence the Pick.
105
+ */
106
+ calcResolved?: Pick<CalcResolved, 'sources' | 'weights'>;
107
+ }, options?: ToFormDocumentOptions): FormDocument;
108
+ //#endregion
109
+ export { ToFormDocumentOptions, toFormDocument };
110
+ //# sourceMappingURL=toFormDocument.d.ts.map
@@ -0,0 +1,89 @@
1
+ import { applyPollOptions } from "../poll/applyPollOptions.js";
2
+ import { applyConsentStatements } from "../consent/applyConsentStatements.js";
3
+ //#region src/form/toFormDocument.ts
4
+ /**
5
+ * Reassemble the client button labels from the document's top-level `submitLabel`/`prevLabel`/
6
+ * `nextLabel` fields, keeping only non-empty strings (mirroring the client's own `storedLabel`
7
+ * fallback). Returns `undefined` when the author set no label, so the client uses its defaults.
8
+ */
9
+ const buttonSettingsOf = (form) => {
10
+ const label = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
11
+ const settings = {};
12
+ const submitLabel = label(form.submitLabel);
13
+ const prevLabel = label(form.prevLabel);
14
+ const nextLabel = label(form.nextLabel);
15
+ if (submitLabel !== void 0) settings.submitLabel = submitLabel;
16
+ if (prevLabel !== void 0) settings.prevLabel = prevLabel;
17
+ if (nextLabel !== void 0) settings.nextLabel = nextLabel;
18
+ return Object.keys(settings).length > 0 ? settings : void 0;
19
+ };
20
+ /**
21
+ * Narrows a Payload-generated form document (from `getPayload().findByID()` or `fetch`) to
22
+ * `FormDocument` without an unsafe `as` cast. Handles the small structural mismatches between
23
+ * the auto-generated collection types and what `<Form>` expects:
24
+ * - `fields` may be a typed blocks-union array or null; normalized to `FormFieldInstance[]`
25
+ * (nameless bare rows, e.g. message blocks, pass through with their row `id` intact)
26
+ * - `flow` is stored as opaque JSON; typed as `FormFlow | undefined`
27
+ * - `response` may be null; coerced to `undefined`, otherwise passed through wholesale, which
28
+ * includes `response.redirect.reference` (present only when the plugin's `redirectRelationships`
29
+ * option is set): `value` may be a bare id (`depth: 0`) or a populated document, and the host
30
+ * resolves it to a URL either by writing `redirect.url` or by passing `options.resolveRedirect`
31
+ * - the button labels (`submitLabel`/`prevLabel`/`nextLabel`) live at the document root now (there
32
+ * is no `buttons` group); the non-empty ones are reassembled into `FormDocument.buttons`
33
+ * - `title` may be null; coerced to `undefined`
34
+ * - `multistep`/`pollEnabled` are the two top-level form-type flags, coerced to strict booleans
35
+ * - `poll` may be null; coerced to `undefined` (`resultsField`, `optionSource`, and
36
+ * `sourceConfig` are dropped: server-side only; `outcome` passes through `winningValues` only)
37
+ *
38
+ * Unknown keys survive on `response` but not on `poll`, which is deliberate rather than incidental.
39
+ * `response` is a visitor-facing group a host is meant to extend (`overrides.forms.fields`) and read
40
+ * back off `FormDocument` in custom chrome, so it is cast wholesale. `poll` is plugin-owned config
41
+ * that is split between
42
+ * client-safe lifecycle state and server-only members, so it is rebuilt from an allowlist: a
43
+ * passthrough would ship whatever a host put in `sourceConfig` (domain config, ids, credentials)
44
+ * to every anonymous visitor. Adding a client-visible poll member means naming it here.
45
+ *
46
+ * Pure and framework-agnostic (no 'use client'): safe to call from a Server Component or any
47
+ * other server-side code before handing the result to the client `<Form>`.
48
+ */
49
+ function toFormDocument(form, options) {
50
+ const rawWinningValues = form.poll?.outcome?.winningValues;
51
+ const winningValues = Array.isArray(rawWinningValues) ? rawWinningValues.filter((value) => typeof value === "string" && value.length > 0) : [];
52
+ const poll = form.poll ? {
53
+ resultsVisibility: form.poll.resultsVisibility ?? void 0,
54
+ closesAt: form.poll.closesAt ?? void 0,
55
+ ...form.poll.allowChange === true ? { allowChange: true } : {},
56
+ ...winningValues.length > 0 ? { outcome: { winningValues } } : {}
57
+ } : void 0;
58
+ let fields = form.fields ?? [];
59
+ if (options?.pollOptions) fields = applyPollOptions(fields, form.poll?.resultsField, options.pollOptions);
60
+ const consentStatements = options?.consentStatements ?? form.consentStatements;
61
+ if (consentStatements) fields = applyConsentStatements(fields, consentStatements);
62
+ let response = form.response ?? void 0;
63
+ if (options?.resolveRedirect && response?.type === "redirect" && response.redirect?.reference && !response.redirect.url) {
64
+ const url = options.resolveRedirect(response.redirect.reference);
65
+ if (url) response = {
66
+ ...response,
67
+ redirect: {
68
+ ...response.redirect,
69
+ url
70
+ }
71
+ };
72
+ }
73
+ return {
74
+ id: form.id,
75
+ fields,
76
+ flow: form.flow,
77
+ response,
78
+ buttons: buttonSettingsOf(form),
79
+ title: form.title ?? void 0,
80
+ multistep: form.multistep === true,
81
+ pollEnabled: form.pollEnabled === true,
82
+ poll,
83
+ calcResolved: form.calcResolved
84
+ };
85
+ }
86
+ //#endregion
87
+ export { toFormDocument };
88
+
89
+ //# sourceMappingURL=toFormDocument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toFormDocument.js","names":[],"sources":["../../src/form/toFormDocument.ts"],"sourcesContent":["import type { CalcResolved } from '../calc/evaluate'\nimport { applyConsentStatements } from '../consent/applyConsentStatements'\nimport type { ConsentStatements } from '../consent/resolveConsentStatements'\nimport type { FormFlow } from '../flow/types'\nimport { applyPollOptions } from '../poll/applyPollOptions'\nimport type { PollOption } from '../poll/definePollOptionSource'\nimport type { FormFieldInstance } from '../submissions/types'\nimport type { FormButtonSettings, FormDocument, FormResponseSettings } from './types'\n\nexport type ToFormDocumentOptions = {\n\t/**\n\t * Source-resolved poll options (from `resolvePollOptions`), injected as the options of the\n\t * field instance named by the form's `poll.resultsField` so the client renders the host's\n\t * current choices instead of hand-authored ones.\n\t */\n\tpollOptions?: PollOption[]\n\t/**\n\t * Source-resolved consent statements (from `resolveConsentStatements`), injected into the\n\t * consent field instances they name. A form stores only a source id, so without these its\n\t * consent fields render with no statement at all.\n\t */\n\tconsentStatements?: ConsentStatements\n\t/**\n\t * Resolve an internal redirect `reference` to a same-site URL. Called only when\n\t * `response.type === 'redirect'`, a `reference` is present, and no `redirect.url` is set. Keep it\n\t * sync: operate on the already-loaded (populated) reference, since resolving a Doc to a URL is host\n\t * routing knowledge the plugin cannot supply. The result is written to `redirect.url`, so `<Form>`\n\t * navigates with no client change.\n\t */\n\tresolveRedirect?: (reference: {\n\t\trelationTo: string\n\t\tvalue: number | string | object\n\t}) => string | null | undefined\n}\n\n/**\n * Reassemble the client button labels from the document's top-level `submitLabel`/`prevLabel`/\n * `nextLabel` fields, keeping only non-empty strings (mirroring the client's own `storedLabel`\n * fallback). Returns `undefined` when the author set no label, so the client uses its defaults.\n */\nconst buttonSettingsOf = (form: {\n\tsubmitLabel?: string | null\n\tprevLabel?: string | null\n\tnextLabel?: string | null\n}): FormButtonSettings | undefined => {\n\tconst label = (value: unknown): string | undefined =>\n\t\ttypeof value === 'string' && value.length > 0 ? value : undefined\n\tconst settings: FormButtonSettings = {}\n\tconst submitLabel = label(form.submitLabel)\n\tconst prevLabel = label(form.prevLabel)\n\tconst nextLabel = label(form.nextLabel)\n\tif (submitLabel !== undefined) settings.submitLabel = submitLabel\n\tif (prevLabel !== undefined) settings.prevLabel = prevLabel\n\tif (nextLabel !== undefined) settings.nextLabel = nextLabel\n\treturn Object.keys(settings).length > 0 ? settings : undefined\n}\n\n/**\n * Narrows a Payload-generated form document (from `getPayload().findByID()` or `fetch`) to\n * `FormDocument` without an unsafe `as` cast. Handles the small structural mismatches between\n * the auto-generated collection types and what `<Form>` expects:\n * - `fields` may be a typed blocks-union array or null; normalized to `FormFieldInstance[]`\n * (nameless bare rows, e.g. message blocks, pass through with their row `id` intact)\n * - `flow` is stored as opaque JSON; typed as `FormFlow | undefined`\n * - `response` may be null; coerced to `undefined`, otherwise passed through wholesale, which\n * includes `response.redirect.reference` (present only when the plugin's `redirectRelationships`\n * option is set): `value` may be a bare id (`depth: 0`) or a populated document, and the host\n * resolves it to a URL either by writing `redirect.url` or by passing `options.resolveRedirect`\n * - the button labels (`submitLabel`/`prevLabel`/`nextLabel`) live at the document root now (there\n * is no `buttons` group); the non-empty ones are reassembled into `FormDocument.buttons`\n * - `title` may be null; coerced to `undefined`\n * - `multistep`/`pollEnabled` are the two top-level form-type flags, coerced to strict booleans\n * - `poll` may be null; coerced to `undefined` (`resultsField`, `optionSource`, and\n * `sourceConfig` are dropped: server-side only; `outcome` passes through `winningValues` only)\n *\n * Unknown keys survive on `response` but not on `poll`, which is deliberate rather than incidental.\n * `response` is a visitor-facing group a host is meant to extend (`overrides.forms.fields`) and read\n * back off `FormDocument` in custom chrome, so it is cast wholesale. `poll` is plugin-owned config\n * that is split between\n * client-safe lifecycle state and server-only members, so it is rebuilt from an allowlist: a\n * passthrough would ship whatever a host put in `sourceConfig` (domain config, ids, credentials)\n * to every anonymous visitor. Adding a client-visible poll member means naming it here.\n *\n * Pure and framework-agnostic (no 'use client'): safe to call from a Server Component or any\n * other server-side code before handing the result to the client `<Form>`.\n */\nexport function toFormDocument(\n\tform: {\n\t\tid: number | string\n\t\tfields?: { blockType: string; name?: string; [key: string]: unknown }[] | null\n\t\tflow?: unknown\n\t\tresponse?: {\n\t\t\ttype?: string | null\n\t\t\tmessage?: unknown\n\t\t\tredirect?: {\n\t\t\t\turl?: string | null\n\t\t\t\treference?: { relationTo?: string | null; value?: number | string | object | null } | null\n\t\t\t} | null\n\t\t} | null\n\t\tsubmitLabel?: string | null\n\t\tprevLabel?: string | null\n\t\tnextLabel?: string | null\n\t\ttitle?: string | null\n\t\tmultistep?: boolean | null\n\t\tpollEnabled?: boolean | null\n\t\tpoll?: {\n\t\t\tresultsField?: string | null\n\t\t\tresultsVisibility?: string | null\n\t\t\tclosesAt?: string | null\n\t\t\tallowChange?: boolean | null\n\t\t\toutcome?: { winningValues?: (string | null)[] | null } | null\n\t\t} | null\n\t\t/**\n\t\t * Consent statements resolved onto the doc by the plugin's forms `afterRead` hook (when\n\t\t * `consent.sources` is set), so consent renders on any fetch path (modal/client, not just RSC).\n\t\t * An explicit `options.consentStatements` takes precedence when both are present.\n\t\t */\n\t\tconsentStatements?: ConsentStatements\n\t\t/**\n\t\t * Calc source values resolved onto the doc by the plugin's forms `afterRead` hook (when calc\n\t\t * sources are registered and used); passed through so the client's live preview computes with\n\t\t * real values. `functions` can never ride a document, hence the Pick.\n\t\t */\n\t\tcalcResolved?: Pick<CalcResolved, 'sources' | 'weights'>\n\t},\n\toptions?: ToFormDocumentOptions\n): FormDocument {\n\tconst rawWinningValues = form.poll?.outcome?.winningValues\n\tconst winningValues = Array.isArray(rawWinningValues)\n\t\t? rawWinningValues.filter(\n\t\t\t\t(value): value is string => typeof value === 'string' && value.length > 0\n\t\t\t)\n\t\t: []\n\tconst poll = form.poll\n\t\t? {\n\t\t\t\tresultsVisibility: (form.poll.resultsVisibility ?? undefined) as\n\t\t\t\t\t| 'afterVote'\n\t\t\t\t\t| 'afterClose'\n\t\t\t\t\t| undefined,\n\t\t\t\tclosesAt: form.poll.closesAt ?? undefined,\n\t\t\t\t...(form.poll.allowChange === true ? { allowChange: true } : {}),\n\t\t\t\t...(winningValues.length > 0 ? { outcome: { winningValues } } : {}),\n\t\t\t}\n\t\t: undefined\n\tlet fields = (form.fields ?? []) as FormFieldInstance[]\n\tif (options?.pollOptions) {\n\t\tfields = applyPollOptions(fields, form.poll?.resultsField, options.pollOptions)\n\t}\n\tconst consentStatements = options?.consentStatements ?? form.consentStatements\n\tif (consentStatements) {\n\t\tfields = applyConsentStatements(fields, consentStatements)\n\t}\n\tlet response = (form.response as FormResponseSettings | null | undefined) ?? undefined\n\t// A host that passes `resolveRedirect` gets internal references turned into `redirect.url` (all\n\t// `<Form>` navigates by), but only when the author set no explicit url. Non-mutating: clone the group.\n\tif (\n\t\toptions?.resolveRedirect &&\n\t\tresponse?.type === 'redirect' &&\n\t\tresponse.redirect?.reference &&\n\t\t!response.redirect.url\n\t) {\n\t\tconst url = options.resolveRedirect(response.redirect.reference)\n\t\tif (url) {\n\t\t\tresponse = { ...response, redirect: { ...response.redirect, url } }\n\t\t}\n\t}\n\treturn {\n\t\tid: form.id,\n\t\tfields,\n\t\tflow: form.flow as FormFlow | undefined,\n\t\tresponse,\n\t\tbuttons: buttonSettingsOf(form),\n\t\ttitle: form.title ?? undefined,\n\t\tmultistep: form.multistep === true,\n\t\tpollEnabled: form.pollEnabled === true,\n\t\tpoll,\n\t\tcalcResolved: form.calcResolved,\n\t}\n}\n"],"mappings":";;;;;;;;AAwCA,MAAM,oBAAoB,SAIY;CACrC,MAAM,SAAS,UACd,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;CACzD,MAAM,WAA+B,CAAC;CACtC,MAAM,cAAc,MAAM,KAAK,WAAW;CAC1C,MAAM,YAAY,MAAM,KAAK,SAAS;CACtC,MAAM,YAAY,MAAM,KAAK,SAAS;CACtC,IAAI,gBAAgB,KAAA,GAAW,SAAS,cAAc;CACtD,IAAI,cAAc,KAAA,GAAW,SAAS,YAAY;CAClD,IAAI,cAAc,KAAA,GAAW,SAAS,YAAY;CAClD,OAAO,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAI,WAAW,KAAA;AACtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,eACf,MAsCA,SACe;CACf,MAAM,mBAAmB,KAAK,MAAM,SAAS;CAC7C,MAAM,gBAAgB,MAAM,QAAQ,gBAAgB,IACjD,iBAAiB,QAChB,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CACzE,IACC,CAAC;CACJ,MAAM,OAAO,KAAK,OACf;EACA,mBAAoB,KAAK,KAAK,qBAAqB,KAAA;EAInD,UAAU,KAAK,KAAK,YAAY,KAAA;EAChC,GAAI,KAAK,KAAK,gBAAgB,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;EAC9D,GAAI,cAAc,SAAS,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,CAAC;CAClE,IACC,KAAA;CACH,IAAI,SAAU,KAAK,UAAU,CAAC;CAC9B,IAAI,SAAS,aACZ,SAAS,iBAAiB,QAAQ,KAAK,MAAM,cAAc,QAAQ,WAAW;CAE/E,MAAM,oBAAoB,SAAS,qBAAqB,KAAK;CAC7D,IAAI,mBACH,SAAS,uBAAuB,QAAQ,iBAAiB;CAE1D,IAAI,WAAY,KAAK,YAAwD,KAAA;CAG7E,IACC,SAAS,mBACT,UAAU,SAAS,cACnB,SAAS,UAAU,aACnB,CAAC,SAAS,SAAS,KAClB;EACD,MAAM,MAAM,QAAQ,gBAAgB,SAAS,SAAS,SAAS;EAC/D,IAAI,KACH,WAAW;GAAE,GAAG;GAAU,UAAU;IAAE,GAAG,SAAS;IAAU;GAAI;EAAE;CAEpE;CACA,OAAO;EACN,IAAI,KAAK;EACT;EACA,MAAM,KAAK;EACX;EACA,SAAS,iBAAiB,IAAI;EAC9B,OAAO,KAAK,SAAS,KAAA;EACrB,WAAW,KAAK,cAAc;EAC9B,aAAa,KAAK,gBAAgB;EAClC;EACA,cAAc,KAAK;CACpB;AACD"}