@ministryofjustice/hmpps-connect-dps-shared-items 4.4.0 → 5.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.
Files changed (29) hide show
  1. package/README.md +8 -6
  2. package/dist/alertFlags/alertTypes.d.ts +25 -0
  3. package/dist/alertFlags/alertTypes.test.d.ts +1 -0
  4. package/dist/alertFlags/getAlertFlagLabelsForAlerts.d.ts +4 -2
  5. package/dist/assets/dps/components/address-autosuggest/_address-autosuggest.scss +9 -10
  6. package/dist/assets/dps/components/address-autosuggest/abortable-fetch.js +40 -46
  7. package/dist/assets/dps/components/address-autosuggest/autosuggest-address.js +74 -85
  8. package/dist/assets/dps/components/address-autosuggest/autosuggest-ui.js +343 -383
  9. package/dist/assets/dps/components/address-autosuggest/index.js +9 -8
  10. package/dist/assets/dps/components/alert-flag/_alert-flag.scss +8 -5
  11. package/dist/assets/dps/components/alert-flag/macro.njk +1 -1
  12. package/dist/assets/dps/components/modal/_index.scss +148 -0
  13. package/dist/assets/dps/components/modal/index.js +171 -0
  14. package/dist/assets/dps/components/modal/index.ts +203 -0
  15. package/dist/assets/dps/components/modal/macro.njk +48 -0
  16. package/dist/assets/dps/components/webcam-capture/_webcam-capture.scss +11 -10
  17. package/dist/assets/dps/components/webcam-capture/index.js +126 -149
  18. package/dist/assets/dps/components/webcam-capture/macro.njk +10 -26
  19. package/dist/assets/js/all.js +10 -5
  20. package/dist/assets/scss/all.css +844 -0
  21. package/dist/assets/scss/all.scss +4 -3
  22. package/dist/index.cjs +57 -0
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.ts +29 -1
  25. package/dist/index.esm.js +56 -1
  26. package/dist/index.esm.js.map +1 -1
  27. package/dist/types/public/alertFlags/index.d.ts +1 -0
  28. package/package.json +18 -7
  29. package/dist/assets/dps/components/_common.scss +0 -21
package/README.md CHANGED
@@ -27,7 +27,7 @@ npm install @ministryofjustice/hmpps-connect-dps-shared-items
27
27
  Add the `hmpps-connect-dps-shared-items` assets directory to nunjucks configuration in your application:
28
28
 
29
29
  ```javascript
30
- const njkEnv = nunjucks.configure(
30
+ const njkEnv = nunjucks.configure(
31
31
  [
32
32
  path.join(__dirname, '../../server/views'),
33
33
  ...,
@@ -48,11 +48,11 @@ then import the component into your nunjucks file:
48
48
  ### Styling
49
49
  Include the package scss within the `index.scss` file. You can either import all:
50
50
  ```scss
51
- @import 'node_modules/@ministryofjustice/hmpps-connect-dps-shared-items/dist/assets/scss/all';
51
+ @import 'node_modules/@ministryofjustice/hmpps-connect-dps-shared-items/dist/assets/scss/all';
52
52
  ```
53
53
  or import the specific component scss you are using, e.g:
54
54
  ```scss
