@ministryofjustice/frontend 4.0.0 → 5.0.0

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 (245) hide show
  1. package/govuk-prototype-kit.config.json +19 -4
  2. package/moj/_base.scss +2 -0
  3. package/moj/_base.scss.map +1 -0
  4. package/moj/all.bundle.js +2523 -0
  5. package/moj/all.bundle.js.map +1 -0
  6. package/moj/all.bundle.mjs +2502 -0
  7. package/moj/all.bundle.mjs.map +1 -0
  8. package/moj/all.mjs +59 -69
  9. package/moj/all.mjs.map +1 -1
  10. package/moj/all.scss +2 -0
  11. package/moj/all.scss.map +1 -0
  12. package/moj/components/_all.scss +2 -0
  13. package/moj/components/_all.scss.map +1 -0
  14. package/moj/components/action-bar/_action-bar.scss +2 -0
  15. package/moj/components/action-bar/_action-bar.scss.map +1 -0
  16. package/moj/components/add-another/_add-another.scss +2 -0
  17. package/moj/components/add-another/_add-another.scss.map +1 -0
  18. package/moj/components/add-another/add-another.bundle.js +128 -0
  19. package/moj/components/add-another/add-another.bundle.js.map +1 -0
  20. package/moj/components/add-another/add-another.bundle.mjs +120 -0
  21. package/moj/components/add-another/add-another.bundle.mjs.map +1 -0
  22. package/moj/components/add-another/add-another.mjs +112 -99
  23. package/moj/components/add-another/add-another.mjs.map +1 -1
  24. package/moj/components/alert/_alert.scss +4 -0
  25. package/moj/components/alert/_alert.scss.map +1 -0
  26. package/moj/components/alert/alert.bundle.js +330 -0
  27. package/moj/components/alert/alert.bundle.js.map +1 -0
  28. package/moj/components/alert/alert.bundle.mjs +322 -0
  29. package/moj/components/alert/alert.bundle.mjs.map +1 -0
  30. package/moj/components/alert/alert.mjs +181 -217
  31. package/moj/components/alert/alert.mjs.map +1 -1
  32. package/moj/components/alert/{alert.spec.helper.js → alert.spec.helper.bundle.js} +1 -1
  33. package/moj/components/alert/alert.spec.helper.bundle.js.map +1 -0
  34. package/moj/components/alert/alert.spec.helper.bundle.mjs +67 -0
  35. package/moj/components/alert/alert.spec.helper.bundle.mjs.map +1 -0
  36. package/moj/components/alert/alert.spec.helper.mjs.map +1 -1
  37. package/moj/components/badge/_badge.scss +2 -0
  38. package/moj/components/badge/_badge.scss.map +1 -0
  39. package/moj/components/banner/_banner.scss +2 -0
  40. package/moj/components/banner/_banner.scss.map +1 -0
  41. package/moj/components/button-menu/README.md +10 -6
  42. package/moj/components/button-menu/_button-menu.scss +10 -3
  43. package/moj/components/button-menu/_button-menu.scss.map +1 -0
  44. package/moj/components/button-menu/button-menu.bundle.js +299 -0
  45. package/moj/components/button-menu/button-menu.bundle.js.map +1 -0
  46. package/moj/components/button-menu/{button-menu.js → button-menu.bundle.mjs} +74 -121
  47. package/moj/components/button-menu/button-menu.bundle.mjs.map +1 -0
  48. package/moj/components/button-menu/button-menu.mjs +246 -285
  49. package/moj/components/button-menu/button-menu.mjs.map +1 -1
  50. package/moj/components/cookie-banner/_cookie-banner.scss +2 -0
  51. package/moj/components/cookie-banner/_cookie-banner.scss.map +1 -0
  52. package/moj/components/currency-input/_currency-input.scss +2 -0
  53. package/moj/components/currency-input/_currency-input.scss.map +1 -0
  54. package/moj/components/date-picker/_date-picker.scss +2 -0
  55. package/moj/components/date-picker/_date-picker.scss.map +1 -0
  56. package/moj/components/date-picker/date-picker.bundle.js +784 -0
  57. package/moj/components/date-picker/date-picker.bundle.js.map +1 -0
  58. package/moj/components/date-picker/{date-picker.js → date-picker.bundle.mjs} +245 -439
  59. package/moj/components/date-picker/date-picker.bundle.mjs.map +1 -0
  60. package/moj/components/date-picker/date-picker.mjs +654 -840
  61. package/moj/components/date-picker/date-picker.mjs.map +1 -1
  62. package/moj/components/filter/_filter.scss +2 -0
  63. package/moj/components/filter/_filter.scss.map +1 -0
  64. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js +96 -0
  65. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js.map +1 -0
  66. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs +88 -0
  67. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs.map +1 -0
  68. package/moj/components/filter-toggle-button/filter-toggle-button.mjs +78 -84
  69. package/moj/components/filter-toggle-button/filter-toggle-button.mjs.map +1 -1
  70. package/moj/components/form-validator/form-validator.bundle.js +198 -0
  71. package/moj/components/form-validator/form-validator.bundle.js.map +1 -0
  72. package/moj/components/form-validator/form-validator.bundle.mjs +190 -0
  73. package/moj/components/form-validator/form-validator.bundle.mjs.map +1 -0
  74. package/moj/components/form-validator/form-validator.mjs +149 -152
  75. package/moj/components/form-validator/form-validator.mjs.map +1 -1
  76. package/moj/components/header/_header.scss +2 -0
  77. package/moj/components/header/_header.scss.map +1 -0
  78. package/moj/components/identity-bar/_identity-bar.scss +2 -0
  79. package/moj/components/identity-bar/_identity-bar.scss.map +1 -0
  80. package/moj/components/interruption-card/_interruption-card.scss +2 -0
  81. package/moj/components/interruption-card/_interruption-card.scss.map +1 -0
  82. package/moj/components/messages/_messages.scss +2 -0
  83. package/moj/components/messages/_messages.scss.map +1 -0
  84. package/moj/components/multi-file-upload/_multi-file-upload.scss +2 -0
  85. package/moj/components/multi-file-upload/_multi-file-upload.scss.map +1 -0
  86. package/moj/components/multi-file-upload/multi-file-upload.bundle.js +223 -0
  87. package/moj/components/multi-file-upload/multi-file-upload.bundle.js.map +1 -0
  88. package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs +215 -0
  89. package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs.map +1 -0
  90. package/moj/components/multi-file-upload/multi-file-upload.mjs +193 -209
  91. package/moj/components/multi-file-upload/multi-file-upload.mjs.map +1 -1
  92. package/moj/components/multi-select/_multi-select.scss +2 -0
  93. package/moj/components/multi-select/_multi-select.scss.map +1 -0
  94. package/moj/components/multi-select/multi-select.bundle.js +78 -0
  95. package/moj/components/multi-select/multi-select.bundle.js.map +1 -0
  96. package/moj/components/multi-select/multi-select.bundle.mjs +70 -0
  97. package/moj/components/multi-select/multi-select.bundle.mjs.map +1 -0
  98. package/moj/components/multi-select/multi-select.mjs +59 -67
  99. package/moj/components/multi-select/multi-select.mjs.map +1 -1
  100. package/moj/components/notification-badge/_notification-badge.scss +2 -0
  101. package/moj/components/notification-badge/_notification-badge.scss.map +1 -0
  102. package/moj/components/organisation-switcher/_organisation-switcher.scss +2 -0
  103. package/moj/components/organisation-switcher/_organisation-switcher.scss.map +1 -0
  104. package/moj/components/page-header-actions/_page-header-actions.scss +2 -0
  105. package/moj/components/page-header-actions/_page-header-actions.scss.map +1 -0
  106. package/moj/components/page-header-actions/template.njk +1 -1
  107. package/moj/components/pagination/_pagination.scss +2 -2
  108. package/moj/components/pagination/_pagination.scss.map +1 -0
  109. package/moj/components/password-reveal/_password-reveal.scss +2 -0
  110. package/moj/components/password-reveal/_password-reveal.scss.map +1 -0
  111. package/moj/components/password-reveal/password-reveal.bundle.js +49 -0
  112. package/moj/components/password-reveal/password-reveal.bundle.js.map +1 -0
  113. package/moj/components/password-reveal/password-reveal.bundle.mjs +41 -0
  114. package/moj/components/password-reveal/password-reveal.bundle.mjs.map +1 -0
  115. package/moj/components/password-reveal/password-reveal.mjs +36 -31
  116. package/moj/components/password-reveal/password-reveal.mjs.map +1 -1
  117. package/moj/components/primary-navigation/_primary-navigation.scss +2 -0
  118. package/moj/components/primary-navigation/_primary-navigation.scss.map +1 -0
  119. package/moj/components/progress-bar/_progress-bar.scss +2 -0
  120. package/moj/components/progress-bar/_progress-bar.scss.map +1 -0
  121. package/moj/components/rich-text-editor/README.md +15 -9
  122. package/moj/components/rich-text-editor/_rich-text-editor.scss +2 -0
  123. package/moj/components/rich-text-editor/_rich-text-editor.scss.map +1 -0
  124. package/moj/components/rich-text-editor/rich-text-editor.bundle.js +145 -0
  125. package/moj/components/rich-text-editor/rich-text-editor.bundle.js.map +1 -0
  126. package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs +137 -0
  127. package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs.map +1 -0
  128. package/moj/components/rich-text-editor/rich-text-editor.mjs +124 -145
  129. package/moj/components/rich-text-editor/rich-text-editor.mjs.map +1 -1
  130. package/moj/components/search/_search.scss +2 -0
  131. package/moj/components/search/_search.scss.map +1 -0
  132. package/moj/components/search-toggle/{search-toggle.scss → _search-toggle.scss} +2 -0
  133. package/moj/components/search-toggle/_search-toggle.scss.map +1 -0
  134. package/moj/components/search-toggle/search-toggle.bundle.js +54 -0
  135. package/moj/components/search-toggle/search-toggle.bundle.js.map +1 -0
  136. package/moj/components/search-toggle/search-toggle.bundle.mjs +46 -0
  137. package/moj/components/search-toggle/search-toggle.bundle.mjs.map +1 -0
  138. package/moj/components/search-toggle/search-toggle.mjs +40 -49
  139. package/moj/components/search-toggle/search-toggle.mjs.map +1 -1
  140. package/moj/components/side-navigation/_side-navigation.scss +2 -0
  141. package/moj/components/side-navigation/_side-navigation.scss.map +1 -0
  142. package/moj/components/sortable-table/_sortable-table.scss +2 -2
  143. package/moj/components/sortable-table/_sortable-table.scss.map +1 -0
  144. package/moj/components/sortable-table/sortable-table.bundle.js +134 -0
  145. package/moj/components/sortable-table/sortable-table.bundle.js.map +1 -0
  146. package/moj/components/sortable-table/sortable-table.bundle.mjs +126 -0
  147. package/moj/components/sortable-table/sortable-table.bundle.mjs.map +1 -0
  148. package/moj/components/sortable-table/sortable-table.mjs +117 -130
  149. package/moj/components/sortable-table/sortable-table.mjs.map +1 -1
  150. package/moj/components/sub-navigation/_sub-navigation.scss +2 -0
  151. package/moj/components/sub-navigation/_sub-navigation.scss.map +1 -0
  152. package/moj/components/tag/_tag.scss +2 -0
  153. package/moj/components/tag/_tag.scss.map +1 -0
  154. package/moj/components/task-list/_task-list.scss +2 -0
  155. package/moj/components/task-list/_task-list.scss.map +1 -0
  156. package/moj/components/ticket-panel/_ticket-panel.scss +2 -0
  157. package/moj/components/ticket-panel/_ticket-panel.scss.map +1 -0
  158. package/moj/components/timeline/_timeline.scss +2 -0
  159. package/moj/components/timeline/_timeline.scss.map +1 -0
  160. package/moj/filters/all.js +44 -22
  161. package/moj/helpers/_all.scss +2 -0
  162. package/moj/helpers/_all.scss.map +1 -0
  163. package/moj/helpers/_hidden.scss +2 -0
  164. package/moj/helpers/_hidden.scss.map +1 -0
  165. package/moj/helpers/_links.scss +2 -0
  166. package/moj/helpers/_links.scss.map +1 -0
  167. package/moj/{helpers.js → helpers.bundle.js} +37 -42
  168. package/moj/helpers.bundle.js.map +1 -0
  169. package/moj/helpers.bundle.mjs +179 -0
  170. package/moj/helpers.bundle.mjs.map +1 -0
  171. package/moj/helpers.mjs +52 -28
  172. package/moj/helpers.mjs.map +1 -1
  173. package/moj/init.js +11 -2
  174. package/moj/moj-frontend.min.css +1 -1
  175. package/moj/moj-frontend.min.css.map +1 -1
  176. package/moj/moj-frontend.min.js +1 -1
  177. package/moj/moj-frontend.min.js.map +1 -1
  178. package/moj/objects/_all.scss +2 -0
  179. package/moj/objects/_all.scss.map +1 -0
  180. package/moj/objects/_button-group.scss +17 -1
  181. package/moj/objects/_button-group.scss.map +1 -0
  182. package/moj/objects/_filter-layout.scss +2 -0
  183. package/moj/objects/_filter-layout.scss.map +1 -0
  184. package/moj/objects/_scrollable-pane.scss +2 -0
  185. package/moj/objects/_scrollable-pane.scss.map +1 -0
  186. package/moj/objects/_width-container.scss +2 -0
  187. package/moj/objects/_width-container.scss.map +1 -0
  188. package/moj/settings/_all.scss +2 -0
  189. package/moj/settings/_all.scss.map +1 -0
  190. package/moj/settings/_assets.scss +2 -0
  191. package/moj/settings/_assets.scss.map +1 -0
  192. package/moj/settings/_colours.scss +2 -0
  193. package/moj/settings/_colours.scss.map +1 -0
  194. package/moj/settings/_measurements.scss +2 -0
  195. package/moj/settings/_measurements.scss.map +1 -0
  196. package/moj/settings/_typography.scss +2 -0
  197. package/moj/settings/_typography.scss.map +1 -0
  198. package/moj/template.njk +13 -0
  199. package/moj/utilities/_all.scss +2 -0
  200. package/moj/utilities/_all.scss.map +1 -0
  201. package/moj/utilities/_hidden.scss +2 -0
  202. package/moj/utilities/_hidden.scss.map +1 -0
  203. package/moj/utilities/_width-container.scss +2 -0
  204. package/moj/utilities/_width-container.scss.map +1 -0
  205. package/moj/vendor/govuk-frontend/_base.scss +2 -0
  206. package/moj/vendor/govuk-frontend/_base.scss.map +1 -0
  207. package/moj/vendor/govuk-frontend/_index.scss +2 -0
  208. package/moj/vendor/govuk-frontend/_index.scss.map +1 -0
  209. package/moj/{version.js → version.bundle.js} +1 -1
  210. package/moj/version.bundle.js.map +1 -0
  211. package/moj/version.bundle.mjs +4 -0
  212. package/moj/version.bundle.mjs.map +1 -0
  213. package/moj/version.mjs.map +1 -1
  214. package/package.json +5 -6
  215. package/moj/all.jquery.min.js +0 -1
  216. package/moj/all.jquery.min.js.map +0 -1
  217. package/moj/all.js +0 -2662
  218. package/moj/all.js.map +0 -1
  219. package/moj/components/add-another/add-another.js +0 -115
  220. package/moj/components/add-another/add-another.js.map +0 -1
  221. package/moj/components/alert/alert.js +0 -356
  222. package/moj/components/alert/alert.js.map +0 -1
  223. package/moj/components/alert/alert.spec.helper.js.map +0 -1
  224. package/moj/components/button-menu/button-menu.js.map +0 -1
  225. package/moj/components/date-picker/date-picker.js.map +0 -1
  226. package/moj/components/filter-toggle-button/filter-toggle-button.js +0 -102
  227. package/moj/components/filter-toggle-button/filter-toggle-button.js.map +0 -1
  228. package/moj/components/form-validator/form-validator.js +0 -205
  229. package/moj/components/form-validator/form-validator.js.map +0 -1
  230. package/moj/components/multi-file-upload/multi-file-upload.js +0 -241
  231. package/moj/components/multi-file-upload/multi-file-upload.js.map +0 -1
  232. package/moj/components/multi-select/multi-select.js +0 -86
  233. package/moj/components/multi-select/multi-select.js.map +0 -1
  234. package/moj/components/password-reveal/password-reveal.js +0 -44
  235. package/moj/components/password-reveal/password-reveal.js.map +0 -1
  236. package/moj/components/rich-text-editor/rich-text-editor.js +0 -166
  237. package/moj/components/rich-text-editor/rich-text-editor.js.map +0 -1
  238. package/moj/components/search-toggle/search-toggle.js +0 -63
  239. package/moj/components/search-toggle/search-toggle.js.map +0 -1
  240. package/moj/components/sortable-table/sortable-table.js +0 -147
  241. package/moj/components/sortable-table/sortable-table.js.map +0 -1
  242. package/moj/helpers.js.map +0 -1
  243. package/moj/vendor/html5shiv.js +0 -326
  244. package/moj/vendor/jquery.js +0 -9300
  245. package/moj/version.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-validator.bundle.mjs","sources":["../../../../src/moj/helpers.mjs","../../../../src/moj/components/form-validator/form-validator.mjs"],"sourcesContent":["export function removeAttributeValue(el, attr, value) {\n let re, m\n if (el.getAttribute(attr)) {\n if (el.getAttribute(attr) === value) {\n el.removeAttribute(attr)\n } else {\n re = new RegExp(`(^|\\\\s)${value}(\\\\s|$)`)\n m = el.getAttribute(attr).match(re)\n if (m && m.length === 3) {\n el.setAttribute(\n attr,\n el.getAttribute(attr).replace(re, m[1] && m[2] ? ' ' : '')\n )\n }\n }\n }\n}\n\nexport function addAttributeValue(el, attr, value) {\n let re\n if (!el.getAttribute(attr)) {\n el.setAttribute(attr, value)\n } else {\n re = new RegExp(`(^|\\\\s)${value}(\\\\s|$)`)\n if (!re.test(el.getAttribute(attr))) {\n el.setAttribute(attr, `${el.getAttribute(attr)} ${value}`)\n }\n }\n}\n\nexport function dragAndDropSupported() {\n const div = document.createElement('div')\n return typeof div.ondrop !== 'undefined'\n}\n\nexport function formDataSupported() {\n return typeof FormData === 'function'\n}\n\nexport function fileApiSupported() {\n const input = document.createElement('input')\n input.type = 'file'\n return typeof input.files !== 'undefined'\n}\n\n/**\n * Find an elements next sibling\n *\n * Utility function to find an elements next sibling matching the provided\n * selector.\n *\n * @param {Element | null} $element - Element to find siblings for\n * @param {string} [selector] - selector for required sibling\n */\nexport function getNextSibling($element, selector) {\n if (!$element || !($element instanceof HTMLElement)) {\n return\n }\n\n // Get the next sibling element\n let $sibling = $element.nextElementSibling\n\n // If there's no selector, return the first sibling\n if (!selector) return $sibling\n\n // If the sibling matches our selector, use it\n // If not, jump to the next sibling and continue the loop\n while ($sibling) {\n if ($sibling.matches(selector)) return $sibling\n $sibling = $sibling.nextElementSibling\n }\n}\n\n/**\n * Find an elements preceding sibling\n *\n * Utility function to find an elements previous sibling matching the provided\n * selector.\n *\n * @param {Element | null} $element - Element to find siblings for\n * @param {string} [selector] - selector for required sibling\n */\nexport function getPreviousSibling($element, selector) {\n if (!$element || !($element instanceof HTMLElement)) {\n return\n }\n\n // Get the previous sibling element\n let $sibling = $element.previousElementSibling\n\n // If there's no selector, return the first sibling\n if (!selector) return $sibling\n\n // If the sibling matches our selector, use it\n // If not, jump to the next sibling and continue the loop\n while ($sibling) {\n if ($sibling.matches(selector)) return $sibling\n $sibling = $sibling.previousElementSibling\n }\n}\n\n/**\n * @param {Element | null} $element\n * @param {string} [selector]\n */\nexport function findNearestMatchingElement($element, selector) {\n // If no element or selector is provided, return\n if (!$element || !($element instanceof HTMLElement) || !selector) {\n return\n }\n\n // Start with the current element\n let $currentElement = $element\n\n while ($currentElement) {\n // First check the current element\n if ($currentElement.matches(selector)) {\n return $currentElement\n }\n\n // Check all previous siblings\n let $sibling = $currentElement.previousElementSibling\n while ($sibling) {\n // Check if the sibling itself is a heading\n if ($sibling.matches(selector)) {\n return $sibling\n }\n $sibling = $sibling.previousElementSibling\n }\n\n // If no match found in siblings, move up to parent\n $currentElement = $currentElement.parentElement\n }\n}\n\n/**\n * Move focus to element\n *\n * Sets tabindex to -1 to make the element programmatically focusable,\n * but removes it on blur as the element doesn't need to be focused again.\n *\n * @param {HTMLElement} $element - HTML element\n * @param {object} [options] - Handler options\n * @param {function(this: HTMLElement): void} [options.onBeforeFocus] - Callback before focus\n * @param {function(this: HTMLElement): void} [options.onBlur] - Callback on blur\n */\nexport function setFocus($element, options = {}) {\n const isFocusable = $element.getAttribute('tabindex')\n\n if (!isFocusable) {\n $element.setAttribute('tabindex', '-1')\n }\n\n /**\n * Handle element focus\n */\n function onFocus() {\n $element.addEventListener('blur', onBlur, { once: true })\n }\n\n /**\n * Handle element blur\n */\n function onBlur() {\n if (options.onBlur) {\n options.onBlur.call($element)\n }\n\n if (!isFocusable) {\n $element.removeAttribute('tabindex')\n }\n }\n\n // Add listener to reset element on blur, after focus\n $element.addEventListener('focus', onFocus, { once: true })\n\n // Focus element\n if (options.onBeforeFocus) {\n options.onBeforeFocus.call($element)\n }\n $element.focus()\n}\n","import { addAttributeValue, removeAttributeValue } from '../../helpers.mjs'\n\nexport class FormValidator {\n /**\n * @param {Element | null} form - HTML element to use for form validator\n * @param {FormValidatorConfig} [config] - Button menu config\n */\n constructor(form, config = {}) {\n if (!form || !(form instanceof HTMLFormElement)) {\n return this\n }\n\n this.form = form\n this.errors = []\n this.validators = []\n this.form.addEventListener('submit', this.onSubmit.bind(this))\n this.summary =\n config.summary || document.querySelector('.govuk-error-summary')\n this.originalTitle = document.title\n }\n\n escapeHtml(string) {\n return String(string).replace(/[&<>\"'`=/]/g, function fromEntityMap(s) {\n return FormValidator.entityMap[s]\n })\n }\n\n resetTitle() {\n document.title = this.originalTitle\n }\n\n updateTitle() {\n document.title = `${this.errors.length} errors - ${document.title}`\n }\n\n showSummary() {\n this.summary.innerHTML = this.getSummaryHtml()\n this.summary.classList.remove('moj-hidden')\n this.summary.setAttribute('aria-labelledby', 'errorSummary-heading')\n this.summary.focus()\n }\n\n getSummaryHtml() {\n let html =\n '<h2 id=\"error-summary-title\" class=\"govuk-error-summary__title\">There is a problem</h2>'\n html += '<div class=\"govuk-error-summary__body\">'\n html += '<ul class=\"govuk-list govuk-error-summary__list\">'\n for (const error of this.errors) {\n html += '<li>'\n html += `<a href=\"#${this.escapeHtml(error.fieldName)}\">`\n html += this.escapeHtml(error.message)\n html += '</a>'\n html += '</li>'\n }\n html += '</ul>'\n html += '</div>'\n return html\n }\n\n hideSummary() {\n this.summary.classList.add('moj-hidden')\n this.summary.removeAttribute('aria-labelledby')\n }\n\n onSubmit(event) {\n this.removeInlineErrors()\n this.hideSummary()\n this.resetTitle()\n if (!this.validate()) {\n event.preventDefault()\n this.updateTitle()\n this.showSummary()\n this.showInlineErrors()\n }\n }\n\n showInlineErrors() {\n for (const error of this.errors) {\n this.showInlineError(error)\n }\n }\n\n showInlineError(error) {\n const errorSpan = document.createElement('span')\n errorSpan.id = `${error.fieldName}-error`\n errorSpan.classList.add('govuk-error-message')\n errorSpan.innerHTML = this.escapeHtml(error.message)\n\n const control = document.querySelector(`#${error.fieldName}`)\n const fieldset = control.closest('.govuk-fieldset')\n const fieldContainer = (fieldset || control).closest('.govuk-form-group')\n\n const label = fieldContainer.querySelector('label')\n const legend = fieldContainer.querySelector('legend')\n\n fieldContainer.classList.add('govuk-form-group--error')\n\n if (fieldset && legend) {\n legend.after(errorSpan)\n fieldContainer.setAttribute('aria-invalid', 'true')\n addAttributeValue(fieldset, 'aria-describedby', errorSpan.id)\n } else if (label && control) {\n label.after(errorSpan)\n control.setAttribute('aria-invalid', 'true')\n addAttributeValue(control, 'aria-describedby', errorSpan.id)\n }\n }\n\n removeInlineErrors() {\n for (const error of this.errors) {\n this.removeInlineError(error)\n }\n }\n\n removeInlineError(error) {\n const errorSpan = document.querySelector(`#${error.fieldName}-error`)\n\n const control = document.querySelector(`#${error.fieldName}`)\n const fieldset = control.closest('.govuk-fieldset')\n const fieldContainer = (fieldset || control).closest('.govuk-form-group')\n\n const label = fieldContainer.querySelector('label')\n const legend = fieldContainer.querySelector('legend')\n\n errorSpan.remove()\n fieldContainer.classList.remove('govuk-form-group--error')\n\n if (fieldset && legend) {\n fieldContainer.removeAttribute('aria-invalid')\n removeAttributeValue(fieldset, 'aria-describedby', errorSpan.id)\n } else if (label && control) {\n control.removeAttribute('aria-invalid')\n removeAttributeValue(control, 'aria-describedby', errorSpan.id)\n }\n }\n\n addValidator(fieldName, rules) {\n this.validators.push({\n fieldName,\n rules,\n field: this.form.elements[fieldName]\n })\n }\n\n validate() {\n this.errors = []\n let validator = null\n let validatorReturnValue = true\n let i\n let j\n for (i = 0; i < this.validators.length; i++) {\n validator = this.validators[i]\n for (j = 0; j < validator.rules.length; j++) {\n validatorReturnValue = validator.rules[j].method(\n validator.field,\n validator.rules[j].params\n )\n\n if (\n typeof validatorReturnValue === 'boolean' &&\n !validatorReturnValue\n ) {\n this.errors.push({\n fieldName: validator.fieldName,\n message: validator.rules[j].message\n })\n break\n } else if (typeof validatorReturnValue === 'string') {\n this.errors.push({\n fieldName: validatorReturnValue,\n message: validator.rules[j].message\n })\n break\n }\n }\n }\n return this.errors.length === 0\n }\n\n static entityMap = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n '/': '&#x2F;',\n '`': '&#x60;',\n '=': '&#x3D;'\n }\n}\n\n/**\n * @typedef {object} FormValidatorConfig\n * @property {HTMLElement} [summary] - HTML element to use for error summary\n */\n"],"names":["removeAttributeValue","el","attr","value","re","m","getAttribute","removeAttribute","RegExp","match","length","setAttribute","replace","addAttributeValue","test","FormValidator","constructor","form","config","HTMLFormElement","errors","validators","addEventListener","onSubmit","bind","summary","document","querySelector","originalTitle","title","escapeHtml","string","String","fromEntityMap","s","entityMap","resetTitle","updateTitle","showSummary","innerHTML","getSummaryHtml","classList","remove","focus","html","error","fieldName","message","hideSummary","add","event","removeInlineErrors","validate","preventDefault","showInlineErrors","showInlineError","errorSpan","createElement","id","control","fieldset","closest","fieldContainer","label","legend","after","removeInlineError","addValidator","rules","push","field","elements","validator","validatorReturnValue","i","j","method","params"],"mappings":"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"}
@@ -1,15 +1,156 @@
1
1
  import { addAttributeValue, removeAttributeValue } from '../../helpers.mjs';
2
2
 
3
- function FormValidator(form, options) {
4
- this.form = form;
5
- this.errors = [];
6
- this.validators = [];
7
- $(this.form).on('submit', $.proxy(this, 'onSubmit'));
8
- this.summary =
9
- options && options.summary ? $(options.summary) : $('.govuk-error-summary');
10
- this.originalTitle = document.title;
3
+ class FormValidator {
4
+ /**
5
+ * @param {Element | null} form - HTML element to use for form validator
6
+ * @param {FormValidatorConfig} [config] - Button menu config
7
+ */
8
+ constructor(form, config = {}) {
9
+ if (!form || !(form instanceof HTMLFormElement)) {
10
+ return this;
11
+ }
12
+ this.form = form;
13
+ this.errors = [];
14
+ this.validators = [];
15
+ this.form.addEventListener('submit', this.onSubmit.bind(this));
16
+ this.summary = config.summary || document.querySelector('.govuk-error-summary');
17
+ this.originalTitle = document.title;
18
+ }
19
+ escapeHtml(string) {
20
+ return String(string).replace(/[&<>"'`=/]/g, function fromEntityMap(s) {
21
+ return FormValidator.entityMap[s];
22
+ });
23
+ }
24
+ resetTitle() {
25
+ document.title = this.originalTitle;
26
+ }
27
+ updateTitle() {
28
+ document.title = `${this.errors.length} errors - ${document.title}`;
29
+ }
30
+ showSummary() {
31
+ this.summary.innerHTML = this.getSummaryHtml();
32
+ this.summary.classList.remove('moj-hidden');
33
+ this.summary.setAttribute('aria-labelledby', 'errorSummary-heading');
34
+ this.summary.focus();
35
+ }
36
+ getSummaryHtml() {
37
+ let html = '<h2 id="error-summary-title" class="govuk-error-summary__title">There is a problem</h2>';
38
+ html += '<div class="govuk-error-summary__body">';
39
+ html += '<ul class="govuk-list govuk-error-summary__list">';
40
+ for (const error of this.errors) {
41
+ html += '<li>';
42
+ html += `<a href="#${this.escapeHtml(error.fieldName)}">`;
43
+ html += this.escapeHtml(error.message);
44
+ html += '</a>';
45
+ html += '</li>';
46
+ }
47
+ html += '</ul>';
48
+ html += '</div>';
49
+ return html;
50
+ }
51
+ hideSummary() {
52
+ this.summary.classList.add('moj-hidden');
53
+ this.summary.removeAttribute('aria-labelledby');
54
+ }
55
+ onSubmit(event) {
56
+ this.removeInlineErrors();
57
+ this.hideSummary();
58
+ this.resetTitle();
59
+ if (!this.validate()) {
60
+ event.preventDefault();
61
+ this.updateTitle();
62
+ this.showSummary();
63
+ this.showInlineErrors();
64
+ }
65
+ }
66
+ showInlineErrors() {
67
+ for (const error of this.errors) {
68
+ this.showInlineError(error);
69
+ }
70
+ }
71
+ showInlineError(error) {
72
+ const errorSpan = document.createElement('span');
73
+ errorSpan.id = `${error.fieldName}-error`;
74
+ errorSpan.classList.add('govuk-error-message');
75
+ errorSpan.innerHTML = this.escapeHtml(error.message);
76
+ const control = document.querySelector(`#${error.fieldName}`);
77
+ const fieldset = control.closest('.govuk-fieldset');
78
+ const fieldContainer = (fieldset || control).closest('.govuk-form-group');
79
+ const label = fieldContainer.querySelector('label');
80
+ const legend = fieldContainer.querySelector('legend');
81
+ fieldContainer.classList.add('govuk-form-group--error');
82
+ if (fieldset && legend) {
83
+ legend.after(errorSpan);
84
+ fieldContainer.setAttribute('aria-invalid', 'true');
85
+ addAttributeValue(fieldset, 'aria-describedby', errorSpan.id);
86
+ } else if (label && control) {
87
+ label.after(errorSpan);
88
+ control.setAttribute('aria-invalid', 'true');
89
+ addAttributeValue(control, 'aria-describedby', errorSpan.id);
90
+ }
91
+ }
92
+ removeInlineErrors() {
93
+ for (const error of this.errors) {
94
+ this.removeInlineError(error);
95
+ }
96
+ }
97
+ removeInlineError(error) {
98
+ const errorSpan = document.querySelector(`#${error.fieldName}-error`);
99
+ const control = document.querySelector(`#${error.fieldName}`);
100
+ const fieldset = control.closest('.govuk-fieldset');
101
+ const fieldContainer = (fieldset || control).closest('.govuk-form-group');
102
+ const label = fieldContainer.querySelector('label');
103
+ const legend = fieldContainer.querySelector('legend');
104
+ errorSpan.remove();
105
+ fieldContainer.classList.remove('govuk-form-group--error');
106
+ if (fieldset && legend) {
107
+ fieldContainer.removeAttribute('aria-invalid');
108
+ removeAttributeValue(fieldset, 'aria-describedby', errorSpan.id);
109
+ } else if (label && control) {
110
+ control.removeAttribute('aria-invalid');
111
+ removeAttributeValue(control, 'aria-describedby', errorSpan.id);
112
+ }
113
+ }
114
+ addValidator(fieldName, rules) {
115
+ this.validators.push({
116
+ fieldName,
117
+ rules,
118
+ field: this.form.elements[fieldName]
119
+ });
120
+ }
121
+ validate() {
122
+ this.errors = [];
123
+ let validator = null;
124
+ let validatorReturnValue = true;
125
+ let i;
126
+ let j;
127
+ for (i = 0; i < this.validators.length; i++) {
128
+ validator = this.validators[i];
129
+ for (j = 0; j < validator.rules.length; j++) {
130
+ validatorReturnValue = validator.rules[j].method(validator.field, validator.rules[j].params);
131
+ if (typeof validatorReturnValue === 'boolean' && !validatorReturnValue) {
132
+ this.errors.push({
133
+ fieldName: validator.fieldName,
134
+ message: validator.rules[j].message
135
+ });
136
+ break;
137
+ } else if (typeof validatorReturnValue === 'string') {
138
+ this.errors.push({
139
+ fieldName: validatorReturnValue,
140
+ message: validator.rules[j].message
141
+ });
142
+ break;
143
+ }
144
+ }
145
+ }
146
+ return this.errors.length === 0;
147
+ }
11
148
  }
12
149
 
150
+ /**
151
+ * @typedef {object} FormValidatorConfig
152
+ * @property {HTMLElement} [summary] - HTML element to use for error summary
153
+ */
13
154
  FormValidator.entityMap = {
14
155
  '&': '&amp;',
15
156
  '<': '&lt;',
@@ -21,149 +162,5 @@ FormValidator.entityMap = {
21
162
  '=': '&#x3D;'
22
163
  };
23
164
 
24
- FormValidator.prototype.escapeHtml = function (string) {
25
- return String(string).replace(/[&<>"'`=/]/g, function fromEntityMap(s) {
26
- return FormValidator.entityMap[s]
27
- })
28
- };
29
-
30
- FormValidator.prototype.resetTitle = function () {
31
- document.title = this.originalTitle;
32
- };
33
-
34
- FormValidator.prototype.updateTitle = function () {
35
- document.title = `${this.errors.length} errors - ${document.title}`;
36
- };
37
-
38
- FormValidator.prototype.showSummary = function () {
39
- this.summary.html(this.getSummaryHtml());
40
- this.summary.removeClass('moj-hidden');
41
- this.summary.attr('aria-labelledby', 'errorSummary-heading');
42
- this.summary.focus();
43
- };
44
-
45
- FormValidator.prototype.getSummaryHtml = function () {
46
- let html =
47
- '<h2 id="error-summary-title" class="govuk-error-summary__title">There is a problem</h2>';
48
- html += '<div class="govuk-error-summary__body">';
49
- html += '<ul class="govuk-list govuk-error-summary__list">';
50
- for (let i = 0, j = this.errors.length; i < j; i++) {
51
- const error = this.errors[i];
52
- html += '<li>';
53
- html += `<a href="#${this.escapeHtml(error.fieldName)}">`;
54
- html += this.escapeHtml(error.message);
55
- html += '</a>';
56
- html += '</li>';
57
- }
58
- html += '</ul>';
59
- html += '</div>';
60
- return html
61
- };
62
-
63
- FormValidator.prototype.hideSummary = function () {
64
- this.summary.addClass('moj-hidden');
65
- this.summary.removeAttr('aria-labelledby');
66
- };
67
-
68
- FormValidator.prototype.onSubmit = function (e) {
69
- this.removeInlineErrors();
70
- this.hideSummary();
71
- this.resetTitle();
72
- if (!this.validate()) {
73
- e.preventDefault();
74
- this.updateTitle();
75
- this.showSummary();
76
- this.showInlineErrors();
77
- }
78
- };
79
-
80
- FormValidator.prototype.showInlineErrors = function () {
81
- for (let i = 0, j = this.errors.length; i < j; i++) {
82
- this.showInlineError(this.errors[i]);
83
- }
84
- };
85
-
86
- FormValidator.prototype.showInlineError = function (error) {
87
- const errorSpanId = `${error.fieldName}-error`;
88
- const errorSpan = `<span class="govuk-error-message" id="${
89
- errorSpanId
90
- }">${this.escapeHtml(error.message)}</span>`;
91
- const control = $(`#${error.fieldName}`);
92
- const fieldContainer = control.parents('.govuk-form-group');
93
- const label = fieldContainer.find('label');
94
- const legend = fieldContainer.find('legend');
95
- const fieldset = fieldContainer.find('fieldset');
96
- fieldContainer.addClass('govuk-form-group--error');
97
- if (legend.length) {
98
- legend.after(errorSpan);
99
- fieldContainer.attr('aria-invalid', 'true');
100
- addAttributeValue(fieldset[0], 'aria-describedby', errorSpanId);
101
- } else {
102
- label.after(errorSpan);
103
- control.attr('aria-invalid', 'true');
104
- addAttributeValue(control[0], 'aria-describedby', errorSpanId);
105
- }
106
- };
107
-
108
- FormValidator.prototype.removeInlineErrors = function () {
109
- for (let i = 0; i < this.errors.length; i++) {
110
- this.removeInlineError(this.errors[i]);
111
- }
112
- };
113
-
114
- FormValidator.prototype.removeInlineError = function (error) {
115
- const control = $(`#${error.fieldName}`);
116
- const fieldContainer = control.parents('.govuk-form-group');
117
- fieldContainer.find('.govuk-error-message').remove();
118
- fieldContainer.removeClass('govuk-form-group--error');
119
- fieldContainer.find('[aria-invalid]').attr('aria-invalid', 'false');
120
- const errorSpanId = `${error.fieldName}-error`;
121
- removeAttributeValue(
122
- fieldContainer.find('[aria-describedby]')[0],
123
- 'aria-describedby',
124
- errorSpanId
125
- );
126
- };
127
-
128
- FormValidator.prototype.addValidator = function (fieldName, rules) {
129
- this.validators.push({
130
- fieldName,
131
- rules,
132
- field: this.form.elements[fieldName]
133
- });
134
- };
135
-
136
- FormValidator.prototype.validate = function () {
137
- this.errors = [];
138
- let validator = null;
139
- let validatorReturnValue = true;
140
- let i;
141
- let j;
142
- for (i = 0; i < this.validators.length; i++) {
143
- validator = this.validators[i];
144
- for (j = 0; j < validator.rules.length; j++) {
145
- validatorReturnValue = validator.rules[j].method(
146
- validator.field,
147
- validator.rules[j].params
148
- );
149
-
150
- if (typeof validatorReturnValue === 'boolean' && !validatorReturnValue) {
151
- this.errors.push({
152
- fieldName: validator.fieldName,
153
- message: validator.rules[j].message
154
- });
155
- break
156
- } else if (typeof validatorReturnValue === 'string') {
157
- this.errors.push({
158
- fieldName: validatorReturnValue,
159
- message: validator.rules[j].message
160
- });
161
- break
162
- }
163
- }
164
- }
165
- return this.errors.length === 0
166
- };
167
-
168
165
  export { FormValidator };
169
166
  //# sourceMappingURL=form-validator.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"form-validator.mjs","sources":["../../../../src/moj/components/form-validator/form-validator.mjs"],"sourcesContent":["import $ from 'jquery'\n\nimport { addAttributeValue, removeAttributeValue } from '../../helpers.mjs'\n\nexport function FormValidator(form, options) {\n this.form = form\n this.errors = []\n this.validators = []\n $(this.form).on('submit', $.proxy(this, 'onSubmit'))\n this.summary =\n options && options.summary ? $(options.summary) : $('.govuk-error-summary')\n this.originalTitle = document.title\n}\n\nFormValidator.entityMap = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n '/': '&#x2F;',\n '`': '&#x60;',\n '=': '&#x3D;'\n}\n\nFormValidator.prototype.escapeHtml = function (string) {\n return String(string).replace(/[&<>\"'`=/]/g, function fromEntityMap(s) {\n return FormValidator.entityMap[s]\n })\n}\n\nFormValidator.prototype.resetTitle = function () {\n document.title = this.originalTitle\n}\n\nFormValidator.prototype.updateTitle = function () {\n document.title = `${this.errors.length} errors - ${document.title}`\n}\n\nFormValidator.prototype.showSummary = function () {\n this.summary.html(this.getSummaryHtml())\n this.summary.removeClass('moj-hidden')\n this.summary.attr('aria-labelledby', 'errorSummary-heading')\n this.summary.focus()\n}\n\nFormValidator.prototype.getSummaryHtml = function () {\n let html =\n '<h2 id=\"error-summary-title\" class=\"govuk-error-summary__title\">There is a problem</h2>'\n html += '<div class=\"govuk-error-summary__body\">'\n html += '<ul class=\"govuk-list govuk-error-summary__list\">'\n for (let i = 0, j = this.errors.length; i < j; i++) {\n const error = this.errors[i]\n html += '<li>'\n html += `<a href=\"#${this.escapeHtml(error.fieldName)}\">`\n html += this.escapeHtml(error.message)\n html += '</a>'\n html += '</li>'\n }\n html += '</ul>'\n html += '</div>'\n return html\n}\n\nFormValidator.prototype.hideSummary = function () {\n this.summary.addClass('moj-hidden')\n this.summary.removeAttr('aria-labelledby')\n}\n\nFormValidator.prototype.onSubmit = function (e) {\n this.removeInlineErrors()\n this.hideSummary()\n this.resetTitle()\n if (!this.validate()) {\n e.preventDefault()\n this.updateTitle()\n this.showSummary()\n this.showInlineErrors()\n }\n}\n\nFormValidator.prototype.showInlineErrors = function () {\n for (let i = 0, j = this.errors.length; i < j; i++) {\n this.showInlineError(this.errors[i])\n }\n}\n\nFormValidator.prototype.showInlineError = function (error) {\n const errorSpanId = `${error.fieldName}-error`\n const errorSpan = `<span class=\"govuk-error-message\" id=\"${\n errorSpanId\n }\">${this.escapeHtml(error.message)}</span>`\n const control = $(`#${error.fieldName}`)\n const fieldContainer = control.parents('.govuk-form-group')\n const label = fieldContainer.find('label')\n const legend = fieldContainer.find('legend')\n const fieldset = fieldContainer.find('fieldset')\n fieldContainer.addClass('govuk-form-group--error')\n if (legend.length) {\n legend.after(errorSpan)\n fieldContainer.attr('aria-invalid', 'true')\n addAttributeValue(fieldset[0], 'aria-describedby', errorSpanId)\n } else {\n label.after(errorSpan)\n control.attr('aria-invalid', 'true')\n addAttributeValue(control[0], 'aria-describedby', errorSpanId)\n }\n}\n\nFormValidator.prototype.removeInlineErrors = function () {\n for (let i = 0; i < this.errors.length; i++) {\n this.removeInlineError(this.errors[i])\n }\n}\n\nFormValidator.prototype.removeInlineError = function (error) {\n const control = $(`#${error.fieldName}`)\n const fieldContainer = control.parents('.govuk-form-group')\n fieldContainer.find('.govuk-error-message').remove()\n fieldContainer.removeClass('govuk-form-group--error')\n fieldContainer.find('[aria-invalid]').attr('aria-invalid', 'false')\n const errorSpanId = `${error.fieldName}-error`\n removeAttributeValue(\n fieldContainer.find('[aria-describedby]')[0],\n 'aria-describedby',\n errorSpanId\n )\n}\n\nFormValidator.prototype.addValidator = function (fieldName, rules) {\n this.validators.push({\n fieldName,\n rules,\n field: this.form.elements[fieldName]\n })\n}\n\nFormValidator.prototype.validate = function () {\n this.errors = []\n let validator = null\n let validatorReturnValue = true\n let i\n let j\n for (i = 0; i < this.validators.length; i++) {\n validator = this.validators[i]\n for (j = 0; j < validator.rules.length; j++) {\n validatorReturnValue = validator.rules[j].method(\n validator.field,\n validator.rules[j].params\n )\n\n if (typeof validatorReturnValue === 'boolean' && !validatorReturnValue) {\n this.errors.push({\n fieldName: validator.fieldName,\n message: validator.rules[j].message\n })\n break\n } else if (typeof validatorReturnValue === 'string') {\n this.errors.push({\n fieldName: validatorReturnValue,\n message: validator.rules[j].message\n })\n break\n }\n }\n }\n return this.errors.length === 0\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"form-validator.mjs","sources":["../../../../src/moj/components/form-validator/form-validator.mjs"],"sourcesContent":["import { addAttributeValue, removeAttributeValue } from '../../helpers.mjs'\n\nexport class FormValidator {\n /**\n * @param {Element | null} form - HTML element to use for form validator\n * @param {FormValidatorConfig} [config] - Button menu config\n */\n constructor(form, config = {}) {\n if (!form || !(form instanceof HTMLFormElement)) {\n return this\n }\n\n this.form = form\n this.errors = []\n this.validators = []\n this.form.addEventListener('submit', this.onSubmit.bind(this))\n this.summary =\n config.summary || document.querySelector('.govuk-error-summary')\n this.originalTitle = document.title\n }\n\n escapeHtml(string) {\n return String(string).replace(/[&<>\"'`=/]/g, function fromEntityMap(s) {\n return FormValidator.entityMap[s]\n })\n }\n\n resetTitle() {\n document.title = this.originalTitle\n }\n\n updateTitle() {\n document.title = `${this.errors.length} errors - ${document.title}`\n }\n\n showSummary() {\n this.summary.innerHTML = this.getSummaryHtml()\n this.summary.classList.remove('moj-hidden')\n this.summary.setAttribute('aria-labelledby', 'errorSummary-heading')\n this.summary.focus()\n }\n\n getSummaryHtml() {\n let html =\n '<h2 id=\"error-summary-title\" class=\"govuk-error-summary__title\">There is a problem</h2>'\n html += '<div class=\"govuk-error-summary__body\">'\n html += '<ul class=\"govuk-list govuk-error-summary__list\">'\n for (const error of this.errors) {\n html += '<li>'\n html += `<a href=\"#${this.escapeHtml(error.fieldName)}\">`\n html += this.escapeHtml(error.message)\n html += '</a>'\n html += '</li>'\n }\n html += '</ul>'\n html += '</div>'\n return html\n }\n\n hideSummary() {\n this.summary.classList.add('moj-hidden')\n this.summary.removeAttribute('aria-labelledby')\n }\n\n onSubmit(event) {\n this.removeInlineErrors()\n this.hideSummary()\n this.resetTitle()\n if (!this.validate()) {\n event.preventDefault()\n this.updateTitle()\n this.showSummary()\n this.showInlineErrors()\n }\n }\n\n showInlineErrors() {\n for (const error of this.errors) {\n this.showInlineError(error)\n }\n }\n\n showInlineError(error) {\n const errorSpan = document.createElement('span')\n errorSpan.id = `${error.fieldName}-error`\n errorSpan.classList.add('govuk-error-message')\n errorSpan.innerHTML = this.escapeHtml(error.message)\n\n const control = document.querySelector(`#${error.fieldName}`)\n const fieldset = control.closest('.govuk-fieldset')\n const fieldContainer = (fieldset || control).closest('.govuk-form-group')\n\n const label = fieldContainer.querySelector('label')\n const legend = fieldContainer.querySelector('legend')\n\n fieldContainer.classList.add('govuk-form-group--error')\n\n if (fieldset && legend) {\n legend.after(errorSpan)\n fieldContainer.setAttribute('aria-invalid', 'true')\n addAttributeValue(fieldset, 'aria-describedby', errorSpan.id)\n } else if (label && control) {\n label.after(errorSpan)\n control.setAttribute('aria-invalid', 'true')\n addAttributeValue(control, 'aria-describedby', errorSpan.id)\n }\n }\n\n removeInlineErrors() {\n for (const error of this.errors) {\n this.removeInlineError(error)\n }\n }\n\n removeInlineError(error) {\n const errorSpan = document.querySelector(`#${error.fieldName}-error`)\n\n const control = document.querySelector(`#${error.fieldName}`)\n const fieldset = control.closest('.govuk-fieldset')\n const fieldContainer = (fieldset || control).closest('.govuk-form-group')\n\n const label = fieldContainer.querySelector('label')\n const legend = fieldContainer.querySelector('legend')\n\n errorSpan.remove()\n fieldContainer.classList.remove('govuk-form-group--error')\n\n if (fieldset && legend) {\n fieldContainer.removeAttribute('aria-invalid')\n removeAttributeValue(fieldset, 'aria-describedby', errorSpan.id)\n } else if (label && control) {\n control.removeAttribute('aria-invalid')\n removeAttributeValue(control, 'aria-describedby', errorSpan.id)\n }\n }\n\n addValidator(fieldName, rules) {\n this.validators.push({\n fieldName,\n rules,\n field: this.form.elements[fieldName]\n })\n }\n\n validate() {\n this.errors = []\n let validator = null\n let validatorReturnValue = true\n let i\n let j\n for (i = 0; i < this.validators.length; i++) {\n validator = this.validators[i]\n for (j = 0; j < validator.rules.length; j++) {\n validatorReturnValue = validator.rules[j].method(\n validator.field,\n validator.rules[j].params\n )\n\n if (\n typeof validatorReturnValue === 'boolean' &&\n !validatorReturnValue\n ) {\n this.errors.push({\n fieldName: validator.fieldName,\n message: validator.rules[j].message\n })\n break\n } else if (typeof validatorReturnValue === 'string') {\n this.errors.push({\n fieldName: validatorReturnValue,\n message: validator.rules[j].message\n })\n break\n }\n }\n }\n return this.errors.length === 0\n }\n\n static entityMap = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n '/': '&#x2F;',\n '`': '&#x60;',\n '=': '&#x3D;'\n }\n}\n\n/**\n * @typedef {object} FormValidatorConfig\n * @property {HTMLElement} [summary] - HTML element to use for error summary\n */\n"],"names":["FormValidator","constructor","form","config","HTMLFormElement","errors","validators","addEventListener","onSubmit","bind","summary","document","querySelector","originalTitle","title","escapeHtml","string","String","replace","fromEntityMap","s","entityMap","resetTitle","updateTitle","length","showSummary","innerHTML","getSummaryHtml","classList","remove","setAttribute","focus","html","error","fieldName","message","hideSummary","add","removeAttribute","event","removeInlineErrors","validate","preventDefault","showInlineErrors","showInlineError","errorSpan","createElement","id","control","fieldset","closest","fieldContainer","label","legend","after","addAttributeValue","removeInlineError","removeAttributeValue","addValidator","rules","push","field","elements","validator","validatorReturnValue","i","j","method","params"],"mappings":"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"}
@@ -169,3 +169,5 @@ span.moj-header__link {
169
169
  .moj-header__navigation-link[aria-current="page"] {
170
170
  text-decoration: none;
171
171
  }
172
+
173
+ /*# sourceMappingURL=_header.scss.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/moj/components/header/_header.scss"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,uCAAuC;;AAEvC;;+EAE+E;;AAE/E;EACE,6BAA6B;EAC7B,6CAA6C;EAC7C,uCAAuC;AACzC;;AAEA;EACE,kBAAkB;EAClB,4BAA4B;EAC5B,uBAAuB;AACzB;;AAEA;EACE,gCAAgC;;EAEhC;IACE,WAAW;EACb;AACF;;AAEA;EACE,kBAAkB;EAClB,SAAS;EACT,8BAA8B;EAC9B,mBAAmB;AACrB;;AAEA;EACE,kBAAkB;EAClB,SAAS;EACT,8BAA8B;EAC9B,mBAAmB;AACrB;;AAEA;EACE,gCAAgC;;EAEhC;IACE,YAAY;EACd;AACF;;AAEA;;EAEE,qBAAqB;EACrB,mBAAmB;EACnB,gBAAgB,EAAE,uCAAuC;EACzD,oCAAoC;EACpC,4BAA4B;EAC5B,iBAAiB,EAAE,2CAA2C;EAC9D,sBAAsB;EACtB,0BAA0B;EAC1B,iCAAiC;;EAEjC;;;;IAIE,4BAA4B;IAC5B,qBAAqB;EACvB;;EAEA;IACE,mCAAmC;EACrC;;EAEA;IACE,yBAAyB;IACzB,4BAA4B;EAC9B;;EAEA;IACE,sBAAsB;IACtB,+CAA+C;;IAE/C;MACE,yBAAyB;IAC3B;EACF;;EAEA;IACE,sBAAsB;IACtB,iDAAiD;;IAEjD;MACE,cAAc;IAChB;IACA;MACE,6BAA6B;IAC/B;;IAEA;MACE,yBAAyB;IAC3B;EACF;AACF;;AAEA;EACE,kBAAkB;EAClB,2BAA2B;;EAE3B;IACE,mCAAmC;EACrC;;EAEA;IACE,mBAAmB;IACnB,sBAAsB;EACxB;AACF;AACA,yDAAyD;AACzD;EACE;IACE,yBAAyB;EAC3B;AACF;;AAEA,YAAY;AACZ;EACE,kCAAkC;EAClC,4BAA4B;AAC9B;;AAEA;EACE,SAAS;EACT,UAAU;EACV,YAAY,EAAE,+DAA+D;EAC7E,gBAAgB;AAClB;;AAEA;EACE,qBAAqB;EACrB,8BAA8B;EAC9B,uBAAuB;;EAEvB;IACE,eAAe;EACjB;AACF;;AAEA;EACE,0BAA0B;EAC1B,iCAAiC;;EAEjC;;;IAGE,cAAc;IACd,qBAAqB;EACvB;;EAEA;IACE,sDAAsD;IACtD,qCAAqC;EACvC;;EAEA;IACE,4BAA4B;EAC9B;AACF;;AAEA;EACE,qBAAqB;AACvB","file":"_header.scss","sourcesContent":["@use \"../../objects/width-container\" as *;\n@use \"../../vendor/govuk-frontend\" as *;\n\n/* ==========================================================================\n #HEADER\n ========================================================================== */\n\n.moj-header {\n padding-top: govuk-spacing(3);\n border-bottom: 10px solid $govuk-brand-colour;\n background-color: govuk-colour(\"black\");\n}\n\n.moj-header__container {\n position: relative;\n @include moj-width-container;\n @include govuk-clearfix;\n}\n\n.moj-header__logo {\n padding-bottom: govuk-spacing(1);\n\n @include govuk-media-query($from: desktop) {\n float: left;\n }\n}\n\n.moj-header__logotype-crown {\n position: relative;\n top: -4px;\n margin-right: govuk-spacing(1);\n vertical-align: top;\n}\n\n.moj-header__logotype-crest {\n position: relative;\n top: -8px;\n margin-right: govuk-spacing(1);\n vertical-align: top;\n}\n\n.moj-header__content {\n padding-bottom: govuk-spacing(2);\n\n @include govuk-media-query($from: desktop) {\n float: right;\n }\n}\n\n.moj-header__link,\n.moj-header__link > a {\n display: inline-block;\n margin-bottom: -1px;\n overflow: hidden; // Fixes focus gaps in background colour\n border-bottom: 1px solid transparent;\n color: govuk-colour(\"white\");\n line-height: 25px; // Override due to alignment issue in Chrome\n vertical-align: middle;\n @include govuk-link-common;\n @include govuk-link-style-default;\n\n &:link,\n &:visited,\n &:hover,\n &:active {\n color: govuk-colour(\"white\");\n text-decoration: none;\n }\n\n &:hover {\n border-color: govuk-colour(\"white\");\n }\n\n &:focus {\n border-color: transparent;\n color: govuk-colour(\"black\");\n }\n\n &--organisation-name {\n vertical-align: middle;\n @include govuk-font($size: 24, $weight: \"bold\");\n\n &:hover {\n border-color: transparent;\n }\n }\n\n &--service-name {\n vertical-align: middle;\n @include govuk-font($size: 24, $weight: \"normal\");\n\n @include govuk-media-query($until: desktop) {\n display: block;\n }\n @include govuk-media-query($from: desktop) {\n margin-left: govuk-spacing(1);\n }\n\n &:hover {\n border-color: transparent;\n }\n }\n}\n\n.moj-header__link a {\n margin-bottom: 1px;\n vertical-align: text-bottom;\n\n &:hover {\n border-color: govuk-colour(\"white\");\n }\n\n @include govuk-media-query($until: desktop) {\n margin-bottom: -1px;\n vertical-align: middle;\n }\n}\n// stylelint-disable-next-line selector-no-qualifying-type\nspan.moj-header__link {\n &:hover {\n border-color: transparent;\n }\n}\n\n// Navigation\n.moj-header__navigation {\n margin-top: govuk-spacing(1) - 2px;\n color: govuk-colour(\"white\");\n}\n\n.moj-header__navigation-list {\n margin: 0;\n padding: 0;\n font-size: 0; // Removes white space when using inline-block on child element.\n list-style: none;\n}\n\n.moj-header__navigation-item {\n display: inline-block;\n margin-right: govuk-spacing(4);\n @include govuk-font(19);\n\n &:last-child {\n margin-right: 0;\n }\n}\n\n.moj-header__navigation-link {\n @include govuk-link-common;\n @include govuk-link-style-default;\n\n &:link,\n &:visited,\n &:active {\n color: inherit;\n text-decoration: none;\n }\n\n &:hover {\n // stylelint-disable-next-line declaration-no-important\n text-decoration: underline !important;\n }\n\n &:focus {\n color: govuk-colour(\"black\");\n }\n}\n\n.moj-header__navigation-link[aria-current=\"page\"] {\n text-decoration: none;\n}\n"]}
@@ -64,3 +64,5 @@
64
64
  margin-bottom: 0;
65
65
  }
66
66
  }
67
+
68
+ /*# sourceMappingURL=_identity-bar.scss.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/moj/components/identity-bar/_identity-bar.scss"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,uCAAuC;;AAEvC;;+EAE+E;;AAE/E;EACE,uBAAuB;EACvB,6BAA6B;EAC7B,sCAAsC,EAAE,kCAAkC;EAC1E,4BAA4B;EAC5B,uCAAuC;EACvC,qDAAqD,EAAE,sBAAsB;AAC/E;;AAEA;EACE,YAAY,EAAE,qCAAqC;EACnD,mBAAmB,EAAE,wCAAwC;EAC7D,4BAA4B;;EAE5B;IACE,WAAW;IACX,qBAAqB;IACrB,WAAW;EACb;AACF;;AAEA;EACE,qBAAqB;EACrB,mBAAmB;EACnB,uBAAuB;AACzB;;AAEA;EACE,8BAA8B;EAC9B,6BAA6B;EAC7B,gCAAgC;;EAEhC;IACE,qBAAqB;IACrB,mCAAmC,EAAE,qBAAqB;IAC1D,sCAAsC,EAAE,qBAAqB;IAC7D,mBAAmB;EACrB;AACF;;AAEA;EACE;IACE,qBAAqB;IACrB,sBAAsB;EACxB;AACF;;AAEA;EACE,qBAAqB;EACrB,8BAA8B;;EAE9B;IACE,eAAe;EACjB;;EAEA;IACE,gBAAgB;EAClB;AACF","file":"_identity-bar.scss","sourcesContent":["@use \"../../objects/width-container\" as *;\n@use \"../../vendor/govuk-frontend\" as *;\n\n/* ==========================================================================\n #IDENTITY BAR\n ========================================================================== */\n\n.moj-identity-bar {\n @include govuk-clearfix;\n padding-top: govuk-spacing(2);\n padding-bottom: govuk-spacing(2) - 1px; /* Negative by 1px to compensate */\n color: govuk-colour(\"black\");\n background-color: govuk-colour(\"white\");\n box-shadow: inset 0 -1px 0 0 govuk-colour(\"mid-grey\"); /* Takes up no space */\n}\n\n.moj-identity-bar__container {\n font-size: 0; /* Hide whitespace between elements */\n text-align: justify; /* Trick to remove the need for floats */\n @include moj-width-container;\n\n &::after {\n content: \"\";\n display: inline-block;\n width: 100%;\n }\n}\n\n.moj-identity-bar__title {\n display: inline-block;\n vertical-align: top;\n @include govuk-font(16);\n}\n\n.moj-identity-bar__details {\n margin-right: govuk-spacing(2);\n padding-top: govuk-spacing(1);\n padding-bottom: govuk-spacing(1);\n\n @include govuk-media-query($from: tablet) {\n display: inline-block;\n padding-top: govuk-spacing(2) + 1px; /* Alignment tweaks */\n padding-bottom: govuk-spacing(2) - 1px; /* Alignment tweaks */\n vertical-align: top;\n }\n}\n\n.moj-identity-bar__actions {\n @include govuk-media-query($from: tablet) {\n display: inline-block;\n vertical-align: middle;\n }\n}\n\n.moj-identity-bar__menu {\n display: inline-block;\n margin-right: govuk-spacing(2);\n\n &:last-child {\n margin-right: 0;\n }\n\n .moj-button-menu__toggle-button {\n margin-bottom: 0;\n }\n}\n"]}
@@ -42,3 +42,5 @@
42
42
  }
43
43
  }
