govuk_publishing_components 51.1.1 → 51.2.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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/components/feedback.js +29 -34
  3. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +7 -2
  4. data/app/assets/stylesheets/component_guide/application.scss +1 -1
  5. data/app/assets/stylesheets/govuk_publishing_components/_all_components.scss +1 -0
  6. data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_markdown-typography.scss +2 -2
  7. data/app/models/govuk_publishing_components/audit_comparer.rb +3 -3
  8. data/app/views/govuk_publishing_components/components/_title.html.erb +2 -3
  9. data/app/views/govuk_publishing_components/components/docs/add_another.yml +1 -1
  10. data/app/views/govuk_publishing_components/components/docs/feedback.yml +1 -1
  11. data/lib/govuk_publishing_components/presenters/checkboxes_helper.rb +1 -1
  12. data/lib/govuk_publishing_components/presenters/shared_helper.rb +0 -11
  13. data/lib/govuk_publishing_components/version.rb +1 -1
  14. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +217 -184
  15. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
  16. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +216 -184
  17. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
  18. data/node_modules/govuk-frontend/dist/govuk/all.mjs +1 -0
  19. data/node_modules/govuk-frontend/dist/govuk/all.mjs.map +1 -1
  20. data/node_modules/govuk-frontend/dist/govuk/all.scss +6 -0
  21. data/node_modules/govuk-frontend/dist/govuk/all.scss.map +1 -1
  22. data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +164 -0
  23. data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs.map +1 -0
  24. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
  25. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +1 -87
  26. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
  27. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +149 -112
  28. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js.map +1 -1
  29. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +148 -111
  30. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs.map +1 -1
  31. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +5 -8
  32. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
  33. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +149 -112
  34. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js.map +1 -1
  35. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +148 -111
  36. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs.map +1 -1
  37. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +5 -8
  38. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
  39. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +174 -140
  40. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js.map +1 -1
  41. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +173 -139
  42. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs.map +1 -1
  43. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +17 -16
  44. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs.map +1 -1
  45. data/node_modules/govuk-frontend/dist/govuk/components/character-count/macro-options.json +4 -4
  46. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +1 -24
  47. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js.map +1 -1
  48. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +0 -23
  49. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
  50. data/node_modules/govuk-frontend/dist/govuk/components/date-input/macro-options.json +2 -2
  51. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +149 -112
  52. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js.map +1 -1
  53. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +148 -111
  54. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs.map +1 -1
  55. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -8
  56. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
  57. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +149 -112
  58. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js.map +1 -1
  59. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +148 -111
  60. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs.map +1 -1
  61. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +5 -8
  62. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs.map +1 -1
  63. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +1 -24
  64. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js.map +1 -1
  65. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +0 -23
  66. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs.map +1 -1
  67. data/node_modules/govuk-frontend/dist/govuk/components/input/macro-options.json +4 -4
  68. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +149 -112
  69. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js.map +1 -1
  70. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +148 -111
  71. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs.map +1 -1
  72. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -8
  73. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
  74. data/node_modules/govuk-frontend/dist/govuk/components/password-input/macro-options.json +1 -1
  75. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +149 -112
  76. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js.map +1 -1
  77. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +148 -111
  78. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs.map +1 -1
  79. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +5 -8
  80. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
  81. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +1 -24
  82. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js.map +1 -1
  83. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +0 -23
  84. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
  85. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +1 -24
  86. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -1
  87. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +0 -23
  88. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -1
  89. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +1 -24
  90. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js.map +1 -1
  91. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +0 -23
  92. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs.map +1 -1
  93. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +1 -24
  94. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js.map +1 -1
  95. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +0 -23
  96. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
  97. data/node_modules/govuk-frontend/dist/govuk/components/textarea/macro-options.json +1 -1
  98. data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
  99. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +1 -1
  100. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css.map +1 -1
  101. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
  102. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map +1 -1
  103. data/node_modules/govuk-frontend/dist/govuk/init.mjs +17 -13
  104. data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
  105. data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss +5 -10
  106. data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss.map +1 -1
  107. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +1 -1
  108. data/node_modules/govuk-frontend/package.json +9 -9
  109. metadata +4 -6
  110. data/node_modules/govuk-frontend/dist/govuk/common/normalise-dataset.mjs +0 -18
  111. data/node_modules/govuk-frontend/dist/govuk/common/normalise-dataset.mjs.map +0 -1
  112. data/node_modules/govuk-frontend/dist/govuk/common/normalise-string.mjs +0 -31
  113. data/node_modules/govuk-frontend/dist/govuk/common/normalise-string.mjs.map +0 -1
