govuk_publishing_components 44.0.0 → 44.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/govuk_publishing_components/crests/dbt_crest_18px_x2.png +0 -0
  3. data/app/assets/images/govuk_publishing_components/crests/ho_crest_18px_x2.png +0 -0
  4. data/app/assets/images/govuk_publishing_components/crests/mod_crest_18px_x2.png +0 -0
  5. data/app/assets/images/govuk_publishing_components/crests/org_crest_18px_x2.png +0 -0
  6. data/app/assets/images/govuk_publishing_components/crests/portcullis_18px_x2.png +0 -0
  7. data/app/assets/images/govuk_publishing_components/crests/so_crest_18px_x2.png +0 -0
  8. data/app/assets/images/govuk_publishing_components/crests/wales_crest_18px_x2.png +0 -0
  9. data/lib/govuk_publishing_components/version.rb +1 -1
  10. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +336 -225
  11. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
  12. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +334 -226
  13. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
  14. data/node_modules/govuk-frontend/dist/govuk/all.mjs +3 -0
  15. data/node_modules/govuk-frontend/dist/govuk/all.mjs.map +1 -1
  16. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.svg +1 -0
  17. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
  18. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +21 -1
  19. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
  20. data/node_modules/govuk-frontend/dist/govuk/components/_index.scss +1 -0
  21. data/node_modules/govuk-frontend/dist/govuk/components/_index.scss.map +1 -1
  22. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +92 -26
  23. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js.map +1 -1
  24. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +92 -26
  25. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs.map +1 -1
  26. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +12 -21
  27. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
  28. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +86 -20
  29. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js.map +1 -1
  30. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +86 -20
  31. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs.map +1 -1
  32. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +6 -16
  33. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
  34. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +89 -23
  35. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js.map +1 -1
  36. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +89 -23
  37. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs.map +1 -1
  38. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +10 -19
  39. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs.map +1 -1
  40. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +113 -47
  41. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js.map +1 -1
  42. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +113 -47
  43. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
  44. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs +7 -16
  45. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs.map +1 -1
  46. data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss +7 -2
  47. data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss.map +1 -1
  48. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +86 -20
  49. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js.map +1 -1
  50. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +86 -20
  51. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs.map +1 -1
  52. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -16
  53. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
  54. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +87 -21
  55. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js.map +1 -1
  56. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +87 -21
  57. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs.map +1 -1
  58. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +7 -16
  59. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs.map +1 -1
  60. data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss +8 -10
  61. data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss.map +1 -1
  62. data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss +8 -0
  63. data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss.map +1 -1
  64. data/node_modules/govuk-frontend/dist/govuk/components/header/fixtures.json +12 -0
  65. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +87 -21
  66. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js.map +1 -1
  67. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +87 -21
  68. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs.map +1 -1
  69. data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs +7 -16
  70. data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs.map +1 -1
  71. data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-full-width-border.html +24 -0
  72. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +86 -20
  73. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js.map +1 -1
  74. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +86 -20
  75. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs.map +1 -1
  76. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -16
  77. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
  78. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +89 -23
  79. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js.map +1 -1
  80. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +89 -23
  81. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs.map +1 -1
  82. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +9 -18
  83. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
  84. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +113 -47
  85. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js.map +1 -1
  86. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +113 -47
  87. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
  88. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs +7 -16
  89. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs.map +1 -1
  90. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/README.md +15 -0
  91. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss +168 -0
  92. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss.map +1 -0
  93. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss +4 -0
  94. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss.map +1 -0
  95. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json +464 -0
  96. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro-options.json +138 -0
  97. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro.njk +3 -0
  98. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +249 -0
  99. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -0
  100. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +241 -0
  101. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -0
  102. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs +85 -0
  103. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs.map +1 -0
  104. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-default.html +57 -0
  105. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-html-navigation-items.html +49 -0
  106. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-large-navigation.html +153 -0
  107. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-long-service-name.html +20 -0
  108. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-a-current-item.html +58 -0
  109. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-an-active-item.html +58 -0
  110. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-non-link-navigation-items.html +49 -0
  111. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-link.html +20 -0
  112. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name-and-navigation.html +63 -0
  113. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name.html +18 -0
  114. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template.njk +102 -0
  115. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +93 -26
  116. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js.map +1 -1
  117. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +93 -26
  118. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs.map +1 -1
  119. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +13 -21
  120. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs.map +1 -1
  121. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +93 -27
  122. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js.map +1 -1
  123. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +93 -27
  124. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
  125. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs +13 -22
  126. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs.map +1 -1
  127. data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss +4 -3
  128. data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss.map +1 -1
  129. data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
  130. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +16 -3
  131. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs.map +1 -1
  132. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs +49 -5
  133. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs.map +1 -1
  134. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +2 -2
  135. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css.map +1 -1
  136. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
  137. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map +1 -1
  138. data/node_modules/govuk-frontend/dist/govuk/init.mjs +72 -10
  139. data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
  140. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +3 -0
  141. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss.map +1 -1
  142. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +5 -1
  143. data/node_modules/govuk-frontend/package.json +8 -8
  144. metadata +29 -4
  145. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest-2x.png +0 -0
  146. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.png +0 -0
