@defra/forms-engine-plugin 5.0.0-alpha.3 → 5.0.0-alpha.30

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 (406) hide show
  1. package/.public/37c964ca545c240f010a.mjs +2 -0
  2. package/.public/37c964ca545c240f010a.mjs.LICENSE.txt +4 -0
  3. package/.public/assets-manifest.json +3 -0
  4. package/.public/javascripts/application.min.js +1 -1
  5. package/.public/javascripts/application.min.js.LICENSE.txt +7 -0
  6. package/.public/javascripts/application.min.js.map +1 -1
  7. package/.public/javascripts/shared.min.js +1 -1
  8. package/.public/javascripts/shared.min.js.LICENSE.txt +9 -0
  9. package/.public/javascripts/shared.min.js.map +1 -1
  10. package/.public/javascripts/vendor/@defra.min.js +1 -1
  11. package/.public/javascripts/vendor/@defra.min.js.map +1 -1
  12. package/.public/javascripts/vendor/maplibre-gl.min.js +1 -1
  13. package/.public/javascripts/vendor/maplibre-gl.min.js.LICENSE.txt +3 -3
  14. package/.public/javascripts/vendor/maplibre-gl.min.js.map +1 -1
  15. package/.public/stylesheets/application.min.css +1 -1
  16. package/.public/stylesheets/application.min.css.map +1 -1
  17. package/.server/client/javascripts/file-upload.js +6 -3
  18. package/.server/client/javascripts/file-upload.js.map +1 -1
  19. package/.server/client/javascripts/geospatial-map.d.ts +159 -5
  20. package/.server/client/javascripts/geospatial-map.js +161 -81
  21. package/.server/client/javascripts/geospatial-map.js.map +1 -1
  22. package/.server/client/javascripts/geospatial-map.test.js +152 -0
  23. package/.server/client/javascripts/geospatial-map.test.js.map +1 -0
  24. package/.server/client/javascripts/govuk.js +2 -1
  25. package/.server/client/javascripts/govuk.js.map +1 -1
  26. package/.server/client/javascripts/location-map.d.ts +44 -0
  27. package/.server/client/javascripts/location-map.js +55 -6
  28. package/.server/client/javascripts/location-map.js.map +1 -1
  29. package/.server/client/javascripts/map-constants.d.ts +3 -0
  30. package/.server/client/javascripts/map-constants.js +4 -0
  31. package/.server/client/javascripts/map-constants.js.map +1 -0
  32. package/.server/client/javascripts/map.d.ts +17 -4
  33. package/.server/client/javascripts/map.js +59 -6
  34. package/.server/client/javascripts/map.js.map +1 -1
  35. package/.server/client/javascripts/maps.d.ts +5 -0
  36. package/.server/client/javascripts/maps.js +6 -0
  37. package/.server/client/javascripts/maps.js.map +1 -0
  38. package/.server/client/javascripts/shared.d.ts +1 -4
  39. package/.server/client/javascripts/shared.js +1 -4
  40. package/.server/client/javascripts/shared.js.map +1 -1
  41. package/.server/client/javascripts/sssi-dataset.d.ts +18 -20
  42. package/.server/client/javascripts/sssi-dataset.js +37 -39
  43. package/.server/client/javascripts/sssi-dataset.js.map +1 -1
  44. package/.server/client/stylesheets/maps.scss +4 -0
  45. package/.server/client/stylesheets/shared.scss +1 -5
  46. package/.server/server/constants.d.ts +2 -0
  47. package/.server/server/constants.js +2 -0
  48. package/.server/server/constants.js.map +1 -1
  49. package/.server/server/forms/components.json +8 -0
  50. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +4 -0
  51. package/.server/server/plugins/engine/__stubs__/definitions.d.ts +29 -0
  52. package/.server/server/plugins/engine/__stubs__/definitions.js +125 -0
  53. package/.server/server/plugins/engine/__stubs__/definitions.js.map +1 -0
  54. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +8 -3
  55. package/.server/server/plugins/engine/components/AutocompleteField.js +17 -0
  56. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  57. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +23 -2
  58. package/.server/server/plugins/engine/components/CheckboxesField.js +30 -5
  59. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  60. package/.server/server/plugins/engine/components/ComponentBase.d.ts +2 -1
  61. package/.server/server/plugins/engine/components/ComponentBase.js +2 -0
  62. package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
  63. package/.server/server/plugins/engine/components/ComponentCollection.js +12 -7
  64. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  65. package/.server/server/plugins/engine/components/DatePartsField.d.ts +6 -3
  66. package/.server/server/plugins/engine/components/DatePartsField.js +12 -7
  67. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  68. package/.server/server/plugins/engine/components/DeclarationField.d.ts +6 -3
  69. package/.server/server/plugins/engine/components/DeclarationField.js +6 -4
  70. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  71. package/.server/server/plugins/engine/components/Details.d.ts +1 -0
  72. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +33 -2
  73. package/.server/server/plugins/engine/components/EastingNorthingField.js +110 -54
  74. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  75. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +4 -1
  76. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -1
  77. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  78. package/.server/server/plugins/engine/components/FileUploadField.d.ts +23 -2
  79. package/.server/server/plugins/engine/components/FileUploadField.js +35 -3
  80. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  81. package/.server/server/plugins/engine/components/FormComponent.d.ts +5 -1
  82. package/.server/server/plugins/engine/components/FormComponent.js +5 -2
  83. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  84. package/.server/server/plugins/engine/components/GeospatialField.d.ts +23 -0
  85. package/.server/server/plugins/engine/components/GeospatialField.js +33 -9
  86. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  87. package/.server/server/plugins/engine/components/Html.d.ts +1 -0
  88. package/.server/server/plugins/engine/components/InsetText.d.ts +1 -0
  89. package/.server/server/plugins/engine/components/LatLongField.d.ts +32 -2
  90. package/.server/server/plugins/engine/components/LatLongField.js +85 -48
  91. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  92. package/.server/server/plugins/engine/components/List.d.ts +1 -0
  93. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +3 -2
  94. package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
  95. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +8 -2
  96. package/.server/server/plugins/engine/components/LocationFieldBase.js +31 -7
  97. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  98. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +12 -3
  99. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +21 -13
  100. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  101. package/.server/server/plugins/engine/components/Markdown.d.ts +1 -0
  102. package/.server/server/plugins/engine/components/Markdown.js +1 -1
  103. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  104. package/.server/server/plugins/engine/components/MonthYearField.d.ts +5 -2
  105. package/.server/server/plugins/engine/components/MonthYearField.js +13 -9
  106. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  107. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +1 -0
  108. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  109. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +4 -3
  110. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  111. package/.server/server/plugins/engine/components/NotificationBanner.d.ts +1 -0
  112. package/.server/server/plugins/engine/components/NumberField.d.ts +5 -0
  113. package/.server/server/plugins/engine/components/NumberField.js +22 -0
  114. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  115. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +103 -1
  116. package/.server/server/plugins/engine/components/OsGridRefField.js +13 -3
  117. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  118. package/.server/server/plugins/engine/components/PaymentField.d.ts +2 -0
  119. package/.server/server/plugins/engine/components/PaymentField.js +9 -5
  120. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  121. package/.server/server/plugins/engine/components/SelectField.d.ts +1 -0
  122. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +1 -0
  123. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +1 -0
  124. package/.server/server/plugins/engine/components/TrackingField.d.ts +21 -0
  125. package/.server/server/plugins/engine/components/TrackingField.js +46 -0
  126. package/.server/server/plugins/engine/components/TrackingField.js.map +1 -0
  127. package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -0
  128. package/.server/server/plugins/engine/components/UkAddressField.js +23 -8
  129. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  130. package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -2
  131. package/.server/server/plugins/engine/components/YesNoField.js +22 -8
  132. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  133. package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
  134. package/.server/server/plugins/engine/components/helpers/components.js +6 -3
  135. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  136. package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +8 -1
  137. package/.server/server/plugins/engine/components/helpers/geospatial.js +58 -17
  138. package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
  139. package/.server/server/plugins/engine/components/helpers/index.d.ts +21 -1
  140. package/.server/server/plugins/engine/components/helpers/index.js +45 -1
  141. package/.server/server/plugins/engine/components/helpers/index.js.map +1 -1
  142. package/.server/server/plugins/engine/components/index.d.ts +1 -0
  143. package/.server/server/plugins/engine/components/index.js +1 -0
  144. package/.server/server/plugins/engine/components/index.js.map +1 -1
  145. package/.server/server/plugins/engine/components/types.d.ts +1 -0
  146. package/.server/server/plugins/engine/components/types.js.map +1 -1
  147. package/.server/server/plugins/engine/errors.d.ts +49 -0
  148. package/.server/server/plugins/engine/errors.js +75 -0
  149. package/.server/server/plugins/engine/errors.js.map +1 -0
  150. package/.server/server/plugins/engine/form-availability.d.ts +3 -2
  151. package/.server/server/plugins/engine/form-availability.js +3 -2
  152. package/.server/server/plugins/engine/form-availability.js.map +1 -1
  153. package/.server/server/plugins/engine/form-context.js +2 -2
  154. package/.server/server/plugins/engine/form-context.js.map +1 -1
  155. package/.server/server/plugins/engine/helpers.d.ts +23 -2
  156. package/.server/server/plugins/engine/helpers.js +44 -5
  157. package/.server/server/plugins/engine/helpers.js.map +1 -1
  158. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +4 -1
  159. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +31 -7
  160. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -1
  161. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +4 -4
  162. package/.server/server/plugins/engine/i18n/createFormTranslator.js +27 -5
  163. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -1
  164. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +1 -1
  165. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +9 -0
  166. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -1
  167. package/.server/server/plugins/engine/i18n/form.d.ts +13 -0
  168. package/.server/server/plugins/engine/i18n/form.js +35 -0
  169. package/.server/server/plugins/engine/i18n/form.js.map +1 -0
  170. package/.server/server/plugins/engine/i18n/languages.d.ts +10 -0
  171. package/.server/server/plugins/engine/i18n/languages.js +19 -0
  172. package/.server/server/plugins/engine/i18n/languages.js.map +1 -0
  173. package/.server/server/plugins/engine/i18n/translations/cy.json +176 -7
  174. package/.server/server/plugins/engine/i18n/translations/en-GB.json +110 -6
  175. package/.server/server/plugins/engine/i18n/types.d.ts +2 -0
  176. package/.server/server/plugins/engine/i18n/types.js.map +1 -1
  177. package/.server/server/plugins/engine/index.d.ts +4 -0
  178. package/.server/server/plugins/engine/index.js +4 -0
  179. package/.server/server/plugins/engine/index.js.map +1 -1
  180. package/.server/server/plugins/engine/models/FormModel.d.ts +0 -4
  181. package/.server/server/plugins/engine/models/FormModel.js +35 -23
  182. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  183. package/.server/server/plugins/engine/models/SummaryViewModel.js +9 -4
  184. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  185. package/.server/server/plugins/engine/models/types.d.ts +28 -1
  186. package/.server/server/plugins/engine/models/types.js.map +1 -1
  187. package/.server/server/plugins/engine/models/unavailable-view-model.d.ts +11 -2
  188. package/.server/server/plugins/engine/models/unavailable-view-model.js +23 -4
  189. package/.server/server/plugins/engine/models/unavailable-view-model.js.map +1 -1
  190. package/.server/server/plugins/engine/options.js +2 -1
  191. package/.server/server/plugins/engine/options.js.map +1 -1
  192. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +14 -6
  193. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  194. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  195. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  196. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +2 -0
  197. package/.server/server/plugins/engine/outputFormatters/machine/v2.js +2 -0
  198. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
  199. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +7 -1
  200. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +56 -10
  201. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  202. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
  203. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -2
  204. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  205. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +3 -4
  206. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  207. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +10 -4
  208. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  209. package/.server/server/plugins/engine/pageControllers/helpers/pages.js +2 -1
  210. package/.server/server/plugins/engine/pageControllers/helpers/pages.js.map +1 -1
  211. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +35 -2
  212. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +100 -3
  213. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  214. package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +1 -1
  215. package/.server/server/plugins/engine/pageControllers/validationOptions.js +24 -3
  216. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  217. package/.server/server/plugins/engine/plugin.js +3 -0
  218. package/.server/server/plugins/engine/plugin.js.map +1 -1
  219. package/.server/server/plugins/engine/referenceNumbers.d.ts +1 -0
  220. package/.server/server/plugins/engine/referenceNumbers.js +1 -0
  221. package/.server/server/plugins/engine/referenceNumbers.js.map +1 -1
  222. package/.server/server/plugins/engine/routes/index.js +9 -4
  223. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  224. package/.server/server/plugins/engine/types/enums.d.ts +3 -3
  225. package/.server/server/plugins/engine/types/enums.js +5 -4
  226. package/.server/server/plugins/engine/types/enums.js.map +1 -1
  227. package/.server/server/plugins/engine/types/schema.js +15 -4
  228. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  229. package/.server/server/plugins/engine/types.d.ts +24 -2
  230. package/.server/server/plugins/engine/types.js.map +1 -1
  231. package/.server/server/plugins/engine/unavailable-response.js +5 -2
  232. package/.server/server/plugins/engine/unavailable-response.js.map +1 -1
  233. package/.server/server/plugins/engine/views/components/_location-field-base.html +4 -2
  234. package/.server/server/plugins/engine/views/components/fileuploadfield.html +1 -1
  235. package/.server/server/plugins/engine/views/components/geospatialfield.html +1 -0
  236. package/.server/server/plugins/engine/views/components/osgridreffield.html +4 -1
  237. package/.server/server/plugins/engine/views/components/trackingfield.html +3 -0
  238. package/.server/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  239. package/.server/server/plugins/engine/views/file-upload.html +1 -1
  240. package/.server/server/plugins/engine/views/summary.html +1 -0
  241. package/.server/server/plugins/engine/views/unavailable.html +14 -11
  242. package/.server/server/plugins/map/routes/index.d.ts +4 -0
  243. package/.server/server/plugins/map/routes/index.js +12 -4
  244. package/.server/server/plugins/map/routes/index.js.map +1 -1
  245. package/.server/server/plugins/map/routes/index.test.js +7 -0
  246. package/.server/server/plugins/map/routes/index.test.js.map +1 -0
  247. package/.server/server/plugins/map/routes/vts/README.md +38 -0
  248. package/.server/server/plugins/map/routes/vts/countries-5dp.geojson +4 -0
  249. package/.server/server/plugins/map/routes/vts/countries.geojson +10 -39283
  250. package/.server/server/plugins/map/types.d.ts +24 -2
  251. package/.server/server/plugins/map/types.js +9 -2
  252. package/.server/server/plugins/map/types.js.map +1 -1
  253. package/.server/server/plugins/nunjucks/enviroment.test.js +11 -4
  254. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
  255. package/.server/server/plugins/nunjucks/filters/applyUrlParam.d.ts +9 -0
  256. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  257. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js.map +1 -0
  258. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js +17 -0
  259. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js.map +1 -0
  260. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  261. package/.server/server/plugins/nunjucks/filters/index.d.ts +1 -0
  262. package/.server/server/plugins/nunjucks/filters/index.js +1 -0
  263. package/.server/server/plugins/nunjucks/filters/index.js.map +1 -1
  264. package/.server/server/plugins/payment/helper.d.ts +11 -1
  265. package/.server/server/plugins/payment/helper.js +18 -2
  266. package/.server/server/plugins/payment/helper.js.map +1 -1
  267. package/.server/server/plugins/payment/helper.test.js +2 -1
  268. package/.server/server/plugins/payment/helper.test.js.map +1 -1
  269. package/.server/server/plugins/payment/service.d.ts +2 -1
  270. package/.server/server/plugins/payment/service.js +5 -2
  271. package/.server/server/plugins/payment/service.js.map +1 -1
  272. package/.server/server/plugins/payment/service.test.js +7 -3
  273. package/.server/server/plugins/payment/service.test.js.map +1 -1
  274. package/.server/server/plugins/payment/types.d.ts +4 -0
  275. package/.server/server/plugins/payment/types.js +1 -0
  276. package/.server/server/plugins/payment/types.js.map +1 -1
  277. package/.server/server/plugins/postcode-lookup/models/index.d.ts +249 -3
  278. package/.server/server/plugins/postcode-lookup/models/index.js +103 -36
  279. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  280. package/.server/server/plugins/postcode-lookup/routes/index.d.ts +15 -1
  281. package/.server/server/plugins/postcode-lookup/routes/index.js +64 -18
  282. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  283. package/.server/server/plugins/postcode-lookup/routes/index.test.js +84 -0
  284. package/.server/server/plugins/postcode-lookup/routes/index.test.js.map +1 -0
  285. package/.server/server/plugins/postcode-lookup/types.d.ts +12 -0
  286. package/.server/server/plugins/postcode-lookup/types.js +6 -1
  287. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  288. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  289. package/.server/server/utils/type-utils.d.ts +1 -2
  290. package/.server/server/utils/type-utils.js +0 -3
  291. package/.server/server/utils/type-utils.js.map +1 -1
  292. package/.server/server/utils/utils.d.ts +6 -0
  293. package/.server/server/utils/utils.js +18 -1
  294. package/.server/server/utils/utils.js.map +1 -1
  295. package/.server/server/utils/utils.test.js +21 -1
  296. package/.server/server/utils/utils.test.js.map +1 -1
  297. package/.server/typings/geodesy/index.d.js +2 -0
  298. package/.server/typings/geodesy/index.d.js.map +1 -0
  299. package/.server/typings/hapi/index.d.js.map +1 -1
  300. package/package.json +24 -9
  301. package/src/client/javascripts/file-upload.js +11 -3
  302. package/src/client/javascripts/geospatial-map.js +181 -86
  303. package/src/client/javascripts/govuk.js +2 -0
  304. package/src/client/javascripts/location-map.js +62 -6
  305. package/src/client/javascripts/map-constants.js +3 -0
  306. package/src/client/javascripts/map.js +66 -9
  307. package/src/client/javascripts/maps.js +5 -0
  308. package/src/client/javascripts/shared.js +1 -4
  309. package/src/client/javascripts/sssi-dataset.js +39 -41
  310. package/src/client/stylesheets/maps.scss +4 -0
  311. package/src/client/stylesheets/shared.scss +1 -5
  312. package/src/server/constants.js +2 -0
  313. package/src/server/forms/components.json +8 -0
  314. package/src/server/forms/register-as-a-unicorn-breeder.yaml +4 -0
  315. package/src/server/plugins/engine/__stubs__/definitions.ts +155 -0
  316. package/src/server/plugins/engine/components/AutocompleteField.ts +20 -0
  317. package/src/server/plugins/engine/components/CheckboxesField.ts +41 -8
  318. package/src/server/plugins/engine/components/ComponentBase.ts +6 -4
  319. package/src/server/plugins/engine/components/ComponentCollection.ts +17 -15
  320. package/src/server/plugins/engine/components/DatePartsField.ts +20 -9
  321. package/src/server/plugins/engine/components/DeclarationField.ts +10 -10
  322. package/src/server/plugins/engine/components/EastingNorthingField.ts +185 -89
  323. package/src/server/plugins/engine/components/EmailAddressField.ts +2 -1
  324. package/src/server/plugins/engine/components/FileUploadField.ts +46 -5
  325. package/src/server/plugins/engine/components/FormComponent.ts +6 -5
  326. package/src/server/plugins/engine/components/GeospatialField.ts +47 -9
  327. package/src/server/plugins/engine/components/LatLongField.ts +128 -58
  328. package/src/server/plugins/engine/components/ListFormComponent.ts +4 -4
  329. package/src/server/plugins/engine/components/LocationFieldBase.ts +41 -8
  330. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +28 -14
  331. package/src/server/plugins/engine/components/Markdown.ts +2 -3
  332. package/src/server/plugins/engine/components/MonthYearField.ts +20 -15
  333. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +9 -3
  334. package/src/server/plugins/engine/components/NumberField.ts +24 -0
  335. package/src/server/plugins/engine/components/OsGridRefField.ts +22 -3
  336. package/src/server/plugins/engine/components/PaymentField.ts +9 -4
  337. package/src/server/plugins/engine/components/TrackingField.ts +64 -0
  338. package/src/server/plugins/engine/components/UkAddressField.ts +30 -7
  339. package/src/server/plugins/engine/components/YesNoField.ts +27 -9
  340. package/src/server/plugins/engine/components/helpers/components.ts +8 -3
  341. package/src/server/plugins/engine/components/helpers/geospatial.ts +87 -24
  342. package/src/server/plugins/engine/components/helpers/index.ts +64 -1
  343. package/src/server/plugins/engine/components/index.ts +1 -0
  344. package/src/server/plugins/engine/components/types.ts +1 -0
  345. package/src/server/plugins/engine/errors.ts +78 -0
  346. package/src/server/plugins/engine/form-availability.ts +8 -2
  347. package/src/server/plugins/engine/form-context.ts +4 -2
  348. package/src/server/plugins/engine/helpers.ts +52 -5
  349. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +16 -8
  350. package/src/server/plugins/engine/i18n/createFormTranslator.ts +43 -12
  351. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +7 -1
  352. package/src/server/plugins/engine/i18n/form.ts +54 -0
  353. package/src/server/plugins/engine/i18n/languages.ts +19 -0
  354. package/src/server/plugins/engine/i18n/translations/cy.json +176 -7
  355. package/src/server/plugins/engine/i18n/translations/en-GB.json +110 -6
  356. package/src/server/plugins/engine/i18n/types.ts +2 -0
  357. package/src/server/plugins/engine/index.ts +7 -0
  358. package/src/server/plugins/engine/models/FormModel.ts +46 -23
  359. package/src/server/plugins/engine/models/SummaryViewModel.ts +6 -5
  360. package/src/server/plugins/engine/models/types.ts +31 -0
  361. package/src/server/plugins/engine/models/unavailable-view-model.ts +26 -5
  362. package/src/server/plugins/engine/options.js +2 -1
  363. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +18 -7
  364. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -1
  365. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +3 -0
  366. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +60 -9
  367. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -2
  368. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +2 -2
  369. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +15 -4
  370. package/src/server/plugins/engine/pageControllers/helpers/pages.ts +2 -1
  371. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +143 -4
  372. package/src/server/plugins/engine/pageControllers/validationOptions.ts +29 -4
  373. package/src/server/plugins/engine/plugin.ts +6 -0
  374. package/src/server/plugins/engine/referenceNumbers.ts +2 -0
  375. package/src/server/plugins/engine/routes/index.ts +9 -3
  376. package/src/server/plugins/engine/types/enums.ts +4 -3
  377. package/src/server/plugins/engine/types/schema.ts +22 -5
  378. package/src/server/plugins/engine/types.ts +28 -1
  379. package/src/server/plugins/engine/unavailable-response.ts +6 -2
  380. package/src/server/plugins/engine/views/components/_location-field-base.html +4 -2
  381. package/src/server/plugins/engine/views/components/fileuploadfield.html +1 -1
  382. package/src/server/plugins/engine/views/components/geospatialfield.html +1 -0
  383. package/src/server/plugins/engine/views/components/osgridreffield.html +4 -1
  384. package/src/server/plugins/engine/views/components/trackingfield.html +3 -0
  385. package/src/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  386. package/src/server/plugins/engine/views/file-upload.html +1 -1
  387. package/src/server/plugins/engine/views/summary.html +1 -0
  388. package/src/server/plugins/engine/views/unavailable.html +14 -11
  389. package/src/server/plugins/map/routes/index.js +29 -4
  390. package/src/server/plugins/map/routes/vts/README.md +38 -0
  391. package/src/server/plugins/map/routes/vts/countries-5dp.geojson +4 -0
  392. package/src/server/plugins/map/routes/vts/countries.geojson +10 -39283
  393. package/src/server/plugins/map/types.js +9 -2
  394. package/src/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  395. package/src/server/plugins/nunjucks/filters/index.js +1 -0
  396. package/src/server/plugins/payment/helper.js +22 -2
  397. package/src/server/plugins/payment/service.js +6 -2
  398. package/src/server/plugins/payment/types.js +1 -0
  399. package/src/server/plugins/postcode-lookup/models/index.js +91 -46
  400. package/src/server/plugins/postcode-lookup/routes/index.js +96 -24
  401. package/src/server/plugins/postcode-lookup/types.js +6 -1
  402. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  403. package/src/server/utils/type-utils.ts +1 -11
  404. package/src/server/utils/utils.js +19 -1
  405. package/src/typings/geodesy/index.d.ts +18 -0
  406. package/src/typings/hapi/index.d.ts +2 -0