44
44
  }
45
+
46
+ /*# sourceMappingURL=_interruption-card.scss.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/moj/components/interruption-card/_interruption-card.scss"],"names":[],"mappings":"AAAA,uCAAuC;;AAEvC;EACE,+BAA+B;EAC/B,6CAA6C;EAC7C,sCAAsC;EACtC,2EAA2E;AAC7E;;AAEA;EACE,gBAAgB;AAClB;;AAEA;;EAEE,4BAA4B;AAC9B;;AAEA,qFAAqF;AACrF,gCAAgC;AAChC;EACE,4BAA4B;EAC5B,mCAAmC;AACrC;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,gBAAgB;;EAEhB;;IAEE,gBAAgB;EAClB;;EAEA;IACE;;MAEE,gBAAgB;IAClB;EACF;AACF","file":"_interruption-card.scss","sourcesContent":["@use \"../../vendor/govuk-frontend\" as *;\n\n.moj-interruption-card {\n margin-bottom: govuk-spacing(3);\n border: $govuk-border-width solid transparent;\n background-color: govuk-colour(\"blue\");\n @include govuk-responsive-padding(7, $adjustment: $govuk-border-width * -1);\n}\n\n.moj-interruption-card__content {\n max-width: 960px;\n}\n\n.moj-interruption-card__heading,\n.moj-interruption-card__body {\n color: govuk-colour(\"white\");\n}\n\n// If $govuk-global-styles is true, we need to override the color and size on elements\n// within the body class directly\n.moj-interruption-card__body > * {\n color: govuk-colour(\"white\");\n @include govuk-font-size($size: 24);\n}\n\n.moj-interruption-card__body:last-child {\n margin-bottom: 0;\n}\n\n.moj-interruption-card__actions:last-child {\n margin-bottom: 0;\n\n .govuk-button:last-child,\n .govuk-link:last-child {\n margin-bottom: 0;\n }\n\n @include govuk-media-query($from: tablet) {\n .govuk-button,\n .govuk-link {\n margin-bottom: 0;\n }\n }\n}\n"]}
@@ -105,3 +105,5 @@
105
105
  @include govuk-font($size: 16, $weight: "bold");
106
106
  }
107
107
  }
108
+
109
+ /*# sourceMappingURL=_messages.scss.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/moj/components/messages/_messages.scss"],"names":[],"mappings":"AAAA,uCAAuC;;AAEvC;;+EAE+E;;AAE/E;EACE,sCAAsC;EACtC,uBAAuB;AACzB;;AAEA;EACE,iBAAiB;EACjB,yBAAyB;EACzB,kBAAkB;EAClB,kBAAkB;;EAElB;IACE,qBAAqB;IACrB,WAAW;IACX,2BAA2B;IAC3B,gCAAgC;IAChC,kBAAkB;IAClB,+CAA+C;EACjD;AACF;;AAEA;EACE,kBAAkB;EAClB,+BAA+B;EAC/B,yBAAyB;EACzB,iCAAiC;;EAEjC;IACE,UAAU;EACZ;;EAEA;IACE,8BAA8B;IAC9B,+BAA+B;IAC/B,YAAY;IACZ,4BAA4B;IAC5B,qCAAqC;IACrC,iBAAiB;;IAEjB;MACE,WAAW;MACX,kBAAkB;MAClB,aAAa;MACb,SAAS;MACT,YAAY;MACZ,aAAa;MACb,0CAA0C;MAC1C,uCAAuC;IACzC;EACF;;EAEA;IACE,6BAA6B;IAC7B,8BAA8B;IAC9B,WAAW;IACX,4CAA4C;;IAE5C;MACE,WAAW;MACX,kBAAkB;MAClB,SAAS;MACT,YAAY;MACZ,YAAY;MACZ,aAAa;MACb,kDAAkD;MAClD,wCAAwC;IAC1C;EACF;AACF;;AAEA;;EAEE,4BAA4B;AAC9B;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE;IACE,4BAA4B;;IAE5B;;MAEE,8CAA8C;IAChD;EACF;AACF;;AAEA;EACE,4BAA4B;;EAE5B;IACE,+CAA+C;EACjD;;EAEA;IACE,+CAA+C;EACjD;AACF","file":"_messages.scss","sourcesContent":["@use \"../../vendor/govuk-frontend\" as *;\n\n/* ==========================================================================\n #MESSAGES\n ========================================================================== */\n\n.moj-messages-container {\n border: 1px solid $govuk-border-colour;\n @include govuk-font(19);\n}\n\n.moj-message-list {\n min-height: 200px;\n padding: govuk-spacing(1);\n overflow-x: hidden;\n overflow-y: scroll;\n\n &__date {\n display: inline-block;\n width: 100%;\n padding: govuk-spacing(3) 0;\n color: govuk-colour(\"dark-grey\");\n text-align: center;\n @include govuk-font($size: 19, $weight: \"bold\");\n }\n}\n\n.moj-message-item {\n position: relative;\n margin-bottom: govuk-spacing(1);\n padding: govuk-spacing(3);\n border-radius: 0.5em 0.5em 0.75em;\n\n @include govuk-media-query($from: tablet) {\n width: 50%;\n }\n\n &--sent {\n margin-right: govuk-spacing(2);\n padding-right: govuk-spacing(5);\n float: right;\n color: govuk-colour(\"white\");\n background-color: $govuk-brand-colour;\n text-align: right;\n\n &::after {\n content: \"\";\n position: absolute;\n right: -1.5em;\n bottom: 0;\n width: 1.5em;\n height: 1.5em;\n border-left: 1em solid $govuk-brand-colour;\n border-bottom-left-radius: 1.75em 1.5em;\n }\n }\n\n &--received {\n margin-left: govuk-spacing(2);\n padding-left: govuk-spacing(5);\n float: left;\n background-color: govuk-colour(\"light-grey\");\n\n &::after {\n content: \"\";\n position: absolute;\n bottom: 0;\n left: -1.5em;\n width: 1.5em;\n height: 1.5em;\n border-right: 1em solid govuk-colour(\"light-grey\");\n border-bottom-right-radius: 1.75em 1.5em;\n }\n }\n}\n\n.moj-message-item a:link,\n.moj-message-item a:visited {\n color: govuk-colour(\"white\");\n}\n\n.moj-message-item a:focus {\n color: $govuk-focus-text-colour;\n}\n\n.moj-message-item__text {\n &--sent table {\n color: govuk-colour(\"white\");\n\n & th,\n & td {\n border-bottom: 1px solid govuk-colour(\"white\");\n }\n }\n}\n\n.moj-message-item__meta {\n margin-top: govuk-spacing(2);\n\n &--sender {\n @include govuk-font($size: 16, $weight: \"bold\");\n }\n\n &--timestamp {\n @include govuk-font($size: 16, $weight: \"bold\");\n }\n}\n"]}
@@ -70,3 +70,5 @@
70
70
  float: left;
71
71
  fill: currentcolor;
72
72
  }
