@smileid/web-components 1.0.0-beta → 1.4.2

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 (44) hide show
  1. package/README.md +15 -0
  2. package/components/README.md +1 -1
  3. package/components/camera-permission/CameraPermission.js +6 -2
  4. package/components/camera-permission/CameraPermission.stories.js +10 -4
  5. package/components/document/src/DocumentCaptureScreens.js +41 -11
  6. package/components/document/src/DocumentCaptureScreens.stories.js +16 -12
  7. package/components/document/src/README.md +11 -8
  8. package/components/document/src/document-capture/DocumentCapture.js +299 -231
  9. package/components/document/src/document-capture/DocumentCapture.stories.js +9 -2
  10. package/components/document/src/document-capture/README.md +5 -4
  11. package/components/document/src/document-capture-instructions/DocumentCaptureInstructions.js +33 -33
  12. package/components/document/src/document-capture-instructions/DocumentCaptureInstructions.stories.js +8 -1
  13. package/components/document/src/document-capture-review/DocumentCaptureReview.js +15 -31
  14. package/components/document/src/document-capture-review/DocumentCaptureReview.stories.js +12 -2
  15. package/components/document/src/document-capture-review/README.md +3 -3
  16. package/components/end-user-consent/src/EndUserConsent.js +14 -31
  17. package/components/end-user-consent/src/EndUserConsent.stories.js +8 -2
  18. package/components/navigation/src/Navigation.js +10 -2
  19. package/components/selfie/README.md +28 -4
  20. package/components/selfie/src/SelfieCaptureScreens.js +36 -10
  21. package/components/selfie/src/SelfieCaptureScreens.stories.js +13 -4
  22. package/components/selfie/src/selfie-capture/SelfieCapture.js +95 -23
  23. package/components/selfie/src/selfie-capture/SelfieCapture.stories.js +14 -1
  24. package/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.js +50 -44
  25. package/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.stories.js +8 -2
  26. package/components/selfie/src/selfie-capture-review/SelfieCaptureReview.js +3 -4
  27. package/components/selfie/src/selfie-capture-review/SelfieCaptureReview.stories.js +8 -1
  28. package/components/signature-pad/package-lock.json +3009 -0
  29. package/components/signature-pad/package.json +6 -6
  30. package/components/signature-pad/src/SignaturePad.js +5 -1
  31. package/components/signature-pad/src/SignaturePad.stories.js +10 -2
  32. package/components/smart-camera-web/src/README.md +207 -0
  33. package/components/smart-camera-web/src/SmartCameraWeb.js +56 -7
  34. package/components/smart-camera-web/src/SmartCameraWeb.stories.js +27 -7
  35. package/components/totp-consent/src/TotpConsent.js +15 -3
  36. package/cypress/e2e/smart-camera-web-agent-mode.cy.js +144 -0
  37. package/cypress/e2e/smart-camera-web-complete-flow.cy.js +221 -0
  38. package/cypress/e2e/smart-camera-web.cy.js +1 -1
  39. package/cypress/pages/smart-camera-web-agent-mode.html +36 -0
  40. package/cypress/pages/smart-camera-web-complete-flow.html +42 -0
  41. package/cypress/pages/smart-camera-web.html +1 -1
  42. package/domain/camera/src/SmartCamera.js +28 -0
  43. package/package.json +8 -8
  44. package/styles/src/styles.js +14 -3