@@ -1,81 +1,11 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
3
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = {}));
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = global.GOVUKFrontend || {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
- const version = '5.7.1';
7
+ const version = '5.8.0';
8
8
 
9
- function normaliseString(value, property) {
10
- const trimmedValue = value ? value.trim() : '';
11
- let output;
12
- let outputType = property == null ? void 0 : property.type;
13
- if (!outputType) {
14
- if (['true', 'false'].includes(trimmedValue)) {
15
- outputType = 'boolean';
16
- }
17
- if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
18
- outputType = 'number';
19
- }
20
- }
21
- switch (outputType) {
22
- case 'boolean':
23
- output = trimmedValue === 'true';
24
- break;
25
- case 'number':
26
- output = Number(trimmedValue);
27
- break;
28
- default:
29
- output = value;
30
- }
31
- return output;
32
- }
33
-
34
- /**
35
- * @typedef {import('./index.mjs').SchemaProperty} SchemaProperty
36
- */
37
-
38
- function mergeConfigs(...configObjects) {
39
- const formattedConfigObject = {};
40
- for (const configObject of configObjects) {
41
- for (const key of Object.keys(configObject)) {
42
- const option = formattedConfigObject[key];
43
- const override = configObject[key];
44
- if (isObject(option) && isObject(override)) {
45
- formattedConfigObject[key] = mergeConfigs(option, override);
46
- } else {
47
- formattedConfigObject[key] = override;
48
- }
49
- }
50
- }
51
- return formattedConfigObject;
52
- }
53
- function extractConfigByNamespace(Component, dataset, namespace) {
54
- const property = Component.schema.properties[namespace];
55
- if ((property == null ? void 0 : property.type) !== 'object') {
56
- return;
57
- }
58
- const newObject = {
59
- [namespace]: ({})
60
- };
61
- for (const [key, value] of Object.entries(dataset)) {
62
- let current = newObject;
63
- const keyParts = key.split('.');
64
- for (const [index, name] of keyParts.entries()) {
65
- if (typeof current === 'object') {
66
- if (index < keyParts.length - 1) {
67
- if (!isObject(current[name])) {
68
- current[name] = {};
69
- }
70
- current = current[name];
71
- } else if (key !== namespace) {
72
- current[name] = normaliseString(value);
73
- }
74
- }
75
- }
76
- }
77
- return newObject[namespace];
78
- }
79
9
  function getFragmentFromUrl(url) {
80
10
  if (!url.includes('#')) {
81
11
  return undefined;
@@ -133,26 +63,6 @@
133
63
  }
134
64
  return $scope.classList.contains('govuk-frontend-supported');
135
65
  }
136
- function validateConfig(schema, config) {
137
- const validationErrors = [];
138
- for (const [name, conditions] of Object.entries(schema)) {
139
- const errors = [];
140
- if (Array.isArray(conditions)) {
141
- for (const {
142
- required,
143
- errorMessage
144
- } of conditions) {
145
- if (!required.every(key => !!config[key])) {
146
- errors.push(errorMessage);
147
- }
148
- }
149
- if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
150
- validationErrors.push(...errors);
151
- }
152
- }
153
- }
154
- return validationErrors;
155
- }
156
66
  function isArray(option) {
157
67
  return Array.isArray(option);
158
68
  }
