@smileid/web-components 11.5.0 → 11.6.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 (82) hide show
  1. package/dist/esm/DocumentCaptureScreens-DjSTdVP-.js +5398 -0
  2. package/dist/esm/DocumentCaptureScreens-DjSTdVP-.js.map +1 -0
  3. package/dist/esm/{Navigation-Xg565kcu.js → Navigation-6DH3vF4-.js} +2 -2
  4. package/dist/esm/{Navigation-Xg565kcu.js.map → Navigation-6DH3vF4-.js.map} +1 -1
  5. package/dist/esm/{PoweredBySmileId-CxbaihMu.js → PoweredBySmileId-DoKwoPUd.js} +424 -6
  6. package/dist/esm/PoweredBySmileId-DoKwoPUd.js.map +1 -0
  7. package/dist/esm/{SelfieCaptureScreens-D3KuMzZA.js → SelfieCaptureScreens-CtX-4Tco.js} +5 -6
  8. package/dist/esm/SelfieCaptureScreens-CtX-4Tco.js.map +1 -0
  9. package/dist/esm/combobox.js +1 -1
  10. package/dist/esm/document.js +1 -1
  11. package/dist/esm/end-user-consent.js +713 -2
  12. package/dist/esm/end-user-consent.js.map +1 -1
  13. package/dist/esm/index-BqyuTk9f.js +1366 -0
  14. package/dist/esm/{index-CUwa6MPI.js.map → index-BqyuTk9f.js.map} +1 -1
  15. package/dist/esm/localisation.js +1 -1
  16. package/dist/esm/main.js +14 -14
  17. package/dist/esm/navigation.js +1 -1
  18. package/dist/esm/{package-BmVbDNny.js → package-CjZI-cNQ.js} +177 -172
  19. package/dist/esm/{package-BmVbDNny.js.map → package-CjZI-cNQ.js.map} +1 -1
  20. package/dist/esm/selfie.js +1 -1
  21. package/dist/esm/smart-camera-web.js +32 -18
  22. package/dist/esm/smart-camera-web.js.map +1 -1
  23. package/dist/esm/totp-consent.js +731 -2
  24. package/dist/esm/totp-consent.js.map +1 -1
  25. package/dist/esm/validate.js +31 -0
  26. package/dist/esm/validate.js.map +1 -0
  27. package/dist/smart-camera-web.js +696 -321
  28. package/dist/smart-camera-web.js.map +1 -1
  29. package/dist/types/main.d.ts +7 -1
  30. package/dist/types/validate.d.ts +21 -0
  31. package/lib/components/document/src/DocumentCaptureScreens.js +97 -18
  32. package/lib/components/document/src/assets/lottie.d.ts +12 -0
  33. package/lib/components/document/src/assets/svg-inline.d.ts +8 -0
  34. package/lib/components/document/src/document-auto-capture/DocumentAutoCapture.stories.js +75 -0
  35. package/lib/components/document/src/document-auto-capture/DocumentAutoCapture.tsx +1458 -0
  36. package/lib/components/document/src/document-auto-capture/README.md +73 -0
  37. package/lib/components/document/src/document-auto-capture/assets/Greenbook_Shimmer.svg +42 -0
  38. package/lib/components/document/src/document-auto-capture/assets/ID_Back_Shimmer.svg +8 -0
  39. package/lib/components/document/src/document-auto-capture/assets/ID_Front_Shimmer.svg +20 -0
  40. package/lib/components/document/src/document-auto-capture/assets/Passport-Shimmer.svg +143 -0
  41. package/lib/components/document/src/document-auto-capture/assets/shimmers.ts +21 -0
  42. package/lib/components/document/src/document-auto-capture/assets/svg-raw.d.ts +4 -0
  43. package/lib/components/document/src/document-auto-capture/components/CaptureButton.tsx +122 -0
  44. package/lib/components/document/src/document-auto-capture/components/Overlay.tsx +167 -0
  45. package/lib/components/document/src/document-auto-capture/components/TuningPanel.tsx +856 -0
  46. package/lib/components/document/src/document-auto-capture/constants/captureLayout.ts +58 -0
  47. package/lib/components/document/src/document-auto-capture/detection/cvErrorRecovery.ts +40 -0
  48. package/lib/components/document/src/document-auto-capture/detection/documentAspect.ts +20 -0
  49. package/lib/components/document/src/document-auto-capture/detection/qualityScoring.ts +35 -0
  50. package/lib/components/document/src/document-auto-capture/detection/seamRejection.ts +209 -0
  51. package/lib/components/document/src/document-auto-capture/detection/synthesisTiming.ts +10 -0
  52. package/lib/components/document/src/document-auto-capture/hooks/useCamera.ts +117 -0
  53. package/lib/components/document/src/document-auto-capture/hooks/useCardDetection.ts +3059 -0
  54. package/lib/components/document/src/document-auto-capture/index.ts +4 -0
  55. package/lib/components/document/src/document-auto-capture/theme.ts +40 -0
  56. package/lib/components/document/src/document-auto-capture/utils/debug.ts +25 -0
  57. package/lib/components/document/src/document-auto-capture/utils/opencvLoader.ts +86 -0
  58. package/lib/components/document/src/document-capture-instructions/DocumentCaptureInstructions.tsx +327 -244
  59. package/lib/components/document/src/document-capture-review/DocumentCaptureReview.js +153 -189
  60. package/lib/components/document/src/document-capture-submission/DocumentCaptureSubmission.tsx +432 -0
  61. package/lib/components/document/src/document-capture-submission/index.js +3 -0
  62. package/lib/components/selfie/README.md +13 -0
  63. package/lib/components/signature-pad/package.json +1 -1
  64. package/lib/components/smart-camera-web/src/README.md +11 -0
  65. package/lib/components/smart-camera-web/src/SmartCameraWeb.js +25 -1
  66. package/lib/components/totp-consent/src/TotpConsent.js +1 -1
  67. package/package.json +8 -4
  68. package/dist/esm/DocumentCaptureScreens-ucJDu5nH.js +0 -2232
  69. package/dist/esm/DocumentCaptureScreens-ucJDu5nH.js.map +0 -1
  70. package/dist/esm/EndUserConsent-CsiwoThZ.js +0 -717
  71. package/dist/esm/EndUserConsent-CsiwoThZ.js.map +0 -1
  72. package/dist/esm/PoweredBySmileId-CxbaihMu.js.map +0 -1
  73. package/dist/esm/SelfieCaptureScreens-D3KuMzZA.js.map +0 -1
  74. package/dist/esm/TotpConsent-CRtmtudl.js +0 -734
  75. package/dist/esm/TotpConsent-CRtmtudl.js.map +0 -1
  76. package/dist/esm/index-CUwa6MPI.js +0 -1363
  77. package/dist/esm/styles-BTEClL7R.js +0 -419
  78. package/dist/esm/styles-BTEClL7R.js.map +0 -1
  79. /package/lib/components/document/src/assets/lottie/{taking photo of green book passport.lottie → greenbook.lottie} +0 -0
  80. /package/lib/components/document/src/assets/lottie/{taking photo of ID FLIP 2D.lottie → id-card-flip.lottie} +0 -0
  81. /package/lib/components/document/src/assets/lottie/{taking photo of ID.lottie → id-card.lottie} +0 -0
  82. /package/lib/components/document/src/assets/lottie/{taking photo of passport 2.lottie → passport.lottie} +0 -0
