govuk_publishing_components 35.11.0 → 35.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +2 -48
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +5 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +2 -2
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +51 -5
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-scroll-tracker.js +225 -0
  7. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +0 -5
  8. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  9. data/app/assets/stylesheets/govuk_publishing_components/components/_document-list.scss +3 -1
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +8 -2
  11. data/app/controllers/govuk_publishing_components/audit_controller.rb +3 -2
  12. data/app/models/govuk_publishing_components/audit_applications.rb +3 -1
  13. data/app/models/govuk_publishing_components/audit_comparer.rb +1 -1
  14. data/app/models/govuk_publishing_components/audit_components.rb +3 -2
  15. data/app/models/govuk_publishing_components/component_wrapper_helper_options.rb +1 -0
  16. data/app/views/govuk_publishing_components/audit/_applications.html.erb +1 -1
  17. data/app/views/govuk_publishing_components/components/_attachment.html.erb +3 -1
  18. data/app/views/govuk_publishing_components/components/_document_list.html.erb +29 -27
  19. data/app/views/govuk_publishing_components/components/_heading.html.erb +8 -5
  20. data/app/views/govuk_publishing_components/components/_tabs.html.erb +30 -14
  21. data/app/views/govuk_publishing_components/components/docs/heading.yml +1 -4
  22. data/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml +1 -6
  23. data/app/views/govuk_publishing_components/components/docs/tabs.yml +26 -3
  24. data/lib/govuk_publishing_components/config.rb +3 -0
  25. data/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb +17 -1
  26. data/lib/govuk_publishing_components/version.rb +1 -1
  27. data/node_modules/govuk-frontend/govuk/all.js +406 -1
  28. data/node_modules/govuk-frontend/govuk/all.js.map +1 -1
  29. data/node_modules/govuk-frontend/govuk/common/govuk-frontend-version.js +1 -1
  30. data/node_modules/govuk-frontend/govuk/components/_all.scss +2 -1
  31. data/node_modules/govuk-frontend/govuk/components/back-link/_index.scss +8 -0
  32. data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +9 -0
  33. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +12 -0
  34. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +21 -0
  35. data/node_modules/govuk-frontend/govuk/components/button/_index.scss +41 -3
  36. data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +44 -0
  37. data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +9 -8
  38. data/node_modules/govuk-frontend/govuk/components/exit-this-page/README.md +15 -0
  39. data/node_modules/govuk-frontend/govuk/components/exit-this-page/_exit-this-page.scss +2 -0
  40. data/node_modules/govuk-frontend/govuk/components/exit-this-page/_index.scss +97 -0
  41. data/node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js +2120 -0
  42. data/node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js.map +1 -0
  43. data/node_modules/govuk-frontend/govuk/components/exit-this-page/fixtures.json +50 -0
  44. data/node_modules/govuk-frontend/govuk/components/exit-this-page/macro-options.json +62 -0
  45. data/node_modules/govuk-frontend/govuk/components/exit-this-page/macro.njk +3 -0
  46. data/node_modules/govuk-frontend/govuk/components/exit-this-page/template.njk +16 -0
  47. data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +9 -8
  48. data/node_modules/govuk-frontend/govuk/core/_govuk-frontend-version.scss +1 -1
  49. data/node_modules/govuk-frontend/govuk/helpers/_visually-hidden.scss +12 -0
  50. data/node_modules/govuk-frontend/govuk/objects/_template.scss +20 -0
  51. data/node_modules/govuk-frontend/govuk-esm/all.mjs +8 -0
  52. data/node_modules/govuk-frontend/govuk-esm/all.mjs.map +1 -1
  53. data/node_modules/govuk-frontend/govuk-esm/common/govuk-frontend-version.mjs +1 -1
  54. data/node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs +406 -0
  55. data/node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs.map +1 -0
  56. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +4 -0
  57. data/node_modules/govuk-frontend/package.json +4 -2
  58. metadata +14 -2
