@smileid/web-components 11.0.2 → 11.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 (93) hide show
  1. package/README.md +61 -0
  2. package/dist/components/smart-camera-web/src/README.md +0 -1
  3. package/dist/esm/{DocumentCaptureScreens-CRx5ymqY.js → DocumentCaptureScreens-DHAfE8VG.js} +191 -185
  4. package/dist/esm/DocumentCaptureScreens-DHAfE8VG.js.map +1 -0
  5. package/dist/esm/{EndUserConsent-D4fd1ovG.js → EndUserConsent-DE6OBSGG.js} +65 -63
  6. package/dist/esm/EndUserConsent-DE6OBSGG.js.map +1 -0
  7. package/dist/esm/{Navigation-CTjK6tLU.js → Navigation-kjll5SgE.js} +17 -9
  8. package/dist/esm/Navigation-kjll5SgE.js.map +1 -0
  9. package/dist/esm/{SelfieCaptureScreens-DuQjKt_K.js → SelfieCaptureScreens-DaREKFi4.js} +3087 -3177
  10. package/dist/esm/SelfieCaptureScreens-DaREKFi4.js.map +1 -0
  11. package/dist/esm/{TotpConsent-CQU5jQi4.js → TotpConsent-DsMJhXD8.js} +13 -9
  12. package/dist/esm/TotpConsent-DsMJhXD8.js.map +1 -0
  13. package/dist/esm/combobox.js +20 -19
  14. package/dist/esm/combobox.js.map +1 -1
  15. package/dist/esm/document.js +1 -1
  16. package/dist/esm/end-user-consent.js +1 -1
  17. package/dist/esm/index-LJce6hoU.js +1360 -0
  18. package/dist/esm/index-LJce6hoU.js.map +1 -0
  19. package/dist/esm/localisation.js +21 -0
  20. package/dist/esm/localisation.js.map +1 -0
  21. package/dist/esm/main.js +34 -17
  22. package/dist/esm/main.js.map +1 -1
  23. package/dist/esm/navigation.js +1 -1
  24. package/dist/esm/{package-C_cKNrUu.js → package-BoRHLVSv.js} +25 -40
  25. package/dist/esm/package-BoRHLVSv.js.map +1 -0
  26. package/dist/esm/selfie.js +1 -1
  27. package/dist/esm/smart-camera-web.js +22 -18
  28. package/dist/esm/smart-camera-web.js.map +1 -1
  29. package/dist/esm/totp-consent.js +1 -1
  30. package/dist/smart-camera-web.js +136 -177
  31. package/dist/smart-camera-web.js.map +1 -1
  32. package/dist/src/components/combobox/src/index.js +424 -1
  33. package/dist/src/components/document/src/index.js +1422 -1
  34. package/dist/src/components/end-user-consent/src/index.js +1573 -1
  35. package/dist/src/components/selfie/src/index.js +1220 -1
  36. package/dist/src/components/signature-pad/src/index.js +787 -1
  37. package/dist/src/components/smart-camera-web/src/SmartCameraWeb.js +2753 -1
  38. package/dist/src/components/totp-consent/src/index.js +1292 -1
  39. package/dist/types/combobox.d.ts +2 -2
  40. package/dist/types/document.d.ts +2 -2
  41. package/dist/types/end-user-consent.d.ts +2 -2
  42. package/dist/types/locale.d.ts +19 -0
  43. package/dist/types/localisation.d.ts +21 -0
  44. package/dist/types/main.d.ts +35 -26
  45. package/dist/types/navigation.d.ts +2 -2
  46. package/dist/types/selfie.d.ts +2 -2
  47. package/dist/types/signature-pad.d.ts +2 -2
  48. package/dist/types/smart-camera-web.d.ts +2 -2
  49. package/dist/types/totp-consent.d.ts +2 -2
  50. package/lib/components/camera-permission/CameraPermission.js +8 -3
  51. package/lib/components/combobox/src/Combobox.js +4 -2
  52. package/lib/components/document/src/DocumentCaptureScreens.js +4 -3
  53. package/lib/components/document/src/DocumentCaptureScreens.stories.js +37 -13
  54. package/lib/components/document/src/document-capture/DocumentCapture.js +20 -14
  55. package/lib/components/document/src/document-capture/DocumentCapture.stories.js +11 -2
  56. package/lib/components/document/src/document-capture-instructions/DocumentCaptureInstructions.js +16 -11
  57. package/lib/components/document/src/document-capture-instructions/DocumentCaptureInstructions.stories.js +14 -5
  58. package/lib/components/document/src/document-capture-review/DocumentCaptureReview.js +11 -7
  59. package/lib/components/document/src/document-capture-review/DocumentCaptureReview.stories.js +14 -5
  60. package/lib/components/end-user-consent/src/EndUserConsent.js +30 -29
  61. package/lib/components/end-user-consent/src/EndUserConsent.stories.js +12 -2
  62. package/lib/components/navigation/src/Navigation.js +15 -2
  63. package/lib/components/navigation/src/Navigation.stories.js +20 -4
  64. package/lib/components/selfie/src/SelfieCaptureScreens.js +3 -7
  65. package/lib/components/selfie/src/SelfieCaptureScreens.stories.js +16 -4
  66. package/lib/components/selfie/src/selfie-capture/SelfieCapture.js +23 -16
  67. package/lib/components/selfie/src/selfie-capture/SelfieCapture.stories.js +19 -7
  68. package/lib/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.js +16 -11
  69. package/lib/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.stories.js +14 -5
  70. package/lib/components/selfie/src/selfie-capture-review/SelfieCaptureReview.js +10 -5
  71. package/lib/components/selfie/src/selfie-capture-review/SelfieCaptureReview.stories.js +14 -5
  72. package/lib/components/selfie/src/selfie-capture-wrapper/SelfieCaptureWrapper.tsx +2 -2
  73. package/lib/components/selfie/src/smartselfie-capture/SmartSelfieCapture.stories.js +47 -0
  74. package/lib/components/selfie/src/smartselfie-capture/SmartSelfieCapture.tsx +2 -2
  75. package/lib/components/selfie/src/smartselfie-capture/components/CaptureControls.tsx +5 -2
  76. package/lib/components/selfie/src/smartselfie-capture/hooks/useCamera.ts +4 -4
  77. package/lib/components/selfie/src/smartselfie-capture/hooks/useFaceCapture.ts +6 -5
  78. package/lib/components/selfie/src/smartselfie-capture/utils/alertMessages.ts +11 -9
  79. package/lib/components/selfie/src/smartselfie-capture/utils/imageCapture.ts +3 -1
  80. package/lib/components/signature-pad/package-lock.json +11 -9
  81. package/lib/components/signature-pad/package.json +1 -1
  82. package/lib/components/totp-consent/src/TotpConsent.js +8 -3
  83. package/lib/domain/camera/src/SmartCamera.js +7 -22
  84. package/lib/domain/constants/src/Constants.js +28 -0
  85. package/lib/domain/file-upload/src/SmartFileUpload.js +9 -10
  86. package/lib/domain/localisation/index.js +456 -0
  87. package/package.json +13 -7
  88. package/dist/esm/DocumentCaptureScreens-CRx5ymqY.js.map +0 -1
  89. package/dist/esm/EndUserConsent-D4fd1ovG.js.map +0 -1
  90. package/dist/esm/Navigation-CTjK6tLU.js.map +0 -1
  91. package/dist/esm/SelfieCaptureScreens-DuQjKt_K.js.map +0 -1
  92. package/dist/esm/TotpConsent-CQU5jQi4.js.map +0 -1
  93. package/dist/esm/package-C_cKNrUu.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import SmartFileUpload from '../../../../domain/file-upload/src/SmartFileUpload';
