govuk_publishing_components 51.1.1 → 51.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/component_guide/application.scss +1 -1
  3. data/app/assets/stylesheets/govuk_publishing_components/_all_components.scss +1 -0
  4. data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_markdown-typography.scss +1 -0
  5. data/app/models/govuk_publishing_components/audit_comparer.rb +3 -3
  6. data/app/views/govuk_publishing_components/components/_title.html.erb +2 -3
  7. data/app/views/govuk_publishing_components/components/docs/add_another.yml +1 -1
  8. data/lib/govuk_publishing_components/presenters/checkboxes_helper.rb +1 -1
  9. data/lib/govuk_publishing_components/presenters/shared_helper.rb +0 -11
  10. data/lib/govuk_publishing_components/version.rb +1 -1
  11. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +217 -184
  12. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
  13. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +216 -184
  14. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
  15. data/node_modules/govuk-frontend/dist/govuk/all.mjs +1 -0
  16. data/node_modules/govuk-frontend/dist/govuk/all.mjs.map +1 -1
  17. data/node_modules/govuk-frontend/dist/govuk/all.scss +6 -0
  18. data/node_modules/govuk-frontend/dist/govuk/all.scss.map +1 -1
  19. data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +164 -0
  20. data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs.map +1 -0
  21. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
  22. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +1 -87
  23. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
  24. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +149 -112
  25. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js.map +1 -1
  26. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +148 -111
  27. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs.map +1 -1
  28. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +5 -8
  29. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
  30. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +149 -112
  31. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js.map +1 -1
  32. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +148 -111
  33. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs.map +1 -1
  34. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +5 -8
  35. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
  36. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +174 -140
  37. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js.map +1 -1
  38. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +173 -139
  39. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs.map +1 -1
  40. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +17 -16
  41. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs.map +1 -1
  42. data/node_modules/govuk-frontend/dist/govuk/components/character-count/macro-options.json +4 -4
  43. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +1 -24
  44. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js.map +1 -1
  45. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +0 -23
  46. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
  47. data/node_modules/govuk-frontend/dist/govuk/components/date-input/macro-options.json +2 -2
  48. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +149 -112
  49. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js.map +1 -1
  50. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +148 -111
  51. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs.map +1 -1
  52. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -8
  53. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
  54. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +149 -112
  55. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js.map +1 -1
  56. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +148 -111
  57. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs.map +1 -1
  58. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +5 -8
  59. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs.map +1 -1
  60. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +1 -24
  61. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js.map +1 -1
  62. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +0 -23
  63. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs.map +1 -1
  64. data/node_modules/govuk-frontend/dist/govuk/components/input/macro-options.json +4 -4
  65. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +149 -112
  66. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js.map +1 -1
  67. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +148 -111
  68. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs.map +1 -1
  69. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -8
  70. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
  71. data/node_modules/govuk-frontend/dist/govuk/components/password-input/macro-options.json +1 -1
  72. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +149 -112
  73. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js.map +1 -1
  74. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +148 -111
  75. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs.map +1 -1
  76. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +5 -8
  77. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
  78. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +1 -24
  79. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js.map +1 -1
  80. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +0 -23
  81. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
  82. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +1 -24
  83. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -1
  84. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +0 -23
  85. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -1
  86. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +1 -24
  87. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js.map +1 -1
  88. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +0 -23
  89. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs.map +1 -1
  90. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +1 -24
  91. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js.map +1 -1
  92. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +0 -23
  93. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
  94. data/node_modules/govuk-frontend/dist/govuk/components/textarea/macro-options.json +1 -1
  95. data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
  96. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +1 -1
  97. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css.map +1 -1
  98. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
  99. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map +1 -1
  100. data/node_modules/govuk-frontend/dist/govuk/init.mjs +17 -13
  101. data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
  102. data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss +5 -10
  103. data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss.map +1 -1
  104. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +1 -1
  105. data/node_modules/govuk-frontend/package.json +9 -9
  106. metadata +4 -6
  107. data/node_modules/govuk-frontend/dist/govuk/common/normalise-dataset.mjs +0 -18
  108. data/node_modules/govuk-frontend/dist/govuk/common/normalise-dataset.mjs.map +0 -1
  109. data/node_modules/govuk-frontend/dist/govuk/common/normalise-string.mjs +0 -31
  110. data/node_modules/govuk-frontend/dist/govuk/common/normalise-string.mjs.map +0 -1
