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

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 (644) hide show
  1. package/CHANGELOG.md +345 -0
  2. package/README.md +45 -1402
  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 +55 -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/textOfBody.d.ts +13 -0
  15. package/dist/actions/body/textOfBody.js +35 -0
  16. package/dist/actions/body/textOfBody.js.map +1 -0
  17. package/dist/actions/body/wildcards.d.ts +10 -0
  18. package/dist/actions/body/wildcards.js +33 -0
  19. package/dist/actions/body/wildcards.js.map +1 -0
  20. package/dist/actions/buildActionBlocks.js +22 -0
  21. package/dist/actions/buildActionBlocks.js.map +1 -0
  22. package/dist/actions/builtin/confirmation.js +52 -0
  23. package/dist/actions/builtin/confirmation.js.map +1 -0
  24. package/dist/actions/builtin/emailAction.d.ts +17 -0
  25. package/dist/actions/builtin/emailAction.js +83 -0
  26. package/dist/actions/builtin/emailAction.js.map +1 -0
  27. package/dist/actions/builtin/emailTeam.js +22 -0
  28. package/dist/actions/builtin/emailTeam.js.map +1 -0
  29. package/dist/actions/builtin/index.d.ts +22 -0
  30. package/dist/actions/builtin/index.js +27 -0
  31. package/dist/actions/builtin/index.js.map +1 -0
  32. package/dist/actions/builtin/signedWebhook.js +53 -0
  33. package/dist/actions/builtin/signedWebhook.js.map +1 -0
  34. package/dist/actions/defineAction.d.ts +37 -0
  35. package/dist/actions/defineAction.js +6 -0
  36. package/dist/actions/defineAction.js.map +1 -0
  37. package/dist/actions/dispatch.js +49 -0
  38. package/dist/actions/dispatch.js.map +1 -0
  39. package/dist/actions/emailRecipients.d.ts +12 -0
  40. package/dist/actions/emailRecipients.js +116 -0
  41. package/dist/actions/emailRecipients.js.map +1 -0
  42. package/dist/actions/fromAddresses.d.ts +21 -0
  43. package/dist/actions/fromAddresses.js +74 -0
  44. package/dist/actions/fromAddresses.js.map +1 -0
  45. package/dist/actions/registry.d.ts +17 -0
  46. package/dist/actions/registry.js +12 -0
  47. package/dist/actions/registry.js.map +1 -0
  48. package/dist/actions/runActions.d.ts +9 -0
  49. package/dist/actions/runActions.js +43 -0
  50. package/dist/actions/runActions.js.map +1 -0
  51. package/dist/actions/sign.d.ts +7 -0
  52. package/dist/actions/sign.js +9 -0
  53. package/dist/actions/sign.js.map +1 -0
  54. package/dist/actions/task.js +87 -0
  55. package/dist/actions/task.js.map +1 -0
  56. package/dist/aggregation/aggregateResponses.d.ts +40 -0
  57. package/dist/aggregation/aggregateResponses.js +80 -0
  58. package/dist/aggregation/aggregateResponses.js.map +1 -0
  59. package/dist/aggregation/aggregateRows.d.ts +10 -0
  60. package/dist/aggregation/aggregateRows.js +64 -0
  61. package/dist/aggregation/aggregateRows.js.map +1 -0
  62. package/dist/aggregation/resolveResultsRequest.d.ts +61 -0
  63. package/dist/aggregation/resolveResultsRequest.js +113 -0
  64. package/dist/aggregation/resolveResultsRequest.js.map +1 -0
  65. package/dist/aggregation/types.d.ts +39 -0
  66. package/dist/calc/computeCalcFields.d.ts +15 -0
  67. package/dist/calc/computeCalcFields.js +28 -0
  68. package/dist/calc/computeCalcFields.js.map +1 -0
  69. package/dist/calc/evaluate.d.ts +8 -0
  70. package/dist/calc/evaluate.js +58 -0
  71. package/dist/calc/evaluate.js.map +1 -0
  72. package/dist/calc/normalizeCalc.d.ts +8 -0
  73. package/dist/calc/normalizeCalc.js +87 -0
  74. package/dist/calc/normalizeCalc.js.map +1 -0
  75. package/dist/calc/types.d.ts +34 -0
  76. package/dist/calc/types.js +22 -0
  77. package/dist/calc/types.js.map +1 -0
  78. package/dist/client/ByteSizeField.d.ts +29 -0
  79. package/dist/client/ByteSizeField.js +58 -0
  80. package/dist/client/ByteSizeField.js.map +1 -0
  81. package/dist/client/ClosePollButton.d.ts +15 -0
  82. package/dist/client/ClosePollButton.js +80 -0
  83. package/dist/client/ClosePollButton.js.map +1 -0
  84. package/dist/client/CondensedArray.d.ts +15 -0
  85. package/dist/client/CondensedArray.js +97 -0
  86. package/dist/client/CondensedArray.js.map +1 -0
  87. package/dist/client/ConditionBuilder.js +122 -0
  88. package/dist/client/ConditionBuilder.js.map +1 -0
  89. package/dist/client/ConditionRow.js +150 -0
  90. package/dist/client/ConditionRow.js.map +1 -0
  91. package/dist/client/ConsentBlockLabel.d.ts +15 -0
  92. package/dist/client/ConsentBlockLabel.js +71 -0
  93. package/dist/client/ConsentBlockLabel.js.map +1 -0
  94. package/dist/client/ConsentSourceRowLabel.d.ts +9 -0
  95. package/dist/client/ConsentSourceRowLabel.js +21 -0
  96. package/dist/client/ConsentSourceRowLabel.js.map +1 -0
  97. package/dist/client/EndpointOptionsSelect.d.ts +46 -0
  98. package/dist/client/EndpointOptionsSelect.js +106 -0
  99. package/dist/client/EndpointOptionsSelect.js.map +1 -0
  100. package/dist/client/FieldBlockLabel.d.ts +18 -0
  101. package/dist/client/FieldBlockLabel.js +34 -0
  102. package/dist/client/FieldBlockLabel.js.map +1 -0
  103. package/dist/client/FieldNameSelect.d.ts +37 -0
  104. package/dist/client/FieldNameSelect.js +72 -0
  105. package/dist/client/FieldNameSelect.js.map +1 -0
  106. package/dist/client/FlowBuilder.d.ts +15 -0
  107. package/dist/client/FlowBuilder.js +457 -0
  108. package/dist/client/FlowBuilder.js.map +1 -0
  109. package/dist/client/FormConditionField.d.ts +21 -0
  110. package/dist/client/FormConditionField.js +30 -0
  111. package/dist/client/FormConditionField.js.map +1 -0
  112. package/dist/client/RecipientsSelect.d.ts +31 -0
  113. package/dist/client/RecipientsSelect.js +174 -0
  114. package/dist/client/RecipientsSelect.js.map +1 -0
  115. package/dist/client/RuleDescription.d.ts +21 -0
  116. package/dist/client/RuleDescription.js +19 -0
  117. package/dist/client/RuleDescription.js.map +1 -0
  118. package/dist/client/admin.css +275 -0
  119. package/dist/client/endpointOptions.js +29 -0
  120. package/dist/client/endpointOptions.js.map +1 -0
  121. package/dist/client/flowAuthoring.js +142 -0
  122. package/dist/client/flowAuthoring.js.map +1 -0
  123. package/dist/client/synthesizeClientField.js +57 -0
  124. package/dist/client/synthesizeClientField.js.map +1 -0
  125. package/dist/client/toStaticLabel.js +13 -0
  126. package/dist/client/toStaticLabel.js.map +1 -0
  127. package/dist/collections/buttonFields.d.ts +34 -0
  128. package/dist/collections/buttonFields.js +35 -0
  129. package/dist/collections/buttonFields.js.map +1 -0
  130. package/dist/collections/cells/FieldCountCell.d.ts +15 -0
  131. package/dist/collections/cells/FieldCountCell.js +18 -0
  132. package/dist/collections/cells/FieldCountCell.js.map +1 -0
  133. package/dist/collections/cells/FlowStepsCell.d.ts +14 -0
  134. package/dist/collections/cells/FlowStepsCell.js +17 -0
  135. package/dist/collections/cells/FlowStepsCell.js.map +1 -0
  136. package/dist/collections/formSubmissions.js +204 -0
  137. package/dist/collections/formSubmissions.js.map +1 -0
  138. package/dist/collections/forms.js +482 -0
  139. package/dist/collections/forms.js.map +1 -0
  140. package/dist/collections/formsEndpoints.js +101 -0
  141. package/dist/collections/formsEndpoints.js.map +1 -0
  142. package/dist/collections/redirectFields.d.ts +29 -0
  143. package/dist/conditions/conditionType.js +21 -0
  144. package/dist/conditions/conditionType.js.map +1 -0
  145. package/dist/conditions/evaluate.d.ts +17 -0
  146. package/dist/conditions/evaluate.js +94 -0
  147. package/dist/conditions/evaluate.js.map +1 -0
  148. package/dist/conditions/fieldTypes.d.ts +11 -0
  149. package/dist/{fieldTypes-CzhhJXjg.js → conditions/fieldTypes.js} +6 -3
  150. package/dist/conditions/fieldTypes.js.map +1 -0
  151. package/dist/conditions/normalizeConditions.js +61 -0
  152. package/dist/conditions/normalizeConditions.js.map +1 -0
  153. package/dist/conditions/types.d.ts +8 -0
  154. package/dist/consent/applyConsentStatements.d.ts +14 -0
  155. package/dist/consent/applyConsentStatements.js +17 -0
  156. package/dist/consent/applyConsentStatements.js.map +1 -0
  157. package/dist/consent/captureConsent.d.ts +55 -0
  158. package/dist/consent/captureConsent.js +73 -0
  159. package/dist/consent/captureConsent.js.map +1 -0
  160. package/dist/consent/consentSourcesField.d.ts +66 -0
  161. package/dist/consent/consentSourcesField.js +90 -0
  162. package/dist/consent/consentSourcesField.js.map +1 -0
  163. package/dist/consent/resolveConsentEntries.d.ts +24 -0
  164. package/dist/consent/resolveConsentEntries.js +40 -0
  165. package/dist/consent/resolveConsentEntries.js.map +1 -0
  166. package/dist/consent/resolveConsentSourcesRequest.d.ts +37 -0
  167. package/dist/consent/resolveConsentSourcesRequest.js +54 -0
  168. package/dist/consent/resolveConsentSourcesRequest.js.map +1 -0
  169. package/dist/consent/resolveConsentStatements.d.ts +45 -0
  170. package/dist/consent/resolveConsentStatements.js +44 -0
  171. package/dist/consent/resolveConsentStatements.js.map +1 -0
  172. package/dist/consent/resolvePublishedVersionRef.d.ts +23 -0
  173. package/dist/consent/resolvePublishedVersionRef.js +30 -0
  174. package/dist/consent/resolvePublishedVersionRef.js.map +1 -0
  175. package/dist/consent/types.d.ts +61 -0
  176. package/dist/email/departments.d.ts +59 -0
  177. package/dist/email/departments.js +87 -0
  178. package/dist/email/departments.js.map +1 -0
  179. package/dist/email/departmentsField.d.ts +53 -0
  180. package/dist/email/departmentsField.js +73 -0
  181. package/dist/email/departmentsField.js.map +1 -0
  182. package/dist/events/noopSink.js +6 -0
  183. package/dist/events/noopSink.js.map +1 -0
  184. package/dist/events/resolveEventSink.js +8 -0
  185. package/dist/events/resolveEventSink.js.map +1 -0
  186. package/dist/events/types.d.ts +31 -0
  187. package/dist/exports/client.d.ts +15 -21
  188. package/dist/exports/client.js +15 -319
  189. package/dist/exports/i18n.d.ts +6 -138
  190. package/dist/exports/i18n.js +6 -3
  191. package/dist/exports/react.d.ts +63 -550
  192. package/dist/exports/react.js +55 -1563
  193. package/dist/exports/rsc.d.ts +9 -16
  194. package/dist/exports/rsc.js +9 -55
  195. package/dist/exports/types.d.ts +36 -5
  196. package/dist/fields/buildFieldBlocks.js +80 -0
  197. package/dist/fields/buildFieldBlocks.js.map +1 -0
  198. package/dist/fields/builtin/calculation.js +144 -0
  199. package/dist/fields/builtin/calculation.js.map +1 -0
  200. package/dist/fields/builtin/checkbox.js +21 -0
  201. package/dist/fields/builtin/checkbox.js.map +1 -0
  202. package/dist/fields/builtin/consent.js +47 -0
  203. package/dist/fields/builtin/consent.js.map +1 -0
  204. package/dist/fields/builtin/country.d.ts +13 -0
  205. package/dist/fields/builtin/country.js +30 -0
  206. package/dist/fields/builtin/country.js.map +1 -0
  207. package/dist/fields/builtin/date.js +31 -0
  208. package/dist/fields/builtin/date.js.map +1 -0
  209. package/dist/fields/builtin/email.js +18 -0
  210. package/dist/fields/builtin/email.js.map +1 -0
  211. package/dist/fields/builtin/file.d.ts +15 -0
  212. package/dist/fields/builtin/file.js +127 -0
  213. package/dist/fields/builtin/file.js.map +1 -0
  214. package/dist/fields/builtin/index.d.ts +26 -0
  215. package/dist/fields/builtin/index.js +49 -0
  216. package/dist/fields/builtin/index.js.map +1 -0
  217. package/dist/fields/builtin/message.js +30 -0
  218. package/dist/fields/builtin/message.js.map +1 -0
  219. package/dist/fields/builtin/number.js +17 -0
  220. package/dist/fields/builtin/number.js.map +1 -0
  221. package/dist/fields/builtin/repeater.js +49 -0
  222. package/dist/fields/builtin/repeater.js.map +1 -0
  223. package/dist/fields/builtin/select.js +49 -0
  224. package/dist/fields/builtin/select.js.map +1 -0
  225. package/dist/fields/builtin/state.d.ts +13 -0
  226. package/dist/fields/builtin/state.js +30 -0
  227. package/dist/fields/builtin/state.js.map +1 -0
  228. package/dist/fields/builtin/text.js +13 -0
  229. package/dist/fields/builtin/text.js.map +1 -0
  230. package/dist/fields/builtin/textarea.js +13 -0
  231. package/dist/fields/builtin/textarea.js.map +1 -0
  232. package/dist/fields/data/regions.d.ts +21 -0
  233. package/dist/fields/data/regions.js +1238 -0
  234. package/dist/fields/data/regions.js.map +1 -0
  235. package/dist/fields/defineFormField.d.ts +13 -0
  236. package/dist/fields/defineFormField.js +12 -0
  237. package/dist/fields/defineFormField.js.map +1 -0
  238. package/dist/fields/fieldKey.d.ts +15 -0
  239. package/dist/fields/fieldKey.js +16 -0
  240. package/dist/fields/fieldKey.js.map +1 -0
  241. package/dist/fields/fieldNamesOfType.js +30 -0
  242. package/dist/fields/fieldNamesOfType.js.map +1 -0
  243. package/dist/fields/instanceOptions.js +20 -0
  244. package/dist/fields/instanceOptions.js.map +1 -0
  245. package/dist/fields/localizedIf.d.ts +13 -0
  246. package/dist/fields/localizedIf.js +12 -0
  247. package/dist/fields/localizedIf.js.map +1 -0
  248. package/dist/fields/registry.d.ts +12 -0
  249. package/dist/fields/registry.js +39 -0
  250. package/dist/fields/registry.js.map +1 -0
  251. package/dist/fields/sharedConfig.js +151 -0
  252. package/dist/fields/sharedConfig.js.map +1 -0
  253. package/dist/fields/types.d.ts +152 -0
  254. package/dist/flow/engine.d.ts +19 -0
  255. package/dist/flow/engine.js +29 -0
  256. package/dist/flow/engine.js.map +1 -0
  257. package/dist/flow/normalizeFlow.js +54 -0
  258. package/dist/flow/normalizeFlow.js.map +1 -0
  259. package/dist/flow/stepLabel.js +15 -0
  260. package/dist/flow/stepLabel.js.map +1 -0
  261. package/dist/flow/types.d.ts +32 -0
  262. package/dist/flow/types.js +11 -0
  263. package/dist/flow/types.js.map +1 -0
  264. package/dist/form/pollState.d.ts +22 -0
  265. package/dist/form/pollState.js +17 -0
  266. package/dist/form/pollState.js.map +1 -0
  267. package/dist/form/toFormDocument.d.ts +102 -0
  268. package/dist/form/toFormDocument.js +87 -0
  269. package/dist/form/toFormDocument.js.map +1 -0
  270. package/dist/form/types.d.ts +65 -0
  271. package/dist/index.d.ts +88 -4
  272. package/dist/index.js +111 -1898
  273. package/dist/index.js.map +1 -1
  274. package/dist/options.d.ts +229 -0
  275. package/dist/plugin/access.js +12 -0
  276. package/dist/plugin/access.js.map +1 -0
  277. package/dist/plugin/applyRegistryConfig.d.ts +11 -0
  278. package/dist/plugin/applyRegistryConfig.js +20 -0
  279. package/dist/plugin/applyRegistryConfig.js.map +1 -0
  280. package/dist/plugin/collectionOverrides.d.ts +22 -0
  281. package/dist/plugin/customState.js +26 -0
  282. package/dist/plugin/customState.js.map +1 -0
  283. package/dist/plugin/registerCollections.js +60 -0
  284. package/dist/plugin/registerCollections.js.map +1 -0
  285. package/dist/plugin/registerTranslations.js +19 -0
  286. package/dist/plugin/registerTranslations.js.map +1 -0
  287. package/dist/plugin/uploadsCollection.d.ts +16 -0
  288. package/dist/plugin/uploadsCollection.js +53 -0
  289. package/dist/plugin/uploadsCollection.js.map +1 -0
  290. package/dist/poll/applyPollOptions.js +18 -0
  291. package/dist/poll/applyPollOptions.js.map +1 -0
  292. package/dist/poll/buildPollOptionSourceFields.js +50 -0
  293. package/dist/poll/buildPollOptionSourceFields.js.map +1 -0
  294. package/dist/poll/closeJob.d.ts +52 -0
  295. package/dist/poll/closeJob.js +119 -0
  296. package/dist/poll/closeJob.js.map +1 -0
  297. package/dist/poll/definePollOptionSource.d.ts +44 -0
  298. package/dist/poll/definePollOptionSource.js +6 -0
  299. package/dist/poll/definePollOptionSource.js.map +1 -0
  300. package/dist/poll/definePollType.d.ts +34 -0
  301. package/dist/poll/definePollType.js +6 -0
  302. package/dist/poll/definePollType.js.map +1 -0
  303. package/dist/poll/effectivePollOptions.d.ts +38 -0
  304. package/dist/poll/effectivePollOptions.js +64 -0
  305. package/dist/poll/effectivePollOptions.js.map +1 -0
  306. package/dist/poll/mostVoted.d.ts +21 -0
  307. package/dist/poll/mostVoted.js +32 -0
  308. package/dist/poll/mostVoted.js.map +1 -0
  309. package/dist/poll/outcomeBeforeChange.js +91 -0
  310. package/dist/poll/outcomeBeforeChange.js.map +1 -0
  311. package/dist/poll/outcomeFields.d.ts +38 -0
  312. package/dist/poll/outcomeFields.js +52 -0
  313. package/dist/poll/outcomeFields.js.map +1 -0
  314. package/dist/poll/pollTypeRegistry.d.ts +34 -0
  315. package/dist/poll/pollTypeRegistry.js +69 -0
  316. package/dist/poll/pollTypeRegistry.js.map +1 -0
  317. package/dist/poll/registry.d.ts +17 -0
  318. package/dist/poll/registry.js +12 -0
  319. package/dist/poll/registry.js.map +1 -0
  320. package/dist/poll/resolvePollCloseRequest.js +105 -0
  321. package/dist/poll/resolvePollCloseRequest.js.map +1 -0
  322. package/dist/poll/resolvePollOptions.d.ts +29 -0
  323. package/dist/poll/resolvePollOptions.js +52 -0
  324. package/dist/poll/resolvePollOptions.js.map +1 -0
  325. package/dist/poll/resolvePollOptionsRequest.js +50 -0
  326. package/dist/poll/resolvePollOptionsRequest.js.map +1 -0
  327. package/dist/poll/resolvePollOutcome.d.ts +34 -0
  328. package/dist/poll/resolvePollOutcome.js +76 -0
  329. package/dist/poll/resolvePollOutcome.js.map +1 -0
  330. package/dist/poll/resultsField.js +21 -0
  331. package/dist/poll/resultsField.js.map +1 -0
  332. package/dist/prefill/valuesFromSearchParams.d.ts +18 -0
  333. package/dist/prefill/valuesFromSearchParams.js +41 -0
  334. package/dist/prefill/valuesFromSearchParams.js.map +1 -0
  335. package/dist/presentations/defaults.d.ts +33 -0
  336. package/dist/presentations/defaults.js +35 -0
  337. package/dist/presentations/defaults.js.map +1 -0
  338. package/dist/presentations/types.d.ts +19 -0
  339. package/dist/react/Form.d.ts +128 -0
  340. package/dist/react/Form.js +619 -0
  341. package/dist/react/Form.js.map +1 -0
  342. package/dist/react/FormContext.d.ts +59 -0
  343. package/dist/react/FormContext.js +14 -0
  344. package/dist/react/FormContext.js.map +1 -0
  345. package/dist/react/FormControls.d.ts +55 -0
  346. package/dist/react/FormControls.js +56 -0
  347. package/dist/react/FormControls.js.map +1 -0
  348. package/dist/react/FormFields.d.ts +18 -0
  349. package/dist/react/FormFields.js +114 -0
  350. package/dist/react/FormFields.js.map +1 -0
  351. package/dist/react/FormLayout.d.ts +22 -0
  352. package/dist/react/FormLayout.js +15 -0
  353. package/dist/react/FormLayout.js.map +1 -0
  354. package/dist/react/FormResults.d.ts +28 -0
  355. package/dist/react/FormResults.js +93 -0
  356. package/dist/react/FormResults.js.map +1 -0
  357. package/dist/react/FormSteps.d.ts +17 -0
  358. package/dist/react/FormSteps.js +35 -0
  359. package/dist/react/FormSteps.js.map +1 -0
  360. package/dist/react/Honeypot.d.ts +22 -0
  361. package/dist/react/Honeypot.js +38 -0
  362. package/dist/react/Honeypot.js.map +1 -0
  363. package/dist/react/Poll.d.ts +43 -0
  364. package/dist/react/Poll.js +135 -0
  365. package/dist/react/Poll.js.map +1 -0
  366. package/dist/react/captcha/HcaptchaCaptcha.d.ts +28 -0
  367. package/dist/react/captcha/HcaptchaCaptcha.js +53 -0
  368. package/dist/react/captcha/HcaptchaCaptcha.js.map +1 -0
  369. package/dist/react/captcha/RecaptchaCaptcha.d.ts +41 -0
  370. package/dist/react/captcha/RecaptchaCaptcha.js +93 -0
  371. package/dist/react/captcha/RecaptchaCaptcha.js.map +1 -0
  372. package/dist/react/captcha/TurnstileCaptcha.d.ts +28 -0
  373. package/dist/react/captcha/TurnstileCaptcha.js +53 -0
  374. package/dist/react/captcha/TurnstileCaptcha.js.map +1 -0
  375. package/dist/react/captcha/types.d.ts +8 -0
  376. package/dist/react/captcha/useCaptchaScript.js +45 -0
  377. package/dist/react/captcha/useCaptchaScript.js.map +1 -0
  378. package/dist/react/captcha/vendors.js +8 -0
  379. package/dist/react/captcha/vendors.js.map +1 -0
  380. package/dist/react/cn.d.ts +6 -0
  381. package/dist/react/cn.js +8 -0
  382. package/dist/react/cn.js.map +1 -0
  383. package/dist/react/contract.d.ts +31 -0
  384. package/dist/react/contract.js +7 -0
  385. package/dist/react/contract.js.map +1 -0
  386. package/dist/react/events.js +14 -0
  387. package/dist/react/events.js.map +1 -0
  388. package/dist/react/fetchResults.d.ts +25 -0
  389. package/dist/react/fetchResults.js +31 -0
  390. package/dist/react/fetchResults.js.map +1 -0
  391. package/dist/react/presentation/Backdrop.d.ts +18 -0
  392. package/dist/react/presentation/Backdrop.js +14 -0
  393. package/dist/react/presentation/Backdrop.js.map +1 -0
  394. package/dist/react/presentation/DialogSurface.d.ts +35 -0
  395. package/dist/react/presentation/DialogSurface.js +53 -0
  396. package/dist/react/presentation/DialogSurface.js.map +1 -0
  397. package/dist/react/presentation/presentations.d.ts +7 -0
  398. package/dist/react/presentation/presentations.js +32 -0
  399. package/dist/react/presentation/presentations.js.map +1 -0
  400. package/dist/react/presentation/registry.d.ts +11 -0
  401. package/dist/react/presentation/registry.js +12 -0
  402. package/dist/react/presentation/registry.js.map +1 -0
  403. package/dist/react/presentation/types.d.ts +19 -0
  404. package/dist/react/presentation/useDismiss.d.ts +19 -0
  405. package/dist/react/presentation/useDismiss.js +33 -0
  406. package/dist/react/presentation/useDismiss.js.map +1 -0
  407. package/dist/react/presentation/useFocusTrap.d.ts +8 -0
  408. package/dist/react/presentation/useFocusTrap.js +35 -0
  409. package/dist/react/presentation/useFocusTrap.js.map +1 -0
  410. package/dist/react/presentation/useScrollLock.d.ts +6 -0
  411. package/dist/react/presentation/useScrollLock.js +18 -0
  412. package/dist/react/presentation/useScrollLock.js.map +1 -0
  413. package/dist/react/primitives/Checkbox.d.ts +28 -0
  414. package/dist/react/primitives/Checkbox.js +21 -0
  415. package/dist/react/primitives/Checkbox.js.map +1 -0
  416. package/dist/react/primitives/FieldShell.d.ts +29 -0
  417. package/dist/react/primitives/FieldShell.js +44 -0
  418. package/dist/react/primitives/FieldShell.js.map +1 -0
  419. package/dist/react/primitives/Input.d.ts +30 -0
  420. package/dist/react/primitives/Input.js +21 -0
  421. package/dist/react/primitives/Input.js.map +1 -0
  422. package/dist/react/primitives/Select.d.ts +34 -0
  423. package/dist/react/primitives/Select.js +26 -0
  424. package/dist/react/primitives/Select.js.map +1 -0
  425. package/dist/react/primitives/Textarea.d.ts +28 -0
  426. package/dist/react/primitives/Textarea.js +20 -0
  427. package/dist/react/primitives/Textarea.js.map +1 -0
  428. package/dist/react/recall.js +20 -0
  429. package/dist/react/recall.js.map +1 -0
  430. package/dist/react/registry.d.ts +16 -0
  431. package/dist/react/registry.js +16 -0
  432. package/dist/react/registry.js.map +1 -0
  433. package/dist/react/renderers/calculation.js +27 -0
  434. package/dist/react/renderers/calculation.js.map +1 -0
  435. package/dist/react/renderers/checkbox.js +32 -0
  436. package/dist/react/renderers/checkbox.js.map +1 -0
  437. package/dist/react/renderers/consent.js +97 -0
  438. package/dist/react/renderers/consent.js.map +1 -0
  439. package/dist/react/renderers/date.js +33 -0
  440. package/dist/react/renderers/date.js.map +1 -0
  441. package/dist/react/renderers/email.js +34 -0
  442. package/dist/react/renderers/email.js.map +1 -0
  443. package/dist/react/renderers/file.js +107 -0
  444. package/dist/react/renderers/file.js.map +1 -0
  445. package/dist/react/renderers/index.d.ts +8 -0
  446. package/dist/react/renderers/index.js +35 -0
  447. package/dist/react/renderers/index.js.map +1 -0
  448. package/dist/react/renderers/message.js +41 -0
  449. package/dist/react/renderers/message.js.map +1 -0
  450. package/dist/react/renderers/number.js +37 -0
  451. package/dist/react/renderers/number.js.map +1 -0
  452. package/dist/react/renderers/region.js +43 -0
  453. package/dist/react/renderers/region.js.map +1 -0
  454. package/dist/react/renderers/repeater.js +131 -0
  455. package/dist/react/renderers/repeater.js.map +1 -0
  456. package/dist/react/renderers/select.js +35 -0
  457. package/dist/react/renderers/select.js.map +1 -0
  458. package/dist/react/renderers/text.js +34 -0
  459. package/dist/react/renderers/text.js.map +1 -0
  460. package/dist/react/renderers/textarea.js +33 -0
  461. package/dist/react/renderers/textarea.js.map +1 -0
  462. package/dist/react/resolveForm.js +16 -0
  463. package/dist/react/resolveForm.js.map +1 -0
  464. package/dist/react/state.d.ts +52 -0
  465. package/dist/react/state.js +125 -0
  466. package/dist/react/state.js.map +1 -0
  467. package/dist/react/submitForm.d.ts +31 -0
  468. package/dist/react/submitForm.js +58 -0
  469. package/dist/react/submitForm.js.map +1 -0
  470. package/dist/react/uploadFile.d.ts +23 -0
  471. package/dist/react/uploadFile.js +39 -0
  472. package/dist/react/uploadFile.js.map +1 -0
  473. package/dist/react/useField.d.ts +13 -0
  474. package/dist/react/useField.js +49 -0
  475. package/dist/react/useField.js.map +1 -0
  476. package/dist/react/useFormState.d.ts +8 -0
  477. package/dist/react/useFormState.js +9 -0
  478. package/dist/react/useFormState.js.map +1 -0
  479. package/dist/react/useFormStep.d.ts +8 -0
  480. package/dist/react/useFormStep.js +9 -0
  481. package/dist/react/useFormStep.js.map +1 -0
  482. package/dist/react/validateField.js +27 -0
  483. package/dist/react/validateField.js.map +1 -0
  484. package/dist/recall/interpolate.d.ts +11 -0
  485. package/dist/recall/interpolate.js +17 -0
  486. package/dist/recall/interpolate.js.map +1 -0
  487. package/dist/recall/resolver.d.ts +22 -0
  488. package/dist/recall/resolver.js +48 -0
  489. package/dist/recall/resolver.js.map +1 -0
  490. package/dist/spam/captcha.d.ts +13 -0
  491. package/dist/spam/captcha.js +12 -0
  492. package/dist/spam/captcha.js.map +1 -0
  493. package/dist/spam/clientIp.js +9 -0
  494. package/dist/spam/clientIp.js.map +1 -0
  495. package/dist/spam/constants.d.ts +12 -0
  496. package/dist/spam/constants.js +21 -0
  497. package/dist/spam/constants.js.map +1 -0
  498. package/dist/spam/identify.d.ts +12 -0
  499. package/dist/spam/identify.js +17 -0
  500. package/dist/spam/identify.js.map +1 -0
  501. package/dist/spam/providers/hcaptcha.d.ts +17 -0
  502. package/dist/spam/providers/hcaptcha.js +18 -0
  503. package/dist/spam/providers/hcaptcha.js.map +1 -0
  504. package/dist/spam/providers/recaptcha.d.ts +23 -0
  505. package/dist/spam/providers/recaptcha.js +23 -0
  506. package/dist/spam/providers/recaptcha.js.map +1 -0
  507. package/dist/spam/providers/siteverify.js +34 -0
  508. package/dist/spam/providers/siteverify.js.map +1 -0
  509. package/dist/spam/providers/turnstile.d.ts +17 -0
  510. package/dist/spam/providers/turnstile.js +18 -0
  511. package/dist/spam/providers/turnstile.js.map +1 -0
  512. package/dist/spam/rateLimiter.d.ts +18 -0
  513. package/dist/spam/rateLimiter.js +41 -0
  514. package/dist/spam/rateLimiter.js.map +1 -0
  515. package/dist/spam/reserved.js +30 -0
  516. package/dist/spam/reserved.js.map +1 -0
  517. package/dist/spam/resolveSpam.d.ts +12 -0
  518. package/dist/spam/resolveSpam.js +43 -0
  519. package/dist/spam/resolveSpam.js.map +1 -0
  520. package/dist/spam/spamGuard.js +81 -0
  521. package/dist/spam/spamGuard.js.map +1 -0
  522. package/dist/spam/types.d.ts +88 -0
  523. package/dist/spam/uploadHooks.js +33 -0
  524. package/dist/spam/uploadHooks.js.map +1 -0
  525. package/dist/submissions/SubmissionAnswers.d.ts +14 -0
  526. package/dist/submissions/SubmissionAnswers.js +137 -0
  527. package/dist/submissions/SubmissionAnswers.js.map +1 -0
  528. package/dist/submissions/SubmissionAnswersClient.js +178 -0
  529. package/dist/submissions/SubmissionAnswersClient.js.map +1 -0
  530. package/dist/submissions/coerceBoolean.js +14 -0
  531. package/dist/submissions/coerceBoolean.js.map +1 -0
  532. package/dist/submissions/createSubmission.d.ts +36 -0
  533. package/dist/submissions/createSubmission.js +26 -0
  534. package/dist/submissions/createSubmission.js.map +1 -0
  535. package/dist/submissions/runSubmission.d.ts +10 -0
  536. package/dist/submissions/runSubmission.js +306 -0
  537. package/dist/submissions/runSubmission.js.map +1 -0
  538. package/dist/submissions/types.d.ts +41 -0
  539. package/dist/submissions/validateSubmission.js +110 -0
  540. package/dist/submissions/validateSubmission.js.map +1 -0
  541. package/dist/submissions/votedCookie.d.ts +13 -0
  542. package/dist/submissions/votedCookie.js +27 -0
  543. package/dist/submissions/votedCookie.js.map +1 -0
  544. package/dist/translations/clientRuntimeKeys.d.ts +17 -0
  545. package/dist/translations/clientRuntimeKeys.js +46 -0
  546. package/dist/translations/clientRuntimeKeys.js.map +1 -0
  547. package/dist/translations/de.d.ts +12 -0
  548. package/dist/translations/de.js +309 -0
  549. package/dist/translations/de.js.map +1 -0
  550. package/dist/translations/en.d.ts +12 -0
  551. package/dist/translations/en.js +309 -0
  552. package/dist/translations/en.js.map +1 -0
  553. package/dist/translations/index.d.ts +23 -0
  554. package/dist/translations/index.js +37 -0
  555. package/dist/translations/index.js.map +1 -0
  556. package/dist/translations/keys.d.ts +308 -0
  557. package/dist/translations/keys.js +308 -0
  558. package/dist/translations/keys.js.map +1 -0
  559. package/dist/translations/makeTranslate.d.ts +15 -0
  560. package/dist/translations/makeTranslate.js +20 -0
  561. package/dist/translations/makeTranslate.js.map +1 -0
  562. package/dist/translations/server.js +32 -0
  563. package/dist/translations/server.js.map +1 -0
  564. package/dist/translations/useTranslation.js +12 -0
  565. package/dist/translations/useTranslation.js.map +1 -0
  566. package/dist/uploads/captureFileRef.d.ts +34 -0
  567. package/dist/uploads/captureFileRef.js +43 -0
  568. package/dist/uploads/captureFileRef.js.map +1 -0
  569. package/dist/uploads/formatBytes.d.ts +9 -0
  570. package/dist/uploads/formatBytes.js +25 -0
  571. package/dist/uploads/formatBytes.js.map +1 -0
  572. package/dist/uploads/resolveFileRef.d.ts +26 -0
  573. package/dist/uploads/resolveFileRef.js +45 -0
  574. package/dist/uploads/resolveFileRef.js.map +1 -0
  575. package/dist/uploads/types.d.ts +19 -0
  576. package/dist/validation/buildRuleBlocks.js +47 -0
  577. package/dist/validation/buildRuleBlocks.js.map +1 -0
  578. package/dist/validation/builtin/email.js +20 -0
  579. package/dist/validation/builtin/email.js.map +1 -0
  580. package/dist/validation/builtin/index.d.ts +14 -0
  581. package/dist/validation/builtin/index.js +38 -0
  582. package/dist/validation/builtin/index.js.map +1 -0
  583. package/dist/validation/builtin/matchesField.js +16 -0
  584. package/dist/validation/builtin/matchesField.js.map +1 -0
  585. package/dist/validation/builtin/max.js +22 -0
  586. package/dist/validation/builtin/max.js.map +1 -0
  587. package/dist/validation/builtin/maxDate.js +24 -0
  588. package/dist/validation/builtin/maxDate.js.map +1 -0
  589. package/dist/validation/builtin/maxLength.js +27 -0
  590. package/dist/validation/builtin/maxLength.js.map +1 -0
  591. package/dist/validation/builtin/min.js +22 -0
  592. package/dist/validation/builtin/min.js.map +1 -0
  593. package/dist/validation/builtin/minDate.js +24 -0
  594. package/dist/validation/builtin/minDate.js.map +1 -0
  595. package/dist/validation/builtin/minLength.js +27 -0
  596. package/dist/validation/builtin/minLength.js.map +1 -0
  597. package/dist/validation/builtin/notAlreadySubmitted.js +34 -0
  598. package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -0
  599. package/dist/validation/builtin/oneOf.js +35 -0
  600. package/dist/validation/builtin/oneOf.js.map +1 -0
  601. package/dist/validation/builtin/pattern.js +50 -0
  602. package/dist/validation/builtin/pattern.js.map +1 -0
  603. package/dist/validation/builtin/url.js +23 -0
  604. package/dist/validation/builtin/url.js.map +1 -0
  605. package/dist/validation/builtin/validateDateBound.js +18 -0
  606. package/dist/validation/builtin/validateDateBound.js.map +1 -0
  607. package/dist/validation/builtin/validateRegexParams.js +44 -0
  608. package/dist/validation/builtin/validateRegexParams.js.map +1 -0
  609. package/dist/validation/defineValidationRule.d.ts +12 -0
  610. package/dist/validation/defineValidationRule.js +11 -0
  611. package/dist/validation/defineValidationRule.js.map +1 -0
  612. package/dist/validation/emailPattern.js +10 -0
  613. package/dist/validation/emailPattern.js.map +1 -0
  614. package/dist/validation/fieldTargetParam.d.ts +22 -0
  615. package/dist/validation/fieldTargetParam.js +38 -0
  616. package/dist/validation/fieldTargetParam.js.map +1 -0
  617. package/dist/validation/message.js +14 -0
  618. package/dist/validation/message.js.map +1 -0
  619. package/dist/validation/registry.d.ts +11 -0
  620. package/dist/validation/registry.js +13 -0
  621. package/dist/validation/registry.js.map +1 -0
  622. package/dist/validation/runValidation.js +90 -0
  623. package/dist/validation/runValidation.js.map +1 -0
  624. package/dist/validation/types.d.ts +70 -0
  625. package/dist/validation/validateUrl.js +22 -0
  626. package/dist/validation/validateUrl.js.map +1 -0
  627. package/package.json +12 -7
  628. package/styles/form-builder.css +21 -11
  629. package/dist/constants-B-BUfetP.d.ts +0 -288
  630. package/dist/exports/client.js.map +0 -1
  631. package/dist/exports/react.js.map +0 -1
  632. package/dist/exports/rsc.js.map +0 -1
  633. package/dist/fieldTypes-B8jkNRob.d.ts +0 -188
  634. package/dist/fieldTypes-CzhhJXjg.js.map +0 -1
  635. package/dist/index-DfFYGbVF.d.ts +0 -481
  636. package/dist/keys-N5xGiUsh.js +0 -132
  637. package/dist/keys-N5xGiUsh.js.map +0 -1
  638. package/dist/registry-CoCyhtvB.js +0 -282
  639. package/dist/registry-CoCyhtvB.js.map +0 -1
  640. package/dist/resolver-OeQyVH2N.js +0 -665
  641. package/dist/resolver-OeQyVH2N.js.map +0 -1
  642. package/dist/translations-edMqq_2e.js +0 -152
  643. package/dist/translations-edMqq_2e.js.map +0 -1
  644. package/dist/types-DsJ_6kGJ.d.ts +0 -23
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Form.js","names":[],"sources":["../../src/react/Form.tsx"],"sourcesContent":["'use client'\n\nimport {\n\ttype CSSProperties,\n\ttype FormEvent as ReactFormEvent,\n\ttype KeyboardEvent as ReactKeyboardEvent,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseReducer,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport type { BodyConverter } from '../actions/body/converters'\nimport { serializeBody } from '../actions/body/serializeBody'\nimport { calcExpressionOf, computeCalcFields } from '../calc/computeCalcFields'\nimport { evaluateCondition } from '../conditions/evaluate'\nimport { noopEventSink } from '../events/noopSink'\nimport type { FormEventSink } from '../events/types'\nimport { fieldKey, isNamedField, type NamedFormFieldInstance } from '../fields/fieldKey'\nimport type { AnyFormFieldDefinition } from '../fields/types'\nimport { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames } from '../flow/engine'\nimport type { FormFlow } from '../flow/types'\nimport type {\n\tFormButtonSettings,\n\tFormDocument,\n\tFormPollSettings,\n\tFormResponseSettings,\n} from '../form/types'\nimport {\n\tDEFAULT_PRESENTATION_NAME,\n\tdefaultPresentationDescriptors,\n} from '../presentations/defaults'\nimport { interpolate } from '../recall/interpolate'\nimport { buildRecallResolver, descriptorsFor } from '../recall/resolver'\nimport { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD, HONEYPOT_VALUE_KEY } from '../spam/constants'\nimport type { FormFieldInstance, SubmissionValue } from '../submissions/types'\nimport { en } from '../translations/en'\nimport { keys } from '../translations/keys'\nimport { makeTranslate } from '../translations/makeTranslate'\nimport { resolveMessage } from '../validation/message'\nimport type { AnyValidationRuleDefinition } from '../validation/types'\nimport { cn } from './cn'\nimport type { RendererTranslate } from './contract'\nimport { emitFormEvent } from './events'\nimport { FormContext, type FormContextValue, type FormStepInfo } from './FormContext'\nimport {\n\ttype BackButtonRenderProps,\n\tFormControls,\n\ttype NextButtonRenderProps,\n\ttype SubmitButtonRenderProps,\n} from './FormControls'\nimport { FormFields } from './FormFields'\nimport { Honeypot } from './Honeypot'\nimport { defaultPresentations } from './presentation/presentations'\nimport { type PresentationsConfig, resolvePresentations } from './presentation/registry'\nimport type { FormPresentation } from './presentation/types'\nimport { type RenderersConfig, resolveRenderers } from './registry'\nimport { defaultRenderers } from './renderers'\nimport { buildFieldTypeRegistry, buildValidationRuleRegistry, visibleFields } from './resolveForm'\nimport {\n\tDEFAULT_STEP_ID,\n\ttype FieldErrors,\n\ttype FormAction,\n\tformReducer,\n\tinitialFormState,\n\tseedFieldValues,\n} from './state'\nimport { type SubmitFormResult, type SubmitHandler, submitForm } from './submitForm'\nimport { validateFieldValue } from './validateField'\n\nexport type {\n\tBackButtonRenderProps,\n\tNextButtonRenderProps,\n\tSubmitButtonRenderProps,\n} from './FormControls'\n// FormResponseSettings, FormButtonSettings, FormPollSettings, and FormDocument live in\n// `../form/types` (no 'use client') so server code (e.g. `toFormDocument` in a Server Component)\n// can use them without pulling in this client module. Re-exported here so `./react` and existing\n// `from './Form'` imports keep working unchanged.\nexport type { FormButtonSettings, FormDocument, FormPollSettings, FormResponseSettings }\n\n/**\n * The success response passed to `onSuccess`, recall-resolved and (for a message) serialized with the\n * form's active converters, so a host can render or toast the resolved response without re-deriving it.\n */\nexport type FormSuccessResponse =\n\t| { type: 'message'; html?: string }\n\t| { type: 'redirect'; url?: string }\n\n/** The second argument to `onSuccess`: the resolved success response (an object, so it can grow). */\nexport type FormSuccessResult = { response?: FormSuccessResponse }\n\nexport type FormProps = {\n\tform: FormDocument\n\tfieldTypes?: AnyFormFieldDefinition[]\n\trules?: AnyValidationRuleDefinition[]\n\trenderers?: RenderersConfig\n\tapiRoute?: string\n\tonSubmit?: SubmitHandler\n\t/**\n\t * Called after a successful submission with the submission id and the resolved success response\n\t * (recall-applied, serialized with `converters`), so a host can toast or render it. Fires in both\n\t * `successBehavior` modes and on the custom-`children` path.\n\t */\n\tonSuccess?: (submissionId?: string, result?: FormSuccessResult) => void\n\tonError?: (message: string) => void\n\t/**\n\t * Custom Lexical block converters (e.g. host `icon`/`badge` blocks) spread over the defaults for the\n\t * client serializer, so those blocks survive in the success message and in the `onSuccess` response.\n\t */\n\tconverters?: Record<string, BodyConverter>\n\t/**\n\t * What happens on a successful submit. `'replace'` (default) swaps the form for the success screen;\n\t * `'reset'` clears the fields in place and shows no success screen, so a host can toast via `onSuccess`\n\t * and keep the form usable.\n\t */\n\tsuccessBehavior?: 'replace' | 'reset'\n\tevents?: FormEventSink\n\tt?: RendererTranslate\n\tlocale?: string\n\tlayout?: boolean\n\t/** Submit button label. Precedence: this prop, then the form's `buttons.submitLabel`, then the translated default. */\n\tsubmitLabel?: string\n\t/** \"Next\" button label for multi-step forms. Precedence: this prop, then the form's `buttons.nextLabel`, then the translated default. */\n\tnextLabel?: string\n\t/** \"Back\" button label for multi-step forms. Precedence: this prop, then the form's `buttons.prevLabel`, then the translated default. */\n\tprevLabel?: string\n\t/** Label for the overlay close control (modal/drawer). */\n\tcloseLabel?: string\n\tsuccessMessage?: string\n\t/** Active presentation: a name into the registry or an inline presentation. Defaults to `'page'` when omitted. */\n\tpresentation?: string | FormPresentation\n\t/** Per-render presentation overrides merged onto the defaults (add, replace, or `false` to remove). */\n\tpresentations?: PresentationsConfig\n\t/** Invoked when an overlay presentation dismisses (close button, Escape, outside click, or `dismissOnSuccess`). */\n\tonClose?: () => void\n\t/**\n\t * Accessible name for an overlay surface (modal/drawer). Hosts choosing between a trigger\n\t * label and the form's own admin title should prefer `form.title` when set, falling back to\n\t * their own label otherwise.\n\t */\n\ttitle?: string\n\t/** Seed initial field values (e.g. from `valuesFromSearchParams`). Still validated on submit. */\n\tinitialValues?: Record<string, unknown>\n\t/** Honeypot decoy (on by default). `false` removes it; `{ name }` matches a customized server `spam.honeypot.fieldName`. */\n\thoneypot?: false | { name?: string }\n\t/** A token from your captcha widget; verified server-side when a captcha provider is configured. */\n\tcaptchaToken?: string\n\t/** Custom layout: render fields with `useField`/`useFormState` instead of the auto-rendered field loop. */\n\tchildren?: ReactNode\n\t/** Chrome rendered inside the form, above the fields, in default mode (e.g. `<FormSteps />`). */\n\theader?: ReactNode\n\t/** Additional CSS class names applied to the root `<form>` element (and the success node). */\n\tclassName?: string\n\t/** Replace the default submit button entirely. Receives the resolved label and submitting state. */\n\trenderSubmit?: (props: SubmitButtonRenderProps) => ReactNode\n\t/** Replace the default \"Next\" button in multi-step forms. */\n\trenderNext?: (props: NextButtonRenderProps) => ReactNode\n\t/** Replace the default \"Back\" button in multi-step forms. */\n\trenderBack?: (props: BackButtonRenderProps) => ReactNode\n\t/** CSS class forwarded to the default submit `<button>`. Ignored when `renderSubmit` is provided. */\n\tsubmitButtonClassName?: string\n\t/** CSS class forwarded to the default \"Next\" `<button>`. Ignored when `renderNext` is provided. */\n\tnextButtonClassName?: string\n\t/** CSS class forwarded to the default \"Back\" `<button>`. Ignored when `renderBack` is provided. */\n\tbackButtonClassName?: string\n}\n\nconst isEmpty = (value: unknown): boolean =>\n\tvalue == null || value === '' || (Array.isArray(value) && value.length === 0)\n\n/** Visually hidden but screen-reader-announced, for the \"Step X of Y\" live region (no host CSS required). */\nconst SR_ONLY: CSSProperties = {\n\tposition: 'absolute',\n\twidth: 1,\n\theight: 1,\n\tpadding: 0,\n\tmargin: -1,\n\toverflow: 'hidden',\n\tclip: 'rect(0, 0, 0, 0)',\n\twhiteSpace: 'nowrap',\n\tborder: 0,\n}\n\n/** The base field name of an error key: the part before a repeater composite suffix (`name[0].sub`). */\nconst baseFieldKey = (key: string): string => {\n\tconst bracket = key.indexOf('[')\n\treturn bracket === -1 ? key : key.slice(0, bracket)\n}\n\n/** The id of the first flow step (in order) that owns an errored field, or undefined when none does. */\nconst firstStepWithError = (flow: FormFlow, errors: FieldErrors): string | undefined => {\n\tconst errored = new Set(Object.keys(errors).map(baseFieldKey))\n\treturn flow.steps.find((flowStep) => flowStep.fields.some((key) => errored.has(key)))?.id\n}\n\n/** The first focusable element under `root` that a step transition should land on (skips hidden/honeypot). */\nconst focusFirstIn = (root: HTMLElement | null, selector: string): void => {\n\tconst target = root?.querySelector<HTMLElement>(selector)\n\ttarget?.focus()\n}\n\n/** A stored button label counts only when it is a non-empty string; anything else falls through. */\nconst storedLabel = (value: unknown): string | undefined =>\n\ttypeof value === 'string' && value.length > 0 ? value : undefined\n\n/** The headless form controller: state, progressive client validation, conditional visibility, submission, events. */\nexport const Form = ({\n\tform,\n\tfieldTypes,\n\trules,\n\trenderers,\n\tapiRoute,\n\tonSubmit,\n\tonSuccess,\n\tonError,\n\tconverters,\n\tsuccessBehavior = 'replace',\n\tevents,\n\tt,\n\tlocale = 'en',\n\tlayout,\n\tsubmitLabel,\n\tnextLabel,\n\tprevLabel,\n\tcloseLabel,\n\tsuccessMessage,\n\tpresentation,\n\tpresentations,\n\tonClose,\n\ttitle,\n\tinitialValues,\n\thoneypot,\n\tcaptchaToken,\n\tchildren,\n\theader,\n\tclassName,\n\trenderSubmit,\n\trenderNext,\n\trenderBack,\n\tsubmitButtonClassName,\n\tnextButtonClassName,\n\tbackButtonClassName,\n}: FormProps) => {\n\tconst honeypotName = honeypot === false ? null : (honeypot?.name ?? DEFAULT_HONEYPOT_FIELD)\n\tconst honeypotRef = useRef<HTMLInputElement>(null)\n\tconst registry = useMemo(() => buildFieldTypeRegistry(fieldTypes), [fieldTypes])\n\tconst ruleRegistry = useMemo(() => buildValidationRuleRegistry(rules), [rules])\n\tconst rendererRegistry = useMemo(() => resolveRenderers(defaultRenderers, renderers), [renderers])\n\tconst presentationRegistry = useMemo(\n\t\t() => resolvePresentations(defaultPresentations, presentations),\n\t\t[presentations]\n\t)\n\tconst activePresentation: FormPresentation =\n\t\ttypeof presentation === 'object'\n\t\t\t? presentation\n\t\t\t: (presentationRegistry.get(presentation ?? DEFAULT_PRESENTATION_NAME) ??\n\t\t\t\tpresentationRegistry.get(DEFAULT_PRESENTATION_NAME) ??\n\t\t\t\tdefaultPresentationDescriptors.page)\n\tconst fieldsByName = useMemo(\n\t\t() => new Map(form.fields.filter(isNamedField).map((field) => [field.name, field])),\n\t\t[form.fields]\n\t)\n\tconst translate = useMemo<RendererTranslate>(() => t ?? makeTranslate(en), [t])\n\tconst resolvedCloseLabel = closeLabel ?? translate(keys.formClose)\n\tconst resolvedSuccessMessage = successMessage ?? translate(keys.formSuccess)\n\tconst docButtons: FormButtonSettings | undefined = form.buttons\n\tconst labels = useMemo(\n\t\t() => ({\n\t\t\tprev: prevLabel ?? storedLabel(docButtons?.prevLabel) ?? translate(keys.formBack),\n\t\t\tnext: nextLabel ?? storedLabel(docButtons?.nextLabel) ?? translate(keys.formNext),\n\t\t\tsubmit: submitLabel ?? storedLabel(docButtons?.submitLabel) ?? translate(keys.formSubmit),\n\t\t}),\n\t\t[prevLabel, nextLabel, submitLabel, docButtons, translate]\n\t)\n\n\t// Latest-value refs so event emission and the mount/unmount effect tolerate an inline `events` prop or a changing form id.\n\tconst sinkRef = useRef<FormEventSink>(noopEventSink)\n\tsinkRef.current = events ?? noopEventSink\n\tconst formIdRef = useRef('')\n\tformIdRef.current = String(form.id)\n\n\tconst [state, rawDispatch] = useReducer(formReducer, form.fields, (fields) =>\n\t\tinitialFormState({\n\t\t\t...seedFieldValues(fields),\n\t\t\t...(initialValues ?? {}),\n\t\t})\n\t)\n\n\t// Authoritative values for derived (calc) fields, recomputed from user answers on every change. The\n\t// server recomputes these too at submit; the client copy drives the live calc renderer, recall, and submit.\n\tconst effectiveValues = useMemo(\n\t\t() => computeCalcFields(form.fields, state.values),\n\t\t[form.fields, state.values]\n\t)\n\n\tconst recall = useMemo(\n\t\t() =>\n\t\t\tbuildRecallResolver({\n\t\t\t\tfields: form.fields,\n\t\t\t\tvalues: effectiveValues,\n\t\t\t\tregistry,\n\t\t\t\tlocale,\n\t\t\t\tt: translate,\n\t\t\t}),\n\t\t[form.fields, effectiveValues, registry, locale, translate]\n\t)\n\n\t// Multi-step is active only when the form is flagged `multistep` and its flow declares two or more\n\t// steps. With the flag off the form renders as a single page even if flow data is still stored.\n\tconst flow =\n\t\tform.multistep === true && form.flow && form.flow.steps.length >= 2 ? form.flow : undefined\n\tconst [currentStepId, setCurrentStepId] = useState<string | undefined>(() =>\n\t\tflow ? firstStepId(flow) : undefined\n\t)\n\tconst [history, setHistory] = useState<string[]>([])\n\n\tconst startedRef = useRef(false)\n\tconst submittedRef = useRef(false)\n\tconst submittingRef = useRef(false)\n\tconst advancingRef = useRef(false)\n\tconst flowRef = useRef(flow)\n\tflowRef.current = flow\n\n\t// Per-step error reveal: a field maps to the id of the flow step whose `fields` include it, else the\n\t// default step (single-step forms, or a field assigned to no step), so a single-step form collapses to\n\t// one step and today's behavior.\n\tconst stepIdOfField = useMemo(() => {\n\t\tconst map = new Map<string, string>()\n\t\tif (flow) {\n\t\t\tfor (const flowStep of flow.steps) {\n\t\t\t\tfor (const key of flowStep.fields) {\n\t\t\t\t\tmap.set(key, flowStep.id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn (fieldKey: string): string => map.get(fieldKey) ?? DEFAULT_STEP_ID\n\t}, [flow])\n\tconst allStepIds = useMemo(\n\t\t() => (flow ? flow.steps.map((flowStep) => flowStep.id) : [DEFAULT_STEP_ID]),\n\t\t[flow]\n\t)\n\n\t// Focus management for step transitions and blocked advances/submits. A pending request is performed\n\t// by an effect after the render it triggers, so focus lands on the DOM that reflects the new state.\n\tconst formRef = useRef<HTMLFormElement>(null)\n\tconst pendingFocusRef = useRef<'stepStart' | 'firstInvalid' | null>(null)\n\tconst [focusNonce, setFocusNonce] = useState(0)\n\tconst requestFocus = (intent: 'stepStart' | 'firstInvalid') => {\n\t\tpendingFocusRef.current = intent\n\t\tsetFocusNonce((nonce) => nonce + 1)\n\t}\n\n\tconst dispatch = useCallback((action: FormAction) => {\n\t\tif (action.type === 'SET_VALUE' && !startedRef.current) {\n\t\t\tstartedRef.current = true\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.started' })\n\t\t}\n\t\trawDispatch(action)\n\t}, [])\n\n\tconst validateField = useCallback(\n\t\t(name: string, value: unknown) => {\n\t\t\tconst field = fieldsByName.get(name)\n\t\t\tif (!field) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst answers = { ...effectiveValues, [name]: value }\n\t\t\t// Mirror the server: a field whose `validateWhen` is unmet is not validated; clear any stale error.\n\t\t\tif (!evaluateCondition(field.validateWhen, answers)) {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name, errors: [] })\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvoid validateFieldValue({\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tregistry,\n\t\t\t\truleRegistry,\n\t\t\t\tanswers,\n\t\t\t\tlocale,\n\t\t\t\tt: translate,\n\t\t\t}).then(({ errors }) => {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name, errors })\n\t\t\t\tconst [firstError] = errors\n\t\t\t\tif (firstError !== undefined) {\n\t\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\t\t\ttype: 'field.errored',\n\t\t\t\t\t\tfield: name,\n\t\t\t\t\t\tmessage: firstError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[fieldsByName, effectiveValues, registry, ruleRegistry, locale, translate]\n\t)\n\n\tconst visible = visibleFields(form.fields, effectiveValues)\n\n\t/** Visible, answered named fields. Display-only ('none' kind) and nameless (bare) fields never contribute. */\n\tconst answerableFields = (): NamedFormFieldInstance[] =>\n\t\tvisibleFields(form.fields, effectiveValues)\n\t\t\t.filter((field) => registry.get(field.blockType)?.value !== 'none')\n\t\t\t.filter(isNamedField)\n\t\t\t.filter((field) => !isEmpty(effectiveValues[field.name]))\n\n\t/** Answered visible fields as raw submission values, sent to the server on submit. */\n\tconst answeredValues = (): SubmissionValue[] =>\n\t\tanswerableFields().map((field) => ({ field: field.name, value: effectiveValues[field.name] }))\n\n\t/**\n\t * Same fields, formatted via `recall` (option labels, Yes/No, localized dates): recall-fidelity\n\t * values for client-rendered templates, matching what the server gives email-team's body.\n\t */\n\tconst formattedValues = (): SubmissionValue[] =>\n\t\tanswerableFields().map((field) => ({ field: field.name, value: recall(field.name) }))\n\n\t/**\n\t * The recall-resolved success response: a redirect's url, or the response message serialized with\n\t * the active `converters` (so host blocks survive). Shared by the success screen and the value\n\t * handed to `onSuccess`, so both stay identical.\n\t */\n\tconst resolveSuccessResponse = (): FormSuccessResponse | undefined => {\n\t\tconst response = form.response\n\t\tif (response?.type === 'redirect') {\n\t\t\treturn { type: 'redirect', url: response.redirect?.url ?? undefined }\n\t\t}\n\t\tconst message =\n\t\t\tresponse?.type === 'message' || response?.type == null ? response?.message : undefined\n\t\tif (!message) {\n\t\t\treturn undefined\n\t\t}\n\t\treturn {\n\t\t\ttype: 'message',\n\t\t\thtml: serializeBody(message, {\n\t\t\t\tvalues: formattedValues(),\n\t\t\t\tdescriptors: descriptorsFor(answerableFields()),\n\t\t\t\tconverters,\n\t\t\t}),\n\t\t}\n\t}\n\n\t// Steps address fields by key: machine names for named fields, block row ids for bare blocks.\n\t// `step.fields` is membership only; render order follows `form.fields` (the order of `visible`),\n\t// so a step shows its fields in the form's field order, not the flow-builder entry order.\n\tconst stepKeys = flow && currentStepId ? stepFieldNames(flow, currentStepId) : []\n\tconst stepKeySet = new Set(stepKeys)\n\tconst stepVisible: FormFieldInstance[] = visible.filter((field) =>\n\t\tstepKeySet.has(fieldKey(field))\n\t)\n\n\t// Validate the sub-fields of the given repeaters, one pass per visible row, returning composite-key\n\t// errors (`fieldName[rowIndex].subFieldName`). Shared by submit and step navigation so both mirror\n\t// the server's per-row pass and neither lets an invalid required sub-field slip through.\n\tconst validateRepeaterSubFields = async (\n\t\trepeaters: FormFieldInstance[]\n\t): Promise<FieldErrors> => {\n\t\tconst errors: FieldErrors = {}\n\t\tfor (const field of repeaters.filter(\n\t\t\t(f): f is NamedFormFieldInstance => f.blockType === 'repeater' && isNamedField(f)\n\t\t)) {\n\t\t\tconst rows = Array.isArray(effectiveValues[field.name])\n\t\t\t\t? (effectiveValues[field.name] as Array<Record<string, unknown>>)\n\t\t\t\t: []\n\t\t\tconst subFields = (\n\t\t\t\tArray.isArray(field.subFields) ? (field.subFields as FormFieldInstance[]) : []\n\t\t\t).filter(isNamedField)\n\t\t\tfor (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n\t\t\t\tconst row = rows[rowIndex] ?? {}\n\t\t\t\tfor (const subField of subFields) {\n\t\t\t\t\tif (!evaluateCondition(subField.visibleWhen, row)) continue\n\t\t\t\t\tif (!evaluateCondition(subField.validateWhen, row)) continue\n\t\t\t\t\tconst subResult = await validateFieldValue({\n\t\t\t\t\t\tfield: subField,\n\t\t\t\t\t\tvalue: row[subField.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: row,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})\n\t\t\t\t\tconst compositeKey = `${field.name}[${rowIndex}].${subField.name}`\n\t\t\t\t\tif (subResult.errors.length > 0) errors[compositeKey] = subResult.errors\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn errors\n\t}\n\n\tconst goNext = async () => {\n\t\t// Re-entrancy guard: a double-click during async validation must not push the same step onto\n\t\t// history twice (which would need two Back presses to undo).\n\t\tif (!flow || !currentStepId || advancingRef.current) {\n\t\t\treturn\n\t\t}\n\t\tadvancingRef.current = true\n\t\ttry {\n\t\t\tconst results = await Promise.all(\n\t\t\t\tstepVisible\n\t\t\t\t\t.filter((field) => !calcExpressionOf(field))\n\t\t\t\t\t.filter((field) => registry.get(field.blockType)?.value !== 'none')\n\t\t\t\t\t.filter(isNamedField)\n\t\t\t\t\t.filter((field) => evaluateCondition(field.validateWhen, effectiveValues))\n\t\t\t\t\t.map(async (field) => ({\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\t...(await validateFieldValue({\n\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\tvalue: effectiveValues[field.name],\n\t\t\t\t\t\t\tregistry,\n\t\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\t\tanswers: effectiveValues,\n\t\t\t\t\t\t\tlocale,\n\t\t\t\t\t\t\tt: translate,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}))\n\t\t\t)\n\t\t\tlet hasError = false\n\t\t\tfor (const result of results) {\n\t\t\t\trawDispatch({ type: 'TOUCH', name: result.field.name })\n\t\t\t\trawDispatch({\n\t\t\t\t\ttype: 'SET_FIELD_ISSUES',\n\t\t\t\t\tname: result.field.name,\n\t\t\t\t\terrors: result.errors,\n\t\t\t\t})\n\t\t\t\tif (result.errors.length > 0) {\n\t\t\t\t\thasError = true\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Mirror submit: validate the step's repeater sub-fields too, so a required sub-field can't be\n\t\t\t// skipped past on a non-terminal step (errors surface inline via the composite key).\n\t\t\tconst repeaterErrors = await validateRepeaterSubFields(stepVisible)\n\t\t\tfor (const [compositeKey, errs] of Object.entries(repeaterErrors)) {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name: compositeKey, errors: errs })\n\t\t\t\thasError = true\n\t\t\t}\n\t\t\tif (hasError) {\n\t\t\t\t// Mark this step attempted so its fields reveal their errors, then focus the first invalid one.\n\t\t\t\trawDispatch({ type: 'MARK_STEP_ATTEMPTED', stepId: currentStepId })\n\t\t\t\trequestFocus('firstInvalid')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = resolveNextStepId(flow, currentStepId, effectiveValues)\n\t\t\tif (!next) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\ttype: 'step.completed',\n\t\t\t\tstepId: currentStepId,\n\t\t\t})\n\t\t\tsetHistory((prev) => [...prev, currentStepId])\n\t\t\tsetCurrentStepId(next)\n\t\t\trequestFocus('stepStart')\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: next })\n\t\t} finally {\n\t\t\tadvancingRef.current = false\n\t\t}\n\t}\n\n\tconst goBack = () => {\n\t\tconst prev = history[history.length - 1]\n\t\tif (prev === undefined) {\n\t\t\treturn\n\t\t}\n\t\tsetHistory((entries) => entries.slice(0, -1))\n\t\tsetCurrentStepId(prev)\n\t\trequestFocus('stepStart')\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: prev })\n\t}\n\n\t// Jump to an earlier step (from the terminal Submit when an earlier step is invalid), rebuilding the\n\t// Back stack as the flow's linear path up to it so Back still works.\n\tconst navigateToStep = (stepId: string) => {\n\t\tif (!flow || stepId === currentStepId) {\n\t\t\treturn\n\t\t}\n\t\tconst idx = flow.steps.findIndex((flowStep) => flowStep.id === stepId)\n\t\tif (idx < 0) {\n\t\t\treturn\n\t\t}\n\t\tsetHistory(flow.steps.slice(0, idx).map((flowStep) => flowStep.id))\n\t\tsetCurrentStepId(stepId)\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId })\n\t}\n\n\t// Perform a pending focus request after the render it triggered, so it lands on the DOM that reflects\n\t// the new state (a changed step, or freshly revealed errors). Null on mount, so the first render never\n\t// steals focus. currentStepId and focusNonce are intentional re-run triggers: a blocked advance keeps\n\t// the same step, so the nonce forces a fresh run; the body reads only refs, hence the ignore.\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: currentStepId/focusNonce are re-run triggers, not read in the body\n\tuseEffect(() => {\n\t\tconst intent = pendingFocusRef.current\n\t\tif (!intent) {\n\t\t\treturn\n\t\t}\n\t\tpendingFocusRef.current = null\n\t\tif (intent === 'firstInvalid') {\n\t\t\tfocusFirstIn(formRef.current, '[aria-invalid=\"true\"]')\n\t\t\treturn\n\t\t}\n\t\tconst region = formRef.current?.querySelector<HTMLElement>('[data-fb-step-region]')\n\t\tif (region) {\n\t\t\tregion.focus()\n\t\t} else {\n\t\t\tfocusFirstIn(formRef.current, 'input:not([type=\"hidden\"]), select, textarea')\n\t\t}\n\t}, [currentStepId, focusNonce])\n\n\tuseEffect(() => {\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.viewed' })\n\t\tconst mountFlow = flowRef.current\n\t\tif (mountFlow) {\n\t\t\tconst first = firstStepId(mountFlow)\n\t\t\tif (first) {\n\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: first })\n\t\t\t}\n\t\t}\n\t\treturn () => {\n\t\t\tif (!submittedRef.current && !submittingRef.current) {\n\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.abandoned' })\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst handleClose = useCallback(() => {\n\t\tonClose?.()\n\t}, [onClose])\n\n\tconst handleSubmit = async (event: ReactFormEvent<HTMLFormElement>) => {\n\t\tevent.preventDefault()\n\t\t// Re-entrancy guard: claim the in-flight slot before the async validation window so a fast second\n\t\t// activation (double-click, Enter + click) cannot reach the transport and POST the submission twice.\n\t\tif (submittingRef.current) {\n\t\t\treturn\n\t\t}\n\t\tsubmittingRef.current = true\n\t\tconst visible = visibleFields(form.fields, effectiveValues)\n\t\tconst results = await Promise.all(\n\t\t\t// Calc fields carry no rules and have no input; they are always satisfied, so skip validating them.\n\t\t\t// Display-only ('none' kind, e.g. message) and nameless (bare) fields are skipped too, mirroring the server.\n\t\t\t// A field whose `validateWhen` is unmet is skipped too, mirroring the server (no client/server divergence).\n\t\t\tvisible\n\t\t\t\t.filter((field) => !calcExpressionOf(field))\n\t\t\t\t.filter((field) => registry.get(field.blockType)?.value !== 'none')\n\t\t\t\t.filter(isNamedField)\n\t\t\t\t.filter((field) => evaluateCondition(field.validateWhen, effectiveValues))\n\t\t\t\t.map(async (field) => ({\n\t\t\t\t\tfield,\n\t\t\t\t\t...(await validateFieldValue({\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tvalue: effectiveValues[field.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: effectiveValues,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})),\n\t\t\t\t}))\n\t\t)\n\t\tconst errors: FieldErrors = {}\n\t\tfor (const result of results) {\n\t\t\tif (result.errors.length > 0) {\n\t\t\t\terrors[result.field.name] = result.errors\n\t\t\t\tconst [firstError] = result.errors\n\t\t\t\tif (firstError !== undefined) {\n\t\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\t\t\ttype: 'field.errored',\n\t\t\t\t\t\tfield: result.field.name,\n\t\t\t\t\t\tmessage: firstError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate sub-fields within each visible repeater (composite keys `fieldName[rowIndex].subFieldName`),\n\t\t// mirroring the server's per-row pass, so the repeater renderer surfaces them inline.\n\t\tObject.assign(errors, await validateRepeaterSubFields(visible))\n\n\t\tconst hasErrors = Object.keys(errors).length > 0\n\t\t// A terminal submit validates every step, so every step is attempted (its errors may now reveal);\n\t\t// a valid submit clears stale errors without marking anything.\n\t\trawDispatch({ type: 'SET_ALL_ISSUES', errors, steps: hasErrors ? allStepIds : [] })\n\t\tif (hasErrors) {\n\t\t\tsubmittingRef.current = false\n\t\t\t// On a multi-step form, route to the first step that owns an invalid field rather than failing in\n\t\t\t// place on the terminal step, then focus its first invalid field.\n\t\t\tif (flow && currentStepId) {\n\t\t\t\tconst target = firstStepWithError(flow, errors)\n\t\t\t\tif (target) {\n\t\t\t\t\tnavigateToStep(target)\n\t\t\t\t}\n\t\t\t}\n\t\t\trequestFocus('firstInvalid')\n\t\t\treturn\n\t\t}\n\t\trawDispatch({ type: 'SUBMIT_START' })\n\t\tconst values: SubmissionValue[] = answeredValues()\n\t\tif (honeypotName) {\n\t\t\tconst decoy = honeypotRef.current?.value ?? ''\n\t\t\tif (decoy !== '') {\n\t\t\t\t// Submit the decoy under a reserved key, not its cosmetic DOM name, so a real field sharing\n\t\t\t\t// that name is never stripped or mistaken for the honeypot on the server.\n\t\t\t\tvalues.push({ field: HONEYPOT_VALUE_KEY, value: decoy })\n\t\t\t}\n\t\t}\n\t\tif (captchaToken) {\n\t\t\tvalues.push({ field: CAPTCHA_TOKEN_KEY, value: captchaToken })\n\t\t}\n\t\tconst result: SubmitFormResult = onSubmit\n\t\t\t? await onSubmit({ formId: form.id, values })\n\t\t\t: await submitForm({ formId: form.id, values, apiRoute })\n\t\tsubmittingRef.current = false\n\t\tif (result.ok) {\n\t\t\t// A submission happened, so the unmount effect must not emit `form.abandoned`, in either mode.\n\t\t\tsubmittedRef.current = true\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\ttype: 'submission.created',\n\t\t\t\tsubmissionId: result.submissionId,\n\t\t\t})\n\t\t\t// Resolve the response before a reset clears the answers the recall reads from.\n\t\t\tonSuccess?.(result.submissionId, { response: resolveSuccessResponse() })\n\t\t\tif (successBehavior === 'reset') {\n\t\t\t\t// Reset in place: the host handles feedback (e.g. a toast via onSuccess); no success screen.\n\t\t\t\trawDispatch({\n\t\t\t\t\ttype: 'RESET',\n\t\t\t\t\tvalues: { ...seedFieldValues(form.fields), ...(initialValues ?? {}) },\n\t\t\t\t})\n\t\t\t\t// The reducer holds only values/errors; flow position and the lifecycle `started` ref live\n\t\t\t\t// outside it. Reset them too so a multi-step form returns to its first step (not stranded on\n\t\t\t\t// the terminal one) and a fresh fill re-emits `form.started`. `submittedRef` stays set: a\n\t\t\t\t// submission did happen, so the unmount guard must not report the completed form abandoned.\n\t\t\t\tif (flow) {\n\t\t\t\t\tsetCurrentStepId(firstStepId(flow))\n\t\t\t\t\tsetHistory([])\n\t\t\t\t}\n\t\t\t\tstartedRef.current = false\n\t\t\t} else {\n\t\t\t\trawDispatch({ type: 'SUBMIT_SUCCESS' })\n\t\t\t\tif (activePresentation.dismissOnSuccess) {\n\t\t\t\t\thandleClose()\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst redirectUrl =\n\t\t\t\tform.response?.type === 'redirect' ? form.response.redirect?.url : undefined\n\t\t\t// Part of submit handling, not rendering: fires on the custom-`children` path too.\n\t\t\t// Browser-only: no-op during SSR or in non-DOM test environments.\n\t\t\tif (\n\t\t\t\ttypeof redirectUrl === 'string' &&\n\t\t\t\tredirectUrl.length > 0 &&\n\t\t\t\ttypeof window !== 'undefined'\n\t\t\t) {\n\t\t\t\twindow.location.assign(redirectUrl)\n\t\t\t}\n\t\t} else {\n\t\t\tif (result.fieldErrors) {\n\t\t\t\trawDispatch({ type: 'SET_ALL_ISSUES', errors: result.fieldErrors, steps: allStepIds })\n\t\t\t}\n\t\t\tconst message = result.message ?? translate(keys.formSubmitFailed)\n\t\t\trawDispatch({ type: 'SUBMIT_ERROR', message })\n\t\t\tonError?.(message)\n\t\t}\n\t}\n\n\tconst isTerminalStep =\n\t\tflow && currentStepId ? isTerminalStepId(flow, currentStepId, effectiveValues) : true\n\n\t// Enter on a multi-step form: on a non-terminal step, advance like Next (validate, then advance or\n\t// reveal + focus); on the terminal step, fall through to native submit (guarded by `submittingRef`).\n\t// A textarea (Enter = newline), select (confirm), and buttons/submit inputs (activation) are exempt.\n\t// Single-step forms keep native Enter-to-submit. The `<form>` is the plugin's even in children mode,\n\t// so this is the only place a host could get this behavior.\n\tconst handleKeyDown = (event: ReactKeyboardEvent<HTMLFormElement>) => {\n\t\tif (!flow || event.key !== 'Enter') {\n\t\t\treturn\n\t\t}\n\t\tconst target = event.target\n\t\tif (\n\t\t\ttarget instanceof HTMLTextAreaElement ||\n\t\t\ttarget instanceof HTMLSelectElement ||\n\t\t\ttarget instanceof HTMLButtonElement\n\t\t) {\n\t\t\treturn\n\t\t}\n\t\tif (\n\t\t\ttarget instanceof HTMLInputElement &&\n\t\t\t(target.type === 'submit' || target.type === 'button')\n\t\t) {\n\t\t\treturn\n\t\t}\n\t\tif (!isTerminalStep) {\n\t\t\tevent.preventDefault()\n\t\t\tvoid goNext()\n\t\t}\n\t}\n\n\tconst step: FormStepInfo = flow\n\t\t? {\n\t\t\t\tflow,\n\t\t\t\tcurrentStepId,\n\t\t\t\tstepIndex: flow.steps.findIndex((s) => s.id === currentStepId),\n\t\t\t\tstepCount: flow.steps.length,\n\t\t\t\tisFirst: history.length === 0,\n\t\t\t\tisTerminal: isTerminalStep,\n\t\t\t\tgoNext: () => {\n\t\t\t\t\tvoid goNext()\n\t\t\t\t},\n\t\t\t\tgoBack,\n\t\t\t}\n\t\t: {\n\t\t\t\tstepIndex: 0,\n\t\t\t\tstepCount: 1,\n\t\t\t\tisFirst: true,\n\t\t\t\tisTerminal: true,\n\t\t\t\tgoNext: () => {},\n\t\t\t\tgoBack: () => {},\n\t\t\t}\n\n\t// The \"Step X of Y\" announcement (aria-live + the step region's accessible name).\n\tconst stepStatusText = flow\n\t\t? resolveMessage(translate(keys.formStepStatus), {\n\t\t\t\tcurrent: String(step.stepIndex + 1),\n\t\t\t\ttotal: String(step.stepCount),\n\t\t\t})\n\t\t: ''\n\t// Whether the current step has been attempted and still has a revealed error (drives the step-level alert).\n\tconst currentStepHasError =\n\t\tflow != null &&\n\t\tcurrentStepId != null &&\n\t\tstate.attemptedSteps.has(currentStepId) &&\n\t\tObject.entries(state.errors).some(\n\t\t\t([key, errs]) => errs.length > 0 && stepIdOfField(baseFieldKey(key)) === currentStepId\n\t\t)\n\n\tconst renderedFields = (flow ? stepVisible : visible).filter(\n\t\t(field) => field.hidden !== true && field.calcDisplay !== false\n\t)\n\n\tconst contextValue: FormContextValue = {\n\t\tform,\n\t\tstate,\n\t\tdispatch,\n\t\tvalidateField,\n\t\tlocale,\n\t\tstep,\n\t\trendererRegistry,\n\t\tlabels,\n\t\tt: translate,\n\t\teffectiveValues,\n\t\trecall,\n\t\trenderedFields,\n\t\tconverters,\n\t\tstepIdOfField,\n\t}\n\n\tconst PresentationWrapper = activePresentation.Wrapper\n\tconst wrap = (content: ReactNode): ReactNode =>\n\t\tPresentationWrapper ? (\n\t\t\t<PresentationWrapper\n\t\t\t\tpresentation={activePresentation}\n\t\t\t\topen\n\t\t\t\tonClose={handleClose}\n\t\t\t\ttitle={title}\n\t\t\t\tcloseLabel={resolvedCloseLabel}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t</PresentationWrapper>\n\t\t) : (\n\t\t\tcontent\n\t\t)\n\n\tif (children !== undefined) {\n\t\treturn (\n\t\t\t<FormContext.Provider value={contextValue}>\n\t\t\t\t{wrap(\n\t\t\t\t\t<form\n\t\t\t\t\t\tref={formRef}\n\t\t\t\t\t\tclassName={cn('fb-form-root', className)}\n\t\t\t\t\t\tnoValidate\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t\t>\n\t\t\t\t\t\t{honeypotName ? <Honeypot name={honeypotName} inputRef={honeypotRef} /> : null}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</form>\n\t\t\t\t)}\n\t\t\t</FormContext.Provider>\n\t\t)\n\t}\n\n\tif (state.submitted) {\n\t\tconst successResponse = resolveSuccessResponse()\n\t\tconst responseHtml = successResponse?.type === 'message' ? successResponse.html : undefined\n\t\treturn (\n\t\t\t<FormContext.Provider value={contextValue}>\n\t\t\t\t{wrap(\n\t\t\t\t\tresponseHtml ? (\n\t\t\t\t\t\t// Safe to inject: serializeBody HTML-escapes all text (recall values included) and sanitizes link URLs.\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\t\tclassName={cn('fb-form__success', className)}\n\t\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\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\t\tdangerouslySetInnerHTML={{ __html: responseHtml }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\t\tclassName={cn('fb-form__success', className)}\n\t\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{interpolate(resolvedSuccessMessage, recall)}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)\n\t\t\t\t)}\n\t\t\t</FormContext.Provider>\n\t\t)\n\t}\n\n\treturn (\n\t\t<FormContext.Provider value={contextValue}>\n\t\t\t{wrap(\n\t\t\t\t<form\n\t\t\t\t\tref={formRef}\n\t\t\t\t\tclassName={cn('fb-form-root', className)}\n\t\t\t\t\tnoValidate\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t>\n\t\t\t\t\t{honeypotName ? <Honeypot name={honeypotName} inputRef={honeypotRef} /> : null}\n\t\t\t\t\t{header}\n\t\t\t\t\t{flow ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{/* Announces \"Step X of Y\" politely on each step change. A bare aria-live region, not\n\t\t\t\t\t\t\t role=status, so the single status role stays with the form's success outcome. */}\n\t\t\t\t\t\t\t<div aria-live=\"polite\" aria-atomic=\"true\" style={SR_ONLY}>\n\t\t\t\t\t\t\t\t{stepStatusText}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{/* Focus lands here on a step change (the region's start), so keyboard/SR users move with it.\n\t\t\t\t\t\t\t A plain focusable container, not a named group; the aria-live region above does the announcing. */}\n\t\t\t\t\t\t\t<div data-fb-step-region tabIndex={-1} className=\"fb-form__step\">\n\t\t\t\t\t\t\t\t<FormFields layout={layout} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{currentStepHasError ? (\n\t\t\t\t\t\t\t\t<p role=\"alert\" className=\"fb-form__step-error\">\n\t\t\t\t\t\t\t\t\t{translate(keys.formStepInvalid)}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<FormFields layout={layout} />\n\t\t\t\t\t)}\n\t\t\t\t\t{state.submitError ? (\n\t\t\t\t\t\t<p role=\"alert\" className=\"fb-form__submit-error\">\n\t\t\t\t\t\t\t{state.submitError}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<FormControls\n\t\t\t\t\t\tbackButtonClassName={backButtonClassName}\n\t\t\t\t\t\tnextButtonClassName={nextButtonClassName}\n\t\t\t\t\t\tsubmitButtonClassName={submitButtonClassName}\n\t\t\t\t\t\trenderBack={renderBack}\n\t\t\t\t\t\trenderNext={renderNext}\n\t\t\t\t\t\trenderSubmit={renderSubmit}\n\t\t\t\t\t/>\n\t\t\t\t</form>\n\t\t\t)}\n\t\t</FormContext.Provider>\n\t)\n}\n"],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { FormFieldInstance } from "../submissions/types.js";
2
+ import { BodyConverter } from "../actions/body/converters.js";
3
+ import { FormFlow } from "../flow/types.js";
4
+ import { FormDocument } from "../form/types.js";
5
+ import { RendererTranslate } from "./contract.js";
6
+ import { RendererRegistry } from "./registry.js";
7
+ import { RecallResolver } from "../recall/resolver.js";
8
+ import { FormAction, FormState } from "./state.js";
9
+ import { Dispatch } from "react";
10
+
11
+ //#region src/react/FormContext.d.ts
12
+ /** Multi-step navigation state. Defaults to a single terminal step when the form has no flow. */
13
+ type FormStepInfo = {
14
+ flow?: FormFlow;
15
+ currentStepId?: string;
16
+ stepIndex: number;
17
+ stepCount: number;
18
+ isFirst: boolean;
19
+ isTerminal: boolean;
20
+ goNext: () => void;
21
+ goBack: () => void;
22
+ };
23
+ /** Resolved chrome button labels. Precedence per label: the `<Form>` prop, then the form's `buttons` value, then the translated default. */
24
+ type FormControlLabels = {
25
+ prev: string;
26
+ next: string;
27
+ submit: string;
28
+ };
29
+ /**
30
+ * The form controller's context, read via `useFormContext` (or the focused `useField`,
31
+ * `useFormState`, and `useFormStep` hooks). Available anywhere under `<Form>`, including
32
+ * custom `children` layouts and custom field renderers.
33
+ */
34
+ type FormContextValue = {
35
+ /** The document rendered by this `<Form>`. Custom chrome reads host-added `buttons` keys from here. */form: FormDocument; /** Current form state: values, errors, touched, submitting, submitted, submitError. */
36
+ state: FormState;
37
+ /**
38
+ * Dispatch a `FormAction` (see `./state` for the action union). Custom field layouts
39
+ * typically dispatch `TOUCH` or `SET_FIELD_ISSUES`; prefer `useField` for value binding,
40
+ * which wires `SET_VALUE` and validation for you.
41
+ */
42
+ dispatch: Dispatch<FormAction>; /** Validate one field now (client mode) against the supplied value and store its issues. */
43
+ validateField: (name: string, value: unknown) => void; /** The locale passed to `<Form>` (defaults to `'en'`). */
44
+ locale: string; /** Multi-step navigation state and the `goNext`/`goBack` handlers. */
45
+ step: FormStepInfo; /** The active renderer registry, exposed so nested renderers (e.g. repeater) can look up sub-renderers. */
46
+ rendererRegistry: RendererRegistry; /** Resolved prev/next/submit labels used by `<FormControls>` and available to custom chrome. */
47
+ labels: FormControlLabels; /** The active translator: the `<Form>` `t` prop, else the bundled English fallback. */
48
+ t: RendererTranslate; /** Calc-authoritative answers: `state.values` overlaid with derived calc values. Consumers fall back to `state.values` when absent. */
49
+ effectiveValues?: Record<string, unknown>; /** Recall resolver for token interpolation, exposed so `<FormFields>` and custom layouts can format values. */
50
+ recall?: RecallResolver; /** The exact visible field list the default loop renders (post hidden/calc filter). Consumed by `<FormFields>`. */
51
+ renderedFields?: FormFieldInstance[]; /** The `<Form>` `converters` prop, so client rich-text serialization (e.g. the `message` renderer) honors host blocks. */
52
+ converters?: Record<string, BodyConverter>; /** Maps a field key to the id of the step it belongs to (or the default step), for per-step error reveal. */
53
+ stepIdOfField?: (fieldKey: string) => string;
54
+ };
55
+ /** Read the form controller context. Throws if used outside `<Form>`. */
56
+ declare const useFormContext: () => FormContextValue;
57
+ //#endregion
58
+ export { FormContextValue, FormControlLabels, FormStepInfo, useFormContext };
59
+ //# sourceMappingURL=FormContext.d.ts.map
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import { createContext, useContext } from "react";
3
+ //#region src/react/FormContext.ts
4
+ const FormContext = createContext(null);
5
+ /** Read the form controller context. Throws if used outside `<Form>`. */
6
+ const useFormContext = () => {
7
+ const context = useContext(FormContext);
8
+ if (!context) throw new Error("useFormContext must be used within a <Form>");
9
+ return context;
10
+ };
11
+ //#endregion
12
+ export { FormContext, useFormContext };
13
+
14
+ //# sourceMappingURL=FormContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormContext.js","names":[],"sources":["../../src/react/FormContext.ts"],"sourcesContent":["'use client'\n\nimport type { Dispatch } from 'react'\nimport { createContext, useContext } from 'react'\nimport type { BodyConverter } from '../actions/body/converters'\nimport type { FormFlow } from '../flow/types'\nimport type { FormDocument } from '../form/types'\nimport type { RecallResolver } from '../recall/resolver'\nimport type { FormFieldInstance } from '../submissions/types'\nimport type { RendererTranslate } from './contract'\nimport type { RendererRegistry } from './registry'\nimport type { FormAction, FormState } from './state'\n\n/** Multi-step navigation state. Defaults to a single terminal step when the form has no flow. */\nexport type FormStepInfo = {\n\tflow?: FormFlow\n\tcurrentStepId?: string\n\tstepIndex: number\n\tstepCount: number\n\tisFirst: boolean\n\tisTerminal: boolean\n\tgoNext: () => void\n\tgoBack: () => void\n}\n\n/** Resolved chrome button labels. Precedence per label: the `<Form>` prop, then the form's `buttons` value, then the translated default. */\nexport type FormControlLabels = {\n\tprev: string\n\tnext: string\n\tsubmit: string\n}\n\n/**\n * The form controller's context, read via `useFormContext` (or the focused `useField`,\n * `useFormState`, and `useFormStep` hooks). Available anywhere under `<Form>`, including\n * custom `children` layouts and custom field renderers.\n */\nexport type FormContextValue = {\n\t/** The document rendered by this `<Form>`. Custom chrome reads host-added `buttons` keys from here. */\n\tform: FormDocument\n\t/** Current form state: values, errors, touched, submitting, submitted, submitError. */\n\tstate: FormState\n\t/**\n\t * Dispatch a `FormAction` (see `./state` for the action union). Custom field layouts\n\t * typically dispatch `TOUCH` or `SET_FIELD_ISSUES`; prefer `useField` for value binding,\n\t * which wires `SET_VALUE` and validation for you.\n\t */\n\tdispatch: Dispatch<FormAction>\n\t/** Validate one field now (client mode) against the supplied value and store its issues. */\n\tvalidateField: (name: string, value: unknown) => void\n\t/** The locale passed to `<Form>` (defaults to `'en'`). */\n\tlocale: string\n\t/** Multi-step navigation state and the `goNext`/`goBack` handlers. */\n\tstep: FormStepInfo\n\t/** The active renderer registry, exposed so nested renderers (e.g. repeater) can look up sub-renderers. */\n\trendererRegistry: RendererRegistry\n\t/** Resolved prev/next/submit labels used by `<FormControls>` and available to custom chrome. */\n\tlabels: FormControlLabels\n\t/** The active translator: the `<Form>` `t` prop, else the bundled English fallback. */\n\tt: RendererTranslate\n\t/** Calc-authoritative answers: `state.values` overlaid with derived calc values. Consumers fall back to `state.values` when absent. */\n\teffectiveValues?: Record<string, unknown>\n\t/** Recall resolver for token interpolation, exposed so `<FormFields>` and custom layouts can format values. */\n\trecall?: RecallResolver\n\t/** The exact visible field list the default loop renders (post hidden/calc filter). Consumed by `<FormFields>`. */\n\trenderedFields?: FormFieldInstance[]\n\t/** The `<Form>` `converters` prop, so client rich-text serialization (e.g. the `message` renderer) honors host blocks. */\n\tconverters?: Record<string, BodyConverter>\n\t/** Maps a field key to the id of the step it belongs to (or the default step), for per-step error reveal. */\n\tstepIdOfField?: (fieldKey: string) => string\n}\n\nexport const FormContext = createContext<FormContextValue | null>(null)\n\n/** Read the form controller context. Throws if used outside `<Form>`. */\nexport const useFormContext = (): FormContextValue => {\n\tconst context = useContext(FormContext)\n\tif (!context) {\n\t\tthrow new Error('useFormContext must be used within a <Form>')\n\t}\n\treturn context\n}\n"],"mappings":";;;AAwEA,MAAa,cAAc,cAAuC,IAAI;;AAGtE,MAAa,uBAAyC;CACrD,MAAM,UAAU,WAAW,WAAW;CACtC,IAAI,CAAC,SACJ,MAAM,IAAI,MAAM,6CAA6C;CAE9D,OAAO;AACR"}
@@ -0,0 +1,55 @@
1
+ import { ReactNode } from "react";
2
+
3
+ //#region src/react/FormControls.d.ts
4
+ /** Props passed to `renderSubmit`. */
5
+ type SubmitButtonRenderProps = {
6
+ label: string;
7
+ submitting: boolean;
8
+ };
9
+ /** Props passed to `renderNext`. */
10
+ type NextButtonRenderProps = {
11
+ label: string;
12
+ submitting: boolean;
13
+ onClick: () => void;
14
+ };
15
+ /** Props passed to `renderBack`. */
16
+ type BackButtonRenderProps = {
17
+ label: string;
18
+ submitting: boolean;
19
+ onClick: () => void;
20
+ };
21
+ type FormControlsProps = {
22
+ /** Override the context-resolved back label for this instance. */prevLabel?: string; /** Override the context-resolved next label for this instance. */
23
+ nextLabel?: string; /** Override the context-resolved submit label for this instance. */
24
+ submitLabel?: string; /** Additional CSS class on the wrapping `.fb-form__controls` element. */
25
+ className?: string; /** CSS class forwarded to the default "Back" `<button>`. Ignored when `renderBack` is provided. */
26
+ backButtonClassName?: string; /** CSS class forwarded to the default "Next" `<button>`. Ignored when `renderNext` is provided. */
27
+ nextButtonClassName?: string; /** CSS class forwarded to the default submit `<button>`. Ignored when `renderSubmit` is provided. */
28
+ submitButtonClassName?: string; /** Replace the default "Back" button entirely. */
29
+ renderBack?: (props: BackButtonRenderProps) => ReactNode; /** Replace the default "Next" button entirely. */
30
+ renderNext?: (props: NextButtonRenderProps) => ReactNode; /** Replace the default submit button entirely. Receives the resolved label and submitting state. */
31
+ renderSubmit?: (props: SubmitButtonRenderProps) => ReactNode;
32
+ };
33
+ /**
34
+ * The form's navigation chrome: back on non-first steps, next on non-terminal steps, submit on
35
+ * the terminal step (a single-step form is first and terminal, so it gets only submit). Driven
36
+ * entirely by the form context, so it composes into custom `children` layouts exactly like the
37
+ * default field loop's chrome. Labels resolve from context (`<Form>` props, the form's
38
+ * `buttons` labels, translated defaults) unless overridden per button here. Must render
39
+ * inside `<Form>`, within its `<form>` element so the submit button submits.
40
+ */
41
+ declare const FormControls: ({
42
+ prevLabel,
43
+ nextLabel,
44
+ submitLabel,
45
+ className,
46
+ backButtonClassName,
47
+ nextButtonClassName,
48
+ submitButtonClassName,
49
+ renderBack,
50
+ renderNext,
51
+ renderSubmit
52
+ }: FormControlsProps) => import("react/jsx-runtime").JSX.Element;
53
+ //#endregion
54
+ export { BackButtonRenderProps, FormControls, FormControlsProps, NextButtonRenderProps, SubmitButtonRenderProps };
55
+ //# sourceMappingURL=FormControls.d.ts.map
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import { cn } from "./cn.js";
3
+ import { useFormContext } from "./FormContext.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/react/FormControls.tsx
6
+ /**
7
+ * The form's navigation chrome: back on non-first steps, next on non-terminal steps, submit on
8
+ * the terminal step (a single-step form is first and terminal, so it gets only submit). Driven
9
+ * entirely by the form context, so it composes into custom `children` layouts exactly like the
10
+ * default field loop's chrome. Labels resolve from context (`<Form>` props, the form's
11
+ * `buttons` labels, translated defaults) unless overridden per button here. Must render
12
+ * inside `<Form>`, within its `<form>` element so the submit button submits.
13
+ */
14
+ const FormControls = ({ prevLabel, nextLabel, submitLabel, className, backButtonClassName, nextButtonClassName, submitButtonClassName, renderBack, renderNext, renderSubmit }) => {
15
+ const { state, step, labels } = useFormContext();
16
+ const submitting = state.submitting;
17
+ const back = prevLabel ?? labels.prev;
18
+ const next = nextLabel ?? labels.next;
19
+ const submit = submitLabel ?? labels.submit;
20
+ return /* @__PURE__ */ jsxs("div", {
21
+ className: cn("fb-form__controls", className),
22
+ children: [!step.isFirst ? renderBack ? renderBack({
23
+ label: back,
24
+ submitting,
25
+ onClick: step.goBack
26
+ }) : /* @__PURE__ */ jsx("button", {
27
+ type: "button",
28
+ className: cn("fb-form__back", backButtonClassName),
29
+ onClick: step.goBack,
30
+ disabled: submitting,
31
+ children: back
32
+ }) : null, step.isTerminal ? renderSubmit ? renderSubmit({
33
+ label: submit,
34
+ submitting
35
+ }) : /* @__PURE__ */ jsx("button", {
36
+ type: "submit",
37
+ className: cn("fb-form__submit", submitButtonClassName),
38
+ disabled: submitting,
39
+ children: submit
40
+ }) : renderNext ? renderNext({
41
+ label: next,
42
+ submitting,
43
+ onClick: step.goNext
44
+ }) : /* @__PURE__ */ jsx("button", {
45
+ type: "button",
46
+ className: cn("fb-form__next", nextButtonClassName),
47
+ onClick: step.goNext,
48
+ disabled: submitting,
49
+ children: next
50
+ })]
51
+ });
52
+ };
53
+ //#endregion
54
+ export { FormControls };
55
+
56
+ //# sourceMappingURL=FormControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormControls.js","names":[],"sources":["../../src/react/FormControls.tsx"],"sourcesContent":["'use client'\n\nimport type { ReactNode } from 'react'\nimport { cn } from './cn'\nimport { useFormContext } from './FormContext'\n\n/** Props passed to `renderSubmit`. */\nexport type SubmitButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n}\n\n/** Props passed to `renderNext`. */\nexport type NextButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n\tonClick: () => void\n}\n\n/** Props passed to `renderBack`. */\nexport type BackButtonRenderProps = {\n\tlabel: string\n\tsubmitting: boolean\n\tonClick: () => void\n}\n\nexport type FormControlsProps = {\n\t/** Override the context-resolved back label for this instance. */\n\tprevLabel?: string\n\t/** Override the context-resolved next label for this instance. */\n\tnextLabel?: string\n\t/** Override the context-resolved submit label for this instance. */\n\tsubmitLabel?: string\n\t/** Additional CSS class on the wrapping `.fb-form__controls` element. */\n\tclassName?: string\n\t/** CSS class forwarded to the default \"Back\" `<button>`. Ignored when `renderBack` is provided. */\n\tbackButtonClassName?: string\n\t/** CSS class forwarded to the default \"Next\" `<button>`. Ignored when `renderNext` is provided. */\n\tnextButtonClassName?: string\n\t/** CSS class forwarded to the default submit `<button>`. Ignored when `renderSubmit` is provided. */\n\tsubmitButtonClassName?: string\n\t/** Replace the default \"Back\" button entirely. */\n\trenderBack?: (props: BackButtonRenderProps) => ReactNode\n\t/** Replace the default \"Next\" button entirely. */\n\trenderNext?: (props: NextButtonRenderProps) => ReactNode\n\t/** Replace the default submit button entirely. Receives the resolved label and submitting state. */\n\trenderSubmit?: (props: SubmitButtonRenderProps) => ReactNode\n}\n\n/**\n * The form's navigation chrome: back on non-first steps, next on non-terminal steps, submit on\n * the terminal step (a single-step form is first and terminal, so it gets only submit). Driven\n * entirely by the form context, so it composes into custom `children` layouts exactly like the\n * default field loop's chrome. Labels resolve from context (`<Form>` props, the form's\n * `buttons` labels, translated defaults) unless overridden per button here. Must render\n * inside `<Form>`, within its `<form>` element so the submit button submits.\n */\nexport const FormControls = ({\n\tprevLabel,\n\tnextLabel,\n\tsubmitLabel,\n\tclassName,\n\tbackButtonClassName,\n\tnextButtonClassName,\n\tsubmitButtonClassName,\n\trenderBack,\n\trenderNext,\n\trenderSubmit,\n}: FormControlsProps) => {\n\tconst { state, step, labels } = useFormContext()\n\tconst submitting = state.submitting\n\tconst back = prevLabel ?? labels.prev\n\tconst next = nextLabel ?? labels.next\n\tconst submit = submitLabel ?? labels.submit\n\treturn (\n\t\t<div className={cn('fb-form__controls', className)}>\n\t\t\t{!step.isFirst ? (\n\t\t\t\trenderBack ? (\n\t\t\t\t\trenderBack({ label: back, submitting, onClick: step.goBack })\n\t\t\t\t) : (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName={cn('fb-form__back', backButtonClassName)}\n\t\t\t\t\t\tonClick={step.goBack}\n\t\t\t\t\t\tdisabled={submitting}\n\t\t\t\t\t>\n\t\t\t\t\t\t{back}\n\t\t\t\t\t</button>\n\t\t\t\t)\n\t\t\t) : null}\n\t\t\t{step.isTerminal ? (\n\t\t\t\trenderSubmit ? (\n\t\t\t\t\trenderSubmit({ label: submit, submitting })\n\t\t\t\t) : (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tclassName={cn('fb-form__submit', submitButtonClassName)}\n\t\t\t\t\t\tdisabled={submitting}\n\t\t\t\t\t>\n\t\t\t\t\t\t{submit}\n\t\t\t\t\t</button>\n\t\t\t\t)\n\t\t\t) : renderNext ? (\n\t\t\t\trenderNext({ label: next, submitting, onClick: step.goNext })\n\t\t\t) : (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={cn('fb-form__next', nextButtonClassName)}\n\t\t\t\t\tonClick={step.goNext}\n\t\t\t\t\tdisabled={submitting}\n\t\t\t\t>\n\t\t\t\t\t{next}\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n"],"mappings":";;;;;;;;;;;;;AAyDA,MAAa,gBAAgB,EAC5B,WACA,WACA,aACA,WACA,qBACA,qBACA,uBACA,YACA,YACA,mBACwB;CACxB,MAAM,EAAE,OAAO,MAAM,WAAW,eAAe;CAC/C,MAAM,aAAa,MAAM;CACzB,MAAM,OAAO,aAAa,OAAO;CACjC,MAAM,OAAO,aAAa,OAAO;CACjC,MAAM,SAAS,eAAe,OAAO;CACrC,OACC,qBAAC,OAAD;EAAK,WAAW,GAAG,qBAAqB,SAAS;YAAjD,CACE,CAAC,KAAK,UACN,aACC,WAAW;GAAE,OAAO;GAAM;GAAY,SAAS,KAAK;EAAO,CAAC,IAE5D,oBAAC,UAAD;GACC,MAAK;GACL,WAAW,GAAG,iBAAiB,mBAAmB;GAClD,SAAS,KAAK;GACd,UAAU;aAET;EACM,CAAA,IAEN,MACH,KAAK,aACL,eACC,aAAa;GAAE,OAAO;GAAQ;EAAW,CAAC,IAE1C,oBAAC,UAAD;GACC,MAAK;GACL,WAAW,GAAG,mBAAmB,qBAAqB;GACtD,UAAU;aAET;EACM,CAAA,IAEN,aACH,WAAW;GAAE,OAAO;GAAM;GAAY,SAAS,KAAK;EAAO,CAAC,IAE5D,oBAAC,UAAD;GACC,MAAK;GACL,WAAW,GAAG,iBAAiB,mBAAmB;GAClD,SAAS,KAAK;GACd,UAAU;aAET;EACM,CAAA,CAEL;;AAEP"}
@@ -0,0 +1,18 @@
1
+ //#region src/react/FormFields.d.ts
2
+ type FormFieldsProps = {
3
+ /** When false, render the fields in document order with no grid class. Defaults to the grid. */layout?: boolean; /** Extra class names merged onto the layout container. */
4
+ className?: string;
5
+ };
6
+ /**
7
+ * The standard field loop, driven entirely by `useFormContext()`. Rendered by `<Form>` in default
8
+ * mode and exported so a custom `children` layout can drop the same loop in without reimplementing
9
+ * visibility, calc, recall, and step filtering. In `children` mode the host owns the success-state
10
+ * swap (via `useFormState`); this component only ever renders the fields.
11
+ */
12
+ declare const FormFields: ({
13
+ layout,
14
+ className
15
+ }: FormFieldsProps) => import("react/jsx-runtime").JSX.Element;
16
+ //#endregion
17
+ export { FormFields, FormFieldsProps };
18
+ //# sourceMappingURL=FormFields.d.ts.map
@@ -0,0 +1,114 @@
1
+ "use client";
2
+ import { fieldKey, isNamedField } from "../fields/fieldKey.js";
3
+ import { calcExpressionOf } from "../calc/computeCalcFields.js";
4
+ import { useFormContext } from "./FormContext.js";
5
+ import { FormLayout, widthProps } from "./FormLayout.js";
6
+ import { applyRecall } from "./recall.js";
7
+ import { useField } from "./useField.js";
8
+ import { jsx } from "react/jsx-runtime";
9
+ import { createElement, useId } from "react";
10
+ //#region src/react/FormFields.tsx
11
+ const FIELD_WIDTHS = new Set([
12
+ "full",
13
+ "half",
14
+ "third",
15
+ "twoThirds"
16
+ ]);
17
+ /** Fallback when no recall resolver is on the context (a hand-built provider); returns the token name unchanged. */
18
+ const identityRecall = (name) => name;
19
+ const FieldHost = ({ field, renderer, locale, t }) => {
20
+ const id = useId();
21
+ const { value, errors, setValue, onBlur } = useField(field.name);
22
+ return createElement(renderer, {
23
+ field,
24
+ id,
25
+ name: field.name,
26
+ value,
27
+ onChange: setValue,
28
+ onBlur,
29
+ errors,
30
+ required: Boolean(field.required),
31
+ locale,
32
+ t
33
+ });
34
+ };
35
+ /** Hosts a derived (calc) field: read-only, value supplied from `effectiveValues`, never bound via `useField`. */
36
+ const CalcFieldHost = ({ field, renderer, value, locale, t }) => {
37
+ return createElement(renderer, {
38
+ field,
39
+ id: useId(),
40
+ name: field.name,
41
+ value,
42
+ onChange: () => {},
43
+ onBlur: () => {},
44
+ errors: [],
45
+ required: false,
46
+ disabled: true,
47
+ locale,
48
+ t
49
+ });
50
+ };
51
+ /**
52
+ * Hosts a nameless (bare) display block, e.g. a message: no `useField` binding at all. The
53
+ * renderer reads only the instance and the form context; `name` is the row key for consistency.
54
+ */
55
+ const StaticFieldHost = ({ field, renderer, locale, t }) => {
56
+ return createElement(renderer, {
57
+ field,
58
+ id: useId(),
59
+ name: fieldKey(field),
60
+ value: void 0,
61
+ onChange: () => {},
62
+ onBlur: () => {},
63
+ errors: [],
64
+ required: false,
65
+ locale,
66
+ t
67
+ });
68
+ };
69
+ /**
70
+ * The standard field loop, driven entirely by `useFormContext()`. Rendered by `<Form>` in default
71
+ * mode and exported so a custom `children` layout can drop the same loop in without reimplementing
72
+ * visibility, calc, recall, and step filtering. In `children` mode the host owns the success-state
73
+ * swap (via `useFormState`); this component only ever renders the fields.
74
+ */
75
+ const FormFields = ({ layout, className }) => {
76
+ const ctx = useFormContext();
77
+ const { rendererRegistry, effectiveValues, locale, t } = ctx;
78
+ const recall = ctx.recall ?? identityRecall;
79
+ const renderedFields = ctx.renderedFields ?? [];
80
+ return /* @__PURE__ */ jsx(FormLayout, {
81
+ enabled: layout !== false,
82
+ className,
83
+ children: renderedFields.map((field) => {
84
+ const renderer = rendererRegistry.get(field.blockType);
85
+ if (!renderer) return null;
86
+ const width = typeof field.width === "string" && FIELD_WIDTHS.has(field.width) ? field.width : void 0;
87
+ const recalledField = applyRecall(field, recall);
88
+ return /* @__PURE__ */ jsx("div", {
89
+ ...widthProps(width),
90
+ children: !isNamedField(recalledField) ? /* @__PURE__ */ jsx(StaticFieldHost, {
91
+ field: recalledField,
92
+ renderer,
93
+ locale,
94
+ t
95
+ }) : calcExpressionOf(recalledField) ? /* @__PURE__ */ jsx(CalcFieldHost, {
96
+ field: recalledField,
97
+ renderer,
98
+ value: effectiveValues?.[recalledField.name],
99
+ locale,
100
+ t
101
+ }) : /* @__PURE__ */ jsx(FieldHost, {
102
+ field: recalledField,
103
+ renderer,
104
+ locale,
105
+ t
106
+ })
107
+ }, fieldKey(field));
108
+ })
109
+ });
110
+ };
111
+ //#endregion
112
+ export { FormFields };
113
+
114
+ //# sourceMappingURL=FormFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormFields.js","names":[],"sources":["../../src/react/FormFields.tsx"],"sourcesContent":["'use client'\n\nimport { createElement, useId } from 'react'\nimport { calcExpressionOf } from '../calc/computeCalcFields'\nimport { fieldKey, isNamedField, type NamedFormFieldInstance } from '../fields/fieldKey'\nimport type { RecallResolver } from '../recall/resolver'\nimport type { FormFieldInstance } from '../submissions/types'\nimport type { FieldRenderer, RendererTranslate } from './contract'\nimport { useFormContext } from './FormContext'\nimport { type FieldWidth, FormLayout, widthProps } from './FormLayout'\nimport { applyRecall } from './recall'\nimport { useField } from './useField'\n\nconst FIELD_WIDTHS = new Set<string>(['full', 'half', 'third', 'twoThirds'])\n\n/** Fallback when no recall resolver is on the context (a hand-built provider); returns the token name unchanged. */\nconst identityRecall: RecallResolver = (name) => name\n\ntype FieldHostProps = {\n\tfield: NamedFormFieldInstance\n\trenderer: FieldRenderer\n\tlocale: string\n\tt: RendererTranslate\n}\n\nconst FieldHost = ({ field, renderer, locale, t }: FieldHostProps) => {\n\tconst id = useId()\n\tconst { value, errors, setValue, onBlur } = useField(field.name)\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: field.name,\n\t\tvalue,\n\t\tonChange: setValue,\n\t\tonBlur,\n\t\terrors,\n\t\trequired: Boolean(field.required),\n\t\tlocale,\n\t\tt,\n\t})\n}\n\ntype CalcFieldHostProps = FieldHostProps & { value: unknown }\n\n/** Hosts a derived (calc) field: read-only, value supplied from `effectiveValues`, never bound via `useField`. */\nconst CalcFieldHost = ({ field, renderer, value, locale, t }: CalcFieldHostProps) => {\n\tconst id = useId()\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: field.name,\n\t\tvalue,\n\t\tonChange: () => {},\n\t\tonBlur: () => {},\n\t\terrors: [],\n\t\trequired: false,\n\t\tdisabled: true,\n\t\tlocale,\n\t\tt,\n\t})\n}\n\ntype StaticFieldHostProps = Omit<FieldHostProps, 'field'> & { field: FormFieldInstance }\n\n/**\n * Hosts a nameless (bare) display block, e.g. a message: no `useField` binding at all. The\n * renderer reads only the instance and the form context; `name` is the row key for consistency.\n */\nconst StaticFieldHost = ({ field, renderer, locale, t }: StaticFieldHostProps) => {\n\tconst id = useId()\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: fieldKey(field),\n\t\tvalue: undefined,\n\t\tonChange: () => {},\n\t\tonBlur: () => {},\n\t\terrors: [],\n\t\trequired: false,\n\t\tlocale,\n\t\tt,\n\t})\n}\n\nexport type FormFieldsProps = {\n\t/** When false, render the fields in document order with no grid class. Defaults to the grid. */\n\tlayout?: boolean\n\t/** Extra class names merged onto the layout container. */\n\tclassName?: string\n}\n\n/**\n * The standard field loop, driven entirely by `useFormContext()`. Rendered by `<Form>` in default\n * mode and exported so a custom `children` layout can drop the same loop in without reimplementing\n * visibility, calc, recall, and step filtering. In `children` mode the host owns the success-state\n * swap (via `useFormState`); this component only ever renders the fields.\n */\nexport const FormFields = ({ layout, className }: FormFieldsProps) => {\n\tconst ctx = useFormContext()\n\tconst { rendererRegistry, effectiveValues, locale, t } = ctx\n\tconst recall = ctx.recall ?? identityRecall\n\tconst renderedFields = ctx.renderedFields ?? []\n\treturn (\n\t\t<FormLayout enabled={layout !== false} className={className}>\n\t\t\t{renderedFields.map((field) => {\n\t\t\t\tconst renderer = rendererRegistry.get(field.blockType)\n\t\t\t\tif (!renderer) {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t\tconst width: FieldWidth | undefined =\n\t\t\t\t\ttypeof field.width === 'string' && FIELD_WIDTHS.has(field.width)\n\t\t\t\t\t\t? (field.width as FieldWidth)\n\t\t\t\t\t\t: undefined\n\t\t\t\tconst recalledField = applyRecall(field, recall)\n\t\t\t\treturn (\n\t\t\t\t\t<div key={fieldKey(field)} {...widthProps(width)}>\n\t\t\t\t\t\t{!isNamedField(recalledField) ? (\n\t\t\t\t\t\t\t<StaticFieldHost field={recalledField} renderer={renderer} locale={locale} t={t} />\n\t\t\t\t\t\t) : calcExpressionOf(recalledField) ? (\n\t\t\t\t\t\t\t<CalcFieldHost\n\t\t\t\t\t\t\t\tfield={recalledField}\n\t\t\t\t\t\t\t\trenderer={renderer}\n\t\t\t\t\t\t\t\tvalue={effectiveValues?.[recalledField.name]}\n\t\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\t\tt={t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<FieldHost field={recalledField} renderer={renderer} locale={locale} t={t} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)\n\t\t\t})}\n\t\t</FormLayout>\n\t)\n}\n"],"mappings":";;;;;;;;;;AAaA,MAAM,eAAe,IAAI,IAAY;CAAC;CAAQ;CAAQ;CAAS;AAAW,CAAC;;AAG3E,MAAM,kBAAkC,SAAS;AASjD,MAAM,aAAa,EAAE,OAAO,UAAU,QAAQ,QAAwB;CACrE,MAAM,KAAK,MAAM;CACjB,MAAM,EAAE,OAAO,QAAQ,UAAU,WAAW,SAAS,MAAM,IAAI;CAC/D,OAAO,cAAc,UAAU;EAC9B;EACA;EACA,MAAM,MAAM;EACZ;EACA,UAAU;EACV;EACA;EACA,UAAU,QAAQ,MAAM,QAAQ;EAChC;EACA;CACD,CAAC;AACF;;AAKA,MAAM,iBAAiB,EAAE,OAAO,UAAU,OAAO,QAAQ,QAA4B;CAEpF,OAAO,cAAc,UAAU;EAC9B;EACA,IAHU,MAGT;EACD,MAAM,MAAM;EACZ;EACA,gBAAgB,CAAC;EACjB,cAAc,CAAC;EACf,QAAQ,CAAC;EACT,UAAU;EACV,UAAU;EACV;EACA;CACD,CAAC;AACF;;;;;AAQA,MAAM,mBAAmB,EAAE,OAAO,UAAU,QAAQ,QAA8B;CAEjF,OAAO,cAAc,UAAU;EAC9B;EACA,IAHU,MAGT;EACD,MAAM,SAAS,KAAK;EACpB,OAAO,KAAA;EACP,gBAAgB,CAAC;EACjB,cAAc,CAAC;EACf,QAAQ,CAAC;EACT,UAAU;EACV;EACA;CACD,CAAC;AACF;;;;;;;AAeA,MAAa,cAAc,EAAE,QAAQ,gBAAiC;CACrE,MAAM,MAAM,eAAe;CAC3B,MAAM,EAAE,kBAAkB,iBAAiB,QAAQ,MAAM;CACzD,MAAM,SAAS,IAAI,UAAU;CAC7B,MAAM,iBAAiB,IAAI,kBAAkB,CAAC;CAC9C,OACC,oBAAC,YAAD;EAAY,SAAS,WAAW;EAAkB;YAChD,eAAe,KAAK,UAAU;GAC9B,MAAM,WAAW,iBAAiB,IAAI,MAAM,SAAS;GACrD,IAAI,CAAC,UACJ,OAAO;GAER,MAAM,QACL,OAAO,MAAM,UAAU,YAAY,aAAa,IAAI,MAAM,KAAK,IAC3D,MAAM,QACP,KAAA;GACJ,MAAM,gBAAgB,YAAY,OAAO,MAAM;GAC/C,OACC,oBAAC,OAAD;IAA2B,GAAI,WAAW,KAAK;cAC7C,CAAC,aAAa,aAAa,IAC3B,oBAAC,iBAAD;KAAiB,OAAO;KAAyB;KAAkB;KAAW;IAAI,CAAA,IAC/E,iBAAiB,aAAa,IACjC,oBAAC,eAAD;KACC,OAAO;KACG;KACV,OAAO,kBAAkB,cAAc;KAC/B;KACL;IACH,CAAA,IAED,oBAAC,WAAD;KAAW,OAAO;KAAyB;KAAkB;KAAW;IAAI,CAAA;GAEzE,GAdK,SAAS,KAAK,CAcnB;EAEP,CAAC;CACU,CAAA;AAEd"}
@@ -0,0 +1,22 @@
1
+ import { ReactNode } from "react";
2
+
3
+ //#region src/react/FormLayout.d.ts
4
+ type FieldWidth = 'full' | 'half' | 'third' | 'twoThirds';
5
+ type FormLayoutProps = {
6
+ children: ReactNode; /** When false, render a plain container with no grid class (document-order layout). */
7
+ enabled?: boolean; /** Extra class names merged onto the layout container. */
8
+ className?: string;
9
+ };
10
+ /** Establishes the layout container. With the stylesheet imported, children with `data-width` flow into a grid. */
11
+ declare const FormLayout: ({
12
+ children,
13
+ enabled,
14
+ className
15
+ }: FormLayoutProps) => import("react/jsx-runtime").JSX.Element;
16
+ /** Props to spread onto a field wrapper to declare its grid width. */
17
+ declare const widthProps: (width: FieldWidth | undefined) => {
18
+ 'data-width': FieldWidth;
19
+ };
20
+ //#endregion
21
+ export { FieldWidth, FormLayout, FormLayoutProps, widthProps };
22
+ //# sourceMappingURL=FormLayout.d.ts.map
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { cn } from "./cn.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/react/FormLayout.tsx
5
+ /** Establishes the layout container. With the stylesheet imported, children with `data-width` flow into a grid. */
6
+ const FormLayout = ({ children, enabled = true, className }) => /* @__PURE__ */ jsx("div", {
7
+ className: cn(enabled ? "fb-form fb-form--grid" : "fb-form", className),
8
+ children
9
+ });
10
+ /** Props to spread onto a field wrapper to declare its grid width. */
11
+ const widthProps = (width) => ({ "data-width": width ?? "full" });
12
+ //#endregion
13
+ export { FormLayout, widthProps };
14
+
15
+ //# sourceMappingURL=FormLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormLayout.js","names":[],"sources":["../../src/react/FormLayout.tsx"],"sourcesContent":["'use client'\n\nimport type { ReactNode } from 'react'\nimport { cn } from './cn'\n\nexport type FieldWidth = 'full' | 'half' | 'third' | 'twoThirds'\n\nexport type FormLayoutProps = {\n\tchildren: ReactNode\n\t/** When false, render a plain container with no grid class (document-order layout). */\n\tenabled?: boolean\n\t/** Extra class names merged onto the layout container. */\n\tclassName?: string\n}\n\n/** Establishes the layout container. With the stylesheet imported, children with `data-width` flow into a grid. */\nexport const FormLayout = ({ children, enabled = true, className }: FormLayoutProps) => (\n\t<div className={cn(enabled ? 'fb-form fb-form--grid' : 'fb-form', className)}>{children}</div>\n)\n\n/** Props to spread onto a field wrapper to declare its grid width. */\nexport const widthProps = (width: FieldWidth | undefined) => ({ 'data-width': width ?? 'full' })\n"],"mappings":";;;;;AAgBA,MAAa,cAAc,EAAE,UAAU,UAAU,MAAM,gBACtD,oBAAC,OAAD;CAAK,WAAW,GAAG,UAAU,0BAA0B,WAAW,SAAS;CAAI;AAAc,CAAA;;AAI9F,MAAa,cAAc,WAAmC,EAAE,cAAc,SAAS,OAAO"}
@@ -0,0 +1,28 @@
1
+ import { FieldAggregation } from "../aggregation/types.js";
2
+ import { RendererTranslate } from "./contract.js";
3
+ import { ReactNode } from "react";
4
+
5
+ //#region src/react/FormResults.d.ts
6
+ type FormResultsProps = {
7
+ /** One field aggregation or several (a survey summary), resolved server-side and passed in. */results: FieldAggregation | FieldAggregation[]; /** Localized translator for built-in copy. Defaults to identity (returns the key). */
8
+ t?: RendererTranslate;
9
+ locale?: string; /** Show the raw count beside each option. Default true. */
10
+ showCounts?: boolean; /** The recorded outcome's stable option values; every matching bucket is highlighted as a winner (a tie highlights more than one). */
11
+ winningValues?: string[];
12
+ };
13
+ /**
14
+ * Presentational results view for polls and survey summaries: per-option bars with percentages. Headless,
15
+ * data resolved server-side via `aggregateFieldResponses`/`aggregateFormResponses` and passed in (it never
16
+ * fetches). The option label, count, and percentage are real text (the accessible content); the bar fill
17
+ * is `aria-hidden` visual sugar sized by inline width. With `winningValues`, every matching bucket gets
18
+ * the winner class and a translated badge (real text, so the outcome is accessible); a tie highlights more than one.
19
+ */
20
+ declare const FormResults: ({
21
+ results,
22
+ t,
23
+ showCounts,
24
+ winningValues
25
+ }: FormResultsProps) => ReactNode;
26
+ //#endregion
27
+ export { FormResults, FormResultsProps };
28
+ //# sourceMappingURL=FormResults.d.ts.map