@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
@@ -1,25 +1,60 @@
1
+ import { fieldNamesOfType } from "../fields/fieldNamesOfType.js";
1
2
  import { localizedIf } from "../fields/localizedIf.js";
2
3
  import { keys } from "../translations/keys.js";
3
- import { labelForKey } from "../translations/server.js";
4
+ import { asTranslate, labelFor, labelForKey } from "../translations/server.js";
5
+ import { resolveFromAddressesRequest } from "../actions/fromAddresses.js";
6
+ import { resolveDepartmentsRequest } from "../email/departments.js";
4
7
  import { validateUrl } from "../validation/validateUrl.js";
5
8
  import { normalizeCalc } from "../calc/normalizeCalc.js";
6
9
  import { isLoggedIn } from "../plugin/access.js";
7
10
  import { buildActionBlocks } from "../actions/buildActionBlocks.js";
11
+ import { resolvePollTypes } from "../poll/pollTypeRegistry.js";
12
+ import { enqueuePollClose } from "../poll/closeJob.js";
8
13
  import { resolveFormResultsRequest } from "../aggregation/resolveResultsRequest.js";
9
14
  import { buildConditionTypeMap } from "../conditions/conditionType.js";
10
15
  import { normalizeFormConditions } from "../conditions/normalizeConditions.js";
16
+ import { resolveConsentSourcesRequest } from "../consent/resolveConsentSourcesRequest.js";
11
17
  import { buildFieldBlocks } from "../fields/buildFieldBlocks.js";
12
18
  import { normalizeFlow } from "../flow/normalizeFlow.js";
19
+ import { END_OF_FORM } from "../flow/types.js";
13
20
  import { buildPollOptionSourceFields } from "../poll/buildPollOptionSourceFields.js";
21
+ import { pollOutcomeBeforeChange } from "../poll/outcomeBeforeChange.js";
22
+ import { buildDefaultOutcomeFields } from "../poll/outcomeFields.js";
23
+ import { resolvePollCloseRequest } from "../poll/resolvePollCloseRequest.js";
24
+ import { resolvePollOptionsRequest } from "../poll/resolvePollOptionsRequest.js";
25
+ import { buildValidateResultsField, pollEligibleTypes } from "../poll/resultsField.js";
26
+ import { buildDefaultButtonFields } from "./buttonFields.js";
14
27
  import { ValidationError } from "payload";
15
28
  //#region src/collections/forms.ts
16
29
  const FORMS_SLUG = "forms";
30
+ /**
31
+ * Require the title in the default locale (and on hosts without localization), but let it be empty in
32
+ * other locales so a localized form falls back to the default-locale title rather than forcing a
33
+ * translation for every locale. Payload's field-level `required` cannot express this: it enforces per
34
+ * write-locale, which would make a title mandatory in every locale and break the documented fallback.
35
+ */
36
+ const validateFormTitle = (value, { req }) => {
37
+ const localization = req.payload.config.localization;
38
+ const defaultLocale = localization ? localization.defaultLocale : void 0;
39
+ if ((defaultLocale === void 0 || req.locale === void 0 || req.locale === defaultLocale) && (typeof value !== "string" || value.trim().length === 0)) return req.t("validation:required");
40
+ return true;
41
+ };
42
+ /**
43
+ * Field-level validation for the raw flow JSON: step ids must be non-empty, unique, and not the
44
+ * reserved `END_OF_FORM` sentinel, and every explicit step-id reference (a string `next`, a
45
+ * transition `to`) must resolve to a known step. `next: null` (explicit end of form) and an
46
+ * absent `next` (fall through to the next step in array order) are always valid. On full-document
47
+ * saves the beforeValidate pass has already run `normalizeFlow` and laundered dangling
48
+ * references, so the unknown-target checks mainly protect partial API updates that send `flow`
49
+ * without `fields`.
50
+ */
17
51
  const validateFlow = (raw) => {
18
52
  if (raw === null || raw === void 0) return true;
19
53
  const r = raw;
20
54
  if (!Array.isArray(r.steps)) return true;
21
55
  const steps = r.steps;
22
56
  if (steps.find((s) => typeof s?.id !== "string" || s.id.length === 0)) return "Flow: every step must have a non-empty ID";
57
+ if (steps.some((s) => s.id === "__end__")) return `Flow: step ID "${END_OF_FORM}" is reserved`;
23
58
  const ids = steps.map((s) => s.id);
24
59
  if (new Set(ids).size !== ids.length) return "Flow: duplicate step IDs found";
25
60
  const idSet = new Set(ids);
@@ -51,17 +86,30 @@ const stampFileCollections = (rows, slug) => {
51
86
  if (Array.isArray(subFields)) stampFileCollections(subFields, slug);
52
87
  }
53
88
  };