55
- @import 'node_modules/@ministryofjustice/hmpps-connect-dps-shared-items/dist/assets/dps/components/alert-flag/alert-flag';
55
+ @import 'node_modules/@ministryofjustice/hmpps-connect-dps-shared-items/dist/assets/dps/components/alert-flag/alert-flag';
56
56
  ```
57
57
 
58
58
  ### Client side javascript
@@ -66,10 +66,12 @@ connectDps.initAll()
66
66
 
67
67
  ## Library Components:
68
68
 
69
- 1. [Alert Flag](readme/components/alertFlag/alert-flag.md)
70
- 2. [Address Autosuggest](readme/components/addressAutosuggest/address-autosuggest.md)
71
- 3. [Webcam Upload](readme/components/webcamCapture/webcam-capture.md)
69
+ 1. [Address Autosuggest](readme/components/addressAutosuggest/address-autosuggest.md)
70
+ 2. [Alert Flag](readme/components/alertFlag/alert-flag.md)
71
+ 3. [Modal](readme/components/modal/modal.md)
72
+ 4. [Webcam Upload](readme/components/webcamCapture/webcam-capture.md)
72
73
 
73
74
  ## For Library Developers
74
75
 
75
76
  1. [Publishing to NPM](readme/publishing.md)
77
+ 2. To preview all components locally, run `npm run build` and then `npm start`
@@ -0,0 +1,25 @@
1
+ /** Alert types that have a DPS alert flag style */
2
+ export declare enum AlertType {
3
+ /** Care leaver */
4
+ CareLeaver = "care-leaver",
5
+ /** Ex-armed forces */
6
+ ExArmedForces = "ex-armed-forces",
7
+ /** MAPPP */
8
+ MAPPP = "MAPPP-case",
9
+ /** Medical */
10
+ Medical = "medical",
11
+ /** Risk */
12
+ Risk = "risk",
13
+ /** Security */
14
+ Security = "security",
15
+ /** Self harm */
16
+ SelfHarm = "self-harm",
17
+ /** Vulnerability */
18
+ Vulnerability = "vulnerability",
19
+ /** Other */
20
+ Other = "other"
21
+ }
22
+ /** Find an alert type that has a DPS alert flag style given an alert type code */
23
+ export declare function getAlertTypeForCode(typeCode: string): AlertType | undefined;
24
+ /** Returns the classes for use with the DPS alert flag component (ie. the `AlertFlagLabel.classes` property) */
25
+ export declare function getAlertFlagCssClasses(alertType: AlertType): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,6 @@
1
- import { Alert } from '../types/public/alertFlags/Alert';
2
- import { AlertFlagLabel } from '../types/public/alertFlags/AlertFlagLabel';
1
+ import type { Alert } from '../types/public/alertFlags/Alert';
2
+ import type { AlertFlagLabel } from '../types/public/alertFlags/AlertFlagLabel';
3
+ /** Alerts that need to be flagged prominently */
3
4
  export declare const alertFlagLabels: AlertFlagLabel[];
5
+ /** Returns alert flags that should be displayed prominently */
4
6
  export declare function getAlertFlagLabelsForAlerts(prisonerAlerts: Alert[]): AlertFlagLabel[];
@@ -1,5 +1,4 @@
1
- @import 'govuk-frontend/dist/govuk/helpers/colour';
2
- @import 'govuk-frontend/dist/govuk/settings/colours-applied';
1
+ @use "govuk-frontend/dist/govuk/helpers/colour";
3
2
 
4
3
  .hmpps-address-autosuggest {
5
4
  position: relative;
@@ -15,7 +14,7 @@
15
14
  }
16
15
 
17
16
  &__results {
18
- border: 1px solid $govuk-border-colour;
17
+ border: 1px solid colour.govuk-functional-colour(border);
19
18
  border-radius: 3px;
20
19
  display: none;
21
20
  margin: 0 0 0;
@@ -25,13 +24,13 @@
25
24
  }
26
25
 
27
26
  &__results-title {
28
- background: govuk-colour("light-grey");
29
- border-bottom: 1px solid $govuk-border-colour;
27
+ background: colour.govuk-colour("black", $variant: "tint-95");
28
+ border-bottom: 1px solid colour.govuk-functional-colour(border);
30
29
  padding: 0.25rem 0.5rem;
31
30
  }
32
31
 
33
32
  &__listbox {
34
- background: govuk-colour("white");
33
+ background: colour.govuk-colour("white");
35
34
  list-style: none;
36
35
  margin: 0;
37
36
  padding: 0;
@@ -47,22 +46,22 @@
47
46
  padding: 0.25rem 0.5rem;
48
47
 
49
48
  &:not(:last-child) {
50
- border-bottom: 1px solid $govuk-border-colour;
49
+ border-bottom: 1px solid colour.govuk-functional-colour(border);
51
50
  }
52
51
 
53
52
  &--focused:not(&--no-results) {
54
53
  background: #1d70b8;
55
54
  border-color: #1d70b8;
56
- color: govuk-colour("white");
55
+ color: colour.govuk-colour("white");
57
56
  }
58
57
 
59
58
  &:active:not(&--no-results) {
60
59
  background: var(--ons-color-focus);
61
- color: govuk-colour("black");
60
+ color: colour.govuk-colour("black");
62
61
  }
63
62
 
64
63
  &--no-results {
65
- background: govuk-colour("light-grey");
64
+ background: colour.govuk-colour("black", $variant: "tint-95");
66
65
  cursor: not-allowed;
67
66
  padding: 0.25rem 0.5rem;
68
67
  }
@@ -1,51 +1,45 @@
1
1
  // Based on ONSDigital's https://github.com/ONSdigital/design-system/blob/main/src/js/abortable-fetch.js
2
-
3
- export const FetchStatus = {
4
- unsent: 'UNSENT',
5
- loading: 'LOADING',
6
- done: 'DONE',
7
- }
8
-
9
- export const abortError = 'AbortError'
10
- export const abortTimeout = 'AbortTimeout'
11
-
2
+ const FetchStatus = {
3
+ unsent: 'UNSENT',
4
+ loading: 'LOADING',
5
+ done: 'DONE',
6
+ };
7
+ const abortError = 'AbortError';
8
+ const abortTimeout = 'AbortTimeout';
12
9
  class AbortableFetch {
13
- constructor(url, options) {
14
- this.url = url
15
- this.controller = new window.AbortController()
16
- this.status = FetchStatus.unsent
17
- this.fetchDelay = options?.fetchDelay || 500
18
- }
19
-
20
- async send() {
21
- this.status = FetchStatus.loading
22
- try {
23
- // Abortable delay before querying the API to limit the rate of requests when someone is typing:
24
- await new Promise((resolve) => {
25
- setTimeout(resolve, this.fetchDelay)
26
- this.controller.signal.addEventListener('abort', () => { resolve() }, { once: true })
27
- })
28
-
29
- setTimeout(() => {
30
- this.controller.abort(abortTimeout)
31
- }, 5000)
32
-
33
- const response = await window.fetch(this.url, { signal: this.controller.signal })
34
-
35
- if (!(+response.status === 200)) {
36
- const error = new Error(`API error: ${response?.status ?? 500}`)
37
- error.response = response
38
- throw error
39
- }
40
- return response
41
- } finally {
42
- this.status = FetchStatus.done
10
+ constructor(url, options) {
11
+ this.url = url;
12
+ this.controller = new window.AbortController();
13
+ this.status = FetchStatus.unsent;
14
+ this.fetchDelay = options?.fetchDelay || 500;
15
+ }
16
+ async send() {
17
+ this.status = FetchStatus.loading;
18
+ try {
19
+ // Abortable delay before querying the API to limit the rate of requests when someone is typing:
20
+ await new Promise((resolve) => {
21
+ setTimeout(resolve, this.fetchDelay);
22
+ this.controller.signal.addEventListener('abort', () => { resolve(); }, { once: true });
23
+ });
24
+ setTimeout(() => {
25
+ this.controller.abort(abortTimeout);
26
+ }, 5000);
27
+ const response = await window.fetch(this.url, { signal: this.controller.signal });
28
+ if (!(+response.status === 200)) {
29
+ const error = new Error(`API error: ${response?.status ?? 500}`);
30
+ error.response = response;
31
+ throw error;
32
+ }
33
+ return response;
34
+ }
35
+ finally {
36
+ this.status = FetchStatus.done;
37
+ }
38
+ }
39
+ abort() {
40
+ this.controller.abort();
43
41
  }
44
- }
45
-
46
- abort() {
47
- this.controller.abort()
48
- }
49
42
  }
43
+ const abortableFetch = (url, options) => new AbortableFetch(url, options);
50
44
 
51
- export const abortableFetch = (url, options) => new AbortableFetch(url, options)
45
+ export { FetchStatus, abortError, abortTimeout, abortableFetch };
@@ -1,91 +1,80 @@
1
- // Based on ONSDigital's https://github.com/ONSdigital/design-system/blob/main/src/components/address-input/autosuggest.address.js
2
- import { AutosuggestUi, NoResults } from './autosuggest-ui'
3
- import { abortableFetch, abortError, FetchStatus } from './abortable-fetch'
4
-
5
- const classUPRN = 'hmpps-js-uprn'
6
- const classInputContainer = 'hmpps-address-autosuggest'
7
- const classInput = 'hmpps-js-autosuggest-input'
8
-
9
- export class AutosuggestAddress {
10
- constructor(context) {
11
- this.context = context
12
- this.input = context.querySelector(`.${classInput}`)
13
- this.container = context.querySelector(`.${classInputContainer}`)
14
- this.uprn = context.querySelector(`.${classUPRN}`)
15
- this.findUrl = this.container.getAttribute('data-find-url')
16
- this.fetchDelay = this.container.getAttribute('data-fetch-delay')
17
-
18
- // State:
19
- this.fetch = null
20
-
21
- // Initialise autosuggest:
22
- this.autosuggest = new AutosuggestUi({
23
- context: this.container,
24
- onSelect: this.onAddressSelect.bind(this),
25
- suggestionFunction: this.suggestAddresses.bind(this),
26
- })
27
-
28
- // Check API status:
29
- this.checkAPIStatus()
30
- }
1
+ import { AutosuggestUi, NoResults } from './autosuggest-ui.js';
2
+ import { abortableFetch, abortError, FetchStatus } from './abortable-fetch.js';
31
3
 
32
- async checkAPIStatus() {
33
- this.fetch = abortableFetch(`${this.findUrl}/SW1H9AJ`, { fetchDelay: this.fetchDelay })
34
-
35
- try {
36
- const response = await this.fetch.send()
37
- const status = response && (await response.json()).status
38
- if (status !== 200) {
39
- this.autosuggest.handleNoResults(NoResults.server_error)
40
- }
41
- } catch (error) {
42
- if (error.name !== abortError) {
43
- this.autosuggest.handleNoResults(NoResults.server_error)
44
- }
4
+ // Based on ONSDigital's https://github.com/ONSdigital/design-system/blob/main/src/components/address-input/autosuggest.address.js
5
+ const classUPRN = 'hmpps-js-uprn';
6
+ const classInputContainer = 'hmpps-address-autosuggest';
7
+ const classInput = 'hmpps-js-autosuggest-input';
8
+ class AutosuggestAddress {
9
+ constructor(context) {
10
+ this.context = context;
11
+ this.input = context.querySelector(`.${classInput}`);
12
+ this.container = context.querySelector(`.${classInputContainer}`);
13
+ this.uprn = context.querySelector(`.${classUPRN}`);
14
+ this.findUrl = this.container.getAttribute('data-find-url');
15
+ this.fetchDelay = this.container.getAttribute('data-fetch-delay');
16
+ // State:
17
+ this.fetch = null;
18
+ // Initialise autosuggest:
19
+ this.autosuggest = new AutosuggestUi({
20
+ context: this.container,
21
+ onSelect: this.onAddressSelect.bind(this),
22
+ suggestionFunction: this.suggestAddresses.bind(this),
23
+ });
24
+ // Check API status:
25
+ this.checkAPIStatus();
45
26
  }
46
- }
47
-
48
- async suggestAddresses(query) {
49
- if (this.fetch && this.fetch.status !== FetchStatus.done) {
50
- this.fetch.abort()
27
+ async checkAPIStatus() {
28
+ this.fetch = abortableFetch(`${this.findUrl}/SW1H9AJ`, { fetchDelay: this.fetchDelay });
29
+ try {
30
+ const response = await this.fetch.send();
31
+ const status = response && (await response.json()).status;
32
+ if (status !== 200) {
33
+ this.autosuggest.handleNoResults(NoResults.server_error);
34
+ }
35
+ }
36
+ catch (error) {
37
+ if (error.name !== abortError) {
38
+ this.autosuggest.handleNoResults(NoResults.server_error);
39
+ }
40
+ }
51
41
  }
52
-
53
- // Reset any previously selected result:
54
- this.uprn.value = ''
55
-
56
- return await this.findAddress(query?.replace(/[^A-Z0-9-.' ]/gi, ''))
57
- }
58
-
59
- async findAddress(query) {
60
- this.fetch = abortableFetch(`${this.findUrl}/${query}`, { fetchDelay: this.fetchDelay })
61
- const data = await this.fetch.send()
62
- const response = await data.json()
63
- const status = response.status
64
- const addresses = response.results
65
- return this.mapFindResults(addresses, status)
66
- }
67
-
68
- mapFindResults(results, status) {
69
- if (!results) return { status }
70
-
71
- return {
72
- results: this.addressMapping(results),
73
- status: status,
42
+ async suggestAddresses(query) {
43
+ if (this.fetch && this.fetch.status !== FetchStatus.done) {
44
+ this.fetch.abort();
45
+ }
46
+ // Reset any previously selected result:
47
+ this.uprn.value = '';
48
+ return await this.findAddress(query?.replace(/[^A-Z0-9-.' ]/gi, ''));
74
49
  }
75
- }
76
-
77
- addressMapping(addresses) {
78
- if (!addresses?.length) return []
79
-
80
- return addresses.map(address => ({ uprn: address.uprn, displayText: address.addressString }))
81
- }
82
-
83
- async onAddressSelect(selectedResult) {
84
- if (this.fetch && this.fetch.status !== FetchStatus.done) {
85
- this.fetch.abort()
50
+ async findAddress(query) {
51
+ this.fetch = abortableFetch(`${this.findUrl}/${query}`, { fetchDelay: this.fetchDelay });
52
+ const data = await this.fetch.send();
53
+ const response = await data.json();
54
+ const status = response.status;
55
+ const addresses = response.results;
56
+ return this.mapFindResults(addresses, status);
57
+ }
58
+ mapFindResults(results, status) {
59
+ if (!results)
60
+ return { status };
61
+ return {
62
+ results: this.addressMapping(results),
63
+ status: status,
64
+ };
65
+ }
66
+ addressMapping(addresses) {
67
+ if (!addresses?.length)
68
+ return [];
69
+ return addresses.map(address => ({ uprn: address.uprn, displayText: address.addressString }));
70
+ }
71
+ async onAddressSelect(selectedResult) {
72
+ if (this.fetch && this.fetch.status !== FetchStatus.done) {
73
+ this.fetch.abort();
74
+ }
75
+ this.autosuggest.input.value = selectedResult.displayText;
76
+ this.uprn.value = selectedResult.uprn;
86
77
  }
87
-
88
- this.autosuggest.input.value = selectedResult.displayText
89
- this.uprn.value = selectedResult.uprn
90
- }
91
78
  }
79
+
80
+ export { AutosuggestAddress };