@smileid/web-components 1.0.0-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/.eslintrc.cjs +72 -0
  2. package/components/README.md +14 -0
  3. package/components/attribution/PoweredBySmileId.js +42 -0
  4. package/components/camera-permission/CameraPermission.js +136 -0
  5. package/components/camera-permission/CameraPermission.stories.js +21 -0
  6. package/components/combobox/src/Combobox.js +586 -0
  7. package/components/combobox/src/index.js +1 -0
  8. package/components/document/src/DocumentCaptureScreens.js +317 -0
  9. package/components/document/src/DocumentCaptureScreens.stories.js +51 -0
  10. package/components/document/src/README.md +108 -0
  11. package/components/document/src/document-capture/DocumentCapture.js +677 -0
  12. package/components/document/src/document-capture/DocumentCapture.stories.js +71 -0
  13. package/components/document/src/document-capture/README.md +89 -0
  14. package/components/document/src/document-capture/index.js +3 -0
  15. package/components/document/src/document-capture-instructions/DocumentCaptureInstructions.js +499 -0
  16. package/components/document/src/document-capture-instructions/DocumentCaptureInstructions.stories.js +17 -0
  17. package/components/document/src/document-capture-instructions/README.md +56 -0
  18. package/components/document/src/document-capture-instructions/index.js +3 -0
  19. package/components/document/src/document-capture-review/DocumentCaptureReview.js +378 -0
  20. package/components/document/src/document-capture-review/DocumentCaptureReview.stories.js +14 -0
  21. package/components/document/src/document-capture-review/README.md +79 -0
  22. package/components/document/src/document-capture-review/index.js +3 -0
  23. package/components/document/src/index.js +3 -0
  24. package/components/end-user-consent/src/EndUserConsent.js +809 -0
  25. package/components/end-user-consent/src/EndUserConsent.stories.js +23 -0
  26. package/components/end-user-consent/src/index.js +4 -0
  27. package/components/navigation/src/Navigation.js +160 -0
  28. package/components/navigation/src/Navigation.stories.js +24 -0
  29. package/components/navigation/src/index.js +3 -0
  30. package/components/selfie/README.md +201 -0
  31. package/components/selfie/src/SelfieCaptureScreens.js +224 -0
  32. package/components/selfie/src/SelfieCaptureScreens.stories.js +21 -0
  33. package/components/selfie/src/index.js +5 -0
  34. package/components/selfie/src/selfie-capture/SelfieCapture.js +878 -0
  35. package/components/selfie/src/selfie-capture/SelfieCapture.stories.js +23 -0
  36. package/components/selfie/src/selfie-capture/index.js +3 -0
  37. package/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.js +638 -0
  38. package/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.stories.js +17 -0
  39. package/components/selfie/src/selfie-capture-instructions/index.js +3 -0
  40. package/components/selfie/src/selfie-capture-review/SelfieCaptureReview.js +348 -0
  41. package/components/selfie/src/selfie-capture-review/SelfieCaptureReview.stories.js +17 -0
  42. package/components/selfie/src/selfie-capture-review/index.js +3 -0
  43. package/components/signature-pad/package.json +30 -0
  44. package/components/signature-pad/src/SignaturePad.js +477 -0
  45. package/components/signature-pad/src/SignaturePad.stories.js +24 -0
  46. package/components/signature-pad/src/index.js +3 -0
  47. package/components/smart-camera-web/src/SmartCameraWeb.js +246 -0
  48. package/components/smart-camera-web/src/SmartCameraWeb.stories.js +35 -0
  49. package/components/totp-consent/src/TotpConsent.js +935 -0
  50. package/components/totp-consent/src/index.js +4 -0
  51. package/cypress/e2e/smart-camera-web-attribution.cy.js +21 -0
  52. package/cypress/e2e/smart-camera-web-back-press.cy.js +481 -0
  53. package/cypress/e2e/smart-camera-web-hide-instructions.cy.js +334 -0
  54. package/cypress/e2e/smart-camera-web.cy.js +309 -0
  55. package/cypress/fixtures/example.json +5 -0
  56. package/cypress/pages/capture-back-of-id-hide-attribution.html +44 -0
  57. package/cypress/pages/capture-back-of-id-navigation.html +72 -0
  58. package/cypress/pages/smart-camera-web-hide-instructions.html +38 -0
  59. package/cypress/pages/smart-camera-web.html +38 -0
  60. package/cypress/support/commands.js +144 -0
  61. package/cypress/support/e2e.js +20 -0
  62. package/cypress.config.js +11 -0
  63. package/domain/camera/src/README.md +38 -0
  64. package/domain/camera/src/SmartCamera.js +81 -0
  65. package/domain/constants/src/Constants.js +27 -0
  66. package/domain/file-upload/README.md +35 -0
  67. package/domain/file-upload/src/SmartFileUpload.js +65 -0
  68. package/esbuild.js +119 -0
  69. package/index.js +5 -0
  70. package/package.json +46 -0
  71. package/styles/README.md +3 -0
  72. package/styles/src/styles.js +348 -0
  73. package/styles/src/typography.js +52 -0
