@defra/forms-engine-plugin 4.23.0 → 5.0.0-alpha

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 (309) hide show
  1. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  2. package/.server/server/forms/simple-form.yaml +106 -3
  3. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +11 -11
  4. package/.server/server/plugins/engine/components/AutocompleteField.js +2 -2
  5. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  6. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +3 -2
  7. package/.server/server/plugins/engine/components/CheckboxesField.js +4 -9
  8. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  9. package/.server/server/plugins/engine/components/ComponentCollection.d.ts +8 -7
  10. package/.server/server/plugins/engine/components/ComponentCollection.js +106 -51
  11. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  12. package/.server/server/plugins/engine/components/DatePartsField.d.ts +8 -6
  13. package/.server/server/plugins/engine/components/DatePartsField.js +27 -9
  14. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  15. package/.server/server/plugins/engine/components/DeclarationField.d.ts +13 -11
  16. package/.server/server/plugins/engine/components/DeclarationField.js +31 -9
  17. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  18. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +6 -5
  19. package/.server/server/plugins/engine/components/EastingNorthingField.js +42 -22
  20. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  21. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +11 -14
  22. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -2
  23. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  24. package/.server/server/plugins/engine/components/FileUploadField.d.ts +14 -12
  25. package/.server/server/plugins/engine/components/FileUploadField.js +22 -12
  26. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  27. package/.server/server/plugins/engine/components/FormComponent.d.ts +21 -12
  28. package/.server/server/plugins/engine/components/FormComponent.js +33 -14
  29. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  30. package/.server/server/plugins/engine/components/GeospatialField.d.ts +14 -12
  31. package/.server/server/plugins/engine/components/GeospatialField.js +19 -13
  32. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  33. package/.server/server/plugins/engine/components/LatLongField.d.ts +6 -5
  34. package/.server/server/plugins/engine/components/LatLongField.js +32 -20
  35. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  36. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +7 -6
  37. package/.server/server/plugins/engine/components/ListFormComponent.js +19 -7
  38. package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
  39. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +17 -16
  40. package/.server/server/plugins/engine/components/LocationFieldBase.js +2 -2
  41. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  42. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +3 -3
  43. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +2 -2
  44. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  45. package/.server/server/plugins/engine/components/Markdown.d.ts +8 -7
  46. package/.server/server/plugins/engine/components/Markdown.js +5 -2
  47. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  48. package/.server/server/plugins/engine/components/MonthYearField.d.ts +9 -7
  49. package/.server/server/plugins/engine/components/MonthYearField.js +26 -8
  50. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  51. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +10 -9
  52. package/.server/server/plugins/engine/components/MultilineTextField.js +2 -2
  53. package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -1
  54. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  55. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +14 -6
  56. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  57. package/.server/server/plugins/engine/components/NumberField.d.ts +10 -9
  58. package/.server/server/plugins/engine/components/NumberField.js +2 -2
  59. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  60. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +2 -1
  61. package/.server/server/plugins/engine/components/OsGridRefField.js +14 -6
  62. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  63. package/.server/server/plugins/engine/components/PaymentField.d.ts +12 -10
  64. package/.server/server/plugins/engine/components/PaymentField.js +21 -8
  65. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  66. package/.server/server/plugins/engine/components/SelectField.d.ts +11 -11
  67. package/.server/server/plugins/engine/components/SelectField.js +2 -2
  68. package/.server/server/plugins/engine/components/SelectField.js.map +1 -1
  69. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +4 -4
  70. package/.server/server/plugins/engine/components/SelectionControlField.js +2 -2
  71. package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -1
  72. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +10 -9
  73. package/.server/server/plugins/engine/components/TelephoneNumberField.js +2 -2
  74. package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -1
  75. package/.server/server/plugins/engine/components/UkAddressField.d.ts +12 -10
  76. package/.server/server/plugins/engine/components/UkAddressField.js +29 -17
  77. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  78. package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -0
  79. package/.server/server/plugins/engine/components/YesNoField.js +9 -0
  80. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  81. package/.server/server/plugins/engine/components/helpers/components.d.ts +3 -2
  82. package/.server/server/plugins/engine/components/helpers/components.js +11 -8
  83. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  84. package/.server/server/plugins/engine/components/types.d.ts +8 -1
  85. package/.server/server/plugins/engine/components/types.js.map +1 -1
  86. package/.server/server/plugins/engine/configureEnginePlugin.js +8 -1
  87. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  88. package/.server/server/plugins/engine/form-context.d.ts +1 -0
  89. package/.server/server/plugins/engine/form-context.js +4 -2
  90. package/.server/server/plugins/engine/form-context.js.map +1 -1
  91. package/.server/server/plugins/engine/helpers.d.ts +1 -1
  92. package/.server/server/plugins/engine/helpers.js +8 -13
  93. package/.server/server/plugins/engine/helpers.js.map +1 -1
  94. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +39 -0
  95. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +50 -0
  96. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -0
  97. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +5 -0
  98. package/.server/server/plugins/engine/i18n/createFormTranslator.js +18 -0
  99. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -0
  100. package/.server/server/plugins/engine/i18n/createTranslator.d.ts +9 -0
  101. package/.server/server/plugins/engine/i18n/createTranslator.js +51 -0
  102. package/.server/server/plugins/engine/i18n/createTranslator.js.map +1 -0
  103. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +5 -0
  104. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +57 -0
  105. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -0
  106. package/.server/server/plugins/engine/i18n/index.d.ts +18 -0
  107. package/.server/server/plugins/engine/i18n/index.js +71 -0
  108. package/.server/server/plugins/engine/i18n/index.js.map +1 -0
  109. package/.server/server/plugins/engine/i18n/translations/cy.json +271 -0
  110. package/.server/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  111. package/.server/server/plugins/engine/i18n/types.d.ts +41 -0
  112. package/.server/server/plugins/engine/i18n/types.js +2 -0
  113. package/.server/server/plugins/engine/i18n/types.js.map +1 -0
  114. package/.server/server/plugins/engine/index.js +3 -2
  115. package/.server/server/plugins/engine/index.js.map +1 -1
  116. package/.server/server/plugins/engine/models/FormModel.d.ts +9 -1
  117. package/.server/server/plugins/engine/models/FormModel.js +44 -18
  118. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  119. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +5 -2
  120. package/.server/server/plugins/engine/models/SummaryViewModel.js +44 -18
  121. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  122. package/.server/server/plugins/engine/options.js +2 -1
  123. package/.server/server/plugins/engine/options.js.map +1 -1
  124. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +4 -0
  125. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  126. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  127. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  128. package/.server/server/plugins/engine/outputFormatters/machine/v1.js +7 -6
  129. package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -1
  130. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +2 -1
  131. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +6 -3
  132. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  133. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +3 -1
  134. package/.server/server/plugins/engine/pageControllers/PageController.js +11 -1
  135. package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
  136. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +4 -2
  137. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +52 -21
  138. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  139. package/.server/server/plugins/engine/pageControllers/RepeatPageController.d.ts +3 -2
  140. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +63 -26
  141. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  142. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +3 -1
  143. package/.server/server/plugins/engine/pageControllers/StartPageController.js +2 -2
  144. package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -1
  145. package/.server/server/plugins/engine/pageControllers/StatusPageController.js +12 -2
  146. package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -1
  147. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +4 -3
  148. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +44 -28
  149. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  150. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.d.ts +2 -0
  151. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js +24 -0
  152. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js.map +1 -0
  153. package/.server/server/plugins/engine/pageControllers/errors.d.ts +1 -1
  154. package/.server/server/plugins/engine/pageControllers/errors.js +3 -2
  155. package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
  156. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +3 -2
  157. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +4 -4
  158. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  159. package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +7 -3
  160. package/.server/server/plugins/engine/pageControllers/validationOptions.js +34 -33
  161. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  162. package/.server/server/plugins/engine/plugin.js +2 -0
  163. package/.server/server/plugins/engine/plugin.js.map +1 -1
  164. package/.server/server/plugins/engine/routes/index.js +4 -1
  165. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  166. package/.server/server/plugins/engine/routes/questions.js +5 -2
  167. package/.server/server/plugins/engine/routes/questions.js.map +1 -1
  168. package/.server/server/plugins/engine/types/index.d.ts +1 -0
  169. package/.server/server/plugins/engine/types/index.js.map +1 -1
  170. package/.server/server/plugins/engine/types/schema.js +1 -0
  171. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  172. package/.server/server/plugins/engine/types.d.ts +12 -1
  173. package/.server/server/plugins/engine/types.js.map +1 -1
  174. package/.server/server/plugins/engine/views/components/_location-field-base.html +1 -1
  175. package/.server/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  176. package/.server/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  177. package/.server/server/plugins/engine/views/components/osgridreffield.html +1 -1
  178. package/.server/server/plugins/engine/views/components/paymentfield.html +8 -8
  179. package/.server/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  180. package/.server/server/plugins/engine/views/confirmation.html +4 -4
  181. package/.server/server/plugins/engine/views/exit.html +4 -4
  182. package/.server/server/plugins/engine/views/file-upload.html +3 -3
  183. package/.server/server/plugins/engine/views/index.html +3 -3
  184. package/.server/server/plugins/engine/views/item-delete.html +1 -1
  185. package/.server/server/plugins/engine/views/partials/form.html +3 -3
  186. package/.server/server/plugins/engine/views/partials/preview-banner.html +4 -4
  187. package/.server/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  188. package/.server/server/plugins/engine/views/repeat-list-summary.html +4 -4
  189. package/.server/server/plugins/engine/views/summary.html +14 -7
  190. package/.server/server/plugins/nunjucks/enviroment.test.js +10 -0
  191. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
  192. package/.server/server/plugins/nunjucks/environment.d.ts +8 -0
  193. package/.server/server/plugins/nunjucks/environment.js +13 -0
  194. package/.server/server/plugins/nunjucks/environment.js.map +1 -1
  195. package/.server/server/plugins/nunjucks/filters/answer.js +9 -1
  196. package/.server/server/plugins/nunjucks/filters/answer.js.map +1 -1
  197. package/.server/server/plugins/nunjucks/filters/answer.test.js +13 -2
  198. package/.server/server/plugins/nunjucks/filters/answer.test.js.map +1 -1
  199. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  200. package/.server/server/plugins/postcode-lookup/models/index.d.ts +24 -19
  201. package/.server/server/plugins/postcode-lookup/models/index.js +83 -76
  202. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  203. package/.server/server/plugins/postcode-lookup/routes/index.js +7 -13
  204. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  205. package/.server/server/plugins/postcode-lookup/types.d.ts +1 -0
  206. package/.server/server/plugins/postcode-lookup/types.js +1 -0
  207. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  208. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  209. package/.server/server/types.d.ts +2 -1
  210. package/.server/server/types.js.map +1 -1
  211. package/.server/server/utils/utils.d.ts +5 -0
  212. package/.server/server/utils/utils.js +16 -0
  213. package/.server/server/utils/utils.js.map +1 -1
  214. package/.server/typings/hapi/index.d.js.map +1 -1
  215. package/package.json +3 -2
  216. package/src/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  217. package/src/server/forms/simple-form.yaml +106 -3
  218. package/src/server/plugins/engine/components/AutocompleteField.ts +3 -6
  219. package/src/server/plugins/engine/components/CheckboxesField.ts +12 -11
  220. package/src/server/plugins/engine/components/ComponentCollection.ts +143 -61
  221. package/src/server/plugins/engine/components/DatePartsField.ts +33 -11
  222. package/src/server/plugins/engine/components/DeclarationField.ts +37 -14
  223. package/src/server/plugins/engine/components/EastingNorthingField.ts +83 -22
  224. package/src/server/plugins/engine/components/EmailAddressField.ts +4 -7
  225. package/src/server/plugins/engine/components/FileUploadField.ts +28 -22
  226. package/src/server/plugins/engine/components/FormComponent.ts +49 -12
  227. package/src/server/plugins/engine/components/GeospatialField.ts +36 -21
  228. package/src/server/plugins/engine/components/LatLongField.ts +52 -21
  229. package/src/server/plugins/engine/components/ListFormComponent.ts +26 -10
  230. package/src/server/plugins/engine/components/LocationFieldBase.ts +5 -8
  231. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +3 -3
  232. package/src/server/plugins/engine/components/Markdown.ts +7 -3
  233. package/src/server/plugins/engine/components/MonthYearField.ts +32 -10
  234. package/src/server/plugins/engine/components/MultilineTextField.ts +5 -8
  235. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +25 -11
  236. package/src/server/plugins/engine/components/NumberField.ts +3 -4
  237. package/src/server/plugins/engine/components/OsGridRefField.ts +25 -9
  238. package/src/server/plugins/engine/components/PaymentField.ts +22 -12
  239. package/src/server/plugins/engine/components/SelectField.ts +3 -6
  240. package/src/server/plugins/engine/components/SelectionControlField.ts +7 -8
  241. package/src/server/plugins/engine/components/TelephoneNumberField.ts +4 -7
  242. package/src/server/plugins/engine/components/UkAddressField.ts +33 -18
  243. package/src/server/plugins/engine/components/YesNoField.ts +10 -0
  244. package/src/server/plugins/engine/components/helpers/components.ts +13 -6
  245. package/src/server/plugins/engine/components/types.ts +9 -0
  246. package/src/server/plugins/engine/configureEnginePlugin.ts +12 -1
  247. package/src/server/plugins/engine/form-context.ts +8 -2
  248. package/src/server/plugins/engine/helpers.ts +10 -18
  249. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +69 -0
  250. package/src/server/plugins/engine/i18n/createFormTranslator.ts +33 -0
  251. package/src/server/plugins/engine/i18n/createTranslator.ts +61 -0
  252. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +61 -0
  253. package/src/server/plugins/engine/i18n/index.ts +80 -0
  254. package/src/server/plugins/engine/i18n/translations/cy.json +271 -0
  255. package/src/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  256. package/src/server/plugins/engine/i18n/types.ts +62 -0
  257. package/src/server/plugins/engine/index.ts +4 -2
  258. package/src/server/plugins/engine/models/FormModel.ts +59 -23
  259. package/src/server/plugins/engine/models/SummaryViewModel.ts +68 -25
  260. package/src/server/plugins/engine/options.js +2 -1
  261. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +5 -0
  262. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -3
  263. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +9 -8
  264. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +7 -3
  265. package/src/server/plugins/engine/pageControllers/PageController.ts +12 -1
  266. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +53 -21
  267. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +66 -29
  268. package/src/server/plugins/engine/pageControllers/StartPageController.ts +7 -2
  269. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +10 -2
  270. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +48 -22
  271. package/src/server/plugins/engine/pageControllers/__stubs__/translator.ts +28 -0
  272. package/src/server/plugins/engine/pageControllers/errors.ts +4 -2
  273. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +11 -4
  274. package/src/server/plugins/engine/pageControllers/validationOptions.ts +43 -53
  275. package/src/server/plugins/engine/plugin.ts +2 -0
  276. package/src/server/plugins/engine/routes/index.ts +9 -1
  277. package/src/server/plugins/engine/routes/questions.ts +5 -1
  278. package/src/server/plugins/engine/types/index.ts +5 -0
  279. package/src/server/plugins/engine/types/schema.ts +1 -0
  280. package/src/server/plugins/engine/types.ts +10 -0
  281. package/src/server/plugins/engine/views/components/_location-field-base.html +1 -1
  282. package/src/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  283. package/src/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  284. package/src/server/plugins/engine/views/components/osgridreffield.html +1 -1
  285. package/src/server/plugins/engine/views/components/paymentfield.html +8 -8
  286. package/src/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  287. package/src/server/plugins/engine/views/confirmation.html +4 -4
  288. package/src/server/plugins/engine/views/exit.html +4 -4
  289. package/src/server/plugins/engine/views/file-upload.html +3 -3
  290. package/src/server/plugins/engine/views/index.html +3 -3
  291. package/src/server/plugins/engine/views/item-delete.html +1 -1
  292. package/src/server/plugins/engine/views/partials/form.html +3 -3
  293. package/src/server/plugins/engine/views/partials/preview-banner.html +4 -4
  294. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  295. package/src/server/plugins/engine/views/repeat-list-summary.html +4 -4
  296. package/src/server/plugins/engine/views/summary.html +14 -7
  297. package/src/server/plugins/nunjucks/environment.js +14 -0
  298. package/src/server/plugins/nunjucks/filters/answer.js +12 -1
  299. package/src/server/plugins/postcode-lookup/models/index.js +144 -87
  300. package/src/server/plugins/postcode-lookup/routes/index.js +13 -16
  301. package/src/server/plugins/postcode-lookup/types.js +1 -0
  302. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  303. package/src/server/types.ts +2 -0
  304. package/src/server/utils/utils.js +14 -0
  305. package/src/typings/hapi/index.d.ts +1 -0
  306. package/.server/server/plugins/engine/components/constants.d.ts +0 -1
  307. package/.server/server/plugins/engine/components/constants.js +0 -2
  308. package/.server/server/plugins/engine/components/constants.js.map +0 -1
  309. package/src/server/plugins/engine/components/constants.ts +0 -1
