@10x-media/form-builder 0.1.0-beta.1 → 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 (546) hide show
  1. package/CHANGELOG.md +293 -0
  2. package/README.md +6 -4
  3. package/dist/actions/body/converters.d.ts +20 -0
  4. package/dist/actions/body/converters.js +57 -0
  5. package/dist/actions/body/converters.js.map +1 -0
  6. package/dist/actions/body/escapeHtml.d.ts +6 -0
  7. package/dist/actions/body/escapeHtml.js +14 -0
  8. package/dist/actions/body/escapeHtml.js.map +1 -0
  9. package/dist/actions/body/serializeBody.d.ts +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 +12 -9
  21. package/dist/actions/buildActionBlocks.js.map +1 -1
  22. package/dist/actions/builtin/confirmation.js +46 -43
  23. package/dist/actions/builtin/confirmation.js.map +1 -1
  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 +14 -38
  28. package/dist/actions/builtin/emailTeam.js.map +1 -1
  29. package/dist/actions/builtin/index.d.ts +16 -1
  30. package/dist/actions/builtin/index.js +21 -7
  31. package/dist/actions/builtin/index.js.map +1 -1
  32. package/dist/actions/builtin/signedWebhook.js +6 -2
  33. package/dist/actions/builtin/signedWebhook.js.map +1 -1
  34. package/dist/actions/defineAction.d.ts +5 -4
  35. package/dist/actions/defineAction.js.map +1 -1
  36. package/dist/actions/dispatch.js +2 -1
  37. package/dist/actions/dispatch.js.map +1 -1
  38. package/dist/actions/emailRecipients.d.ts +12 -0
  39. package/dist/actions/emailRecipients.js +116 -0
  40. package/dist/actions/emailRecipients.js.map +1 -0
  41. package/dist/actions/fromAddresses.d.ts +21 -0
  42. package/dist/actions/fromAddresses.js +74 -0
  43. package/dist/actions/fromAddresses.js.map +1 -0
  44. package/dist/actions/registry.d.ts +2 -1
  45. package/dist/actions/registry.js +2 -6
  46. package/dist/actions/registry.js.map +1 -1
  47. package/dist/actions/runActions.js +10 -1
  48. package/dist/actions/runActions.js.map +1 -1
  49. package/dist/actions/task.js +20 -15
  50. package/dist/actions/task.js.map +1 -1
  51. package/dist/aggregation/aggregateResponses.d.ts +9 -0
  52. package/dist/aggregation/aggregateResponses.js +8 -14
  53. package/dist/aggregation/aggregateResponses.js.map +1 -1
  54. package/dist/aggregation/resolveResultsRequest.d.ts +35 -6
  55. package/dist/aggregation/resolveResultsRequest.js +68 -11
  56. package/dist/aggregation/resolveResultsRequest.js.map +1 -1
  57. package/dist/calc/computeCalcFields.js +2 -1
  58. package/dist/calc/computeCalcFields.js.map +1 -1
  59. package/dist/calc/evaluate.js +1 -2
  60. package/dist/calc/evaluate.js.map +1 -1
  61. package/dist/calc/normalizeCalc.js +6 -19
  62. package/dist/calc/normalizeCalc.js.map +1 -1
  63. package/dist/calc/types.d.ts +8 -2
  64. package/dist/calc/types.js +22 -0
  65. package/dist/calc/types.js.map +1 -0
  66. package/dist/client/ByteSizeField.d.ts +29 -0
  67. package/dist/client/ByteSizeField.js +58 -0
  68. package/dist/client/ByteSizeField.js.map +1 -0
  69. package/dist/client/ClosePollButton.d.ts +15 -0
  70. package/dist/client/ClosePollButton.js +80 -0
  71. package/dist/client/ClosePollButton.js.map +1 -0
  72. package/dist/client/CondensedArray.d.ts +15 -0
  73. package/dist/client/CondensedArray.js +97 -0
  74. package/dist/client/CondensedArray.js.map +1 -0
  75. package/dist/client/ConditionBuilder.js +2 -1
  76. package/dist/client/ConditionBuilder.js.map +1 -1
  77. package/dist/client/ConsentBlockLabel.d.ts +15 -0
  78. package/dist/client/ConsentBlockLabel.js +71 -0
  79. package/dist/client/ConsentBlockLabel.js.map +1 -0
  80. package/dist/client/ConsentSourceRowLabel.d.ts +9 -0
  81. package/dist/client/ConsentSourceRowLabel.js +21 -0
  82. package/dist/client/ConsentSourceRowLabel.js.map +1 -0
  83. package/dist/client/EndpointOptionsSelect.d.ts +46 -0
  84. package/dist/client/EndpointOptionsSelect.js +106 -0
  85. package/dist/client/EndpointOptionsSelect.js.map +1 -0
  86. package/dist/client/FieldBlockLabel.d.ts +18 -0
  87. package/dist/client/FieldBlockLabel.js +34 -0
  88. package/dist/client/FieldBlockLabel.js.map +1 -0
  89. package/dist/client/FieldNameSelect.d.ts +37 -0
  90. package/dist/client/FieldNameSelect.js +72 -0
  91. package/dist/client/FieldNameSelect.js.map +1 -0
  92. package/dist/client/FlowBuilder.d.ts +2 -2
  93. package/dist/client/FlowBuilder.js +137 -88
  94. package/dist/client/FlowBuilder.js.map +1 -1
  95. package/dist/client/FormConditionField.js +1 -4
  96. package/dist/client/FormConditionField.js.map +1 -1
  97. package/dist/client/RecipientsSelect.d.ts +31 -0
  98. package/dist/client/RecipientsSelect.js +174 -0
  99. package/dist/client/RecipientsSelect.js.map +1 -0
  100. package/dist/client/RuleDescription.d.ts +21 -0
  101. package/dist/client/RuleDescription.js +19 -0
  102. package/dist/client/RuleDescription.js.map +1 -0
  103. package/dist/client/admin.css +275 -0
  104. package/dist/client/endpointOptions.js +29 -0
  105. package/dist/client/endpointOptions.js.map +1 -0
  106. package/dist/client/flowAuthoring.js +142 -0
  107. package/dist/client/flowAuthoring.js.map +1 -0
  108. package/dist/client/synthesizeClientField.js +21 -10
  109. package/dist/client/synthesizeClientField.js.map +1 -1
  110. package/dist/client/toStaticLabel.js +13 -0
  111. package/dist/client/toStaticLabel.js.map +1 -0
  112. package/dist/collections/buttonFields.d.ts +34 -0
  113. package/dist/collections/buttonFields.js +35 -0
  114. package/dist/collections/buttonFields.js.map +1 -0
  115. package/dist/collections/cells/FieldCountCell.d.ts +15 -0
  116. package/dist/collections/cells/FieldCountCell.js +18 -0
  117. package/dist/collections/cells/FieldCountCell.js.map +1 -0
  118. package/dist/collections/cells/FlowStepsCell.d.ts +14 -0
  119. package/dist/collections/cells/FlowStepsCell.js +17 -0
  120. package/dist/collections/cells/FlowStepsCell.js.map +1 -0
  121. package/dist/collections/formSubmissions.js +108 -42
  122. package/dist/collections/formSubmissions.js.map +1 -1
  123. package/dist/collections/forms.js +409 -114
  124. package/dist/collections/forms.js.map +1 -1
  125. package/dist/collections/formsEndpoints.js +101 -0
  126. package/dist/collections/formsEndpoints.js.map +1 -0
  127. package/dist/collections/redirectFields.d.ts +29 -0
  128. package/dist/conditions/conditionType.js +9 -2
  129. package/dist/conditions/conditionType.js.map +1 -1
  130. package/dist/conditions/evaluate.js +1 -1
  131. package/dist/conditions/evaluate.js.map +1 -1
  132. package/dist/conditions/fieldTypes.d.ts +3 -1
  133. package/dist/conditions/fieldTypes.js +4 -1
  134. package/dist/conditions/fieldTypes.js.map +1 -1
  135. package/dist/conditions/normalizeConditions.js +20 -6
  136. package/dist/conditions/normalizeConditions.js.map +1 -1
  137. package/dist/consent/applyConsentStatements.d.ts +14 -0
  138. package/dist/consent/applyConsentStatements.js +17 -0
  139. package/dist/consent/applyConsentStatements.js.map +1 -0
  140. package/dist/consent/captureConsent.d.ts +38 -11
  141. package/dist/consent/captureConsent.js +60 -13
  142. package/dist/consent/captureConsent.js.map +1 -1
  143. package/dist/consent/consentSourcesField.d.ts +66 -0
  144. package/dist/consent/consentSourcesField.js +90 -0
  145. package/dist/consent/consentSourcesField.js.map +1 -0
  146. package/dist/consent/resolveConsentEntries.d.ts +24 -0
  147. package/dist/consent/resolveConsentEntries.js +40 -0
  148. package/dist/consent/resolveConsentEntries.js.map +1 -0
  149. package/dist/consent/resolveConsentSourcesRequest.d.ts +37 -0
  150. package/dist/consent/resolveConsentSourcesRequest.js +54 -0
  151. package/dist/consent/resolveConsentSourcesRequest.js.map +1 -0
  152. package/dist/consent/resolveConsentStatements.d.ts +45 -0
  153. package/dist/consent/resolveConsentStatements.js +44 -0
  154. package/dist/consent/resolveConsentStatements.js.map +1 -0
  155. package/dist/consent/resolvePublishedVersionRef.d.ts +17 -11
  156. package/dist/consent/resolvePublishedVersionRef.js +13 -10
  157. package/dist/consent/resolvePublishedVersionRef.js.map +1 -1
  158. package/dist/consent/types.d.ts +61 -0
  159. package/dist/email/departments.d.ts +59 -0
  160. package/dist/email/departments.js +87 -0
  161. package/dist/email/departments.js.map +1 -0
  162. package/dist/email/departmentsField.d.ts +53 -0
  163. package/dist/email/departmentsField.js +73 -0
  164. package/dist/email/departmentsField.js.map +1 -0
  165. package/dist/exports/client.d.ts +13 -1
  166. package/dist/exports/client.js +13 -1
  167. package/dist/exports/i18n.d.ts +5 -2
  168. package/dist/exports/i18n.js +5 -2
  169. package/dist/exports/react.d.ts +26 -8
  170. package/dist/exports/react.js +19 -3
  171. package/dist/exports/rsc.d.ts +8 -1
  172. package/dist/exports/rsc.js +8 -1
  173. package/dist/exports/types.d.ts +19 -10
  174. package/dist/fields/buildFieldBlocks.js +53 -19
  175. package/dist/fields/buildFieldBlocks.js.map +1 -1
  176. package/dist/fields/builtin/calculation.js +122 -2
  177. package/dist/fields/builtin/calculation.js.map +1 -1
  178. package/dist/fields/builtin/checkbox.js +8 -0
  179. package/dist/fields/builtin/checkbox.js.map +1 -1
  180. package/dist/fields/builtin/consent.js +30 -15
  181. package/dist/fields/builtin/consent.js.map +1 -1
  182. package/dist/fields/builtin/country.d.ts +13 -0
  183. package/dist/fields/builtin/country.js +30 -0
  184. package/dist/fields/builtin/country.js.map +1 -0
  185. package/dist/fields/builtin/date.js +31 -0
  186. package/dist/fields/builtin/date.js.map +1 -0
  187. package/dist/fields/builtin/email.js +1 -1
  188. package/dist/fields/builtin/email.js.map +1 -1
  189. package/dist/fields/builtin/file.d.ts +15 -0
  190. package/dist/fields/builtin/file.js +95 -8
  191. package/dist/fields/builtin/file.js.map +1 -1
  192. package/dist/fields/builtin/index.d.ts +26 -0
  193. package/dist/fields/builtin/index.js +30 -6
  194. package/dist/fields/builtin/index.js.map +1 -1
  195. package/dist/fields/builtin/message.js +30 -0
  196. package/dist/fields/builtin/message.js.map +1 -0
  197. package/dist/fields/builtin/repeater.js +49 -0
  198. package/dist/fields/builtin/repeater.js.map +1 -0
  199. package/dist/fields/builtin/select.js +8 -3
  200. package/dist/fields/builtin/select.js.map +1 -1
  201. package/dist/fields/builtin/state.d.ts +13 -0
  202. package/dist/fields/builtin/state.js +30 -0
  203. package/dist/fields/builtin/state.js.map +1 -0
  204. package/dist/fields/data/regions.d.ts +21 -0
  205. package/dist/fields/data/regions.js +1238 -0
  206. package/dist/fields/data/regions.js.map +1 -0
  207. package/dist/fields/fieldKey.d.ts +15 -0
  208. package/dist/fields/fieldKey.js +16 -0
  209. package/dist/fields/fieldKey.js.map +1 -0
  210. package/dist/fields/fieldNamesOfType.js +30 -0
  211. package/dist/fields/fieldNamesOfType.js.map +1 -0
  212. package/dist/fields/instanceOptions.js +20 -0
  213. package/dist/fields/instanceOptions.js.map +1 -0
  214. package/dist/fields/localizedIf.d.ts +13 -0
  215. package/dist/fields/localizedIf.js +12 -0
  216. package/dist/fields/localizedIf.js.map +1 -0
  217. package/dist/fields/registry.d.ts +3 -1
  218. package/dist/fields/registry.js +23 -8
  219. package/dist/fields/registry.js.map +1 -1
  220. package/dist/fields/sharedConfig.js +120 -58
  221. package/dist/fields/sharedConfig.js.map +1 -1
  222. package/dist/fields/types.d.ts +71 -7
  223. package/dist/flow/engine.d.ts +6 -4
  224. package/dist/flow/engine.js +11 -6
  225. package/dist/flow/engine.js.map +1 -1
  226. package/dist/flow/normalizeFlow.js +28 -9
  227. package/dist/flow/normalizeFlow.js.map +1 -1
  228. package/dist/flow/stepLabel.js +15 -0
  229. package/dist/flow/stepLabel.js.map +1 -0
  230. package/dist/flow/types.d.ts +12 -3
  231. package/dist/flow/types.js +11 -0
  232. package/dist/flow/types.js.map +1 -0
  233. package/dist/form/pollState.d.ts +22 -0
  234. package/dist/form/pollState.js +17 -0
  235. package/dist/form/pollState.js.map +1 -0
  236. package/dist/form/toFormDocument.d.ts +102 -0
  237. package/dist/form/toFormDocument.js +87 -0
  238. package/dist/form/toFormDocument.js.map +1 -0
  239. package/dist/form/types.d.ts +65 -0
  240. package/dist/index.d.ts +53 -39
  241. package/dist/index.js +85 -23
  242. package/dist/index.js.map +1 -1
  243. package/dist/options.d.ts +229 -0
  244. package/dist/plugin/applyRegistryConfig.d.ts +11 -0
  245. package/dist/plugin/applyRegistryConfig.js +20 -0
  246. package/dist/plugin/applyRegistryConfig.js.map +1 -0
  247. package/dist/plugin/collectionOverrides.d.ts +22 -0
  248. package/dist/plugin/customState.js +26 -0
  249. package/dist/plugin/customState.js.map +1 -0
  250. package/dist/plugin/registerCollections.js +40 -20
  251. package/dist/plugin/registerCollections.js.map +1 -1
  252. package/dist/plugin/uploadsCollection.d.ts +16 -0
  253. package/dist/plugin/uploadsCollection.js +53 -0
  254. package/dist/plugin/uploadsCollection.js.map +1 -0
  255. package/dist/poll/applyPollOptions.js +18 -0
  256. package/dist/poll/applyPollOptions.js.map +1 -0
  257. package/dist/poll/buildPollOptionSourceFields.js +50 -0
  258. package/dist/poll/buildPollOptionSourceFields.js.map +1 -0
  259. package/dist/poll/closeJob.d.ts +52 -0
  260. package/dist/poll/closeJob.js +119 -0
  261. package/dist/poll/closeJob.js.map +1 -0
  262. package/dist/poll/definePollOptionSource.d.ts +44 -0
  263. package/dist/poll/definePollOptionSource.js +6 -0
  264. package/dist/poll/definePollOptionSource.js.map +1 -0
  265. package/dist/poll/definePollType.d.ts +34 -0
  266. package/dist/poll/definePollType.js +6 -0
  267. package/dist/poll/definePollType.js.map +1 -0
  268. package/dist/poll/effectivePollOptions.d.ts +38 -0
  269. package/dist/poll/effectivePollOptions.js +64 -0
  270. package/dist/poll/effectivePollOptions.js.map +1 -0
  271. package/dist/poll/mostVoted.d.ts +21 -0
  272. package/dist/poll/mostVoted.js +32 -0
  273. package/dist/poll/mostVoted.js.map +1 -0
  274. package/dist/poll/outcomeBeforeChange.js +91 -0
  275. package/dist/poll/outcomeBeforeChange.js.map +1 -0
  276. package/dist/poll/outcomeFields.d.ts +38 -0
  277. package/dist/poll/outcomeFields.js +52 -0
  278. package/dist/poll/outcomeFields.js.map +1 -0
  279. package/dist/poll/pollTypeRegistry.d.ts +34 -0
  280. package/dist/poll/pollTypeRegistry.js +69 -0
  281. package/dist/poll/pollTypeRegistry.js.map +1 -0
  282. package/dist/poll/registry.d.ts +17 -0
  283. package/dist/poll/registry.js +12 -0
  284. package/dist/poll/registry.js.map +1 -0
  285. package/dist/poll/resolvePollCloseRequest.js +105 -0
  286. package/dist/poll/resolvePollCloseRequest.js.map +1 -0
  287. package/dist/poll/resolvePollOptions.d.ts +29 -0
  288. package/dist/poll/resolvePollOptions.js +52 -0
  289. package/dist/poll/resolvePollOptions.js.map +1 -0
  290. package/dist/poll/resolvePollOptionsRequest.js +50 -0
  291. package/dist/poll/resolvePollOptionsRequest.js.map +1 -0
  292. package/dist/poll/resolvePollOutcome.d.ts +34 -0
  293. package/dist/poll/resolvePollOutcome.js +76 -0
  294. package/dist/poll/resolvePollOutcome.js.map +1 -0
  295. package/dist/poll/resultsField.js +21 -0
  296. package/dist/poll/resultsField.js.map +1 -0
  297. package/dist/prefill/valuesFromSearchParams.js +5 -9
  298. package/dist/prefill/valuesFromSearchParams.js.map +1 -1
  299. package/dist/presentations/types.d.ts +3 -2
  300. package/dist/react/Form.d.ts +66 -19
  301. package/dist/react/Form.js +342 -180
  302. package/dist/react/Form.js.map +1 -1
  303. package/dist/react/FormContext.d.ts +44 -1
  304. package/dist/react/FormContext.js.map +1 -1
  305. package/dist/react/FormControls.d.ts +55 -0
  306. package/dist/react/FormControls.js +56 -0
  307. package/dist/react/FormControls.js.map +1 -0
  308. package/dist/react/FormFields.d.ts +18 -0
  309. package/dist/react/FormFields.js +114 -0
  310. package/dist/react/FormFields.js.map +1 -0
  311. package/dist/react/FormLayout.d.ts +4 -2
  312. package/dist/react/FormLayout.js +3 -2
  313. package/dist/react/FormLayout.js.map +1 -1
  314. package/dist/react/FormResults.d.ts +6 -3
  315. package/dist/react/FormResults.js +37 -29
  316. package/dist/react/FormResults.js.map +1 -1
  317. package/dist/react/FormSteps.d.ts +17 -0
  318. package/dist/react/FormSteps.js +35 -0
  319. package/dist/react/FormSteps.js.map +1 -0
  320. package/dist/react/Poll.d.ts +17 -6
  321. package/dist/react/Poll.js +79 -21
  322. package/dist/react/Poll.js.map +1 -1
  323. package/dist/react/captcha/HcaptchaCaptcha.d.ts +28 -0
  324. package/dist/react/captcha/HcaptchaCaptcha.js +53 -0
  325. package/dist/react/captcha/HcaptchaCaptcha.js.map +1 -0
  326. package/dist/react/captcha/RecaptchaCaptcha.d.ts +41 -0
  327. package/dist/react/captcha/RecaptchaCaptcha.js +93 -0
  328. package/dist/react/captcha/RecaptchaCaptcha.js.map +1 -0
  329. package/dist/react/captcha/TurnstileCaptcha.d.ts +28 -0
  330. package/dist/react/captcha/TurnstileCaptcha.js +53 -0
  331. package/dist/react/captcha/TurnstileCaptcha.js.map +1 -0
  332. package/dist/react/captcha/types.d.ts +8 -0
  333. package/dist/react/captcha/useCaptchaScript.js +45 -0
  334. package/dist/react/captcha/useCaptchaScript.js.map +1 -0
  335. package/dist/react/captcha/vendors.js +8 -0
  336. package/dist/react/captcha/vendors.js.map +1 -0
  337. package/dist/react/contract.d.ts +2 -3
  338. package/dist/react/contract.js.map +1 -1
  339. package/dist/react/fetchResults.d.ts +1 -1
  340. package/dist/react/fetchResults.js +1 -1
  341. package/dist/react/fetchResults.js.map +1 -1
  342. package/dist/react/presentation/DialogSurface.js +1 -4
  343. package/dist/react/presentation/DialogSurface.js.map +1 -1
  344. package/dist/react/primitives/Checkbox.d.ts +4 -2
  345. package/dist/react/primitives/Checkbox.js +2 -1
  346. package/dist/react/primitives/Checkbox.js.map +1 -1
  347. package/dist/react/primitives/FieldShell.d.ts +2 -4
  348. package/dist/react/primitives/FieldShell.js +12 -19
  349. package/dist/react/primitives/FieldShell.js.map +1 -1
  350. package/dist/react/primitives/Input.d.ts +1 -1
  351. package/dist/react/primitives/Input.js.map +1 -1
  352. package/dist/react/renderers/calculation.js +1 -4
  353. package/dist/react/renderers/calculation.js.map +1 -1
  354. package/dist/react/renderers/checkbox.js +1 -4
  355. package/dist/react/renderers/checkbox.js.map +1 -1
  356. package/dist/react/renderers/consent.js +78 -35
  357. package/dist/react/renderers/consent.js.map +1 -1
  358. package/dist/react/renderers/date.js +33 -0
  359. package/dist/react/renderers/date.js.map +1 -0
  360. package/dist/react/renderers/email.js +1 -4
  361. package/dist/react/renderers/email.js.map +1 -1
  362. package/dist/react/renderers/file.js +29 -14
  363. package/dist/react/renderers/file.js.map +1 -1
  364. package/dist/react/renderers/index.js +9 -0
  365. package/dist/react/renderers/index.js.map +1 -1
  366. package/dist/react/renderers/message.js +41 -0
  367. package/dist/react/renderers/message.js.map +1 -0
  368. package/dist/react/renderers/number.js +1 -4
  369. package/dist/react/renderers/number.js.map +1 -1
  370. package/dist/react/renderers/region.js +43 -0
  371. package/dist/react/renderers/region.js.map +1 -0
  372. package/dist/react/renderers/repeater.js +131 -0
  373. package/dist/react/renderers/repeater.js.map +1 -0
  374. package/dist/react/renderers/select.js +1 -4
  375. package/dist/react/renderers/select.js.map +1 -1
  376. package/dist/react/renderers/text.js +1 -4
  377. package/dist/react/renderers/text.js.map +1 -1
  378. package/dist/react/renderers/textarea.js +1 -4
  379. package/dist/react/renderers/textarea.js.map +1 -1
  380. package/dist/react/state.d.ts +40 -3
  381. package/dist/react/state.js +64 -9
  382. package/dist/react/state.js.map +1 -1
  383. package/dist/react/uploadFile.d.ts +2 -2
  384. package/dist/react/uploadFile.js +1 -1
  385. package/dist/react/uploadFile.js.map +1 -1
  386. package/dist/react/useField.d.ts +0 -1
  387. package/dist/react/useField.js +6 -6
  388. package/dist/react/useField.js.map +1 -1
  389. package/dist/react/useFormState.d.ts +1 -1
  390. package/dist/react/useFormState.js +1 -1
  391. package/dist/react/useFormState.js.map +1 -1
  392. package/dist/react/validateField.js +3 -6
  393. package/dist/react/validateField.js.map +1 -1
  394. package/dist/recall/interpolate.d.ts +4 -3
  395. package/dist/recall/interpolate.js +5 -4
  396. package/dist/recall/interpolate.js.map +1 -1
  397. package/dist/recall/resolver.d.ts +1 -1
  398. package/dist/recall/resolver.js +14 -2
  399. package/dist/recall/resolver.js.map +1 -1
  400. package/dist/spam/captcha.d.ts +4 -3
  401. package/dist/spam/captcha.js +4 -3
  402. package/dist/spam/captcha.js.map +1 -1
  403. package/dist/spam/clientIp.js +9 -0
  404. package/dist/spam/clientIp.js.map +1 -0
  405. package/dist/spam/constants.js +7 -1
  406. package/dist/spam/constants.js.map +1 -1
  407. package/dist/spam/identify.js +3 -6
  408. package/dist/spam/identify.js.map +1 -1
  409. package/dist/spam/providers/hcaptcha.d.ts +17 -0
  410. package/dist/spam/providers/hcaptcha.js +18 -0
  411. package/dist/spam/providers/hcaptcha.js.map +1 -0
  412. package/dist/spam/providers/recaptcha.d.ts +23 -0
  413. package/dist/spam/providers/recaptcha.js +23 -0
  414. package/dist/spam/providers/recaptcha.js.map +1 -0
  415. package/dist/spam/providers/siteverify.js +34 -0
  416. package/dist/spam/providers/siteverify.js.map +1 -0
  417. package/dist/spam/providers/turnstile.d.ts +17 -0
  418. package/dist/spam/providers/turnstile.js +18 -0
  419. package/dist/spam/providers/turnstile.js.map +1 -0
  420. package/dist/spam/resolveSpam.js +2 -1
  421. package/dist/spam/resolveSpam.js.map +1 -1
  422. package/dist/spam/spamGuard.js +23 -10
  423. package/dist/spam/spamGuard.js.map +1 -1
  424. package/dist/spam/types.d.ts +19 -4
  425. package/dist/submissions/SubmissionAnswers.d.ts +2 -4
  426. package/dist/submissions/SubmissionAnswers.js +114 -34
  427. package/dist/submissions/SubmissionAnswers.js.map +1 -1
  428. package/dist/submissions/SubmissionAnswersClient.js +178 -0
  429. package/dist/submissions/SubmissionAnswersClient.js.map +1 -0
  430. package/dist/submissions/coerceBoolean.js +14 -0
  431. package/dist/submissions/coerceBoolean.js.map +1 -0
  432. package/dist/submissions/createSubmission.d.ts +36 -0
  433. package/dist/submissions/createSubmission.js +26 -0
  434. package/dist/submissions/createSubmission.js.map +1 -0
  435. package/dist/submissions/runSubmission.d.ts +10 -0
  436. package/dist/submissions/runSubmission.js +128 -27
  437. package/dist/submissions/runSubmission.js.map +1 -1
  438. package/dist/submissions/types.d.ts +12 -4
  439. package/dist/submissions/validateSubmission.js +62 -11
  440. package/dist/submissions/validateSubmission.js.map +1 -1
  441. package/dist/submissions/votedCookie.d.ts +13 -0
  442. package/dist/submissions/votedCookie.js +27 -0
  443. package/dist/submissions/votedCookie.js.map +1 -0
  444. package/dist/translations/clientRuntimeKeys.d.ts +17 -0
  445. package/dist/translations/clientRuntimeKeys.js +46 -0
  446. package/dist/translations/clientRuntimeKeys.js.map +1 -0
  447. package/dist/translations/de.d.ts +12 -0
  448. package/dist/translations/de.js +309 -0
  449. package/dist/translations/de.js.map +1 -0
  450. package/dist/translations/en.js +203 -27
  451. package/dist/translations/en.js.map +1 -1
  452. package/dist/translations/index.d.ts +14 -5
  453. package/dist/translations/index.js +14 -3
  454. package/dist/translations/index.js.map +1 -1
  455. package/dist/translations/keys.d.ts +199 -23
  456. package/dist/translations/keys.js +200 -24
  457. package/dist/translations/keys.js.map +1 -1
  458. package/dist/translations/makeTranslate.d.ts +7 -3
  459. package/dist/translations/makeTranslate.js +12 -3
  460. package/dist/translations/makeTranslate.js.map +1 -1
  461. package/dist/translations/server.js +8 -1
  462. package/dist/translations/server.js.map +1 -1
  463. package/dist/uploads/captureFileRef.d.ts +10 -3
  464. package/dist/uploads/captureFileRef.js +18 -9
  465. package/dist/uploads/captureFileRef.js.map +1 -1
  466. package/dist/uploads/formatBytes.d.ts +9 -0
  467. package/dist/uploads/formatBytes.js +25 -0
  468. package/dist/uploads/formatBytes.js.map +1 -0
  469. package/dist/uploads/resolveFileRef.js +3 -2
  470. package/dist/uploads/resolveFileRef.js.map +1 -1
  471. package/dist/uploads/types.d.ts +1 -2
  472. package/dist/validation/buildRuleBlocks.js +18 -17
  473. package/dist/validation/buildRuleBlocks.js.map +1 -1
  474. package/dist/validation/builtin/email.js +2 -1
  475. package/dist/validation/builtin/email.js.map +1 -1
  476. package/dist/validation/builtin/index.d.ts +14 -0
  477. package/dist/validation/builtin/index.js +12 -1
  478. package/dist/validation/builtin/index.js.map +1 -1
  479. package/dist/validation/builtin/matchesField.js +3 -7
  480. package/dist/validation/builtin/matchesField.js.map +1 -1
  481. package/dist/validation/builtin/max.js +1 -0
  482. package/dist/validation/builtin/max.js.map +1 -1
  483. package/dist/validation/builtin/maxDate.js +24 -0
  484. package/dist/validation/builtin/maxDate.js.map +1 -0
  485. package/dist/validation/builtin/maxLength.js +1 -0
  486. package/dist/validation/builtin/maxLength.js.map +1 -1
  487. package/dist/validation/builtin/min.js +1 -0
  488. package/dist/validation/builtin/min.js.map +1 -1
  489. package/dist/validation/builtin/minDate.js +24 -0
  490. package/dist/validation/builtin/minDate.js.map +1 -0
  491. package/dist/validation/builtin/minLength.js +1 -0
  492. package/dist/validation/builtin/minLength.js.map +1 -1
  493. package/dist/validation/builtin/notAlreadySubmitted.js +2 -0
  494. package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -1
  495. package/dist/validation/builtin/oneOf.js +1 -0
  496. package/dist/validation/builtin/oneOf.js.map +1 -1
  497. package/dist/validation/builtin/pattern.js +11 -2
  498. package/dist/validation/builtin/pattern.js.map +1 -1
  499. package/dist/validation/builtin/url.js +1 -0
  500. package/dist/validation/builtin/url.js.map +1 -1
  501. package/dist/validation/builtin/validateDateBound.js +18 -0
  502. package/dist/validation/builtin/validateDateBound.js.map +1 -0
  503. package/dist/validation/builtin/validateRegexParams.js +44 -0
  504. package/dist/validation/builtin/validateRegexParams.js.map +1 -0
  505. package/dist/validation/emailPattern.js +10 -0
  506. package/dist/validation/emailPattern.js.map +1 -0
  507. package/dist/validation/fieldTargetParam.d.ts +22 -0
  508. package/dist/validation/fieldTargetParam.js +38 -0
  509. package/dist/validation/fieldTargetParam.js.map +1 -0
  510. package/dist/validation/registry.d.ts +2 -1
  511. package/dist/validation/registry.js +2 -9
  512. package/dist/validation/registry.js.map +1 -1
  513. package/dist/validation/runValidation.js +9 -30
  514. package/dist/validation/runValidation.js.map +1 -1
  515. package/dist/validation/types.d.ts +5 -11
  516. package/dist/validation/validateUrl.js +22 -0
  517. package/dist/validation/validateUrl.js.map +1 -0
  518. package/package.json +7 -5
  519. package/styles/form-builder.css +10 -190
  520. package/dist/collections/uploads.d.ts +0 -29
  521. package/dist/collections/uploads.js +0 -46
  522. package/dist/collections/uploads.js.map +0 -1
  523. package/dist/consent/buildConsentSourceConfig.js +0 -49
  524. package/dist/consent/buildConsentSourceConfig.js.map +0 -1
  525. package/dist/consent/builtin/index.d.ts +0 -7
  526. package/dist/consent/builtin/index.js +0 -11
  527. package/dist/consent/builtin/index.js.map +0 -1
  528. package/dist/consent/builtin/pageReference.js +0 -75
  529. package/dist/consent/builtin/pageReference.js.map +0 -1
  530. package/dist/consent/builtin/static.js +0 -44
  531. package/dist/consent/builtin/static.js.map +0 -1
  532. package/dist/consent/defineConsentSource.d.ts +0 -35
  533. package/dist/consent/defineConsentSource.js +0 -6
  534. package/dist/consent/defineConsentSource.js.map +0 -1
  535. package/dist/consent/registry.d.ts +0 -16
  536. package/dist/consent/registry.js +0 -16
  537. package/dist/consent/registry.js.map +0 -1
  538. package/dist/consent/resolveConsentLinks.d.ts +0 -19
  539. package/dist/consent/resolveConsentLinks.js +0 -26
  540. package/dist/consent/resolveConsentLinks.js.map +0 -1
  541. package/dist/presentations/registry.d.ts +0 -15
  542. package/dist/presentations/registry.js +0 -15
  543. package/dist/presentations/registry.js.map +0 -1
  544. package/dist/react/toFormDocument.d.ts +0 -24
  545. package/dist/react/toFormDocument.js +0 -22
  546. package/dist/react/toFormDocument.js.map +0 -1
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { formatBytes } from "../uploads/formatBytes.js";
3
+ import { useTranslation as useTranslation$1 } from "../translations/useTranslation.js";
4
+ import { toStaticLabel } from "./toStaticLabel.js";
5
+ import { FieldDescription, FieldLabel, useField } from "@payloadcms/ui";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/client/ByteSizeField.tsx
8
+ /**
9
+ * The `Field` mounted on a byte-count number config field (the file field's `maxSize`): a plain
10
+ * number input that live-previews the value as a human-readable size ('= 2.5 MB') so authors are
11
+ * not left decoding raw bytes. Stores the raw byte number unchanged.
12
+ */
13
+ const ByteSizeField = (props) => {
14
+ const { path, setValue, value } = useField({ path: props.path });
15
+ const label = toStaticLabel(props.field?.label ?? props.label);
16
+ const { t } = useTranslation$1();
17
+ const description = props.descriptionKey ? t(props.descriptionKey) : toStaticLabel(props.field?.admin?.description);
18
+ const handleChange = (event) => {
19
+ if (event.target.value === "") {
20
+ setValue(null);
21
+ return;
22
+ }
23
+ const parsed = Number(event.target.value);
24
+ if (Number.isFinite(parsed)) setValue(parsed);
25
+ };
26
+ return /* @__PURE__ */ jsxs("div", {
27
+ className: "field-type number",
28
+ style: { marginBlockEnd: "1rem" },
29
+ children: [/* @__PURE__ */ jsx(FieldLabel, {
30
+ label,
31
+ path
32
+ }), /* @__PURE__ */ jsxs("div", {
33
+ className: "field-type__wrap",
34
+ children: [
35
+ /* @__PURE__ */ jsx("input", {
36
+ id: `field-${path.replace(/\./g, "__")}`,
37
+ min: 0,
38
+ name: path,
39
+ onChange: handleChange,
40
+ type: "number",
41
+ value: typeof value === "number" ? value : ""
42
+ }),
43
+ typeof value === "number" && value > 0 ? /* @__PURE__ */ jsx("div", {
44
+ className: "field-description",
45
+ children: `= ${formatBytes(value)}`
46
+ }) : null,
47
+ /* @__PURE__ */ jsx(FieldDescription, {
48
+ description,
49
+ path
50
+ })
51
+ ]
52
+ })]
53
+ });
54
+ };
55
+ //#endregion
56
+ export { ByteSizeField };
57
+
58
+ //# sourceMappingURL=ByteSizeField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ByteSizeField.js","names":["useTranslation"],"sources":["../../src/client/ByteSizeField.tsx"],"sourcesContent":["'use client'\n\nimport { FieldDescription, FieldLabel, useField } from '@payloadcms/ui'\nimport type { ChangeEvent } from 'react'\nimport type { TranslationKey } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\nimport { formatBytes } from '../uploads/formatBytes'\nimport { toStaticLabel } from './toStaticLabel'\n\n/** Props: standard number field client props; label and description arrive resolved on `field`. */\nexport type ByteSizeFieldProps = {\n\tpath?: string\n\tfield?: { label?: unknown; admin?: { description?: unknown } }\n\tlabel?: unknown\n\t/**\n\t * Field description as a translation key, resolved client-side. Payload drops `admin.description`\n\t * functions from client fields, so a translated description must travel as a key; a static\n\t * `admin.description` string still renders when this is unset.\n\t */\n\tdescriptionKey?: TranslationKey\n}\n\n/**\n * The `Field` mounted on a byte-count number config field (the file field's `maxSize`): a plain\n * number input that live-previews the value as a human-readable size ('= 2.5 MB') so authors are\n * not left decoding raw bytes. Stores the raw byte number unchanged.\n */\nexport const ByteSizeField = (props: ByteSizeFieldProps) => {\n\tconst { path, setValue, value } = useField<number>({ path: props.path })\n\tconst label = toStaticLabel(props.field?.label ?? props.label)\n\tconst { t } = useTranslation()\n\tconst description = props.descriptionKey\n\t\t? t(props.descriptionKey)\n\t\t: toStaticLabel(props.field?.admin?.description)\n\n\tconst handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n\t\tif (event.target.value === '') {\n\t\t\tsetValue(null)\n\t\t\treturn\n\t\t}\n\t\tconst parsed = Number(event.target.value)\n\t\tif (Number.isFinite(parsed)) {\n\t\t\tsetValue(parsed)\n\t\t}\n\t}\n\n\treturn (\n\t\t<div className=\"field-type number\" style={{ marginBlockEnd: '1rem' }}>\n\t\t\t<FieldLabel label={label} path={path} />\n\t\t\t<div className=\"field-type__wrap\">\n\t\t\t\t<input\n\t\t\t\t\tid={`field-${path.replace(/\\./g, '__')}`}\n\t\t\t\t\tmin={0}\n\t\t\t\t\tname={path}\n\t\t\t\t\tonChange={handleChange}\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\tvalue={typeof value === 'number' ? value : ''}\n\t\t\t\t/>\n\t\t\t\t{typeof value === 'number' && value > 0 ? (\n\t\t\t\t\t<div className=\"field-description\">{`= ${formatBytes(value)}`}</div>\n\t\t\t\t) : null}\n\t\t\t\t<FieldDescription description={description} path={path} />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n"],"mappings":";;;;;;;;;;;;AA2BA,MAAa,iBAAiB,UAA8B;CAC3D,MAAM,EAAE,MAAM,UAAU,UAAU,SAAiB,EAAE,MAAM,MAAM,KAAK,CAAC;CACvE,MAAM,QAAQ,cAAc,MAAM,OAAO,SAAS,MAAM,KAAK;CAC7D,MAAM,EAAE,MAAMA,iBAAe;CAC7B,MAAM,cAAc,MAAM,iBACvB,EAAE,MAAM,cAAc,IACtB,cAAc,MAAM,OAAO,OAAO,WAAW;CAEhD,MAAM,gBAAgB,UAAyC;EAC9D,IAAI,MAAM,OAAO,UAAU,IAAI;GAC9B,SAAS,IAAI;GACb;EACD;EACA,MAAM,SAAS,OAAO,MAAM,OAAO,KAAK;EACxC,IAAI,OAAO,SAAS,MAAM,GACzB,SAAS,MAAM;CAEjB;CAEA,OACC,qBAAC,OAAD;EAAK,WAAU;EAAoB,OAAO,EAAE,gBAAgB,OAAO;YAAnE,CACC,oBAAC,YAAD;GAAmB;GAAa;EAAO,CAAA,GACvC,qBAAC,OAAD;GAAK,WAAU;aAAf;IACC,oBAAC,SAAD;KACC,IAAI,SAAS,KAAK,QAAQ,OAAO,IAAI;KACrC,KAAK;KACL,MAAM;KACN,UAAU;KACV,MAAK;KACL,OAAO,OAAO,UAAU,WAAW,QAAQ;IAC3C,CAAA;IACA,OAAO,UAAU,YAAY,QAAQ,IACrC,oBAAC,OAAD;KAAK,WAAU;eAAqB,KAAK,YAAY,KAAK;IAAS,CAAA,IAChE;IACJ,oBAAC,kBAAD;KAA+B;KAAmB;IAAO,CAAA;GACrD;IACD;;AAEP"}
@@ -0,0 +1,15 @@
1
+ //#region src/client/ClosePollButton.d.ts
2
+ /**
3
+ * The `poll.closePoll` UI field: one button that closes the poll and, once closed, reopens it, by
4
+ * saving the whole document rather than calling the `/:id/close` endpoint. Closing stamps
5
+ * `poll.closesAt` now while keeping the admin's just-picked winner, so both persist together through
6
+ * the normal save (`pollOutcomeBeforeChange` validates the winner and stamps `resolvedAt`; the
7
+ * `afterChange` hook enqueues the close for a `mostVoted`/`source` strategy). Reopening clears both
8
+ * `closesAt` and `winningValues`, since either one keeps a poll finalized. A `manual` poll with no
9
+ * winner selected disables the button (there is nothing to record); `mostVoted`/`source` stay enabled
10
+ * because the winner is server-computed. Disabled on an unsaved document (no id yet).
11
+ */
12
+ declare const ClosePollButton: () => import("react/jsx-runtime").JSX.Element;
13
+ //#endregion
14
+ export { ClosePollButton };
15
+ //# sourceMappingURL=ClosePollButton.d.ts.map
@@ -0,0 +1,80 @@
1
+ "use client";
2
+ import { keys } from "../translations/keys.js";
3
+ import { useTranslation as useTranslation$1 } from "../translations/useTranslation.js";
4
+ import { Button, useDocumentInfo, useForm, useFormFields } from "@payloadcms/ui";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useState } from "react";
7
+ //#region src/client/ClosePollButton.tsx
8
+ /** The help line under the button when closing, tailored to the strategy that closing will apply. */
9
+ const closeHintKeyFor = (type) => {
10
+ if (type === "mostVoted") return keys.pollCloseHintMostVoted;
11
+ if (type === "source") return keys.pollCloseHintSource;
12
+ return keys.pollCloseHintManual;
13
+ };
14
+ const strOf = (value) => typeof value === "string" && value.length > 0 ? value : "manual";
15
+ /** True once a `closesAt` is set (scheduled or past): the toggle treats that as closed/finalized. */
16
+ const isClosed = (value) => typeof value === "string" && value.length > 0;
17
+ /** True when the winner set holds at least one non-empty value. */
18
+ const hasWinner = (value) => Array.isArray(value) && value.some((entry) => typeof entry === "string" && entry.length > 0);
19
+ const asRecord = (value) => value != null && typeof value === "object" ? value : {};
20
+ /**
21
+ * The `poll.closePoll` UI field: one button that closes the poll and, once closed, reopens it, by
22
+ * saving the whole document rather than calling the `/:id/close` endpoint. Closing stamps
23
+ * `poll.closesAt` now while keeping the admin's just-picked winner, so both persist together through
24
+ * the normal save (`pollOutcomeBeforeChange` validates the winner and stamps `resolvedAt`; the
25
+ * `afterChange` hook enqueues the close for a `mostVoted`/`source` strategy). Reopening clears both
26
+ * `closesAt` and `winningValues`, since either one keeps a poll finalized. A `manual` poll with no
27
+ * winner selected disables the button (there is nothing to record); `mostVoted`/`source` stay enabled
28
+ * because the winner is server-computed. Disabled on an unsaved document (no id yet).
29
+ */
30
+ const ClosePollButton = () => {
31
+ const { t } = useTranslation$1();
32
+ const { id } = useDocumentInfo();
33
+ const { getDataByPath, submit } = useForm();
34
+ const type = useFormFields(([fields]) => strOf(fields?.["poll.type"]?.value));
35
+ const closed = useFormFields(([fields]) => isClosed(fields?.["poll.closesAt"]?.value));
36
+ const winnerSet = useFormFields(([fields]) => hasWinner(fields?.["poll.outcome.winningValues"]?.value));
37
+ const [submitting, setSubmitting] = useState(false);
38
+ const manualNeedsWinner = !closed && type === "manual" && !winnerSet;
39
+ const disabled = id == null || submitting || manualNeedsWinner;
40
+ const save = async (nextPoll) => {
41
+ if (id == null) return;
42
+ setSubmitting(true);
43
+ try {
44
+ await submit({ overrides: { poll: nextPoll(asRecord(getDataByPath("poll"))) } });
45
+ } finally {
46
+ setSubmitting(false);
47
+ }
48
+ };
49
+ const close = () => save((poll) => ({
50
+ ...poll,
51
+ closesAt: (/* @__PURE__ */ new Date()).toISOString()
52
+ }));
53
+ const reopen = () => save((poll) => ({
54
+ ...poll,
55
+ closesAt: null,
56
+ outcome: {
57
+ ...asRecord(poll.outcome),
58
+ winningValues: []
59
+ }
60
+ }));
61
+ const hintKey = closed ? keys.pollReopenHint : manualNeedsWinner ? keys.pollCloseNeedsWinner : closeHintKeyFor(type);
62
+ return /* @__PURE__ */ jsxs("div", {
63
+ className: "field-type",
64
+ style: { marginBlockEnd: "1rem" },
65
+ children: [/* @__PURE__ */ jsx(Button, {
66
+ buttonStyle: "secondary",
67
+ onClick: closed ? reopen : close,
68
+ disabled,
69
+ children: t(closed ? keys.pollReopenButton : keys.pollCloseButton)
70
+ }), /* @__PURE__ */ jsx("p", {
71
+ className: "field-description",
72
+ style: { marginBlockStart: "0.5rem" },
73
+ children: t(hintKey)
74
+ })]
75
+ });
76
+ };
77
+ //#endregion
78
+ export { ClosePollButton };
79
+
80
+ //# sourceMappingURL=ClosePollButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClosePollButton.js","names":["useTranslation"],"sources":["../../src/client/ClosePollButton.tsx"],"sourcesContent":["'use client'\n\nimport { Button, useDocumentInfo, useForm, useFormFields } from '@payloadcms/ui'\nimport { useState } from 'react'\nimport { keys, type TranslationKey } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\n\n/** The help line under the button when closing, tailored to the strategy that closing will apply. */\nconst closeHintKeyFor = (type: string): TranslationKey => {\n\tif (type === 'mostVoted') {\n\t\treturn keys.pollCloseHintMostVoted\n\t}\n\tif (type === 'source') {\n\t\treturn keys.pollCloseHintSource\n\t}\n\treturn keys.pollCloseHintManual\n}\n\nconst strOf = (value: unknown): string =>\n\ttypeof value === 'string' && value.length > 0 ? value : 'manual'\n\n/** True once a `closesAt` is set (scheduled or past): the toggle treats that as closed/finalized. */\nconst isClosed = (value: unknown): boolean => typeof value === 'string' && value.length > 0\n\n/** True when the winner set holds at least one non-empty value. */\nconst hasWinner = (value: unknown): boolean =>\n\tArray.isArray(value) && value.some((entry) => typeof entry === 'string' && entry.length > 0)\n\nconst asRecord = (value: unknown): Record<string, unknown> =>\n\tvalue != null && typeof value === 'object' ? (value as Record<string, unknown>) : {}\n\n/**\n * The `poll.closePoll` UI field: one button that closes the poll and, once closed, reopens it, by\n * saving the whole document rather than calling the `/:id/close` endpoint. Closing stamps\n * `poll.closesAt` now while keeping the admin's just-picked winner, so both persist together through\n * the normal save (`pollOutcomeBeforeChange` validates the winner and stamps `resolvedAt`; the\n * `afterChange` hook enqueues the close for a `mostVoted`/`source` strategy). Reopening clears both\n * `closesAt` and `winningValues`, since either one keeps a poll finalized. A `manual` poll with no\n * winner selected disables the button (there is nothing to record); `mostVoted`/`source` stay enabled\n * because the winner is server-computed. Disabled on an unsaved document (no id yet).\n */\nexport const ClosePollButton = () => {\n\tconst { t } = useTranslation()\n\tconst { id } = useDocumentInfo()\n\tconst { getDataByPath, submit } = useForm()\n\tconst type = useFormFields(([fields]) => strOf(fields?.['poll.type']?.value))\n\tconst closed = useFormFields(([fields]) => isClosed(fields?.['poll.closesAt']?.value))\n\tconst winnerSet = useFormFields(([fields]) =>\n\t\thasWinner(fields?.['poll.outcome.winningValues']?.value)\n\t)\n\tconst [submitting, setSubmitting] = useState(false)\n\n\tconst manualNeedsWinner = !closed && type === 'manual' && !winnerSet\n\tconst disabled = id == null || submitting || manualNeedsWinner\n\n\tconst save = async (nextPoll: (poll: Record<string, unknown>) => Record<string, unknown>) => {\n\t\tif (id == null) {\n\t\t\treturn\n\t\t}\n\t\tsetSubmitting(true)\n\t\ttry {\n\t\t\t// Rebuild the whole poll group from live form state and override it in one shot: a shallow\n\t\t\t// top-level override, so the winner and every other poll field are preserved (a dotted\n\t\t\t// `poll.closesAt` override key never reaches the nested field on the server).\n\t\t\tconst poll = asRecord(getDataByPath('poll'))\n\t\t\tawait submit({ overrides: { poll: nextPoll(poll) } })\n\t\t} finally {\n\t\t\tsetSubmitting(false)\n\t\t}\n\t}\n\n\tconst close = () => save((poll) => ({ ...poll, closesAt: new Date().toISOString() }))\n\tconst reopen = () =>\n\t\tsave((poll) => ({\n\t\t\t...poll,\n\t\t\tclosesAt: null,\n\t\t\toutcome: { ...asRecord(poll.outcome), winningValues: [] },\n\t\t}))\n\n\tconst hintKey: TranslationKey = closed\n\t\t? keys.pollReopenHint\n\t\t: manualNeedsWinner\n\t\t\t? keys.pollCloseNeedsWinner\n\t\t\t: closeHintKeyFor(type)\n\n\treturn (\n\t\t<div className=\"field-type\" style={{ marginBlockEnd: '1rem' }}>\n\t\t\t<Button buttonStyle=\"secondary\" onClick={closed ? reopen : close} disabled={disabled}>\n\t\t\t\t{t(closed ? keys.pollReopenButton : keys.pollCloseButton)}\n\t\t\t</Button>\n\t\t\t<p className=\"field-description\" style={{ marginBlockStart: '0.5rem' }}>\n\t\t\t\t{t(hintKey)}\n\t\t\t</p>\n\t\t</div>\n\t)\n}\n"],"mappings":";;;;;;;;AAQA,MAAM,mBAAmB,SAAiC;CACzD,IAAI,SAAS,aACZ,OAAO,KAAK;CAEb,IAAI,SAAS,UACZ,OAAO,KAAK;CAEb,OAAO,KAAK;AACb;AAEA,MAAM,SAAS,UACd,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;;AAGzD,MAAM,YAAY,UAA4B,OAAO,UAAU,YAAY,MAAM,SAAS;;AAG1F,MAAM,aAAa,UAClB,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,UAAU,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC;AAE5F,MAAM,YAAY,UACjB,SAAS,QAAQ,OAAO,UAAU,WAAY,QAAoC,CAAC;;;;;;;;;;;AAYpF,MAAa,wBAAwB;CACpC,MAAM,EAAE,MAAMA,iBAAe;CAC7B,MAAM,EAAE,OAAO,gBAAgB;CAC/B,MAAM,EAAE,eAAe,WAAW,QAAQ;CAC1C,MAAM,OAAO,eAAe,CAAC,YAAY,MAAM,SAAS,cAAc,KAAK,CAAC;CAC5E,MAAM,SAAS,eAAe,CAAC,YAAY,SAAS,SAAS,kBAAkB,KAAK,CAAC;CACrF,MAAM,YAAY,eAAe,CAAC,YACjC,UAAU,SAAS,+BAA+B,KAAK,CACxD;CACA,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAElD,MAAM,oBAAoB,CAAC,UAAU,SAAS,YAAY,CAAC;CAC3D,MAAM,WAAW,MAAM,QAAQ,cAAc;CAE7C,MAAM,OAAO,OAAO,aAAyE;EAC5F,IAAI,MAAM,MACT;EAED,cAAc,IAAI;EAClB,IAAI;GAKH,MAAM,OAAO,EAAE,WAAW,EAAE,MAAM,SADrB,SAAS,cAAc,MAAM,CACI,CAAC,EAAE,EAAE,CAAC;EACrD,UAAU;GACT,cAAc,KAAK;EACpB;CACD;CAEA,MAAM,cAAc,MAAM,UAAU;EAAE,GAAG;EAAM,2BAAU,IAAI,KAAK,GAAE,YAAY;CAAE,EAAE;CACpF,MAAM,eACL,MAAM,UAAU;EACf,GAAG;EACH,UAAU;EACV,SAAS;GAAE,GAAG,SAAS,KAAK,OAAO;GAAG,eAAe,CAAC;EAAE;CACzD,EAAE;CAEH,MAAM,UAA0B,SAC7B,KAAK,iBACL,oBACC,KAAK,uBACL,gBAAgB,IAAI;CAExB,OACC,qBAAC,OAAD;EAAK,WAAU;EAAa,OAAO,EAAE,gBAAgB,OAAO;YAA5D,CACC,oBAAC,QAAD;GAAQ,aAAY;GAAY,SAAS,SAAS,SAAS;GAAiB;aAC1E,EAAE,SAAS,KAAK,mBAAmB,KAAK,eAAe;EACjD,CAAA,GACR,oBAAC,KAAD;GAAG,WAAU;GAAoB,OAAO,EAAE,kBAAkB,SAAS;aACnE,EAAE,OAAO;EACR,CAAA,CACC;;AAEP"}
@@ -0,0 +1,15 @@
1
+ import { ArrayFieldClientComponent } from "payload";
2
+ //#region src/client/CondensedArray.d.ts
3
+ /**
4
+ * A custom `Field` for a real Payload `array` that renders its rows flat: each row is `[label, email]`
5
+ * laid out at 50% width with a remove control, added by a footer button, and never wrapped in the
6
+ * per-row `Collapsible` that Payload's native array applies unconditionally. Row ids and per-locale
7
+ * storage stay Payload's: rows come from `useField({ hasRows: true })`, mutations go through
8
+ * `useForm`'s `addFieldRow`/`removeFieldRow`, and each row's subfields render through `RenderFields`
9
+ * at `{path}.{index}` exactly as the native array does, so localization, validation, and descriptions
10
+ * work natively. Placed by {@link departmentsField}.
11
+ */
12
+ declare const CondensedArray: ArrayFieldClientComponent;
13
+ //#endregion
14
+ export { CondensedArray };
15
+ //# sourceMappingURL=CondensedArray.d.ts.map
@@ -0,0 +1,97 @@
1
+ "use client";
2
+ import { keys } from "../translations/keys.js";
3
+ import { useTranslation as useTranslation$1 } from "../translations/useTranslation.js";
4
+ import { Button, FieldDescription, FieldLabel, RenderCustomComponent, RenderFields, useField, useForm } from "@payloadcms/ui";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import "./admin.css";
7
+ //#region src/client/CondensedArray.tsx
8
+ const baseClass = "fb-condensed-array";
9
+ /**
10
+ * A custom `Field` for a real Payload `array` that renders its rows flat: each row is `[label, email]`
11
+ * laid out at 50% width with a remove control, added by a footer button, and never wrapped in the
12
+ * per-row `Collapsible` that Payload's native array applies unconditionally. Row ids and per-locale
13
+ * storage stay Payload's: rows come from `useField({ hasRows: true })`, mutations go through
14
+ * `useForm`'s `addFieldRow`/`removeFieldRow`, and each row's subfields render through `RenderFields`
15
+ * at `{path}.{index}` exactly as the native array does, so localization, validation, and descriptions
16
+ * work natively. Placed by {@link departmentsField}.
17
+ */
18
+ const CondensedArray = (props) => {
19
+ const { field: { name, admin: { description } = {}, fields, label, localized }, forceRender = false, path: pathFromProps, permissions, readOnly, schemaPath: schemaPathFromProps } = props;
20
+ const schemaPath = schemaPathFromProps ?? name;
21
+ const { t } = useTranslation$1();
22
+ const { addFieldRow, removeFieldRow } = useForm();
23
+ const { customComponents: { Description, Label } = {}, path, rows = [] } = useField({
24
+ hasRows: true,
25
+ potentiallyStalePath: pathFromProps
26
+ });
27
+ return /* @__PURE__ */ jsxs("div", {
28
+ className: `field-type ${baseClass}`,
29
+ id: `field-${path.replace(/\./g, "__")}`,
30
+ children: [
31
+ /* @__PURE__ */ jsx(RenderCustomComponent, {
32
+ CustomComponent: Label,
33
+ Fallback: /* @__PURE__ */ jsx(FieldLabel, {
34
+ label,
35
+ localized,
36
+ path
37
+ })
38
+ }),
39
+ /* @__PURE__ */ jsx(RenderCustomComponent, {
40
+ CustomComponent: Description,
41
+ Fallback: /* @__PURE__ */ jsx(FieldDescription, {
42
+ description,
43
+ path
44
+ })
45
+ }),
46
+ rows.length > 0 ? /* @__PURE__ */ jsx("div", {
47
+ className: `${baseClass}__rows`,
48
+ children: rows.map((row, index) => /* @__PURE__ */ jsxs("div", {
49
+ className: `${baseClass}__row`,
50
+ children: [/* @__PURE__ */ jsx(RenderFields, {
51
+ className: `${baseClass}__fields`,
52
+ fields,
53
+ forceRender,
54
+ margins: false,
55
+ parentIndexPath: "",
56
+ parentPath: `${path}.${index}`,
57
+ parentSchemaPath: schemaPath,
58
+ permissions: permissions === true ? permissions : permissions?.fields ?? {},
59
+ readOnly
60
+ }), !readOnly ? /* @__PURE__ */ jsx("div", {
61
+ className: `${baseClass}__remove`,
62
+ children: /* @__PURE__ */ jsx(Button, {
63
+ buttonStyle: "icon-label",
64
+ icon: "x",
65
+ onClick: () => removeFieldRow({
66
+ path,
67
+ rowIndex: index
68
+ }),
69
+ "aria-label": t(keys.departmentRemoveRow),
70
+ margin: false
71
+ })
72
+ }) : null]
73
+ }, row.id))
74
+ }) : null,
75
+ !readOnly ? /* @__PURE__ */ jsx("div", {
76
+ className: `${baseClass}__actions`,
77
+ children: /* @__PURE__ */ jsx(Button, {
78
+ buttonStyle: "icon-label",
79
+ icon: "plus",
80
+ iconStyle: "with-border",
81
+ iconPosition: "left",
82
+ onClick: () => addFieldRow({
83
+ path,
84
+ rowIndex: rows.length,
85
+ schemaPath
86
+ }),
87
+ margin: false,
88
+ children: t(keys.departmentAddRow)
89
+ })
90
+ }) : null
91
+ ]
92
+ });
93
+ };
94
+ //#endregion
95
+ export { CondensedArray };
96
+
97
+ //# sourceMappingURL=CondensedArray.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CondensedArray.js","names":["useTranslation"],"sources":["../../src/client/CondensedArray.tsx"],"sourcesContent":["'use client'\n\nimport {\n\tButton,\n\tFieldDescription,\n\tFieldLabel,\n\tRenderCustomComponent,\n\tRenderFields,\n\tuseField,\n\tuseForm,\n} from '@payloadcms/ui'\nimport type { ArrayFieldClientComponent } from 'payload'\nimport { keys } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\nimport './admin.css'\n\nconst baseClass = 'fb-condensed-array'\n\n/**\n * A custom `Field` for a real Payload `array` that renders its rows flat: each row is `[label, email]`\n * laid out at 50% width with a remove control, added by a footer button, and never wrapped in the\n * per-row `Collapsible` that Payload's native array applies unconditionally. Row ids and per-locale\n * storage stay Payload's: rows come from `useField({ hasRows: true })`, mutations go through\n * `useForm`'s `addFieldRow`/`removeFieldRow`, and each row's subfields render through `RenderFields`\n * at `{path}.{index}` exactly as the native array does, so localization, validation, and descriptions\n * work natively. Placed by {@link departmentsField}.\n */\nexport const CondensedArray: ArrayFieldClientComponent = (props) => {\n\tconst {\n\t\tfield: { name, admin: { description } = {}, fields, label, localized },\n\t\tforceRender = false,\n\t\tpath: pathFromProps,\n\t\tpermissions,\n\t\treadOnly,\n\t\tschemaPath: schemaPathFromProps,\n\t} = props\n\tconst schemaPath = schemaPathFromProps ?? name\n\n\tconst { t } = useTranslation()\n\tconst { addFieldRow, removeFieldRow } = useForm()\n\tconst {\n\t\tcustomComponents: { Description, Label } = {},\n\t\tpath,\n\t\trows = [],\n\t} = useField<number>({ hasRows: true, potentiallyStalePath: pathFromProps })\n\n\treturn (\n\t\t<div className={`field-type ${baseClass}`} id={`field-${path.replace(/\\./g, '__')}`}>\n\t\t\t<RenderCustomComponent\n\t\t\t\tCustomComponent={Label}\n\t\t\t\tFallback={<FieldLabel label={label} localized={localized} path={path} />}\n\t\t\t/>\n\t\t\t<RenderCustomComponent\n\t\t\t\tCustomComponent={Description}\n\t\t\t\tFallback={<FieldDescription description={description} path={path} />}\n\t\t\t/>\n\t\t\t{rows.length > 0 ? (\n\t\t\t\t<div className={`${baseClass}__rows`}>\n\t\t\t\t\t{rows.map((row, index) => (\n\t\t\t\t\t\t<div key={row.id} className={`${baseClass}__row`}>\n\t\t\t\t\t\t\t<RenderFields\n\t\t\t\t\t\t\t\tclassName={`${baseClass}__fields`}\n\t\t\t\t\t\t\t\tfields={fields}\n\t\t\t\t\t\t\t\tforceRender={forceRender}\n\t\t\t\t\t\t\t\tmargins={false}\n\t\t\t\t\t\t\t\tparentIndexPath=\"\"\n\t\t\t\t\t\t\t\tparentPath={`${path}.${index}`}\n\t\t\t\t\t\t\t\tparentSchemaPath={schemaPath}\n\t\t\t\t\t\t\t\tpermissions={permissions === true ? permissions : (permissions?.fields ?? {})}\n\t\t\t\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{!readOnly ? (\n\t\t\t\t\t\t\t\t<div className={`${baseClass}__remove`}>\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\t\t\t\t\t\ticon=\"x\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => removeFieldRow({ path, rowIndex: index })}\n\t\t\t\t\t\t\t\t\t\taria-label={t(keys.departmentRemoveRow)}\n\t\t\t\t\t\t\t\t\t\tmargin={false}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t{!readOnly ? (\n\t\t\t\t<div className={`${baseClass}__actions`}>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\t\tonClick={() => addFieldRow({ path, rowIndex: rows.length, schemaPath })}\n\t\t\t\t\t\tmargin={false}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(keys.departmentAddRow)}\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t)\n}\n"],"mappings":";;;;;;;AAgBA,MAAM,YAAY;;;;;;;;;;AAWlB,MAAa,kBAA6C,UAAU;CACnE,MAAM,EACL,OAAO,EAAE,MAAM,OAAO,EAAE,gBAAgB,CAAC,GAAG,QAAQ,OAAO,aAC3D,cAAc,OACd,MAAM,eACN,aACA,UACA,YAAY,wBACT;CACJ,MAAM,aAAa,uBAAuB;CAE1C,MAAM,EAAE,MAAMA,iBAAe;CAC7B,MAAM,EAAE,aAAa,mBAAmB,QAAQ;CAChD,MAAM,EACL,kBAAkB,EAAE,aAAa,UAAU,CAAC,GAC5C,MACA,OAAO,CAAC,MACL,SAAiB;EAAE,SAAS;EAAM,sBAAsB;CAAc,CAAC;CAE3E,OACC,qBAAC,OAAD;EAAK,WAAW,cAAc;EAAa,IAAI,SAAS,KAAK,QAAQ,OAAO,IAAI;YAAhF;GACC,oBAAC,uBAAD;IACC,iBAAiB;IACjB,UAAU,oBAAC,YAAD;KAAmB;KAAkB;KAAiB;IAAO,CAAA;GACvE,CAAA;GACD,oBAAC,uBAAD;IACC,iBAAiB;IACjB,UAAU,oBAAC,kBAAD;KAA+B;KAAmB;IAAO,CAAA;GACnE,CAAA;GACA,KAAK,SAAS,IACd,oBAAC,OAAD;IAAK,WAAW,GAAG,UAAU;cAC3B,KAAK,KAAK,KAAK,UACf,qBAAC,OAAD;KAAkB,WAAW,GAAG,UAAU;eAA1C,CACC,oBAAC,cAAD;MACC,WAAW,GAAG,UAAU;MAChB;MACK;MACb,SAAS;MACT,iBAAgB;MAChB,YAAY,GAAG,KAAK,GAAG;MACvB,kBAAkB;MAClB,aAAa,gBAAgB,OAAO,cAAe,aAAa,UAAU,CAAC;MACjE;KACV,CAAA,GACA,CAAC,WACD,oBAAC,OAAD;MAAK,WAAW,GAAG,UAAU;gBAC5B,oBAAC,QAAD;OACC,aAAY;OACZ,MAAK;OACL,eAAe,eAAe;QAAE;QAAM,UAAU;OAAM,CAAC;OACvD,cAAY,EAAE,KAAK,mBAAmB;OACtC,QAAQ;MACR,CAAA;KACG,CAAA,IACF,IACA;OAvBK,IAAI,EAuBT,CACL;GACG,CAAA,IACF;GACH,CAAC,WACD,oBAAC,OAAD;IAAK,WAAW,GAAG,UAAU;cAC5B,oBAAC,QAAD;KACC,aAAY;KACZ,MAAK;KACL,WAAU;KACV,cAAa;KACb,eAAe,YAAY;MAAE;MAAM,UAAU,KAAK;MAAQ;KAAW,CAAC;KACtE,QAAQ;eAEP,EAAE,KAAK,gBAAgB;IACjB,CAAA;GACJ,CAAA,IACF;EACA;;AAEP"}
@@ -6,8 +6,9 @@ import { operandFromRow } from "./synthesizeClientField.js";
6
6
  import { ConditionRow } from "./ConditionRow.js";
