govuk_publishing_components 32.1.0 → 35.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 (496) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/app/assets/config/govuk_publishing_components_manifest.js +75 -1
  4. data/app/assets/images/govuk_publishing_components/icon-search.svg +3 -0
  5. data/app/assets/images/govuk_publishing_components/youtube-play-icon.png +0 -0
  6. data/app/assets/images/govuk_publishing_components/youtube-play-icon.svg +4 -0
  7. data/app/assets/javascripts/component_guide/accessibility-test.js +0 -1
  8. data/app/assets/javascripts/govuk_publishing_components/analytics/auto-scroll-tracker.js +2 -1
  9. data/app/assets/javascripts/govuk_publishing_components/analytics/linked-domains.js +135 -0
  10. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-auto-tracker.js +49 -0
  11. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +341 -27
  12. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-ecommerce-tracker.js +17 -92
  13. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js +11 -23
  14. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +121 -0
  15. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +86 -305
  16. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +13 -6
  17. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +31 -1
  18. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-smart-answer-results-tracker.js +57 -0
  19. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +131 -0
  20. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +9 -4
  21. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/pii-remover.js +4 -2
  22. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +4 -0
  23. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +12 -1
  24. data/app/assets/javascripts/govuk_publishing_components/components/cookie-banner.js +2 -2
  25. data/app/assets/javascripts/govuk_publishing_components/components/image-card.js +19 -0
  26. data/app/assets/javascripts/govuk_publishing_components/components/layout-super-navigation-header.js +2 -81
  27. data/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js +24 -8
  28. data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +23 -1
  29. data/app/assets/javascripts/govuk_publishing_components/dependencies.js +13 -0
  30. data/app/assets/javascripts/govuk_publishing_components/lib/govspeak/youtube-link-enhancement.js +3 -2
  31. data/app/assets/javascripts/govuk_publishing_components/lib/trigger-event.js +1 -0
  32. data/app/assets/javascripts/govuk_publishing_components/load-analytics.js +116 -0
  33. data/app/assets/javascripts/govuk_publishing_components/modules.js +7 -2
  34. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +140 -191
  35. data/app/assets/stylesheets/govuk_publishing_components/_individual_component_support.scss +10 -0
  36. data/app/assets/stylesheets/govuk_publishing_components/components/_accordion.scss +29 -0
  37. data/app/assets/stylesheets/govuk_publishing_components/components/_action-link.scss +2 -0
  38. data/app/assets/stylesheets/govuk_publishing_components/components/_attachment.scss +2 -0
  39. data/app/assets/stylesheets/govuk_publishing_components/components/_back-link.scss +1 -0
  40. data/app/assets/stylesheets/govuk_publishing_components/components/_big-number.scss +4 -5
  41. data/app/assets/stylesheets/govuk_publishing_components/components/_breadcrumbs.scss +1 -0
  42. data/app/assets/stylesheets/govuk_publishing_components/components/_button.scss +12 -0
  43. data/app/assets/stylesheets/govuk_publishing_components/components/_cards.scss +20 -0
  44. data/app/assets/stylesheets/govuk_publishing_components/components/_character-count.scss +1 -0
  45. data/app/assets/stylesheets/govuk_publishing_components/components/_checkboxes.scss +1 -0
  46. data/app/assets/stylesheets/govuk_publishing_components/components/_contents-list.scss +21 -0
  47. data/app/assets/stylesheets/govuk_publishing_components/components/_contextual-guidance.scss +2 -0
  48. data/app/assets/stylesheets/govuk_publishing_components/components/_contextual-sidebar.scss +2 -0
  49. data/app/assets/stylesheets/govuk_publishing_components/components/_cookie-banner.scss +7 -0
  50. data/app/assets/stylesheets/govuk_publishing_components/components/_date-input.scss +1 -0
  51. data/app/assets/stylesheets/govuk_publishing_components/components/_details.scss +1 -0
  52. data/app/assets/stylesheets/govuk_publishing_components/components/_devolved-nations.scss +2 -0
  53. data/app/assets/stylesheets/govuk_publishing_components/components/_document-list.scss +8 -0
  54. data/app/assets/stylesheets/govuk_publishing_components/components/_emergency-banner.scss +8 -0
  55. data/app/assets/stylesheets/govuk_publishing_components/components/_error-alert.scss +2 -0
  56. data/app/assets/stylesheets/govuk_publishing_components/components/_error-message.scss +1 -0
  57. data/app/assets/stylesheets/govuk_publishing_components/components/_error-summary.scss +1 -0
  58. data/app/assets/stylesheets/govuk_publishing_components/components/_feedback.scss +17 -19
  59. data/app/assets/stylesheets/govuk_publishing_components/components/_fieldset.scss +1 -0
  60. data/app/assets/stylesheets/govuk_publishing_components/components/_file-upload.scss +1 -0
  61. data/app/assets/stylesheets/govuk_publishing_components/components/_govspeak-html-publication.scss +10 -0
  62. data/app/assets/stylesheets/govuk_publishing_components/components/_govspeak.scss +85 -0
  63. data/app/assets/stylesheets/govuk_publishing_components/components/_heading.scss +2 -0
  64. data/app/assets/stylesheets/govuk_publishing_components/components/_hint.scss +1 -0
  65. data/app/assets/stylesheets/govuk_publishing_components/components/_image-card.scss +85 -6
  66. data/app/assets/stylesheets/govuk_publishing_components/components/_input.scss +6 -6
  67. data/app/assets/stylesheets/govuk_publishing_components/components/_inset-text.scss +1 -0
  68. data/app/assets/stylesheets/govuk_publishing_components/components/_intervention.scss +2 -0
  69. data/app/assets/stylesheets/govuk_publishing_components/components/_inverse-header.scss +2 -0
  70. data/app/assets/stylesheets/govuk_publishing_components/components/_label.scss +1 -0
  71. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-footer.scss +1 -0
  72. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-for-public.scss +2 -0
  73. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +253 -483
  74. data/app/assets/stylesheets/govuk_publishing_components/components/_lead-paragraph.scss +2 -0
  75. data/app/assets/stylesheets/govuk_publishing_components/components/_metadata.scss +2 -0
  76. data/app/assets/stylesheets/govuk_publishing_components/components/_modal-dialogue.scss +2 -0
  77. data/app/assets/stylesheets/govuk_publishing_components/components/_notice.scss +1 -0
  78. data/app/assets/stylesheets/govuk_publishing_components/components/_organisation-logo.scss +2 -0
  79. data/app/assets/stylesheets/govuk_publishing_components/components/_panel.scss +1 -0
  80. data/app/assets/stylesheets/govuk_publishing_components/components/_phase-banner.scss +1 -0
  81. data/app/assets/stylesheets/govuk_publishing_components/components/_previous-and-next-navigation.scss +1 -0
  82. data/app/assets/stylesheets/govuk_publishing_components/components/_print-link.scss +2 -0
  83. data/app/assets/stylesheets/govuk_publishing_components/components/_radio.scss +1 -0
  84. data/app/assets/stylesheets/govuk_publishing_components/components/_related-navigation.scss +2 -0
  85. data/app/assets/stylesheets/govuk_publishing_components/components/_reorderable-list.scss +2 -0
  86. data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +2 -7
  87. data/app/assets/stylesheets/govuk_publishing_components/components/_select.scss +1 -0
  88. data/app/assets/stylesheets/govuk_publishing_components/components/_share-links.scss +2 -0
  89. data/app/assets/stylesheets/govuk_publishing_components/components/_show-password.scss +2 -0
  90. data/app/assets/stylesheets/govuk_publishing_components/components/_signup-link.scss +2 -0
  91. data/app/assets/stylesheets/govuk_publishing_components/components/_single-page-notification-button.scss +2 -0
  92. data/app/assets/stylesheets/govuk_publishing_components/components/_skip-link.scss +1 -0
  93. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-header.scss +17 -0
  94. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-related.scss +2 -0
  95. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav.scss +8 -0
  96. data/app/assets/stylesheets/govuk_publishing_components/components/_subscription-links.scss +2 -1
  97. data/app/assets/stylesheets/govuk_publishing_components/components/_success-alert.scss +1 -0
  98. data/app/assets/stylesheets/govuk_publishing_components/components/_summary-list.scss +1 -0
  99. data/app/assets/stylesheets/govuk_publishing_components/components/_table.scss +1 -0
  100. data/app/assets/stylesheets/govuk_publishing_components/components/_tabs.scss +1 -0
  101. data/app/assets/stylesheets/govuk_publishing_components/components/_textarea.scss +17 -0
  102. data/app/assets/stylesheets/govuk_publishing_components/components/_title.scss +12 -0
  103. data/app/assets/stylesheets/govuk_publishing_components/components/_translation-nav.scss +2 -0
  104. data/app/assets/stylesheets/govuk_publishing_components/components/_warning-text.scss +1 -0
  105. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_steps.scss +26 -9
  106. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_tables.scss +12 -0
  107. data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_brand-colours.scss +2 -2
  108. data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_contents-list-helper.scss +0 -1
  109. data/app/controllers/govuk_publishing_components/application_controller.rb +0 -13
  110. data/app/controllers/govuk_publishing_components/audit_controller.rb +1 -1
  111. data/app/controllers/govuk_publishing_components/component_guide_controller.rb +6 -9
  112. data/app/models/govuk_publishing_components/audit_applications.rb +10 -19
  113. data/app/models/govuk_publishing_components/audit_comparer.rb +29 -24
  114. data/app/models/govuk_publishing_components/audit_components.rb +157 -82
  115. data/app/models/govuk_publishing_components/component_doc.rb +14 -0
  116. data/app/models/govuk_publishing_components/component_wrapper_helper_options.rb +15 -0
  117. data/app/views/govuk_publishing_components/audit/_applications.html.erb +3 -3
  118. data/app/views/govuk_publishing_components/audit/_component_contents.html.erb +47 -39
  119. data/app/views/govuk_publishing_components/audit/_components.html.erb +47 -2
  120. data/app/views/govuk_publishing_components/component_guide/_application_stylesheet.html.erb +0 -3
  121. data/app/views/govuk_publishing_components/component_guide/index.html.erb +0 -7
  122. data/app/views/govuk_publishing_components/component_guide/show.html.erb +21 -6
  123. data/app/views/govuk_publishing_components/components/_accordion.html.erb +30 -36
  124. data/app/views/govuk_publishing_components/components/_action_link.html.erb +7 -2
  125. data/app/views/govuk_publishing_components/components/_attachment.html.erb +2 -0
  126. data/app/views/govuk_publishing_components/components/_attachment_link.html.erb +2 -0
  127. data/app/views/govuk_publishing_components/components/_back_link.html.erb +2 -0
  128. data/app/views/govuk_publishing_components/components/_big_number.html.erb +3 -1
  129. data/app/views/govuk_publishing_components/components/_breadcrumbs.html.erb +8 -2
  130. data/app/views/govuk_publishing_components/components/_button.html.erb +2 -0
  131. data/app/views/govuk_publishing_components/components/_cards.html.erb +6 -4
  132. data/app/views/govuk_publishing_components/components/_character_count.html.erb +2 -0
  133. data/app/views/govuk_publishing_components/components/_checkboxes.html.erb +6 -2
  134. data/app/views/govuk_publishing_components/components/_contents_list.html.erb +11 -15
  135. data/app/views/govuk_publishing_components/components/_contextual_breadcrumbs.html.erb +7 -4
  136. data/app/views/govuk_publishing_components/components/_contextual_footer.html.erb +2 -0
  137. data/app/views/govuk_publishing_components/components/_contextual_guidance.html.erb +2 -0
  138. data/app/views/govuk_publishing_components/components/_contextual_sidebar.html.erb +13 -6
  139. data/app/views/govuk_publishing_components/components/_cookie_banner.html.erb +12 -6
  140. data/app/views/govuk_publishing_components/components/_date_input.html.erb +2 -0
  141. data/app/views/govuk_publishing_components/components/_details.html.erb +5 -1
  142. data/app/views/govuk_publishing_components/components/_devolved_nations.html.erb +2 -0
  143. data/app/views/govuk_publishing_components/components/_document_list.html.erb +3 -0
  144. data/app/views/govuk_publishing_components/components/_emergency_banner.html.erb +2 -0
  145. data/app/views/govuk_publishing_components/components/_error_alert.html.erb +2 -0
  146. data/app/views/govuk_publishing_components/components/_error_message.html.erb +4 -1
  147. data/app/views/govuk_publishing_components/components/_error_summary.html.erb +29 -26
  148. data/app/views/govuk_publishing_components/components/_feedback.html.erb +2 -0
  149. data/app/views/govuk_publishing_components/components/_fieldset.html.erb +2 -0
  150. data/app/views/govuk_publishing_components/components/_file_upload.html.erb +2 -0
  151. data/app/views/govuk_publishing_components/components/_google_tag_manager_script.html.erb +2 -2
  152. data/app/views/govuk_publishing_components/components/_govspeak.html.erb +1 -0
  153. data/app/views/govuk_publishing_components/components/_govspeak_html_publication.html.erb +2 -0
  154. data/app/views/govuk_publishing_components/components/_heading.html.erb +2 -0
  155. data/app/views/govuk_publishing_components/components/_hint.html.erb +4 -1
  156. data/app/views/govuk_publishing_components/components/_image_card.html.erb +17 -12
  157. data/app/views/govuk_publishing_components/components/_input.html.erb +10 -2
  158. data/app/views/govuk_publishing_components/components/_inset_text.html.erb +2 -0
  159. data/app/views/govuk_publishing_components/components/_intervention.html.erb +2 -0
  160. data/app/views/govuk_publishing_components/components/_inverse_header.html.erb +2 -0
  161. data/app/views/govuk_publishing_components/components/_label.html.erb +7 -3
  162. data/app/views/govuk_publishing_components/components/_layout_footer.html.erb +2 -0
  163. data/app/views/govuk_publishing_components/components/_layout_for_admin.html.erb +8 -5
  164. data/app/views/govuk_publishing_components/components/_layout_for_public.html.erb +8 -3
  165. data/app/views/govuk_publishing_components/components/_layout_header.html.erb +2 -0
  166. data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +238 -267
  167. data/app/views/govuk_publishing_components/components/_lead_paragraph.html.erb +2 -0
  168. data/app/views/govuk_publishing_components/components/_metadata.html.erb +2 -0
  169. data/app/views/govuk_publishing_components/components/_modal_dialogue.html.erb +2 -0
  170. data/app/views/govuk_publishing_components/components/_notice.html.erb +2 -0
  171. data/app/views/govuk_publishing_components/components/_organisation_logo.html.erb +2 -0
  172. data/app/views/govuk_publishing_components/components/_panel.html.erb +2 -0
  173. data/app/views/govuk_publishing_components/components/_phase_banner.html.erb +3 -1
  174. data/app/views/govuk_publishing_components/components/_previous_and_next_navigation.html.erb +6 -1
  175. data/app/views/govuk_publishing_components/components/_print_link.html.erb +2 -0
  176. data/app/views/govuk_publishing_components/components/_radio.html.erb +2 -0
  177. data/app/views/govuk_publishing_components/components/_related_navigation.html.erb +16 -6
  178. data/app/views/govuk_publishing_components/components/_reorderable_list.html.erb +2 -0
  179. data/app/views/govuk_publishing_components/components/_search.html.erb +2 -0
  180. data/app/views/govuk_publishing_components/components/_select.html.erb +2 -0
  181. data/app/views/govuk_publishing_components/components/_share_links.html.erb +13 -13
  182. data/app/views/govuk_publishing_components/components/_show_password.html.erb +2 -0
  183. data/app/views/govuk_publishing_components/components/_signup_link.html.erb +2 -0
  184. data/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb +8 -2
  185. data/app/views/govuk_publishing_components/components/_skip_link.html.erb +2 -0
  186. data/app/views/govuk_publishing_components/components/_step_by_step_nav.html.erb +8 -1
  187. data/app/views/govuk_publishing_components/components/_step_by_step_nav_header.html.erb +12 -2
  188. data/app/views/govuk_publishing_components/components/_step_by_step_nav_related.html.erb +21 -8
  189. data/app/views/govuk_publishing_components/components/_subscription_links.html.erb +3 -1
  190. data/app/views/govuk_publishing_components/components/_success_alert.html.erb +2 -0
  191. data/app/views/govuk_publishing_components/components/_summary_list.html.erb +2 -0
  192. data/app/views/govuk_publishing_components/components/_table.html.erb +3 -1
  193. data/app/views/govuk_publishing_components/components/_tabs.html.erb +22 -2
  194. data/app/views/govuk_publishing_components/components/_textarea.html.erb +12 -2
  195. data/app/views/govuk_publishing_components/components/_title.html.erb +2 -0
  196. data/app/views/govuk_publishing_components/components/_translation_nav.html.erb +2 -0
  197. data/app/views/govuk_publishing_components/components/_warning_text.html.erb +2 -0
  198. data/app/views/govuk_publishing_components/components/contextual_sidebar/_ukraine_cta.html.erb +16 -6
  199. data/app/views/govuk_publishing_components/components/docs/accordion.yml +16 -3
  200. data/app/views/govuk_publishing_components/components/docs/action_link.yml +1 -0
  201. data/app/views/govuk_publishing_components/components/docs/breadcrumbs.yml +2 -1
  202. data/app/views/govuk_publishing_components/components/docs/button.yml +10 -0
  203. data/app/views/govuk_publishing_components/components/docs/cards.yml +1 -0
  204. data/app/views/govuk_publishing_components/components/docs/checkboxes.yml +1 -0
  205. data/app/views/govuk_publishing_components/components/docs/contents_list.yml +1 -12
  206. data/app/views/govuk_publishing_components/components/docs/contextual_breadcrumbs.yml +13 -0
  207. data/app/views/govuk_publishing_components/components/docs/contextual_footer.yml +43 -0
  208. data/app/views/govuk_publishing_components/components/docs/contextual_sidebar.yml +65 -0
  209. data/app/views/govuk_publishing_components/components/docs/details.yml +17 -0
  210. data/app/views/govuk_publishing_components/components/docs/document_list.yml +18 -1
  211. data/app/views/govuk_publishing_components/components/docs/emergency_banner.yml +3 -1
  212. data/app/views/govuk_publishing_components/components/docs/error_message.yml +13 -0
  213. data/app/views/govuk_publishing_components/components/docs/govspeak.yml +22 -1
  214. data/app/views/govuk_publishing_components/components/docs/hint.yml +6 -0
  215. data/app/views/govuk_publishing_components/components/docs/image_card.yml +24 -1
  216. data/app/views/govuk_publishing_components/components/docs/input.yml +32 -0
  217. data/app/views/govuk_publishing_components/components/docs/intervention.yml +2 -1
  218. data/app/views/govuk_publishing_components/components/docs/label.yml +17 -0
  219. data/app/views/govuk_publishing_components/components/docs/layout_header.yml +1 -0
  220. data/app/views/govuk_publishing_components/components/docs/previous_and_next_navigation.yml +2 -0
  221. data/app/views/govuk_publishing_components/components/docs/related_navigation.yml +47 -0
  222. data/app/views/govuk_publishing_components/components/docs/share_links.yml +59 -30
  223. data/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml +16 -1
  224. data/app/views/govuk_publishing_components/components/docs/step_by_step_nav.yml +54 -0
  225. data/app/views/govuk_publishing_components/components/docs/step_by_step_nav_header.yml +6 -0
  226. data/app/views/govuk_publishing_components/components/docs/step_by_step_nav_related.yml +10 -0
  227. data/app/views/govuk_publishing_components/components/docs/tabs.yml +15 -0
  228. data/app/views/govuk_publishing_components/components/docs/textarea.yml +31 -0
  229. data/app/views/govuk_publishing_components/components/docs/translation_nav.yml +2 -0
  230. data/app/views/govuk_publishing_components/components/feedback/_problem_form.html.erb +3 -3
  231. data/app/views/govuk_publishing_components/components/feedback/_survey_signup_form.html.erb +1 -1
  232. data/app/views/govuk_publishing_components/components/feedback/_yes_no_banner.html.erb +4 -5
  233. data/app/views/govuk_publishing_components/components/metadata/_sentence.html.erb +4 -2
  234. data/app/views/govuk_publishing_components/components/related_navigation/_section.html.erb +36 -16
  235. data/app/views/layouts/govuk_publishing_components/application.html.erb +3 -4
  236. data/config/locales/ar.yml +14 -14
  237. data/config/locales/az.yml +15 -14
  238. data/config/locales/be.yml +14 -14
  239. data/config/locales/bg.yml +14 -14
  240. data/config/locales/bn.yml +14 -14
  241. data/config/locales/cs.yml +14 -14
  242. data/config/locales/cy.yml +14 -14
  243. data/config/locales/da.yml +14 -14
  244. data/config/locales/de.yml +14 -14
  245. data/config/locales/dr.yml +14 -14
  246. data/config/locales/el.yml +14 -14
  247. data/config/locales/en.yml +21 -28
  248. data/config/locales/es-419.yml +14 -14
  249. data/config/locales/es.yml +14 -14
  250. data/config/locales/et.yml +14 -14
  251. data/config/locales/fa.yml +15 -14
  252. data/config/locales/fi.yml +14 -14
  253. data/config/locales/fr.yml +14 -14
  254. data/config/locales/gd.yml +14 -14
  255. data/config/locales/gu.yml +14 -14
  256. data/config/locales/he.yml +14 -14
  257. data/config/locales/hi.yml +14 -14
  258. data/config/locales/hr.yml +14 -14
  259. data/config/locales/hu.yml +14 -14
  260. data/config/locales/hy.yml +14 -14
  261. data/config/locales/id.yml +14 -14
  262. data/config/locales/is.yml +14 -14
  263. data/config/locales/it.yml +14 -14
  264. data/config/locales/ja.yml +14 -14
  265. data/config/locales/ka.yml +14 -14
  266. data/config/locales/kk.yml +14 -14
  267. data/config/locales/ko.yml +14 -14
  268. data/config/locales/lt.yml +14 -14
  269. data/config/locales/lv.yml +14 -14
  270. data/config/locales/ms.yml +14 -14
  271. data/config/locales/mt.yml +14 -14
  272. data/config/locales/nl.yml +14 -14
  273. data/config/locales/no.yml +14 -14
  274. data/config/locales/pa-pk.yml +14 -14
  275. data/config/locales/pa.yml +14 -14
  276. data/config/locales/pl.yml +14 -14
  277. data/config/locales/ps.yml +14 -14
  278. data/config/locales/pt.yml +14 -14
  279. data/config/locales/ro.yml +14 -14
  280. data/config/locales/ru.yml +14 -14
  281. data/config/locales/si.yml +14 -14
  282. data/config/locales/sk.yml +14 -14
  283. data/config/locales/sl.yml +14 -14
  284. data/config/locales/so.yml +14 -14
  285. data/config/locales/sq.yml +14 -14
  286. data/config/locales/sr.yml +14 -14
  287. data/config/locales/sv.yml +14 -14
  288. data/config/locales/sw.yml +14 -14
  289. data/config/locales/ta.yml +14 -14
  290. data/config/locales/th.yml +14 -14
  291. data/config/locales/tk.yml +14 -14
  292. data/config/locales/tr.yml +14 -14
  293. data/config/locales/uk.yml +14 -14
  294. data/config/locales/ur.yml +14 -14
  295. data/config/locales/uz.yml +14 -14
  296. data/config/locales/vi.yml +14 -14
  297. data/config/locales/zh-hk.yml +14 -14
  298. data/config/locales/zh-tw.yml +14 -14
  299. data/config/locales/zh.yml +14 -14
  300. data/lib/govuk_publishing_components/app_helpers/asset_helper.rb +86 -0
  301. data/lib/govuk_publishing_components/config.rb +3 -3
  302. data/lib/govuk_publishing_components/presenters/accordion_helper.rb +38 -0
  303. data/lib/govuk_publishing_components/presenters/breadcrumb_selector.rb +3 -2
  304. data/lib/govuk_publishing_components/presenters/{breadcrumbs.rb → breadcrumbs_helper.rb} +8 -0
  305. data/lib/govuk_publishing_components/presenters/button_helper.rb +9 -2
  306. data/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb +95 -0
  307. data/lib/govuk_publishing_components/presenters/image_card_helper.rb +65 -2
  308. data/lib/govuk_publishing_components/presenters/page_with_step_by_step_navigation.rb +3 -2
  309. data/lib/govuk_publishing_components/presenters/related_navigation_helper.rb +16 -7
  310. data/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb +43 -2
  311. data/lib/govuk_publishing_components/presenters/step_by_step_nav_helper.rb +16 -0
  312. data/lib/govuk_publishing_components/railtie.rb +7 -0
  313. data/lib/govuk_publishing_components/version.rb +1 -1
  314. data/lib/govuk_publishing_components.rb +6 -1
  315. data/node_modules/axe-core/README.md +1 -1
  316. data/node_modules/axe-core/axe.d.ts +76 -24
  317. data/node_modules/axe-core/axe.js +9200 -9059
  318. data/node_modules/axe-core/axe.min.js +3 -3
  319. data/node_modules/axe-core/package.json +29 -29
  320. data/node_modules/axe-core/sri-history.json +20 -0
  321. data/node_modules/govuk-frontend/README.md +1 -2
  322. data/node_modules/govuk-frontend/govuk/all.js +4035 -2673
  323. data/node_modules/govuk-frontend/govuk/all.js.map +1 -0
  324. data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js +71 -0
  325. data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js.map +1 -0
  326. data/node_modules/govuk-frontend/govuk/common/index.js +180 -0
  327. data/node_modules/govuk-frontend/govuk/common/index.js.map +1 -0
  328. data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js +376 -0
  329. data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js.map +1 -0
  330. data/node_modules/govuk-frontend/govuk/common.js +173 -30
  331. data/node_modules/govuk-frontend/govuk/common.js.map +1 -0
  332. data/node_modules/govuk-frontend/govuk/components/_all.scss +1 -1
  333. data/node_modules/govuk-frontend/govuk/components/accordion/_index.scss +23 -4
  334. data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +2116 -983
  335. data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js.map +1 -0
  336. data/node_modules/govuk-frontend/govuk/components/accordion/fixtures.json +54 -22
  337. data/node_modules/govuk-frontend/govuk/components/accordion/macro-options.json +36 -0
  338. data/node_modules/govuk-frontend/govuk/components/accordion/template.njk +8 -2
  339. data/node_modules/govuk-frontend/govuk/components/back-link/_index.scss +19 -19
  340. data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +12 -12
  341. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +21 -10
  342. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +22 -22
  343. data/node_modules/govuk-frontend/govuk/components/button/_index.scss +23 -5
  344. data/node_modules/govuk-frontend/govuk/components/button/button.js +958 -690
  345. data/node_modules/govuk-frontend/govuk/components/button/button.js.map +1 -0
  346. data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +85 -66
  347. data/node_modules/govuk-frontend/govuk/components/button/template.njk +1 -1
  348. data/node_modules/govuk-frontend/govuk/components/character-count/_index.scss +9 -0
  349. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +2083 -1161
  350. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js.map +1 -0
  351. data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +112 -36
  352. data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +42 -0
  353. data/node_modules/govuk-frontend/govuk/components/character-count/template.njk +27 -3
  354. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +1155 -1119
  355. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js.map +1 -0
  356. data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +96 -93
  357. data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +46 -46
  358. data/node_modules/govuk-frontend/govuk/components/cookie-banner/template.njk +1 -1
  359. data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +50 -50
  360. data/node_modules/govuk-frontend/govuk/components/details/details.js +797 -766
  361. data/node_modules/govuk-frontend/govuk/components/details/details.js.map +1 -0
  362. data/node_modules/govuk-frontend/govuk/components/details/fixtures.json +20 -20
  363. data/node_modules/govuk-frontend/govuk/components/error-message/fixtures.json +20 -20
  364. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +1089 -814
  365. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js.map +1 -0
  366. data/node_modules/govuk-frontend/govuk/components/error-summary/fixtures.json +44 -35
  367. data/node_modules/govuk-frontend/govuk/components/error-summary/template.njk +25 -21
  368. data/node_modules/govuk-frontend/govuk/components/fieldset/fixtures.json +51 -39
  369. data/node_modules/govuk-frontend/govuk/components/file-upload/fixtures.json +26 -26
  370. data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +1 -1
  371. data/node_modules/govuk-frontend/govuk/components/footer/fixtures.json +46 -46
  372. data/node_modules/govuk-frontend/govuk/components/footer/macro-options.json +2 -2
  373. data/node_modules/govuk-frontend/govuk/components/header/_index.scss +6 -0
  374. data/node_modules/govuk-frontend/govuk/components/header/fixtures.json +93 -38
  375. data/node_modules/govuk-frontend/govuk/components/header/header.js +646 -992
  376. data/node_modules/govuk-frontend/govuk/components/header/header.js.map +1 -0
  377. data/node_modules/govuk-frontend/govuk/components/header/macro-options.json +8 -2
  378. data/node_modules/govuk-frontend/govuk/components/header/template.njk +4 -2
  379. data/node_modules/govuk-frontend/govuk/components/hint/fixtures.json +12 -12
  380. data/node_modules/govuk-frontend/govuk/components/input/fixtures.json +80 -80
  381. data/node_modules/govuk-frontend/govuk/components/inset-text/fixtures.json +12 -12
  382. data/node_modules/govuk-frontend/govuk/components/label/fixtures.json +34 -34
  383. data/node_modules/govuk-frontend/govuk/components/notification-banner/fixtures.json +56 -46
  384. data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +790 -532
  385. data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js.map +1 -0
  386. data/node_modules/govuk-frontend/govuk/components/notification-banner/template.njk +1 -1
  387. data/node_modules/govuk-frontend/govuk/components/pagination/_index.scss +10 -7
  388. data/node_modules/govuk-frontend/govuk/components/pagination/fixtures.json +94 -26
  389. data/node_modules/govuk-frontend/govuk/components/pagination/template.njk +1 -1
  390. data/node_modules/govuk-frontend/govuk/components/panel/fixtures.json +18 -18
  391. data/node_modules/govuk-frontend/govuk/components/phase-banner/fixtures.json +14 -14
  392. data/node_modules/govuk-frontend/govuk/components/phase-banner/macro-options.json +1 -1
  393. data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +94 -91
  394. data/node_modules/govuk-frontend/govuk/components/radios/radios.js +1110 -1079
  395. data/node_modules/govuk-frontend/govuk/components/radios/radios.js.map +1 -0
  396. data/node_modules/govuk-frontend/govuk/components/select/fixtures.json +32 -32
  397. data/node_modules/govuk-frontend/govuk/components/skip-link/fixtures.json +22 -20
  398. data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +1017 -1008
  399. data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js.map +1 -0
  400. data/node_modules/govuk-frontend/govuk/components/summary-list/_index.scss +107 -0
  401. data/node_modules/govuk-frontend/govuk/components/summary-list/fixtures.json +345 -50
  402. data/node_modules/govuk-frontend/govuk/components/summary-list/macro-options.json +110 -0
  403. data/node_modules/govuk-frontend/govuk/components/summary-list/template.njk +72 -28
  404. data/node_modules/govuk-frontend/govuk/components/table/_index.scss +1 -1
  405. data/node_modules/govuk-frontend/govuk/components/table/fixtures.json +40 -40
  406. data/node_modules/govuk-frontend/govuk/components/tabs/fixtures.json +29 -29
  407. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +1389 -1233
  408. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js.map +1 -0
  409. data/node_modules/govuk-frontend/govuk/components/tag/fixtures.json +28 -28
  410. data/node_modules/govuk-frontend/govuk/components/textarea/fixtures.json +34 -34
  411. data/node_modules/govuk-frontend/govuk/components/warning-text/fixtures.json +14 -14
  412. data/node_modules/govuk-frontend/govuk/core/_section-break.scss +1 -1
  413. data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +2 -2
  414. data/node_modules/govuk-frontend/govuk/helpers/_focused.scss +5 -0
  415. data/node_modules/govuk-frontend/govuk/helpers/_links.scss +6 -6
  416. data/node_modules/govuk-frontend/govuk/i18n.js +389 -0
  417. data/node_modules/govuk-frontend/govuk/i18n.js.map +1 -0
  418. data/node_modules/govuk-frontend/govuk/macros/i18n.njk +15 -0
  419. data/node_modules/govuk-frontend/govuk/settings/_all.scss +1 -0
  420. data/node_modules/govuk-frontend/govuk/settings/_colours-palette.scss +12 -0
  421. data/node_modules/govuk-frontend/govuk/settings/_compatibility.scss +26 -0
  422. data/node_modules/govuk-frontend/govuk/settings/_measurements.scss +5 -5
  423. data/node_modules/govuk-frontend/govuk/settings/_typography-font.scss +23 -0
  424. data/node_modules/govuk-frontend/govuk/settings/_typography-responsive.scss +12 -0
  425. data/node_modules/govuk-frontend/govuk/settings/_warnings.scss +53 -0
  426. data/node_modules/govuk-frontend/govuk/tools/_compatibility.scss +20 -6
  427. data/node_modules/govuk-frontend/govuk/vendor/polyfills/DOMTokenList.js +242 -241
  428. data/node_modules/govuk-frontend/govuk/vendor/polyfills/DOMTokenList.js.map +1 -0
  429. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js +22 -0
  430. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js.map +1 -0
  431. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Document.js +17 -16
  432. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Document.js.map +1 -0
  433. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/classList.js +547 -546
  434. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/classList.js.map +1 -0
  435. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/closest.js +37 -36
  436. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/closest.js.map +1 -0
  437. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js +301 -0
  438. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js.map +1 -0
  439. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/matches.js +21 -20
  440. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/matches.js.map +1 -0
  441. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/nextElementSibling.js +198 -197
  442. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/nextElementSibling.js.map +1 -0
  443. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/previousElementSibling.js +198 -197
  444. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/previousElementSibling.js.map +1 -0
  445. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element.js +106 -105
  446. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element.js.map +1 -0
  447. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Event.js +400 -399
  448. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Event.js.map +1 -0
  449. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Function/prototype/bind.js +239 -238
  450. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Function/prototype/bind.js.map +1 -0
  451. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Object/defineProperty.js +72 -71
  452. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Object/defineProperty.js.map +1 -0
  453. data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js +22 -0
  454. data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js.map +1 -0
  455. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Window.js +17 -16
  456. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Window.js.map +1 -0
  457. data/node_modules/govuk-frontend/govuk-esm/all.mjs +52 -29
  458. data/node_modules/govuk-frontend/govuk-esm/common/closest-attribute-value.mjs +15 -0
  459. data/node_modules/govuk-frontend/govuk-esm/common/index.mjs +166 -0
  460. data/node_modules/govuk-frontend/govuk-esm/common/normalise-dataset.mjs +60 -0
  461. data/node_modules/govuk-frontend/govuk-esm/common.mjs +6 -28
  462. data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +238 -85
  463. data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +73 -34
  464. data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +329 -124
  465. data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +32 -20
  466. data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +41 -20
  467. data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +60 -14
  468. data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +9 -2
  469. data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +33 -4
  470. data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +18 -11
  471. data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +15 -7
  472. data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +171 -38
  473. data/node_modules/govuk-frontend/govuk-esm/i18n.mjs +378 -0
  474. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Date/now.mjs +13 -0
  475. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/dataset.mjs +68 -0
  476. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/String/prototype/trim.mjs +13 -0
  477. data/node_modules/govuk-frontend/govuk-prototype-kit/init.js +7 -0
  478. data/node_modules/govuk-frontend/govuk-prototype-kit/init.scss +12 -0
  479. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +138 -7
  480. data/node_modules/govuk-frontend/package.json +1 -1
  481. metadata +70 -19
  482. data/app/assets/stylesheets/component_guide/print.scss +0 -1
  483. data/app/assets/stylesheets/govuk_publishing_components/_all_components_print.scss +0 -18
  484. data/app/assets/stylesheets/govuk_publishing_components/components/print/_accordion.scss +0 -28
  485. data/app/assets/stylesheets/govuk_publishing_components/components/print/_button.scss +0 -8
  486. data/app/assets/stylesheets/govuk_publishing_components/components/print/_cards.scss +0 -4
  487. data/app/assets/stylesheets/govuk_publishing_components/components/print/_contents-list.scss +0 -19
  488. data/app/assets/stylesheets/govuk_publishing_components/components/print/_emergency-banner.scss +0 -3
  489. data/app/assets/stylesheets/govuk_publishing_components/components/print/_govspeak-html-publication.scss +0 -5
  490. data/app/assets/stylesheets/govuk_publishing_components/components/print/_govspeak.scss +0 -80
  491. data/app/assets/stylesheets/govuk_publishing_components/components/print/_layout-super-navigation-header.scss +0 -3
  492. data/app/assets/stylesheets/govuk_publishing_components/components/print/_organisation-logo.scss +0 -7
  493. data/app/assets/stylesheets/govuk_publishing_components/components/print/_step-by-step-nav-header.scss +0 -7
  494. data/app/assets/stylesheets/govuk_publishing_components/components/print/_step-by-step-nav.scss +0 -116
  495. data/app/assets/stylesheets/govuk_publishing_components/components/print/_textarea.scss +0 -13
  496. data/app/assets/stylesheets/govuk_publishing_components/components/print/_title.scss +0 -7
