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

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 (272) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +4 -4
  3. package/dist/actions/body/converters.d.ts +20 -0
  4. package/dist/actions/body/converters.js +57 -0
  5. package/dist/actions/body/converters.js.map +1 -0
  6. package/dist/actions/body/escapeHtml.d.ts +6 -0
  7. package/dist/actions/body/escapeHtml.js +14 -0
  8. package/dist/actions/body/escapeHtml.js.map +1 -0
  9. package/dist/actions/body/serializeBody.d.ts +50 -0
  10. package/dist/actions/body/serializeBody.js +78 -0
  11. package/dist/actions/body/serializeBody.js.map +1 -0
  12. package/dist/actions/body/serializeSlate.js +31 -0
  13. package/dist/actions/body/serializeSlate.js.map +1 -0
  14. package/dist/actions/body/wildcards.d.ts +10 -0
  15. package/dist/actions/body/wildcards.js +33 -0
  16. package/dist/actions/body/wildcards.js.map +1 -0
  17. package/dist/actions/builtin/confirmation.js +40 -15
  18. package/dist/actions/builtin/confirmation.js.map +1 -1
  19. package/dist/actions/builtin/emailTeam.js +19 -12
  20. package/dist/actions/builtin/emailTeam.js.map +1 -1
  21. package/dist/actions/builtin/index.d.ts +13 -1
  22. package/dist/actions/builtin/index.js +18 -7
  23. package/dist/actions/builtin/index.js.map +1 -1
  24. package/dist/actions/builtin/signedWebhook.js +6 -2
  25. package/dist/actions/builtin/signedWebhook.js.map +1 -1
  26. package/dist/actions/defineAction.d.ts +2 -1
  27. package/dist/actions/defineAction.js.map +1 -1
  28. package/dist/actions/dispatch.js +2 -1
  29. package/dist/actions/dispatch.js.map +1 -1
  30. package/dist/actions/runActions.js +10 -1
  31. package/dist/actions/runActions.js.map +1 -1
  32. package/dist/actions/task.js +7 -5
  33. package/dist/actions/task.js.map +1 -1
  34. package/dist/aggregation/resolveResultsRequest.d.ts +22 -6
  35. package/dist/aggregation/resolveResultsRequest.js +18 -7
  36. package/dist/aggregation/resolveResultsRequest.js.map +1 -1
  37. package/dist/calc/normalizeCalc.js +5 -17
  38. package/dist/calc/normalizeCalc.js.map +1 -1
  39. package/dist/calc/types.d.ts +8 -2
  40. package/dist/calc/types.js +22 -0
  41. package/dist/calc/types.js.map +1 -0
  42. package/dist/client/ByteSizeField.d.ts +21 -0
  43. package/dist/client/ByteSizeField.js +56 -0
  44. package/dist/client/ByteSizeField.js.map +1 -0
  45. package/dist/client/ConditionBuilder.js +2 -1
  46. package/dist/client/ConditionBuilder.js.map +1 -1
  47. package/dist/client/FieldNameSelect.d.ts +20 -0
  48. package/dist/client/FieldNameSelect.js +58 -0
  49. package/dist/client/FieldNameSelect.js.map +1 -0
  50. package/dist/client/FlowBuilder.d.ts +0 -1
  51. package/dist/client/FlowBuilder.js +102 -59
  52. package/dist/client/FlowBuilder.js.map +1 -1
  53. package/dist/client/FormConditionField.js +1 -4
  54. package/dist/client/FormConditionField.js.map +1 -1
  55. package/dist/client/admin.css +234 -0
  56. package/dist/client/flowAuthoring.js +35 -0
  57. package/dist/client/flowAuthoring.js.map +1 -0
  58. package/dist/client/synthesizeClientField.js +6 -2
  59. package/dist/client/synthesizeClientField.js.map +1 -1
  60. package/dist/client/toStaticLabel.js +13 -0
  61. package/dist/client/toStaticLabel.js.map +1 -0
  62. package/dist/collections/formSubmissions.js +49 -9
  63. package/dist/collections/formSubmissions.js.map +1 -1
  64. package/dist/collections/forms.js +251 -88
  65. package/dist/collections/forms.js.map +1 -1
  66. package/dist/conditions/conditionType.js +9 -2
  67. package/dist/conditions/conditionType.js.map +1 -1
  68. package/dist/conditions/normalizeConditions.js +2 -1
  69. package/dist/conditions/normalizeConditions.js.map +1 -1
  70. package/dist/consent/builtin/index.d.ts +11 -1
  71. package/dist/consent/builtin/index.js +15 -5
  72. package/dist/consent/builtin/index.js.map +1 -1
  73. package/dist/consent/builtin/static.js +7 -3
  74. package/dist/consent/builtin/static.js.map +1 -1
  75. package/dist/exports/client.d.ts +3 -1
  76. package/dist/exports/client.js +3 -1
  77. package/dist/exports/react.d.ts +15 -6
  78. package/dist/exports/react.js +10 -2
  79. package/dist/exports/rsc.d.ts +6 -1
  80. package/dist/exports/rsc.js +6 -1
  81. package/dist/exports/types.d.ts +4 -4
  82. package/dist/fields/buildFieldBlocks.js +20 -15
  83. package/dist/fields/buildFieldBlocks.js.map +1 -1
  84. package/dist/fields/builtin/calculation.js +115 -2
  85. package/dist/fields/builtin/calculation.js.map +1 -1
  86. package/dist/fields/builtin/consent.js +8 -4
  87. package/dist/fields/builtin/consent.js.map +1 -1
  88. package/dist/fields/builtin/date.js +29 -0
  89. package/dist/fields/builtin/date.js.map +1 -0
  90. package/dist/fields/builtin/file.d.ts +15 -0
  91. package/dist/fields/builtin/file.js +87 -7
  92. package/dist/fields/builtin/file.js.map +1 -1
  93. package/dist/fields/builtin/index.d.ts +24 -0
  94. package/dist/fields/builtin/index.js +29 -8
  95. package/dist/fields/builtin/index.js.map +1 -1
  96. package/dist/fields/builtin/message.js +26 -0
  97. package/dist/fields/builtin/message.js.map +1 -0
  98. package/dist/fields/builtin/repeater.js +7 -3
  99. package/dist/fields/builtin/repeater.js.map +1 -1
  100. package/dist/fields/builtin/select.js +7 -3
  101. package/dist/fields/builtin/select.js.map +1 -1
  102. package/dist/fields/fieldNamesOfType.js +25 -0
  103. package/dist/fields/fieldNamesOfType.js.map +1 -0
  104. package/dist/fields/localizedIf.d.ts +13 -0
  105. package/dist/fields/localizedIf.js +12 -0
  106. package/dist/fields/localizedIf.js.map +1 -0
  107. package/dist/fields/sharedConfig.js +82 -57
  108. package/dist/fields/sharedConfig.js.map +1 -1
  109. package/dist/fields/types.d.ts +7 -2
  110. package/dist/flow/normalizeFlow.js +7 -1
  111. package/dist/flow/normalizeFlow.js.map +1 -1
  112. package/dist/flow/stepLabel.js +15 -0
  113. package/dist/flow/stepLabel.js.map +1 -0
  114. package/dist/form/pollState.d.ts +22 -0
  115. package/dist/form/pollState.js +17 -0
  116. package/dist/form/pollState.js.map +1 -0
  117. package/dist/form/toFormDocument.d.ts +60 -0
  118. package/dist/form/toFormDocument.js +39 -0
  119. package/dist/form/toFormDocument.js.map +1 -0
  120. package/dist/form/types.d.ts +48 -0
  121. package/dist/index.d.ts +81 -13
  122. package/dist/index.js +36 -15
  123. package/dist/index.js.map +1 -1
  124. package/dist/plugin/registerCollections.js +17 -37
  125. package/dist/plugin/registerCollections.js.map +1 -1
  126. package/dist/plugin/uploadsCollection.d.ts +11 -0
  127. package/dist/plugin/uploadsCollection.js +44 -0
  128. package/dist/plugin/uploadsCollection.js.map +1 -0
  129. package/dist/poll/applyPollOptions.js +17 -0
  130. package/dist/poll/applyPollOptions.js.map +1 -0
  131. package/dist/poll/buildPollOptionSourceFields.js +53 -0
  132. package/dist/poll/buildPollOptionSourceFields.js.map +1 -0
  133. package/dist/poll/definePollOptionSource.d.ts +35 -0
  134. package/dist/poll/definePollOptionSource.js +6 -0
  135. package/dist/poll/definePollOptionSource.js.map +1 -0
  136. package/dist/poll/registry.d.ts +16 -0
  137. package/dist/poll/registry.js +16 -0
  138. package/dist/poll/registry.js.map +1 -0
  139. package/dist/poll/resolvePollOptions.d.ts +28 -0
  140. package/dist/poll/resolvePollOptions.js +64 -0
  141. package/dist/poll/resolvePollOptions.js.map +1 -0
  142. package/dist/poll/resolvePollOutcome.d.ts +21 -0
  143. package/dist/poll/resolvePollOutcome.js +36 -0
  144. package/dist/poll/resolvePollOutcome.js.map +1 -0
  145. package/dist/prefill/valuesFromSearchParams.js +1 -1
  146. package/dist/prefill/valuesFromSearchParams.js.map +1 -1
  147. package/dist/presentations/types.d.ts +3 -2
  148. package/dist/react/Form.d.ts +13 -31
  149. package/dist/react/Form.js +98 -85
  150. package/dist/react/Form.js.map +1 -1
  151. package/dist/react/FormContext.d.ts +35 -1
  152. package/dist/react/FormContext.js.map +1 -1
  153. package/dist/react/FormControls.d.ts +55 -0
  154. package/dist/react/FormControls.js +56 -0
  155. package/dist/react/FormControls.js.map +1 -0
  156. package/dist/react/FormResults.d.ts +6 -3
  157. package/dist/react/FormResults.js +37 -29
  158. package/dist/react/FormResults.js.map +1 -1
  159. package/dist/react/FormSteps.d.ts +17 -0
  160. package/dist/react/FormSteps.js +35 -0
  161. package/dist/react/FormSteps.js.map +1 -0
  162. package/dist/react/Poll.d.ts +17 -6
  163. package/dist/react/Poll.js +66 -18
  164. package/dist/react/Poll.js.map +1 -1
  165. package/dist/react/captcha/HcaptchaCaptcha.d.ts +28 -0
  166. package/dist/react/captcha/HcaptchaCaptcha.js +53 -0
  167. package/dist/react/captcha/HcaptchaCaptcha.js.map +1 -0
  168. package/dist/react/captcha/RecaptchaCaptcha.d.ts +41 -0
  169. package/dist/react/captcha/RecaptchaCaptcha.js +93 -0
  170. package/dist/react/captcha/RecaptchaCaptcha.js.map +1 -0
  171. package/dist/react/captcha/TurnstileCaptcha.d.ts +28 -0
  172. package/dist/react/captcha/TurnstileCaptcha.js +53 -0
  173. package/dist/react/captcha/TurnstileCaptcha.js.map +1 -0
  174. package/dist/react/captcha/types.d.ts +8 -0
  175. package/dist/react/captcha/useCaptchaScript.js +45 -0
  176. package/dist/react/captcha/useCaptchaScript.js.map +1 -0
  177. package/dist/react/captcha/vendors.js +8 -0
  178. package/dist/react/captcha/vendors.js.map +1 -0
  179. package/dist/react/fetchResults.d.ts +1 -1
  180. package/dist/react/fetchResults.js +1 -1
  181. package/dist/react/fetchResults.js.map +1 -1
  182. package/dist/react/primitives/Input.d.ts +1 -1
  183. package/dist/react/primitives/Input.js.map +1 -1
  184. package/dist/react/renderers/calculation.js +1 -1
  185. package/dist/react/renderers/checkbox.js +1 -1
  186. package/dist/react/renderers/consent.js +1 -1
  187. package/dist/react/renderers/date.js +37 -0
  188. package/dist/react/renderers/date.js.map +1 -0
  189. package/dist/react/renderers/email.js +1 -1
  190. package/dist/react/renderers/file.js +25 -8
  191. package/dist/react/renderers/file.js.map +1 -1
  192. package/dist/react/renderers/index.js +4 -0
  193. package/dist/react/renderers/index.js.map +1 -1
  194. package/dist/react/renderers/message.js +35 -0
  195. package/dist/react/renderers/message.js.map +1 -0
  196. package/dist/react/renderers/number.js +1 -1
  197. package/dist/react/renderers/repeater.js +1 -1
  198. package/dist/react/renderers/select.js +1 -1
  199. package/dist/react/renderers/text.js +1 -1
  200. package/dist/react/renderers/textarea.js +1 -1
  201. package/dist/react/state.d.ts +25 -1
  202. package/dist/react/state.js +14 -1
  203. package/dist/react/state.js.map +1 -1
  204. package/dist/react/uploadFile.d.ts +2 -2
  205. package/dist/react/uploadFile.js +1 -1
  206. package/dist/react/uploadFile.js.map +1 -1
  207. package/dist/spam/captcha.d.ts +3 -2
  208. package/dist/spam/captcha.js +3 -2
  209. package/dist/spam/captcha.js.map +1 -1
  210. package/dist/spam/clientIp.js +9 -0
  211. package/dist/spam/clientIp.js.map +1 -0
  212. package/dist/spam/identify.js +3 -6
  213. package/dist/spam/identify.js.map +1 -1
  214. package/dist/spam/providers/hcaptcha.d.ts +17 -0
  215. package/dist/spam/providers/hcaptcha.js +18 -0
  216. package/dist/spam/providers/hcaptcha.js.map +1 -0
  217. package/dist/spam/providers/recaptcha.d.ts +23 -0
  218. package/dist/spam/providers/recaptcha.js +23 -0
  219. package/dist/spam/providers/recaptcha.js.map +1 -0
  220. package/dist/spam/providers/siteverify.js +34 -0
  221. package/dist/spam/providers/siteverify.js.map +1 -0
  222. package/dist/spam/providers/turnstile.d.ts +17 -0
  223. package/dist/spam/providers/turnstile.js +18 -0
  224. package/dist/spam/providers/turnstile.js.map +1 -0
  225. package/dist/spam/spamGuard.js +2 -5
  226. package/dist/spam/spamGuard.js.map +1 -1
  227. package/dist/spam/types.d.ts +2 -2
  228. package/dist/submissions/runSubmission.js +70 -33
  229. package/dist/submissions/runSubmission.js.map +1 -1
  230. package/dist/submissions/validateSubmission.js +41 -7
  231. package/dist/submissions/validateSubmission.js.map +1 -1
  232. package/dist/submissions/votedCookie.d.ts +13 -0
  233. package/dist/submissions/votedCookie.js +27 -0
  234. package/dist/submissions/votedCookie.js.map +1 -0
  235. package/dist/translations/de.js +219 -0
  236. package/dist/translations/de.js.map +1 -0
  237. package/dist/translations/en.js +71 -10
  238. package/dist/translations/en.js.map +1 -1
  239. package/dist/translations/index.d.ts +2 -1
  240. package/dist/translations/index.js +6 -2
  241. package/dist/translations/index.js.map +1 -1
  242. package/dist/translations/keys.d.ts +69 -8
  243. package/dist/translations/keys.js +70 -9
  244. package/dist/translations/keys.js.map +1 -1
  245. package/dist/uploads/formatBytes.d.ts +9 -0
  246. package/dist/uploads/formatBytes.js +25 -0
  247. package/dist/uploads/formatBytes.js.map +1 -0
  248. package/dist/uploads/resolveFileRef.js +1 -1
  249. package/dist/uploads/resolveFileRef.js.map +1 -1
  250. package/dist/uploads/types.d.ts +1 -2
  251. package/dist/validation/builtin/index.d.ts +14 -0
  252. package/dist/validation/builtin/index.js +12 -1
  253. package/dist/validation/builtin/index.js.map +1 -1
  254. package/dist/validation/builtin/maxDate.js +23 -0
  255. package/dist/validation/builtin/maxDate.js.map +1 -0
  256. package/dist/validation/builtin/minDate.js +23 -0
  257. package/dist/validation/builtin/minDate.js.map +1 -0
  258. package/dist/validation/builtin/validateDateBound.js +18 -0
  259. package/dist/validation/builtin/validateDateBound.js.map +1 -0
  260. package/dist/validation/validateUrl.js +22 -0
  261. package/dist/validation/validateUrl.js.map +1 -0
  262. package/package.json +4 -2
  263. package/styles/form-builder.css +10 -190
  264. package/dist/collections/uploads.d.ts +0 -30
  265. package/dist/collections/uploads.js +0 -55
  266. package/dist/collections/uploads.js.map +0 -1
  267. package/dist/presentations/registry.d.ts +0 -15
  268. package/dist/presentations/registry.js +0 -15
  269. package/dist/presentations/registry.js.map +0 -1
  270. package/dist/react/toFormDocument.d.ts +0 -24
  271. package/dist/react/toFormDocument.js +0 -22
  272. package/dist/react/toFormDocument.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"static.js","names":[],"sources":["../../../src/consent/builtin/static.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineConsentSource } from '../defineConsentSource'\n\ntype StaticConfig = { label?: string; url?: string; version?: string }\n\nexport const staticSource = defineConsentSource<StaticConfig>({\n\ttype: 'static',\n\tlabel: keys.consentSourceStatic,\n\tconfig: [\n\t\t{ name: 'label', type: 'text', label: labelFor(keys.consentConfigLabel) },\n\t\t{ name: 'url', type: 'text', label: labelFor(keys.consentConfigUrl) },\n\t\t{ name: 'version', type: 'text', label: labelFor(keys.consentConfigVersion) },\n\t],\n\tresolve({ config }) {\n\t\tconst label = String(config.label ?? '')\n\t\tconst url = String(config.url ?? '')\n\t\tconst version = config.version ? String(config.version) : undefined\n\t\treturn {\n\t\t\tlinks: [{ label, url }],\n\t\t\t...(version ? { versionRef: version, versionLabel: version } : {}),\n\t\t}\n\t},\n})\n"],"mappings":";;;;AAMA,MAAa,eAAe,oBAAkC;CAC7D,MAAM;CACN,OAAO,KAAK;CACZ,QAAQ;EACP;GAAE,MAAM;GAAS,MAAM;GAAQ,OAAO,SAAS,KAAK,kBAAkB;EAAE;EACxE;GAAE,MAAM;GAAO,MAAM;GAAQ,OAAO,SAAS,KAAK,gBAAgB;EAAE;EACpE;GAAE,MAAM;GAAW,MAAM;GAAQ,OAAO,SAAS,KAAK,oBAAoB;EAAE;CAC7E;CACA,QAAQ,EAAE,UAAU;EACnB,MAAM,QAAQ,OAAO,OAAO,SAAS,EAAE;EACvC,MAAM,MAAM,OAAO,OAAO,OAAO,EAAE;EACnC,MAAM,UAAU,OAAO,UAAU,OAAO,OAAO,OAAO,IAAI,KAAA;EAC1D,OAAO;GACN,OAAO,CAAC;IAAE;IAAO;GAAI,CAAC;GACtB,GAAI,UAAU;IAAE,YAAY;IAAS,cAAc;GAAQ,IAAI,CAAC;EACjE;CACD;AACD,CAAC"}