@@ -1,75 +1,5 @@
1
- const version = '5.7.1';
1
+ const version = '5.8.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,47 +66,11 @@ 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
73
 
187
- function normaliseDataset(Component, dataset) {
188
- const out = {};
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
- }
199
-
200
74
  class GOVUKFrontendError extends Error {
201
75
  constructor(...args) {
202
76
  super(...args);
@@ -305,6 +179,164 @@ class GOVUKFrontendComponent {
305
179
  */
306
180
  GOVUKFrontendComponent.elementType = HTMLElement;
307
181
 
182
+ const configOverride = Symbol.for('configOverride');
183
+ class ConfigurableComponent extends GOVUKFrontendComponent {
184
+ [configOverride](param) {
185
+ return {};
186
+ }
187
+
188
+ /**
189
+ * Returns the root element of the component
190
+ *
191
+ * @protected
192
+ * @returns {ConfigurationType} - the root element of component
193
+ */
194
+ get config() {
195
+ return this._config;
196
+ }
197
+ constructor($root, config) {
198
+ super($root);
199
+ this._config = void 0;
200
+ const childConstructor = this.constructor;
201
+ if (typeof childConstructor.defaults === 'undefined') {
202
+ throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
203
+ }
204
+ const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
205
+ this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
206
+ }
207
+ }
208
+ function normaliseString(value, property) {
209
+ const trimmedValue = value ? value.trim() : '';
210
+ let output;
211
+ let outputType = property == null ? void 0 : property.type;
212
+ if (!outputType) {
213
+ if (['true', 'false'].includes(trimmedValue)) {
214
+ outputType = 'boolean';
215
+ }
216
+ if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
217
+ outputType = 'number';
218
+ }
219
+ }
220
+ switch (outputType) {
221
+ case 'boolean':
222
+ output = trimmedValue === 'true';
223
+ break;
224
+ case 'number':
225
+ output = Number(trimmedValue);
226
+ break;
227
+ default:
228
+ output = value;
229
+ }
230
+ return output;
231
+ }
232
+ function normaliseDataset(Component, dataset) {
233
+ if (typeof Component.schema === 'undefined') {
234
+ throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));
235
+ }
236
+ const out = {};
237
+ for (const [field, property] of Object.entries(Component.schema.properties)) {
238
+ if (field in dataset) {
239
+ out[field] = normaliseString(dataset[field], property);
240
+ }
241
+ if ((property == null ? void 0 : property.type) === 'object') {
242
+ out[field] = extractConfigByNamespace(Component.schema, dataset, field);
243
+ }
244
+ }
245
+ return out;
246
+ }
247
+ function mergeConfigs(...configObjects) {
248
+ const formattedConfigObject = {};
249
+ for (const configObject of configObjects) {
250
+ for (const key of Object.keys(configObject)) {
251
+ const option = formattedConfigObject[key];
252
+ const override = configObject[key];
253
+ if (isObject(option) && isObject(override)) {
254
+ formattedConfigObject[key] = mergeConfigs(option, override);
255
+ } else {
256
+ formattedConfigObject[key] = override;
257
+ }
258
+ }
259
+ }
260
+ return formattedConfigObject;
261
+ }
262
+ function validateConfig(schema, config) {
263
+ const validationErrors = [];
264
+ for (const [name, conditions] of Object.entries(schema)) {
265
+ const errors = [];
266
+ if (Array.isArray(conditions)) {
267
+ for (const {
268
+ required,
269
+ errorMessage
270
+ } of conditions) {
271
+ if (!required.every(key => !!config[key])) {
272
+ errors.push(errorMessage);
273
+ }
274
+ }
275
+ if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
276
+ validationErrors.push(...errors);
277
+ }
278
+ }
279
+ }
280
+ return validationErrors;
281
+ }
282
+ function extractConfigByNamespace(schema, dataset, namespace) {
283
+ const property = schema.properties[namespace];
284
+ if ((property == null ? void 0 : property.type) !== 'object') {
285
+ return;
286
+ }
287
+ const newObject = {
288
+ [namespace]: ({})
289
+ };
290
+ for (const [key, value] of Object.entries(dataset)) {
291
+ let current = newObject;
292
+ const keyParts = key.split('.');
293
+ for (const [index, name] of keyParts.entries()) {
294
+ if (typeof current === 'object') {
295
+ if (index < keyParts.length - 1) {
296
+ if (!isObject(current[name])) {
297
+ current[name] = {};
298
+ }
299
+ current = current[name];
300
+ } else if (key !== namespace) {
301
+ current[name] = normaliseString(value);
302
+ }
303
+ }
304
+ }
305
+ }
306
+ return newObject[namespace];
307
+ }
308
+ /**
309
+ * Schema for component config
310
+ *
311
+ * @typedef {object} Schema
312
+ * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
313
+ * @property {SchemaCondition[]} [anyOf] - List of schema conditions
314
+ */
315
+ /**
316
+ * Schema property for component config
317
+ *
318
+ * @typedef {object} SchemaProperty
319
+ * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
320
+ */
321
+ /**
322
+ * Schema condition for component config
323
+ *
324
+ * @typedef {object} SchemaCondition
325
+ * @property {string[]} required - List of required config fields
326
+ * @property {string} errorMessage - Error message when required config fields not provided
327
+ */
328
+ /**
329
+ * @template {ObjectNested} [ConfigurationType={}]
330
+ * @typedef ChildClass
331
+ * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
332
+ * @property {Schema} [schema] - The schema of the component configuration
333
+ * @property {ConfigurationType} [defaults] - The default values of the configuration of the component
334
+ */
335
+ /**
336
+ * @template {ObjectNested} [ConfigurationType={}]
337
+ * @typedef {typeof GOVUKFrontendComponent & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
338
+ */
339
+
308
340
  class I18n {
309
341
  constructor(translations = {}, config = {}) {
310
342
  var _config$locale;
@@ -511,15 +543,15 @@ I18n.pluralRules = {
511
543
  * attribute, which also provides accessibility.
512
544
  *
513
545
  * @preserve
546
+ * @augments ConfigurableComponent<AccordionConfig>
514
547
  */
515
- class Accordion extends GOVUKFrontendComponent {
548
+ class Accordion extends ConfigurableComponent {
516
549
  /**
517
550
  * @param {Element | null} $root - HTML element to use for accordion
518
551
  * @param {AccordionConfig} [config] - Accordion config
519
552
  */
520
553
  constructor($root, config = {}) {
521
- super($root);
522
- this.config = void 0;
554
+ super($root, config);
523
555
  this.i18n = void 0;
524
556
  this.controlsClass = 'govuk-accordion__controls';
525
557
  this.showAllClass = 'govuk-accordion__show-all';
@@ -544,7 +576,6 @@ class Accordion extends GOVUKFrontendComponent {
544
576
  this.$showAllButton = null;
545
577
  this.$showAllIcon = null;
546
578
  this.$showAllText = null;
547
- this.config = mergeConfigs(Accordion.defaults, config, normaliseDataset(Accordion, this.$root.dataset));
548
579
  this.i18n = new I18n(this.config.i18n);
549
580
  const $sections = this.$root.querySelectorAll(`.${this.sectionClass}`);
550
581
  if (!$sections.length) {
@@ -814,7 +845,7 @@ class Accordion extends GOVUKFrontendComponent {
814
845
  */
815
846
 
816
847
  /**
817
- * @typedef {import('../../common/index.mjs').Schema} Schema
848
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
818
849
  */
819
850
  Accordion.moduleName = 'govuk-accordion';
820
851
  Accordion.defaults = Object.freeze({
@@ -845,17 +876,16 @@ const DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
845
876
  * JavaScript enhancements for the Button component
846
877
  *
847
878
  * @preserve
879
+ * @augments ConfigurableComponent<ButtonConfig>
848
880
  */
849
- class Button extends GOVUKFrontendComponent {
881
+ class Button extends ConfigurableComponent {
850
882
  /**
851
883
  * @param {Element | null} $root - HTML element to use for button
852
884
  * @param {ButtonConfig} [config] - Button config
853
885
  */
854
886
  constructor($root, config = {}) {
855
- super($root);
856
- this.config = void 0;
887
+ super($root, config);
857
888
  this.debounceFormSubmitTimer = null;
858
- this.config = mergeConfigs(Button.defaults, config, normaliseDataset(Button, this.$root.dataset));
859
889
  this.$root.addEventListener('keydown', event => this.handleKeyDown(event));
860
890
  this.$root.addEventListener('click', event => this.debounce(event));
861
891
  }
@@ -892,7 +922,7 @@ class Button extends GOVUKFrontendComponent {
892
922
  */
893
923
 
894
924
  /**
895
- * @typedef {import('../../common/index.mjs').Schema} Schema
925
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
896
926
  */
897
927
  Button.moduleName = 'govuk-button';
898
928
  Button.defaults = Object.freeze({
@@ -922,22 +952,33 @@ function closestAttributeValue($element, attributeName) {
922
952
  * of the available characters/words has been entered.
923
953
  *
924
954
  * @preserve
955
+ * @augments ConfigurableComponent<CharacterCountConfig>
925
956
  */
926
- class CharacterCount extends GOVUKFrontendComponent {
957
+ class CharacterCount extends ConfigurableComponent {
958
+ [configOverride](datasetConfig) {
959
+ let configOverrides = {};
960
+ if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
961
+ configOverrides = {
962
+ maxlength: undefined,
963
+ maxwords: undefined
964
+ };
965
+ }
966
+ return configOverrides;
967
+ }
968
+
927
969
  /**
928
970
  * @param {Element | null} $root - HTML element to use for character count
929
971
  * @param {CharacterCountConfig} [config] - Character count config
930
972
  */
931
973
  constructor($root, config = {}) {
932
974
  var _ref, _this$config$maxwords;
933
- super($root);
975
+ super($root, config);
934
976
  this.$textarea = void 0;
935
977
  this.$visibleCountMessage = void 0;
936
978
  this.$screenReaderCountMessage = void 0;
937
979
  this.lastInputTimestamp = null;
938
980
  this.lastInputValue = '';
939
981
  this.valueChecker = null;
940
- this.config = void 0;
941
982
  this.i18n = void 0;
942
983
  this.maxLength = void 0;
943
984
  const $textarea = this.$root.querySelector('.govuk-js-character-count');
@@ -949,15 +990,6 @@ class CharacterCount extends GOVUKFrontendComponent {
949
990
  identifier: 'Form field (`.govuk-js-character-count`)'
950
991
  });
951
992
  }
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
993
  const errors = validateConfig(CharacterCount.schema, this.config);
962
994
  if (errors[0]) {
963
995
  throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]));
@@ -1143,7 +1175,7 @@ class CharacterCount extends GOVUKFrontendComponent {
1143
1175
  */
1144
1176
 
1145
1177
  /**
1146
- * @typedef {import('../../common/index.mjs').Schema} Schema
1178
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1147
1179
  * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
1148
1180
  */
1149
1181
  CharacterCount.moduleName = 'govuk-character-count';
@@ -1310,16 +1342,15 @@ Checkboxes.moduleName = 'govuk-checkboxes';
1310
1342
  * configuration.
1311
1343
  *
1312
1344
  * @preserve
1345
+ * @augments ConfigurableComponent<ErrorSummaryConfig>
1313
1346
  */
1314
- class ErrorSummary extends GOVUKFrontendComponent {
1347
+ class ErrorSummary extends ConfigurableComponent {
1315
1348
  /**
1316
1349
  * @param {Element | null} $root - HTML element to use for error summary
1317
1350
  * @param {ErrorSummaryConfig} [config] - Error summary config
1318
1351
  */
1319
1352
  constructor($root, config = {}) {
1320
- super($root);
1321
- this.config = void 0;
1322
- this.config = mergeConfigs(ErrorSummary.defaults, config, normaliseDataset(ErrorSummary, this.$root.dataset));
1353
+ super($root, config);
1323
1354
  if (!this.config.disableAutoFocus) {
1324
1355
  setFocus(this.$root);
1325
1356
  }
@@ -1386,7 +1417,7 @@ class ErrorSummary extends GOVUKFrontendComponent {
1386
1417
  */
1387
1418
 
1388
1419
  /**
1389
- * @typedef {import('../../common/index.mjs').Schema} Schema
1420
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1390
1421
  */
1391
1422
  ErrorSummary.moduleName = 'govuk-error-summary';
1392
1423
  ErrorSummary.defaults = Object.freeze({
@@ -1404,15 +1435,15 @@ ErrorSummary.schema = Object.freeze({
1404
1435
  * Exit this page component
1405
1436
  *
1406
1437
  * @preserve
1438
+ * @augments ConfigurableComponent<ExitThisPageConfig>
1407
1439
  */
1408
- class ExitThisPage extends GOVUKFrontendComponent {
1440
+ class ExitThisPage extends ConfigurableComponent {
1409
1441
  /**
1410
1442
  * @param {Element | null} $root - HTML element that wraps the Exit This Page button
1411
1443
  * @param {ExitThisPageConfig} [config] - Exit This Page config
1412
1444
  */
1413
1445
  constructor($root, config = {}) {
1414
- super($root);
1415
- this.config = void 0;
1446
+ super($root, config);
1416
1447
  this.i18n = void 0;
1417
1448
  this.$button = void 0;
1418
1449
  this.$skiplinkButton = null;
@@ -1433,7 +1464,6 @@ class ExitThisPage extends GOVUKFrontendComponent {
1433
1464
  identifier: 'Button (`.govuk-exit-this-page__button`)'
1434
1465
  });
1435
1466
  }
1436
- this.config = mergeConfigs(ExitThisPage.defaults, config, normaliseDataset(ExitThisPage, this.$root.dataset));
1437
1467
  this.i18n = new I18n(this.config.i18n);
1438
1468
  this.$button = $button;
1439
1469
  const $skiplinkButton = document.querySelector('.govuk-js-exit-this-page-skiplink');
@@ -1599,7 +1629,7 @@ class ExitThisPage extends GOVUKFrontendComponent {
1599
1629
  */
1600
1630
 
1601
1631
  /**
1602
- * @typedef {import('../../common/index.mjs').Schema} Schema
1632
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1603
1633
  */
1604
1634
  ExitThisPage.moduleName = 'govuk-exit-this-page';
1605
1635
  ExitThisPage.defaults = Object.freeze({
@@ -1704,16 +1734,15 @@ Header.moduleName = 'govuk-header';
1704
1734
  * Notification Banner component
1705
1735
  *
1706
1736
  * @preserve
1737
+ * @augments ConfigurableComponent<NotificationBannerConfig>
1707
1738
  */
1708
- class NotificationBanner extends GOVUKFrontendComponent {
1739
+ class NotificationBanner extends ConfigurableComponent {
1709
1740
  /**
1710
1741
  * @param {Element | null} $root - HTML element to use for notification banner
1711
1742
  * @param {NotificationBannerConfig} [config] - Notification banner config
1712
1743
  */
1713
1744
  constructor($root, config = {}) {
1714
- super($root);
1715
- this.config = void 0;
1716
- this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, this.$root.dataset));
1745
+ super($root, config);
1717
1746
  if (this.$root.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
1718
1747
  setFocus(this.$root);
1719
1748
  }
@@ -1731,7 +1760,7 @@ class NotificationBanner extends GOVUKFrontendComponent {
1731
1760
  */
1732
1761
 
1733
1762
  /**
1734
- * @typedef {import('../../common/index.mjs').Schema} Schema
1763
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1735
1764
  */
1736
1765
  NotificationBanner.moduleName = 'govuk-notification-banner';
1737
1766
  NotificationBanner.defaults = Object.freeze({
@@ -1749,15 +1778,15 @@ NotificationBanner.schema = Object.freeze({
1749
1778
  * Password input component
1750
1779
  *
1751
1780
  * @preserve
1781
+ * @augments ConfigurableComponent<PasswordInputConfig>
1752
1782
  */
1753
- class PasswordInput extends GOVUKFrontendComponent {
1783
+ class PasswordInput extends ConfigurableComponent {
1754
1784
  /**
1755
1785
  * @param {Element | null} $root - HTML element to use for password input
1756
1786
  * @param {PasswordInputConfig} [config] - Password input config
1757
1787
  */
1758
1788
  constructor($root, config = {}) {
1759
- super($root);
1760
- this.config = void 0;
1789
+ super($root, config);
1761
1790
  this.i18n = void 0;
1762
1791
  this.$input = void 0;
1763
1792
  this.$showHideButton = void 0;
@@ -1788,7 +1817,6 @@ class PasswordInput extends GOVUKFrontendComponent {
1788
1817
  }
1789
1818
  this.$input = $input;
1790
1819
  this.$showHideButton = $showHideButton;
1791
- this.config = mergeConfigs(PasswordInput.defaults, config, normaliseDataset(PasswordInput, this.$root.dataset));
1792
1820
  this.i18n = new I18n(this.config.i18n, {
1793
1821
  locale: closestAttributeValue(this.$root, 'lang')
1794
1822
  });
@@ -1868,7 +1896,7 @@ class PasswordInput extends GOVUKFrontendComponent {
1868
1896
  */
1869
1897
 
1870
1898
  /**
1871
- * @typedef {import('../../common/index.mjs').Schema} Schema
1899
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1872
1900
  * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
1873
1901
  */
1874
1902
  PasswordInput.moduleName = 'govuk-password-input';
@@ -2421,11 +2449,11 @@ function initAll(config) {
2421
2449
  *
2422
2450
  * Any component errors will be caught and logged to the console.
2423
2451
  *
2424
- * @template {CompatibleClass} T
2425
- * @param {T} Component - class of the component to create
2426
- * @param {T["defaults"]} [config] - Config supplied to component
2427
- * @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
2428
- * @returns {Array<InstanceType<T>>} - array of instantiated components
2452
+ * @template {CompatibleClass} ComponentClass
2453
+ * @param {ComponentClass} Component - class of the component to create
2454
+ * @param {ComponentConfig<ComponentClass>} [config] - Config supplied to component
2455
+ * @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
2456
+ * @returns {Array<InstanceType<ComponentClass>>} - array of instantiated components
2429
2457
  */
2430
2458
  function createAll(Component, config, createAllOptions) {
2431
2459
  let $scope = document;
@@ -2472,7 +2500,7 @@ function createAll(Component, config, createAllOptions) {
2472
2500
  }).filter(Boolean);
2473
2501
  }
2474
2502
  /**
2475
- * @typedef {{new (...args: any[]): any, defaults?: object, moduleName: string}} CompatibleClass
2503
+ * @typedef {{new (...args: any[]): any, moduleName: string}} CompatibleClass
2476
2504
  */
2477
2505
  /**
2478
2506
  * Config for all components via `initAll()`
@@ -2506,24 +2534,28 @@ function createAll(Component, config, createAllOptions) {
2506
2534
  * @typedef {keyof Config} ConfigKey
2507
2535
  */
2508
2536
  /**
2509
- * @template {CompatibleClass} T
2537
+ * @template {CompatibleClass} ComponentClass
2538
+ * @typedef {ConstructorParameters<ComponentClass>[1]} ComponentConfig
2539
+ */
2540
+ /**
2541
+ * @template {CompatibleClass} ComponentClass
2510
2542
  * @typedef {object} ErrorContext
2511
2543
  * @property {Element} [element] - Element used for component module initialisation
2512
- * @property {T} [component] - Class of component
2513
- * @property {T["defaults"]} config - Config supplied to component
2544
+ * @property {ComponentClass} [component] - Class of component
2545
+ * @property {ComponentConfig<ComponentClass>} config - Config supplied to component
2514
2546
  */
2515
2547
  /**
2516
- * @template {CompatibleClass} T
2548
+ * @template {CompatibleClass} ComponentClass
2517
2549
  * @callback OnErrorCallback
2518
2550
  * @param {unknown} error - Thrown error
2519
- * @param {ErrorContext<T>} context - Object containing the element, component class and configuration
2551
+ * @param {ErrorContext<ComponentClass>} context - Object containing the element, component class and configuration
2520
2552
  */
2521
2553
  /**
2522
- * @template {CompatibleClass} T
2554
+ * @template {CompatibleClass} ComponentClass
2523
2555
  * @typedef {object} CreateAllOptions
2524
2556
  * @property {Element | Document} [scope] - scope of the document to search within
2525
- * @property {OnErrorCallback<T>} [onError] - callback function if error throw by component on init
2557
+ * @property {OnErrorCallback<ComponentClass>} [onError] - callback function if error throw by component on init
2526
2558
  */
2527
2559
 
2528
- export { Accordion, Button, CharacterCount, Checkboxes, GOVUKFrontendComponent as Component, ErrorSummary, ExitThisPage, Header, NotificationBanner, PasswordInput, Radios, ServiceNavigation, SkipLink, Tabs, createAll, initAll, isSupported, version };
2560
+ export { Accordion, Button, CharacterCount, Checkboxes, GOVUKFrontendComponent as Component, ConfigurableComponent, ErrorSummary, ExitThisPage, Header, NotificationBanner, PasswordInput, Radios, ServiceNavigation, SkipLink, Tabs, createAll, initAll, isSupported, version };
2529
2561
  //# sourceMappingURL=all.bundle.mjs.map