govuk_tech_docs 4.2.0 → 4.3.0

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/govuk_tech_docs.gemspec +1 -1
  4. data/lib/assets/stylesheets/_govuk_tech_docs.scss +3 -0
  5. data/lib/govuk_tech_docs/version.rb +1 -1
  6. data/lib/source/layouts/core.erb +16 -5
  7. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +508 -209
  8. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +505 -208
  9. data/node_modules/govuk-frontend/dist/govuk/all.mjs +3 -1
  10. data/node_modules/govuk-frontend/dist/govuk/all.scss +6 -0
  11. data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +169 -0
  12. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
  13. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +4 -87
  14. data/node_modules/govuk-frontend/dist/govuk/{govuk-frontend-component.mjs → component.mjs} +5 -5
  15. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +161 -116
  16. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +160 -115
  17. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +5 -8
  18. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +161 -116
  19. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +160 -115
  20. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +5 -8
  21. data/node_modules/govuk-frontend/dist/govuk/components/character-count/_index.scss +8 -0
  22. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +187 -145
  23. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +186 -144
  24. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +18 -17
  25. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +9 -29
  26. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +8 -28
  27. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs +2 -2
  28. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +161 -116
  29. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +160 -115
  30. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -8
  31. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +161 -116
  32. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +160 -115
  33. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +5 -8
  34. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/_index.scss +167 -0
  35. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js +754 -0
  36. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs +746 -0
  37. data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs +267 -0
  38. data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss +14 -10
  39. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +9 -29
  40. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +8 -28
  41. data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs +2 -2
  42. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +161 -116
  43. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +160 -115
  44. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -8
  45. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +161 -117
  46. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +160 -116
  47. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +5 -9
  48. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +9 -29
  49. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +8 -28
  50. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs +2 -2
  51. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +9 -29
  52. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +8 -28
  53. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs +2 -2
  54. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +10 -30
  55. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +9 -29
  56. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +3 -3
  57. data/node_modules/govuk-frontend/dist/govuk/components/summary-list/_index.scss +12 -21
  58. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +9 -29
  59. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +8 -28
  60. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs +2 -2
  61. data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
  62. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +1 -1
  63. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
  64. data/node_modules/govuk-frontend/dist/govuk/helpers/_colour.scss +2 -2
  65. data/node_modules/govuk-frontend/dist/govuk/init.mjs +28 -24
  66. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +18 -5
  67. data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss +5 -10
  68. data/node_modules/govuk-frontend/dist/govuk-prototype-kit/init.scss +1 -1
  69. data/package-lock.json +8 -7
  70. data/package.json +1 -1
  71. metadata +12 -10
  72. data/node_modules/govuk-frontend/dist/govuk/common/normalise-dataset.mjs +0 -18
  73. data/node_modules/govuk-frontend/dist/govuk/common/normalise-string.mjs +0 -31
@@ -3,76 +3,6 @@ function closestAttributeValue($element, attributeName) {
3
3
  return $closestElementWithAttribute ? $closestElementWithAttribute.getAttribute(attributeName) : null;
4
4
  }
5
5
 
6
- function normaliseString(value, property) {
7
- const trimmedValue = value ? value.trim() : '';
8
- let output;
9
- let outputType = property == null ? void 0 : property.type;
10
- if (!outputType) {
11
- if (['true', 'false'].includes(trimmedValue)) {
12
- outputType = 'boolean';
13
- }
14
- if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
15
- outputType = 'number';
16
- }
17
- }
18
- switch (outputType) {
19
- case 'boolean':
20
- output = trimmedValue === 'true';
21
- break;
22
- case 'number':
23
- output = Number(trimmedValue);
24
- break;
25
- default:
26
- output = value;
27
- }
28
- return output;
29
- }
30
-
31
- /**
32
- * @typedef {import('./index.mjs').SchemaProperty} SchemaProperty
33
- */
34
-
35
- function mergeConfigs(...configObjects) {
36
- const formattedConfigObject = {};
37
- for (const configObject of configObjects) {
38
- for (const key of Object.keys(configObject)) {
39
- const option = formattedConfigObject[key];
40
- const override = configObject[key];
41
- if (isObject(option) && isObject(override)) {
42
- formattedConfigObject[key] = mergeConfigs(option, override);
43
- } else {
44
- formattedConfigObject[key] = override;
45
- }
46
- }
47
- }
48
- return formattedConfigObject;
49
- }
50
- function extractConfigByNamespace(Component, dataset, namespace) {
51
- const property = Component.schema.properties[namespace];
52
- if ((property == null ? void 0 : property.type) !== 'object') {
53
- return;
54
- }
55
- const newObject = {
56
- [namespace]: ({})
57
- };
58
- for (const [key, value] of Object.entries(dataset)) {
59
- let current = newObject;
60
- const keyParts = key.split('.');
61
- for (const [index, name] of keyParts.entries()) {
62
- if (typeof current === 'object') {
63
- if (index < keyParts.length - 1) {
64
- if (!isObject(current[name])) {
65
- current[name] = {};
66
- }
67
- current = current[name];
68
- } else if (key !== namespace) {
69
- current[name] = normaliseString(value);
70
- }
71
- }
72
- }
73
- }
74
- return newObject[namespace];
75
- }
76
6
  function isInitialised($root, moduleName) {
77
7
  return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
78
8
  }