@@ -3,6 +3,57 @@ name: Page events
3
3
  engine: V2
4
4
  schema: 2
5
5
  startPage: '/summary'
6
+ metadata:
7
+ language: en-GB
8
+ translations:
9
+ cy:
10
+ components:
11
+ 1fb8e182-c709-4792-8f83-e01d8b1fee1a:
12
+ title: Beth yw eich enw cyntaf?
13
+ shortDescription: Eich enw cyntaf
14
+ b68df7f1-d4f4-4c17-83c8-402f584906c9:
15
+ title: Beth yw eich enw olaf?
16
+ shortDescription: Eich enw olaf
17
+ 987c1234-56d7-89e0-1234-56789abcdef0:
18
+ title: Llwytho copi o'ch pasbort
19
+ shortDescription: Llwytho pasbort
20
+ 987c1234-56d7-89e0-1234-56789abcdef1:
21
+ title: Llwytho copi o'ch trwydded yrru
22
+ shortDescription: Llwytho trwydded yrru
23
+ 00738799-3489-4ab2-a57b-542eecb31bfa:
24
+ title: Pryd yw pen-blwydd {{ applicantFirstName }} {{ applicantLastName }}?
25
+ shortDescription: Eich pen-blwydd
26
+ 123e4567-e89b-12d3-a456-426614174000:
27
+ title: Beth yw eich cyfeiriad?
28
+ shortDescription: Eich cyfeiriad
29
+ aabbccdd-1122-3344-5566-778899001123:
30
+ title: Oes gennych chi drwydded yrru?
31
+ shortDescription: Trwydded yrru
32
+ aabbccdd-1122-3344-5566-778899001124:
33
+ title: Sut rydych chi fel arfer yn teithio?
34
+ shortDescription: Eich ffordd o deithio
35
+ listItems:
36
+ aabbccdd-1122-3344-5566-778899001126:
37
+ text: Car
38
+ aabbccdd-1122-3344-5566-778899001127:
39
+ text: Bws
40
+ aabbccdd-1122-3344-5566-778899001128:
41
+ text: Trên
42
+ pages:
43
+ 622a35ec-3795-418a-81f3-a45746959045:
44
+ title: Eich enw
45
+ 23456789-0abc-def1-2345-67890abcdef1:
46
+ title: Llwytho copi o'ch pasbort
47
+ 23456789-0abc-def1-2345-67890abcdef2:
48
+ title: Llwytho copi o'ch trwydded yrru
49
+ da0fbdb4-a2de-4650-be16-9ba552af135f:
50
+ title: Dyddiad geni
51
+ 449a45f6-4541-4a46-91bd-8b8931b07b50:
52
+ title: Crynodeb
53
+ 123e4567-e89b-12d3-a456-426614174001:
54
+ title: Ble rydych chi'n byw?
55
+ aabbccdd-1122-3344-5566-778899001122:
56
+ title: Amdanoch chi
6
57
  pages:
