@smileid/web-components 11.0.3 → 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.
- package/README.md +61 -0
- package/dist/components/smart-camera-web/src/README.md +0 -1
- package/dist/esm/{DocumentCaptureScreens-C5BhNB-0.js → DocumentCaptureScreens-DHAfE8VG.js} +191 -185
- package/dist/esm/DocumentCaptureScreens-DHAfE8VG.js.map +1 -0
- package/dist/esm/{EndUserConsent-D4fd1ovG.js → EndUserConsent-DE6OBSGG.js} +65 -63
- package/dist/esm/EndUserConsent-DE6OBSGG.js.map +1 -0
- package/dist/esm/{Navigation-CTjK6tLU.js → Navigation-kjll5SgE.js} +17 -9
- package/dist/esm/Navigation-kjll5SgE.js.map +1 -0
- package/dist/esm/{SelfieCaptureScreens-KoQpCxtc.js → SelfieCaptureScreens-DaREKFi4.js} +3087 -3159
- package/dist/esm/SelfieCaptureScreens-DaREKFi4.js.map +1 -0
- package/dist/esm/{TotpConsent-CQU5jQi4.js → TotpConsent-DsMJhXD8.js} +13 -9
- package/dist/esm/TotpConsent-DsMJhXD8.js.map +1 -0
- package/dist/esm/combobox.js +20 -19
- package/dist/esm/combobox.js.map +1 -1
- package/dist/esm/document.js +1 -1
- package/dist/esm/end-user-consent.js +1 -1
- package/dist/esm/index-LJce6hoU.js +1360 -0
- package/dist/esm/index-LJce6hoU.js.map +1 -0
- package/dist/esm/localisation.js +21 -0
- package/dist/esm/localisation.js.map +1 -0
- package/dist/esm/main.js +34 -17
- package/dist/esm/main.js.map +1 -1
- package/dist/esm/navigation.js +1 -1
- package/dist/esm/{package-B-UwEdv7.js → package-BoRHLVSv.js} +25 -40
- package/dist/esm/package-BoRHLVSv.js.map +1 -0
- package/dist/esm/selfie.js +1 -1
- package/dist/esm/smart-camera-web.js +22 -18
- package/dist/esm/smart-camera-web.js.map +1 -1
- package/dist/esm/totp-consent.js +1 -1
- package/dist/smart-camera-web.js +136 -152
- package/dist/smart-camera-web.js.map +1 -1
- package/dist/src/components/combobox/src/index.js +424 -1
- package/dist/src/components/document/src/index.js +1422 -1
- package/dist/src/components/end-user-consent/src/index.js +1573 -1
- package/dist/src/components/selfie/src/index.js +1220 -1
- package/dist/src/components/signature-pad/src/index.js +787 -1
- package/dist/src/components/smart-camera-web/src/SmartCameraWeb.js +2753 -1
- package/dist/src/components/totp-consent/src/index.js +1292 -1
- package/dist/types/combobox.d.ts +2 -2
- package/dist/types/document.d.ts +2 -2
- package/dist/types/end-user-consent.d.ts +2 -2
- package/dist/types/locale.d.ts +19 -0
- package/dist/types/localisation.d.ts +21 -0
- package/dist/types/main.d.ts +35 -26
- package/dist/types/navigation.d.ts +2 -2
- package/dist/types/selfie.d.ts +2 -2
- package/dist/types/signature-pad.d.ts +2 -2
- package/dist/types/smart-camera-web.d.ts +2 -2
- package/dist/types/totp-consent.d.ts +2 -2
- package/lib/components/camera-permission/CameraPermission.js +8 -3
- package/lib/components/combobox/src/Combobox.js +4 -2
- package/lib/components/document/src/DocumentCaptureScreens.js +4 -3
- package/lib/components/document/src/DocumentCaptureScreens.stories.js +37 -13
- package/lib/components/document/src/document-capture/DocumentCapture.js +20 -14
- package/lib/components/document/src/document-capture/DocumentCapture.stories.js +11 -2
- package/lib/components/document/src/document-capture-instructions/DocumentCaptureInstructions.js +16 -11
- package/lib/components/document/src/document-capture-instructions/DocumentCaptureInstructions.stories.js +14 -5
- package/lib/components/document/src/document-capture-review/DocumentCaptureReview.js +11 -7
- package/lib/components/document/src/document-capture-review/DocumentCaptureReview.stories.js +14 -5
- package/lib/components/end-user-consent/src/EndUserConsent.js +30 -29
- package/lib/components/end-user-consent/src/EndUserConsent.stories.js +12 -2
- package/lib/components/navigation/src/Navigation.js +15 -2
- package/lib/components/navigation/src/Navigation.stories.js +20 -4
- package/lib/components/selfie/src/SelfieCaptureScreens.js +3 -7
- package/lib/components/selfie/src/SelfieCaptureScreens.stories.js +16 -4
- package/lib/components/selfie/src/selfie-capture/SelfieCapture.js +23 -16
- package/lib/components/selfie/src/selfie-capture/SelfieCapture.stories.js +19 -7
- package/lib/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.js +16 -11
- package/lib/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.stories.js +14 -5
- package/lib/components/selfie/src/selfie-capture-review/SelfieCaptureReview.js +10 -5
- package/lib/components/selfie/src/selfie-capture-review/SelfieCaptureReview.stories.js +14 -5
- package/lib/components/selfie/src/selfie-capture-wrapper/SelfieCaptureWrapper.tsx +2 -2
- package/lib/components/selfie/src/smartselfie-capture/SmartSelfieCapture.stories.js +47 -0
- package/lib/components/selfie/src/smartselfie-capture/SmartSelfieCapture.tsx +2 -2
- package/lib/components/selfie/src/smartselfie-capture/components/CaptureControls.tsx +5 -2
- package/lib/components/selfie/src/smartselfie-capture/hooks/useCamera.ts +4 -4
- package/lib/components/selfie/src/smartselfie-capture/hooks/useFaceCapture.ts +6 -5
- package/lib/components/selfie/src/smartselfie-capture/utils/alertMessages.ts +11 -9
- package/lib/components/selfie/src/smartselfie-capture/utils/imageCapture.ts +3 -1
- package/lib/components/signature-pad/package.json +1 -1
- package/lib/components/totp-consent/src/TotpConsent.js +8 -3
- package/lib/domain/camera/src/SmartCamera.js +7 -22
- package/lib/domain/constants/src/Constants.js +28 -0
- package/lib/domain/file-upload/src/SmartFileUpload.js +9 -10
- package/lib/domain/localisation/index.js +456 -0
- package/package.json +12 -6
- package/dist/esm/DocumentCaptureScreens-C5BhNB-0.js.map +0 -1
- package/dist/esm/EndUserConsent-D4fd1ovG.js.map +0 -1
- package/dist/esm/Navigation-CTjK6tLU.js.map +0 -1
- package/dist/esm/SelfieCaptureScreens-KoQpCxtc.js.map +0 -1
- package/dist/esm/TotpConsent-CQU5jQi4.js.map +0 -1
- package/dist/esm/package-B-UwEdv7.js.map +0 -1
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
IMAGE_TYPE,
|
|
3
|
+
JPEG_QUALITY,
|
|
4
|
+
} from '../../../../domain/constants/src/Constants';
|
|
2
5
|
import SmartCamera from '../../../../domain/camera/src/SmartCamera';
|
|
3
6
|
import styles from '../../../../styles/src/styles';
|
|
4
7
|
import packageJson from '../../../../../package.json';
|
|
5
8
|
import '../../../navigation/src';
|
|
9
|
+
import { t, tHtml, getDirection } from '../../../../domain/localisation';
|
|
6
10
|
|
|
7
11
|
const COMPONENTS_VERSION = packageJson.version;
|
|
8
12
|
|
|
@@ -28,8 +32,9 @@ function getLivenessFramesIndices(
|
|
|
28
32
|
|
|
29
33
|
if (totalNoOfFrames < numberOfFramesRequired) {
|
|
30
34
|
throw new Error(
|
|
31
|
-
'
|
|
32
|
-
|
|
35
|
+
tHtml('selfie.capture.error.minFrames', {
|
|
36
|
+
count: numberOfFramesRequired,
|
|
37
|
+
}),
|
|
33
38
|
);
|
|
34
39
|
}
|
|
35
40
|
|
|
@@ -146,7 +151,7 @@ function templateString() {
|
|
|
146
151
|
.title-color {
|
|
147
152
|
color: ${this.themeColor};
|
|
148
153
|
}
|
|
149
|
-
|
|
154
|
+
|
|
150
155
|
.theme-color {
|
|
151
156
|
color: ${this.themeColor};
|
|
152
157
|
}
|
|
@@ -509,10 +514,10 @@ function templateString() {
|
|
|
509
514
|
margin-inline-start; 1em;
|
|
510
515
|
}
|
|
511
516
|
</style>
|
|
512
|
-
<div id='selfie-capture-screen' class='flow center'>
|
|
517
|
+
<div id='selfie-capture-screen' class='flow center' dir='${this.direction}'>
|
|
513
518
|
<smileid-navigation theme-color='${this.themeColor}' ${this.showNavigation ? 'show-navigation' : ''} ${this.hideBack ? 'hide-back' : ''}></smileid-navigation>
|
|
514
519
|
|
|
515
|
-
<div class='tips'
|
|
520
|
+
<div class='tips'>${t('selfie.capture.tip.fitHead')}</div>
|
|
516
521
|
|
|
517
522
|
<div className="error">
|
|
518
523
|
${this.cameraError ? `<p class="color-red">${this.cameraError}</p>` : ''}
|
|
@@ -544,15 +549,15 @@ function templateString() {
|
|
|
544
549
|
</svg>
|
|
545
550
|
</div>
|
|
546
551
|
<div>
|
|
547
|
-
<p id='smile-cta'
|
|
552
|
+
<p id='smile-cta'>${t('selfie.capture.cta.smile')}</p>
|
|
548
553
|
</div>
|
|
549
554
|
</div>
|
|
550
555
|
</div>
|
|
551
556
|
|
|
552
|
-
${this.allowAgentMode ? `<button data-variant='outline small' id='switch-camera' class='button | center' type='button'>${this.inAgentMode ? '
|
|
557
|
+
${this.allowAgentMode ? `<button data-variant='outline small' id='switch-camera' class='button | center' type='button'>${this.inAgentMode ? t('selfie.capture.agentMode.on') : t('selfie.capture.agentMode.off')}</button>` : ''}
|
|
553
558
|
|
|
554
559
|
<button data-variant='solid' id='start-image-capture' class='button | center' type='button'>
|
|
555
|
-
|
|
560
|
+
${t('selfie.capture.button.takeSelfie')}
|
|
556
561
|
</button>
|
|
557
562
|
|
|
558
563
|
${this.hideAttribution ? '' : '<powered-by-smile-id></powered-by-smile-id>'}
|
|
@@ -687,7 +692,7 @@ class SelfieCaptureScreen extends HTMLElement {
|
|
|
687
692
|
|
|
688
693
|
setTimeout(() => {
|
|
689
694
|
this.smileCTABox.style.opacity = 1;
|
|
690
|
-
this.smileCTA.textContent = '
|
|
695
|
+
this.smileCTA.textContent = t('selfie.capture.cta.widerSmile');
|
|
691
696
|
this.mouth.setAttribute(
|
|
692
697
|
'd',
|
|
693
698
|
'm 213.88314,319.4551 c -1.58,0.97 -0.35309,9.33393 1.50671,9.30586 6.05679,-0.0914 16.11631,0.17227 34.57066,0.13346 18.45435,-0.0388 28.15778,-0.0418 31.09964,-0.79956 1.80122,-0.46394 2.75061,-7.48365 1.16061,-8.45365 -1.6,-1.74874 -2.96432,-0.94348 -6.77747,-1.56441 -12.83012,0.04 -36.52534,0.50197 -41.29469,0.43262 -2.51525,-0.0713 -18.41588,-0.61 -20.01588,0.35 z m 57.29363,1.36599 c -9.24417,-2.23757 -8.08363,-2.42362 -20.78363,-2.42362 -12.7,0 -17.77931,2.69528 -26.84042,5.36549 12.57883,3.28731 33.57775,-4.29887 49.70067,2.24964 z',
|
|
@@ -773,7 +778,7 @@ class SelfieCaptureScreen extends HTMLElement {
|
|
|
773
778
|
// NOTE: we do not want to test POL images
|
|
774
779
|
this._drawImage(canvas, false);
|
|
775
780
|
|
|
776
|
-
this._rawImages.push(canvas.toDataURL('image/jpeg'));
|
|
781
|
+
this._rawImages.push(canvas.toDataURL('image/jpeg', JPEG_QUALITY));
|
|
777
782
|
}
|
|
778
783
|
|
|
779
784
|
_captureReferencePhoto() {
|
|
@@ -801,7 +806,7 @@ class SelfieCaptureScreen extends HTMLElement {
|
|
|
801
806
|
// NOTE: we want to test the image quality of the reference photo
|
|
802
807
|
this._drawImage(canvas, !this.disableImageTests);
|
|
803
808
|
|
|
804
|
-
const image = canvas.toDataURL('image/jpeg');
|
|
809
|
+
const image = canvas.toDataURL('image/jpeg', JPEG_QUALITY);
|
|
805
810
|
|
|
806
811
|
this._referenceImage = image;
|
|
807
812
|
|
|
@@ -852,9 +857,7 @@ class SelfieCaptureScreen extends HTMLElement {
|
|
|
852
857
|
if (hasEnoughColors) {
|
|
853
858
|
return context;
|
|
854
859
|
}
|
|
855
|
-
throw new Error(
|
|
856
|
-
'Unable to capture webcam images - Please try another device',
|
|
857
|
-
);
|
|
860
|
+
throw new Error(t('selfie.capture.error.webcamCapture'));
|
|
858
861
|
} else {
|
|
859
862
|
return context;
|
|
860
863
|
}
|
|
@@ -994,7 +997,11 @@ class SelfieCaptureScreen extends HTMLElement {
|
|
|
994
997
|
}
|
|
995
998
|
|
|
996
999
|
get title() {
|
|
997
|
-
return this.getAttribute('title') || '
|
|
1000
|
+
return this.getAttribute('title') || t('selfie.instructions.title');
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
get direction() {
|
|
1004
|
+
return this.getAttribute('dir') || getDirection() || 'ltr';
|
|
998
1005
|
}
|
|
999
1006
|
|
|
1000
1007
|
get hidden() {
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import SmartCamera from '../../../../domain/camera/src/SmartCamera';
|
|
2
|
+
import { setCurrentLocale } from '../../../../domain/localisation';
|
|
2
3
|
import './SelfieCapture';
|
|
3
4
|
|
|
4
5
|
const meta = {
|
|
6
|
+
args: {
|
|
7
|
+
language: 'en',
|
|
8
|
+
'theme-color': '#001096',
|
|
9
|
+
},
|
|
5
10
|
argTypes: {
|
|
11
|
+
language: {
|
|
12
|
+
control: 'select',
|
|
13
|
+
options: ['en', 'ar'],
|
|
14
|
+
},
|
|
6
15
|
'theme-color': { control: 'color' },
|
|
7
16
|
},
|
|
8
17
|
component: 'selfie-capture',
|
|
@@ -11,9 +20,6 @@ const meta = {
|
|
|
11
20
|
export default meta;
|
|
12
21
|
|
|
13
22
|
export const SelfieCapture = {
|
|
14
|
-
args: {
|
|
15
|
-
'theme-color': '#001096',
|
|
16
|
-
},
|
|
17
23
|
loaders: [
|
|
18
24
|
async () => ({
|
|
19
25
|
permissionGranted: await SmartCamera.getMedia({
|
|
@@ -22,15 +28,21 @@ export const SelfieCapture = {
|
|
|
22
28
|
}),
|
|
23
29
|
}),
|
|
24
30
|
],
|
|
25
|
-
render: (args) =>
|
|
31
|
+
render: (args) => {
|
|
32
|
+
setCurrentLocale(args.language);
|
|
33
|
+
return `
|
|
26
34
|
<selfie-capture theme-color='${args['theme-color']}'>
|
|
27
35
|
</selfie-capture>
|
|
28
|
-
|
|
36
|
+
`;
|
|
37
|
+
},
|
|
29
38
|
};
|
|
30
39
|
|
|
31
40
|
export const SelfieCaptureAgentMode = {
|
|
32
|
-
render: () =>
|
|
41
|
+
render: (args) => {
|
|
42
|
+
setCurrentLocale(args.language);
|
|
43
|
+
return `
|
|
33
44
|
<selfie-capture allow-agent-mode='true' data-camera-ready show-agent-mode-for-tests>
|
|
34
45
|
</selfie-capture>
|
|
35
|
-
|
|
46
|
+
`;
|
|
47
|
+
},
|
|
36
48
|
};
|
|
@@ -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 `
|
|
@@ -339,7 +340,7 @@ function templateString() {
|
|
|
339
340
|
}
|
|
340
341
|
</style>
|
|
341
342
|
${styles(this.themeColor)}
|
|
342
|
-
<div id="selfie-capture-instruction-screen" class="center">
|
|
343
|
+
<div id="selfie-capture-instruction-screen" class="center" dir="${this.direction}">
|
|
343
344
|
<div class="content-root">
|
|
344
345
|
<div class="content-header">
|
|
345
346
|
<smileid-navigation theme-color=${this.themeColor} ${this.hideBack ? 'hide-back' : ''} ${this.showNavigation ? '' : 'hidden'}></smileid-navigation>
|
|
@@ -370,7 +371,7 @@ function templateString() {
|
|
|
370
371
|
</clipPath>
|
|
371
372
|
</defs>
|
|
372
373
|
</svg>
|
|
373
|
-
<h1 class='title-color font-bold'
|
|
374
|
+
<h1 class='title-color font-bold'>${t('selfie.instructions.title')}</h1>
|
|
374
375
|
</header>
|
|
375
376
|
<div class="instructions-wrapper">
|
|
376
377
|
<div class="instructions">
|
|
@@ -449,9 +450,9 @@ function templateString() {
|
|
|
449
450
|
</defs>
|
|
450
451
|
</svg>
|
|
451
452
|
<div class="instruction">
|
|
452
|
-
<p class="text-base title-color font-bold tip-header"
|
|
453
|
+
<p class="text-base title-color font-bold tip-header">${t('selfie.instructions.tips.goodLight.header')}</p>
|
|
453
454
|
<p class="tip-body">
|
|
454
|
-
|
|
455
|
+
${t('selfie.instructions.tips.goodLight.body')}
|
|
455
456
|
</p>
|
|
456
457
|
</div>
|
|
457
458
|
</div>
|
|
@@ -537,9 +538,9 @@ function templateString() {
|
|
|
537
538
|
</defs>
|
|
538
539
|
</svg>
|
|
539
540
|
<div class="instruction">
|
|
540
|
-
<p class="text-base title-color font-bold tip-header"
|
|
541
|
+
<p class="text-base title-color font-bold tip-header">${t('selfie.instructions.tips.clearImage.header')}</p>
|
|
541
542
|
<p class="tip-body">
|
|
542
|
-
|
|
543
|
+
${t('selfie.instructions.tips.clearImage.body')}
|
|
543
544
|
</p>
|
|
544
545
|
</div>
|
|
545
546
|
</div>
|
|
@@ -569,25 +570,25 @@ function templateString() {
|
|
|
569
570
|
/>
|
|
570
571
|
</svg>
|
|
571
572
|
<div class="instruction">
|
|
572
|
-
<p class="text-base title-color font-bold tip-header"
|
|
573
|
+
<p class="text-base title-color font-bold tip-header">${t('selfie.instructions.tips.removeObstructions.header')}</p>
|
|
573
574
|
<p class="tip-body">
|
|
574
|
-
|
|
575
|
+
${t('selfie.instructions.tips.removeObstructions.body')}
|
|
575
576
|
</p>
|
|
576
577
|
</div>
|
|
577
578
|
</div>
|
|
578
579
|
<div class="instructions">
|
|
579
580
|
<svg xmlns="http://www.w3.org/2000/svg" width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="${this.themeColor}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-mood-happy"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" /><path d="M9 9l.01 0" /><path d="M15 9l.01 0" /><path d="M8 13a4 4 0 1 0 8 0h-8" /></svg>
|
|
580
581
|
<div class="instruction">
|
|
581
|
-
<p class="text-base title-color font-bold tip-header"
|
|
582
|
+
<p class="text-base title-color font-bold tip-header">${t('selfie.instructions.tips.wideSmile.header')}</p>
|
|
582
583
|
<p class="tip-body">
|
|
583
|
-
|
|
584
|
+
${t('selfie.instructions.tips.wideSmile.body')}
|
|
584
585
|
</p>
|
|
585
586
|
</div>
|
|
586
587
|
</div>
|
|
587
588
|
</div>
|
|
588
589
|
<section class="controls">
|
|
589
590
|
<button id='allow' data-variant='solid full-width' class='button theme-background'>
|
|
590
|
-
|
|
591
|
+
${t('selfie.instructions.allowButton')}
|
|
591
592
|
</button>
|
|
592
593
|
</section>
|
|
593
594
|
${
|
|
@@ -667,6 +668,10 @@ class SelfieCaptureInstructions extends HTMLElement {
|
|
|
667
668
|
return this.hasAttribute('show-navigation');
|
|
668
669
|
}
|
|
669
670
|
|
|
671
|
+
get direction() {
|
|
672
|
+
return this.getAttribute('dir') || getDirection() || 'ltr';
|
|
673
|
+
}
|
|
674
|
+
|
|
670
675
|
handleCloseEvents() {
|
|
671
676
|
this.dispatchEvent(new CustomEvent('selfie-capture-instructions.close'));
|
|
672
677
|
}
|
package/lib/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.stories.js
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import { setCurrentLocale } from '../../../../domain/localisation';
|
|
1
2
|
import './index';
|
|
2
3
|
|
|
3
4
|
const meta = {
|
|
5
|
+
args: {
|
|
6
|
+
language: 'en',
|
|
7
|
+
'theme-color': '#001096',
|
|
8
|
+
},
|
|
4
9
|
argTypes: {
|
|
10
|
+
language: {
|
|
11
|
+
control: 'select',
|
|
12
|
+
options: ['en', 'ar'],
|
|
13
|
+
},
|
|
5
14
|
'theme-color': { control: 'color' },
|
|
6
15
|
},
|
|
7
16
|
component: 'selfie-capture-instructions',
|
|
@@ -10,14 +19,14 @@ const meta = {
|
|
|
10
19
|
export default meta;
|
|
11
20
|
|
|
12
21
|
export const SelfieInstruction = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
render: (args) => `
|
|
22
|
+
render: (args) => {
|
|
23
|
+
setCurrentLocale(args.language);
|
|
24
|
+
return `
|
|
17
25
|
<selfie-capture-instructions
|
|
18
26
|
show-navigation
|
|
19
27
|
theme-color='${args['theme-color']}'
|
|
20
28
|
>
|
|
21
29
|
</selfie-capture-instructions>
|
|
22
|
-
|
|
30
|
+
`;
|
|
31
|
+
},
|
|
23
32
|
};
|
|
@@ -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 `
|
|
@@ -55,10 +56,10 @@ function templateString() {
|
|
|
55
56
|
}
|
|
56
57
|
</style>
|
|
57
58
|
${styles(this.themeColor)}
|
|
58
|
-
<div id='selfie-capture-review-screen' class='center'>
|
|
59
|
+
<div id='selfie-capture-review-screen' class='center' dir='${this.direction}'>
|
|
59
60
|
<smileid-navigation ${this.showNavigation ? 'show-navigation' : ''} hide-back></smileid-navigation>
|
|
60
61
|
<h1 class="header-title title-color font-bold">
|
|
61
|
-
|
|
62
|
+
${t('selfie.review.question')}
|
|
62
63
|
</h1>
|
|
63
64
|
<div class='section | flow'>
|
|
64
65
|
<div class='selfie-review-container ${this.isPortraitCaptureView ? 'portrait' : 'landscape'}'>
|
|
@@ -76,10 +77,10 @@ function templateString() {
|
|
|
76
77
|
</div>
|
|
77
78
|
<div class='flow action-buttons'>
|
|
78
79
|
<button data-variant='solid full-width' class='button' type='button' id='select-id-image'>
|
|
79
|
-
|
|
80
|
+
${t('selfie.review.acceptButton')}
|
|
80
81
|
</button>
|
|
81
82
|
<button data-variant='ghost full-width' class='button retake-photo' type='button' id='re-capture-image'>
|
|
82
|
-
|
|
83
|
+
${t('selfie.review.retakeButton')}
|
|
83
84
|
</button>
|
|
84
85
|
</div>
|
|
85
86
|
${
|
|
@@ -145,7 +146,11 @@ class SelfieCaptureReview extends HTMLElement {
|
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
get title() {
|
|
148
|
-
return this.getAttribute('title') || '
|
|
149
|
+
return this.getAttribute('title') || t('selfie.review.title');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
get direction() {
|
|
153
|
+
return this.getAttribute('dir') || getDirection() || 'ltr';
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
handleBackEvents() {
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import { setCurrentLocale } from '../../../../domain/localisation';
|
|
1
2
|
import './SelfieCaptureReview';
|
|
2
3
|
|
|
3
4
|
const meta = {
|
|
5
|
+
args: {
|
|
6
|
+
language: 'en',
|
|
7
|
+
'theme-color': '#001096',
|
|
8
|
+
},
|
|
4
9
|
argTypes: {
|
|
10
|
+
language: {
|
|
11
|
+
control: 'select',
|
|
12
|
+
options: ['en', 'ar'],
|
|
13
|
+
},
|
|
5
14
|
'theme-color': { control: 'color' },
|
|
6
15
|
},
|
|
7
16
|
component: 'selfie-capture-review',
|
|
@@ -10,15 +19,15 @@ const meta = {
|
|
|
10
19
|
export default meta;
|
|
11
20
|
|
|
12
21
|
export const SelfieCaptureReview = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
render: (args) => `
|
|
22
|
+
render: (args) => {
|
|
23
|
+
setCurrentLocale(args.language);
|
|
24
|
+
return `
|
|
17
25
|
<selfie-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
|
</selfie-capture-review>
|
|
23
|
-
|
|
31
|
+
`;
|
|
32
|
+
},
|
|
24
33
|
};
|
|
@@ -3,7 +3,7 @@ import { IconLoader2 } from '@tabler/icons-preact';
|
|
|
3
3
|
import register from 'preact-custom-element';
|
|
4
4
|
import type { FunctionComponent } from 'preact';
|
|
5
5
|
|
|
6
|
-
import { getBoolProp } from '
|
|
6
|
+
import { getBoolProp } from '../../../../utils/props';
|
|
7
7
|
import SmartSelfieCapture from '../smartselfie-capture/SmartSelfieCapture';
|
|
8
8
|
// Legacy web component fallback (used when Mediapipe isn't available)
|
|
9
9
|
import '../selfie-capture/SelfieCapture';
|
|
@@ -196,7 +196,7 @@ const SelfieCaptureWrapper: FunctionComponent<Props> = ({
|
|
|
196
196
|
delete (propsWithoutHidden as any).hidden;
|
|
197
197
|
|
|
198
198
|
return (
|
|
199
|
-
// @ts-
|
|
199
|
+
// @ts-expect-error --- preact-custom-element doesn't have proper types for refs
|
|
200
200
|
<selfie-capture
|
|
201
201
|
{...propsWithoutHidden}
|
|
202
202
|
ref={(el: HTMLElement) => {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { setCurrentLocale } from '../../../../domain/localisation';
|
|
2
|
+
import './index';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
args: {
|
|
6
|
+
language: 'en',
|
|
7
|
+
'theme-color': '#001096',
|
|
8
|
+
},
|
|
9
|
+
argTypes: {
|
|
10
|
+
language: {
|
|
11
|
+
control: 'select',
|
|
12
|
+
options: ['en', 'ar'],
|
|
13
|
+
},
|
|
14
|
+
'theme-color': { control: 'color' },
|
|
15
|
+
},
|
|
16
|
+
component: 'smart-selfie-capture',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
|
|
21
|
+
export const SmartSelfieCapture = {
|
|
22
|
+
render: (args) => {
|
|
23
|
+
setCurrentLocale(args.language);
|
|
24
|
+
return `
|
|
25
|
+
<smart-selfie-capture
|
|
26
|
+
show-navigation
|
|
27
|
+
theme-color='${args['theme-color']}'
|
|
28
|
+
>
|
|
29
|
+
</smart-selfie-capture>
|
|
30
|
+
`;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const SmartSelfieCaptureAgentMode = {
|
|
35
|
+
render: (args) => {
|
|
36
|
+
setCurrentLocale(args.language);
|
|
37
|
+
return `
|
|
38
|
+
<smart-selfie-capture
|
|
39
|
+
show-navigation
|
|
40
|
+
allow-agent-mode
|
|
41
|
+
show-agent-mode-for-tests
|
|
42
|
+
theme-color='${args['theme-color']}'
|
|
43
|
+
>
|
|
44
|
+
</smart-selfie-capture>
|
|
45
|
+
`;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -152,7 +152,7 @@ const SmartSelfieCapture: FunctionComponent<Props> = ({
|
|
|
152
152
|
return (
|
|
153
153
|
<div className="smartselfie-capture">
|
|
154
154
|
{showNavigation && (
|
|
155
|
-
// @ts-
|
|
155
|
+
// @ts-expect-error --- preact-custom-element doesn't have proper types for refs
|
|
156
156
|
<smileid-navigation ref={navigationRef} theme-color={themeColor} />
|
|
157
157
|
)}
|
|
158
158
|
|
|
@@ -188,7 +188,7 @@ const SmartSelfieCapture: FunctionComponent<Props> = ({
|
|
|
188
188
|
/>
|
|
189
189
|
)}
|
|
190
190
|
|
|
191
|
-
{/* @ts-
|
|
191
|
+
{/* @ts-expect-error -- preact-custom-element doesn't have proper types for refs */}
|
|
192
192
|
{!hideAttribution && <powered-by-smile-id />}
|
|
193
193
|
|
|
194
194
|
<style>{`
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FunctionComponent } from 'preact';
|
|
2
|
+
import { t } from '../../../../../domain/localisation';
|
|
2
3
|
|
|
3
4
|
interface CaptureControlsProps {
|
|
4
5
|
isCapturing: boolean;
|
|
@@ -33,7 +34,7 @@ export const CaptureControls: FunctionComponent<CaptureControlsProps> = ({
|
|
|
33
34
|
onClick={onStartCapture}
|
|
34
35
|
disabled={isCapturing || hasFinishedCapture || !isReadyToCapture}
|
|
35
36
|
>
|
|
36
|
-
|
|
37
|
+
{t('selfie.capture.button.startCapture')}
|
|
37
38
|
</button>
|
|
38
39
|
|
|
39
40
|
{allowAgentMode && (agentSupported || showAgentModeForTests) && (
|
|
@@ -43,7 +44,9 @@ export const CaptureControls: FunctionComponent<CaptureControlsProps> = ({
|
|
|
43
44
|
className="agent-mode-btn"
|
|
44
45
|
disabled={isCapturing || hasFinishedCapture}
|
|
45
46
|
>
|
|
46
|
-
{facingMode === 'user'
|
|
47
|
+
{facingMode === 'user'
|
|
48
|
+
? t('selfie.capture.agentMode.off')
|
|
49
|
+
: t('selfie.capture.agentMode.on')}
|
|
47
50
|
</button>
|
|
48
51
|
)}
|
|
49
52
|
</div>
|
|
@@ -110,7 +110,7 @@ export const useCamera = (initialFacingMode: CameraFacingMode = 'user') => {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
await startCamera(newFacingMode);
|
|
113
|
-
} catch
|
|
113
|
+
} catch {
|
|
114
114
|
setFacingMode(previousFacingMode);
|
|
115
115
|
isSwitchingCameraRef.current = false;
|
|
116
116
|
|
|
@@ -180,7 +180,7 @@ export const useCamera = (initialFacingMode: CameraFacingMode = 'user') => {
|
|
|
180
180
|
userCameraId =
|
|
181
181
|
userStream.getVideoTracks()[0].getSettings().deviceId ?? null;
|
|
182
182
|
userStream.getTracks().forEach((track) => track.stop());
|
|
183
|
-
} catch
|
|
183
|
+
} catch {
|
|
184
184
|
// no user-facing camera available
|
|
185
185
|
}
|
|
186
186
|
|
|
@@ -192,7 +192,7 @@ export const useCamera = (initialFacingMode: CameraFacingMode = 'user') => {
|
|
|
192
192
|
environmentCameraId =
|
|
193
193
|
envStream.getVideoTracks()[0].getSettings().deviceId ?? null;
|
|
194
194
|
envStream.getTracks().forEach((track) => track.stop());
|
|
195
|
-
} catch
|
|
195
|
+
} catch {
|
|
196
196
|
// no environment-facing camera available
|
|
197
197
|
}
|
|
198
198
|
|
|
@@ -207,7 +207,7 @@ export const useCamera = (initialFacingMode: CameraFacingMode = 'user') => {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
setAgentSupported(!isGecko);
|
|
210
|
-
} catch
|
|
210
|
+
} catch {
|
|
211
211
|
setAgentSupported(false);
|
|
212
212
|
}
|
|
213
213
|
};
|
|
@@ -17,6 +17,7 @@ import { captureImageFromVideo } from '../utils/imageCapture';
|
|
|
17
17
|
import { ImageType } from '../constants';
|
|
18
18
|
import { MESSAGES, type MessageKey } from '../utils/alertMessages';
|
|
19
19
|
import { getMediapipeInstance } from '../utils/mediapipeManager';
|
|
20
|
+
import { t } from '../../../../../domain/localisation';
|
|
20
21
|
import packageJson from '../../../../../../package.json';
|
|
21
22
|
|
|
22
23
|
const COMPONENTS_VERSION = packageJson.version;
|
|
@@ -88,7 +89,7 @@ export const useFaceCapture = ({
|
|
|
88
89
|
|
|
89
90
|
const updateAlertImmediate = (messageKey: MessageKey | null) => {
|
|
90
91
|
if (messageKey && MESSAGES[messageKey]) {
|
|
91
|
-
alertTitle.value = MESSAGES[messageKey];
|
|
92
|
+
alertTitle.value = MESSAGES[messageKey]?.();
|
|
92
93
|
} else {
|
|
93
94
|
alertTitle.value = '';
|
|
94
95
|
}
|
|
@@ -141,7 +142,7 @@ export const useFaceCapture = ({
|
|
|
141
142
|
const isInSmileZone = capturesTaken.value >= smileCheckpoint.value;
|
|
142
143
|
|
|
143
144
|
if (isInNeutralZone) {
|
|
144
|
-
alertTitle.value = '
|
|
145
|
+
alertTitle.value = t('selfie.smart.status.capturing');
|
|
145
146
|
} else if (isInSmileZone) {
|
|
146
147
|
const timeSinceSmile = Date.now() - lastSmileTime.value;
|
|
147
148
|
if (timeSinceSmile > smileCooldown) {
|
|
@@ -154,7 +155,7 @@ export const useFaceCapture = ({
|
|
|
154
155
|
updateAlert('smile-required');
|
|
155
156
|
}
|
|
156
157
|
} else {
|
|
157
|
-
alertTitle.value = '
|
|
158
|
+
alertTitle.value = t('selfie.smart.status.keepSmiling');
|
|
158
159
|
}
|
|
159
160
|
} else {
|
|
160
161
|
updateAlert(null);
|
|
@@ -177,7 +178,7 @@ export const useFaceCapture = ({
|
|
|
177
178
|
} else if (isCapturing.value) {
|
|
178
179
|
updateCaptureAlerts();
|
|
179
180
|
} else {
|
|
180
|
-
alertTitle.value = '
|
|
181
|
+
alertTitle.value = t('selfie.smart.status.readyToCapture');
|
|
181
182
|
}
|
|
182
183
|
};
|
|
183
184
|
|
|
@@ -330,7 +331,7 @@ export const useFaceCapture = ({
|
|
|
330
331
|
}
|
|
331
332
|
|
|
332
333
|
updateAlerts();
|
|
333
|
-
} catch
|
|
334
|
+
} catch {
|
|
334
335
|
faceDetected.value = false;
|
|
335
336
|
faceInBounds.value = false;
|
|
336
337
|
multipleFaces.value = false;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import { t } from '../../../../../domain/localisation';
|
|
2
|
+
|
|
1
3
|
export const MESSAGES = {
|
|
2
|
-
'multiple-faces':
|
|
3
|
-
'no-face':
|
|
4
|
-
'out-of-bounds':
|
|
5
|
-
'too-close':
|
|
6
|
-
'too-far':
|
|
7
|
-
'neutral-expression':
|
|
8
|
-
'smile-required': '
|
|
9
|
-
'open-mouth-smile':
|
|
10
|
-
initializing: '
|
|
4
|
+
'multiple-faces': () => t('selfie.smart.alert.multipleFaces'),
|
|
5
|
+
'no-face': () => t('selfie.smart.alert.noFace'),
|
|
6
|
+
'out-of-bounds': () => t('selfie.smart.alert.outOfBounds'),
|
|
7
|
+
'too-close': () => t('selfie.smart.alert.tooClose'),
|
|
8
|
+
'too-far': () => t('selfie.smart.alert.tooFar'),
|
|
9
|
+
'neutral-expression': () => t('selfie.smart.alert.neutralExpression'),
|
|
10
|
+
'smile-required': () => t('selfie.smart.alert.smileRequired'),
|
|
11
|
+
'open-mouth-smile': () => t('selfie.smart.alert.openMouthSmile'),
|
|
12
|
+
initializing: () => t('selfie.smart.alert.initializing'),
|
|
11
13
|
};
|
|
12
14
|
|
|
13
15
|
export type MessageKey = keyof typeof MESSAGES;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { JPEG_QUALITY } from '../../../../../domain/constants/src/Constants';
|
|
2
|
+
|
|
1
3
|
export const captureImageFromVideo = (
|
|
2
4
|
videoElement: HTMLVideoElement,
|
|
3
5
|
isReference: boolean = false,
|
|
@@ -60,5 +62,5 @@ export const captureImageFromVideo = (
|
|
|
60
62
|
canvas.height,
|
|
61
63
|
);
|
|
62
64
|
|
|
63
|
-
return canvas.toDataURL('image/jpeg');
|
|
65
|
+
return canvas.toDataURL('image/jpeg', JPEG_QUALITY);
|
|
64
66
|
};
|