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

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 (356) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +3 -3
  3. package/dist/actions/body/serializeBody.d.ts +8 -5
  4. package/dist/actions/body/serializeBody.js.map +1 -1
  5. package/dist/actions/body/textOfBody.d.ts +13 -0
  6. package/dist/actions/body/textOfBody.js +35 -0
  7. package/dist/actions/body/textOfBody.js.map +1 -0
  8. package/dist/actions/builtin/confirmation.js +41 -11
  9. package/dist/actions/builtin/confirmation.js.map +1 -1
  10. package/dist/actions/builtin/emailTeam.js +77 -38
  11. package/dist/actions/builtin/emailTeam.js.map +1 -1
  12. package/dist/actions/builtin/index.d.ts +8 -3
  13. package/dist/actions/builtin/index.js +8 -5
  14. package/dist/actions/builtin/index.js.map +1 -1
  15. package/dist/actions/defineAction.d.ts +1 -1
  16. package/dist/actions/fromAddresses.d.ts +21 -0
  17. package/dist/actions/fromAddresses.js +74 -0
  18. package/dist/actions/fromAddresses.js.map +1 -0
  19. package/dist/actions/task.js +9 -8
  20. package/dist/actions/task.js.map +1 -1
  21. package/dist/aggregation/aggregateResponses.d.ts +9 -0
  22. package/dist/aggregation/aggregateResponses.js +8 -14
  23. package/dist/aggregation/aggregateResponses.js.map +1 -1
  24. package/dist/aggregation/resolveResultsRequest.d.ts +19 -6
  25. package/dist/aggregation/resolveResultsRequest.js +58 -12
  26. package/dist/aggregation/resolveResultsRequest.js.map +1 -1
  27. package/dist/calc/computeCalcFields.js +2 -1
  28. package/dist/calc/computeCalcFields.js.map +1 -1
  29. package/dist/client/ByteSizeField.d.ts +8 -0
  30. package/dist/client/ByteSizeField.js +3 -1
  31. package/dist/client/ByteSizeField.js.map +1 -1
  32. package/dist/client/ClosePollButton.d.ts +15 -0
  33. package/dist/client/ClosePollButton.js +80 -0
  34. package/dist/client/ClosePollButton.js.map +1 -0
  35. package/dist/client/CondensedArray.d.ts +15 -0
  36. package/dist/client/CondensedArray.js +97 -0
  37. package/dist/client/CondensedArray.js.map +1 -0
  38. package/dist/client/EndpointOptionsSelect.d.ts +45 -0
  39. package/dist/client/EndpointOptionsSelect.js +103 -0
  40. package/dist/client/EndpointOptionsSelect.js.map +1 -0
  41. package/dist/client/FieldBlockLabel.d.ts +18 -0
  42. package/dist/client/FieldBlockLabel.js +34 -0
  43. package/dist/client/FieldBlockLabel.js.map +1 -0
  44. package/dist/client/FieldNameSelect.d.ts +20 -4
  45. package/dist/client/FieldNameSelect.js +25 -14
  46. package/dist/client/FieldNameSelect.js.map +1 -1
  47. package/dist/client/FlowBuilder.d.ts +2 -1
  48. package/dist/client/FlowBuilder.js +63 -57
  49. package/dist/client/FlowBuilder.js.map +1 -1
  50. package/dist/client/RuleDescription.d.ts +21 -0
  51. package/dist/client/RuleDescription.js +19 -0
  52. package/dist/client/RuleDescription.js.map +1 -0
  53. package/dist/client/admin.css +36 -0
  54. package/dist/client/endpointOptions.js +29 -0
  55. package/dist/client/endpointOptions.js.map +1 -0
  56. package/dist/client/flowAuthoring.js +114 -7
  57. package/dist/client/flowAuthoring.js.map +1 -1
  58. package/dist/client/synthesizeClientField.js +15 -8
  59. package/dist/client/synthesizeClientField.js.map +1 -1
  60. package/dist/collections/buttonFields.d.ts +34 -0
  61. package/dist/collections/buttonFields.js +35 -0
  62. package/dist/collections/buttonFields.js.map +1 -0
  63. package/dist/collections/cells/FieldCountCell.d.ts +15 -0
  64. package/dist/collections/cells/FieldCountCell.js +18 -0
  65. package/dist/collections/cells/FieldCountCell.js.map +1 -0
  66. package/dist/collections/cells/FlowStepsCell.d.ts +14 -0
  67. package/dist/collections/cells/FlowStepsCell.js +17 -0
  68. package/dist/collections/cells/FlowStepsCell.js.map +1 -0
  69. package/dist/collections/formSubmissions.js +22 -17
  70. package/dist/collections/formSubmissions.js.map +1 -1
  71. package/dist/collections/forms.js +310 -137
  72. package/dist/collections/forms.js.map +1 -1
  73. package/dist/collections/redirectFields.d.ts +29 -0
  74. package/dist/consent/applyConsentStatements.d.ts +14 -0
  75. package/dist/consent/applyConsentStatements.js +17 -0
  76. package/dist/consent/applyConsentStatements.js.map +1 -0
  77. package/dist/consent/captureConsent.d.ts +19 -8
  78. package/dist/consent/captureConsent.js +34 -11
  79. package/dist/consent/captureConsent.js.map +1 -1
  80. package/dist/consent/consentSourcesField.d.ts +58 -0
  81. package/dist/consent/consentSourcesField.js +79 -0
  82. package/dist/consent/consentSourcesField.js.map +1 -0
  83. package/dist/consent/resolveConsentEntries.d.ts +24 -0
  84. package/dist/consent/resolveConsentEntries.js +43 -0
  85. package/dist/consent/resolveConsentEntries.js.map +1 -0
  86. package/dist/consent/resolveConsentSourcesRequest.d.ts +37 -0
  87. package/dist/consent/resolveConsentSourcesRequest.js +55 -0
  88. package/dist/consent/resolveConsentSourcesRequest.js.map +1 -0
  89. package/dist/consent/resolveConsentStatements.d.ts +45 -0
  90. package/dist/consent/resolveConsentStatements.js +44 -0
  91. package/dist/consent/resolveConsentStatements.js.map +1 -0
  92. package/dist/consent/resolvePublishedVersionRef.d.ts +17 -11
  93. package/dist/consent/resolvePublishedVersionRef.js +13 -10
  94. package/dist/consent/resolvePublishedVersionRef.js.map +1 -1
  95. package/dist/consent/types.d.ts +49 -0
  96. package/dist/email/departments.d.ts +55 -0
  97. package/dist/email/departments.js +130 -0
  98. package/dist/email/departments.js.map +1 -0
  99. package/dist/email/departmentsField.d.ts +49 -0
  100. package/dist/email/departmentsField.js +69 -0
  101. package/dist/email/departmentsField.js.map +1 -0
  102. package/dist/exports/client.d.ts +8 -1
  103. package/dist/exports/client.js +8 -1
  104. package/dist/exports/react.d.ts +8 -3
  105. package/dist/exports/react.js +6 -2
  106. package/dist/exports/rsc.d.ts +3 -1
  107. package/dist/exports/rsc.js +4 -2
  108. package/dist/exports/types.d.ts +16 -8
  109. package/dist/fields/buildFieldBlocks.js +28 -13
  110. package/dist/fields/buildFieldBlocks.js.map +1 -1
  111. package/dist/fields/builtin/calculation.js +7 -0
  112. package/dist/fields/builtin/calculation.js.map +1 -1
  113. package/dist/fields/builtin/checkbox.js +8 -0
  114. package/dist/fields/builtin/checkbox.js.map +1 -1
  115. package/dist/fields/builtin/consent.js +27 -21
  116. package/dist/fields/builtin/consent.js.map +1 -1
  117. package/dist/fields/builtin/country.d.ts +13 -0
  118. package/dist/fields/builtin/country.js +30 -0
  119. package/dist/fields/builtin/country.js.map +1 -0
  120. package/dist/fields/builtin/date.js +2 -0
  121. package/dist/fields/builtin/date.js.map +1 -1
  122. package/dist/fields/builtin/file.js +5 -4
  123. package/dist/fields/builtin/file.js.map +1 -1
  124. package/dist/fields/builtin/index.d.ts +8 -6
  125. package/dist/fields/builtin/index.js +10 -9
  126. package/dist/fields/builtin/index.js.map +1 -1
  127. package/dist/fields/builtin/message.js +8 -4
  128. package/dist/fields/builtin/message.js.map +1 -1
  129. package/dist/fields/builtin/repeater.js +1 -0
  130. package/dist/fields/builtin/repeater.js.map +1 -1
  131. package/dist/fields/builtin/select.js +1 -0
  132. package/dist/fields/builtin/select.js.map +1 -1
  133. package/dist/fields/builtin/state.d.ts +13 -0
  134. package/dist/fields/builtin/state.js +30 -0
  135. package/dist/fields/builtin/state.js.map +1 -0
  136. package/dist/fields/data/regions.d.ts +21 -0
  137. package/dist/fields/data/regions.js +1238 -0
  138. package/dist/fields/data/regions.js.map +1 -0
  139. package/dist/fields/fieldKey.d.ts +15 -0
  140. package/dist/fields/fieldKey.js +16 -0
  141. package/dist/fields/fieldKey.js.map +1 -0
  142. package/dist/fields/fieldNamesOfType.js +13 -8
  143. package/dist/fields/fieldNamesOfType.js.map +1 -1
  144. package/dist/fields/instanceOptions.js +20 -0
  145. package/dist/fields/instanceOptions.js.map +1 -0
  146. package/dist/fields/registry.d.ts +1 -0
  147. package/dist/fields/registry.js +21 -2
  148. package/dist/fields/registry.js.map +1 -1
  149. package/dist/fields/sharedConfig.js +46 -9
  150. package/dist/fields/sharedConfig.js.map +1 -1
  151. package/dist/fields/types.d.ts +54 -3
  152. package/dist/flow/engine.d.ts +6 -4
  153. package/dist/flow/engine.js +11 -6
  154. package/dist/flow/engine.js.map +1 -1
  155. package/dist/flow/normalizeFlow.js +16 -7
  156. package/dist/flow/normalizeFlow.js.map +1 -1
  157. package/dist/flow/types.d.ts +12 -3
  158. package/dist/flow/types.js +11 -0
  159. package/dist/flow/types.js.map +1 -0
  160. package/dist/form/pollState.d.ts +4 -4
  161. package/dist/form/pollState.js.map +1 -1
  162. package/dist/form/toFormDocument.d.ts +37 -12
  163. package/dist/form/toFormDocument.js +43 -7
  164. package/dist/form/toFormDocument.js.map +1 -1
  165. package/dist/form/types.d.ts +31 -14
  166. package/dist/index.d.ts +143 -28
  167. package/dist/index.js +43 -14
  168. package/dist/index.js.map +1 -1
  169. package/dist/plugin/customState.js +26 -0
  170. package/dist/plugin/customState.js.map +1 -0
  171. package/dist/plugin/registerCollections.js +23 -13
  172. package/dist/plugin/registerCollections.js.map +1 -1
  173. package/dist/plugin/uploadsCollection.d.ts +2 -0
  174. package/dist/poll/applyPollOptions.js +3 -2
  175. package/dist/poll/applyPollOptions.js.map +1 -1
  176. package/dist/poll/buildPollOptionSourceFields.js +2 -5
  177. package/dist/poll/buildPollOptionSourceFields.js.map +1 -1
  178. package/dist/poll/closeJob.d.ts +52 -0
  179. package/dist/poll/closeJob.js +119 -0
  180. package/dist/poll/closeJob.js.map +1 -0
  181. package/dist/poll/definePollOptionSource.d.ts +10 -1
  182. package/dist/poll/definePollOptionSource.js.map +1 -1
  183. package/dist/poll/definePollType.d.ts +34 -0
  184. package/dist/poll/definePollType.js +6 -0
  185. package/dist/poll/definePollType.js.map +1 -0
  186. package/dist/poll/effectivePollOptions.d.ts +38 -0
  187. package/dist/poll/effectivePollOptions.js +64 -0
  188. package/dist/poll/effectivePollOptions.js.map +1 -0
  189. package/dist/poll/mostVoted.d.ts +21 -0
  190. package/dist/poll/mostVoted.js +32 -0
  191. package/dist/poll/mostVoted.js.map +1 -0
  192. package/dist/poll/outcomeBeforeChange.js +91 -0
  193. package/dist/poll/outcomeBeforeChange.js.map +1 -0
  194. package/dist/poll/outcomeFields.d.ts +38 -0
  195. package/dist/poll/outcomeFields.js +52 -0
  196. package/dist/poll/outcomeFields.js.map +1 -0
  197. package/dist/poll/pollTypeRegistry.d.ts +34 -0
  198. package/dist/poll/pollTypeRegistry.js +71 -0
  199. package/dist/poll/pollTypeRegistry.js.map +1 -0
  200. package/dist/poll/resolvePollCloseRequest.js +105 -0
  201. package/dist/poll/resolvePollCloseRequest.js.map +1 -0
  202. package/dist/poll/resolvePollOptions.d.ts +2 -1
  203. package/dist/poll/resolvePollOptions.js +5 -17
  204. package/dist/poll/resolvePollOptions.js.map +1 -1
  205. package/dist/poll/resolvePollOptionsRequest.js +51 -0
  206. package/dist/poll/resolvePollOptionsRequest.js.map +1 -0
  207. package/dist/poll/resolvePollOutcome.d.ts +22 -9
  208. package/dist/poll/resolvePollOutcome.js +54 -14
  209. package/dist/poll/resolvePollOutcome.js.map +1 -1
  210. package/dist/poll/resultsField.js +21 -0
  211. package/dist/poll/resultsField.js.map +1 -0
  212. package/dist/prefill/valuesFromSearchParams.js +2 -1
  213. package/dist/prefill/valuesFromSearchParams.js.map +1 -1
  214. package/dist/react/Form.d.ts +8 -8
  215. package/dist/react/Form.js +74 -62
  216. package/dist/react/Form.js.map +1 -1
  217. package/dist/react/FormContext.d.ts +6 -4
  218. package/dist/react/FormContext.js.map +1 -1
  219. package/dist/react/FormControls.d.ts +3 -3
  220. package/dist/react/FormControls.js +3 -3
  221. package/dist/react/FormControls.js.map +1 -1
  222. package/dist/react/FormResults.d.ts +5 -5
  223. package/dist/react/FormResults.js +6 -6
  224. package/dist/react/FormResults.js.map +1 -1
  225. package/dist/react/Poll.d.ts +2 -2
  226. package/dist/react/Poll.js +5 -5
  227. package/dist/react/Poll.js.map +1 -1
  228. package/dist/react/contract.d.ts +2 -3
  229. package/dist/react/contract.js.map +1 -1
  230. package/dist/react/primitives/Checkbox.d.ts +4 -2
  231. package/dist/react/primitives/Checkbox.js +2 -1
  232. package/dist/react/primitives/Checkbox.js.map +1 -1
  233. package/dist/react/primitives/FieldShell.d.ts +2 -4
  234. package/dist/react/primitives/FieldShell.js +12 -19
  235. package/dist/react/primitives/FieldShell.js.map +1 -1
  236. package/dist/react/renderers/calculation.js +1 -2
  237. package/dist/react/renderers/calculation.js.map +1 -1
  238. package/dist/react/renderers/checkbox.js +1 -2
  239. package/dist/react/renderers/checkbox.js.map +1 -1
  240. package/dist/react/renderers/consent.js +78 -34
  241. package/dist/react/renderers/consent.js.map +1 -1
  242. package/dist/react/renderers/date.js +1 -3
  243. package/dist/react/renderers/date.js.map +1 -1
  244. package/dist/react/renderers/email.js +1 -2
  245. package/dist/react/renderers/email.js.map +1 -1
  246. package/dist/react/renderers/file.js +1 -2
  247. package/dist/react/renderers/file.js.map +1 -1
  248. package/dist/react/renderers/index.js +3 -0
  249. package/dist/react/renderers/index.js.map +1 -1
  250. package/dist/react/renderers/number.js +1 -2
  251. package/dist/react/renderers/number.js.map +1 -1
  252. package/dist/react/renderers/region.js +45 -0
  253. package/dist/react/renderers/region.js.map +1 -0
  254. package/dist/react/renderers/repeater.js +7 -10
  255. package/dist/react/renderers/repeater.js.map +1 -1
  256. package/dist/react/renderers/select.js +1 -2
  257. package/dist/react/renderers/select.js.map +1 -1
  258. package/dist/react/renderers/text.js +1 -2
  259. package/dist/react/renderers/text.js.map +1 -1
  260. package/dist/react/renderers/textarea.js +1 -2
  261. package/dist/react/renderers/textarea.js.map +1 -1
  262. package/dist/react/state.d.ts +0 -3
  263. package/dist/react/state.js +7 -11
  264. package/dist/react/state.js.map +1 -1
  265. package/dist/react/useField.d.ts +0 -1
  266. package/dist/react/useField.js +0 -1
  267. package/dist/react/useField.js.map +1 -1
  268. package/dist/react/useFormState.d.ts +1 -1
  269. package/dist/react/useFormState.js +1 -1
  270. package/dist/react/useFormState.js.map +1 -1
  271. package/dist/react/validateField.js +3 -6
  272. package/dist/react/validateField.js.map +1 -1
  273. package/dist/recall/interpolate.d.ts +4 -3
  274. package/dist/recall/interpolate.js +5 -4
  275. package/dist/recall/interpolate.js.map +1 -1
  276. package/dist/recall/resolver.d.ts +1 -1
  277. package/dist/recall/resolver.js +14 -2
  278. package/dist/recall/resolver.js.map +1 -1
  279. package/dist/spam/captcha.d.ts +1 -1
  280. package/dist/spam/captcha.js +1 -1
  281. package/dist/spam/captcha.js.map +1 -1
  282. package/dist/submissions/SubmissionAnswers.js +6 -2
  283. package/dist/submissions/SubmissionAnswers.js.map +1 -1
  284. package/dist/submissions/SubmissionAnswersClient.js +91 -62
  285. package/dist/submissions/SubmissionAnswersClient.js.map +1 -1
  286. package/dist/submissions/createSubmission.d.ts +36 -0
  287. package/dist/submissions/createSubmission.js +26 -0
  288. package/dist/submissions/createSubmission.js.map +1 -0
  289. package/dist/submissions/runSubmission.d.ts +10 -0
  290. package/dist/submissions/runSubmission.js +29 -18
  291. package/dist/submissions/runSubmission.js.map +1 -1
  292. package/dist/submissions/types.d.ts +11 -4
  293. package/dist/submissions/validateSubmission.js +38 -23
  294. package/dist/submissions/validateSubmission.js.map +1 -1
  295. package/dist/submissions/votedCookie.js +3 -3
  296. package/dist/submissions/votedCookie.js.map +1 -1
  297. package/dist/translations/de.js +102 -26
  298. package/dist/translations/de.js.map +1 -1
  299. package/dist/translations/en.js +103 -27
  300. package/dist/translations/en.js.map +1 -1
  301. package/dist/translations/keys.d.ts +97 -21
  302. package/dist/translations/keys.js +98 -22
  303. package/dist/translations/keys.js.map +1 -1
  304. package/dist/validation/buildRuleBlocks.js +18 -17
  305. package/dist/validation/buildRuleBlocks.js.map +1 -1
  306. package/dist/validation/builtin/email.js +1 -0
  307. package/dist/validation/builtin/email.js.map +1 -1
  308. package/dist/validation/builtin/matchesField.js +3 -7
  309. package/dist/validation/builtin/matchesField.js.map +1 -1
  310. package/dist/validation/builtin/max.js +1 -0
  311. package/dist/validation/builtin/max.js.map +1 -1
  312. package/dist/validation/builtin/maxDate.js +1 -0
  313. package/dist/validation/builtin/maxDate.js.map +1 -1
  314. package/dist/validation/builtin/maxLength.js +1 -0
  315. package/dist/validation/builtin/maxLength.js.map +1 -1
  316. package/dist/validation/builtin/min.js +1 -0
  317. package/dist/validation/builtin/min.js.map +1 -1
  318. package/dist/validation/builtin/minDate.js +1 -0
  319. package/dist/validation/builtin/minDate.js.map +1 -1
  320. package/dist/validation/builtin/minLength.js +1 -0
  321. package/dist/validation/builtin/minLength.js.map +1 -1
  322. package/dist/validation/builtin/notAlreadySubmitted.js +1 -0
  323. package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -1
  324. package/dist/validation/builtin/oneOf.js +1 -0
  325. package/dist/validation/builtin/oneOf.js.map +1 -1
  326. package/dist/validation/builtin/pattern.js +11 -2
  327. package/dist/validation/builtin/pattern.js.map +1 -1
  328. package/dist/validation/builtin/url.js +1 -0
  329. package/dist/validation/builtin/url.js.map +1 -1
  330. package/dist/validation/builtin/validateRegexParams.js +44 -0
  331. package/dist/validation/builtin/validateRegexParams.js.map +1 -0
  332. package/dist/validation/fieldTargetParam.d.ts +22 -0
  333. package/dist/validation/fieldTargetParam.js +38 -0
  334. package/dist/validation/fieldTargetParam.js.map +1 -0
  335. package/dist/validation/runValidation.js +8 -29
  336. package/dist/validation/runValidation.js.map +1 -1
  337. package/dist/validation/types.d.ts +5 -11
  338. package/package.json +6 -6
  339. package/dist/consent/buildConsentSourceConfig.js +0 -49
  340. package/dist/consent/buildConsentSourceConfig.js.map +0 -1
  341. package/dist/consent/builtin/index.d.ts +0 -17
  342. package/dist/consent/builtin/index.js +0 -21
  343. package/dist/consent/builtin/index.js.map +0 -1
  344. package/dist/consent/builtin/pageReference.js +0 -75
  345. package/dist/consent/builtin/pageReference.js.map +0 -1
  346. package/dist/consent/builtin/static.js +0 -48
  347. package/dist/consent/builtin/static.js.map +0 -1
  348. package/dist/consent/defineConsentSource.d.ts +0 -35
  349. package/dist/consent/defineConsentSource.js +0 -6
  350. package/dist/consent/defineConsentSource.js.map +0 -1
  351. package/dist/consent/registry.d.ts +0 -16
  352. package/dist/consent/registry.js +0 -16
  353. package/dist/consent/registry.js.map +0 -1
  354. package/dist/consent/resolveConsentLinks.d.ts +0 -19
  355. package/dist/consent/resolveConsentLinks.js +0 -26
  356. package/dist/consent/resolveConsentLinks.js.map +0 -1