73
+
74
+ /*# sourceMappingURL=_multi-file-upload.scss.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/moj/components/multi-file-upload/_multi-file-upload.scss"],"names":[],"mappings":"AAAA,uCAAuC;;AAEvC;EACE,mBAAmB;AACrB;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,aAAa;EACb,0CAA0C;EAC1C;;gCAE8B;EAC9B,yCAAyC;EACzC,kBAAkB;AACpB;;AAEA;EACE,qBAAqB;EACrB,WAAW;EACX,gBAAgB;AAClB;;AAEA;EACE,kBAAkB;EAClB,gBAAgB;EAChB,gBAAgB;AAClB;;AAEA;EACE,kBAAkB;EAClB,aAAa;AACf;;AAEA;EACE,sBAAsB;EACtB,mBAAmB;AACrB;;AAEA;EACE,aAAa;EACb,+BAA+B;EAC/B,qCAAqC;EACrC;;kCAEgC;AAClC;;AAEA;EACE,0BAA0B;EAC1B,iBAAiB;AACnB;;AAEA;EACE,4BAA4B;EAC5B,iBAAiB;AACnB;;AAEA;EACE,8BAA8B;EAC9B,WAAW;EACX,kBAAkB;AACpB;;AAEA;EACE,8BAA8B;EAC9B,WAAW;EACX,kBAAkB;AACpB","file":"_multi-file-upload.scss","sourcesContent":["@use \"../../vendor/govuk-frontend\" as *;\n\n.moj-multi-file-upload {\n margin-bottom: 40px;\n}\n\n.moj-multi-file-upload--enhanced .moj-multi-file-upload__button {\n display: none;\n}\n\n.moj-multi-file-upload__dropzone {\n display: flex;\n padding: govuk-spacing(9) govuk-spacing(3);\n transition:\n outline-offset 0.1s ease-in-out,\n background-color 0.1s linear;\n outline: 3px dashed govuk-colour(\"black\");\n text-align: center;\n}\n\n.moj-multi-file-upload__dropzone label {\n display: inline-block;\n width: auto;\n margin-bottom: 0;\n}\n\n.moj-multi-file-upload__dropzone p {\n margin-right: 10px;\n margin-bottom: 0;\n padding-top: 7px;\n}\n\n.moj-multi-file-upload__dropzone [type=\"file\"] {\n position: absolute;\n left: -9999em;\n}\n\n.moj-multi-file-upload--dragover {\n outline-color: #6f777b;\n background: #b1b4b6;\n}\n\n.moj-multi-file-upload--focused {\n outline: none;\n color: $govuk-focus-text-colour;\n background-color: $govuk-focus-colour;\n box-shadow:\n 0 -2px $govuk-focus-colour,\n 0 4px $govuk-focus-text-colour;\n}\n\n.moj-multi-file-upload__error {\n color: govuk-colour(\"red\");\n font-weight: bold;\n}\n\n.moj-multi-file-upload__success {\n color: govuk-colour(\"green\");\n font-weight: bold;\n}\n\n.moj-multi-file-upload__error svg {\n margin-right: govuk-spacing(2);\n float: left;\n fill: currentcolor;\n}\n\n.moj-multi-file-upload__success svg {\n margin-right: govuk-spacing(2);\n float: left;\n fill: currentcolor;\n}\n"]}