@@ -0,0 +1,23 @@
1
+ import './EndUserConsent';
2
+
3
+ const meta = {
4
+ component: 'end-user-consent',
5
+ };
6
+
7
+ export default meta;
8
+
9
+ export const EndUserConsent = {
10
+ render: () => `
11
+ <end-user-consent
12
+ country="NG"
13
+ id-type="NATIONAL_ID"
14
+ id-type-label="National ID"
15
+ partner-id="007"
16
+ partner-name="SmileID Stories"
17
+ policy-url="https://usesmileid.com/privacy-policy"
18
+ theme-color="#001096"
19
+ partner-logo="https://portal.usesmileid.com/favicon.ico"
20
+ >
21
+ </end-user-consent>
22
+ `,
23
+ };
@@ -0,0 +1,4 @@
1
+ export {
2
+ // eslint-disable-next-line import/prefer-default-export
3
+ EndUserConsent,
4
+ } from './EndUserConsent';
@@ -0,0 +1,160 @@
1
+ class Navigation extends HTMLElement {
2
+ connectedCallback() {
3
+ const shadow = this.attachShadow({ mode: 'open' });
4
+
5
+ const style = document.createElement('style');
6
+ style.textContent = `
7
+ :host {
8
+ display: flex;
9
+ max-inline-size: 100%;
10
+ justify-content: ${this.showBackButton ? 'space-between' : 'flex-end'};
11
+ }
12
+
13
+ button {
14
+ --button-color: var(--color-default);
15
+ --flow-space: 3rem;
16
+ -webkit-appearance: none;
17
+ -moz-appearance: none;
18
+ align-items: center;
19
+ appearance: none;
20
+ background-color: transparent;
21
+ border-radius: 2.5rem;
22
+ border: none;
23
+ color: #ffffff;
24
+ cursor: pointer;
25
+ display: inline-flex;
26
+ font-size: 20px;
27
+ font-weight: 500;
28
+ inline-size: 100%;
29
+ justify-content: center;
30
+ letter-spacing: 0.05ch;
31
+ line-height: 1;
32
+ padding: 1rem 2.5rem;
33
+ text-align: center;
34
+ text-decoration: none;
35
+ }
36
+
37
+ button[data-type="icon"] {
38
+ align-items: center;
39
+ background-color: transparent;
40
+ border: 0;
41
+ cursor: pointer;
42
+ display: flex;
43
+ padding: 0;
44
+ width: auto;
45
+ }
46
+
47
+ :host::part(back-button) {
48
+ display: flex;
49
+ align-items: center;
50
+ }
51
+
52
+ :host::part(back-button-text) {
53
+ line-height: 1;
54
+ color: rgb(21, 31, 114) !important;
55
+ }
56
+
57
+ :host::part(close-button) {
58
+ }
59
+
60
+ .visually-hidden {
61
+ clip: rect(0 0 0 0);
62
+ clip-path: inset(50%);
63
+ block-size: 1px;
64
+ overflow: hidden;
65
+ position: absolute;
66
+ white-space: nowrap;
67
+ inline-size: 1px;
68
+ }
69
+ `;
70
+
71
+ const backButton = document.createElement('button');
72
+ backButton.setAttribute('class', 'back-button');
73
+ backButton.setAttribute('data-type', 'icon');
74
+ backButton.setAttribute('part', 'back-button');
75
+ backButton.setAttribute('type', 'button');
76
+ backButton.innerHTML = `
77
+ <svg
78
+ xmlns="http://www.w3.org/2000/svg"
79
+ width="40"
80
+ height="40"
81
+ viewBox="0 0 24 24"
82
+ fill="none"
83
+ >
84
+ <path
85
+ fill="#DBDBC4"
86
+ d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Z"
87
+ opacity=".4"
88
+ />
89
+ <path
90
+ fill="#001096"
91
+ d="M15.5 11.25h-5.19l1.72-1.72c.29-.29.29-.77 0-1.06a.754.754 0 0 0-1.06 0l-3 3c-.29.29-.29.77 0 1.06l3 3c.15.15.34.22.53.22s.38-.07.53-.22c.29-.29.29-.77 0-1.06l-1.72-1.72h5.19c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"
92
+ />
93
+ </svg>
94
+ <span part="back-button-text">Back</span>
95
+ `;
96
+
97
+ const closeButton = document.createElement('button');
98
+ closeButton.setAttribute('class', 'close-button');
99
+ closeButton.setAttribute('data-type', 'icon');
100
+ closeButton.setAttribute('part', 'close-button');
101
+ closeButton.setAttribute('type', 'button');
102
+ closeButton.innerHTML = `
103
+ <svg
104
+ xmlns="http://www.w3.org/2000/svg"
105
+ viewBox="0 0 24 24"
106
+ width="40"
107
+ height="40"
108
+ fill="none"
109
+ >
110
+ <path
111
+ fill="#DBDBC4"
112
+ d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Z"
113
+ opacity=".4"
114
+ />
115
+ <path
116
+ fill="#91190F"
117
+ d="m13.06 12 2.3-2.3c.29-.29.29-.77 0-1.06a.754.754 0 0 0-1.06 0l-2.3 2.3-2.3-2.3a.754.754 0 0 0-1.06 0c-.29.29-.29.77 0 1.06l2.3 2.3-2.3 2.3c-.29.29-.29.77 0 1.06.15.15.34.22.53.22s.38-.07.53-.22l2.3-2.3 2.3 2.3c.15.15.34.22.53.22s.38-.07.53-.22c.29-.29.29-.77 0-1.06l-2.3-2.3Z"
118
+ />
119
+ </svg>
120
+ <span class="visually-hidden"
121
+ >Close SmileIdentity Verification frame</span
122
+ >
123
+ `;
124
+
125
+ shadow.appendChild(style);
126
+ if (this.showBackButton) shadow.appendChild(backButton);
127
+ shadow.appendChild(closeButton);
128
+
129
+ // Back Button Controls
130
+ this.backButton = backButton;
131
+ this.backButton.addEventListener('click', () => this.handleBack());
132
+
133
+ // Close Button Controls
134
+ this.closeButton = closeButton;
135
+ this.closeButton.addEventListener('click', () => this.handleClose());
136
+ }
137
+
138
+ disconnectedCallback() {
139
+ this.backButton.removeEventListener('click', () => this.handleBack());
140
+ this.closeButton.removeEventListener('click', () => this.handleClose());
141
+ }
142
+
143
+ handleBack() {
144
+ this.dispatchEvent(new CustomEvent('navigation.back'));
145
+ }
146
+
147
+ handleClose() {
148
+ this.dispatchEvent(new CustomEvent('navigation.close'));
149
+ }
150
+
151
+ get showBackButton() {
152
+ return !this.hasAttribute('hide-back');
153
+ }
154
+ }
155
+
156
+ if ('customElements' in window) {
157
+ window.customElements.define('smileid-navigation', Navigation);
158
+ }
159
+
160
+ export default Navigation;
@@ -0,0 +1,24 @@
1
+ import './Navigation';
2
+
3
+ const meta = {
4
+ component: 'smileid-navigation',
5
+ };
6
+
7
+ export default meta;
8
+
9
+ export const Navigation = {
10
+ render: () => `
11
+ <smileid-navigation
12
+ >
13
+ </smileid-navigation>
14
+ `,
15
+ };
16
+
17
+ export const NavigationWithBackHidden = {
18
+ render: () => `
19
+ <smileid-navigation
20
+ hide-back
21
+ >
22
+ </smileid-navigation>
23
+ `,
24
+ };
@@ -0,0 +1,3 @@
1
+ import Navigation from './Navigation';
2
+
3
+ export default Navigation;
@@ -0,0 +1,201 @@
1
+ # SelfieCaptureScreens Web Component
2
+
3
+ ## Overview
4
+
5
+ The `SelfieCaptureScreens` is a custom web component designed to capture selfies and liveness images using a camera. It uses the `SmartCamera` module to interact with the device's camera and handle permissions.
6
+
7
+ ### Importing the Component
8
+
9
+ To use the SelfieCaptureScreens component, you need to import it into your JavaScript file:
10
+
11
+ ```js
12
+ import '@smileid/web-components/selfie-capture-screens';
13
+ ```
14
+
15
+ ### Using the Component
16
+
17
+ You can use the SelfieCaptureScreens component in your HTML like any other HTML element:
18
+
19
+ ```html
20
+ <selfie-capture-screens></selfie-capture-screens>
21
+ ```
22
+
23
+ ### SelfieCaptureScreens Web Component Attributes
24
+
25
+ You can use a mixture of the following attributes to configure the behavior of the component.
26
+
27
+ #### hide-instructions
28
+
29
+ This attribute, when present, hides the instructions for the liveness capture process. It does not require a value.
30
+
31
+ Usage:
32
+
33
+ ```html
34
+ <selfie-capture-screens hide-instructions></selfie-capture-screens>
35
+ ```
36
+
37
+ #### show-navigation
38
+
39
+ This attribute, when present, shows the navigation controls for the liveness capture process. It does not require a value.
40
+
41
+ Usage:
42
+
43
+ ```html
44
+ <selfie-capture-screens show-navigation></selfie-capture-screens>
45
+ ```
46
+
47
+ ### Permissions
48
+
49
+ The `SelfieCaptureScreens` component requires camera permissions to function. It will automatically request these permissions when used. If the permissions are granted, it will remove the `data-camera-error` attribute from the capture screen and set the `data-camera-ready` attribute to true. If the permissions are denied, it will remove the `data-camera-ready` attribute and set the `data-camera-error` attribute with the error message.
50
+
51
+ If you handle the permissions yourself, make sure to set `data-camera-ready` and `data-camera-error` appropriately.
52
+
53
+ ### Error Handling
54
+
55
+ If there is an error while requesting permissions or capturing the images, the `SelfieCaptureScreens` component will handle it and set the `data-camera-error` attribute with the error message.
56
+
57
+ ### Event Handlers
58
+
59
+ To receive the images after they have been captured, you can listen to the custom event `selfie-capture-screens.publish`. The data posted to this event has the structure:
60
+
61
+ ```json
62
+ {
63
+ "detail": {
64
+ "images": [{ "image": "base64 image", "image_type_id": "" }],
65
+ "meta": {
66
+ "version": "version of the library in use"
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ Usage:
73
+
74
+ ```js
75
+ document
76
+ .querySelector('selfie-capture-screens')
77
+ .addEventListener('selfie-capture-screens.publish', function (event) {
78
+ console.log(event.detail);
79
+ });
80
+ ```
81
+
82
+ ### Dependencies
83
+
84
+ The `SelfieCaptureScreens` component depends on the following modules:
85
+
86
+ - [selfie-capture](#selfiecapture-web-component)
87
+ - [selfie-capture-review](#selfie-capture-review-web-component)
88
+ - Selfie-instructions
89
+ - SmartCamera
90
+
91
+ These modules are imported when you use the `SelfieCaptureScreens` component in your projects.
92
+
93
+ ### SelfieCapture Web Component
94
+
95
+ #### Overview
96
+
97
+ The `SelfieCapture` is a custom web component designed to capture selfies and liveness images using a camera. It uses the `SmartCamera` module to interact with the device's camera and handle permissions.
98
+
99
+ #### Importing the SelfieCapture Component
100
+
101
+ To use the SelfieCapture component, you need to import it into your JavaScript file:
102
+
103
+ ```js
104
+ import '@smileid/web-components/selfie-capture';
105
+ ```
106
+
107
+ ### Using the Component
108
+
109
+ You can use the SelfieCapture component in your HTML like any other HTML element:
110
+
111
+ ```html
112
+ <selfie-capture></selfie-capture>
113
+ ```
114
+
115
+ ### SelfieCapture Web Component Attributes
116
+
117
+ You can use a mixture of the following attributes to configure the behavior of the component.
118
+
119
+ #### show-navigation
120
+
121
+ This attribute, when present, shows the navigation controls for the document capture process. It does not require a value.
122
+
123
+ Usage:
124
+
125
+ ```html
126
+ <selfie-capture show-navigation></selfie-capture>
127
+ ```
128
+
129
+ ### Permissions
130
+
131
+ The `SelfieCapture` component requires camera permissions to function. It will automatically request these permissions when used. If the permissions are granted, it will remove the `data-camera-error` attribute from the capture screen and set the `data-camera-ready` attribute to true. If the permissions are denied, it will remove the `data-camera-ready` attribute and set the `data-camera-error` attribute with the error message.
132
+
133
+ If you handle the permissions yourself, make sure to set `data-camera-ready` and `data-camera-error` appropriately.
134
+
135
+ ### Error Handling
136
+
137
+ If there is an error while requesting permissions or capturing the images, the `SelfieCapture` component will handle it and set the `data-camera-error` attribute with the error message.
138
+
139
+ ### Event Handlers
140
+
141
+ To receive the images after they have been captured, you can listen to the custom event `selfie-capture.publish`. The data posted to this event has the structure:
142
+
143
+ ```json
144
+ {
145
+ "detail": {
146
+ "images": [
147
+ {"image": "
148
+
149
+ base64 image", "image_type_id": ""}
150
+ ],
151
+ "meta": {
152
+ "version": "version of the library in use"
153
+ }
154
+ }
155
+ }
156
+ ```
157
+
158
+ Usage:
159
+
160
+ ```js
161
+ document
162
+ .querySelector('selfie-capture')
163
+ .addEventListener('selfie-capture.publish', function (event) {
164
+ console.log(event.detail);
165
+ });
166
+ ```
167
+
168
+ ### SelfieCaptureReview Web Component
169
+
170
+ This component is used to allow the user to verify the accuracy of the capture.
171
+ The user can choose to use the captured image or recapture a new selfie.
172
+
173
+ Usage:
174
+
175
+ ```html
176
+ <selfie-capture-review
177
+ data-image="base64 image"
178
+ show-navigation
179
+ hide-back-to-host
180
+ ></selfie-capture-review>
181
+ ```
182
+
183
+ When a user accepts an image, an event is triggered as shown below:
184
+
185
+ ```js
186
+ document
187
+ .querySelector('selfie-capture-review')
188
+ .addEventListener('selfie-capture-review.accepted', function (event) {});
189
+ ```
190
+
191
+ When a user wants to recapture a selfie, an event is triggered as shown below:
192
+
193
+ ```js
194
+ document
195
+ .querySelector('selfie-capture-review')
196
+ .addEventListener('selfie-capture-review.rejected', function (event) {});
197
+ ```
198
+
199
+ ### Compatibility
200
+
201
+ The SelfieCaptureScreens component is designed to work on all modern browsers that support custom web components. However, it includes a special case for multi-camera Samsung devices to mitigate blurry images at the edges. Please report any issues found on other devices to our support team.
@@ -0,0 +1,224 @@
1
+ import './selfie-capture';
2
+ import './selfie-capture-instructions';
3
+ import './selfie-capture-review';
4
+ import SmartCamera from '../../../domain/camera/src/SmartCamera';
5
+ import styles from '../../../styles/src/styles';
6
+ import { version as COMPONENTS_VERSION } from '../../../package.json';
7
+
8
+ async function getPermissions(captureScreen) {
9
+ try {
10
+ await SmartCamera.getMedia({ audio: false, video: true });
11
+ captureScreen.removeAttribute('data-camera-error');
12
+ captureScreen.setAttribute('data-camera-ready', true);
13
+ } catch (error) {
14
+ captureScreen.removeAttribute('data-camera-ready');
15
+ captureScreen.setAttribute(
16
+ 'data-camera-error',
17
+ SmartCamera.handleCameraError(error),
18
+ );
19
+ }
20
+ }
21
+
22
+ class SelfieCaptureScreens extends HTMLElement {
23
+ constructor() {
24
+ super();
25
+ this.activeScreen = null;
26
+ }
27
+
28
+ connectedCallback() {
29
+ this.innerHTML = `
30
+ ${styles}
31
+ <div>
32
+ <selfie-capture-instructions ${this.showNavigation} ${this.hideAttribution} ${this.hideBack} hidden></selfie-capture-instructions>
33
+ <selfie-capture ${this.showNavigation} ${this.hideAttribution} ${this.disableImageTests} hidden></selfie-capture>
34
+ <selfie-capture-review ${this.showNavigation} ${this.hideAttribution} hidden></selfie-capture-review>
35
+ </div>
36
+ `;
37
+
38
+ this._data = {
39
+ images: [],
40
+ meta: {
41
+ libraryVersion: COMPONENTS_VERSION,
42
+ },
43
+ };
44
+
45
+ this.selfieInstruction = this.querySelector('selfie-capture-instructions');
46
+ this.selfieCapture = this.querySelector('selfie-capture');
47
+ this.selfieReview = this.querySelector('selfie-capture-review');
48
+
49
+ if (this.hideInstructions && !this.hasAttribute('hidden')) {
50
+ getPermissions(this.selfieCapture);
51
+ }
52
+
53
+ if (this.getAttribute('initial-screen') === 'selfie-capture') {
54
+ getPermissions(this.selfieCapture);
55
+ this.setActiveScreen(this.selfieCapture);
56
+ } else if (this.hideInstructions) {
57
+ this.setActiveScreen(this.selfieCapture);
58
+ } else {
59
+ this.setActiveScreen(this.selfieInstruction);
60
+ }
61
+
62
+ this.setUpEventListeners();
63
+ }
64
+
65
+ disconnectedCallback() {
66
+ SmartCamera.stopMedia();
67
+ if (this.activeScreen) {
68
+ this.activeScreen.removeAttribute('hidden');
69
+ }
70
+ this.activeScreen = null;
71
+ this.innerHTML = '';
72
+ }
73
+
74
+ setUpEventListeners() {
75
+ this.selfieInstruction.addEventListener(
76
+ 'selfie-capture-instructions.capture',
77
+ async () => {
78
+ await getPermissions(this.selfieCapture);
79
+ this.setActiveScreen(this.selfieCapture);
80
+ },
81
+ );
82
+ this.selfieInstruction.addEventListener(
83
+ 'selfie-capture-instructions.cancelled',
84
+ () => {
85
+ this.handleBackEvents();
86
+ },
87
+ );
88
+
89
+ this.selfieCapture.addEventListener('selfie-capture.cancelled', () => {
90
+ if (this.hideInstructions) {
91
+ this.dispatchEvent(new CustomEvent('selfie-capture-screens.cancelled'));
92
+ } else {
93
+ this.setActiveScreen(this.selfieInstruction);
94
+ }
95
+ });
96
+
97
+ this.selfieCapture.addEventListener('selfie-capture.publish', (event) => {
98
+ this.selfieReview.setAttribute('data-image', event.detail.referenceImage);
99
+ this._data.images = event.detail.images;
100
+ SmartCamera.stopMedia();
101
+ this.setActiveScreen(this.selfieReview);
102
+ });
103
+
104
+ this.selfieCapture.addEventListener('selfie-capture.cancelled', () => {
105
+ this.selfieCapture.reset();
106
+ SmartCamera.stopMedia();
107
+ if (this.hideInstructions) {
108
+ this.handleBackEvents();
109
+ return;
110
+ }
111
+
112
+ this.setActiveScreen(this.selfieInstruction);
113
+ });
114
+
115
+ this.selfieReview.addEventListener(
116
+ 'selfie-capture-review.rejected',
117
+ async () => {
118
+ this.selfieReview.removeAttribute('data-image');
119
+ this._data.images = [];
120
+ if (this.hideInstructions) {
121
+ this.setActiveScreen(this.selfieCapture);
122
+ await getPermissions(this.selfieCapture);
123
+ } else {
124
+ this.setActiveScreen(this.selfieInstruction);
125
+ }
126
+ },
127
+ );
128
+
129
+ this.selfieReview.addEventListener(
130
+ 'selfie-capture-review.accepted',
131
+ async () => {
132
+ this._publishSelectedImages();
133
+ },
134
+ );
135
+
136
+ [this.selfieInstruction, this.selfieCapture, this.selfieReview].forEach(
137
+ (screen) => {
138
+ screen.addEventListener(
139
+ `${screen.nodeName.toLowerCase()}.close`,
140
+ () => {
141
+ this.handleCloseEvent();
142
+ },
143
+ );
144
+ },
145
+ );
146
+ }
147
+
148
+ _publishSelectedImages() {
149
+ this.dispatchEvent(
150
+ new CustomEvent('selfie-capture-screens.publish', { detail: this._data }),
151
+ );
152
+ }
153
+
154
+ get hideInstructions() {
155
+ return this.hasAttribute('hide-instructions');
156
+ }
157
+
158
+ get hideAttribution() {
159
+ return this.hasAttribute('hide-attribution') ? 'hide-attribution' : '';
160
+ }
161
+
162
+ get hideBackOfId() {
163
+ return this.hasAttribute('hide-back-of-id');
164
+ }
165
+
166
+ get showNavigation() {
167
+ return this.hasAttribute('show-navigation') ? 'show-navigation' : '';
168
+ }
169
+
170
+ get hideBack() {
171
+ return this.hasAttribute('hide-back-to-host') ? 'hide-back' : '';
172
+ }
173
+
174
+ get disableImageTests() {
175
+ return this.hasAttribute('disable-image-tests')
176
+ ? 'disable-image-tests'
177
+ : '';
178
+ }
179
+
180
+ setActiveScreen(screen) {
181
+ this.activeScreen?.setAttribute('hidden', '');
182
+ screen.removeAttribute('hidden');
183
+ this.activeScreen = screen;
184
+ }
185
+
186
+ handleBackEvents() {
187
+ this.dispatchEvent(new CustomEvent('selfie-capture-screens.cancelled'));
188
+ }
189
+
190
+ handleCloseEvent() {
191
+ this.dispatchEvent(new CustomEvent('selfie-capture-screens.close'));
192
+ }
193
+
194
+ static get observedAttributes() {
195
+ return [
196
+ 'title',
197
+ 'hidden',
198
+ 'show-navigation',
199
+ 'hide-back-to-host',
200
+ 'initial-screen',
201
+ ];
202
+ }
203
+
204
+ attributeChangedCallback(name) {
205
+ switch (name) {
206
+ case 'title':
207
+ case 'hidden':
208
+ case 'initial-screen':
209
+ this.connectedCallback();
210
+ break;
211
+ default:
212
+ break;
213
+ }
214
+ }
215
+ }
216
+
217
+ if (
218
+ 'customElements' in window &&
219
+ !customElements.get('selfie-capture-screens')
220
+ ) {
221
+ customElements.define('selfie-capture-screens', SelfieCaptureScreens);
222
+ }
223
+
224
+ export default SelfieCaptureScreens;
@@ -0,0 +1,21 @@
1
+ import './SelfieCaptureScreens';
2
+
3
+ const meta = {
4
+ component: 'selfie-capture-screens',
5
+ };
6
+
7
+ export default meta;
8
+
9
+ export const SelfieCaptureFlow = {
10
+ render: () => `
11
+ <selfie-capture-screens>
12
+ </selfie-capture-screens>
13
+ `,
14
+ };
15
+
16
+ export const SelfieCaptureFlowHiddenInstructions = {
17
+ render: () => `
18
+ <selfie-capture-screens hide-instructions >
19
+ </selfie-capture-screens>
20
+ `,
21
+ };
@@ -0,0 +1,5 @@
1
+ import SelfieCaptureScreens from './SelfieCaptureScreens';
2
+ import SelfieCapture from './selfie-capture/SelfieCapture';
3
+
4
+ export default SelfieCaptureScreens;
5
+ export { SelfieCapture };