@ministryofjustice/hmpps-connect-dps-shared-items 5.1.0 → 5.2.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/dist/assets/dps/components/address-autosuggest/_address-autosuggest.scss +7 -0
- package/dist/assets/dps/components/address-autosuggest/abortable-fetch.d.ts +26 -0
- package/dist/assets/dps/components/address-autosuggest/abortable-fetch.js +20 -8
- package/dist/assets/dps/components/address-autosuggest/abortable-fetch.ts +76 -0
- package/dist/assets/dps/components/address-autosuggest/autosuggest-address.d.ts +18 -0
- package/dist/assets/dps/components/address-autosuggest/autosuggest-address.js +27 -13
- package/dist/assets/dps/components/address-autosuggest/autosuggest-address.ts +108 -0
- package/dist/assets/dps/components/address-autosuggest/autosuggest-ui.d.ts +82 -0
- package/dist/assets/dps/components/address-autosuggest/autosuggest-ui.js +83 -53
- package/dist/assets/dps/components/address-autosuggest/autosuggest-ui.ts +459 -0
- package/dist/assets/dps/components/address-autosuggest/index.d.ts +1 -0
- package/dist/assets/dps/components/address-autosuggest/index.js +4 -4
- package/dist/assets/dps/components/address-autosuggest/index.ts +9 -0
- package/dist/assets/dps/components/alert-flag/_alert-flag.scss +2 -1
- package/dist/assets/dps/components/modal/index.d.ts +34 -0
- package/dist/assets/dps/components/modal/macro.njk +2 -1
- package/dist/assets/dps/components/webcam-capture/_webcam-capture.scss +2 -2
- package/dist/assets/dps/components/webcam-capture/index.d.ts +1 -0
- package/dist/assets/dps/components/webcam-capture/index.js +14 -8
- package/dist/assets/dps/components/webcam-capture/index.ts +165 -0
- package/dist/assets/js/all.d.ts +1 -0
- package/dist/assets/js/all.ts +10 -0
- package/dist/assets/scss/all.css +66 -16
- package/dist/index.d.ts +10 -1
- package/dist/types/public/addressAutosuggest/addressAutosuggestResponse.d.ts +9 -0
- package/package.json +4 -4
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
@use "govuk-frontend/dist/govuk/helpers/colour";
|
|
2
|
+
@use "govuk-frontend/dist/govuk/helpers/typography";
|
|
2
3
|
|
|
3
4
|
.hmpps-address-autosuggest {
|
|
4
5
|
position: relative;
|
|
5
6
|
max-width: 630px;
|
|
6
7
|
|
|
8
|
+
.hmpps-display-none {
|
|
9
|
+
display: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
7
12
|
.govuk-form-group {
|
|
8
13
|
margin-bottom: 10px;
|
|
9
14
|
}
|
|
@@ -27,6 +32,7 @@
|
|
|
27
32
|
background: colour.govuk-colour("black", $variant: "tint-95");
|
|
28
33
|
border-bottom: 1px solid colour.govuk-functional-colour(border);
|
|
29
34
|
padding: 0.25rem 0.5rem;
|
|
35
|
+
@include typography.govuk-font($size: 19);
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
&__listbox {
|
|
@@ -37,6 +43,7 @@
|
|
|
37
43
|
&:focus {
|
|
38
44
|
outline: none;
|
|
39
45
|
}
|
|
46
|
+
@include typography.govuk-font($size: 19);
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
&__option {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const FetchStatus: {
|
|
2
|
+
readonly unsent: "UNSENT";
|
|
3
|
+
readonly loading: "LOADING";
|
|
4
|
+
readonly done: "DONE";
|
|
5
|
+
};
|
|
6
|
+
export type FetchStatus = typeof FetchStatus;
|
|
7
|
+
export declare const abortError: "AbortError";
|
|
8
|
+
export declare const abortTimeout: "AbortTimeout";
|
|
9
|
+
export interface AbortableFetchOptions {
|
|
10
|
+
/** How long to delay the fetch call for; defaults to 0.5s */
|
|
11
|
+
fetchDelay?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class AbortableFetch {
|
|
14
|
+
private controller;
|
|
15
|
+
status: FetchStatus[keyof FetchStatus];
|
|
16
|
+
private readonly fetchDelay;
|
|
17
|
+
private readonly url;
|
|
18
|
+
constructor(url: string, options?: AbortableFetchOptions);
|
|
19
|
+
send(): Promise<Response>;
|
|
20
|
+
abort(): void;
|
|
21
|
+
}
|
|
22
|
+
export declare class ResponseError extends Error {
|
|
23
|
+
readonly response: Response;
|
|
24
|
+
constructor(message: string, response: Response);
|
|
25
|
+
}
|
|
26
|
+
export declare const abortableFetch: (url: string, options: AbortableFetchOptions) => AbortableFetch;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Based on ONSDigital's https://github.com/ONSdigital/design-system/blob/main/src/js/abortable-fetch.js
|
|
2
|
+
/* eslint-disable max-classes-per-file, @stylistic/lines-between-class-members */
|
|
2
3
|
const FetchStatus = {
|
|
3
4
|
unsent: 'UNSENT',
|
|
4
5
|
loading: 'LOADING',
|
|
@@ -7,7 +8,11 @@ const FetchStatus = {
|
|
|
7
8
|
const abortError = 'AbortError';
|
|
8
9
|
const abortTimeout = 'AbortTimeout';
|
|
9
10
|
class AbortableFetch {
|
|
10
|
-
|
|
11
|
+
controller;
|
|
12
|
+
status;
|
|
13
|
+
fetchDelay;
|
|
14
|
+
url;
|
|
15
|
+
constructor(url, options = {}) {
|
|
11
16
|
this.url = url;
|
|
12
17
|
this.controller = new window.AbortController();
|
|
13
18
|
this.status = FetchStatus.unsent;
|
|
@@ -17,18 +22,18 @@ class AbortableFetch {
|
|
|
17
22
|
this.status = FetchStatus.loading;
|
|
18
23
|
try {
|
|
19
24
|
// Abortable delay before querying the API to limit the rate of requests when someone is typing:
|
|
20
|
-
await new Promise(
|
|
25
|
+
await new Promise(resolve => {
|
|
21
26
|
setTimeout(resolve, this.fetchDelay);
|
|
22
|
-
this.controller.signal.addEventListener('abort', () => {
|
|
27
|
+
this.controller.signal.addEventListener('abort', () => {
|
|
28
|
+
resolve();
|
|
29
|
+
}, { once: true });
|
|
23
30
|
});
|
|
24
31
|
setTimeout(() => {
|
|
25
32
|
this.controller.abort(abortTimeout);
|
|
26
33
|
}, 5000);
|
|
27
34
|
const response = await window.fetch(this.url, { signal: this.controller.signal });
|
|
28
|
-
if (!
|
|
29
|
-
|
|
30
|
-
error.response = response;
|
|
31
|
-
throw error;
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
throw new ResponseError(`API error: ${response.status ?? 500}`, response);
|
|
32
37
|
}
|
|
33
38
|
return response;
|
|
34
39
|
}
|
|
@@ -40,6 +45,13 @@ class AbortableFetch {
|
|
|
40
45
|
this.controller.abort();
|
|
41
46
|
}
|
|
42
47
|
}
|
|
48
|
+
class ResponseError extends Error {
|
|
49
|
+
response;
|
|
50
|
+
constructor(message, response) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.response = response;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
43
55
|
const abortableFetch = (url, options) => new AbortableFetch(url, options);
|
|
44
56
|
|
|
45
|
-
export { FetchStatus, abortError, abortTimeout, abortableFetch };
|
|
57
|
+
export { AbortableFetch, FetchStatus, ResponseError, abortError, abortTimeout, abortableFetch };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Based on ONSDigital's https://github.com/ONSdigital/design-system/blob/main/src/js/abortable-fetch.js
|
|
2
|
+
/* eslint-disable max-classes-per-file, @stylistic/lines-between-class-members */
|
|
3
|
+
|
|
4
|
+
export const FetchStatus = {
|
|
5
|
+
unsent: 'UNSENT',
|
|
6
|
+
loading: 'LOADING',
|
|
7
|
+
done: 'DONE',
|
|
8
|
+
} as const
|
|
9
|
+
export type FetchStatus = typeof FetchStatus
|
|
10
|
+
|
|
11
|
+
export const abortError = 'AbortError' as const
|
|
12
|
+
export const abortTimeout = 'AbortTimeout' as const
|
|
13
|
+
|
|
14
|
+
export interface AbortableFetchOptions {
|
|
15
|
+
/** How long to delay the fetch call for; defaults to 0.5s */
|
|
16
|
+
fetchDelay?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class AbortableFetch {
|
|
20
|
+
private controller: AbortController
|
|
21
|
+
public status: FetchStatus[keyof FetchStatus]
|
|
22
|
+
private readonly fetchDelay: number
|
|
23
|
+
private readonly url: string
|
|
24
|
+
|
|
25
|
+
constructor(url: string, options: AbortableFetchOptions = {}) {
|
|
26
|
+
this.url = url
|
|
27
|
+
this.controller = new window.AbortController()
|
|
28
|
+
this.status = FetchStatus.unsent
|
|
29
|
+
this.fetchDelay = options?.fetchDelay || 500
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public async send(): Promise<Response> {
|
|
33
|
+
this.status = FetchStatus.loading
|
|
34
|
+
try {
|
|
35
|
+
// Abortable delay before querying the API to limit the rate of requests when someone is typing:
|
|
36
|
+
await new Promise<void>(resolve => {
|
|
37
|
+
setTimeout(resolve, this.fetchDelay)
|
|
38
|
+
this.controller.signal.addEventListener(
|
|
39
|
+
'abort',
|
|
40
|
+
() => {
|
|
41
|
+
resolve()
|
|
42
|
+
},
|
|
43
|
+
{ once: true },
|
|
44
|
+
)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
this.controller.abort(abortTimeout)
|
|
49
|
+
}, 5000)
|
|
50
|
+
|
|
51
|
+
const response = await window.fetch(this.url, { signal: this.controller.signal })
|
|
52
|
+
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
throw new ResponseError(`API error: ${response.status ?? 500}`, response)
|
|
55
|
+
}
|
|
56
|
+
return response
|
|
57
|
+
} finally {
|
|
58
|
+
this.status = FetchStatus.done
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public abort(): void {
|
|
63
|
+
this.controller.abort()
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class ResponseError extends Error {
|
|
68
|
+
constructor(
|
|
69
|
+
message: string,
|
|
70
|
+
public readonly response: Response,
|
|
71
|
+
) {
|
|
72
|
+
super(message)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const abortableFetch = (url: string, options: AbortableFetchOptions) => new AbortableFetch(url, options)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type AddressSuggestion, type AddressSuggestions } from './autosuggest-ui';
|
|
2
|
+
export declare class AutosuggestAddress {
|
|
3
|
+
readonly context: HTMLDivElement;
|
|
4
|
+
readonly input: HTMLInputElement;
|
|
5
|
+
readonly container: HTMLDivElement;
|
|
6
|
+
readonly uprn: HTMLInputElement;
|
|
7
|
+
private readonly findUrl;
|
|
8
|
+
private readonly fetchDelay;
|
|
9
|
+
private fetch;
|
|
10
|
+
private autosuggest;
|
|
11
|
+
constructor(context: HTMLDivElement);
|
|
12
|
+
private checkAPIStatus;
|
|
13
|
+
suggestAddresses(query: string): Promise<AddressSuggestions>;
|
|
14
|
+
private findAddress;
|
|
15
|
+
private mapFindResults;
|
|
16
|
+
private addressMapping;
|
|
17
|
+
onAddressSelect(selectedResult: AddressSuggestion): Promise<void>;
|
|
18
|
+
}
|
|
@@ -1,18 +1,30 @@
|
|
|
1
|
-
import
|
|
1
|
+
import AutosuggestUi, { NoResults } from './autosuggest-ui.js';
|
|
2
2
|
import { abortableFetch, abortError, FetchStatus } from './abortable-fetch.js';
|
|
3
3
|
|
|
4
4
|
// Based on ONSDigital's https://github.com/ONSdigital/design-system/blob/main/src/components/address-input/autosuggest.address.js
|
|
5
|
+
/* eslint-disable import/prefer-default-export, @stylistic/lines-between-class-members */
|
|
5
6
|
const classUPRN = 'hmpps-js-uprn';
|
|
6
7
|
const classInputContainer = 'hmpps-address-autosuggest';
|
|
7
8
|
const classInput = 'hmpps-js-autosuggest-input';
|
|
8
9
|
class AutosuggestAddress {
|
|
10
|
+
context;
|
|
11
|
+
input;
|
|
12
|
+
container;
|
|
13
|
+
uprn;
|
|
14
|
+
findUrl;
|
|
15
|
+
fetchDelay;
|
|
16
|
+
fetch;
|
|
17
|
+
autosuggest;
|
|
9
18
|
constructor(context) {
|
|
10
19
|
this.context = context;
|
|
11
20
|
this.input = context.querySelector(`.${classInput}`);
|
|
12
21
|
this.container = context.querySelector(`.${classInputContainer}`);
|
|
13
22
|
this.uprn = context.querySelector(`.${classUPRN}`);
|
|
14
|
-
this.findUrl = this.container.
|
|
15
|
-
|
|
23
|
+
this.findUrl = this.container.dataset.findUrl;
|
|
24
|
+
const fetchDelay = Number.parseInt(this.container.dataset.fetchDelay, 10);
|
|
25
|
+
if (Number.isSafeInteger(fetchDelay)) {
|
|
26
|
+
this.fetchDelay = fetchDelay;
|
|
27
|
+
}
|
|
16
28
|
// State:
|
|
17
29
|
this.fetch = null;
|
|
18
30
|
// Initialise autosuggest:
|
|
@@ -34,7 +46,7 @@ class AutosuggestAddress {
|
|
|
34
46
|
}
|
|
35
47
|
}
|
|
36
48
|
catch (error) {
|
|
37
|
-
if (error.name !== abortError) {
|
|
49
|
+
if (error && typeof error === 'object' && 'name' in error && error.name !== abortError) {
|
|
38
50
|
this.autosuggest.handleNoResults(NoResults.server_error);
|
|
39
51
|
}
|
|
40
52
|
}
|
|
@@ -51,29 +63,31 @@ class AutosuggestAddress {
|
|
|
51
63
|
this.fetch = abortableFetch(`${this.findUrl}/${query}`, { fetchDelay: this.fetchDelay });
|
|
52
64
|
const data = await this.fetch.send();
|
|
53
65
|
const response = await data.json();
|
|
54
|
-
|
|
55
|
-
const addresses = response.results;
|
|
56
|
-
return this.mapFindResults(addresses, status);
|
|
66
|
+
return this.mapFindResults(response);
|
|
57
67
|
}
|
|
58
|
-
mapFindResults(
|
|
59
|
-
|
|
68
|
+
mapFindResults(response) {
|
|
69
|
+
const { status } = response;
|
|
70
|
+
if (!('results' in response)) {
|
|
60
71
|
return { status };
|
|
72
|
+
}
|
|
73
|
+
const { results } = response;
|
|
61
74
|
return {
|
|
62
75
|
results: this.addressMapping(results),
|
|
63
|
-
status
|
|
76
|
+
status,
|
|
64
77
|
};
|
|
65
78
|
}
|
|
66
79
|
addressMapping(addresses) {
|
|
67
|
-
if (!addresses?.length)
|
|
80
|
+
if (!addresses?.length) {
|
|
68
81
|
return [];
|
|
82
|
+
}
|
|
69
83
|
return addresses.map(address => ({ uprn: address.uprn, displayText: address.addressString }));
|
|
70
84
|
}
|
|
71
85
|
async onAddressSelect(selectedResult) {
|
|
72
86
|
if (this.fetch && this.fetch.status !== FetchStatus.done) {
|
|
73
87
|
this.fetch.abort();
|
|
74
88
|
}
|
|
75
|
-
this.autosuggest.input.value = selectedResult.displayText;
|
|
76
|
-
this.uprn.value = selectedResult.uprn
|
|
89
|
+
this.autosuggest.input.value = selectedResult.displayText ? selectedResult.displayText : '';
|
|
90
|
+
this.uprn.value = `${selectedResult.uprn}`;
|
|
77
91
|
}
|
|
78
92
|
}
|
|
79
93
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Based on ONSDigital's https://github.com/ONSdigital/design-system/blob/main/src/components/address-input/autosuggest.address.js
|
|
2
|
+
/* eslint-disable import/prefer-default-export, @stylistic/lines-between-class-members */
|
|
3
|
+
|
|
4
|
+
import type { AddressAutosuggestResponse } from '../../../../types/public/addressAutosuggest/addressAutosuggestResponse'
|
|
5
|
+
import type { OsAddress } from '../../../../types/public/addressAutosuggest/osAddress'
|
|
6
|
+
import AutosuggestUi, { type AddressSuggestion, type AddressSuggestions, NoResults } from './autosuggest-ui'
|
|
7
|
+
import { type AbortableFetch, abortableFetch, abortError, FetchStatus } from './abortable-fetch'
|
|
8
|
+
|
|
9
|
+
const classUPRN = 'hmpps-js-uprn'
|
|
10
|
+
const classInputContainer = 'hmpps-address-autosuggest'
|
|
11
|
+
const classInput = 'hmpps-js-autosuggest-input'
|
|
12
|
+
|
|
13
|
+
export class AutosuggestAddress {
|
|
14
|
+
public readonly input: HTMLInputElement
|
|
15
|
+
public readonly container: HTMLDivElement
|
|
16
|
+
public readonly uprn: HTMLInputElement
|
|
17
|
+
private readonly findUrl: string
|
|
18
|
+
private readonly fetchDelay: number | undefined
|
|
19
|
+
private fetch: AbortableFetch | null
|
|
20
|
+
private autosuggest: AutosuggestUi
|
|
21
|
+
|
|
22
|
+
constructor(public readonly context: HTMLDivElement) {
|
|
23
|
+
this.input = context.querySelector(`.${classInput}`)!
|
|
24
|
+
this.container = context.querySelector(`.${classInputContainer}`)!
|
|
25
|
+
this.uprn = context.querySelector(`.${classUPRN}`)!
|
|
26
|
+
this.findUrl = this.container.dataset.findUrl!
|
|
27
|
+
const fetchDelay = Number.parseInt(this.container.dataset.fetchDelay!, 10)
|
|
28
|
+
if (Number.isSafeInteger(fetchDelay)) {
|
|
29
|
+
this.fetchDelay = fetchDelay
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// State:
|
|
33
|
+
this.fetch = null
|
|
34
|
+
|
|
35
|
+
// Initialise autosuggest:
|
|
36
|
+
this.autosuggest = new AutosuggestUi({
|
|
37
|
+
context: this.container,
|
|
38
|
+
onSelect: this.onAddressSelect.bind(this),
|
|
39
|
+
suggestionFunction: this.suggestAddresses.bind(this),
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Check API status:
|
|
43
|
+
this.checkAPIStatus()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private async checkAPIStatus(): Promise<void> {
|
|
47
|
+
this.fetch = abortableFetch(`${this.findUrl}/SW1H9AJ`, { fetchDelay: this.fetchDelay })
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const response = await this.fetch.send()
|
|
51
|
+
const status = response && ((await response.json()) as AddressAutosuggestResponse).status
|
|
52
|
+
if (status !== 200) {
|
|
53
|
+
this.autosuggest.handleNoResults(NoResults.server_error)
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (error && typeof error === 'object' && 'name' in error && error.name !== abortError) {
|
|
57
|
+
this.autosuggest.handleNoResults(NoResults.server_error)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public async suggestAddresses(query: string): Promise<AddressSuggestions> {
|
|
63
|
+
if (this.fetch && this.fetch.status !== FetchStatus.done) {
|
|
64
|
+
this.fetch.abort()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Reset any previously selected result:
|
|
68
|
+
this.uprn.value = ''
|
|
69
|
+
|
|
70
|
+
return await this.findAddress(query?.replace(/[^A-Z0-9-.' ]/gi, ''))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private async findAddress(query: string): Promise<AddressSuggestions> {
|
|
74
|
+
this.fetch = abortableFetch(`${this.findUrl}/${query}`, { fetchDelay: this.fetchDelay })
|
|
75
|
+
const data = await this.fetch.send()
|
|
76
|
+
const response: AddressAutosuggestResponse = await data.json()
|
|
77
|
+
return this.mapFindResults(response)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private mapFindResults(response: AddressAutosuggestResponse): AddressSuggestions {
|
|
81
|
+
const { status } = response
|
|
82
|
+
if (!('results' in response)) {
|
|
83
|
+
return { status }
|
|
84
|
+
}
|
|
85
|
+
const { results } = response
|
|
86
|
+
return {
|
|
87
|
+
results: this.addressMapping(results),
|
|
88
|
+
status,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private addressMapping(addresses: OsAddress[]): AddressSuggestion[] {
|
|
93
|
+
if (!addresses?.length) {
|
|
94
|
+
return []
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return addresses.map(address => ({ uprn: address.uprn, displayText: address.addressString }))
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public async onAddressSelect(selectedResult: AddressSuggestion): Promise<void> {
|
|
101
|
+
if (this.fetch && this.fetch.status !== FetchStatus.done) {
|
|
102
|
+
this.fetch.abort()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
this.autosuggest.input.value = selectedResult.displayText ? selectedResult.displayText : ''
|
|
106
|
+
this.uprn.value = `${selectedResult.uprn}`
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export declare const NoResults: {
|
|
2
|
+
readonly type_more: "TYPE_MORE";
|
|
3
|
+
readonly no_match: "NO_MATCH";
|
|
4
|
+
readonly server_error: "SERVER_ERROR";
|
|
5
|
+
};
|
|
6
|
+
type NoResults = typeof NoResults;
|
|
7
|
+
export interface AddressSuggestion {
|
|
8
|
+
displayText?: string;
|
|
9
|
+
uprn?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface AddressSuggestions {
|
|
12
|
+
status: number;
|
|
13
|
+
results?: AddressSuggestion[];
|
|
14
|
+
}
|
|
15
|
+
type AddressSuggestionFunction = (query: string) => Promise<AddressSuggestions>;
|
|
16
|
+
type AddressSelectedCallback = (selectedResult: AddressSuggestion) => Promise<void>;
|
|
17
|
+
interface AutosuggestUiOptions {
|
|
18
|
+
context: HTMLDivElement;
|
|
19
|
+
suggestionFunction: AddressSuggestionFunction;
|
|
20
|
+
onSelect: AddressSelectedCallback;
|
|
21
|
+
}
|
|
22
|
+
export default class AutosuggestUi {
|
|
23
|
+
private readonly context;
|
|
24
|
+
readonly input: HTMLInputElement;
|
|
25
|
+
private readonly resultsContainer;
|
|
26
|
+
private readonly resultsTitleContainer;
|
|
27
|
+
private readonly listbox;
|
|
28
|
+
private readonly instructions;
|
|
29
|
+
private readonly errorContainer;
|
|
30
|
+
private readonly errorTextContainer;
|
|
31
|
+
private readonly ariaStatus;
|
|
32
|
+
private readonly minChars;
|
|
33
|
+
private readonly ariaYouHaveSelected;
|
|
34
|
+
private readonly ariaMinChars;
|
|
35
|
+
private readonly ariaOneResult;
|
|
36
|
+
private readonly ariaNResults;
|
|
37
|
+
private readonly noResults;
|
|
38
|
+
private readonly typeMore;
|
|
39
|
+
private readonly listboxId;
|
|
40
|
+
private readonly errorMessage;
|
|
41
|
+
private readonly stylingBaseClass;
|
|
42
|
+
private readonly fetchSuggestions;
|
|
43
|
+
private readonly onSelect;
|
|
44
|
+
private query;
|
|
45
|
+
private sanitisedQuery;
|
|
46
|
+
private results;
|
|
47
|
+
private resultOptions;
|
|
48
|
+
private numberOfResults;
|
|
49
|
+
private blurring;
|
|
50
|
+
private blurTimeout;
|
|
51
|
+
private scrolling;
|
|
52
|
+
private scrollTimeout;
|
|
53
|
+
private inputTimeout;
|
|
54
|
+
private highlightedResultIndex;
|
|
55
|
+
constructor({ context, onSelect, suggestionFunction }: AutosuggestUiOptions);
|
|
56
|
+
private initialiseUI;
|
|
57
|
+
private bindEventListeners;
|
|
58
|
+
private handleKeydown;
|
|
59
|
+
private handleKeyup;
|
|
60
|
+
private handleChange;
|
|
61
|
+
private handleBlur;
|
|
62
|
+
private handleFocus;
|
|
63
|
+
private handleScroll;
|
|
64
|
+
private checkCharCount;
|
|
65
|
+
private navigateResults;
|
|
66
|
+
private sanitiseAutosuggestText;
|
|
67
|
+
private getSuggestions;
|
|
68
|
+
private unsetResults;
|
|
69
|
+
private clearListbox;
|
|
70
|
+
private handleResults;
|
|
71
|
+
private createListElement;
|
|
72
|
+
handleNoResults(reason: NoResults[keyof NoResults]): void;
|
|
73
|
+
private displayAPIError;
|
|
74
|
+
private setHighlightedResult;
|
|
75
|
+
private selectResult;
|
|
76
|
+
private setAriaStatus;
|
|
77
|
+
private emboldenMatch;
|
|
78
|
+
private escapeRegExp;
|
|
79
|
+
private isAboveViewport;
|
|
80
|
+
private isBelowViewport;
|
|
81
|
+
}
|
|
82
|
+
export {};
|