@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
@@ -30,7 +30,7 @@ import {
30
30
  type FormStateValue,
31
31
  type FormSubmissionState
32
32
  } from '../types.js'
33
- import { convertToLanguageMessages } from '../../../utils/type-utils.js'
33
+ import { formatDateForLanguage } from '../../payment/helper.js'
34
34
 
35
35
  export class MonthYearField extends FormComponent {
36
36
  declare options: MonthYearFieldComponent['options']
@@ -48,16 +48,15 @@ export class MonthYearField extends FormComponent {
48
48
 
49
49
  const isRequired = options.required !== false
50
50
 
51
- const customValidationMessages: LanguageMessages =
52
- convertToLanguageMessages({
53
- 'any.required': messageTemplate.objectMissing,
54
- 'number.base': messageTemplate.objectMissing,
55
- 'number.precision': messageTemplate.dateFormat,
56
- 'number.integer': messageTemplate.dateFormat,
57
- 'number.unsafe': messageTemplate.dateFormat,
58
- 'number.min': messageTemplate.dateFormat,
59
- 'number.max': messageTemplate.dateFormat
60
- })
51
+ const customValidationMessages = {
52
+ 'any.required': messageTemplate.objectMissing,
53
+ 'number.base': messageTemplate.objectMissing,
54
+ 'number.precision': messageTemplate.dateFormat,
55
+ 'number.integer': messageTemplate.dateFormat,
56
+ 'number.unsafe': messageTemplate.dateFormat,
57
+ 'number.min': messageTemplate.dateFormat,
58
+ 'number.max': messageTemplate.dateFormat
59
+ } as LanguageMessages
61
60
 
62
61
  this.collection = new ComponentCollection(
63
62
  [
@@ -105,16 +104,18 @@ export class MonthYearField extends FormComponent {
105
104
 
106
105
  getDisplayStringFromFormValue(
107
106
  value: MonthYearState | undefined,
108
- _translator: Translator
107
+ translator: Translator
109
108
  ): string {
110
109
  if (!value) {
111
110
  return ''
112
111
  }
113
112
 
114
113
  const date = new Date()
114
+ // Force to first day of month in case current date was say 31st and specified month has fewer than 31 days
115
+ date.setDate(1)
115
116
  date.setMonth(value.month - 1)
116
117
 
117
- const monthString = date.toLocaleString('default', { month: 'long' })
118
+ const monthString = formatDateForLanguage(date, 'LLLL', translator.language)
118
119
  return `${monthString} ${value.year}`
119
120
  }
120
121
 
@@ -155,7 +156,7 @@ export class MonthYearField extends FormComponent {
155
156
 
156
157
  getValidationMessagesOverride(translator: Translator) {
157
158
  const { t } = translator
158
- return convertToLanguageMessages({
159
+ const messages = {
159
160
  'any.required': buildValidationMessages(t).objectMissing,
160
161
  'number.base': buildValidationMessages(t).objectMissing,
161
162
  'number.precision': buildValidationMessages(t).dateFormat,
@@ -163,7 +164,11 @@ export class MonthYearField extends FormComponent {
163
164
  'number.unsafe': buildValidationMessages(t).dateFormat,
164
165
  'number.min': buildValidationMessages(t).dateFormat,
165
166
  'number.max': buildValidationMessages(t).dateFormat
166
- })
167
+ } as LanguageMessages
168
+ return {
169
+ [`${this.name}__month`]: messages,
170
+ [`${this.name}__year`]: messages
171
+ }
167
172
  }
168
173
 
169
174
  getViewModel(context: RenderContext) {
@@ -1,14 +1,16 @@
1
1
  import { type NationalGridFieldNumberFieldComponent } from '@defra/forms-model'
2
2
 
3
+ import { EN_GB } from '../../../constants.js'
3
4
  import { LocationFieldBase } from './LocationFieldBase.js'
4
5
  import { createLowerFirstExpression } from './helpers/index.js'
5
6
  import { t } from '../i18n/index.js'
7
+ import { type Translator } from '../i18n/types.js'
6
8
  import { type ErrorMessageTemplateList } from '../types.js'
7
9
 
8
10
  export class NationalGridFieldNumberField extends LocationFieldBase {
9
11
  declare options: NationalGridFieldNumberFieldComponent['options']
10
12
 
11
- protected getValidationConfig() {
13
+ protected getValidationConfig(translator: Translator | undefined) {
12
14
  // Regex for OS national grid field references (NGFR)
13
15
  // Validates specific valid OS grid letter combinations with:
14
16
  // - 2 letters & 8 digits in 2 blocks of 4 e.g. ST 6789 6789
@@ -18,10 +20,14 @@ export class NationalGridFieldNumberField extends LocationFieldBase {
18
20
  return {
19
21
  pattern,
20
22
  patternErrorMessage: createLowerFirstExpression(
21
- t('components.nationalGridField.pattern', 'en-GB')
23
+ translator
24
+ ? translator.t('components.nationalGridField.pattern')
25
+ : t('components.nationalGridField.pattern', EN_GB)
22
26
  ),
23
27
  requiredMessage: createLowerFirstExpression(
24
- t('components.nationalGridField.required', 'en-GB')
28
+ translator
29
+ ? translator.t('components.nationalGridField.required')
30
+ : t('components.nationalGridField.required', EN_GB)
25
31
  )
26
32
  }
27
33
  }
@@ -5,8 +5,11 @@ import {
5
5
  FormComponent,
6
6
  isFormValue
7
7
  } from './FormComponent.js'
8
+ import { withCustomValidationOverrides } from './helpers/index.js'
8
9
  import { type RenderContext } from './types.js'
10
+ import { buildValidationMessages } from '../i18n/buildValidationMessages.js'
9
11
  import { messageTemplate } from '../pageControllers/validationOptions.js'
12
+ import { type Translator } from '../types/index.js'
10
13
  import {
11
14
  type ErrorMessageTemplateList,
12
15
  type FormState,
@@ -130,6 +133,27 @@ export class NumberField extends FormComponent {
130
133
  return NumberField.isNumber(value)
131
134
  }
132
135
 
136
+ getValidationMessagesOverride(translator: Translator) {
137
+ const { customValidationMessage, customValidationMessages } = this.options
138
+ const { t } = translator
139
+ const defaults = {
140
+ 'any.required': buildValidationMessages(t).objectRequired,
141
+ 'number.base': buildValidationMessages(t).objectMissing,
142
+ 'number.precision': buildValidationMessages(t).numberPrecision,
143
+ 'number.integer': buildValidationMessages(t).numberInteger,
144
+ 'number.min': buildValidationMessages(t).numberMin,
145
+ 'number.max': buildValidationMessages(t).numberMax
146
+ }
147
+
148
+ return {
149
+ [this.name]: withCustomValidationOverrides(
150
+ defaults,
151
+ customValidationMessage,
152
+ customValidationMessages
153
+ )
154
+ }
155
+ }
156
+
133
157
  /**
134
158
  * For error preview page that shows all possible errors on a component
135
159
  */
@@ -1,14 +1,29 @@
1
1
  import { type OsGridRefFieldComponent } from '@defra/forms-model'
2
2
 
3
+ import { EN_GB } from '../../../constants.js'
3
4
  import { LocationFieldBase } from './LocationFieldBase.js'
5
+ import { getMapLayers } from './LocationFieldHelpers.js'
4
6
  import { createLowerFirstExpression } from './helpers/index.js'
7
+ import { type RenderContext } from './types.js'
5
8
  import { t } from '../i18n/index.js'
9
+ import { type Translator } from '../types/index.js'
6
10
  import { type ErrorMessageTemplateList } from '../types.js'
7
11
 
8
12
  export class OsGridRefField extends LocationFieldBase {
9
13
  declare options: OsGridRefFieldComponent['options']
10
14
 
11
- protected getValidationConfig() {
15
+ getViewModel(context: RenderContext) {
16
+ const viewModel = super.getViewModel(context)
17
+
18
+ Object.assign(viewModel, {
19
+ lang: context.translator.language,
20
+ mapLayers: getMapLayers(this)
21
+ })
22
+
23
+ return viewModel
24
+ }
25
+
26
+ protected getValidationConfig(translator: Translator | undefined) {
12
27
  // Regex for OS national grid references (NGR)
13
28
  // Validates specific valid OS grid letter combinations with:
14
29
  // - 2 letters & 6 digits in 2 blocks of 3 e.g. ST 678 678
@@ -21,10 +36,14 @@ export class OsGridRefField extends LocationFieldBase {
21
36
  return {
22
37
  pattern,
23
38
  patternErrorMessage: createLowerFirstExpression(
24
- t('components.osGridRefField.pattern', 'en-GB')
39
+ translator
40
+ ? translator.t('components.osGridRefField.pattern')
41
+ : t('components.osGridRefField.pattern', EN_GB)
25
42
  ),
26
43
  requiredMessage: createLowerFirstExpression(
27
- t('components.osGridRefField.required', 'en-GB')
44
+ translator
45
+ ? translator.t('components.osGridRefField.required')
46
+ : t('components.osGridRefField.required', EN_GB)
28
47
  )
29
48
  }
30
49
  }
@@ -63,6 +63,7 @@ export class PaymentField extends FormComponent {
63
63
  reference: joi.string().required(),
64
64
  amount: joi.number().required(),
65
65
  description: joi.string().required(),
66
+ descriptionInEng: joi.string().optional(),
66
67
  uuid: joi.string().uuid().required(),
67
68
  formId: joi.string().required(),
68
69
  isLivePayment: joi.boolean().required(),
@@ -239,8 +240,9 @@ export class PaymentField extends FormComponent {
239
240
  ): Promise<unknown> {
240
241
  const { options, name: componentName } = args.component
241
242
  const { model } = args.controller
242
- const language = resolveLanguage(request)
243
- const { t } = model.createTranslator(language)
243
+ const { language, t, tComponent } = model.createTranslator(
244
+ resolveLanguage(request)
245
+ )
244
246
  const state = await args.controller.getState(request)
245
247
  const { baseUrl } = getPluginOptions(request.server)
246
248
  const summaryUrl = `${baseUrl}/${model.basePath}/summary`
@@ -272,7 +274,8 @@ export class PaymentField extends FormComponent {
272
274
  return h.redirect(summaryUrl).code(StatusCodes.SEE_OTHER)
273
275
  }
274
276
 
275
- const description = options.description
277
+ const description =
278
+ tComponent(args.component, 'paymentDescription') || options.description
276
279
 
277
280
  const slug = `/${model.basePath}`
278
281
 
@@ -292,7 +295,7 @@ export class PaymentField extends FormComponent {
292
295
  payCallbackUrl,
293
296
  reference,
294
297
  isLivePayment,
295
- { formId, slug },
298
+ { formId, slug, language },
296
299
  prefilledEmail
297
300
  )
298
301
 
@@ -313,6 +316,7 @@ export class PaymentField extends FormComponent {
313
316
  reference,
314
317
  amount: resolvedAmount,
315
318
  description,
319
+ descriptionInEng: options.description,
316
320
  paymentId: payment.paymentId,
317
321
  componentName,
318
322
  returnUrl: summaryUrl,
@@ -449,6 +453,7 @@ export interface PaymentSessionData {
449
453
  reference: string
450
454
  amount: number
451
455
  description: string
456
+ descriptionInEng?: string
452
457
  paymentId: string
453
458
  componentName: string
454
459
  returnUrl: string
@@ -0,0 +1,64 @@
1
+ import { type TrackingFieldComponent } from '@defra/forms-model'
2
+ import joi, { type BooleanSchema } from 'joi'
3
+
4
+ import {
5
+ FormComponent,
6
+ isFormValue
7
+ } from './FormComponent.js'
8
+ import { messageTemplate } from '../pageControllers/validationOptions.js'
9
+ import {
10
+ type ErrorMessageTemplateList,
11
+ type FormState,
12
+ type FormStateValue,
13
+ type FormSubmissionState
14
+ } from '../types.js'
15
+
16
+ export class TrackingField extends FormComponent {
17
+ declare formSchema: BooleanSchema
18
+ declare stateSchema: BooleanSchema
19
+ declare options: TrackingFieldComponent['options']
20
+
21
+ constructor(
22
+ def: TrackingFieldComponent,
23
+ props: ConstructorParameters<typeof FormComponent>[1]
24
+ ) {
25
+ super(def, props)
26
+
27
+ const formSchema = joi.boolean().valid(true).label(this.label).required()
28
+
29
+ this.formSchema = formSchema.default(false)
30
+ this.stateSchema = formSchema.default(null).allow(null)
31
+ this.schema = {}
32
+ this.options = {}
33
+ }
34
+
35
+ getFormValueFromState(state: FormSubmissionState) {
36
+ const { name } = this
37
+ return this.getFormValue(state[name])
38
+ }
39
+
40
+ isValue(value?: FormStateValue | FormState): value is true {
41
+ return TrackingField.isTracking(value)
42
+ }
43
+
44
+ /**
45
+ * For error preview page that shows all possible errors on a component
46
+ */
47
+ getAllPossibleErrors(): ErrorMessageTemplateList {
48
+ return TrackingField.getAllPossibleErrors()
49
+ }
50
+
51
+ static isTracking(value?: FormStateValue | FormState): value is true {
52
+ return isFormValue(value) && typeof value === 'boolean'
53
+ }
54
+
55
+ /**
56
+ * Static version of getAllPossibleErrors that doesn't require a component instance.
57
+ */
58
+ static getAllPossibleErrors(): ErrorMessageTemplateList {
59
+ return {
60
+ baseErrors: [{ type: 'required', template: messageTemplate.required }],
61
+ advancedSettingsErrors: []
62
+ }
63
+ }
64
+ }
@@ -1,4 +1,9 @@
1
- import { ComponentType, type UkAddressFieldComponent } from '@defra/forms-model'
1
+ import {
2
+ ComponentType,
3
+ FormStatus,
4
+ type FormMetadata,
5
+ type UkAddressFieldComponent
6
+ } from '@defra/forms-model'
2
7
  import { type ObjectSchema } from 'joi'
3
8
  import lowerFirst from 'lodash/lowerFirst.js'
4
9
 
@@ -9,6 +14,8 @@ import {
9
14
  } from './FormComponent.js'
10
15
  import { TextField } from './TextField.js'
11
16
  import { type RenderContext } from './types.js'
17
+ import { getCachedPluginTranslator } from '../i18n/form.js'
18
+ import { getAvailableLanguages } from '../i18n/languages.js'
12
19
  import { type Translator } from '../i18n/types.js'
13
20
  import {
14
21
  type FormRequestPayload,
@@ -207,7 +214,7 @@ export class UkAddressField extends FormComponent {
207
214
 
208
215
  /**
209
216
  * For screen readers, only hide legend visually. This can be overridden
210
- * by single component {@link QuestionPageController | `showTitle` handling}
217
+ * by single component (see QuestionPageController and showTitle handling)
211
218
  */
212
219
  classes: options.hideTitle
213
220
  ? 'govuk-visually-hidden'
@@ -290,7 +297,6 @@ export class UkAddressField extends FormComponent {
290
297
  )
291
298
  }
292
299
 
293
- // eslint-disable-next-line @typescript-eslint/require-await
294
300
  static async dispatcher(
295
301
  request: FormRequestPayload,
296
302
  h: FormResponseToolkit,
@@ -299,14 +305,31 @@ export class UkAddressField extends FormComponent {
299
305
  const { controller, component } = args
300
306
  const language = resolveLanguage(request)
301
307
 
308
+ const availableLanguages = getAvailableLanguages(controller.model.def)
309
+ const languages = availableLanguages.length
310
+ ? { languages: availableLanguages }
311
+ : {}
312
+
313
+ const translator = await getCachedPluginTranslator(
314
+ request,
315
+ { id: controller.model.formId } as unknown as FormMetadata,
316
+ args.isLive ? FormStatus.Live : FormStatus.Draft,
317
+ language
318
+ )
319
+ const { tComponent, tForm } = translator
320
+
302
321
  return dispatch(request, h, {
303
- formName: controller.model.name,
322
+ formName: tForm('title'),
323
+ formId: controller.model.formId,
324
+ formStatus: args.isLive ? FormStatus.Live : FormStatus.Draft,
325
+ componentId: component.id ?? 'unknown',
304
326
  componentName: component.name,
305
- componentHint: component.hint,
306
- componentTitle: component.title || controller.title,
327
+ componentHint: tComponent(component, 'hint'),
328
+ componentTitle: tComponent(component, 'title') || controller.title,
307
329
  step: args.actionArgs.step,
308
330
  sourceUrl: args.sourceUrl,
309
- language
331
+ language,
332
+ ...languages
310
333
  })
311
334
  }
312
335
  }
@@ -4,15 +4,16 @@ import {
4
4
  yesNoListName,
5
5
  type YesNoFieldComponent
6
6
  } from '@defra/forms-model'
7
- import { type LanguageMessages } from 'joi'
8
7
 
9
8
  import { SelectionControlField } from './SelectionControlField.js'
10
- import { addClassOptionIfNone } from './helpers/index.js'
9
+ import {
10
+ addClassOptionIfNone,
11
+ withCustomValidationOverrides
12
+ } from './helpers/index.js'
11
13
  import { buildValidationMessages } from '../i18n/buildValidationMessages.js'
12
14
  import { type Translator } from '../i18n/types.js'
13
15
  import { messageTemplate } from '../pageControllers/validationOptions.js'
14
16
  import { type ErrorMessageTemplateList } from '../types.js'
15
- import { convertToLanguageMessages } from '../../../utils/type-utils.js'
16
17
 
17
18
  /**
18
19
  * @description
@@ -45,21 +46,38 @@ export class YesNoField extends SelectionControlField {
45
46
  formSchema = formSchema.optional()
46
47
  }
47
48
 
48
- formSchema = formSchema.messages(
49
- convertToLanguageMessages({
49
+ if (options.customValidationMessage) {
50
+ const message = options.customValidationMessage
51
+
52
+ formSchema = formSchema.messages({
53
+ 'any.required': message
54
+ })
55
+ } else if (options.customValidationMessages) {
56
+ formSchema = formSchema.messages(options.customValidationMessages)
57
+ } else {
58
+ formSchema = formSchema.messages({
50
59
  'any.required': messageTemplate.selectYesNoRequired
51
60
  })
52
- )
61
+ }
53
62
 
54
63
  this.formSchema = formSchema
55
64
  this.options = options
56
65
  }
57
66
 
58
- getValidationMessagesOverride(translator: Translator): LanguageMessages {
67
+ getValidationMessagesOverride(translator: Translator) {
68
+ const { customValidationMessage, customValidationMessages } = this.options
59
69
  const { selectYesNoRequired } = buildValidationMessages(translator.t)
60
- return convertToLanguageMessages({
70
+ const defaults = {
61
71
  'any.required': selectYesNoRequired
62
- })
72
+ }
73
+
74
+ return {
75
+ [this.name]: withCustomValidationOverrides(
76
+ defaults,
77
+ customValidationMessage,
78
+ customValidationMessages
79
+ )
80
+ }
63
81
  }
64
82
 
65
83
  /**
@@ -6,6 +6,7 @@ import { ListFormComponent } from '../ListFormComponent.js'
6
6
  import { escapeMarkdown } from './index.js'
7
7
  import * as Components from '../index.js'
8
8
  import { markdown } from '../markdownParser.js'
9
+ import { UnknownComponentTypeError } from '../../errors.js'
9
10
  import { type Translator } from '../../i18n/types.js'
10
11
  import { type FormState } from '../../types.js'
11
12
 
@@ -36,6 +37,7 @@ export type Field = InstanceType<
36
37
  | typeof Components.UkAddressField
37
38
  | typeof Components.FileUploadField
38
39
  | typeof Components.HiddenField
40
+ | typeof Components.TrackingField
39
41
  | typeof Components.PaymentField
40
42
  | typeof Components.GeospatialField
41
43
  >
@@ -200,6 +202,10 @@ export function createComponent(
200
202
  component = new Components.HiddenField(def, options)
201
203
  break
202
204
 
205
+ case ComponentType.TrackingField:
206
+ component = new Components.TrackingField(def, options)
207
+ break
208
+
203
209
  case ComponentType.PaymentField:
204
210
  component = new Components.PaymentField(def, options)
205
211
  break
@@ -210,7 +216,7 @@ export function createComponent(
210
216
  }
211
217
 
212
218
  if (typeof component === 'undefined') {
213
- throw new Error(`Component type ${def.type} does not exist`)
219
+ throw new UnknownComponentTypeError(def.type)
214
220
  }
215
221
 
216
222
  return component
@@ -347,8 +353,7 @@ export function getAnswerMarkdown(
347
353
  field instanceof Components.EastingNorthingField ||
348
354
  field instanceof Components.LatLongField
349
355
  ) {
350
- const contextValue = field.getContextValueFromState(state)
351
- answerEscaped = contextValue ? `${contextValue}\n` : ''
356
+ answerEscaped = answer ? `${answer}\n` : ''
352
357
  } else if (field instanceof Components.GeospatialField) {
353
358
  const features = field.getFormValueFromState(state)
354
359
  const value = field.getDisplayStringFromFormValue(features, translator)
@@ -1,26 +1,23 @@
1
1
  import {
2
- GeospatialFieldOptionsCountryEnum,
3
2
  type GeospatialFieldComponent,
4
3
  type GeospatialFieldOptionsCountry
5
4
  } from '@defra/forms-model'
6
5
  import Bourne from '@hapi/bourne'
7
6
  import { booleanWithin } from '@turf/boolean-within'
7
+ import { point } from '@turf/helpers'
8
+ import OsGridRef from 'geodesy/osgridref.js'
8
9
  import JoiBase, { type CustomValidator } from 'joi'
9
10
 
11
+ import { type EastingNorthingField } from '../EastingNorthingField.js'
12
+ import { type EastingNorthingState } from '../types.js'
10
13
  import {
11
14
  type Coordinates,
12
15
  type Feature,
13
16
  type FeatureProperties,
14
17
  type Geometry
15
18
  } from '../../types.js'
16
- import { countries } from '../../../map/routes/index.js'
17
-
18
- const countriesDesc: Record<GeospatialFieldOptionsCountryEnum, string> = {
19
- [GeospatialFieldOptionsCountryEnum.England]: 'England',
20
- [GeospatialFieldOptionsCountryEnum.NorthernIreland]: 'Northern Ireland',
21
- [GeospatialFieldOptionsCountryEnum.Scotland]: 'Scotland',
22
- [GeospatialFieldOptionsCountryEnum.Wales]: 'Wales'
23
- }
19
+ import { countriesValidate } from '../../../map/routes/index.js'
20
+ import { CountryMap } from '../../../map/types.js'
24
21
 
25
22
  const Joi = JoiBase.extend({
26
23
  type: 'array',
@@ -98,25 +95,43 @@ const featureSchema = Joi.object<Feature>().keys({
98
95
  geometry: featureGeometrySchema
99
96
  })
100
97
 
101
- function applySchemaConstraints(
102
- schema: JoiBase.ArraySchema<Feature[]>,
103
- def: GeospatialFieldComponent
98
+ export function determineLimits(
99
+ def: GeospatialFieldComponent,
100
+ isOptional: boolean
104
101
  ) {
105
- const { options, schema: constraints } = def
106
- const isOptional = options.required === false
107
-
102
+ const { schema: constraints } = def
103
+ const limits: { min?: number; max?: number; length?: number } = {}
108
104
  if (typeof constraints?.length === 'number') {
109
- schema = schema.length(constraints.length)
105
+ limits.length = constraints.length
110
106
  } else {
111
107
  if (typeof constraints?.min === 'number') {
112
- schema = schema.min(constraints.min)
108
+ limits.min = constraints.min
113
109
  } else if (!isOptional) {
114
- schema = schema.min(1)
110
+ limits.min = 1
115
111
  }
116
112
 
117
- schema = schema.max(
118
- typeof constraints?.max === 'number' ? constraints.max : 50
119
- )
113
+ limits.max = typeof constraints?.max === 'number' ? constraints.max : 50
114
+ }
115
+ return limits
116
+ }
117
+
118
+ function applySchemaConstraints(
119
+ schema: JoiBase.ArraySchema<Feature[]>,
120
+ def: GeospatialFieldComponent
121
+ ) {
122
+ const { options } = def
123
+ const isOptional = options.required === false
124
+
125
+ const limits = determineLimits(def, isOptional)
126
+
127
+ if (limits.length !== undefined) {
128
+ schema = schema.length(limits.length)
129
+ }
130
+ if (limits.min !== undefined) {
131
+ schema = schema.min(limits.min)
132
+ }
133
+ if (limits.max !== undefined) {
134
+ schema = schema.max(limits.max)
120
135
  }
121
136
 
122
137
  if (isOptional) {
@@ -143,8 +158,8 @@ export function getGeospatialSchema(
143
158
  }
144
159
 
145
160
  const validateCountryBounds: CustomValidator = (value, helpers) => {
146
- const countryFeature = countries.features.find(
147
- (feature) => feature.id === country
161
+ const countryFeature = countriesValidate.features.find(
162
+ (feature) => feature.id === CountryMap[country]
148
163
  )
149
164
 
150
165
  if (!countryFeature) {
@@ -156,7 +171,7 @@ export function getGeospatialSchema(
156
171
 
157
172
  if (!result) {
158
173
  return helpers.error('any.custom', {
159
- country: countriesDesc[country as GeospatialFieldOptionsCountryEnum]
174
+ country
160
175
  })
161
176
  }
162
177
 
@@ -171,3 +186,51 @@ export function getGeospatialSchema(
171
186
  def
172
187
  )
173
188
  }
189
+
190
+ export function getEastingNorthingCountryValidator(
191
+ field: EastingNorthingField,
192
+ country: GeospatialFieldOptionsCountry
193
+ ) {
194
+ const validateCountryBounds: CustomValidator = (value, helpers) => {
195
+ const countryFeature = countriesValidate.features.find(
196
+ (feature) => feature.id === CountryMap[country]
197
+ )
198
+
199
+ if (!countryFeature) {
200
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
201
+ return value
202
+ }
203
+
204
+ const eastingNorthing = field.getFormValueFromState(
205
+ value as EastingNorthingState
206
+ )
207
+
208
+ if (!eastingNorthing) {
209
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
210
+ return value
211
+ }
212
+
213
+ const gridRef = new OsGridRef(
214
+ eastingNorthing.easting,
215
+ eastingNorthing.northing
216
+ )
217
+ const latLong = gridRef.toLatLon()
218
+ const coord = point([latLong.longitude, latLong.latitude])
219
+ const within = booleanWithin(coord, countryFeature)
220
+
221
+ if (!within) {
222
+ return helpers.error(
223
+ 'any.custom',
224
+ {
225
+ country
226
+ },
227
+ { path: [field.name] }
228
+ )
229
+ }
230
+
231
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
232
+ return value
233
+ }
234
+
235
+ return validateCountryBounds
236
+ }