katalyst-govuk-formbuilder 1.13.0 → 1.14.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb7a5f79742efe731b47dcf4f26f797b4d43e7a97593e979be80c4da34e47707
4
- data.tar.gz: 334a40fb19dd3362db6532b68fb33ee4ded7134e293db426af65fc7ab33724dc
3
+ metadata.gz: da880fe6a065ccf8448421e041d1c32f634eaaa1a2fd01487ab4effb71747350
4
+ data.tar.gz: c908724012b845f60d31f8fe4c5390b4ba8b1402dc36c90b3c49b43e19f555e1
5
5
  SHA512:
6
- metadata.gz: 8a24b9773c6b0426ac5864fd9bc2d5b71ec145f9759b2b54c45651c92aef1bc639a945db305972c9893fb95b161affd2da2f4c696c38ff9a1e79e04b4c42d188
7
- data.tar.gz: 1aacfcaaeaa8dedae0fa8add858555ad677002dada8f6ccf7f64a92be07ee09dd2d42c95258f664299454025fb7b8622a25b3e8452d258cc2259a0b9b1c8fce9
6
+ metadata.gz: 5d919c4cd82b24cd149019fd99b4b423b284fcaeac98dd302071051657255f4f4927c1d6f19126b517f50d36aa98b3b6670b971214d3f9c687fec8c1c153db2f
7
+ data.tar.gz: bdfa418fa809c75069efc79296bfce96a3321adf3d481be56303df42aa3785d75af1179d9b6c1cb9603f4a5da609b3496763fb924bfb97fc25096af3e60b89eb
@@ -43,7 +43,7 @@
43
43
 
44
44
 
45
45
  :root {
46
- --govuk-frontend-version: "5.7.1";
46
+ --govuk-frontend-version: "5.8.0";
47
47
  --govuk-frontend-breakpoint-mobile: 20rem;
48
48
  --govuk-frontend-breakpoint-tablet: 40.0625rem;
49
49
  --govuk-frontend-breakpoint-desktop: 48.0625rem;
@@ -1,69 +1,3 @@
1
- function normaliseString(value, property) {
2
- const trimmedValue = value ? value.trim() : '';
3
- let output;
4
- let outputType = property == null ? void 0 : property.type;
5
- if (!outputType) {
6
- if (['true', 'false'].includes(trimmedValue)) {
7
- outputType = 'boolean';
8
- }
9
- if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
10
- outputType = 'number';
11
- }
12
- }
13
- switch (outputType) {
14
- case 'boolean':
15
- output = trimmedValue === 'true';
16
- break;
17
- case 'number':
18
- output = Number(trimmedValue);
19
- break;
20
- default:
21
- output = value;
22
- }
23
- return output;
24
- }
25
-
26
- function mergeConfigs(...configObjects) {
27
- const formattedConfigObject = {};
28
- for (const configObject of configObjects) {
29
- for (const key of Object.keys(configObject)) {
30
- const option = formattedConfigObject[key];
31
- const override = configObject[key];
32
- if (isObject(option) && isObject(override)) {
33
- formattedConfigObject[key] = mergeConfigs(option, override);
34
- } else {
35
- formattedConfigObject[key] = override;
36
- }
37
- }
38
- }
39
- return formattedConfigObject;
40
- }
41
- function extractConfigByNamespace(Component, dataset, namespace) {
42
- const property = Component.schema.properties[namespace];
43
- if ((property == null ? void 0 : property.type) !== 'object') {
44
- return;
45
- }
46
- const newObject = {
47
- [namespace]: ({})
48
- };
49
- for (const [key, value] of Object.entries(dataset)) {
50
- let current = newObject;
51
- const keyParts = key.split('.');
52
- for (const [index, name] of keyParts.entries()) {
53
- if (typeof current === 'object') {
54
- if (index < keyParts.length - 1) {
55
- if (!isObject(current[name])) {
56
- current[name] = {};
57
- }
58
- current = current[name];
59
- } else if (key !== namespace) {
60
- current[name] = normaliseString(value);
61
- }
62
- }
63
- }
64
- }
65
- return newObject[namespace];
66
- }
67
1
  function getFragmentFromUrl(url) {
68
2
  if (!url.includes('#')) {
69
3
  return undefined;
@@ -113,26 +47,6 @@ function isSupported($scope = document.body) {
113
47
  }
114
48
  return $scope.classList.contains('govuk-frontend-supported');
115
49
  }
116
- function validateConfig(schema, config) {
117
- const validationErrors = [];
118
- for (const [name, conditions] of Object.entries(schema)) {
119
- const errors = [];
120
- if (Array.isArray(conditions)) {
121
- for (const {
122
- required,
123
- errorMessage
124
- } of conditions) {
125
- if (!required.every(key => !!config[key])) {
126
- errors.push(errorMessage);
127
- }
128
- }
129
- if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
130
- validationErrors.push(...errors);
131
- }
132
- }
133
- }
134
- return validationErrors;
135
- }
136
50
  function isArray(option) {
137
51
  return Array.isArray(option);
138
52
  }
@@ -143,19 +57,6 @@ function formatErrorMessage(Component, message) {
143
57
  return `${Component.moduleName}: ${message}`;
144
58
  }
145
59
 
