govuk_publishing_components 44.1.0 → 44.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/govuk_publishing_components/components/_share-links.scss +32 -0
- data/app/views/govuk_publishing_components/components/_share_links.html.erb +4 -1
- data/app/views/govuk_publishing_components/components/docs/share_links.yml +36 -0
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +336 -225
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +334 -226
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.mjs +3 -0
- data/node_modules/govuk-frontend/dist/govuk/all.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.svg +1 -0
- data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
- data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +21 -1
- data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/_index.scss +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +92 -26
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +92 -26
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +12 -21
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +86 -20
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +86 -20
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +6 -16
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +89 -23
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +89 -23
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +10 -19
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +113 -47
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +113 -47
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs +7 -16
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss +7 -2
- data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +86 -20
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +86 -20
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -16
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +87 -21
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +87 -21
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +7 -16
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss +8 -10
- data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss +8 -0
- data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/fixtures.json +12 -0
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +87 -21
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +87 -21
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs +7 -16
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-full-width-border.html +24 -0
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +86 -20
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +86 -20
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -16
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +89 -23
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +89 -23
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +9 -18
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +113 -47
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +113 -47
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs +7 -16
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/README.md +15 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss +168 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss +4 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json +464 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro-options.json +138 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro.njk +3 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +249 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +241 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs +85 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-default.html +57 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-html-navigation-items.html +49 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-large-navigation.html +153 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-long-service-name.html +20 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-a-current-item.html +58 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-an-active-item.html +58 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-non-link-navigation-items.html +49 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-link.html +20 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name-and-navigation.html +63 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name.html +18 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template.njk +102 -0
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +93 -26
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +93 -26
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +13 -21
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +93 -27
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +93 -27
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs +13 -22
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss +4 -3
- data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +16 -3
- data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs +49 -5
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +2 -2
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/init.mjs +72 -10
- data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +3 -0
- data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss.map +1 -1
- data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +5 -1
- data/node_modules/govuk-frontend/package.json +8 -8
- metadata +29 -4
- data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest-2x.png +0 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.png +0 -0
@@ -4,7 +4,7 @@
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = {}));
|
5
5
|
})(this, (function (exports) { 'use strict';
|
6
6
|
|
7
|
-
const version = '5.
|
7
|
+
const version = '5.7.0';
|
8
8
|
|
9
9
|
function normaliseString(value, property) {
|
10
10
|
const trimmedValue = value ? value.trim() : '';
|
@@ -114,6 +114,19 @@
|
|
114
114
|
(_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
|
115
115
|
$element.focus();
|
116
116
|
}
|
117
|
+
function isInitialised($root, moduleName) {
|
118
|
+
return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
|
119
|
+
}
|
120
|
+
|
121
|
+
/**
|
122
|
+
* Checks if GOV.UK Frontend is supported on this page
|
123
|
+
*
|
124
|
+
* Some browsers will load and run our JavaScript but GOV.UK Frontend
|
125
|
+
* won't be supported.
|
126
|
+
*
|
127
|
+
* @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
|
128
|
+
* @returns {boolean} Whether GOV.UK Frontend is supported on this page
|
129
|
+
*/
|
117
130
|
function isSupported($scope = document.body) {
|
118
131
|
if (!$scope) {
|
119
132
|
return false;
|
@@ -146,6 +159,9 @@
|
|
146
159
|
function isObject(option) {
|
147
160
|
return !!option && typeof option === 'object' && !isArray(option);
|
148
161
|
}
|
162
|
+
function formatErrorMessage(Component, message) {
|
163
|
+
return `${Component.moduleName}: ${message}`;
|
164
|
+
}
|
149
165
|
|
150
166
|
/**
|
151
167
|
* Schema for component config
|
@@ -169,6 +185,10 @@
|
|
169
185
|
* @property {string[]} required - List of required config fields
|
170
186
|
* @property {string} errorMessage - Error message when required config fields not provided
|
171
187
|
*/
|
188
|
+
/**
|
189
|
+
* @typedef ComponentWithModuleName
|
190
|
+
* @property {string} moduleName - Name of the component
|
191
|
+
*/
|
172
192
|
|
173
193
|
function normaliseDataset(Component, dataset) {
|
174
194
|
const out = {};
|
@@ -212,30 +232,85 @@
|
|
212
232
|
let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
|
213
233
|
if (typeof messageOrOptions === 'object') {
|
214
234
|
const {
|
215
|
-
|
235
|
+
component,
|
216
236
|
identifier,
|
217
237
|
element,
|
218
238
|
expectedType
|
219
239
|
} = messageOrOptions;
|
220
|
-
message =
|
240
|
+
message = identifier;
|
221
241
|
message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
|
242
|
+
message = formatErrorMessage(component, message);
|
222
243
|
}
|
223
244
|
super(message);
|
224
245
|
this.name = 'ElementError';
|
225
246
|
}
|
226
247
|
}
|
248
|
+
class InitError extends GOVUKFrontendError {
|
249
|
+
constructor(componentOrMessage) {
|
250
|
+
const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\`$root\`) already initialised`);
|
251
|
+
super(message);
|
252
|
+
this.name = 'InitError';
|
253
|
+
}
|
254
|
+
}
|
255
|
+
/**
|
256
|
+
* @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName
|
257
|
+
*/
|
227
258
|
|
228
259
|
class GOVUKFrontendComponent {
|
229
|
-
|
230
|
-
|
260
|
+
/**
|
261
|
+
* Returns the root element of the component
|
262
|
+
*
|
263
|
+
* @protected
|
264
|
+
* @returns {RootElementType} - the root element of component
|
265
|
+
*/
|
266
|
+
get $root() {
|
267
|
+
return this._$root;
|
268
|
+
}
|
269
|
+
constructor($root) {
|
270
|
+
this._$root = void 0;
|
271
|
+
const childConstructor = this.constructor;
|
272
|
+
if (typeof childConstructor.moduleName !== 'string') {
|
273
|
+
throw new InitError(`\`moduleName\` not defined in component`);
|
274
|
+
}
|
275
|
+
if (!($root instanceof childConstructor.elementType)) {
|
276
|
+
throw new ElementError({
|
277
|
+
element: $root,
|
278
|
+
component: childConstructor,
|
279
|
+
identifier: 'Root element (`$root`)',
|
280
|
+
expectedType: childConstructor.elementType.name
|
281
|
+
});
|
282
|
+
} else {
|
283
|
+
this._$root = $root;
|
284
|
+
}
|
285
|
+
childConstructor.checkSupport();
|
286
|
+
this.checkInitialised();
|
287
|
+
const moduleName = childConstructor.moduleName;
|
288
|
+
this.$root.setAttribute(`data-${moduleName}-init`, '');
|
289
|
+
}
|
290
|
+
checkInitialised() {
|
291
|
+
const constructor = this.constructor;
|
292
|
+
const moduleName = constructor.moduleName;
|
293
|
+
if (moduleName && isInitialised(this.$root, moduleName)) {
|
294
|
+
throw new InitError(constructor);
|
295
|
+
}
|
231
296
|
}
|
232
|
-
checkSupport() {
|
297
|
+
static checkSupport() {
|
233
298
|
if (!isSupported()) {
|
234
299
|
throw new SupportError();
|
235
300
|
}
|
236
301
|
}
|
237
302
|
}
|
238
303
|
|
304
|
+
/**
|
305
|
+
* @typedef ChildClass
|
306
|
+
* @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
|
307
|
+
*/
|
308
|
+
|
309
|
+
/**
|
310
|
+
* @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor
|
311
|
+
*/
|
312
|
+
GOVUKFrontendComponent.elementType = HTMLElement;
|
313
|
+
|
239
314
|
class I18n {
|
240
315
|
constructor(translations = {}, config = {}) {
|
241
316
|
var _config$locale;
|
@@ -445,12 +520,11 @@
|
|
445
520
|
*/
|
446
521
|
class Accordion extends GOVUKFrontendComponent {
|
447
522
|
/**
|
448
|
-
* @param {Element | null} $
|
523
|
+
* @param {Element | null} $root - HTML element to use for accordion
|
449
524
|
* @param {AccordionConfig} [config] - Accordion config
|
450
525
|
*/
|
451
|
-
constructor($
|
452
|
-
super();
|
453
|
-
this.$module = void 0;
|
526
|
+
constructor($root, config = {}) {
|
527
|
+
super($root);
|
454
528
|
this.config = void 0;
|
455
529
|
this.i18n = void 0;
|
456
530
|
this.controlsClass = 'govuk-accordion__controls';
|
@@ -476,20 +550,12 @@
|
|
476
550
|
this.$showAllButton = null;
|
477
551
|
this.$showAllIcon = null;
|
478
552
|
this.$showAllText = null;
|
479
|
-
|
480
|
-
throw new ElementError({
|
481
|
-
componentName: 'Accordion',
|
482
|
-
element: $module,
|
483
|
-
identifier: 'Root element (`$module`)'
|
484
|
-
});
|
485
|
-
}
|
486
|
-
this.$module = $module;
|
487
|
-
this.config = mergeConfigs(Accordion.defaults, config, normaliseDataset(Accordion, $module.dataset));
|
553
|
+
this.config = mergeConfigs(Accordion.defaults, config, normaliseDataset(Accordion, this.$root.dataset));
|
488
554
|
this.i18n = new I18n(this.config.i18n);
|
489
|
-
const $sections = this.$
|
555
|
+
const $sections = this.$root.querySelectorAll(`.${this.sectionClass}`);
|
490
556
|
if (!$sections.length) {
|
491
557
|
throw new ElementError({
|
492
|
-
|
558
|
+
component: Accordion,
|
493
559
|
identifier: `Sections (\`<div class="${this.sectionClass}">\`)`
|
494
560
|
});
|
495
561
|
}
|
@@ -509,7 +575,7 @@
|
|
509
575
|
const $accordionControls = document.createElement('div');
|
510
576
|
$accordionControls.setAttribute('class', this.controlsClass);
|
511
577
|
$accordionControls.appendChild(this.$showAllButton);
|
512
|
-
this.$
|
578
|
+
this.$root.insertBefore($accordionControls, this.$root.firstChild);
|
513
579
|
this.$showAllText = document.createElement('span');
|
514
580
|
this.$showAllText.classList.add(this.showAllTextClass);
|
515
581
|
this.$showAllButton.appendChild(this.$showAllText);
|
@@ -523,7 +589,7 @@
|
|
523
589
|
const $header = $section.querySelector(`.${this.sectionHeaderClass}`);
|
524
590
|
if (!$header) {
|
525
591
|
throw new ElementError({
|
526
|
-
|
592
|
+
component: Accordion,
|
527
593
|
identifier: `Section headers (\`<div class="${this.sectionHeaderClass}">\`)`
|
528
594
|
});
|
529
595
|
}
|
@@ -539,19 +605,19 @@
|
|
539
605
|
const $summary = $header.querySelector(`.${this.sectionSummaryClass}`);
|
540
606
|
if (!$heading) {
|
541
607
|
throw new ElementError({
|
542
|
-
|
608
|
+
component: Accordion,
|
543
609
|
identifier: `Section heading (\`.${this.sectionHeadingClass}\`)`
|
544
610
|
});
|
545
611
|
}
|
546
612
|
if (!$span) {
|
547
613
|
throw new ElementError({
|
548
|
-
|
614
|
+
component: Accordion,
|
549
615
|
identifier: `Section button placeholder (\`<span class="${this.sectionButtonClass}">\`)`
|
550
616
|
});
|
551
617
|
}
|
552
618
|
const $button = document.createElement('button');
|
553
619
|
$button.setAttribute('type', 'button');
|
554
|
-
$button.setAttribute('aria-controls', `${this.$
|
620
|
+
$button.setAttribute('aria-controls', `${this.$root.id}-content-${index + 1}`);
|
555
621
|
for (const attr of Array.from($span.attributes)) {
|
556
622
|
if (attr.name !== 'id') {
|
557
623
|
$button.setAttribute(attr.name, attr.value);
|
@@ -625,7 +691,7 @@
|
|
625
691
|
const $content = $section.querySelector(`.${this.sectionContentClass}`);
|
626
692
|
if (!$content) {
|
627
693
|
throw new ElementError({
|
628
|
-
|
694
|
+
component: Accordion,
|
629
695
|
identifier: `Section content (\`<div class="${this.sectionContentClass}">\`)`
|
630
696
|
});
|
631
697
|
}
|
@@ -788,25 +854,16 @@
|
|
788
854
|
*/
|
789
855
|
class Button extends GOVUKFrontendComponent {
|
790
856
|
/**
|
791
|
-
* @param {Element | null} $
|
857
|
+
* @param {Element | null} $root - HTML element to use for button
|
792
858
|
* @param {ButtonConfig} [config] - Button config
|
793
859
|
*/
|
794
|
-
constructor($
|
795
|
-
super();
|
796
|
-
this.$module = void 0;
|
860
|
+
constructor($root, config = {}) {
|
861
|
+
super($root);
|
797
862
|
this.config = void 0;
|
798
863
|
this.debounceFormSubmitTimer = null;
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
element: $module,
|
803
|
-
identifier: 'Root element (`$module`)'
|
804
|
-
});
|
805
|
-
}
|
806
|
-
this.$module = $module;
|
807
|
-
this.config = mergeConfigs(Button.defaults, config, normaliseDataset(Button, $module.dataset));
|
808
|
-
this.$module.addEventListener('keydown', event => this.handleKeyDown(event));
|
809
|
-
this.$module.addEventListener('click', event => this.debounce(event));
|
864
|
+
this.config = mergeConfigs(Button.defaults, config, normaliseDataset(Button, this.$root.dataset));
|
865
|
+
this.$root.addEventListener('keydown', event => this.handleKeyDown(event));
|
866
|
+
this.$root.addEventListener('click', event => this.debounce(event));
|
810
867
|
}
|
811
868
|
handleKeyDown(event) {
|
812
869
|
const $target = event.target;
|
@@ -874,13 +931,12 @@
|
|
874
931
|
*/
|
875
932
|
class CharacterCount extends GOVUKFrontendComponent {
|
876
933
|
/**
|
877
|
-
* @param {Element | null} $
|
934
|
+
* @param {Element | null} $root - HTML element to use for character count
|
878
935
|
* @param {CharacterCountConfig} [config] - Character count config
|
879
936
|
*/
|
880
|
-
constructor($
|
937
|
+
constructor($root, config = {}) {
|
881
938
|
var _ref, _this$config$maxwords;
|
882
|
-
super();
|
883
|
-
this.$module = void 0;
|
939
|
+
super($root);
|
884
940
|
this.$textarea = void 0;
|
885
941
|
this.$visibleCountMessage = void 0;
|
886
942
|
this.$screenReaderCountMessage = void 0;
|
@@ -890,23 +946,16 @@
|
|
890
946
|
this.config = void 0;
|
891
947
|
this.i18n = void 0;
|
892
948
|
this.maxLength = void 0;
|
893
|
-
|
894
|
-
throw new ElementError({
|
895
|
-
componentName: 'Character count',
|
896
|
-
element: $module,
|
897
|
-
identifier: 'Root element (`$module`)'
|
898
|
-
});
|
899
|
-
}
|
900
|
-
const $textarea = $module.querySelector('.govuk-js-character-count');
|
949
|
+
const $textarea = this.$root.querySelector('.govuk-js-character-count');
|
901
950
|
if (!($textarea instanceof HTMLTextAreaElement || $textarea instanceof HTMLInputElement)) {
|
902
951
|
throw new ElementError({
|
903
|
-
|
952
|
+
component: CharacterCount,
|
904
953
|
element: $textarea,
|
905
954
|
expectedType: 'HTMLTextareaElement or HTMLInputElement',
|
906
955
|
identifier: 'Form field (`.govuk-js-character-count`)'
|
907
956
|
});
|
908
957
|
}
|
909
|
-
const datasetConfig = normaliseDataset(CharacterCount,
|
958
|
+
const datasetConfig = normaliseDataset(CharacterCount, this.$root.dataset);
|
910
959
|
let configOverrides = {};
|
911
960
|
if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
|
912
961
|
configOverrides = {
|
@@ -917,19 +966,18 @@
|
|
917
966
|
this.config = mergeConfigs(CharacterCount.defaults, config, configOverrides, datasetConfig);
|
918
967
|
const errors = validateConfig(CharacterCount.schema, this.config);
|
919
968
|
if (errors[0]) {
|
920
|
-
throw new ConfigError(
|
969
|
+
throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]));
|
921
970
|
}
|
922
971
|
this.i18n = new I18n(this.config.i18n, {
|
923
|
-
locale: closestAttributeValue(
|
972
|
+
locale: closestAttributeValue(this.$root, 'lang')
|
924
973
|
});
|
925
974
|
this.maxLength = (_ref = (_this$config$maxwords = this.config.maxwords) != null ? _this$config$maxwords : this.config.maxlength) != null ? _ref : Infinity;
|
926
|
-
this.$module = $module;
|
927
975
|
this.$textarea = $textarea;
|
928
976
|
const textareaDescriptionId = `${this.$textarea.id}-info`;
|
929
977
|
const $textareaDescription = document.getElementById(textareaDescriptionId);
|
930
978
|
if (!$textareaDescription) {
|
931
979
|
throw new ElementError({
|
932
|
-
|
980
|
+
component: CharacterCount,
|
933
981
|
element: $textareaDescription,
|
934
982
|
identifier: `Count message (\`id="${textareaDescriptionId}"\`)`
|
935
983
|
});
|
@@ -1173,27 +1221,18 @@
|
|
1173
1221
|
* (for example if the user has navigated back), and set up event handlers to
|
1174
1222
|
* keep the reveal in sync with the checkbox state.
|
1175
1223
|
*
|
1176
|
-
* @param {Element | null} $
|
1224
|
+
* @param {Element | null} $root - HTML element to use for checkboxes
|
1177
1225
|
*/
|
1178
|
-
constructor($
|
1179
|
-
super();
|
1180
|
-
this.$module = void 0;
|
1226
|
+
constructor($root) {
|
1227
|
+
super($root);
|
1181
1228
|
this.$inputs = void 0;
|
1182
|
-
|
1183
|
-
throw new ElementError({
|
1184
|
-
componentName: 'Checkboxes',
|
1185
|
-
element: $module,
|
1186
|
-
identifier: 'Root element (`$module`)'
|
1187
|
-
});
|
1188
|
-
}
|
1189
|
-
const $inputs = $module.querySelectorAll('input[type="checkbox"]');
|
1229
|
+
const $inputs = this.$root.querySelectorAll('input[type="checkbox"]');
|
1190
1230
|
if (!$inputs.length) {
|
1191
1231
|
throw new ElementError({
|
1192
|
-
|
1232
|
+
component: Checkboxes,
|
1193
1233
|
identifier: 'Form inputs (`<input type="checkbox">`)'
|
1194
1234
|
});
|
1195
1235
|
}
|
1196
|
-
this.$module = $module;
|
1197
1236
|
this.$inputs = $inputs;
|
1198
1237
|
this.$inputs.forEach($input => {
|
1199
1238
|
const targetId = $input.getAttribute('data-aria-controls');
|
@@ -1202,7 +1241,7 @@
|
|
1202
1241
|
}
|
1203
1242
|
if (!document.getElementById(targetId)) {
|
1204
1243
|
throw new ElementError({
|
1205
|
-
|
1244
|
+
component: Checkboxes,
|
1206
1245
|
identifier: `Conditional reveal (\`id="${targetId}"\`)`
|
1207
1246
|
});
|
1208
1247
|
}
|
@@ -1211,7 +1250,7 @@
|
|
1211
1250
|
});
|
1212
1251
|
window.addEventListener('pageshow', () => this.syncAllConditionalReveals());
|
1213
1252
|
this.syncAllConditionalReveals();
|
1214
|
-
this.$
|
1253
|
+
this.$root.addEventListener('click', event => this.handleClick(event));
|
1215
1254
|
}
|
1216
1255
|
syncAllConditionalReveals() {
|
1217
1256
|
this.$inputs.forEach($input => this.syncConditionalRevealWithInputState($input));
|
@@ -1280,26 +1319,17 @@
|
|
1280
1319
|
*/
|
1281
1320
|
class ErrorSummary extends GOVUKFrontendComponent {
|
1282
1321
|
/**
|
1283
|
-
* @param {Element | null} $
|
1322
|
+
* @param {Element | null} $root - HTML element to use for error summary
|
1284
1323
|
* @param {ErrorSummaryConfig} [config] - Error summary config
|
1285
1324
|
*/
|
1286
|
-
constructor($
|
1287
|
-
super();
|
1288
|
-
this.$module = void 0;
|
1325
|
+
constructor($root, config = {}) {
|
1326
|
+
super($root);
|
1289
1327
|
this.config = void 0;
|
1290
|
-
|
1291
|
-
throw new ElementError({
|
1292
|
-
componentName: 'Error summary',
|
1293
|
-
element: $module,
|
1294
|
-
identifier: 'Root element (`$module`)'
|
1295
|
-
});
|
1296
|
-
}
|
1297
|
-
this.$module = $module;
|
1298
|
-
this.config = mergeConfigs(ErrorSummary.defaults, config, normaliseDataset(ErrorSummary, $module.dataset));
|
1328
|
+
this.config = mergeConfigs(ErrorSummary.defaults, config, normaliseDataset(ErrorSummary, this.$root.dataset));
|
1299
1329
|
if (!this.config.disableAutoFocus) {
|
1300
|
-
setFocus(this.$
|
1330
|
+
setFocus(this.$root);
|
1301
1331
|
}
|
1302
|
-
this.$
|
1332
|
+
this.$root.addEventListener('click', event => this.handleClick(event));
|
1303
1333
|
}
|
1304
1334
|
handleClick(event) {
|
1305
1335
|
const $target = event.target;
|
@@ -1383,12 +1413,11 @@
|
|
1383
1413
|
*/
|
1384
1414
|
class ExitThisPage extends GOVUKFrontendComponent {
|
1385
1415
|
/**
|
1386
|
-
* @param {Element | null} $
|
1416
|
+
* @param {Element | null} $root - HTML element that wraps the Exit This Page button
|
1387
1417
|
* @param {ExitThisPageConfig} [config] - Exit This Page config
|
1388
1418
|
*/
|
1389
|
-
constructor($
|
1390
|
-
super();
|
1391
|
-
this.$module = void 0;
|
1419
|
+
constructor($root, config = {}) {
|
1420
|
+
super($root);
|
1392
1421
|
this.config = void 0;
|
1393
1422
|
this.i18n = void 0;
|
1394
1423
|
this.$button = void 0;
|
@@ -1401,25 +1430,17 @@
|
|
1401
1430
|
this.timeoutTime = 5000;
|
1402
1431
|
this.keypressTimeoutId = null;
|
1403
1432
|
this.timeoutMessageId = null;
|
1404
|
-
|
1405
|
-
throw new ElementError({
|
1406
|
-
componentName: 'Exit this page',
|
1407
|
-
element: $module,
|
1408
|
-
identifier: 'Root element (`$module`)'
|
1409
|
-
});
|
1410
|
-
}
|
1411
|
-
const $button = $module.querySelector('.govuk-exit-this-page__button');
|
1433
|
+
const $button = this.$root.querySelector('.govuk-exit-this-page__button');
|
1412
1434
|
if (!($button instanceof HTMLAnchorElement)) {
|
1413
1435
|
throw new ElementError({
|
1414
|
-
|
1436
|
+
component: ExitThisPage,
|
1415
1437
|
element: $button,
|
1416
1438
|
expectedType: 'HTMLAnchorElement',
|
1417
1439
|
identifier: 'Button (`.govuk-exit-this-page__button`)'
|
1418
1440
|
});
|
1419
1441
|
}
|
1420
|
-
this.config = mergeConfigs(ExitThisPage.defaults, config, normaliseDataset(ExitThisPage,
|
1442
|
+
this.config = mergeConfigs(ExitThisPage.defaults, config, normaliseDataset(ExitThisPage, this.$root.dataset));
|
1421
1443
|
this.i18n = new I18n(this.config.i18n);
|
1422
|
-
this.$module = $module;
|
1423
1444
|
this.$button = $button;
|
1424
1445
|
const $skiplinkButton = document.querySelector('.govuk-js-exit-this-page-skiplink');
|
1425
1446
|
if ($skiplinkButton instanceof HTMLAnchorElement) {
|
@@ -1438,7 +1459,7 @@
|
|
1438
1459
|
this.$updateSpan = document.createElement('span');
|
1439
1460
|
this.$updateSpan.setAttribute('role', 'status');
|
1440
1461
|
this.$updateSpan.className = 'govuk-visually-hidden';
|
1441
|
-
this.$
|
1462
|
+
this.$root.appendChild(this.$updateSpan);
|
1442
1463
|
}
|
1443
1464
|
initButtonClickHandler() {
|
1444
1465
|
this.$button.addEventListener('click', this.handleClick.bind(this));
|
@@ -1613,38 +1634,29 @@
|
|
1613
1634
|
* Apply a matchMedia for desktop which will trigger a state sync if the
|
1614
1635
|
* browser viewport moves between states.
|
1615
1636
|
*
|
1616
|
-
* @param {Element | null} $
|
1637
|
+
* @param {Element | null} $root - HTML element to use for header
|
1617
1638
|
*/
|
1618
|
-
constructor($
|
1619
|
-
super();
|
1620
|
-
this.$module = void 0;
|
1639
|
+
constructor($root) {
|
1640
|
+
super($root);
|
1621
1641
|
this.$menuButton = void 0;
|
1622
1642
|
this.$menu = void 0;
|
1623
1643
|
this.menuIsOpen = false;
|
1624
1644
|
this.mql = null;
|
1625
|
-
|
1626
|
-
throw new ElementError({
|
1627
|
-
componentName: 'Header',
|
1628
|
-
element: $module,
|
1629
|
-
identifier: 'Root element (`$module`)'
|
1630
|
-
});
|
1631
|
-
}
|
1632
|
-
this.$module = $module;
|
1633
|
-
const $menuButton = $module.querySelector('.govuk-js-header-toggle');
|
1645
|
+
const $menuButton = this.$root.querySelector('.govuk-js-header-toggle');
|
1634
1646
|
if (!$menuButton) {
|
1635
1647
|
return this;
|
1636
1648
|
}
|
1637
1649
|
const menuId = $menuButton.getAttribute('aria-controls');
|
1638
1650
|
if (!menuId) {
|
1639
1651
|
throw new ElementError({
|
1640
|
-
|
1652
|
+
component: Header,
|
1641
1653
|
identifier: 'Navigation button (`<button class="govuk-js-header-toggle">`) attribute (`aria-controls`)'
|
1642
1654
|
});
|
1643
1655
|
}
|
1644
1656
|
const $menu = document.getElementById(menuId);
|
1645
1657
|
if (!$menu) {
|
1646
1658
|
throw new ElementError({
|
1647
|
-
|
1659
|
+
component: Header,
|
1648
1660
|
element: $menu,
|
1649
1661
|
identifier: `Navigation (\`<ul id="${menuId}">\`)`
|
1650
1662
|
});
|
@@ -1658,7 +1670,7 @@
|
|
1658
1670
|
const breakpoint = getBreakpoint('desktop');
|
1659
1671
|
if (!breakpoint.value) {
|
1660
1672
|
throw new ElementError({
|
1661
|
-
|
1673
|
+
component: Header,
|
1662
1674
|
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
|
1663
1675
|
});
|
1664
1676
|
}
|
@@ -1701,24 +1713,15 @@
|
|
1701
1713
|
*/
|
1702
1714
|
class NotificationBanner extends GOVUKFrontendComponent {
|
1703
1715
|
/**
|
1704
|
-
* @param {Element | null} $
|
1716
|
+
* @param {Element | null} $root - HTML element to use for notification banner
|
1705
1717
|
* @param {NotificationBannerConfig} [config] - Notification banner config
|
1706
1718
|
*/
|
1707
|
-
constructor($
|
1708
|
-
super();
|
1709
|
-
this.$module = void 0;
|
1719
|
+
constructor($root, config = {}) {
|
1720
|
+
super($root);
|
1710
1721
|
this.config = void 0;
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
element: $module,
|
1715
|
-
identifier: 'Root element (`$module`)'
|
1716
|
-
});
|
1717
|
-
}
|
1718
|
-
this.$module = $module;
|
1719
|
-
this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, $module.dataset));
|
1720
|
-
if (this.$module.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
|
1721
|
-
setFocus(this.$module);
|
1722
|
+
this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, this.$root.dataset));
|
1723
|
+
if (this.$root.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
|
1724
|
+
setFocus(this.$root);
|
1722
1725
|
}
|
1723
1726
|
}
|
1724
1727
|
}
|
@@ -1755,28 +1758,20 @@
|
|
1755
1758
|
*/
|
1756
1759
|
class PasswordInput extends GOVUKFrontendComponent {
|
1757
1760
|
/**
|
1758
|
-
* @param {Element | null} $
|
1761
|
+
* @param {Element | null} $root - HTML element to use for password input
|
1759
1762
|
* @param {PasswordInputConfig} [config] - Password input config
|
1760
1763
|
*/
|
1761
|
-
constructor($
|
1762
|
-
super();
|
1763
|
-
this.$module = void 0;
|
1764
|
+
constructor($root, config = {}) {
|
1765
|
+
super($root);
|
1764
1766
|
this.config = void 0;
|
1765
1767
|
this.i18n = void 0;
|
1766
1768
|
this.$input = void 0;
|
1767
1769
|
this.$showHideButton = void 0;
|
1768
1770
|
this.$screenReaderStatusMessage = void 0;
|
1769
|
-
|
1770
|
-
throw new ElementError({
|
1771
|
-
componentName: 'Password input',
|
1772
|
-
element: $module,
|
1773
|
-
identifier: 'Root element (`$module`)'
|
1774
|
-
});
|
1775
|
-
}
|
1776
|
-
const $input = $module.querySelector('.govuk-js-password-input-input');
|
1771
|
+
const $input = this.$root.querySelector('.govuk-js-password-input-input');
|
1777
1772
|
if (!($input instanceof HTMLInputElement)) {
|
1778
1773
|
throw new ElementError({
|
1779
|
-
|
1774
|
+
component: PasswordInput,
|
1780
1775
|
element: $input,
|
1781
1776
|
expectedType: 'HTMLInputElement',
|
1782
1777
|
identifier: 'Form field (`.govuk-js-password-input-input`)'
|
@@ -1785,10 +1780,10 @@
|
|
1785
1780
|
if ($input.type !== 'password') {
|
1786
1781
|
throw new ElementError('Password input: Form field (`.govuk-js-password-input-input`) must be of type `password`.');
|
1787
1782
|
}
|
1788
|
-
const $showHideButton =
|
1783
|
+
const $showHideButton = this.$root.querySelector('.govuk-js-password-input-toggle');
|
1789
1784
|
if (!($showHideButton instanceof HTMLButtonElement)) {
|
1790
1785
|
throw new ElementError({
|
1791
|
-
|
1786
|
+
component: PasswordInput,
|
1792
1787
|
element: $showHideButton,
|
1793
1788
|
expectedType: 'HTMLButtonElement',
|
1794
1789
|
identifier: 'Button (`.govuk-js-password-input-toggle`)'
|
@@ -1797,12 +1792,11 @@
|
|
1797
1792
|
if ($showHideButton.type !== 'button') {
|
1798
1793
|
throw new ElementError('Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.');
|
1799
1794
|
}
|
1800
|
-
this.$module = $module;
|
1801
1795
|
this.$input = $input;
|
1802
1796
|
this.$showHideButton = $showHideButton;
|
1803
|
-
this.config = mergeConfigs(PasswordInput.defaults, config, normaliseDataset(PasswordInput,
|
1797
|
+
this.config = mergeConfigs(PasswordInput.defaults, config, normaliseDataset(PasswordInput, this.$root.dataset));
|
1804
1798
|
this.i18n = new I18n(this.config.i18n, {
|
1805
|
-
locale: closestAttributeValue(
|
1799
|
+
locale: closestAttributeValue(this.$root, 'lang')
|
1806
1800
|
});
|
1807
1801
|
this.$showHideButton.removeAttribute('hidden');
|
1808
1802
|
const $screenReaderStatusMessage = document.createElement('div');
|
@@ -1920,27 +1914,18 @@
|
|
1920
1914
|
* (for example if the user has navigated back), and set up event handlers to
|
1921
1915
|
* keep the reveal in sync with the radio state.
|
1922
1916
|
*
|
1923
|
-
* @param {Element | null} $
|
1917
|
+
* @param {Element | null} $root - HTML element to use for radios
|
1924
1918
|
*/
|
1925
|
-
constructor($
|
1926
|
-
super();
|
1927
|
-
this.$module = void 0;
|
1919
|
+
constructor($root) {
|
1920
|
+
super($root);
|
1928
1921
|
this.$inputs = void 0;
|
1929
|
-
|
1930
|
-
throw new ElementError({
|
1931
|
-
componentName: 'Radios',
|
1932
|
-
element: $module,
|
1933
|
-
identifier: 'Root element (`$module`)'
|
1934
|
-
});
|
1935
|
-
}
|
1936
|
-
const $inputs = $module.querySelectorAll('input[type="radio"]');
|
1922
|
+
const $inputs = this.$root.querySelectorAll('input[type="radio"]');
|
1937
1923
|
if (!$inputs.length) {
|
1938
1924
|
throw new ElementError({
|
1939
|
-
|
1925
|
+
component: Radios,
|
1940
1926
|
identifier: 'Form inputs (`<input type="radio">`)'
|
1941
1927
|
});
|
1942
1928
|
}
|
1943
|
-
this.$module = $module;
|
1944
1929
|
this.$inputs = $inputs;
|
1945
1930
|
this.$inputs.forEach($input => {
|
1946
1931
|
const targetId = $input.getAttribute('data-aria-controls');
|
@@ -1949,7 +1934,7 @@
|
|
1949
1934
|
}
|
1950
1935
|
if (!document.getElementById(targetId)) {
|
1951
1936
|
throw new ElementError({
|
1952
|
-
|
1937
|
+
component: Radios,
|
1953
1938
|
identifier: `Conditional reveal (\`id="${targetId}"\`)`
|
1954
1939
|
});
|
1955
1940
|
}
|
@@ -1958,7 +1943,7 @@
|
|
1958
1943
|
});
|
1959
1944
|
window.addEventListener('pageshow', () => this.syncAllConditionalReveals());
|
1960
1945
|
this.syncAllConditionalReveals();
|
1961
|
-
this.$
|
1946
|
+
this.$root.addEventListener('click', event => this.handleClick(event));
|
1962
1947
|
}
|
1963
1948
|
syncAllConditionalReveals() {
|
1964
1949
|
this.$inputs.forEach($input => this.syncConditionalRevealWithInputState($input));
|
@@ -1995,35 +1980,105 @@
|
|
1995
1980
|
Radios.moduleName = 'govuk-radios';
|
1996
1981
|
|
1997
1982
|
/**
|
1998
|
-
*
|
1983
|
+
* Service Navigation component
|
1999
1984
|
*
|
2000
1985
|
* @preserve
|
2001
1986
|
*/
|
2002
|
-
class
|
1987
|
+
class ServiceNavigation extends GOVUKFrontendComponent {
|
2003
1988
|
/**
|
2004
|
-
* @param {Element | null} $
|
2005
|
-
* @throws {ElementError} when $module is not set or the wrong type
|
2006
|
-
* @throws {ElementError} when $module.hash does not contain a hash
|
2007
|
-
* @throws {ElementError} when the linked element is missing or the wrong type
|
1989
|
+
* @param {Element | null} $root - HTML element to use for header
|
2008
1990
|
*/
|
2009
|
-
constructor($
|
2010
|
-
|
2011
|
-
|
2012
|
-
this.$
|
2013
|
-
|
1991
|
+
constructor($root) {
|
1992
|
+
super($root);
|
1993
|
+
this.$menuButton = void 0;
|
1994
|
+
this.$menu = void 0;
|
1995
|
+
this.menuIsOpen = false;
|
1996
|
+
this.mql = null;
|
1997
|
+
const $menuButton = this.$root.querySelector('.govuk-js-service-navigation-toggle');
|
1998
|
+
if (!$menuButton) {
|
1999
|
+
return this;
|
2000
|
+
}
|
2001
|
+
const menuId = $menuButton.getAttribute('aria-controls');
|
2002
|
+
if (!menuId) {
|
2014
2003
|
throw new ElementError({
|
2015
|
-
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
2004
|
+
component: ServiceNavigation,
|
2005
|
+
identifier: 'Navigation button (`<button class="govuk-js-service-navigation-toggle">`) attribute (`aria-controls`)'
|
2006
|
+
});
|
2007
|
+
}
|
2008
|
+
const $menu = document.getElementById(menuId);
|
2009
|
+
if (!$menu) {
|
2010
|
+
throw new ElementError({
|
2011
|
+
component: ServiceNavigation,
|
2012
|
+
element: $menu,
|
2013
|
+
identifier: `Navigation (\`<ul id="${menuId}">\`)`
|
2014
|
+
});
|
2015
|
+
}
|
2016
|
+
this.$menu = $menu;
|
2017
|
+
this.$menuButton = $menuButton;
|
2018
|
+
this.setupResponsiveChecks();
|
2019
|
+
this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
|
2020
|
+
}
|
2021
|
+
setupResponsiveChecks() {
|
2022
|
+
const breakpoint = getBreakpoint('tablet');
|
2023
|
+
if (!breakpoint.value) {
|
2024
|
+
throw new ElementError({
|
2025
|
+
component: ServiceNavigation,
|
2026
|
+
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
|
2019
2027
|
});
|
2020
2028
|
}
|
2021
|
-
this
|
2022
|
-
|
2023
|
-
|
2029
|
+
this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
|
2030
|
+
if ('addEventListener' in this.mql) {
|
2031
|
+
this.mql.addEventListener('change', () => this.checkMode());
|
2032
|
+
} else {
|
2033
|
+
this.mql.addListener(() => this.checkMode());
|
2034
|
+
}
|
2035
|
+
this.checkMode();
|
2036
|
+
}
|
2037
|
+
checkMode() {
|
2038
|
+
if (!this.mql || !this.$menu || !this.$menuButton) {
|
2039
|
+
return;
|
2040
|
+
}
|
2041
|
+
if (this.mql.matches) {
|
2042
|
+
this.$menu.removeAttribute('hidden');
|
2043
|
+
this.$menuButton.setAttribute('hidden', '');
|
2044
|
+
} else {
|
2045
|
+
this.$menuButton.removeAttribute('hidden');
|
2046
|
+
this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString());
|
2047
|
+
if (this.menuIsOpen) {
|
2048
|
+
this.$menu.removeAttribute('hidden');
|
2049
|
+
} else {
|
2050
|
+
this.$menu.setAttribute('hidden', '');
|
2051
|
+
}
|
2052
|
+
}
|
2053
|
+
}
|
2054
|
+
handleMenuButtonClick() {
|
2055
|
+
this.menuIsOpen = !this.menuIsOpen;
|
2056
|
+
this.checkMode();
|
2057
|
+
}
|
2058
|
+
}
|
2059
|
+
ServiceNavigation.moduleName = 'govuk-service-navigation';
|
2060
|
+
|
2061
|
+
/**
|
2062
|
+
* Skip link component
|
2063
|
+
*
|
2064
|
+
* @preserve
|
2065
|
+
* @augments GOVUKFrontendComponent<HTMLAnchorElement>
|
2066
|
+
*/
|
2067
|
+
class SkipLink extends GOVUKFrontendComponent {
|
2068
|
+
/**
|
2069
|
+
* @param {Element | null} $root - HTML element to use for skip link
|
2070
|
+
* @throws {ElementError} when $root is not set or the wrong type
|
2071
|
+
* @throws {ElementError} when $root.hash does not contain a hash
|
2072
|
+
* @throws {ElementError} when the linked element is missing or the wrong type
|
2073
|
+
*/
|
2074
|
+
constructor($root) {
|
2075
|
+
var _this$$root$getAttrib;
|
2076
|
+
super($root);
|
2077
|
+
const hash = this.$root.hash;
|
2078
|
+
const href = (_this$$root$getAttrib = this.$root.getAttribute('href')) != null ? _this$$root$getAttrib : '';
|
2024
2079
|
let url;
|
2025
2080
|
try {
|
2026
|
-
url = new window.URL(this.$
|
2081
|
+
url = new window.URL(this.$root.href);
|
2027
2082
|
} catch (error) {
|
2028
2083
|
throw new ElementError(`Skip link: Target link (\`href="${href}"\`) is invalid`);
|
2029
2084
|
}
|
@@ -2037,12 +2092,12 @@
|
|
2037
2092
|
const $linkedElement = document.getElementById(linkedElementId);
|
2038
2093
|
if (!$linkedElement) {
|
2039
2094
|
throw new ElementError({
|
2040
|
-
|
2095
|
+
component: SkipLink,
|
2041
2096
|
element: $linkedElement,
|
2042
2097
|
identifier: `Target content (\`id="${linkedElementId}"\`)`
|
2043
2098
|
});
|
2044
2099
|
}
|
2045
|
-
this.$
|
2100
|
+
this.$root.addEventListener('click', () => setFocus($linkedElement, {
|
2046
2101
|
onBeforeFocus() {
|
2047
2102
|
$linkedElement.classList.add('govuk-skip-link-focused-element');
|
2048
2103
|
},
|
@@ -2052,6 +2107,7 @@
|
|
2052
2107
|
}));
|
2053
2108
|
}
|
2054
2109
|
}
|
2110
|
+
SkipLink.elementType = HTMLAnchorElement;
|
2055
2111
|
SkipLink.moduleName = 'govuk-skip-link';
|
2056
2112
|
|
2057
2113
|
/**
|
@@ -2061,11 +2117,10 @@
|
|
2061
2117
|
*/
|
2062
2118
|
class Tabs extends GOVUKFrontendComponent {
|
2063
2119
|
/**
|
2064
|
-
* @param {Element | null} $
|
2120
|
+
* @param {Element | null} $root - HTML element to use for tabs
|
2065
2121
|
*/
|
2066
|
-
constructor($
|
2067
|
-
super();
|
2068
|
-
this.$module = void 0;
|
2122
|
+
constructor($root) {
|
2123
|
+
super($root);
|
2069
2124
|
this.$tabs = void 0;
|
2070
2125
|
this.$tabList = void 0;
|
2071
2126
|
this.$tabListItems = void 0;
|
@@ -2075,36 +2130,28 @@
|
|
2075
2130
|
this.boundTabKeydown = void 0;
|
2076
2131
|
this.boundOnHashChange = void 0;
|
2077
2132
|
this.mql = null;
|
2078
|
-
|
2079
|
-
throw new ElementError({
|
2080
|
-
componentName: 'Tabs',
|
2081
|
-
element: $module,
|
2082
|
-
identifier: 'Root element (`$module`)'
|
2083
|
-
});
|
2084
|
-
}
|
2085
|
-
const $tabs = $module.querySelectorAll('a.govuk-tabs__tab');
|
2133
|
+
const $tabs = this.$root.querySelectorAll('a.govuk-tabs__tab');
|
2086
2134
|
if (!$tabs.length) {
|
2087
2135
|
throw new ElementError({
|
2088
|
-
|
2136
|
+
component: Tabs,
|
2089
2137
|
identifier: 'Links (`<a class="govuk-tabs__tab">`)'
|
2090
2138
|
});
|
2091
2139
|
}
|
2092
|
-
this.$module = $module;
|
2093
2140
|
this.$tabs = $tabs;
|
2094
2141
|
this.boundTabClick = this.onTabClick.bind(this);
|
2095
2142
|
this.boundTabKeydown = this.onTabKeydown.bind(this);
|
2096
2143
|
this.boundOnHashChange = this.onHashChange.bind(this);
|
2097
|
-
const $tabList = this.$
|
2098
|
-
const $tabListItems = this.$
|
2144
|
+
const $tabList = this.$root.querySelector('.govuk-tabs__list');
|
2145
|
+
const $tabListItems = this.$root.querySelectorAll('li.govuk-tabs__list-item');
|
2099
2146
|
if (!$tabList) {
|
2100
2147
|
throw new ElementError({
|
2101
|
-
|
2148
|
+
component: Tabs,
|
2102
2149
|
identifier: 'List (`<ul class="govuk-tabs__list">`)'
|
2103
2150
|
});
|
2104
2151
|
}
|
2105
2152
|
if (!$tabListItems.length) {
|
2106
2153
|
throw new ElementError({
|
2107
|
-
|
2154
|
+
component: Tabs,
|
2108
2155
|
identifier: 'List items (`<li class="govuk-tabs__list-item">`)'
|
2109
2156
|
});
|
2110
2157
|
}
|
@@ -2116,7 +2163,7 @@
|
|
2116
2163
|
const breakpoint = getBreakpoint('tablet');
|
2117
2164
|
if (!breakpoint.value) {
|
2118
2165
|
throw new ElementError({
|
2119
|
-
|
2166
|
+
component: Tabs,
|
2120
2167
|
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
|
2121
2168
|
});
|
2122
2169
|
}
|
@@ -2191,7 +2238,7 @@
|
|
2191
2238
|
this.showPanel($tab);
|
2192
2239
|
}
|
2193
2240
|
getTab(hash) {
|
2194
|
-
return this.$
|
2241
|
+
return this.$root.querySelector(`a.govuk-tabs__tab[href="${hash}"]`);
|
2195
2242
|
}
|
2196
2243
|
setAttributes($tab) {
|
2197
2244
|
const panelId = getFragmentFromUrl($tab.href);
|
@@ -2302,7 +2349,7 @@
|
|
2302
2349
|
if (!panelId) {
|
2303
2350
|
return null;
|
2304
2351
|
}
|
2305
|
-
return this.$
|
2352
|
+
return this.$root.querySelector(`#${panelId}`);
|
2306
2353
|
}
|
2307
2354
|
showPanel($tab) {
|
2308
2355
|
const $panel = this.getPanel($tab);
|
@@ -2335,7 +2382,7 @@
|
|
2335
2382
|
$tab.setAttribute('tabindex', '0');
|
2336
2383
|
}
|
2337
2384
|
getCurrentTab() {
|
2338
|
-
return this.$
|
2385
|
+
return this.$root.querySelector('.govuk-tabs__list-item--selected a.govuk-tabs__tab');
|
2339
2386
|
}
|
2340
2387
|
}
|
2341
2388
|
Tabs.moduleName = 'govuk-tabs';
|
@@ -2346,19 +2393,28 @@
|
|
2346
2393
|
* Use the `data-module` attributes to find, instantiate and init all of the
|
2347
2394
|
* components provided as part of GOV.UK Frontend.
|
2348
2395
|
*
|
2349
|
-
* @param {Config & { scope?: Element }} [config] - Config for all components (with optional scope)
|
2396
|
+
* @param {Config & { scope?: Element, onError?: OnErrorCallback<CompatibleClass> }} [config] - Config for all components (with optional scope)
|
2350
2397
|
*/
|
2351
2398
|
function initAll(config) {
|
2352
2399
|
var _config$scope;
|
2353
2400
|
config = typeof config !== 'undefined' ? config : {};
|
2354
2401
|
if (!isSupported()) {
|
2355
|
-
|
2402
|
+
if (config.onError) {
|
2403
|
+
config.onError(new SupportError(), {
|
2404
|
+
config
|
2405
|
+
});
|
2406
|
+
} else {
|
2407
|
+
console.log(new SupportError());
|
2408
|
+
}
|
2356
2409
|
return;
|
2357
2410
|
}
|
2358
|
-
const components = [[Accordion, config.accordion], [Button, config.button], [CharacterCount, config.characterCount], [Checkboxes], [ErrorSummary, config.errorSummary], [ExitThisPage, config.exitThisPage], [Header], [NotificationBanner, config.notificationBanner], [PasswordInput, config.passwordInput], [Radios], [SkipLink], [Tabs]];
|
2359
|
-
const
|
2411
|
+
const components = [[Accordion, config.accordion], [Button, config.button], [CharacterCount, config.characterCount], [Checkboxes], [ErrorSummary, config.errorSummary], [ExitThisPage, config.exitThisPage], [Header], [NotificationBanner, config.notificationBanner], [PasswordInput, config.passwordInput], [Radios], [ServiceNavigation], [SkipLink], [Tabs]];
|
2412
|
+
const options = {
|
2413
|
+
scope: (_config$scope = config.scope) != null ? _config$scope : document,
|
2414
|
+
onError: config.onError
|
2415
|
+
};
|
2360
2416
|
components.forEach(([Component, config]) => {
|
2361
|
-
createAll(Component, config,
|
2417
|
+
createAll(Component, config, options);
|
2362
2418
|
});
|
2363
2419
|
}
|
2364
2420
|
|
@@ -2373,17 +2429,50 @@
|
|
2373
2429
|
*
|
2374
2430
|
* @template {CompatibleClass} T
|
2375
2431
|
* @param {T} Component - class of the component to create
|
2376
|
-
* @param {T["defaults"]} [config] -
|
2377
|
-
* @param {Element|Document} [
|
2432
|
+
* @param {T["defaults"]} [config] - Config supplied to component
|
2433
|
+
* @param {OnErrorCallback<T> | Element | Document | CreateAllOptions<T> } [createAllOptions] - options for createAll including scope of the document to search within and callback function if error throw by component on init
|
2378
2434
|
* @returns {Array<InstanceType<T>>} - array of instantiated components
|
2379
2435
|
*/
|
2380
|
-
function createAll(Component, config,
|
2436
|
+
function createAll(Component, config, createAllOptions) {
|
2437
|
+
let $scope = document;
|
2438
|
+
let onError;
|
2439
|
+
if (typeof createAllOptions === 'object') {
|
2440
|
+
var _createAllOptions$sco;
|
2441
|
+
createAllOptions = createAllOptions;
|
2442
|
+
$scope = (_createAllOptions$sco = createAllOptions.scope) != null ? _createAllOptions$sco : $scope;
|
2443
|
+
onError = createAllOptions.onError;
|
2444
|
+
}
|
2445
|
+
if (typeof createAllOptions === 'function') {
|
2446
|
+
onError = createAllOptions;
|
2447
|
+
}
|
2448
|
+
if (createAllOptions instanceof HTMLElement) {
|
2449
|
+
$scope = createAllOptions;
|
2450
|
+
}
|
2381
2451
|
const $elements = $scope.querySelectorAll(`[data-module="${Component.moduleName}"]`);
|
2452
|
+
if (!isSupported()) {
|
2453
|
+
if (onError) {
|
2454
|
+
onError(new SupportError(), {
|
2455
|
+
component: Component,
|
2456
|
+
config
|
2457
|
+
});
|
2458
|
+
} else {
|
2459
|
+
console.log(new SupportError());
|
2460
|
+
}
|
2461
|
+
return [];
|
2462
|
+
}
|
2382
2463
|
return Array.from($elements).map($element => {
|
2383
2464
|
try {
|
2384
|
-
return
|
2465
|
+
return typeof config !== 'undefined' ? new Component($element, config) : new Component($element);
|
2385
2466
|
} catch (error) {
|
2386
|
-
|
2467
|
+
if (onError) {
|
2468
|
+
onError(error, {
|
2469
|
+
element: $element,
|
2470
|
+
component: Component,
|
2471
|
+
config
|
2472
|
+
});
|
2473
|
+
} else {
|
2474
|
+
console.log(error);
|
2475
|
+
}
|
2387
2476
|
return null;
|
2388
2477
|
}
|
2389
2478
|
}).filter(Boolean);
|
@@ -2422,21 +2511,43 @@
|
|
2422
2511
|
*
|
2423
2512
|
* @typedef {keyof Config} ConfigKey
|
2424
2513
|
*/
|
2514
|
+
/**
|
2515
|
+
* @template {CompatibleClass} T
|
2516
|
+
* @typedef {object} ErrorContext
|
2517
|
+
* @property {Element} [element] - Element used for component module initialisation
|
2518
|
+
* @property {T} [component] - Class of component
|
2519
|
+
* @property {T["defaults"]} config - Config supplied to component
|
2520
|
+
*/
|
2521
|
+
/**
|
2522
|
+
* @template {CompatibleClass} T
|
2523
|
+
* @callback OnErrorCallback
|
2524
|
+
* @param {unknown} error - Thrown error
|
2525
|
+
* @param {ErrorContext<T>} context - Object containing the element, component class and configuration
|
2526
|
+
*/
|
2527
|
+
/**
|
2528
|
+
* @template {CompatibleClass} T
|
2529
|
+
* @typedef {object} CreateAllOptions
|
2530
|
+
* @property {Element | Document} [scope] - scope of the document to search within
|
2531
|
+
* @property {OnErrorCallback<T>} [onError] - callback function if error throw by component on init
|
2532
|
+
*/
|
2425
2533
|
|
2426
2534
|
exports.Accordion = Accordion;
|
2427
2535
|
exports.Button = Button;
|
2428
2536
|
exports.CharacterCount = CharacterCount;
|
2429
2537
|
exports.Checkboxes = Checkboxes;
|
2538
|
+
exports.Component = GOVUKFrontendComponent;
|
2430
2539
|
exports.ErrorSummary = ErrorSummary;
|
2431
2540
|
exports.ExitThisPage = ExitThisPage;
|
2432
2541
|
exports.Header = Header;
|
2433
2542
|
exports.NotificationBanner = NotificationBanner;
|
2434
2543
|
exports.PasswordInput = PasswordInput;
|
2435
2544
|
exports.Radios = Radios;
|
2545
|
+
exports.ServiceNavigation = ServiceNavigation;
|
2436
2546
|
exports.SkipLink = SkipLink;
|
2437
2547
|
exports.Tabs = Tabs;
|
2438
2548
|
exports.createAll = createAll;
|
2439
2549
|
exports.initAll = initAll;
|
2550
|
+
exports.isSupported = isSupported;
|
2440
2551
|
exports.version = version;
|
2441
2552
|
|
2442
2553
|
}));
|