govuk_tech_docs 4.2.0 → 4.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/govuk_tech_docs.gemspec +1 -1
- data/lib/assets/stylesheets/_govuk_tech_docs.scss +3 -0
- data/lib/govuk_tech_docs/version.rb +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +508 -209
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +505 -208
- data/node_modules/govuk-frontend/dist/govuk/all.mjs +3 -1
- data/node_modules/govuk-frontend/dist/govuk/all.scss +6 -0
- data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +169 -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 +4 -87
- data/node_modules/govuk-frontend/dist/govuk/{govuk-frontend-component.mjs → component.mjs} +5 -5
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +161 -116
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +160 -115
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +5 -8
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +161 -116
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +160 -115
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +5 -8
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/_index.scss +8 -0
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +187 -145
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +186 -144
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +18 -17
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +9 -29
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +8 -28
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +161 -116
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +160 -115
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -8
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +161 -116
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +160 -115
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +5 -8
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/_index.scss +167 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js +754 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs +746 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs +267 -0
- data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss +14 -10
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +9 -29
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +8 -28
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +161 -116
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +160 -115
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -8
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +161 -117
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +160 -116
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +5 -9
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +9 -29
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +8 -28
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +9 -29
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +8 -28
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +10 -30
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +9 -29
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +3 -3
- data/node_modules/govuk-frontend/dist/govuk/components/summary-list/_index.scss +12 -21
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +9 -29
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +8 -28
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs +2 -2
- data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_colour.scss +2 -2
- data/node_modules/govuk-frontend/dist/govuk/init.mjs +28 -24
- data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +18 -5
- data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss +5 -10
- data/node_modules/govuk-frontend/dist/govuk-prototype-kit/init.scss +1 -1
- data/package-lock.json +8 -7
- data/package.json +1 -1
- metadata +12 -10
- data/node_modules/govuk-frontend/dist/govuk/common/normalise-dataset.mjs +0 -18
- data/node_modules/govuk-frontend/dist/govuk/common/normalise-string.mjs +0 -31
@@ -1,75 +1,5 @@
|
|
1
|
-
const version = '5.
|
1
|
+
const version = '5.9.0';
|
2
2
|
|
3
|
-
function normaliseString(value, property) {
|
4
|
-
const trimmedValue = value ? value.trim() : '';
|
5
|
-
let output;
|
6
|
-
let outputType = property == null ? void 0 : property.type;
|
7
|
-
if (!outputType) {
|
8
|
-
if (['true', 'false'].includes(trimmedValue)) {
|
9
|
-
outputType = 'boolean';
|
10
|
-
}
|
11
|
-
if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
|
12
|
-
outputType = 'number';
|
13
|
-
}
|
14
|
-
}
|
15
|
-
switch (outputType) {
|
16
|
-
case 'boolean':
|
17
|
-
output = trimmedValue === 'true';
|
18
|
-
break;
|
19
|
-
case 'number':
|
20
|
-
output = Number(trimmedValue);
|
21
|
-
break;
|
22
|
-
default:
|
23
|
-
output = value;
|
24
|
-
}
|
25
|
-
return output;
|
26
|
-
}
|
27
|
-
|
28
|
-
/**
|
29
|
-
* @typedef {import('./index.mjs').SchemaProperty} SchemaProperty
|
30
|
-
*/
|
31
|
-
|
32
|
-
function mergeConfigs(...configObjects) {
|
33
|
-
const formattedConfigObject = {};
|
34
|
-
for (const configObject of configObjects) {
|
35
|
-
for (const key of Object.keys(configObject)) {
|
36
|
-
const option = formattedConfigObject[key];
|
37
|
-
const override = configObject[key];
|
38
|
-
if (isObject(option) && isObject(override)) {
|
39
|
-
formattedConfigObject[key] = mergeConfigs(option, override);
|
40
|
-
} else {
|
41
|
-
formattedConfigObject[key] = override;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
}
|
45
|
-
return formattedConfigObject;
|
46
|
-
}
|
47
|
-
function extractConfigByNamespace(Component, dataset, namespace) {
|
48
|
-
const property = Component.schema.properties[namespace];
|
49
|
-
if ((property == null ? void 0 : property.type) !== 'object') {
|
50
|
-
return;
|
51
|
-
}
|
52
|
-
const newObject = {
|
53
|
-
[namespace]: ({})
|
54
|
-
};
|
55
|
-
for (const [key, value] of Object.entries(dataset)) {
|
56
|
-
let current = newObject;
|
57
|
-
const keyParts = key.split('.');
|
58
|
-
for (const [index, name] of keyParts.entries()) {
|
59
|
-
if (typeof current === 'object') {
|
60
|
-
if (index < keyParts.length - 1) {
|
61
|
-
if (!isObject(current[name])) {
|
62
|
-
current[name] = {};
|
63
|
-
}
|
64
|
-
current = current[name];
|
65
|
-
} else if (key !== namespace) {
|
66
|
-
current[name] = normaliseString(value);
|
67
|
-
}
|
68
|
-
}
|
69
|
-
}
|
70
|
-
}
|
71
|
-
return newObject[namespace];
|
72
|
-
}
|
73
3
|
function getFragmentFromUrl(url) {
|
74
4
|
if (!url.includes('#')) {
|
75
5
|
return undefined;
|
@@ -127,26 +57,6 @@ function isSupported($scope = document.body) {
|
|
127
57
|
}
|
128
58
|
return $scope.classList.contains('govuk-frontend-supported');
|
129
59
|
}
|
130
|
-
function validateConfig(schema, config) {
|
131
|
-
const validationErrors = [];
|
132
|
-
for (const [name, conditions] of Object.entries(schema)) {
|
133
|
-
const errors = [];
|
134
|
-
if (Array.isArray(conditions)) {
|
135
|
-
for (const {
|
136
|
-
required,
|
137
|
-
errorMessage
|
138
|
-
} of conditions) {
|
139
|
-
if (!required.every(key => !!config[key])) {
|
140
|
-
errors.push(errorMessage);
|
141
|
-
}
|
142
|
-
}
|
143
|
-
if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
|
144
|
-
validationErrors.push(...errors);
|
145
|
-
}
|
146
|
-
}
|
147
|
-
}
|
148
|
-
return validationErrors;
|
149
|
-
}
|
150
60
|
function isArray(option) {
|
151
61
|
return Array.isArray(option);
|
152
62
|
}
|
@@ -156,46 +66,13 @@ function isObject(option) {
|
|
156
66
|
function formatErrorMessage(Component, message) {
|
157
67
|
return `${Component.moduleName}: ${message}`;
|
158
68
|
}
|
159
|
-
|
160
|
-
/**
|
161
|
-
* Schema for component config
|
162
|
-
*
|
163
|
-
* @typedef {object} Schema
|
164
|
-
* @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
|
165
|
-
* @property {SchemaCondition[]} [anyOf] - List of schema conditions
|
166
|
-
*/
|
167
|
-
|
168
|
-
/**
|
169
|
-
* Schema property for component config
|
170
|
-
*
|
171
|
-
* @typedef {object} SchemaProperty
|
172
|
-
* @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
|
173
|
-
*/
|
174
|
-
|
175
|
-
/**
|
176
|
-
* Schema condition for component config
|
177
|
-
*
|
178
|
-
* @typedef {object} SchemaCondition
|
179
|
-
* @property {string[]} required - List of required config fields
|
180
|
-
* @property {string} errorMessage - Error message when required config fields not provided
|
181
|
-
*/
|
182
69
|
/**
|
183
70
|
* @typedef ComponentWithModuleName
|
184
71
|
* @property {string} moduleName - Name of the component
|
185
72
|
*/
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
for (const [field, property] of Object.entries(Component.schema.properties)) {
|
190
|
-
if (field in dataset) {
|
191
|
-
out[field] = normaliseString(dataset[field], property);
|
192
|
-
}
|
193
|
-
if ((property == null ? void 0 : property.type) === 'object') {
|
194
|
-
out[field] = extractConfigByNamespace(Component, dataset, field);
|
195
|
-
}
|
196
|
-
}
|
197
|
-
return out;
|
198
|
-
}
|
73
|
+
/**
|
74
|
+
* @import { ObjectNested } from './configuration.mjs'
|
75
|
+
*/
|
199
76
|
|
200
77
|
class GOVUKFrontendError extends Error {
|
201
78
|
constructor(...args) {
|
@@ -247,10 +124,10 @@ class InitError extends GOVUKFrontendError {
|
|
247
124
|
}
|
248
125
|
}
|
249
126
|
/**
|
250
|
-
* @
|
127
|
+
* @import { ComponentWithModuleName } from '../common/index.mjs'
|
251
128
|
*/
|
252
129
|
|
253
|
-
class
|
130
|
+
class Component {
|
254
131
|
/**
|
255
132
|
* Returns the root element of the component
|
256
133
|
*
|
@@ -301,9 +178,172 @@ class GOVUKFrontendComponent {
|
|
301
178
|
*/
|
302
179
|
|
303
180
|
/**
|
304
|
-
* @typedef {typeof
|
181
|
+
* @typedef {typeof Component & ChildClass} ChildClassConstructor
|
182
|
+
*/
|
183
|
+
Component.elementType = HTMLElement;
|
184
|
+
|
185
|
+
const configOverride = Symbol.for('configOverride');
|
186
|
+
class ConfigurableComponent extends Component {
|
187
|
+
[configOverride](param) {
|
188
|
+
return {};
|
189
|
+
}
|
190
|
+
|
191
|
+
/**
|
192
|
+
* Returns the root element of the component
|
193
|
+
*
|
194
|
+
* @protected
|
195
|
+
* @returns {ConfigurationType} - the root element of component
|
196
|
+
*/
|
197
|
+
get config() {
|
198
|
+
return this._config;
|
199
|
+
}
|
200
|
+
constructor($root, config) {
|
201
|
+
super($root);
|
202
|
+
this._config = void 0;
|
203
|
+
const childConstructor = this.constructor;
|
204
|
+
if (!isObject(childConstructor.defaults)) {
|
205
|
+
throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
|
206
|
+
}
|
207
|
+
const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
|
208
|
+
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
|
209
|
+
}
|
210
|
+
}
|
211
|
+
function normaliseString(value, property) {
|
212
|
+
const trimmedValue = value ? value.trim() : '';
|
213
|
+
let output;
|
214
|
+
let outputType = property == null ? void 0 : property.type;
|
215
|
+
if (!outputType) {
|
216
|
+
if (['true', 'false'].includes(trimmedValue)) {
|
217
|
+
outputType = 'boolean';
|
218
|
+
}
|
219
|
+
if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
|
220
|
+
outputType = 'number';
|
221
|
+
}
|
222
|
+
}
|
223
|
+
switch (outputType) {
|
224
|
+
case 'boolean':
|
225
|
+
output = trimmedValue === 'true';
|
226
|
+
break;
|
227
|
+
case 'number':
|
228
|
+
output = Number(trimmedValue);
|
229
|
+
break;
|
230
|
+
default:
|
231
|
+
output = value;
|
232
|
+
}
|
233
|
+
return output;
|
234
|
+
}
|
235
|
+
function normaliseDataset(Component, dataset) {
|
236
|
+
if (!isObject(Component.schema)) {
|
237
|
+
throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));
|
238
|
+
}
|
239
|
+
const out = {};
|
240
|
+
const entries = Object.entries(Component.schema.properties);
|
241
|
+
for (const entry of entries) {
|
242
|
+
const [namespace, property] = entry;
|
243
|
+
const field = namespace.toString();
|
244
|
+
if (field in dataset) {
|
245
|
+
out[field] = normaliseString(dataset[field], property);
|
246
|
+
}
|
247
|
+
if ((property == null ? void 0 : property.type) === 'object') {
|
248
|
+
out[field] = extractConfigByNamespace(Component.schema, dataset, namespace);
|
249
|
+
}
|
250
|
+
}
|
251
|
+
return out;
|
252
|
+
}
|
253
|
+
function mergeConfigs(...configObjects) {
|
254
|
+
const formattedConfigObject = {};
|
255
|
+
for (const configObject of configObjects) {
|
256
|
+
for (const key of Object.keys(configObject)) {
|
257
|
+
const option = formattedConfigObject[key];
|
258
|
+
const override = configObject[key];
|
259
|
+
if (isObject(option) && isObject(override)) {
|
260
|
+
formattedConfigObject[key] = mergeConfigs(option, override);
|
261
|
+
} else {
|
262
|
+
formattedConfigObject[key] = override;
|
263
|
+
}
|
264
|
+
}
|
265
|
+
}
|
266
|
+
return formattedConfigObject;
|
267
|
+
}
|
268
|
+
function validateConfig(schema, config) {
|
269
|
+
const validationErrors = [];
|
270
|
+
for (const [name, conditions] of Object.entries(schema)) {
|
271
|
+
const errors = [];
|
272
|
+
if (Array.isArray(conditions)) {
|
273
|
+
for (const {
|
274
|
+
required,
|
275
|
+
errorMessage
|
276
|
+
} of conditions) {
|
277
|
+
if (!required.every(key => !!config[key])) {
|
278
|
+
errors.push(errorMessage);
|
279
|
+
}
|
280
|
+
}
|
281
|
+
if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
|
282
|
+
validationErrors.push(...errors);
|
283
|
+
}
|
284
|
+
}
|
285
|
+
}
|
286
|
+
return validationErrors;
|
287
|
+
}
|
288
|
+
function extractConfigByNamespace(schema, dataset, namespace) {
|
289
|
+
const property = schema.properties[namespace];
|
290
|
+
if ((property == null ? void 0 : property.type) !== 'object') {
|
291
|
+
return;
|
292
|
+
}
|
293
|
+
const newObject = {
|
294
|
+
[namespace]: {}
|
295
|
+
};
|
296
|
+
for (const [key, value] of Object.entries(dataset)) {
|
297
|
+
let current = newObject;
|
298
|
+
const keyParts = key.split('.');
|
299
|
+
for (const [index, name] of keyParts.entries()) {
|
300
|
+
if (isObject(current)) {
|
301
|
+
if (index < keyParts.length - 1) {
|
302
|
+
if (!isObject(current[name])) {
|
303
|
+
current[name] = {};
|
304
|
+
}
|
305
|
+
current = current[name];
|
306
|
+
} else if (key !== namespace) {
|
307
|
+
current[name] = normaliseString(value);
|
308
|
+
}
|
309
|
+
}
|
310
|
+
}
|
311
|
+
}
|
312
|
+
return newObject[namespace];
|
313
|
+
}
|
314
|
+
/**
|
315
|
+
* Schema for component config
|
316
|
+
*
|
317
|
+
* @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType
|
318
|
+
* @typedef {object} Schema
|
319
|
+
* @property {Record<keyof ConfigurationType, SchemaProperty | undefined>} properties - Schema properties
|
320
|
+
* @property {SchemaCondition<ConfigurationType>[]} [anyOf] - List of schema conditions
|
321
|
+
*/
|
322
|
+
/**
|
323
|
+
* Schema property for component config
|
324
|
+
*
|
325
|
+
* @typedef {object} SchemaProperty
|
326
|
+
* @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
|
327
|
+
*/
|
328
|
+
/**
|
329
|
+
* Schema condition for component config
|
330
|
+
*
|
331
|
+
* @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType
|
332
|
+
* @typedef {object} SchemaCondition
|
333
|
+
* @property {(keyof ConfigurationType)[]} required - List of required config fields
|
334
|
+
* @property {string} errorMessage - Error message when required config fields not provided
|
335
|
+
*/
|
336
|
+
/**
|
337
|
+
* @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]
|
338
|
+
* @typedef ChildClass
|
339
|
+
* @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
|
340
|
+
* @property {Schema<ConfigurationType>} [schema] - The schema of the component configuration
|
341
|
+
* @property {ConfigurationType} [defaults] - The default values of the configuration of the component
|
342
|
+
*/
|
343
|
+
/**
|
344
|
+
* @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]
|
345
|
+
* @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
|
305
346
|
*/
|
306
|
-
GOVUKFrontendComponent.elementType = HTMLElement;
|
307
347
|
|
308
348
|
class I18n {
|
309
349
|
constructor(translations = {}, config = {}) {
|
@@ -511,15 +551,15 @@ I18n.pluralRules = {
|
|
511
551
|
* attribute, which also provides accessibility.
|
512
552
|
*
|
513
553
|
* @preserve
|
554
|
+
* @augments ConfigurableComponent<AccordionConfig>
|
514
555
|
*/
|
515
|
-
class Accordion extends
|
556
|
+
class Accordion extends ConfigurableComponent {
|
516
557
|
/**
|
517
558
|
* @param {Element | null} $root - HTML element to use for accordion
|
518
559
|
* @param {AccordionConfig} [config] - Accordion config
|
519
560
|
*/
|
520
561
|
constructor($root, config = {}) {
|
521
|
-
super($root);
|
522
|
-
this.config = void 0;
|
562
|
+
super($root, config);
|
523
563
|
this.i18n = void 0;
|
524
564
|
this.controlsClass = 'govuk-accordion__controls';
|
525
565
|
this.showAllClass = 'govuk-accordion__show-all';
|
@@ -544,7 +584,6 @@ class Accordion extends GOVUKFrontendComponent {
|
|
544
584
|
this.$showAllButton = null;
|
545
585
|
this.$showAllIcon = null;
|
546
586
|
this.$showAllText = null;
|
547
|
-
this.config = mergeConfigs(Accordion.defaults, config, normaliseDataset(Accordion, this.$root.dataset));
|
548
587
|
this.i18n = new I18n(this.config.i18n);
|
549
588
|
const $sections = this.$root.querySelectorAll(`.${this.sectionClass}`);
|
550
589
|
if (!$sections.length) {
|
@@ -814,7 +853,7 @@ class Accordion extends GOVUKFrontendComponent {
|
|
814
853
|
*/
|
815
854
|
|
816
855
|
/**
|
817
|
-
* @
|
856
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
818
857
|
*/
|
819
858
|
Accordion.moduleName = 'govuk-accordion';
|
820
859
|
Accordion.defaults = Object.freeze({
|
@@ -845,17 +884,16 @@ const DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
|
|
845
884
|
* JavaScript enhancements for the Button component
|
846
885
|
*
|
847
886
|
* @preserve
|
887
|
+
* @augments ConfigurableComponent<ButtonConfig>
|
848
888
|
*/
|
849
|
-
class Button extends
|
889
|
+
class Button extends ConfigurableComponent {
|
850
890
|
/**
|
851
891
|
* @param {Element | null} $root - HTML element to use for button
|
852
892
|
* @param {ButtonConfig} [config] - Button config
|
853
893
|
*/
|
854
894
|
constructor($root, config = {}) {
|
855
|
-
super($root);
|
856
|
-
this.config = void 0;
|
895
|
+
super($root, config);
|
857
896
|
this.debounceFormSubmitTimer = null;
|
858
|
-
this.config = mergeConfigs(Button.defaults, config, normaliseDataset(Button, this.$root.dataset));
|
859
897
|
this.$root.addEventListener('keydown', event => this.handleKeyDown(event));
|
860
898
|
this.$root.addEventListener('click', event => this.debounce(event));
|
861
899
|
}
|
@@ -892,7 +930,7 @@ class Button extends GOVUKFrontendComponent {
|
|
892
930
|
*/
|
893
931
|
|
894
932
|
/**
|
895
|
-
* @
|
933
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
896
934
|
*/
|
897
935
|
Button.moduleName = 'govuk-button';
|
898
936
|
Button.defaults = Object.freeze({
|
@@ -922,22 +960,33 @@ function closestAttributeValue($element, attributeName) {
|
|
922
960
|
* of the available characters/words has been entered.
|
923
961
|
*
|
924
962
|
* @preserve
|
963
|
+
* @augments ConfigurableComponent<CharacterCountConfig>
|
925
964
|
*/
|
926
|
-
class CharacterCount extends
|
965
|
+
class CharacterCount extends ConfigurableComponent {
|
966
|
+
[configOverride](datasetConfig) {
|
967
|
+
let configOverrides = {};
|
968
|
+
if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
|
969
|
+
configOverrides = {
|
970
|
+
maxlength: undefined,
|
971
|
+
maxwords: undefined
|
972
|
+
};
|
973
|
+
}
|
974
|
+
return configOverrides;
|
975
|
+
}
|
976
|
+
|
927
977
|
/**
|
928
978
|
* @param {Element | null} $root - HTML element to use for character count
|
929
979
|
* @param {CharacterCountConfig} [config] - Character count config
|
930
980
|
*/
|
931
981
|
constructor($root, config = {}) {
|
932
982
|
var _ref, _this$config$maxwords;
|
933
|
-
super($root);
|
983
|
+
super($root, config);
|
934
984
|
this.$textarea = void 0;
|
935
985
|
this.$visibleCountMessage = void 0;
|
936
986
|
this.$screenReaderCountMessage = void 0;
|
937
987
|
this.lastInputTimestamp = null;
|
938
988
|
this.lastInputValue = '';
|
939
989
|
this.valueChecker = null;
|
940
|
-
this.config = void 0;
|
941
990
|
this.i18n = void 0;
|
942
991
|
this.maxLength = void 0;
|
943
992
|
const $textarea = this.$root.querySelector('.govuk-js-character-count');
|
@@ -949,15 +998,6 @@ class CharacterCount extends GOVUKFrontendComponent {
|
|
949
998
|
identifier: 'Form field (`.govuk-js-character-count`)'
|
950
999
|
});
|
951
1000
|
}
|
952
|
-
const datasetConfig = normaliseDataset(CharacterCount, this.$root.dataset);
|
953
|
-
let configOverrides = {};
|
954
|
-
if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
|
955
|
-
configOverrides = {
|
956
|
-
maxlength: undefined,
|
957
|
-
maxwords: undefined
|
958
|
-
};
|
959
|
-
}
|
960
|
-
this.config = mergeConfigs(CharacterCount.defaults, config, configOverrides, datasetConfig);
|
961
1001
|
const errors = validateConfig(CharacterCount.schema, this.config);
|
962
1002
|
if (errors[0]) {
|
963
1003
|
throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]));
|
@@ -1143,8 +1183,8 @@ class CharacterCount extends GOVUKFrontendComponent {
|
|
1143
1183
|
*/
|
1144
1184
|
|
1145
1185
|
/**
|
1146
|
-
* @
|
1147
|
-
* @
|
1186
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1187
|
+
* @import { TranslationPluralForms } from '../../i18n.mjs'
|
1148
1188
|
*/
|
1149
1189
|
CharacterCount.moduleName = 'govuk-character-count';
|
1150
1190
|
CharacterCount.defaults = Object.freeze({
|
@@ -1202,7 +1242,7 @@ CharacterCount.schema = Object.freeze({
|
|
1202
1242
|
*
|
1203
1243
|
* @preserve
|
1204
1244
|
*/
|
1205
|
-
class Checkboxes extends
|
1245
|
+
class Checkboxes extends Component {
|
1206
1246
|
/**
|
1207
1247
|
* Checkboxes can be associated with a 'conditionally revealed' content block
|
1208
1248
|
* – for example, a checkbox for 'Phone' could reveal an additional form field
|
@@ -1310,16 +1350,15 @@ Checkboxes.moduleName = 'govuk-checkboxes';
|
|
1310
1350
|
* configuration.
|
1311
1351
|
*
|
1312
1352
|
* @preserve
|
1353
|
+
* @augments ConfigurableComponent<ErrorSummaryConfig>
|
1313
1354
|
*/
|
1314
|
-
class ErrorSummary extends
|
1355
|
+
class ErrorSummary extends ConfigurableComponent {
|
1315
1356
|
/**
|
1316
1357
|
* @param {Element | null} $root - HTML element to use for error summary
|
1317
1358
|
* @param {ErrorSummaryConfig} [config] - Error summary config
|
1318
1359
|
*/
|
1319
1360
|
constructor($root, config = {}) {
|
1320
|
-
super($root);
|
1321
|
-
this.config = void 0;
|
1322
|
-
this.config = mergeConfigs(ErrorSummary.defaults, config, normaliseDataset(ErrorSummary, this.$root.dataset));
|
1361
|
+
super($root, config);
|
1323
1362
|
if (!this.config.disableAutoFocus) {
|
1324
1363
|
setFocus(this.$root);
|
1325
1364
|
}
|
@@ -1386,7 +1425,7 @@ class ErrorSummary extends GOVUKFrontendComponent {
|
|
1386
1425
|
*/
|
1387
1426
|
|
1388
1427
|
/**
|
1389
|
-
* @
|
1428
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1390
1429
|
*/
|
1391
1430
|
ErrorSummary.moduleName = 'govuk-error-summary';
|
1392
1431
|
ErrorSummary.defaults = Object.freeze({
|
@@ -1404,15 +1443,15 @@ ErrorSummary.schema = Object.freeze({
|
|
1404
1443
|
* Exit this page component
|
1405
1444
|
*
|
1406
1445
|
* @preserve
|
1446
|
+
* @augments ConfigurableComponent<ExitThisPageConfig>
|
1407
1447
|
*/
|
1408
|
-
class ExitThisPage extends
|
1448
|
+
class ExitThisPage extends ConfigurableComponent {
|
1409
1449
|
/**
|
1410
1450
|
* @param {Element | null} $root - HTML element that wraps the Exit This Page button
|
1411
1451
|
* @param {ExitThisPageConfig} [config] - Exit This Page config
|
1412
1452
|
*/
|
1413
1453
|
constructor($root, config = {}) {
|
1414
|
-
super($root);
|
1415
|
-
this.config = void 0;
|
1454
|
+
super($root, config);
|
1416
1455
|
this.i18n = void 0;
|
1417
1456
|
this.$button = void 0;
|
1418
1457
|
this.$skiplinkButton = null;
|
@@ -1433,7 +1472,6 @@ class ExitThisPage extends GOVUKFrontendComponent {
|
|
1433
1472
|
identifier: 'Button (`.govuk-exit-this-page__button`)'
|
1434
1473
|
});
|
1435
1474
|
}
|
1436
|
-
this.config = mergeConfigs(ExitThisPage.defaults, config, normaliseDataset(ExitThisPage, this.$root.dataset));
|
1437
1475
|
this.i18n = new I18n(this.config.i18n);
|
1438
1476
|
this.$button = $button;
|
1439
1477
|
const $skiplinkButton = document.querySelector('.govuk-js-exit-this-page-skiplink');
|
@@ -1599,7 +1637,7 @@ class ExitThisPage extends GOVUKFrontendComponent {
|
|
1599
1637
|
*/
|
1600
1638
|
|
1601
1639
|
/**
|
1602
|
-
* @
|
1640
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1603
1641
|
*/
|
1604
1642
|
ExitThisPage.moduleName = 'govuk-exit-this-page';
|
1605
1643
|
ExitThisPage.defaults = Object.freeze({
|
@@ -1618,12 +1656,271 @@ ExitThisPage.schema = Object.freeze({
|
|
1618
1656
|
}
|
1619
1657
|
});
|
1620
1658
|
|
1659
|
+
/**
|
1660
|
+
* File upload component
|
1661
|
+
*
|
1662
|
+
* @preserve
|
1663
|
+
* @augments ConfigurableComponent<FileUploadConfig>
|
1664
|
+
*/
|
1665
|
+
class FileUpload extends ConfigurableComponent {
|
1666
|
+
/**
|
1667
|
+
* @param {Element | null} $root - File input element
|
1668
|
+
* @param {FileUploadConfig} [config] - File Upload config
|
1669
|
+
*/
|
1670
|
+
constructor($root, config = {}) {
|
1671
|
+
super($root, config);
|
1672
|
+
this.$input = void 0;
|
1673
|
+
this.$button = void 0;
|
1674
|
+
this.$status = void 0;
|
1675
|
+
this.i18n = void 0;
|
1676
|
+
this.id = void 0;
|
1677
|
+
const $input = this.$root.querySelector('input');
|
1678
|
+
if ($input === null) {
|
1679
|
+
throw new ElementError({
|
1680
|
+
component: FileUpload,
|
1681
|
+
identifier: 'File inputs (`<input type="file">`)'
|
1682
|
+
});
|
1683
|
+
}
|
1684
|
+
if ($input.type !== 'file') {
|
1685
|
+
throw new ElementError(formatErrorMessage(FileUpload, 'File input (`<input type="file">`) attribute (`type`) is not `file`'));
|
1686
|
+
}
|
1687
|
+
this.$input = $input;
|
1688
|
+
this.$input.setAttribute('hidden', 'true');
|
1689
|
+
if (!this.$input.id) {
|
1690
|
+
throw new ElementError({
|
1691
|
+
component: FileUpload,
|
1692
|
+
identifier: 'File input (`<input type="file">`) attribute (`id`)'
|
1693
|
+
});
|
1694
|
+
}
|
1695
|
+
this.id = this.$input.id;
|
1696
|
+
this.i18n = new I18n(this.config.i18n, {
|
1697
|
+
locale: closestAttributeValue(this.$root, 'lang')
|
1698
|
+
});
|
1699
|
+
const $label = this.findLabel();
|
1700
|
+
if (!$label.id) {
|
1701
|
+
$label.id = `${this.id}-label`;
|
1702
|
+
}
|
1703
|
+
this.$input.id = `${this.id}-input`;
|
1704
|
+
const $button = document.createElement('button');
|
1705
|
+
$button.classList.add('govuk-file-upload-button');
|
1706
|
+
$button.type = 'button';
|
1707
|
+
$button.id = this.id;
|
1708
|
+
$button.classList.add('govuk-file-upload-button--empty');
|
1709
|
+
const ariaDescribedBy = this.$input.getAttribute('aria-describedby');
|
1710
|
+
if (ariaDescribedBy) {
|
1711
|
+
$button.setAttribute('aria-describedby', ariaDescribedBy);
|
1712
|
+
}
|
1713
|
+
const $status = document.createElement('span');
|
1714
|
+
$status.className = 'govuk-body govuk-file-upload-button__status';
|
1715
|
+
$status.setAttribute('aria-live', 'polite');
|
1716
|
+
$status.innerText = this.i18n.t('noFileChosen');
|
1717
|
+
$button.appendChild($status);
|
1718
|
+
const commaSpan = document.createElement('span');
|
1719
|
+
commaSpan.className = 'govuk-visually-hidden';
|
1720
|
+
commaSpan.innerText = ', ';
|
1721
|
+
commaSpan.id = `${this.id}-comma`;
|
1722
|
+
$button.appendChild(commaSpan);
|
1723
|
+
const containerSpan = document.createElement('span');
|
1724
|
+
containerSpan.className = 'govuk-file-upload-button__pseudo-button-container';
|
1725
|
+
const buttonSpan = document.createElement('span');
|
1726
|
+
buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload-button__pseudo-button';
|
1727
|
+
buttonSpan.innerText = this.i18n.t('chooseFilesButton');
|
1728
|
+
containerSpan.appendChild(buttonSpan);
|
1729
|
+
containerSpan.insertAdjacentText('beforeend', ' ');
|
1730
|
+
const instructionSpan = document.createElement('span');
|
1731
|
+
instructionSpan.className = 'govuk-body govuk-file-upload-button__instruction';
|
1732
|
+
instructionSpan.innerText = this.i18n.t('dropInstruction');
|
1733
|
+
containerSpan.appendChild(instructionSpan);
|
1734
|
+
$button.appendChild(containerSpan);
|
1735
|
+
$button.setAttribute('aria-labelledby', `${$label.id} ${commaSpan.id} ${$button.id}`);
|
1736
|
+
$button.addEventListener('click', this.onClick.bind(this));
|
1737
|
+
$button.addEventListener('dragover', event => {
|
1738
|
+
event.preventDefault();
|
1739
|
+
});
|
1740
|
+
this.$root.insertAdjacentElement('afterbegin', $button);
|
1741
|
+
this.$input.setAttribute('tabindex', '-1');
|
1742
|
+
this.$input.setAttribute('aria-hidden', 'true');
|
1743
|
+
this.$button = $button;
|
1744
|
+
this.$status = $status;
|
1745
|
+
this.$input.addEventListener('change', this.onChange.bind(this));
|
1746
|
+
this.updateDisabledState();
|
1747
|
+
this.observeDisabledState();
|
1748
|
+
this.$announcements = document.createElement('span');
|
1749
|
+
this.$announcements.classList.add('govuk-file-upload-announcements');
|
1750
|
+
this.$announcements.classList.add('govuk-visually-hidden');
|
1751
|
+
this.$announcements.setAttribute('aria-live', 'assertive');
|
1752
|
+
this.$root.insertAdjacentElement('afterend', this.$announcements);
|
1753
|
+
this.$button.addEventListener('drop', this.onDrop.bind(this));
|
1754
|
+
document.addEventListener('dragenter', this.updateDropzoneVisibility.bind(this));
|
1755
|
+
document.addEventListener('dragenter', () => {
|
1756
|
+
this.enteredAnotherElement = true;
|
1757
|
+
});
|
1758
|
+
document.addEventListener('dragleave', () => {
|
1759
|
+
if (!this.enteredAnotherElement && !this.$button.disabled) {
|
1760
|
+
this.hideDraggingState();
|
1761
|
+
this.$announcements.innerText = this.i18n.t('leftDropZone');
|
1762
|
+
}
|
1763
|
+
this.enteredAnotherElement = false;
|
1764
|
+
});
|
1765
|
+
}
|
1766
|
+
|
1767
|
+
/**
|
1768
|
+
* Updates the visibility of the dropzone as users enters the various elements on the page
|
1769
|
+
*
|
1770
|
+
* @param {DragEvent} event - The `dragenter` event
|
1771
|
+
*/
|
1772
|
+
updateDropzoneVisibility(event) {
|
1773
|
+
if (this.$button.disabled) return;
|
1774
|
+
if (event.target instanceof Node) {
|
1775
|
+
if (this.$root.contains(event.target)) {
|
1776
|
+
if (event.dataTransfer && isContainingFiles(event.dataTransfer)) {
|
1777
|
+
if (!this.$button.classList.contains('govuk-file-upload-button--dragging')) {
|
1778
|
+
this.showDraggingState();
|
1779
|
+
this.$announcements.innerText = this.i18n.t('enteredDropZone');
|
1780
|
+
}
|
1781
|
+
}
|
1782
|
+
} else {
|
1783
|
+
if (this.$button.classList.contains('govuk-file-upload-button--dragging')) {
|
1784
|
+
this.hideDraggingState();
|
1785
|
+
this.$announcements.innerText = this.i18n.t('leftDropZone');
|
1786
|
+
}
|
1787
|
+
}
|
1788
|
+
}
|
1789
|
+
}
|
1790
|
+
showDraggingState() {
|
1791
|
+
this.$button.classList.add('govuk-file-upload-button--dragging');
|
1792
|
+
}
|
1793
|
+
hideDraggingState() {
|
1794
|
+
this.$button.classList.remove('govuk-file-upload-button--dragging');
|
1795
|
+
}
|
1796
|
+
|
1797
|
+
/**
|
1798
|
+
* Handles user dropping on the component
|
1799
|
+
*
|
1800
|
+
* @param {DragEvent} event - The `dragenter` event
|
1801
|
+
*/
|
1802
|
+
onDrop(event) {
|
1803
|
+
event.preventDefault();
|
1804
|
+
if (event.dataTransfer && isContainingFiles(event.dataTransfer)) {
|
1805
|
+
this.$input.files = event.dataTransfer.files;
|
1806
|
+
this.$input.dispatchEvent(new CustomEvent('change'));
|
1807
|
+
this.hideDraggingState();
|
1808
|
+
}
|
1809
|
+
}
|
1810
|
+
onChange() {
|
1811
|
+
const fileCount = this.$input.files.length;
|
1812
|
+
if (fileCount === 0) {
|
1813
|
+
this.$status.innerText = this.i18n.t('noFileChosen');
|
1814
|
+
this.$button.classList.add('govuk-file-upload-button--empty');
|
1815
|
+
} else {
|
1816
|
+
if (fileCount === 1) {
|
1817
|
+
this.$status.innerText = this.$input.files[0].name;
|
1818
|
+
} else {
|
1819
|
+
this.$status.innerText = this.i18n.t('multipleFilesChosen', {
|
1820
|
+
count: fileCount
|
1821
|
+
});
|
1822
|
+
}
|
1823
|
+
this.$button.classList.remove('govuk-file-upload-button--empty');
|
1824
|
+
}
|
1825
|
+
}
|
1826
|
+
findLabel() {
|
1827
|
+
const $label = document.querySelector(`label[for="${this.$input.id}"]`);
|
1828
|
+
if (!$label) {
|
1829
|
+
throw new ElementError({
|
1830
|
+
component: FileUpload,
|
1831
|
+
identifier: `Field label (\`<label for=${this.$input.id}>\`)`
|
1832
|
+
});
|
1833
|
+
}
|
1834
|
+
return $label;
|
1835
|
+
}
|
1836
|
+
onClick() {
|
1837
|
+
this.$input.click();
|
1838
|
+
}
|
1839
|
+
observeDisabledState() {
|
1840
|
+
const observer = new MutationObserver(mutationList => {
|
1841
|
+
for (const mutation of mutationList) {
|
1842
|
+
if (mutation.type === 'attributes' && mutation.attributeName === 'disabled') {
|
1843
|
+
this.updateDisabledState();
|
1844
|
+
}
|
1845
|
+
}
|
1846
|
+
});
|
1847
|
+
observer.observe(this.$input, {
|
1848
|
+
attributes: true
|
1849
|
+
});
|
1850
|
+
}
|
1851
|
+
updateDisabledState() {
|
1852
|
+
this.$button.disabled = this.$input.disabled;
|
1853
|
+
this.$root.classList.toggle('govuk-drop-zone--disabled', this.$button.disabled);
|
1854
|
+
}
|
1855
|
+
}
|
1856
|
+
FileUpload.moduleName = 'govuk-file-upload';
|
1857
|
+
FileUpload.defaults = Object.freeze({
|
1858
|
+
i18n: {
|
1859
|
+
chooseFilesButton: 'Choose file',
|
1860
|
+
dropInstruction: 'or drop file',
|
1861
|
+
noFileChosen: 'No file chosen',
|
1862
|
+
multipleFilesChosen: {
|
1863
|
+
one: '%{count} file chosen',
|
1864
|
+
other: '%{count} files chosen'
|
1865
|
+
},
|
1866
|
+
enteredDropZone: 'Entered drop zone',
|
1867
|
+
leftDropZone: 'Left drop zone'
|
1868
|
+
}
|
1869
|
+
});
|
1870
|
+
FileUpload.schema = Object.freeze({
|
1871
|
+
properties: {
|
1872
|
+
i18n: {
|
1873
|
+
type: 'object'
|
1874
|
+
}
|
1875
|
+
}
|
1876
|
+
});
|
1877
|
+
function isContainingFiles(dataTransfer) {
|
1878
|
+
const hasNoTypesInfo = dataTransfer.types.length === 0;
|
1879
|
+
const isDraggingFiles = dataTransfer.types.some(type => type === 'Files');
|
1880
|
+
return hasNoTypesInfo || isDraggingFiles;
|
1881
|
+
}
|
1882
|
+
|
1883
|
+
/**
|
1884
|
+
* @typedef {HTMLInputElement & {files: FileList}} HTMLFileInputElement
|
1885
|
+
*/
|
1886
|
+
|
1887
|
+
/**
|
1888
|
+
* File upload config
|
1889
|
+
*
|
1890
|
+
* @see {@link FileUpload.defaults}
|
1891
|
+
* @typedef {object} FileUploadConfig
|
1892
|
+
* @property {FileUploadTranslations} [i18n=FileUpload.defaults.i18n] - File upload translations
|
1893
|
+
*/
|
1894
|
+
|
1895
|
+
/**
|
1896
|
+
* File upload translations
|
1897
|
+
*
|
1898
|
+
* @see {@link FileUpload.defaults.i18n}
|
1899
|
+
* @typedef {object} FileUploadTranslations
|
1900
|
+
*
|
1901
|
+
* Messages used by the component
|
1902
|
+
* @property {string} [chooseFile] - The text of the button that opens the file picker
|
1903
|
+
* @property {string} [dropInstruction] - The text informing users they can drop files
|
1904
|
+
* @property {TranslationPluralForms} [multipleFilesChosen] - The text displayed when multiple files
|
1905
|
+
* have been chosen by the user
|
1906
|
+
* @property {string} [noFileChosen] - The text to displayed when no file has been chosen by the user
|
1907
|
+
* @property {string} [enteredDropZone] - The text announced by assistive technology
|
1908
|
+
* when user drags files and enters the drop zone
|
1909
|
+
* @property {string} [leftDropZone] - The text announced by assistive technology
|
1910
|
+
* when user drags files and leaves the drop zone without dropping
|
1911
|
+
*/
|
1912
|
+
|
1913
|
+
/**
|
1914
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1915
|
+
* @import { TranslationPluralForms } from '../../i18n.mjs'
|
1916
|
+
*/
|
1917
|
+
|
1621
1918
|
/**
|
1622
1919
|
* Header component
|
1623
1920
|
*
|
1624
1921
|
* @preserve
|
1625
1922
|
*/
|
1626
|
-
class Header extends
|
1923
|
+
class Header extends Component {
|
1627
1924
|
/**
|
1628
1925
|
* Apply a matchMedia for desktop which will trigger a state sync if the
|
1629
1926
|
* browser viewport moves between states.
|
@@ -1704,16 +2001,15 @@ Header.moduleName = 'govuk-header';
|
|
1704
2001
|
* Notification Banner component
|
1705
2002
|
*
|
1706
2003
|
* @preserve
|
2004
|
+
* @augments ConfigurableComponent<NotificationBannerConfig>
|
1707
2005
|
*/
|
1708
|
-
class NotificationBanner extends
|
2006
|
+
class NotificationBanner extends ConfigurableComponent {
|
1709
2007
|
/**
|
1710
2008
|
* @param {Element | null} $root - HTML element to use for notification banner
|
1711
2009
|
* @param {NotificationBannerConfig} [config] - Notification banner config
|
1712
2010
|
*/
|
1713
2011
|
constructor($root, config = {}) {
|
1714
|
-
super($root);
|
1715
|
-
this.config = void 0;
|
1716
|
-
this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, this.$root.dataset));
|
2012
|
+
super($root, config);
|
1717
2013
|
if (this.$root.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
|
1718
2014
|
setFocus(this.$root);
|
1719
2015
|
}
|
@@ -1731,7 +2027,7 @@ class NotificationBanner extends GOVUKFrontendComponent {
|
|
1731
2027
|
*/
|
1732
2028
|
|
1733
2029
|
/**
|
1734
|
-
* @
|
2030
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1735
2031
|
*/
|
1736
2032
|
NotificationBanner.moduleName = 'govuk-notification-banner';
|
1737
2033
|
NotificationBanner.defaults = Object.freeze({
|
@@ -1749,15 +2045,15 @@ NotificationBanner.schema = Object.freeze({
|
|
1749
2045
|
* Password input component
|
1750
2046
|
*
|
1751
2047
|
* @preserve
|
2048
|
+
* @augments ConfigurableComponent<PasswordInputConfig>
|
1752
2049
|
*/
|
1753
|
-
class PasswordInput extends
|
2050
|
+
class PasswordInput extends ConfigurableComponent {
|
1754
2051
|
/**
|
1755
2052
|
* @param {Element | null} $root - HTML element to use for password input
|
1756
2053
|
* @param {PasswordInputConfig} [config] - Password input config
|
1757
2054
|
*/
|
1758
2055
|
constructor($root, config = {}) {
|
1759
|
-
super($root);
|
1760
|
-
this.config = void 0;
|
2056
|
+
super($root, config);
|
1761
2057
|
this.i18n = void 0;
|
1762
2058
|
this.$input = void 0;
|
1763
2059
|
this.$showHideButton = void 0;
|
@@ -1788,7 +2084,6 @@ class PasswordInput extends GOVUKFrontendComponent {
|
|
1788
2084
|
}
|
1789
2085
|
this.$input = $input;
|
1790
2086
|
this.$showHideButton = $showHideButton;
|
1791
|
-
this.config = mergeConfigs(PasswordInput.defaults, config, normaliseDataset(PasswordInput, this.$root.dataset));
|
1792
2087
|
this.i18n = new I18n(this.config.i18n, {
|
1793
2088
|
locale: closestAttributeValue(this.$root, 'lang')
|
1794
2089
|
});
|
@@ -1868,8 +2163,7 @@ class PasswordInput extends GOVUKFrontendComponent {
|
|
1868
2163
|
*/
|
1869
2164
|
|
1870
2165
|
/**
|
1871
|
-
* @
|
1872
|
-
* @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
|
2166
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1873
2167
|
*/
|
1874
2168
|
PasswordInput.moduleName = 'govuk-password-input';
|
1875
2169
|
PasswordInput.defaults = Object.freeze({
|
@@ -1895,7 +2189,7 @@ PasswordInput.schema = Object.freeze({
|
|
1895
2189
|
*
|
1896
2190
|
* @preserve
|
1897
2191
|
*/
|
1898
|
-
class Radios extends
|
2192
|
+
class Radios extends Component {
|
1899
2193
|
/**
|
1900
2194
|
* Radios can be associated with a 'conditionally revealed' content block –
|
1901
2195
|
* for example, a radio for 'Phone' could reveal an additional form field for
|
@@ -1978,7 +2272,7 @@ Radios.moduleName = 'govuk-radios';
|
|
1978
2272
|
*
|
1979
2273
|
* @preserve
|
1980
2274
|
*/
|
1981
|
-
class ServiceNavigation extends
|
2275
|
+
class ServiceNavigation extends Component {
|
1982
2276
|
/**
|
1983
2277
|
* @param {Element | null} $root - HTML element to use for header
|
1984
2278
|
*/
|
@@ -2056,9 +2350,9 @@ ServiceNavigation.moduleName = 'govuk-service-navigation';
|
|
2056
2350
|
* Skip link component
|
2057
2351
|
*
|
2058
2352
|
* @preserve
|
2059
|
-
* @augments
|
2353
|
+
* @augments Component<HTMLAnchorElement>
|
2060
2354
|
*/
|
2061
|
-
class SkipLink extends
|
2355
|
+
class SkipLink extends Component {
|
2062
2356
|
/**
|
2063
2357
|
* @param {Element | null} $root - HTML element to use for skip link
|
2064
2358
|
* @throws {ElementError} when $root is not set or the wrong type
|
@@ -2109,7 +2403,7 @@ SkipLink.moduleName = 'govuk-skip-link';
|
|
2109
2403
|
*
|
2110
2404
|
* @preserve
|
2111
2405
|
*/
|
2112
|
-
class Tabs extends
|
2406
|
+
class Tabs extends Component {
|
2113
2407
|
/**
|
2114
2408
|
* @param {Element | null} $root - HTML element to use for tabs
|
2115
2409
|
*/
|
@@ -2402,7 +2696,7 @@ function initAll(config) {
|
|
2402
2696
|
}
|
2403
2697
|
return;
|
2404
2698
|
}
|
2405
|
-
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]];
|
2699
|
+
const components = [[Accordion, config.accordion], [Button, config.button], [CharacterCount, config.characterCount], [Checkboxes], [ErrorSummary, config.errorSummary], [ExitThisPage, config.exitThisPage], [FileUpload, config.fileUpload], [Header], [NotificationBanner, config.notificationBanner], [PasswordInput, config.passwordInput], [Radios], [ServiceNavigation], [SkipLink], [Tabs]];
|
2406
2700
|
const options = {
|
2407
2701
|
scope: (_config$scope = config.scope) != null ? _config$scope : document,
|
2408
2702
|
onError: config.onError
|
@@ -2421,11 +2715,11 @@ function initAll(config) {
|
|
2421
2715
|
*
|
2422
2716
|
* Any component errors will be caught and logged to the console.
|
2423
2717
|
*
|
2424
|
-
* @template {CompatibleClass}
|
2425
|
-
* @param {
|
2426
|
-
* @param {
|
2427
|
-
* @param {OnErrorCallback<
|
2428
|
-
* @returns {Array<InstanceType<
|
2718
|
+
* @template {CompatibleClass} ComponentClass
|
2719
|
+
* @param {ComponentClass} Component - class of the component to create
|
2720
|
+
* @param {ComponentConfig<ComponentClass>} [config] - Config supplied to component
|
2721
|
+
* @param {OnErrorCallback<ComponentClass> | Element | Document | CreateAllOptions<ComponentClass> } [createAllOptions] - options for createAll including scope of the document to search within and callback function if error throw by component on init
|
2722
|
+
* @returns {Array<InstanceType<ComponentClass>>} - array of instantiated components
|
2429
2723
|
*/
|
2430
2724
|
function createAll(Component, config, createAllOptions) {
|
2431
2725
|
let $scope = document;
|
@@ -2472,7 +2766,7 @@ function createAll(Component, config, createAllOptions) {
|
|
2472
2766
|
}).filter(Boolean);
|
2473
2767
|
}
|
2474
2768
|
/**
|
2475
|
-
* @typedef {{new (...args: any[]): any,
|
2769
|
+
* @typedef {{new (...args: any[]): any, moduleName: string}} CompatibleClass
|
2476
2770
|
*/
|
2477
2771
|
/**
|
2478
2772
|
* Config for all components via `initAll()`
|
@@ -2483,22 +2777,21 @@ function createAll(Component, config, createAllOptions) {
|
|
2483
2777
|
* @property {CharacterCountConfig} [characterCount] - Character Count config
|
2484
2778
|
* @property {ErrorSummaryConfig} [errorSummary] - Error Summary config
|
2485
2779
|
* @property {ExitThisPageConfig} [exitThisPage] - Exit This Page config
|
2780
|
+
* @property {FileUploadConfig} [fileUpload] - File Upload config
|
2486
2781
|
* @property {NotificationBannerConfig} [notificationBanner] - Notification Banner config
|
2487
2782
|
* @property {PasswordInputConfig} [passwordInput] - Password input config
|
2488
2783
|
*/
|
2489
2784
|
/**
|
2490
2785
|
* Config for individual components
|
2491
2786
|
*
|
2492
|
-
* @
|
2493
|
-
* @
|
2494
|
-
* @
|
2495
|
-
* @
|
2496
|
-
* @
|
2497
|
-
* @
|
2498
|
-
* @
|
2499
|
-
* @
|
2500
|
-
* @typedef {import('./components/notification-banner/notification-banner.mjs').NotificationBannerConfig} NotificationBannerConfig
|
2501
|
-
* @typedef {import('./components/password-input/password-input.mjs').PasswordInputConfig} PasswordInputConfig
|
2787
|
+
* @import { AccordionConfig } from './components/accordion/accordion.mjs'
|
2788
|
+
* @import { ButtonConfig } from './components/button/button.mjs'
|
2789
|
+
* @import { CharacterCountConfig } from './components/character-count/character-count.mjs'
|
2790
|
+
* @import { ErrorSummaryConfig } from './components/error-summary/error-summary.mjs'
|
2791
|
+
* @import { ExitThisPageConfig } from './components/exit-this-page/exit-this-page.mjs'
|
2792
|
+
* @import { NotificationBannerConfig } from './components/notification-banner/notification-banner.mjs'
|
2793
|
+
* @import { PasswordInputConfig } from './components/password-input/password-input.mjs'
|
2794
|
+
* @import { FileUploadConfig } from './components/file-upload/file-upload.mjs'
|
2502
2795
|
*/
|
2503
2796
|
/**
|
2504
2797
|
* Component config keys, e.g. `accordion` and `characterCount`
|
@@ -2506,24 +2799,28 @@ function createAll(Component, config, createAllOptions) {
|
|
2506
2799
|
* @typedef {keyof Config} ConfigKey
|
2507
2800
|
*/
|
2508
2801
|
/**
|
2509
|
-
* @template {CompatibleClass}
|
2802
|
+
* @template {CompatibleClass} ComponentClass
|
2803
|
+
* @typedef {ConstructorParameters<ComponentClass>[1]} ComponentConfig
|
2804
|
+
*/
|
2805
|
+
/**
|
2806
|
+
* @template {CompatibleClass} ComponentClass
|
2510
2807
|
* @typedef {object} ErrorContext
|
2511
2808
|
* @property {Element} [element] - Element used for component module initialisation
|
2512
|
-
* @property {
|
2513
|
-
* @property {
|
2809
|
+
* @property {ComponentClass} [component] - Class of component
|
2810
|
+
* @property {ComponentConfig<ComponentClass>} config - Config supplied to component
|
2514
2811
|
*/
|
2515
2812
|
/**
|
2516
|
-
* @template {CompatibleClass}
|
2813
|
+
* @template {CompatibleClass} ComponentClass
|
2517
2814
|
* @callback OnErrorCallback
|
2518
2815
|
* @param {unknown} error - Thrown error
|
2519
|
-
* @param {ErrorContext<
|
2816
|
+
* @param {ErrorContext<ComponentClass>} context - Object containing the element, component class and configuration
|
2520
2817
|
*/
|
2521
2818
|
/**
|
2522
|
-
* @template {CompatibleClass}
|
2819
|
+
* @template {CompatibleClass} ComponentClass
|
2523
2820
|
* @typedef {object} CreateAllOptions
|
2524
2821
|
* @property {Element | Document} [scope] - scope of the document to search within
|
2525
|
-
* @property {OnErrorCallback<
|
2822
|
+
* @property {OnErrorCallback<ComponentClass>} [onError] - callback function if error throw by component on init
|
2526
2823
|
*/
|
2527
2824
|
|
2528
|
-
export { Accordion, Button, CharacterCount, Checkboxes,
|
2825
|
+
export { Accordion, Button, CharacterCount, Checkboxes, Component, ConfigurableComponent, ErrorSummary, ExitThisPage, FileUpload, Header, NotificationBanner, PasswordInput, Radios, ServiceNavigation, SkipLink, Tabs, createAll, initAll, isSupported, version };
|
2529
2826
|
//# sourceMappingURL=all.bundle.mjs.map
|