defra_ruby_template 6.4.0 → 6.6.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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +73 -19
  3. data/Rakefile +10 -33
  4. data/lib/defra_ruby_template/version.rb +1 -1
  5. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +202 -137
  6. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
  7. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +202 -137
  8. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
  9. data/node_modules/govuk-frontend/dist/govuk/common/closest-attribute-value.mjs.map +1 -1
  10. data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +5 -1
  11. data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs.map +1 -1
  12. data/node_modules/govuk-frontend/dist/govuk/common/create-element.mjs +13 -0
  13. data/node_modules/govuk-frontend/dist/govuk/common/create-element.mjs.map +1 -0
  14. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
  15. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs.map +1 -1
  16. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
  17. data/node_modules/govuk-frontend/dist/govuk/component.mjs +2 -1
  18. data/node_modules/govuk-frontend/dist/govuk/component.mjs.map +1 -1
  19. data/node_modules/govuk-frontend/dist/govuk/components/_index.import.scss +2 -0
  20. data/node_modules/govuk-frontend/dist/govuk/components/_index.scss +2 -0
  21. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +87 -62
  22. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js.map +1 -1
  23. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +87 -62
  24. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs.map +1 -1
  25. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +60 -56
  26. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
  27. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +17 -6
  28. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js.map +1 -1
  29. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +17 -6
  30. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs.map +1 -1
  31. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
  32. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +90 -32
  33. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js.map +1 -1
  34. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +90 -32
  35. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs.map +1 -1
  36. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +64 -27
  37. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs.map +1 -1
  38. data/node_modules/govuk-frontend/dist/govuk/components/character-count/fixtures.json +173 -6
  39. data/node_modules/govuk-frontend/dist/govuk/components/character-count/macro-options.json +13 -6
  40. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-characters-and-error-message.html +12 -0
  41. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-characters-and-threshold.html +9 -0
  42. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-characters-and-value.html +9 -0
  43. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-characters.html +9 -0
  44. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-length.html +9 -0
  45. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-words-and-error-message.html +12 -0
  46. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-words-and-threshold.html +9 -0
  47. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-words-and-value.html +9 -0
  48. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-count-type-words.html +9 -0
  49. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-maxwords.html +9 -0
  50. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template.njk +10 -3
  51. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +12 -5
  52. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js.map +1 -1
  53. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +12 -5
  54. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
  55. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs.map +1 -1
  56. data/node_modules/govuk-frontend/dist/govuk/components/cookie-banner/_mixin.scss +6 -0
  57. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +17 -6
  58. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js.map +1 -1
  59. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +17 -6
  60. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs.map +1 -1
  61. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
  62. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +43 -18
  63. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js.map +1 -1
  64. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +43 -18
  65. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs.map +1 -1
  66. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +16 -12
  67. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs.map +1 -1
  68. data/node_modules/govuk-frontend/dist/govuk/components/feedback/README.md +15 -0
  69. data/node_modules/govuk-frontend/dist/govuk/components/feedback/_feedback.import.scss +6 -0
  70. data/node_modules/govuk-frontend/dist/govuk/components/feedback/_index.import.scss +8 -0
  71. data/node_modules/govuk-frontend/dist/govuk/components/feedback/_index.scss +5 -0
  72. data/node_modules/govuk-frontend/dist/govuk/components/feedback/_mixin.scss +48 -0
  73. data/node_modules/govuk-frontend/dist/govuk/components/feedback/fixtures.json +95 -0
  74. data/node_modules/govuk-frontend/dist/govuk/components/feedback/macro-options.json +50 -0
  75. data/node_modules/govuk-frontend/dist/govuk/components/feedback/macro.njk +3 -0
  76. data/node_modules/govuk-frontend/dist/govuk/components/feedback/template-default.html +12 -0
  77. data/node_modules/govuk-frontend/dist/govuk/components/feedback/template-silly-example.html +19 -0
  78. data/node_modules/govuk-frontend/dist/govuk/components/feedback/template.njk +24 -0
  79. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js +54 -30
  80. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js.map +1 -1
  81. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs +54 -30
  82. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs.map +1 -1
  83. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs +27 -24
  84. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs.map +1 -1
  85. data/node_modules/govuk-frontend/dist/govuk/components/footer/_mixin.scss +6 -0
  86. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/README.md +15 -0
  87. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/_index.import.scss +8 -0
  88. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/_index.scss +6 -0
  89. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/_language-navigation.import.scss +6 -0
  90. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/_mixin.scss +68 -0
  91. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/fixtures.json +482 -0
  92. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/macro-options.json +88 -0
  93. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/macro.njk +3 -0
  94. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/template-default.html +12 -0
  95. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/template-inverse.html +12 -0
  96. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/template-with-language-description.html +12 -0
  97. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/template-with-large-amount-of-multiple-languages.html +99 -0
  98. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/template-with-mixed-text-directions.html +12 -0
  99. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/template-with-multiple-languages.html +24 -0
  100. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/template-with-translated-navigation-label.html +12 -0
  101. data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/template.njk +33 -0
  102. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +17 -6
  103. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js.map +1 -1
  104. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +17 -6
  105. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs.map +1 -1
  106. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
  107. data/node_modules/govuk-frontend/dist/govuk/components/panel/fixtures.json +13 -11
  108. data/node_modules/govuk-frontend/dist/govuk/components/panel/template-interruption-with-headings-content-and-lists.html +6 -1
  109. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +32 -9
  110. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js.map +1 -1
  111. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +32 -9
  112. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs.map +1 -1
  113. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +5 -3
  114. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
  115. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +12 -5
  116. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js.map +1 -1
  117. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +12 -5
  118. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
  119. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs.map +1 -1
  120. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_mixin.scss +48 -3
  121. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json +121 -0
  122. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro-options.json +20 -0
  123. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +12 -5
  124. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -1
  125. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +12 -5
  126. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -1
  127. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs.map +1 -1
  128. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-inverse-with-language-navigation.html +72 -0
  129. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-inline-end-slot.html +33 -0
  130. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-language-navigation.html +62 -0
  131. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-right-aligned-language-navigation.html +62 -0
  132. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template.njk +8 -3
  133. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +14 -6
  134. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js.map +1 -1
  135. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +14 -6
  136. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs.map +1 -1
  137. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +2 -1
  138. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs.map +1 -1
  139. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +12 -5
  140. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js.map +1 -1
  141. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +12 -5
  142. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
  143. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs.map +1 -1
  144. data/node_modules/govuk-frontend/dist/govuk/custom-properties/_frontend-version.mixin.scss +1 -1
  145. data/node_modules/govuk-frontend/dist/govuk/custom-properties/_functional-colours.mixin.scss +1 -0
  146. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +8 -5
  147. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs.map +1 -1
  148. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +2 -2
  149. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css.map +1 -1
  150. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
  151. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map +1 -1
  152. data/node_modules/govuk-frontend/dist/govuk/helpers/_colour.scss +1 -1
  153. data/node_modules/govuk-frontend/dist/govuk/i18n.mjs.map +1 -1
  154. data/node_modules/govuk-frontend/dist/govuk/init.mjs +8 -8
  155. data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
  156. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +16 -2
  157. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +9 -1
  158. data/node_modules/govuk-frontend/package.json +9 -7
  159. data/vendor/assets/javascripts/defra_ruby_template.js +202 -137
  160. data/vendor/assets/stylesheets/components/_index.import.scss +2 -0
  161. data/vendor/assets/stylesheets/components/_index.scss +2 -0
  162. data/vendor/assets/stylesheets/components/cookie-banner/_mixin.scss +6 -0
  163. data/vendor/assets/stylesheets/components/feedback/_feedback.import.scss +6 -0
  164. data/vendor/assets/stylesheets/components/feedback/_index.import.scss +8 -0
  165. data/vendor/assets/stylesheets/components/feedback/_index.scss +5 -0
  166. data/vendor/assets/stylesheets/components/feedback/_mixin.scss +48 -0
  167. data/vendor/assets/stylesheets/components/footer/_mixin.scss +6 -0
  168. data/vendor/assets/stylesheets/components/language-navigation/_index.import.scss +8 -0
  169. data/vendor/assets/stylesheets/components/language-navigation/_index.scss +6 -0
  170. data/vendor/assets/stylesheets/components/language-navigation/_language-navigation.import.scss +6 -0
  171. data/vendor/assets/stylesheets/components/language-navigation/_mixin.scss +68 -0
  172. data/vendor/assets/stylesheets/components/service-navigation/_mixin.scss +48 -3
  173. data/vendor/assets/stylesheets/custom-properties/_frontend-version.mixin.scss +1 -1
  174. data/vendor/assets/stylesheets/custom-properties/_functional-colours.mixin.scss +1 -0
  175. data/vendor/assets/stylesheets/defra_ruby_template.scss +8 -30
  176. data/vendor/assets/stylesheets/govuk-frontend.min.css +2 -2
  177. data/vendor/assets/stylesheets/helpers/_colour.scss +1 -1
  178. data/vendor/assets/stylesheets/settings/_colours-organisations.scss +16 -2
  179. metadata +53 -3
  180. data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-word-count.html +0 -9