54
- const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegistry, actionRegistry = /* @__PURE__ */ new Map(), localizeContent = true, uploadsCollectionSlug, resultsAccess, pollSourceRegistry }) => {
89
+ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentSources, actionRegistry = /* @__PURE__ */ new Map(), localizeContent = true, richText, uploadsCollectionSlug, resultsAccess, pollSourceRegistry, pollTypeRegistry, outcomeFields, buttons, response, fromAddresses, departments, redirectRelationships }) => {
55
90
  const conditionTypes = buildConditionTypeMap(registry);
91
+ const pollTypes = pollTypeRegistry ?? resolvePollTypes();
92
+ const pollResultsTypes = pollEligibleTypes(registry);
93
+ const bareTypes = new Set([...registry.values()].filter((d) => d.bare === true).map((d) => d.type));
94
+ const bareTypeLabels = Object.fromEntries([...registry.values()].filter((d) => d.bare === true).map((d) => [d.type, d.label]));
56
95
  const FLOW_BUILDER_REF = "@10x-media/form-builder/client#FlowBuilder";
96
+ const FIELD_NAME_SELECT_REF = "@10x-media/form-builder/client#FieldNameSelect";
97
+ const FLOW_STEPS_CELL_REF = "@10x-media/form-builder/client#FlowStepsCell";
98
+ const FIELD_COUNT_CELL_REF = "@10x-media/form-builder/client#FieldCountCell";
99
+ const CLOSE_POLL_BUTTON_REF = "@10x-media/form-builder/client#ClosePollButton";
100
+ const hasOptionSources = (pollSourceRegistry?.size ?? 0) > 0;
101
+ const orderedPollTypes = [...[...pollTypes.values()].filter((strategy) => strategy.type === "mostVoted"), ...[...pollTypes.values()].filter((strategy) => strategy.type !== "mostVoted")];
57
102
  const beforeValidate = ({ data, req }) => {
58
103
  if (data && Array.isArray(data.fields)) {
59
104
  const normalized = normalizeFormConditions(data.fields, conditionTypes);
60
105
  for (const field of normalized) if ("expression" in field) field.expression = normalizeCalc(field.expression);
61
106
  if (uploadsCollectionSlug) stampFileCollections(normalized, uploadsCollectionSlug);
62
107
  data.fields = normalized;
63
- const fieldNames = normalized.map((field) => typeof field.name === "string" ? field.name : void 0).filter((name) => name !== void 0);
64
- const normalizedFlow = normalizeFlow(data.flow, fieldNames);
108
+ const fieldKeys = normalized.map((field) => {
109
+ if (typeof field.name === "string" && field.name.length > 0) return field.name;
110
+ return bareTypes.has(field.blockType) && field.id != null ? String(field.id) : void 0;
111
+ }).filter((key) => key !== void 0);
112
+ const normalizedFlow = normalizeFlow(data.flow, fieldKeys);
65
113
  if (providedFlowStepCount(data.flow) > 0 && normalizedFlow === void 0) throw new ValidationError({
66
114
  collection: FORMS_SLUG,
67
115
  errors: [{
@@ -70,27 +118,64 @@ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegist
70
118
  }]
71
119
  }, req.t);
72
120
  data.flow = normalizedFlow;
121
+ if (data.pollEnabled === true) {
122
+ const poll = data.poll != null && typeof data.poll === "object" ? data.poll : {};
123
+ const resultsField = typeof poll.resultsField === "string" ? poll.resultsField.trim() : "";
124
+ const sourceDriven = (typeof poll.optionSource === "string" ? poll.optionSource.trim() : "").length > 0 || poll.type === "source";
125
+ if (resultsField.length === 0 && !sourceDriven) {
126
+ const eligible = fieldNamesOfType(data.fields, pollResultsTypes);
127
+ if (eligible.length === 1) data.poll = {
128
+ ...poll,
129
+ resultsField: eligible[0]
130
+ };
131
+ else {
132
+ const messageKey = eligible.length > 1 ? keys.pollVoteFieldChoose : keys.pollVoteFieldMissing;
133
+ throw new ValidationError({
134
+ collection: FORMS_SLUG,
135
+ errors: [{
136
+ path: "poll.resultsField",
137
+ message: asTranslate(req.t)(messageKey)
138
+ }]
139
+ }, req.t);
140
+ }
141
+ }
142
+ }
73
143
  }
74
144
  return data;
75
145
  };
146
+ const pollCloseAfterChange = async ({ doc, req }) => {
147
+ await enqueuePollClose({
148
+ payload: req.payload,
149
+ form: doc,
150
+ req
151
+ });
152
+ return doc;
153
+ };
154
+ const pollTypeOptionLabel = (label) => typeof label === "string" ? labelFor(label) : label;
76
155
  const fieldsField = {
77
156
  name: "fields",
78
157
  type: "blocks",
79
158
  blocks: buildFieldBlocks({
80
159
  registry,
81
160
  ruleRegistry,
82
- consentRegistry,
83
161
  localize: localizeContent
84
- })
162
+ }),
163
+ admin: { components: { Cell: FIELD_COUNT_CELL_REF } }
85
164
  };