@@ -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"}
@@ -1,14 +1,14 @@
1
1
  //#region src/form/pollState.d.ts
2
2
  /** Poll settings as loaded from a forms document (server) or a `FormDocument` (client). */
3
3
  type PollConfigLike = {
4
- enabled?: boolean | null;
5
4
  resultsField?: string | null;
6
5
  resultsVisibility?: string | null;
7
- closesAt?: string | null;
6
+ closesAt?: string | null; /** The outcome-resolution strategy slug (`poll.types` registry). Absent is treated as `manual`. */
7
+ type?: string | null;
8
8
  optionSource?: string | null;
9
9
  sourceConfig?: Record<string, unknown> | null;
10
10
  outcome?: {
11
- winningValue?: string | null;
11
+ winningValues?: (string | null)[] | null;
12
12
  resolvedAt?: string | null;
13
13
  } | null;
14
14
  };
@@ -18,5 +18,5 @@ type PollConfigLike = {
18
18
  */
19
19
  declare const isPollClosed: (poll: PollConfigLike | null | undefined, now?: number) => boolean;
20
20
  //#endregion
21
- export { isPollClosed };
21
+ export { PollConfigLike, isPollClosed };
22
22
  //# sourceMappingURL=pollState.d.ts.map
@@ -1 +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\tenabled?: boolean | null\n\tresultsField?: string | null\n\tresultsVisibility?: string | null\n\tclosesAt?: string | null\n\toptionSource?: string | null\n\tsourceConfig?: Record<string, unknown> | null\n\toutcome?: { winningValue?: string | 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":";;AAYA,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"}
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\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":";;AAaA,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"}
@@ -1,4 +1,5 @@
1
1
  import { PollOption } from "../poll/definePollOptionSource.js";
2
+ import { ConsentStatements } from "../consent/resolveConsentStatements.js";
2
3
  import { FormDocument } from "./types.js";
3
4
 
4
5
  //#region src/form/toFormDocument.d.ts
@@ -9,17 +10,38 @@ type ToFormDocumentOptions = {
9
10
  * current choices instead of hand-authored ones.
10
11
  */
11
12
  pollOptions?: PollOption[];
13
+ /**
14
+ * Source-resolved consent statements (from `resolveConsentStatements`), injected into the
15
+ * consent field instances they name. A form stores only a source id, so without these its
16
+ * consent fields render with no statement at all.
17
+ */
18
+ consentStatements?: ConsentStatements;
12
19
  };
13
20
  /**
14
21
  * Narrows a Payload-generated form document (from `getPayload().findByID()` or `fetch`) to
15
22
  * `FormDocument` without an unsafe `as` cast. Handles the small structural mismatches between
16
23
  * the auto-generated collection types and what `<Form>` expects:
17
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)
18
26
  * - `flow` is stored as opaque JSON; typed as `FormFlow | undefined`
19
- * - `response` may be null; coerced to `undefined`
20
- * - `display` may be null; coerced to `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): read the form at `depth: 0` to get Payload's raw `{ relationTo, value }` pair
30
+ * rather than a populated document, since the host is the one who resolves it to a URL
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
21
35
  * - `poll` may be null; coerced to `undefined` (`resultsField`, `optionSource`, and
22
- * `sourceConfig` are dropped: server-side only; `outcome` passes through `winningValue` only)
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.
23
45
  *
24
46
  * Pure and framework-agnostic (no 'use client'): safe to call from a Server Component or any
25
47
  * other server-side code before handing the result to the client `<Form>`.
@@ -28,7 +50,7 @@ declare function toFormDocument(form: {
28
50
  id: number | string;
29
51
  fields?: {
30
52
  blockType: string;
31
- name: string;
53
+ name?: string;
32
54
  [key: string]: unknown;
33
55
  }[] | null;
34
56
  flow?: unknown;
@@ -37,21 +59,24 @@ declare function toFormDocument(form: {
37
59
  message?: unknown;
38
60
  redirect?: {
39
61
  url?: string | null;
62
+ reference?: {
63
+ relationTo?: string | null;
64
+ value?: number | string | null;
65
+ } | null;
40
66
  } | null;
41
- submitLabel?: string | null;
42
- } | null;
43
- display?: {
44
- showTitle?: boolean | null;
45
- title?: string | null;
46
- intro?: unknown;
47
67
  } | null;
68
+ submitLabel?: string | null;
69
+ prevLabel?: string | null;
70
+ nextLabel?: string | null;
71
+ title?: string | null;
72
+ multistep?: boolean | null;
73
+ pollEnabled?: boolean | null;
48
74
  poll?: {
49
- enabled?: boolean | null;
50
75
  resultsField?: string | null;
51
76
  resultsVisibility?: string | null;
52
77
  closesAt?: string | null;
53
78
  outcome?: {
54
- winningValue?: string | null;
79
+ winningValues?: (string | null)[] | null;
55
80
  } | null;
56
81
  } | null;
57
82
  }, options?: ToFormDocumentOptions): FormDocument;
@@ -1,35 +1,71 @@
1
1
  import { applyPollOptions } from "../poll/applyPollOptions.js";
2
+ import { applyConsentStatements } from "../consent/applyConsentStatements.js";
2
3
  //#region src/form/toFormDocument.ts
3
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
+ /**
4
21
  * Narrows a Payload-generated form document (from `getPayload().findByID()` or `fetch`) to
5
22
  * `FormDocument` without an unsafe `as` cast. Handles the small structural mismatches between
6
23
  * the auto-generated collection types and what `<Form>` expects:
7
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)
8
26
  * - `flow` is stored as opaque JSON; typed as `FormFlow | undefined`
9
- * - `response` may be null; coerced to `undefined`
10
- * - `display` may be null; coerced to `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): read the form at `depth: 0` to get Payload's raw `{ relationTo, value }` pair
30
+ * rather than a populated document, since the host is the one who resolves it to a URL
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
11
35
  * - `poll` may be null; coerced to `undefined` (`resultsField`, `optionSource`, and
12
- * `sourceConfig` are dropped: server-side only; `outcome` passes through `winningValue` only)
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.
13
45
  *
14
46
  * Pure and framework-agnostic (no 'use client'): safe to call from a Server Component or any
15
47
  * other server-side code before handing the result to the client `<Form>`.
16
48
  */
17
49
  function toFormDocument(form, options) {
18
- const winningValue = form.poll?.outcome?.winningValue;
50
+ const rawWinningValues = form.poll?.outcome?.winningValues;
51
+ const winningValues = Array.isArray(rawWinningValues) ? rawWinningValues.filter((value) => typeof value === "string" && value.length > 0) : [];
19
52
  const poll = form.poll ? {
20
- enabled: form.poll.enabled ?? void 0,
21
53
  resultsVisibility: form.poll.resultsVisibility ?? void 0,
22
54
  closesAt: form.poll.closesAt ?? void 0,
23
- ...typeof winningValue === "string" && winningValue.length > 0 ? { outcome: { winningValue } } : {}
55
+ ...winningValues.length > 0 ? { outcome: { winningValues } } : {}
24
56
  } : void 0;
25
57
  let fields = form.fields ?? [];
26
58
  if (options?.pollOptions) fields = applyPollOptions(fields, form.poll?.resultsField, options.pollOptions);
59
+ if (options?.consentStatements) fields = applyConsentStatements(fields, options.consentStatements);
27
60
  return {
28
61
  id: form.id,
29
62
  fields,
30
63
  flow: form.flow,
31
64
  response: form.response ?? void 0,
32
- display: form.display ?? void 0,
65
+ buttons: buttonSettingsOf(form),
66
+ title: form.title ?? void 0,
67
+ multistep: form.multistep === true,
68
+ pollEnabled: form.pollEnabled === true,
33
69
  poll
34
70
  };
35
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"toFormDocument.js","names":[],"sources":["../../src/form/toFormDocument.ts"],"sourcesContent":["import type { FormFlow } from '../flow/types'\nimport { applyPollOptions } from '../poll/applyPollOptions'\nimport type { PollOption } from '../poll/definePollOptionSource'\nimport type { FormFieldInstance } from '../submissions/types'\nimport type { FormDisplaySettings, 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}\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 * - `flow` is stored as opaque JSON; typed as `FormFlow | undefined`\n * - `response` may be null; coerced to `undefined`\n * - `display` may be null; coerced to `undefined`\n * - `poll` may be null; coerced to `undefined` (`resultsField`, `optionSource`, and\n * `sourceConfig` are dropped: server-side only; `outcome` passes through `winningValue` only)\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?: { url?: string | null } | null\n\t\t\tsubmitLabel?: string | null\n\t\t} | null\n\t\tdisplay?: {\n\t\t\tshowTitle?: boolean | null\n\t\t\ttitle?: string | null\n\t\t\tintro?: unknown\n\t\t} | null\n\t\tpoll?: {\n\t\t\tenabled?: boolean | null\n\t\t\tresultsField?: string | null\n\t\t\tresultsVisibility?: string | null\n\t\t\tclosesAt?: string | null\n\t\t\toutcome?: { winningValue?: string | null } | null\n\t\t} | null\n\t},\n\toptions?: ToFormDocumentOptions\n): FormDocument {\n\tconst winningValue = form.poll?.outcome?.winningValue\n\tconst poll = form.poll\n\t\t? {\n\t\t\t\tenabled: form.poll.enabled ?? undefined,\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...(typeof winningValue === 'string' && winningValue.length > 0\n\t\t\t\t\t? { outcome: { winningValue } }\n\t\t\t\t\t: {}),\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\treturn {\n\t\tid: form.id,\n\t\tfields,\n\t\tflow: form.flow as FormFlow | undefined,\n\t\tresponse: (form.response as FormResponseSettings | null | undefined) ?? undefined,\n\t\tdisplay: (form.display as FormDisplaySettings | null | undefined) ?? undefined,\n\t\tpoll,\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA6BA,SAAgB,eACf,MAuBA,SACe;CACf,MAAM,eAAe,KAAK,MAAM,SAAS;CACzC,MAAM,OAAO,KAAK,OACf;EACA,SAAS,KAAK,KAAK,WAAW,KAAA;EAC9B,mBAAoB,KAAK,KAAK,qBAAqB,KAAA;EAInD,UAAU,KAAK,KAAK,YAAY,KAAA;EAChC,GAAI,OAAO,iBAAiB,YAAY,aAAa,SAAS,IAC3D,EAAE,SAAS,EAAE,aAAa,EAAE,IAC5B,CAAC;CACL,IACC,KAAA;CACH,IAAI,SAAU,KAAK,UAAU,CAAC;CAC9B,IAAI,SAAS,aACZ,SAAS,iBAAiB,QAAQ,KAAK,MAAM,cAAc,QAAQ,WAAW;CAE/E,OAAO;EACN,IAAI,KAAK;EACT;EACA,MAAM,KAAK;EACX,UAAW,KAAK,YAAwD,KAAA;EACxE,SAAU,KAAK,WAAsD,KAAA;EACrE;CACD;AACD"}
1
+ {"version":3,"file":"toFormDocument.js","names":[],"sources":["../../src/form/toFormDocument.ts"],"sourcesContent":["import { applyConsentStatements } from '../consent/applyConsentStatements'\nimport type { ConsentStatements } from '../consent/resolveConsentStatements'\nimport type { FormFlow } from '../flow/types'\nimport { applyPollOptions } from '../poll/applyPollOptions'\nimport type { PollOption } from '../poll/definePollOptionSource'\nimport type { FormFieldInstance } from '../submissions/types'\nimport type { FormButtonSettings, FormDocument, FormResponseSettings } from './types'\n\nexport type ToFormDocumentOptions = {\n\t/**\n\t * Source-resolved poll options (from `resolvePollOptions`), injected as the options of the\n\t * field instance named by the form's `poll.resultsField` so the client renders the host's\n\t * current choices instead of hand-authored ones.\n\t */\n\tpollOptions?: PollOption[]\n\t/**\n\t * Source-resolved consent statements (from `resolveConsentStatements`), injected into the\n\t * consent field instances they name. A form stores only a source id, so without these its\n\t * consent fields render with no statement at all.\n\t */\n\tconsentStatements?: ConsentStatements\n}\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): read the form at `depth: 0` to get Payload's raw `{ relationTo, value }` pair\n * rather than a populated document, since the host is the one who resolves it to a URL\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 | null } | null\n\t\t\t} | null\n\t\t} | null\n\t\tsubmitLabel?: string | null\n\t\tprevLabel?: string | null\n\t\tnextLabel?: string | null\n\t\ttitle?: string | null\n\t\tmultistep?: boolean | null\n\t\tpollEnabled?: boolean | null\n\t\tpoll?: {\n\t\t\tresultsField?: string | null\n\t\t\tresultsVisibility?: string | null\n\t\t\tclosesAt?: string | null\n\t\t\toutcome?: { winningValues?: (string | null)[] | null } | null\n\t\t} | null\n\t},\n\toptions?: ToFormDocumentOptions\n): FormDocument {\n\tconst rawWinningValues = form.poll?.outcome?.winningValues\n\tconst winningValues = Array.isArray(rawWinningValues)\n\t\t? rawWinningValues.filter(\n\t\t\t\t(value): value is string => typeof value === 'string' && value.length > 0\n\t\t\t)\n\t\t: []\n\tconst poll = form.poll\n\t\t? {\n\t\t\t\tresultsVisibility: (form.poll.resultsVisibility ?? undefined) as\n\t\t\t\t\t| 'afterVote'\n\t\t\t\t\t| 'afterClose'\n\t\t\t\t\t| undefined,\n\t\t\t\tclosesAt: form.poll.closesAt ?? undefined,\n\t\t\t\t...(winningValues.length > 0 ? { outcome: { winningValues } } : {}),\n\t\t\t}\n\t\t: undefined\n\tlet fields = (form.fields ?? []) as FormFieldInstance[]\n\tif (options?.pollOptions) {\n\t\tfields = applyPollOptions(fields, form.poll?.resultsField, options.pollOptions)\n\t}\n\tif (options?.consentStatements) {\n\t\tfields = applyConsentStatements(fields, options.consentStatements)\n\t}\n\treturn {\n\t\tid: form.id,\n\t\tfields,\n\t\tflow: form.flow as FormFlow | undefined,\n\t\tresponse: (form.response as FormResponseSettings | null | undefined) ?? undefined,\n\t\tbuttons: buttonSettingsOf(form),\n\t\ttitle: form.title ?? undefined,\n\t\tmultistep: form.multistep === true,\n\t\tpollEnabled: form.pollEnabled === true,\n\t\tpoll,\n\t}\n}\n"],"mappings":";;;;;;;;AA4BA,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,MAyBA,SACe;CACf,MAAM,mBAAmB,KAAK,MAAM,SAAS;CAC7C,MAAM,gBAAgB,MAAM,QAAQ,gBAAgB,IACjD,iBAAiB,QAChB,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CACzE,IACC,CAAC;CACJ,MAAM,OAAO,KAAK,OACf;EACA,mBAAoB,KAAK,KAAK,qBAAqB,KAAA;EAInD,UAAU,KAAK,KAAK,YAAY,KAAA;EAChC,GAAI,cAAc,SAAS,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,CAAC;CAClE,IACC,KAAA;CACH,IAAI,SAAU,KAAK,UAAU,CAAC;CAC9B,IAAI,SAAS,aACZ,SAAS,iBAAiB,QAAQ,KAAK,MAAM,cAAc,QAAQ,WAAW;CAE/E,IAAI,SAAS,mBACZ,SAAS,uBAAuB,QAAQ,QAAQ,iBAAiB;CAElE,OAAO;EACN,IAAI,KAAK;EACT;EACA,MAAM,KAAK;EACX,UAAW,KAAK,YAAwD,KAAA;EACxE,SAAS,iBAAiB,IAAI;EAC9B,OAAO,KAAK,SAAS,KAAA;EACrB,WAAW,KAAK,cAAc;EAC9B,aAAa,KAAK,gBAAgB;EAClC;CACD;AACD"}
@@ -5,17 +5,32 @@ import { FormFlow } from "../flow/types.js";
5
5
  /** Serializable per-form response settings: what the visitor gets after a successful submit. */
6
6
  type FormResponseSettings = {
7
7
  type?: 'message' | 'redirect' | null; /** Rich text state serialized via `serializeBody`; shown instead of the plain `successMessage`. */
8
- message?: unknown; /** Applies on the custom-`children` path too (part of submit handling); `message`/`submitLabel` only affect default rendering. */
8
+ message?: unknown; /** Applies on the custom-`children` path too (part of submit handling); `message` only affects default rendering. */
9
9
  redirect?: {
10
10
  url?: string | null;
11
+ /**
12
+ * Present when the plugin's `redirectRelationships` option is set and the author picked an
13
+ * internal document. Mirrors Payload's depth-0 polymorphic relationship shape (`value` is
14
+ * the bare id, never populated): the HOST resolves this to a URL itself (e.g. by looking up
15
+ * the referenced document's own route), since the plugin has no notion of the host's
16
+ * routing, matching the model of Payload's native `plugin-form-builder` redirect relationship.
17
+ */
18
+ reference?: {
19
+ relationTo: string;
20
+ value: number | string;
21
+ } | null;
11
22
  } | null;
12
- submitLabel?: string | null;
13
23
  };
14
- /** Serializable per-form display settings: what the visitor sees above the fields, before submit. */
15
- type FormDisplaySettings = {
16
- showTitle?: boolean;
17
- title?: string; /** Rich text state serialized via `serializeBody`; rendered above the fields when non-empty. */
18
- intro?: unknown;
24
+ /**
25
+ * Serializable per-form button labels. `toFormDocument` reassembles these from the document's
26
+ * top-level `submitLabel`/`prevLabel`/`nextLabel` fields (there is no longer a `buttons` group).
27
+ * The index signature lets custom chrome read any extra label a host threads on itself.
28
+ */
29
+ type FormButtonSettings = {
30
+ submitLabel?: string | null;
31
+ nextLabel?: string | null;
32
+ prevLabel?: string | null;
33
+ [key: string]: unknown;
19
34
  };
20
35
  /**
21
36
  * Serializable per-form poll settings the client needs for lifecycle rendering (open/voted/closed).
@@ -23,11 +38,10 @@ type FormDisplaySettings = {
23
38
  * itself, so the client never needs it from the document.
24
39
  */
25
40
  type FormPollSettings = {
26
- enabled?: boolean; /** When anonymous callers may read aggregate results. Default 'afterVote'. */
27
- resultsVisibility?: 'afterVote' | 'afterClose' | null; /** ISO date after which submissions are rejected and the poll renders as closed. */
28
- closesAt?: string | null; /** Present once the host recorded a final outcome via `resolvePollOutcome`; `<Poll>` renders the final state. */
41
+ /** When anonymous callers may read aggregate results. Default 'afterVote'. */resultsVisibility?: 'afterVote' | 'afterClose' | null; /** ISO date after which submissions are rejected and the poll renders as closed. */
42
+ closesAt?: string | null; /** Present once the host recorded a final outcome via `resolvePollOutcome`; `<Poll>` renders the final state. A tie carries more than one value. */
29
43
  outcome?: {
30
- winningValue?: string;
44
+ winningValues?: string[];
31
45
  };
32
46
  };
33
47
  /**
@@ -39,10 +53,13 @@ type FormDocument = {
39
53
  id: number | string;
40
54
  fields: FormFieldInstance[];
41
55
  flow?: FormFlow;
42
- response?: FormResponseSettings;
43
- display?: FormDisplaySettings;
56
+ response?: FormResponseSettings; /** Button labels (and any host-added button settings). Label precedence: `<Form>` prop, then this, then the translated default. */
57
+ buttons?: FormButtonSettings; /** The form's admin title (the collection's `useAsTitle` field). Render it, or not: the host decides. */
58
+ title?: string; /** Whether the form uses multi-step (flow) navigation. Drives client step rendering; flow data may still exist when false. */
59
+ multistep: boolean; /** Whether this form is a poll. Gates poll rendering and results; the poll config lives under `poll`. */
60
+ pollEnabled: boolean;
44
61
  poll?: FormPollSettings;
45
62
  };
46
63
  //#endregion
47
- export { FormDisplaySettings, FormDocument, FormPollSettings, FormResponseSettings };
64
+ export { FormButtonSettings, FormDocument, FormPollSettings, FormResponseSettings };
48
65
  //# sourceMappingURL=types.d.ts.map