@@ -1 +1 @@
1
- {"version":3,"file":"character-count.mjs","sources":["../../../../src/govuk/components/character-count/character-count.mjs"],"sourcesContent":["import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'\nimport {\n validateConfig,\n ConfigurableComponent,\n configOverride\n} from '../../common/configuration.mjs'\nimport { formatErrorMessage } from '../../common/index.mjs'\nimport { ConfigError, ElementError } from '../../errors/index.mjs'\nimport { I18n } from '../../i18n.mjs'\n\n/**\n * Character count component\n *\n * Tracks the number of characters or words in the `.govuk-js-character-count`\n * `<textarea>` inside the element. Displays a message with the remaining number\n * of characters/words available, or the number of characters/words in excess.\n *\n * You can configure the message to only appear after a certain percentage\n * of the available characters/words has been entered.\n *\n * @preserve\n * @augments ConfigurableComponent<CharacterCountConfig>\n */\nexport class CharacterCount extends ConfigurableComponent {\n /** @private */\n $textarea\n\n /** @private */\n count = 0\n\n /** @private */\n $visibleCountMessage\n\n /** @private */\n $screenReaderCountMessage\n\n /**\n * @private\n * @type {number | null}\n */\n lastInputTimestamp = null\n\n /** @private */\n lastInputValue = ''\n\n /**\n * @private\n * @type {number | null}\n */\n valueChecker = null\n\n /** @private */\n i18n\n\n /** @private */\n maxLength;\n\n /**\n * Character count config override\n *\n * To ensure data-attributes take complete precedence, even if they change\n * the type of count, we need to reset the `maxlength` and `maxwords` from\n * the JavaScript config.\n *\n * @internal\n * @param {CharacterCountConfig} datasetConfig - configuration specified by dataset\n * @returns {CharacterCountConfig} - configuration to override by dataset\n */\n [configOverride](datasetConfig) {\n let configOverrides = {}\n if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {\n configOverrides = {\n maxlength: undefined,\n maxwords: undefined\n }\n }\n\n return configOverrides\n }\n\n /**\n * @param {Element | null} $root - HTML element to use for character count\n * @param {CharacterCountConfig} [config] - Character count config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $textarea = this.$root.querySelector('.govuk-js-character-count')\n if (\n !(\n $textarea instanceof HTMLTextAreaElement ||\n $textarea instanceof HTMLInputElement\n )\n ) {\n throw new ElementError({\n component: CharacterCount,\n element: $textarea,\n expectedType: 'HTMLTextareaElement or HTMLInputElement',\n identifier: 'Form field (`.govuk-js-character-count`)'\n })\n }\n\n // Check for valid config\n const errors = validateConfig(CharacterCount.schema, this.config)\n if (errors[0]) {\n throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]))\n }\n\n this.i18n = new I18n(this.config.i18n, {\n // Read the fallback if necessary rather than have it set in the defaults\n locale: closestAttributeValue(this.$root, 'lang')\n })\n\n // Determine the limit attribute (characters or words)\n this.maxLength = this.config.maxwords ?? this.config.maxlength ?? Infinity\n\n this.$textarea = $textarea\n\n const textareaDescriptionId = `${this.$textarea.id}-info`\n const $textareaDescription = document.getElementById(textareaDescriptionId)\n if (!$textareaDescription) {\n throw new ElementError({\n component: CharacterCount,\n element: $textareaDescription,\n identifier: `Count message (\\`id=\"${textareaDescriptionId}\"\\`)`\n })\n }\n\n // Pre-existing validation error rendered from server\n this.$errorMessage = this.$root.querySelector('.govuk-error-message')\n\n // Inject a description for the textarea if none is present already\n // for when the component was rendered with no maxlength, maxwords\n // nor custom textareaDescriptionText\n // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec\n if ($textareaDescription.textContent.match(/^\\s*$/)) {\n $textareaDescription.textContent = this.i18n.t('textareaDescription', {\n count: this.maxLength\n })\n }\n\n // Move the textarea description to be immediately after the textarea\n // Kept for backwards compatibility\n this.$textarea.insertAdjacentElement('afterend', $textareaDescription)\n\n // Create the *screen reader* specific live-updating counter\n // This doesn't need any styling classes, as it is never visible\n const $screenReaderCountMessage = document.createElement('div')\n $screenReaderCountMessage.className =\n 'govuk-character-count__sr-status govuk-visually-hidden'\n $screenReaderCountMessage.setAttribute('aria-live', 'polite')\n this.$screenReaderCountMessage = $screenReaderCountMessage\n $textareaDescription.insertAdjacentElement(\n 'afterend',\n $screenReaderCountMessage\n )\n\n // Create our live-updating counter element, copying the classes from the\n // textarea description for backwards compatibility as these may have been\n // configured\n const $visibleCountMessage = document.createElement('div')\n $visibleCountMessage.className = $textareaDescription.className\n $visibleCountMessage.classList.add('govuk-character-count__status')\n $visibleCountMessage.setAttribute('aria-hidden', 'true')\n this.$visibleCountMessage = $visibleCountMessage\n $textareaDescription.insertAdjacentElement('afterend', $visibleCountMessage)\n\n // Hide the textarea description\n $textareaDescription.classList.add('govuk-visually-hidden')\n\n // Remove hard limit if set\n this.$textarea.removeAttribute('maxlength')\n\n this.bindChangeEvents()\n\n // When the page is restored after navigating 'back' in some browsers the\n // state of form controls is not restored until *after* the DOMContentLoaded\n // event is fired, so we need to sync after the pageshow event.\n window.addEventListener('pageshow', () => {\n // If the current value of the textarea is the same as what's\n // in the HTML, don't re-run when users have not edited the field yet\n // (new page load or BF cache navigation without having edited).\n if (this.$textarea.value !== this.$textarea.textContent) {\n this.updateCount()\n this.updateCountMessage()\n }\n })\n\n // Although we've set up handlers to sync state on the pageshow event, init\n // could be called after those events have fired, for example if they are\n // added to the page dynamically, so update now too.\n this.updateCount()\n this.updateCountMessage()\n }\n\n /**\n * Bind change events\n *\n * Set up event listeners on the $textarea so that the count messages update\n * when the user types.\n *\n * @private\n */\n bindChangeEvents() {\n this.$textarea.addEventListener('input', () => this.handleInput())\n\n // Bind focus/blur events to start/stop polling\n this.$textarea.addEventListener('focus', () => this.handleFocus())\n this.$textarea.addEventListener('blur', () => this.handleBlur())\n }\n\n /**\n * Handle input event\n *\n * Update the visible character counter and keep track of when the last update\n * happened for each keypress\n *\n * @private\n */\n handleInput() {\n this.updateCount()\n this.updateVisibleCountMessage()\n this.lastInputTimestamp = Date.now()\n }\n\n /**\n * Handle focus event\n *\n * Speech recognition software such as Dragon NaturallySpeaking will modify\n * the fields by directly changing its `value`. These changes don't trigger\n * events in JavaScript, so we need to poll to handle when and if they occur.\n *\n * Once the keyup event hasn't been detected for at least 1000 ms (1s), check\n * if the textarea value has changed and update the count message if it has.\n *\n * This is so that the update triggered by the manual comparison doesn't\n * conflict with debounced KeyboardEvent updates.\n *\n * @private\n */\n handleFocus() {\n this.valueChecker = window.setInterval(() => {\n if (\n !this.lastInputTimestamp ||\n Date.now() - 500 >= this.lastInputTimestamp\n ) {\n this.updateIfValueChanged()\n }\n }, 1000)\n }\n\n /**\n * Handle blur event\n *\n * Stop checking the textarea value once the textarea no longer has focus\n *\n * @private\n */\n handleBlur() {\n // Cancel value checking on blur\n if (this.valueChecker) {\n window.clearInterval(this.valueChecker)\n }\n }\n\n /**\n * Update count message if textarea value has changed\n *\n * @private\n */\n updateIfValueChanged() {\n if (this.$textarea.value !== this.lastInputValue) {\n this.lastInputValue = this.$textarea.value\n this.updateCountMessage()\n }\n }\n\n /**\n * Update count message\n *\n * Helper function to update both the visible and screen reader-specific\n * counters simultaneously (e.g. on init)\n *\n * @private\n */\n updateCountMessage() {\n this.updateVisibleCountMessage()\n this.updateScreenReaderCountMessage()\n }\n\n /**\n * Update visible count message\n *\n * @private\n */\n updateVisibleCountMessage() {\n const remainingNumber = this.maxLength - this.count\n const isError = remainingNumber < 0\n\n // If input is over the threshold, remove the disabled class which renders\n // the counter invisible.\n this.$visibleCountMessage.classList.toggle(\n 'govuk-character-count__message--disabled',\n !this.isOverThreshold()\n )\n\n // Update styles\n if (!this.$errorMessage) {\n // Only toggle the textarea error class if there isn't an error message\n // already, as it may be unrelated to the limit (eg: allowed characters)\n // and would set the border colour back to black.\n this.$textarea.classList.toggle('govuk-textarea--error', isError)\n }\n this.$visibleCountMessage.classList.toggle('govuk-error-message', isError)\n this.$visibleCountMessage.classList.toggle('govuk-hint', !isError)\n\n // Update message\n this.$visibleCountMessage.textContent = this.getCountMessage()\n }\n\n /**\n * Update screen reader count message\n *\n * @private\n */\n updateScreenReaderCountMessage() {\n // If over the threshold, remove the aria-hidden attribute, allowing screen\n // readers to announce the content of the element.\n if (this.isOverThreshold()) {\n this.$screenReaderCountMessage.removeAttribute('aria-hidden')\n } else {\n this.$screenReaderCountMessage.setAttribute('aria-hidden', 'true')\n }\n\n // Update message\n this.$screenReaderCountMessage.textContent = this.getCountMessage()\n }\n\n /**\n * Count the number of characters (or words, if `config.maxwords` is set)\n * in the given text, and update the component-wide count\n *\n * @private\n */\n updateCount() {\n const text = this.$textarea.value\n\n if (this.config.maxwords) {\n const tokens = text.match(/\\S+/g) ?? [] // Matches consecutive non-whitespace chars\n this.count = tokens.length\n return\n }\n\n this.count = text.length\n }\n\n /**\n * Get count message\n *\n * @private\n * @returns {string} Status message\n */\n getCountMessage() {\n const remainingNumber = this.maxLength - this.count\n const countType = this.config.maxwords ? 'words' : 'characters'\n return this.formatCountMessage(remainingNumber, countType)\n }\n\n /**\n * Formats the message shown to users according to what's counted\n * and how many remain\n *\n * @private\n * @param {number} remainingNumber - The number of words/characaters remaining\n * @param {string} countType - \"words\" or \"characters\"\n * @returns {string} Status message\n */\n formatCountMessage(remainingNumber, countType) {\n if (remainingNumber === 0) {\n return this.i18n.t(`${countType}AtLimit`)\n }\n\n const translationKeySuffix =\n remainingNumber < 0 ? 'OverLimit' : 'UnderLimit'\n\n return this.i18n.t(`${countType}${translationKeySuffix}`, {\n count: Math.abs(remainingNumber)\n })\n }\n\n /**\n * Check if count is over threshold\n *\n * Checks whether the value is over the configured threshold for the input.\n * If there is no configured threshold, it is set to 0 and this function will\n * always return true.\n *\n * @private\n * @returns {boolean} true if the current count is over the config.threshold\n * (or no threshold is set)\n */\n isOverThreshold() {\n // No threshold means we're always above threshold so save some computation\n if (!this.config.threshold) {\n return true\n }\n\n // Determine the remaining number of characters/words\n const currentLength = this.count\n const maxLength = this.maxLength\n\n const thresholdValue = (maxLength * this.config.threshold) / 100\n\n return thresholdValue <= currentLength\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-character-count'\n\n /**\n * Character count default config\n *\n * @see {@link CharacterCountConfig}\n * @constant\n * @type {CharacterCountConfig}\n */\n static defaults = Object.freeze({\n threshold: 0,\n i18n: {\n // Characters\n charactersUnderLimit: {\n one: 'You have %{count} character remaining',\n other: 'You have %{count} characters remaining'\n },\n charactersAtLimit: 'You have 0 characters remaining',\n charactersOverLimit: {\n one: 'You have %{count} character too many',\n other: 'You have %{count} characters too many'\n },\n // Words\n wordsUnderLimit: {\n one: 'You have %{count} word remaining',\n other: 'You have %{count} words remaining'\n },\n wordsAtLimit: 'You have 0 words remaining',\n wordsOverLimit: {\n one: 'You have %{count} word too many',\n other: 'You have %{count} words too many'\n },\n textareaDescription: {\n other: ''\n }\n }\n })\n\n /**\n * Character count config schema\n *\n * @constant\n * @satisfies {Schema<CharacterCountConfig>}\n */\n static schema = Object.freeze({\n properties: {\n i18n: { type: 'object' },\n maxwords: { type: 'number' },\n maxlength: { type: 'number' },\n threshold: { type: 'number' }\n },\n anyOf: [\n {\n required: ['maxwords'],\n errorMessage: 'Either \"maxlength\" or \"maxwords\" must be provided'\n },\n {\n required: ['maxlength'],\n errorMessage: 'Either \"maxlength\" or \"maxwords\" must be provided'\n }\n ]\n })\n}\n\n/**\n * Character count config\n *\n * @see {@link CharacterCount.defaults}\n * @typedef {object} CharacterCountConfig\n * @property {number} [maxlength] - The maximum number of characters.\n * If maxwords is provided, the maxlength option will be ignored.\n * @property {number} [maxwords] - The maximum number of words. If maxwords is\n * provided, the maxlength option will be ignored.\n * @property {number} [threshold=0] - The percentage value of the limit at\n * which point the count message is displayed. If this attribute is set, the\n * count message will be hidden by default.\n * @property {CharacterCountTranslations} [i18n=CharacterCount.defaults.i18n] - Character count translations\n */\n\n/**\n * Character count translations\n *\n * @see {@link CharacterCount.defaults.i18n}\n * @typedef {object} CharacterCountTranslations\n *\n * Messages shown to users as they type. It provides feedback on how many words\n * or characters they have remaining or if they are over the limit. This also\n * includes a message used as an accessible description for the textarea.\n * @property {TranslationPluralForms} [charactersUnderLimit] - Message displayed\n * when the number of characters is under the configured maximum, `maxlength`.\n * This message is displayed visually and through assistive technologies. The\n * component will replace the `%{count}` placeholder with the number of\n * remaining characters. This is a [pluralised list of\n * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {string} [charactersAtLimit] - Message displayed when the number of\n * characters reaches the configured maximum, `maxlength`. This message is\n * displayed visually and through assistive technologies.\n * @property {TranslationPluralForms} [charactersOverLimit] - Message displayed\n * when the number of characters is over the configured maximum, `maxlength`.\n * This message is displayed visually and through assistive technologies. The\n * component will replace the `%{count}` placeholder with the number of\n * remaining characters. This is a [pluralised list of\n * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {TranslationPluralForms} [wordsUnderLimit] - Message displayed when\n * the number of words is under the configured maximum, `maxlength`. This\n * message is displayed visually and through assistive technologies. The\n * component will replace the `%{count}` placeholder with the number of\n * remaining words. This is a [pluralised list of\n * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {string} [wordsAtLimit] - Message displayed when the number of\n * words reaches the configured maximum, `maxlength`. This message is\n * displayed visually and through assistive technologies.\n * @property {TranslationPluralForms} [wordsOverLimit] - Message displayed when\n * the number of words is over the configured maximum, `maxlength`. This\n * message is displayed visually and through assistive technologies. The\n * component will replace the `%{count}` placeholder with the number of\n * remaining words. This is a [pluralised list of\n * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {TranslationPluralForms} [textareaDescription] - Message made\n * available to assistive technologies, if none is already present in the\n * HTML, to describe that the component accepts only a limited amount of\n * content. It is visible on the page when JavaScript is unavailable. The\n * component will replace the `%{count}` placeholder with the value of the\n * `maxlength` or `maxwords` parameter.\n */\n\n/**\n * @import { Schema } from '../../common/configuration.mjs'\n * @import { TranslationPluralForms } from '../../i18n.mjs'\n */\n"],"names":["CharacterCount","ConfigurableComponent","configOverride","datasetConfig","configOverrides","maxlength","undefined","maxwords","constructor","$root","config","_ref","_this$config$maxwords","$textarea","count","$visibleCountMessage","$screenReaderCountMessage","lastInputTimestamp","lastInputValue","valueChecker","i18n","maxLength","querySelector","HTMLTextAreaElement","HTMLInputElement","ElementError","component","element","expectedType","identifier","errors","validateConfig","schema","ConfigError","formatErrorMessage","I18n","locale","closestAttributeValue","Infinity","textareaDescriptionId","id","$textareaDescription","document","getElementById","$errorMessage","textContent","match","t","insertAdjacentElement","createElement","className","setAttribute","classList","add","removeAttribute","bindChangeEvents","window","addEventListener","value","updateCount","updateCountMessage","handleInput","handleFocus","handleBlur","updateVisibleCountMessage","Date","now","setInterval","updateIfValueChanged","clearInterval","updateScreenReaderCountMessage","remainingNumber","isError","toggle","isOverThreshold","getCountMessage","text","_text$match","tokens","length","countType","formatCountMessage","translationKeySuffix","Math","abs","threshold","currentLength","thresholdValue","moduleName","defaults","Object","freeze","charactersUnderLimit","one","other","charactersAtLimit","charactersOverLimit","wordsUnderLimit","wordsAtLimit","wordsOverLimit","textareaDescription","properties","type","anyOf","required","errorMessage"],"mappings":"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"}
1
+ {"version":3,"file":"character-count.mjs","sources":["../../../../src/govuk/components/character-count/character-count.mjs"],"sourcesContent":["import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'\nimport {\n validateConfig,\n ConfigurableComponent,\n configOverride\n} from '../../common/configuration.mjs'\nimport { createElement } from '../../common/create-element.mjs'\nimport { formatErrorMessage } from '../../common/index.mjs'\nimport { ConfigError, ElementError, SupportError } from '../../errors/index.mjs'\nimport { I18n } from '../../i18n.mjs'\n\n/**\n * Character count component\n *\n * Tracks the number of characters or words in the `.govuk-js-character-count`\n * `<textarea>` inside the element. Displays a message with the remaining number\n * of characters/words available, or the number of characters/words in excess.\n *\n * You can configure the message to only appear after a certain percentage\n * of the available characters/words has been entered.\n *\n * @preserve\n * @augments ConfigurableComponent<CharacterCountConfig>\n */\nexport class CharacterCount extends ConfigurableComponent {\n /** @private */\n $textarea\n\n /** @private */\n count = 0\n\n /**\n * @type {Intl.Segmenter | null}\n */\n segmenter = null\n\n /** @private */\n $visibleCountMessage\n\n /** @private */\n $screenReaderCountMessage\n\n /**\n * @private\n * @type {number | null}\n */\n lastInputTimestamp = null\n\n /** @private */\n lastInputValue = ''\n\n /**\n * @private\n * @type {number | null}\n */\n valueChecker = null\n\n /** @private */\n i18n\n\n /** @private */\n maxLength;\n\n /**\n * Character count config override\n *\n * @internal\n * @param {Partial<CharacterCountConfig>} datasetConfig - configuration specified by dataset\n * @returns {Partial<CharacterCountConfig>} - configuration to override by dataset\n */\n [configOverride](datasetConfig) {\n let configOverrides = /** @type {Partial<CharacterCountConfig>} */ ({})\n\n // To ensure data-attributes take complete precedence, even if they change\n // the type of count, we need to reset the `maxlength` and `maxwords` from\n // the JavaScript config\n if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {\n configOverrides = {\n maxlength: undefined,\n maxwords: undefined\n }\n }\n\n if ('maxwords' in datasetConfig || this.config.maxwords !== undefined) {\n console.warn(\n formatErrorMessage(\n CharacterCount,\n 'Option `maxwords` is deprecated. Use `maxlength` with `countType: \"words\"` instead.'\n )\n )\n\n if (!('maxlength' in datasetConfig)) {\n configOverrides.maxlength =\n datasetConfig.maxwords ?? this.config.maxwords\n configOverrides.countType = 'words'\n }\n }\n\n return configOverrides\n }\n\n /**\n * @param {Element | null} $root - HTML element to use for character count\n * @param {CharacterCountConfig} [config] - Character count config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $textarea = this.$root.querySelector('.govuk-js-character-count')\n if (\n !(\n $textarea instanceof HTMLTextAreaElement ||\n $textarea instanceof HTMLInputElement\n )\n ) {\n throw new ElementError({\n component: CharacterCount,\n element: $textarea,\n expectedType: 'HTMLTextareaElement or HTMLInputElement',\n identifier: 'Form field (`.govuk-js-character-count`)'\n })\n }\n\n // Check for valid config\n const errors = validateConfig(CharacterCount.schema, this.config)\n if (errors[0]) {\n throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]))\n }\n\n this.i18n = new I18n(this.config.i18n, {\n // Read the fallback if necessary rather than have it set in the defaults\n locale: closestAttributeValue(this.$root, 'lang')\n })\n\n if (\n this.config.countType === 'characters' ||\n (this.config.countType === 'words' && this.config.maxwords === undefined)\n ) {\n if (!('Segmenter' in Intl)) {\n throw new SupportError(\n formatErrorMessage(\n CharacterCount,\n 'Support for \"Intl.Segmenter\" required'\n )\n )\n }\n\n this.segmenter = new Intl.Segmenter(this.i18n.locale, {\n granularity: this.config.countType === 'words' ? 'word' : 'grapheme'\n })\n }\n\n // Determine the limit attribute (characters or words)\n this.maxLength = this.config.maxlength ?? Infinity\n\n this.$textarea = $textarea\n\n const textareaDescriptionId = `${this.$textarea.id}-info`\n const $textareaDescription = document.getElementById(textareaDescriptionId)\n if (!$textareaDescription) {\n throw new ElementError({\n component: CharacterCount,\n element: $textareaDescription,\n identifier: `Count message (\\`id=\"${textareaDescriptionId}\"\\`)`\n })\n }\n\n // Pre-existing validation error rendered from server\n this.$errorMessage = this.$root.querySelector('.govuk-error-message')\n\n // Inject a description for the textarea if none is present already\n // for when the component was rendered with no maxlength nor custom\n // textareaDescriptionText\n // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec\n if ($textareaDescription.textContent.match(/^\\s*$/)) {\n $textareaDescription.textContent = this.i18n.t('textareaDescription', {\n count: this.maxLength\n })\n }\n\n // Move the textarea description to be immediately after the textarea\n // Kept for backwards compatibility\n this.$textarea.insertAdjacentElement('afterend', $textareaDescription)\n\n // Create the *screen reader* specific live-updating counter\n // This doesn't need any styling classes, as it is never visible\n const $screenReaderCountMessage = createElement('div', {\n class: 'govuk-character-count__sr-status govuk-visually-hidden',\n 'aria-live': 'polite'\n })\n\n this.$screenReaderCountMessage = $screenReaderCountMessage\n $textareaDescription.insertAdjacentElement(\n 'afterend',\n $screenReaderCountMessage\n )\n\n // Create our live-updating counter element, copying the classes from the\n // textarea description for backwards compatibility as these may have been\n // configured\n const $visibleCountMessage = createElement('div', {\n class: `${$textareaDescription.className} govuk-character-count__status`,\n 'aria-hidden': 'true'\n })\n\n this.$visibleCountMessage = $visibleCountMessage\n $textareaDescription.insertAdjacentElement('afterend', $visibleCountMessage)\n\n // Hide the textarea description\n $textareaDescription.classList.add('govuk-visually-hidden')\n\n // Remove hard limit if set\n this.$textarea.removeAttribute('maxlength')\n\n this.bindChangeEvents()\n\n // When the page is restored after navigating 'back' in some browsers the\n // state of form controls is not restored until *after* the DOMContentLoaded\n // event is fired, so we need to sync after the pageshow event.\n window.addEventListener('pageshow', () => {\n // If the current value of the textarea is the same as what's\n // in the HTML, don't re-run when users have not edited the field yet\n // (new page load or BF cache navigation without having edited).\n if (this.$textarea.value !== this.$textarea.textContent) {\n this.updateCount()\n this.updateCountMessage()\n }\n })\n\n // Although we've set up handlers to sync state on the pageshow event, init\n // could be called after those events have fired, for example if they are\n // added to the page dynamically, so update now too.\n this.updateCount()\n this.updateCountMessage()\n }\n\n /**\n * Bind change events\n *\n * Set up event listeners on the $textarea so that the count messages update\n * when the user types.\n *\n * @private\n */\n bindChangeEvents() {\n this.$textarea.addEventListener('input', () => this.handleInput())\n\n // Bind focus/blur events to start/stop polling\n this.$textarea.addEventListener('focus', () => this.handleFocus())\n this.$textarea.addEventListener('blur', () => this.handleBlur())\n }\n\n /**\n * Handle input event\n *\n * Update the visible character counter and keep track of when the last update\n * happened for each keypress\n *\n * @private\n */\n handleInput() {\n this.updateCount()\n this.updateVisibleCountMessage()\n this.lastInputTimestamp = Date.now()\n }\n\n /**\n * Handle focus event\n *\n * Speech recognition software such as Dragon NaturallySpeaking will modify\n * the fields by directly changing its `value`. These changes don't trigger\n * events in JavaScript, so we need to poll to handle when and if they occur.\n *\n * Once the keyup event hasn't been detected for at least 1000 ms (1s), check\n * if the textarea value has changed and update the count message if it has.\n *\n * This is so that the update triggered by the manual comparison doesn't\n * conflict with debounced KeyboardEvent updates.\n *\n * @private\n */\n handleFocus() {\n this.valueChecker = window.setInterval(() => {\n if (\n !this.lastInputTimestamp ||\n Date.now() - 500 >= this.lastInputTimestamp\n ) {\n this.updateIfValueChanged()\n }\n }, 1000)\n }\n\n /**\n * Handle blur event\n *\n * Stop checking the textarea value once the textarea no longer has focus\n *\n * @private\n */\n handleBlur() {\n // Cancel value checking on blur\n if (this.valueChecker) {\n window.clearInterval(this.valueChecker)\n }\n }\n\n /**\n * Update count message if textarea value has changed\n *\n * @private\n */\n updateIfValueChanged() {\n if (this.$textarea.value !== this.lastInputValue) {\n this.lastInputValue = this.$textarea.value\n this.updateCountMessage()\n }\n }\n\n /**\n * Update count message\n *\n * Helper function to update both the visible and screen reader-specific\n * counters simultaneously (e.g. on init)\n *\n * @private\n */\n updateCountMessage() {\n this.updateVisibleCountMessage()\n this.updateScreenReaderCountMessage()\n }\n\n /**\n * Update visible count message\n *\n * @private\n */\n updateVisibleCountMessage() {\n const remainingNumber = this.maxLength - this.count\n const isError = remainingNumber < 0\n\n // If input is over the threshold, remove the disabled class which renders\n // the counter invisible.\n this.$visibleCountMessage.classList.toggle(\n 'govuk-character-count__message--disabled',\n !this.isOverThreshold()\n )\n\n // Update styles\n if (!this.$errorMessage) {\n // Only toggle the textarea error class if there isn't an error message\n // already, as it may be unrelated to the limit (eg: allowed characters)\n // and would set the border colour back to black.\n this.$textarea.classList.toggle('govuk-textarea--error', isError)\n }\n this.$visibleCountMessage.classList.toggle('govuk-error-message', isError)\n this.$visibleCountMessage.classList.toggle('govuk-hint', !isError)\n\n // Update message\n this.$visibleCountMessage.textContent = this.getCountMessage()\n }\n\n /**\n * Update screen reader count message\n *\n * @private\n */\n updateScreenReaderCountMessage() {\n // If over the threshold, remove the aria-hidden attribute, allowing screen\n // readers to announce the content of the element.\n if (this.isOverThreshold()) {\n this.$screenReaderCountMessage.removeAttribute('aria-hidden')\n } else {\n this.$screenReaderCountMessage.setAttribute('aria-hidden', 'true')\n }\n\n // Update message\n this.$screenReaderCountMessage.textContent = this.getCountMessage()\n }\n\n /**\n * Count the number of characters (or words) in the given text, using the\n * configured count type, and update the component-wide count\n *\n * @private\n */\n updateCount() {\n const text = this.$textarea.value\n\n // Count grapheme clusters (user-perceived characters)\n if (this.config.countType === 'characters') {\n this.count = this.segmenter\n ? Array.from(this.segmenter.segment(text)).length\n : 0\n\n return\n }\n\n // Count words\n //\n // If the (deprecated) `maxwords` option is set, count consecutive\n // non-whitespace results rather than using the segmenter\n if (this.config.countType === 'words') {\n if (this.config.maxwords !== undefined) {\n this.count = text.match(/\\S+/g)?.length ?? 0\n return\n }\n\n const segments = this.segmenter\n ? Array.from(this.segmenter.segment(text))\n : []\n\n // Filter out punctuation and whitespace, leaving only words\n this.count = segments.filter((segment) => segment.isWordLike).length\n return\n }\n\n this.count = text.length\n }\n\n /**\n * Get count message\n *\n * @private\n * @returns {string} Status message\n */\n getCountMessage() {\n const remainingNumber = this.maxLength - this.count\n return this.formatCountMessage(remainingNumber)\n }\n\n /**\n * Formats the message shown to users according to what's counted\n * and how many remain\n *\n * @private\n * @param {number} remainingNumber - The number of words/characters remaining\n * @param {CharacterCountConfig['countType']} [countType] - Deprecated\n * @returns {string} Status message\n */\n formatCountMessage(remainingNumber, countType) {\n countType = countType ?? this.config.countType\n\n let translationKeyPrefix = 'characters'\n let translationKeySuffix = remainingNumber < 0 ? 'OverLimit' : 'UnderLimit'\n\n if (countType === 'words') {\n translationKeyPrefix = 'words'\n }\n\n if (remainingNumber === 0) {\n translationKeySuffix = 'AtLimit'\n }\n\n return this.i18n.t(`${translationKeyPrefix}${translationKeySuffix}`, {\n count: remainingNumber === 0 ? undefined : Math.abs(remainingNumber)\n })\n }\n\n /**\n * Check if count is over threshold\n *\n * Checks whether the value is over the configured threshold for the input.\n * If there is no configured threshold, it is set to 0 and this function will\n * always return true.\n *\n * @private\n * @returns {boolean} true if the current count is over the config.threshold\n * (or no threshold is set)\n */\n isOverThreshold() {\n // No threshold means we're always above threshold so save some computation\n if (!this.config.threshold) {\n return true\n }\n\n // Determine the remaining number of characters/words\n const currentLength = this.count\n const maxLength = this.maxLength\n\n const thresholdValue = (maxLength * this.config.threshold) / 100\n\n return thresholdValue <= currentLength\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-character-count'\n\n /**\n * Character count default config\n *\n * @see {@link CharacterCountConfig}\n * @constant\n * @type {CharacterCountConfig}\n */\n static defaults = Object.freeze({\n threshold: 0,\n countType: 'length',\n i18n: {\n // Characters\n charactersUnderLimit: {\n one: 'You have %{count} character remaining',\n other: 'You have %{count} characters remaining'\n },\n charactersAtLimit: 'You have 0 characters remaining',\n charactersOverLimit: {\n one: 'You have %{count} character too many',\n other: 'You have %{count} characters too many'\n },\n // Words\n wordsUnderLimit: {\n one: 'You have %{count} word remaining',\n other: 'You have %{count} words remaining'\n },\n wordsAtLimit: 'You have 0 words remaining',\n wordsOverLimit: {\n one: 'You have %{count} word too many',\n other: 'You have %{count} words too many'\n },\n textareaDescription: {\n other: ''\n }\n }\n })\n\n /**\n * Character count config schema\n *\n * @constant\n * @satisfies {Schema<CharacterCountConfig>}\n */\n static schema = Object.freeze({\n properties: {\n i18n: { type: 'object' },\n maxwords: { type: 'number' },\n maxlength: { type: 'number' },\n threshold: { type: 'number' },\n countType: { type: 'string' }\n },\n anyOf: [\n {\n required: ['maxwords'],\n errorMessage: 'Either \"maxlength\" or \"maxwords\" must be provided'\n },\n {\n required: ['maxlength'],\n errorMessage: 'Either \"maxlength\" or \"maxwords\" must be provided'\n }\n ]\n })\n}\n\n/**\n * Character count config\n *\n * @see {@link CharacterCount.defaults}\n * @typedef {object} CharacterCountConfig\n * @property {number} [maxlength] - The maximum number of characters (or words\n * if `countType` is set to `\"words\"`).\n * @property {number} [maxwords] - Deprecated. Use `maxlength` and\n * `countType: \"words\"` instead.\n * @property {number} [threshold=0] - The percentage value of the limit at\n * which point the count message is displayed. If this attribute is set, the\n * count message will be hidden by default.\n * @property {'characters' | 'length' | 'words'} [countType] - The count type\n * (`\"characters\"`, `\"length\"` or `\"words\"`) used to count the text.\n * @property {CharacterCountTranslations} [i18n=CharacterCount.defaults.i18n] - Character count translations\n */\n\n/**\n * Character count translations\n *\n * @see {@link CharacterCount.defaults.i18n}\n * @typedef {object} CharacterCountTranslations\n *\n * Messages shown to users as they type. It provides feedback on how many words\n * or characters they have remaining or if they are over the limit. This also\n * includes a message used as an accessible description for the textarea.\n * @property {TranslationPluralForms} [charactersUnderLimit] - Message displayed\n * when the number of characters is under the configured maximum, `maxlength`.\n * This message is displayed visually and through assistive technologies. The\n * component will replace the `%{count}` placeholder with the number of\n * remaining characters. This is a [pluralised list of\n * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {string} [charactersAtLimit] - Message displayed when the number of\n * characters reaches the configured maximum, `maxlength`. This message is\n * displayed visually and through assistive technologies.\n * @property {TranslationPluralForms} [charactersOverLimit] - Message displayed\n * when the number of characters is over the configured maximum, `maxlength`.\n * This message is displayed visually and through assistive technologies. The\n * component will replace the `%{count}` placeholder with the number of\n * remaining characters. This is a [pluralised list of\n * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {TranslationPluralForms} [wordsUnderLimit] - Message displayed when\n * the number of words is under the configured maximum, `maxlength`. This\n * message is displayed visually and through assistive technologies. The\n * component will replace the `%{count}` placeholder with the number of\n * remaining words. This is a [pluralised list of\n * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {string} [wordsAtLimit] - Message displayed when the number of\n * words reaches the configured maximum, `maxlength`. This message is\n * displayed visually and through assistive technologies.\n * @property {TranslationPluralForms} [wordsOverLimit] - Message displayed when\n * the number of words is over the configured maximum, `maxlength`. This\n * message is displayed visually and through assistive technologies. The\n * component will replace the `%{count}` placeholder with the number of\n * remaining words. This is a [pluralised list of\n * messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {TranslationPluralForms} [textareaDescription] - Message made\n * available to assistive technologies, if none is already present in the\n * HTML, to describe that the component accepts only a limited amount of\n * content. It is visible on the page if `countType` is not supported or\n * JavaScript is unavailable. The component will replace the `%{count}`\n * placeholder with the value of the `maxlength` parameter.\n */\n\n/**\n * @import { Schema } from '../../common/configuration.mjs'\n * @import { TranslationPluralForms } from '../../i18n.mjs'\n */\n"],"names":["CharacterCount","ConfigurableComponent","configOverride","datasetConfig","configOverrides","maxlength","undefined","maxwords","config","console","warn","formatErrorMessage","_datasetConfig$maxwor","countType","constructor","$root","_this$config$maxlengt","$textarea","count","segmenter","$visibleCountMessage","$screenReaderCountMessage","lastInputTimestamp","lastInputValue","valueChecker","i18n","maxLength","querySelector","HTMLTextAreaElement","HTMLInputElement","ElementError","component","element","expectedType","identifier","errors","validateConfig","schema","ConfigError","I18n","locale","closestAttributeValue","Intl","SupportError","Segmenter","granularity","Infinity","textareaDescriptionId","id","$textareaDescription","document","getElementById","$errorMessage","textContent","match","t","insertAdjacentElement","createElement","class","className","classList","add","removeAttribute","bindChangeEvents","window","addEventListener","value","updateCount","updateCountMessage","handleInput","handleFocus","handleBlur","updateVisibleCountMessage","Date","now","setInterval","updateIfValueChanged","clearInterval","updateScreenReaderCountMessage","remainingNumber","isError","toggle","isOverThreshold","getCountMessage","setAttribute","text","Array","from","segment","length","_text$match$length","_text$match","segments","filter","isWordLike","formatCountMessage","translationKeyPrefix","translationKeySuffix","Math","abs","threshold","currentLength","thresholdValue","moduleName","defaults","Object","freeze","charactersUnderLimit","one","other","charactersAtLimit","charactersOverLimit","wordsUnderLimit","wordsAtLimit","wordsOverLimit","textareaDescription","properties","type","anyOf","required","errorMessage"],"mappings":"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"}
@@ -135,10 +135,10 @@
135
135
  "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n <h1 class=\"govuk-label-wrapper\">\n <label class=\"govuk-label govuk-label--l\" for=\"textarea-with-page-heading\">\n Full address\n </label>\n </h1>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"textarea-with-page-heading\" name=\"address\" rows=\"5\" aria-describedby=\"textarea-with-page-heading-info\"></textarea>\n <div id=\"textarea-with-page-heading-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n </div>\n</div>"