@@ -0,0 +1,249 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ function getBreakpoint(name) {
8
+ const property = `--govuk-frontend-breakpoint-${name}`;
9
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
10
+ return {
11
+ property,
12
+ value: value || undefined
13
+ };
14
+ }
15
+ function isInitialised($root, moduleName) {
16
+ return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
17
+ }
18
+
19
+ /**
20
+ * Checks if GOV.UK Frontend is supported on this page
21
+ *
22
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
23
+ * won't be supported.
24
+ *
25
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
26
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
27
+ */
28
+ function isSupported($scope = document.body) {
29
+ if (!$scope) {
30
+ return false;
31
+ }
32
+ return $scope.classList.contains('govuk-frontend-supported');
33
+ }
34
+ function formatErrorMessage(Component, message) {
35
+ return `${Component.moduleName}: ${message}`;
36
+ }
37
+
38
+ /**
39
+ * Schema for component config
40
+ *
41
+ * @typedef {object} Schema
42
+ * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
43
+ * @property {SchemaCondition[]} [anyOf] - List of schema conditions
44
+ */
45
+
46
+ /**
47
+ * Schema property for component config
48
+ *
49
+ * @typedef {object} SchemaProperty
50
+ * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
51
+ */
52
+
53
+ /**
54
+ * Schema condition for component config
55
+ *
56
+ * @typedef {object} SchemaCondition
57
+ * @property {string[]} required - List of required config fields
58
+ * @property {string} errorMessage - Error message when required config fields not provided
59
+ */
60
+ /**
61
+ * @typedef ComponentWithModuleName
62
+ * @property {string} moduleName - Name of the component
63
+ */
64
+
65
+ class GOVUKFrontendError extends Error {
66
+ constructor(...args) {
67
+ super(...args);
68
+ this.name = 'GOVUKFrontendError';
69
+ }
70
+ }
71
+ class SupportError extends GOVUKFrontendError {
72
+ /**
73
+ * Checks if GOV.UK Frontend is supported on this page
74
+ *
75
+ * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support
76
+ */
77
+ constructor($scope = document.body) {
78
+ const supportMessage = 'noModule' in HTMLScriptElement.prototype ? 'GOV.UK Frontend initialised without `<body class="govuk-frontend-supported">` from template `<script>` snippet' : 'GOV.UK Frontend is not supported in this browser';
79
+ super($scope ? supportMessage : 'GOV.UK Frontend initialised without `<script type="module">`');
80
+ this.name = 'SupportError';
81
+ }
82
+ }
83
+ class ElementError extends GOVUKFrontendError {
84
+ constructor(messageOrOptions) {
85
+ let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
86
+ if (typeof messageOrOptions === 'object') {
87
+ const {
88
+ component,
89
+ identifier,
90
+ element,
91
+ expectedType
92
+ } = messageOrOptions;
93
+ message = identifier;
94
+ message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
95
+ message = formatErrorMessage(component, message);
96
+ }
97
+ super(message);
98
+ this.name = 'ElementError';
99
+ }
100
+ }
101
+ class InitError extends GOVUKFrontendError {
102
+ constructor(componentOrMessage) {
103
+ const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\`$root\`) already initialised`);
104
+ super(message);
105
+ this.name = 'InitError';
106
+ }
107
+ }
108
+ /**
109
+ * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName
110
+ */
111
+
112
+ class GOVUKFrontendComponent {
113
+ /**
114
+ * Returns the root element of the component
115
+ *
116
+ * @protected
117
+ * @returns {RootElementType} - the root element of component
118
+ */
119
+ get $root() {
120
+ return this._$root;
121
+ }
122
+ constructor($root) {
123
+ this._$root = void 0;
124
+ const childConstructor = this.constructor;
125
+ if (typeof childConstructor.moduleName !== 'string') {
126
+ throw new InitError(`\`moduleName\` not defined in component`);
127
+ }
128
+ if (!($root instanceof childConstructor.elementType)) {
129
+ throw new ElementError({
130
+ element: $root,
131
+ component: childConstructor,
132
+ identifier: 'Root element (`$root`)',
133
+ expectedType: childConstructor.elementType.name
134
+ });
135
+ } else {
136
+ this._$root = $root;
137
+ }
138
+ childConstructor.checkSupport();
139
+ this.checkInitialised();
140
+ const moduleName = childConstructor.moduleName;
141
+ this.$root.setAttribute(`data-${moduleName}-init`, '');
142
+ }
143
+ checkInitialised() {
144
+ const constructor = this.constructor;
145
+ const moduleName = constructor.moduleName;
146
+ if (moduleName && isInitialised(this.$root, moduleName)) {
147
+ throw new InitError(constructor);
148
+ }
149
+ }
150
+ static checkSupport() {
151
+ if (!isSupported()) {
152
+ throw new SupportError();
153
+ }
154
+ }
155
+ }
156
+
157
+ /**
158
+ * @typedef ChildClass
159
+ * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
160
+ */
161
+
162
+ /**
163
+ * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor
164
+ */
165
+ GOVUKFrontendComponent.elementType = HTMLElement;
166
+
167
+ /**
168
+ * Service Navigation component
169
+ *
170
+ * @preserve
171
+ */
172
+ class ServiceNavigation extends GOVUKFrontendComponent {
173
+ /**
174
+ * @param {Element | null} $root - HTML element to use for header
175
+ */
176
+ constructor($root) {
177
+ super($root);
178
+ this.$menuButton = void 0;
179
+ this.$menu = void 0;
180
+ this.menuIsOpen = false;
181
+ this.mql = null;
182
+ const $menuButton = this.$root.querySelector('.govuk-js-service-navigation-toggle');
183
+ if (!$menuButton) {
184
+ return this;
185
+ }
186
+ const menuId = $menuButton.getAttribute('aria-controls');
187
+ if (!menuId) {
188
+ throw new ElementError({
189
+ component: ServiceNavigation,
190
+ identifier: 'Navigation button (`<button class="govuk-js-service-navigation-toggle">`) attribute (`aria-controls`)'
191
+ });
192
+ }
193
+ const $menu = document.getElementById(menuId);
194
+ if (!$menu) {
195
+ throw new ElementError({
196
+ component: ServiceNavigation,
197
+ element: $menu,
198
+ identifier: `Navigation (\`<ul id="${menuId}">\`)`
199
+ });
200
+ }
201
+ this.$menu = $menu;
202
+ this.$menuButton = $menuButton;
203
+ this.setupResponsiveChecks();
204
+ this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
205
+ }
206
+ setupResponsiveChecks() {
207
+ const breakpoint = getBreakpoint('tablet');
208
+ if (!breakpoint.value) {
209
+ throw new ElementError({
210
+ component: ServiceNavigation,
211
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
212
+ });
213
+ }
214
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
215
+ if ('addEventListener' in this.mql) {
216
+ this.mql.addEventListener('change', () => this.checkMode());
217
+ } else {
218
+ this.mql.addListener(() => this.checkMode());
219
+ }
220
+ this.checkMode();
221
+ }
222
+ checkMode() {
223
+ if (!this.mql || !this.$menu || !this.$menuButton) {
224
+ return;
225
+ }
226
+ if (this.mql.matches) {
227
+ this.$menu.removeAttribute('hidden');
228
+ this.$menuButton.setAttribute('hidden', '');
229
+ } else {
230
+ this.$menuButton.removeAttribute('hidden');
231
+ this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString());
232
+ if (this.menuIsOpen) {
233
+ this.$menu.removeAttribute('hidden');
234
+ } else {
235
+ this.$menu.setAttribute('hidden', '');
236
+ }
237
+ }
238
+ }
239
+ handleMenuButtonClick() {
240
+ this.menuIsOpen = !this.menuIsOpen;
241
+ this.checkMode();
242
+ }
243
+ }
244
+ ServiceNavigation.moduleName = 'govuk-service-navigation';
245
+
246
+ exports.ServiceNavigation = ServiceNavigation;
247
+
248
+ }));
249
+ //# sourceMappingURL=service-navigation.bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-navigation.bundle.js","sources":["../../../../src/govuk/common/index.mjs","../../../../src/govuk/errors/index.mjs","../../../../src/govuk/govuk-frontend-component.mjs","../../../../src/govuk/components/service-navigation/service-navigation.mjs"],"sourcesContent":["import { normaliseString } from './normalise-string.mjs'\n\n/**\n * Common helpers which do not require polyfill.\n *\n * IMPORTANT: If a helper require a polyfill, please isolate it in its own module\n * so that the polyfill can be properly tree-shaken and does not burden\n * the components that do not need that helper\n */\n\n/**\n * Config merging function\n *\n * Takes any number of objects and combines them together, with\n * greatest priority on the LAST item passed in.\n *\n * @internal\n * @param {...{ [key: string]: unknown }} configObjects - Config objects to merge\n * @returns {{ [key: string]: unknown }} A merged config object\n */\nexport function mergeConfigs(...configObjects) {\n // Start with an empty object as our base\n /** @type {{ [key: string]: unknown }} */\n const formattedConfigObject = {}\n\n // Loop through each of the passed objects\n for (const configObject of configObjects) {\n for (const key of Object.keys(configObject)) {\n const option = formattedConfigObject[key]\n const override = configObject[key]\n\n // Push their keys one-by-one into formattedConfigObject. Any duplicate\n // keys with object values will be merged, otherwise the new value will\n // override the existing value.\n if (isObject(option) && isObject(override)) {\n // @ts-expect-error Index signature for type 'string' is missing\n formattedConfigObject[key] = mergeConfigs(option, override)\n } else {\n // Apply override\n formattedConfigObject[key] = override\n }\n }\n }\n\n return formattedConfigObject\n}\n\n/**\n * Extracts keys starting with a particular namespace from dataset ('data-*')\n * object, removing the namespace in the process, normalising all values\n *\n * @internal\n * @param {{ schema: Schema }} Component - Component class\n * @param {DOMStringMap} dataset - The object to extract key-value pairs from\n * @param {string} namespace - The namespace to filter keys with\n * @returns {ObjectNested | undefined} Nested object with dot-separated key namespace removed\n */\nexport function extractConfigByNamespace(Component, dataset, namespace) {\n const property = Component.schema.properties[namespace]\n\n // Only extract configs for object schema properties\n if (property?.type !== 'object') {\n return\n }\n\n // Add default empty config\n const newObject = {\n [namespace]: /** @type {ObjectNested} */ ({})\n }\n\n for (const [key, value] of Object.entries(dataset)) {\n /** @type {ObjectNested | ObjectNested[NestedKey]} */\n let current = newObject\n\n // Split the key into parts, using . as our namespace separator\n const keyParts = key.split('.')\n\n /**\n * Create new level per part\n *\n * e.g. 'i18n.textareaDescription.other' becomes\n * `{ i18n: { textareaDescription: { other } } }`\n */\n for (const [index, name] of keyParts.entries()) {\n if (typeof current === 'object') {\n // Drop down to nested object until the last part\n if (index < keyParts.length - 1) {\n // New nested object (optionally) replaces existing value\n if (!isObject(current[name])) {\n current[name] = {}\n }\n\n // Drop down into new or existing nested object\n current = current[name]\n } else if (key !== namespace) {\n // Normalised value (optionally) replaces existing value\n current[name] = normaliseString(value)\n }\n }\n }\n }\n\n return newObject[namespace]\n}\n\n/**\n * Get hash fragment from URL\n *\n * Extract the hash fragment (everything after the hash) from a URL,\n * but not including the hash symbol\n *\n * @private\n * @param {string} url - URL\n * @returns {string | undefined} Fragment from URL, without the hash\n */\nexport function getFragmentFromUrl(url) {\n if (!url.includes('#')) {\n return undefined\n }\n\n return url.split('#').pop()\n}\n\n/**\n * Get GOV.UK Frontend breakpoint value from CSS custom property\n *\n * @private\n * @param {string} name - Breakpoint name\n * @returns {{ property: string, value?: string }} Breakpoint object\n */\nexport function getBreakpoint(name) {\n const property = `--govuk-frontend-breakpoint-${name}`\n\n // Get value from `<html>` with breakpoints on CSS :root\n const value = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue(property)\n\n return {\n property,\n value: value || undefined\n }\n}\n\n/**\n * Move focus to element\n *\n * Sets tabindex to -1 to make the element programmatically focusable,\n * but removes it on blur as the element doesn't need to be focused again.\n *\n * @private\n * @template {HTMLElement} FocusElement\n * @param {FocusElement} $element - HTML element\n * @param {object} [options] - Handler options\n * @param {function(this: FocusElement): void} [options.onBeforeFocus] - Callback before focus\n * @param {function(this: FocusElement): void} [options.onBlur] - Callback on blur\n */\nexport function setFocus($element, options = {}) {\n const isFocusable = $element.getAttribute('tabindex')\n\n if (!isFocusable) {\n $element.setAttribute('tabindex', '-1')\n }\n\n /**\n * Handle element focus\n */\n function onFocus() {\n $element.addEventListener('blur', onBlur, { once: true })\n }\n\n /**\n * Handle element blur\n */\n function onBlur() {\n options.onBlur?.call($element)\n\n if (!isFocusable) {\n $element.removeAttribute('tabindex')\n }\n }\n\n // Add listener to reset element on blur, after focus\n $element.addEventListener('focus', onFocus, { once: true })\n\n // Focus element\n options.onBeforeFocus?.call($element)\n $element.focus()\n}\n\n/**\n * Checks if component is already initialised\n *\n * @internal\n * @param {Element} $root - HTML element to be checked\n * @param {string} moduleName - name of component module\n * @returns {boolean} Whether component is already initialised\n */\nexport function isInitialised($root, moduleName) {\n return (\n $root instanceof HTMLElement &&\n $root.hasAttribute(`data-${moduleName}-init`)\n )\n}\n\n/**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * Some browsers will load and run our JavaScript but GOV.UK Frontend\n * won't be supported.\n *\n * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support\n * @returns {boolean} Whether GOV.UK Frontend is supported on this page\n */\nexport function isSupported($scope = document.body) {\n if (!$scope) {\n return false\n }\n\n return $scope.classList.contains('govuk-frontend-supported')\n}\n\n/**\n * Validate component config by schema\n *\n * Follows limited examples in JSON schema for wider support in future\n *\n * {@link https://ajv.js.org/json-schema.html#compound-keywords}\n * {@link https://ajv.js.org/packages/ajv-errors.html#single-message}\n *\n * @internal\n * @param {Schema} schema - Config schema\n * @param {{ [key: string]: unknown }} config - Component config\n * @returns {string[]} List of validation errors\n */\nexport function validateConfig(schema, config) {\n const validationErrors = []\n\n // Check errors for each schema\n for (const [name, conditions] of Object.entries(schema)) {\n const errors = []\n\n // Check errors for each schema condition\n if (Array.isArray(conditions)) {\n for (const { required, errorMessage } of conditions) {\n if (!required.every((key) => !!config[key])) {\n errors.push(errorMessage) // Missing config key value\n }\n }\n\n // Check one condition passes or add errors\n if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {\n validationErrors.push(...errors)\n }\n }\n }\n\n return validationErrors\n}\n\n/**\n * Check for an array\n *\n * @internal\n * @param {unknown} option - Option to check\n * @returns {boolean} Whether the option is an array\n */\nfunction isArray(option) {\n return Array.isArray(option)\n}\n\n/**\n * Check for an object\n *\n * @internal\n * @param {unknown} option - Option to check\n * @returns {boolean} Whether the option is an object\n */\nfunction isObject(option) {\n return !!option && typeof option === 'object' && !isArray(option)\n}\n\n/**\n * Format error message\n *\n * @internal\n * @param {ComponentWithModuleName} Component - Component that threw the error\n * @param {string} message - Error message\n * @returns {string} - Formatted error message\n */\nexport function formatErrorMessage(Component, message) {\n return `${Component.moduleName}: ${message}`\n}\n\n/**\n * Schema for component config\n *\n * @typedef {object} Schema\n * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties\n * @property {SchemaCondition[]} [anyOf] - List of schema conditions\n */\n\n/**\n * Schema property for component config\n *\n * @typedef {object} SchemaProperty\n * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type\n */\n\n/**\n * Schema condition for component config\n *\n * @typedef {object} SchemaCondition\n * @property {string[]} required - List of required config fields\n * @property {string} errorMessage - Error message when required config fields not provided\n */\n\n/**\n * @internal\n * @typedef {keyof ObjectNested} NestedKey\n * @typedef {{ [key: string]: string | boolean | number | ObjectNested | undefined }} ObjectNested\n */\n\n/* eslint-disable jsdoc/valid-types --\n * `{new(...args: any[] ): object}` is not recognised as valid\n * https://github.com/gajus/eslint-plugin-jsdoc/issues/145#issuecomment-1308722878\n * https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/131\n **/\n\n/**\n * @typedef ComponentWithModuleName\n * @property {string} moduleName - Name of the component\n */\n\n/* eslint-enable jsdoc/valid-types */\n","import { formatErrorMessage } from '../common/index.mjs'\n\n/**\n * GOV.UK Frontend error\n *\n * A base class for `Error`s thrown by GOV.UK Frontend.\n *\n * It is meant to be extended into specific types of errors\n * to be thrown by our code.\n *\n * @example\n * ```js\n * class MissingRootError extends GOVUKFrontendError {\n * // Setting an explicit name is important as extending the class will not\n * // set a new `name` on the subclass. The `name` property is important\n * // to ensure intelligible error names even if the class name gets\n * // mangled by a minifier\n * name = \"MissingRootError\"\n * }\n * ```\n * @virtual\n */\nexport class GOVUKFrontendError extends Error {\n name = 'GOVUKFrontendError'\n}\n\n/**\n * Indicates that GOV.UK Frontend is not supported\n */\nexport class SupportError extends GOVUKFrontendError {\n name = 'SupportError'\n\n /**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support\n */\n constructor($scope = document.body) {\n const supportMessage =\n 'noModule' in HTMLScriptElement.prototype\n ? 'GOV.UK Frontend initialised without `<body class=\"govuk-frontend-supported\">` from template `<script>` snippet'\n : 'GOV.UK Frontend is not supported in this browser'\n\n super(\n $scope\n ? supportMessage\n : 'GOV.UK Frontend initialised without `<script type=\"module\">`'\n )\n }\n}\n\n/**\n * Indicates that a component has received an illegal configuration\n */\nexport class ConfigError extends GOVUKFrontendError {\n name = 'ConfigError'\n}\n\n/**\n * Indicates an issue with an element (possibly `null` or `undefined`)\n */\nexport class ElementError extends GOVUKFrontendError {\n name = 'ElementError'\n\n /**\n * @internal\n * @overload\n * @param {string} message - Element error message\n */\n\n /**\n * @internal\n * @overload\n * @param {ElementErrorOptions} options - Element error options\n */\n\n /**\n * @internal\n * @param {string | ElementErrorOptions} messageOrOptions - Element error message or options\n */\n constructor(messageOrOptions) {\n let message = typeof messageOrOptions === 'string' ? messageOrOptions : ''\n\n // Build message from options\n if (typeof messageOrOptions === 'object') {\n const { component, identifier, element, expectedType } = messageOrOptions\n\n message = identifier\n\n // Append reason\n message += element\n ? ` is not of type ${expectedType ?? 'HTMLElement'}`\n : ' not found'\n\n message = formatErrorMessage(component, message)\n }\n\n super(message)\n }\n}\n\n/**\n * Indicates that a component is already initialised\n */\nexport class InitError extends GOVUKFrontendError {\n name = 'InitError'\n\n /**\n * @internal\n * @param {ComponentWithModuleName | string} componentOrMessage - name of the component module\n */\n constructor(componentOrMessage) {\n const message =\n typeof componentOrMessage === 'string'\n ? componentOrMessage\n : formatErrorMessage(\n componentOrMessage,\n `Root element (\\`$root\\`) already initialised`\n )\n\n super(message)\n }\n}\n\n/**\n * Element error options\n *\n * @internal\n * @typedef {object} ElementErrorOptions\n * @property {string} identifier - An identifier that'll let the user understand which element has an error. This is whatever makes the most sense\n * @property {Element | null} [element] - The element in error\n * @property {string} [expectedType] - The type that was expected for the identifier\n * @property {ComponentWithModuleName} component - Component throwing the error\n */\n\n/**\n * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName\n */\n","import { isInitialised, isSupported } from './common/index.mjs'\nimport { ElementError, InitError, SupportError } from './errors/index.mjs'\n\n/**\n * Base Component class\n *\n * Centralises the behaviours shared by our components\n *\n * @virtual\n * @template {Element} [RootElementType=HTMLElement]\n */\nexport class GOVUKFrontendComponent {\n /**\n * @type {typeof Element}\n */\n static elementType = HTMLElement\n\n // allows Typescript user to work around the lack of types\n // in GOVUKFrontend package, Typescript is not aware of $root\n // in components that extend GOVUKFrontendComponent\n /**\n * Returns the root element of the component\n *\n * @protected\n * @returns {RootElementType} - the root element of component\n */\n get $root() {\n return this._$root\n }\n\n /**\n * @protected\n * @type {RootElementType}\n */\n _$root\n\n /**\n * Constructs a new component, validating that GOV.UK Frontend is supported\n *\n * @internal\n * @param {Element | null} [$root] - HTML element to use for component\n */\n constructor($root) {\n const childConstructor = /** @type {ChildClassConstructor} */ (\n this.constructor\n )\n\n // TypeScript does not enforce that inheriting classes will define a `moduleName`\n // (even if we add a `@virtual` `static moduleName` property to this class).\n // While we trust users to do this correctly, we do a little check to provide them\n // a helpful error message.\n //\n // After this, we'll be sure that `childConstructor` has a `moduleName`\n // as expected of the `ChildClassConstructor` we've cast `this.constructor` to.\n if (typeof childConstructor.moduleName !== 'string') {\n throw new InitError(`\\`moduleName\\` not defined in component`)\n }\n\n if (!($root instanceof childConstructor.elementType)) {\n throw new ElementError({\n element: $root,\n component: childConstructor,\n identifier: 'Root element (`$root`)',\n expectedType: childConstructor.elementType.name\n })\n } else {\n this._$root = /** @type {RootElementType} */ ($root)\n }\n\n childConstructor.checkSupport()\n\n this.checkInitialised()\n\n const moduleName = childConstructor.moduleName\n\n this.$root.setAttribute(`data-${moduleName}-init`, '')\n }\n\n /**\n * Validates whether component is already initialised\n *\n * @private\n * @throws {InitError} when component is already initialised\n */\n checkInitialised() {\n const constructor = /** @type {ChildClassConstructor} */ (this.constructor)\n const moduleName = constructor.moduleName\n\n if (moduleName && isInitialised(this.$root, moduleName)) {\n throw new InitError(constructor)\n }\n }\n\n /**\n * Validates whether components are supported\n *\n * @throws {SupportError} when the components are not supported\n */\n static checkSupport() {\n if (!isSupported()) {\n throw new SupportError()\n }\n }\n}\n\n/**\n * @typedef ChildClass\n * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component\n */\n\n/**\n * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor\n */\n","import { getBreakpoint } from '../../common/index.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Service Navigation component\n *\n * @preserve\n */\nexport class ServiceNavigation extends GOVUKFrontendComponent {\n /** @private */\n $menuButton\n\n /** @private */\n $menu\n\n /**\n * Remember the open/closed state of the nav so we can maintain it when the\n * screen is resized.\n *\n * @private\n */\n menuIsOpen = false\n\n /**\n * A global const for storing a matchMedia instance which we'll use to detect\n * when a screen size change happens. We rely on it being null if the feature\n * isn't available to initially apply hidden attributes\n *\n * @private\n * @type {MediaQueryList | null}\n */\n mql = null\n\n /**\n * @param {Element | null} $root - HTML element to use for header\n */\n constructor($root) {\n super($root)\n\n const $menuButton = this.$root.querySelector(\n '.govuk-js-service-navigation-toggle'\n )\n\n // Headers don't necessarily have a navigation. When they don't, the menu\n // toggle won't be rendered by our macro (or may be omitted when writing\n // plain HTML)\n if (!$menuButton) {\n return this\n }\n\n const menuId = $menuButton.getAttribute('aria-controls')\n if (!menuId) {\n throw new ElementError({\n component: ServiceNavigation,\n identifier:\n 'Navigation button (`<button class=\"govuk-js-service-navigation-toggle\">`) attribute (`aria-controls`)'\n })\n }\n\n const $menu = document.getElementById(menuId)\n if (!$menu) {\n throw new ElementError({\n component: ServiceNavigation,\n element: $menu,\n identifier: `Navigation (\\`<ul id=\"${menuId}\">\\`)`\n })\n }\n\n this.$menu = $menu\n this.$menuButton = $menuButton\n\n this.setupResponsiveChecks()\n\n this.$menuButton.addEventListener('click', () =>\n this.handleMenuButtonClick()\n )\n }\n\n /**\n * Setup viewport resize check\n *\n * @private\n */\n setupResponsiveChecks() {\n const breakpoint = getBreakpoint('tablet')\n\n if (!breakpoint.value) {\n throw new ElementError({\n component: ServiceNavigation,\n identifier: `CSS custom property (\\`${breakpoint.property}\\`) on pseudo-class \\`:root\\``\n })\n }\n\n // Media query list for GOV.UK Frontend desktop breakpoint\n this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`)\n\n // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need\n // to be able to fall back to the deprecated MediaQueryList.addListener\n if ('addEventListener' in this.mql) {\n this.mql.addEventListener('change', () => this.checkMode())\n } else {\n // @ts-expect-error Property 'addListener' does not exist\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n this.mql.addListener(() => this.checkMode())\n }\n\n this.checkMode()\n }\n\n /**\n * Sync menu state\n *\n * Uses the global variable menuIsOpen to correctly set the accessible and\n * visual states of the menu and the menu button.\n * Additionally will force the menu to be visible and the menu button to be\n * hidden if the matchMedia is triggered to desktop.\n *\n * @private\n */\n checkMode() {\n if (!this.mql || !this.$menu || !this.$menuButton) {\n return\n }\n\n if (this.mql.matches) {\n this.$menu.removeAttribute('hidden')\n this.$menuButton.setAttribute('hidden', '')\n } else {\n this.$menuButton.removeAttribute('hidden')\n this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString())\n\n if (this.menuIsOpen) {\n this.$menu.removeAttribute('hidden')\n } else {\n this.$menu.setAttribute('hidden', '')\n }\n }\n }\n\n /**\n * Handle menu button click\n *\n * When the menu button is clicked, change the visibility of the menu and then\n * sync the accessibility state and menu button state\n *\n * @private\n */\n handleMenuButtonClick() {\n this.menuIsOpen = !this.menuIsOpen\n this.checkMode()\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-service-navigation'\n}\n"],"names":["getBreakpoint","name","property","value","window","getComputedStyle","document","documentElement","getPropertyValue","undefined","isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","body","classList","contains","formatErrorMessage","Component","message","GOVUKFrontendError","Error","constructor","args","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","GOVUKFrontendComponent","_$root","childConstructor","elementType","checkSupport","checkInitialised","setAttribute","ServiceNavigation","$menuButton","$menu","menuIsOpen","mql","querySelector","menuId","getAttribute","getElementById","setupResponsiveChecks","addEventListener","handleMenuButtonClick","breakpoint","matchMedia","checkMode","addListener","matches","removeAttribute","toString"],"mappings":"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"}
@@ -0,0 +1,241 @@
1
+ function getBreakpoint(name) {
2
+ const property = `--govuk-frontend-breakpoint-${name}`;
3
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
4
+ return {
5
+ property,
6
+ value: value || undefined
7
+ };
8
+ }
9
+ function isInitialised($root, moduleName) {
10
+ return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
11
+ }
12
+
13
+ /**
14
+ * Checks if GOV.UK Frontend is supported on this page
15
+ *
16
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
17
+ * won't be supported.
18
+ *
19
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
20
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
21
+ */
22
+ function isSupported($scope = document.body) {
23
+ if (!$scope) {
24
+ return false;
25
+ }
26
+ return $scope.classList.contains('govuk-frontend-supported');
27
+ }
28
+ function formatErrorMessage(Component, message) {
29
+ return `${Component.moduleName}: ${message}`;
30
+ }
31
+
32
+ /**
33
+ * Schema for component config
34
+ *
35
+ * @typedef {object} Schema
36
+ * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
37
+ * @property {SchemaCondition[]} [anyOf] - List of schema conditions
38
+ */
39
+
40
+ /**
41
+ * Schema property for component config
42
+ *
43
+ * @typedef {object} SchemaProperty
44
+ * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
45
+ */
46
+
47
+ /**
48
+ * Schema condition for component config
49
+ *
50
+ * @typedef {object} SchemaCondition
51
+ * @property {string[]} required - List of required config fields
52
+ * @property {string} errorMessage - Error message when required config fields not provided
53
+ */
54
+ /**
55
+ * @typedef ComponentWithModuleName
56
+ * @property {string} moduleName - Name of the component
57
+ */
58
+
59
+ class GOVUKFrontendError extends Error {
60
+ constructor(...args) {
61
+ super(...args);
62
+ this.name = 'GOVUKFrontendError';
63
+ }
64
+ }
65
+ class SupportError extends GOVUKFrontendError {
66
+ /**
67
+ * Checks if GOV.UK Frontend is supported on this page
68
+ *
69
+ * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support
70
+ */
71
+ constructor($scope = document.body) {
72
+ const supportMessage = 'noModule' in HTMLScriptElement.prototype ? 'GOV.UK Frontend initialised without `<body class="govuk-frontend-supported">` from template `<script>` snippet' : 'GOV.UK Frontend is not supported in this browser';
73
+ super($scope ? supportMessage : 'GOV.UK Frontend initialised without `<script type="module">`');
74
+ this.name = 'SupportError';
75
+ }
76
+ }
77
+ class ElementError extends GOVUKFrontendError {
78
+ constructor(messageOrOptions) {
79
+ let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
80
+ if (typeof messageOrOptions === 'object') {
81
+ const {
82
+ component,
83
+ identifier,
84
+ element,
85
+ expectedType
86
+ } = messageOrOptions;
87
+ message = identifier;
88
+ message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
89
+ message = formatErrorMessage(component, message);
90
+ }
91
+ super(message);
92
+ this.name = 'ElementError';
93
+ }
94
+ }
95
+ class InitError extends GOVUKFrontendError {
96
+ constructor(componentOrMessage) {
97
+ const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\`$root\`) already initialised`);
98
+ super(message);
99
+ this.name = 'InitError';
100
+ }
101
+ }
102
+ /**
103
+ * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName
104
+ */
105
+
106
+ class GOVUKFrontendComponent {
107
+ /**
108
+ * Returns the root element of the component
109
+ *
110
+ * @protected
111
+ * @returns {RootElementType} - the root element of component
112
+ */
113
+ get $root() {
114
+ return this._$root;
115
+ }
116
+ constructor($root) {
117
+ this._$root = void 0;
118
+ const childConstructor = this.constructor;
119
+ if (typeof childConstructor.moduleName !== 'string') {
120
+ throw new InitError(`\`moduleName\` not defined in component`);
121
+ }
122
+ if (!($root instanceof childConstructor.elementType)) {
123
+ throw new ElementError({
124
+ element: $root,
125
+ component: childConstructor,
126
+ identifier: 'Root element (`$root`)',
127
+ expectedType: childConstructor.elementType.name
128
+ });
129
+ } else {
130
+ this._$root = $root;
131
+ }
132
+ childConstructor.checkSupport();
133
+ this.checkInitialised();
134
+ const moduleName = childConstructor.moduleName;
135
+ this.$root.setAttribute(`data-${moduleName}-init`, '');
136
+ }
137
+ checkInitialised() {
138
+ const constructor = this.constructor;
139
+ const moduleName = constructor.moduleName;
140
+ if (moduleName && isInitialised(this.$root, moduleName)) {
141
+ throw new InitError(constructor);
142
+ }
143
+ }
144
+ static checkSupport() {
145
+ if (!isSupported()) {
146
+ throw new SupportError();
147
+ }
148
+ }
149
+ }
150
+
151
+ /**
152
+ * @typedef ChildClass
153
+ * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
154
+ */
155
+
156
+ /**
157
+ * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor
158
+ */
159
+ GOVUKFrontendComponent.elementType = HTMLElement;
160
+
161
+ /**
162
+ * Service Navigation component
163
+ *
164
+ * @preserve
165
+ */
166
+ class ServiceNavigation extends GOVUKFrontendComponent {
167
+ /**
168
+ * @param {Element | null} $root - HTML element to use for header
169
+ */
170
+ constructor($root) {
171
+ super($root);
172
+ this.$menuButton = void 0;
173
+ this.$menu = void 0;
174
+ this.menuIsOpen = false;
175
+ this.mql = null;
176
+ const $menuButton = this.$root.querySelector('.govuk-js-service-navigation-toggle');
177
+ if (!$menuButton) {
178
+ return this;
179
+ }
180
+ const menuId = $menuButton.getAttribute('aria-controls');
181
+ if (!menuId) {
182
+ throw new ElementError({
183
+ component: ServiceNavigation,
184
+ identifier: 'Navigation button (`<button class="govuk-js-service-navigation-toggle">`) attribute (`aria-controls`)'
185
+ });
186
+ }
187
+ const $menu = document.getElementById(menuId);
188
+ if (!$menu) {
189
+ throw new ElementError({
190
+ component: ServiceNavigation,
191
+ element: $menu,
192
+ identifier: `Navigation (\`<ul id="${menuId}">\`)`
193
+ });
194
+ }
195
+ this.$menu = $menu;
196
+ this.$menuButton = $menuButton;
197
+ this.setupResponsiveChecks();
198
+ this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
199
+ }
200
+ setupResponsiveChecks() {
201
+ const breakpoint = getBreakpoint('tablet');
202
+ if (!breakpoint.value) {
203
+ throw new ElementError({
204
+ component: ServiceNavigation,
205
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
206
+ });
207
+ }
208
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
209
+ if ('addEventListener' in this.mql) {
210
+ this.mql.addEventListener('change', () => this.checkMode());
211
+ } else {
212
+ this.mql.addListener(() => this.checkMode());
213
+ }
214
+ this.checkMode();
215
+ }
216
+ checkMode() {
217
+ if (!this.mql || !this.$menu || !this.$menuButton) {
218
+ return;
219
+ }
220
+ if (this.mql.matches) {
221
+ this.$menu.removeAttribute('hidden');
222
+ this.$menuButton.setAttribute('hidden', '');
223
+ } else {
224
+ this.$menuButton.removeAttribute('hidden');
225
+ this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString());
226
+ if (this.menuIsOpen) {
227
+ this.$menu.removeAttribute('hidden');
228
+ } else {
229
+ this.$menu.setAttribute('hidden', '');
230
+ }
231
+ }
232
+ }
233
+ handleMenuButtonClick() {
234
+ this.menuIsOpen = !this.menuIsOpen;
235
+ this.checkMode();
236
+ }
237
+ }
238
+ ServiceNavigation.moduleName = 'govuk-service-navigation';
239
+
240
+ export { ServiceNavigation };
241
+ //# sourceMappingURL=service-navigation.bundle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-navigation.bundle.mjs","sources":["../../../../src/govuk/common/index.mjs","../../../../src/govuk/errors/index.mjs","../../../../src/govuk/govuk-frontend-component.mjs","../../../../src/govuk/components/service-navigation/service-navigation.mjs"],"sourcesContent":["import { normaliseString } from './normalise-string.mjs'\n\n/**\n * Common helpers which do not require polyfill.\n *\n * IMPORTANT: If a helper require a polyfill, please isolate it in its own module\n * so that the polyfill can be properly tree-shaken and does not burden\n * the components that do not need that helper\n */\n\n/**\n * Config merging function\n *\n * Takes any number of objects and combines them together, with\n * greatest priority on the LAST item passed in.\n *\n * @internal\n * @param {...{ [key: string]: unknown }} configObjects - Config objects to merge\n * @returns {{ [key: string]: unknown }} A merged config object\n */\nexport function mergeConfigs(...configObjects) {\n // Start with an empty object as our base\n /** @type {{ [key: string]: unknown }} */\n const formattedConfigObject = {}\n\n // Loop through each of the passed objects\n for (const configObject of configObjects) {\n for (const key of Object.keys(configObject)) {\n const option = formattedConfigObject[key]\n const override = configObject[key]\n\n // Push their keys one-by-one into formattedConfigObject. Any duplicate\n // keys with object values will be merged, otherwise the new value will\n // override the existing value.\n if (isObject(option) && isObject(override)) {\n // @ts-expect-error Index signature for type 'string' is missing\n formattedConfigObject[key] = mergeConfigs(option, override)\n } else {\n // Apply override\n formattedConfigObject[key] = override\n }\n }\n }\n\n return formattedConfigObject\n}\n\n/**\n * Extracts keys starting with a particular namespace from dataset ('data-*')\n * object, removing the namespace in the process, normalising all values\n *\n * @internal\n * @param {{ schema: Schema }} Component - Component class\n * @param {DOMStringMap} dataset - The object to extract key-value pairs from\n * @param {string} namespace - The namespace to filter keys with\n * @returns {ObjectNested | undefined} Nested object with dot-separated key namespace removed\n */\nexport function extractConfigByNamespace(Component, dataset, namespace) {\n const property = Component.schema.properties[namespace]\n\n // Only extract configs for object schema properties\n if (property?.type !== 'object') {\n return\n }\n\n // Add default empty config\n const newObject = {\n [namespace]: /** @type {ObjectNested} */ ({})\n }\n\n for (const [key, value] of Object.entries(dataset)) {\n /** @type {ObjectNested | ObjectNested[NestedKey]} */\n let current = newObject\n\n // Split the key into parts, using . as our namespace separator\n const keyParts = key.split('.')\n\n /**\n * Create new level per part\n *\n * e.g. 'i18n.textareaDescription.other' becomes\n * `{ i18n: { textareaDescription: { other } } }`\n */\n for (const [index, name] of keyParts.entries()) {\n if (typeof current === 'object') {\n // Drop down to nested object until the last part\n if (index < keyParts.length - 1) {\n // New nested object (optionally) replaces existing value\n if (!isObject(current[name])) {\n current[name] = {}\n }\n\n // Drop down into new or existing nested object\n current = current[name]\n } else if (key !== namespace) {\n // Normalised value (optionally) replaces existing value\n current[name] = normaliseString(value)\n }\n }\n }\n }\n\n return newObject[namespace]\n}\n\n/**\n * Get hash fragment from URL\n *\n * Extract the hash fragment (everything after the hash) from a URL,\n * but not including the hash symbol\n *\n * @private\n * @param {string} url - URL\n * @returns {string | undefined} Fragment from URL, without the hash\n */\nexport function getFragmentFromUrl(url) {\n if (!url.includes('#')) {\n return undefined\n }\n\n return url.split('#').pop()\n}\n\n/**\n * Get GOV.UK Frontend breakpoint value from CSS custom property\n *\n * @private\n * @param {string} name - Breakpoint name\n * @returns {{ property: string, value?: string }} Breakpoint object\n */\nexport function getBreakpoint(name) {\n const property = `--govuk-frontend-breakpoint-${name}`\n\n // Get value from `<html>` with breakpoints on CSS :root\n const value = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue(property)\n\n return {\n property,\n value: value || undefined\n }\n}\n\n/**\n * Move focus to element\n *\n * Sets tabindex to -1 to make the element programmatically focusable,\n * but removes it on blur as the element doesn't need to be focused again.\n *\n * @private\n * @template {HTMLElement} FocusElement\n * @param {FocusElement} $element - HTML element\n * @param {object} [options] - Handler options\n * @param {function(this: FocusElement): void} [options.onBeforeFocus] - Callback before focus\n * @param {function(this: FocusElement): void} [options.onBlur] - Callback on blur\n */\nexport function setFocus($element, options = {}) {\n const isFocusable = $element.getAttribute('tabindex')\n\n if (!isFocusable) {\n $element.setAttribute('tabindex', '-1')\n }\n\n /**\n * Handle element focus\n */\n function onFocus() {\n $element.addEventListener('blur', onBlur, { once: true })\n }\n\n /**\n * Handle element blur\n */\n function onBlur() {\n options.onBlur?.call($element)\n\n if (!isFocusable) {\n $element.removeAttribute('tabindex')\n }\n }\n\n // Add listener to reset element on blur, after focus\n $element.addEventListener('focus', onFocus, { once: true })\n\n // Focus element\n options.onBeforeFocus?.call($element)\n $element.focus()\n}\n\n/**\n * Checks if component is already initialised\n *\n * @internal\n * @param {Element} $root - HTML element to be checked\n * @param {string} moduleName - name of component module\n * @returns {boolean} Whether component is already initialised\n */\nexport function isInitialised($root, moduleName) {\n return (\n $root instanceof HTMLElement &&\n $root.hasAttribute(`data-${moduleName}-init`)\n )\n}\n\n/**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * Some browsers will load and run our JavaScript but GOV.UK Frontend\n * won't be supported.\n *\n * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support\n * @returns {boolean} Whether GOV.UK Frontend is supported on this page\n */\nexport function isSupported($scope = document.body) {\n if (!$scope) {\n return false\n }\n\n return $scope.classList.contains('govuk-frontend-supported')\n}\n\n/**\n * Validate component config by schema\n *\n * Follows limited examples in JSON schema for wider support in future\n *\n * {@link https://ajv.js.org/json-schema.html#compound-keywords}\n * {@link https://ajv.js.org/packages/ajv-errors.html#single-message}\n *\n * @internal\n * @param {Schema} schema - Config schema\n * @param {{ [key: string]: unknown }} config - Component config\n * @returns {string[]} List of validation errors\n */\nexport function validateConfig(schema, config) {\n const validationErrors = []\n\n // Check errors for each schema\n for (const [name, conditions] of Object.entries(schema)) {\n const errors = []\n\n // Check errors for each schema condition\n if (Array.isArray(conditions)) {\n for (const { required, errorMessage } of conditions) {\n if (!required.every((key) => !!config[key])) {\n errors.push(errorMessage) // Missing config key value\n }\n }\n\n // Check one condition passes or add errors\n if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {\n validationErrors.push(...errors)\n }\n }\n }\n\n return validationErrors\n}\n\n/**\n * Check for an array\n *\n * @internal\n * @param {unknown} option - Option to check\n * @returns {boolean} Whether the option is an array\n */\nfunction isArray(option) {\n return Array.isArray(option)\n}\n\n/**\n * Check for an object\n *\n * @internal\n * @param {unknown} option - Option to check\n * @returns {boolean} Whether the option is an object\n */\nfunction isObject(option) {\n return !!option && typeof option === 'object' && !isArray(option)\n}\n\n/**\n * Format error message\n *\n * @internal\n * @param {ComponentWithModuleName} Component - Component that threw the error\n * @param {string} message - Error message\n * @returns {string} - Formatted error message\n */\nexport function formatErrorMessage(Component, message) {\n return `${Component.moduleName}: ${message}`\n}\n\n/**\n * Schema for component config\n *\n * @typedef {object} Schema\n * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties\n * @property {SchemaCondition[]} [anyOf] - List of schema conditions\n */\n\n/**\n * Schema property for component config\n *\n * @typedef {object} SchemaProperty\n * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type\n */\n\n/**\n * Schema condition for component config\n *\n * @typedef {object} SchemaCondition\n * @property {string[]} required - List of required config fields\n * @property {string} errorMessage - Error message when required config fields not provided\n */\n\n/**\n * @internal\n * @typedef {keyof ObjectNested} NestedKey\n * @typedef {{ [key: string]: string | boolean | number | ObjectNested | undefined }} ObjectNested\n */\n\n/* eslint-disable jsdoc/valid-types --\n * `{new(...args: any[] ): object}` is not recognised as valid\n * https://github.com/gajus/eslint-plugin-jsdoc/issues/145#issuecomment-1308722878\n * https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/131\n **/\n\n/**\n * @typedef ComponentWithModuleName\n * @property {string} moduleName - Name of the component\n */\n\n/* eslint-enable jsdoc/valid-types */\n","import { formatErrorMessage } from '../common/index.mjs'\n\n/**\n * GOV.UK Frontend error\n *\n * A base class for `Error`s thrown by GOV.UK Frontend.\n *\n * It is meant to be extended into specific types of errors\n * to be thrown by our code.\n *\n * @example\n * ```js\n * class MissingRootError extends GOVUKFrontendError {\n * // Setting an explicit name is important as extending the class will not\n * // set a new `name` on the subclass. The `name` property is important\n * // to ensure intelligible error names even if the class name gets\n * // mangled by a minifier\n * name = \"MissingRootError\"\n * }\n * ```\n * @virtual\n */\nexport class GOVUKFrontendError extends Error {\n name = 'GOVUKFrontendError'\n}\n\n/**\n * Indicates that GOV.UK Frontend is not supported\n */\nexport class SupportError extends GOVUKFrontendError {\n name = 'SupportError'\n\n /**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support\n */\n constructor($scope = document.body) {\n const supportMessage =\n 'noModule' in HTMLScriptElement.prototype\n ? 'GOV.UK Frontend initialised without `<body class=\"govuk-frontend-supported\">` from template `<script>` snippet'\n : 'GOV.UK Frontend is not supported in this browser'\n\n super(\n $scope\n ? supportMessage\n : 'GOV.UK Frontend initialised without `<script type=\"module\">`'\n )\n }\n}\n\n/**\n * Indicates that a component has received an illegal configuration\n */\nexport class ConfigError extends GOVUKFrontendError {\n name = 'ConfigError'\n}\n\n/**\n * Indicates an issue with an element (possibly `null` or `undefined`)\n */\nexport class ElementError extends GOVUKFrontendError {\n name = 'ElementError'\n\n /**\n * @internal\n * @overload\n * @param {string} message - Element error message\n */\n\n /**\n * @internal\n * @overload\n * @param {ElementErrorOptions} options - Element error options\n */\n\n /**\n * @internal\n * @param {string | ElementErrorOptions} messageOrOptions - Element error message or options\n */\n constructor(messageOrOptions) {\n let message = typeof messageOrOptions === 'string' ? messageOrOptions : ''\n\n // Build message from options\n if (typeof messageOrOptions === 'object') {\n const { component, identifier, element, expectedType } = messageOrOptions\n\n message = identifier\n\n // Append reason\n message += element\n ? ` is not of type ${expectedType ?? 'HTMLElement'}`\n : ' not found'\n\n message = formatErrorMessage(component, message)\n }\n\n super(message)\n }\n}\n\n/**\n * Indicates that a component is already initialised\n */\nexport class InitError extends GOVUKFrontendError {\n name = 'InitError'\n\n /**\n * @internal\n * @param {ComponentWithModuleName | string} componentOrMessage - name of the component module\n */\n constructor(componentOrMessage) {\n const message =\n typeof componentOrMessage === 'string'\n ? componentOrMessage\n : formatErrorMessage(\n componentOrMessage,\n `Root element (\\`$root\\`) already initialised`\n )\n\n super(message)\n }\n}\n\n/**\n * Element error options\n *\n * @internal\n * @typedef {object} ElementErrorOptions\n * @property {string} identifier - An identifier that'll let the user understand which element has an error. This is whatever makes the most sense\n * @property {Element | null} [element] - The element in error\n * @property {string} [expectedType] - The type that was expected for the identifier\n * @property {ComponentWithModuleName} component - Component throwing the error\n */\n\n/**\n * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName\n */\n","import { isInitialised, isSupported } from './common/index.mjs'\nimport { ElementError, InitError, SupportError } from './errors/index.mjs'\n\n/**\n * Base Component class\n *\n * Centralises the behaviours shared by our components\n *\n * @virtual\n * @template {Element} [RootElementType=HTMLElement]\n */\nexport class GOVUKFrontendComponent {\n /**\n * @type {typeof Element}\n */\n static elementType = HTMLElement\n\n // allows Typescript user to work around the lack of types\n // in GOVUKFrontend package, Typescript is not aware of $root\n // in components that extend GOVUKFrontendComponent\n /**\n * Returns the root element of the component\n *\n * @protected\n * @returns {RootElementType} - the root element of component\n */\n get $root() {\n return this._$root\n }\n\n /**\n * @protected\n * @type {RootElementType}\n */\n _$root\n\n /**\n * Constructs a new component, validating that GOV.UK Frontend is supported\n *\n * @internal\n * @param {Element | null} [$root] - HTML element to use for component\n */\n constructor($root) {\n const childConstructor = /** @type {ChildClassConstructor} */ (\n this.constructor\n )\n\n // TypeScript does not enforce that inheriting classes will define a `moduleName`\n // (even if we add a `@virtual` `static moduleName` property to this class).\n // While we trust users to do this correctly, we do a little check to provide them\n // a helpful error message.\n //\n // After this, we'll be sure that `childConstructor` has a `moduleName`\n // as expected of the `ChildClassConstructor` we've cast `this.constructor` to.\n if (typeof childConstructor.moduleName !== 'string') {\n throw new InitError(`\\`moduleName\\` not defined in component`)\n }\n\n if (!($root instanceof childConstructor.elementType)) {\n throw new ElementError({\n element: $root,\n component: childConstructor,\n identifier: 'Root element (`$root`)',\n expectedType: childConstructor.elementType.name\n })\n } else {\n this._$root = /** @type {RootElementType} */ ($root)\n }\n\n childConstructor.checkSupport()\n\n this.checkInitialised()\n\n const moduleName = childConstructor.moduleName\n\n this.$root.setAttribute(`data-${moduleName}-init`, '')\n }\n\n /**\n * Validates whether component is already initialised\n *\n * @private\n * @throws {InitError} when component is already initialised\n */\n checkInitialised() {\n const constructor = /** @type {ChildClassConstructor} */ (this.constructor)\n const moduleName = constructor.moduleName\n\n if (moduleName && isInitialised(this.$root, moduleName)) {\n throw new InitError(constructor)\n }\n }\n\n /**\n * Validates whether components are supported\n *\n * @throws {SupportError} when the components are not supported\n */\n static checkSupport() {\n if (!isSupported()) {\n throw new SupportError()\n }\n }\n}\n\n/**\n * @typedef ChildClass\n * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component\n */\n\n/**\n * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor\n */\n","import { getBreakpoint } from '../../common/index.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Service Navigation component\n *\n * @preserve\n */\nexport class ServiceNavigation extends GOVUKFrontendComponent {\n /** @private */\n $menuButton\n\n /** @private */\n $menu\n\n /**\n * Remember the open/closed state of the nav so we can maintain it when the\n * screen is resized.\n *\n * @private\n */\n menuIsOpen = false\n\n /**\n * A global const for storing a matchMedia instance which we'll use to detect\n * when a screen size change happens. We rely on it being null if the feature\n * isn't available to initially apply hidden attributes\n *\n * @private\n * @type {MediaQueryList | null}\n */\n mql = null\n\n /**\n * @param {Element | null} $root - HTML element to use for header\n */\n constructor($root) {\n super($root)\n\n const $menuButton = this.$root.querySelector(\n '.govuk-js-service-navigation-toggle'\n )\n\n // Headers don't necessarily have a navigation. When they don't, the menu\n // toggle won't be rendered by our macro (or may be omitted when writing\n // plain HTML)\n if (!$menuButton) {\n return this\n }\n\n const menuId = $menuButton.getAttribute('aria-controls')\n if (!menuId) {\n throw new ElementError({\n component: ServiceNavigation,\n identifier:\n 'Navigation button (`<button class=\"govuk-js-service-navigation-toggle\">`) attribute (`aria-controls`)'\n })\n }\n\n const $menu = document.getElementById(menuId)\n if (!$menu) {\n throw new ElementError({\n component: ServiceNavigation,\n element: $menu,\n identifier: `Navigation (\\`<ul id=\"${menuId}\">\\`)`\n })\n }\n\n this.$menu = $menu\n this.$menuButton = $menuButton\n\n this.setupResponsiveChecks()\n\n this.$menuButton.addEventListener('click', () =>\n this.handleMenuButtonClick()\n )\n }\n\n /**\n * Setup viewport resize check\n *\n * @private\n */\n setupResponsiveChecks() {\n const breakpoint = getBreakpoint('tablet')\n\n if (!breakpoint.value) {\n throw new ElementError({\n component: ServiceNavigation,\n identifier: `CSS custom property (\\`${breakpoint.property}\\`) on pseudo-class \\`:root\\``\n })\n }\n\n // Media query list for GOV.UK Frontend desktop breakpoint\n this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`)\n\n // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need\n // to be able to fall back to the deprecated MediaQueryList.addListener\n if ('addEventListener' in this.mql) {\n this.mql.addEventListener('change', () => this.checkMode())\n } else {\n // @ts-expect-error Property 'addListener' does not exist\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n this.mql.addListener(() => this.checkMode())\n }\n\n this.checkMode()\n }\n\n /**\n * Sync menu state\n *\n * Uses the global variable menuIsOpen to correctly set the accessible and\n * visual states of the menu and the menu button.\n * Additionally will force the menu to be visible and the menu button to be\n * hidden if the matchMedia is triggered to desktop.\n *\n * @private\n */\n checkMode() {\n if (!this.mql || !this.$menu || !this.$menuButton) {\n return\n }\n\n if (this.mql.matches) {\n this.$menu.removeAttribute('hidden')\n this.$menuButton.setAttribute('hidden', '')\n } else {\n this.$menuButton.removeAttribute('hidden')\n this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString())\n\n if (this.menuIsOpen) {\n this.$menu.removeAttribute('hidden')\n } else {\n this.$menu.setAttribute('hidden', '')\n }\n }\n }\n\n /**\n * Handle menu button click\n *\n * When the menu button is clicked, change the visibility of the menu and then\n * sync the accessibility state and menu button state\n *\n * @private\n */\n handleMenuButtonClick() {\n this.menuIsOpen = !this.menuIsOpen\n this.checkMode()\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-service-navigation'\n}\n"],"names":["getBreakpoint","name","property","value","window","getComputedStyle","document","documentElement","getPropertyValue","undefined","isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","body","classList","contains","formatErrorMessage","Component","message","GOVUKFrontendError","Error","constructor","args","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","GOVUKFrontendComponent","_$root","childConstructor","elementType","checkSupport","checkInitialised","setAttribute","ServiceNavigation","$menuButton","$menu","menuIsOpen","mql","querySelector","menuId","getAttribute","getElementById","setupResponsiveChecks","addEventListener","handleMenuButtonClick","breakpoint","matchMedia","checkMode","addListener","matches","removeAttribute","toString"],"mappings":"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"}