@@ -1,47 +1,86 @@
1
- import '../../vendor/polyfills/Event.mjs' // addEventListener and event.target normaliziation
1
+ /* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
2
+
3
+ import { mergeConfigs } from '../../common/index.mjs'
4
+ import { normaliseDataset } from '../../common/normalise-dataset.mjs'
5
+ import '../../vendor/polyfills/Event.mjs' // addEventListener, event.target normalization and DOMContentLoaded
2
6
  import '../../vendor/polyfills/Function/prototype/bind.mjs'
3
7
 
4
8
  var KEY_SPACE = 32
5
9
  var DEBOUNCE_TIMEOUT_IN_SECONDS = 1
6
10
 
7
- function Button ($module) {
11
+ /**
12
+ * JavaScript enhancements for the Button component
13
+ *
14
+ * @class
15
+ * @param {HTMLElement} $module - HTML element to use for button
16
+ * @param {ButtonConfig} [config] - Button config
17
+ */
18
+ function Button ($module, config) {
19
+ if (!$module) {
20
+ return this
21
+ }
22
+
8
23
  this.$module = $module
9
24
  this.debounceFormSubmitTimer = null
25
+
26
+ var defaultConfig = {
27
+ preventDoubleClick: false
28
+ }
29
+ this.config = mergeConfigs(
30
+ defaultConfig,
31
+ config || {},
32
+ normaliseDataset($module.dataset)
33
+ )
10
34
  }