@@ -92,26 +22,6 @@ function isSupported($scope = document.body) {
92
22
  }
93
23
  return $scope.classList.contains('govuk-frontend-supported');
94
24
  }
95
- function validateConfig(schema, config) {
96
- const validationErrors = [];
97
- for (const [name, conditions] of Object.entries(schema)) {
98
- const errors = [];
99
- if (Array.isArray(conditions)) {
100
- for (const {
101
- required,
102
- errorMessage
103
- } of conditions) {
104
- if (!required.every(key => !!config[key])) {
105
- errors.push(errorMessage);
106
- }
107
- }
108
- if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
109
- validationErrors.push(...errors);
110
- }
111
- }
112
- }
113
- return validationErrors;
114
- }
115
25
  function isArray(option) {
116
26
  return Array.isArray(option);
117
27
  }
@@ -121,46 +31,13 @@ function isObject(option) {
121
31
  function formatErrorMessage(Component, message) {
122
32
  return `${Component.moduleName}: ${message}`;
123
33
  }
124
-
125
- /**
126
- * Schema for component config
127
- *
128
- * @typedef {object} Schema
129
- * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
130
- * @property {SchemaCondition[]} [anyOf] - List of schema conditions
131
- */
132
-
133
- /**
134
- * Schema property for component config
135
- *
136
- * @typedef {object} SchemaProperty
137
- * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
138
- */
139
-
140
- /**
141
- * Schema condition for component config
142
- *
143
- * @typedef {object} SchemaCondition
144
- * @property {string[]} required - List of required config fields
145
- * @property {string} errorMessage - Error message when required config fields not provided
146
- */
147
34
  /**
148
35
  * @typedef ComponentWithModuleName
149
36
  * @property {string} moduleName - Name of the component
150
37
  */
151
-
152
- function normaliseDataset(Component, dataset) {
153
- const out = {};
154
- for (const [field, property] of Object.entries(Component.schema.properties)) {
155
- if (field in dataset) {
156
- out[field] = normaliseString(dataset[field], property);
157
- }
158
- if ((property == null ? void 0 : property.type) === 'object') {
159
- out[field] = extractConfigByNamespace(Component, dataset, field);
160
- }
161
- }
162
- return out;
163
- }
38
+ /**
39
+ * @import { ObjectNested } from './configuration.mjs'
40
+ */
164
41
 
165
42
  class GOVUKFrontendError extends Error {
166
43
  constructor(...args) {
@@ -212,10 +89,10 @@ class InitError extends GOVUKFrontendError {
212
89
  }
213
90
  }
214
91
  /**
215
- * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName
92
+ * @import { ComponentWithModuleName } from '../common/index.mjs'
216
93
  */
217
94
 
218
- class GOVUKFrontendComponent {
95
+ class Component {
219
96
  /**
220
97
  * Returns the root element of the component
221
98
  *
@@ -266,9 +143,172 @@ class GOVUKFrontendComponent {
266
143
  */
267
144
 
268
145
  /**
269
- * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor
146
+ * @typedef {typeof Component & ChildClass} ChildClassConstructor
147
+ */
148
+ Component.elementType = HTMLElement;
149
+
150
+ const configOverride = Symbol.for('configOverride');
151
+ class ConfigurableComponent extends Component {
152
+ [configOverride](param) {
153
+ return {};
154
+ }
155
+
156
+ /**
157
+ * Returns the root element of the component
158
+ *
159
+ * @protected
160
+ * @returns {ConfigurationType} - the root element of component
161
+ */
162
+ get config() {
163
+ return this._config;
164
+ }
165
+ constructor($root, config) {
166
+ super($root);
167
+ this._config = void 0;
168
+ const childConstructor = this.constructor;
169
+ if (!isObject(childConstructor.defaults)) {
170
+ throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
171
+ }
172
+ const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
173
+ this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
174
+ }
175
+ }
176
+ function normaliseString(value, property) {
177
+ const trimmedValue = value ? value.trim() : '';
178
+ let output;
179
+ let outputType = property == null ? void 0 : property.type;
180
+ if (!outputType) {
181
+ if (['true', 'false'].includes(trimmedValue)) {
182
+ outputType = 'boolean';
183
+ }
184
+ if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
185
+ outputType = 'number';
186
+ }
187
+ }
188
+ switch (outputType) {
189
+ case 'boolean':
190
+ output = trimmedValue === 'true';
191
+ break;
192
+ case 'number':
193
+ output = Number(trimmedValue);
194
+ break;
195
+ default:
196
+ output = value;
197
+ }
198
+ return output;
199
+ }
200
+ function normaliseDataset(Component, dataset) {
201
+ if (!isObject(Component.schema)) {
202
+ throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));
203
+ }
204
+ const out = {};
205
+ const entries = Object.entries(Component.schema.properties);
206
+ for (const entry of entries) {
207
+ const [namespace, property] = entry;
208
+ const field = namespace.toString();
209
+ if (field in dataset) {
210
+ out[field] = normaliseString(dataset[field], property);
211
+ }
212
+ if ((property == null ? void 0 : property.type) === 'object') {
213
+ out[field] = extractConfigByNamespace(Component.schema, dataset, namespace);
214
+ }
215
+ }
216
+ return out;
217
+ }
218
+ function mergeConfigs(...configObjects) {
219
+ const formattedConfigObject = {};
220
+ for (const configObject of configObjects) {
221
+ for (const key of Object.keys(configObject)) {
222
+ const option = formattedConfigObject[key];
223
+ const override = configObject[key];
224
+ if (isObject(option) && isObject(override)) {
225
+ formattedConfigObject[key] = mergeConfigs(option, override);
226
+ } else {
227
+ formattedConfigObject[key] = override;
228
+ }
229
+ }
230
+ }
231
+ return formattedConfigObject;
232
+ }
233
+ function validateConfig(schema, config) {
234
+ const validationErrors = [];
235
+ for (const [name, conditions] of Object.entries(schema)) {
236
+ const errors = [];
237
+ if (Array.isArray(conditions)) {
238
+ for (const {
239
+ required,
240
+ errorMessage
241
+ } of conditions) {
242
+ if (!required.every(key => !!config[key])) {
243
+ errors.push(errorMessage);
244
+ }
245
+ }
246
+ if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
247
+ validationErrors.push(...errors);
248
+ }
249
+ }
250
+ }
251
+ return validationErrors;
252
+ }
253
+ function extractConfigByNamespace(schema, dataset, namespace) {
254
+ const property = schema.properties[namespace];
255
+ if ((property == null ? void 0 : property.type) !== 'object') {
256
+ return;
257
+ }
258
+ const newObject = {
259
+ [namespace]: {}
260
+ };
261
+ for (const [key, value] of Object.entries(dataset)) {
262
+ let current = newObject;
263
+ const keyParts = key.split('.');
264
+ for (const [index, name] of keyParts.entries()) {
265
+ if (isObject(current)) {
266
+ if (index < keyParts.length - 1) {
267
+ if (!isObject(current[name])) {
268
+ current[name] = {};
269
+ }
270
+ current = current[name];
271
+ } else if (key !== namespace) {
272
+ current[name] = normaliseString(value);
273
+ }
274
+ }
275
+ }
276
+ }
277
+ return newObject[namespace];
278
+ }
279
+ /**
280
+ * Schema for component config
281
+ *
282
+ * @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType
283
+ * @typedef {object} Schema
284
+ * @property {Record<keyof ConfigurationType, SchemaProperty | undefined>} properties - Schema properties
285
+ * @property {SchemaCondition<ConfigurationType>[]} [anyOf] - List of schema conditions
286
+ */
287
+ /**
288
+ * Schema property for component config
289
+ *
290
+ * @typedef {object} SchemaProperty
291
+ * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
292
+ */
293
+ /**
294
+ * Schema condition for component config
295
+ *
296
+ * @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType
297
+ * @typedef {object} SchemaCondition
298
+ * @property {(keyof ConfigurationType)[]} required - List of required config fields
299
+ * @property {string} errorMessage - Error message when required config fields not provided
300
+ */
301
+ /**
302
+ * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]
303
+ * @typedef ChildClass
304
+ * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
305
+ * @property {Schema<ConfigurationType>} [schema] - The schema of the component configuration
306
+ * @property {ConfigurationType} [defaults] - The default values of the configuration of the component
307
+ */
308
+ /**
309
+ * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]
310
+ * @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
270
311
  */