@@ -1 +1 @@
1
- {"version":3,"file":"all.mjs","sources":["../../src/govuk/all.mjs"],"sourcesContent":["import { version } from './common/govuk-frontend-version.mjs'\nimport { nodeListForEach } from './common/index.mjs'\nimport Accordion from './components/accordion/accordion.mjs'\nimport Button from './components/button/button.mjs'\nimport CharacterCount from './components/character-count/character-count.mjs'\nimport Checkboxes from './components/checkboxes/checkboxes.mjs'\nimport Details from './components/details/details.mjs'\nimport ErrorSummary from './components/error-summary/error-summary.mjs'\nimport Header from './components/header/header.mjs'\nimport NotificationBanner from './components/notification-banner/notification-banner.mjs'\nimport Radios from './components/radios/radios.mjs'\nimport SkipLink from './components/skip-link/skip-link.mjs'\nimport Tabs from './components/tabs/tabs.mjs'\n\n/**\n * Initialise all components\n *\n * Use the `data-module` attributes to find, instantiate and init all of the\n * components provided as part of GOV.UK Frontend.\n *\n * @param {Config} [config] - Config for all components\n */\nfunction initAll (config) {\n config = typeof config !== 'undefined' ? config : {}\n\n // Allow the user to initialise GOV.UK Frontend in only certain sections of the page\n // Defaults to the entire document if nothing is set.\n var $scope = config.scope instanceof HTMLElement ? config.scope : document\n\n var $accordions = $scope.querySelectorAll('[data-module=\"govuk-accordion\"]')\n nodeListForEach($accordions, function ($accordion) {\n new Accordion($accordion, config.accordion).init()\n })\n\n var $buttons = $scope.querySelectorAll('[data-module=\"govuk-button\"]')\n nodeListForEach($buttons, function ($button) {\n new Button($button, config.button).init()\n })\n\n var $characterCounts = $scope.querySelectorAll('[data-module=\"govuk-character-count\"]')\n nodeListForEach($characterCounts, function ($characterCount) {\n new CharacterCount($characterCount, config.characterCount).init()\n })\n\n var $checkboxes = $scope.querySelectorAll('[data-module=\"govuk-checkboxes\"]')\n nodeListForEach($checkboxes, function ($checkbox) {\n new Checkboxes($checkbox).init()\n })\n\n var $details = $scope.querySelectorAll('[data-module=\"govuk-details\"]')\n nodeListForEach($details, function ($detail) {\n new Details($detail).init()\n })\n\n // Find first error summary module to enhance.\n var $errorSummary = $scope.querySelector('[data-module=\"govuk-error-summary\"]')\n if ($errorSummary) {\n new ErrorSummary($errorSummary, config.errorSummary).init()\n }\n\n // Find first header module to enhance.\n var $header = $scope.querySelector('[data-module=\"govuk-header\"]')\n if ($header) {\n new Header($header).init()\n }\n\n var $notificationBanners = $scope.querySelectorAll('[data-module=\"govuk-notification-banner\"]')\n nodeListForEach($notificationBanners, function ($notificationBanner) {\n new NotificationBanner($notificationBanner, config.notificationBanner).init()\n })\n\n var $radios = $scope.querySelectorAll('[data-module=\"govuk-radios\"]')\n nodeListForEach($radios, function ($radio) {\n new Radios($radio).init()\n })\n\n // Find first skip link module to enhance.\n var $skipLink = $scope.querySelector('[data-module=\"govuk-skip-link\"]')\n if ($skipLink) {\n new SkipLink($skipLink).init()\n }\n\n var $tabs = $scope.querySelectorAll('[data-module=\"govuk-tabs\"]')\n nodeListForEach($tabs, function ($tabs) {\n new Tabs($tabs).init()\n })\n}\n\nexport {\n initAll,\n version,\n\n // Components\n Accordion,\n Button,\n Details,\n CharacterCount,\n Checkboxes,\n ErrorSummary,\n Header,\n NotificationBanner,\n Radios,\n SkipLink,\n Tabs\n}\n\n/**\n * Config for all components\n *\n * @typedef {object} Config\n * @property {Element} [scope=document] - Scope to query for components\n * @property {import('./components/accordion/accordion.mjs').AccordionConfig} [accordion] - Accordion config\n * @property {import('./components/button/button.mjs').ButtonConfig} [button] - Button config\n * @property {import('./components/character-count/character-count.mjs').CharacterCountConfig} [characterCount] - Character Count config\n * @property {import('./components/error-summary/error-summary.mjs').ErrorSummaryConfig} [errorSummary] - Error Summary config\n * @property {import('./components/notification-banner/notification-banner.mjs').NotificationBannerConfig} [notificationBanner] - Notification Banner config\n */\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA;;;;;;;;AAQA,SAAS,OAAO,EAAE,MAAM,EAAE;EACxB,MAAM,GAAG,OAAO,MAAM,KAAK,WAAW,GAAG,MAAM,GAAG,GAAE;;;;EAIpD,IAAI,MAAM,GAAG,MAAM,CAAC,KAAK,YAAY,WAAW,GAAG,MAAM,CAAC,KAAK,GAAG,SAAQ;;EAE1E,IAAI,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,iCAAiC,EAAC;EAC5E,eAAe,CAAC,WAAW,EAAE,UAAU,UAAU,EAAE;IACjD,IAAI,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,GAAE;GACnD,EAAC;;EAEF,IAAI,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,8BAA8B,EAAC;EACtE,eAAe,CAAC,QAAQ,EAAE,UAAU,OAAO,EAAE;IAC3C,IAAI,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,GAAE;GAC1C,EAAC;;EAEF,IAAI,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC,uCAAuC,EAAC;EACvF,eAAe,CAAC,gBAAgB,EAAE,UAAU,eAAe,EAAE;IAC3D,IAAI,cAAc,CAAC,eAAe,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,GAAE;GAClE,EAAC;;EAEF,IAAI,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,kCAAkC,EAAC;EAC7E,eAAe,CAAC,WAAW,EAAE,UAAU,SAAS,EAAE;IAChD,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,IAAI,GAAE;GACjC,EAAC;;EAEF,IAAI,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,+BAA+B,EAAC;EACvE,eAAe,CAAC,QAAQ,EAAE,UAAU,OAAO,EAAE;IAC3C,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,GAAE;GAC5B,EAAC;;;EAGF,IAAI,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC,qCAAqC,EAAC;EAC/E,IAAI,aAAa,EAAE;IACjB,IAAI,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,GAAE;GAC5D;;;EAGD,IAAI,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,8BAA8B,EAAC;EAClE,IAAI,OAAO,EAAE;IACX,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,GAAE;GAC3B;;EAED,IAAI,oBAAoB,GAAG,MAAM,CAAC,gBAAgB,CAAC,2CAA2C,EAAC;EAC/F,eAAe,CAAC,oBAAoB,EAAE,UAAU,mBAAmB,EAAE;IACnE,IAAI,kBAAkB,CAAC,mBAAmB,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,GAAE;GAC9E,EAAC;;EAEF,IAAI,OAAO,GAAG,MAAM,CAAC,gBAAgB,CAAC,8BAA8B,EAAC;EACrE,eAAe,CAAC,OAAO,EAAE,UAAU,MAAM,EAAE;IACzC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,GAAE;GAC1B,EAAC;;;EAGF,IAAI,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,iCAAiC,EAAC;EACvE,IAAI,SAAS,EAAE;IACb,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,GAAE;GAC/B;;EAED,IAAI,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAC,4BAA4B,EAAC;EACjE,eAAe,CAAC,KAAK,EAAE,UAAU,KAAK,EAAE;IACtC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAE;GACvB,EAAC;CACH;AACD,AAkBA;;;;;;;;;;;GAWG;;;;"}
1
+ {"version":3,"file":"all.mjs","sources":["../../src/govuk/all.mjs"],"sourcesContent":["import { version } from './common/govuk-frontend-version.mjs'\nimport { nodeListForEach } from './common/index.mjs'\nimport Accordion from './components/accordion/accordion.mjs'\nimport Button from './components/button/button.mjs'\nimport CharacterCount from './components/character-count/character-count.mjs'\nimport Checkboxes from './components/checkboxes/checkboxes.mjs'\nimport Details from './components/details/details.mjs'\nimport ErrorSummary from './components/error-summary/error-summary.mjs'\nimport ExitThisPage from './components/exit-this-page/exit-this-page.mjs'\nimport Header from './components/header/header.mjs'\nimport NotificationBanner from './components/notification-banner/notification-banner.mjs'\nimport Radios from './components/radios/radios.mjs'\nimport SkipLink from './components/skip-link/skip-link.mjs'\nimport Tabs from './components/tabs/tabs.mjs'\n\n/**\n * Initialise all components\n *\n * Use the `data-module` attributes to find, instantiate and init all of the\n * components provided as part of GOV.UK Frontend.\n *\n * @param {Config} [config] - Config for all components\n */\nfunction initAll (config) {\n config = typeof config !== 'undefined' ? config : {}\n\n // Allow the user to initialise GOV.UK Frontend in only certain sections of the page\n // Defaults to the entire document if nothing is set.\n var $scope = config.scope instanceof HTMLElement ? config.scope : document\n\n var $accordions = $scope.querySelectorAll('[data-module=\"govuk-accordion\"]')\n nodeListForEach($accordions, function ($accordion) {\n new Accordion($accordion, config.accordion).init()\n })\n\n var $buttons = $scope.querySelectorAll('[data-module=\"govuk-button\"]')\n nodeListForEach($buttons, function ($button) {\n new Button($button, config.button).init()\n })\n\n var $characterCounts = $scope.querySelectorAll('[data-module=\"govuk-character-count\"]')\n nodeListForEach($characterCounts, function ($characterCount) {\n new CharacterCount($characterCount, config.characterCount).init()\n })\n\n var $checkboxes = $scope.querySelectorAll('[data-module=\"govuk-checkboxes\"]')\n nodeListForEach($checkboxes, function ($checkbox) {\n new Checkboxes($checkbox).init()\n })\n\n var $details = $scope.querySelectorAll('[data-module=\"govuk-details\"]')\n nodeListForEach($details, function ($detail) {\n new Details($detail).init()\n })\n\n // Find first error summary module to enhance.\n var $errorSummary = $scope.querySelector('[data-module=\"govuk-error-summary\"]')\n if ($errorSummary) {\n new ErrorSummary($errorSummary, config.errorSummary).init()\n }\n\n var $exitThisPageButtons = $scope.querySelectorAll('[data-module=\"govuk-exit-this-page\"]')\n nodeListForEach($exitThisPageButtons, function ($button) {\n new ExitThisPage($button, config.exitThisPage).init()\n })\n\n // Find first header module to enhance.\n var $header = $scope.querySelector('[data-module=\"govuk-header\"]')\n if ($header) {\n new Header($header).init()\n }\n\n var $notificationBanners = $scope.querySelectorAll('[data-module=\"govuk-notification-banner\"]')\n nodeListForEach($notificationBanners, function ($notificationBanner) {\n new NotificationBanner($notificationBanner, config.notificationBanner).init()\n })\n\n var $radios = $scope.querySelectorAll('[data-module=\"govuk-radios\"]')\n nodeListForEach($radios, function ($radio) {\n new Radios($radio).init()\n })\n\n // Find first skip link module to enhance.\n var $skipLink = $scope.querySelector('[data-module=\"govuk-skip-link\"]')\n if ($skipLink) {\n new SkipLink($skipLink).init()\n }\n\n var $tabs = $scope.querySelectorAll('[data-module=\"govuk-tabs\"]')\n nodeListForEach($tabs, function ($tabs) {\n new Tabs($tabs).init()\n })\n}\n\nexport {\n initAll,\n version,\n\n // Components\n Accordion,\n Button,\n Details,\n CharacterCount,\n Checkboxes,\n ErrorSummary,\n ExitThisPage,\n Header,\n NotificationBanner,\n Radios,\n SkipLink,\n Tabs\n}\n\n/**\n * Config for all components\n *\n * @typedef {object} Config\n * @property {Element} [scope=document] - Scope to query for components\n * @property {import('./components/accordion/accordion.mjs').AccordionConfig} [accordion] - Accordion config\n * @property {import('./components/button/button.mjs').ButtonConfig} [button] - Button config\n * @property {import('./components/character-count/character-count.mjs').CharacterCountConfig} [characterCount] - Character Count config\n * @property {import('./components/error-summary/error-summary.mjs').ErrorSummaryConfig} [errorSummary] - Error Summary config\n * @property {import('./components/exit-this-page/exit-this-page.mjs').ExitThisPageConfig} [exitThisPage] - Exit This Page config\n * @property {import('./components/notification-banner/notification-banner.mjs').NotificationBannerConfig} [notificationBanner] - Notification Banner config\n */\n"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  * It doesn't need to be updated manually.
4
4
  */
5
5
 
6
- var version = '4.6.0';
6
+ var version = '4.7.0';
7
7
 
8
8
  export { version };
9
9
  //# sourceMappingURL=common/govuk-frontend-version.mjs.map
@@ -0,0 +1,406 @@
1
+ import { normaliseDataset } from '../../common/normalise-dataset.mjs';
2
+ import { I18n } from '../../i18n.mjs';
3
+ import '../../vendor/polyfills/Element/prototype/classList.mjs';
4
+ import '../../vendor/polyfills/Event.mjs';
5
+ import '../../vendor/polyfills/Element/prototype/dataset.mjs';
6
+ import '../../vendor/polyfills/Function/prototype/bind.mjs';
7
+ import { nodeListForEach, mergeConfigs, extractConfigByNamespace } from '../../common/index.mjs';
8
+
9
+ /* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
10
+
11
+ /**
12
+ * @constant
13
+ * @type {ExitThisPageTranslations}
14
+ * @see Default value for {@link ExitThisPageConfig.i18n}
15
+ * @default
16
+ */
17
+ var EXIT_THIS_PAGE_TRANSLATIONS = {
18
+ activated: 'Loading.',
19
+ timedOut: 'Exit this page expired.',
20
+ pressTwoMoreTimes: 'Shift, press 2 more times to exit.',
21
+ pressOneMoreTime: 'Shift, press 1 more time to exit.'
22
+ };
23
+
24
+ /**
25
+ * Exit This Page component
26
+ *
27
+ * @class
28
+ * @param {HTMLElement} $module - HTML element that wraps the Exit This Page button
29
+ * @param {ExitThisPageConfig} [config] - Exit This Page config
30
+ */
31
+ function ExitThisPage ($module, config) {
32
+ /** @type {ExitThisPageConfig} */
33
+ var defaultConfig = {
34
+ i18n: EXIT_THIS_PAGE_TRANSLATIONS
35
+ };
36
+
37
+ if (!($module instanceof HTMLElement)) {
38
+ return this
39
+ }
40
+
41
+ var $button = $module.querySelector('.govuk-exit-this-page__button');
42
+ if (!($button instanceof HTMLElement)) {
43
+ return this
44
+ }
45
+
46
+ /**
47
+ * @deprecated Will be made private in v5.0
48
+ * @type {ExitThisPageConfig}
49
+ */
50
+ this.config = mergeConfigs(
51
+ defaultConfig,
52
+ config || {},
53
+ normaliseDataset($module.dataset)
54
+ );
55
+
56
+ this.i18n = new I18n(extractConfigByNamespace(this.config, 'i18n'));
57
+
58
+ /** @deprecated Will be made private in v5.0 */
59
+ this.$module = $module;
60
+
61
+ /** @deprecated Will be made private in v5.0 */
62
+ this.$button = $button;
63
+
64
+ /** @deprecated Will be made private in v5.0 */
65
+ this.$skiplinkButton = document.querySelector('.govuk-js-exit-this-page-skiplink');
66
+
67
+ /** @deprecated Will be made private in v5.0 */
68
+ this.$updateSpan = null;
69
+
70
+ /** @deprecated Will be made private in v5.0 */
71
+ this.$indicatorContainer = null;
72
+
73
+ /** @deprecated Will be made private in v5.0 */
74
+ this.$overlay = null;
75
+
76
+ /** @deprecated Will be made private in v5.0 */
77
+ this.keypressCounter = 0;
78
+
79
+ /** @deprecated Will be made private in v5.0 */
80
+ this.lastKeyWasModified = false;
81
+
82
+ /** @deprecated Will be made private in v5.0 */
83
+ this.timeoutTime = 5000; // milliseconds
84
+
85
+ // Store the timeout events so that we can clear them to avoid user keypresses overlapping
86
+ // setTimeout returns an id that we can use to clear it with clearTimeout,
87
+ // hence the 'Id' suffix
88
+
89
+ /** @deprecated Will be made private in v5.0 */
90
+ this.keypressTimeoutId = null;
91
+
92
+ /** @deprecated Will be made private in v5.0 */
93
+ this.timeoutMessageId = null;
94
+ }
95
+
96
+ /**
97
+ * Create the <span> we use for screen reader announcements.
98
+ *
99
+ * @deprecated Will be made private in v5.0
100
+ */
101
+ ExitThisPage.prototype.initUpdateSpan = function () {
102
+ this.$updateSpan = document.createElement('span');
103
+ this.$updateSpan.setAttribute('role', 'status');
104
+ this.$updateSpan.className = 'govuk-visually-hidden';
105
+
106
+ this.$module.appendChild(this.$updateSpan);
107
+ };
108
+
109
+ /**
110
+ * Create button click handlers.
111
+ *
112
+ * @deprecated Will be made private in v5.0
113
+ */
114
+ ExitThisPage.prototype.initButtonClickHandler = function () {
115
+ // Main EtP button
116
+ this.$button.addEventListener('click', this.handleClick.bind(this));
117
+
118
+ // EtP skiplink
119
+ if (this.$skiplinkButton) {
120
+ this.$skiplinkButton.addEventListener('click', this.handleClick.bind(this));
121
+ }
122
+ };
123
+
124
+ /**
125
+ * Create the HTML for the 'three lights' indicator on the button.
126
+ *
127
+ * @deprecated Will be made private in v5.0
128
+ */
129
+ ExitThisPage.prototype.buildIndicator = function () {
130
+ // Build container
131
+ // Putting `aria-hidden` on it as it won't contain any readable information
132
+ this.$indicatorContainer = document.createElement('div');
133
+ this.$indicatorContainer.className = 'govuk-exit-this-page__indicator';
134
+ this.$indicatorContainer.setAttribute('aria-hidden', 'true');
135
+
136
+ // Create three 'lights' and place them within the container
137
+ for (var i = 0; i < 3; i++) {
138
+ var $indicator = document.createElement('div');
139
+ $indicator.className = 'govuk-exit-this-page__indicator-light';
140
+ this.$indicatorContainer.appendChild($indicator);
141
+ }
142
+
143
+ // Append it all to the module
144
+ this.$button.appendChild(this.$indicatorContainer);
145
+ };
146
+
147
+ /**
148
+ * Update whether the lights are visible and which ones are lit up depending on
149
+ * the value of `keypressCounter`.
150
+ *
151
+ * @deprecated Will be made private in v5.0
152
+ */
153
+ ExitThisPage.prototype.updateIndicator = function () {
154
+ // Show or hide the indicator container depending on keypressCounter value
155
+ if (this.keypressCounter > 0) {
156
+ this.$indicatorContainer.classList.add('govuk-exit-this-page__indicator--visible');
157
+ } else {
158
+ this.$indicatorContainer.classList.remove('govuk-exit-this-page__indicator--visible');
159
+ }
160
+
161
+ // Turn on only the indicators we want on
162
+ var $indicators = this.$indicatorContainer.querySelectorAll(
163
+ '.govuk-exit-this-page__indicator-light'
164
+ );
165
+ nodeListForEach($indicators, function ($indicator, index) {
166
+ $indicator.classList.toggle(
167
+ 'govuk-exit-this-page__indicator-light--on',
168
+ index < this.keypressCounter
169
+ );
170
+ }.bind(this));
171
+ };
172
+
173
+ /**
174
+ * Initiates the redirection away from the current page.
175
+ * Includes the loading overlay functionality, which covers the current page with a
176
+ * white overlay so that the contents are not visible during the loading
177
+ * process. This is particularly important on slow network connections.
178
+ *
179
+ * @deprecated Will be made private in v5.0
180
+ */
181
+ ExitThisPage.prototype.exitPage = function () {
182
+ this.$updateSpan.innerText = '';
183
+
184
+ // Blank the page
185
+ // As well as creating an overlay with text, we also set the body to hidden
186
+ // to prevent screen reader and sequential navigation users potentially
187
+ // navigating through the page behind the overlay during loading
188
+ document.body.classList.add('govuk-exit-this-page-hide-content');
189
+ this.$overlay = document.createElement('div');
190
+ this.$overlay.className = 'govuk-exit-this-page-overlay';
191
+ this.$overlay.setAttribute('role', 'alert');
192
+
193
+ // we do these this way round, thus incurring a second paint, because changing
194
+ // the element text after adding it means that screen readers pick up the
195
+ // announcement more reliably.
196
+ document.body.appendChild(this.$overlay);
197
+ this.$overlay.innerText = this.i18n.t('activated');
198
+
199
+ window.location.href = this.$button.getAttribute('href');
200
+ };
201
+
202
+ /**
203
+ * Pre-activation logic for when the button is clicked/activated via mouse or
204
+ * pointer.
205
+ *
206
+ * We do this to differentiate it from the keyboard activation event because we
207
+ * need to run `e.preventDefault` as the button or skiplink are both links and we
208
+ * want to apply some additional logic in `exitPage` before navigating.
209
+ *
210
+ * @deprecated Will be made private in v5.0
211
+ * @param {MouseEvent} event - mouse click event
212
+ */
213
+ ExitThisPage.prototype.handleClick = function (event) {
214
+ event.preventDefault();
215
+ this.exitPage();
216
+ };
217
+
218
+ /**
219
+ * Logic for the 'quick escape' keyboard sequence functionality (pressing the
220
+ * Shift key three times without interruption, within a time limit).
221
+ *
222
+ * @deprecated Will be made private in v5.0
223
+ * @param {KeyboardEvent} event - keyup event
224
+ */
225
+ ExitThisPage.prototype.handleKeypress = function (event) {
226
+ // Detect if the 'Shift' key has been pressed. We want to only do things if it
227
+ // was pressed by itself and not in a combination with another key—so we keep
228
+ // track of whether the preceding keyup had shiftKey: true on it, and if it
229
+ // did, we ignore the next Shift keyup event.
230
+ //
231
+ // This works because using Shift as a modifier key (e.g. pressing Shift + A)
232
+ // will fire TWO keyup events, one for A (with e.shiftKey: true) and the other
233
+ // for Shift (with e.shiftKey: false).
234
+ if (
235
+ (event.key === 'Shift' || event.keyCode === 16 || event.which === 16) &&
236
+ !this.lastKeyWasModified
237
+ ) {
238
+ this.keypressCounter += 1;
239
+
240
+ // Update the indicator before the below if statement can reset it back to 0
241
+ this.updateIndicator();
242
+
243
+ // Clear the timeout for the keypress timeout message clearing itself
244
+ if (this.timeoutMessageId !== null) {
245
+ clearTimeout(this.timeoutMessageId);
246
+ this.timeoutMessageId = null;
247
+ }
248
+
249
+ if (this.keypressCounter >= 3) {
250
+ this.keypressCounter = 0;
251
+
252
+ if (this.keypressTimeoutId !== null) {
253
+ clearTimeout(this.keypressTimeoutId);
254
+ this.keypressTimeoutId = null;
255
+ }
256
+
257
+ this.exitPage();
258
+ } else {
259
+ if (this.keypressCounter === 1) {
260
+ this.$updateSpan.innerText = this.i18n.t('pressTwoMoreTimes');
261
+ } else {
262
+ this.$updateSpan.innerText = this.i18n.t('pressOneMoreTime');
263
+ }
264
+ }
265
+
266
+ this.setKeypressTimer();
267
+ } else if (this.keypressTimeoutId !== null) {
268
+ // If the user pressed any key other than 'Shift', after having pressed
269
+ // 'Shift' and activating the timer, stop and reset the timer.
270
+ this.resetKeypressTimer();
271
+ }
272
+
273
+ // Keep track of whether the Shift modifier key was held during this keypress
274
+ this.lastKeyWasModified = event.shiftKey;
275
+ };
276
+
277
+ /**
278
+ * Starts the 'quick escape' keyboard sequence timer.
279
+ *
280
+ * This can be invoked several times. We want this to be possible so that the
281
+ * timer is restarted each time the shortcut key is pressed (e.g. the user has
282
+ * up to n seconds between each keypress, rather than n seconds to invoke the
283
+ * entire sequence.)
284
+ *
285
+ * @deprecated Will be made private in v5.0
286
+ */
287
+ ExitThisPage.prototype.setKeypressTimer = function () {
288
+ // Clear any existing timeout. This is so only one timer is running even if
289
+ // there are multiple keypresses in quick succession.
290
+ clearTimeout(this.keypressTimeoutId);
291
+
292
+ // Set a fresh timeout
293
+ this.keypressTimeoutId = setTimeout(
294
+ this.resetKeypressTimer.bind(this),
295
+ this.timeoutTime
296
+ );
297
+ };
298
+
299
+ /**
300
+ * Stops and resets the 'quick escape' keyboard sequence timer.
301
+ *
302
+ * @deprecated Will be made private in v5.0
303
+ */
304
+ ExitThisPage.prototype.resetKeypressTimer = function () {
305
+ clearTimeout(this.keypressTimeoutId);
306
+ this.keypressTimeoutId = null;
307
+
308
+ this.keypressCounter = 0;
309
+ this.$updateSpan.innerText = this.i18n.t('timedOut');
310
+
311
+ this.timeoutMessageId = setTimeout(function () {
312
+ this.$updateSpan.innerText = '';
313
+ }.bind(this), this.timeoutTime);
314
+
315
+ this.updateIndicator();
316
+ };
317
+
318
+ /**
319
+ * Reset the page using the EtP button
320
+ *
321
+ * We use this in situations where a user may re-enter a page using the browser
322
+ * back button. In these cases, the browser can choose to restore the state of
323
+ * the page as it was previously, including restoring the 'ghost page' overlay,
324
+ * the announcement span having it's role set to "alert" and the keypress
325
+ * indicator still active, leaving the page in an unusable state.
326
+ *
327
+ * By running this check when the page is shown, we can programatically restore
328
+ * the page and the component to a "default" state
329
+ *
330
+ * @deprecated Will be made private in v5.0
331
+ */
332
+ ExitThisPage.prototype.resetPage = function () {
333
+ // If an overlay is set, remove it and reset the value
334
+ document.body.classList.remove('govuk-exit-this-page-hide-content');
335
+
336
+ if (this.$overlay) {
337
+ this.$overlay.remove();
338
+ this.$overlay = null;
339
+ }
340
+
341
+ // Ensure the announcement span's role is status, not alert and clear any text
342
+ this.$updateSpan.setAttribute('role', 'status');
343
+ this.$updateSpan.innerText = '';
344
+
345
+ // Sync the keypress indicator lights
346
+ this.updateIndicator();
347
+
348
+ // If the timeouts are active, clear them
349
+ if (this.keypressTimeoutId) {
350
+ clearTimeout(this.keypressTimeoutId);
351
+ }
352
+
353
+ if (this.timeoutMessageId) {
354
+ clearTimeout(this.timeoutMessageId);
355
+ }
356
+ };
357
+
358
+ /**
359
+ * Initialise component
360
+ */
361
+ ExitThisPage.prototype.init = function () {
362
+ this.buildIndicator();
363
+ this.initUpdateSpan();
364
+ this.initButtonClickHandler();
365
+
366
+ // Check to see if this has already been done by a previous initialisation of ExitThisPage
367
+ if (!('govukFrontendExitThisPageKeypress' in document.body.dataset)) {
368
+ document.addEventListener('keyup', this.handleKeypress.bind(this), true);
369
+ document.body.dataset.govukFrontendExitThisPageKeypress = 'true';
370
+ }
371
+
372
+ // When the page is restored after navigating 'back' in some browsers the
373
+ // blank overlay remains present, rendering the page unusable. Here, we check
374
+ // to see if it's present on page (re)load, and remove it if so.
375
+ window.addEventListener(
376
+ 'onpageshow' in window ? 'pageshow' : 'DOMContentLoaded',
377
+ this.resetPage.bind(this)
378
+ );
379
+ };
380
+
381
+ /**
382
+ * Exit this Page config
383
+ *
384
+ * @typedef {object} ExitThisPageConfig
385
+ * @property {ExitThisPageTranslations} [i18n = EXIT_THIS_PAGE_TRANSLATIONS] - See constant {@link EXIT_THIS_PAGE_TRANSLATIONS}
386
+ */
387
+
388
+ /**
389
+ * Exit this Page translations
390
+ *
391
+ * @typedef {object} ExitThisPageTranslations
392
+ *
393
+ * Messages used by the component programatically inserted text, including
394
+ * overlay text and screen reader announcements.
395
+ * @property {string} [activated] - Screen reader announcement for when EtP
396
+ * keypress functionality has been successfully activated.
397
+ * @property {string} [timedOut] - Screen reader announcement for when the EtP
398
+ * keypress functionality has timed out.
399
+ * @property {string} [pressTwoMoreTimes] - Screen reader announcement informing
400
+ * the user they must press the activation key two more times.
401
+ * @property {string} [pressOneMoreTime] - Screen reader announcement informing
402
+ * the user they must press the activation key one more time.
403
+ */
404
+
405
+ export default ExitThisPage;
406
+ //# sourceMappingURL=components/exit-this-page/exit-this-page.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-this-page.mjs","sources":["../../../../src/govuk/components/exit-this-page/exit-this-page.mjs"],"sourcesContent":["/* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */\n\nimport { normaliseDataset } from '../../common/normalise-dataset.mjs'\nimport { nodeListForEach, mergeConfigs, extractConfigByNamespace } from '../../common.mjs'\nimport { I18n } from '../../i18n.mjs'\nimport '../../vendor/polyfills/Element/prototype/classList.mjs'\nimport '../../vendor/polyfills/Event.mjs' // addEventListener, event.target normalization and DOMContentLoaded\nimport '../../vendor/polyfills/Element/prototype/dataset.mjs'\nimport '../../vendor/polyfills/Function/prototype/bind.mjs'\n\n/**\n * @constant\n * @type {ExitThisPageTranslations}\n * @see Default value for {@link ExitThisPageConfig.i18n}\n * @default\n */\nvar EXIT_THIS_PAGE_TRANSLATIONS = {\n activated: 'Loading.',\n timedOut: 'Exit this page expired.',\n pressTwoMoreTimes: 'Shift, press 2 more times to exit.',\n pressOneMoreTime: 'Shift, press 1 more time to exit.'\n}\n\n/**\n * Exit This Page component\n *\n * @class\n * @param {HTMLElement} $module - HTML element that wraps the Exit This Page button\n * @param {ExitThisPageConfig} [config] - Exit This Page config\n */\nfunction ExitThisPage ($module, config) {\n /** @type {ExitThisPageConfig} */\n var defaultConfig = {\n i18n: EXIT_THIS_PAGE_TRANSLATIONS\n }\n\n if (!($module instanceof HTMLElement)) {\n return this\n }\n\n var $button = $module.querySelector('.govuk-exit-this-page__button')\n if (!($button instanceof HTMLElement)) {\n return this\n }\n\n /**\n * @deprecated Will be made private in v5.0\n * @type {ExitThisPageConfig}\n */\n this.config = mergeConfigs(\n defaultConfig,\n config || {},\n normaliseDataset($module.dataset)\n )\n\n this.i18n = new I18n(extractConfigByNamespace(this.config, 'i18n'))\n\n /** @deprecated Will be made private in v5.0 */\n this.$module = $module\n\n /** @deprecated Will be made private in v5.0 */\n this.$button = $button\n\n /** @deprecated Will be made private in v5.0 */\n this.$skiplinkButton = document.querySelector('.govuk-js-exit-this-page-skiplink')\n\n /** @deprecated Will be made private in v5.0 */\n this.$updateSpan = null\n\n /** @deprecated Will be made private in v5.0 */\n this.$indicatorContainer = null\n\n /** @deprecated Will be made private in v5.0 */\n this.$overlay = null\n\n /** @deprecated Will be made private in v5.0 */\n this.keypressCounter = 0\n\n /** @deprecated Will be made private in v5.0 */\n this.lastKeyWasModified = false\n\n /** @deprecated Will be made private in v5.0 */\n this.timeoutTime = 5000 // milliseconds\n\n // Store the timeout events so that we can clear them to avoid user keypresses overlapping\n // setTimeout returns an id that we can use to clear it with clearTimeout,\n // hence the 'Id' suffix\n\n /** @deprecated Will be made private in v5.0 */\n this.keypressTimeoutId = null\n\n /** @deprecated Will be made private in v5.0 */\n this.timeoutMessageId = null\n}\n\n/**\n * Create the <span> we use for screen reader announcements.\n *\n * @deprecated Will be made private in v5.0\n */\nExitThisPage.prototype.initUpdateSpan = function () {\n this.$updateSpan = document.createElement('span')\n this.$updateSpan.setAttribute('role', 'status')\n this.$updateSpan.className = 'govuk-visually-hidden'\n\n this.$module.appendChild(this.$updateSpan)\n}\n\n/**\n * Create button click handlers.\n *\n * @deprecated Will be made private in v5.0\n */\nExitThisPage.prototype.initButtonClickHandler = function () {\n // Main EtP button\n this.$button.addEventListener('click', this.handleClick.bind(this))\n\n // EtP skiplink\n if (this.$skiplinkButton) {\n this.$skiplinkButton.addEventListener('click', this.handleClick.bind(this))\n }\n}\n\n/**\n * Create the HTML for the 'three lights' indicator on the button.\n *\n * @deprecated Will be made private in v5.0\n */\nExitThisPage.prototype.buildIndicator = function () {\n // Build container\n // Putting `aria-hidden` on it as it won't contain any readable information\n this.$indicatorContainer = document.createElement('div')\n this.$indicatorContainer.className = 'govuk-exit-this-page__indicator'\n this.$indicatorContainer.setAttribute('aria-hidden', 'true')\n\n // Create three 'lights' and place them within the container\n for (var i = 0; i < 3; i++) {\n var $indicator = document.createElement('div')\n $indicator.className = 'govuk-exit-this-page__indicator-light'\n this.$indicatorContainer.appendChild($indicator)\n }\n\n // Append it all to the module\n this.$button.appendChild(this.$indicatorContainer)\n}\n\n/**\n * Update whether the lights are visible and which ones are lit up depending on\n * the value of `keypressCounter`.\n *\n * @deprecated Will be made private in v5.0\n */\nExitThisPage.prototype.updateIndicator = function () {\n // Show or hide the indicator container depending on keypressCounter value\n if (this.keypressCounter > 0) {\n this.$indicatorContainer.classList.add('govuk-exit-this-page__indicator--visible')\n } else {\n this.$indicatorContainer.classList.remove('govuk-exit-this-page__indicator--visible')\n }\n\n // Turn on only the indicators we want on\n var $indicators = this.$indicatorContainer.querySelectorAll(\n '.govuk-exit-this-page__indicator-light'\n )\n nodeListForEach($indicators, function ($indicator, index) {\n $indicator.classList.toggle(\n 'govuk-exit-this-page__indicator-light--on',\n index < this.keypressCounter\n )\n }.bind(this))\n}\n\n/**\n * Initiates the redirection away from the current page.\n * Includes the loading overlay functionality, which covers the current page with a\n * white overlay so that the contents are not visible during the loading\n * process. This is particularly important on slow network connections.\n *\n * @deprecated Will be made private in v5.0\n */\nExitThisPage.prototype.exitPage = function () {\n this.$updateSpan.innerText = ''\n\n // Blank the page\n // As well as creating an overlay with text, we also set the body to hidden\n // to prevent screen reader and sequential navigation users potentially\n // navigating through the page behind the overlay during loading\n document.body.classList.add('govuk-exit-this-page-hide-content')\n this.$overlay = document.createElement('div')\n this.$overlay.className = 'govuk-exit-this-page-overlay'\n this.$overlay.setAttribute('role', 'alert')\n\n // we do these this way round, thus incurring a second paint, because changing\n // the element text after adding it means that screen readers pick up the\n // announcement more reliably.\n document.body.appendChild(this.$overlay)\n this.$overlay.innerText = this.i18n.t('activated')\n\n window.location.href = this.$button.getAttribute('href')\n}\n\n/**\n * Pre-activation logic for when the button is clicked/activated via mouse or\n * pointer.\n *\n * We do this to differentiate it from the keyboard activation event because we\n * need to run `e.preventDefault` as the button or skiplink are both links and we\n * want to apply some additional logic in `exitPage` before navigating.\n *\n * @deprecated Will be made private in v5.0\n * @param {MouseEvent} event - mouse click event\n */\nExitThisPage.prototype.handleClick = function (event) {\n event.preventDefault()\n this.exitPage()\n}\n\n/**\n * Logic for the 'quick escape' keyboard sequence functionality (pressing the\n * Shift key three times without interruption, within a time limit).\n *\n * @deprecated Will be made private in v5.0\n * @param {KeyboardEvent} event - keyup event\n */\nExitThisPage.prototype.handleKeypress = function (event) {\n // Detect if the 'Shift' key has been pressed. We want to only do things if it\n // was pressed by itself and not in a combination with another key—so we keep\n // track of whether the preceding keyup had shiftKey: true on it, and if it\n // did, we ignore the next Shift keyup event.\n //\n // This works because using Shift as a modifier key (e.g. pressing Shift + A)\n // will fire TWO keyup events, one for A (with e.shiftKey: true) and the other\n // for Shift (with e.shiftKey: false).\n if (\n (event.key === 'Shift' || event.keyCode === 16 || event.which === 16) &&\n !this.lastKeyWasModified\n ) {\n this.keypressCounter += 1\n\n // Update the indicator before the below if statement can reset it back to 0\n this.updateIndicator()\n\n // Clear the timeout for the keypress timeout message clearing itself\n if (this.timeoutMessageId !== null) {\n clearTimeout(this.timeoutMessageId)\n this.timeoutMessageId = null\n }\n\n if (this.keypressCounter >= 3) {\n this.keypressCounter = 0\n\n if (this.keypressTimeoutId !== null) {\n clearTimeout(this.keypressTimeoutId)\n this.keypressTimeoutId = null\n }\n\n this.exitPage()\n } else {\n if (this.keypressCounter === 1) {\n this.$updateSpan.innerText = this.i18n.t('pressTwoMoreTimes')\n } else {\n this.$updateSpan.innerText = this.i18n.t('pressOneMoreTime')\n }\n }\n\n this.setKeypressTimer()\n } else if (this.keypressTimeoutId !== null) {\n // If the user pressed any key other than 'Shift', after having pressed\n // 'Shift' and activating the timer, stop and reset the timer.\n this.resetKeypressTimer()\n }\n\n // Keep track of whether the Shift modifier key was held during this keypress\n this.lastKeyWasModified = event.shiftKey\n}\n\n/**\n * Starts the 'quick escape' keyboard sequence timer.\n *\n * This can be invoked several times. We want this to be possible so that the\n * timer is restarted each time the shortcut key is pressed (e.g. the user has\n * up to n seconds between each keypress, rather than n seconds to invoke the\n * entire sequence.)\n *\n * @deprecated Will be made private in v5.0\n */\nExitThisPage.prototype.setKeypressTimer = function () {\n // Clear any existing timeout. This is so only one timer is running even if\n // there are multiple keypresses in quick succession.\n clearTimeout(this.keypressTimeoutId)\n\n // Set a fresh timeout\n this.keypressTimeoutId = setTimeout(\n this.resetKeypressTimer.bind(this),\n this.timeoutTime\n )\n}\n\n/**\n * Stops and resets the 'quick escape' keyboard sequence timer.\n *\n * @deprecated Will be made private in v5.0\n */\nExitThisPage.prototype.resetKeypressTimer = function () {\n clearTimeout(this.keypressTimeoutId)\n this.keypressTimeoutId = null\n\n this.keypressCounter = 0\n this.$updateSpan.innerText = this.i18n.t('timedOut')\n\n this.timeoutMessageId = setTimeout(function () {\n this.$updateSpan.innerText = ''\n }.bind(this), this.timeoutTime)\n\n this.updateIndicator()\n}\n\n/**\n * Reset the page using the EtP button\n *\n * We use this in situations where a user may re-enter a page using the browser\n * back button. In these cases, the browser can choose to restore the state of\n * the page as it was previously, including restoring the 'ghost page' overlay,\n * the announcement span having it's role set to \"alert\" and the keypress\n * indicator still active, leaving the page in an unusable state.\n *\n * By running this check when the page is shown, we can programatically restore\n * the page and the component to a \"default\" state\n *\n * @deprecated Will be made private in v5.0\n */\nExitThisPage.prototype.resetPage = function () {\n // If an overlay is set, remove it and reset the value\n document.body.classList.remove('govuk-exit-this-page-hide-content')\n\n if (this.$overlay) {\n this.$overlay.remove()\n this.$overlay = null\n }\n\n // Ensure the announcement span's role is status, not alert and clear any text\n this.$updateSpan.setAttribute('role', 'status')\n this.$updateSpan.innerText = ''\n\n // Sync the keypress indicator lights\n this.updateIndicator()\n\n // If the timeouts are active, clear them\n if (this.keypressTimeoutId) {\n clearTimeout(this.keypressTimeoutId)\n }\n\n if (this.timeoutMessageId) {\n clearTimeout(this.timeoutMessageId)\n }\n}\n\n/**\n * Initialise component\n */\nExitThisPage.prototype.init = function () {\n this.buildIndicator()\n this.initUpdateSpan()\n this.initButtonClickHandler()\n\n // Check to see if this has already been done by a previous initialisation of ExitThisPage\n if (!('govukFrontendExitThisPageKeypress' in document.body.dataset)) {\n document.addEventListener('keyup', this.handleKeypress.bind(this), true)\n document.body.dataset.govukFrontendExitThisPageKeypress = 'true'\n }\n\n // When the page is restored after navigating 'back' in some browsers the\n // blank overlay remains present, rendering the page unusable. Here, we check\n // to see if it's present on page (re)load, and remove it if so.\n window.addEventListener(\n 'onpageshow' in window ? 'pageshow' : 'DOMContentLoaded',\n this.resetPage.bind(this)\n )\n}\n\nexport default ExitThisPage\n\n/**\n * Exit this Page config\n *\n * @typedef {object} ExitThisPageConfig\n * @property {ExitThisPageTranslations} [i18n = EXIT_THIS_PAGE_TRANSLATIONS] - See constant {@link EXIT_THIS_PAGE_TRANSLATIONS}\n */\n\n/**\n * Exit this Page translations\n *\n * @typedef {object} ExitThisPageTranslations\n *\n * Messages used by the component programatically inserted text, including\n * overlay text and screen reader announcements.\n * @property {string} [activated] - Screen reader announcement for when EtP\n * keypress functionality has been successfully activated.\n * @property {string} [timedOut] - Screen reader announcement for when the EtP\n * keypress functionality has timed out.\n * @property {string} [pressTwoMoreTimes] - Screen reader announcement informing\n * the user they must press the activation key two more times.\n * @property {string} [pressOneMoreTime] - Screen reader announcement informing\n * the user they must press the activation key one more time.\n */\n"],"names":[],"mappings":"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"}
@@ -55,6 +55,10 @@
55
55
  "importFrom": "govuk/components/error-summary/macro.njk",
56
56
  "macroName": "govukErrorSummary"
57
57
  },
58
+ {
59
+ "importFrom": "govuk/components/exit-this-page/macro.njk",
60
+ "macroName": "govukExitThisPage"
61
+ },
58
62
  {
59
63
  "importFrom": "govuk/components/fieldset/macro.njk",
60
64
  "macroName": "govukFieldset"
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "govuk-frontend",
3
3
  "description": "GOV.UK Frontend contains the code you need to start building a user interface for government platforms and services.",
4
- "version": "4.6.0",
4
+ "version": "4.7.0",
5
5
  "main": "govuk/all.js",
6
6
  "module": "govuk-esm/all.mjs",
7
+ "sass": "govuk/all.scss",
7
8
  "exports": {
8
9
  ".": {
9
10
  "sass": "./govuk/all.scss",
@@ -11,13 +12,14 @@
11
12
  "require": "./govuk/all.js"
12
13
  },
13
14
  "./govuk/": "./govuk/",
15
+ "./govuk/*": "./govuk/*",
14
16
  "./govuk-esm/": "./govuk-esm/",
17
+ "./govuk-esm/*": "./govuk-esm/*",
15
18
  "./package.json": "./package.json"
16
19
  },
17
20
  "sideEffects": [
18
21
  "govuk-esm/vendor/**"
19
22
  ],
20
- "sass": "govuk/all.scss",
21
23
  "engines": {
22
24
  "node": ">= 4.2.0"
23
25
  },
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_publishing_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 35.11.0
4
+ version: 35.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-18 00:00:00.000000000 Z
11
+ date: 2023-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: govuk_app_config
@@ -448,6 +448,7 @@ files:
448
448
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js
449
449
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js
450
450
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js
451
+ - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-scroll-tracker.js
451
452
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-smart-answer-results-tracker.js
452
453
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js
453
454
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js
@@ -1010,6 +1011,8 @@ files:
1010
1011
  - node_modules/govuk-frontend/govuk-esm/components/details/details.mjs.map
1011
1012
  - node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs
1012
1013
  - node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs.map
1014
+ - node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs
1015
+ - node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs.map
1013
1016
  - node_modules/govuk-frontend/govuk-esm/components/header/header.mjs
1014
1017
  - node_modules/govuk-frontend/govuk-esm/components/header/header.mjs.map
1015
1018
  - node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs
@@ -1175,6 +1178,15 @@ files:
1175
1178
  - node_modules/govuk-frontend/govuk/components/error-summary/macro-options.json
1176
1179
  - node_modules/govuk-frontend/govuk/components/error-summary/macro.njk
1177
1180
  - node_modules/govuk-frontend/govuk/components/error-summary/template.njk
1181
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/README.md
1182
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/_exit-this-page.scss
1183
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/_index.scss
1184
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js
1185
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js.map
1186
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/fixtures.json
1187
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/macro-options.json
1188
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/macro.njk
1189
+ - node_modules/govuk-frontend/govuk/components/exit-this-page/template.njk
1178
1190
  - node_modules/govuk-frontend/govuk/components/fieldset/README.md
1179
1191
  - node_modules/govuk-frontend/govuk/components/fieldset/_fieldset.scss
1180
1192
  - node_modules/govuk-frontend/govuk/components/fieldset/_index.scss