7
58
  - title: Your name
8
59
  path: '/your-name'
@@ -36,6 +87,21 @@ pages:
36
87
  id: e18116e0-7c3e-416a-af42-6f229017c5b1
37
88
  next: []
38
89
  id: 622a35ec-3795-418a-81f3-a45746959045
90
+ - title: Where do you live?
91
+ path: '/where-you-live'
92
+ components:
93
+ - type: UkAddressField
94
+ title: What is your address?
95
+ name: applicantAddress
96
+ shortDescription: Your address
97
+ hint: ''
98
+ options:
99
+ required: true
100
+ usePostcodeLookup: true
101
+ schema: {}
102
+ id: 123e4567-e89b-12d3-a456-426614174000
103
+ next: []
104
+ id: 123e4567-e89b-12d3-a456-426614174001
39
105
  - title: Upload a copy of your passport
40
106
  controller: FileUploadPageController
41
107
  path: '/upload-passport'
@@ -46,7 +112,7 @@ pages:
46
112
  shortDescription: Upload passport
47
113
  hint: ''
48
114
  options:
49
- required: true
115
+ required: false
50
116
  schema: {}
51
117
  id: 987c1234-56d7-89e0-1234-56789abcdef0
52
118
  id: 23456789-0abc-def1-2345-67890abcdef1