@@ -0,0 +1,221 @@
1
+ const themeColor = '#001093';
2
+ context('SmartCameraWeb', () => {
3
+ beforeEach(() => {
4
+ cy.visit('/smart-camera-web-complete-flow');
5
+ });
6
+
7
+ it('should go from the camera screen through to document review with camera capture', () => {
8
+ cy.clock();
9
+
10
+ cy.get('smart-camera-web')
11
+ .invoke('attr', 'theme-color')
12
+ .should('equal', themeColor);
13
+
14
+ cy.get('smart-camera-web')
15
+ .shadow()
16
+ .find('selfie-capture-instructions')
17
+ .invoke('attr', 'theme-color')
18
+ .should('equal', themeColor);
19
+
20
+ cy.get('smart-camera-web')
21
+ .shadow()
22
+ .find('selfie-capture-instructions')
23
+ .shadow()
24
+ .find('#allow')
25
+ .click();
26
+
27
+ cy.get('smart-camera-web')
28
+ .shadow()
29
+ .find('selfie-capture-instructions')
30
+ .should('not.be.visible');
31
+
32
+ cy.get('smart-camera-web')
33
+ .shadow()
34
+ .find('selfie-capture')
35
+ .should('be.visible');
36
+
37
+ cy.get('smart-camera-web')
38
+ .shadow()
39
+ .find('selfie-capture')
40
+ .invoke('attr', 'theme-color')
41
+ .should('equal', themeColor);
42
+
43
+ cy.get('smart-camera-web')
44
+ .shadow()
45
+ .find('selfie-capture')
46
+ .shadow()
47
+ .should('contain.text', 'Take a Selfie');
48
+
49
+ cy.get('smart-camera-web')
50
+ .shadow()
51
+ .find('selfie-capture')
52
+ .shadow()
53
+ .find('#start-image-capture')
54
+ .click();
55
+
56
+ cy.tick(8000);
57
+
58
+ cy.get('smart-camera-web')
59
+ .shadow()
60
+ .find('selfie-capture')
61
+ .shadow()
62
+ .should('not.be.visible');
63
+
64
+ cy.get('smart-camera-web')
65
+ .shadow()
66
+ .find('selfie-capture-review')
67
+ .should('be.visible');
68
+
69
+ cy.get('smart-camera-web')
70
+ .shadow()
71
+ .find('selfie-capture-review')
72
+ .invoke('attr', 'theme-color')
73
+ .should('equal', themeColor);
74
+
75
+ cy.get('smart-camera-web')
76
+ .shadow()
77
+ .find('selfie-capture-review')
78
+ .shadow()
79
+ .find('#select-id-image')
80
+ .click();
81
+
82
+ cy.get('smart-camera-web')
83
+ .shadow()
84
+ .find('selfie-capture-review')
85
+ .shadow()
86
+ .should('not.be.visible');
87
+
88
+ cy.get('smart-camera-web')
89
+ .shadow()
90
+ .find('document-capture-instructions')
91
+ .should('be.visible');
92
+
93
+ cy.get('smart-camera-web')
94
+ .shadow()
95
+ .find('document-capture-instructions#document-capture-instructions-front')
96
+ .invoke('attr', 'theme-color')
97
+ .should('equal', themeColor);
98
+
99
+ cy.get('smart-camera-web')
100
+ .shadow()
101
+ .find('document-capture-instructions#document-capture-instructions-front')
102
+ .shadow()
103
+ .find('#take-photo')
104
+ .click();
105
+
106
+ cy.get('smart-camera-web')
107
+ .shadow()
108
+ .find('document-capture-instructions#document-capture-instructions-front')
109
+ .should('not.be.visible');
110
+
111
+ cy.get('smart-camera-web')
112
+ .shadow()
113
+ .find('document-capture#document-capture-front')
114
+ .should('be.visible');
115
+
116
+ cy.get('smart-camera-web')
117
+ .shadow()
118
+ .find('document-capture#document-capture-front')
119
+ .invoke('attr', 'theme-color')
120
+ .should('equal', themeColor);
121
+
122
+ cy.get('smart-camera-web')
123
+ .shadow()
124
+ .find('document-capture#document-capture-front')
125
+ .shadow()
126
+ .find('#capture-id-image')
127
+ .click();
128
+
129
+ cy.get('smart-camera-web')
130
+ .shadow()
131
+ .find('document-capture#document-capture-front')
132
+ .should('not.be.visible');
133
+
134
+ cy.get('smart-camera-web')
135
+ .shadow()
136
+ .find('document-capture-review#front-of-document-capture-review')
137
+ .should('be.visible');
138
+
139
+ cy.get('smart-camera-web')
140
+ .shadow()
141
+ .find('document-capture-review#front-of-document-capture-review')
142
+ .invoke('attr', 'theme-color')
143
+ .should('equal', themeColor);
144
+
145
+ cy.get('smart-camera-web')
146
+ .shadow()
147
+ .find('document-capture-review#front-of-document-capture-review')
148
+ .shadow()
149
+ .find('#select-id-image')
150
+ .click();
151
+
152
+ cy.get('smart-camera-web')
153
+ .shadow()
154
+ .find('document-capture-review#front-of-document-capture-review')
155
+ .should('not.be.visible');
156
+
157
+ cy.get('smart-camera-web')
158
+ .shadow()
159
+ .find('document-capture-instructions#document-capture-instructions-back')
160
+ .should('be.visible');
161
+
162
+ cy.get('smart-camera-web')
163
+ .shadow()
164
+ .find('document-capture-instructions#document-capture-instructions-back')
165
+ .invoke('attr', 'theme-color')
166
+ .should('equal', themeColor);
167
+
168
+ cy.get('smart-camera-web')
169
+ .shadow()
170
+ .find('document-capture-instructions#document-capture-instructions-back')
171
+ .shadow()
172
+ .find('#take-photo')
173
+ .click();
174
+
175
+ cy.get('smart-camera-web')
176
+ .shadow()
177
+ .find('document-capture-instructions#document-capture-instructions-back')
178
+ .should('not.be.visible');
179
+
180
+ cy.get('smart-camera-web')
181
+ .shadow()
182
+ .find('document-capture#document-capture-back')
183
+ .should('be.visible');
184
+
185
+ cy.get('smart-camera-web')
186
+ .shadow()
187
+ .find('document-capture#document-capture-back')
188
+ .invoke('attr', 'theme-color')
189
+ .should('equal', themeColor);
190
+
191
+ cy.get('smart-camera-web')
192
+ .shadow()
193
+ .find('document-capture#document-capture-back')
194
+ .shadow()
195
+ .find('#capture-id-image')
196
+ .click();
197
+
198
+ cy.get('smart-camera-web')
199
+ .shadow()
200
+ .find('document-capture#document-capture-back')
201
+ .should('not.be.visible');
202
+
203
+ cy.get('smart-camera-web')
204
+ .shadow()
205
+ .find('document-capture-review#back-of-document-capture-review')
206
+ .should('be.visible');
207
+
208
+ cy.get('smart-camera-web')
209
+ .shadow()
210
+ .find('document-capture-review#back-of-document-capture-review')
211
+ .invoke('attr', 'theme-color')
212
+ .should('equal', themeColor);
213
+
214
+ cy.get('smart-camera-web')
215
+ .shadow()
216
+ .find('document-capture-review#back-of-document-capture-review')
217
+ .shadow()
218
+ .find('#select-id-image')
219
+ .click();
220
+ });
221
+ });
@@ -271,7 +271,7 @@ context('SmartCameraWeb', () => {
271
271
  .should('not.be.visible');
272
272
  });