2
2
  import styles from '../../../../styles/src/styles';
3
3
  import '../../../navigation/src';
4
+ import { t, escapeHtml, getDirection } from '../../../../domain/localisation';
4
5
 
5
6
  function frontDocumentIcon() {
6
7
  return `<svg xmlns="http://www.w3.org/2000/svg" width="173" height="103" viewBox="0 0 173 103" fill="none">
@@ -191,7 +192,7 @@ function templateString() {
191
192
  margin-top: 1rem;
192
193
  }
193
194
  </style>
194
- <div id="document-capture-instructions-screen" class="flow center">
195
+ <div id="document-capture-instructions-screen" class="flow center" dir="${this.direction}">
195
196
  <div class="content-root">
196
197
  <div class="content-header">
197
198
  <smileid-navigation theme-color='${this.themeColor}' ${this.showNavigation ? 'show-navigation' : ''} ${this.hideBack ? 'hide-back' : ''}></smileid-navigation>
@@ -199,12 +200,12 @@ function templateString() {
199
200
  <div class="content-body">
200
201
  <header>
201
202
  ${this.isFrontOfId ? frontDocumentIcon() : backDocumentIcon()}
202
- <h1 class='title-color font-bold'>${this.title}</h1>
203
+ <h1 class='title-color font-bold'>${escapeHtml(this.title)}</h1>
203
204
  <p class="description text-sm font-normal">
204
- We'll use it to verify your identity.
205
+ ${t('document.instructions.description')}
205
206
  </p>
206
207
  <p class="description padding-bottom-2">
207
- Please follow the instructions below.
208
+ ${t('document.instructions.followInstructions')}
208
209
  </p>
209
210
  </header>
210
211
  <div class="instructions-wrapper">
@@ -284,9 +285,9 @@ function templateString() {
284
285
  </defs>
285
286
  </svg>
286
287
  <div class="instruction">
287
- <p class="instruction-header font-bold text-base">Good Light</p>
288
+ <p class="instruction-header font-bold text-base">${t('document.instructions.goodLight.header')}</p>
288
289
  <p class="instruction-body text-xs font-medium">
289
- Make sure the image is taken in a well-lit environment where the ID document is easy to read.
290
+ ${t('document.instructions.goodLight.body')}
290
291
  </p>
291
292
  </div>
292
293
  </div>
@@ -372,9 +373,9 @@ function templateString() {
372
373
  </defs>
373
374
  </svg>
374
375
  <div>
375
- <p class="instruction-header font-bold text-base">Clear Image</p>
376
+ <p class="instruction-header font-bold text-base">${t('document.instructions.clearImage.header')}</p>
376
377
  <p class="instruction-body text-xs font-medium">
377
- Hold your camera steady so the words on the ID are not blurry.
378
+ ${t('document.instructions.clearImage.body')}
378
379
  </p>
379
380
  </div>
380
381
  </div>
@@ -386,7 +387,7 @@ function templateString() {
386
387
  this.supportBothCaptureModes || this.documentCaptureModes === 'camera'
387
388
  ? `
388
389
  <button data-variant='solid full-width' class='button' type='button' id='take-photo'>
389
- Take Photo
390
+ ${t('document.instructions.takePhotoButton')}
390
391
  </button>
391
392
  `
392
393
  : ''
@@ -398,7 +399,7 @@ function templateString() {
398
399
  this.supportBothCaptureModes ? 'outline' : 'solid'
399
400
  }' class='button'>
400
401
  <input type='file' hidden onclick='this.value=null;' id='upload-photo' name='document' accept='image/png, image/jpeg' />
401
- <span>Upload Photo</span>
402
+ <span>${t('document.instructions.uploadPhotoButton')}</span>
402
403
  </label>
403
404
  `
404
405
  : ''
@@ -506,7 +507,7 @@ class DocumentInstruction extends HTMLElement {
506
507
  }
507
508
 
508
509
  get title() {
509
- return this.getAttribute('title') || 'Submit Front of ID';
510
+ return this.getAttribute('title') || t('document.title.front');
510
511
  }
511
512
 
512
513
  get sideOfId() {
@@ -521,6 +522,10 @@ class DocumentInstruction extends HTMLElement {
521
522
  return !this.isFrontOfId;
522
523
  }
523
524
 
525
+ get direction() {
526
+ return this.getAttribute('dir') || getDirection() || 'ltr';
527
+ }
528
+
524
529
  handleBackEvents() {
525
530
  this.dispatchEvent(
526
531
  new CustomEvent('document-capture-instructions.cancelled'),
@@ -1,7 +1,16 @@
1
1
  import './index';
2
+ import { setCurrentLocale } from '../../../../domain/localisation';
2
3
 
3
4
  const meta = {
5
+ args: {
6
+ language: 'en',
7
+ 'theme-color': '#001096',
8
+ },
4
9
  argTypes: {
10
+ language: {
11
+ control: { type: 'select' },
12
+ options: ['en', 'ar'],
13
+ },
5
14
  'theme-color': { control: 'color' },
6
15
  },
7
16
  component: 'document-capture-instructions',
@@ -10,15 +19,15 @@ const meta = {
10
19
  export default meta;
11
20
 
12
21
  export const DocumentInstruction = {
13
- args: {
14
- 'theme-color': '#001096',
15
- },
16
- render: (args) => `
22
+ render: (args) => {
23
+ setCurrentLocale(args.language);
24
+ return `
17
25
  <document-capture-instructions
18
26
  show-navigation
19
27
  document-capture-modes="camera,upload"
20
28
  theme-color='${args['theme-color']}'
21
29
  >
22
30
  </document-capture-instructions>
23
- `,
31
+ `;
32
+ },
24
33
  };
@@ -1,5 +1,6 @@
1
1
  import styles from '../../../../styles/src/styles';
2
2
  import '../../../navigation/src';
3
+ import { t, getDirection } from '../../../../domain/localisation';
3
4
 
4
5
  function templateString() {
5
6
  return `
@@ -218,13 +219,12 @@ function templateString() {
218
219
  }
219
220
  </style>
220
221
  ${styles(this.themeColor)}
221
- <div id='document-capture-review-screen' class='flow center'>
222
+ <div id='document-capture-review-screen' class='flow center' dir='${this.direction}'>
222
223
  <smileid-navigation ${this.showNavigation ? 'show-navigation' : ''} hide-back></smileid-navigation>
223
224
  <h1 class="header-title title-color">
224
- Is the document clear and readable?
225
+ ${t('document.review.question')}
225
226
  </h1>
226
- <p class="description">Make sure all corners of the document
227
- are visible and there is no glare</p>
227
+ <p class="description">${t('document.review.description')}</p>
228
228
  <div class='section | flow'>
229
229
  <div class='id-image-container'>
230
230
  <div class='id-image'>
@@ -233,10 +233,10 @@ function templateString() {
233
233
  </div>
234
234
  <div class='flow action-buttons'>
235
235
  <button data-variant='solid full-width' class='button' type='button' id='select-id-image'>
236
- Yes, my ID is readable
236
+ ${t('document.review.acceptButton')}
237
237
  </button>
238
238
  <button data-variant='ghost full-width' class='button retake-photo' type='button' id='re-capture-id-image'>
239
- No, retake photo
239
+ ${t('document.review.retakeButton')}
240
240
  </button>
241
241
  </div>
242
242
  </div>
@@ -295,7 +295,11 @@ class IdReview extends HTMLElement {
295
295
  }
296
296
 
297
297
  get title() {
298
- return this.getAttribute('title') || 'Submit Front of ID';
298
+ return this.getAttribute('title') || t('document.title.front');
299
+ }
300
+
301
+ get direction() {
302
+ return this.getAttribute('dir') || getDirection() || 'ltr';
299
303
  }
300
304
 
301
305
  handleBackEvents() {
@@ -1,7 +1,16 @@
1
1
  import './index';
2
+ import { setCurrentLocale } from '../../../../domain/localisation';
2
3
 
3
4
  const meta = {
5
+ args: {
6
+ language: 'en',
7
+ 'theme-color': '#001096',
8
+ },
4
9
  argTypes: {
10
+ language: {
11
+ control: { type: 'select' },
12
+ options: ['en', 'ar'],
13
+ },
5
14
  'theme-color': { control: 'color' },
6
15
  },
7
16
  component: 'document-capture-review',
@@ -10,15 +19,15 @@ const meta = {
10
19
  export default meta;
11
20
 
12
21
  export const IdReview = {
13
- args: {
14
- 'theme-color': '#001096',
15
- },
16
- render: (args) => `
22
+ render: (args) => {
23
+ setCurrentLocale(args.language);
24
+ return `
17
25
  <document-capture-review
18
26
  show-navigation
19
27
  data-image="https://placehold.co/600x400"
20
28
  theme-color='${args['theme-color']}'
21
29
  >
22
30
  </document-capture-review>
23
- `,
31
+ `;
32
+ },
24
33
  };
@@ -1,6 +1,7 @@
1
1
  import styles from '../../../styles/src/styles';
2
2
  import '../../totp-consent/src/TotpConsent';
3
3
  import '../../attribution/PoweredBySmileId';
4
+ import { t, tHtml, getDirection } from '../../../domain/localisation';
4
5
 
5
6
  function templateString() {
6
7
  return `
@@ -316,7 +317,7 @@ function templateString() {
316
317
  }
317
318
  </style>
318
319
  ${styles(this.themeColor)}
319
- <div id='consent-screen'>
320
+ <div id='consent-screen' dir='${this.direction}'>
320
321
  <section class='flow center'>
321
322
  <div class="nav ${this.hideBack ? 'justify-right' : ''}">
322
323
  <div class="back-wrapper" ${this.hideBack ? 'hidden' : ''}>
@@ -326,14 +327,14 @@ function templateString() {
326
327
  <path fill="${this.themeColor}" 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"/>
327
328
  </svg>
328
329
  </button>
329
- <div class="back-button-text">Back</div>
330
+ <div class="back-button-text">${t('common.back')}</div>
330
331
  </div>
331
332
  <button data-type='icon' type='button' class='close-iframe'>
332
333
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none">
333
334
  <path fill="#DBDBC4" d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Z" opacity=".4"/>
334
335
  <path fill="#91190F" 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"/>
335
336
  </svg>
336
- <span class='visually-hidden'>Close SmileIdentity Verification frame</span>
337
+ <span class='visually-hidden'>${t('common.close')} SmileIdentity Verification frame</span>
337
338
  </button>
338
339
  </div>
339
340
  <img alt='' width='50' height='50' src='${this.partnerLogoURL}' />
@@ -345,17 +346,17 @@ function templateString() {
345
346
  </svg>
346
347
 
347
348
  <span>
348
- This consent screen is for illustrative purposes only. Demo App does not collect personal ID data.
349
+ ${t('consent.demoTip')}
349
350
  </span>
350
351
  </p>
351
352
  <h1 class='text-base font-bold'>
352
- <span class='theme'>${this.partnerName}</span>
353
- wants to access your
354
- <span class='theme'>${this.idTypeLabel}</span>
355
- information
353
+ ${tHtml('consent.accessRequest', {
354
+ idTypeLabel: { className: 'theme', value: this.idTypeLabel },
355
+ partnerName: { className: 'theme', value: this.partnerName },
356
+ })}
356
357
  </h1>
357
358
  <p class='text-base font-normal'>
358
- This will allow ${this.partnerName} to:
359
+ ${tHtml('consent.allowPartner', { partnerName: this.partnerName })}
359
360
  </p>
360
361
  </section>
361
362
 
@@ -367,8 +368,8 @@ function templateString() {
367
368
  <path d="M14.9238 19.0148L13.8262 17.931C13.8262 17.931 13.6341 17.7956 13.5244 17.7956C13.4146 17.7956 13.3049 17.8498 13.2226 17.931C13.1402 18.0123 13.0854 18.1207 13.0854 18.2291C13.0854 18.3374 13.1402 18.4458 13.2226 18.5271L14.622 19.9089C14.622 19.9089 14.814 20.0443 14.9238 20.0443C15.0335 20.0443 15.1433 19.9901 15.2256 19.9089L17.8323 17.335C17.8323 17.335 17.9421 17.1724 17.9421 17.0369C17.9421 16.9015 17.9146 16.8202 17.8323 16.7389C17.75 16.6576 17.6677 16.6305 17.5579 16.6305C17.4482 16.6305 17.3384 16.6576 17.2835 16.7389L15.0061 18.9877L14.9238 19.0148ZM15.5 24C15.5 24 15.4177 24 15.3902 24C15.3628 24 15.3354 24 15.3079 24C14.0457 23.6207 13.0305 22.8621 12.2073 21.7241C11.4116 20.5862 11 19.3128 11 17.931V15.2217C11 15.0591 11.0549 14.8965 11.1646 14.734C11.2744 14.5714 11.4116 14.4901 11.5488 14.4089L15.1982 13.0542C15.1982 13.0542 15.3902 13 15.5 13C15.6098 13 15.6921 13 15.8018 13.0542L19.4512 14.4089C19.6159 14.4631 19.753 14.5714 19.8354 14.734C19.9177 14.8965 20 15.032 20 15.2217V17.931C20 19.3128 19.5884 20.5862 18.7927 21.7241C17.9969 22.8621 16.9543 23.6478 15.6921 24H15.5Z" fill="#2CC05C"/>
368
369
  </svg>
369
370
  <div class='processing-list__items-item'>
370
- <p class='font-medium text-base processing-list__item__title'>Process your personal details</p>
371
- <p class='text-xs font-medium processing-list__items-item__description'>Partner can process your names, DoB and gender</p>
371
+ <p class='font-medium text-base processing-list__item__title'>${t('consent.processing.personalDetails.title')}</p>
372
+ <p class='text-xs font-medium processing-list__items-item__description'>${t('consent.processing.personalDetails.description')}</p>
372
373
  </div
373
374
  </li>
374
375
  <li class='processing-list__items'>
@@ -378,8 +379,8 @@ function templateString() {
378
379
  <path d="M20 16.83C19.9987 17.2074 19.9131 17.5798 19.7496 17.92C19.5794 18.28 19.359 18.62 19.0686 18.94C18.5779 19.48 18.037 19.87 17.4261 20.12C17.4161 20.12 17.4061 20.13 17.3961 20.13C16.8052 20.37 16.1642 20.5 15.4732 20.5C14.4517 20.5 13.36 20.26 12.2083 19.77C11.0566 19.28 9.90483 18.62 8.76312 17.79C8.37253 17.5 7.98195 17.21 7.61139 16.9L10.8863 13.63C11.1667 13.84 11.4171 14 11.6274 14.11C11.6775 14.13 11.7376 14.16 11.8077 14.19C11.8878 14.22 11.9679 14.23 12.0581 14.23C12.2283 14.23 12.3585 14.17 12.4687 14.06L13.2298 13.31C13.4802 13.06 13.7206 12.87 13.9509 12.75C14.1813 12.61 14.4116 12.54 14.662 12.54C14.8523 12.54 15.0526 12.58 15.2729 12.67C15.4932 12.76 15.7236 12.89 15.9739 13.06L19.2889 15.41C19.5493 15.59 19.7296 15.8 19.8397 16.05C19.9399 16.3 20 16.55 20 16.83Z" fill="#151F72"/>
379
380
  </svg>
380
381
  <div class='processing-list__items-item'>
381
- <p class='font-medium text-base processing-list__item__title'>Process your contact information</p>
382
- <p class='text-xs font-medium processing-list__items-item__description'>Partner can process your phone numbers and address</p>
382
+ <p class='font-medium text-base processing-list__item__title'>${t('consent.processing.contactInfo.title')}</p>
383
+ <p class='text-xs font-medium processing-list__items-item__description'>${t('consent.processing.contactInfo.description')}</p>
383
384
  </div
384
385
  </li>
385
386
  <li class='processing-list__items'>
@@ -402,34 +403,30 @@ function templateString() {
402
403
  </defs>
403
404
  </svg>
404
405
  <div class='processing-list__items-item'>
405
- <p class='font-medium text-base processing-list__item__title'>Process your document information</p>
406
- <p class='text-xs font-medium processing-list__items-item__description'>Partner can process your photo, ID expiration date, country of issuance and document number</p>
406
+ <p class='font-medium text-base processing-list__item__title'>${t('consent.processing.documentInfo.title')}</p>
407
+ <p class='text-xs font-medium processing-list__items-item__description'>${t('consent.processing.documentInfo.description')}</p>
407
408
  </div
408
409
  </li>
409
410
  </ul>
410
411
 
411
412
  <section class='callout | flow center' style='--flow-space: 2rem; margin: var(--flow-space) auto;'>
412
413
  <p>
413
- You can view <span class='theme'>${this.partnerName}</span>'s privacy policy
414
- <a class='theme' href='${
415
- this.partnerPolicyURL
416
- }' rel='noreferer noopener' target='_blank'>here</a>
414
+ ${tHtml('consent.privacyPolicy', { partnerName: this.partnerName })}
415
+ <a class='theme' href='${this.partnerPolicyURL}' rel='noreferer noopener' target='_blank'>${t('consent.privacyPolicyLink')}</a>
417
416
  </p>
418
417
 
419
418
  <p style='--flow-space: .75rem'>
420
- By choosing "Allow", you grant
421
- <span class='theme'>${this.partnerName}</span>
422
- consent to process your personal data to offer you this service
419
+ ${tHtml('consent.grantConsent', { partnerName: this.partnerName })}
423
420
  </p>
424
421
  </section>
425
422
 
426
423
  <section class='flow' style='--flow-space: 2.5rem'>
427
424
  <button id='allow' data-variant='solid'>
428
- Allow
425
+ ${t('common.allow')}
429
426
  </button>
430
427
 
431
428
  <button id='cancel' data-variant='ghost' class='color-danger' style='--flow-space: 1.5rem'>
432
- Cancel
429
+ ${t('common.cancel')}
433
430
  </button>
434
431
  </section>
435
432
  </div>
@@ -557,15 +554,15 @@ function templateString() {
557
554
  </svg>
558
555
 
559
556
  <h1 style='font-size: 36px; line-height: 1; font-weight: 500; --flow-space: 1.5rem'>
560
- Consent Denied
557
+ ${t('consent.denied.title')}
561
558
  </h1>
562
559
 
563
560
  <p class='color-grey' style='--flow-space: 1rem'>
564
- We cannot verify you without your consent
561
+ ${t('consent.denied.message')}
565
562
  </p>
566
563
 
567
564
  <p>
568
- Wish to correct that?
565
+ ${t('consent.denied.prompt')}
569
566
  </p>
570
567
  </section>
571
568
 
@@ -573,11 +570,11 @@ function templateString() {
573
570
  <svg style='transform: rotate(.5turn);' width="25" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
574
571
  <path d="M7 12h11m0 0-4.588-4M18 12l-4.588 4" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
575
572
  </svg>
576
- Go Back
573
+ ${t('consent.denied.goBack')}
577
574
  </button>
578
575
 
579
576
  <button data-variant='outline' id='confirm-consent-rejection' style='--flow-space: 1rem; border-radius: 2rem'>
580
- No, Cancel Verification
577
+ ${t('consent.denied.confirmCancel')}
581
578
  </button>
582
579
 
583
580
  ${this.hideAttribution ? '' : '<powered-by-smile-id></powered-by-smile-id>'}
@@ -725,6 +722,10 @@ class EndUserConsent extends HTMLElement {
725
722
  return this.getAttribute('theme-color') || '#151F72';
726
723
  }
727
724
 
725
+ get direction() {
726
+ return this.getAttribute('dir') || getDirection() || 'ltr';
727
+ }
728
+
728
729
  get token() {
729
730
  return this.getAttribute('token');
730
731
  }
@@ -1,10 +1,16 @@
1
1
  import './EndUserConsent';
2
+ import { setCurrentLocale } from '../../../domain/localisation';
2
3
 
3
4
  const meta = {
4
5
  args: {
6
+ language: 'en',
5
7
  'theme-color': '#001096',
6
8
  },
7
9
  argTypes: {
10
+ language: {
11
+ control: 'select',
12
+ options: ['en', 'ar'],
13
+ },
8
14
  'theme-color': { control: 'color' },
9
15
  },
10
16
  component: 'end-user-consent',
@@ -13,7 +19,10 @@ const meta = {
13
19
  export default meta;
14
20
 
15
21
  export const EndUserConsent = {
16
- render: (args) => `
22
+ render: (args) => {
23
+ setCurrentLocale(args.language);
24
+
25
+ return `
17
26
  <end-user-consent
18
27
  country="NG"
19
28
  id-type="NATIONAL_ID"
@@ -25,5 +34,6 @@ export const EndUserConsent = {
25
34
  partner-logo="https://portal.usesmileid.com/favicon.ico"
26
35
  >
27
36
  </end-user-consent>
28
- `,
37
+ `;
38
+ },
29
39
  };
@@ -1,6 +1,9 @@
1
+ import { t, getDirection } from '../../../domain/localisation';
2
+
1
3
  class Navigation extends HTMLElement {
2
4
  connectedCallback() {
3
5
  const shadow = this.attachShadow({ mode: 'open' });
6
+ const direction = getDirection();
4
7
 
5
8
  const style = document.createElement('style');
6
9
  style.textContent = `
@@ -8,6 +11,12 @@ class Navigation extends HTMLElement {
8
11
  display: flex;
9
12
  max-inline-size: 100%;
10
13
  justify-content: ${this.showBackButton ? 'space-between' : 'flex-end'};
14
+ direction: ${direction};
15
+ }
16
+
17
+ :host([dir="rtl"]) .back-button svg,
18
+ :host .back-button svg[data-rtl="true"] {
19
+ transform: scaleX(-1);
11
20
  }
12
21
 
13
22
  button {
@@ -80,6 +89,7 @@ button[data-type="icon"] {
80
89
  height="24"
81
90
  viewBox="0 0 24 24"
82
91
  fill="none"
92
+ data-rtl="${direction === 'rtl'}"
83
93
  >
84
94
  <path
85
95
  fill="#DBDBC4"
@@ -91,7 +101,7 @@ button[data-type="icon"] {
91
101
  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
102
  />
93
103
  </svg>
94
- <span part="back-button-text">Back</span>
104
+ <span part="back-button-text">${t('navigation.back')}</span>
95
105
  `;
96
106
 
97
107
  const closeButton = document.createElement('button');
@@ -118,7 +128,7 @@ button[data-type="icon"] {
118
128
  />
119
129
  </svg>
120
130
  <span class="visually-hidden"
121
- >Close SmileIdentity Verification frame</span
131
+ >${t('navigation.closeVerificationFrame')}</span
122
132
  >
123
133
  `;
124
134
 
@@ -126,6 +136,9 @@ button[data-type="icon"] {
126
136
  if (this.showBackButton) shadow.appendChild(backButton);
127
137
  shadow.appendChild(closeButton);
128
138
 
139
+ // Set language direction attribute on host for CSS selectors
140
+ this.setAttribute('dir', direction);
141
+
129
142
  // Back Button Controls
130
143
  this.backButton = backButton;
131
144
  this.backButton.addEventListener('click', () => this.handleBack());
@@ -1,24 +1,40 @@
1
1
  import './Navigation';
2
+ import { setCurrentLocale } from '../../../domain/localisation';
2
3
 
3
4
  const meta = {
5
+ args: {
6
+ language: 'en',
7
+ },
8
+ argTypes: {
9
+ language: {
10
+ control: { type: 'select' },
11
+ options: ['en', 'ar'],
12
+ },
13
+ },
4
14
  component: 'smileid-navigation',
5
15
  };
6
16
 
7
17
  export default meta;
8
18
 
9
19
  export const Navigation = {
10
- render: () => `
20
+ render: (args) => {
21
+ setCurrentLocale(args.language);
22
+ return `
11
23
  <smileid-navigation
12
24
  >
13
25
  </smileid-navigation>
14
- `,
26
+ `;
27
+ },
15
28
  };
16
29
 
17
30
  export const NavigationWithBackHidden = {
18
- render: () => `
31
+ render: (args) => {
32
+ setCurrentLocale(args.language);
33
+ return `
19
34
  <smileid-navigation
20
35
  hide-back
21
36
  >
22
37
  </smileid-navigation>
23
- `,
38
+ `;
39
+ },
24
40
  };
@@ -4,17 +4,13 @@ import './selfie-capture-wrapper/index.ts';
4
4
  import SmartCamera from '../../../domain/camera/src/SmartCamera';
5
5
  import styles from '../../../styles/src/styles';
6
6
  import packageJson from '../../../../package.json';
7
+ import { JPEG_QUALITY } from '../../../domain/constants/src/Constants';
7
8
 
8
9
  const COMPONENTS_VERSION = packageJson.version;
9
10
 
10
11
  const smartCameraWeb = document.querySelector('smart-camera-web');
11
12
 
12
- const cropImageFromDataUri = (
13
- dataUri,
14
- cropPercentX = 0,
15
- cropPercentY = 0,
16
- quality = 0.9,
17
- ) =>
13
+ const cropImageFromDataUri = (dataUri, cropPercentX = 0, cropPercentY = 0) =>
18
14
  new Promise((resolve, reject) => {
19
15
  if (!dataUri || typeof dataUri !== 'string') {
20
16
  reject(new Error('Invalid data URI provided'));
@@ -60,7 +56,7 @@ const cropImageFromDataUri = (
60
56
  newHeight,
61
57
  );
62
58
 
63
- const croppedDataUri = canvas.toDataURL('image/jpeg', quality);
59
+ const croppedDataUri = canvas.toDataURL('image/jpeg', JPEG_QUALITY);
64
60
  resolve(croppedDataUri);
65
61
  } catch (error) {
66
62
  reject(new Error(`Failed to process image: ${error.message}`));
@@ -1,12 +1,18 @@
1
+ import { setCurrentLocale } from '../../../domain/localisation';
1
2
  import './SelfieCaptureScreens';
2
3
 
3
4
  const meta = {
4
5
  args: {
5
6
  'hide-attribution': false,
7
+ language: 'en',
6
8
  'theme-color': '#001096',
7
9
  },
8
10
  argTypes: {
9
11
  'hide-attribution': { control: 'boolean' },
12
+ language: {
13
+ control: 'select',
14
+ options: ['en', 'ar'],
15
+ },
10
16
  'theme-color': { control: 'color' },
11
17
  },
12
18
  component: 'selfie-capture-screens',
@@ -15,15 +21,21 @@ const meta = {
15
21
  export default meta;
16
22
 
17
23
  export const SelfieCaptureFlow = {
18
- render: (args) => `
24
+ render: (args) => {
25
+ setCurrentLocale(args.language);
26
+ return `
19
27
  <selfie-capture-screens theme-color='${args['theme-color']}' ${args['hide-attribution'] ? 'hide-attribution' : ''}>
20
28
  </selfie-capture-screens>
21
- `,
29
+ `;
30
+ },
22
31
  };
23
32
 
24
33
  export const SelfieCaptureFlowHiddenInstructions = {
25
- render: (args) => `
34
+ render: (args) => {
35
+ setCurrentLocale(args.language);
36
+ return `
26
37
  <selfie-capture-screens hide-instructions theme-color='${args['theme-color']}' ${args['hide-attribution'] ? 'hide-attribution' : ''}>
27
38
  </selfie-capture-screens>
28
- `,
39
+ `;
40
+ },
29
41
  };