@@ -60,7 +126,7 @@ pages:
60
126
  shortDescription: Upload drivers licence
61
127
  hint: ''
62
128
  options:
63
- required: true
129
+ required: false
64
130
  schema: {}
65
131
  id: 987c1234-56d7-89e0-1234-56789abcdef1
66
132
  id: 23456789-0abc-def1-2345-67890abcdef2
@@ -78,6 +144,29 @@ pages:
78
144
  id: '00738799-3489-4ab2-a57b-542eecb31bfa'
79
145
  next: []
80
146
  id: da0fbdb4-a2de-4650-be16-9ba552af135f
147
+ - title: About you
148
+ path: '/about-you'
149
+ components:
150
+ - type: YesNoField
151
+ title: Do you have a driving licence?
152
+ name: hasDrivingLicence
153
+ shortDescription: Driving licence
154
+ hint: ''
155
+ options: {}
156
+ schema: {}
157
+ id: aabbccdd-1122-3344-5566-778899001123
158
+ - type: RadiosField
159
+ title: How do you usually travel?
160
+ name: travelMethod
161
+ shortDescription: Your travel method
162
+ hint: ''
163
+ options:
164
+ required: true
165
+ schema: {}
166
+ list: aabbccdd-1122-3344-5566-778899001125
167
+ id: aabbccdd-1122-3344-5566-778899001124
168
+ next: []
169
+ id: aabbccdd-1122-3344-5566-778899001122
81
170
  - title: ''