146
- function normaliseDataset(Component, dataset) {
147
- const out = {};
148
- for (const [field, property] of Object.entries(Component.schema.properties)) {
149
- if (field in dataset) {
150
- out[field] = normaliseString(dataset[field], property);
151
- }
152
- if ((property == null ? void 0 : property.type) === 'object') {
153
- out[field] = extractConfigByNamespace(Component, dataset, field);
154
- }
155
- }
156
- return out;
157
- }
158
-
159
60
  class GOVUKFrontendError extends Error {
160
61
  constructor(...args) {
161
62
  super(...args);
@@ -217,7 +118,7 @@ class GOVUKFrontendComponent {
217
118
  return this._$root;
218
119
  }
219
120
  constructor($root) {
220
- this._$root = void 0;
121
+ this._$root = undefined;
221
122
  const childConstructor = this.constructor;
222
123
  if (typeof childConstructor.moduleName !== 'string') {
223
124
  throw new InitError(`\`moduleName\` not defined in component`);
@@ -261,11 +162,138 @@ class GOVUKFrontendComponent {
261
162
  */
262
163
  GOVUKFrontendComponent.elementType = HTMLElement;
263
164
 
165
+ const configOverride = Symbol.for('configOverride');
166
+ class ConfigurableComponent extends GOVUKFrontendComponent {
167
+ [configOverride](param) {
168
+ return {};
169
+ }
170
+
171
+ /**
172
+ * Returns the root element of the component
173
+ *
174
+ * @protected
175
+ * @returns {ConfigurationType} - the root element of component
176
+ */
177
+ get config() {
178
+ return this._config;
179
+ }
180
+ constructor($root, config) {
181
+ super($root);
182
+ this._config = undefined;
183
+ const childConstructor = this.constructor;
184
+ if (typeof childConstructor.defaults === 'undefined') {
185
+ throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
186
+ }
187
+ const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
188
+ this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
189
+ }
190
+ }
191
+ function normaliseString(value, property) {
192
+ const trimmedValue = value ? value.trim() : '';
193
+ let output;
194
+ let outputType = property == null ? undefined : property.type;
195
+ if (!outputType) {
196
+ if (['true', 'false'].includes(trimmedValue)) {
197
+ outputType = 'boolean';
198
+ }
199
+ if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
200
+ outputType = 'number';
201
+ }
202
+ }
203
+ switch (outputType) {
204
+ case 'boolean':
205
+ output = trimmedValue === 'true';
206
+ break;
207
+ case 'number':
208
+ output = Number(trimmedValue);
209
+ break;
210
+ default:
211
+ output = value;
212
+ }
213
+ return output;
214
+ }
215
+ function normaliseDataset(Component, dataset) {
216
+ if (typeof Component.schema === 'undefined') {
217
+ throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));
218
+ }
219
+ const out = {};
220
+ for (const [field, property] of Object.entries(Component.schema.properties)) {
221
+ if (field in dataset) {
222
+ out[field] = normaliseString(dataset[field], property);
223
+ }
224
+ if ((property == null ? undefined : property.type) === 'object') {
225
+ out[field] = extractConfigByNamespace(Component.schema, dataset, field);
226
+ }
227
+ }
228
+ return out;
229
+ }
230
+ function mergeConfigs(...configObjects) {
231
+ const formattedConfigObject = {};
232
+ for (const configObject of configObjects) {
233
+ for (const key of Object.keys(configObject)) {
234
+ const option = formattedConfigObject[key];
235
+ const override = configObject[key];
236
+ if (isObject(option) && isObject(override)) {
237
+ formattedConfigObject[key] = mergeConfigs(option, override);
238
+ } else {
239
+ formattedConfigObject[key] = override;
240
+ }
241
+ }
242
+ }
243
+ return formattedConfigObject;
244
+ }
245
+ function validateConfig(schema, config) {
246
+ const validationErrors = [];
247
+ for (const [name, conditions] of Object.entries(schema)) {
248
+ const errors = [];
249
+ if (Array.isArray(conditions)) {
250
+ for (const {
251
+ required,
252
+ errorMessage
253
+ } of conditions) {
254
+ if (!required.every(key => !!config[key])) {
255
+ errors.push(errorMessage);
256
+ }
257
+ }
258
+ if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
259
+ validationErrors.push(...errors);
260
+ }
261
+ }
262
+ }
263
+ return validationErrors;
264
+ }
265
+ function extractConfigByNamespace(schema, dataset, namespace) {
266
+ const property = schema.properties[namespace];
267
+ if ((property == null ? undefined : property.type) !== 'object') {
268
+ return;
269
+ }
270
+ const newObject = {
271
+ [namespace]: ({})
272
+ };
273
+ for (const [key, value] of Object.entries(dataset)) {
274
+ let current = newObject;
275
+ const keyParts = key.split('.');
276
+ for (const [index, name] of keyParts.entries()) {
277
+ if (typeof current === 'object') {
278
+ if (index < keyParts.length - 1) {
279
+ if (!isObject(current[name])) {
280
+ current[name] = {};
281
+ }
282
+ current = current[name];
283
+ } else if (key !== namespace) {
284
+ current[name] = normaliseString(value);
285
+ }
286
+ }
287
+ }
288
+ }
289
+ return newObject[namespace];
290
+ }
291
+
264
292
  class I18n {
265
293
  constructor(translations = {}, config = {}) {
266
294
  var _config$locale;
267
- this.translations = void 0;
268
- this.locale = void 0;
295
+ this.translations = undefined;
296
+ this.locale = undefined;
269
297
  this.translations = translations;
270
298
  this.locale = (_config$locale = config.locale) != null ? _config$locale : document.documentElement.lang || 'en';
271
299
  }
@@ -274,7 +302,7 @@ class I18n {
274
302
  throw new Error('i18n: lookup key missing');
275
303
  }
276
304
  let translation = this.translations[lookupKey];
277
- if (typeof (options == null ? void 0 : options.count) === 'number' && typeof translation === 'object') {
305
+ if (typeof (options == null ? undefined : options.count) === 'number' && typeof translation === 'object') {
278
306
  const translationPluralForm = translation[this.getPluralSuffix(lookupKey, options.count)];
279
307
  if (translationPluralForm) {
280
308
  translation = translationPluralForm;
@@ -460,17 +488,16 @@ const DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
460
488
  * JavaScript enhancements for the Button component
461
489
  *
462
490
  * @preserve
491
+ * @augments ConfigurableComponent<ButtonConfig>
463
492
  */
464
- class Button extends GOVUKFrontendComponent {
493
+ class Button extends ConfigurableComponent {
465
494
  /**
466
495
  * @param {Element | null} $root - HTML element to use for button
467
496
  * @param {ButtonConfig} [config] - Button config
468
497
  */
469
498
  constructor($root, config = {}) {
470
- super($root);
471
- this.config = void 0;
499
+ super($root, config);
472
500
  this.debounceFormSubmitTimer = null;
473
- this.config = mergeConfigs(Button.defaults, config, normaliseDataset(Button, this.$root.dataset));
474
501
  this.$root.addEventListener('keydown', event => this.handleKeyDown(event));
475
502
  this.$root.addEventListener('click', event => this.debounce(event));
476
503
  }
@@ -507,7 +534,7 @@ class Button extends GOVUKFrontendComponent {
507
534
  */
508
535
 
509
536
  /**
510
- * @typedef {import('../../common/index.mjs').Schema} Schema
537
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
511
538
  */
512
539
  Button.moduleName = 'govuk-button';
513
540
  Button.defaults = Object.freeze({
@@ -537,24 +564,35 @@ function closestAttributeValue($element, attributeName) {
537
564
  * of the available characters/words has been entered.
538
565
  *
539
566
  * @preserve
567
+ * @augments ConfigurableComponent<CharacterCountConfig>
540
568
  */
541
- class CharacterCount extends GOVUKFrontendComponent {
569
+ class CharacterCount extends ConfigurableComponent {
570
+ [configOverride](datasetConfig) {
571
+ let configOverrides = {};
572
+ if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
573
+ configOverrides = {
574
+ maxlength: undefined,
575
+ maxwords: undefined
576
+ };
577
+ }
578
+ return configOverrides;
579
+ }
580
+
542
581
  /**
543
582
  * @param {Element | null} $root - HTML element to use for character count
544
583
  * @param {CharacterCountConfig} [config] - Character count config
545
584
  */
546
585
  constructor($root, config = {}) {
547
586
  var _ref, _this$config$maxwords;
548
- super($root);
549
- this.$textarea = void 0;
550
- this.$visibleCountMessage = void 0;
551
- this.$screenReaderCountMessage = void 0;
587
+ super($root, config);
588
+ this.$textarea = undefined;
589
+ this.$visibleCountMessage = undefined;
590
+ this.$screenReaderCountMessage = undefined;
552
591
  this.lastInputTimestamp = null;
553
592
  this.lastInputValue = '';
554
593
  this.valueChecker = null;
555
- this.config = void 0;
556
- this.i18n = void 0;
557
- this.maxLength = void 0;
594
+ this.i18n = undefined;
595
+ this.maxLength = undefined;
558
596
  const $textarea = this.$root.querySelector('.govuk-js-character-count');
559
597
  if (!($textarea instanceof HTMLTextAreaElement || $textarea instanceof HTMLInputElement)) {
560
598
  throw new ElementError({
@@ -564,15 +602,6 @@ class CharacterCount extends GOVUKFrontendComponent {
564
602
  identifier: 'Form field (`.govuk-js-character-count`)'
565
603
  });
566
604
  }
567
- const datasetConfig = normaliseDataset(CharacterCount, this.$root.dataset);
568
- let configOverrides = {};
569
- if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
570
- configOverrides = {
571
- maxlength: undefined,
572
- maxwords: undefined
573
- };
574
- }
575
- this.config = mergeConfigs(CharacterCount.defaults, config, configOverrides, datasetConfig);
576
605
  const errors = validateConfig(CharacterCount.schema, this.config);
577
606
  if (errors[0]) {
578
607
  throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]));
@@ -758,7 +787,7 @@ class CharacterCount extends GOVUKFrontendComponent {
758
787
  */
759
788
 
760
789
  /**
761
- * @typedef {import('../../common/index.mjs').Schema} Schema
790
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
762
791
  * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
763
792
  */
764
793
  CharacterCount.moduleName = 'govuk-character-count';
@@ -834,7 +863,7 @@ class Checkboxes extends GOVUKFrontendComponent {
834
863
  */
835
864
  constructor($root) {
836
865
  super($root);
837
- this.$inputs = void 0;
866
+ this.$inputs = undefined;
838
867
  const $inputs = this.$root.querySelectorAll('input[type="checkbox"]');
839
868
  if (!$inputs.length) {
840
869
  throw new ElementError({
@@ -925,16 +954,15 @@ Checkboxes.moduleName = 'govuk-checkboxes';
925
954
  * configuration.
926
955
  *
927
956
  * @preserve
957
+ * @augments ConfigurableComponent<ErrorSummaryConfig>
928
958
  */
929
- class ErrorSummary extends GOVUKFrontendComponent {
959
+ class ErrorSummary extends ConfigurableComponent {
930
960
  /**
931
961
  * @param {Element | null} $root - HTML element to use for error summary
932
962
  * @param {ErrorSummaryConfig} [config] - Error summary config
933
963
  */
934
964
  constructor($root, config = {}) {
935
- super($root);
936
- this.config = void 0;
937
- this.config = mergeConfigs(ErrorSummary.defaults, config, normaliseDataset(ErrorSummary, this.$root.dataset));
965
+ super($root, config);
938
966
  if (!this.config.disableAutoFocus) {
939
967
  setFocus(this.$root);
940
968
  }
@@ -1001,7 +1029,7 @@ class ErrorSummary extends GOVUKFrontendComponent {
1001
1029
  */
1002
1030
 
1003
1031
  /**
1004
- * @typedef {import('../../common/index.mjs').Schema} Schema
1032
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1005
1033
  */
1006
1034
  ErrorSummary.moduleName = 'govuk-error-summary';
1007
1035
  ErrorSummary.defaults = Object.freeze({
@@ -1019,19 +1047,19 @@ ErrorSummary.schema = Object.freeze({
1019
1047
  * Password input component
1020
1048
  *
1021
1049
  * @preserve
1050
+ * @augments ConfigurableComponent<PasswordInputConfig>
1022
1051
  */
1023
- class PasswordInput extends GOVUKFrontendComponent {
1052
+ class PasswordInput extends ConfigurableComponent {
1024
1053
  /**
1025
1054
  * @param {Element | null} $root - HTML element to use for password input
1026
1055
  * @param {PasswordInputConfig} [config] - Password input config
1027
1056
  */
1028
1057
  constructor($root, config = {}) {
1029
- super($root);
1030
- this.config = void 0;
1031
- this.i18n = void 0;
1032
- this.$input = void 0;
1033
- this.$showHideButton = void 0;
1034
- this.$screenReaderStatusMessage = void 0;
1058
+ super($root, config);
1059
+ this.i18n = undefined;
1060
+ this.$input = undefined;
1061
+ this.$showHideButton = undefined;
1062
+ this.$screenReaderStatusMessage = undefined;
1035
1063
  const $input = this.$root.querySelector('.govuk-js-password-input-input');
1036
1064
  if (!($input instanceof HTMLInputElement)) {
1037
1065
  throw new ElementError({
@@ -1058,7 +1086,6 @@ class PasswordInput extends GOVUKFrontendComponent {
1058
1086
  }
1059
1087
  this.$input = $input;
1060
1088
  this.$showHideButton = $showHideButton;
1061
- this.config = mergeConfigs(PasswordInput.defaults, config, normaliseDataset(PasswordInput, this.$root.dataset));
1062
1089
  this.i18n = new I18n(this.config.i18n, {
1063
1090
  locale: closestAttributeValue(this.$root, 'lang')
1064
1091
  });
@@ -1138,7 +1165,7 @@ class PasswordInput extends GOVUKFrontendComponent {
1138
1165
  */
1139
1166
 
1140
1167
  /**
1141
- * @typedef {import('../../common/index.mjs').Schema} Schema
1168
+ * @typedef {import('../../common/configuration.mjs').Schema} Schema
1142
1169
  * @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
1143
1170
  */
1144
1171
  PasswordInput.moduleName = 'govuk-password-input';
@@ -1182,7 +1209,7 @@ class Radios extends GOVUKFrontendComponent {
1182
1209
  */
1183
1210
  constructor($root) {
1184
1211
  super($root);
1185
- this.$inputs = void 0;
1212
+ this.$inputs = undefined;
1186
1213
  const $inputs = this.$root.querySelectorAll('input[type="radio"]');
1187
1214
  if (!$inputs.length) {
1188
1215
  throw new ElementError({
@@ -1,10 +1,11 @@
1
- function e(e,t){const n=e?e.trim():"";let o,s=null==t?void 0:t.type;switch(s||(["true","false"].includes(n)&&(s="boolean"),n.length>0&&isFinite(Number(n))&&(s="number")),s){case"boolean":o="true"===n;break;case"number":o=Number(n);break;default:o=e}return o}function t(...e){const n={};for(const o of e)for(const e of Object.keys(o)){const i=n[e],r=o[e];s(i)&&s(r)?n[e]=t(i,r):n[e]=r}return n}function n(t,n,o){const i=t.schema.properties[o];if("object"!==(null==i?void 0:i.type))return;const r={[o]:{}};for(const[t,i]of Object.entries(n)){let n=r;const a=t.split(".");for(const[r,u]of a.entries())"object"==typeof n&&(r<a.length-1?(s(n[u])||(n[u]={}),n=n[u]):t!==o&&(n[u]=e(i)))}return r[o]}function o(e=document.body){return!!e&&e.classList.contains("govuk-frontend-supported")}function s(e){return!!e&&"object"==typeof e&&!function(e){return Array.isArray(e)}(e)}function i(e,t){return`${e.moduleName}: ${t}`}function r(t,o){const s={};for(const[i,r]of Object.entries(t.schema.properties))i in o&&(s[i]=e(o[i],r)),"object"===(null==r?void 0:r.type)&&(s[i]=n(t,o,i));return s}class a extends Error{constructor(...e){super(...e),this.name="GOVUKFrontendError"}}class u extends a{constructor(e=document.body){const t="noModule"in HTMLScriptElement.prototype?'GOV.UK Frontend initialised without `<body class="govuk-frontend-supported">` from template `<script>` snippet':"GOV.UK Frontend is not supported in this browser";super(e?t:'GOV.UK Frontend initialised without `<script type="module">`'),this.name="SupportError"}}class l extends a{constructor(...e){super(...e),this.name="ConfigError"}}class c extends a{constructor(e){let t="string"==typeof e?e:"";if("object"==typeof e){const{component:n,identifier:o,element:s,expectedType:r}=e;t=o,t+=s?` is not of type ${null!=r?r:"HTMLElement"}`:" not found",t=i(n,t)}super(t),this.name="ElementError"}}class h extends a{constructor(e){super("string"==typeof e?e:i(e,"Root element (`$root`) already initialised")),this.name="InitError"}}class d{get $root(){return this._$root}constructor(e){this._$root=void 0;const t=this.constructor;if("string"!=typeof t.moduleName)throw new h("`moduleName` not defined in component");if(!(e instanceof t.elementType))throw new c({element:e,component:t,identifier:"Root element (`$root`)",expectedType:t.elementType.name});this._$root=e,t.checkSupport(),this.checkInitialised();const n=t.moduleName;this.$root.setAttribute(`data-${n}-init`,"")}checkInitialised(){const e=this.constructor,t=e.moduleName;if(t&&function(e,t){return e instanceof HTMLElement&&e.hasAttribute(`data-${t}-init`)}(this.$root,t))throw new h(e)}static checkSupport(){if(!o())throw new u}}d.elementType=HTMLElement;class p{constructor(e={},t={}){var n;this.translations=void 0,this.locale=void 0,this.translations=e,this.locale=null!=(n=t.locale)?n:document.documentElement.lang||"en"}t(e,t){if(!e)throw new Error("i18n: lookup key missing");let n=this.translations[e];if("number"==typeof(null==t?void 0:t.count)&&"object"==typeof n){const o=n[this.getPluralSuffix(e,t.count)];o&&(n=o)}if("string"==typeof n){if(n.match(/%{(.\S+)}/)){if(!t)throw new Error("i18n: cannot replace placeholders in string if no option data provided");return this.replacePlaceholders(n,t)}return n}return e}replacePlaceholders(e,t){const n=Intl.NumberFormat.supportedLocalesOf(this.locale).length?new Intl.NumberFormat(this.locale):void 0;return e.replace(/%{(.\S+)}/g,(function(e,o){if(Object.prototype.hasOwnProperty.call(t,o)){const e=t[o];return!1===e||"number"!=typeof e&&"string"!=typeof e?"":"number"==typeof e?n?n.format(e):`${e}`:e}throw new Error(`i18n: no data found to replace ${e} placeholder in string`)}))}hasIntlPluralRulesSupport(){return Boolean("PluralRules"in window.Intl&&Intl.PluralRules.supportedLocalesOf(this.locale).length)}getPluralSuffix(e,t){if(t=Number(t),!isFinite(t))return"other";const n=this.translations[e],o=this.hasIntlPluralRulesSupport()?new Intl.PluralRules(this.locale).select(t):this.selectPluralFormUsingFallbackRules(t);if("object"==typeof n){if(o in n)return o;if("other"in n)return console.warn(`i18n: Missing plural form ".${o}" for "${this.locale}" locale. Falling back to ".other".`),"other"}throw new Error(`i18n: Plural form ".other" is required for "${this.locale}" locale`)}selectPluralFormUsingFallbackRules(e){e=Math.abs(Math.floor(e));const t=this.getPluralRulesForLocale();return t?p.pluralRules[t](e):"other"}getPluralRulesForLocale(){const e=this.locale.split("-")[0];for(const t in p.pluralRulesMap){const n=p.pluralRulesMap[t];if(n.includes(this.locale)||n.includes(e))return t}}}p.pluralRulesMap={arabic:["ar"],chinese:["my","zh","id","ja","jv","ko","ms","th","vi"],french:["hy","bn","fr","gu","hi","fa","pa","zu"],german:["af","sq","az","eu","bg","ca","da","nl","en","et","fi","ka","de","el","hu","lb","no","so","sw","sv","ta","te","tr","ur"],irish:["ga"],russian:["ru","uk"],scottish:["gd"],spanish:["pt-PT","it","es"],welsh:["cy"]},p.pluralRules={arabic:e=>0===e?"zero":1===e?"one":2===e?"two":e%100>=3&&e%100<=10?"few":e%100>=11&&e%100<=99?"many":"other",chinese:()=>"other",french:e=>0===e||1===e?"one":"other",german:e=>1===e?"one":"other",irish:e=>1===e?"one":2===e?"two":e>=3&&e<=6?"few":e>=7&&e<=10?"many":"other",russian(e){const t=e%100,n=t%10;return 1===n&&11!==t?"one":n>=2&&n<=4&&!(t>=12&&t<=14)?"few":0===n||n>=5&&n<=9||t>=11&&t<=14?"many":"other"},scottish:e=>1===e||11===e?"one":2===e||12===e?"two":e>=3&&e<=10||e>=13&&e<=19?"few":"other",spanish:e=>1===e?"one":e%1e6==0&&0!==e?"many":"other",welsh:e=>0===e?"zero":1===e?"one":2===e?"two":3===e?"few":6===e?"many":"other"};
1
+ function e(e=document.body){return!!e&&e.classList.contains("govuk-frontend-supported")}function t(e){return!!e&&"object"==typeof e&&!function(e){return Array.isArray(e)}(e)}function n(e,t){return`${e.moduleName}: ${t}`}class o extends Error{constructor(...e){super(...e),this.name="GOVUKFrontendError"}}class s extends o{constructor(e=document.body){const t="noModule"in HTMLScriptElement.prototype?'GOV.UK Frontend initialised without `<body class="govuk-frontend-supported">` from template `<script>` snippet':"GOV.UK Frontend is not supported in this browser";super(e?t:'GOV.UK Frontend initialised without `<script type="module">`'),this.name="SupportError"}}class i extends o{constructor(...e){super(...e),this.name="ConfigError"}}class r extends o{constructor(e){let t="string"==typeof e?e:"";if("object"==typeof e){const{component:o,identifier:s,element:i,expectedType:r}=e;t=s,t+=i?` is not of type ${null!=r?r:"HTMLElement"}`:" not found",t=n(o,t)}super(t),this.name="ElementError"}}class a extends o{constructor(e){super("string"==typeof e?e:n(e,"Root element (`$root`) already initialised")),this.name="InitError"}}class u{get $root(){return this._$root}constructor(e){this._$root=void 0;const t=this.constructor;if("string"!=typeof t.moduleName)throw new a("`moduleName` not defined in component");if(!(e instanceof t.elementType))throw new r({element:e,component:t,identifier:"Root element (`$root`)",expectedType:t.elementType.name});this._$root=e,t.checkSupport(),this.checkInitialised();const n=t.moduleName;this.$root.setAttribute(`data-${n}-init`,"")}checkInitialised(){const e=this.constructor,t=e.moduleName;if(t&&function(e,t){return e instanceof HTMLElement&&e.hasAttribute(`data-${t}-init`)}(this.$root,t))throw new a(e)}static checkSupport(){if(!e())throw new s}}u.elementType=HTMLElement;const c=Symbol.for("configOverride");class l extends u{[c](e){return{}}get config(){return this._config}constructor(e,t){super(e),this._config=void 0;const o=this.constructor;if(void 0===o.defaults)throw new i(n(o,"Config passed as parameter into constructor but no defaults defined"));const s=function(e,t){if(void 0===e.schema)throw new i(n(e,"Config passed as parameter into constructor but no schema defined"));const o={};for(const[n,s]of Object.entries(e.schema.properties))n in t&&(o[n]=h(t[n],s)),"object"===(null==s?void 0:s.type)&&(o[n]=p(e.schema,t,n));return o}(o,this._$root.dataset);this._config=d(o.defaults,null!=t?t:{},this[c](s),s)}}function h(e,t){const n=e?e.trim():"";let o,s=null==t?void 0:t.type;switch(s||(["true","false"].includes(n)&&(s="boolean"),n.length>0&&isFinite(Number(n))&&(s="number")),s){case"boolean":o="true"===n;break;case"number":o=Number(n);break;default:o=e}return o}function d(...e){const n={};for(const o of e)for(const e of Object.keys(o)){const s=n[e],i=o[e];t(s)&&t(i)?n[e]=d(s,i):n[e]=i}return n}function p(e,n,o){const s=e.properties[o];if("object"!==(null==s?void 0:s.type))return;const i={[o]:{}};for(const[e,s]of Object.entries(n)){let n=i;const r=e.split(".");for(const[i,a]of r.entries())"object"==typeof n&&(i<r.length-1?(t(n[a])||(n[a]={}),n=n[a]):e!==o&&(n[a]=h(s)))}return i[o]}class m{constructor(e={},t={}){var n;this.translations=void 0,this.locale=void 0,this.translations=e,this.locale=null!=(n=t.locale)?n:document.documentElement.lang||"en"}t(e,t){if(!e)throw new Error("i18n: lookup key missing");let n=this.translations[e];if("number"==typeof(null==t?void 0:t.count)&&"object"==typeof n){const o=n[this.getPluralSuffix(e,t.count)];o&&(n=o)}if("string"==typeof n){if(n.match(/%{(.\S+)}/)){if(!t)throw new Error("i18n: cannot replace placeholders in string if no option data provided");return this.replacePlaceholders(n,t)}return n}return e}replacePlaceholders(e,t){const n=Intl.NumberFormat.supportedLocalesOf(this.locale).length?new Intl.NumberFormat(this.locale):void 0;return e.replace(/%{(.\S+)}/g,(function(e,o){if(Object.prototype.hasOwnProperty.call(t,o)){const e=t[o];return!1===e||"number"!=typeof e&&"string"!=typeof e?"":"number"==typeof e?n?n.format(e):`${e}`:e}throw new Error(`i18n: no data found to replace ${e} placeholder in string`)}))}hasIntlPluralRulesSupport(){return Boolean("PluralRules"in window.Intl&&Intl.PluralRules.supportedLocalesOf(this.locale).length)}getPluralSuffix(e,t){if(t=Number(t),!isFinite(t))return"other";const n=this.translations[e],o=this.hasIntlPluralRulesSupport()?new Intl.PluralRules(this.locale).select(t):this.selectPluralFormUsingFallbackRules(t);if("object"==typeof n){if(o in n)return o;if("other"in n)return console.warn(`i18n: Missing plural form ".${o}" for "${this.locale}" locale. Falling back to ".other".`),"other"}throw new Error(`i18n: Plural form ".other" is required for "${this.locale}" locale`)}selectPluralFormUsingFallbackRules(e){e=Math.abs(Math.floor(e));const t=this.getPluralRulesForLocale();return t?m.pluralRules[t](e):"other"}getPluralRulesForLocale(){const e=this.locale.split("-")[0];for(const t in m.pluralRulesMap){const n=m.pluralRulesMap[t];if(n.includes(this.locale)||n.includes(e))return t}}}m.pluralRulesMap={arabic:["ar"],chinese:["my","zh","id","ja","jv","ko","ms","th","vi"],french:["hy","bn","fr","gu","hi","fa","pa","zu"],german:["af","sq","az","eu","bg","ca","da","nl","en","et","fi","ka","de","el","hu","lb","no","so","sw","sv","ta","te","tr","ur"],irish:["ga"],russian:["ru","uk"],scottish:["gd"],spanish:["pt-PT","it","es"],welsh:["cy"]},m.pluralRules={arabic:e=>0===e?"zero":1===e?"one":2===e?"two":e%100>=3&&e%100<=10?"few":e%100>=11&&e%100<=99?"many":"other",chinese:()=>"other",french:e=>0===e||1===e?"one":"other",german:e=>1===e?"one":"other",irish:e=>1===e?"one":2===e?"two":e>=3&&e<=6?"few":e>=7&&e<=10?"many":"other",russian(e){const t=e%100,n=t%10;return 1===n&&11!==t?"one":n>=2&&n<=4&&!(t>=12&&t<=14)?"few":0===n||n>=5&&n<=9||t>=11&&t<=14?"many":"other"},scottish:e=>1===e||11===e?"one":2===e||12===e?"two":e>=3&&e<=10||e>=13&&e<=19?"few":"other",spanish:e=>1===e?"one":e%1e6==0&&0!==e?"many":"other",welsh:e=>0===e?"zero":1===e?"one":2===e?"two":3===e?"few":6===e?"many":"other"};
2
2
  /**
3
3
  * JavaScript enhancements for the Button component
4
4
  *
5
5
  * @preserve
6
+ * @augments ConfigurableComponent<ButtonConfig>
6
7
  */
7
- class m extends d{constructor(e,n={}){super(e),this.config=void 0,this.debounceFormSubmitTimer=null,this.config=t(m.defaults,n,r(m,this.$root.dataset)),this.$root.addEventListener("keydown",(e=>this.handleKeyDown(e))),this.$root.addEventListener("click",(e=>this.debounce(e)))}handleKeyDown(e){const t=e.target;" "===e.key&&t instanceof HTMLElement&&"button"===t.getAttribute("role")&&(e.preventDefault(),t.click())}debounce(e){if(this.config.preventDoubleClick)return this.debounceFormSubmitTimer?(e.preventDefault(),!1):void(this.debounceFormSubmitTimer=window.setTimeout((()=>{this.debounceFormSubmitTimer=null}),1e3))}}function f(e,t){const n=e.closest(`[${t}]`);return n?n.getAttribute(t):null}
8
+ class f extends l{constructor(e,t={}){super(e,t),this.debounceFormSubmitTimer=null,this.$root.addEventListener("keydown",(e=>this.handleKeyDown(e))),this.$root.addEventListener("click",(e=>this.debounce(e)))}handleKeyDown(e){const t=e.target;" "===e.key&&t instanceof HTMLElement&&"button"===t.getAttribute("role")&&(e.preventDefault(),t.click())}debounce(e){if(this.config.preventDoubleClick)return this.debounceFormSubmitTimer?(e.preventDefault(),!1):void(this.debounceFormSubmitTimer=window.setTimeout((()=>{this.debounceFormSubmitTimer=null}),1e3))}}function g(e,t){const n=e.closest(`[${t}]`);return n?n.getAttribute(t):null}
8
9
  /**
9
10
  * Character count component
10
11
  *
@@ -16,13 +17,14 @@ class m extends d{constructor(e,n={}){super(e),this.config=void 0,this.debounceF
16
17
  * of the available characters/words has been entered.
17
18
  *
18
19
  * @preserve
19
- */m.moduleName="govuk-button",m.defaults=Object.freeze({preventDoubleClick:!1}),m.schema=Object.freeze({properties:{preventDoubleClick:{type:"boolean"}}});class g extends d{constructor(e,n={}){var o,s;super(e),this.$textarea=void 0,this.$visibleCountMessage=void 0,this.$screenReaderCountMessage=void 0,this.lastInputTimestamp=null,this.lastInputValue="",this.valueChecker=null,this.config=void 0,this.i18n=void 0,this.maxLength=void 0;const a=this.$root.querySelector(".govuk-js-character-count");if(!(a instanceof HTMLTextAreaElement||a instanceof HTMLInputElement))throw new c({component:g,element:a,expectedType:"HTMLTextareaElement or HTMLInputElement",identifier:"Form field (`.govuk-js-character-count`)"});const u=r(g,this.$root.dataset);let h={};("maxwords"in u||"maxlength"in u)&&(h={maxlength:void 0,maxwords:void 0}),this.config=t(g.defaults,n,h,u);const d=function(e,t){const n=[];for(const[o,s]of Object.entries(e)){const e=[];if(Array.isArray(s)){for(const{required:n,errorMessage:o}of s)n.every((e=>!!t[e]))||e.push(o);"anyOf"!==o||s.length-e.length>=1||n.push(...e)}}return n}(g.schema,this.config);if(d[0])throw new l(i(g,d[0]));this.i18n=new p(this.config.i18n,{locale:f(this.$root,"lang")}),this.maxLength=null!=(o=null!=(s=this.config.maxwords)?s:this.config.maxlength)?o:1/0,this.$textarea=a;const m=`${this.$textarea.id}-info`,v=document.getElementById(m);if(!v)throw new c({component:g,element:v,identifier:`Count message (\`id="${m}"\`)`});`${v.textContent}`.match(/^\s*$/)&&(v.textContent=this.i18n.t("textareaDescription",{count:this.maxLength})),this.$textarea.insertAdjacentElement("afterend",v);const w=document.createElement("div");w.className="govuk-character-count__sr-status govuk-visually-hidden",w.setAttribute("aria-live","polite"),this.$screenReaderCountMessage=w,v.insertAdjacentElement("afterend",w);const b=document.createElement("div");b.className=v.className,b.classList.add("govuk-character-count__status"),b.setAttribute("aria-hidden","true"),this.$visibleCountMessage=b,v.insertAdjacentElement("afterend",b),v.classList.add("govuk-visually-hidden"),this.$textarea.removeAttribute("maxlength"),this.bindChangeEvents(),window.addEventListener("pageshow",(()=>this.updateCountMessage())),this.updateCountMessage()}bindChangeEvents(){this.$textarea.addEventListener("keyup",(()=>this.handleKeyUp())),this.$textarea.addEventListener("focus",(()=>this.handleFocus())),this.$textarea.addEventListener("blur",(()=>this.handleBlur()))}handleKeyUp(){this.updateVisibleCountMessage(),this.lastInputTimestamp=Date.now()}handleFocus(){this.valueChecker=window.setInterval((()=>{(!this.lastInputTimestamp||Date.now()-500>=this.lastInputTimestamp)&&this.updateIfValueChanged()}),1e3)}handleBlur(){this.valueChecker&&window.clearInterval(this.valueChecker)}updateIfValueChanged(){this.$textarea.value!==this.lastInputValue&&(this.lastInputValue=this.$textarea.value,this.updateCountMessage())}updateCountMessage(){this.updateVisibleCountMessage(),this.updateScreenReaderCountMessage()}updateVisibleCountMessage(){const e=this.maxLength-this.count(this.$textarea.value)<0;this.$visibleCountMessage.classList.toggle("govuk-character-count__message--disabled",!this.isOverThreshold()),this.$textarea.classList.toggle("govuk-textarea--error",e),this.$visibleCountMessage.classList.toggle("govuk-error-message",e),this.$visibleCountMessage.classList.toggle("govuk-hint",!e),this.$visibleCountMessage.textContent=this.getCountMessage()}updateScreenReaderCountMessage(){this.isOverThreshold()?this.$screenReaderCountMessage.removeAttribute("aria-hidden"):this.$screenReaderCountMessage.setAttribute("aria-hidden","true"),this.$screenReaderCountMessage.textContent=this.getCountMessage()}count(e){if(this.config.maxwords){var t;return(null!=(t=e.match(/\S+/g))?t:[]).length}return e.length}getCountMessage(){const e=this.maxLength-this.count(this.$textarea.value),t=this.config.maxwords?"words":"characters";return this.formatCountMessage(e,t)}formatCountMessage(e,t){if(0===e)return this.i18n.t(`${t}AtLimit`);const n=e<0?"OverLimit":"UnderLimit";return this.i18n.t(`${t}${n}`,{count:Math.abs(e)})}isOverThreshold(){if(!this.config.threshold)return!0;const e=this.count(this.$textarea.value);return this.maxLength*this.config.threshold/100<=e}}g.moduleName="govuk-character-count",g.defaults=Object.freeze({threshold:0,i18n:{charactersUnderLimit:{one:"You have %{count} character remaining",other:"You have %{count} characters remaining"},charactersAtLimit:"You have 0 characters remaining",charactersOverLimit:{one:"You have %{count} character too many",other:"You have %{count} characters too many"},wordsUnderLimit:{one:"You have %{count} word remaining",other:"You have %{count} words remaining"},wordsAtLimit:"You have 0 words remaining",wordsOverLimit:{one:"You have %{count} word too many",other:"You have %{count} words too many"},textareaDescription:{other:""}}}),g.schema=Object.freeze({properties:{i18n:{type:"object"},maxwords:{type:"number"},maxlength:{type:"number"},threshold:{type:"number"}},anyOf:[{required:["maxwords"],errorMessage:'Either "maxlength" or "maxwords" must be provided'},{required:["maxlength"],errorMessage:'Either "maxlength" or "maxwords" must be provided'}]});
20
+ * @augments ConfigurableComponent<CharacterCountConfig>
21
+ */f.moduleName="govuk-button",f.defaults=Object.freeze({preventDoubleClick:!1}),f.schema=Object.freeze({properties:{preventDoubleClick:{type:"boolean"}}});class v extends l{[c](e){let t={};return("maxwords"in e||"maxlength"in e)&&(t={maxlength:void 0,maxwords:void 0}),t}constructor(e,t={}){var o,s;super(e,t),this.$textarea=void 0,this.$visibleCountMessage=void 0,this.$screenReaderCountMessage=void 0,this.lastInputTimestamp=null,this.lastInputValue="",this.valueChecker=null,this.i18n=void 0,this.maxLength=void 0;const a=this.$root.querySelector(".govuk-js-character-count");if(!(a instanceof HTMLTextAreaElement||a instanceof HTMLInputElement))throw new r({component:v,element:a,expectedType:"HTMLTextareaElement or HTMLInputElement",identifier:"Form field (`.govuk-js-character-count`)"});const u=function(e,t){const n=[];for(const[o,s]of Object.entries(e)){const e=[];if(Array.isArray(s)){for(const{required:n,errorMessage:o}of s)n.every((e=>!!t[e]))||e.push(o);"anyOf"!==o||s.length-e.length>=1||n.push(...e)}}return n}(v.schema,this.config);if(u[0])throw new i(n(v,u[0]));this.i18n=new m(this.config.i18n,{locale:g(this.$root,"lang")}),this.maxLength=null!=(o=null!=(s=this.config.maxwords)?s:this.config.maxlength)?o:1/0,this.$textarea=a;const c=`${this.$textarea.id}-info`,l=document.getElementById(c);if(!l)throw new r({component:v,element:l,identifier:`Count message (\`id="${c}"\`)`});`${l.textContent}`.match(/^\s*$/)&&(l.textContent=this.i18n.t("textareaDescription",{count:this.maxLength})),this.$textarea.insertAdjacentElement("afterend",l);const h=document.createElement("div");h.className="govuk-character-count__sr-status govuk-visually-hidden",h.setAttribute("aria-live","polite"),this.$screenReaderCountMessage=h,l.insertAdjacentElement("afterend",h);const d=document.createElement("div");d.className=l.className,d.classList.add("govuk-character-count__status"),d.setAttribute("aria-hidden","true"),this.$visibleCountMessage=d,l.insertAdjacentElement("afterend",d),l.classList.add("govuk-visually-hidden"),this.$textarea.removeAttribute("maxlength"),this.bindChangeEvents(),window.addEventListener("pageshow",(()=>this.updateCountMessage())),this.updateCountMessage()}bindChangeEvents(){this.$textarea.addEventListener("keyup",(()=>this.handleKeyUp())),this.$textarea.addEventListener("focus",(()=>this.handleFocus())),this.$textarea.addEventListener("blur",(()=>this.handleBlur()))}handleKeyUp(){this.updateVisibleCountMessage(),this.lastInputTimestamp=Date.now()}handleFocus(){this.valueChecker=window.setInterval((()=>{(!this.lastInputTimestamp||Date.now()-500>=this.lastInputTimestamp)&&this.updateIfValueChanged()}),1e3)}handleBlur(){this.valueChecker&&window.clearInterval(this.valueChecker)}updateIfValueChanged(){this.$textarea.value!==this.lastInputValue&&(this.lastInputValue=this.$textarea.value,this.updateCountMessage())}updateCountMessage(){this.updateVisibleCountMessage(),this.updateScreenReaderCountMessage()}updateVisibleCountMessage(){const e=this.maxLength-this.count(this.$textarea.value)<0;this.$visibleCountMessage.classList.toggle("govuk-character-count__message--disabled",!this.isOverThreshold()),this.$textarea.classList.toggle("govuk-textarea--error",e),this.$visibleCountMessage.classList.toggle("govuk-error-message",e),this.$visibleCountMessage.classList.toggle("govuk-hint",!e),this.$visibleCountMessage.textContent=this.getCountMessage()}updateScreenReaderCountMessage(){this.isOverThreshold()?this.$screenReaderCountMessage.removeAttribute("aria-hidden"):this.$screenReaderCountMessage.setAttribute("aria-hidden","true"),this.$screenReaderCountMessage.textContent=this.getCountMessage()}count(e){if(this.config.maxwords){var t;return(null!=(t=e.match(/\S+/g))?t:[]).length}return e.length}getCountMessage(){const e=this.maxLength-this.count(this.$textarea.value),t=this.config.maxwords?"words":"characters";return this.formatCountMessage(e,t)}formatCountMessage(e,t){if(0===e)return this.i18n.t(`${t}AtLimit`);const n=e<0?"OverLimit":"UnderLimit";return this.i18n.t(`${t}${n}`,{count:Math.abs(e)})}isOverThreshold(){if(!this.config.threshold)return!0;const e=this.count(this.$textarea.value);return this.maxLength*this.config.threshold/100<=e}}v.moduleName="govuk-character-count",v.defaults=Object.freeze({threshold:0,i18n:{charactersUnderLimit:{one:"You have %{count} character remaining",other:"You have %{count} characters remaining"},charactersAtLimit:"You have 0 characters remaining",charactersOverLimit:{one:"You have %{count} character too many",other:"You have %{count} characters too many"},wordsUnderLimit:{one:"You have %{count} word remaining",other:"You have %{count} words remaining"},wordsAtLimit:"You have 0 words remaining",wordsOverLimit:{one:"You have %{count} word too many",other:"You have %{count} words too many"},textareaDescription:{other:""}}}),v.schema=Object.freeze({properties:{i18n:{type:"object"},maxwords:{type:"number"},maxlength:{type:"number"},threshold:{type:"number"}},anyOf:[{required:["maxwords"],errorMessage:'Either "maxlength" or "maxwords" must be provided'},{required:["maxlength"],errorMessage:'Either "maxlength" or "maxwords" must be provided'}]});
20
22
  /**
21
23
  * Checkboxes component
22
24
  *
23
25
  * @preserve
24
26
  */
25
- class v extends d{constructor(e){super(e),this.$inputs=void 0;const t=this.$root.querySelectorAll('input[type="checkbox"]');if(!t.length)throw new c({component:v,identifier:'Form inputs (`<input type="checkbox">`)'});this.$inputs=t,this.$inputs.forEach((e=>{const t=e.getAttribute("data-aria-controls");if(t){if(!document.getElementById(t))throw new c({component:v,identifier:`Conditional reveal (\`id="${t}"\`)`});e.setAttribute("aria-controls",t),e.removeAttribute("data-aria-controls")}})),window.addEventListener("pageshow",(()=>this.syncAllConditionalReveals())),this.syncAllConditionalReveals(),this.$root.addEventListener("click",(e=>this.handleClick(e)))}syncAllConditionalReveals(){this.$inputs.forEach((e=>this.syncConditionalRevealWithInputState(e)))}syncConditionalRevealWithInputState(e){const t=e.getAttribute("aria-controls");if(!t)return;const n=document.getElementById(t);if(null!=n&&n.classList.contains("govuk-checkboxes__conditional")){const t=e.checked;e.setAttribute("aria-expanded",t.toString()),n.classList.toggle("govuk-checkboxes__conditional--hidden",!t)}}unCheckAllInputsExcept(e){document.querySelectorAll(`input[type="checkbox"][name="${e.name}"]`).forEach((t=>{e.form===t.form&&t!==e&&(t.checked=!1,this.syncConditionalRevealWithInputState(t))}))}unCheckExclusiveInputs(e){document.querySelectorAll(`input[data-behaviour="exclusive"][type="checkbox"][name="${e.name}"]`).forEach((t=>{e.form===t.form&&(t.checked=!1,this.syncConditionalRevealWithInputState(t))}))}handleClick(e){const t=e.target;if(!(t instanceof HTMLInputElement)||"checkbox"!==t.type)return;if(t.getAttribute("aria-controls")&&this.syncConditionalRevealWithInputState(t),!t.checked)return;"exclusive"===t.getAttribute("data-behaviour")?this.unCheckAllInputsExcept(t):this.unCheckExclusiveInputs(t)}}v.moduleName="govuk-checkboxes";
27
+ class w extends u{constructor(e){super(e),this.$inputs=void 0;const t=this.$root.querySelectorAll('input[type="checkbox"]');if(!t.length)throw new r({component:w,identifier:'Form inputs (`<input type="checkbox">`)'});this.$inputs=t,this.$inputs.forEach((e=>{const t=e.getAttribute("data-aria-controls");if(t){if(!document.getElementById(t))throw new r({component:w,identifier:`Conditional reveal (\`id="${t}"\`)`});e.setAttribute("aria-controls",t),e.removeAttribute("data-aria-controls")}})),window.addEventListener("pageshow",(()=>this.syncAllConditionalReveals())),this.syncAllConditionalReveals(),this.$root.addEventListener("click",(e=>this.handleClick(e)))}syncAllConditionalReveals(){this.$inputs.forEach((e=>this.syncConditionalRevealWithInputState(e)))}syncConditionalRevealWithInputState(e){const t=e.getAttribute("aria-controls");if(!t)return;const n=document.getElementById(t);if(null!=n&&n.classList.contains("govuk-checkboxes__conditional")){const t=e.checked;e.setAttribute("aria-expanded",t.toString()),n.classList.toggle("govuk-checkboxes__conditional--hidden",!t)}}unCheckAllInputsExcept(e){document.querySelectorAll(`input[type="checkbox"][name="${e.name}"]`).forEach((t=>{e.form===t.form&&t!==e&&(t.checked=!1,this.syncConditionalRevealWithInputState(t))}))}unCheckExclusiveInputs(e){document.querySelectorAll(`input[data-behaviour="exclusive"][type="checkbox"][name="${e.name}"]`).forEach((t=>{e.form===t.form&&(t.checked=!1,this.syncConditionalRevealWithInputState(t))}))}handleClick(e){const t=e.target;if(!(t instanceof HTMLInputElement)||"checkbox"!==t.type)return;if(t.getAttribute("aria-controls")&&this.syncConditionalRevealWithInputState(t),!t.checked)return;"exclusive"===t.getAttribute("data-behaviour")?this.unCheckAllInputsExcept(t):this.unCheckExclusiveInputs(t)}}w.moduleName="govuk-checkboxes";
26
28
  /**
27
29
  * Error summary component
28
30
  *
@@ -30,17 +32,19 @@ class v extends d{constructor(e){super(e),this.$inputs=void 0;const t=this.$root
30
32
  * configuration.
31
33
  *
32
34
  * @preserve
35
+ * @augments ConfigurableComponent<ErrorSummaryConfig>
33
36
  */
34
- class w extends d{constructor(e,n={}){super(e),this.config=void 0,this.config=t(w.defaults,n,r(w,this.$root.dataset)),this.config.disableAutoFocus||function(e,t={}){var n;const o=e.getAttribute("tabindex");function s(){var n;null==(n=t.onBlur)||n.call(e),o||e.removeAttribute("tabindex")}o||e.setAttribute("tabindex","-1"),e.addEventListener("focus",(function(){e.addEventListener("blur",s,{once:!0})}),{once:!0}),null==(n=t.onBeforeFocus)||n.call(e),e.focus()}(this.$root),this.$root.addEventListener("click",(e=>this.handleClick(e)))}handleClick(e){const t=e.target;t&&this.focusTarget(t)&&e.preventDefault()}focusTarget(e){if(!(e instanceof HTMLAnchorElement))return!1;const t=function(e){if(e.includes("#"))return e.split("#").pop()}(e.href);if(!t)return!1;const n=document.getElementById(t);if(!n)return!1;const o=this.getAssociatedLegendOrLabel(n);return!!o&&(o.scrollIntoView(),n.focus({preventScroll:!0}),!0)}getAssociatedLegendOrLabel(e){var t;const n=e.closest("fieldset");if(n){const t=n.getElementsByTagName("legend");if(t.length){const n=t[0];if(e instanceof HTMLInputElement&&("checkbox"===e.type||"radio"===e.type))return n;const o=n.getBoundingClientRect().top,s=e.getBoundingClientRect();if(s.height&&window.innerHeight){if(s.top+s.height-o<window.innerHeight/2)return n}}}return null!=(t=document.querySelector(`label[for='${e.getAttribute("id")}']`))?t:e.closest("label")}}w.moduleName="govuk-error-summary",w.defaults=Object.freeze({disableAutoFocus:!1}),w.schema=Object.freeze({properties:{disableAutoFocus:{type:"boolean"}}});
37
+ class b extends l{constructor(e,t={}){super(e,t),this.config.disableAutoFocus||function(e,t={}){var n;const o=e.getAttribute("tabindex");function s(){var n;null==(n=t.onBlur)||n.call(e),o||e.removeAttribute("tabindex")}o||e.setAttribute("tabindex","-1"),e.addEventListener("focus",(function(){e.addEventListener("blur",s,{once:!0})}),{once:!0}),null==(n=t.onBeforeFocus)||n.call(e),e.focus()}(this.$root),this.$root.addEventListener("click",(e=>this.handleClick(e)))}handleClick(e){const t=e.target;t&&this.focusTarget(t)&&e.preventDefault()}focusTarget(e){if(!(e instanceof HTMLAnchorElement))return!1;const t=function(e){if(e.includes("#"))return e.split("#").pop()}(e.href);if(!t)return!1;const n=document.getElementById(t);if(!n)return!1;const o=this.getAssociatedLegendOrLabel(n);return!!o&&(o.scrollIntoView(),n.focus({preventScroll:!0}),!0)}getAssociatedLegendOrLabel(e){var t;const n=e.closest("fieldset");if(n){const t=n.getElementsByTagName("legend");if(t.length){const n=t[0];if(e instanceof HTMLInputElement&&("checkbox"===e.type||"radio"===e.type))return n;const o=n.getBoundingClientRect().top,s=e.getBoundingClientRect();if(s.height&&window.innerHeight){if(s.top+s.height-o<window.innerHeight/2)return n}}}return null!=(t=document.querySelector(`label[for='${e.getAttribute("id")}']`))?t:e.closest("label")}}b.moduleName="govuk-error-summary",b.defaults=Object.freeze({disableAutoFocus:!1}),b.schema=Object.freeze({properties:{disableAutoFocus:{type:"boolean"}}});
35
38
  /**
36
39
  * Password input component
37
40
  *
38
41
  * @preserve
42
+ * @augments ConfigurableComponent<PasswordInputConfig>
39
43
  */
40
- class b extends d{constructor(e,n={}){super(e),this.config=void 0,this.i18n=void 0,this.$input=void 0,this.$showHideButton=void 0,this.$screenReaderStatusMessage=void 0;const o=this.$root.querySelector(".govuk-js-password-input-input");if(!(o instanceof HTMLInputElement))throw new c({component:b,element:o,expectedType:"HTMLInputElement",identifier:"Form field (`.govuk-js-password-input-input`)"});if("password"!==o.type)throw new c("Password input: Form field (`.govuk-js-password-input-input`) must be of type `password`.");const s=this.$root.querySelector(".govuk-js-password-input-toggle");if(!(s instanceof HTMLButtonElement))throw new c({component:b,element:s,expectedType:"HTMLButtonElement",identifier:"Button (`.govuk-js-password-input-toggle`)"});if("button"!==s.type)throw new c("Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.");this.$input=o,this.$showHideButton=s,this.config=t(b.defaults,n,r(b,this.$root.dataset)),this.i18n=new p(this.config.i18n,{locale:f(this.$root,"lang")}),this.$showHideButton.removeAttribute("hidden");const i=document.createElement("div");i.className="govuk-password-input__sr-status govuk-visually-hidden",i.setAttribute("aria-live","polite"),this.$screenReaderStatusMessage=i,this.$input.insertAdjacentElement("afterend",i),this.$showHideButton.addEventListener("click",this.toggle.bind(this)),this.$input.form&&this.$input.form.addEventListener("submit",(()=>this.hide())),window.addEventListener("pageshow",(e=>{e.persisted&&"password"!==this.$input.type&&this.hide()})),this.hide()}toggle(e){e.preventDefault(),"password"!==this.$input.type?this.hide():this.show()}show(){this.setType("text")}hide(){this.setType("password")}setType(e){if(e===this.$input.type)return;this.$input.setAttribute("type",e);const t="password"===e,n=t?"show":"hide",o=t?"passwordHidden":"passwordShown";this.$showHideButton.innerText=this.i18n.t(`${n}Password`),this.$showHideButton.setAttribute("aria-label",this.i18n.t(`${n}PasswordAriaLabel`)),this.$screenReaderStatusMessage.innerText=this.i18n.t(`${o}Announcement`)}}b.moduleName="govuk-password-input",b.defaults=Object.freeze({i18n:{showPassword:"Show",hidePassword:"Hide",showPasswordAriaLabel:"Show password",hidePasswordAriaLabel:"Hide password",passwordShownAnnouncement:"Your password is visible",passwordHiddenAnnouncement:"Your password is hidden"}}),b.schema=Object.freeze({properties:{i18n:{type:"object"}}});
44
+ class y extends l{constructor(e,t={}){super(e,t),this.i18n=void 0,this.$input=void 0,this.$showHideButton=void 0,this.$screenReaderStatusMessage=void 0;const n=this.$root.querySelector(".govuk-js-password-input-input");if(!(n instanceof HTMLInputElement))throw new r({component:y,element:n,expectedType:"HTMLInputElement",identifier:"Form field (`.govuk-js-password-input-input`)"});if("password"!==n.type)throw new r("Password input: Form field (`.govuk-js-password-input-input`) must be of type `password`.");const o=this.$root.querySelector(".govuk-js-password-input-toggle");if(!(o instanceof HTMLButtonElement))throw new r({component:y,element:o,expectedType:"HTMLButtonElement",identifier:"Button (`.govuk-js-password-input-toggle`)"});if("button"!==o.type)throw new r("Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.");this.$input=n,this.$showHideButton=o,this.i18n=new m(this.config.i18n,{locale:g(this.$root,"lang")}),this.$showHideButton.removeAttribute("hidden");const s=document.createElement("div");s.className="govuk-password-input__sr-status govuk-visually-hidden",s.setAttribute("aria-live","polite"),this.$screenReaderStatusMessage=s,this.$input.insertAdjacentElement("afterend",s),this.$showHideButton.addEventListener("click",this.toggle.bind(this)),this.$input.form&&this.$input.form.addEventListener("submit",(()=>this.hide())),window.addEventListener("pageshow",(e=>{e.persisted&&"password"!==this.$input.type&&this.hide()})),this.hide()}toggle(e){e.preventDefault(),"password"!==this.$input.type?this.hide():this.show()}show(){this.setType("text")}hide(){this.setType("password")}setType(e){if(e===this.$input.type)return;this.$input.setAttribute("type",e);const t="password"===e,n=t?"show":"hide",o=t?"passwordHidden":"passwordShown";this.$showHideButton.innerText=this.i18n.t(`${n}Password`),this.$showHideButton.setAttribute("aria-label",this.i18n.t(`${n}PasswordAriaLabel`)),this.$screenReaderStatusMessage.innerText=this.i18n.t(`${o}Announcement`)}}y.moduleName="govuk-password-input",y.defaults=Object.freeze({i18n:{showPassword:"Show",hidePassword:"Hide",showPasswordAriaLabel:"Show password",hidePasswordAriaLabel:"Hide password",passwordShownAnnouncement:"Your password is visible",passwordHiddenAnnouncement:"Your password is hidden"}}),y.schema=Object.freeze({properties:{i18n:{type:"object"}}});
41
45
  /**
42
46
  * Radios component
43
47
  *
44
48
  * @preserve
45
49
  */
46
- class y extends d{constructor(e){super(e),this.$inputs=void 0;const t=this.$root.querySelectorAll('input[type="radio"]');if(!t.length)throw new c({component:y,identifier:'Form inputs (`<input type="radio">`)'});this.$inputs=t,this.$inputs.forEach((e=>{const t=e.getAttribute("data-aria-controls");if(t){if(!document.getElementById(t))throw new c({component:y,identifier:`Conditional reveal (\`id="${t}"\`)`});e.setAttribute("aria-controls",t),e.removeAttribute("data-aria-controls")}})),window.addEventListener("pageshow",(()=>this.syncAllConditionalReveals())),this.syncAllConditionalReveals(),this.$root.addEventListener("click",(e=>this.handleClick(e)))}syncAllConditionalReveals(){this.$inputs.forEach((e=>this.syncConditionalRevealWithInputState(e)))}syncConditionalRevealWithInputState(e){const t=e.getAttribute("aria-controls");if(!t)return;const n=document.getElementById(t);if(null!=n&&n.classList.contains("govuk-radios__conditional")){const t=e.checked;e.setAttribute("aria-expanded",t.toString()),n.classList.toggle("govuk-radios__conditional--hidden",!t)}}handleClick(e){const t=e.target;if(!(t instanceof HTMLInputElement)||"radio"!==t.type)return;const n=document.querySelectorAll('input[type="radio"][aria-controls]'),o=t.form,s=t.name;n.forEach((e=>{const t=e.form===o;e.name===s&&t&&this.syncConditionalRevealWithInputState(e)}))}}function $(e){let t;if(e=void 0!==e?e:{},!o())return void console.log(new u);const n=[[m,e.button],[g,e.characterCount],[v],[w,e.errorSummary],[y],[b,e.passwordInput]],s=null!=(t=e.scope)?t:document;n.forEach((([e,t])=>{s.querySelectorAll(`[data-module="${e.moduleName}"]`).forEach((n=>{try{"defaults"in e?new e(n,t):new e(n)}catch(e){console.log(e)}}))}))}y.moduleName="govuk-radios";export{m as Button,g as CharacterCount,v as Checkboxes,w as ErrorSummary,b as PasswordInput,y as Radios,$ as initAll};
50
+ class $ extends u{constructor(e){super(e),this.$inputs=void 0;const t=this.$root.querySelectorAll('input[type="radio"]');if(!t.length)throw new r({component:$,identifier:'Form inputs (`<input type="radio">`)'});this.$inputs=t,this.$inputs.forEach((e=>{const t=e.getAttribute("data-aria-controls");if(t){if(!document.getElementById(t))throw new r({component:$,identifier:`Conditional reveal (\`id="${t}"\`)`});e.setAttribute("aria-controls",t),e.removeAttribute("data-aria-controls")}})),window.addEventListener("pageshow",(()=>this.syncAllConditionalReveals())),this.syncAllConditionalReveals(),this.$root.addEventListener("click",(e=>this.handleClick(e)))}syncAllConditionalReveals(){this.$inputs.forEach((e=>this.syncConditionalRevealWithInputState(e)))}syncConditionalRevealWithInputState(e){const t=e.getAttribute("aria-controls");if(!t)return;const n=document.getElementById(t);if(null!=n&&n.classList.contains("govuk-radios__conditional")){const t=e.checked;e.setAttribute("aria-expanded",t.toString()),n.classList.toggle("govuk-radios__conditional--hidden",!t)}}handleClick(e){const t=e.target;if(!(t instanceof HTMLInputElement)||"radio"!==t.type)return;const n=document.querySelectorAll('input[type="radio"][aria-controls]'),o=t.form,s=t.name;n.forEach((e=>{const t=e.form===o;e.name===s&&t&&this.syncConditionalRevealWithInputState(e)}))}}function x(t){let n;if(t=void 0!==t?t:{},!e())return void console.log(new s);const o=[[f,t.button],[v,t.characterCount],[w],[b,t.errorSummary],[$],[y,t.passwordInput]],i=null!=(n=t.scope)?n:document;o.forEach((([e,t])=>{i.querySelectorAll(`[data-module="${e.moduleName}"]`).forEach((n=>{try{"defaults"in e?new e(n,t):new e(n)}catch(e){console.log(e)}}))}))}$.moduleName="govuk-radios";export{f as Button,v as CharacterCount,w as Checkboxes,b as ErrorSummary,y as PasswordInput,$ as Radios,x as initAll};
@@ -1,3 +1,9 @@
1
1
  @import "index";
2
2
 
3
+ @include _warning(
4
+ "import-using-all",
5
+ "Importing using 'govuk/all' is deprecated. Update your import statement to import 'govuk/index'.",
6
+ $silence-further-warnings: false
7
+ );
8
+
3
9
  /*# sourceMappingURL=all.scss.map */
@@ -1,7 +1,7 @@
1
1
  :root {
2
2
  // This variable is automatically overwritten during builds and releases.
3
3
  // It doesn't need to be updated manually.
4
- --govuk-frontend-version: "5.7.1";
4
+ --govuk-frontend-version: "5.8.0";
5
5
 
6
6
  // CSS custom property for each breakpoint
7
7
  @each $name, $value in $govuk-breakpoints {
@@ -216,8 +216,7 @@ $_govuk-typography-scale-modern: (
216
216
  ),
217
217
  27: (
218
218
  // Made same as 24 on mobile (consider deprecating this size)
219
- null:
220
- (
219
+ null: (
221
220
  font-size: 21px,
222
221
  line-height: 25px
223
222
  ),
@@ -232,8 +231,7 @@ $_govuk-typography-scale-modern: (
232
231
  ),
233
232
  24: (
234
233
  // Bump up mobile size from 18/20 to 21/25
235
- null:
236
- (
234
+ null: (
237
235
  font-size: 21px,
238
236
  line-height: 25px
239
237
  ),
@@ -248,8 +246,7 @@ $_govuk-typography-scale-modern: (
248
246
  ),
249
247
  19: (
250
248
  // Stay at 19/25 at all sizes
251
- null:
252
- (
249
+ null: (
253
250
  font-size: 19px,
254
251
  line-height: 25px
255
252
  ),
@@ -260,8 +257,7 @@ $_govuk-typography-scale-modern: (
260
257
  ),
261
258
  16: (
262
259
  // Stay at 16/20 at all sizes
263
- null:
264
- (
260
+ null: (
265
261
  font-size: 16px,
266
262
  line-height: 20px
267
263
  ),
@@ -272,8 +268,7 @@ $_govuk-typography-scale-modern: (
272
268
  ),
273
269
  14: (
274
270
  // Stay at 14/20 at all sizes (consider deprecating this size)
275
- null:
276
- (
271
+ null: (
277
272
  font-size: 14px,
278
273
  line-height: 20px
279
274
  ),
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katalyst-govuk-formbuilder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.13.0
4
+ version: 1.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katalyst Interactive
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-11-06 00:00:00.000000000 Z
10
+ date: 2025-01-31 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: govuk_design_system_formbuilder
@@ -197,7 +196,6 @@ licenses:
197
196
  - MIT
198
197
  metadata:
199
198
  rubygems_mfa_required: 'true'
200
- post_install_message:
201
199
  rdoc_options: []
202
200
  require_paths:
203
201
  - lib
@@ -212,8 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
210
  - !ruby/object:Gem::Version
213
211
  version: '0'
214
212
  requirements: []
215
- rubygems_version: 3.5.16
216
- signing_key:
213
+ rubygems_version: 3.6.2
217
214
  specification_version: 4
218
215
  summary: Repackaging of UK.GOV forms for Rails 7 asset pipeline
219
216
  test_files: []