@@ -162,47 +72,11 @@
162
72
  function formatErrorMessage(Component, message) {
163
73
  return `${Component.moduleName}: ${message}`;
164
74
  }
165
-
166
- /**
167
- * Schema for component config
168
- *
169
- * @typedef {object} Schema
170
- * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
171
- * @property {SchemaCondition[]} [anyOf] - List of schema conditions
172
- */
173
-
174
- /**
175
- * Schema property for component config
176
- *
177
- * @typedef {object} SchemaProperty
178
- * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
179
- */
180
-
181
- /**
182
- * Schema condition for component config
183
- *
184
- * @typedef {object} SchemaCondition
185
- * @property {string[]} required - List of required config fields
186
- * @property {string} errorMessage - Error message when required config fields not provided
187
- */
188
75
  /**
189
76
  * @typedef ComponentWithModuleName
190
77
  * @property {string} moduleName - Name of the component
191
78
  */
192
79
 
193
- function normaliseDataset(Component, dataset) {
194
- const out = {};
195
- for (const [field, property] of Object.entries(Component.schema.properties)) {
196
- if (field in dataset) {
197
- out[field] = normaliseString(dataset[field], property);
198
- }
199
- if ((property == null ? void 0 : property.type) === 'object') {
200
- out[field] = extractConfigByNamespace(Component, dataset, field);
201
- }
202
- }
203
- return out;
204
- }
205
-
206
80
  class GOVUKFrontendError extends Error {
207
81
  constructor(...args) {
208
82
  super(...args);
@@ -311,6 +185,164 @@
311
185
  */
312
186
  GOVUKFrontendComponent.elementType = HTMLElement;
313
187
 
188
+ const configOverride = Symbol.for('configOverride');
189
+ class ConfigurableComponent extends GOVUKFrontendComponent {
190
+ [configOverride](param) {
191
+ return {};
192
+ }
193
+
194
+ /**
195
+ * Returns the root element of the component
196
+ *
197
+ * @protected
198
+ * @returns {ConfigurationType} - the root element of component
199
+ */
200
+ get config() {
201
+ return this._config;
202
+ }
203
+ constructor($root, config) {
204
+ super($root);
205
+ this._config = void 0;
206
+ const childConstructor = this.constructor;
207
+ if (typeof childConstructor.defaults === 'undefined') {
208
+ throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
209
+ }
210
+ const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
211
+ this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
212
+ }
213
+ }
214
+ function normaliseString(value, property) {
215
+ const trimmedValue = value ? value.trim() : '';
216
+ let output;
217
+ let outputType = property == null ? void 0 : property.type;
218
+ if (!outputType) {
219
+ if (['true', 'false'].includes(trimmedValue)) {
220
+ outputType = 'boolean';
221
+ }
222
+ if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
223
+ outputType = 'number';
224
+ }
225
+ }
226
+ switch (outputType) {
227
+ case 'boolean':
228
+ output = trimmedValue === 'true';
229
+ break;
230
+ case 'number':
231
+ output = Number(trimmedValue);
232
+ break;
233
+ default:
234
+ output = value;
235
+ }
236
+ return output;
237
+ }
238
+ function normaliseDataset(Component, dataset) {
239
+ if (typeof Component.schema === 'undefined') {
240
+ throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));
241
+ }
242
+ const out = {};
243
+ for (const [field, property] of Object.entries(Component.schema.properties)) {
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, field);
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 (typeof current === 'object') {
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
+ * @typedef {object} Schema
318
+ * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
319
+ * @property {SchemaCondition[]} [anyOf] - List of schema conditions
320
+ */
321
+ /**
322
+ * Schema property for component config
323
+ *
324
+ * @typedef {object} SchemaProperty
325
+ * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
326
+ */
327
+ /**
328
+ * Schema condition for component config
329
+ *
330
+ * @typedef {object} SchemaCondition
331
+ * @property {string[]} required - List of required config fields
332
+ * @property {string} errorMessage - Error message when required config fields not provided
333
+ */
334
+ /**
335
+ * @template {ObjectNested} [ConfigurationType={}]
336
+ * @typedef ChildClass
337
+ * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
338
+ * @property {Schema} [schema] - The schema of the component configuration
339
+ * @property {ConfigurationType} [defaults] - The default values of the configuration of the component
340
+ */
341
+ /**
342
+ * @template {ObjectNested} [ConfigurationType={}]
343
+ * @typedef {typeof GOVUKFrontendComponent & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
344
+ */
345
+
314
346
  class I18n {
315
347
  constructor(translations = {}, config = {}) {
316
348
  var _config$locale;
@@ -517,15 +549,15 @@
517
549
  * attribute, which also provides accessibility.
518
550
  *
519
551
  * @preserve
552
+ * @augments ConfigurableComponent<AccordionConfig>
520
553
  */
521
- class Accordion extends GOVUKFrontendComponent {
554
+ class Accordion extends ConfigurableComponent {
522
555
  /**
523
556
  * @param {Element | null} $root - HTML element to use for accordion
524
557
  * @param {AccordionConfig} [config] - Accordion config
525
558
  */
526
559
  constructor($root, config = {}) {
527
- super($root);
528
- this.config = void 0;
560
+ super($root, config);
529
561
  this.i18n = void 0;
530
562
  this.controlsClass = 'govuk-accordion__controls';
531
563
  this.showAllClass = 'govuk-accordion__show-all';
@@ -550,7 +582,6 @@
550
582
  this.$showAllButton = null;
551
583
  this.$showAllIcon = null;
552
584
  this.$showAllText = null;
553
- this.config = mergeConfigs(Accordion.defaults, config, normaliseDataset(Accordion, this.$root.dataset));
554
585
  this.i18n = new I18n(this.config.i18n);
555
586
  const $sections = this.$root.querySelectorAll(`.${this.sectionClass}`);
556
587
  if (!$sections.length) {
@@ -820,7 +851,7 @@
820
851
  */
821
852
 
822
853
  /**
823
- * @typedef {import('../../common/index.mjs').Schema} Schema
854
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
824
855
  */
825
856
  Accordion.moduleName = 'govuk-accordion';
826
857
  Accordion.defaults = Object.freeze({
@@ -851,17 +882,16 @@
851
882
  * JavaScript enhancements for the Button component
852
883
  *
853
884
  * @preserve
885
+ * @augments ConfigurableComponent<ButtonConfig>
854
886
  */
855
- class Button extends GOVUKFrontendComponent {
887
+ class Button extends ConfigurableComponent {
856
888
  /**
857
889
  * @param {Element | null} $root - HTML element to use for button
858
890
  * @param {ButtonConfig} [config] - Button config
859
891
  */
860
892
  constructor($root, config = {}) {
861
- super($root);
862
- this.config = void 0;
893
+ super($root, config);
863
894
  this.debounceFormSubmitTimer = null;
864
- this.config = mergeConfigs(Button.defaults, config, normaliseDataset(Button, this.$root.dataset));
865
895
  this.$root.addEventListener('keydown', event => this.handleKeyDown(event));
866
896
  this.$root.addEventListener('click', event => this.debounce(event));
867
897
  }
@@ -898,7 +928,7 @@
898
928
  */
899
929
 
900
930
  /**
901
- * @typedef {import('../../common/index.mjs').Schema} Schema
931
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
902
932
  */
903
933
  Button.moduleName = 'govuk-button';
904
934
  Button.defaults = Object.freeze({
@@ -928,22 +958,33 @@
928
958
  * of the available characters/words has been entered.
929
959
  *
930
960
  * @preserve
961
+ * @augments ConfigurableComponent<CharacterCountConfig>
931
962
  */
932
- class CharacterCount extends GOVUKFrontendComponent {
963
+ class CharacterCount extends ConfigurableComponent {
964
+ [configOverride](datasetConfig) {
965
+ let configOverrides = {};
966
+ if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
967
+ configOverrides = {
968
+ maxlength: undefined,
969
+ maxwords: undefined
970
+ };
971
+ }
972
+ return configOverrides;
973
+ }
974
+
933
975
  /**
934
976
  * @param {Element | null} $root - HTML element to use for character count
935
977
  * @param {CharacterCountConfig} [config] - Character count config
936
978
  */
937
979
  constructor($root, config = {}) {
938
980
  var _ref, _this$config$maxwords;
939
- super($root);
981
+ super($root, config);
940
982
  this.$textarea = void 0;
941
983
  this.$visibleCountMessage = void 0;
942
984
  this.$screenReaderCountMessage = void 0;
943
985
  this.lastInputTimestamp = null;
944
986
  this.lastInputValue = '';
945
987
  this.valueChecker = null;
946
- this.config = void 0;
947
988
  this.i18n = void 0;
948
989
  this.maxLength = void 0;
949
990
  const $textarea = this.$root.querySelector('.govuk-js-character-count');
@@ -955,15 +996,6 @@
955
996
  identifier: 'Form field (`.govuk-js-character-count`)'
956
997
  });
957
998
  }
958
- const datasetConfig = normaliseDataset(CharacterCount, this.$root.dataset);
959
- let configOverrides = {};
960
- if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
961
- configOverrides = {
962
- maxlength: undefined,
963
- maxwords: undefined
964
- };
965
- }
966
- this.config = mergeConfigs(CharacterCount.defaults, config, configOverrides, datasetConfig);
967
999
  const errors = validateConfig(CharacterCount.schema, this.config);
968
1000
  if (errors[0]) {
969
1001
  throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]));
@@ -1149,7 +1181,7 @@
1149
1181
  */
1150
1182
 
1151
1183
  /**
1152
- * @typedef {import('../../common/index.mjs').Schema} Schema
1184
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1153
1185
  * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
1154
1186
  */
1155
1187
  CharacterCount.moduleName = 'govuk-character-count';
@@ -1316,16 +1348,15 @@
1316
1348
  * configuration.
1317
1349
  *
1318
1350
  * @preserve
1351
+ * @augments ConfigurableComponent<ErrorSummaryConfig>
1319
1352
  */
1320
- class ErrorSummary extends GOVUKFrontendComponent {
1353
+ class ErrorSummary extends ConfigurableComponent {
1321
1354
  /**
1322
1355
  * @param {Element | null} $root - HTML element to use for error summary
1323
1356
  * @param {ErrorSummaryConfig} [config] - Error summary config
1324
1357
  */
1325
1358
  constructor($root, config = {}) {
1326
- super($root);
1327
- this.config = void 0;
1328
- this.config = mergeConfigs(ErrorSummary.defaults, config, normaliseDataset(ErrorSummary, this.$root.dataset));
1359
+ super($root, config);
1329
1360
  if (!this.config.disableAutoFocus) {
1330
1361
  setFocus(this.$root);
1331
1362
  }
@@ -1392,7 +1423,7 @@
1392
1423
  */
1393
1424
 
1394
1425
  /**
1395
- * @typedef {import('../../common/index.mjs').Schema} Schema
1426
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1396
1427
  */
1397
1428
  ErrorSummary.moduleName = 'govuk-error-summary';
1398
1429
  ErrorSummary.defaults = Object.freeze({
@@ -1410,15 +1441,15 @@
1410
1441
  * Exit this page component
1411
1442
  *
1412
1443
  * @preserve
1444
+ * @augments ConfigurableComponent<ExitThisPageConfig>
1413
1445
  */
1414
- class ExitThisPage extends GOVUKFrontendComponent {
1446
+ class ExitThisPage extends ConfigurableComponent {
1415
1447
  /**
1416
1448
  * @param {Element | null} $root - HTML element that wraps the Exit This Page button
1417
1449
  * @param {ExitThisPageConfig} [config] - Exit This Page config
1418
1450
  */
1419
1451
  constructor($root, config = {}) {
1420
- super($root);
1421
- this.config = void 0;
1452
+ super($root, config);
1422
1453
  this.i18n = void 0;
1423
1454
  this.$button = void 0;
1424
1455
  this.$skiplinkButton = null;
@@ -1439,7 +1470,6 @@
1439
1470
  identifier: 'Button (`.govuk-exit-this-page__button`)'
1440
1471
  });
1441
1472
  }
1442
- this.config = mergeConfigs(ExitThisPage.defaults, config, normaliseDataset(ExitThisPage, this.$root.dataset));
1443
1473
  this.i18n = new I18n(this.config.i18n);
1444
1474
  this.$button = $button;
1445
1475
  const $skiplinkButton = document.querySelector('.govuk-js-exit-this-page-skiplink');
@@ -1605,7 +1635,7 @@
1605
1635
  */
1606
1636
 
1607
1637
  /**
1608
- * @typedef {import('../../common/index.mjs').Schema} Schema
1638
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1609
1639
  */
1610
1640
  ExitThisPage.moduleName = 'govuk-exit-this-page';
1611
1641
  ExitThisPage.defaults = Object.freeze({
@@ -1710,16 +1740,15 @@
1710
1740
  * Notification Banner component
1711
1741
  *
1712
1742
  * @preserve
1743
+ * @augments ConfigurableComponent<NotificationBannerConfig>
1713
1744
  */
1714
- class NotificationBanner extends GOVUKFrontendComponent {
1745
+ class NotificationBanner extends ConfigurableComponent {
1715
1746
  /**
1716
1747
  * @param {Element | null} $root - HTML element to use for notification banner
1717
1748
  * @param {NotificationBannerConfig} [config] - Notification banner config
1718
1749
  */
1719
1750
  constructor($root, config = {}) {
1720
- super($root);
1721
- this.config = void 0;
1722
- this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, this.$root.dataset));
1751
+ super($root, config);
1723
1752
  if (this.$root.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
1724
1753
  setFocus(this.$root);
1725
1754
  }
@@ -1737,7 +1766,7 @@
1737
1766
  */
1738
1767
 
1739
1768
  /**
1740
- * @typedef {import('../../common/index.mjs').Schema} Schema
1769
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1741
1770
  */
1742
1771
  NotificationBanner.moduleName = 'govuk-notification-banner';
1743
1772
  NotificationBanner.defaults = Object.freeze({
@@ -1755,15 +1784,15 @@
1755
1784
  * Password input component
1756
1785
  *
1757
1786
  * @preserve
1787
+ * @augments ConfigurableComponent<PasswordInputConfig>
1758
1788
  */
1759
- class PasswordInput extends GOVUKFrontendComponent {
1789
+ class PasswordInput extends ConfigurableComponent {
1760
1790
  /**
1761
1791
  * @param {Element | null} $root - HTML element to use for password input
1762
1792
  * @param {PasswordInputConfig} [config] - Password input config
1763
1793
  */
1764
1794
  constructor($root, config = {}) {
1765
- super($root);
1766
- this.config = void 0;
1795
+ super($root, config);
1767
1796
  this.i18n = void 0;
1768
1797
  this.$input = void 0;
1769
1798
  this.$showHideButton = void 0;
@@ -1794,7 +1823,6 @@
1794
1823
  }
1795
1824
  this.$input = $input;
1796
1825
  this.$showHideButton = $showHideButton;
1797
- this.config = mergeConfigs(PasswordInput.defaults, config, normaliseDataset(PasswordInput, this.$root.dataset));
1798
1826
  this.i18n = new I18n(this.config.i18n, {
1799
1827
  locale: closestAttributeValue(this.$root, 'lang')
1800
1828
  });
@@ -1874,7 +1902,7 @@
1874
1902
  */
1875
1903
 
1876
1904
  /**
1877
- * @typedef {import('../../common/index.mjs').Schema} Schema
1905
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1878
1906
  * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
1879
1907
  */
1880
1908
  PasswordInput.moduleName = 'govuk-password-input';
@@ -2427,11 +2455,11 @@
2427
2455
  *
2428
2456
  * Any component errors will be caught and logged to the console.
2429
2457
  *
2430
- * @template {CompatibleClass} T
2431
- * @param {T} Component - class of the component to create
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
2434
- * @returns {Array<InstanceType<T>>} - array of instantiated components
2458
+ * @template {CompatibleClass} ComponentClass
2459
+ * @param {ComponentClass} Component - class of the component to create
2460
+ * @param {ComponentConfig<ComponentClass>} [config] - Config supplied to component
2461
+ * @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
2462
+ * @returns {Array<InstanceType<ComponentClass>>} - array of instantiated components
2435
2463
  */
2436
2464
  function createAll(Component, config, createAllOptions) {
2437
2465
  let $scope = document;
@@ -2478,7 +2506,7 @@
2478
2506
  }).filter(Boolean);
2479
2507
  }
2480
2508
  /**
2481
- * @typedef {{new (...args: any[]): any, defaults?: object, moduleName: string}} CompatibleClass
2509
+ * @typedef {{new (...args: any[]): any, moduleName: string}} CompatibleClass
2482
2510
  */
2483
2511
  /**
2484
2512
  * Config for all components via `initAll()`
@@ -2512,23 +2540,27 @@
2512
2540
  * @typedef {keyof Config} ConfigKey
2513
2541
  */
2514
2542
  /**
2515
- * @template {CompatibleClass} T
2543
+ * @template {CompatibleClass} ComponentClass
2544
+ * @typedef {ConstructorParameters<ComponentClass>[1]} ComponentConfig
2545
+ */
2546
+ /**
2547
+ * @template {CompatibleClass} ComponentClass
2516
2548
  * @typedef {object} ErrorContext
2517
2549
  * @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
2550
+ * @property {ComponentClass} [component] - Class of component
2551
+ * @property {ComponentConfig<ComponentClass>} config - Config supplied to component
2520
2552
  */
2521
2553
  /**
2522
- * @template {CompatibleClass} T
2554
+ * @template {CompatibleClass} ComponentClass
2523
2555
  * @callback OnErrorCallback
2524
2556
  * @param {unknown} error - Thrown error
2525
- * @param {ErrorContext<T>} context - Object containing the element, component class and configuration
2557
+ * @param {ErrorContext<ComponentClass>} context - Object containing the element, component class and configuration
2526
2558
  */
2527
2559
  /**
2528
- * @template {CompatibleClass} T
2560
+ * @template {CompatibleClass} ComponentClass
2529
2561
  * @typedef {object} CreateAllOptions
2530
2562
  * @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
2563
+ * @property {OnErrorCallback<ComponentClass>} [onError] - callback function if error throw by component on init
2532
2564
  */
2533
2565
 
2534
2566
  exports.Accordion = Accordion;
@@ -2536,6 +2568,7 @@
2536
2568
  exports.CharacterCount = CharacterCount;
2537
2569
  exports.Checkboxes = Checkboxes;
2538
2570
  exports.Component = GOVUKFrontendComponent;
2571
+ exports.ConfigurableComponent = ConfigurableComponent;
2539
2572
  exports.ErrorSummary = ErrorSummary;
2540
2573
  exports.ExitThisPage = ExitThisPage;
2541
2574
  exports.Header = Header;