govuk_tech_docs 5.2.1 → 6.0.0.beta

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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +59 -0
  3. data/.npmrc +1 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +19 -0
  6. data/README.md +13 -4
  7. data/example/config/tech-docs.yml +1 -1
  8. data/govuk_tech_docs.gemspec +2 -2
  9. data/lib/assets/stylesheets/_core.scss +1 -0
  10. data/lib/assets/stylesheets/_govuk_tech_docs.scss +13 -15
  11. data/lib/assets/stylesheets/modules/_app-pane.scss +3 -3
  12. data/lib/assets/stylesheets/modules/_page-review.scss +4 -4
  13. data/lib/assets/stylesheets/modules/_search.scss +3 -3
  14. data/lib/assets/stylesheets/modules/_service-navigation.scss +5 -0
  15. data/lib/assets/stylesheets/modules/_technical-documentation.scss +7 -7
  16. data/lib/assets/stylesheets/modules/_toc.scss +13 -13
  17. data/lib/assets/stylesheets/palette/_syntax-highlighting.scss +9 -7
  18. data/lib/govuk_tech_docs/meta_tags.rb +1 -1
  19. data/lib/govuk_tech_docs/version.rb +1 -1
  20. data/lib/source/layouts/_header.erb +2 -16
  21. data/lib/source/layouts/_service_navigation.erb +27 -0
  22. data/lib/source/layouts/core.erb +7 -7
  23. data/node_modules/govuk-frontend/dist/govuk/_base.scss +1 -0
  24. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +183 -300
  25. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +184 -300
  26. data/node_modules/govuk-frontend/dist/govuk/all.mjs +0 -1
  27. data/node_modules/govuk-frontend/dist/govuk/assets/images/favicon.ico +0 -0
  28. data/node_modules/govuk-frontend/dist/govuk/assets/images/favicon.svg +1 -1
  29. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-icon-180.png +0 -0
  30. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-icon-192.png +0 -0
  31. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-icon-512.png +0 -0
  32. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-opengraph-image.png +0 -0
  33. data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +29 -2
  34. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
  35. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +4 -10
  36. data/node_modules/govuk-frontend/dist/govuk/components/accordion/_index.scss +18 -15
  37. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +14 -137
  38. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +14 -137
  39. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +4 -4
  40. data/node_modules/govuk-frontend/dist/govuk/components/back-link/_index.scss +2 -2
  41. data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/_index.scss +2 -2
  42. data/node_modules/govuk-frontend/dist/govuk/components/button/_index.scss +18 -21
  43. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +7 -5
  44. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +7 -5
  45. data/node_modules/govuk-frontend/dist/govuk/components/character-count/_index.scss +2 -2
  46. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +30 -143
  47. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +30 -143
  48. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +20 -10
  49. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/_index.scss +7 -6
  50. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +10 -5
  51. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +10 -5
  52. data/node_modules/govuk-frontend/dist/govuk/components/cookie-banner/_index.scss +2 -5
  53. data/node_modules/govuk-frontend/dist/govuk/components/date-input/_index.scss +5 -0
  54. data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss +6 -4
  55. data/node_modules/govuk-frontend/dist/govuk/components/error-message/_index.scss +1 -1
  56. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/_index.scss +4 -2
  57. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +8 -12
  58. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +8 -12
  59. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +2 -2
  60. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/_index.scss +1 -1
  61. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +10 -133
  62. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +10 -133
  63. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/_index.scss +30 -38
  64. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js +46 -140
  65. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs +46 -140
  66. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs +36 -7
  67. data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss +30 -27
  68. data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss +89 -449
  69. data/node_modules/govuk-frontend/dist/govuk/components/hint/_index.scss +1 -1
  70. data/node_modules/govuk-frontend/dist/govuk/components/input/_index.scss +14 -20
  71. data/node_modules/govuk-frontend/dist/govuk/components/inset-text/_index.scss +2 -1
  72. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/_index.scss +10 -8
  73. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +7 -5
  74. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +7 -5
  75. data/node_modules/govuk-frontend/dist/govuk/components/pagination/_index.scss +16 -11
  76. data/node_modules/govuk-frontend/dist/govuk/components/panel/_index.scss +4 -4
  77. data/node_modules/govuk-frontend/dist/govuk/components/password-input/_index.scss +2 -2
  78. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +10 -133
  79. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +10 -133
  80. data/node_modules/govuk-frontend/dist/govuk/components/phase-banner/_index.scss +12 -6
  81. data/node_modules/govuk-frontend/dist/govuk/components/radios/_index.scss +8 -7
  82. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +10 -5
  83. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +10 -5
  84. data/node_modules/govuk-frontend/dist/govuk/components/select/_index.scss +6 -11
  85. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss +58 -74
  86. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +40 -7
  87. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +40 -7
  88. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs +30 -2
  89. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/_index.scss +8 -4
  90. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +12 -19
  91. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +12 -19
  92. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +3 -9
  93. data/node_modules/govuk-frontend/dist/govuk/components/summary-list/_index.scss +25 -21
  94. data/node_modules/govuk-frontend/dist/govuk/components/table/_index.scss +7 -8
  95. data/node_modules/govuk-frontend/dist/govuk/components/tabs/_index.scss +9 -6
  96. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +12 -13
  97. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +12 -13
  98. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs +3 -3
  99. data/node_modules/govuk-frontend/dist/govuk/components/tag/_index.scss +66 -31
  100. data/node_modules/govuk-frontend/dist/govuk/components/task-list/_index.scss +7 -5
  101. data/node_modules/govuk-frontend/dist/govuk/components/textarea/_index.scss +5 -10
  102. data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss +5 -4
  103. data/node_modules/govuk-frontend/dist/govuk/core/_index.scss +0 -1
  104. data/node_modules/govuk-frontend/dist/govuk/core/_lists.scss +2 -2
  105. data/node_modules/govuk-frontend/dist/govuk/core/_section-break.scss +2 -1
  106. data/node_modules/govuk-frontend/dist/govuk/core/_typography.scss +6 -20
  107. data/node_modules/govuk-frontend/dist/govuk/custom-properties/_breakpoints.scss +17 -0
  108. data/node_modules/govuk-frontend/dist/govuk/custom-properties/_frontend-version.scss +15 -0
  109. data/node_modules/govuk-frontend/dist/govuk/custom-properties/_functional-colours.scss +17 -0
  110. data/node_modules/govuk-frontend/dist/govuk/custom-properties/_index.scss +5 -0
  111. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +5 -3
  112. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
  113. data/node_modules/govuk-frontend/dist/govuk/helpers/_colour.scss +187 -72
  114. data/node_modules/govuk-frontend/dist/govuk/helpers/_focused.scss +41 -6
  115. data/node_modules/govuk-frontend/dist/govuk/helpers/_grid.scss +1 -1
  116. data/node_modules/govuk-frontend/dist/govuk/helpers/_links.scss +24 -40
  117. data/node_modules/govuk-frontend/dist/govuk/helpers/_media-queries.scss +172 -33
  118. data/node_modules/govuk-frontend/dist/govuk/helpers/_spacing.scss +1 -1
  119. data/node_modules/govuk-frontend/dist/govuk/helpers/_typography.scss +6 -30
  120. data/node_modules/govuk-frontend/dist/govuk/helpers/_visually-hidden.scss +4 -1
  121. data/node_modules/govuk-frontend/dist/govuk/i18n.mjs +5 -128
  122. data/node_modules/govuk-frontend/dist/govuk/init.mjs +53 -45
  123. data/node_modules/govuk-frontend/dist/govuk/objects/_button-group.scss +1 -1
  124. data/node_modules/govuk-frontend/dist/govuk/objects/_form-group.scss +2 -1
  125. data/node_modules/govuk-frontend/dist/govuk/objects/_main-wrapper.scss +1 -1
  126. data/node_modules/govuk-frontend/dist/govuk/objects/_template.scss +3 -7
  127. data/node_modules/govuk-frontend/dist/govuk/objects/_width-container.scss +2 -2
  128. data/node_modules/govuk-frontend/dist/govuk/overrides/_display.scss +1 -1
  129. data/node_modules/govuk-frontend/dist/govuk/overrides/_typography.scss +0 -2
  130. data/node_modules/govuk-frontend/dist/govuk/overrides/_width.scss +5 -5
  131. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-applied.scss +3 -188
  132. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-functional.scss +366 -0
  133. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +9 -255
  134. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-palette.scss +117 -25
  135. data/node_modules/govuk-frontend/dist/govuk/settings/_custom-properties.scss +18 -0
  136. data/node_modules/govuk-frontend/dist/govuk/settings/_index.scss +3 -14
  137. data/node_modules/govuk-frontend/dist/govuk/settings/_media-queries.scss +0 -9
  138. data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss +12 -189
  139. data/node_modules/govuk-frontend/dist/govuk/tools/_index.scss +0 -1
  140. data/node_modules/govuk-frontend/dist/govuk/tools/_px-to-em.scss +4 -2
  141. data/node_modules/govuk-frontend/dist/govuk/tools/_px-to-rem.scss +2 -0
  142. data/package-lock.json +2461 -1150
  143. data/package.json +3 -3
  144. metadata +16 -30
  145. data/node_modules/govuk-frontend/dist/govuk/all.scss +0 -9
  146. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/favicon.ico +0 -0
  147. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/favicon.svg +0 -1
  148. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-crest.svg +0 -1
  149. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-icon-180.png +0 -0
  150. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-icon-192.png +0 -0
  151. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-icon-512.png +0 -0
  152. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-icon-mask.svg +0 -1
  153. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-opengraph-image.png +0 -0
  154. data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/manifest.json +0 -39
  155. data/node_modules/govuk-frontend/dist/govuk/components/_all.scss +0 -10
  156. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +0 -233
  157. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +0 -225
  158. data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs +0 -89
  159. data/node_modules/govuk-frontend/dist/govuk/core/_all.scss +0 -10
  160. data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +0 -15
  161. data/node_modules/govuk-frontend/dist/govuk/helpers/_all.scss +0 -10
  162. data/node_modules/govuk-frontend/dist/govuk/objects/_all.scss +0 -10
  163. data/node_modules/govuk-frontend/dist/govuk/overrides/_all.scss +0 -9
  164. data/node_modules/govuk-frontend/dist/govuk/settings/_all.scss +0 -10
  165. data/node_modules/govuk-frontend/dist/govuk/tools/_all.scss +0 -10
  166. data/node_modules/govuk-frontend/dist/govuk/tools/_rebrand.scss +0 -65
  167. data/node_modules/govuk-frontend/dist/govuk/utilities/_all.scss +0 -10
  168. data/node_modules/govuk-frontend/dist/govuk/vendor/_sass-mq.scss +0 -349
  169. data/node_modules/govuk-frontend/dist/govuk-prototype-kit/functions.js +0 -25
