govuk_tech_docs 6.5.2.0 → 6.6.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/publish-gem.yaml +4 -1
- data/lib/govuk_tech_docs/version.rb +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +202 -137
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +202 -137
- data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +5 -1
- data/node_modules/govuk-frontend/dist/govuk/common/create-element.mjs +13 -0
- data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
- data/node_modules/govuk-frontend/dist/govuk/component.mjs +2 -1
- data/node_modules/govuk-frontend/dist/govuk/components/_index.import.scss +2 -0
- data/node_modules/govuk-frontend/dist/govuk/components/_index.scss +2 -0
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +87 -62
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +87 -62
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +60 -56
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +17 -6
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +17 -6
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +90 -32
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +90 -32
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +64 -27
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +12 -5
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +12 -5
- data/node_modules/govuk-frontend/dist/govuk/components/cookie-banner/_mixin.scss +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +17 -6
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +17 -6
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +43 -18
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +43 -18
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +16 -12
- data/node_modules/govuk-frontend/dist/govuk/components/feedback/_feedback.import.scss +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/feedback/_index.import.scss +8 -0
- data/node_modules/govuk-frontend/dist/govuk/components/feedback/_index.scss +5 -0
- data/node_modules/govuk-frontend/dist/govuk/components/feedback/_mixin.scss +48 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js +54 -30
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs +54 -30
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs +27 -24
- data/node_modules/govuk-frontend/dist/govuk/components/footer/_mixin.scss +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/_index.import.scss +8 -0
- data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/_index.scss +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/_language-navigation.import.scss +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/language-navigation/_mixin.scss +68 -0
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +17 -6
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +17 -6
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +32 -9
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +32 -9
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +5 -3
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +12 -5
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +12 -5
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_mixin.scss +48 -3
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +12 -5
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +12 -5
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +14 -6
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +14 -6
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +2 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +12 -5
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +12 -5
- data/node_modules/govuk-frontend/dist/govuk/custom-properties/_frontend-version.mixin.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk/custom-properties/_functional-colours.mixin.scss +1 -0
- data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +8 -5
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_colour.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk/init.mjs +8 -8
- data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +16 -2
- data/package-lock.json +4 -4
- data/package.json +1 -1
- metadata +10 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ConfigurableComponent } from '../../common/configuration.mjs';
|
|
2
|
+
import { createElement } from '../../common/create-element.mjs';
|
|
2
3
|
import { ElementError } from '../../errors/index.mjs';
|
|
3
4
|
import { I18n } from '../../i18n.mjs';
|
|
4
5
|
|
|
@@ -25,24 +26,16 @@ class Accordion extends ConfigurableComponent {
|
|
|
25
26
|
constructor($root, config = {}) {
|
|
26
27
|
super($root, config);
|
|
27
28
|
this.i18n = void 0;
|
|
28
|
-
this.controlsClass = 'govuk-accordion__controls';
|
|
29
|
-
this.showAllClass = 'govuk-accordion__show-all';
|
|
30
|
-
this.showAllTextClass = 'govuk-accordion__show-all-text';
|
|
31
29
|
this.sectionClass = 'govuk-accordion__section';
|
|
32
|
-
this.
|
|
30
|
+
this.sectionExpandedModifier = 'govuk-accordion__section--expanded';
|
|
33
31
|
this.sectionButtonClass = 'govuk-accordion__section-button';
|
|
34
32
|
this.sectionHeaderClass = 'govuk-accordion__section-header';
|
|
35
33
|
this.sectionHeadingClass = 'govuk-accordion__section-heading';
|
|
36
|
-
this.sectionHeadingDividerClass = 'govuk-accordion__section-heading-divider';
|
|
37
34
|
this.sectionHeadingTextClass = 'govuk-accordion__section-heading-text';
|
|
38
|
-
this.
|
|
39
|
-
this.
|
|
40
|
-
this.
|
|
41
|
-
this.sectionShowHideTextClass = 'govuk-accordion__section-toggle-text';
|
|
42
|
-
this.upChevronIconClass = 'govuk-accordion-nav__chevron';
|
|
43
|
-
this.downChevronIconClass = 'govuk-accordion-nav__chevron--down';
|
|
35
|
+
this.sectionToggleTextClass = 'govuk-accordion__section-toggle-text';
|
|
36
|
+
this.iconClass = 'govuk-accordion-nav__chevron';
|
|
37
|
+
this.iconOpenModifier = 'govuk-accordion-nav__chevron--down';
|
|
44
38
|
this.sectionSummaryClass = 'govuk-accordion__section-summary';
|
|
45
|
-
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
|
|
46
39
|
this.sectionContentClass = 'govuk-accordion__section-content';
|
|
47
40
|
this.$sections = void 0;
|
|
48
41
|
this.$showAllButton = null;
|
|
@@ -62,19 +55,23 @@ class Accordion extends ConfigurableComponent {
|
|
|
62
55
|
this.updateShowAllButton(this.areAllSectionsOpen());
|
|
63
56
|
}
|
|
64
57
|
initControls() {
|
|
65
|
-
this.$showAllButton =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.$showAllIcon
|
|
58
|
+
this.$showAllButton = createElement('button', {
|
|
59
|
+
type: 'button',
|
|
60
|
+
class: 'govuk-accordion__show-all',
|
|
61
|
+
'aria-expanded': 'false'
|
|
62
|
+
});
|
|
63
|
+
this.$showAllIcon = createElement('span', {
|
|
64
|
+
class: this.iconClass
|
|
65
|
+
});
|
|
71
66
|
this.$showAllButton.appendChild(this.$showAllIcon);
|
|
72
|
-
const $accordionControls =
|
|
73
|
-
|
|
67
|
+
const $accordionControls = createElement('div', {
|
|
68
|
+
class: 'govuk-accordion__controls'
|
|
69
|
+
});
|
|
74
70
|
$accordionControls.appendChild(this.$showAllButton);
|
|
75
71
|
this.$root.insertBefore($accordionControls, this.$root.firstChild);
|
|
76
|
-
this.$showAllText =
|
|
77
|
-
|
|
72
|
+
this.$showAllText = createElement('span', {
|
|
73
|
+
class: 'govuk-accordion__show-all-text'
|
|
74
|
+
});
|
|
78
75
|
this.$showAllButton.appendChild(this.$showAllText);
|
|
79
76
|
this.$showAllButton.addEventListener('click', () => this.onShowOrHideAllToggle());
|
|
80
77
|
if ('onbeforematch' in document) {
|
|
@@ -112,39 +109,45 @@ class Accordion extends ConfigurableComponent {
|
|
|
112
109
|
identifier: `Section button placeholder (\`<span class="${this.sectionButtonClass}">\`)`
|
|
113
110
|
});
|
|
114
111
|
}
|
|
115
|
-
const $button =
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
const $button = createElement('button', {
|
|
113
|
+
type: 'button',
|
|
114
|
+
'aria-controls': `${this.$root.id}-content-${index + 1}`
|
|
115
|
+
});
|
|
118
116
|
for (const attr of Array.from($span.attributes)) {
|
|
119
117
|
if (attr.name !== 'id') {
|
|
120
118
|
$button.setAttribute(attr.name, attr.value);
|
|
121
119
|
}
|
|
122
120
|
}
|
|
123
|
-
const $headingText =
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
$headingTextFocus
|
|
121
|
+
const $headingText = createElement('span', {
|
|
122
|
+
class: this.sectionHeadingTextClass,
|
|
123
|
+
id: $span.id
|
|
124
|
+
});
|
|
125
|
+
const $headingTextFocus = createElement('span', {
|
|
126
|
+
class: 'govuk-accordion__section-heading-text-focus'
|
|
127
|
+
});
|
|
128
128
|
$headingText.appendChild($headingTextFocus);
|
|
129
129
|
Array.from($span.childNodes).forEach($child => $headingTextFocus.appendChild($child));
|
|
130
|
-
const $showHideToggle =
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
$showHideToggleFocus
|
|
130
|
+
const $showHideToggle = createElement('span', {
|
|
131
|
+
class: 'govuk-accordion__section-toggle',
|
|
132
|
+
'data-nosnippet': ''
|
|
133
|
+
});
|
|
134
|
+
const $showHideToggleFocus = createElement('span', {
|
|
135
|
+
class: 'govuk-accordion__section-toggle-focus'
|
|
136
|
+
});
|
|
135
137
|
$showHideToggle.appendChild($showHideToggleFocus);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
$showHideToggleFocus.appendChild(
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
$showHideToggleFocus.appendChild(createElement('span', {
|
|
139
|
+
class: this.iconClass
|
|
140
|
+
}));
|
|
141
|
+
$showHideToggleFocus.appendChild(createElement('span', {
|
|
142
|
+
class: this.sectionToggleTextClass
|
|
143
|
+
}));
|
|
142
144
|
$button.appendChild($headingText);
|
|
143
145
|
$button.appendChild(this.getButtonPunctuationEl());
|
|
144
146
|
if ($summary) {
|
|
145
|
-
const $summarySpan =
|
|
146
|
-
const $summarySpanFocus =
|
|
147
|
-
|
|
147
|
+
const $summarySpan = createElement('span');
|
|
148
|
+
const $summarySpanFocus = createElement('span', {
|
|
149
|
+
class: 'govuk-accordion__section-summary-focus'
|
|
150
|
+
});
|
|
148
151
|
$summarySpan.appendChild($summarySpanFocus);
|
|
149
152
|
for (const attr of Array.from($summary.attributes)) {
|
|
150
153
|
$summarySpan.setAttribute(attr.name, attr.value);
|
|
@@ -182,8 +185,8 @@ class Accordion extends ConfigurableComponent {
|
|
|
182
185
|
this.updateShowAllButton(nowExpanded);
|
|
183
186
|
}
|
|
184
187
|
setExpanded(expanded, $section) {
|
|
185
|
-
const $showHideIcon = $section.querySelector(`.${this.
|
|
186
|
-
const $showHideText = $section.querySelector(`.${this.
|
|
188
|
+
const $showHideIcon = $section.querySelector(`.${this.iconClass}`);
|
|
189
|
+
const $showHideText = $section.querySelector(`.${this.sectionToggleTextClass}`);
|
|
187
190
|
const $button = $section.querySelector(`.${this.sectionButtonClass}`);
|
|
188
191
|
const $content = $section.querySelector(`.${this.sectionContentClass}`);
|
|
189
192
|
if (!$content) {
|
|
@@ -212,17 +215,17 @@ class Accordion extends ConfigurableComponent {
|
|
|
212
215
|
$button.setAttribute('aria-label', ariaLabelParts.join(' , '));
|
|
213
216
|
if (expanded) {
|
|
214
217
|
$content.removeAttribute('hidden');
|
|
215
|
-
$section.classList.add(this.
|
|
216
|
-
$showHideIcon.classList.remove(this.
|
|
218
|
+
$section.classList.add(this.sectionExpandedModifier);
|
|
219
|
+
$showHideIcon.classList.remove(this.iconOpenModifier);
|
|
217
220
|
} else {
|
|
218
221
|
$content.setAttribute('hidden', 'until-found');
|
|
219
|
-
$section.classList.remove(this.
|
|
220
|
-
$showHideIcon.classList.add(this.
|
|
222
|
+
$section.classList.remove(this.sectionExpandedModifier);
|
|
223
|
+
$showHideIcon.classList.add(this.iconOpenModifier);
|
|
221
224
|
}
|
|
222
225
|
this.updateShowAllButton(this.areAllSectionsOpen());
|
|
223
226
|
}
|
|
224
227
|
isExpanded($section) {
|
|
225
|
-
return $section.classList.contains(this.
|
|
228
|
+
return $section.classList.contains(this.sectionExpandedModifier);
|
|
226
229
|
}
|
|
227
230
|
areAllSectionsOpen() {
|
|
228
231
|
return Array.from(this.$sections).every($section => this.isExpanded($section));
|
|
@@ -233,7 +236,7 @@ class Accordion extends ConfigurableComponent {
|
|
|
233
236
|
}
|
|
234
237
|
this.$showAllButton.setAttribute('aria-expanded', expanded.toString());
|
|
235
238
|
this.$showAllText.textContent = expanded ? this.i18n.t('hideAllSections') : this.i18n.t('showAllSections');
|
|
236
|
-
this.$showAllIcon.classList.toggle(this.
|
|
239
|
+
this.$showAllIcon.classList.toggle(this.iconOpenModifier, !expanded);
|
|
237
240
|
}
|
|
238
241
|
|
|
239
242
|
/**
|
|
@@ -276,10 +279,11 @@ class Accordion extends ConfigurableComponent {
|
|
|
276
279
|
}
|
|
277
280
|
}
|
|
278
281
|
getButtonPunctuationEl() {
|
|
279
|
-
const $
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
282
|
+
const $element = createElement('span', {
|
|
283
|
+
class: 'govuk-visually-hidden govuk-accordion__section-heading-divider'
|
|
284
|
+
});
|
|
285
|
+
$element.textContent = ', ';
|
|
286
|
+
return $element;
|
|
283
287
|
}
|
|
284
288
|
}
|
|
285
289
|
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
function isObject(option) {
|
|
30
30
|
return !!option && typeof option === 'object' && !isArray(option);
|
|
31
31
|
}
|
|
32
|
+
function isScope($scope) {
|
|
33
|
+
return !!$scope && ($scope instanceof Element || $scope instanceof Document);
|
|
34
|
+
}
|
|
32
35
|
function formatErrorMessage(Component, message) {
|
|
33
36
|
return `${Component.moduleName}: ${message}`;
|
|
34
37
|
}
|
|
@@ -47,11 +50,14 @@
|
|
|
47
50
|
/**
|
|
48
51
|
* Checks if GOV.UK Frontend is supported on this page
|
|
49
52
|
*
|
|
50
|
-
* @param {
|
|
53
|
+
* @param {Element | Document | null | string} [scopeOrMessage] - HTML element `<body>` checked for browser support or support error message
|
|
51
54
|
*/
|
|
52
|
-
constructor(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
constructor(scopeOrMessage = document.body) {
|
|
56
|
+
let supportMessage = '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';
|
|
57
|
+
if (!isScope(scopeOrMessage)) {
|
|
58
|
+
supportMessage = 'GOV.UK Frontend initialised without `<script type="module">`';
|
|
59
|
+
}
|
|
60
|
+
super(typeof scopeOrMessage === 'string' ? scopeOrMessage : supportMessage);
|
|
55
61
|
this.name = 'SupportError';
|
|
56
62
|
}
|
|
57
63
|
}
|
|
@@ -92,6 +98,7 @@
|
|
|
92
98
|
* @import { ComponentWithModuleName } from '../common/index.mjs'
|
|
93
99
|
*/
|
|
94
100
|
|
|
101
|
+
const _self = typeof globalThis !== 'undefined' ? globalThis : self;
|
|
95
102
|
class Component {
|
|
96
103
|
/**
|
|
97
104
|
* Returns the root element of the component
|
|
@@ -145,7 +152,7 @@
|
|
|
145
152
|
/**
|
|
146
153
|
* @typedef {typeof Component & ChildClass} ChildClassConstructor
|
|
147
154
|
*/
|
|
148
|
-
Component.elementType = HTMLElement;
|
|
155
|
+
Component.elementType = _self.HTMLElement;
|
|
149
156
|
|
|
150
157
|
const configOverride = Symbol.for('configOverride');
|
|
151
158
|
class ConfigurableComponent extends Component {
|
|
@@ -170,10 +177,14 @@
|
|
|
170
177
|
throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
|
|
171
178
|
}
|
|
172
179
|
const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
|
|
173
|
-
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}
|
|
180
|
+
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {});
|
|
181
|
+
this._config = mergeConfigs(this._config, this[configOverride](datasetConfig), datasetConfig);
|
|
174
182
|
}
|
|
175
183
|
}
|
|
176
184
|
function normaliseString(value, property) {
|
|
185
|
+
if (property != null && property.type && !['string', 'number', 'boolean'].includes(property.type)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
177
188
|
const trimmedValue = value ? value.trim() : '';
|
|
178
189
|
let output;
|
|
179
190
|
let outputType = property == null ? void 0 : property.type;
|
|
@@ -23,6 +23,9 @@ function isArray(option) {
|
|
|
23
23
|
function isObject(option) {
|
|
24
24
|
return !!option && typeof option === 'object' && !isArray(option);
|
|
25
25
|
}
|
|
26
|
+
function isScope($scope) {
|
|
27
|
+
return !!$scope && ($scope instanceof Element || $scope instanceof Document);
|
|
28
|
+
}
|
|
26
29
|
function formatErrorMessage(Component, message) {
|
|
27
30
|
return `${Component.moduleName}: ${message}`;
|
|
28
31
|
}
|
|
@@ -41,11 +44,14 @@ class SupportError extends GOVUKFrontendError {
|
|
|
41
44
|
/**
|
|
42
45
|
* Checks if GOV.UK Frontend is supported on this page
|
|
43
46
|
*
|
|
44
|
-
* @param {
|
|
47
|
+
* @param {Element | Document | null | string} [scopeOrMessage] - HTML element `<body>` checked for browser support or support error message
|
|
45
48
|
*/
|
|
46
|
-
constructor(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
constructor(scopeOrMessage = document.body) {
|
|
50
|
+
let supportMessage = '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';
|
|
51
|
+
if (!isScope(scopeOrMessage)) {
|
|
52
|
+
supportMessage = 'GOV.UK Frontend initialised without `<script type="module">`';
|
|
53
|
+
}
|
|
54
|
+
super(typeof scopeOrMessage === 'string' ? scopeOrMessage : supportMessage);
|
|
49
55
|
this.name = 'SupportError';
|
|
50
56
|
}
|
|
51
57
|
}
|
|
@@ -86,6 +92,7 @@ class InitError extends GOVUKFrontendError {
|
|
|
86
92
|
* @import { ComponentWithModuleName } from '../common/index.mjs'
|
|
87
93
|
*/
|
|
88
94
|
|
|
95
|
+
const _self = typeof globalThis !== 'undefined' ? globalThis : self;
|
|
89
96
|
class Component {
|
|
90
97
|
/**
|
|
91
98
|
* Returns the root element of the component
|
|
@@ -139,7 +146,7 @@ class Component {
|
|
|
139
146
|
/**
|
|
140
147
|
* @typedef {typeof Component & ChildClass} ChildClassConstructor
|
|
141
148
|
*/
|
|
142
|
-
Component.elementType = HTMLElement;
|
|
149
|
+
Component.elementType = _self.HTMLElement;
|
|
143
150
|
|
|
144
151
|
const configOverride = Symbol.for('configOverride');
|
|
145
152
|
class ConfigurableComponent extends Component {
|
|
@@ -164,10 +171,14 @@ class ConfigurableComponent extends Component {
|
|
|
164
171
|
throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
|
|
165
172
|
}
|
|
166
173
|
const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
|
|
167
|
-
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}
|
|
174
|
+
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {});
|
|
175
|
+
this._config = mergeConfigs(this._config, this[configOverride](datasetConfig), datasetConfig);
|
|
168
176
|
}
|
|
169
177
|
}
|
|
170
178
|
function normaliseString(value, property) {
|
|
179
|
+
if (property != null && property.type && !['string', 'number', 'boolean'].includes(property.type)) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
171
182
|
const trimmedValue = value ? value.trim() : '';
|
|
172
183
|
let output;
|
|
173
184
|
let outputType = property == null ? void 0 : property.type;
|
data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js
CHANGED
|
@@ -34,6 +34,9 @@
|
|
|
34
34
|
function isObject(option) {
|
|
35
35
|
return !!option && typeof option === 'object' && !isArray(option);
|
|
36
36
|
}
|
|
37
|
+
function isScope($scope) {
|
|
38
|
+
return !!$scope && ($scope instanceof Element || $scope instanceof Document);
|
|
39
|
+
}
|
|
37
40
|
function formatErrorMessage(Component, message) {
|
|
38
41
|
return `${Component.moduleName}: ${message}`;
|
|
39
42
|
}
|
|
@@ -52,11 +55,14 @@
|
|
|
52
55
|
/**
|
|
53
56
|
* Checks if GOV.UK Frontend is supported on this page
|
|
54
57
|
*
|
|
55
|
-
* @param {
|
|
58
|
+
* @param {Element | Document | null | string} [scopeOrMessage] - HTML element `<body>` checked for browser support or support error message
|
|
56
59
|
*/
|
|
57
|
-
constructor(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
constructor(scopeOrMessage = document.body) {
|
|
61
|
+
let supportMessage = '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';
|
|
62
|
+
if (!isScope(scopeOrMessage)) {
|
|
63
|
+
supportMessage = 'GOV.UK Frontend initialised without `<script type="module">`';
|
|
64
|
+
}
|
|
65
|
+
super(typeof scopeOrMessage === 'string' ? scopeOrMessage : supportMessage);
|
|
60
66
|
this.name = 'SupportError';
|
|
61
67
|
}
|
|
62
68
|
}
|
|
@@ -97,6 +103,7 @@
|
|
|
97
103
|
* @import { ComponentWithModuleName } from '../common/index.mjs'
|
|
98
104
|
*/
|
|
99
105
|
|
|
106
|
+
const _self = typeof globalThis !== 'undefined' ? globalThis : self;
|
|
100
107
|
class Component {
|
|
101
108
|
/**
|
|
102
109
|
* Returns the root element of the component
|
|
@@ -150,7 +157,7 @@
|
|
|
150
157
|
/**
|
|
151
158
|
* @typedef {typeof Component & ChildClass} ChildClassConstructor
|
|
152
159
|
*/
|
|
153
|
-
Component.elementType = HTMLElement;
|
|
160
|
+
Component.elementType = _self.HTMLElement;
|
|
154
161
|
|
|
155
162
|
const configOverride = Symbol.for('configOverride');
|
|
156
163
|
class ConfigurableComponent extends Component {
|
|
@@ -175,10 +182,14 @@
|
|
|
175
182
|
throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
|
|
176
183
|
}
|
|
177
184
|
const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
|
|
178
|
-
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}
|
|
185
|
+
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {});
|
|
186
|
+
this._config = mergeConfigs(this._config, this[configOverride](datasetConfig), datasetConfig);
|
|
179
187
|
}
|
|
180
188
|
}
|
|
181
189
|
function normaliseString(value, property) {
|
|
190
|
+
if (property != null && property.type && !['string', 'number', 'boolean'].includes(property.type)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
182
193
|
const trimmedValue = value ? value.trim() : '';
|
|
183
194
|
let output;
|
|
184
195
|
let outputType = property == null ? void 0 : property.type;
|
|
@@ -318,6 +329,17 @@
|
|
|
318
329
|
* @import { CompatibleClass, Config, CreateAllOptions, OnErrorCallback } from '../init.mjs'
|
|
319
330
|
*/
|
|
320
331
|
|
|
332
|
+
function createElement(tagName, attributes = {}, children = []) {
|
|
333
|
+
const $element = document.createElement(tagName);
|
|
334
|
+
Object.entries(attributes).forEach(([name, value]) => {
|
|
335
|
+
$element.setAttribute(name, value);
|
|
336
|
+
});
|
|
337
|
+
for (const child of children) {
|
|
338
|
+
$element.append(child);
|
|
339
|
+
}
|
|
340
|
+
return $element;
|
|
341
|
+
}
|
|
342
|
+
|
|
321
343
|
class I18n {
|
|
322
344
|
constructor(translations = {}, config = {}) {
|
|
323
345
|
var _config$locale;
|
|
@@ -408,6 +430,14 @@
|
|
|
408
430
|
maxwords: undefined
|
|
409
431
|
};
|
|
410
432
|
}
|
|
433
|
+
if ('maxwords' in datasetConfig || this.config.maxwords !== undefined) {
|
|
434
|
+
console.warn(formatErrorMessage(CharacterCount, 'Option `maxwords` is deprecated. Use `maxlength` with `countType: "words"` instead.'));
|
|
435
|
+
if (!('maxlength' in datasetConfig)) {
|
|
436
|
+
var _datasetConfig$maxwor;
|
|
437
|
+
configOverrides.maxlength = (_datasetConfig$maxwor = datasetConfig.maxwords) != null ? _datasetConfig$maxwor : this.config.maxwords;
|
|
438
|
+
configOverrides.countType = 'words';
|
|
439
|
+
}
|
|
440
|
+
}
|
|
411
441
|
return configOverrides;
|
|
412
442
|
}
|
|
413
443
|
|
|
@@ -416,10 +446,11 @@
|
|
|
416
446
|
* @param {CharacterCountConfig} [config] - Character count config
|
|
417
447
|
*/
|
|
418
448
|
constructor($root, config = {}) {
|
|
419
|
-
var
|
|
449
|
+
var _this$config$maxlengt;
|
|
420
450
|
super($root, config);
|
|
421
451
|
this.$textarea = void 0;
|
|
422
452
|
this.count = 0;
|
|
453
|
+
this.segmenter = null;
|
|
423
454
|
this.$visibleCountMessage = void 0;
|
|
424
455
|
this.$screenReaderCountMessage = void 0;
|
|
425
456
|
this.lastInputTimestamp = null;
|
|
@@ -443,7 +474,15 @@
|
|
|
443
474
|
this.i18n = new I18n(this.config.i18n, {
|
|
444
475
|
locale: closestAttributeValue(this.$root, 'lang')
|
|
445
476
|
});
|
|
446
|
-
this.
|
|
477
|
+
if (this.config.countType === 'characters' || this.config.countType === 'words' && this.config.maxwords === undefined) {
|
|
478
|
+
if (!('Segmenter' in Intl)) {
|
|
479
|
+
throw new SupportError(formatErrorMessage(CharacterCount, 'Support for "Intl.Segmenter" required'));
|
|
480
|
+
}
|
|
481
|
+
this.segmenter = new Intl.Segmenter(this.i18n.locale, {
|
|
482
|
+
granularity: this.config.countType === 'words' ? 'word' : 'grapheme'
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
this.maxLength = (_this$config$maxlengt = this.config.maxlength) != null ? _this$config$maxlengt : Infinity;
|
|
447
486
|
this.$textarea = $textarea;
|
|
448
487
|
const textareaDescriptionId = `${this.$textarea.id}-info`;
|
|
449
488
|
const $textareaDescription = document.getElementById(textareaDescriptionId);
|
|
@@ -461,15 +500,16 @@
|
|
|
461
500
|
});
|
|
462
501
|
}
|
|
463
502
|
this.$textarea.insertAdjacentElement('afterend', $textareaDescription);
|
|
464
|
-
const $screenReaderCountMessage =
|
|
465
|
-
|
|
466
|
-
|
|
503
|
+
const $screenReaderCountMessage = createElement('div', {
|
|
504
|
+
class: 'govuk-character-count__sr-status govuk-visually-hidden',
|
|
505
|
+
'aria-live': 'polite'
|
|
506
|
+
});
|
|
467
507
|
this.$screenReaderCountMessage = $screenReaderCountMessage;
|
|
468
508
|
$textareaDescription.insertAdjacentElement('afterend', $screenReaderCountMessage);
|
|
469
|
-
const $visibleCountMessage =
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
509
|
+
const $visibleCountMessage = createElement('div', {
|
|
510
|
+
class: `${$textareaDescription.className} govuk-character-count__status`,
|
|
511
|
+
'aria-hidden': 'true'
|
|
512
|
+
});
|
|
473
513
|
this.$visibleCountMessage = $visibleCountMessage;
|
|
474
514
|
$textareaDescription.insertAdjacentElement('afterend', $visibleCountMessage);
|
|
475
515
|
$textareaDescription.classList.add('govuk-visually-hidden');
|
|
@@ -537,26 +577,38 @@
|
|
|
537
577
|
}
|
|
538
578
|
updateCount() {
|
|
539
579
|
const text = this.$textarea.value;
|
|
540
|
-
if (this.config.
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
580
|
+
if (this.config.countType === 'characters') {
|
|
581
|
+
this.count = this.segmenter ? Array.from(this.segmenter.segment(text)).length : 0;
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
if (this.config.countType === 'words') {
|
|
585
|
+
if (this.config.maxwords !== undefined) {
|
|
586
|
+
var _text$match$length, _text$match;
|
|
587
|
+
this.count = (_text$match$length = (_text$match = text.match(/\S+/g)) == null ? void 0 : _text$match.length) != null ? _text$match$length : 0;
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
const segments = this.segmenter ? Array.from(this.segmenter.segment(text)) : [];
|
|
591
|
+
this.count = segments.filter(segment => segment.isWordLike).length;
|
|
544
592
|
return;
|
|
545
593
|
}
|
|
546
594
|
this.count = text.length;
|
|
547
595
|
}
|
|
548
596
|
getCountMessage() {
|
|
549
597
|
const remainingNumber = this.maxLength - this.count;
|
|
550
|
-
|
|
551
|
-
return this.formatCountMessage(remainingNumber, countType);
|
|
598
|
+
return this.formatCountMessage(remainingNumber);
|
|
552
599
|
}
|
|
553
600
|
formatCountMessage(remainingNumber, countType) {
|
|
601
|
+
countType = countType != null ? countType : this.config.countType;
|
|
602
|
+
let translationKeyPrefix = 'characters';
|
|
603
|
+
let translationKeySuffix = remainingNumber < 0 ? 'OverLimit' : 'UnderLimit';
|
|
604
|
+
if (countType === 'words') {
|
|
605
|
+
translationKeyPrefix = 'words';
|
|
606
|
+
}
|
|
554
607
|
if (remainingNumber === 0) {
|
|
555
|
-
|
|
608
|
+
translationKeySuffix = 'AtLimit';
|
|
556
609
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
count: Math.abs(remainingNumber)
|
|
610
|
+
return this.i18n.t(`${translationKeyPrefix}${translationKeySuffix}`, {
|
|
611
|
+
count: remainingNumber === 0 ? undefined : Math.abs(remainingNumber)
|
|
560
612
|
});
|
|
561
613
|
}
|
|
562
614
|
isOverThreshold() {
|
|
@@ -575,13 +627,15 @@
|
|
|
575
627
|
*
|
|
576
628
|
* @see {@link CharacterCount.defaults}
|
|
577
629
|
* @typedef {object} CharacterCountConfig
|
|
578
|
-
* @property {number} [maxlength] - The maximum number of characters
|
|
579
|
-
*
|
|
580
|
-
* @property {number} [maxwords] -
|
|
581
|
-
*
|
|
630
|
+
* @property {number} [maxlength] - The maximum number of characters (or words
|
|
631
|
+
* if `countType` is set to `"words"`).
|
|
632
|
+
* @property {number} [maxwords] - Deprecated. Use `maxlength` and
|
|
633
|
+
* `countType: "words"` instead.
|
|
582
634
|
* @property {number} [threshold=0] - The percentage value of the limit at
|
|
583
635
|
* which point the count message is displayed. If this attribute is set, the
|
|
584
636
|
* count message will be hidden by default.
|
|
637
|
+
* @property {'characters' | 'length' | 'words'} [countType] - The count type
|
|
638
|
+
* (`"characters"`, `"length"` or `"words"`) used to count the text.
|
|
585
639
|
* @property {CharacterCountTranslations} [i18n=CharacterCount.defaults.i18n] - Character count translations
|
|
586
640
|
*/
|
|
587
641
|
|
|
@@ -627,9 +681,9 @@
|
|
|
627
681
|
* @property {TranslationPluralForms} [textareaDescription] - Message made
|
|
628
682
|
* available to assistive technologies, if none is already present in the
|
|
629
683
|
* HTML, to describe that the component accepts only a limited amount of
|
|
630
|
-
* content. It is visible on the page
|
|
631
|
-
* component will replace the `%{count}`
|
|
632
|
-
*
|
|
684
|
+
* content. It is visible on the page if `countType` is not supported or
|
|
685
|
+
* JavaScript is unavailable. The component will replace the `%{count}`
|
|
686
|
+
* placeholder with the value of the `maxlength` parameter.
|
|
633
687
|
*/
|
|
634
688
|
|
|
635
689
|
/**
|
|
@@ -639,6 +693,7 @@
|
|
|
639
693
|
CharacterCount.moduleName = 'govuk-character-count';
|
|
640
694
|
CharacterCount.defaults = Object.freeze({
|
|
641
695
|
threshold: 0,
|
|
696
|
+
countType: 'length',
|
|
642
697
|
i18n: {
|
|
643
698
|
charactersUnderLimit: {
|
|
644
699
|
one: 'You have %{count} character remaining',
|
|
@@ -676,6 +731,9 @@
|
|
|
676
731
|
},
|
|
677
732
|
threshold: {
|
|
678
733
|
type: 'number'
|
|
734
|
+
},
|
|
735
|
+
countType: {
|
|
736
|
+
type: 'string'
|
|
679
737
|
}
|
|
680
738
|
},
|
|
681
739
|
anyOf: [{
|