11
35
 
12
36
  /**
13
- * JavaScript 'shim' to trigger the click event of element(s) when the space key is pressed.
14
- *
15
- * Created since some Assistive Technologies (for example some Screenreaders)
16
- * will tell a user to press space on a 'button', so this functionality needs to be shimmed
17
- * See https://github.com/alphagov/govuk_elements/pull/272#issuecomment-233028270
18
- *
19
- * @param {object} event event
20
- */
37
+ * Initialise component
38
+ */
39
+ Button.prototype.init = function () {
40
+ if (!this.$module) {
41
+ return
42
+ }
43
+
44
+ this.$module.addEventListener('keydown', this.handleKeyDown)
45
+ this.$module.addEventListener('click', this.debounce.bind(this))
46
+ }
47
+
48
+ /**
49
+ * Trigger a click event when the space key is pressed
50
+ *
51
+ * Some screen readers tell users they can activate things with the 'button'
52
+ * role, so we need to match the functionality of native HTML buttons
53
+ *
54
+ * See https://github.com/alphagov/govuk_elements/pull/272#issuecomment-233028270
55
+ *
56
+ * @param {KeyboardEvent} event - Keydown event
57
+ */
21
58
  Button.prototype.handleKeyDown = function (event) {
22
- // get the target element
23
- var target = event.target
24
- // if the element has a role='button' and the pressed key is a space, we'll simulate a click
25
- if (target.getAttribute('role') === 'button' && event.keyCode === KEY_SPACE) {
26
- event.preventDefault()
27
- // trigger the target's click event
28
- target.click()
59
+ var $target = event.target
60
+
61
+ if ($target.getAttribute('role') === 'button' && event.keyCode === KEY_SPACE) {
62
+ event.preventDefault() // prevent the page from scrolling
63
+ $target.click()
29
64
  }
30
65
  }
31
66
 
32
67
  /**
33
- * If the click quickly succeeds a previous click then nothing will happen.
34
- * This stops people accidentally causing multiple form submissions by
35
- * double clicking buttons.
36
- */
68
+ * Debounce double-clicks
69
+ *
70
+ * If the click quickly succeeds a previous click then nothing will happen. This
71
+ * stops people accidentally causing multiple form submissions by double
72
+ * clicking buttons.
73
+ *
74
+ * @param {MouseEvent} event - Mouse click event
75
+ * @returns {undefined | false} Returns undefined, or false when debounced
76
+ */
37
77
  Button.prototype.debounce = function (event) {
38
- var target = event.target
39
- // Check the button that is clicked on has the preventDoubleClick feature enabled
40
- if (target.getAttribute('data-prevent-double-click') !== 'true') {
78
+ // Check the button that was clicked has preventDoubleClick enabled
79
+ if (!this.config.preventDoubleClick) {
41
80
  return
42
81
  }
43
82
 
44
- // If the timer is still running then we want to prevent the click from submitting the form
83
+ // If the timer is still running, prevent the click from submitting the form
45
84
  if (this.debounceFormSubmitTimer) {
46
85
  event.preventDefault()
47
86
  return false
@@ -52,13 +91,13 @@ Button.prototype.debounce = function (event) {
52
91
  }.bind(this), DEBOUNCE_TIMEOUT_IN_SECONDS * 1000)
53
92
  }
54
93
 
55
- /**
56
- * Initialise an event listener for keydown at document level
57
- * this will help listening for later inserted elements with a role="button"
58
- */
59
- Button.prototype.init = function () {
60
- this.$module.addEventListener('keydown', this.handleKeyDown)
61
- this.$module.addEventListener('click', this.debounce)
62
- }
63
-
64
94
  export default Button
95
+
96
+ /**
97
+ * Button config
98
+ *
99
+ * @typedef {object} ButtonConfig
100
+ * @property {boolean} [preventDoubleClick = false] -
101
+ * Prevent accidental double clicks on submit buttons from submitting forms
102
+ * multiple times.
103
+ */
@@ -1,8 +1,109 @@
1
- import '../../vendor/polyfills/Function/prototype/bind.mjs'
2
- import '../../vendor/polyfills/Event.mjs' // addEventListener and event.target normaliziation
1
+ /* eslint-disable es-x/no-date-now -- Polyfill imported */
2
+ /* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
3
+
4
+ import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'
5
+ import { extractConfigByNamespace, mergeConfigs } from '../../common/index.mjs'
6
+ import { normaliseDataset } from '../../common/normalise-dataset.mjs'
7
+ import { I18n } from '../../i18n.mjs'
8
+ import '../../vendor/polyfills/Date/now.mjs'
3
9
  import '../../vendor/polyfills/Element/prototype/classList.mjs'
10
+ import '../../vendor/polyfills/Event.mjs' // addEventListener, event.target normalization and DOMContentLoaded
11
+ import '../../vendor/polyfills/Function/prototype/bind.mjs'
12
+
13
+ /**
14
+ * @constant
15
+ * @type {CharacterCountTranslations}
16
+ * @see Default value for {@link CharacterCountConfig.i18n}
17
+ * @default
18
+ */
19
+ var CHARACTER_COUNT_TRANSLATIONS = {
20
+ // Characters
21
+ charactersUnderLimit: {
22
+ one: 'You have %{count} character remaining',
23
+ other: 'You have %{count} characters remaining'
24
+ },
25
+ charactersAtLimit: 'You have 0 characters remaining',
26
+ charactersOverLimit: {
27
+ one: 'You have %{count} character too many',
28
+ other: 'You have %{count} characters too many'
29
+ },
30
+ // Words
31
+ wordsUnderLimit: {
32
+ one: 'You have %{count} word remaining',
33
+ other: 'You have %{count} words remaining'
34
+ },
35
+ wordsAtLimit: 'You have 0 words remaining',
36
+ wordsOverLimit: {
37
+ one: 'You have %{count} word too many',
38
+ other: 'You have %{count} words too many'
39
+ },
40
+ textareaDescription: {
41
+ other: ''
42
+ }
43
+ }
44
+
45
+ /**
46
+ * JavaScript enhancements for the CharacterCount component
47
+ *
48
+ * Tracks the number of characters or words in the `.govuk-js-character-count`
49
+ * `<textarea>` inside the element. Displays a message with the remaining number
50
+ * of characters/words available, or the number of characters/words in excess.
51
+ *
52
+ * You can configure the message to only appear after a certain percentage
53
+ * of the available characters/words has been entered.
54
+ *
55
+ * @class
56
+ * @param {HTMLElement} $module - HTML element to use for character count
57
+ * @param {CharacterCountConfig} [config] - Character count config
58
+ */
59
+ function CharacterCount ($module, config) {
60
+ if (!$module) {
61
+ return this
62
+ }
63
+
64
+ var defaultConfig = {
65
+ threshold: 0,
66
+ i18n: CHARACTER_COUNT_TRANSLATIONS
67
+ }
68
+
69
+ // Read config set using dataset ('data-' values)
70
+ var datasetConfig = normaliseDataset($module.dataset)
71
+
72
+ // To ensure data-attributes take complete precedence, even if they change the
73
+ // type of count, we need to reset the `maxlength` and `maxwords` from the
74
+ // JavaScript config.
75
+ //
76
+ // We can't mutate `config`, though, as it may be shared across multiple
77
+ // components inside `initAll`.
78
+ var configOverrides = {}
79
+ if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
80
+ configOverrides = {
81
+ maxlength: false,
82
+ maxwords: false
83
+ }
84
+ }
85
+
86
+ this.config = mergeConfigs(
87
+ defaultConfig,
88
+ config || {},
89
+ configOverrides,
90
+ datasetConfig
91
+ )
92
+
93
+ this.i18n = new I18n(extractConfigByNamespace(this.config, 'i18n'), {
94
+ // Read the fallback if necessary rather than have it set in the defaults
95
+ locale: closestAttributeValue($module, 'lang')
96
+ })
97
+
98
+ // Determine the limit attribute (characters or words)
99
+ if (this.config.maxwords) {
100
+ this.maxLength = this.config.maxwords
101
+ } else if (this.config.maxlength) {
102
+ this.maxLength = this.config.maxlength
103
+ } else {
104
+ return
105
+ }
4
106
 
5
- function CharacterCount ($module) {
6
107
  this.$module = $module
7
108
  this.$textarea = $module.querySelector('.govuk-js-character-count')
8
109
  this.$visibleCountMessage = null
@@ -10,26 +111,28 @@ function CharacterCount ($module) {
10
111
  this.lastInputTimestamp = null
11
112
  }
12
113
 
13
- CharacterCount.prototype.defaults = {
14
- characterCountAttribute: 'data-maxlength',
15
- wordCountAttribute: 'data-maxwords'
16
- }
17
-
18
- // Initialize component
114
+ /**
115
+ * Initialise component
116
+ */
19
117
  CharacterCount.prototype.init = function () {
20
118
  // Check that required elements are present
21
119
  if (!this.$textarea) {
22
120
  return
23
121
  }
24
122
 
25
- // Check for module
26
- var $module = this.$module
27
123
  var $textarea = this.$textarea
28
- var $fallbackLimitMessage = document.getElementById($textarea.id + '-info')
124
+ var $textareaDescription = document.getElementById($textarea.id + '-info')
125
+
126
+ // Inject a decription for the textarea if none is present already
127
+ // for when the component was rendered with no maxlength, maxwords
128
+ // nor custom textareaDescriptionText
129
+ if ($textareaDescription.innerText.match(/^\s*$/)) {
130
+ $textareaDescription.innerText = this.i18n.t('textareaDescription', { count: this.maxLength })
131
+ }
29
132
 
30
- // Move the fallback count message to be immediately after the textarea
133
+ // Move the textarea description to be immediately after the textarea
31
134
  // Kept for backwards compatibility
32
- $textarea.insertAdjacentElement('afterend', $fallbackLimitMessage)
135
+ $textarea.insertAdjacentElement('afterend', $textareaDescription)
33
136
 
34
137
  // Create the *screen reader* specific live-updating counter
35
138
  // This doesn't need any styling classes, as it is never visible
@@ -37,36 +140,20 @@ CharacterCount.prototype.init = function () {
37
140
  $screenReaderCountMessage.className = 'govuk-character-count__sr-status govuk-visually-hidden'
38
141
  $screenReaderCountMessage.setAttribute('aria-live', 'polite')
39
142
  this.$screenReaderCountMessage = $screenReaderCountMessage
40
- $fallbackLimitMessage.insertAdjacentElement('afterend', $screenReaderCountMessage)
143
+ $textareaDescription.insertAdjacentElement('afterend', $screenReaderCountMessage)
41
144
 
42
145
  // Create our live-updating counter element, copying the classes from the
43
- // fallback element for backwards compatibility as these may have been configured
146
+ // textarea description for backwards compatibility as these may have been
147
+ // configured
44
148
  var $visibleCountMessage = document.createElement('div')
45
- $visibleCountMessage.className = $fallbackLimitMessage.className
149
+ $visibleCountMessage.className = $textareaDescription.className
46
150
  $visibleCountMessage.classList.add('govuk-character-count__status')
47
151
  $visibleCountMessage.setAttribute('aria-hidden', 'true')
48
152
  this.$visibleCountMessage = $visibleCountMessage
49
- $fallbackLimitMessage.insertAdjacentElement('afterend', $visibleCountMessage)
50
-
51
- // Hide the fallback limit message
52
- $fallbackLimitMessage.classList.add('govuk-visually-hidden')
53
-
54
- // Read options set using dataset ('data-' values)
55
- this.options = this.getDataset($module)
56
-
57
- // Determine the limit attribute (characters or words)
58
- var countAttribute = this.defaults.characterCountAttribute
59
- if (this.options.maxwords) {
60
- countAttribute = this.defaults.wordCountAttribute
61
- }
153
+ $textareaDescription.insertAdjacentElement('afterend', $visibleCountMessage)
62
154
 
63
- // Save the element limit
64
- this.maxLength = $module.getAttribute(countAttribute)
65
-
66
- // Check for limit
67
- if (!this.maxLength) {
68
- return
69
- }
155
+ // Hide the textarea description
156
+ $textareaDescription.classList.add('govuk-visually-hidden')
70
157
 
71
158
  // Remove hard limit if set
72
159
  $textarea.removeAttribute('maxlength')
@@ -74,9 +161,9 @@ CharacterCount.prototype.init = function () {
74
161
  this.bindChangeEvents()
75
162
 
76
163
  // When the page is restored after navigating 'back' in some browsers the
77
- // state of the character count is not restored until *after* the DOMContentLoaded
78
- // event is fired, so we need to manually update it after the pageshow event
79
- // in browsers that support it.
164
+ // state of the character count is not restored until *after* the
165
+ // DOMContentLoaded event is fired, so we need to manually update it after the
166
+ // pageshow event in browsers that support it.
80
167
  if ('onpageshow' in window) {
81
168
  window.addEventListener('pageshow', this.updateCountMessage.bind(this))
82
169
  } else {
@@ -85,35 +172,12 @@ CharacterCount.prototype.init = function () {
85
172
  this.updateCountMessage()
86
173
  }
87
174
 
88
- // Read data attributes
89
- CharacterCount.prototype.getDataset = function (element) {
90
- var dataset = {}
91
- var attributes = element.attributes
92
- if (attributes) {
93
- for (var i = 0; i < attributes.length; i++) {
94
- var attribute = attributes[i]
95
- var match = attribute.name.match(/^data-(.+)/)
96
- if (match) {
97
- dataset[match[1]] = attribute.value
98
- }
99
- }
100
- }
101
- return dataset
102
- }
103
-
104
- // Counts characters or words in text
105
- CharacterCount.prototype.count = function (text) {
106
- var length
107
- if (this.options.maxwords) {
108
- var tokens = text.match(/\S+/g) || [] // Matches consecutive non-whitespace chars
109
- length = tokens.length
110
- } else {
111
- length = text.length
112
- }
113
- return length
114
- }
115
-
116
- // Bind input propertychange to the elements and update based on the change
175
+ /**
176
+ * Bind change events
177
+ *
178
+ * Set up event listeners on the $textarea so that the count messages update
179
+ * when the user types.
180
+ */
117
181
  CharacterCount.prototype.bindChangeEvents = function () {
118
182
  var $textarea = this.$textarea
119
183
  $textarea.addEventListener('keyup', this.handleKeyUp.bind(this))
@@ -123,10 +187,52 @@ CharacterCount.prototype.bindChangeEvents = function () {
123
187
  $textarea.addEventListener('blur', this.handleBlur.bind(this))
124
188
  }
125
189
 
126
- // Speech recognition software such as Dragon NaturallySpeaking will modify the
127
- // fields by directly changing its `value`. These changes don't trigger events
128
- // in JavaScript, so we need to poll to handle when and if they occur.
129
- CharacterCount.prototype.checkIfValueChanged = function () {
190
+ /**
191
+ * Handle key up event
192
+ *
193
+ * Update the visible character counter and keep track of when the last update
194
+ * happened for each keypress
195
+ */
196
+ CharacterCount.prototype.handleKeyUp = function () {
197
+ this.updateVisibleCountMessage()
198
+ this.lastInputTimestamp = Date.now()
199
+ }
200
+
201
+ /**
202
+ * Handle focus event
203
+ *
204
+ * Speech recognition software such as Dragon NaturallySpeaking will modify the
205
+ * fields by directly changing its `value`. These changes don't trigger events
206
+ * in JavaScript, so we need to poll to handle when and if they occur.
207
+ *
208
+ * Once the keyup event hasn't been detected for at least 1000 ms (1s), check if
209
+ * the textarea value has changed and update the count message if it has.
210
+ *
211
+ * This is so that the update triggered by the manual comparison doesn't
212
+ * conflict with debounced KeyboardEvent updates.
213
+ */
214
+ CharacterCount.prototype.handleFocus = function () {
215
+ this.valueChecker = setInterval(function () {
216
+ if (!this.lastInputTimestamp || (Date.now() - 500) >= this.lastInputTimestamp) {
217
+ this.updateIfValueChanged()
218
+ }
219
+ }.bind(this), 1000)
220
+ }
221
+
222
+ /**
223
+ * Handle blur event
224
+ *
225
+ * Stop checking the textarea value once the textarea no longer has focus
226
+ */
227
+ CharacterCount.prototype.handleBlur = function () {
228
+ // Cancel value checking on blur
229
+ clearInterval(this.valueChecker)
230
+ }
231
+
232
+ /**
233
+ * Update count message if textarea value has changed
234
+ */
235
+ CharacterCount.prototype.updateIfValueChanged = function () {
130
236
  if (!this.$textarea.oldValue) this.$textarea.oldValue = ''
131
237
  if (this.$textarea.value !== this.$textarea.oldValue) {
132
238
  this.$textarea.oldValue = this.$textarea.value
@@ -134,14 +240,20 @@ CharacterCount.prototype.checkIfValueChanged = function () {
134
240
  }
135
241
  }
136
242
 
137
- // Helper function to update both the visible and screen reader-specific
138
- // counters simultaneously (e.g. on init)
243
+ /**
244
+ * Update count message
245
+ *
246
+ * Helper function to update both the visible and screen reader-specific
247
+ * counters simultaneously (e.g. on init)
248
+ */
139
249
  CharacterCount.prototype.updateCountMessage = function () {
140
250
  this.updateVisibleCountMessage()
141
251
  this.updateScreenReaderCountMessage()
142
252
  }
143
253
 
144
- // Update visible counter
254
+ /**
255
+ * Update visible count message
256
+ */
145
257
  CharacterCount.prototype.updateVisibleCountMessage = function () {
146
258
  var $textarea = this.$textarea
147
259
  var $visibleCountMessage = this.$visibleCountMessage
@@ -167,10 +279,12 @@ CharacterCount.prototype.updateVisibleCountMessage = function () {
167
279
  }
168
280
 
169
281
  // Update message
170
- $visibleCountMessage.innerHTML = this.formattedUpdateMessage()
282
+ $visibleCountMessage.innerText = this.getCountMessage()
171
283
  }
172
284
 
173
- // Update screen reader-specific counter
285
+ /**
286
+ * Update screen reader count message
287
+ */
174
288
  CharacterCount.prototype.updateScreenReaderCountMessage = function () {
175
289
  var $screenReaderCountMessage = this.$screenReaderCountMessage
176
290
 
@@ -183,69 +297,160 @@ CharacterCount.prototype.updateScreenReaderCountMessage = function () {
183
297
  }
184
298
 
185
299
  // Update message
186
- $screenReaderCountMessage.innerHTML = this.formattedUpdateMessage()
300
+ $screenReaderCountMessage.innerText = this.getCountMessage()
187
301
  }
188
302
 
189
- // Format update message
190
- CharacterCount.prototype.formattedUpdateMessage = function () {
191
- var $textarea = this.$textarea
192
- var options = this.options
193
- var remainingNumber = this.maxLength - this.count($textarea.value)
303
+ /**
304
+ * Count the number of characters (or words, if `config.maxwords` is set)
305
+ * in the given text
306
+ *
307
+ * @param {string} text - The text to count the characters of
308
+ * @returns {number} the number of characters (or words) in the text
309
+ */
310
+ CharacterCount.prototype.count = function (text) {
311
+ if (this.config.maxwords) {
312
+ var tokens = text.match(/\S+/g) || [] // Matches consecutive non-whitespace chars
313
+ return tokens.length
314
+ } else {
315
+ return text.length
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Get count message
321
+ *
322
+ * @returns {string} Status message
323
+ */
324
+ CharacterCount.prototype.getCountMessage = function () {
325
+ var remainingNumber = this.maxLength - this.count(this.$textarea.value)
194
326
 
195
- var charVerb = 'remaining'
196
- var charNoun = 'character'
197
- var displayNumber = remainingNumber
198
- if (options.maxwords) {
199
- charNoun = 'word'
327
+ var countType = this.config.maxwords ? 'words' : 'characters'
328
+ return this.formatCountMessage(remainingNumber, countType)
329
+ }
330
+
331
+ /**
332
+ * Formats the message shown to users according to what's counted
333
+ * and how many remain
334
+ *
335
+ * @param {number} remainingNumber - The number of words/characaters remaining
336
+ * @param {string} countType - "words" or "characters"
337
+ * @returns {string} Status message
338
+ */
339
+ CharacterCount.prototype.formatCountMessage = function (remainingNumber, countType) {
340
+ if (remainingNumber === 0) {
341
+ return this.i18n.t(countType + 'AtLimit')
200
342
  }
201
- charNoun = charNoun + ((remainingNumber === -1 || remainingNumber === 1) ? '' : 's')
202
343
 
203
- charVerb = (remainingNumber < 0) ? 'too many' : 'remaining'
204
- displayNumber = Math.abs(remainingNumber)
344
+ var translationKeySuffix = remainingNumber < 0 ? 'OverLimit' : 'UnderLimit'
205
345
 
206
- return 'You have ' + displayNumber + ' ' + charNoun + ' ' + charVerb
346
+ return this.i18n.t(countType + translationKeySuffix, { count: Math.abs(remainingNumber) })
207
347
  }
208
348
 
209
- // Checks whether the value is over the configured threshold for the input.
210
- // If there is no configured threshold, it is set to 0 and this function will
211
- // always return true.
349
+ /**
350
+ * Check if count is over threshold
351
+ *
352
+ * Checks whether the value is over the configured threshold for the input.
353
+ * If there is no configured threshold, it is set to 0 and this function will
354
+ * always return true.
355
+ *
356
+ * @returns {boolean} true if the current count is over the config.threshold
357
+ * (or no threshold is set)
358
+ */
212
359
  CharacterCount.prototype.isOverThreshold = function () {
360
+ // No threshold means we're always above threshold so save some computation
361
+ if (!this.config.threshold) {
362
+ return true
363
+ }
364
+
213
365
  var $textarea = this.$textarea
214
- var options = this.options
215
366
 
216
367
  // Determine the remaining number of characters/words
217
368
  var currentLength = this.count($textarea.value)
218
369
  var maxLength = this.maxLength
219
370
 
220
- // Set threshold if presented in options
221
- var thresholdPercent = options.threshold ? options.threshold : 0
222
- var thresholdValue = maxLength * thresholdPercent / 100
371
+ var thresholdValue = maxLength * this.config.threshold / 100
223
372
 
224
373
  return (thresholdValue <= currentLength)
225
374
  }
226
375
 
227
- // Update the visible character counter and keep track of when the last update
228
- // happened for each keypress
229
- CharacterCount.prototype.handleKeyUp = function () {
230
- this.updateVisibleCountMessage()
231
- this.lastInputTimestamp = Date.now()
232
- }
233
-
234
- CharacterCount.prototype.handleFocus = function () {
235
- // If the field is focused, and a keyup event hasn't been detected for at
236
- // least 1000 ms (1 second), then run the manual change check.
237
- // This is so that the update triggered by the manual comparison doesn't
238
- // conflict with debounced KeyboardEvent updates.
239
- this.valueChecker = setInterval(function () {
240
- if (!this.lastInputTimestamp || (Date.now() - 500) >= this.lastInputTimestamp) {
241
- this.checkIfValueChanged()
242
- }
243
- }.bind(this), 1000)
244
- }
245
-
246
- CharacterCount.prototype.handleBlur = function () {
247
- // Cancel value checking on blur
248
- clearInterval(this.valueChecker)
249
- }
250
-
251
376
  export default CharacterCount
377
+
378
+ /**
379
+ * Character count config
380
+ *
381
+ * @typedef {CharacterCountConfigWithMaxLength | CharacterCountConfigWithMaxWords} CharacterCountConfig
382
+ */
383
+
384
+ /**
385
+ * Character count config (with maximum number of characters)
386
+ *
387
+ * @typedef {object} CharacterCountConfigWithMaxLength
388
+ * @property {number} [maxlength] - The maximum number of characters.
389
+ * If maxwords is provided, the maxlength option will be ignored.
390
+ * @property {number} [threshold = 0] - The percentage value of the limit at
391
+ * which point the count message is displayed. If this attribute is set, the
392
+ * count message will be hidden by default.
393
+ * @property {CharacterCountTranslations} [i18n = CHARACTER_COUNT_TRANSLATIONS] - See constant {@link CHARACTER_COUNT_TRANSLATIONS}
394
+ */
395
+
396
+ /**
397
+ * Character count config (with maximum number of words)
398
+ *
399
+ * @typedef {object} CharacterCountConfigWithMaxWords
400
+ * @property {number} [maxwords] - The maximum number of words. If maxwords is
401
+ * provided, the maxlength option will be ignored.
402
+ * @property {number} [threshold = 0] - The percentage value of the limit at
403
+ * which point the count message is displayed. If this attribute is set, the
404
+ * count message will be hidden by default.
405
+ * @property {CharacterCountTranslations} [i18n = CHARACTER_COUNT_TRANSLATIONS] - See constant {@link CHARACTER_COUNT_TRANSLATIONS}
406
+ */
407
+
408
+ /**
409
+ * Character count translations
410
+ *
411
+ * @typedef {object} CharacterCountTranslations
412
+ *
413
+ * Messages shown to users as they type. It provides feedback on how many words
414
+ * or characters they have remaining or if they are over the limit. This also
415
+ * includes a message used as an accessible description for the textarea.
416
+ * @property {TranslationPluralForms} [charactersUnderLimit] - Message displayed
417
+ * when the number of characters is under the configured maximum, `maxlength`.
418
+ * This message is displayed visually and through assistive technologies. The
419
+ * component will replace the `%{count}` placeholder with the number of
420
+ * remaining characters. This is a [pluralised list of
421
+ * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).
422
+ * @property {string} [charactersAtLimit] - Message displayed when the number of
423
+ * characters reaches the configured maximum, `maxlength`. This message is
424
+ * displayed visually and through assistive technologies.
425
+ * @property {TranslationPluralForms} [charactersOverLimit] - Message displayed
426
+ * when the number of characters is over the configured maximum, `maxlength`.
427
+ * This message is displayed visually and through assistive technologies. The
428
+ * component will replace the `%{count}` placeholder with the number of
429
+ * remaining characters. This is a [pluralised list of
430
+ * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).
431
+ * @property {TranslationPluralForms} [wordsUnderLimit] - Message displayed when
432
+ * the number of words is under the configured maximum, `maxlength`. This
433
+ * message is displayed visually and through assistive technologies. The
434
+ * component will replace the `%{count}` placeholder with the number of
435
+ * remaining words. This is a [pluralised list of
436
+ * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).
437
+ * @property {string} [wordsAtLimit] - Message displayed when the number of
438
+ * words reaches the configured maximum, `maxlength`. This message is
439
+ * displayed visually and through assistive technologies.
440
+ * @property {TranslationPluralForms} [wordsOverLimit] - Message displayed when
441
+ * the number of words is over the configured maximum, `maxlength`. This
442
+ * message is displayed visually and through assistive technologies. The
443
+ * component will replace the `%{count}` placeholder with the number of
444
+ * remaining words. This is a [pluralised list of
445
+ * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).
446
+ * @property {TranslationPluralForms} [textareaDescription] - Message made
447
+ * available to assistive technologies, if none is already present in the
448
+ * HTML, to describe that the component accepts only a limited amount of
449
+ * content. It is visible on the page when JavaScript is unavailable. The
450
+ * component will replace the `%{count}` placeholder with the value of the
451
+ * `maxlength` or `maxwords` parameter.
452
+ */
453
+
454
+ /**
455
+ * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
456
+ */