@@ -89,6 +89,9 @@ export declare class DocumentCaptureScreens extends HTMLElement {
89
89
  setUpEventListeners(): void;
90
90
  _publishSelectedImages(): void;
91
91
  get hideInstructions(): boolean;
92
+ get autoCaptureFeature(): boolean;
93
+ get autoCapture(): string;
94
+ get autoCaptureTimeout(): string;
92
95
  get hideBackOfId(): boolean;
93
96
  get showNavigation(): "" | "show-navigation";
94
97
  get title(): string;
@@ -346,6 +349,9 @@ export declare class SmartCameraWeb extends HTMLElement {
346
349
  get allowAgentModeTests(): "" | "show-agent-mode-for-tests";
347
350
  get title(): string;
348
351
  get documentCaptureModes(): string;
352
+ get autoCaptureFeature(): "" | "auto-capture-enabled";
353
+ get autoCapture(): string;
354
+ get autoCaptureTimeout(): string;
349
355
  get disableImageTests(): "" | "disable-image-tests";
350
356
  get allowLegacySelfieFallback(): string;
351
357
  get useStrictMode(): "" | "use-strict-mode=\"true\"";
@@ -425,7 +431,7 @@ export declare class TotpConsent extends HTMLElement {
425
431
  resetForm(): void;
426
432
  handleIdNumberValidationErrors(errors: any): void;
427
433
  handleActiveScreenErrors(error: any): void;
428
- validateIdNumber(idNumber: any): any;
434
+ validateIdNumber(idNumber: any): {} | undefined;
429
435
  sessionId: any;
430
436
  mode: any;
431
437
  selectedOtpDeliveryMode: any;
@@ -0,0 +1,21 @@
1
+ export { }
2
+
3
+
4
+
5
+ declare module 'signature_pad' {
6
+ export default class SignaturePad {
7
+ constructor(canvas: HTMLCanvasElement, options?: any);
8
+
9
+ clear(): void;
10
+
11
+ toDataURL(type?: string): string;
12
+
13
+ fromDataURL(dataURL: string): void;
14
+
15
+ isEmpty(): boolean;
16
+
17
+ on(event: string, callback: (...args: unknown[]) => void): void;
18
+
19
+ off(event: string, callback: (...args: unknown[]) => void): void;
20
+ }
21
+ }
@@ -6,6 +6,8 @@ import { t } from '../../../domain/localisation';
6
6
  import './document-capture';
7
7
  import './document-capture-review';
8
8
  import './document-capture-instructions';
9
+ import './document-capture-submission';
10
+ import './document-auto-capture/index.ts';
9
11
  import packageJson from '../../../../package.json';
10
12
 
11
13
  const COMPONENTS_VERSION = packageJson.version;
@@ -49,6 +51,12 @@ class DocumentCaptureScreens extends HTMLElement {
49
51
  }
50
52
 
51
53
  connectedCallback() {
54
+ // Tag name to use for the live capture view. Opt-in via the
55
+ // `auto-capture-enabled` attribute on <document-capture-screens>; defaults to the
56
+ // legacy <document-capture> element so existing flows are untouched.
57
+ const captureTag = this.autoCaptureFeature
58
+ ? 'document-auto-capture'
59
+ : 'document-capture';
52
60
  const instructionsTag = this.newInstructions
53
61
  ? 'document-capture-instructions-v2'
54
62
  : 'document-capture-instructions';
@@ -59,19 +67,19 @@ class DocumentCaptureScreens extends HTMLElement {
59
67
  ${this.documentCaptureModes} ${this.showNavigation} ${this.hideInstructions ? 'hidden' : ''}
60
68
  ${this.hideAttribution}
61
69
  ></${instructionsTag}>
62
- <document-capture id='document-capture-front' side-of-id='Front'
70
+ <${captureTag} id='document-capture-front' side-of-id='Front'
63
71
  ${this.title || `title='${t('document.title.front')}'`} ${this.showNavigation} ${this.hideInstructions ? '' : 'hidden'} ${this.hideAttribution}
64
- ${this.documentCaptureModes} ${this.documentType} theme-color='${this.themeColor}'
65
- ></document-capture>
72
+ ${this.documentCaptureModes} ${this.documentType} ${this.autoCapture} ${this.autoCaptureTimeout} theme-color='${this.themeColor}'
73
+ ></${captureTag}>
66
74
  <${instructionsTag} id='document-capture-instructions-back' side-of-id='Back' title='${t('document.title.back')}'
67
- ${this.documentCaptureModes} ${this.showNavigation} theme-color='${this.themeColor}' ${this.hideAttribution} hidden
75
+ ${this.documentCaptureModes} ${this.documentType} ${this.showNavigation} theme-color='${this.themeColor}' ${this.hideAttribution} hidden
68
76
  ></${instructionsTag}>
69
- <document-capture id='document-capture-back' side-of-id='Back' ${this.title || `title='${t('document.title.back')}'`} ${this.showNavigation}
70
- ${this.documentCaptureModes} theme-color='${this.themeColor}' ${this.hideAttribution}
71
- hidden
72
- ></document-capture>
73
- <document-capture-review id='front-of-document-capture-review' theme-color='${this.themeColor}' ${this.hideAttribution} hidden></document-capture-review>
74
- <document-capture-review id='back-of-document-capture-review' theme-color='${this.themeColor}' ${this.hideAttribution} hidden></document-capture-review>
77
+ <${captureTag} id='document-capture-back' side-of-id='Back' ${this.title || `title='${t('document.title.back')}'`} ${this.showNavigation}
78
+ ${this.documentCaptureModes} ${this.documentType} ${this.autoCapture} ${this.autoCaptureTimeout} theme-color='${this.themeColor}' ${this.hideAttribution}
79
+ hidden
80
+ ></${captureTag}>
81
+ <document-capture-review id='front-of-document-capture-review' theme-color='${this.themeColor}' ${this.showNavigation} ${this.hideAttribution} hidden></document-capture-review>
82
+ <document-capture-review id='back-of-document-capture-review' theme-color='${this.themeColor}' ${this.showNavigation} ${this.hideAttribution} hidden></document-capture-review>
75
83
  </div>
76
84
  `;
77
85
 
@@ -97,7 +105,12 @@ class DocumentCaptureScreens extends HTMLElement {
97
105
  this.thankYouScreen = this.querySelector('thank-you');
98
106
 
99
107
  if (this.hideInstructions) {
100
- getPermissions(this.idCapture);
108
+ if (!this.autoCaptureFeature) {
109
+ // <document-auto-capture> manages its own camera; calling
110
+ // getPermissions here would race a second getUserMedia for the
111
+ // rear camera and freeze the page.
112
+ getPermissions(this.idCapture);
113
+ }
101
114
  this.setActiveScreen(this.idCapture);
102
115
  } else {
103
116
  this.setActiveScreen(this.documentInstruction);
@@ -136,7 +149,7 @@ class DocumentCaptureScreens extends HTMLElement {
136
149
  }),
137
150
  );
138
151
  this.setActiveScreen(this.idCapture);
139
- await getPermissions(this.idCapture);
152
+ if (!this.autoCaptureFeature) await getPermissions(this.idCapture);
140
153
  },
141
154
  );
142
155
  this.documentInstruction.addEventListener(
@@ -160,6 +173,13 @@ class DocumentCaptureScreens extends HTMLElement {
160
173
  smartCameraWeb?.dispatchEvent(
161
174
  new CustomEvent('metadata.document-front-capture-end'),
162
175
  );
176
+ if (this.autoCaptureFeature) {
177
+ smartCameraWeb?.dispatchEvent(
178
+ new CustomEvent('metadata.document-front-origin', {
179
+ detail: { imageOrigin: event.detail.captureOrigin },
180
+ }),
181
+ );
182
+ }
163
183
  this.idReview.setAttribute('data-image', event.detail.previewImage);
164
184
  this._data.images.push({
165
185
  image: event.detail.image.split(',')[1],
@@ -187,7 +207,7 @@ class DocumentCaptureScreens extends HTMLElement {
187
207
  this._data.images.pop();
188
208
  if (this.hideInstructions) {
189
209
  this.setActiveScreen(this.idCapture);
190
- await getPermissions(this.idCapture);
210
+ if (!this.autoCaptureFeature) await getPermissions(this.idCapture);
191
211
  } else {
192
212
  this.setActiveScreen(this.documentInstruction);
193
213
  }
@@ -201,7 +221,8 @@ class DocumentCaptureScreens extends HTMLElement {
201
221
  this._publishSelectedImages();
202
222
  } else if (this.hideInstructions) {
203
223
  this.setActiveScreen(this.idCaptureBack);
204
- await getPermissions(this.idCaptureBack);
224
+ if (!this.autoCaptureFeature)
225
+ await getPermissions(this.idCaptureBack);
205
226
  } else {
206
227
  this.setActiveScreen(this.documentInstructionBack);
207
228
  }
@@ -220,7 +241,7 @@ class DocumentCaptureScreens extends HTMLElement {
220
241
  }),
221
242
  );
222
243
  this.setActiveScreen(this.idCaptureBack);
223
- await getPermissions(this.idCaptureBack);
244
+ if (!this.autoCaptureFeature) await getPermissions(this.idCaptureBack);
224
245
  },
225
246
  );
226
247
 
@@ -231,13 +252,22 @@ class DocumentCaptureScreens extends HTMLElement {
231
252
  this._data.images.pop();
232
253
  if (this.hideInstructions) {
233
254
  this.setActiveScreen(this.idCapture);
234
- await getPermissions(this.idCapture);
255
+ if (!this.autoCaptureFeature) await getPermissions(this.idCapture);
235
256
  } else {
236
257
  this.setActiveScreen(this.documentInstruction);
237
258
  }
238
259
  },
239
260
  );
240
261
 
262
+ // "Skip" on the back instruction screen: the user chooses not to capture
263
+ // the back of the document, so we publish with just the front image.
264
+ this.documentInstructionBack.addEventListener(
265
+ 'document-capture-instructions.skip',
266
+ () => {
267
+ this._publishSelectedImages();
268
+ },
269
+ );
270
+
241
271
  this.documentInstructionBack.addEventListener(
242
272
  'document-capture-instructions.upload',
243
273
  async (event) => {
@@ -258,6 +288,13 @@ class DocumentCaptureScreens extends HTMLElement {
258
288
  smartCameraWeb?.dispatchEvent(
259
289
  new CustomEvent('metadata.document-back-capture-end'),
260
290
  );
291
+ if (this.autoCaptureFeature) {
292
+ smartCameraWeb?.dispatchEvent(
293
+ new CustomEvent('metadata.document-back-origin', {
294
+ detail: { imageOrigin: event.detail.captureOrigin },
295
+ }),
296
+ );
297
+ }
261
298
  this.backOfIdReview.setAttribute('data-image', event.detail.previewImage);
262
299
  this._data.images.push({
263
300
  image: event.detail.image.split(',')[1],
@@ -272,7 +309,7 @@ class DocumentCaptureScreens extends HTMLElement {
272
309
  async () => {
273
310
  if (this.hideInstructions) {
274
311
  this.setActiveScreen(this.idCapture);
275
- await getPermissions(this.idCapture);
312
+ if (!this.autoCaptureFeature) await getPermissions(this.idCapture);
276
313
  } else {
277
314
  this.setActiveScreen(this.documentInstructionBack);
278
315
  }
@@ -289,7 +326,8 @@ class DocumentCaptureScreens extends HTMLElement {
289
326
  this._data.images.pop();
290
327
  if (this.hideInstructions) {
291
328
  this.setActiveScreen(this.idCaptureBack);
292
- await getPermissions(this.idCaptureBack);
329
+ if (!this.autoCaptureFeature)
330
+ await getPermissions(this.idCaptureBack);
293
331
  } else {
294
332
  this.setActiveScreen(this.documentInstructionBack);
295
333
  }
@@ -331,6 +369,41 @@ class DocumentCaptureScreens extends HTMLElement {
331
369
  return this.hasAttribute('hide-instructions');
332
370
  }
333
371
 
372
+ get autoCaptureFeature() {
373
+ return this.hasAttribute('auto-capture-enabled');
374
+ }
375
+
376
+ get autoCapture() {
377
+ if (!this.hasAttribute('auto-capture')) {
378
+ return '';
379
+ }
380
+
381
+ const value = this.getAttribute('auto-capture');
382
+ const normalizedValue = value === '' ? 'autoCapture' : value;
383
+ const allowedValues = [
384
+ 'autoCapture',
385
+ 'autoCaptureOnly',
386
+ 'manualCaptureOnly',
387
+ ];
388
+
389
+ if (allowedValues.includes(normalizedValue)) {
390
+ return `auto-capture='${normalizedValue}'`;
391
+ }
392
+
393
+ return `auto-capture='autoCapture'`;
394
+ }
395
+
396
+ get autoCaptureTimeout() {
397
+ const raw = this.getAttribute('auto-capture-timeout');
398
+ const n = Number(raw);
399
+ // Numeric milliseconds only — omit if not a finite positive number so an
400
+ // arbitrary attribute value can't break/inject the template. The downstream
401
+ // <document-auto-capture> clamps the value to its supported range.
402
+ return raw !== null && Number.isFinite(n) && n > 0
403
+ ? `auto-capture-timeout="${n}"`
404
+ : '';
405
+ }
406
+
334
407
  get hideBackOfId() {
335
408
  return this.hasAttribute('hide-back-of-id');
336
409
  }
@@ -390,6 +463,9 @@ class DocumentCaptureScreens extends HTMLElement {
390
463
  'hide-back-to-host',
391
464
  'show-navigation',
392
465
  'hide-back-of-id',
466
+ 'auto-capture-enabled',
467
+ 'auto-capture',
468
+ 'auto-capture-timeout',
393
469
  'new-instructions',
394
470
  ];
395
471
  }
@@ -401,6 +477,9 @@ class DocumentCaptureScreens extends HTMLElement {
401
477
  case 'hide-back-of-id':
402
478
  case 'hide-back-to-host':
403
479
  case 'show-navigation':
480
+ case 'auto-capture-enabled':
481
+ case 'auto-capture':
482
+ case 'auto-capture-timeout':
404
483
  case 'new-instructions':
405
484
  this.innerHTML = '';
406
485
  this.connectedCallback();
@@ -0,0 +1,12 @@
1
+ // dotLottie animations imported as inlined data URIs via Vite's ?inline query
2
+ // so they ship inside the JS bundle (no loose asset files that break in
3
+ // library mode), mirroring how shimmer SVGs are inlined via ?raw.
4
+ declare module '*.lottie?inline' {
5
+ const src: string;
6
+ export default src;
7
+ }
8
+
9
+ declare module '*.lottie' {
10
+ const src: string;
11
+ export default src;
12
+ }
@@ -0,0 +1,8 @@
1
+ // SVG icons imported as inlined data URIs via Vite's ?inline query so they
2
+ // ship inside the JS bundle (no loose asset files that break in library mode)
3
+ // while still being usable as an <img src>. Used for guideline illustrations
4
+ // that exceed Vite's default inline byte limit.
5
+ declare module '*.svg?inline' {
6
+ const src: string;
7
+ export default src;
8
+ }
@@ -0,0 +1,75 @@
1
+ import { setCurrentLocale } from '../../../../domain/localisation';
2
+ import './index.ts';
3
+
4
+ const meta = {
5
+ args: {
6
+ 'auto-capture': 'autoCapture',
7
+ 'auto-capture-timeout': 20000,
8
+ 'document-type': 'id-card',
9
+ language: 'en',
10
+ 'side-of-id': 'Front',
11
+ 'theme-color': '#001096',
12
+ title: 'Submit Front of ID',
13
+ },
14
+ argTypes: {
15
+ 'auto-capture': {
16
+ control: { type: 'select' },
17
+ options: ['autoCapture', 'autoCaptureOnly', 'manualCaptureOnly'],
18
+ },
19
+ 'auto-capture-timeout': { control: { type: 'number' } },
20
+ 'document-type': {
21
+ control: { type: 'select' },
22
+ options: ['id-card', 'passport', 'greenbook'],
23
+ },
24
+ language: {
25
+ control: { type: 'select' },
26
+ options: ['en', 'ar'],
27
+ },
28
+ 'side-of-id': {
29
+ control: { type: 'select' },
30
+ options: ['Front', 'Back'],
31
+ },
32
+ 'theme-color': { control: 'color' },
33
+ title: { control: 'text' },
34
+ },
35
+ component: 'document-auto-capture',
36
+ render: (args) => {
37
+ setCurrentLocale(args.language);
38
+ return `
39
+ <document-auto-capture
40
+ show-navigation
41
+ document-type="${args['document-type']}"
42
+ auto-capture="${args['auto-capture']}"
43
+ auto-capture-timeout="${args['auto-capture-timeout']}"
44
+ side-of-id="${args['side-of-id']}"
45
+ theme-color='${args['theme-color']}'
46
+ title='${args.title}'
47
+ >
48
+ </document-auto-capture>
49
+ `;
50
+ },
51
+ };
52
+
53
+ export default meta;
54
+
55
+ export const DocumentAutoCapture = {};
56
+
57
+ export const Passport = {
58
+ args: {
59
+ 'document-type': 'passport',
60
+ title: 'Submit Passport Page',
61
+ },
62
+ };
63
+
64
+ export const Greenbook = {
65
+ args: {
66
+ 'document-type': 'greenbook',
67
+ title: 'Submit Greenbook',
68
+ },
69
+ };
70
+
71
+ export const ManualOnly = {
72
+ args: {
73
+ 'auto-capture': 'manualCaptureOnly',
74
+ },
75
+ };