271
- GOVUKFrontendComponent.elementType = HTMLElement;
272
312
 
273
313
  class I18n {
274
314
  constructor(translations = {}, config = {}) {
@@ -474,22 +514,33 @@ I18n.pluralRules = {
474
514
  * of the available characters/words has been entered.
475
515
  *
476
516
  * @preserve
517
+ * @augments ConfigurableComponent<CharacterCountConfig>
477
518
  */
478
- class CharacterCount extends GOVUKFrontendComponent {
519
+ class CharacterCount extends ConfigurableComponent {
520
+ [configOverride](datasetConfig) {
521
+ let configOverrides = {};
522
+ if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
523
+ configOverrides = {
524
+ maxlength: undefined,
525
+ maxwords: undefined
526
+ };
527
+ }
528
+ return configOverrides;
529
+ }
530
+
479
531
  /**
480
532
  * @param {Element | null} $root - HTML element to use for character count
481
533
  * @param {CharacterCountConfig} [config] - Character count config
482
534
  */
483
535
  constructor($root, config = {}) {
484
536
  var _ref, _this$config$maxwords;
485
- super($root);
537
+ super($root, config);
486
538
  this.$textarea = void 0;
487
539
  this.$visibleCountMessage = void 0;
488
540
  this.$screenReaderCountMessage = void 0;
489
541
  this.lastInputTimestamp = null;
490
542
  this.lastInputValue = '';
491
543
  this.valueChecker = null;
492
- this.config = void 0;
493
544
  this.i18n = void 0;
494
545
  this.maxLength = void 0;
495
546
  const $textarea = this.$root.querySelector('.govuk-js-character-count');
@@ -501,15 +552,6 @@ class CharacterCount extends GOVUKFrontendComponent {
501
552
  identifier: 'Form field (`.govuk-js-character-count`)'
502
553
  });
503
554
  }
504
- const datasetConfig = normaliseDataset(CharacterCount, this.$root.dataset);
505
- let configOverrides = {};
506
- if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
507
- configOverrides = {
508
- maxlength: undefined,
509
- maxwords: undefined
510
- };
511
- }
512
- this.config = mergeConfigs(CharacterCount.defaults, config, configOverrides, datasetConfig);
513
555
  const errors = validateConfig(CharacterCount.schema, this.config);
514
556
  if (errors[0]) {
515
557
  throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]));