1
+ {"version":3,"file":"static.js","names":[],"sources":["../../../src/consent/builtin/static.ts"],"sourcesContent":["import { localizedIf } from '../../fields/localizedIf'\nimport { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineConsentSource } from '../defineConsentSource'\n\ntype StaticConfig = { label?: string; url?: string; version?: string }\n\n/** The link `label` is visitor-facing text and follows `localize`; `url` and `version` are identifiers and never do. */\nexport const buildStaticSource = (localize: boolean) =>\n\tdefineConsentSource<StaticConfig>({\n\t\ttype: 'static',\n\t\tlabel: keys.consentSourceStatic,\n\t\tconfig: [\n\t\t\t{\n\t\t\t\tname: 'label',\n\t\t\t\ttype: 'text',\n\t\t\t\tlabel: labelFor(keys.consentConfigLabel),\n\t\t\t\t...localizedIf(localize),\n\t\t\t},\n\t\t\t{ name: 'url', type: 'text', label: labelFor(keys.consentConfigUrl) },\n\t\t\t{ name: 'version', type: 'text', label: labelFor(keys.consentConfigVersion) },\n\t\t],\n\t\tresolve({ config }) {\n\t\t\tconst label = String(config.label ?? '')\n\t\t\tconst url = String(config.url ?? '')\n\t\t\tconst version = config.version ? String(config.version) : undefined\n\t\t\treturn {\n\t\t\t\tlinks: [{ label, url }],\n\t\t\t\t...(version ? { versionRef: version, versionLabel: version } : {}),\n\t\t\t}\n\t\t},\n\t})\n\nexport const staticSource = buildStaticSource(true)\n"],"mappings":";;;;;;AAQA,MAAa,qBAAqB,aACjC,oBAAkC;CACjC,MAAM;CACN,OAAO,KAAK;CACZ,QAAQ;EACP;GACC,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,kBAAkB;GACvC,GAAG,YAAY,QAAQ;EACxB;EACA;GAAE,MAAM;GAAO,MAAM;GAAQ,OAAO,SAAS,KAAK,gBAAgB;EAAE;EACpE;GAAE,MAAM;GAAW,MAAM;GAAQ,OAAO,SAAS,KAAK,oBAAoB;EAAE;CAC7E;CACA,QAAQ,EAAE,UAAU;EACnB,MAAM,QAAQ,OAAO,OAAO,SAAS,EAAE;EACvC,MAAM,MAAM,OAAO,OAAO,OAAO,EAAE;EACnC,MAAM,UAAU,OAAO,UAAU,OAAO,OAAO,OAAO,IAAI,KAAA;EAC1D,OAAO;GACN,OAAO,CAAC;IAAE;IAAO;GAAI,CAAC;GACtB,GAAI,UAAU;IAAE,YAAY;IAAS,cAAc;GAAQ,IAAI,CAAC;EACjE;CACD;AACD,CAAC;AAE0B,kBAAkB,IAAI"}
@@ -1,3 +1,5 @@
1
+ import { ByteSizeField } from "../client/ByteSizeField.js";
2
+ import { FieldNameSelect } from "../client/FieldNameSelect.js";
1
3
  import { FlowBuilder } from "../client/FlowBuilder.js";