86
165
  const flowField = {
87
166
  name: "flow",
88
167
  type: "json",
89
168
  validate: validateFlow,
90
- admin: { components: { Field: {
91
- path: FLOW_BUILDER_REF,
92
- clientProps: { conditionTypes }
93
- } } },
169
+ admin: { components: {
170
+ Cell: FLOW_STEPS_CELL_REF,
171
+ Field: {
172
+ path: FLOW_BUILDER_REF,
173
+ clientProps: {
174
+ conditionTypes,
175
+ bareTypeLabels
176
+ }
177
+ }
178
+ } },
94
179
  typescriptSchema: [() => ({
95
180
  type: "object",
96
181
  required: ["steps"],
@@ -108,7 +193,7 @@ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegist
108
193
  type: "array",
109
194
  items: { type: "string" }
110
195
  },
111
- next: { type: "string" },
196
+ next: { type: ["string", "null"] },
112
197
  transitions: {
113
198
  type: "array",
114
199
  items: {
@@ -136,6 +221,20 @@ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegist
136
221
  label: labelForKey(keys.configActions),
137
222
  access: { read: isLoggedIn }
138
223
  };
224
+ const redirectReferenceField = redirectRelationships && redirectRelationships.length > 0 ? [{
225
+ name: "reference",
226
+ type: "relationship",
227
+ relationTo: redirectRelationships,
228
+ label: labelForKey(keys.responseRedirectReference),
229
+ admin: { description: labelForKey(keys.responseRedirectReferenceDescription) }
230
+ }] : [];
231
+ const defaultRedirectFields = [{
232
+ name: "url",
233
+ type: "text",
234
+ label: labelForKey(keys.responseUrl),
235
+ validate: validateUrl
236
+ }, ...redirectReferenceField];
237
+ const redirectFields = response?.redirect?.fields ? response.redirect.fields({ defaultFields: defaultRedirectFields }) : defaultRedirectFields;
139
238
  const responseField = {
140
239
  name: "response",
141
240
  type: "group",
@@ -159,50 +258,104 @@ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegist
159
258
  type: "richText",
160
259
  label: labelForKey(keys.responseMessage),
161
260
  admin: { condition: (_data, siblingData) => siblingData?.type !== "redirect" },
261
+ ...richText?.editor ? { editor: richText.editor } : {},
162
262
  ...localizedIf(localizeContent)
163
263
  },
164
264
  {
165
265
  name: "redirect",
166
266
  type: "group",
167
267
  label: labelForKey(keys.responseRedirect),
168
- admin: { condition: (_data, siblingData) => siblingData?.type === "redirect" },
169
- fields: [{
170
- name: "url",
171
- type: "text",
172
- label: labelForKey(keys.responseUrl),
173
- validate: validateUrl
174
- }]
175
- },
176
- {
177
- name: "submitLabel",
178
- type: "text",
179
- label: labelForKey(keys.responseSubmitLabel),
180
- ...localizedIf(localizeContent)
268
+ admin: {
269
+ condition: (_data, siblingData) => siblingData?.type === "redirect",
270
+ hideGutter: true
271
+ },
272
+ fields: redirectFields
181
273
  }
182
274
  ]
183
275
  };
184
- const displayField = {
185
- name: "display",
276
+ const defaultOutcomeFields = buildDefaultOutcomeFields();
277
+ const defaultButtonFields = buildDefaultButtonFields(localizeContent);
278
+ const halfWidth = (field) => ({
279
+ ...field,
280
+ admin: {
281
+ ...field.admin,
282
+ width: "50%"
283
+ }
284
+ });
285
+ const composedButtons = buttons?.fields ? buttons.fields({ defaultFields: defaultButtonFields }) : defaultButtonFields;
286
+ const submitField = composedButtons.submit;
287
+ const prevNextRow = {
288
+ type: "row",
289
+ admin: { condition: (data) => {
290
+ const steps = data?.flow?.steps;
291
+ return Array.isArray(steps) && steps.length >= 1;
292
+ } },
293
+ fields: [halfWidth(composedButtons.prev), halfWidth(composedButtons.next)]
294
+ };
295
+ const pollGroupField = {
296
+ name: "poll",
186
297
  type: "group",
298
+ label: false,
187
299
  fields: [
188
300
  {
189
- name: "showTitle",
190
- type: "checkbox",
191
- defaultValue: false,
192
- label: labelForKey(keys.displayShowTitle)
301
+ name: "resultsField",
302
+ type: "text",
303
+ label: labelForKey(keys.pollResultsField),
304
+ validate: buildValidateResultsField(pollResultsTypes),
305
+ admin: { components: { Field: {
306
+ path: FIELD_NAME_SELECT_REF,
307
+ clientProps: {
308
+ types: pollResultsTypes,
309
+ descriptionKey: keys.pollResultsFieldDescription
310
+ }
311
+ } } }
193
312
  },
194
313
  {
195
- name: "title",
196
- type: "text",
197
- label: labelForKey(keys.displayTitle),
198
- admin: { condition: (_data, siblingData) => Boolean(siblingData?.showTitle) },
199
- ...localizedIf(localizeContent)
314
+ name: "type",
315
+ type: "select",
316
+ defaultValue: "mostVoted",
317
+ label: labelForKey(keys.pollType),
318
+ admin: {
319
+ isClearable: false,
320
+ description: labelForKey(keys.pollTypeDescription)
321
+ },
322
+ options: orderedPollTypes.filter((strategy) => strategy.type !== "source" || hasOptionSources).map((strategy) => ({
323
+ label: pollTypeOptionLabel(strategy.label),
324
+ value: strategy.type
325
+ }))
200
326
  },
201
327
  {
202
- name: "intro",
203
- type: "richText",
204
- label: labelForKey(keys.displayIntro),
205
- ...localizedIf(localizeContent)
328
+ name: "resultsVisibility",
329
+ type: "select",
330
+ defaultValue: "afterVote",
331
+ label: labelForKey(keys.pollResultsVisibility),
332
+ admin: { isClearable: false },
333
+ options: [{
334
+ label: labelForKey(keys.pollVisibilityAfterVote),
335
+ value: "afterVote"
336
+ }, {
337
+ label: labelForKey(keys.pollVisibilityAfterClose),
338
+ value: "afterClose"
339
+ }]
340
+ },
341
+ {
342
+ name: "closesAt",
343
+ type: "date",
344
+ label: labelForKey(keys.pollClosesAt),
345
+ admin: { date: { pickerAppearance: "dayAndTime" } }
346
+ },
347
+ {
348
+ name: "closePoll",
349
+ type: "ui",
350
+ admin: { components: { Field: CLOSE_POLL_BUTTON_REF } }
351
+ },
352
+ ...buildPollOptionSourceFields(pollSourceRegistry ?? /* @__PURE__ */ new Map()),
353
+ {
354
+ name: "outcome",
355
+ type: "group",
356
+ label: labelForKey(keys.pollOutcome),
357
+ admin: { hideGutter: true },
358
+ fields: outcomeFields ? outcomeFields({ defaultFields: defaultOutcomeFields }) : [defaultOutcomeFields.winningValues, defaultOutcomeFields.resolvedAt]
206
359
  }
207
360
  ]
208
361
  };
@@ -210,23 +363,42 @@ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegist
210
363
  {
211
364
  name: "title",
212
365
  type: "text",
213
- required: true,
214
- label: labelForKey(keys.fieldTitle)
366
+ label: labelForKey(keys.fieldTitle),
367
+ ...localizedIf(localizeContent),
368
+ validate: validateFormTitle
369
+ },
370
+ {
371
+ type: "row",
372
+ fields: [{
373
+ name: "multistep",
374
+ type: "checkbox",
375
+ defaultValue: false,
376
+ label: labelForKey(keys.formMultistep),
377
+ admin: { width: "50%" }
378
+ }, {
379
+ name: "pollEnabled",
380
+ type: "checkbox",
381
+ defaultValue: false,
382
+ label: labelForKey(keys.formPollEnabled),
383
+ admin: { width: "50%" }
384
+ }]
215
385
  },
216
386
  {
217
387
  type: "tabs",
218
388
  tabs: [
219
389
  {
220
390
  label: labelForKey(keys.tabFields),
221
- fields: [fieldsField]
391
+ fields: [fieldsField, submitField]
222
392
  },
223
393
  {
224
- label: labelForKey(keys.tabDisplay),
225
- fields: [displayField]
394
+ label: labelForKey(keys.tabFlow),
395
+ admin: { condition: (_data, siblingData) => siblingData?.multistep === true },
396
+ fields: [flowField, prevNextRow]
226
397
  },
227
398
  {
228
- label: labelForKey(keys.tabFlow),
229
- fields: [flowField]
399
+ label: labelForKey(keys.pollGroup),
400
+ admin: { condition: (_data, siblingData) => siblingData?.pollEnabled === true },
401
+ fields: [pollGroupField]
230
402
  },
231
403
  {
232
404
  label: labelForKey(keys.tabActions),
@@ -237,99 +409,91 @@ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegist
237
409
  fields: [responseField]
238
410
  }
239
411
  ]
412
+ }
413
+ ];
414
+ const defaultEndpoints = [
415
+ {
416
+ path: "/:id/results",
417
+ method: "get",
418
+ handler: async (req) => {
419
+ const field = typeof req.query?.field === "string" ? req.query.field : void 0;
420
+ const { status, body } = await resolveFormResultsRequest({
421
+ payload: req.payload,
422
+ formId: req.routeParams?.id,
423
+ field,
424
+ isAuthed: Boolean(req.user),
425
+ req,
426
+ access: resultsAccess,
427
+ eligibleTypes: pollResultsTypes
428
+ });
429
+ return Response.json(body, { status });
430
+ }
240
431
  },
241
432
  {
242
- name: "poll",
243
- type: "group",
244
- label: labelForKey(keys.pollGroup),
245
- admin: { position: "sidebar" },
246
- fields: [
247
- {
248
- name: "enabled",
249
- type: "checkbox",
250
- defaultValue: false,
251
- label: labelForKey(keys.pollEnabled)
252
- },
253
- {
254
- name: "resultsField",
255
- type: "text",
256
- label: labelForKey(keys.pollResultsField),
257
- admin: {
258
- description: labelForKey(keys.pollResultsFieldDescription),
259
- condition: (_data, siblingData) => Boolean(siblingData?.enabled)
260
- }
261
- },
262
- {
263
- name: "resultsVisibility",
264
- type: "select",
265
- defaultValue: "afterVote",
266
- label: labelForKey(keys.pollResultsVisibility),
267
- admin: {
268
- isClearable: false,
269
- condition: (_data, siblingData) => Boolean(siblingData?.enabled)
270
- },
271
- options: [{
272
- label: labelForKey(keys.pollVisibilityAfterVote),
273
- value: "afterVote"
274
- }, {
275
- label: labelForKey(keys.pollVisibilityAfterClose),
276
- value: "afterClose"
277
- }]
278
- },
279
- {
280
- name: "closesAt",
281
- type: "date",
282
- label: labelForKey(keys.pollClosesAt),
283
- admin: {
284
- date: { pickerAppearance: "dayAndTime" },
285
- condition: (_data, siblingData) => Boolean(siblingData?.enabled)
286
- }
287
- },
288
- ...buildPollOptionSourceFields(pollSourceRegistry ?? /* @__PURE__ */ new Map()),
289
- {
290
- name: "outcome",
291
- type: "group",
292
- label: labelForKey(keys.pollOutcome),
293
- admin: { condition: (_data, siblingData) => Boolean(siblingData?.enabled) },
294
- fields: [{
295
- name: "winningValue",
296
- type: "text",
297
- label: labelForKey(keys.pollWinningValue),
298
- admin: { readOnly: true },
299
- access: {
300
- create: () => false,
301
- update: () => false
302
- }
303
- }, {
304
- name: "resolvedAt",
305
- type: "date",
306
- label: labelForKey(keys.pollResolvedAt),
307
- admin: { readOnly: true },
308
- access: {
309
- create: () => false,
310
- update: () => false
311
- }
312
- }]
313
- }
314
- ]
315
- }
433
+ path: "/:id/poll-options",
434
+ method: "get",
435
+ handler: async (req) => {
436
+ const { status, body } = await resolvePollOptionsRequest({
437
+ payload: req.payload,
438
+ formId: req.routeParams?.id,
439
+ isAuthed: Boolean(req.user),
440
+ req
441
+ });
442
+ return Response.json(body, { status });
443
+ }
444
+ },
445
+ {
446
+ path: "/:id/close",
447
+ method: "post",
448
+ handler: async (req) => {
449
+ const { status, body } = await resolvePollCloseRequest({
450
+ payload: req.payload,
451
+ formId: req.routeParams?.id,
452
+ isAuthed: Boolean(req.user),
453
+ req
454
+ });
455
+ return Response.json(body, { status });
456
+ }
457
+ },
458
+ ...consentSources ? [{
459
+ path: "/:id/consent-sources",
460
+ method: "get",
461
+ handler: async (req) => {
462
+ const { status, body } = await resolveConsentSourcesRequest({
463
+ payload: req.payload,
464
+ formId: req.routeParams?.id,
465
+ isAuthed: Boolean(req.user),
466
+ req,
467
+ resolver: consentSources
468
+ });
469
+ return Response.json(body, { status });
470
+ }
471
+ }] : [],
472
+ ...fromAddresses ? [{
473
+ path: "/:id/from-addresses",
474
+ method: "get",
475
+ handler: async (req) => {
476
+ const { status, body } = await resolveFromAddressesRequest({
477
+ isAuthed: Boolean(req.user),
478
+ req,
479
+ resolver: fromAddresses
480
+ });
481
+ return Response.json(body, { status });
482
+ }
483
+ }] : [],
484
+ ...departments ? [{
485
+ path: "/:id/departments",
486
+ method: "get",
487
+ handler: async (req) => {
488
+ const { status, body } = await resolveDepartmentsRequest({
489
+ isAuthed: Boolean(req.user),
490
+ req,
491
+ resolver: departments
492
+ });
493
+ return Response.json(body, { status });
494
+ }
495
+ }] : []
316
496
  ];
317
- const defaultEndpoints = [{
318
- path: "/:id/results",
319
- method: "get",
320
- handler: async (req) => {
321
- const field = typeof req.query?.field === "string" ? req.query.field : void 0;
322
- const { status, body } = await resolveFormResultsRequest({
323
- payload: req.payload,
324
- formId: req.routeParams?.id,
325
- field,
326
- isAuthed: Boolean(req.user),
327
- req,
328
- access: resultsAccess
329
- });
330
- return Response.json(body, { status });
331
- }
332
- }];
333
497
  return {
334
498
  ...overrides ?? {},
335
499
  slug: FORMS_SLUG,
@@ -341,6 +505,13 @@ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegist
341
505
  admin: {
342
506
  group: "Forms",
343
507
  useAsTitle: "title",
508
+ defaultColumns: [
509
+ "title",
510
+ "fields",
511
+ "flow",
512
+ "pollEnabled",
513
+ "updatedAt"
514
+ ],
344
515
  ...overrides?.admin ?? {}
345
516
  },
346
517
  access: {
@@ -349,7 +520,9 @@ const buildFormsCollection = ({ overrides, registry, ruleRegistry, consentRegist
349
520
  },
350
521
  hooks: {
351
522
  ...overrides?.hooks ?? {},
352
- beforeValidate: [beforeValidate, ...overrides?.hooks?.beforeValidate ?? []]
523
+ beforeValidate: [beforeValidate, ...overrides?.hooks?.beforeValidate ?? []],
524
+ beforeChange: [pollOutcomeBeforeChange, ...overrides?.hooks?.beforeChange ?? []],
525
+ afterChange: [pollCloseAfterChange, ...overrides?.hooks?.afterChange ?? []]
353
526
  },
354
527
  endpoints: [...defaultEndpoints, ...Array.isArray(overrides?.endpoints) ? overrides.endpoints : []],
355
528
  fields: overrides?.fields ? overrides.fields({ defaultFields }) : defaultFields