136
136
  },
137
137
  {
138
- "name": "with word count",
138
+ "name": "with maxwords",
139
139
  "options": {
140
- "id": "word-count",
141
- "name": "word-count",
140
+ "id": "maxwords",
141
+ "name": "maxwords",
142
142
  "maxwords": 10,
143
143
  "label": {
144
144
  "text": "Full address"
@@ -148,7 +148,174 @@
148
148
  "description": "",
149
149
  "pageTemplateOptions": {},
150
150
  "screenshot": false,
151
- "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxwords=\"10\">\n <label class=\"govuk-label\" for=\"word-count\">\n Full address\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"word-count\" name=\"word-count\" rows=\"5\" aria-describedby=\"word-count-info\"></textarea>\n <div id=\"word-count-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 words\n </div>\n</div>"
151
+ "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxwords=\"10\" data-count-type=\"words\">\n <label class=\"govuk-label\" for=\"maxwords\">\n Full address\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"maxwords\" name=\"maxwords\" rows=\"5\" aria-describedby=\"maxwords-info\"></textarea>\n <div id=\"maxwords-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 words\n </div>\n</div>"
152
+ },
153
+ {
154
+ "name": "with count type 'length'",
155
+ "options": {
156
+ "id": "with-count-type-length",
157
+ "name": "example",
158
+ "countType": "length",
159
+ "maxlength": 200,
160
+ "label": {
161
+ "text": "Enter a job description"
162
+ }
163
+ },
164
+ "hidden": false,
165
+ "description": "",
166
+ "pageTemplateOptions": {},
167
+ "screenshot": false,
168
+ "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"200\" data-count-type=\"length\">\n <label class=\"govuk-label\" for=\"with-count-type-length\">\n Enter a job description\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-count-type-length\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-length-info\"></textarea>\n <div id=\"with-count-type-length-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 200 characters\n </div>\n</div>"
169
+ },
170
+ {
171
+ "name": "with count type 'characters'",
172
+ "options": {
173
+ "id": "with-count-type-characters",
174
+ "name": "example",
175
+ "countType": "characters",
176
+ "maxlength": 200,
177
+ "label": {
178
+ "text": "Enter a job description"
179
+ }
180
+ },
181
+ "hidden": false,
182
+ "description": "",
183
+ "pageTemplateOptions": {},
184
+ "screenshot": false,
185
+ "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"200\" data-count-type=\"characters\">\n <label class=\"govuk-label\" for=\"with-count-type-characters\">\n Enter a job description\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-count-type-characters\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-characters-info\"></textarea>\n <div id=\"with-count-type-characters-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 200 characters\n </div>\n</div>"
186
+ },
187
+ {
188
+ "name": "with count type 'characters' and value",
189
+ "options": {
190
+ "id": "with-count-type-characters-value",
191
+ "name": "example",
192
+ "countType": "characters",
193
+ "maxlength": 350,
194
+ "label": {
195
+ "text": "Enter a job description"
196
+ },
197
+ "value": "👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels."
198
+ },
199
+ "hidden": false,
200
+ "description": "",
201
+ "pageTemplateOptions": {},
202
+ "screenshot": false,
203
+ "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"350\" data-count-type=\"characters\">\n <label class=\"govuk-label\" for=\"with-count-type-characters-value\">\n Enter a job description\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-count-type-characters-value\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-characters-value-info\">👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels.</textarea>\n <div id=\"with-count-type-characters-value-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 350 characters\n </div>\n</div>"
204
+ },
205
+ {
206
+ "name": "with count type 'characters' and error message",
207
+ "options": {
208
+ "id": "with-count-type-characters-error",
209
+ "name": "example",
210
+ "countType": "characters",
211
+ "maxlength": 350,
212
+ "label": {
213
+ "text": "Enter a job description"
214
+ },
215
+ "errorMessage": {
216
+ "text": "Job description must be 350 characters or less"
217
+ },
218
+ "value": "👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels. They make sure appropriate content is shown to a user in the right place and in the best format."
219
+ },
220
+ "hidden": false,
221
+ "description": "",
222
+ "pageTemplateOptions": {},
223
+ "screenshot": false,
224
+ "html": "<div class=\"govuk-form-group govuk-form-group--error govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"350\" data-count-type=\"characters\">\n <label class=\"govuk-label\" for=\"with-count-type-characters-error\">\n Enter a job description\n </label>\n <p id=\"with-count-type-characters-error-error\" class=\"govuk-error-message\">\n <span class=\"govuk-visually-hidden\">Error:</span> Job description must be 350 characters or less\n </p>\n <textarea class=\"govuk-textarea govuk-textarea--error govuk-js-character-count\" id=\"with-count-type-characters-error\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-characters-error-info with-count-type-characters-error-error\">👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels. They make sure appropriate content is shown to a user in the right place and in the best format.</textarea>\n <div id=\"with-count-type-characters-error-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 350 characters\n </div>\n</div>"
225
+ },
226
+ {
227
+ "name": "with count type 'characters' and threshold",
228
+ "options": {
229
+ "id": "with-count-type-characters-threshold",
230
+ "name": "example",
231
+ "countType": "characters",
232
+ "maxlength": 112,
233
+ "threshold": 75,
234
+ "label": {
235
+ "text": "Enter a job description"
236
+ },
237
+ "value": "Type another letter into this field after this message to see the threshold feature"
238
+ },
239
+ "hidden": false,
240
+ "description": "",
241
+ "pageTemplateOptions": {},
242
+ "screenshot": false,
243
+ "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"112\" data-threshold=\"75\" data-count-type=\"characters\">\n <label class=\"govuk-label\" for=\"with-count-type-characters-threshold\">\n Enter a job description\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-count-type-characters-threshold\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-characters-threshold-info\">Type another letter into this field after this message to see the threshold feature</textarea>\n <div id=\"with-count-type-characters-threshold-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 112 characters\n </div>\n</div>"
244
+ },
245
+ {
246
+ "name": "with count type 'words'",
247
+ "options": {
248
+ "id": "with-count-type-words",
249
+ "name": "example",
250
+ "countType": "words",
251
+ "maxlength": 50,
252
+ "label": {
253
+ "text": "Enter a job description"
254
+ }
255
+ },
256
+ "hidden": false,
257
+ "description": "",
258
+ "pageTemplateOptions": {},
259
+ "screenshot": false,
260
+ "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"50\" data-count-type=\"words\">\n <label class=\"govuk-label\" for=\"with-count-type-words\">\n Enter a job description\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-count-type-words\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-words-info\"></textarea>\n <div id=\"with-count-type-words-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 50 words\n </div>\n</div>"
261
+ },
262
+ {
263
+ "name": "with count type 'words' and value",
264
+ "options": {
265
+ "id": "with-count-type-words-value",
266
+ "name": "example",
267
+ "countType": "words",
268
+ "maxlength": 51,
269
+ "label": {
270
+ "text": "Enter a job description"
271
+ },
272
+ "value": "👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels."
273
+ },
274
+ "hidden": false,
275
+ "description": "",
276
+ "pageTemplateOptions": {},
277
+ "screenshot": false,
278
+ "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"51\" data-count-type=\"words\">\n <label class=\"govuk-label\" for=\"with-count-type-words-value\">\n Enter a job description\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-count-type-words-value\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-words-value-info\">👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels.</textarea>\n <div id=\"with-count-type-words-value-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 51 words\n </div>\n</div>"
279
+ },
280
+ {
281
+ "name": "with count type 'words' and error message",
282
+ "options": {
283
+ "id": "with-count-type-words-error",
284
+ "name": "example",
285
+ "countType": "words",
286
+ "maxlength": 51,
287
+ "label": {
288
+ "text": "Enter a job description"
289
+ },
290
+ "errorMessage": {
291
+ "text": "Job description must be 51 words or less"
292
+ },
293
+ "value": "👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels. They make sure appropriate content is shown to a user in the right place and in the best format."
294
+ },
295
+ "hidden": false,
296
+ "description": "",
297
+ "pageTemplateOptions": {},
298
+ "screenshot": false,
299
+ "html": "<div class=\"govuk-form-group govuk-form-group--error govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"51\" data-count-type=\"words\">\n <label class=\"govuk-label\" for=\"with-count-type-words-error\">\n Enter a job description\n </label>\n <p id=\"with-count-type-words-error-error\" class=\"govuk-error-message\">\n <span class=\"govuk-visually-hidden\">Error:</span> Job description must be 51 words or less\n </p>\n <textarea class=\"govuk-textarea govuk-textarea--error govuk-js-character-count\" id=\"with-count-type-words-error\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-words-error-info with-count-type-words-error-error\">👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels. They make sure appropriate content is shown to a user in the right place and in the best format.</textarea>\n <div id=\"with-count-type-words-error-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 51 words\n </div>\n</div>"
300
+ },
301
+ {
302
+ "name": "with count type 'words' and threshold",
303
+ "options": {
304
+ "id": "with-count-type-words-threshold",
305
+ "name": "example",
306
+ "countType": "words",
307
+ "maxlength": 51,
308
+ "threshold": 30,
309
+ "label": {
310
+ "text": "Enter a job description"
311
+ },
312
+ "value": "Type another word into this field after this message to see the threshold feature"
313
+ },
314
+ "hidden": false,
315
+ "description": "",
316
+ "pageTemplateOptions": {},
317
+ "screenshot": false,
318
+ "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"51\" data-threshold=\"30\" data-count-type=\"words\">\n <label class=\"govuk-label\" for=\"with-count-type-words-threshold\">\n Enter a job description\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-count-type-words-threshold\" name=\"example\" rows=\"5\" aria-describedby=\"with-count-type-words-threshold-info\">Type another word into this field after this message to see the threshold feature</textarea>\n <div id=\"with-count-type-words-threshold-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 51 words\n </div>\n</div>"
152
319
  },
153
320
  {
154
321
  "name": "with threshold",
@@ -395,7 +562,7 @@
395
562
  "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\">\n <label class=\"govuk-label\" for=\"to-configure-in-javascript\">\n Full address\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"to-configure-in-javascript\" name=\"address\" rows=\"5\" aria-describedby=\"to-configure-in-javascript-info\"></textarea>\n <div id=\"to-configure-in-javascript-info\" class=\"govuk-hint govuk-character-count__message\">\n \n </div>\n</div>"
396
563
  },
397
564
  {
398
- "name": "when neither maxlength nor maxwords are set",
565
+ "name": "with neither maxlength nor maxwords set",
399
566
  "options": {
400
567
  "id": "no-maximum",
401
568
  "name": "no-maximum",
@@ -411,7 +578,7 @@
411
578
  "html": "<div class=\"govuk-form-group govuk-character-count\" data-module=\"govuk-character-count\" data-i18n.textarea-description.other=\"No more than %{count} characters\">\n <label class=\"govuk-label\" for=\"no-maximum\">\n Full address\n </label>\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"no-maximum\" name=\"no-maximum\" rows=\"5\" aria-describedby=\"no-maximum-info\"></textarea>\n <div id=\"no-maximum-info\" class=\"govuk-hint govuk-character-count__message\">\n \n </div>\n</div>"
412
579
  },
413
580
  {
414
- "name": "when neither maxlength/maxwords nor textarea description are set",
581
+ "name": "with neither maxlength, maxwords nor textarea description set",
415
582
  "options": {
416
583
  "id": "no-maximum",
417
584
  "name": "no-maximum",
@@ -27,13 +27,14 @@
27
27
  "name": "maxlength",
28
28
  "type": "string",
29
29
  "required": true,
30
- "description": "If `maxwords` is set, this is not required. The maximum number of characters. If `maxwords` is provided, the `maxlength` option will be ignored."
30
+ "description": "The maximum number of characters (or words if `countType` is set to `\"words\"`)."
31
31
  },
32
32
  {
33
33
  "name": "maxwords",
34
34
  "type": "string",
35
35
  "required": true,
36
- "description": "If `maxlength` is set, this is not required. The maximum number of words. If `maxwords` is provided, the `maxlength` option will be ignored."
36
+ "description": "The maximum number of words. Replaced by the `maxlength` and `countType: \"words\"` options.",
37
+ "deprecated": "6.6.0"
37
38
  },
38
39
  {
39
40
  "name": "threshold",
@@ -41,6 +42,12 @@
41
42
  "required": false,
42
43
  "description": "The percentage value of the limit at which point the count message is displayed. If this attribute is set, the count message will be hidden by default."
43
44
  },
45
+ {
46
+ "name": "countType",
47
+ "type": "string",
48
+ "required": false,
49
+ "description": "The count type used to count the text – `\"length\"` or `\"words\"`. Defaults to `\"length\"`."
50
+ },
44
51
  {
45
52
  "name": "label",
46
53
  "type": "object",
@@ -158,7 +165,7 @@
158
165
  "name": "textareaDescriptionText",
159
166
  "type": "string",
160
167
  "required": false,
161
- "description": "Message made available to assistive technologies to describe that the component accepts only a limited amount of content. It is visible on the page when JavaScript is unavailable. The component will replace the `%{count}` placeholder with the value of the `maxlength` or `maxwords` parameter."
168
+ "description": "Message made available to assistive technologies to describe that the component accepts only a limited amount of content. It is visible on the page if `countType` is not supported or JavaScript is unavailable. The component will replace the `%{count}` placeholder with the value of the `maxlength` parameter."
162
169
  },
163
170
  {
164
171
  "name": "charactersUnderLimitText",
@@ -182,18 +189,18 @@
182
189
  "name": "wordsUnderLimitText",
183
190
  "type": "object",
184
191
  "required": false,
185
- "description": "Message displayed when the number of words is under the configured maximum, `maxwords`. This message is displayed visually and through assistive technologies. The component will replace the `%{count}` placeholder with the number of remaining words. [Our pluralisation rules apply to this macro option](https://frontend.design-system.service.gov.uk/localise-govuk-frontend/#understanding-pluralisation-rules)."
192
+ "description": "Message displayed when the number of words is under the configured maximum, `maxlength` with `countType: \"words\"`. This message is displayed visually and through assistive technologies. The component will replace the `%{count}` placeholder with the number of remaining words. [Our pluralisation rules apply to this macro option](https://frontend.design-system.service.gov.uk/localise-govuk-frontend/#understanding-pluralisation-rules)."
186
193
  },
187
194
  {
188
195
  "name": "wordsAtLimitText",
189
196
  "type": "string",
190
197
  "required": false,
191
- "description": "Message displayed when the number of words reaches the configured maximum, `maxwords`. This message is displayed visually and through assistive technologies."
198
+ "description": "Message displayed when the number of words reaches the configured maximum, `maxlength` with `countType: \"words\"`. This message is displayed visually and through assistive technologies."
192
199
  },
193
200
  {
194
201
  "name": "wordsOverLimitText",
195
202
  "type": "object",
196
203
  "required": false,
197
- "description": "Message displayed when the number of words is over the configured maximum, `maxwords`. This message is displayed visually and through assistive technologies. The component will replace the `%{count}` placeholder with the number of characters above the maximum. [Our pluralisation rules apply to this macro option](https://frontend.design-system.service.gov.uk/localise-govuk-frontend/#understanding-pluralisation-rules)."
204
+ "description": "Message displayed when the number of words is over the configured maximum, `maxlength` with `countType: \"words\"`. This message is displayed visually and through assistive technologies. The component will replace the `%{count}` placeholder with the number of words above the maximum. [Our pluralisation rules apply to this macro option](https://frontend.design-system.service.gov.uk/localise-govuk-frontend/#understanding-pluralisation-rules)."
198
205
  }
199
206
  ]
@@ -0,0 +1,12 @@
1
+ <div class="govuk-form-group govuk-form-group--error govuk-character-count" data-module="govuk-character-count" data-maxlength="350" data-count-type="characters">
2
+ <label class="govuk-label" for="with-count-type-characters-error">
3
+ Enter a job description
4
+ </label>
5
+ <p id="with-count-type-characters-error-error" class="govuk-error-message">
6
+ <span class="govuk-visually-hidden">Error:</span> Job description must be 350 characters or less
7
+ </p>
8
+ <textarea class="govuk-textarea govuk-textarea--error govuk-js-character-count" id="with-count-type-characters-error" name="example" rows="5" aria-describedby="with-count-type-characters-error-info with-count-type-characters-error-error">👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels. They make sure appropriate content is shown to a user in the right place and in the best format.</textarea>
9
+ <div id="with-count-type-characters-error-info" class="govuk-hint govuk-character-count__message">
10
+ You can enter up to 350 characters
11
+ </div>
12
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="govuk-form-group govuk-character-count" data-module="govuk-character-count" data-maxlength="112" data-threshold="75" data-count-type="characters">
2
+ <label class="govuk-label" for="with-count-type-characters-threshold">
3
+ Enter a job description
4
+ </label>
5
+ <textarea class="govuk-textarea govuk-js-character-count" id="with-count-type-characters-threshold" name="example" rows="5" aria-describedby="with-count-type-characters-threshold-info">Type another letter into this field after this message to see the threshold feature</textarea>
6
+ <div id="with-count-type-characters-threshold-info" class="govuk-hint govuk-character-count__message">
7
+ You can enter up to 112 characters
8
+ </div>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="govuk-form-group govuk-character-count" data-module="govuk-character-count" data-maxlength="350" data-count-type="characters">
2
+ <label class="govuk-label" for="with-count-type-characters-value">
3
+ Enter a job description
4
+ </label>
5
+ <textarea class="govuk-textarea govuk-js-character-count" id="with-count-type-characters-value" name="example" rows="5" aria-describedby="with-count-type-characters-value-info">👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels.</textarea>
6
+ <div id="with-count-type-characters-value-info" class="govuk-hint govuk-character-count__message">
7
+ You can enter up to 350 characters
8
+ </div>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="govuk-form-group govuk-character-count" data-module="govuk-character-count" data-maxlength="200" data-count-type="characters">
2
+ <label class="govuk-label" for="with-count-type-characters">
3
+ Enter a job description
4
+ </label>
5
+ <textarea class="govuk-textarea govuk-js-character-count" id="with-count-type-characters" name="example" rows="5" aria-describedby="with-count-type-characters-info"></textarea>
6
+ <div id="with-count-type-characters-info" class="govuk-hint govuk-character-count__message">
7
+ You can enter up to 200 characters
8
+ </div>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="govuk-form-group govuk-character-count" data-module="govuk-character-count" data-maxlength="200" data-count-type="length">
2
+ <label class="govuk-label" for="with-count-type-length">
3
+ Enter a job description
4
+ </label>
5
+ <textarea class="govuk-textarea govuk-js-character-count" id="with-count-type-length" name="example" rows="5" aria-describedby="with-count-type-length-info"></textarea>
6
+ <div id="with-count-type-length-info" class="govuk-hint govuk-character-count__message">
7
+ You can enter up to 200 characters
8
+ </div>
9
+ </div>
@@ -0,0 +1,12 @@
1
+ <div class="govuk-form-group govuk-form-group--error govuk-character-count" data-module="govuk-character-count" data-maxlength="51" data-count-type="words">
2
+ <label class="govuk-label" for="with-count-type-words-error">
3
+ Enter a job description
4
+ </label>
5
+ <p id="with-count-type-words-error-error" class="govuk-error-message">
6
+ <span class="govuk-visually-hidden">Error:</span> Job description must be 51 words or less
7
+ </p>
8
+ <textarea class="govuk-textarea govuk-textarea--error govuk-js-character-count" id="with-count-type-words-error" name="example" rows="5" aria-describedby="with-count-type-words-error-info with-count-type-words-error-error">👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels. They make sure appropriate content is shown to a user in the right place and in the best format.</textarea>
9
+ <div id="with-count-type-words-error-info" class="govuk-hint govuk-character-count__message">
10
+ You can enter up to 51 words
11
+ </div>
12
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="govuk-form-group govuk-character-count" data-module="govuk-character-count" data-maxlength="51" data-threshold="30" data-count-type="words">
2
+ <label class="govuk-label" for="with-count-type-words-threshold">
3
+ Enter a job description
4
+ </label>
5
+ <textarea class="govuk-textarea govuk-js-character-count" id="with-count-type-words-threshold" name="example" rows="5" aria-describedby="with-count-type-words-threshold-info">Type another word into this field after this message to see the threshold feature</textarea>
6
+ <div id="with-count-type-words-threshold-info" class="govuk-hint govuk-character-count__message">
7
+ You can enter up to 51 words
8
+ </div>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="govuk-form-group govuk-character-count" data-module="govuk-character-count" data-maxlength="51" data-count-type="words">
2
+ <label class="govuk-label" for="with-count-type-words-value">
3
+ Enter a job description
4
+ </label>
5
+ <textarea class="govuk-textarea govuk-js-character-count" id="with-count-type-words-value" name="example" rows="5" aria-describedby="with-count-type-words-value-info">👩🏻‍🚀 A content designer works on the end-to-end journey of a service to help users complete their goal and government deliver a policy intent. Their work may involve the creation of, or change to, a transaction, product or single piece of content that stretches across digital and offline channels.</textarea>
6
+ <div id="with-count-type-words-value-info" class="govuk-hint govuk-character-count__message">
7
+ You can enter up to 51 words
8
+ </div>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="govuk-form-group govuk-character-count" data-module="govuk-character-count" data-maxlength="50" data-count-type="words">
2
+ <label class="govuk-label" for="with-count-type-words">
3
+ Enter a job description
4
+ </label>
5
+ <textarea class="govuk-textarea govuk-js-character-count" id="with-count-type-words" name="example" rows="5" aria-describedby="with-count-type-words-info"></textarea>
6
+ <div id="with-count-type-words-info" class="govuk-hint govuk-character-count__message">
7
+ You can enter up to 50 words
8
+ </div>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="govuk-form-group govuk-character-count" data-module="govuk-character-count" data-maxwords="10" data-count-type="words">
2
+ <label class="govuk-label" for="maxwords">
3
+ Full address
4
+ </label>
5
+ <textarea class="govuk-textarea govuk-js-character-count" id="maxwords" name="maxwords" rows="5" aria-describedby="maxwords-info"></textarea>
6
+ <div id="maxwords-info" class="govuk-hint govuk-character-count__message">
7
+ You can enter up to 10 words
8
+ </div>
9
+ </div>
@@ -3,6 +3,9 @@
3
3
  {% from "../textarea/macro.njk" import govukTextarea %}
4
4
  {% from "../hint/macro.njk" import govukHint %}
5
5
 
6
+ {%- set countType = params.countType if params.countType
7
+ else ("words" if params.maxwords) -%}
8
+
6
9
  {#-
7
10
  If the limit is set in JavaScript, we won't be able to interpolate the message
8
11
  until JavaScript, so we only set a text if the `maxlength` or `maxwords` options
@@ -10,7 +13,7 @@
10
13
  #}
11
14
  {%- set hasNoLimit = (not params.maxwords and not params.maxlength) -%}
12
15
  {%- set textareaDescriptionLength = params.maxwords or params.maxlength -%}
13
- {%- set textareaDescriptionText = params.textareaDescriptionText or 'You can enter up to %{count} ' + ('words' if params.maxwords else 'characters') -%}
16
+ {%- set textareaDescriptionText = params.textareaDescriptionText or "You can enter up to %{count} " + ("words" if countType == "words" else "characters") -%}
14
17
  {%- set textareaDescriptionTextNoLimit = textareaDescriptionText | replace('%{count}', textareaDescriptionLength) if not hasNoLimit -%}
15
18
  {%- set id = params.id if params.id else params.name -%}
16
19
 
@@ -32,12 +35,16 @@
32
35
  value: params.maxlength,
33
36
  optional: true
34
37
  },
38
+ "data-maxwords": {
39
+ value: params.maxwords,
40
+ optional: true
41
+ },
35
42
  "data-threshold": {
36
43
  value: params.threshold,
37
44
  optional: true
38
45
  },
39
- "data-maxwords": {
40
- value: params.maxwords,
46
+ "data-count-type": {
47
+ value: countType if countType else false,
41
48
  optional: true
42
49
  }
43
50
  }) -}}