2
4
  import { FormConditionField } from "../client/FormConditionField.js";
3
- export { FlowBuilder, FormConditionField };
5
+ export { ByteSizeField, FieldNameSelect, FlowBuilder, FormConditionField };
@@ -1,4 +1,6 @@
1
1
  "use client";
2
+ import { ByteSizeField } from "../client/ByteSizeField.js";
3
+ import { FieldNameSelect } from "../client/FieldNameSelect.js";
2
4
  import { FlowBuilder } from "../client/FlowBuilder.js";
3
5
  import { FormConditionField } from "../client/FormConditionField.js";
4
- export { FlowBuilder, FormConditionField };
6
+ export { ByteSizeField, FieldNameSelect, FlowBuilder, FormConditionField };
@@ -1,22 +1,31 @@
1
- import { FormFieldInstance } from "../submissions/types.js";
1
+ import { FormFieldInstance, SubmissionValue } from "../submissions/types.js";
2
+ import { BodyContext, serializeBody } from "../actions/body/serializeBody.js";
2
3
  import { AggregationBucket, FieldAggregation } from "../aggregation/types.js";
3
4
  import { CalcExpression } from "../calc/types.js";
4
5
  import { computeCalcFields } from "../calc/computeCalcFields.js";
5
6
  import { evaluateCalc } from "../calc/evaluate.js";
6
7
  import { evaluateCondition } from "../conditions/evaluate.js";
7
8
  import { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames } from "../flow/engine.js";
9
+ import { FormDisplaySettings, FormDocument, FormPollSettings, FormResponseSettings } from "../form/types.js";
10
+ import { toFormDocument } from "../form/toFormDocument.js";
8
11
  import { PrefillOptions, valuesFromSearchParams } from "../prefill/valuesFromSearchParams.js";
12
+ import { CaptchaWidgetHandle } from "../react/captcha/types.js";
13
+ import { HCAPTCHA_SCRIPT_URL, HcaptchaCaptcha, HcaptchaCaptchaProps } from "../react/captcha/HcaptchaCaptcha.js";
14
+ import { RECAPTCHA_SCRIPT_URL, RecaptchaCaptcha, RecaptchaCaptchaHandle, RecaptchaCaptchaProps } from "../react/captcha/RecaptchaCaptcha.js";
15
+ import { TURNSTILE_SCRIPT_URL, TurnstileCaptcha, TurnstileCaptchaProps } from "../react/captcha/TurnstileCaptcha.js";
9
16
  import { cn } from "../react/cn.js";
10
17
  import { FieldRenderer, FieldRendererProps, RendererTranslate, defineFieldRenderer } from "../react/contract.js";
18
+ import { BackButtonRenderProps, FormControls, FormControlsProps, NextButtonRenderProps, SubmitButtonRenderProps } from "../react/FormControls.js";
11
19
  import { FormPresentation, PresentationWrapperProps } from "../react/presentation/types.js";
12
20
  import { PresentationOption, PresentationRegistry, PresentationsConfig, resolvePresentations } from "../react/presentation/registry.js";
13
21
  import { RendererOption, RendererRegistry, RenderersConfig, resolveRenderers } from "../react/registry.js";
14
22
  import { SubmitFormResult, SubmitHandler, submitForm } from "../react/submitForm.js";
15
- import { BackButtonRenderProps, Form, FormDocument, FormProps, NextButtonRenderProps, SubmitButtonRenderProps } from "../react/Form.js";
16
- import { FormState } from "../react/state.js";
17
- import { FormStepInfo } from "../react/FormContext.js";
23
+ import { Form, FormProps } from "../react/Form.js";
24
+ import { FieldErrors, FormAction, FormState } from "../react/state.js";
25
+ import { FormContextValue, FormControlLabels, FormStepInfo, useFormContext } from "../react/FormContext.js";
18
26
  import { FieldWidth, FormLayout, FormLayoutProps, widthProps } from "../react/FormLayout.js";
19
27
  import { FormResults, FormResultsProps } from "../react/FormResults.js";
28
+ import { FormSteps, FormStepsProps } from "../react/FormSteps.js";
20
29
  import { FetchResultsInput, FetchResultsResult, fetchFormResults } from "../react/fetchResults.js";
21
30
  import { Honeypot, HoneypotProps } from "../react/Honeypot.js";
22
31
  import { Poll, PollProps } from "../react/Poll.js";
@@ -32,7 +41,6 @@ import { Input, InputProps } from "../react/primitives/Input.js";
32
41
  import { Select, SelectOption, SelectProps } from "../react/primitives/Select.js";
33
42
  import { Textarea, TextareaProps } from "../react/primitives/Textarea.js";
34
43
  import { defaultRenderers } from "../react/renderers/index.js";
35
- import { toFormDocument } from "../react/toFormDocument.js";
36
44
  import { UploadFileInput, UploadFileResult, uploadFile } from "../react/uploadFile.js";
37
45
  import { UseFieldResult, useField } from "../react/useField.js";
38
46
  import { useFormState } from "../react/useFormState.js";