@@ -695,8 +737,8 @@ class CharacterCount extends GOVUKFrontendComponent {
695
737
  */
696
738
 
697
739
  /**
698
- * @typedef {import('../../common/index.mjs').Schema} Schema
699
- * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
740
+ * @import { Schema } from '../../common/configuration.mjs'
741
+ * @import { TranslationPluralForms } from '../../i18n.mjs'
700
742
  */
701
743
  CharacterCount.moduleName = 'govuk-character-count';
702
744
  CharacterCount.defaults = Object.freeze({
@@ -1,8 +1,7 @@
1
1
  import { closestAttributeValue } from '../../common/closest-attribute-value.mjs';
2
- import { mergeConfigs, validateConfig, formatErrorMessage } from '../../common/index.mjs';
3
- import { normaliseDataset } from '../../common/normalise-dataset.mjs';
2
+ import { ConfigurableComponent, configOverride, validateConfig } from '../../common/configuration.mjs';
3
+ import { formatErrorMessage } from '../../common/index.mjs';
4
4
  import { ElementError, ConfigError } from '../../errors/index.mjs';
5
- import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs';
6
5
  import { I18n } from '../../i18n.mjs';
7
6
 
8
7
  /**
@@ -16,22 +15,33 @@ import { I18n } from '../../i18n.mjs';
16
15
  * of the available characters/words has been entered.
17
16
  *
18
17
  * @preserve
18
+ * @augments ConfigurableComponent<CharacterCountConfig>
19
19
  */
20
- class CharacterCount extends GOVUKFrontendComponent {
20
+ class CharacterCount extends ConfigurableComponent {
21
+ [configOverride](datasetConfig) {
22
+ let configOverrides = {};
23
+ if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
24
+ configOverrides = {
25
+ maxlength: undefined,
26
+ maxwords: undefined
27
+ };
28
+ }
29
+ return configOverrides;
30
+ }
31
+
21
32
  /**
22
33
  * @param {Element | null} $root - HTML element to use for character count
23
34
  * @param {CharacterCountConfig} [config] - Character count config
24
35
  */
25
36
  constructor($root, config = {}) {
26
37
  var _ref, _this$config$maxwords;
27
- super($root);
38
+ super($root, config);
28
39
  this.$textarea = void 0;
29
40
  this.$visibleCountMessage = void 0;
30
41
  this.$screenReaderCountMessage = void 0;
31
42
  this.lastInputTimestamp = null;
32
43
  this.lastInputValue = '';
33
44
  this.valueChecker = null;
34
- this.config = void 0;
35
45
  this.i18n = void 0;
36
46
  this.maxLength = void 0;
37
47
  const $textarea = this.$root.querySelector('.govuk-js-character-count');
@@ -43,15 +53,6 @@ class CharacterCount extends GOVUKFrontendComponent {
43
53
  identifier: 'Form field (`.govuk-js-character-count`)'
44
54
  });
45
55
  }
46
- const datasetConfig = normaliseDataset(CharacterCount, this.$root.dataset);
47
- let configOverrides = {};
48
- if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
49
- configOverrides = {
50
- maxlength: undefined,
51
- maxwords: undefined
52
- };
53
- }
54
- this.config = mergeConfigs(CharacterCount.defaults, config, configOverrides, datasetConfig);
55
56
  const errors = validateConfig(CharacterCount.schema, this.config);
56
57
  if (errors[0]) {
57
58
  throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]));