273
273
 
274
- it('should switch to request screen when "Rest"', () => {
274
+ it('should switch to request screen when "Reset"', () => {
275
275
  cy.get('smart-camera-web').then((element) => {
276
276
  element[0].reset();
277
277
  });
@@ -0,0 +1,36 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
+ <style>
6
+ *,
7
+ *::before,
8
+ *::after {
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ body {
13
+ max-width: 100%;
14
+ min-height: 100%;
15
+ }
16
+
17
+ smart-camera-web {
18
+ margin-left: auto;
19
+ margin-right: auto;
20
+ max-width: 40ch;
21
+ padding: 1rem;
22
+ width: auto;
23
+ }
24
+ </style>
25
+ </head>
26
+
27
+ <body>
28
+ <smart-camera-web></smart-camera-web>
29
+
30
+ <script src="./js/components/smart-camera-web/src/SmartCameraWeb.js"></script>
31
+ <script>
32
+ const app = document.querySelector('smart-camera-web');
33
+ app.addEventListener('smart-camera-web.published', async (e) => {});
34
+ </script>
35
+ </body>
36
+ </html>
@@ -0,0 +1,42 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
+ <style>
6
+ *,
7
+ *::before,
8
+ *::after {
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ body {
13
+ max-width: 100%;
14
+ min-height: 100%;
15
+ }
16
+
17
+ smart-camera-web {
18
+ margin-left: auto;
19
+ margin-right: auto;
20
+ max-width: 40ch;
21
+ padding: 1rem;
22
+ width: auto;
23
+ }
24
+ </style>
25
+ </head>
26
+
27
+ <body>
28
+ <smart-camera-web
29
+ capture-id
30
+ disable-image-tests
31
+ theme-color="#001093"
32
+ ></smart-camera-web>
33
+
34
+ <script src="./js/components/smart-camera-web/src/SmartCameraWeb.js"></script>
35
+ <script>
36
+ const app = document.querySelector('smart-camera-web');
37
+ app.addEventListener('smart-camera-web.published', async (e) => {
38
+ console.log(e.detail);
39
+ });
40
+ </script>
41
+ </body>
42
+ </html>
@@ -30,7 +30,7 @@
30
30
  <script src="./js/components/smart-camera-web/src/SmartCameraWeb.js"></script>
31
31
  <script>
32
32
  const app = document.querySelector('smart-camera-web');
33
- app.addEventListener('imagesComputed', async (e) => {
33
+ app.addEventListener('smart-camera-web.published', async (e) => {
34
34
  console.log(e.detail);
35
35
  });
36
36
  </script>
@@ -31,6 +31,34 @@ class SmartCamera {
31
31
  }
32
32
  }
33
33
 
34
+ static async supportsAgentMode() {
35
+ try {
36
+ const devices = await navigator.mediaDevices.enumerateDevices();
37
+ const videoDevices = devices.filter(
38
+ (device) => device.kind === 'videoinput',
39
+ );
40
+
41
+ let hasBackCamera = false;
42
+
43
+ videoDevices.forEach((device) => {
44
+ // Check if the device label or device ID indicates a back camera
45
+ if (
46
+ device.label.toLowerCase().includes('back') ||
47
+ device.label.toLowerCase().includes('rear')
48
+ ) {
49
+ hasBackCamera = true;
50
+ return true;
51
+ }
52
+ return false;
53
+ });
54
+
55
+ return hasBackCamera;
56
+ } catch (error) {
57
+ console.warn('Error accessing media devices: ', error);
58
+ return false;
59
+ }
60
+ }
61
+
34
62
  static isSamsungMultiCameraDevice() {
35
63
  const matchedModelNumber = navigator.userAgent.match(/SM-[N|G]\d{3}/);
36
64
  if (!matchedModelNumber) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smileid/web-components",
3
- "version": "1.0.0-beta",
3
+ "version": "1.4.2",
4
4
  "exports": {
5
5
  ".": "./index.js",
6
6
  "./combobox": "./components/combobox/src/index.js",
@@ -28,19 +28,19 @@
28
28
  "type": "module",
29
29
  "author": "SmileID <support@usesmileid.com> (https://usesmileid.com)",
30
30
  "dependencies": {
31
- "signature_pad": "^4.1.7",
31
+ "signature_pad": "^5.0.2",
32
32
  "validate.js": "^0.13.1"
33
33
  },
34
34
  "devDependencies": {
35
- "cypress": "^13.6.6",
36
- "esbuild": "^0.20.2",
35
+ "cypress": "^13.14.1",
36
+ "esbuild": "^0.21.5",
37
37
  "eslint": "^8.57.0",
38
38
  "eslint-config-airbnb-base": "^15.0.0",
39
39
  "eslint-config-prettier": "^9.1.0",
40
- "eslint-plugin-cypress": "^2.15.1",
40
+ "eslint-plugin-cypress": "^3.3.0",
41
41
  "eslint-plugin-import": "^2.29.1",
42
- "eslint-plugin-jest": "^28.2.0",
43
- "eslint-plugin-prettier": "^5.1.3",
44
- "prettier": "^3.2.2"
42
+ "eslint-plugin-jest": "^28.6.0",
43
+ "eslint-plugin-prettier": "^5.2.1",
44
+ "prettier": "^3.3.3"
45
45
  }
46
46
  }
@@ -1,6 +1,8 @@
1
1
  import typography from './typography';
2
2
 
3
- const styles = `<link rel="preconnect" href="https://fonts.gstatic.com" />
3
+ const styles = (
4
+ themeColor,
5
+ ) => `<link rel="preconnect" href="https://fonts.gstatic.com" />
4
6
  <link
5
7
  href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap"
6
8
  rel="stylesheet"
@@ -9,6 +11,7 @@ const styles = `<link rel="preconnect" href="https://fonts.gstatic.com" />
9
11
  <style>
10
12
  ${typography}
11
13
  :host {
14
+ --theme-color: ${themeColor || '#001096'};
12
15
  --color-active: #001096;
13
16
  --color-default: #2d2b2a;
14
17
  --color-disabled: #848282;
@@ -83,6 +86,14 @@ ${typography}
83
86
  color: #001096;
84
87
  }
85
88
 
89
+ .title-color {
90
+ color: ${themeColor || '#001096'};
91
+ }
92
+
93
+ .theme-color {
94
+ color: ${themeColor || '#001096'};
95
+ }
96
+
86
97
  .center {
87
98
  text-align: center;
88
99
  margin-left: auto;
@@ -114,7 +125,7 @@ ${typography}
114
125
  }
115
126
 
116
127
  .button {
117
- --button-color: var(--color-active);
128
+ --button-color: ${themeColor || 'var(--active-color)'};
118
129
  -webkit-appearance: none;
119
130
  appearance: none;
120
131
  border-radius: 2.5rem;
@@ -310,7 +321,7 @@ ${typography}
310
321
  }
311
322
 
312
323
  .instruction-header {
313
- color: var(--web-digital-blue, #001096);
324
+ color: ${themeColor};
314
325
  }
315
326
 
316
327
  .flex-column {