@@ -42,4 +50,5 @@ import { RecallResolver, buildRecallResolver } from "../recall/resolver.js";
42
50
  import { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from "../spam/constants.js";
43
51
  import { en } from "../translations/en.js";
44
52
  import { makeTranslate } from "../translations/makeTranslate.js";
45
- export { type AggregationBucket, type BackButtonRenderProps, Backdrop, type BackdropProps, CAPTCHA_TOKEN_KEY, type CalcExpression, Checkbox, type CheckboxProps, DEFAULT_HONEYPOT_FIELD, DialogSurface, type DialogSurfaceProps, type FetchResultsInput, type FetchResultsResult, type FieldAggregation, type FieldRenderer, type FieldRendererProps, FieldShell, type FieldShellProps, type FieldWidth, Form, type FormDocument, type FormFieldInstance, FormLayout, type FormLayoutProps, type FormPresentation, type FormProps, FormResults, type FormResultsProps, type FormState, type FormStepInfo, Honeypot, type HoneypotProps, Input, type InputProps, type NextButtonRenderProps, Poll, type PollProps, type PrefillOptions, type PresentationOption, type PresentationRegistry, type PresentationWrapperProps, type PresentationsConfig, type RecallResolver, type RendererOption, type RendererRegistry, type RendererTranslate, type RenderersConfig, Select, type SelectOption, type SelectProps, type SubmitButtonRenderProps, type SubmitFormResult, type SubmitHandler, Textarea, type TextareaProps, type UploadFileInput, type UploadFileResult, type UseDismissOptions, type UseFieldResult, buildRecallResolver, cn, computeCalcFields, defaultPresentations, defaultRenderers, defineFieldRenderer, en, evaluateCalc, evaluateCondition, fetchFormResults, firstStepId, interpolate, isTerminalStepId, makeTranslate, resolveNextStepId, resolvePresentations, resolveRenderers, stepFieldNames, submitForm, toFormDocument, uploadFile, useDismiss, useField, useFocusTrap, useFormState, useFormStep, useScrollLock, valuesFromSearchParams, widthProps };
53
+ import { formatBytes } from "../uploads/formatBytes.js";
54
+ export { type AggregationBucket, type BackButtonRenderProps, Backdrop, type BackdropProps, type BodyContext, CAPTCHA_TOKEN_KEY, type CalcExpression, type CaptchaWidgetHandle, Checkbox, type CheckboxProps, DEFAULT_HONEYPOT_FIELD, DialogSurface, type DialogSurfaceProps, type FetchResultsInput, type FetchResultsResult, type FieldAggregation, type FieldErrors, type FieldRenderer, type FieldRendererProps, FieldShell, type FieldShellProps, type FieldWidth, Form, type FormAction, type FormContextValue, type FormControlLabels, FormControls, type FormControlsProps, type FormDisplaySettings, type FormDocument, type FormFieldInstance, FormLayout, type FormLayoutProps, type FormPollSettings, type FormPresentation, type FormProps, type FormResponseSettings, FormResults, type FormResultsProps, type FormState, type FormStepInfo, FormSteps, type FormStepsProps, HCAPTCHA_SCRIPT_URL, HcaptchaCaptcha, type HcaptchaCaptchaProps, Honeypot, type HoneypotProps, Input, type InputProps, type NextButtonRenderProps, Poll, type PollProps, type PrefillOptions, type PresentationOption, type PresentationRegistry, type PresentationWrapperProps, type PresentationsConfig, RECAPTCHA_SCRIPT_URL, type RecallResolver, RecaptchaCaptcha, type RecaptchaCaptchaHandle, type RecaptchaCaptchaProps, type RendererOption, type RendererRegistry, type RendererTranslate, type RenderersConfig, Select, type SelectOption, type SelectProps, type SubmissionValue, type SubmitButtonRenderProps, type SubmitFormResult, type SubmitHandler, TURNSTILE_SCRIPT_URL, Textarea, type TextareaProps, TurnstileCaptcha, type TurnstileCaptchaProps, type UploadFileInput, type UploadFileResult, type UseDismissOptions, type UseFieldResult, buildRecallResolver, cn, computeCalcFields, defaultPresentations, defaultRenderers, defineFieldRenderer, en, evaluateCalc, evaluateCondition, fetchFormResults, firstStepId, formatBytes, interpolate, isTerminalStepId, makeTranslate, resolveNextStepId, resolvePresentations, resolveRenderers, serializeBody, stepFieldNames, submitForm, toFormDocument, uploadFile, useDismiss, useField, useFocusTrap, useFormContext, useFormState, useFormStep, useScrollLock, valuesFromSearchParams, widthProps };
@@ -1,16 +1,24 @@
1
1
  "use client";
2
2
  import { interpolate } from "../recall/interpolate.js";
3
+ import { serializeBody } from "../actions/body/serializeBody.js";
3
4
  import { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from "../spam/constants.js";
4
5
  import { evaluateCalc } from "../calc/evaluate.js";
5
6
  import { computeCalcFields } from "../calc/computeCalcFields.js";
6
7
  import { evaluateCondition } from "../conditions/evaluate.js";
7
8
  import { en } from "../translations/en.js";
9
+ import { toFormDocument } from "../form/toFormDocument.js";
8
10
  import { valuesFromSearchParams } from "../prefill/valuesFromSearchParams.js";
9
11
  import { buildRecallResolver } from "../recall/resolver.js";
12
+ import { formatBytes } from "../uploads/formatBytes.js";
10
13
  import { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames } from "../flow/engine.js";
14
+ import { HCAPTCHA_SCRIPT_URL, HcaptchaCaptcha } from "../react/captcha/HcaptchaCaptcha.js";
15
+ import { RECAPTCHA_SCRIPT_URL, RecaptchaCaptcha } from "../react/captcha/RecaptchaCaptcha.js";
16
+ import { TURNSTILE_SCRIPT_URL, TurnstileCaptcha } from "../react/captcha/TurnstileCaptcha.js";
11
17
  import { cn } from "../react/cn.js";
12
18
  import { defineFieldRenderer } from "../react/contract.js";
13
19
  import { makeTranslate } from "../translations/makeTranslate.js";
20
+ import { useFormContext } from "../react/FormContext.js";
21
+ import { FormControls } from "../react/FormControls.js";
14
22
  import { FormLayout, widthProps } from "../react/FormLayout.js";
15
23
  import { Honeypot } from "../react/Honeypot.js";
16
24
  import { Backdrop } from "../react/presentation/Backdrop.js";
@@ -32,9 +40,9 @@ import { defaultRenderers } from "../react/renderers/index.js";
32
40
  import { submitForm } from "../react/submitForm.js";
33
41
  import { Form } from "../react/Form.js";
34
42
  import { FormResults } from "../react/FormResults.js";
43
+ import { FormSteps } from "../react/FormSteps.js";
35
44
  import { fetchFormResults } from "../react/fetchResults.js";
36
45
  import { Poll } from "../react/Poll.js";
37
- import { toFormDocument } from "../react/toFormDocument.js";
38
46
  import { useFormState } from "../react/useFormState.js";
39
47
  import { useFormStep } from "../react/useFormStep.js";
40
- export { Backdrop, CAPTCHA_TOKEN_KEY, Checkbox, DEFAULT_HONEYPOT_FIELD, DialogSurface, FieldShell, Form, FormLayout, FormResults, Honeypot, Input, Poll, Select, Textarea, buildRecallResolver, cn, computeCalcFields, defaultPresentations, defaultRenderers, defineFieldRenderer, en, evaluateCalc, evaluateCondition, fetchFormResults, firstStepId, interpolate, isTerminalStepId, makeTranslate, resolveNextStepId, resolvePresentations, resolveRenderers, stepFieldNames, submitForm, toFormDocument, uploadFile, useDismiss, useField, useFocusTrap, useFormState, useFormStep, useScrollLock, valuesFromSearchParams, widthProps };
48
+ export { Backdrop, CAPTCHA_TOKEN_KEY, Checkbox, DEFAULT_HONEYPOT_FIELD, DialogSurface, FieldShell, Form, FormControls, FormLayout, FormResults, FormSteps, HCAPTCHA_SCRIPT_URL, HcaptchaCaptcha, Honeypot, Input, Poll, RECAPTCHA_SCRIPT_URL, RecaptchaCaptcha, Select, TURNSTILE_SCRIPT_URL, Textarea, TurnstileCaptcha, buildRecallResolver, cn, computeCalcFields, defaultPresentations, defaultRenderers, defineFieldRenderer, en, evaluateCalc, evaluateCondition, fetchFormResults, firstStepId, formatBytes, interpolate, isTerminalStepId, makeTranslate, resolveNextStepId, resolvePresentations, resolveRenderers, serializeBody, stepFieldNames, submitForm, toFormDocument, uploadFile, useDismiss, useField, useFocusTrap, useFormContext, useFormState, useFormStep, useScrollLock, valuesFromSearchParams, widthProps };
@@ -1,2 +1,7 @@
1
+ import { toFormDocument } from "../form/toFormDocument.js";
2
+ import { isPollClosed } from "../form/pollState.js";
3
+ import { resolvePollOptions } from "../poll/resolvePollOptions.js";
4
+ import { resolvePollOutcome } from "../poll/resolvePollOutcome.js";
1
5
  import { SubmissionAnswers } from "../submissions/SubmissionAnswers.js";
2
- export { SubmissionAnswers };
6
+ import { hasVotedCookie, votedCookieName } from "../submissions/votedCookie.js";
7
+ export { SubmissionAnswers, hasVotedCookie, isPollClosed, resolvePollOptions, resolvePollOutcome, toFormDocument, votedCookieName };
@@ -1,2 +1,7 @@
1
+ import { isPollClosed } from "../form/pollState.js";
2
+ import { resolvePollOptions } from "../poll/resolvePollOptions.js";
3
+ import { hasVotedCookie, votedCookieName } from "../submissions/votedCookie.js";
4
+ import { toFormDocument } from "../form/toFormDocument.js";
5
+ import { resolvePollOutcome } from "../poll/resolvePollOutcome.js";
1
6
  import { SubmissionAnswers } from "../submissions/SubmissionAnswers.js";
2
- export { SubmissionAnswers };
7
+ export { SubmissionAnswers, hasVotedCookie, isPollClosed, resolvePollOptions, resolvePollOutcome, toFormDocument, votedCookieName };
@@ -4,6 +4,7 @@ import { FormFieldInstance, SubmissionDescriptor, SubmissionFieldError, Submissi
4
4
  import { AggregationBucket, AggregationRow, FieldAggregation, FieldMeta, SubmissionStatusFilter } from "../aggregation/types.js";
5
5
  import { CalcExpression } from "../calc/types.js";
6
6
  import { FlowStep, FlowTransition, FormFlow } from "../flow/types.js";
7
+ import { FormDisplaySettings, FormDocument, FormPollSettings, FormResponseSettings } from "../form/types.js";
7
8
  import { FieldTypeOption, FieldTypeRegistry, FieldTypesConfig } from "../fields/registry.js";
8
9
  import { PrefillOptions } from "../prefill/valuesFromSearchParams.js";
9
10
  import { FormEvent, FormEventSink } from "../events/types.js";
@@ -15,14 +16,13 @@ import { ActionOption, ActionRegistry, ActionsConfig } from "../actions/registry
15
16
  import { ActionResult } from "../actions/runActions.js";
16
17
  import { AggregateFieldResponsesArgs, AggregateFormResponsesArgs } from "../aggregation/aggregateResponses.js";
17
18
  import { ResolveResultsRequestArgs, ResolveResultsRequestResult } from "../aggregation/resolveResultsRequest.js";
18
- import { CollectionOverrides, FieldsOverride } from "../plugin/collectionOverrides.js";
19
- import { UploadsCollectionConfig, UploadsOption } from "../collections/uploads.js";
20
19
  import { FieldCondition } from "../conditions/types.js";
21
20
  import { AnyConsentSource, ConsentLink, ConsentResolveArgs, ConsentResolved, ConsentSource } from "../consent/defineConsentSource.js";
22
21
  import { ConsentSourceOption, ConsentSourceRegistry, ConsentSourcesConfig } from "../consent/registry.js";
23
22
  import { ConsentProof } from "../consent/captureConsent.js";
24
- import { PresentationDescriptorOption, PresentationDescriptorRegistry, PresentationsDescriptorConfig } from "../presentations/registry.js";
23
+ import { CollectionOverrides, FieldsOverride } from "../plugin/collectionOverrides.js";
25
24
  import { CaptchaProvider, CaptchaVerifyArgs, IdentifyFn, RateLimitCheckArgs, RateLimitConfig, RateLimitResult, RateLimiter, SpamConfig, SpamMetadataConfig, SpamOption } from "../spam/types.js";
25
+ import { UploadsOption } from "../plugin/uploadsCollection.js";
26
26
  import { ValidationRuleOption, ValidationRuleRegistry, ValidationRulesConfig } from "../validation/registry.js";
27
27
  import { FormBuilderPluginOptions } from "../index.js";
28
- export type { ActionDefinition, ActionOption, ActionRegistry, ActionResult, ActionRunArgs, ActionsConfig, AggregateFieldResponsesArgs, AggregateFormResponsesArgs, AggregationBucket, AggregationRow, AnyActionDefinition, AnyConsentSource, AnyFormFieldDefinition, AnyValidationRuleDefinition, CalcExpression, CaptchaProvider, CaptchaVerifyArgs, CollectionOverrides, ConsentLink, ConsentProof, ConsentResolveArgs, ConsentResolved, ConsentSource, ConsentSourceOption, ConsentSourceRegistry, ConsentSourcesConfig, FieldAggregation, FieldCondition, FieldMeta, FieldTypeOption, FieldTypeRegistry, FieldTypesConfig, FieldsOverride, FileFieldConfig, FileRef, FileRefError, FlowStep, FlowTransition, FormBuilderPluginOptions, FormEvent, FormEventSink, FormFieldDefinition, FormFieldFormat, FormFieldInstance, FormFieldValidate, FormFieldValueKind, FormFlow, IdentifyFn, PrefillOptions, PresentationDensity, PresentationDescriptor, PresentationDescriptorOption, PresentationDescriptorRegistry, PresentationSurface, PresentationsDescriptorConfig, RateLimitCheckArgs, RateLimitConfig, RateLimitResult, RateLimiter, RecallResolver, ResolveResultsRequestArgs, ResolveResultsRequestResult, SpamConfig, SpamMetadataConfig, SpamOption, SubmissionDescriptor, SubmissionFieldError, SubmissionStatusFilter, SubmissionValue, UploadsCollectionConfig, UploadsOption, ValidationRuleDefinition, ValidationRuleOption, ValidationRuleRegistry, ValidationRuleResult, ValidationRulesConfig, ValidationSeverity };
28
+ export type { ActionDefinition, ActionOption, ActionRegistry, ActionResult, ActionRunArgs, ActionsConfig, AggregateFieldResponsesArgs, AggregateFormResponsesArgs, AggregationBucket, AggregationRow, AnyActionDefinition, AnyConsentSource, AnyFormFieldDefinition, AnyValidationRuleDefinition, CalcExpression, CaptchaProvider, CaptchaVerifyArgs, CollectionOverrides, ConsentLink, ConsentProof, ConsentResolveArgs, ConsentResolved, ConsentSource, ConsentSourceOption, ConsentSourceRegistry, ConsentSourcesConfig, FieldAggregation, FieldCondition, FieldMeta, FieldTypeOption, FieldTypeRegistry, FieldTypesConfig, FieldsOverride, FileFieldConfig, FileRef, FileRefError, FlowStep, FlowTransition, FormBuilderPluginOptions, FormDisplaySettings, FormDocument, FormEvent, FormEventSink, FormFieldDefinition, FormFieldFormat, FormFieldInstance, FormFieldValidate, FormFieldValueKind, FormFlow, FormPollSettings, FormResponseSettings, IdentifyFn, PrefillOptions, PresentationDensity, PresentationDescriptor, PresentationSurface, RateLimitCheckArgs, RateLimitConfig, RateLimitResult, RateLimiter, RecallResolver, ResolveResultsRequestArgs, ResolveResultsRequestResult, SpamConfig, SpamMetadataConfig, SpamOption, SubmissionDescriptor, SubmissionFieldError, SubmissionStatusFilter, SubmissionValue, UploadsOption, ValidationRuleDefinition, ValidationRuleOption, ValidationRuleRegistry, ValidationRuleResult, ValidationRulesConfig, ValidationSeverity };
@@ -3,10 +3,18 @@ import { labelFor } from "../translations/server.js";
3
3
  import { buildConditionTypeMap } from "../conditions/conditionType.js";
4
4
  import { buildConsentSourceConfig } from "../consent/buildConsentSourceConfig.js";
5
5
  import { buildRuleBlocks } from "../validation/buildRuleBlocks.js";
6
- import { sharedFieldConfig } from "./sharedConfig.js";
6
+ import { fieldBlockTabs } from "./sharedConfig.js";
7
7
  //#region src/fields/buildFieldBlocks.ts
8
- /** One add-field block per registered type: shared config, the type's own config, then its validations. */
9
- const buildFieldBlocks = (registry, ruleRegistry, consentRegistry) => {
8
+ /** Whether `fields` contains a field named `name`, descending into presentational rows. */
9
+ const hasNameField = (fields) => fields.some((f) => {
10
+ if ("name" in f && f.name === "name") return true;
11
+ return f.type === "row" && hasNameField(f.fields);
12
+ });
13
+ /** The tab whose fields hold the shared basics and type config, found by the `name` field it carries. */
14
+ const fieldTabOf = (block) => {
15
+ return block.fields.find((f) => f.type === "tabs")?.tabs.find((tab) => hasNameField(tab.fields))?.fields;
16
+ };
17
+ const buildFieldBlocks = ({ registry, ruleRegistry, consentRegistry, localize = true }) => {
10
18
  const conditionTypes = buildConditionTypeMap(registry);
11
19
  const blocks = [];
12
20
  for (const definition of registry.values()) {
@@ -26,31 +34,28 @@ const buildFieldBlocks = (registry, ruleRegistry, consentRegistry) => {
26
34
  singular: labelFor(definition.label),
27
35
  plural: labelFor(definition.label)
28
36
  },
29
- fields: [
30
- ...sharedFieldConfig(conditionTypes),
31
- ...typeConfig,
32
- {
37
+ fields: [fieldBlockTabs({
38
+ conditionTypes,
39
+ typeConfig,
40
+ validations: {
33
41
  name: "validations",
34
42
  type: "blocks",
35
43
  label: labelFor(keys.validationsLabel),
36
44
  blocks: buildRuleBlocks(ruleRegistry, definition.type)
37
- }
38
- ]
45
+ },
46
+ localize
47
+ })]
39
48
  });
40
49
  }
41
50
  const repeaterBlock = blocks.find((b) => b.slug === "repeater");
42
51
  if (repeaterBlock) {
43
- const subFieldBlocks = blocks.filter((b) => b.slug !== "repeater");
44
- const fieldsArr = repeaterBlock.fields;
45
- const validationsIdx = fieldsArr.findIndex((f) => f.name === "validations");
46
52
  const subFieldsField = {
47
53
  name: "subFields",
48
54
  type: "blocks",
49
55
  label: labelFor(keys.configSubFields),
50
- blocks: subFieldBlocks
56
+ blocks: blocks.filter((b) => b.slug !== "repeater")
51
57
  };
52
- if (validationsIdx >= 0) fieldsArr.splice(validationsIdx, 0, subFieldsField);
53
- else fieldsArr.push(subFieldsField);
58
+ (fieldTabOf(repeaterBlock) ?? repeaterBlock.fields).push(subFieldsField);
54
59
  }
55
60
  return blocks;
56
61
  };
@@ -1 +1 @@
1
- {"version":3,"file":"buildFieldBlocks.js","names":[],"sources":["../../src/fields/buildFieldBlocks.ts"],"sourcesContent":["import type { Block, Field } from 'payload'\nimport { buildConditionTypeMap } from '../conditions/conditionType'\nimport { buildConsentSourceConfig } from '../consent/buildConsentSourceConfig'\nimport type { ConsentSourceRegistry } from '../consent/registry'\nimport { keys } from '../translations/keys'\nimport { labelFor } from '../translations/server'\nimport { buildRuleBlocks } from '../validation/buildRuleBlocks'\nimport type { ValidationRuleRegistry } from '../validation/registry'\nimport type { FieldTypeRegistry } from './registry'\nimport { sharedFieldConfig } from './sharedConfig'\n\n/** One add-field block per registered type: shared config, the type's own config, then its validations. */\nexport const buildFieldBlocks = (\n\tregistry: FieldTypeRegistry,\n\truleRegistry: ValidationRuleRegistry,\n\tconsentRegistry?: ConsentSourceRegistry\n): Block[] => {\n\tconst conditionTypes = buildConditionTypeMap(registry)\n\tconst blocks: Block[] = []\n\tfor (const definition of registry.values()) {\n\t\tlet typeConfig: Field[] = definition.config ?? []\n\n\t\t// Inject dynamic source select + conditional sourceConfig group for the consent field.\n\t\t// consent.ts intentionally omits source/sourceConfig; the live registry drives the\n\t\t// select options and per-source field visibility (admin.condition).\n\t\tif (definition.type === 'consent' && consentRegistry) {\n\t\t\t// statement is first; optional is last; source/sourceConfig go in between.\n\t\t\tconst statement = typeConfig.find((f) => (f as { name?: string }).name === 'statement')\n\t\t\tconst optional = typeConfig.find((f) => (f as { name?: string }).name === 'optional')\n\t\t\ttypeConfig = [\n\t\t\t\t...(statement ? [statement] : []),\n\t\t\t\t...buildConsentSourceConfig(consentRegistry),\n\t\t\t\t...(optional ? [optional] : []),\n\t\t\t]\n\t\t}\n\n\t\tblocks.push({\n\t\t\tslug: definition.type,\n\t\t\tlabels: { singular: labelFor(definition.label), plural: labelFor(definition.label) },\n\t\t\tfields: [\n\t\t\t\t...sharedFieldConfig(conditionTypes),\n\t\t\t\t...typeConfig,\n\t\t\t\t{\n\t\t\t\t\tname: 'validations',\n\t\t\t\t\ttype: 'blocks',\n\t\t\t\t\tlabel: labelFor(keys.validationsLabel),\n\t\t\t\t\tblocks: buildRuleBlocks(ruleRegistry, definition.type),\n\t\t\t\t},\n\t\t\t],\n\t\t})\n\t}\n\n\t// Second pass: inject subFields into the repeater block using all non-repeater blocks.\n\t// Done after the main loop so every sibling block is already built.\n\t// Repeater-in-repeater is not supported in v1; the repeater block is excluded from subFields.\n\tconst repeaterBlock = blocks.find((b) => b.slug === 'repeater')\n\tif (repeaterBlock) {\n\t\tconst subFieldBlocks = blocks.filter((b) => b.slug !== 'repeater')\n\t\tconst fieldsArr = repeaterBlock.fields as Field[]\n\t\tconst validationsIdx = fieldsArr.findIndex(\n\t\t\t(f) => (f as { name?: string }).name === 'validations'\n\t\t)\n\t\tconst subFieldsField: Field = {\n\t\t\tname: 'subFields',\n\t\t\ttype: 'blocks',\n\t\t\tlabel: labelFor(keys.configSubFields),\n\t\t\tblocks: subFieldBlocks,\n\t\t}\n\t\tif (validationsIdx >= 0) {\n\t\t\tfieldsArr.splice(validationsIdx, 0, subFieldsField)\n\t\t} else {\n\t\t\tfieldsArr.push(subFieldsField)\n\t\t}\n\t}\n\n\treturn blocks\n}\n"],"mappings":";;;;;;;;AAYA,MAAa,oBACZ,UACA,cACA,oBACa;CACb,MAAM,iBAAiB,sBAAsB,QAAQ;CACrD,MAAM,SAAkB,CAAC;CACzB,KAAK,MAAM,cAAc,SAAS,OAAO,GAAG;EAC3C,IAAI,aAAsB,WAAW,UAAU,CAAC;EAKhD,IAAI,WAAW,SAAS,aAAa,iBAAiB;GAErD,MAAM,YAAY,WAAW,MAAM,MAAO,EAAwB,SAAS,WAAW;GACtF,MAAM,WAAW,WAAW,MAAM,MAAO,EAAwB,SAAS,UAAU;GACpF,aAAa;IACZ,GAAI,YAAY,CAAC,SAAS,IAAI,CAAC;IAC/B,GAAG,yBAAyB,eAAe;IAC3C,GAAI,WAAW,CAAC,QAAQ,IAAI,CAAC;GAC9B;EACD;EAEA,OAAO,KAAK;GACX,MAAM,WAAW;GACjB,QAAQ;IAAE,UAAU,SAAS,WAAW,KAAK;IAAG,QAAQ,SAAS,WAAW,KAAK;GAAE;GACnF,QAAQ;IACP,GAAG,kBAAkB,cAAc;IACnC,GAAG;IACH;KACC,MAAM;KACN,MAAM;KACN,OAAO,SAAS,KAAK,gBAAgB;KACrC,QAAQ,gBAAgB,cAAc,WAAW,IAAI;IACtD;GACD;EACD,CAAC;CACF;CAKA,MAAM,gBAAgB,OAAO,MAAM,MAAM,EAAE,SAAS,UAAU;CAC9D,IAAI,eAAe;EAClB,MAAM,iBAAiB,OAAO,QAAQ,MAAM,EAAE,SAAS,UAAU;EACjE,MAAM,YAAY,cAAc;EAChC,MAAM,iBAAiB,UAAU,WAC/B,MAAO,EAAwB,SAAS,aAC1C;EACA,MAAM,iBAAwB;GAC7B,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,eAAe;GACpC,QAAQ;EACT;EACA,IAAI,kBAAkB,GACrB,UAAU,OAAO,gBAAgB,GAAG,cAAc;OAElD,UAAU,KAAK,cAAc;CAE/B;CAEA,OAAO;AACR"}
1
+ {"version":3,"file":"buildFieldBlocks.js","names":[],"sources":["../../src/fields/buildFieldBlocks.ts"],"sourcesContent":["import type { Block, Field, TabsField } from 'payload'\nimport { buildConditionTypeMap } from '../conditions/conditionType'\nimport { buildConsentSourceConfig } from '../consent/buildConsentSourceConfig'\nimport type { ConsentSourceRegistry } from '../consent/registry'\nimport { keys } from '../translations/keys'\nimport { labelFor } from '../translations/server'\nimport { buildRuleBlocks } from '../validation/buildRuleBlocks'\nimport type { ValidationRuleRegistry } from '../validation/registry'\nimport type { FieldTypeRegistry } from './registry'\nimport { fieldBlockTabs } from './sharedConfig'\n\n/** Whether `fields` contains a field named `name`, descending into presentational rows. */\nconst hasNameField = (fields: Field[]): boolean =>\n\tfields.some((f) => {\n\t\tif ('name' in f && f.name === 'name') {\n\t\t\treturn true\n\t\t}\n\t\treturn f.type === 'row' && hasNameField(f.fields)\n\t})\n\n/** The tab whose fields hold the shared basics and type config, found by the `name` field it carries. */\nconst fieldTabOf = (block: Block): Field[] | undefined => {\n\tconst tabsField = block.fields.find((f): f is TabsField => f.type === 'tabs')\n\treturn tabsField?.tabs.find((tab) => hasNameField(tab.fields))?.fields\n}\n\n/**\n * One add-field block per registered type: tabs holding shared config, type config, and\n * validations. `localize` controls whether the shared content fields carry `localized: true`;\n * per-type config fields carry their own flag from the registry definitions.\n */\ntype BuildFieldBlocksArgs = {\n\tregistry: FieldTypeRegistry\n\truleRegistry: ValidationRuleRegistry\n\tconsentRegistry?: ConsentSourceRegistry\n\tlocalize?: boolean\n}\n\nexport const buildFieldBlocks = ({\n\tregistry,\n\truleRegistry,\n\tconsentRegistry,\n\tlocalize = true,\n}: BuildFieldBlocksArgs): Block[] => {\n\tconst conditionTypes = buildConditionTypeMap(registry)\n\tconst blocks: Block[] = []\n\tfor (const definition of registry.values()) {\n\t\tlet typeConfig: Field[] = definition.config ?? []\n\n\t\t// Inject dynamic source select + conditional sourceConfig group for the consent field.\n\t\t// consent.ts intentionally omits source/sourceConfig; the live registry drives the\n\t\t// select options and per-source field visibility (admin.condition).\n\t\tif (definition.type === 'consent' && consentRegistry) {\n\t\t\t// statement is first; optional is last; source/sourceConfig go in between.\n\t\t\tconst statement = typeConfig.find((f) => (f as { name?: string }).name === 'statement')\n\t\t\tconst optional = typeConfig.find((f) => (f as { name?: string }).name === 'optional')\n\t\t\ttypeConfig = [\n\t\t\t\t...(statement ? [statement] : []),\n\t\t\t\t...buildConsentSourceConfig(consentRegistry),\n\t\t\t\t...(optional ? [optional] : []),\n\t\t\t]\n\t\t}\n\n\t\tblocks.push({\n\t\t\tslug: definition.type,\n\t\t\tlabels: { singular: labelFor(definition.label), plural: labelFor(definition.label) },\n\t\t\tfields: [\n\t\t\t\tfieldBlockTabs({\n\t\t\t\t\tconditionTypes,\n\t\t\t\t\ttypeConfig,\n\t\t\t\t\tvalidations: {\n\t\t\t\t\t\tname: 'validations',\n\t\t\t\t\t\ttype: 'blocks',\n\t\t\t\t\t\tlabel: labelFor(keys.validationsLabel),\n\t\t\t\t\t\tblocks: buildRuleBlocks(ruleRegistry, definition.type),\n\t\t\t\t\t},\n\t\t\t\t\tlocalize,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\t// Second pass: inject subFields into the repeater block using all non-repeater blocks.\n\t// Done after the main loop so every sibling block is already built.\n\t// Repeater-in-repeater is not supported in v1; the repeater block is excluded from subFields.\n\tconst repeaterBlock = blocks.find((b) => b.slug === 'repeater')\n\tif (repeaterBlock) {\n\t\tconst subFieldsField: Field = {\n\t\t\tname: 'subFields',\n\t\t\ttype: 'blocks',\n\t\t\tlabel: labelFor(keys.configSubFields),\n\t\t\tblocks: blocks.filter((b) => b.slug !== 'repeater'),\n\t\t}\n\t\tconst fieldTabFields = fieldTabOf(repeaterBlock)\n\t\t;(fieldTabFields ?? (repeaterBlock.fields as Field[])).push(subFieldsField)\n\t}\n\n\treturn blocks\n}\n"],"mappings":";;;;;;;;AAYA,MAAM,gBAAgB,WACrB,OAAO,MAAM,MAAM;CAClB,IAAI,UAAU,KAAK,EAAE,SAAS,QAC7B,OAAO;CAER,OAAO,EAAE,SAAS,SAAS,aAAa,EAAE,MAAM;AACjD,CAAC;;AAGF,MAAM,cAAc,UAAsC;CAEzD,OADkB,MAAM,OAAO,MAAM,MAAsB,EAAE,SAAS,MACvD,GAAG,KAAK,MAAM,QAAQ,aAAa,IAAI,MAAM,CAAC,GAAG;AACjE;AAcA,MAAa,oBAAoB,EAChC,UACA,cACA,iBACA,WAAW,WACyB;CACpC,MAAM,iBAAiB,sBAAsB,QAAQ;CACrD,MAAM,SAAkB,CAAC;CACzB,KAAK,MAAM,cAAc,SAAS,OAAO,GAAG;EAC3C,IAAI,aAAsB,WAAW,UAAU,CAAC;EAKhD,IAAI,WAAW,SAAS,aAAa,iBAAiB;GAErD,MAAM,YAAY,WAAW,MAAM,MAAO,EAAwB,SAAS,WAAW;GACtF,MAAM,WAAW,WAAW,MAAM,MAAO,EAAwB,SAAS,UAAU;GACpF,aAAa;IACZ,GAAI,YAAY,CAAC,SAAS,IAAI,CAAC;IAC/B,GAAG,yBAAyB,eAAe;IAC3C,GAAI,WAAW,CAAC,QAAQ,IAAI,CAAC;GAC9B;EACD;EAEA,OAAO,KAAK;GACX,MAAM,WAAW;GACjB,QAAQ;IAAE,UAAU,SAAS,WAAW,KAAK;IAAG,QAAQ,SAAS,WAAW,KAAK;GAAE;GACnF,QAAQ,CACP,eAAe;IACd;IACA;IACA,aAAa;KACZ,MAAM;KACN,MAAM;KACN,OAAO,SAAS,KAAK,gBAAgB;KACrC,QAAQ,gBAAgB,cAAc,WAAW,IAAI;IACtD;IACA;GACD,CAAC,CACF;EACD,CAAC;CACF;CAKA,MAAM,gBAAgB,OAAO,MAAM,MAAM,EAAE,SAAS,UAAU;CAC9D,IAAI,eAAe;EAClB,MAAM,iBAAwB;GAC7B,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,eAAe;GACpC,QAAQ,OAAO,QAAQ,MAAM,EAAE,SAAS,UAAU;EACnD;EAEC,CADsB,WAAW,aACnB,KAAM,cAAc,QAAoB,KAAK,cAAc;CAC3E;CAEA,OAAO;AACR"}
@@ -1,7 +1,116 @@
1
1
  import { keys } from "../../translations/keys.js";
2
- import { labelFor } from "../../translations/server.js";
2
+ import { asTranslate, labelFor } from "../../translations/server.js";
3
+ import { CALC_FNS, CALC_OPS } from "../../calc/types.js";
4
+ import { normalizeCalc } from "../../calc/normalizeCalc.js";
3
5
  import { defineFormField } from "../defineFormField.js";
4
6
  //#region src/fields/builtin/calculation.ts
7
+ /**
8
+ * Editor-facing JSON schema for `CalcExpression` (src/calc/types.ts), used by the admin JSON
9
+ * field's Monaco editor for autocomplete and inline diagnostics. The real validity gate is
10
+ * `validateExpression`/`normalizeCalc`; this schema is a convenience, not the source of truth.
11
+ */
12
+ const calcExpressionSchema = {
13
+ uri: "https://10xmedia.de/schemas/form-builder/calc-expression.json",
14
+ fileMatch: ["https://10xmedia.de/schemas/form-builder/calc-expression.json"],
15
+ schema: {
16
+ $ref: "#/definitions/expr",
17
+ definitions: {
18
+ expr: { oneOf: [
19
+ { $ref: "#/definitions/lit" },
20
+ { $ref: "#/definitions/ref" },
21
+ { $ref: "#/definitions/op" },
22
+ { $ref: "#/definitions/neg" },
23
+ { $ref: "#/definitions/fn" },
24
+ { $ref: "#/definitions/weight" }
25
+ ] },
26
+ lit: {
27
+ type: "object",
28
+ properties: {
29
+ type: { enum: ["lit"] },
30
+ value: { type: "number" }
31
+ },
32
+ required: ["type", "value"],
33
+ additionalProperties: false
34
+ },
35
+ ref: {
36
+ type: "object",
37
+ properties: {
38
+ type: { enum: ["ref"] },
39
+ field: { type: "string" }
40
+ },
41
+ required: ["type", "field"],
42
+ additionalProperties: false
43
+ },
44
+ op: {
45
+ type: "object",
46
+ properties: {
47
+ type: { enum: ["op"] },
48
+ op: { enum: [...CALC_OPS] },
49
+ left: { $ref: "#/definitions/expr" },
50
+ right: { $ref: "#/definitions/expr" }
51
+ },
52
+ required: [
53
+ "type",
54
+ "op",
55
+ "left",
56
+ "right"
57
+ ],
58
+ additionalProperties: false
59
+ },
60
+ neg: {
61
+ type: "object",
62
+ properties: {
63
+ type: { enum: ["neg"] },
64
+ operand: { $ref: "#/definitions/expr" }
65
+ },
66
+ required: ["type", "operand"],
67
+ additionalProperties: false
68
+ },
69
+ fn: {
70
+ type: "object",
71
+ properties: {
72
+ type: { enum: ["fn"] },
73
+ fn: { enum: [...CALC_FNS] },
74
+ args: {
75
+ type: "array",
76
+ items: { $ref: "#/definitions/expr" }
77
+ }
78
+ },
79
+ required: [
80
+ "type",
81
+ "fn",
82
+ "args"
83
+ ],
84
+ additionalProperties: false
85
+ },
86
+ weight: {
87
+ type: "object",
88
+ properties: {
89
+ type: { enum: ["weight"] },
90
+ field: { type: "string" },
91
+ weights: {
92
+ type: "object",
93
+ additionalProperties: { type: "number" }
94
+ }
95
+ },
96
+ required: [
97
+ "type",
98
+ "field",
99
+ "weights"
100
+ ],
101
+ additionalProperties: false
102
+ }
103
+ }
104
+ }
105
+ };
106
+ /**
107
+ * Validates the calculation field's `expression`: unset/empty is fine, otherwise it must
108
+ * normalize into a well-formed `CalcExpression` tree. Exported for unit testing.
109
+ */
110
+ const validateExpression = (value, { req }) => {
111
+ if (value == null || value === "") return true;
112
+ return normalizeCalc(value) !== void 0 ? true : asTranslate(req.t)(keys.validationCalcExpressionInvalid);
113
+ };
5
114
  const calculationField = defineFormField({
6
115
  type: "calculation",
7
116
  label: keys.fieldTypeCalculation,
@@ -9,7 +118,11 @@ const calculationField = defineFormField({
9
118
  config: [{
10
119
  name: "expression",
11
120
  type: "json",
12
- label: labelFor(keys.configExpression)
121
+ label: labelFor(keys.configExpression),
122
+ admin: { description: labelFor(keys.configExpressionDescription) },
123
+ jsonSchema: calcExpressionSchema,
124
+ typescriptSchema: [() => ({ type: "object" })],
125
+ validate: validateExpression
13
126
  }, {
14
127
  name: "calcDisplay",
15
128
  type: "checkbox",
@@ -1 +1 @@
1
- {"version":3,"file":"calculation.js","names":[],"sources":["../../../src/fields/builtin/calculation.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\n\nexport const calculationField = defineFormField<'number'>({\n\ttype: 'calculation',\n\tlabel: keys.fieldTypeCalculation,\n\tvalue: 'number',\n\tconfig: [\n\t\t{ name: 'expression', type: 'json', label: labelFor(keys.configExpression) },\n\t\t{\n\t\t\tname: 'calcDisplay',\n\t\t\ttype: 'checkbox',\n\t\t\tdefaultValue: true,\n\t\t\tlabel: labelFor(keys.configCalcDisplay),\n\t\t},\n\t],\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n"],"mappings":";;;;AAIA,MAAa,mBAAmB,gBAA0B;CACzD,MAAM;CACN,OAAO,KAAK;CACZ,OAAO;CACP,QAAQ,CACP;EAAE,MAAM;EAAc,MAAM;EAAQ,OAAO,SAAS,KAAK,gBAAgB;CAAE,GAC3E;EACC,MAAM;EACN,MAAM;EACN,cAAc;EACd,OAAO,SAAS,KAAK,iBAAiB;CACvC,CACD;CACA,SAAS,EAAE,YAAa,SAAS,OAAO,KAAK,OAAO,KAAK;AAC1D,CAAC"}
1
+ {"version":3,"file":"calculation.js","names":[],"sources":["../../../src/fields/builtin/calculation.ts"],"sourcesContent":["import type { JSONField, PayloadRequest } from 'payload'\nimport { normalizeCalc } from '../../calc/normalizeCalc'\nimport { CALC_FNS, CALC_OPS } from '../../calc/types'\nimport { keys } from '../../translations/keys'\nimport { asTranslate, labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\n\ntype CalcExpressionSchema = NonNullable<JSONField['jsonSchema']>\n\n/**\n * Editor-facing JSON schema for `CalcExpression` (src/calc/types.ts), used by the admin JSON\n * field's Monaco editor for autocomplete and inline diagnostics. The real validity gate is\n * `validateExpression`/`normalizeCalc`; this schema is a convenience, not the source of truth.\n */\nconst calcExpressionSchema: CalcExpressionSchema = {\n\turi: 'https://10xmedia.de/schemas/form-builder/calc-expression.json',\n\tfileMatch: ['https://10xmedia.de/schemas/form-builder/calc-expression.json'],\n\tschema: {\n\t\t$ref: '#/definitions/expr',\n\t\tdefinitions: {\n\t\t\texpr: {\n\t\t\t\toneOf: [\n\t\t\t\t\t{ $ref: '#/definitions/lit' },\n\t\t\t\t\t{ $ref: '#/definitions/ref' },\n\t\t\t\t\t{ $ref: '#/definitions/op' },\n\t\t\t\t\t{ $ref: '#/definitions/neg' },\n\t\t\t\t\t{ $ref: '#/definitions/fn' },\n\t\t\t\t\t{ $ref: '#/definitions/weight' },\n\t\t\t\t],\n\t\t\t},\n\t\t\tlit: {\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: { type: { enum: ['lit'] }, value: { type: 'number' } },\n\t\t\t\trequired: ['type', 'value'],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t\tref: {\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: { type: { enum: ['ref'] }, field: { type: 'string' } },\n\t\t\t\trequired: ['type', 'field'],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t\top: {\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: {\n\t\t\t\t\ttype: { enum: ['op'] },\n\t\t\t\t\top: { enum: [...CALC_OPS] },\n\t\t\t\t\tleft: { $ref: '#/definitions/expr' },\n\t\t\t\t\tright: { $ref: '#/definitions/expr' },\n\t\t\t\t},\n\t\t\t\trequired: ['type', 'op', 'left', 'right'],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t\tneg: {\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: { type: { enum: ['neg'] }, operand: { $ref: '#/definitions/expr' } },\n\t\t\t\trequired: ['type', 'operand'],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t\tfn: {\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: {\n\t\t\t\t\ttype: { enum: ['fn'] },\n\t\t\t\t\tfn: { enum: [...CALC_FNS] },\n\t\t\t\t\targs: { type: 'array', items: { $ref: '#/definitions/expr' } },\n\t\t\t\t},\n\t\t\t\trequired: ['type', 'fn', 'args'],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t\tweight: {\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: {\n\t\t\t\t\ttype: { enum: ['weight'] },\n\t\t\t\t\tfield: { type: 'string' },\n\t\t\t\t\tweights: { type: 'object', additionalProperties: { type: 'number' } },\n\t\t\t\t},\n\t\t\t\trequired: ['type', 'field', 'weights'],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t},\n\t},\n}\n\n/**\n * Validates the calculation field's `expression`: unset/empty is fine, otherwise it must\n * normalize into a well-formed `CalcExpression` tree. Exported for unit testing.\n */\nexport const validateExpression = (\n\tvalue: unknown,\n\t{ req }: { data?: unknown; req: PayloadRequest }\n): string | true => {\n\tif (value == null || value === '') {\n\t\treturn true\n\t}\n\treturn normalizeCalc(value) !== undefined\n\t\t? true\n\t\t: asTranslate(req.t)(keys.validationCalcExpressionInvalid)\n}\n\nexport const calculationField = defineFormField<'number'>({\n\ttype: 'calculation',\n\tlabel: keys.fieldTypeCalculation,\n\tvalue: 'number',\n\tconfig: [\n\t\t{\n\t\t\tname: 'expression',\n\t\t\ttype: 'json',\n\t\t\tlabel: labelFor(keys.configExpression),\n\t\t\tadmin: { description: labelFor(keys.configExpressionDescription) },\n\t\t\tjsonSchema: calcExpressionSchema,\n\t\t\t// generate:types embeds jsonSchema.schema into the config-level schema, where its\n\t\t\t// document-root-relative $refs cannot resolve; hand type generation a flat shape instead.\n\t\t\ttypescriptSchema: [() => ({ type: 'object' })],\n\t\t\tvalidate: validateExpression,\n\t\t},\n\t\t{\n\t\t\tname: 'calcDisplay',\n\t\t\ttype: 'checkbox',\n\t\t\tdefaultValue: true,\n\t\t\tlabel: labelFor(keys.configCalcDisplay),\n\t\t},\n\t],\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n"],"mappings":";;;;;;;;;;;AAcA,MAAM,uBAA6C;CAClD,KAAK;CACL,WAAW,CAAC,+DAA+D;CAC3E,QAAQ;EACP,MAAM;EACN,aAAa;GACZ,MAAM,EACL,OAAO;IACN,EAAE,MAAM,oBAAoB;IAC5B,EAAE,MAAM,oBAAoB;IAC5B,EAAE,MAAM,mBAAmB;IAC3B,EAAE,MAAM,oBAAoB;IAC5B,EAAE,MAAM,mBAAmB;IAC3B,EAAE,MAAM,uBAAuB;GAChC,EACD;GACA,KAAK;IACJ,MAAM;IACN,YAAY;KAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE;KAAG,OAAO,EAAE,MAAM,SAAS;IAAE;IACjE,UAAU,CAAC,QAAQ,OAAO;IAC1B,sBAAsB;GACvB;GACA,KAAK;IACJ,MAAM;IACN,YAAY;KAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE;KAAG,OAAO,EAAE,MAAM,SAAS;IAAE;IACjE,UAAU,CAAC,QAAQ,OAAO;IAC1B,sBAAsB;GACvB;GACA,IAAI;IACH,MAAM;IACN,YAAY;KACX,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;KACrB,IAAI,EAAE,MAAM,CAAC,GAAG,QAAQ,EAAE;KAC1B,MAAM,EAAE,MAAM,qBAAqB;KACnC,OAAO,EAAE,MAAM,qBAAqB;IACrC;IACA,UAAU;KAAC;KAAQ;KAAM;KAAQ;IAAO;IACxC,sBAAsB;GACvB;GACA,KAAK;IACJ,MAAM;IACN,YAAY;KAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE;KAAG,SAAS,EAAE,MAAM,qBAAqB;IAAE;IAC/E,UAAU,CAAC,QAAQ,SAAS;IAC5B,sBAAsB;GACvB;GACA,IAAI;IACH,MAAM;IACN,YAAY;KACX,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;KACrB,IAAI,EAAE,MAAM,CAAC,GAAG,QAAQ,EAAE;KAC1B,MAAM;MAAE,MAAM;MAAS,OAAO,EAAE,MAAM,qBAAqB;KAAE;IAC9D;IACA,UAAU;KAAC;KAAQ;KAAM;IAAM;IAC/B,sBAAsB;GACvB;GACA,QAAQ;IACP,MAAM;IACN,YAAY;KACX,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE;KACzB,OAAO,EAAE,MAAM,SAAS;KACxB,SAAS;MAAE,MAAM;MAAU,sBAAsB,EAAE,MAAM,SAAS;KAAE;IACrE;IACA,UAAU;KAAC;KAAQ;KAAS;IAAS;IACrC,sBAAsB;GACvB;EACD;CACD;AACD;;;;;AAMA,MAAa,sBACZ,OACA,EAAE,UACiB;CACnB,IAAI,SAAS,QAAQ,UAAU,IAC9B,OAAO;CAER,OAAO,cAAc,KAAK,MAAM,KAAA,IAC7B,OACA,YAAY,IAAI,CAAC,EAAE,KAAK,+BAA+B;AAC3D;AAEA,MAAa,mBAAmB,gBAA0B;CACzD,MAAM;CACN,OAAO,KAAK;CACZ,OAAO;CACP,QAAQ,CACP;EACC,MAAM;EACN,MAAM;EACN,OAAO,SAAS,KAAK,gBAAgB;EACrC,OAAO,EAAE,aAAa,SAAS,KAAK,2BAA2B,EAAE;EACjE,YAAY;EAGZ,kBAAkB,QAAQ,EAAE,MAAM,SAAS,EAAE;EAC7C,UAAU;CACX,GACA;EACC,MAAM;EACN,MAAM;EACN,cAAc;EACd,OAAO,SAAS,KAAK,iBAAiB;CACvC,CACD;CACA,SAAS,EAAE,YAAa,SAAS,OAAO,KAAK,OAAO,KAAK;AAC1D,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { localizedIf } from "../localizedIf.js";
1
2
  import { keys } from "../../translations/keys.js";
2
3
  import { labelFor } from "../../translations/server.js";
3
4
  import { defineFormField } from "../defineFormField.js";
@@ -5,16 +6,18 @@ import { defineFormField } from "../defineFormField.js";
5
6
  /**
6
7
  * Base consent field definition. `source` select and `sourceConfig` group are injected
7
8
  * by `buildFieldBlocks` from the live `consentRegistry`, so only the selected source's
8
- * fields are visible in the admin UI via `admin.condition`.
9
+ * fields are visible in the admin UI via `admin.condition`. The `statement` is
10
+ * author-facing content and follows `localize`.
9
11
  */
10
- const consentField = defineFormField({
12
+ const buildConsentField = (localize) => defineFormField({
11
13
  type: "consent",
12
14
  label: keys.fieldTypeConsent,
13
15
  value: "boolean",
14
16
  config: [{
15
17
  name: "statement",
16
18
  type: "text",
17
- label: labelFor(keys.consentConfigStatement)
19
+ label: labelFor(keys.consentConfigStatement),
20
+ ...localizedIf(localize)
18
21
  }, {
19
22
  name: "optional",
20
23
  type: "checkbox",
@@ -26,7 +29,8 @@ const consentField = defineFormField({
26
29
  },
27
30
  format: ({ value, t }) => t(value === true ? keys.formatYes : keys.formatNo)
28
31
  });
32
+ buildConsentField(true);
29
33
  //#endregion
30
- export { consentField };
34
+ export { buildConsentField };
31
35
 
32
36
  //# sourceMappingURL=consent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consent.js","names":[],"sources":["../../../src/fields/builtin/consent.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\n\ntype ConsentConfig = {\n\tstatement?: string\n\tsource?: string\n\tsourceConfig?: Record<string, unknown>\n\toptional?: boolean\n}\n\n/**\n * Base consent field definition. `source` select and `sourceConfig` group are injected\n * by `buildFieldBlocks` from the live `consentRegistry`, so only the selected source's\n * fields are visible in the admin UI via `admin.condition`.\n */\nexport const consentField = defineFormField<'boolean', ConsentConfig>({\n\ttype: 'consent',\n\tlabel: keys.fieldTypeConsent,\n\tvalue: 'boolean',\n\tconfig: [\n\t\t{ name: 'statement', type: 'text', label: labelFor(keys.consentConfigStatement) },\n\t\t// source select and sourceConfig group are injected by buildFieldBlocks at plugin boot\n\t\t// so the options reflect the live consentRegistry rather than this static list.\n\t\t{ name: 'optional', type: 'checkbox', label: labelFor(keys.consentConfigOptional) },\n\t],\n\tvalidate: ({ value, config, t }) => {\n\t\tconst optional = (config as ConsentConfig).optional === true\n\t\tif (!optional && value !== true) {\n\t\t\treturn t(keys.validationRequired)\n\t\t}\n\t\treturn true\n\t},\n\tformat: ({ value, t }) => t(value === true ? keys.formatYes : keys.formatNo),\n})\n"],"mappings":";;;;;;;;;AAgBA,MAAa,eAAe,gBAA0C;CACrE,MAAM;CACN,OAAO,KAAK;CACZ,OAAO;CACP,QAAQ,CACP;EAAE,MAAM;EAAa,MAAM;EAAQ,OAAO,SAAS,KAAK,sBAAsB;CAAE,GAGhF;EAAE,MAAM;EAAY,MAAM;EAAY,OAAO,SAAS,KAAK,qBAAqB;CAAE,CACnF;CACA,WAAW,EAAE,OAAO,QAAQ,QAAQ;EAEnC,IAAI,EADc,OAAyB,aAAa,SACvC,UAAU,MAC1B,OAAO,EAAE,KAAK,kBAAkB;EAEjC,OAAO;CACR;CACA,SAAS,EAAE,OAAO,QAAQ,EAAE,UAAU,OAAO,KAAK,YAAY,KAAK,QAAQ;AAC5E,CAAC"}
1
+ {"version":3,"file":"consent.js","names":[],"sources":["../../../src/fields/builtin/consent.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineFormField } from '../defineFormField'\nimport { localizedIf } from '../localizedIf'\n\ntype ConsentConfig = {\n\tstatement?: string\n\tsource?: string\n\tsourceConfig?: Record<string, unknown>\n\toptional?: boolean\n}\n\n/**\n * Base consent field definition. `source` select and `sourceConfig` group are injected\n * by `buildFieldBlocks` from the live `consentRegistry`, so only the selected source's\n * fields are visible in the admin UI via `admin.condition`. The `statement` is\n * author-facing content and follows `localize`.\n */\nexport const buildConsentField = (localize: boolean) =>\n\tdefineFormField<'boolean', ConsentConfig>({\n\t\ttype: 'consent',\n\t\tlabel: keys.fieldTypeConsent,\n\t\tvalue: 'boolean',\n\t\tconfig: [\n\t\t\t{\n\t\t\t\tname: 'statement',\n\t\t\t\ttype: 'text',\n\t\t\t\tlabel: labelFor(keys.consentConfigStatement),\n\t\t\t\t...localizedIf(localize),\n\t\t\t},\n\t\t\t// source select and sourceConfig group are injected by buildFieldBlocks at plugin boot\n\t\t\t// so the options reflect the live consentRegistry rather than this static list.\n\t\t\t{ name: 'optional', type: 'checkbox', label: labelFor(keys.consentConfigOptional) },\n\t\t],\n\t\tvalidate: ({ value, config, t }) => {\n\t\t\tconst optional = (config as ConsentConfig).optional === true\n\t\t\tif (!optional && value !== true) {\n\t\t\t\treturn t(keys.validationRequired)\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t\tformat: ({ value, t }) => t(value === true ? keys.formatYes : keys.formatNo),\n\t})\n\nexport const consentField = buildConsentField(true)\n"],"mappings":";;;;;;;;;;;AAkBA,MAAa,qBAAqB,aACjC,gBAA0C;CACzC,MAAM;CACN,OAAO,KAAK;CACZ,OAAO;CACP,QAAQ,CACP;EACC,MAAM;EACN,MAAM;EACN,OAAO,SAAS,KAAK,sBAAsB;EAC3C,GAAG,YAAY,QAAQ;CACxB,GAGA;EAAE,MAAM;EAAY,MAAM;EAAY,OAAO,SAAS,KAAK,qBAAqB;CAAE,CACnF;CACA,WAAW,EAAE,OAAO,QAAQ,QAAQ;EAEnC,IAAI,EADc,OAAyB,aAAa,SACvC,UAAU,MAC1B,OAAO,EAAE,KAAK,kBAAkB;EAEjC,OAAO;CACR;CACA,SAAS,EAAE,OAAO,QAAQ,EAAE,UAAU,OAAO,KAAK,YAAY,KAAK,QAAQ;AAC5E,CAAC;AAE0B,kBAAkB,IAAI"}
@@ -0,0 +1,29 @@
1
+ import { keys } from "../../translations/keys.js";
2
+ import { defineFormField } from "../defineFormField.js";
3
+ //#region src/fields/builtin/date.ts
4
+ const DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
5
+ /** True calendar-date check for `YYYY-MM-DD` strings (rejects e.g. `2024-02-30`). */
6
+ const isValidCalendarDate = (value) => {
7
+ const match = DATE_PATTERN.exec(value);
8
+ if (!match) return false;
9
+ const [, yearStr, monthStr, dayStr] = match;
10
+ const year = Number(yearStr);
11
+ const month = Number(monthStr);
12
+ const day = Number(dayStr);
13
+ const date = new Date(Date.UTC(year, month - 1, day));
14
+ return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
15
+ };
16
+ const dateField = defineFormField({
17
+ type: "date",
18
+ label: keys.fieldTypeDate,
19
+ value: "date",
20
+ validate: ({ value, t }) => {
21
+ if (value == null || value === "") return true;
22
+ return isValidCalendarDate(value) ? true : t(keys.validationDate);
23
+ },
24
+ format: ({ value }) => value == null ? "" : String(value)
25
+ });
26
+ //#endregion
27
+ export { dateField, isValidCalendarDate };
28
+
29
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.js","names":[],"sources":["../../../src/fields/builtin/date.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { defineFormField } from '../defineFormField'\n\nconst DATE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/\n\n/** True calendar-date check for `YYYY-MM-DD` strings (rejects e.g. `2024-02-30`). */\nexport const isValidCalendarDate = (value: string): boolean => {\n\tconst match = DATE_PATTERN.exec(value)\n\tif (!match) {\n\t\treturn false\n\t}\n\tconst [, yearStr, monthStr, dayStr] = match\n\tconst year = Number(yearStr)\n\tconst month = Number(monthStr)\n\tconst day = Number(dayStr)\n\tconst date = new Date(Date.UTC(year, month - 1, day))\n\treturn (\n\t\tdate.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day\n\t)\n}\n\nexport const dateField = defineFormField<'date'>({\n\ttype: 'date',\n\tlabel: keys.fieldTypeDate,\n\tvalue: 'date',\n\tvalidate: ({ value, t }) => {\n\t\tif (value == null || value === '') {\n\t\t\treturn true\n\t\t}\n\t\treturn isValidCalendarDate(value) ? true : t(keys.validationDate)\n\t},\n\tformat: ({ value }) => (value == null ? '' : String(value)),\n})\n"],"mappings":";;;AAGA,MAAM,eAAe;;AAGrB,MAAa,uBAAuB,UAA2B;CAC9D,MAAM,QAAQ,aAAa,KAAK,KAAK;CACrC,IAAI,CAAC,OACJ,OAAO;CAER,MAAM,GAAG,SAAS,UAAU,UAAU;CACtC,MAAM,OAAO,OAAO,OAAO;CAC3B,MAAM,QAAQ,OAAO,QAAQ;CAC7B,MAAM,MAAM,OAAO,MAAM;CACzB,MAAM,OAAO,IAAI,KAAK,KAAK,IAAI,MAAM,QAAQ,GAAG,GAAG,CAAC;CACpD,OACC,KAAK,eAAe,MAAM,QAAQ,KAAK,YAAY,MAAM,QAAQ,KAAK,KAAK,WAAW,MAAM;AAE9F;AAEA,MAAa,YAAY,gBAAwB;CAChD,MAAM;CACN,OAAO,KAAK;CACZ,OAAO;CACP,WAAW,EAAE,OAAO,QAAQ;EAC3B,IAAI,SAAS,QAAQ,UAAU,IAC9B,OAAO;EAER,OAAO,oBAAoB,KAAK,IAAI,OAAO,EAAE,KAAK,cAAc;CACjE;CACA,SAAS,EAAE,YAAa,SAAS,OAAO,KAAK,OAAO,KAAK;AAC1D,CAAC"}
@@ -0,0 +1,15 @@
1
+ //#region src/fields/builtin/file.d.ts
2
+ /**
3
+ * Curated MIME type choices for the file field's `mimeTypes` select. Values are raw MIME strings or
4
+ * trailing-`*` prefix wildcards, exactly the patterns `resolveFileRef` matches server-side; `type/*`
5
+ * values double as the file input's `accept` attribute (browsers ignore other prefix patterns, which
6
+ * is fine since the server stays authoritative). Every value must be 63 bytes or less: Payload's
7
+ * db-postgres adapter stores select options as a pg enum, and pg enum labels cap at 63 bytes.
8
+ */
9
+ declare const fileMimeTypeOptions: {
10
+ label: string;
11
+ value: string;
12
+ }[];
13
+ //#endregion
14
+ export { fileMimeTypeOptions };
15
+ //# sourceMappingURL=file.d.ts.map