@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,348 @@
1
+ import styles from '../../../../styles/src/styles';
2
+ import '../../../navigation/src';
3
+
4
+ function templateString() {
5
+ return `
6
+ ${styles}
7
+ <style>
8
+ .retake-photo.button[data-variant~="ghost"] {
9
+ color: #FF5805;
10
+ }
11
+ .icon-btn {
12
+ appearance: none;
13
+ background: none;
14
+ border: none;
15
+ color: hsl(0deg 0% 94%);
16
+ cursor: pointer;
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ padding: 4px 8px;
21
+ }
22
+ .justify-right {
23
+ justify-content: end !important;
24
+ }
25
+ .nav {
26
+ display: flex;
27
+ justify-content: space-between;
28
+ }
29
+ .back-wrapper {
30
+ display: flex;
31
+ align-items: center;
32
+ }
33
+ .back-button-text {
34
+ font-size: 11px;
35
+ line-height: 11px;
36
+ color: rgb(21, 31, 114);
37
+ }
38
+ .section {
39
+ border-radius: .5rem;
40
+ margin-left: auto;
41
+ margin-right: auto;
42
+ max-width: 35ch;
43
+ padding: 1rem;
44
+ }
45
+ .selfie-capture-review-image {
46
+ overflow: hidden;
47
+ aspect-ratio: 1/1;
48
+ }
49
+ #review-image {
50
+ scale: 1.75;
51
+ }
52
+ @media (max-aspect-ratio: 1/1) {
53
+ #review-image {
54
+ transform: scaleX(-1) translateY(-10%);
55
+ }
56
+ }
57
+ .tips,
58
+ .powered-by {
59
+ align-items: center;
60
+ border-radius: 0.25rem;
61
+ color: #4e6577;
62
+ display: flex;
63
+ justify-content: center;
64
+ letter-spacing: 0.075em;
65
+ }
66
+ .powered-by {
67
+ box-shadow: 0px 2.57415px 2.57415px rgba(0, 0, 0, 0.06);
68
+ display: inline-flex;
69
+ font-size: 0.5rem;
70
+ }
71
+ .tips {
72
+ margin-left: auto;
73
+ margin-right: auto;
74
+ max-width: 17rem;
75
+ }
76
+ .tips > * + *,
77
+ .powered-by > * + * {
78
+ display: inline-block;
79
+ margin-left: 0.5em;
80
+ }
81
+ .powered-by .company {
82
+ color: #18406d;
83
+ font-weight: 700;
84
+ letter-spacing: 0.15rem;
85
+ }
86
+ .logo-mark {
87
+ background-color: #004071;
88
+ display: inline-block;
89
+ padding: 0.25em 0.5em;
90
+ }
91
+ .logo-mark svg {
92
+ height: auto;
93
+ justify-self: center;
94
+ width: 0.75em;
95
+ }
96
+ #selfie-capture-review-screen {
97
+ block-size: 45rem;
98
+ padding-block: 2rem;
99
+ display: flex;
100
+ flex-direction: column;
101
+ max-block-size: 100%;
102
+ max-inline-size: 40ch;
103
+ }
104
+ #selfie-capture-review-screen .selfie-review-container.landscape {
105
+ height: auto;
106
+ }
107
+ #selfie-capture-review-screen header p {
108
+ margin-block: 0 !important;
109
+ }
110
+ .selfie-review-container.portrait {
111
+ width: 100%;
112
+ position: relative;
113
+ height: calc(200px * 1.4);
114
+ }
115
+
116
+ .selfie-review-container.portrait img {
117
+ width: calc(213px + 0.9rem);
118
+ height: 100%;
119
+ position: absolute;
120
+ top: 239px;
121
+ left: 161px;
122
+ padding-bottom: calc((214px * 1.4) / 3);
123
+ padding-top: calc((191px * 1.4) / 3);
124
+ object-fit: cover;
125
+
126
+ transform: translateX(-50%) translateY(-50%);
127
+ z-index: 1;
128
+ block-size: 100%;
129
+ }
130
+
131
+ .selfie-container,
132
+ .selfie-review-container.landscape {
133
+ height: auto;
134
+ clip-path: inset(15% 20% 20% 20% round 10px);
135
+ overflow: hidden;
136
+ }
137
+
138
+ .selfie-container img {
139
+ background-color: black;
140
+ position: absolute;
141
+ left: 50%;
142
+ height: calc(100% - 6px);
143
+ clip-path: ellipse(101px 118px);
144
+ }
145
+
146
+ .description {
147
+ color: var(--neutral-off-black, #2D2B2A);
148
+ text-align: center;
149
+ /* p */
150
+ font-family: DM Sans;
151
+ font-size: 0.875rem;
152
+ font-style: normal;
153
+ font-weight: 400;
154
+ line-height: 18px;
155
+ }
156
+ .padding-bottom-2 {
157
+ padding-bottom: 2rem;
158
+ }
159
+ .instructions-wrapper {
160
+ display: inline-flex;
161
+ flex-direction: column;
162
+ align-items: flex-start;
163
+ gap: 2rem;
164
+ margin-block-start: 2rem;
165
+ margin-block-end: 4rem;
166
+ }
167
+ .instructions {
168
+ display: flex;
169
+ align-items: center;
170
+ text-align: initial;
171
+ }
172
+ .instructions svg {
173
+ flex-shrink: 0;
174
+ margin-inline-end: 2rem;
175
+ }
176
+ .instructions p {
177
+ margin-block: 0;
178
+ }
179
+ .instruction-body {
180
+ font-size: 0.75rem;
181
+ }
182
+ h1 {
183
+ color: var(--web-digital-blue, #001096);
184
+ text-align: center;
185
+ /* h1 */
186
+ font-size: 1.5rem;
187
+ font-style: normal;
188
+ font-weight: 700;
189
+ line-height: 36px; /* 150% */
190
+ }
191
+ .p2 {
192
+ font-size: 1rem;
193
+ font-style: normal;
194
+ font-weight: 500;
195
+ line-height: 1rem;
196
+ }
197
+ .instruction-header {
198
+ color: var(--web-digital-blue, #001096);
199
+ }
200
+ .h2 {
201
+ font-size: 1rem;
202
+ font-style: normal;
203
+ font-weight: 700;
204
+ line-height: 1.5rem;
205
+ }
206
+ </style>
207
+ ${styles}
208
+ <div id='selfie-capture-review-screen' class='flow center'>
209
+ <smileid-navigation ${this.showNavigation ? 'show-navigation' : ''} hide-back></smileid-navigation>
210
+ <h1 class="header-title text-2xl color-digital-blue font-bold">
211
+ Is your whole face visible and clear in this photo?
212
+ </h1>
213
+ <div class='section | flow'>
214
+ <div class='selfie-review-container ${this.isPortraitCaptureView ? 'portrait' : 'landscape'}'>
215
+ ${
216
+ this.imageSrc
217
+ ? `<img
218
+ alt='your ID card'
219
+ id='document-capture-review-image'
220
+ src='${this.imageSrc}'
221
+ width='396'
222
+ />`
223
+ : ''
224
+ }
225
+ </div>
226
+ <div class='flow action-buttons'>
227
+ <button data-variant='solid full-width' class='button' type='button' id='select-id-image'>
228
+ Yes, use this
229
+ </button>
230
+ <button data-variant='ghost full-width' class='button retake-photo' type='button' id='re-capture-image'>
231
+ No, Retake Selfie
232
+ </button>
233
+ </div>
234
+ ${
235
+ this.hideAttribution
236
+ ? ''
237
+ : `
238
+ <powered-by-smile-id></powered-by-smile-id>
239
+ `
240
+ }
241
+ </div>
242
+ </div>
243
+ `;
244
+ }
245
+
246
+ class SelfieCaptureReview extends HTMLElement {
247
+ constructor() {
248
+ super();
249
+ this.templateString = templateString.bind(this);
250
+ this.render = () => this.templateString();
251
+
252
+ this.attachShadow({ mode: 'open' });
253
+ }
254
+
255
+ connectedCallback() {
256
+ const template = document.createElement('template');
257
+ template.innerHTML = this.render();
258
+ this.shadowRoot.innerHTML = '';
259
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
260
+ this.setUpEventListeners();
261
+ }
262
+
263
+ static get observedAttributes() {
264
+ return ['hide-back-to-host', 'show-navigation', 'data-image'];
265
+ }
266
+
267
+ get hideBack() {
268
+ return this.hasAttribute('hide-back-to-host');
269
+ }
270
+
271
+ get showNavigation() {
272
+ return this.hasAttribute('show-navigation');
273
+ }
274
+
275
+ get themeColor() {
276
+ return this.getAttribute('theme-color') || '#043C93';
277
+ }
278
+
279
+ get hideAttribution() {
280
+ return this.hasAttribute('hide-attribution');
281
+ }
282
+
283
+ get imageSrc() {
284
+ return this.getAttribute('data-image');
285
+ }
286
+
287
+ get title() {
288
+ return this.getAttribute('title') || 'Submit Front of ID';
289
+ }
290
+
291
+ handleBackEvents() {
292
+ this.dispatchEvent(new CustomEvent('selfie-capture-review.cancelled'));
293
+ }
294
+
295
+ handleCloseEvents() {
296
+ this.dispatchEvent(new CustomEvent('selfie-capture-review.close'));
297
+ }
298
+
299
+ attributeChangedCallback(name) {
300
+ switch (name) {
301
+ case 'data-image':
302
+ case 'hide-back-to-host':
303
+ case 'show-navigation':
304
+ this.shadowRoot.innerHTML = this.render();
305
+ this.setUpEventListeners();
306
+ break;
307
+ default:
308
+ break;
309
+ }
310
+ }
311
+
312
+ setUpEventListeners() {
313
+ this.selectImage = this.shadowRoot.querySelector('#select-id-image');
314
+ this.reCaptureImage = this.shadowRoot.querySelector('#re-capture-image');
315
+ this.navigation = this.shadowRoot.querySelector('smileid-navigation');
316
+
317
+ this.navigation.addEventListener('navigation.back', () => {
318
+ this.handleBackEvents();
319
+ });
320
+ this.navigation.addEventListener('navigation.close', () => {
321
+ this.handleCloseEvents();
322
+ });
323
+
324
+ this.selectImage.addEventListener('click', () => {
325
+ this.dispatchEvent(
326
+ new CustomEvent('selfie-capture-review.accepted', {
327
+ detail: {},
328
+ }),
329
+ );
330
+ });
331
+ this.reCaptureImage.addEventListener('click', () => {
332
+ this.dispatchEvent(
333
+ new CustomEvent('selfie-capture-review.rejected', {
334
+ detail: {},
335
+ }),
336
+ );
337
+ });
338
+ }
339
+ }
340
+
341
+ if (
342
+ 'customElements' in window &&
343
+ !customElements.get('selfie-capture-review')
344
+ ) {
345
+ window.customElements.define('selfie-capture-review', SelfieCaptureReview);
346
+ }
347
+
348
+ export default SelfieCaptureReview;
@@ -0,0 +1,17 @@
1
+ import './SelfieCaptureReview';
2
+
3
+ const meta = {
4
+ component: 'selfie-capture-review',
5
+ };
6
+
7
+ export default meta;
8
+
9
+ export const SelfieCaptureReview = {
10
+ render: () => `
11
+ <selfie-capture-review
12
+ show-navigation
13
+ data-image="https://placehold.co/600x400"
14
+ >
15
+ </selfie-capture-review>
16
+ `,
17
+ };
@@ -0,0 +1,3 @@
1
+ import SelfieCaptureReview from './SelfieCaptureReview';
2
+
3
+ export default SelfieCaptureReview;
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@smileid/signature-pad",
3
+ "version": "1.0.0",
4
+ "private": "true",
5
+ "exports": {
6
+ ".": "./index.js"
7
+ },
8
+ "scripts": {
9
+ "lint": "eslint . --ext .js",
10
+ "lint:fix": "eslint . --ext .js --fix"
11
+ },
12
+ "description": "A component to capture signatures using the signature_pad library, and uploads",
13
+ "keywords": [
14
+ "Web Components"
15
+ ],
16
+ "author": "SmileID <support@usesmileid.com> (https://usesmileid.com)",
17
+ "dependencies": {
18
+ "signature_pad": "^4.1.7"
19
+ },
20
+ "devDependencies": {
21
+ "eslint": "^8.57.0",
22
+ "eslint-config-airbnb-base": "^15.0.0",
23
+ "eslint-config-prettier": "^9.1.0",
24
+ "eslint-plugin-cypress": "^2.15.1",
25
+ "eslint-plugin-import": "^2.29.1",
26
+ "eslint-plugin-jest": "^28.2.0",
27
+ "eslint-plugin-prettier": "^5.1.3",
28
+ "prettier": "^3.2.2"
29
+ }
30
+ }