@@ -35,9 +35,6 @@ function formatErrorMessage(Component, message) {
35
35
  * @typedef ComponentWithModuleName
36
36
  * @property {string} moduleName - Name of the component
37
37
  */
38
- /**
39
- * @import { ObjectNested } from './configuration.mjs'
40
- */
41
38
 
42
39
  class GOVUKFrontendError extends Error {
43
40
  constructor(...args) {
@@ -66,7 +63,7 @@ class ConfigError extends GOVUKFrontendError {
66
63
  class ElementError extends GOVUKFrontendError {
67
64
  constructor(messageOrOptions) {
68
65
  let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
69
- if (typeof messageOrOptions === 'object') {
66
+ if (isObject(messageOrOptions)) {
70
67
  const {
71
68
  component,
72
69
  identifier,
@@ -75,7 +72,9 @@ class ElementError extends GOVUKFrontendError {
75
72
  } = messageOrOptions;
76
73
  message = identifier;
77
74
  message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
78
- message = formatErrorMessage(component, message);
75
+ if (component) {
76
+ message = formatErrorMessage(component, message);
77
+ }
79
78
  }
80
79
  super(message);
81
80
  this.name = 'ElementError';
@@ -309,6 +308,9 @@ function extractConfigByNamespace(schema, dataset, namespace) {
309
308
  * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]
310
309
  * @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
311
310
  */
311
+ /**
312
+ * @import { CompatibleClass, Config, CreateAllOptions, OnErrorCallback } from '../init.mjs'
313
+ */
312
314
 
313
315
  class I18n {
314
316
  constructor(translations = {}, config = {}) {
@@ -323,7 +325,7 @@ class I18n {
323
325
  throw new Error('i18n: lookup key missing');
324
326
  }
325
327
  let translation = this.translations[lookupKey];
326
- if (typeof (options == null ? void 0 : options.count) === 'number' && typeof translation === 'object') {
328
+ if (typeof (options == null ? void 0 : options.count) === 'number' && isObject(translation)) {
327
329
  const translationPluralForm = translation[this.getPluralSuffix(lookupKey, options.count)];
328
330
  if (translationPluralForm) {
329
331
  translation = translationPluralForm;
@@ -365,8 +367,8 @@ class I18n {
365
367
  return 'other';
366
368
  }
367
369
  const translation = this.translations[lookupKey];
368
- const preferredForm = this.hasIntlPluralRulesSupport() ? new Intl.PluralRules(this.locale).select(count) : this.selectPluralFormUsingFallbackRules(count);
369
- if (typeof translation === 'object') {
370
+ const preferredForm = this.hasIntlPluralRulesSupport() ? new Intl.PluralRules(this.locale).select(count) : 'other';
371
+ if (isObject(translation)) {
370
372
  if (preferredForm in translation) {
371
373
  return preferredForm;
372
374
  } else if ('other' in translation) {
@@ -376,132 +378,7 @@ class I18n {
376
378
  }
377
379
  throw new Error(`i18n: Plural form ".other" is required for "${this.locale}" locale`);
378
380
  }
379
- selectPluralFormUsingFallbackRules(count) {
380
- count = Math.abs(Math.floor(count));
381
- const ruleset = this.getPluralRulesForLocale();
382
- if (ruleset) {
383
- return I18n.pluralRules[ruleset](count);
384
- }
385
- return 'other';
386
- }
387
- getPluralRulesForLocale() {
388
- const localeShort = this.locale.split('-')[0];
389
- for (const pluralRule in I18n.pluralRulesMap) {
390
- const languages = I18n.pluralRulesMap[pluralRule];
391
- if (languages.includes(this.locale) || languages.includes(localeShort)) {
392
- return pluralRule;
393
- }
394
- }
395
- }
396
381
  }
397
- I18n.pluralRulesMap = {
398
- arabic: ['ar'],
399
- chinese: ['my', 'zh', 'id', 'ja', 'jv', 'ko', 'ms', 'th', 'vi'],
400
- french: ['hy', 'bn', 'fr', 'gu', 'hi', 'fa', 'pa', 'zu'],
401
- german: ['af', 'sq', 'az', 'eu', 'bg', 'ca', 'da', 'nl', 'en', 'et', 'fi', 'ka', 'de', 'el', 'hu', 'lb', 'no', 'so', 'sw', 'sv', 'ta', 'te', 'tr', 'ur'],
402
- irish: ['ga'],
403
- russian: ['ru', 'uk'],
404
- scottish: ['gd'],
405
- spanish: ['pt-PT', 'it', 'es'],
406
- welsh: ['cy']
407
- };
408
- I18n.pluralRules = {
409
- arabic(n) {
410
- if (n === 0) {
411
- return 'zero';
412
- }
413
- if (n === 1) {
414
- return 'one';
415
- }
416
- if (n === 2) {
417
- return 'two';
418
- }
419
- if (n % 100 >= 3 && n % 100 <= 10) {
420
- return 'few';
421
- }
422
- if (n % 100 >= 11 && n % 100 <= 99) {
423
- return 'many';
424
- }
425
- return 'other';
426
- },
427
- chinese() {
428
- return 'other';
429
- },
430
- french(n) {
431
- return n === 0 || n === 1 ? 'one' : 'other';
432
- },
433
- german(n) {
434
- return n === 1 ? 'one' : 'other';
435
- },
436
- irish(n) {
437
- if (n === 1) {
438
- return 'one';
439
- }
440
- if (n === 2) {
441
- return 'two';
442
- }
443
- if (n >= 3 && n <= 6) {
444
- return 'few';
445
- }
446
- if (n >= 7 && n <= 10) {
447
- return 'many';
448
- }
449
- return 'other';
450
- },
451
- russian(n) {
452
- const lastTwo = n % 100;
453
- const last = lastTwo % 10;
454
- if (last === 1 && lastTwo !== 11) {
455
- return 'one';
456
- }
457
- if (last >= 2 && last <= 4 && !(lastTwo >= 12 && lastTwo <= 14)) {
458
- return 'few';
459
- }
460
- if (last === 0 || last >= 5 && last <= 9 || lastTwo >= 11 && lastTwo <= 14) {
461
- return 'many';
462
- }
463
- return 'other';
464
- },
465
- scottish(n) {
466
- if (n === 1 || n === 11) {
467
- return 'one';
468
- }
469
- if (n === 2 || n === 12) {
470
- return 'two';
471
- }
472
- if (n >= 3 && n <= 10 || n >= 13 && n <= 19) {
473
- return 'few';
474
- }
475
- return 'other';
476
- },
477
- spanish(n) {
478
- if (n === 1) {
479
- return 'one';
480
- }
481
- if (n % 1000000 === 0 && n !== 0) {
482
- return 'many';
483
- }
484
- return 'other';
485
- },
486
- welsh(n) {
487
- if (n === 0) {
488
- return 'zero';
489
- }
490
- if (n === 1) {
491
- return 'one';
492
- }
493
- if (n === 2) {
494
- return 'two';
495
- }
496
- if (n === 3) {
497
- return 'few';
498
- }
499
- if (n === 6) {
500
- return 'many';
501
- }
502
- return 'other';
503
- }
504
- };
505
382
 
506
383
  /**
507
384
  * Character count component
@@ -536,6 +413,7 @@ class CharacterCount extends ConfigurableComponent {
536
413
  var _ref, _this$config$maxwords;
537
414
  super($root, config);
538
415
  this.$textarea = void 0;
416
+ this.count = 0;
539
417
  this.$visibleCountMessage = void 0;
540
418
  this.$screenReaderCountMessage = void 0;
541
419
  this.lastInputTimestamp = null;
@@ -571,7 +449,7 @@ class CharacterCount extends ConfigurableComponent {
571
449
  });
572
450
  }
573
451
  this.$errorMessage = this.$root.querySelector('.govuk-error-message');
574
- if (`${$textareaDescription.textContent}`.match(/^\s*$/)) {
452
+ if ($textareaDescription.textContent.match(/^\s*$/)) {
575
453
  $textareaDescription.textContent = this.i18n.t('textareaDescription', {
576
454
  count: this.maxLength
577
455
  });
@@ -591,15 +469,22 @@ class CharacterCount extends ConfigurableComponent {
591
469
  $textareaDescription.classList.add('govuk-visually-hidden');
592
470
  this.$textarea.removeAttribute('maxlength');
593
471
  this.bindChangeEvents();
594
- window.addEventListener('pageshow', () => this.updateCountMessage());
472
+ window.addEventListener('pageshow', () => {
473
+ if (this.$textarea.value !== this.$textarea.textContent) {
474
+ this.updateCount();
475
+ this.updateCountMessage();
476
+ }
477
+ });
478
+ this.updateCount();
595
479
  this.updateCountMessage();
596
480
  }
597
481
  bindChangeEvents() {
598
- this.$textarea.addEventListener('keyup', () => this.handleKeyUp());
482
+ this.$textarea.addEventListener('input', () => this.handleInput());
599
483
  this.$textarea.addEventListener('focus', () => this.handleFocus());
600
484
  this.$textarea.addEventListener('blur', () => this.handleBlur());
601
485
  }
602
- handleKeyUp() {
486
+ handleInput() {
487
+ this.updateCount();
603
488
  this.updateVisibleCountMessage();
604
489
  this.lastInputTimestamp = Date.now();
605
490
  }
@@ -626,7 +511,7 @@ class CharacterCount extends ConfigurableComponent {
626
511
  this.updateScreenReaderCountMessage();
627
512
  }
628
513
  updateVisibleCountMessage() {
629
- const remainingNumber = this.maxLength - this.count(this.$textarea.value);
514
+ const remainingNumber = this.maxLength - this.count;
630
515
  const isError = remainingNumber < 0;
631
516
  this.$visibleCountMessage.classList.toggle('govuk-character-count__message--disabled', !this.isOverThreshold());
632
517
  if (!this.$errorMessage) {
@@ -644,16 +529,18 @@ class CharacterCount extends ConfigurableComponent {
644
529
  }
645
530
  this.$screenReaderCountMessage.textContent = this.getCountMessage();
646
531
  }
647
- count(text) {
532
+ updateCount() {
533
+ const text = this.$textarea.value;
648
534
  if (this.config.maxwords) {
649
535
  var _text$match;
650
536
  const tokens = (_text$match = text.match(/\S+/g)) != null ? _text$match : [];
651
- return tokens.length;
537
+ this.count = tokens.length;
538
+ return;
652
539
  }
653
- return text.length;
540
+ this.count = text.length;
654
541
  }
655
542
  getCountMessage() {
656
- const remainingNumber = this.maxLength - this.count(this.$textarea.value);
543
+ const remainingNumber = this.maxLength - this.count;
657
544
  const countType = this.config.maxwords ? 'words' : 'characters';
658
545
  return this.formatCountMessage(remainingNumber, countType);
659
546
  }
@@ -670,7 +557,7 @@ class CharacterCount extends ConfigurableComponent {
670
557
  if (!this.config.threshold) {
671
558
  return true;
672
559
  }
673
- const currentLength = this.count(this.$textarea.value);
560
+ const currentLength = this.count;
674
561
  const maxLength = this.maxLength;
675
562
  const thresholdValue = maxLength * this.config.threshold / 100;
676
563
  return thresholdValue <= currentLength;
@@ -37,6 +37,7 @@ class CharacterCount extends ConfigurableComponent {
37
37
  var _ref, _this$config$maxwords;
38
38
  super($root, config);
39
39
  this.$textarea = void 0;
40
+ this.count = 0;
40
41
  this.$visibleCountMessage = void 0;
41
42
  this.$screenReaderCountMessage = void 0;
42
43
  this.lastInputTimestamp = null;
@@ -72,7 +73,7 @@ class CharacterCount extends ConfigurableComponent {
72
73
  });
73
74
  }
74
75
  this.$errorMessage = this.$root.querySelector('.govuk-error-message');
75
- if (`${$textareaDescription.textContent}`.match(/^\s*$/)) {
76
+ if ($textareaDescription.textContent.match(/^\s*$/)) {
76
77
  $textareaDescription.textContent = this.i18n.t('textareaDescription', {
77
78
  count: this.maxLength
78
79
  });
@@ -92,15 +93,22 @@ class CharacterCount extends ConfigurableComponent {
92
93
  $textareaDescription.classList.add('govuk-visually-hidden');
93
94
  this.$textarea.removeAttribute('maxlength');
94
95
  this.bindChangeEvents();
95
- window.addEventListener('pageshow', () => this.updateCountMessage());
96
+ window.addEventListener('pageshow', () => {
97
+ if (this.$textarea.value !== this.$textarea.textContent) {
98
+ this.updateCount();
99
+ this.updateCountMessage();
100
+ }
101
+ });
102
+ this.updateCount();
96
103
  this.updateCountMessage();
97
104
  }
98
105
  bindChangeEvents() {
99
- this.$textarea.addEventListener('keyup', () => this.handleKeyUp());
106
+ this.$textarea.addEventListener('input', () => this.handleInput());
100
107
  this.$textarea.addEventListener('focus', () => this.handleFocus());
101
108
  this.$textarea.addEventListener('blur', () => this.handleBlur());
102
109
  }
103
- handleKeyUp() {
110
+ handleInput() {
111
+ this.updateCount();
104
112
  this.updateVisibleCountMessage();
105
113
  this.lastInputTimestamp = Date.now();
106
114
  }
@@ -127,7 +135,7 @@ class CharacterCount extends ConfigurableComponent {
127
135
  this.updateScreenReaderCountMessage();
128
136
  }
129
137
  updateVisibleCountMessage() {
130
- const remainingNumber = this.maxLength - this.count(this.$textarea.value);
138
+ const remainingNumber = this.maxLength - this.count;
131
139
  const isError = remainingNumber < 0;
132
140
  this.$visibleCountMessage.classList.toggle('govuk-character-count__message--disabled', !this.isOverThreshold());
133
141
  if (!this.$errorMessage) {
@@ -145,16 +153,18 @@ class CharacterCount extends ConfigurableComponent {
145
153
  }
146
154
  this.$screenReaderCountMessage.textContent = this.getCountMessage();
147
155
  }
148
- count(text) {
156
+ updateCount() {
157
+ const text = this.$textarea.value;
149
158
  if (this.config.maxwords) {
150
159
  var _text$match;
151
160
  const tokens = (_text$match = text.match(/\S+/g)) != null ? _text$match : [];
152
- return tokens.length;
161
+ this.count = tokens.length;
162
+ return;
153
163
  }
154
- return text.length;
164
+ this.count = text.length;
155
165
  }
156
166
  getCountMessage() {
157
- const remainingNumber = this.maxLength - this.count(this.$textarea.value);
167
+ const remainingNumber = this.maxLength - this.count;
158
168
  const countType = this.config.maxwords ? 'words' : 'characters';
159
169
  return this.formatCountMessage(remainingNumber, countType);
160
170
  }
@@ -171,7 +181,7 @@ class CharacterCount extends ConfigurableComponent {
171
181
  if (!this.config.threshold) {
172
182
  return true;
173
183
  }
174
- const currentLength = this.count(this.$textarea.value);
184
+ const currentLength = this.count;
175
185
  const maxLength = this.maxLength;
176
186
  const thresholdValue = maxLength * this.config.threshold / 100;
177
187
  return thresholdValue <= currentLength;
@@ -119,7 +119,7 @@
119
119
  outline-color: Highlight;
120
120
  }
121
121
 
122
- box-shadow: 0 0 0 $govuk-focus-width $govuk-focus-colour;
122
+ box-shadow: 0 0 0 $govuk-focus-width govuk-functional-colour(focus);
123
123
  }
124
124
 
125
125
  // Selected state
@@ -169,7 +169,8 @@
169
169
  @include govuk-responsive-margin(4, "bottom");
170
170
  margin-left: $conditional-margin-left;
171
171
  padding-left: $conditional-padding-left;
172
- border-left: $conditional-border-width solid $govuk-border-colour;
172
+ border-left: $conditional-border-width solid;
173
+ border-left-color: govuk-functional-colour(border);
173
174
 
174
175
  .govuk-frontend-supported &--hidden {
175
176
  display: none;
@@ -271,7 +272,7 @@
271
272
  // Apply an outline for those modes to use instead.
272
273
  outline: $govuk-focus-width dashed transparent;
273
274
  outline-offset: 1px;
274
- box-shadow: 0 0 0 $govuk-hover-width $govuk-hover-colour;
275
+ box-shadow: 0 0 0 $govuk-hover-width govuk-functional-colour(hover);
275
276
  }
276
277
 
277
278
  // Because we've overridden the border-shadow provided by the focus state,
@@ -286,8 +287,8 @@
286
287
  }
287
288
  // prettier-ignore
288
289
  box-shadow:
289
- 0 0 0 $govuk-focus-width $govuk-focus-colour, // 1
290
- 0 0 0 $govuk-hover-width $govuk-hover-colour; // 2
290
+ 0 0 0 $govuk-focus-width govuk-functional-colour(focus), // 1
291
+ 0 0 0 $govuk-hover-width govuk-functional-colour(hover); // 2
291
292
  }
292
293
 
293
294
  // For devices that explicitly don't support hover, don't provide a hover
@@ -302,7 +303,7 @@
302
303
  }
303
304
 
304
305
  .govuk-checkboxes__item:hover .govuk-checkboxes__input:focus + .govuk-checkboxes__label::before {
305
- box-shadow: 0 0 0 $govuk-focus-width $govuk-focus-colour;
306
+ box-shadow: 0 0 0 $govuk-focus-width govuk-functional-colour(focus);
306
307
  }
307
308
  }
308
309
  }
@@ -23,6 +23,12 @@
23
23
  }
24
24
  return $scope.classList.contains('govuk-frontend-supported');
25
25
  }
26
+ function isArray(option) {
27
+ return Array.isArray(option);
28
+ }
29
+ function isObject(option) {
30
+ return !!option && typeof option === 'object' && !isArray(option);
31
+ }
26
32
  function formatErrorMessage(Component, message) {
27
33
  return `${Component.moduleName}: ${message}`;
28
34
  }
@@ -30,9 +36,6 @@
30
36
  * @typedef ComponentWithModuleName
31
37
  * @property {string} moduleName - Name of the component
32
38
  */
33
- /**
34
- * @import { ObjectNested } from './configuration.mjs'
35
- */
36
39
 
37
40
  class GOVUKFrontendError extends Error {
38
41
  constructor(...args) {
@@ -55,7 +58,7 @@
55
58
  class ElementError extends GOVUKFrontendError {
56
59
  constructor(messageOrOptions) {
57
60
  let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
58
- if (typeof messageOrOptions === 'object') {
61
+ if (isObject(messageOrOptions)) {
59
62
  const {
60
63
  component,
61
64
  identifier,
@@ -64,7 +67,9 @@
64
67
  } = messageOrOptions;
65
68
  message = identifier;
66
69
  message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
67
- message = formatErrorMessage(component, message);
70
+ if (component) {
71
+ message = formatErrorMessage(component, message);
72
+ }
68
73
  }
69
74
  super(message);
70
75
  this.name = 'ElementError';
@@ -17,6 +17,12 @@ function isSupported($scope = document.body) {
17
17
  }
18
18
  return $scope.classList.contains('govuk-frontend-supported');
19
19
  }
20
+ function isArray(option) {
21
+ return Array.isArray(option);
22
+ }
23
+ function isObject(option) {
24
+ return !!option && typeof option === 'object' && !isArray(option);
25
+ }
20
26
  function formatErrorMessage(Component, message) {
21
27
  return `${Component.moduleName}: ${message}`;
22
28
  }
@@ -24,9 +30,6 @@ function formatErrorMessage(Component, message) {
24
30
  * @typedef ComponentWithModuleName
25
31
  * @property {string} moduleName - Name of the component
26
32
  */
27
- /**
28
- * @import { ObjectNested } from './configuration.mjs'
29
- */
30
33
 
31
34
  class GOVUKFrontendError extends Error {
32
35
  constructor(...args) {
@@ -49,7 +52,7 @@ class SupportError extends GOVUKFrontendError {
49
52
  class ElementError extends GOVUKFrontendError {
50
53
  constructor(messageOrOptions) {
51
54
  let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
52
- if (typeof messageOrOptions === 'object') {
55
+ if (isObject(messageOrOptions)) {
53
56
  const {
54
57
  component,
55
58
  identifier,
@@ -58,7 +61,9 @@ class ElementError extends GOVUKFrontendError {
58
61
  } = messageOrOptions;
59
62
  message = identifier;
60
63
  message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
61
- message = formatErrorMessage(component, message);
64
+ if (component) {
65
+ message = formatErrorMessage(component, message);
66
+ }
62
67
  }
63
68
  super(message);
64
69
  this.name = 'ElementError';
@@ -13,11 +13,8 @@
13
13
  // changes colours in their browser.
14
14
  border-bottom: $border-bottom-width solid transparent;
15
15
 
16
- @include _govuk-rebrand(
17
- "background-color",
18
- $govuk-template-background-colour,
19
- $_govuk-rebrand-template-background-colour
20
- );
16
+ color: govuk-functional-colour(surface-text);
17
+ background-color: govuk-functional-colour(surface-background);
21
18
  }
22
19
 
23
20
  // Support older browsers which don't hide elements with the `hidden` attribute
@@ -14,6 +14,11 @@
14
14
  display: inline-block;
15
15
  margin-right: govuk-spacing(4);
16
16
  margin-bottom: 0;
17
+
18
+ // Prevents an issue in iOS Safari 18 where the items vertically
19
+ // shift when the value of inputs is changed.
20
+ // https://github.com/alphagov/reported-bugs/issues/90
21
+ vertical-align: bottom;
17
22
  }
18
23
 
19
24
  .govuk-date-input__label {
@@ -46,7 +46,8 @@
46
46
  // like inset text
47
47
  @media screen\0 {
48
48
  .govuk-details {
49
- border-left: $govuk-border-width-wide solid $govuk-border-colour;
49
+ border-left: $govuk-border-width-wide solid;
50
+ border-left-color: govuk-functional-colour(border);
50
51
  }
51
52
 
52
53
  .govuk-details__summary {
@@ -81,11 +82,11 @@
81
82
  padding-left: govuk-spacing(4) + $govuk-border-width;
82
83
 
83
84
  // Style the summary to look like a link...
84
- color: $govuk-link-colour;
85
+ color: govuk-functional-colour(link);
85
86
  cursor: pointer;
86
87
 
87
88
  &:hover {
88
- color: $govuk-link-hover-colour;
89
+ color: govuk-functional-colour(link-hover);
89
90
  }
90
91
 
91
92
  &:focus {
@@ -131,7 +132,8 @@
131
132
  }
132
133
 
133
134
  .govuk-details__text {
134
- border-left: $govuk-border-width solid $govuk-border-colour;
135
+ border-left: $govuk-border-width solid;
136
+ border-left-color: govuk-functional-colour(border);
135
137
  }
136
138
  }
137
139
  }
@@ -7,7 +7,7 @@
7
7
  margin-bottom: govuk-spacing(3);
8
8
  clear: both;
9
9
 
10
- color: $govuk-error-colour;
10
+ color: govuk-functional-colour(error);
11
11
  }
12
12
  }
13
13
 
@@ -7,10 +7,12 @@
7
7
  @include govuk-responsive-padding(4);
8
8
  @include govuk-responsive-margin(8, "bottom");
9
9
 
10
- border: $govuk-border-width solid $govuk-error-colour;
10
+ border: $govuk-border-width solid;
11
+ border-color: govuk-functional-colour(error);
11
12
 
12
13
  &:focus {
13
- outline: $govuk-focus-width solid $govuk-focus-colour;
14
+ outline: $govuk-focus-width solid;
15
+ outline-color: govuk-functional-colour(focus);
14
16
  }
15
17
  }
16
18
 
@@ -4,12 +4,6 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = global.GOVUKFrontend || {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
- function getFragmentFromUrl(url) {
8
- if (!url.includes('#')) {
9
- return undefined;
10
- }
11
- return url.split('#').pop();
12
- }
13
7
  function setFocus($element, options = {}) {
14
8
  var _options$onBeforeFocu;
15
9
  const isFocusable = $element.getAttribute('tabindex');
@@ -66,9 +60,6 @@
66
60
  * @typedef ComponentWithModuleName
67
61
  * @property {string} moduleName - Name of the component
68
62
  */
69
- /**
70
- * @import { ObjectNested } from './configuration.mjs'
71
- */
72
63
 
73
64
  class GOVUKFrontendError extends Error {
74
65
  constructor(...args) {
@@ -97,7 +88,7 @@
97
88
  class ElementError extends GOVUKFrontendError {
98
89
  constructor(messageOrOptions) {
99
90
  let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
100
- if (typeof messageOrOptions === 'object') {
91
+ if (isObject(messageOrOptions)) {
101
92
  const {
102
93
  component,
103
94
  identifier,
@@ -106,7 +97,9 @@
106
97
  } = messageOrOptions;
107
98
  message = identifier;
108
99
  message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
109
- message = formatErrorMessage(component, message);
100
+ if (component) {
101
+ message = formatErrorMessage(component, message);
102
+ }
110
103
  }
111
104
  super(message);
112
105
  this.name = 'ElementError';
@@ -320,6 +313,9 @@
320
313
  * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]
321
314
  * @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
322
315
  */
316
+ /**
317
+ * @import { CompatibleClass, Config, CreateAllOptions, OnErrorCallback } from '../init.mjs'
318
+ */
323
319
 
324
320
  /**
325
321
  * Error summary component
@@ -352,7 +348,7 @@
352
348
  if (!($target instanceof HTMLAnchorElement)) {
353
349
  return false;
354
350
  }
355
- const inputId = getFragmentFromUrl($target.href);
351
+ const inputId = $target.hash.replace('#', '');
356
352
  if (!inputId) {
357
353
  return false;
358
354
  }