7
7
  import { reduceFieldsToValues, transformWhereQuery } from "payload/shared";
8
8
  import { Button, useFormFields } from "@payloadcms/ui";
9
- import { useMemo } from "react";
10
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { useMemo } from "react";
11
+ import "./admin.css";
11
12
  //#region src/client/ConditionBuilder.tsx
12
13
  const toRow = (constraint) => {
13
14
  const field = Object.keys(constraint)[0];
@@ -1 +1 @@
1
- {"version":3,"file":"ConditionBuilder.js","names":["useTranslation"],"sources":["../../src/client/ConditionBuilder.tsx"],"sourcesContent":["'use client'\n\nimport { Button, useFormFields } from '@payloadcms/ui'\nimport type { Operator, Where } from 'payload'\nimport { reduceFieldsToValues, transformWhereQuery } from 'payload/shared'\nimport { useMemo } from 'react'\nimport { type ConditionFieldType, firstOperatorFor } from '../conditions/fieldTypes'\nimport { keys } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\nimport { ConditionRow, type RowCondition } from './ConditionRow'\nimport { type ConditionOperand, type FieldRow, operandFromRow } from './synthesizeClientField'\n\nexport type ConditionBuilderProps = {\n\tvalue?: Where\n\tonChange: (next: Where) => void\n\tconditionTypes: Record<string, ConditionFieldType>\n\t/** This field's own machine name, excluded from the operand list (a field cannot condition on itself). */\n\tselfName?: string\n}\n\nconst toRow = (constraint: Record<string, unknown>): RowCondition | null => {\n\tconst field = Object.keys(constraint)[0]\n\tif (!field) {\n\t\treturn null\n\t}\n\tconst ops = constraint[field] as Record<string, unknown>\n\tconst operator = Object.keys(ops)[0] as Operator | undefined\n\tif (!operator) {\n\t\treturn null\n\t}\n\treturn { field, operator, value: ops[operator] }\n}\n\nconst fromRow = (row: RowCondition): Where => ({ [row.field]: { [row.operator]: row.value } })\n\nconst readGroups = (value: Where | undefined): RowCondition[][] => {\n\tif (!value || Object.keys(value).length === 0) {\n\t\treturn []\n\t}\n\tconst canonical = transformWhereQuery(value)\n\tconst or = Array.isArray(canonical.or) ? canonical.or : []\n\treturn or.map((group) => {\n\t\tconst and = Array.isArray((group as Where).and) ? ((group as Where).and as Where[]) : []\n\t\treturn and\n\t\t\t.map((constraint) => toRow(constraint as Record<string, unknown>))\n\t\t\t.filter((row): row is RowCondition => row !== null)\n\t})\n}\n\nconst writeGroups = (groups: RowCondition[][]): Where => ({\n\tor: groups.filter((group) => group.length > 0).map((group) => ({ and: group.map(fromRow) })),\n})\n\nconst operandsFromData = (\n\tdata: Record<string, unknown>,\n\tconditionTypes: Record<string, ConditionFieldType>,\n\tselfName: string | undefined\n): ConditionOperand[] => {\n\tconst rows = Array.isArray(data.fields) ? (data.fields as FieldRow[]) : []\n\treturn rows\n\t\t.map((row) => operandFromRow(row, conditionTypes))\n\t\t.filter((operand): operand is ConditionOperand => operand !== null && operand.name !== selfName)\n}\n\nexport const ConditionBuilder = ({\n\tvalue,\n\tonChange,\n\tconditionTypes,\n\tselfName,\n}: ConditionBuilderProps) => {\n\tconst { t } = useTranslation()\n\t// Serialize the operand list so the builder re-renders only when operands actually change (a field\n\t// added, renamed, retyped, or its options edited), not on every unrelated form-state update.\n\tconst operandsJson = useFormFields(([fields]) =>\n\t\tJSON.stringify(operandsFromData(reduceFieldsToValues(fields, true), conditionTypes, selfName))\n\t)\n\tconst operands = useMemo(() => JSON.parse(operandsJson) as ConditionOperand[], [operandsJson])\n\n\tconst groups = readGroups(value)\n\tconst emit = (next: RowCondition[][]) => onChange(writeGroups(next))\n\n\tconst addCondition = (groupIndex: number) => {\n\t\tconst first = operands[0]\n\t\tif (!first) {\n\t\t\treturn\n\t\t}\n\t\tconst row: RowCondition = {\n\t\t\tfield: first.name,\n\t\t\toperator: firstOperatorFor(first.conditionType),\n\t\t\tvalue: undefined,\n\t\t}\n\t\temit(\n\t\t\tgroups.length === 0\n\t\t\t\t? [[row]]\n\t\t\t\t: groups.map((group, index) => (index === groupIndex ? [...group, row] : group))\n\t\t)\n\t}\n\n\tconst addOrGroup = () => {\n\t\tconst first = operands[0]\n\t\tif (!first) {\n\t\t\treturn\n\t\t}\n\t\temit([\n\t\t\t...groups,\n\t\t\t[{ field: first.name, operator: firstOperatorFor(first.conditionType), value: undefined }],\n\t\t])\n\t}\n\n\tconst updateRow = (groupIndex: number, rowIndex: number, row: RowCondition) =>\n\t\temit(\n\t\t\tgroups.map((group, index) =>\n\t\t\t\tindex === groupIndex\n\t\t\t\t\t? group.map((existing, position) => (position === rowIndex ? row : existing))\n\t\t\t\t\t: group\n\t\t\t)\n\t\t)\n\n\tconst removeRow = (groupIndex: number, rowIndex: number) =>\n\t\temit(\n\t\t\tgroups\n\t\t\t\t.map((group, index) =>\n\t\t\t\t\tindex === groupIndex ? group.filter((_, position) => position !== rowIndex) : group\n\t\t\t\t)\n\t\t\t\t.filter((group) => group.length > 0)\n\t\t)\n\n\tif (operands.length === 0) {\n\t\treturn <p className=\"fb-condition-builder__hint\">{t(keys.conditionNoFields)}</p>\n\t}\n\n\treturn (\n\t\t<div className=\"fb-condition-builder\">\n\t\t\t{groups.length === 0 ? (\n\t\t\t\t<p className=\"fb-condition-builder__hint\">{t(keys.conditionEmpty)}</p>\n\t\t\t) : (\n\t\t\t\tgroups.map((group, groupIndex) => (\n\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: groups are positional and never reordered\n\t\t\t\t\t<div key={groupIndex} className=\"fb-condition-builder__group\">\n\t\t\t\t\t\t{groupIndex > 0 ? (\n\t\t\t\t\t\t\t<div className=\"fb-condition-builder__or-label\">{t(keys.conditionOr)}</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{group.map((row, rowIndex) => (\n\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and never reordered\n\t\t\t\t\t\t\t<div key={rowIndex} className=\"fb-condition-builder__and-row\">\n\t\t\t\t\t\t\t\t{rowIndex > 0 ? (\n\t\t\t\t\t\t\t\t\t<span className=\"fb-condition-builder__and-label\">{t(keys.conditionAnd)}</span>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t<ConditionRow\n\t\t\t\t\t\t\t\t\tcondition={row}\n\t\t\t\t\t\t\t\t\toperands={operands}\n\t\t\t\t\t\t\t\t\tonChange={(next) => updateRow(groupIndex, rowIndex, next)}\n\t\t\t\t\t\t\t\t\tonRemove={() => removeRow(groupIndex, rowIndex)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<div className=\"fb-condition-builder__add-condition\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\t\t\t\tonClick={() => addCondition(groupIndex)}\n\t\t\t\t\t\t\t\tmargin={false}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(keys.conditionAddCondition)}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t))\n\t\t\t)}\n\t\t\t<div className=\"fb-condition-builder__actions\">\n\t\t\t\t<Button\n\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\tonClick={() => (groups.length === 0 ? addCondition(0) : addOrGroup())}\n\t\t\t\t\tmargin={false}\n\t\t\t\t>\n\t\t\t\t\t{groups.length === 0 ? t(keys.conditionAddCondition) : t(keys.conditionAddOr)}\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ConditionBuilder.js","names":["useTranslation"],"sources":["../../src/client/ConditionBuilder.tsx"],"sourcesContent":["'use client'\n\nimport { Button, useFormFields } from '@payloadcms/ui'\nimport type { Operator, Where } from 'payload'\nimport { reduceFieldsToValues, transformWhereQuery } from 'payload/shared'\nimport { useMemo } from 'react'\nimport { type ConditionFieldType, firstOperatorFor } from '../conditions/fieldTypes'\nimport { keys } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\nimport { ConditionRow, type RowCondition } from './ConditionRow'\nimport { type ConditionOperand, type FieldRow, operandFromRow } from './synthesizeClientField'\nimport './admin.css'\n\nexport type ConditionBuilderProps = {\n\tvalue?: Where\n\tonChange: (next: Where) => void\n\tconditionTypes: Record<string, ConditionFieldType>\n\t/** This field's own machine name, excluded from the operand list (a field cannot condition on itself). */\n\tselfName?: string\n}\n\nconst toRow = (constraint: Record<string, unknown>): RowCondition | null => {\n\tconst field = Object.keys(constraint)[0]\n\tif (!field) {\n\t\treturn null\n\t}\n\tconst ops = constraint[field] as Record<string, unknown>\n\tconst operator = Object.keys(ops)[0] as Operator | undefined\n\tif (!operator) {\n\t\treturn null\n\t}\n\treturn { field, operator, value: ops[operator] }\n}\n\nconst fromRow = (row: RowCondition): Where => ({ [row.field]: { [row.operator]: row.value } })\n\nconst readGroups = (value: Where | undefined): RowCondition[][] => {\n\tif (!value || Object.keys(value).length === 0) {\n\t\treturn []\n\t}\n\tconst canonical = transformWhereQuery(value)\n\tconst or = Array.isArray(canonical.or) ? canonical.or : []\n\treturn or.map((group) => {\n\t\tconst and = Array.isArray((group as Where).and) ? ((group as Where).and as Where[]) : []\n\t\treturn and\n\t\t\t.map((constraint) => toRow(constraint as Record<string, unknown>))\n\t\t\t.filter((row): row is RowCondition => row !== null)\n\t})\n}\n\nconst writeGroups = (groups: RowCondition[][]): Where => ({\n\tor: groups.filter((group) => group.length > 0).map((group) => ({ and: group.map(fromRow) })),\n})\n\nconst operandsFromData = (\n\tdata: Record<string, unknown>,\n\tconditionTypes: Record<string, ConditionFieldType>,\n\tselfName: string | undefined\n): ConditionOperand[] => {\n\tconst rows = Array.isArray(data.fields) ? (data.fields as FieldRow[]) : []\n\treturn rows\n\t\t.map((row) => operandFromRow(row, conditionTypes))\n\t\t.filter((operand): operand is ConditionOperand => operand !== null && operand.name !== selfName)\n}\n\nexport const ConditionBuilder = ({\n\tvalue,\n\tonChange,\n\tconditionTypes,\n\tselfName,\n}: ConditionBuilderProps) => {\n\tconst { t } = useTranslation()\n\t// Serialize the operand list so the builder re-renders only when operands actually change (a field\n\t// added, renamed, retyped, or its options edited), not on every unrelated form-state update.\n\tconst operandsJson = useFormFields(([fields]) =>\n\t\tJSON.stringify(operandsFromData(reduceFieldsToValues(fields, true), conditionTypes, selfName))\n\t)\n\tconst operands = useMemo(() => JSON.parse(operandsJson) as ConditionOperand[], [operandsJson])\n\n\tconst groups = readGroups(value)\n\tconst emit = (next: RowCondition[][]) => onChange(writeGroups(next))\n\n\tconst addCondition = (groupIndex: number) => {\n\t\tconst first = operands[0]\n\t\tif (!first) {\n\t\t\treturn\n\t\t}\n\t\tconst row: RowCondition = {\n\t\t\tfield: first.name,\n\t\t\toperator: firstOperatorFor(first.conditionType),\n\t\t\tvalue: undefined,\n\t\t}\n\t\temit(\n\t\t\tgroups.length === 0\n\t\t\t\t? [[row]]\n\t\t\t\t: groups.map((group, index) => (index === groupIndex ? [...group, row] : group))\n\t\t)\n\t}\n\n\tconst addOrGroup = () => {\n\t\tconst first = operands[0]\n\t\tif (!first) {\n\t\t\treturn\n\t\t}\n\t\temit([\n\t\t\t...groups,\n\t\t\t[{ field: first.name, operator: firstOperatorFor(first.conditionType), value: undefined }],\n\t\t])\n\t}\n\n\tconst updateRow = (groupIndex: number, rowIndex: number, row: RowCondition) =>\n\t\temit(\n\t\t\tgroups.map((group, index) =>\n\t\t\t\tindex === groupIndex\n\t\t\t\t\t? group.map((existing, position) => (position === rowIndex ? row : existing))\n\t\t\t\t\t: group\n\t\t\t)\n\t\t)\n\n\tconst removeRow = (groupIndex: number, rowIndex: number) =>\n\t\temit(\n\t\t\tgroups\n\t\t\t\t.map((group, index) =>\n\t\t\t\t\tindex === groupIndex ? group.filter((_, position) => position !== rowIndex) : group\n\t\t\t\t)\n\t\t\t\t.filter((group) => group.length > 0)\n\t\t)\n\n\tif (operands.length === 0) {\n\t\treturn <p className=\"fb-condition-builder__hint\">{t(keys.conditionNoFields)}</p>\n\t}\n\n\treturn (\n\t\t<div className=\"fb-condition-builder\">\n\t\t\t{groups.length === 0 ? (\n\t\t\t\t<p className=\"fb-condition-builder__hint\">{t(keys.conditionEmpty)}</p>\n\t\t\t) : (\n\t\t\t\tgroups.map((group, groupIndex) => (\n\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: groups are positional and never reordered\n\t\t\t\t\t<div key={groupIndex} className=\"fb-condition-builder__group\">\n\t\t\t\t\t\t{groupIndex > 0 ? (\n\t\t\t\t\t\t\t<div className=\"fb-condition-builder__or-label\">{t(keys.conditionOr)}</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{group.map((row, rowIndex) => (\n\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and never reordered\n\t\t\t\t\t\t\t<div key={rowIndex} className=\"fb-condition-builder__and-row\">\n\t\t\t\t\t\t\t\t{rowIndex > 0 ? (\n\t\t\t\t\t\t\t\t\t<span className=\"fb-condition-builder__and-label\">{t(keys.conditionAnd)}</span>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t<ConditionRow\n\t\t\t\t\t\t\t\t\tcondition={row}\n\t\t\t\t\t\t\t\t\toperands={operands}\n\t\t\t\t\t\t\t\t\tonChange={(next) => updateRow(groupIndex, rowIndex, next)}\n\t\t\t\t\t\t\t\t\tonRemove={() => removeRow(groupIndex, rowIndex)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<div className=\"fb-condition-builder__add-condition\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\t\t\t\tonClick={() => addCondition(groupIndex)}\n\t\t\t\t\t\t\t\tmargin={false}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(keys.conditionAddCondition)}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t))\n\t\t\t)}\n\t\t\t<div className=\"fb-condition-builder__actions\">\n\t\t\t\t<Button\n\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\tonClick={() => (groups.length === 0 ? addCondition(0) : addOrGroup())}\n\t\t\t\t\tmargin={false}\n\t\t\t\t>\n\t\t\t\t\t{groups.length === 0 ? t(keys.conditionAddCondition) : t(keys.conditionAddOr)}\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ //#region src/client/ConsentBlockLabel.d.ts
2
+ /**
3
+ * Block row header for a consent field. The consent field stores only the source id, so this resolves
4
+ * it to the source's name via the same `consent-sources` endpoint the Source select uses, rendering
5
+ * "NN Consent {name}". Falls back to "NN Consent" while loading, when unset, or on an unsaved form
6
+ * (no document id yet, so the endpoint cannot resolve options).
7
+ */
8
+ declare const ConsentBlockLabel: ({
9
+ typeLabelKey
10
+ }: {
11
+ typeLabelKey?: string;
12
+ }) => import("react/jsx-runtime").JSX.Element;
13
+ //#endregion
14
+ export { ConsentBlockLabel };
15
+ //# sourceMappingURL=ConsentBlockLabel.d.ts.map
@@ -0,0 +1,71 @@
1
+ "use client";
2
+ import { useTranslation as useTranslation$1 } from "../translations/useTranslation.js";
3
+ import { buildEndpointOptionsUrl, parseEndpointOptions } from "./endpointOptions.js";
4
+ import { useConfig, useDocumentInfo, useRowLabel } from "@payloadcms/ui";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useEffect, useState } from "react";
7
+ //#region src/client/ConsentBlockLabel.tsx
8
+ /** Endpoint url -> `{ sourceId: name }`, shared across every consent block label and re-render. */
9
+ const nameCache = /* @__PURE__ */ new Map();
10
+ /**
11
+ * Block row header for a consent field. The consent field stores only the source id, so this resolves
12
+ * it to the source's name via the same `consent-sources` endpoint the Source select uses, rendering
13
+ * "NN Consent {name}". Falls back to "NN Consent" while loading, when unset, or on an unsaved form
14
+ * (no document id yet, so the endpoint cannot resolve options).
15
+ */
16
+ const ConsentBlockLabel = ({ typeLabelKey }) => {
17
+ const { data, rowNumber } = useRowLabel();
18
+ const { t } = useTranslation$1();
19
+ const { id, collectionSlug } = useDocumentInfo();
20
+ const { config } = useConfig();
21
+ const source = typeof data?.source === "string" ? data.source : "";
22
+ const [names, setNames] = useState({});
23
+ useEffect(() => {
24
+ if (id == null || !collectionSlug) return;
25
+ const url = buildEndpointOptionsUrl({
26
+ apiRoute: config.routes.api,
27
+ collectionSlug,
28
+ id,
29
+ endpoint: "consent-sources"
30
+ });
31
+ const cached = nameCache.get(url);
32
+ if (cached) {
33
+ setNames(cached);
34
+ return;
35
+ }
36
+ const controller = new AbortController();
37
+ fetch(url, {
38
+ credentials: "include",
39
+ headers: { Accept: "application/json" },
40
+ signal: controller.signal
41
+ }).then(async (response) => {
42
+ if (!response.ok) throw new Error(`Options request failed with ${response.status}`);
43
+ const map = Object.fromEntries(parseEndpointOptions(await response.json()).map((o) => [o.value, o.label]));
44
+ nameCache.set(url, map);
45
+ setNames(map);
46
+ }).catch(() => {});
47
+ return () => controller.abort();
48
+ }, [
49
+ config.routes.api,
50
+ collectionSlug,
51
+ id
52
+ ]);
53
+ const typeLabel = typeLabelKey ? t(typeLabelKey) : "";
54
+ const number = String((rowNumber ?? 0) + 1).padStart(2, "0");
55
+ const name = source ? names[source] ?? "" : "";
56
+ return /* @__PURE__ */ jsxs("span", {
57
+ style: {
58
+ alignItems: "center",
59
+ display: "inline-flex",
60
+ gap: "0.5rem"
61
+ },
62
+ children: [/* @__PURE__ */ jsx("span", {
63
+ style: { color: "var(--theme-elevation-500)" },
64
+ children: typeLabel ? `${number} ${typeLabel}` : number
65
+ }), name ? /* @__PURE__ */ jsx("span", { children: name }) : null]
66
+ });
67
+ };
68
+ //#endregion
69
+ export { ConsentBlockLabel };
70
+
71
+ //# sourceMappingURL=ConsentBlockLabel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentBlockLabel.js","names":["useTranslation"],"sources":["../../src/client/ConsentBlockLabel.tsx"],"sourcesContent":["'use client'\n\nimport { useConfig, useDocumentInfo, useRowLabel } from '@payloadcms/ui'\nimport { useEffect, useState } from 'react'\nimport type { TranslationKey } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\nimport { buildEndpointOptionsUrl, parseEndpointOptions } from './endpointOptions'\n\ntype RowData = { source?: unknown }\n\n/** Endpoint url -> `{ sourceId: name }`, shared across every consent block label and re-render. */\nconst nameCache = new Map<string, Record<string, string>>()\n\n/**\n * Block row header for a consent field. The consent field stores only the source id, so this resolves\n * it to the source's name via the same `consent-sources` endpoint the Source select uses, rendering\n * \"NN Consent {name}\". Falls back to \"NN Consent\" while loading, when unset, or on an unsaved form\n * (no document id yet, so the endpoint cannot resolve options).\n */\nexport const ConsentBlockLabel = ({ typeLabelKey }: { typeLabelKey?: string }) => {\n\tconst { data, rowNumber } = useRowLabel<RowData>()\n\tconst { t } = useTranslation()\n\tconst { id, collectionSlug } = useDocumentInfo()\n\tconst { config } = useConfig()\n\tconst source = typeof data?.source === 'string' ? data.source : ''\n\tconst [names, setNames] = useState<Record<string, string>>({})\n\n\tuseEffect(() => {\n\t\tif (id == null || !collectionSlug) {\n\t\t\treturn\n\t\t}\n\t\tconst url = buildEndpointOptionsUrl({\n\t\t\tapiRoute: config.routes.api,\n\t\t\tcollectionSlug,\n\t\t\tid,\n\t\t\tendpoint: 'consent-sources',\n\t\t})\n\t\tconst cached = nameCache.get(url)\n\t\tif (cached) {\n\t\t\tsetNames(cached)\n\t\t\treturn\n\t\t}\n\t\tconst controller = new AbortController()\n\t\tfetch(url, {\n\t\t\tcredentials: 'include',\n\t\t\theaders: { Accept: 'application/json' },\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\t\t.then(async (response) => {\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`Options request failed with ${response.status}`)\n\t\t\t\t}\n\t\t\t\tconst map = Object.fromEntries(\n\t\t\t\t\tparseEndpointOptions(await response.json()).map((o) => [o.value, o.label])\n\t\t\t\t)\n\t\t\t\tnameCache.set(url, map)\n\t\t\t\tsetNames(map)\n\t\t\t})\n\t\t\t.catch(() => {})\n\t\treturn () => controller.abort()\n\t}, [config.routes.api, collectionSlug, id])\n\n\tconst typeLabel = typeLabelKey ? t(typeLabelKey as TranslationKey) : ''\n\tconst number = String((rowNumber ?? 0) + 1).padStart(2, '0')\n\tconst name = source ? (names[source] ?? '') : ''\n\treturn (\n\t\t<span style={{ alignItems: 'center', display: 'inline-flex', gap: '0.5rem' }}>\n\t\t\t<span style={{ color: 'var(--theme-elevation-500)' }}>\n\t\t\t\t{typeLabel ? `${number} ${typeLabel}` : number}\n\t\t\t</span>\n\t\t\t{name ? <span>{name}</span> : null}\n\t\t</span>\n\t)\n}\n"],"mappings":";;;;;;;;AAWA,MAAM,4BAAY,IAAI,IAAoC;;;;;;;AAQ1D,MAAa,qBAAqB,EAAE,mBAA8C;CACjF,MAAM,EAAE,MAAM,cAAc,YAAqB;CACjD,MAAM,EAAE,MAAMA,iBAAe;CAC7B,MAAM,EAAE,IAAI,mBAAmB,gBAAgB;CAC/C,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,SAAS,OAAO,MAAM,WAAW,WAAW,KAAK,SAAS;CAChE,MAAM,CAAC,OAAO,YAAY,SAAiC,CAAC,CAAC;CAE7D,gBAAgB;EACf,IAAI,MAAM,QAAQ,CAAC,gBAClB;EAED,MAAM,MAAM,wBAAwB;GACnC,UAAU,OAAO,OAAO;GACxB;GACA;GACA,UAAU;EACX,CAAC;EACD,MAAM,SAAS,UAAU,IAAI,GAAG;EAChC,IAAI,QAAQ;GACX,SAAS,MAAM;GACf;EACD;EACA,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,KAAK;GACV,aAAa;GACb,SAAS,EAAE,QAAQ,mBAAmB;GACtC,QAAQ,WAAW;EACpB,CAAC,EACC,KAAK,OAAO,aAAa;GACzB,IAAI,CAAC,SAAS,IACb,MAAM,IAAI,MAAM,+BAA+B,SAAS,QAAQ;GAEjE,MAAM,MAAM,OAAO,YAClB,qBAAqB,MAAM,SAAS,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,CAC1E;GACA,UAAU,IAAI,KAAK,GAAG;GACtB,SAAS,GAAG;EACb,CAAC,EACA,YAAY,CAAC,CAAC;EAChB,aAAa,WAAW,MAAM;CAC/B,GAAG;EAAC,OAAO,OAAO;EAAK;EAAgB;CAAE,CAAC;CAE1C,MAAM,YAAY,eAAe,EAAE,YAA8B,IAAI;CACrE,MAAM,SAAS,QAAQ,aAAa,KAAK,CAAC,EAAE,SAAS,GAAG,GAAG;CAC3D,MAAM,OAAO,SAAU,MAAM,WAAW,KAAM;CAC9C,OACC,qBAAC,QAAD;EAAM,OAAO;GAAE,YAAY;GAAU,SAAS;GAAe,KAAK;EAAS;YAA3E,CACC,oBAAC,QAAD;GAAM,OAAO,EAAE,OAAO,6BAA6B;aACjD,YAAY,GAAG,OAAO,GAAG,cAAc;EACnC,CAAA,GACL,OAAO,oBAAC,QAAD,EAAA,UAAO,KAAW,CAAA,IAAI,IACzB;;AAER"}
@@ -0,0 +1,9 @@
1
+ //#region src/client/ConsentSourceRowLabel.d.ts
2
+ /**
3
+ * Row header for a consent source array row: shows the source `name` (e.g. "Privacy Policy") instead
4
+ * of Payload's default "Consent source NN". Falls back to the singular label + number while unnamed.
5
+ */
6
+ declare const ConsentSourceRowLabel: () => import("react/jsx-runtime").JSX.Element;
7
+ //#endregion
8
+ export { ConsentSourceRowLabel };
9
+ //# sourceMappingURL=ConsentSourceRowLabel.d.ts.map
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { keys } from "../translations/keys.js";
3
+ import { useTranslation as useTranslation$1 } from "../translations/useTranslation.js";
4
+ import { useRowLabel } from "@payloadcms/ui";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/client/ConsentSourceRowLabel.tsx
7
+ /**
8
+ * Row header for a consent source array row: shows the source `name` (e.g. "Privacy Policy") instead
9
+ * of Payload's default "Consent source NN". Falls back to the singular label + number while unnamed.
10
+ */
11
+ const ConsentSourceRowLabel = () => {
12
+ const { data, rowNumber } = useRowLabel();
13
+ const { t } = useTranslation$1();
14
+ const name = typeof data?.name === "string" && data.name.trim().length > 0 ? data.name.trim() : "";
15
+ const number = String((rowNumber ?? 0) + 1).padStart(2, "0");
16
+ return /* @__PURE__ */ jsx("span", { children: name || `${t(keys.consentSourceSingular)} ${number}` });
17
+ };
18
+ //#endregion
19
+ export { ConsentSourceRowLabel };
20
+
21
+ //# sourceMappingURL=ConsentSourceRowLabel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentSourceRowLabel.js","names":["useTranslation"],"sources":["../../src/client/ConsentSourceRowLabel.tsx"],"sourcesContent":["'use client'\n\nimport { useRowLabel } from '@payloadcms/ui'\nimport { keys } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\n\ntype RowData = { name?: unknown }\n\n/**\n * Row header for a consent source array row: shows the source `name` (e.g. \"Privacy Policy\") instead\n * of Payload's default \"Consent source NN\". Falls back to the singular label + number while unnamed.\n */\nexport const ConsentSourceRowLabel = () => {\n\tconst { data, rowNumber } = useRowLabel<RowData>()\n\tconst { t } = useTranslation()\n\tconst name = typeof data?.name === 'string' && data.name.trim().length > 0 ? data.name.trim() : ''\n\tconst number = String((rowNumber ?? 0) + 1).padStart(2, '0')\n\treturn <span>{name || `${t(keys.consentSourceSingular)} ${number}`}</span>\n}\n"],"mappings":";;;;;;;;;;AAYA,MAAa,8BAA8B;CAC1C,MAAM,EAAE,MAAM,cAAc,YAAqB;CACjD,MAAM,EAAE,MAAMA,iBAAe;CAC7B,MAAM,OAAO,OAAO,MAAM,SAAS,YAAY,KAAK,KAAK,KAAK,EAAE,SAAS,IAAI,KAAK,KAAK,KAAK,IAAI;CAChG,MAAM,SAAS,QAAQ,aAAa,KAAK,CAAC,EAAE,SAAS,GAAG,GAAG;CAC3D,OAAO,oBAAC,QAAD,EAAA,UAAO,QAAQ,GAAG,EAAE,KAAK,qBAAqB,EAAE,GAAG,SAAe,CAAA;AAC1E"}
@@ -0,0 +1,46 @@
1
+ import { TranslationKey } from "../translations/keys.js";
2
+
3
+ //#region src/client/EndpointOptionsSelect.d.ts
4
+ /** Standard text-field client props plus this component's `clientProps`. */
5
+ type EndpointOptionsSelectProps = {
6
+ /** The field path within the document (Payload-injected, not the endpoint path). */path?: string;
7
+ field?: {
8
+ label?: unknown;
9
+ admin?: {
10
+ description?: unknown;
11
+ width?: string;
12
+ };
13
+ };
14
+ label?: unknown;
15
+ /**
16
+ * Endpoint subpath under the current document's collection API route; `'poll-options'` fetches
17
+ * `GET {routes.api}/{collectionSlug}/{id}/poll-options`. The endpoint must return
18
+ * `{ options: { label, value }[] }`.
19
+ */
20
+ endpoint: string;
21
+ /**
22
+ * Field description as a translation key, resolved client-side. Payload drops `admin.description`
23
+ * functions from client fields, so a translated description must travel as a key; a static
24
+ * `admin.description` string still renders when this is unset.
25
+ */
26
+ descriptionKey?: TranslationKey; /** Mirrors ReactSelect's `isClearable`; defaults to true. */
27
+ isClearable?: boolean;
28
+ /**
29
+ * Render a multi-value select bound to a `string[]`, for a `hasMany` field (e.g. a poll outcome
30
+ * with tied winners). Default false: a single-value select bound to a `string`.
31
+ */
32
+ isMulti?: boolean;
33
+ };
34
+ /**
35
+ * A select whose options load from a document-scoped plugin endpoint, for stored values whose
36
+ * valid choices only the server knows (e.g. a poll's source-resolved options). The pattern: pass
37
+ * `endpoint` via `clientProps`, the component reads the document id from `useDocumentInfo` and the
38
+ * API route from `useConfig`, fetches once per document with the admin cookie, and renders
39
+ * translated loading/error states. The stored value stays selectable even when it is missing from
40
+ * the fetched options (or the fetch failed), so opening an old document never silently drops data;
41
+ * unsaved documents skip the fetch since the server cannot resolve options for them yet.
42
+ */
43
+ declare const EndpointOptionsSelect: (props: EndpointOptionsSelectProps) => import("react/jsx-runtime").JSX.Element;
44
+ //#endregion
45
+ export { EndpointOptionsSelect };
46
+ //# sourceMappingURL=EndpointOptionsSelect.d.ts.map