@@ -1,5 +1,4 @@
1
1
  import {
2
- type ComponentDef,
3
2
  type FormComponentsDef,
4
3
  type FormMetadata,
5
4
  type Item
@@ -158,10 +157,13 @@ export class FormComponent extends ComponentBase {
158
157
  * Override in composite fields to return translated Joi message overrides for
159
158
  * their sub-fields, applied at validation time so schema-level English messages
160
159
  * are replaced with the correct language. Return null to skip message patching.
160
+ * The return object may contain message overrides at component-level, or sub-field-level.
161
+ * This would allow different error message overrides per field within a collection e.g.
162
+ * for EastingNothingField
161
163
  */
162
164
  getValidationMessagesOverride(
163
165
  _translator: Translator
164
- ): LanguageMessages | null {
166
+ ): Record<string, LanguageMessages> | null {
165
167
  return null
166
168
  }
167
169
 
@@ -178,15 +180,14 @@ export class FormComponent extends ComponentBase {
178
180
  const isRequired = !('required' in options) || options.required !== false
179
181
  const hideOptional = 'optionalText' in options && options.optionalText
180
182
 
181
- const resolvedTitle =
182
- tComponent(this as unknown as ComponentDef, 'title') || title
183
+ const resolvedTitle = tComponent(this.def, 'title') || title
183
184
  const optionalTag =
184
185
  !isRequired && !hideOptional ? ` ${t('common.optional')}` : ''
185
186
  const label = `${resolvedTitle}${optionalTag}`
186
187
 
187
188
  if (hint) {
188
189
  viewModel.hint = {
189
- text: tComponent(this as unknown as ComponentDef, 'hint') || hint
190
+ text: tComponent(this.def, 'hint') || hint
190
191
  }
191
192
  }
192
193
 
@@ -1,14 +1,19 @@
1
1
  import { type GeospatialFieldComponent } from '@defra/forms-model'
2
2
  import { type ArraySchema } from 'joi'
3
3
 
4
+ import { EN_GB } from '../../../constants.js'
4
5
  import { type ComponentBase } from './ComponentBase.js'
5
6
  import {
6
7
  FormComponent,
7
8
  isGeospatialState
8
9
  } from './FormComponent.js'
9
10
  import { getMapLayers } from './LocationFieldHelpers.js'
10
- import { getGeospatialSchema } from './helpers/geospatial.js'
11
+ import {
12
+ determineLimits,
13
+ getGeospatialSchema
14
+ } from './helpers/geospatial.js'
11
15
  import { type RenderContext } from './types.js'
16
+ import { t as tPlugin } from '../i18n/index.js'
12
17
  import { type Translator } from '../i18n/types.js'
13
18
  import { messageTemplate } from '../pageControllers/validationOptions.js'
14
19
  import {
@@ -24,6 +29,7 @@ export class GeospatialField extends FormComponent {
24
29
  declare options: GeospatialFieldComponent['options']
25
30
  declare formSchema: ArraySchema<GeospatialState>
26
31
  declare stateSchema: ArraySchema<GeospatialState>
32
+ declare limits: { min?: number; max?: number; length?: number }
27
33
 
28
34
  constructor(
29
35
  def: GeospatialFieldComponent,
@@ -33,20 +39,24 @@ export class GeospatialField extends FormComponent {
33
39
 
34
40
  const { options } = def
35
41
 
36
- const formSchema = getGeospatialSchema(def).label(this.label).messages({
37
- 'array.min': messageTemplate.featuresMin,
38
- 'array.max': messageTemplate.featuresMax,
39
- 'array.length': messageTemplate.featuresLength
40
- })
42
+ let formSchema = getGeospatialSchema(def).label(this.label)
43
+
44
+ const isOptional = options.required === false
45
+ const limits = determineLimits(def, isOptional)
46
+
47
+ formSchema = formSchema.messages(
48
+ GeospatialField.buildErrorMessages(EN_GB, limits)
49
+ )
41
50
 
42
51
  this.formSchema = formSchema
43
52
  this.stateSchema = formSchema.default(null)
44
53
 
45
- if (options.required === false) {
54
+ if (isOptional) {
46
55
  this.stateSchema = this.stateSchema.allow(null)
47
56
  }
48
57
 
49
58
  this.options = options
59
+ this.limits = limits
50
60
  }
51
61
 
52
62
  getFormValueFromState(state: FormSubmissionState) {
@@ -101,6 +111,7 @@ export class GeospatialField extends FormComponent {
101
111
 
102
112
  return {
103
113
  ...viewModel,
114
+ lang: context.translator.language,
104
115
  country: this.options.countries?.at(0),
105
116
  geometryTypes: this.options.geometryTypes,
106
117
  mapLayers: getMapLayers(this),
@@ -125,7 +136,10 @@ export class GeospatialField extends FormComponent {
125
136
  err.href = `#description_${err.path[1]}`
126
137
  err.text = translator.t(
127
138
  'components.geospatialField.validation.wrongCountry',
128
- { count: Number(err.path[1]) + 1, country: err.context.country }
139
+ {
140
+ count: Number(err.path[1]) + 1,
141
+ country: translator.t(`common.${err.context.country}`)
142
+ }
129
143
  )
130
144
  }
131
145
  })
@@ -144,6 +158,13 @@ export class GeospatialField extends FormComponent {
144
158
  return isGeospatialState(value)
145
159
  }
146
160
 
161
+ getValidationMessagesOverride(translator: Translator) {
162
+ const { language } = translator
163
+ return {
164
+ [this.name]: GeospatialField.buildErrorMessages(language, this.limits)
165
+ }
166
+ }
167
+
147
168
  /**
148
169
  * For error preview page that shows all possible errors on a component
149
170
  */
@@ -164,11 +185,28 @@ export class GeospatialField extends FormComponent {
164
185
  { type: 'required', template: messageTemplate.selectRequired },
165
186
  {
166
187
  type: 'array.min',
167
- template: '{{#title}} must contain at least 1 items'
188
+ template: '{{#title}} must contain at least 1 item'
168
189
  },
169
190
  { type: 'object.invalidjson', template: messageTemplate.format }
170
191
  ],
171
192
  advancedSettingsErrors: []
172
193
  }
173
194
  }
195
+
196
+ static buildErrorMessages(
197
+ language: string,
198
+ limits: { min?: number; max?: number; length?: number } = {}
199
+ ) {
200
+ return {
201
+ 'array.min': tPlugin('validation.featuresMin', language, {
202
+ count: limits.min ?? 1
203
+ }),
204
+ 'array.max': tPlugin('validation.featuresMax', language, {
205
+ count: limits.max ?? 1
206
+ }),
207
+ 'array.length': tPlugin('validation.featuresLength', language, {
208
+ count: limits.length ?? 1
209
+ })
210
+ }
211
+ }
174
212
  }
@@ -12,7 +12,10 @@ import {
12
12
  getLocationFieldViewModel
13
13
  } from './LocationFieldHelpers.js'
14
14
  import { NumberField } from './NumberField.js'
15
- import { createLowerFirstExpression } from './helpers/index.js'
15
+ import {
16
+ createLowerFirstExpression,
17
+ getTranslatedLabel
18
+ } from './helpers/index.js'
16
19
  import {
17
20
  type LatLongState,
18
21
  type RenderContext
@@ -28,7 +31,6 @@ import {
28
31
  type FormSubmissionError,
29
32
  type FormSubmissionState
30
33
  } from '../types.js'
31
- import { convertToLanguageMessages } from '../../../utils/type-utils.js'
32
34
 
33
35
  // Precision constants
34
36
  // UK latitude/longitude requires high precision for accurate location (within ~11mm)
@@ -50,59 +52,18 @@ export class LatLongField extends FormComponent {
50
52
 
51
53
  const isRequired = options.required !== false
52
54
 
53
- // Read schema values from def.schema with fallback defaults
54
- const latitudeMin = schema?.latitude?.min ?? 49.85
55
- const latitudeMax = schema?.latitude?.max ?? 60.859
56
- const longitudeMin = schema?.longitude?.min ?? -13.687
57
- const longitudeMax = schema?.longitude?.max ?? 1.767
58
-
59
- const fieldLabel = lowerFirst(this.label)
60
-
61
- const customValidationMessages: LanguageMessages =
62
- convertToLanguageMessages({
63
- 'number.precision': tPlugin(
64
- 'components.latLongField.precision',
65
- 'en-GB'
66
- ),
67
- 'number.unsafe': tPlugin('components.latLongField.notANumber', 'en-GB')
68
- })
69
-
70
- const latitudeRangeMessage = tPlugin(
71
- 'components.latLongField.latitudeRange',
72
- 'en-GB',
73
- { fieldLabel, min: latitudeMin, max: latitudeMax }
74
- )
75
- const longitudeRangeMessage = tPlugin(
76
- 'components.latLongField.longitudeRange',
77
- 'en-GB',
78
- { fieldLabel, min: longitudeMin, max: longitudeMax }
79
- )
80
-
81
- const latitudeMessages: LanguageMessages = convertToLanguageMessages({
82
- ...customValidationMessages,
83
- 'any.required': tPlugin(
84
- 'components.latLongField.latitudeRequired',
85
- 'en-GB'
86
- ),
87
- 'number.base': tPlugin('components.latLongField.latitudeBase', 'en-GB', {
88
- fieldLabel
89
- }),
90
- 'number.min': latitudeRangeMessage,
91
- 'number.max': latitudeRangeMessage
92
- })
55
+ const { latitudeMin, latitudeMax, longitudeMin, longitudeMax } =
56
+ LatLongField.getMinMax(schema)
93
57
 
94
- const longitudeMessages: LanguageMessages = convertToLanguageMessages({
95
- ...customValidationMessages,
96
- 'any.required': tPlugin(
97
- 'components.latLongField.longitudeRequired',
58
+ const { latitudeMessages, longitudeMessages } =
59
+ LatLongField.buildErrorMessages(
60
+ this.label,
61
+ latitudeMin,
62
+ latitudeMax,
63
+ longitudeMin,
64
+ longitudeMax,
98
65
  'en-GB'
99
- ),
100
- 'number.base': tPlugin('components.latLongField.longitudeBase', 'en-GB', {
101
- fieldLabel
102
- }),
103
- 'number.min': longitudeRangeMessage,
104
- 'number.max': longitudeRangeMessage
105
- })
66
+ )
106
67
 
107
68
  this.collection = new ComponentCollection(
108
69
  [
@@ -159,14 +120,16 @@ export class LatLongField extends FormComponent {
159
120
 
160
121
  getDisplayStringFromFormValue(
161
122
  value: LatLongState | undefined,
162
- _translator: Translator
123
+ translator: Translator
163
124
  ): string {
164
125
  if (!value) {
165
126
  return ''
166
127
  }
167
128
 
168
- // CYA page format: <<latvalue, langvalue>>
169
- return `${value.latitude}, ${value.longitude}`
129
+ const { t } = translator
130
+
131
+ // Output format: Latitude: <<entry>>\nLongitude: <<entry>>
132
+ return `${t('components.latLongField.latitude')}: ${value.latitude}\n${t('components.latLongField.longitude')}: ${value.longitude}`
170
133
  }
171
134
 
172
135
  getDisplayStringFromState(
@@ -183,8 +146,7 @@ export class LatLongField extends FormComponent {
183
146
  return null
184
147
  }
185
148
 
186
- // Output format: Latitude: <<entry>>\nLongitude: <<entry>>
187
- return `Latitude: ${value.latitude}\nLongitude: ${value.longitude}`
149
+ return `${value.latitude}, ${value.longitude}`
188
150
  }
189
151
 
190
152
  getContextValueFromState(state: FormSubmissionState) {
@@ -210,6 +172,26 @@ export class LatLongField extends FormComponent {
210
172
  return LatLongField.isLatLong(value)
211
173
  }
212
174
 
175
+ getValidationMessagesOverride(translator: Translator) {
176
+ const def = this.def as LatLongFieldComponent
177
+ const translatedLabel = getTranslatedLabel(def, translator)
178
+ const { latitudeMin, latitudeMax, longitudeMin, longitudeMax } =
179
+ LatLongField.getMinMax(def.schema)
180
+ const { latitudeMessages, longitudeMessages } =
181
+ LatLongField.buildErrorMessages(
182
+ translatedLabel,
183
+ latitudeMin,
184
+ latitudeMax,
185
+ longitudeMin,
186
+ longitudeMax,
187
+ translator.language
188
+ )
189
+ return {
190
+ [`${this.name}__latitude`]: latitudeMessages,
191
+ [`${this.name}__longitude`]: longitudeMessages
192
+ }
193
+ }
194
+
213
195
  /**
214
196
  * For error preview page that shows all possible errors on a component
215
197
  */
@@ -273,4 +255,92 @@ export class LatLongField extends FormComponent {
273
255
  NumberField.isNumber(value.longitude)
274
256
  )
275
257
  }
258
+
259
+ static buildErrorMessages(
260
+ label: string,
261
+ latitudeMin: number,
262
+ latitudeMax: number,
263
+ longitudeMin: number,
264
+ longitudeMax: number,
265
+ language: string
266
+ ) {
267
+ const fieldLabel = lowerFirst(label)
268
+
269
+ const customValidationMessages: LanguageMessages = {
270
+ 'number.precision': tPlugin(
271
+ 'components.latLongField.precision',
272
+ language
273
+ ),
274
+ 'number.unsafe': tPlugin('components.latLongField.notANumber', language)
275
+ }
276
+
277
+ const latitudeRangeMessage = tPlugin(
278
+ 'components.latLongField.latitudeRange',
279
+ language,
280
+ { fieldLabel, min: latitudeMin, max: latitudeMax }
281
+ )
282
+ const longitudeRangeMessage = tPlugin(
283
+ 'components.latLongField.longitudeRange',
284
+ language,
285
+ { fieldLabel, min: longitudeMin, max: longitudeMax }
286
+ )
287
+
288
+ const latitudeMessages: LanguageMessages = {
289
+ ...customValidationMessages,
290
+ 'any.required': tPlugin(
291
+ 'components.latLongField.latitudeRequired',
292
+ language
293
+ ),
294
+ 'number.base': tPlugin('components.latLongField.latitudeBase', language, {
295
+ fieldLabel
296
+ }),
297
+ 'number.min': latitudeRangeMessage,
298
+ 'number.max': latitudeRangeMessage
299
+ }
300
+
301
+ const longitudeMessages: LanguageMessages = {
302
+ ...customValidationMessages,
303
+ 'any.required': tPlugin(
304
+ 'components.latLongField.longitudeRequired',
305
+ language
306
+ ),
307
+ 'number.base': tPlugin(
308
+ 'components.latLongField.longitudeBase',
309
+ language,
310
+ {
311
+ fieldLabel
312
+ }
313
+ ),
314
+ 'number.min': longitudeRangeMessage,
315
+ 'number.max': longitudeRangeMessage
316
+ }
317
+
318
+ return {
319
+ latitudeMessages,
320
+ longitudeMessages
321
+ }
322
+ }
323
+
324
+ // Read schema values from def.schema with fallback defaults
325
+ static getMinMax(
326
+ schema:
327
+ | {
328
+ latitude?: {
329
+ min?: number
330
+ max?: number
331
+ }
332
+ longitude?: {
333
+ min?: number
334
+ max?: number
335
+ }
336
+ }
337
+ | undefined
338
+ ) {
339
+ return {
340
+ latitudeMin: schema?.latitude?.min ?? 49.85,
341
+ latitudeMax: schema?.latitude?.max ?? 60.859,
342
+ longitudeMin: schema?.longitude?.min ?? -13.687,
343
+ longitudeMax: schema?.longitude?.max ?? 1.767
344
+ }
345
+ }
276
346
  }
@@ -31,16 +31,16 @@ export class ListFormComponent extends FormComponent {
31
31
  >['options']
32
32
 
33
33
  declare formSchema:
34
- | ArraySchema<string>
35
- | ArraySchema<number>
34
+ | ArraySchema<string[]>
35
+ | ArraySchema<number[]>
36
36
  | BooleanSchema<string>
37
37
  | NumberSchema<string>
38
38
  | NumberSchema
39
39
  | StringSchema
40
40
 
41
41
  declare stateSchema:
42
- | ArraySchema<string>
43
- | ArraySchema<number>
42
+ | ArraySchema<string[]>
43
+ | ArraySchema<number[]>
44
44
  | BooleanSchema<string>
45
45
  | NumberSchema<string>
46
46
  | NumberSchema
@@ -9,16 +9,20 @@ import {
9
9
  FormComponent,
10
10
  isFormValue
11
11
  } from './FormComponent.js'
12
- import { addClassOptionIfNone } from './helpers/index.js'
12
+ import {
13
+ addClassOptionIfNone,
14
+ withCustomValidationOverrides
15
+ } from './helpers/index.js'
13
16
  import { type RenderContext } from './types.js'
17
+ import { buildValidationMessages } from '../i18n/buildValidationMessages.js'
14
18
  import { messageTemplate } from '../pageControllers/validationOptions.js'
19
+ import { type Translator } from '../types/index.js'
15
20
  import {
16
21
  type ErrorMessageTemplateList,
17
22
  type FormState,
18
23
  type FormStateValue,
19
24
  type FormSubmissionState
20
25
  } from '../types.js'
21
- import { convertToLanguageMessages } from '../../../utils/type-utils.js'
22
26
 
23
27
  interface LocationFieldOptions {
24
28
  instructionText?: string
@@ -43,7 +47,9 @@ export abstract class LocationFieldBase extends FormComponent {
43
47
  declare stateSchema: StringSchema
44
48
  instructionText?: string
45
49
 
46
- protected abstract getValidationConfig(): ValidationConfig
50
+ protected abstract getValidationConfig(
51
+ translator: Translator | undefined
52
+ ): ValidationConfig
47
53
  protected abstract getErrorTemplates(): {
48
54
  type: string
49
55
  template: JoiExpression
@@ -61,14 +67,14 @@ export abstract class LocationFieldBase extends FormComponent {
61
67
 
62
68
  addClassOptionIfNone(locationOptions, 'govuk-input--width-10')
63
69
 
64
- const config = this.getValidationConfig()
70
+ const config = this.getValidationConfig(undefined)
65
71
  const requiredMessage = config.requiredMessage ?? messageTemplate.required
66
72
 
67
- const messages = convertToLanguageMessages({
73
+ const messages = {
68
74
  'any.required': requiredMessage,
69
75
  'string.empty': requiredMessage,
70
76
  'string.pattern.base': config.patternErrorMessage
71
- })
77
+ } as LanguageMessages
72
78
 
73
79
  let formSchema = joi
74
80
  .string()
@@ -121,18 +127,45 @@ export abstract class LocationFieldBase extends FormComponent {
121
127
  getViewModel(context: RenderContext) {
122
128
  const viewModel = super.getViewModel(context)
123
129
 
130
+ Object.assign(viewModel, {
131
+ lang: context.translator.language
132
+ })
133
+
124
134
  if (this.instructionText) {
135
+ const { tComponent } = context.translator
125
136
  return {
126
137
  ...viewModel,
127
- instructionText: this.instructionText
138
+ instructionText:
139
+ tComponent(this.def, 'instructionText') || this.instructionText
128
140
  }
129
141
  }
130
142
 
131
143
  return viewModel
132
144
  }
133
145
 
146
+ getValidationMessagesOverride(translator: Translator) {
147
+ const { customValidationMessage, customValidationMessages } = this.options
148
+ const { t } = translator
149
+ const config = this.getValidationConfig(translator)
150
+ const defaults = {
151
+ 'any.required':
152
+ config.requiredMessage ?? buildValidationMessages(t).objectRequired,
153
+ 'string.empty':
154
+ config.requiredMessage ?? buildValidationMessages(t).objectRequired,
155
+ 'string.pattern.base': config.patternErrorMessage
156
+ }
157
+
158
+ return {
159
+ [this.name]: withCustomValidationOverrides(
160
+ defaults,
161
+ customValidationMessage,
162
+ customValidationMessages
163
+ )
164
+ }
165
+ }
166
+
134
167
  getAllPossibleErrors(): ErrorMessageTemplateList {
135
- const config = this.getValidationConfig()
168
+ const config = this.getValidationConfig(undefined)
136
169
 
137
170
  return {
138
171
  baseErrors: [
@@ -1,6 +1,6 @@
1
1
  import { type Context, type CustomValidator } from 'joi'
2
2
 
3
- import { type EastingNorthingField } from './EastingNorthingField.js'
3
+ import { EastingNorthingField } from './EastingNorthingField.js'
4
4
  import { isFormValue } from './FormComponent.js'
5
5
  import { type GeospatialField } from './GeospatialField.js'
6
6
  import { type LatLongField } from './LatLongField.js'
@@ -11,6 +11,7 @@ import {
11
11
  type RenderContext,
12
12
  type ViewModel
13
13
  } from './types.js'
14
+ import { type Translator } from '../i18n/types.js'
14
15
  import {
15
16
  type FormPayload,
16
17
  type FormSubmissionError,
@@ -29,25 +30,25 @@ export type LocationField =
29
30
  * - "latitude must be..." -> "latitude must be..."
30
31
  */
31
32
  function lowercaseMessageStart(message: string): string {
32
- if (message.startsWith('Enter ')) {
33
- return 'enter' + message.slice(5)
34
- }
35
-
36
- // Lowercase first character for any other message
33
+ // Lowercase first character for a message
37
34
  return message.charAt(0).toLowerCase() + message.slice(1)
38
35
  }
39
36
 
40
- export function joinWithAnd(items: string[]): string {
37
+ export function joinWithAnd(items: string[], translator: Translator): string {
38
+ const { t } = translator
41
39
  if (items.length === 2) {
42
- return `${items[0]} and ${items[1]}`
40
+ return `${items[0]} ${t('common.and')} ${items[1]}`
43
41
  }
44
42
 
45
43
  const leading = items.slice(0, -1).join(', ')
46
44
  const last = items[items.length - 1]
47
- return `${leading} and ${last}`
45
+ return `${leading} ${t('common.and')} ${last}`
48
46
  }
49
47
 
50
- export function formatErrorList(messages: string[]): string {
48
+ export function formatErrorList(
49
+ messages: string[],
50
+ translator: Translator
51
+ ): string {
51
52
  if (!messages.length) {
52
53
  return ''
53
54
  }
@@ -60,7 +61,7 @@ export function formatErrorList(messages: string[]): string {
60
61
  index === 0 ? msg : lowercaseMessageStart(msg)
61
62
  )
62
63
 
63
- return joinWithAnd(formattedMessages)
64
+ return joinWithAnd(formattedMessages, translator)
64
65
  }
65
66
 
66
67
  export function mergeCssClasses(...classNames: (string | undefined)[]) {
@@ -172,7 +173,9 @@ export function getLocationFieldViewModel(
172
173
  if (hasFieldErrors) {
173
174
  viewModel.errorMessage = {
174
175
  text:
175
- fieldErrors.length === 1 ? fieldErrors[0] : formatErrorList(fieldErrors)
176
+ fieldErrors.length === 1
177
+ ? fieldErrors[0]
178
+ : formatErrorList(fieldErrors, context.translator)
176
179
  }
177
180
  }
178
181
 
@@ -187,13 +190,24 @@ export function getLocationFieldViewModel(
187
190
  ...viewModel,
188
191
  fieldset,
189
192
  items,
190
- mapLayers: getMapLayers(component)
193
+ mapLayers: getMapLayers(component),
194
+ country:
195
+ component instanceof EastingNorthingField
196
+ ? component.options.countries?.at(0)
197
+ : undefined,
198
+ lang: context.translator.language
191
199
  }
192
200
 
193
201
  if (component.options.instructionText) {
202
+ const { t, tComponent } = context.translator
203
+
194
204
  return {
195
205
  ...result,
196
- instructionText: component.options.instructionText
206
+ instructionSummary: t('components.locationFieldBase.howToFind'),
207
+ instructionText:
208
+ tComponent(component.def, 'instructionText') ||
209
+ component.options.instructionText,
210
+ t
197
211
  }
198
212
  }
199
213
 
@@ -1,4 +1,4 @@
1
- import { type ComponentDef, type MarkdownComponent } from '@defra/forms-model'
1
+ import { type MarkdownComponent } from '@defra/forms-model'
2
2
 
3
3
  import { ComponentBase } from './ComponentBase.js'
4
4
  import { type RenderContext } from './types.js'
@@ -28,8 +28,7 @@ export class Markdown extends ComponentBase {
28
28
 
29
29
  return {
30
30
  ...viewModel,
31
- content:
32
- tComponent(this as unknown as ComponentDef, 'content') || content,
31
+ content: tComponent(this.def, 'content') || content,
33
32
  headerStartLevel: this.headerStartLevel
34
33
  }
35
34
  }