@@ -237,8 +238,8 @@ class CharacterCount extends GOVUKFrontendComponent {
237
238
  */
238
239
 
239
240
  /**
240
- * @typedef {import('../../common/index.mjs').Schema} Schema
241
- * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
241
+ * @import { Schema } from '../../common/configuration.mjs'
242
+ * @import { TranslationPluralForms } from '../../i18n.mjs'
242
243
  */
243
244
  CharacterCount.moduleName = 'govuk-character-count';
244
245
  CharacterCount.defaults = Object.freeze({
@@ -1,7 +1,7 @@
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
7
  function isInitialised($root, moduleName) {
@@ -26,33 +26,13 @@
26
26
  function formatErrorMessage(Component, message) {
27
27
  return `${Component.moduleName}: ${message}`;
28
28
  }
29
-
30
- /**
31
- * Schema for component config
32
- *
33
- * @typedef {object} Schema
34
- * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
35
- * @property {SchemaCondition[]} [anyOf] - List of schema conditions
36
- */
37
-
38
- /**
39
- * Schema property for component config
40
- *
41
- * @typedef {object} SchemaProperty
42
- * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
43
- */
44
-
45
- /**
46
- * Schema condition for component config
47
- *
48
- * @typedef {object} SchemaCondition
49
- * @property {string[]} required - List of required config fields
50
- * @property {string} errorMessage - Error message when required config fields not provided
51
- */
52
29
  /**
53
30
  * @typedef ComponentWithModuleName
54
31
  * @property {string} moduleName - Name of the component
55
32
  */
33
+ /**
34
+ * @import { ObjectNested } from './configuration.mjs'
35
+ */
56
36
 
57
37
  class GOVUKFrontendError extends Error {
58
38
  constructor(...args) {
@@ -98,10 +78,10 @@
98
78
  }
99
79
  }
100
80
  /**
101
- * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName
81
+ * @import { ComponentWithModuleName } from '../common/index.mjs'
102
82
  */
103
83
 
104
- class GOVUKFrontendComponent {
84
+ class Component {
105
85
  /**
106
86
  * Returns the root element of the component
107
87
  *
@@ -152,16 +132,16 @@
152
132
  */
153
133
 
154
134
  /**
155
- * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor
135
+ * @typedef {typeof Component & ChildClass} ChildClassConstructor
156
136
  */
157
- GOVUKFrontendComponent.elementType = HTMLElement;
137
+ Component.elementType = HTMLElement;
158
138
 
159
139
  /**
160
140
  * Checkboxes component
161
141
  *
162
142
  * @preserve
163
143
  */
164
- class Checkboxes extends GOVUKFrontendComponent {
144
+ class Checkboxes extends Component {
165
145
  /**
166
146
  * Checkboxes can be associated with a 'conditionally revealed' content block
167
147
  * – for example, a checkbox for 'Phone' could reveal an additional form field
@@ -20,33 +20,13 @@ function isSupported($scope = document.body) {
20
20
  function formatErrorMessage(Component, message) {
21
21
  return `${Component.moduleName}: ${message}`;
22
22
  }
23
-
24
- /**
25
- * Schema for component config
26
- *
27
- * @typedef {object} Schema
28
- * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
29
- * @property {SchemaCondition[]} [anyOf] - List of schema conditions
30
- */
31
-
32
- /**
33
- * Schema property for component config
34
- *
35
- * @typedef {object} SchemaProperty
36
- * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
37
- */
38
-
39
- /**
40
- * Schema condition for component config
41
- *
42
- * @typedef {object} SchemaCondition
43
- * @property {string[]} required - List of required config fields
44
- * @property {string} errorMessage - Error message when required config fields not provided
45
- */
46
23
  /**
47
24
  * @typedef ComponentWithModuleName
48
25
  * @property {string} moduleName - Name of the component
49
26
  */
27
+ /**
28
+ * @import { ObjectNested } from './configuration.mjs'
29
+ */
50
30
 
51
31
  class GOVUKFrontendError extends Error {
52
32
  constructor(...args) {
@@ -92,10 +72,10 @@ class InitError extends GOVUKFrontendError {
92
72
  }
93
73
  }
94
74
  /**
95
- * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName
75
+ * @import { ComponentWithModuleName } from '../common/index.mjs'
96
76
  */
97
77
 
98
- class GOVUKFrontendComponent {
78
+ class Component {
99
79
  /**
100
80
  * Returns the root element of the component
101
81
  *
@@ -146,16 +126,16 @@ class GOVUKFrontendComponent {
146
126
  */
147
127
 
148
128
  /**
149
- * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor
129
+ * @typedef {typeof Component & ChildClass} ChildClassConstructor
150
130
  */
151
- GOVUKFrontendComponent.elementType = HTMLElement;
131
+ Component.elementType = HTMLElement;
152
132
 
153
133
  /**
154
134
  * Checkboxes component
155
135
  *
156
136
  * @preserve
157
137
  */
158
- class Checkboxes extends GOVUKFrontendComponent {
138
+ class Checkboxes extends Component {
159
139
  /**
160
140
  * Checkboxes can be associated with a 'conditionally revealed' content block
161
141
  * – for example, a checkbox for 'Phone' could reveal an additional form field
@@ -1,12 +1,12 @@
1
+ import { Component } from '../../component.mjs';
1
2
  import { ElementError } from '../../errors/index.mjs';
2
- import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs';
3
3
 
4
4
  /**
5
5
  * Checkboxes component
6
6
  *
7
7
  * @preserve
8
8
  */
9
- class Checkboxes extends GOVUKFrontendComponent {
9
+ class Checkboxes extends Component {
10
10
  /**
11
11
  * Checkboxes can be associated with a 'conditionally revealed' content block
12
12
  * – for example, a checkbox for 'Phone' could reveal an additional form field