@govuk-one-login/frontend-ui 1.4.3 → 2.0.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.
@@ -1,249 +1,312 @@
1
- const WaitInteractions = (() => {
2
- var _a;
3
- const content = {
4
- initial: {
5
- spinnerState: "pending",
6
- },
7
- complete: { spinnerState: "completed" },
8
- };
9
- const state = {
10
- spinnerState: (_a = content === null || content === void 0 ? void 0 : content.initial) === null || _a === void 0 ? void 0 : _a.spinnerState,
11
- done: false,
12
- virtualDom: [],
13
- abortController: null,
14
- };
15
- const timers = {};
16
- let { container, ariaLiveContainer, domRequirementsMet, initTime, abortController, config, } = {
17
- };
18
- const handleAbort = () => {
19
- abortController === null || abortController === void 0 ? void 0 : abortController.abort();
20
- };
21
- const initialiseAbortController = () => {
22
- abortController = new AbortController();
23
- window.removeEventListener("beforeunload", handleAbort);
24
- window.addEventListener("beforeunload", handleAbort);
25
- };
26
- const updateAccordingToTimeElapsed = () => {
27
- const now = Date.now();
28
- const elapsedMilliseconds = now - initTime;
29
- if (elapsedMilliseconds >= config.msBeforeAbort) {
30
- reflectError();
1
+ function useSpinner() {
2
+ const element = document.getElementById("spinner-container");
3
+ if (element) {
4
+ const spinner = new Spinner(element);
5
+ spinner.init();
6
+ }
7
+ else {
8
+ console.warn("Attempting to initiate a spinner on a page with no '#spinner-container' element.");
9
+ }
10
+ }
11
+ class Spinner {
12
+ reflectLongWait() {
13
+ if (this.state.spinnerState !== "ready") {
14
+ this.state.spinnerStateText = this.content.longWait.spinnerStateText;
15
+ }
16
+ }
17
+ initialiseState() {
18
+ if (this.domRequirementsMet) {
19
+ this.state = {
20
+ heading: this.content.initial.heading,
21
+ spinnerStateText: this.content.initial.spinnerStateText,
22
+ spinnerState: this.content.initial.spinnerState,
23
+ buttonDisabled: true,
24
+ ariaButtonEnabledMessage: "",
25
+ done: false,
26
+ error: false,
27
+ virtualDom: [],
28
+ };
29
+ }
30
+ }
31
+ initialiseContent(element) {
32
+ var _a;
33
+ function throwIfMissing(data) {
34
+ if (data === undefined || data === null) {
35
+ throw new Error("Missing required data");
36
+ }
37
+ return data;
38
+ }
39
+ try {
40
+ this.content = {
41
+ initial: {
42
+ heading: throwIfMissing(element.dataset.initialHeading),
43
+ spinnerStateText: throwIfMissing(element.dataset.initialSpinnerstatetext),
44
+ spinnerState: throwIfMissing(element.dataset.initialSpinnerstate),
45
+ },
46
+ error: {
47
+ heading: throwIfMissing(element.dataset.errorHeading),
48
+ messageText: throwIfMissing(element.dataset.errorMessagetext),
49
+ whatYouCanDo: {
50
+ heading: throwIfMissing(element.dataset.errorWhatyoucandoHeading),
51
+ message: {
52
+ text1: throwIfMissing(element.dataset.errorWhatyoucandoMessageText1),
53
+ link: {
54
+ href: throwIfMissing(element.dataset.errorWhatyoucandoMessageLinkHref),
55
+ text: throwIfMissing(element.dataset.errorWhatyoucandoMessageLinkText),
56
+ },
57
+ text2: throwIfMissing(element.dataset.errorWhatyoucandoMessageText2),
58
+ },
59
+ },
60
+ },
61
+ complete: {
62
+ spinnerState: throwIfMissing(element.dataset.completeSpinnerstate),
63
+ },
64
+ longWait: {
65
+ spinnerStateText: throwIfMissing(element.dataset.longwaitSpinnerstatetext),
66
+ },
67
+ continueButton: {
68
+ text: (_a = element.dataset.continuebuttonText) !== null && _a !== void 0 ? _a : "Continue",
69
+ },
70
+ };
71
+ this.config = {
72
+ apiUrl: element.dataset.apiUrl || this.config.apiUrl,
73
+ ariaButtonEnabledMessage: throwIfMissing(element.dataset.ariaButtonEnabledMessage),
74
+ msBeforeInformingOfLongWait: element.dataset.msBeforeInformingOfLongWait
75
+ ? parseInt(element.dataset.msBeforeInformingOfLongWait)
76
+ : this.config.msBeforeInformingOfLongWait,
77
+ msBeforeAbort: element.dataset.msBeforeAbort
78
+ ? parseInt(element.dataset.msBeforeAbort)
79
+ : this.config.msBeforeAbort,
80
+ msBetweenRequests: element.dataset.msBetweenRequests
81
+ ? parseInt(element.dataset.msBetweenRequests)
82
+ : this.config.msBetweenRequests,
83
+ msBetweenDomUpdate: element.dataset.msBetweenDomUpdate
84
+ ? parseInt(element.dataset.msBetweenDomUpdate)
85
+ : this.config.msBetweenDomUpdate,
86
+ };
87
+ this.domRequirementsMet = true;
31
88
  }
32
- else if ((elapsedMilliseconds >=
33
- config.msBeforeInformingOfLongWait)) {
34
- reflectLongWait();
89
+ catch (e) {
90
+ this.domRequirementsMet = false;
35
91
  }
36
- };
37
- const createVirtualDom = () => {
38
- var _a, _b, _c, _d, _e, _f;
39
- const initialState = [
92
+ }
93
+ createVirtualDom() {
94
+ const domInitialState = [
40
95
  {
41
96
  nodeName: "h1",
42
- text: state.heading,
97
+ text: this.state.heading,
43
98
  classes: ["govuk-heading-l"],
44
99
  },
45
100
  {
46
101
  nodeName: "div",
47
102
  id: "spinner",
48
- classes: ["spinner", "spinner__pending", "centre", state.spinnerState],
103
+ classes: [
104
+ "spinner",
105
+ "spinner__pending",
106
+ "centre",
107
+ this.state.spinnerState,
108
+ ],
49
109
  },
50
110
  {
51
111
  nodeName: "p",
52
- text: state.spinnerStateText,
112
+ text: this.state.spinnerStateText,
53
113
  classes: ["centre", "spinner-state-text", "govuk-body"],
54
114
  },
55
115
  {
56
116
  nodeName: "button",
57
- text: (_a = content === null || content === void 0 ? void 0 : content.continueButton) === null || _a === void 0 ? void 0 : _a.text,
58
- buttonDisabled: state.buttonDisabled,
117
+ text: this.content.continueButton.text,
118
+ buttonDisabled: this.state.buttonDisabled,
59
119
  classes: ["govuk-button", "govuk-!-margin-top-4"],
60
120
  },
61
121
  ];
62
122
  const domErrorState = [
63
123
  {
64
124
  nodeName: "h1",
65
- text: state.heading,
125
+ text: this.state.heading,
66
126
  classes: ["govuk-heading-l"],
67
127
  },
68
128
  {
69
129
  nodeName: "p",
70
- text: state.messageText,
130
+ text: this.state.messageText,
71
131
  classes: ["govuk-body"],
72
132
  },
73
133
  {
74
134
  nodeName: "h2",
75
- text: (_b = content === null || content === void 0 ? void 0 : content.error) === null || _b === void 0 ? void 0 : _b.whatYouCanDo.heading,
135
+ text: this.content.error.whatYouCanDo.heading,
76
136
  classes: ["govuk-heading-m"],
77
137
  },
78
138
  {
79
139
  nodeName: "p",
80
- innerHTML: `${(_c = content === null || content === void 0 ? void 0 : content.error) === null || _c === void 0 ? void 0 : _c.whatYouCanDo.message.text1}<a href="${(_d = content === null || content === void 0 ? void 0 : content.error) === null || _d === void 0 ? void 0 : _d.whatYouCanDo.message.link.href}">${(_e = content === null || content === void 0 ? void 0 : content.error) === null || _e === void 0 ? void 0 : _e.whatYouCanDo.message.link.text}</a>${(_f = content === null || content === void 0 ? void 0 : content.error) === null || _f === void 0 ? void 0 : _f.whatYouCanDo.message.text2}`,
140
+ innerHTML: `${this.content.error.whatYouCanDo.message.text1}<a href="${this.content.error.whatYouCanDo.message.link.href}">${this.content.error.whatYouCanDo.message.link.text}</a>${this.content.error.whatYouCanDo.message.text2}`,
81
141
  classes: ["govuk-body"],
82
142
  },
83
143
  ];
84
- return state.error ? domErrorState : initialState;
85
- };
86
- const vDomHasChanged = (currentVDom, nextVDom) => {
87
- return JSON.stringify(currentVDom) !== JSON.stringify(nextVDom);
88
- };
89
- const updateDom = () => {
90
- var _a;
91
- const vDomChanged = vDomHasChanged(state.virtualDom, createVirtualDom());
92
- const container = document.getElementById("spinner-container");
93
- if (vDomChanged) {
94
- document.title = state.heading;
95
- state.virtualDom = createVirtualDom();
96
- const elements = (_a = state === null || state === void 0 ? void 0 : state.virtualDom) === null || _a === void 0 ? void 0 : _a.map(convert);
97
- container === null || container === void 0 ? void 0 : container.replaceChildren(...elements);
98
- }
99
- if (state.error) {
100
- container === null || container === void 0 ? void 0 : container.classList.add("spinner-container__error");
101
- }
102
- if (state.done) {
103
- clearInterval(timers.updateDomTimer);
104
- }
105
- if (state.ariaButtonEnabledMessage !== "") {
106
- updateAriaAlert(config === null || config === void 0 ? void 0 : config.ariaButtonEnabledMessage);
107
- }
108
- };
109
- const reflectCompletion = () => {
110
- var _a, _b;
111
- state.spinnerState = "spinner__ready";
112
- state.spinnerStateText = (_a = content === null || content === void 0 ? void 0 : content.complete) === null || _a === void 0 ? void 0 : _a.spinnerState;
113
- state.buttonDisabled = false;
114
- state.ariaButtonEnabledMessage =
115
- (_b = content === null || content === void 0 ? void 0 : content.complete) === null || _b === void 0 ? void 0 : _b.ariaButtonEnabledMessage;
116
- state.done = true;
117
- sessionStorage.removeItem("spinnerInitTime");
118
- };
119
- const reflectError = () => {
120
- var _a, _b, _c;
121
- state.heading = (_a = content === null || content === void 0 ? void 0 : content.error) === null || _a === void 0 ? void 0 : _a.heading;
122
- state.messageText = (_b = content === null || content === void 0 ? void 0 : content.error) === null || _b === void 0 ? void 0 : _b.messageText;
123
- state.spinnerState = "spinner__failed";
124
- state.done = true;
125
- state.error = true;
126
- sessionStorage.removeItem("spinnerInitTime");
127
- (_c = state === null || state === void 0 ? void 0 : state.abortController) === null || _c === void 0 ? void 0 : _c.abort();
128
- };
129
- const reflectLongWait = () => {
130
- var _a;
131
- if (state.spinnerState !== "ready") {
132
- state.spinnerStateText = (_a = content === null || content === void 0 ? void 0 : content.longWait) === null || _a === void 0 ? void 0 : _a.spinnerStateText;
133
- }
134
- };
135
- const convert = (node) => {
136
- const el = document.createElement(node.nodeName);
137
- if (node.text)
138
- el.textContent = node.text;
139
- if (node.innerHTML)
140
- el.innerHTML = node.innerHTML;
141
- if (node.id)
142
- el.id = node.id;
143
- if (node.classes)
144
- el.classList.add(...node.classes);
145
- if (node.buttonDisabled)
146
- el.setAttribute("disabled", node.buttonDisabled);
147
- return el;
148
- };
149
- const updateAriaAlert = (messageText) => {
150
- while (ariaLiveContainer === null || ariaLiveContainer === void 0 ? void 0 : ariaLiveContainer.firstChild) {
151
- ariaLiveContainer.removeChild(ariaLiveContainer.firstChild);
152
- }
153
- /* Create new message and append it to the live region */
154
- const messageNode = document.createTextNode(messageText);
155
- ariaLiveContainer === null || ariaLiveContainer === void 0 ? void 0 : ariaLiveContainer.appendChild(messageNode);
156
- };
157
- const notInErrorOrDoneState = () => {
158
- return !(state.done || state.error);
159
- };
160
- const requestIDProcessingStatus = async () => {
161
- var _a;
162
- const signal = abortController.signal;
163
- const apiRoute = (_a = document === null || document === void 0 ? void 0 : document.getElementById("spinner-container")) === null || _a === void 0 ? void 0 : _a.dataset.apiRoute;
164
- try {
165
- const response = await fetch(apiRoute, { signal });
166
- if (response.status !== 200) {
167
- throw new Error(`Status code ${response.status} received`);
168
- }
169
- const data = await response.json();
170
- if (data.status === "COMPLETED" ||
171
- data.status === "INTERVENTION") {
172
- reflectCompletion();
144
+ return this.state.error ? domErrorState : domInitialState;
145
+ }
146
+ async requestIDProcessingStatus(initTime) {
147
+ const signal = this.abortController.signal;
148
+ await fetch(this.config.apiUrl, { signal })
149
+ .then((response) => response.json())
150
+ .then((data) => {
151
+ if (data.status === "COMPLETED" || data.status === "INTERVENTION") {
152
+ this.reflectCompletion();
173
153
  }
174
154
  else if (data.status === "ERROR") {
175
- reflectError();
155
+ this.reflectError();
176
156
  }
177
- else if (notInErrorOrDoneState()) {
157
+ else if (this.notInErrorOrDoneState()) {
178
158
  setTimeout(async () => {
179
- if (Date.now() - initTime >= config.msBeforeAbort) {
159
+ if (Date.now() - initTime >= this.config.msBeforeAbort) {
180
160
  return;
181
161
  }
182
- await requestIDProcessingStatus();
183
- }, config.msBetweenRequests);
184
- }
185
- if (data.status === "Clear to proceed") {
186
- reflectCompletion();
162
+ await this.requestIDProcessingStatus(initTime);
163
+ }, this.config.msBetweenRequests);
187
164
  }
188
- else if (notInErrorOrDoneState()) {
189
- setTimeout(async () => {
190
- await requestIDProcessingStatus();
191
- }, 1000);
165
+ })
166
+ .catch((error) => {
167
+ if (error.name !== "AbortError") {
168
+ console.error("Error in requestIDProcessingStatus:", error);
169
+ this.reflectError();
192
170
  }
193
- }
194
- catch (e) {
195
- console.log(e);
196
- reflectError();
197
- if (e.name !== "AbortError") {
198
- console.error("Error in requestIdProcessingStatus:", e);
199
- reflectError();
200
- }
201
- }
202
- };
203
- const initTimer = () => {
204
- let spinnerInitTime = sessionStorage.getItem("spinnerInitTime");
205
- if (spinnerInitTime === null) {
171
+ })
172
+ .finally(() => {
173
+ this.updateDom();
174
+ });
175
+ }
176
+ getInitTime() {
177
+ const storedSpinnerInitTime = sessionStorage.getItem("spinnerInitTime");
178
+ let spinnerInitTime;
179
+ if (storedSpinnerInitTime === null) {
206
180
  spinnerInitTime = Date.now();
207
181
  sessionStorage.setItem("spinnerInitTime", spinnerInitTime.toString());
208
182
  }
209
183
  else {
210
- spinnerInitTime = parseInt(spinnerInitTime, 10);
184
+ spinnerInitTime = parseInt(storedSpinnerInitTime, 10);
185
+ }
186
+ return spinnerInitTime;
187
+ }
188
+ init() {
189
+ if (this.domRequirementsMet) {
190
+ const initTime = this.getInitTime();
191
+ this.initTimer(initTime);
192
+ this.initialiseContainers();
193
+ this.updateDom();
194
+ this.requestIDProcessingStatus(initTime);
211
195
  }
212
- initTime = spinnerInitTime;
213
- updateAccordingToTimeElapsed();
214
- setInterval(() => {
215
- updateAccordingToTimeElapsed();
216
- updateDom();
217
- }, config === null || config === void 0 ? void 0 : config.msBetweenDomUpdate);
218
- };
219
- const initialiseContainers = () => {
220
- const spinnerContainer = document.createElement("div");
221
- const ariaLiveContainer = document.createElement("div");
222
- ariaLiveContainer.setAttribute("aria-live", "assertive");
223
- ariaLiveContainer.classList.add("govuk-visually-hidden");
224
- ariaLiveContainer.appendChild(document.createTextNode(""));
225
- container === null || container === void 0 ? void 0 : container.replaceChildren(spinnerContainer, ariaLiveContainer);
226
- };
227
- return {
228
- state: state,
229
- init: () => {
230
- timers.updateDomTimer = setInterval(updateDom, 2000);
231
- timers.abortUnresponsiveRequest = setTimeout(() => {
232
- reflectError();
233
- }, 15000);
234
- updateDom();
235
- requestIDProcessingStatus().then(() => {
236
- updateDom();
237
- });
238
- if (domRequirementsMet) {
239
- initTimer();
240
- initialiseContainers();
241
- initialiseAbortController();
242
- updateDom();
243
- requestIDProcessingStatus();
196
+ }
197
+ constructor(domContainer) {
198
+ this.config = {
199
+ apiUrl: "/prove-identity-status",
200
+ msBeforeInformingOfLongWait: 5000,
201
+ msBeforeAbort: 25000,
202
+ msBetweenRequests: 1000,
203
+ msBetweenDomUpdate: 2000,
204
+ };
205
+ this.notInErrorOrDoneState = () => {
206
+ return !(this.state.done || this.state.error);
207
+ };
208
+ this.reflectCompletion = () => {
209
+ this.state.spinnerState = "spinner__ready";
210
+ this.state.spinnerStateText = this.content.complete.spinnerState;
211
+ this.state.buttonDisabled = false;
212
+ this.state.ariaButtonEnabledMessage =
213
+ this.content.complete.ariaButtonEnabledMessage;
214
+ this.state.done = true;
215
+ sessionStorage.removeItem("spinnerInitTime");
216
+ };
217
+ this.reflectError = () => {
218
+ this.state.heading = this.content.error.heading;
219
+ this.state.messageText = this.content.error.messageText;
220
+ this.state.spinnerState = "spinner__failed";
221
+ this.state.done = true;
222
+ this.state.error = true;
223
+ sessionStorage.removeItem("spinnerInitTime");
224
+ this.abortController.abort();
225
+ };
226
+ this.updateAccordingToTimeElapsed = (initTime) => {
227
+ const elapsedMilliseconds = Date.now() - initTime;
228
+ if (elapsedMilliseconds >= this.config.msBeforeAbort) {
229
+ this.reflectError();
230
+ }
231
+ else if (elapsedMilliseconds >= this.config.msBeforeInformingOfLongWait) {
232
+ this.reflectLongWait();
233
+ }
234
+ };
235
+ this.vDomHasChanged = (currentVDom, nextVDom) => {
236
+ return JSON.stringify(currentVDom) !== JSON.stringify(nextVDom);
237
+ };
238
+ this.convert = (node) => {
239
+ const el = document.createElement(node.nodeName);
240
+ if (node.text)
241
+ el.textContent = node.text;
242
+ if (node.innerHTML)
243
+ el.innerHTML = node.innerHTML;
244
+ if (node.id)
245
+ el.id = node.id;
246
+ if (node.classes)
247
+ el.classList.add(...node.classes);
248
+ if (node.buttonDisabled)
249
+ el.setAttribute("disabled", `${node.buttonDisabled}`);
250
+ return el;
251
+ };
252
+ this.updateAriaAlert = (messageText) => {
253
+ while (this.ariaLiveContainer.firstChild) {
254
+ this.ariaLiveContainer.removeChild(this.ariaLiveContainer.firstChild);
255
+ }
256
+ /* Create new message and append it to the live region */
257
+ const messageNode = document.createTextNode(messageText);
258
+ this.ariaLiveContainer.appendChild(messageNode);
259
+ };
260
+ this.updateDom = () => {
261
+ const vDomChanged = this.vDomHasChanged(this.state.virtualDom, this.createVirtualDom());
262
+ if (vDomChanged) {
263
+ document.title = this.state.heading;
264
+ this.state.virtualDom = this.createVirtualDom();
265
+ const elements = this.state.virtualDom.map(this.convert);
266
+ this.spinnerContainer.replaceChildren(...elements);
267
+ }
268
+ if (this.state.error) {
269
+ this.spinnerContainer.classList.add("spinner-container__error");
270
+ }
271
+ if (this.state.done) {
272
+ clearInterval(this.updateDomTimer);
273
+ }
274
+ if (this.config.ariaButtonEnabledMessage &&
275
+ this.state.ariaButtonEnabledMessage !== "") {
276
+ this.updateAriaAlert(this.config.ariaButtonEnabledMessage);
244
277
  }
245
- },
246
- };
247
- })();
278
+ };
279
+ // For the Aria alert to work reliably we need to create its container once and then update the contents
280
+ // https://tetralogical.com/blog/2024/05/01/why-are-my-live-regions-not-working/
281
+ // So here we create a separate DOM element for the Aria live text that won't be touched when the spinner updates.
282
+ this.initialiseContainers = () => {
283
+ this.spinnerContainer = document.createElement("div");
284
+ this.ariaLiveContainer = document.createElement("div");
285
+ this.ariaLiveContainer.setAttribute("aria-live", "assertive");
286
+ this.ariaLiveContainer.classList.add("govuk-visually-hidden");
287
+ this.ariaLiveContainer.appendChild(document.createTextNode(""));
288
+ this.container.replaceChildren(this.spinnerContainer, this.ariaLiveContainer);
289
+ };
290
+ this.initTimer = (initTime) => {
291
+ this.updateAccordingToTimeElapsed(initTime);
292
+ this.updateDomTimer = setInterval(() => {
293
+ this.updateAccordingToTimeElapsed(initTime);
294
+ this.updateDom();
295
+ }, this.config.msBetweenDomUpdate);
296
+ };
297
+ this.handleAbort = () => {
298
+ this.abortController.abort();
299
+ };
300
+ this.initialiseAbortController = () => {
301
+ this.abortController = new AbortController();
302
+ window.removeEventListener("beforeunload", this.handleAbort);
303
+ window.addEventListener("beforeunload", this.handleAbort);
304
+ };
305
+ this.container = domContainer;
306
+ this.initialiseContent(this.container);
307
+ this.initialiseState();
308
+ this.initialiseAbortController();
309
+ }
310
+ }
248
311
 
249
- export { WaitInteractions };
312
+ export { useSpinner };
@@ -0,0 +1,6 @@
1
+ export declare function wait(ms: number): Promise<unknown>;
2
+ export declare function waitUntil(conditionFn: Function, { timeout, interval }?: {
3
+ timeout?: number | undefined;
4
+ interval?: number | undefined;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=spinner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.test.d.ts","sourceRoot":"","sources":["../../../../../frontend-src/spinner/__tests__/spinner.test.ts"],"names":[],"mappings":"AAEA,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,oBAE9B;AAED,wBAAsB,SAAS,CAC7B,WAAW,EAAE,QAAQ,EACrB,EAAE,OAAc,EAAE,QAAa,EAAE;;;CAAK,iBAcvC"}
@@ -0,0 +1,90 @@
1
+ export declare function useSpinner(): void;
2
+ type TVDOM = {
3
+ classes: string[];
4
+ buttonDisabled?: boolean;
5
+ id?: string;
6
+ innerHTML?: string;
7
+ nodeName: string;
8
+ text?: string;
9
+ };
10
+ export declare class Spinner {
11
+ container: HTMLElement;
12
+ spinnerContainer: HTMLElement;
13
+ ariaLiveContainer: HTMLElement;
14
+ content: {
15
+ complete: {
16
+ ariaButtonEnabledMessage?: string;
17
+ spinnerState: string;
18
+ };
19
+ continueButton: {
20
+ text: string;
21
+ };
22
+ error: {
23
+ heading: string;
24
+ messageText: string;
25
+ whatYouCanDo: {
26
+ heading: string;
27
+ message: {
28
+ text1: string;
29
+ link: {
30
+ href: string;
31
+ text: string;
32
+ };
33
+ text2: string;
34
+ };
35
+ };
36
+ };
37
+ initial: {
38
+ heading: string;
39
+ spinnerStateText: string;
40
+ spinnerState: string;
41
+ };
42
+ longWait: {
43
+ spinnerStateText: string;
44
+ };
45
+ };
46
+ domRequirementsMet?: boolean;
47
+ state: {
48
+ ariaButtonEnabledMessage?: string;
49
+ buttonDisabled: boolean;
50
+ done: boolean;
51
+ error: boolean;
52
+ heading: string;
53
+ messageText?: string;
54
+ spinnerState: string;
55
+ spinnerStateText: string;
56
+ virtualDom: TVDOM[];
57
+ };
58
+ updateDomTimer: NodeJS.Timeout;
59
+ abortController: AbortController;
60
+ config: {
61
+ apiUrl: string;
62
+ ariaButtonEnabledMessage?: string;
63
+ msBeforeInformingOfLongWait: number;
64
+ msBeforeAbort: number;
65
+ msBetweenRequests: number;
66
+ msBetweenDomUpdate: number;
67
+ };
68
+ notInErrorOrDoneState: () => boolean;
69
+ reflectCompletion: () => void;
70
+ reflectError: () => void;
71
+ reflectLongWait(): void;
72
+ updateAccordingToTimeElapsed: (initTime: number) => void;
73
+ initialiseState(): void;
74
+ initialiseContent(element: HTMLElement): void;
75
+ createVirtualDom(): TVDOM[];
76
+ vDomHasChanged: (currentVDom: TVDOM[], nextVDom: TVDOM[]) => boolean;
77
+ convert: (node: TVDOM) => HTMLElement;
78
+ updateAriaAlert: (messageText: string) => void;
79
+ updateDom: () => void;
80
+ requestIDProcessingStatus(initTime: number): Promise<void>;
81
+ initialiseContainers: () => void;
82
+ getInitTime(): number;
83
+ initTimer: (initTime: number) => void;
84
+ handleAbort: () => void;
85
+ initialiseAbortController: () => void;
86
+ init(): void;
87
+ constructor(domContainer: HTMLElement);
88
+ }
89
+ export {};
90
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../../frontend-src/spinner/spinner.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,SAWzB;AAED,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,OAAO;IAClB,SAAS,cAAC;IACV,gBAAgB,EAAE,WAAW,CAAC;IAC9B,iBAAiB,EAAE,WAAW,CAAC;IAC/B,OAAO,EAAE;QACP,QAAQ,EAAE;YACR,wBAAwB,CAAC,EAAE,MAAM,CAAC;YAClC,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,cAAc,EAAE;YACd,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;QACF,KAAK,EAAE;YACL,OAAO,EAAE,MAAM,CAAC;YAChB,WAAW,EAAE,MAAM,CAAC;YACpB,YAAY,EAAE;gBACZ,OAAO,EAAE,MAAM,CAAC;gBAChB,OAAO,EAAE;oBACP,KAAK,EAAE,MAAM,CAAC;oBACd,IAAI,EAAE;wBACJ,IAAI,EAAE,MAAM,CAAC;wBACb,IAAI,EAAE,MAAM,CAAC;qBACd,CAAC;oBACF,KAAK,EAAE,MAAM,CAAC;iBACf,CAAC;aACH,CAAC;SACH,CAAC;QACF,OAAO,EAAE;YACP,OAAO,EAAE,MAAM,CAAC;YAChB,gBAAgB,EAAE,MAAM,CAAC;YACzB,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,QAAQ,EAAE;YACR,gBAAgB,EAAE,MAAM,CAAC;SAC1B,CAAC;KACH,CAAC;IACF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE;QACL,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,cAAc,EAAE,OAAO,CAAC;QACxB,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,KAAK,EAAE,CAAC;KACrB,CAAC;IACF,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC;IAC/B,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,2BAA2B,EAAE,MAAM,CAAC;QACpC,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAMC;IAEF,qBAAqB,gBAEnB;IAEF,iBAAiB,aAQf;IAEF,YAAY,aAQV;IAEF,eAAe;IAMf,4BAA4B,GAAI,UAAU,MAAM,UAO9C;IAEF,eAAe;IAef,iBAAiB,CAAC,OAAO,EAAE,WAAW;IA8EtC,gBAAgB,IAAI,KAAK,EAAE;IAwD3B,cAAc,GAAI,aAAa,KAAK,EAAE,EAAE,UAAU,KAAK,EAAE,aAEvD;IAEF,OAAO,GAAI,MAAM,KAAK,iBASpB;IAEF,eAAe,GAAI,aAAa,MAAM,UAQpC;IAEF,SAAS,aA0BP;IAEI,yBAAyB,CAAC,QAAQ,EAAE,MAAM;IAgChD,oBAAoB,aAUlB;IAEF,WAAW;IAYX,SAAS,GAAI,UAAU,MAAM,UAO3B;IAEF,WAAW,aAET;IAEF,yBAAyB,aAIvB;IAEF,IAAI;gBAWQ,YAAY,EAAE,WAAW;CAMtC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@govuk-one-login/frontend-ui",
3
- "version": "1.4.3",
3
+ "version": "2.0.0",
4
4
  "description": "",
5
5
  "main": "build/cjs/backend/index.cjs",
6
6
  "module": "build/esm/backend/index.js",
@@ -12,8 +12,8 @@
12
12
  "build": "rollup -c",
13
13
  "dev": "rollup -c --watch",
14
14
  "test": "jest --coverage src",
15
- "test:visual": "playwright test browser-tests/functional-tests",
16
- "test:visual:update": "playwright test browser-tests/functional-tests --update-snapshots"
15
+ "test:visual": "npx playwright install --with-deps && playwright test browser-tests/functional-tests",
16
+ "test:visual:update": "npx playwright install --with-deps && playwright test browser-tests/functional-tests --update-snapshots"
17
17
  },
18
18
  "files": [
19
19
  "build/",
@@ -42,7 +42,8 @@
42
42
  },
43
43
  "peerDependencies": {
44
44
  "express": "^5.1.0 || >= 4.21.2",
45
- "govuk-frontend": "^4.10.1 || ^5.0.0"
45
+ "govuk-frontend": "^4.10.1 || ^5.0.0",
46
+ "@govuk-one-login/frontend-analytics": " ^3.0.1 || ^4.0.3"
46
47
  },
47
48
  "exports": {
48
49
  ".": {
@@ -57,6 +58,6 @@
57
58
  "types": "./build/esm/backend/index.d.ts",
58
59
  "optionalDependencies": {
59
60
  "hmpo-components": "^7.1.0",
60
- "@govuk-one-login/frontend-analytics": "^4.0.1"
61
+ "@govuk-one-login/frontend-analytics": "^4.0.3"
61
62
  }
62
63
  }
@@ -1,6 +0,0 @@
1
- import { state } from "../utils/types";
2
- export declare const WaitInteractions: {
3
- state: state;
4
- init: () => void;
5
- };
6
- //# sourceMappingURL=spinner.d.ts.map