82
171
  path: '/notification-demo'
83
172
  components:
@@ -103,4 +192,18 @@ pages:
103
192
  controller: SummaryPageController
104
193
  conditions: []
105
194
  sections: []
106
- lists: []
195
+ lists:
196
+ - id: aabbccdd-1122-3344-5566-778899001125
197
+ name: travelMethods
198
+ title: Travel methods
199
+ type: string
200
+ items:
201
+ - id: aabbccdd-1122-3344-5566-778899001126
202
+ text: Car
203
+ value: car
204
+ - id: aabbccdd-1122-3344-5566-778899001127
205
+ text: Bus
206
+ value: bus
207
+ - id: aabbccdd-1122-3344-5566-778899001128
208
+ text: Train
209
+ value: train
@@ -1,11 +1,8 @@
1
1
  import { type AutocompleteFieldComponent } from '@defra/forms-model'
2
2
 
3
3
  import { SelectField } from './SelectField.js'
4
+ import { type RenderContext } from './types.js'
4
5
  import { messageTemplate } from '../pageControllers/validationOptions.js'
5
- import {
6
- type FormPayload,
7
- type FormSubmissionError
8
- } from '../types.js'
9
6
 
10
7
  export class AutocompleteField extends SelectField {
11
8
  declare options: AutocompleteFieldComponent['options']
@@ -34,8 +31,8 @@ export class AutocompleteField extends SelectField {
34
31
  this.formSchema = formSchema
35
32
  }
36
33
 
37
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
38
- const viewModel = super.getViewModel(payload, errors)
34
+ getViewModel(context: RenderContext) {
35
+ const viewModel = super.getViewModel(context)
39
36
  let { formGroup } = viewModel
40
37
 
41
38
  formGroup ??= {}
@@ -3,6 +3,7 @@ import joi, { type ArraySchema } from 'joi'
3
3
 
4
4
  import { isFormValue } from './FormComponent.js'
5
5
  import { SelectionControlField } from './SelectionControlField.js'
6
+ import { type Translator } from '../i18n/types.js'
6
7
  import { type FormModel } from '../models/FormModel.js'
7
8
  import { type QuestionPageController } from '../pageControllers/QuestionPageController.js'
8
9
  import { messageTemplate } from '../pageControllers/validationOptions.js'
@@ -41,9 +42,9 @@ export class CheckboxesField extends SelectionControlField {
41
42
  .label(this.label)
42
43
  .required()
43
44
  .messages({
44
- 'array.min': messageTemplate.arrayMin as string,
45
- 'array.max': messageTemplate.arrayMax as string,
46
- 'array.length': messageTemplate.arrayLength as string
45
+ 'array.min': messageTemplate.arrayMin,
46
+ 'array.max': messageTemplate.arrayMax,
47
+ 'array.length': messageTemplate.arrayLength
47
48
  })
48
49
 
49
50
  if (options.required === false) {
@@ -86,7 +87,8 @@ export class CheckboxesField extends SelectionControlField {
86
87
  }
87
88
 
88
89
  getDisplayStringFromFormValue(
89
- selected: (string | number | boolean)[] | undefined
90
+ selected: (string | number | boolean)[] | undefined,
91
+ translator: Translator
90
92
  ) {
91
93
  const { items } = this
92
94
 
@@ -94,10 +96,9 @@ export class CheckboxesField extends SelectionControlField {
94
96
  return ''
95
97
  }
96
98
 
97
- // Map selected values to text
98
99
  return items
99
100
  .filter((item) => selected.includes(item.value))
100
- .map((item) => item.text)
101
+ .map((item) => translator.tListItem(item, 'text') || item.text)
101
102
  .join(', ')
102
103
  }
103
104
 
@@ -118,12 +119,12 @@ export class CheckboxesField extends SelectionControlField {
118
119
  return values ?? []
119
120
  }
120
121
 
121
- getDisplayStringFromState(state: FormSubmissionState) {
122
- // Selected checkbox values
122
+ getDisplayStringFromState(
123
+ state: FormSubmissionState,
124
+ translator: Translator
125
+ ) {
123
126
  const selected = this.getFormValueFromState(state) ?? []
124
-
125
- // Map selected values to text
126
- return this.getDisplayStringFromFormValue(selected)
127
+ return this.getDisplayStringFromFormValue(selected, translator)
127
128
  }
128
129
 
129
130
  getContextValueFromState(state: FormSubmissionState) {
@@ -6,7 +6,6 @@ import joi, {
6
6
  } from 'joi'
7
7
 
8
8
  import {
9
- FormComponent,
10
9
  isFormState,
11
10
  isFormValue
12
11
  } from './FormComponent.js'
@@ -16,11 +15,18 @@ import {
16
15
  type Field,
17
16
  type Guidance
18
17
  } from './helpers/components.js'
19
- import { type ComponentViewModel } from './types.js'
18
+ import {
19
+ type ComponentViewModel,
20
+ type RenderContext
21
+ } from './types.js'
20
22
  import { getErrors } from '../helpers.js'
23
+ import { type Translator } from '../i18n/types.js'
21
24
  import { type FormModel } from '../models/index.js'
22
25
  import { type PageControllerClass } from '../pageControllers/helpers/pages.js'
23
- import { validationOptions as opts } from '../pageControllers/validationOptions.js'
26
+ import {
27
+ buildLanguageMessages,
28
+ validationOptions as opts
29
+ } from '../pageControllers/validationOptions.js'
24
30
  import {
25
31
  type FormPayload,
26
32
  type FormState,
@@ -28,7 +34,6 @@ import {
28
34
  type FormSubmissionState,
29
35
  type FormValidationResult
30
36
  } from '../types.js'
31
- import { type FormQuery } from '../../../routes/types.js'
32
37
 
33
38
  export class ComponentCollection {
34
39
  page?: PageControllerClass
@@ -87,49 +92,6 @@ export class ComponentCollection {
87
92
  : stateSchema.keys({ [name]: field.stateSchema })
88
93
  }
89
94
 
90
- // Add parent field title to collection field errors
91
- formSchema = formSchema.error((errors) => {
92
- return errors.flatMap((error) => {
93
- if (!isErrorContext(error.local) || error.local.title) {
94
- return error
95
- }
96
-
97
- // Use field key or first missing child field
98
- let { missing, key = missing?.[0] } = error.local
99
-
100
- // But avoid numeric key used by array payloads
101
- if (typeof key === 'number') {
102
- key = error.path[0]
103
- }
104
-
105
- // Find the parent field
106
- const parent = fields.find(
107
- (item) => item.name === key?.split('__').shift()
108
- )
109
-
110
- // Find the child field
111
- const child = (parent?.collection?.fields ?? fields).find(
112
- (item) => item.name === key
113
- )
114
-
115
- // Update error with child label
116
- if (child && (!error.local.label || error.local.label === 'value')) {
117
- error.local.label = child.title
118
- }
119
-
120
- // Fix error summary links for missing fields
121
- if (missing?.length) {
122
- error.path = missing
123
- error.local.key = missing[0]
124
- }
125
-
126
- // Update error with parent title
127
- error.local.title ??= parent?.label
128
-
129
- return error
130
- })
131
- })
132
-
133
95
  if (schema?.peers) {
134
96
  formSchema = formSchema.and(...schema.peers, {
135
97
  isPresent: isFormValue
@@ -215,8 +177,14 @@ export class ComponentCollection {
215
177
  /**
216
178
  * Get all errors for all fields in this collection
217
179
  */
218
- getErrors(errors?: FormSubmissionError[]): FormSubmissionError[] | undefined {
219
- return this.getFieldErrors((field) => field.getErrors(errors), errors)
180
+ getErrors(
181
+ translator: Translator,
182
+ errors?: FormSubmissionError[]
183
+ ): FormSubmissionError[] | undefined {
184
+ return this.getFieldErrors(
185
+ (field) => field.getErrors(translator, errors),
186
+ errors
187
+ )
220
188
  }
221
189
 
222
190
  /**
@@ -225,25 +193,22 @@ export class ComponentCollection {
225
193
  * Composite fields like UKAddress can choose to return more than one error.
226
194
  */
227
195
  getViewErrors(
196
+ translator: Translator,
228
197
  errors?: FormSubmissionError[]
229
198
  ): FormSubmissionError[] | undefined {
230
- return this.getFieldErrors((field) => field.getViewErrors(errors), errors)
199
+ return this.getFieldErrors(
200
+ (field) => field.getViewErrors(translator, errors),
201
+ errors
202
+ )
231
203
  }
232
204
 
233
- getViewModel(
234
- payload: FormPayload,
235
- errors?: FormSubmissionError[],
236
- query: FormQuery = {}
237
- ) {
205
+ getViewModel(context: RenderContext) {
238
206
  const { components } = this
239
207
 
240
208
  const result: ComponentViewModel[] = components.map((component) => {
241
209
  const { isFormComponent, type } = component
242
210
 
243
- const model =
244
- component instanceof FormComponent
245
- ? component.getViewModel(payload, errors, query)
246
- : component.getViewModel()
211
+ const model = component.getViewModel(context)
247
212
 
248
213
  return { type, isFormComponent, model }
249
214
  })
@@ -251,11 +216,128 @@ export class ComponentCollection {
251
216
  return result
252
217
  }
253
218
 
219
+ overrideParentTitle(
220
+ formSchema: joi.ObjectSchema<FormPayload>,
221
+ translator: Translator | undefined
222
+ ) {
223
+ // Add parent field title to collection field errors
224
+ return formSchema.error((errors) => {
225
+ return errors.flatMap((error) => {
226
+ if (!isErrorContext(error.local) || error.local.title) {
227
+ return error
228
+ }
229
+
230
+ // Use field key or first missing child field
231
+ let { missing, key = missing?.[0] } = error.local
232
+
233
+ // But avoid numeric key used by array payloads
234
+ if (typeof key === 'number') {
235
+ key = error.path[0]
236
+ }
237
+
238
+ // Find the parent field
239
+ const parent = this.fields.find(
240
+ (item) => item.name === key?.split('__').shift()
241
+ )
242
+
243
+ // Find the child field
244
+ const child = (parent?.collection?.fields ?? this.fields).find(
245
+ (item) => item.name === key
246
+ )
247
+
248
+ // Update error with child label
249
+ if (child && (!error.local.label || error.local.label === 'value')) {
250
+ error.local.label = child.title
251
+ }
252
+
253
+ // Fix error summary links for missing fields
254
+ if (missing?.length) {
255
+ error.path = missing
256
+ error.local.key = missing[0]
257
+ }
258
+
259
+ // Update error with parent title
260
+ if (translator && parent) {
261
+ error.local.title ??= translator.tComponent(
262
+ parent as ComponentDef,
263
+ 'title'
264
+ )
265
+ } else {
266
+ error.local.title ??= parent?.label
267
+ }
268
+
269
+ return error
270
+ })
271
+ })
272
+ }
273
+
254
274
  /**
255
275
  * Validate form payload
256
276
  */
257
- validate(value: FormPayload = {}): FormValidationResult<FormPayload> {
258
- const result = this.formSchema.validate(value, opts)
277
+ validate(
278
+ value: FormPayload = {},
279
+ translator?: Translator
280
+ ): FormValidationResult<FormPayload> {
281
+ const messages = translator
282
+ ? buildLanguageMessages(translator.t)
283
+ : undefined
284
+
285
+ // When translating, override Joi labels (and custom schema messages where
286
+ // needed) so #label/#title in message templates resolve in the correct language.
287
+ let schema = this.formSchema
288
+ // Add parent field title to collection field errors
289
+ schema = this.overrideParentTitle(schema, translator)
290
+
291
+ if (translator) {
292
+ const { t } = translator
293
+ const labelOverrides: Record<string, joi.Schema> = {}
294
+
295
+ for (const field of this.fields) {
296
+ if (field.collection) {
297
+ // Composite field: translate each sub-field's label using the key constant
298
+ // (e.g. 'components.addressField.line1' → "Llinell cyfeiriad 1") and apply
299
+ // any field-type-specific message overrides (e.g. objectMissing for dates).
300
+ const messagesOverride =
301
+ field.getValidationMessagesOverride(translator)
302
+ for (const subField of field.collection.fields) {
303
+ const translatedSubLabel = t(subField.title) || subField.label
304
+ let patchedSchema = subField.formSchema.label(translatedSubLabel)
305
+ if (messagesOverride) {
306
+ patchedSchema = patchedSchema.messages(messagesOverride)
307
+ }
308
+ labelOverrides[subField.name] = patchedSchema
309
+ }
310
+ } else {
311
+ const translatedLabel =
312
+ translator.tComponent(
313
+ field as unknown as ComponentDef,
314
+ 'shortDescription'
315
+ ) ||
316
+ translator.tComponent(field as unknown as ComponentDef, 'title')
317
+ const messagesOverride =
318
+ field.getValidationMessagesOverride(translator)
319
+ let patchedSchema = field.formSchema
320
+ if (translatedLabel && translatedLabel !== field.label) {
321
+ patchedSchema = patchedSchema.label(translatedLabel)
322
+ }
323
+ if (messagesOverride) {
324
+ patchedSchema = patchedSchema.messages(messagesOverride)
325
+ }
326
+ if (patchedSchema !== field.formSchema) {
327
+ labelOverrides[field.name] = patchedSchema
328
+ }
329
+ }
330
+ }
331
+
332
+ if (Object.keys(labelOverrides).length) {
333
+ schema = schema.keys(labelOverrides)
334
+ }
335
+ }
336
+
337
+ const result = schema.validate(value, {
338
+ ...opts,
339
+ ...(messages && { messages })
340
+ })
259
341
 
260
342
  const details = result.error?.details
261
343
 
@@ -11,16 +11,18 @@ import {
11
11
  import { NumberField } from './NumberField.js'
12
12
  import {
13
13
  type DateInputItem,
14
- type DatePartsState
14
+ type DatePartsState,
15
+ type RenderContext
15
16
  } from './types.js'
16
17
  import { parseStrictDate } from '../date-helper.js'
18
+ import { buildValidationMessages } from '../i18n/buildValidationMessages.js'
19
+ import { type Translator } from '../i18n/types.js'
17
20
  import { messageTemplate } from '../pageControllers/validationOptions.js'
18
21
  import {
19
22
  type ErrorMessageTemplateList,
20
23
  type FormPayload,
21
24
  type FormState,
22
25
  type FormStateValue,
23
- type FormSubmissionError,
24
26
  type FormSubmissionState
25
27
  } from '../types.js'
26
28
  import { convertToLanguageMessages } from '../../../utils/type-utils.js'
@@ -56,7 +58,7 @@ export class DatePartsField extends FormComponent {
56
58
  {
57
59
  type: ComponentType.NumberField,
58
60
  name: `${name}__day`,
59
- title: 'Day',
61
+ title: 'components.dateField.day',
60
62
  schema: { min: 1, max: 31, precision: 0 },
61
63
  options: {
62
64
  required: isRequired,
@@ -68,7 +70,7 @@ export class DatePartsField extends FormComponent {
68
70
  {
69
71
  type: ComponentType.NumberField,
70
72
  name: `${name}__month`,
71
- title: 'Month',
73
+ title: 'components.dateField.month',
72
74
  schema: { min: 1, max: 12, precision: 0 },
73
75
  options: {
74
76
  required: isRequired,
@@ -80,7 +82,7 @@ export class DatePartsField extends FormComponent {
80
82
  {
81
83
  type: ComponentType.NumberField,
82
84
  name: `${name}__year`,
83
- title: 'Year',
85
+ title: 'components.dateField.year',
84
86
  schema: { min: 1000, max: 3000, precision: 0 },
85
87
  options: {
86
88
  required: isRequired,
@@ -107,7 +109,10 @@ export class DatePartsField extends FormComponent {
107
109
  return this.isState(value) ? value : undefined
108
110
  }
109
111
 
110
- getDisplayStringFromFormValue(formValue: DatePartsState | undefined) {
112
+ getDisplayStringFromFormValue(
113
+ formValue: DatePartsState | undefined,
114
+ _translator: Translator
115
+ ) {
111
116
  if (!formValue) {
112
117
  return ''
113
118
  }
@@ -118,10 +123,13 @@ export class DatePartsField extends FormComponent {
118
123
  )
119
124
  }
120
125
 
121
- getDisplayStringFromState(state: FormSubmissionState) {
126
+ getDisplayStringFromState(
127
+ state: FormSubmissionState,
128
+ translator: Translator
129
+ ) {
122
130
  const value = this.getFormValueFromState(state)
123
131
 
124
- return this.getDisplayStringFromFormValue(value)
132
+ return this.getDisplayStringFromFormValue(value, translator)
125
133
  }
126
134
 
127
135
  getContextValueFromFormValue(value: DatePartsState | undefined) {
@@ -148,10 +156,24 @@ export class DatePartsField extends FormComponent {
148
156
  return this.getContextValueFromFormValue(value)
149
157
  }
150
158
 
151
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
159
+ getValidationMessagesOverride(translator: Translator) {
160
+ const { t } = translator
161
+ return convertToLanguageMessages({
162
+ 'any.required': buildValidationMessages(t).objectMissing,
163
+ 'number.base': buildValidationMessages(t).objectMissing,
164
+ 'number.precision': buildValidationMessages(t).dateFormat,
165
+ 'number.integer': buildValidationMessages(t).dateFormat,
166
+ 'number.unsafe': buildValidationMessages(t).dateFormat,
167
+ 'number.min': buildValidationMessages(t).dateFormat,
168
+ 'number.max': buildValidationMessages(t).dateFormat
169
+ })
170
+ }
171
+
172
+ getViewModel(context: RenderContext) {
173
+ const { errors } = context
152
174
  const { collection, name } = this
153
175
 
154
- const viewModel = super.getViewModel(payload, errors)
176
+ const viewModel = super.getViewModel(context)
155
177
  let { fieldset, label } = viewModel
156
178
 
157
179
  // Check for component errors only
@@ -159,7 +181,7 @@ export class DatePartsField extends FormComponent {
159
181
 
160
182
  // Use the component collection to generate the subitems
161
183
  const items: DateInputItem[] = collection
162
- .getViewModel(payload, errors)
184
+ .getViewModel(context)
163
185
  .map(({ model }) => {
164
186
  let { label, type, value, classes, errorMessage } = model
165
187