@govuk-one-login/frontend-ui 3.0.0 → 3.1.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.
- package/build/cjs/backend/index.cjs +4 -2
- package/build/cjs/backend/index.d.cts +2 -0
- package/build/cjs/backend/index.d.ts +2 -0
- package/build/cjs/backend/index.d.ts.map +1 -1
- package/build/cjs/frontend/index.cjs +64 -1
- package/build/cjs/frontend/index.d.cts +1 -0
- package/build/cjs/frontend/index.d.ts +1 -0
- package/build/cjs/frontend/index.d.ts.map +1 -1
- package/build/cjs/frontend/progress-button/progress-button.d.ts +2 -0
- package/build/cjs/frontend/progress-button/progress-button.d.ts.map +1 -0
- package/build/cjs/frontend/spinner/spinner.d.ts +5 -1
- package/build/cjs/frontend/spinner/spinner.d.ts.map +1 -1
- package/build/components/progress-button/template.njk +73 -78
- package/build/components/spinner/README.md +5 -0
- package/build/esm/backend/index.d.ts +2 -0
- package/build/esm/backend/index.d.ts.map +1 -1
- package/build/esm/backend/index.js +4 -2
- package/build/esm/frontend/index.d.ts +1 -0
- package/build/esm/frontend/index.d.ts.map +1 -1
- package/build/esm/frontend/index.js +64 -2
- package/build/esm/frontend/progress-button/progress-button.d.ts +2 -0
- package/build/esm/frontend/progress-button/progress-button.d.ts.map +1 -0
- package/build/esm/frontend/spinner/spinner.d.ts +5 -1
- package/build/esm/frontend/spinner/spinner.d.ts.map +1 -1
- package/package.json +3 -2
|
@@ -76,7 +76,8 @@ var skipLink$1 = {
|
|
|
76
76
|
var progressButton$1 = {
|
|
77
77
|
text: "Parhau",
|
|
78
78
|
waitingText: "Aros",
|
|
79
|
-
longWaitingText: "Parhau i aros"
|
|
79
|
+
longWaitingText: "Parhau i aros",
|
|
80
|
+
noJavascriptMessage: "Gall gymryd hyd at 10 eiliad i barhau i'r dudalen nesaf. Ar ôl i chi barhau, peidiwch ag ail-lwytho na chau'r dudalen hon."
|
|
80
81
|
};
|
|
81
82
|
var translationCy = {
|
|
82
83
|
cookieBanner: cookieBanner$1,
|
|
@@ -161,7 +162,8 @@ var skipLink = {
|
|
|
161
162
|
var progressButton = {
|
|
162
163
|
text: "Continue",
|
|
163
164
|
waitingText: "Wait",
|
|
164
|
-
longWaitingText: "Keep waiting"
|
|
165
|
+
longWaitingText: "Keep waiting",
|
|
166
|
+
noJavascriptMessage: "It can take up to 10 seconds to continue to the next page. After you continue, do not reload or close this page."
|
|
165
167
|
};
|
|
166
168
|
var translationEn = {
|
|
167
169
|
cookieBanner: cookieBanner,
|
|
@@ -95,6 +95,7 @@ export declare const frontendUiTranslationEn: {
|
|
|
95
95
|
text: string;
|
|
96
96
|
waitingText: string;
|
|
97
97
|
longWaitingText: string;
|
|
98
|
+
noJavascriptMessage: string;
|
|
98
99
|
};
|
|
99
100
|
};
|
|
100
101
|
export declare const frontendUiTranslationCy: {
|
|
@@ -158,6 +159,7 @@ export declare const frontendUiTranslationCy: {
|
|
|
158
159
|
text: string;
|
|
159
160
|
waitingText: string;
|
|
160
161
|
longWaitingText: string;
|
|
162
|
+
noJavascriptMessage: string;
|
|
161
163
|
};
|
|
162
164
|
};
|
|
163
165
|
export {};
|
|
@@ -95,6 +95,7 @@ export declare const frontendUiTranslationEn: {
|
|
|
95
95
|
text: string;
|
|
96
96
|
waitingText: string;
|
|
97
97
|
longWaitingText: string;
|
|
98
|
+
noJavascriptMessage: string;
|
|
98
99
|
};
|
|
99
100
|
};
|
|
100
101
|
export declare const frontendUiTranslationCy: {
|
|
@@ -158,6 +159,7 @@ export declare const frontendUiTranslationCy: {
|
|
|
158
159
|
text: string;
|
|
159
160
|
waitingText: string;
|
|
160
161
|
longWaitingText: string;
|
|
162
|
+
noJavascriptMessage: string;
|
|
161
163
|
};
|
|
162
164
|
};
|
|
163
165
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQ1D,UAAU,QAAQ;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,IAAI,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC;KAClC,CAAC;CACH;AAED,UAAU,cAAe,SAAQ,OAAO;IACtC,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,eAAgB,SAAQ,QAAQ;IACxC,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAGD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAER,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAaR,eAAO,MAAM,yBAAyB,GAAI,cAAc,OAAO,OAAO,SAerE,CAAC;AAGF,eAAO,MAAM,kCAAkC,GAC7C,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,MAAM,YAAY,SAUnB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,UAU3D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAkBhE;AAED,eAAO,MAAM,mBAAmB,GAC9B,cAAc,OAAO,OAAO,EAC5B,WAAW,MAAM,SASlB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAuBxB,CAAC;AAEF,eAAO,MAAM,uBAAuB
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQ1D,UAAU,QAAQ;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,IAAI,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC;KAClC,CAAC;CACH;AAED,UAAU,cAAe,SAAQ,OAAO;IACtC,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,eAAgB,SAAQ,QAAQ;IACxC,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAGD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAER,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAaR,eAAO,MAAM,yBAAyB,GAAI,cAAc,OAAO,OAAO,SAerE,CAAC;AAGF,eAAO,MAAM,kCAAkC,GAC7C,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,MAAM,YAAY,SAUnB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,UAU3D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAkBhE;AAED,eAAO,MAAM,mBAAmB,GAC9B,cAAc,OAAO,OAAO,EAC5B,WAAW,MAAM,SASlB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAuBxB,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAgB,CAAC;AACrD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAgB,CAAC"}
|
|
@@ -24,6 +24,7 @@ exports.PollResult = void 0;
|
|
|
24
24
|
PollResult[PollResult["Success"] = 0] = "Success";
|
|
25
25
|
PollResult[PollResult["Failure"] = 1] = "Failure";
|
|
26
26
|
PollResult[PollResult["Pending"] = 2] = "Pending";
|
|
27
|
+
PollResult[PollResult["Backoff"] = 3] = "Backoff";
|
|
27
28
|
})(exports.PollResult || (exports.PollResult = {}));
|
|
28
29
|
var SpinnerState;
|
|
29
30
|
(function (SpinnerState) {
|
|
@@ -35,6 +36,7 @@ var SpinnerState;
|
|
|
35
36
|
class Spinner {
|
|
36
37
|
constructor(domContainer, pollingFunction, onSuccess, onError) {
|
|
37
38
|
this.state = SpinnerState.Waiting;
|
|
39
|
+
this.backOffCount = 0;
|
|
38
40
|
this.handleAbort = () => {
|
|
39
41
|
this.abortController.abort();
|
|
40
42
|
};
|
|
@@ -172,6 +174,9 @@ class Spinner {
|
|
|
172
174
|
hideSpinnerOnError: element.dataset.hideSpinnerOnError
|
|
173
175
|
? (element.dataset.hideSpinnerOnError === 'true')
|
|
174
176
|
: false,
|
|
177
|
+
maxBackoffTries: element.dataset.maxBackoffTries
|
|
178
|
+
? parseInt(element.dataset.maxBackoffTries)
|
|
179
|
+
: 3,
|
|
175
180
|
};
|
|
176
181
|
}
|
|
177
182
|
createAbortController() {
|
|
@@ -230,12 +235,24 @@ class Spinner {
|
|
|
230
235
|
this.reflectError();
|
|
231
236
|
}
|
|
232
237
|
else if (!this.hasCompleted()) {
|
|
238
|
+
let timeToNextPoll = this.config.msBetweenRequests;
|
|
239
|
+
if (response === exports.PollResult.Backoff) {
|
|
240
|
+
this.backOffCount++;
|
|
241
|
+
if (this.backOffCount > this.config.maxBackoffTries) {
|
|
242
|
+
this.reflectError();
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
timeToNextPoll = this.calculateBackoffTime(this.backOffCount);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
this.backOffCount = 0;
|
|
249
|
+
}
|
|
233
250
|
setTimeout(async () => {
|
|
234
251
|
if (Date.now() - initTime >= this.config.msBeforeAbort) {
|
|
235
252
|
return;
|
|
236
253
|
}
|
|
237
254
|
await this.callPollingFunction(initTime);
|
|
238
|
-
},
|
|
255
|
+
}, timeToNextPoll);
|
|
239
256
|
}
|
|
240
257
|
})
|
|
241
258
|
.catch((error) => {
|
|
@@ -248,6 +265,10 @@ class Spinner {
|
|
|
248
265
|
this.updateDom();
|
|
249
266
|
});
|
|
250
267
|
}
|
|
268
|
+
calculateBackoffTime(backOffCount) {
|
|
269
|
+
const extraDelay = Math.pow(2, backOffCount - 2) * this.config.msBetweenRequests;
|
|
270
|
+
return this.config.msBetweenRequests + extraDelay;
|
|
271
|
+
}
|
|
251
272
|
createAriaLiveContainer() {
|
|
252
273
|
// For the Aria alert to work reliably we need to create its container once and then update the contents
|
|
253
274
|
// https://tetralogical.com/blog/2024/05/01/why-are-my-live-regions-not-working/
|
|
@@ -268,4 +289,46 @@ class Spinner {
|
|
|
268
289
|
}
|
|
269
290
|
}
|
|
270
291
|
|
|
292
|
+
function initialiseProgressButtons() {
|
|
293
|
+
const progressButtons = document.querySelectorAll('[data-frontendui="di-progress-button"]');
|
|
294
|
+
progressButtons.forEach((button) => {
|
|
295
|
+
button.addEventListener('click', (event) => {
|
|
296
|
+
const waitingText = button.getAttribute('data-waiting-text');
|
|
297
|
+
const longWaitingText = button.getAttribute('data-long-waiting-text');
|
|
298
|
+
const errorPage = button.getAttribute('data-error-page');
|
|
299
|
+
const isInput = button.tagName.toLowerCase() === 'input';
|
|
300
|
+
if (!waitingText || !longWaitingText || !errorPage) {
|
|
301
|
+
console.error('Progress button is missing required data attributes.');
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
handleProgressButtonClick(button, waitingText, longWaitingText, errorPage, isInput);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
const handleProgressButtonClick = (element, waitingText, longWaitingText, errorPage, isInput = false) => {
|
|
309
|
+
element.blur();
|
|
310
|
+
element.setAttribute('data-prevent-double-click', 'true');
|
|
311
|
+
element.classList.add('govuk-button--progress-loading');
|
|
312
|
+
if (isInput && element instanceof HTMLInputElement) {
|
|
313
|
+
element.value = waitingText;
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
element.innerText = waitingText;
|
|
317
|
+
}
|
|
318
|
+
element.setAttribute('aria-label', waitingText);
|
|
319
|
+
setTimeout(() => {
|
|
320
|
+
if (isInput && element instanceof HTMLInputElement) {
|
|
321
|
+
element.value = longWaitingText;
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
element.innerText = longWaitingText;
|
|
325
|
+
}
|
|
326
|
+
element.setAttribute('aria-label', longWaitingText);
|
|
327
|
+
}, 5000);
|
|
328
|
+
setTimeout(() => {
|
|
329
|
+
window.location.href = errorPage;
|
|
330
|
+
}, 10000);
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
exports.initialiseProgressButtons = initialiseProgressButtons;
|
|
271
334
|
exports.useSpinner = useSpinner;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../frontend-src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../frontend-src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress-button.d.ts","sourceRoot":"","sources":["../../../../frontend-src/progress-button/progress-button.ts"],"names":[],"mappings":"AAAA,wBAAgB,yBAAyB,SAgBxC"}
|
|
@@ -3,7 +3,8 @@ export type PollingFunction = (abortSignal: AbortSignal) => Promise<PollResult>;
|
|
|
3
3
|
export declare enum PollResult {
|
|
4
4
|
Success = 0,
|
|
5
5
|
Failure = 1,
|
|
6
|
-
Pending = 2
|
|
6
|
+
Pending = 2,
|
|
7
|
+
Backoff = 3
|
|
7
8
|
}
|
|
8
9
|
declare enum SpinnerState {
|
|
9
10
|
Waiting = 0,
|
|
@@ -18,6 +19,7 @@ type SpinnerConfig = {
|
|
|
18
19
|
msBetweenDomUpdate: number;
|
|
19
20
|
ariaAlertCompletionText?: string;
|
|
20
21
|
hideSpinnerOnError: boolean;
|
|
22
|
+
maxBackoffTries: number;
|
|
21
23
|
};
|
|
22
24
|
export declare class Spinner {
|
|
23
25
|
container: HTMLDivElement;
|
|
@@ -33,6 +35,7 @@ export declare class Spinner {
|
|
|
33
35
|
updateDomTimer?: NodeJS.Timeout;
|
|
34
36
|
abortController: AbortController;
|
|
35
37
|
config: SpinnerConfig;
|
|
38
|
+
backOffCount: number;
|
|
36
39
|
pollingFunction: PollingFunction;
|
|
37
40
|
onSuccess: VoidFunction;
|
|
38
41
|
onError: VoidFunction;
|
|
@@ -53,6 +56,7 @@ export declare class Spinner {
|
|
|
53
56
|
private updateDom;
|
|
54
57
|
private cloneAndAddIfExists;
|
|
55
58
|
private callPollingFunction;
|
|
59
|
+
private calculateBackoffTime;
|
|
56
60
|
private createAriaLiveContainer;
|
|
57
61
|
private updateAriaAlert;
|
|
58
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../../frontend-src/spinner/spinner.ts"],"names":[],"mappings":"AAAA,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,iBAoBjJ;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAEhF,oBAAY,UAAU;IACpB,OAAO,IAAA;IACP,OAAO,IAAA;IACP,OAAO,IAAA;CACR;AAED,aAAK,YAAY;IACf,OAAO,IAAA;IACP,WAAW,IAAA;IACX,KAAK,IAAA;IACL,QAAQ,IAAA;CACT;AAED,KAAK,aAAa,GAAG;IACnB,2BAA2B,EAAE,MAAM,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../../frontend-src/spinner/spinner.ts"],"names":[],"mappings":"AAAA,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,iBAoBjJ;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAEhF,oBAAY,UAAU;IACpB,OAAO,IAAA;IACP,OAAO,IAAA;IACP,OAAO,IAAA;IACP,OAAO,IAAA;CACR;AAED,aAAK,YAAY;IACf,OAAO,IAAA;IACP,WAAW,IAAA;IACX,KAAK,IAAA;IACL,QAAQ,IAAA;CACT;AAED,KAAK,aAAa,GAAG;IACnB,2BAA2B,EAAE,MAAM,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,qBAAa,OAAO;IAClB,SAAS,EAAE,cAAc,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,eAAe,CAAC,EAAE,WAAW,CAAC;IAC9B,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,iBAAiB,EAAE,cAAc,CAAC;IAElC,wBAAwB,EAAE,cAAc,CAAC;IAEzC,KAAK,EAAE,YAAY,CAAwB;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAChC,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,EAAE,MAAM,CAAK;IAEzB,eAAe,EAAE,eAAe,CAAC;IACjC,SAAS,EAAE,YAAY,CAAC;IACxB,OAAO,EAAE,YAAY,CAAC;gBAGpB,YAAY,EAAE,cAAc,EAC5B,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,YAAY,EACvB,OAAO,EAAE,YAAY;IA2CjB,IAAI;IAUV,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,SAAS;IA0BjB,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,WAAW,CAEjB;IAEF,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,SAAS,CAKf;IAEF,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc,CAGpB;IAEF,OAAO,CAAC,YAAY,CAIlB;IAEF,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,iCAAiC,CAWvC;IAEF,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,SAAS,CAkDf;IAEF,OAAO,CAAC,mBAAmB;YASb,mBAAmB;IA2CjC,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,eAAe;CAWxB"}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
{% set progressButton = params.translations %}
|
|
2
|
-
|
|
2
|
+
<noscript>
|
|
3
|
+
<style>
|
|
4
|
+
.noscript {
|
|
5
|
+
border: #F3F3F3 3px solid;
|
|
6
|
+
padding-top: 28px;
|
|
7
|
+
padding-left: 12px;
|
|
8
|
+
padding-right: 12px;
|
|
9
|
+
margin-bottom: 12px;
|
|
10
|
+
}
|
|
11
|
+
</style>
|
|
12
|
+
</noscript>
|
|
3
13
|
|
|
4
14
|
{# Set classes for this component #}
|
|
5
15
|
{%- set classNames = "govuk-button govuk-button--progress" -%}
|
|
@@ -23,98 +33,83 @@
|
|
|
23
33
|
|
|
24
34
|
{% if params.isStartButton %}
|
|
25
35
|
{% set iconHtml %}
|
|
26
|
-
{#- The SVG needs `focusable="false"` so that Internet Explorer does not
|
|
36
|
+
{#- The SVG needs `focusable="false"` so that Internet Explorer does not
|
|
27
37
|
treat it as an interactive element - without this it will be
|
|
28
38
|
'focusable' when using the keyboard to navigate. #}
|
|
29
|
-
<svg class="govuk-button__start-icon" xmlns="http://www.w3.org/2000/svg" width="17.5" height="19" viewBox="0 0 33 40" aria-hidden="true" focusable="false">
|
|
30
|
-
|
|
31
|
-
</svg>
|
|
39
|
+
<svg class="govuk-button__start-icon" xmlns="http://www.w3.org/2000/svg" width="17.5" height="19" viewBox="0 0 33 40" aria-hidden="true" focusable="false">
|
|
40
|
+
<path fill="currentColor" d="M0 0h13l20 20-20 20H0l20-20z"/>
|
|
41
|
+
</svg>
|
|
32
42
|
{% endset %}
|
|
33
43
|
{% set classNames = classNames + " govuk-button--start" %}
|
|
34
44
|
{% endif %}
|
|
35
45
|
|
|
36
46
|
{#- Define common attributes that we can use across all element types #}
|
|
37
47
|
|
|
38
|
-
{%- set commonAttributes %}
|
|
48
|
+
{%- set commonAttributes %} data-module="govuk-button"{% for attribute, value in params.attributes %}
|
|
49
|
+
{{attribute}}="{{value}}"{% endfor %}
|
|
50
|
+
{% if params.id %} id="{{ params.id }}"{% endif %}
|
|
51
|
+
{% endset %}
|
|
39
52
|
|
|
40
53
|
{#- Define common attributes we can use for both button and input types #}
|
|
41
54
|
|
|
42
|
-
{%- set buttonAttributes %}
|
|
43
|
-
|
|
55
|
+
{%- set buttonAttributes %}
|
|
56
|
+
{% if params.name %} name="{{ params.name }}"{% endif %}
|
|
57
|
+
{% if params.disabled %} disabled="disabled" aria-disabled="true"{% endif %}
|
|
58
|
+
{% if params.preventDoubleClick !== undefined %} data-prevent-double-click="{{params.preventDoubleClick}}"{% endif %}{% endset %}
|
|
44
59
|
|
|
45
60
|
{%- if element == 'a' %}
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{{ params.text | safe }}
|
|
66
|
-
{% else %}
|
|
67
|
-
{{ progressButton.text }}
|
|
68
|
-
{% endif %}
|
|
69
|
-
{{- iconHtml | safe | trim | indent(2, true) if iconHtml -}}
|
|
70
|
-
</a>
|
|
61
|
+
<div class="noscript">
|
|
62
|
+
<noscript>
|
|
63
|
+
<div class="govuk-body" >
|
|
64
|
+
{{ progressButton.noJavascriptMessage }}
|
|
65
|
+
</div>
|
|
66
|
+
</noscript>
|
|
67
|
+
|
|
68
|
+
<a href="{{ params.href if params.href else '#' }}" role="button" draggable="false" {{- commonAttributes | safe }} class = "{{ classNames }}"
|
|
69
|
+
aria-live="assertive" data-frontendui="di-progress-button" data-waiting-text="{{ progressButton.waitingText }}" data-long-waiting-text="{{ progressButton.longWaitingText }}" data-error-page="{{ params.errorPage | default('#') }}" >
|
|
70
|
+
{% if params.html %}
|
|
71
|
+
{{ params.html | safe }}
|
|
72
|
+
{% elseif params.text %}
|
|
73
|
+
{{ params.text | safe }}
|
|
74
|
+
{% else %}
|
|
75
|
+
{{ progressButton.text }}
|
|
76
|
+
{% endif %}
|
|
77
|
+
{{- iconHtml | safe | trim | indent(2, true) if iconHtml -}}
|
|
78
|
+
</a>
|
|
79
|
+
</div>
|
|
71
80
|
|
|
72
81
|
{%- elseif element == 'button' %}
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
{{ params.html | safe }}
|
|
91
|
-
{% elseif params.text %}
|
|
92
|
-
{{ params.text | safe }}
|
|
93
|
-
{% else %}
|
|
94
|
-
{{ progressButton.text }}
|
|
95
|
-
{% endif %}
|
|
96
|
-
{{- iconHtml | safe | trim | indent(2, true) if iconHtml -}}
|
|
82
|
+
<div class="noscript">
|
|
83
|
+
<noscript>
|
|
84
|
+
<div class="govuk-body" >
|
|
85
|
+
{{ progressButton.noJavascriptMessage }}
|
|
86
|
+
</div>
|
|
87
|
+
</noscript>
|
|
88
|
+
|
|
89
|
+
<button {%- if params.value %} value="{{ params.value }}"{% endif %}{%- if params.type %} type="{{ params.type }}"{% endif %} {{- buttonAttributes | safe }} {{- commonAttributes | safe }} class = "{{ classNames }}"
|
|
90
|
+
aria-live="assertive" data-frontendui="di-progress-button" data-waiting-text="{{ progressButton.waitingText }}" data-long-waiting-text="{{ progressButton.longWaitingText }}" data-error-page="{{ params.errorPage | default('#') }}" >
|
|
91
|
+
{% if params.html %}
|
|
92
|
+
{{ params.html | safe }}
|
|
93
|
+
{% elseif params.text %}
|
|
94
|
+
{{ params.text | safe }}
|
|
95
|
+
{% else %}
|
|
96
|
+
{{ progressButton.text }}
|
|
97
|
+
{% endif %}
|
|
98
|
+
{{- iconHtml | safe | trim | indent(2, true) if iconHtml -}}
|
|
97
99
|
|
|
98
|
-
</button>
|
|
100
|
+
</button>
|
|
101
|
+
</div>
|
|
99
102
|
|
|
100
103
|
{%- elseif element == 'input' %}
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
setTimeout(() => {
|
|
114
|
-
window.location.href = '{{ params.errorPage | default('#') }}';
|
|
115
|
-
}, 10000);
|
|
116
|
-
return false;
|
|
117
|
-
"
|
|
118
|
-
>
|
|
119
|
-
{{- iconHtml | safe | trim | indent(2, true) if iconHtml -}}
|
|
120
|
-
{% endif %}
|
|
104
|
+
<div class="noscript">
|
|
105
|
+
<noscript>
|
|
106
|
+
<div class="govuk-body" >
|
|
107
|
+
{{ progressButton.noJavascriptMessage }}
|
|
108
|
+
</div>
|
|
109
|
+
</noscript>
|
|
110
|
+
<input value="{{ params.value }}" type="{{ params.type if params.type else 'submit'}}"{{- buttonAttributes | safe }} {{- commonAttributes | safe }} class = "{{ classNames }}"
|
|
111
|
+
aria-live="assertive" data-frontendui="di-progress-button" data-waiting-text="{{ progressButton.waitingText }}" data-long-waiting-text="{{ progressButton.longWaitingText }}" data-error-page="{{ params.errorPage | default('#') }}" >
|
|
112
|
+
{{- iconHtml | safe | trim | indent(2, true) if iconHtml -}}
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
{% endif %}
|
|
@@ -25,6 +25,7 @@ For the spinner to perform correctly it requires the following:
|
|
|
25
25
|
- An optional data attribute `data-ms-between-dom-update` to set the amount of time between updates to the spinner UI
|
|
26
26
|
- An optional data attribute `data-ms-between-requests` to set the amount of time between calls to the `pollingFunction`
|
|
27
27
|
- An optional data attribute `data-hide-spinner-on-error` to hide the spinner graphic on error (defaults to false)
|
|
28
|
+
- An optional data attribute `data-max-backoff-tries` to set the number of times in a row the polling function can return `backoff` before the error content is displayed (defaults to 3)
|
|
28
29
|
- An optional data attribute `aria-alert-completion-text`. If supplied this text will be set as an aria alert if the spinner completes successfully
|
|
29
30
|
|
|
30
31
|
For example:
|
|
@@ -36,6 +37,7 @@ For example:
|
|
|
36
37
|
data-ms-between-dom-update="1000"
|
|
37
38
|
data-ms-between-requests="2000"
|
|
38
39
|
data-hide-spinner-on-error="true"
|
|
40
|
+
data-max-backoff-tries="3"
|
|
39
41
|
data-aria-alert-completion-text="Task completed successfully, you may now continue">
|
|
40
42
|
<div id="no-js-content"><p class="centre govuk-body">JS is disabled</p></div>
|
|
41
43
|
<div id="wait-content" style="display:none"><p class="centre govuk-body">Waiting</p></div>
|
|
@@ -70,6 +72,9 @@ If a call to the polling function returns `success` the spinner will stop animat
|
|
|
70
72
|
If a call to the polling function returns `failure` the spinner will stop animating, display the `error-content` content, and call the `errorFunction` (if specified)
|
|
71
73
|
If the spinner waits past the `long-wait` duration while the polling function keeps returning `pending` the spinner will display the `long-wait-content` content
|
|
72
74
|
If the spinner waits past the `abort` duration while the polling function keeps returning `pending` the spinner will stop animating, display the `error-content` content, and call the `errorFunction` (if specified)
|
|
75
|
+
The polling function can optionally return `backoff` if it should be tried again but after a delay (e.g. to account for network instability). On receiving `backoff` the spinner will exponentially increase the time before the
|
|
76
|
+
next call to the polling function. If the polling function returns `backoff` more times than the `max-backoff-tries` value in a row then the final call is treated as if had returned `failure` instead. If a call to the polling
|
|
77
|
+
function returns `pending` then the backoff counter resets.
|
|
73
78
|
|
|
74
79
|
### Page refreshes
|
|
75
80
|
|
|
@@ -95,6 +95,7 @@ export declare const frontendUiTranslationEn: {
|
|
|
95
95
|
text: string;
|
|
96
96
|
waitingText: string;
|
|
97
97
|
longWaitingText: string;
|
|
98
|
+
noJavascriptMessage: string;
|
|
98
99
|
};
|
|
99
100
|
};
|
|
100
101
|
export declare const frontendUiTranslationCy: {
|
|
@@ -158,6 +159,7 @@ export declare const frontendUiTranslationCy: {
|
|
|
158
159
|
text: string;
|
|
159
160
|
waitingText: string;
|
|
160
161
|
longWaitingText: string;
|
|
162
|
+
noJavascriptMessage: string;
|
|
161
163
|
};
|
|
162
164
|
};
|
|
163
165
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQ1D,UAAU,QAAQ;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,IAAI,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC;KAClC,CAAC;CACH;AAED,UAAU,cAAe,SAAQ,OAAO;IACtC,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,eAAgB,SAAQ,QAAQ;IACxC,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAGD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAER,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAaR,eAAO,MAAM,yBAAyB,GAAI,cAAc,OAAO,OAAO,SAerE,CAAC;AAGF,eAAO,MAAM,kCAAkC,GAC7C,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,MAAM,YAAY,SAUnB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,UAU3D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAkBhE;AAED,eAAO,MAAM,mBAAmB,GAC9B,cAAc,OAAO,OAAO,EAC5B,WAAW,MAAM,SASlB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAuBxB,CAAC;AAEF,eAAO,MAAM,uBAAuB
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQ1D,UAAU,QAAQ;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,IAAI,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC;KAClC,CAAC;CACH;AAED,UAAU,cAAe,SAAQ,OAAO;IACtC,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,eAAgB,SAAQ,QAAQ;IACxC,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,MAAM,EAAE;QACN,YAAY,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAGD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAER,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,YAAY,GACjB,IAAI,CAAC;AAaR,eAAO,MAAM,yBAAyB,GAAI,cAAc,OAAO,OAAO,SAerE,CAAC;AAGF,eAAO,MAAM,kCAAkC,GAC7C,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,MAAM,YAAY,SAUnB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,UAU3D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAkBhE;AAED,eAAO,MAAM,mBAAmB,GAC9B,cAAc,OAAO,OAAO,EAC5B,WAAW,MAAM,SASlB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAuBxB,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAgB,CAAC;AACrD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAgB,CAAC"}
|
|
@@ -74,7 +74,8 @@ var skipLink$1 = {
|
|
|
74
74
|
var progressButton$1 = {
|
|
75
75
|
text: "Parhau",
|
|
76
76
|
waitingText: "Aros",
|
|
77
|
-
longWaitingText: "Parhau i aros"
|
|
77
|
+
longWaitingText: "Parhau i aros",
|
|
78
|
+
noJavascriptMessage: "Gall gymryd hyd at 10 eiliad i barhau i'r dudalen nesaf. Ar ôl i chi barhau, peidiwch ag ail-lwytho na chau'r dudalen hon."
|
|
78
79
|
};
|
|
79
80
|
var translationCy = {
|
|
80
81
|
cookieBanner: cookieBanner$1,
|
|
@@ -159,7 +160,8 @@ var skipLink = {
|
|
|
159
160
|
var progressButton = {
|
|
160
161
|
text: "Continue",
|
|
161
162
|
waitingText: "Wait",
|
|
162
|
-
longWaitingText: "Keep waiting"
|
|
163
|
+
longWaitingText: "Keep waiting",
|
|
164
|
+
noJavascriptMessage: "It can take up to 10 seconds to continue to the next page. After you continue, do not reload or close this page."
|
|
163
165
|
};
|
|
164
166
|
var translationEn = {
|
|
165
167
|
cookieBanner: cookieBanner,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../frontend-src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../frontend-src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC"}
|
|
@@ -22,6 +22,7 @@ var PollResult;
|
|
|
22
22
|
PollResult[PollResult["Success"] = 0] = "Success";
|
|
23
23
|
PollResult[PollResult["Failure"] = 1] = "Failure";
|
|
24
24
|
PollResult[PollResult["Pending"] = 2] = "Pending";
|
|
25
|
+
PollResult[PollResult["Backoff"] = 3] = "Backoff";
|
|
25
26
|
})(PollResult || (PollResult = {}));
|
|
26
27
|
var SpinnerState;
|
|
27
28
|
(function (SpinnerState) {
|
|
@@ -33,6 +34,7 @@ var SpinnerState;
|
|
|
33
34
|
class Spinner {
|
|
34
35
|
constructor(domContainer, pollingFunction, onSuccess, onError) {
|
|
35
36
|
this.state = SpinnerState.Waiting;
|
|
37
|
+
this.backOffCount = 0;
|
|
36
38
|
this.handleAbort = () => {
|
|
37
39
|
this.abortController.abort();
|
|
38
40
|
};
|
|
@@ -170,6 +172,9 @@ class Spinner {
|
|
|
170
172
|
hideSpinnerOnError: element.dataset.hideSpinnerOnError
|
|
171
173
|
? (element.dataset.hideSpinnerOnError === 'true')
|
|
172
174
|
: false,
|
|
175
|
+
maxBackoffTries: element.dataset.maxBackoffTries
|
|
176
|
+
? parseInt(element.dataset.maxBackoffTries)
|
|
177
|
+
: 3,
|
|
173
178
|
};
|
|
174
179
|
}
|
|
175
180
|
createAbortController() {
|
|
@@ -228,12 +233,24 @@ class Spinner {
|
|
|
228
233
|
this.reflectError();
|
|
229
234
|
}
|
|
230
235
|
else if (!this.hasCompleted()) {
|
|
236
|
+
let timeToNextPoll = this.config.msBetweenRequests;
|
|
237
|
+
if (response === PollResult.Backoff) {
|
|
238
|
+
this.backOffCount++;
|
|
239
|
+
if (this.backOffCount > this.config.maxBackoffTries) {
|
|
240
|
+
this.reflectError();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
timeToNextPoll = this.calculateBackoffTime(this.backOffCount);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
this.backOffCount = 0;
|
|
247
|
+
}
|
|
231
248
|
setTimeout(async () => {
|
|
232
249
|
if (Date.now() - initTime >= this.config.msBeforeAbort) {
|
|
233
250
|
return;
|
|
234
251
|
}
|
|
235
252
|
await this.callPollingFunction(initTime);
|
|
236
|
-
},
|
|
253
|
+
}, timeToNextPoll);
|
|
237
254
|
}
|
|
238
255
|
})
|
|
239
256
|
.catch((error) => {
|
|
@@ -246,6 +263,10 @@ class Spinner {
|
|
|
246
263
|
this.updateDom();
|
|
247
264
|
});
|
|
248
265
|
}
|
|
266
|
+
calculateBackoffTime(backOffCount) {
|
|
267
|
+
const extraDelay = Math.pow(2, backOffCount - 2) * this.config.msBetweenRequests;
|
|
268
|
+
return this.config.msBetweenRequests + extraDelay;
|
|
269
|
+
}
|
|
249
270
|
createAriaLiveContainer() {
|
|
250
271
|
// For the Aria alert to work reliably we need to create its container once and then update the contents
|
|
251
272
|
// https://tetralogical.com/blog/2024/05/01/why-are-my-live-regions-not-working/
|
|
@@ -266,4 +287,45 @@ class Spinner {
|
|
|
266
287
|
}
|
|
267
288
|
}
|
|
268
289
|
|
|
269
|
-
|
|
290
|
+
function initialiseProgressButtons() {
|
|
291
|
+
const progressButtons = document.querySelectorAll('[data-frontendui="di-progress-button"]');
|
|
292
|
+
progressButtons.forEach((button) => {
|
|
293
|
+
button.addEventListener('click', (event) => {
|
|
294
|
+
const waitingText = button.getAttribute('data-waiting-text');
|
|
295
|
+
const longWaitingText = button.getAttribute('data-long-waiting-text');
|
|
296
|
+
const errorPage = button.getAttribute('data-error-page');
|
|
297
|
+
const isInput = button.tagName.toLowerCase() === 'input';
|
|
298
|
+
if (!waitingText || !longWaitingText || !errorPage) {
|
|
299
|
+
console.error('Progress button is missing required data attributes.');
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
handleProgressButtonClick(button, waitingText, longWaitingText, errorPage, isInput);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
const handleProgressButtonClick = (element, waitingText, longWaitingText, errorPage, isInput = false) => {
|
|
307
|
+
element.blur();
|
|
308
|
+
element.setAttribute('data-prevent-double-click', 'true');
|
|
309
|
+
element.classList.add('govuk-button--progress-loading');
|
|
310
|
+
if (isInput && element instanceof HTMLInputElement) {
|
|
311
|
+
element.value = waitingText;
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
element.innerText = waitingText;
|
|
315
|
+
}
|
|
316
|
+
element.setAttribute('aria-label', waitingText);
|
|
317
|
+
setTimeout(() => {
|
|
318
|
+
if (isInput && element instanceof HTMLInputElement) {
|
|
319
|
+
element.value = longWaitingText;
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
element.innerText = longWaitingText;
|
|
323
|
+
}
|
|
324
|
+
element.setAttribute('aria-label', longWaitingText);
|
|
325
|
+
}, 5000);
|
|
326
|
+
setTimeout(() => {
|
|
327
|
+
window.location.href = errorPage;
|
|
328
|
+
}, 10000);
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
export { PollResult, initialiseProgressButtons, useSpinner };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress-button.d.ts","sourceRoot":"","sources":["../../../../frontend-src/progress-button/progress-button.ts"],"names":[],"mappings":"AAAA,wBAAgB,yBAAyB,SAgBxC"}
|
|
@@ -3,7 +3,8 @@ export type PollingFunction = (abortSignal: AbortSignal) => Promise<PollResult>;
|
|
|
3
3
|
export declare enum PollResult {
|
|
4
4
|
Success = 0,
|
|
5
5
|
Failure = 1,
|
|
6
|
-
Pending = 2
|
|
6
|
+
Pending = 2,
|
|
7
|
+
Backoff = 3
|
|
7
8
|
}
|
|
8
9
|
declare enum SpinnerState {
|
|
9
10
|
Waiting = 0,
|
|
@@ -18,6 +19,7 @@ type SpinnerConfig = {
|
|
|
18
19
|
msBetweenDomUpdate: number;
|
|
19
20
|
ariaAlertCompletionText?: string;
|
|
20
21
|
hideSpinnerOnError: boolean;
|
|
22
|
+
maxBackoffTries: number;
|
|
21
23
|
};
|
|
22
24
|
export declare class Spinner {
|
|
23
25
|
container: HTMLDivElement;
|
|
@@ -33,6 +35,7 @@ export declare class Spinner {
|
|
|
33
35
|
updateDomTimer?: NodeJS.Timeout;
|
|
34
36
|
abortController: AbortController;
|
|
35
37
|
config: SpinnerConfig;
|
|
38
|
+
backOffCount: number;
|
|
36
39
|
pollingFunction: PollingFunction;
|
|
37
40
|
onSuccess: VoidFunction;
|
|
38
41
|
onError: VoidFunction;
|
|
@@ -53,6 +56,7 @@ export declare class Spinner {
|
|
|
53
56
|
private updateDom;
|
|
54
57
|
private cloneAndAddIfExists;
|
|
55
58
|
private callPollingFunction;
|
|
59
|
+
private calculateBackoffTime;
|
|
56
60
|
private createAriaLiveContainer;
|
|
57
61
|
private updateAriaAlert;
|
|
58
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../../frontend-src/spinner/spinner.ts"],"names":[],"mappings":"AAAA,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,iBAoBjJ;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAEhF,oBAAY,UAAU;IACpB,OAAO,IAAA;IACP,OAAO,IAAA;IACP,OAAO,IAAA;CACR;AAED,aAAK,YAAY;IACf,OAAO,IAAA;IACP,WAAW,IAAA;IACX,KAAK,IAAA;IACL,QAAQ,IAAA;CACT;AAED,KAAK,aAAa,GAAG;IACnB,2BAA2B,EAAE,MAAM,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../../frontend-src/spinner/spinner.ts"],"names":[],"mappings":"AAAA,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,iBAoBjJ;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAEhF,oBAAY,UAAU;IACpB,OAAO,IAAA;IACP,OAAO,IAAA;IACP,OAAO,IAAA;IACP,OAAO,IAAA;CACR;AAED,aAAK,YAAY;IACf,OAAO,IAAA;IACP,WAAW,IAAA;IACX,KAAK,IAAA;IACL,QAAQ,IAAA;CACT;AAED,KAAK,aAAa,GAAG;IACnB,2BAA2B,EAAE,MAAM,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,qBAAa,OAAO;IAClB,SAAS,EAAE,cAAc,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,eAAe,CAAC,EAAE,WAAW,CAAC;IAC9B,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,iBAAiB,EAAE,cAAc,CAAC;IAElC,wBAAwB,EAAE,cAAc,CAAC;IAEzC,KAAK,EAAE,YAAY,CAAwB;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAChC,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,EAAE,MAAM,CAAK;IAEzB,eAAe,EAAE,eAAe,CAAC;IACjC,SAAS,EAAE,YAAY,CAAC;IACxB,OAAO,EAAE,YAAY,CAAC;gBAGpB,YAAY,EAAE,cAAc,EAC5B,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,YAAY,EACvB,OAAO,EAAE,YAAY;IA2CjB,IAAI;IAUV,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,SAAS;IA0BjB,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,WAAW,CAEjB;IAEF,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,SAAS,CAKf;IAEF,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc,CAGpB;IAEF,OAAO,CAAC,YAAY,CAIlB;IAEF,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,iCAAiC,CAWvC;IAEF,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,SAAS,CAkDf;IAEF,OAAO,CAAC,mBAAmB;YASb,mBAAmB;IA2CjC,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,eAAe;CAWxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@govuk-one-login/frontend-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/cjs/backend/index.cjs",
|
|
6
6
|
"module": "build/esm/backend/index.js",
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
],
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/govuk-one-login/govuk-one-login-frontend.git"
|
|
25
|
+
"url": "git+https://github.com/govuk-one-login/govuk-one-login-frontend.git",
|
|
26
|
+
"directory": "packages/frontend-ui"
|
|
26
27
|
},
|
|
27
28
|
"keywords": [
|
|
28
29
|
"govuk-one-login",
|