@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
@@ -3,10 +3,10 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/react/primitives/FieldShell.tsx
4
4
  /**
5
5
  * Accessible wrapper for a single field: a `<label>` bound to the control, the control slot, an optional
6
- * description, and error/warning messages. The control inside must set `aria-describedby={describedById}`
6
+ * description, and error messages. The control inside must set `aria-describedby={describedById}`
7
7
  * and `aria-invalid` when errors exist; this shell renders the matching `id={describedById}` region.
8
8
  */
9
- const FieldShell = ({ id, label, description, required, errors = [], warnings = [], describedById, children }) => /* @__PURE__ */ jsxs("div", {
9
+ const FieldShell = ({ id, label, description, required, errors = [], describedById, children }) => /* @__PURE__ */ jsxs("div", {
10
10
  className: "fb-field",
11
11
  "data-invalid": errors.length > 0 ? "" : void 0,
12
12
  children: [
@@ -23,25 +23,18 @@ const FieldShell = ({ id, label, description, required, errors = [], warnings =
23
23
  /* @__PURE__ */ jsxs("div", {
24
24
  id: describedById,
25
25
  className: "fb-field__messages",
26
- children: [
27
- description ? /* @__PURE__ */ jsx("p", {
28
- className: "fb-field__description",
29
- children: description
30
- }) : null,
31
- errors.length > 0 ? /* @__PURE__ */ jsx("div", {
32
- role: "alert",
33
- "aria-atomic": "true",
34
- className: "fb-field__errors",
35
- children: errors.map((message) => /* @__PURE__ */ jsx("p", {
36
- className: "fb-field__error",
37
- children: message
38
- }, message))
39
- }) : null,
40
- warnings.map((message) => /* @__PURE__ */ jsx("p", {
41
- className: "fb-field__warning",
26
+ children: [description ? /* @__PURE__ */ jsx("p", {
27
+ className: "fb-field__description",
28
+ children: description
29
+ }) : null, errors.length > 0 ? /* @__PURE__ */ jsx("div", {
30
+ role: "alert",
31
+ "aria-atomic": "true",
32
+ className: "fb-field__errors",
33
+ children: errors.map((message) => /* @__PURE__ */ jsx("p", {
34
+ className: "fb-field__error",
42
35
  children: message
43
36
  }, message))
44
- ]
37
+ }) : null]
45
38
  })
46
39
  ]
47
40
  });
@@ -1 +1 @@
1
- {"version":3,"file":"FieldShell.js","names":[],"sources":["../../../src/react/primitives/FieldShell.tsx"],"sourcesContent":["'use client'\n\nimport type { ReactNode } from 'react'\n\nexport type FieldShellProps = {\n\t/** The control id this shell labels and describes. */\n\tid: string\n\tlabel?: string\n\tdescription?: string\n\trequired?: boolean\n\terrors?: string[]\n\twarnings?: string[]\n\t/** id used for aria-describedby on the control; the shell renders description + messages under it. */\n\tdescribedById: string\n\tchildren: ReactNode\n}\n\n/**\n * Accessible wrapper for a single field: a `<label>` bound to the control, the control slot, an optional\n * description, and error/warning messages. The control inside must set `aria-describedby={describedById}`\n * and `aria-invalid` when errors exist; this shell renders the matching `id={describedById}` region.\n */\nexport const FieldShell = ({\n\tid,\n\tlabel,\n\tdescription,\n\trequired,\n\terrors = [],\n\twarnings = [],\n\tdescribedById,\n\tchildren,\n}: FieldShellProps) => (\n\t<div className=\"fb-field\" data-invalid={errors.length > 0 ? '' : undefined}>\n\t\t{label ? (\n\t\t\t<label className=\"fb-field__label\" htmlFor={id}>\n\t\t\t\t{label}\n\t\t\t\t{required ? (\n\t\t\t\t\t<span className=\"fb-field__required\" aria-hidden=\"true\">\n\t\t\t\t\t\t{' *'}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</label>\n\t\t) : null}\n\t\t{children}\n\t\t<div id={describedById} className=\"fb-field__messages\">\n\t\t\t{description ? <p className=\"fb-field__description\">{description}</p> : null}\n\t\t\t{errors.length > 0 ? (\n\t\t\t\t<div role=\"alert\" aria-atomic=\"true\" className=\"fb-field__errors\">\n\t\t\t\t\t{errors.map((message) => (\n\t\t\t\t\t\t<p key={message} className=\"fb-field__error\">\n\t\t\t\t\t\t\t{message}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t{warnings.map((message) => (\n\t\t\t\t<p key={message} className=\"fb-field__warning\">\n\t\t\t\t\t{message}\n\t\t\t\t</p>\n\t\t\t))}\n\t\t</div>\n\t</div>\n)\n"],"mappings":";;;;;;;;AAsBA,MAAa,cAAc,EAC1B,IACA,OACA,aACA,UACA,SAAS,CAAC,GACV,WAAW,CAAC,GACZ,eACA,eAEA,qBAAC,OAAD;CAAK,WAAU;CAAW,gBAAc,OAAO,SAAS,IAAI,KAAK,KAAA;WAAjE;EACE,QACA,qBAAC,SAAD;GAAO,WAAU;GAAkB,SAAS;aAA5C,CACE,OACA,WACA,oBAAC,QAAD;IAAM,WAAU;IAAqB,eAAY;cAC/C;GACI,CAAA,IACH,IACE;OACJ;EACH;EACD,qBAAC,OAAD;GAAK,IAAI;GAAe,WAAU;aAAlC;IACE,cAAc,oBAAC,KAAD;KAAG,WAAU;eAAyB;IAAe,CAAA,IAAI;IACvE,OAAO,SAAS,IAChB,oBAAC,OAAD;KAAK,MAAK;KAAQ,eAAY;KAAO,WAAU;eAC7C,OAAO,KAAK,YACZ,oBAAC,KAAD;MAAiB,WAAU;gBACzB;KACC,GAFK,OAEL,CACH;IACG,CAAA,IACF;IACH,SAAS,KAAK,YACd,oBAAC,KAAD;KAAiB,WAAU;eACzB;IACC,GAFK,OAEL,CACH;GACG;;CACD"}
1
+ {"version":3,"file":"FieldShell.js","names":[],"sources":["../../../src/react/primitives/FieldShell.tsx"],"sourcesContent":["'use client'\n\nimport type { ReactNode } from 'react'\n\nexport type FieldShellProps = {\n\t/** The control id this shell labels and describes. */\n\tid: string\n\tlabel?: string\n\tdescription?: string\n\trequired?: boolean\n\terrors?: string[]\n\t/** id used for aria-describedby on the control; the shell renders description + messages under it. */\n\tdescribedById: string\n\tchildren: ReactNode\n}\n\n/**\n * Accessible wrapper for a single field: a `<label>` bound to the control, the control slot, an optional\n * description, and error messages. The control inside must set `aria-describedby={describedById}`\n * and `aria-invalid` when errors exist; this shell renders the matching `id={describedById}` region.\n */\nexport const FieldShell = ({\n\tid,\n\tlabel,\n\tdescription,\n\trequired,\n\terrors = [],\n\tdescribedById,\n\tchildren,\n}: FieldShellProps) => (\n\t<div className=\"fb-field\" data-invalid={errors.length > 0 ? '' : undefined}>\n\t\t{label ? (\n\t\t\t<label className=\"fb-field__label\" htmlFor={id}>\n\t\t\t\t{label}\n\t\t\t\t{required ? (\n\t\t\t\t\t<span className=\"fb-field__required\" aria-hidden=\"true\">\n\t\t\t\t\t\t{' *'}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</label>\n\t\t) : null}\n\t\t{children}\n\t\t<div id={describedById} className=\"fb-field__messages\">\n\t\t\t{description ? <p className=\"fb-field__description\">{description}</p> : null}\n\t\t\t{errors.length > 0 ? (\n\t\t\t\t<div role=\"alert\" aria-atomic=\"true\" className=\"fb-field__errors\">\n\t\t\t\t\t{errors.map((message) => (\n\t\t\t\t\t\t<p key={message} className=\"fb-field__error\">\n\t\t\t\t\t\t\t{message}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t</div>\n)\n"],"mappings":";;;;;;;;AAqBA,MAAa,cAAc,EAC1B,IACA,OACA,aACA,UACA,SAAS,CAAC,GACV,eACA,eAEA,qBAAC,OAAD;CAAK,WAAU;CAAW,gBAAc,OAAO,SAAS,IAAI,KAAK,KAAA;WAAjE;EACE,QACA,qBAAC,SAAD;GAAO,WAAU;GAAkB,SAAS;aAA5C,CACE,OACA,WACA,oBAAC,QAAD;IAAM,WAAU;IAAqB,eAAY;cAC/C;GACI,CAAA,IACH,IACE;OACJ;EACH;EACD,qBAAC,OAAD;GAAK,IAAI;GAAe,WAAU;aAAlC,CACE,cAAc,oBAAC,KAAD;IAAG,WAAU;cAAyB;GAAe,CAAA,IAAI,MACvE,OAAO,SAAS,IAChB,oBAAC,OAAD;IAAK,MAAK;IAAQ,eAAY;IAAO,WAAU;cAC7C,OAAO,KAAK,YACZ,oBAAC,KAAD;KAAiB,WAAU;eACzB;IACC,GAFK,OAEL,CACH;GACG,CAAA,IACF,IACA;;CACD"}
@@ -5,7 +5,7 @@ import { jsx } from "react/jsx-runtime";
5
5
  import { useId } from "react";
6
6
  //#region src/react/renderers/calculation.tsx
7
7
  /** Read-only renderer for a calculation field: the value is derived, never user-editable, so it shows in an `<output>` rather than an input. */
8
- const calculationRenderer = defineFieldRenderer(({ field, value, errors, warnings, required }) => {
8
+ const calculationRenderer = defineFieldRenderer(({ field, value, errors, required }) => {
9
9
  const id = useId();
10
10
  const describedById = `${id}-desc`;
11
11
  return /* @__PURE__ */ jsx(FieldShell, {
@@ -14,7 +14,6 @@ const calculationRenderer = defineFieldRenderer(({ field, value, errors, warning
14
14
  description: typeof field.description === "string" ? field.description : void 0,
15
15
  required,
16
16
  errors,
17
- warnings,
18
17
  describedById,
19
18
  children: /* @__PURE__ */ jsx("output", {
20
19
  id,
@@ -1 +1 @@
1
- {"version":3,"file":"calculation.js","names":[],"sources":["../../../src/react/renderers/calculation.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\n\n/** Read-only renderer for a calculation field: the value is derived, never user-editable, so it shows in an `<output>` rather than an input. */\nexport const calculationRenderer = defineFieldRenderer<number | undefined>(\n\t({ field, value, errors, warnings, required }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<output id={id} className=\"fb-field__calc\" aria-describedby={describedById}>\n\t\t\t\t\t{value == null ? '' : String(value)}\n\t\t\t\t</output>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,sBAAsB,qBACjC,EAAE,OAAO,OAAO,QAAQ,UAAU,eAAe;CACjD,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACE;EACK;YAEf,oBAAC,UAAD;GAAY;GAAI,WAAU;GAAiB,oBAAkB;aAC3D,SAAS,OAAO,KAAK,OAAO,KAAK;EAC3B,CAAA;CACG,CAAA;AAEd,CACD"}
1
+ {"version":3,"file":"calculation.js","names":[],"sources":["../../../src/react/renderers/calculation.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\n\n/** Read-only renderer for a calculation field: the value is derived, never user-editable, so it shows in an `<output>` rather than an input. */\nexport const calculationRenderer = defineFieldRenderer<number | undefined>(\n\t({ field, value, errors, required }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<output id={id} className=\"fb-field__calc\" aria-describedby={describedById}>\n\t\t\t\t\t{value == null ? '' : String(value)}\n\t\t\t\t</output>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,sBAAsB,qBACjC,EAAE,OAAO,OAAO,QAAQ,eAAe;CACvC,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACO;YAEf,oBAAC,UAAD;GAAY;GAAI,WAAU;GAAiB,oBAAkB;aAC3D,SAAS,OAAO,KAAK,OAAO,KAAK;EAC3B,CAAA;CACG,CAAA;AAEd,CACD"}
@@ -5,7 +5,7 @@ import { Checkbox } from "../primitives/Checkbox.js";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { useId } from "react";
7
7
  //#region src/react/renderers/checkbox.tsx
8
- const checkboxRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {
8
+ const checkboxRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, required, disabled }) => {
9
9
  const id = useId();
10
10
  const describedById = `${id}-desc`;
11
11
  return /* @__PURE__ */ jsx(FieldShell, {
@@ -14,7 +14,6 @@ const checkboxRenderer = defineFieldRenderer(({ field, name, value, onChange, on
14
14
  description: typeof field.description === "string" ? field.description : void 0,
15
15
  required,
16
16
  errors,
17
- warnings,
18
17
  describedById,
19
18
  children: /* @__PURE__ */ jsx(Checkbox, {
20
19
  id,
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","names":[],"sources":["../../../src/react/renderers/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { Checkbox } from '../primitives/Checkbox'\nimport { FieldShell } from '../primitives/FieldShell'\n\nexport const checkboxRenderer = defineFieldRenderer<boolean>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Checkbox\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\tchecked={value ?? false}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,mBAAmB,qBAC9B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,UAAU,eAAe;CACnF,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACE;EACK;YAEf,oBAAC,UAAD;GACK;GACE;GACN,SAAS,SAAS;GACR;GACF;GACE;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD"}
1
+ {"version":3,"file":"checkbox.js","names":[],"sources":["../../../src/react/renderers/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { Checkbox } from '../primitives/Checkbox'\nimport { FieldShell } from '../primitives/FieldShell'\n\nexport const checkboxRenderer = defineFieldRenderer<boolean>(\n\t({ field, name, value, onChange, onBlur, errors, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Checkbox\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\tchecked={value ?? false}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,mBAAmB,qBAC9B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,eAAe;CACzE,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACO;YAEf,oBAAC,UAAD;GACK;GACE;GACN,SAAS,SAAS;GACR;GACF;GACE;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD"}
@@ -1,51 +1,95 @@
1
1
  "use client";
2
+ import { sanitizeUrl } from "../../actions/body/converters.js";
3
+ import { serializeBody } from "../../actions/body/serializeBody.js";
4
+ import { textOfBody } from "../../actions/body/textOfBody.js";
2
5
  import { defineFieldRenderer } from "../contract.js";
3
6
  import { FieldShell } from "../primitives/FieldShell.js";
4
7
  import { Checkbox } from "../primitives/Checkbox.js";
5
8
  import { jsx, jsxs } from "react/jsx-runtime";
6
- import { useId } from "react";
9
+ import { useId, useMemo } from "react";
7
10
  //#region src/react/renderers/consent.tsx
8
- const consentRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {
11
+ const text = (raw) => typeof raw === "string" && raw.trim() !== "" ? raw : void 0;
12
+ /**
13
+ * HTML for a rich text statement. A plain string never goes through this path: `serializeBody`
14
+ * interpolates a string body unescaped (its pre-richText behavior), so rendering one as HTML would
15
+ * let literal markup execute; the renderer shows a plain string as text instead.
16
+ */
17
+ const richStatementHtml = (statement) => {
18
+ if (typeof statement === "string" || statement == null) return;
19
+ const html = serializeBody(statement, {
20
+ values: [],
21
+ descriptors: []
22
+ });
23
+ return html === "" ? void 0 : html;
24
+ };
25
+ /**
26
+ * The resolved policy link, or nothing unless the source carries both a url and a name to show
27
+ * for it: an anchor labelled by a raw URL or a machine key is worse than no anchor. The href is
28
+ * sanitized like every other url the package renders, since a source is admin-authored and can
29
+ * point anywhere (`sanitizeUrl` keeps http(s)/mailto/tel and relative urls, and neutralizes the
30
+ * rest to `#`).
31
+ */
32
+ const linkOf = (raw) => {
33
+ const link = raw;
34
+ const label = text(link?.label);
35
+ return label && typeof link?.url === "string" && link.url !== "" ? {
36
+ label,
37
+ url: sanitizeUrl(link.url)
38
+ } : void 0;
39
+ };
40
+ /**
41
+ * The `statement` and `link` this reads are server-resolved from the field's consent source and
42
+ * injected by `toFormDocument(doc, { consentStatements })`; the form document itself carries only
43
+ * the source key, so a form rendered without that step shows no statement rather than a stale one.
44
+ */
45
+ const consentRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, required, disabled }) => {
9
46
  const id = useId();
10
47
  const describedById = `${id}-desc`;
11
- const text = (raw) => typeof raw === "string" && raw.trim() !== "" ? raw : void 0;
12
- const statement = text(field.statement) ?? text(field.label);
13
- const links = Array.isArray(field.consentLinks) ? field.consentLinks : (() => {
14
- const sc = field.sourceConfig;
15
- if (sc && typeof sc.url === "string" && sc.url) return [{
16
- label: typeof sc.label === "string" ? sc.label : "Policy",
17
- url: sc.url
18
- }];
19
- return [];
20
- })();
48
+ const plainStatement = text(textOfBody(field.statement));
49
+ const html = useMemo(() => richStatementHtml(field.statement), [field.statement]);
50
+ const link = linkOf(field.link);
21
51
  return /* @__PURE__ */ jsxs(FieldShell, {
22
52
  id,
23
- label: statement,
24
53
  description: typeof field.description === "string" ? field.description : void 0,
25
54
  required,
26
55
  errors,
27
- warnings,
28
56
  describedById,
29
- children: [/* @__PURE__ */ jsx(Checkbox, {
30
- id,
31
- name,
32
- checked: value ?? false,
33
- onChange,
34
- onBlur,
35
- required,
36
- disabled,
37
- invalid: errors.length > 0,
38
- describedById
39
- }), links.length > 0 ? /* @__PURE__ */ jsx("span", {
40
- className: "fb-consent__links",
41
- children: links.map((link) => /* @__PURE__ */ jsx("a", {
42
- href: link.url,
43
- target: "_blank",
44
- rel: "noopener noreferrer",
45
- className: "fb-consent__link",
46
- children: link.label
47
- }, link.url))
48
- }) : null]
57
+ children: [
58
+ html ? /* @__PURE__ */ jsx("div", {
59
+ className: "fb-consent__statement",
60
+ dangerouslySetInnerHTML: { __html: html }
61
+ }) : plainStatement ? /* @__PURE__ */ jsx("span", {
62
+ className: "fb-consent__statement",
63
+ children: plainStatement
64
+ }) : null,
65
+ required && (html || plainStatement) ? /* @__PURE__ */ jsx("span", {
66
+ className: "fb-field__required",
67
+ "aria-hidden": "true",
68
+ children: " *"
69
+ }) : null,
70
+ /* @__PURE__ */ jsx(Checkbox, {
71
+ id,
72
+ name,
73
+ checked: value ?? false,
74
+ onChange,
75
+ onBlur,
76
+ required,
77
+ disabled,
78
+ invalid: errors.length > 0,
79
+ describedById,
80
+ ariaLabel: plainStatement ?? name
81
+ }),
82
+ link ? /* @__PURE__ */ jsx("span", {
83
+ className: "fb-consent__links",
84
+ children: /* @__PURE__ */ jsx("a", {
85
+ href: link.url,
86
+ target: "_blank",
87
+ rel: "noopener noreferrer",
88
+ className: "fb-consent__link",
89
+ children: link.label
90
+ })
91
+ }) : null
92
+ ]
49
93
  });
50
94
  });
51
95
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"consent.js","names":[],"sources":["../../../src/react/renderers/consent.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport type { ConsentLink } from '../../consent/defineConsentSource'\nimport { defineFieldRenderer } from '../contract'\nimport { Checkbox } from '../primitives/Checkbox'\nimport { FieldShell } from '../primitives/FieldShell'\n\nexport const consentRenderer = defineFieldRenderer<boolean>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\t// The visible agreement text labels the checkbox. Prefer the explicit `statement`; fall back to the\n\t\t// field `label` so a consent field authored with only a label (or a blank statement) is never an\n\t\t// unlabelled control (a11y). A blank or whitespace-only value counts as absent.\n\t\tconst text = (raw: unknown): string | undefined =>\n\t\t\ttypeof raw === 'string' && raw.trim() !== '' ? raw : undefined\n\t\tconst statement = text(field.statement) ?? text(field.label)\n\n\t\tconst links: ConsentLink[] = Array.isArray(field.consentLinks)\n\t\t\t? (field.consentLinks as ConsentLink[])\n\t\t\t: (() => {\n\t\t\t\t\tconst sc = field.sourceConfig as Record<string, unknown> | undefined\n\t\t\t\t\tif (sc && typeof sc.url === 'string' && sc.url) {\n\t\t\t\t\t\treturn [{ label: typeof sc.label === 'string' ? sc.label : 'Policy', url: sc.url }]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t})()\n\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={statement}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Checkbox\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\tchecked={value ?? false}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t\t{links.length > 0 ? (\n\t\t\t\t\t<span className=\"fb-consent__links\">\n\t\t\t\t\t\t{links.map((link) => (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\tkey={link.url}\n\t\t\t\t\t\t\t\thref={link.url}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"fb-consent__link\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{link.label}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAQA,MAAa,kBAAkB,qBAC7B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,UAAU,eAAe;CACnF,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAI5B,MAAM,QAAQ,QACb,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,KAAK,MAAM,KAAA;CACtD,MAAM,YAAY,KAAK,MAAM,SAAS,KAAK,KAAK,MAAM,KAAK;CAE3D,MAAM,QAAuB,MAAM,QAAQ,MAAM,YAAY,IACzD,MAAM,sBACA;EACP,MAAM,KAAK,MAAM;EACjB,IAAI,MAAM,OAAO,GAAG,QAAQ,YAAY,GAAG,KAC1C,OAAO,CAAC;GAAE,OAAO,OAAO,GAAG,UAAU,WAAW,GAAG,QAAQ;GAAU,KAAK,GAAG;EAAI,CAAC;EAEnF,OAAO,CAAC;CACT,GAAG;CAEL,OACC,qBAAC,YAAD;EACK;EACJ,OAAO;EACP,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACE;EACK;YAPhB,CASC,oBAAC,UAAD;GACK;GACE;GACN,SAAS,SAAS;GACR;GACF;GACE;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA,GACA,MAAM,SAAS,IACf,oBAAC,QAAD;GAAM,WAAU;aACd,MAAM,KAAK,SACX,oBAAC,KAAD;IAEC,MAAM,KAAK;IACX,QAAO;IACP,KAAI;IACJ,WAAU;cAET,KAAK;GACJ,GAPG,KAAK,GAOR,CACH;EACI,CAAA,IACH,IACO;;AAEd,CACD"}
1
+ {"version":3,"file":"consent.js","names":[],"sources":["../../../src/react/renderers/consent.tsx"],"sourcesContent":["'use client'\n\nimport { useId, useMemo } from 'react'\nimport { sanitizeUrl } from '../../actions/body/converters'\nimport { serializeBody } from '../../actions/body/serializeBody'\nimport { textOfBody } from '../../actions/body/textOfBody'\nimport { defineFieldRenderer } from '../contract'\nimport { Checkbox } from '../primitives/Checkbox'\nimport { FieldShell } from '../primitives/FieldShell'\n\ntype ConsentLink = { label: string; url: string }\n\nconst text = (raw: unknown): string | undefined =>\n\ttypeof raw === 'string' && raw.trim() !== '' ? raw : undefined\n\n/**\n * HTML for a rich text statement. A plain string never goes through this path: `serializeBody`\n * interpolates a string body unescaped (its pre-richText behavior), so rendering one as HTML would\n * let literal markup execute; the renderer shows a plain string as text instead.\n */\nconst richStatementHtml = (statement: unknown): string | undefined => {\n\tif (typeof statement === 'string' || statement == null) {\n\t\treturn undefined\n\t}\n\tconst html = serializeBody(statement, { values: [], descriptors: [] })\n\treturn html === '' ? undefined : html\n}\n\n/**\n * The resolved policy link, or nothing unless the source carries both a url and a name to show\n * for it: an anchor labelled by a raw URL or a machine key is worse than no anchor. The href is\n * sanitized like every other url the package renders, since a source is admin-authored and can\n * point anywhere (`sanitizeUrl` keeps http(s)/mailto/tel and relative urls, and neutralizes the\n * rest to `#`).\n */\nconst linkOf = (raw: unknown): ConsentLink | undefined => {\n\tconst link = raw as Partial<ConsentLink> | undefined\n\tconst label = text(link?.label)\n\treturn label && typeof link?.url === 'string' && link.url !== ''\n\t\t? { label, url: sanitizeUrl(link.url) }\n\t\t: undefined\n}\n\n/**\n * The `statement` and `link` this reads are server-resolved from the field's consent source and\n * injected by `toFormDocument(doc, { consentStatements })`; the form document itself carries only\n * the source key, so a form rendered without that step shows no statement rather than a stale one.\n */\nexport const consentRenderer = defineFieldRenderer<boolean>(\n\t({ field, name, value, onChange, onBlur, errors, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\n\t\t// The checkbox's accessible name is always plain text, regardless of the statement's shape,\n\t\t// so it stays a single unambiguous string even though the visible statement can carry\n\t\t// formatting and inline links. With no statement resolved the field is misconfigured; the\n\t\t// machine name still beats leaving the control unnamed.\n\t\tconst plainStatement = text(textOfBody(field.statement))\n\t\tconst html = useMemo(() => richStatementHtml(field.statement), [field.statement])\n\t\tconst link = linkOf(field.link)\n\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t{html ? (\n\t\t\t\t\t// The statement is a plain sibling, never a <label>: a native <label> forwards clicks to\n\t\t\t\t\t// its control even for descendant links (they aren't \"labelable\" elements per the HTML\n\t\t\t\t\t// spec), so an inline link here would also silently toggle the checkbox. The checkbox's\n\t\t\t\t\t// name comes from aria-label instead. A <div>, because serializeBody emits block\n\t\t\t\t\t// elements (<p>, headings, lists) that are invalid inside inline wrappers.\n\t\t\t\t\t// Safe to inject: serializeBody HTML-escapes all text and sanitizes link URLs.\n\t\t\t\t\t// biome-ignore lint/security/noDangerouslySetInnerHtml: HTML is produced by our escaping serializer, never raw user input\n\t\t\t\t\t<div className=\"fb-consent__statement\" dangerouslySetInnerHTML={{ __html: html }} />\n\t\t\t\t) : plainStatement ? (\n\t\t\t\t\t<span className=\"fb-consent__statement\">{plainStatement}</span>\n\t\t\t\t) : null}\n\t\t\t\t{required && (html || plainStatement) ? (\n\t\t\t\t\t<span className=\"fb-field__required\" aria-hidden=\"true\">\n\t\t\t\t\t\t{' *'}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t\t<Checkbox\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\tchecked={value ?? false}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t\tariaLabel={plainStatement ?? name}\n\t\t\t\t/>\n\t\t\t\t{link ? (\n\t\t\t\t\t<span className=\"fb-consent__links\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\thref={link.url}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\tclassName=\"fb-consent__link\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{link.label}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;;;;AAYA,MAAM,QAAQ,QACb,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,KAAK,MAAM,KAAA;;;;;;AAOtD,MAAM,qBAAqB,cAA2C;CACrE,IAAI,OAAO,cAAc,YAAY,aAAa,MACjD;CAED,MAAM,OAAO,cAAc,WAAW;EAAE,QAAQ,CAAC;EAAG,aAAa,CAAC;CAAE,CAAC;CACrE,OAAO,SAAS,KAAK,KAAA,IAAY;AAClC;;;;;;;;AASA,MAAM,UAAU,QAA0C;CACzD,MAAM,OAAO;CACb,MAAM,QAAQ,KAAK,MAAM,KAAK;CAC9B,OAAO,SAAS,OAAO,MAAM,QAAQ,YAAY,KAAK,QAAQ,KAC3D;EAAE;EAAO,KAAK,YAAY,KAAK,GAAG;CAAE,IACpC,KAAA;AACJ;;;;;;AAOA,MAAa,kBAAkB,qBAC7B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,eAAe;CACzE,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAM5B,MAAM,iBAAiB,KAAK,WAAW,MAAM,SAAS,CAAC;CACvD,MAAM,OAAO,cAAc,kBAAkB,MAAM,SAAS,GAAG,CAAC,MAAM,SAAS,CAAC;CAChF,MAAM,OAAO,OAAO,MAAM,IAAI;CAE9B,OACC,qBAAC,YAAD;EACK;EACJ,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACO;YALhB;GAOE,OAQA,oBAAC,OAAD;IAAK,WAAU;IAAwB,yBAAyB,EAAE,QAAQ,KAAK;GAAI,CAAA,IAChF,iBACH,oBAAC,QAAD;IAAM,WAAU;cAAyB;GAAqB,CAAA,IAC3D;GACH,aAAa,QAAQ,kBACrB,oBAAC,QAAD;IAAM,WAAU;IAAqB,eAAY;cAC/C;GACI,CAAA,IACH;GACJ,oBAAC,UAAD;IACK;IACE;IACN,SAAS,SAAS;IACR;IACF;IACE;IACA;IACV,SAAS,OAAO,SAAS;IACV;IACf,WAAW,kBAAkB;GAC7B,CAAA;GACA,OACA,oBAAC,QAAD;IAAM,WAAU;cACf,oBAAC,KAAD;KACC,MAAM,KAAK;KACX,QAAO;KACP,KAAI;KACJ,WAAU;eAET,KAAK;IACJ,CAAA;GACE,CAAA,IACH;EACO;;AAEd,CACD"}
@@ -5,7 +5,7 @@ import { Input } from "../primitives/Input.js";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { useId } from "react";
7
7
  //#region src/react/renderers/date.tsx
8
- const dateRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {
8
+ const dateRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, required, disabled }) => {
9
9
  const id = useId();
10
10
  const describedById = `${id}-desc`;
11
11
  return /* @__PURE__ */ jsx(FieldShell, {
@@ -14,7 +14,6 @@ const dateRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur
14
14
  description: typeof field.description === "string" ? field.description : void 0,
15
15
  required,
16
16
  errors,
17
- warnings,
18
17
  describedById,
19
18
  children: /* @__PURE__ */ jsx(Input, {
20
19
  id,
@@ -23,7 +22,6 @@ const dateRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur
23
22
  value: value ?? "",
24
23
  onChange,
25
24
  onBlur,
26
- placeholder: typeof field.placeholder === "string" ? field.placeholder : void 0,
27
25
  required,
28
26
  disabled,
29
27
  invalid: errors.length > 0,
@@ -1 +1 @@
1
- {"version":3,"file":"date.js","names":[],"sources":["../../../src/react/renderers/date.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const dateRenderer = defineFieldRenderer<string>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"date\"\n\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,eAAe,qBAC1B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,UAAU,eAAe;CACnF,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACE;EACK;YAEf,oBAAC,OAAD;GACK;GACE;GACN,MAAK;GACL,OAAO,SAAS;GACN;GACF;GACR,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;GAC/D;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD"}
1
+ {"version":3,"file":"date.js","names":[],"sources":["../../../src/react/renderers/date.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const dateRenderer = defineFieldRenderer<string>(\n\t({ field, name, value, onChange, onBlur, errors, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"date\"\n\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,eAAe,qBAC1B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,eAAe;CACzE,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACO;YAEf,oBAAC,OAAD;GACK;GACE;GACN,MAAK;GACL,OAAO,SAAS;GACN;GACF;GACE;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD"}
@@ -5,7 +5,7 @@ import { Input } from "../primitives/Input.js";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { useId } from "react";
7
7
  //#region src/react/renderers/email.tsx
8
- const emailRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {
8
+ const emailRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, required, disabled }) => {
9
9
  const id = useId();
10
10
  const describedById = `${id}-desc`;
11
11
  return /* @__PURE__ */ jsx(FieldShell, {
@@ -14,7 +14,6 @@ const emailRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlu
14
14
  description: typeof field.description === "string" ? field.description : void 0,
15
15
  required,
16
16
  errors,
17
- warnings,
18
17
  describedById,
19
18
  children: /* @__PURE__ */ jsx(Input, {
20
19
  id,
@@ -1 +1 @@
1
- {"version":3,"file":"email.js","names":[],"sources":["../../../src/react/renderers/email.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const emailRenderer = defineFieldRenderer<string>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,gBAAgB,qBAC3B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,UAAU,eAAe;CACnF,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACE;EACK;YAEf,oBAAC,OAAD;GACK;GACE;GACN,MAAK;GACL,OAAO,SAAS;GACN;GACF;GACR,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;GAC/D;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD"}
1
+ {"version":3,"file":"email.js","names":[],"sources":["../../../src/react/renderers/email.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const emailRenderer = defineFieldRenderer<string>(\n\t({ field, name, value, onChange, onBlur, errors, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,gBAAgB,qBAC3B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,eAAe;CACzE,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACO;YAEf,oBAAC,OAAD;GACK;GACE;GACN,MAAK;GACL,OAAO,SAAS;GACN;GACF;GACR,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;GAC/D;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD"}
@@ -18,7 +18,7 @@ const typesOf = (mimeTypes) => {
18
18
  * stored doc at submit, so the client value is only the id. Shows the uploaded filename with a clear
19
19
  * control and surfaces upload errors. Single file (v1); the upload posts to the default `/api` route.
20
20
  */
21
- const fileRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, warnings, required, disabled, t }) => {
21
+ const fileRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, required, disabled, t }) => {
22
22
  const id = useId();
23
23
  const describedById = `${id}-desc`;
24
24
  const [uploading, setUploading] = useState(false);
@@ -65,7 +65,6 @@ const fileRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur
65
65
  description: typeof field.description === "string" ? field.description : void 0,
66
66
  required,
67
67
  errors: allErrors,
68
- warnings,
69
68
  describedById,
70
69
  children: [
71
70
  /* @__PURE__ */ jsx("input", {
@@ -1 +1 @@
1
- {"version":3,"file":"file.js","names":[],"sources":["../../../src/react/renderers/file.tsx"],"sourcesContent":["'use client'\n\nimport { type ChangeEvent, useId, useState } from 'react'\nimport { keys } from '../../translations/keys'\nimport { formatBytes } from '../../uploads/formatBytes'\nimport { resolveMessage } from '../../validation/message'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { uploadFile } from '../uploadFile'\n\nconst typesOf = (mimeTypes: unknown): string[] => {\n\tif (!Array.isArray(mimeTypes)) {\n\t\treturn []\n\t}\n\treturn mimeTypes.filter((entry): entry is string => typeof entry === 'string')\n}\n\n/**\n * Headless file renderer: a native file input that uploads the chosen file to the upload collection and\n * stores the returned id as the field value. The server re-derives filename/mimeType/filesize from the\n * stored doc at submit, so the client value is only the id. Shows the uploaded filename with a clear\n * control and surfaces upload errors. Single file (v1); the upload posts to the default `/api` route.\n */\nexport const fileRenderer = defineFieldRenderer<string | number>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled, t }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\tconst [uploading, setUploading] = useState(false)\n\t\tconst [filename, setFilename] = useState<string | undefined>(undefined)\n\t\tconst [localError, setLocalError] = useState<string | undefined>(undefined)\n\n\t\t// Stamped server-side onto the block from plugin config; absent only for stale form docs saved\n\t\t// before uploads were configured (uploading then fails with a visible error, never a guess).\n\t\tconst collection =\n\t\t\ttypeof field.uploadsCollection === 'string' ? field.uploadsCollection : undefined\n\t\tconst types = typesOf(field.mimeTypes)\n\t\tconst accept = types.length > 0 ? types.join(',') : undefined\n\t\t// Zero is a real limit, matching resolveFileRef server-side (filesize > maxSize rejects any non-empty file).\n\t\tconst maxSize =\n\t\t\ttypeof field.maxSize === 'number' && field.maxSize >= 0 ? field.maxSize : undefined\n\t\tconst hints = [\n\t\t\ttypes.length > 0\n\t\t\t\t? resolveMessage(t(keys.fileHintAccepted), { types: types.join(', ') })\n\t\t\t\t: undefined,\n\t\t\tmaxSize !== undefined\n\t\t\t\t? resolveMessage(t(keys.fileHintMaxSize), { max: formatBytes(maxSize) })\n\t\t\t\t: undefined,\n\t\t].filter((hint): hint is string => typeof hint === 'string')\n\t\tconst allErrors = localError ? [...errors, localError] : errors\n\t\t// Show the just-uploaded filename, or a generic indicator when the field already holds an id (recall/prefill): the filename is not part of the client value.\n\t\tconst hasValue = value !== undefined && value !== null && value !== ''\n\t\tconst displayName = filename ?? (hasValue ? 'Uploaded file' : undefined)\n\n\t\tconst handleChange = async (event: ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst selected = event.target.files?.[0]\n\t\t\tif (!selected) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (maxSize !== undefined && selected.size > maxSize) {\n\t\t\t\tsetLocalError(resolveMessage(t(keys.fileTooLarge), { max: formatBytes(maxSize) }))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!collection) {\n\t\t\t\tsetLocalError(t(keys.fileUploadMisconfigured))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetUploading(true)\n\t\t\tsetLocalError(undefined)\n\t\t\tconst result = await uploadFile({ file: selected, collection })\n\t\t\tsetUploading(false)\n\t\t\tif (result.ok) {\n\t\t\t\tsetFilename(selected.name)\n\t\t\t\tonChange(result.id)\n\t\t\t} else {\n\t\t\t\tsetLocalError(result.message ?? 'Upload failed')\n\t\t\t}\n\t\t}\n\n\t\tconst clear = () => {\n\t\t\tsetFilename(undefined)\n\t\t\tsetLocalError(undefined)\n\t\t\tonChange('')\n\t\t}\n\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={allErrors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\taccept={accept}\n\t\t\t\t\tdisabled={disabled || uploading}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tvoid handleChange(event)\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\taria-invalid={allErrors.length > 0}\n\t\t\t\t\taria-describedby={describedById}\n\t\t\t\t/>\n\t\t\t\t{hints.length > 0 ? <p className=\"fb-field__file-hint\">{hints.join(' · ')}</p> : null}\n\t\t\t\t{uploading ? (\n\t\t\t\t\t<p className=\"fb-field__file-status\" aria-live=\"polite\">\n\t\t\t\t\t\tUploading\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t\t{displayName ? (\n\t\t\t\t\t<p className=\"fb-field__file-name\">\n\t\t\t\t\t\t<span>{displayName}</span>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"fb-field__file-clear\"\n\t\t\t\t\t\t\tonClick={clear}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tRemove\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"file.js","names":[],"sources":["../../../src/react/renderers/file.tsx"],"sourcesContent":["'use client'\n\nimport { type ChangeEvent, useId, useState } from 'react'\nimport { keys } from '../../translations/keys'\nimport { formatBytes } from '../../uploads/formatBytes'\nimport { resolveMessage } from '../../validation/message'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { uploadFile } from '../uploadFile'\n\nconst typesOf = (mimeTypes: unknown): string[] => {\n\tif (!Array.isArray(mimeTypes)) {\n\t\treturn []\n\t}\n\treturn mimeTypes.filter((entry): entry is string => typeof entry === 'string')\n}\n\n/**\n * Headless file renderer: a native file input that uploads the chosen file to the upload collection and\n * stores the returned id as the field value. The server re-derives filename/mimeType/filesize from the\n * stored doc at submit, so the client value is only the id. Shows the uploaded filename with a clear\n * control and surfaces upload errors. Single file (v1); the upload posts to the default `/api` route.\n */\nexport const fileRenderer = defineFieldRenderer<string | number>(\n\t({ field, name, value, onChange, onBlur, errors, required, disabled, t }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\tconst [uploading, setUploading] = useState(false)\n\t\tconst [filename, setFilename] = useState<string | undefined>(undefined)\n\t\tconst [localError, setLocalError] = useState<string | undefined>(undefined)\n\n\t\t// Stamped server-side onto the block from plugin config; absent only for stale form docs saved\n\t\t// before uploads were configured (uploading then fails with a visible error, never a guess).\n\t\tconst collection =\n\t\t\ttypeof field.uploadsCollection === 'string' ? field.uploadsCollection : undefined\n\t\tconst types = typesOf(field.mimeTypes)\n\t\tconst accept = types.length > 0 ? types.join(',') : undefined\n\t\t// Zero is a real limit, matching resolveFileRef server-side (filesize > maxSize rejects any non-empty file).\n\t\tconst maxSize =\n\t\t\ttypeof field.maxSize === 'number' && field.maxSize >= 0 ? field.maxSize : undefined\n\t\tconst hints = [\n\t\t\ttypes.length > 0\n\t\t\t\t? resolveMessage(t(keys.fileHintAccepted), { types: types.join(', ') })\n\t\t\t\t: undefined,\n\t\t\tmaxSize !== undefined\n\t\t\t\t? resolveMessage(t(keys.fileHintMaxSize), { max: formatBytes(maxSize) })\n\t\t\t\t: undefined,\n\t\t].filter((hint): hint is string => typeof hint === 'string')\n\t\tconst allErrors = localError ? [...errors, localError] : errors\n\t\t// Show the just-uploaded filename, or a generic indicator when the field already holds an id (recall/prefill): the filename is not part of the client value.\n\t\tconst hasValue = value !== undefined && value !== null && value !== ''\n\t\tconst displayName = filename ?? (hasValue ? 'Uploaded file' : undefined)\n\n\t\tconst handleChange = async (event: ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst selected = event.target.files?.[0]\n\t\t\tif (!selected) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (maxSize !== undefined && selected.size > maxSize) {\n\t\t\t\tsetLocalError(resolveMessage(t(keys.fileTooLarge), { max: formatBytes(maxSize) }))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!collection) {\n\t\t\t\tsetLocalError(t(keys.fileUploadMisconfigured))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetUploading(true)\n\t\t\tsetLocalError(undefined)\n\t\t\tconst result = await uploadFile({ file: selected, collection })\n\t\t\tsetUploading(false)\n\t\t\tif (result.ok) {\n\t\t\t\tsetFilename(selected.name)\n\t\t\t\tonChange(result.id)\n\t\t\t} else {\n\t\t\t\tsetLocalError(result.message ?? 'Upload failed')\n\t\t\t}\n\t\t}\n\n\t\tconst clear = () => {\n\t\t\tsetFilename(undefined)\n\t\t\tsetLocalError(undefined)\n\t\t\tonChange('')\n\t\t}\n\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={allErrors}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\taccept={accept}\n\t\t\t\t\tdisabled={disabled || uploading}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tvoid handleChange(event)\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\taria-invalid={allErrors.length > 0}\n\t\t\t\t\taria-describedby={describedById}\n\t\t\t\t/>\n\t\t\t\t{hints.length > 0 ? <p className=\"fb-field__file-hint\">{hints.join(' · ')}</p> : null}\n\t\t\t\t{uploading ? (\n\t\t\t\t\t<p className=\"fb-field__file-status\" aria-live=\"polite\">\n\t\t\t\t\t\tUploading\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t\t{displayName ? (\n\t\t\t\t\t<p className=\"fb-field__file-name\">\n\t\t\t\t\t\t<span>{displayName}</span>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"fb-field__file-clear\"\n\t\t\t\t\t\t\tonClick={clear}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tRemove\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":"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"}
@@ -6,6 +6,7 @@ import { emailRenderer } from "./email.js";
6
6
  import { fileRenderer } from "./file.js";
7
7
  import { messageRenderer } from "./message.js";
8
8
  import { numberRenderer } from "./number.js";
9
+ import { countryRenderer, stateRenderer } from "./region.js";
9
10
  import { repeaterRenderer } from "./repeater.js";
10
11
  import { selectRenderer } from "./select.js";
11
12
  import { textRenderer } from "./text.js";
@@ -16,6 +17,7 @@ const defaultRenderers = {
16
17
  calculation: calculationRenderer,
17
18
  checkbox: checkboxRenderer,
18
19
  consent: consentRenderer,
20
+ country: countryRenderer,
19
21
  date: dateRenderer,
20
22
  email: emailRenderer,
21
23
  file: fileRenderer,
@@ -23,6 +25,7 @@ const defaultRenderers = {
23
25
  number: numberRenderer,
24
26
  repeater: repeaterRenderer,
25
27
  select: selectRenderer,
28
+ state: stateRenderer,
26
29
  text: textRenderer,
27
30
  textarea: textareaRenderer
28
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/react/renderers/index.ts"],"sourcesContent":["import type { FieldRenderer } from '../contract'\nimport { calculationRenderer } from './calculation'\nimport { checkboxRenderer } from './checkbox'\nimport { consentRenderer } from './consent'\nimport { dateRenderer } from './date'\nimport { emailRenderer } from './email'\nimport { fileRenderer } from './file'\nimport { messageRenderer } from './message'\nimport { numberRenderer } from './number'\nimport { repeaterRenderer } from './repeater'\nimport { selectRenderer } from './select'\nimport { textRenderer } from './text'\nimport { textareaRenderer } from './textarea'\n\n/** The built-in field renderers, keyed by field-type slug. Override via the renderer registry. */\nexport const defaultRenderers: Record<string, FieldRenderer> = {\n\tcalculation: calculationRenderer as FieldRenderer,\n\tcheckbox: checkboxRenderer as FieldRenderer,\n\tconsent: consentRenderer as FieldRenderer,\n\tdate: dateRenderer as FieldRenderer,\n\temail: emailRenderer as FieldRenderer,\n\tfile: fileRenderer as FieldRenderer,\n\tmessage: messageRenderer as FieldRenderer,\n\tnumber: numberRenderer as FieldRenderer,\n\trepeater: repeaterRenderer as FieldRenderer,\n\tselect: selectRenderer as FieldRenderer,\n\ttext: textRenderer as FieldRenderer,\n\ttextarea: textareaRenderer as FieldRenderer,\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,MAAa,mBAAkD;CAC9D,aAAa;CACb,UAAU;CACV,SAAS;CACT,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,QAAQ;CACR,UAAU;CACV,QAAQ;CACR,MAAM;CACN,UAAU;AACX"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/react/renderers/index.ts"],"sourcesContent":["import type { FieldRenderer } from '../contract'\nimport { calculationRenderer } from './calculation'\nimport { checkboxRenderer } from './checkbox'\nimport { consentRenderer } from './consent'\nimport { dateRenderer } from './date'\nimport { emailRenderer } from './email'\nimport { fileRenderer } from './file'\nimport { messageRenderer } from './message'\nimport { numberRenderer } from './number'\nimport { countryRenderer, stateRenderer } from './region'\nimport { repeaterRenderer } from './repeater'\nimport { selectRenderer } from './select'\nimport { textRenderer } from './text'\nimport { textareaRenderer } from './textarea'\n\n/** The built-in field renderers, keyed by field-type slug. Override via the renderer registry. */\nexport const defaultRenderers: Record<string, FieldRenderer> = {\n\tcalculation: calculationRenderer as FieldRenderer,\n\tcheckbox: checkboxRenderer as FieldRenderer,\n\tconsent: consentRenderer as FieldRenderer,\n\tcountry: countryRenderer as FieldRenderer,\n\tdate: dateRenderer as FieldRenderer,\n\temail: emailRenderer as FieldRenderer,\n\tfile: fileRenderer as FieldRenderer,\n\tmessage: messageRenderer as FieldRenderer,\n\tnumber: numberRenderer as FieldRenderer,\n\trepeater: repeaterRenderer as FieldRenderer,\n\tselect: selectRenderer as FieldRenderer,\n\tstate: stateRenderer as FieldRenderer,\n\ttext: textRenderer as FieldRenderer,\n\ttextarea: textareaRenderer as FieldRenderer,\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,MAAa,mBAAkD;CAC9D,aAAa;CACb,UAAU;CACV,SAAS;CACT,SAAS;CACT,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,QAAQ;CACR,UAAU;CACV,QAAQ;CACR,OAAO;CACP,MAAM;CACN,UAAU;AACX"}
@@ -5,7 +5,7 @@ import { Input } from "../primitives/Input.js";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { useId } from "react";
7
7
  //#region src/react/renderers/number.tsx
8
- const numberRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {
8
+ const numberRenderer = defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, required, disabled }) => {
9
9
  const id = useId();
10
10
  const describedById = `${id}-desc`;
11
11
  return /* @__PURE__ */ jsx(FieldShell, {
@@ -14,7 +14,6 @@ const numberRenderer = defineFieldRenderer(({ field, name, value, onChange, onBl
14
14
  description: typeof field.description === "string" ? field.description : void 0,
15
15
  required,
16
16
  errors,
17
- warnings,
18
17
  describedById,
19
18
  children: /* @__PURE__ */ jsx(Input, {
20
19
  id,
@@ -1 +1 @@
1
- {"version":3,"file":"number.js","names":[],"sources":["../../../src/react/renderers/number.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const numberRenderer = defineFieldRenderer<number | undefined>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\tvalue={value == null ? '' : String(value)}\n\t\t\t\t\tonChange={(raw) => {\n\t\t\t\t\t\tconst next = Number(raw)\n\t\t\t\t\t\tonChange(raw === '' || Number.isNaN(next) ? undefined : next)\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,iBAAiB,qBAC5B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,UAAU,eAAe;CACnF,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACE;EACK;YAEf,oBAAC,OAAD;GACK;GACE;GACN,MAAK;GACL,OAAO,SAAS,OAAO,KAAK,OAAO,KAAK;GACxC,WAAW,QAAQ;IAClB,MAAM,OAAO,OAAO,GAAG;IACvB,SAAS,QAAQ,MAAM,OAAO,MAAM,IAAI,IAAI,KAAA,IAAY,IAAI;GAC7D;GACQ;GACR,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;GAC/D;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD"}
1
+ {"version":3,"file":"number.js","names":[],"sources":["../../../src/react/renderers/number.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const numberRenderer = defineFieldRenderer<number | undefined>(\n\t({ field, name, value, onChange, onBlur, errors, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\tvalue={value == null ? '' : String(value)}\n\t\t\t\t\tonChange={(raw) => {\n\t\t\t\t\t\tconst next = Number(raw)\n\t\t\t\t\t\tonChange(raw === '' || Number.isNaN(next) ? undefined : next)\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n"],"mappings":";;;;;;;AAOA,MAAa,iBAAiB,qBAC5B,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,eAAe;CACzE,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACO;YAEf,oBAAC,OAAD;GACK;GACE;GACN,MAAK;GACL,OAAO,SAAS,OAAO,KAAK,OAAO,KAAK;GACxC,WAAW,QAAQ;IAClB,MAAM,OAAO,OAAO,GAAG;IACvB,SAAS,QAAQ,MAAM,OAAO,MAAM,IAAI,IAAI,KAAA,IAAY,IAAI;GAC7D;GACQ;GACR,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;GAC/D;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD"}
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { COUNTRIES, US_STATES } from "../../fields/data/regions.js";
3
+ import { defineFieldRenderer } from "../contract.js";
4
+ import { FieldShell } from "../primitives/FieldShell.js";
5
+ import { Select } from "../primitives/Select.js";
6
+ import { jsx } from "react/jsx-runtime";
7
+ import { useId } from "react";
8
+ //#region src/react/renderers/region.tsx
9
+ /**
10
+ * A `<select>` over a fixed, code-supplied option set, for field types (country/state) whose choices
11
+ * live in the plugin rather than in per-instance `options`. Mirrors `selectRenderer` but takes the
12
+ * options as a closure argument instead of reading `field.options`, so the stored value is one of the
13
+ * fixed codes and the placeholder still gates the empty selection.
14
+ */
15
+ const regionRenderer = (options) => defineFieldRenderer(({ field, name, value, onChange, onBlur, errors, required, disabled }) => {
16
+ const id = useId();
17
+ const describedById = `${id}-desc`;
18
+ return /* @__PURE__ */ jsx(FieldShell, {
19
+ id,
20
+ label: field.label,
21
+ description: typeof field.description === "string" ? field.description : void 0,
22
+ required,
23
+ errors,
24
+ describedById,
25
+ children: /* @__PURE__ */ jsx(Select, {
26
+ id,
27
+ name,
28
+ value: value ?? "",
29
+ options,
30
+ onChange,
31
+ onBlur,
32
+ placeholder: typeof field.placeholder === "string" ? field.placeholder : void 0,
33
+ required,
34
+ disabled,
35
+ invalid: errors.length > 0,
36
+ describedById
37
+ })
38
+ });
39
+ });
40
+ const countryRenderer = regionRenderer(COUNTRIES);
41
+ const stateRenderer = regionRenderer(US_STATES);
42
+ //#endregion
43
+ export { countryRenderer, stateRenderer };
44
+
45
+ //# sourceMappingURL=region.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"region.js","names":[],"sources":["../../../src/react/renderers/region.tsx"],"sourcesContent":["'use client'\n\nimport { useId } from 'react'\nimport { COUNTRIES, US_STATES } from '../../fields/data/regions'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Select, type SelectOption } from '../primitives/Select'\n\n/**\n * A `<select>` over a fixed, code-supplied option set, for field types (country/state) whose choices\n * live in the plugin rather than in per-instance `options`. Mirrors `selectRenderer` but takes the\n * options as a closure argument instead of reading `field.options`, so the stored value is one of the\n * fixed codes and the placeholder still gates the empty selection.\n */\nconst regionRenderer = (options: SelectOption[]) =>\n\tdefineFieldRenderer<string>(\n\t\t({ field, name, value, onChange, onBlur, errors, required, disabled }) => {\n\t\t\tconst id = useId()\n\t\t\tconst describedById = `${id}-desc`\n\t\t\treturn (\n\t\t\t\t<FieldShell\n\t\t\t\t\tid={id}\n\t\t\t\t\tlabel={field.label}\n\t\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\terrors={errors}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t>\n\t\t\t\t\t<Select\n\t\t\t\t\t\tid={id}\n\t\t\t\t\t\tname={name}\n\t\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\t\toptions={options}\n\t\t\t\t\t\tonChange={onChange}\n\t\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\t\trequired={required}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t\t/>\n\t\t\t\t</FieldShell>\n\t\t\t)\n\t\t}\n\t)\n\nexport const countryRenderer = regionRenderer(COUNTRIES)\nexport const stateRenderer = regionRenderer(US_STATES)\n"],"mappings":";;;;;;;;;;;;;;AAcA,MAAM,kBAAkB,YACvB,qBACE,EAAE,OAAO,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,eAAe;CACzE,MAAM,KAAK,MAAM;CACjB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,OACC,oBAAC,YAAD;EACK;EACJ,OAAO,MAAM;EACb,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;EAC/D;EACF;EACO;YAEf,oBAAC,QAAD;GACK;GACE;GACN,OAAO,SAAS;GACP;GACC;GACF;GACR,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc,KAAA;GAC/D;GACA;GACV,SAAS,OAAO,SAAS;GACV;EACf,CAAA;CACU,CAAA;AAEd,CACD;AAED,MAAa,kBAAkB,eAAe,SAAS;AACvD,MAAa,gBAAgB,eAAe,SAAS"}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { keys } from "../../translations/keys.js";
3
+ import { isNamedField } from "../../fields/fieldKey.js";
3
4
  import { defineFieldRenderer } from "../contract.js";
4
5
  import { useFormContext } from "../FormContext.js";
5
6
  import { FieldShell } from "../primitives/FieldShell.js";
@@ -9,27 +10,25 @@ import { createElement, useId } from "react";
9
10
  //#region src/react/renderers/repeater.tsx
10
11
  /**
11
12
  * Thin wrapper so each sub-field renderer is a proper React component (has stable hook identity
12
- * per row/field). Reads errors and warnings for the composite path `field[row].subField` from
13
+ * per row/field). Reads errors for the composite path `field[row].subField` from
13
14
  * form state so server-side validation errors are surfaced inline next to the sub-field input,
14
15
  * overriding any static values passed by the parent.
15
16
  */
16
17
  const SubFieldWrapper = ({ renderer, name, ...props }) => {
17
18
  const { state } = useFormContext();
18
19
  const errors = state.errors?.[name] ?? [];
19
- const warnings = state.warnings?.[name] ?? [];
20
20
  return renderer({
21
21
  ...props,
22
22
  name,
23
- errors,
24
- warnings
23
+ errors
25
24
  });
26
25
  };
27
- const repeaterRenderer = defineFieldRenderer(({ field, id: rootId, errors, warnings, required, t, locale }) => {
26
+ const repeaterRenderer = defineFieldRenderer(({ field, name, id: rootId, errors, required, t, locale }) => {
28
27
  const { rendererRegistry } = useFormContext();
29
- const { value, setValue, onBlur } = useField(field.name);
28
+ const { value, setValue, onBlur } = useField(name);
30
29
  const addId = useId();
31
30
  const rows = Array.isArray(value) ? value : [];
32
- const subFields = Array.isArray(field.subFields) ? field.subFields : [];
31
+ const subFields = (Array.isArray(field.subFields) ? field.subFields : []).filter(isNamedField);
33
32
  const maxRows = typeof field.maxRows === "number" ? field.maxRows : void 0;
34
33
  const minRows = typeof field.minRows === "number" ? field.minRows : 0;
35
34
  const addLabel = typeof field.addLabel === "string" && field.addLabel.length > 0 ? field.addLabel : t(keys.repeaterAddRow);
@@ -54,7 +53,6 @@ const repeaterRenderer = defineFieldRenderer(({ field, id: rootId, errors, warni
54
53
  description: typeof field.description === "string" ? field.description : void 0,
55
54
  required,
56
55
  errors,
57
- warnings,
58
56
  describedById: `${rootId}-desc`,
59
57
  children: /* @__PURE__ */ jsxs("div", {
60
58
  className: "fb-repeater",
@@ -82,12 +80,11 @@ const repeaterRenderer = defineFieldRenderer(({ field, id: rootId, errors, warni
82
80
  renderer,
83
81
  field: subField,
84
82
  id: `${rootId}-${rowIndex}-${subField.name}`,
85
- name: `${field.name}[${rowIndex}].${subField.name}`,
83
+ name: `${name}[${rowIndex}].${subField.name}`,
86
84
  value: row[subField.name],
87
85
  onChange: (v) => updateRow(rowIndex, subField.name, v),
88
86
  onBlur,
89
87
  errors: [],
90
- warnings: [],
91
88
  required: subField.required ?? false,
92
89
  disabled: false,
93
90
  locale,