@getyoti/react-face-capture 0.5.0 → 1.0.0-beta.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,68 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v1.0.0-beta.3
4
+
5
+ Fix a package install error which cause `yarn` and older `npm` versions to fail.
6
+
7
+ ## v1.0.0-beta.2
8
+
9
+ ### New features
10
+
11
+ - Capture secure mode.
12
+ - Vanilla version reload.
13
+ - New FCM Design.
14
+ - New optional "consent" button.
15
+ - Default captureMethod changed from "Manual" to "Auto".
16
+
17
+ ### Breaking changes
18
+
19
+ Now the `onSuccess` callback returns the image in the `img` field instead for
20
+ `image`.
21
+
22
+ - Before:
23
+
24
+ ```json
25
+ {
26
+ "image": "<base64_img>"
27
+ }
28
+ ```
29
+
30
+ - After:
31
+
32
+ - No secure:
33
+
34
+ ```json
35
+ {
36
+ "img": "<base64_img>"
37
+ }
38
+ ```
39
+
40
+ - Secure:
41
+
42
+ ```json
43
+ {
44
+ "img": "<base64_img>",
45
+ "secure": {
46
+ "version": "<fcm_version>",
47
+ "token": "<session_token>",
48
+ "signature": "<result_signature>"
49
+ }
50
+ }
51
+ ```
52
+
53
+ Now the `CustomButton` has been splited in `CustomManualButton` and `CustomConsentButton` because
54
+ of the implementation of the new consent mode. Each of the properties has the same definitions as
55
+ the old `CustomButton`, funtions using `onClick` and `disabled` as props that returns a button
56
+ component.
57
+
58
+ ## v0.6.0
59
+
60
+ ### New features
61
+
62
+ - Implemented localisation languages
63
+ - `ar`: Arabic
64
+ - `lv`: Latvian
65
+
3
66
  ## v0.5.0
4
67
 
5
68
  ### New features
package/README.md CHANGED
@@ -9,8 +9,8 @@ The purpose of this module is to capture a face and return the output image.
9
9
  The package depends on the following peer dependencies
10
10
 
11
11
  ```
12
- "react": "16.12.0",
13
- "react-dom": "16.12.0"
12
+ "react": ">=16.12.0 <18",
13
+ "react-dom": ">=16.12.0 <18"
14
14
  ```
15
15
 
16
16
  ### Browser support
@@ -19,12 +19,12 @@ The package depends on the following peer dependencies
19
19
 
20
20
  | Browser | Versions |
21
21
  | ------- | ----------------------------- |
22
- | and_chr | 96 |
23
- | chrome | 96,95,94,93 |
24
- | edge | 96,95 |
25
- | firefox | 95,94,93,92 |
26
- | ios_saf | 15.0-15.1,14.5-14.8,14.0-14.4 |
27
- | safari | 15.1,15,14.1,14 |
22
+ | and_chr | 98 |
23
+ | chrome | 98,97,96,95 |
24
+ | edge | 98,97 |
25
+ | firefox | 97,96,95,94 |
26
+ | ios_saf | 15.2-15.3,15.0-15.1,14.5-14.8 |
27
+ | safari | 15.2-15.3,15.1,15,14.1 |
28
28
 
29
29
  </browserSupportTable>
30
30
 
@@ -34,7 +34,9 @@ _Note: Non-Safari browsers on iOS are not supported because of an iOS limitation
34
34
 
35
35
  Finally, some devices might experience poor performance when attempting to detect a face. This is because the underlying library TensorFlow.js can still be too demanding for older less performant devices.
36
36
 
37
- ## Install dependency
37
+ ## React face capture module
38
+
39
+ ### Install dependency
38
40
 
39
41
  ```
40
42
  npm i @getyoti/react-face-capture -S
@@ -47,7 +49,7 @@ import FaceCapture from "@getyoti/react-face-capture"
47
49
  import "@getyoti/react-face-capture/index.css"
48
50
  ```
49
51
 
50
- ## Copy assets
52
+ ### Copy assets
51
53
 
52
54
  **Assets** are not included in the javascript bundle. To have the components to work correctly, you will need to copy library assets from `@getyoti/react-face-capture/assets` folder into your assets folder.
53
55
 
@@ -62,28 +64,33 @@ new CopyPlugin([
62
64
  ]),
63
65
  ```
64
66
 
65
- ## Props
66
-
67
- | Property name | Type | Default | Mand | Description |
68
- | -------------------- | -------------------------- | ------------- | ---- | -------------------------------------------------------------------------------------------------------------------- |
69
- | captureMethod | String `manual/auto` | `manual` | - | The way you capture the photo, either with the button of auto-capture |
70
- | onSuccess | Function({ image }) | - | Y | Callback which will be called once the result (capture) is complete |
71
- | onError | Function | - | - | Callback which will be called when there is an error. See Appendix for the list of error codes we currently support. |
72
- | showOverlay | Boolean | `true` | - | Use a face overlay |
73
- | widthMinConstraint | Number | `1024` | - | Video min width constraint passed to `getUserMedia` |
74
- | widthIdealConstraint | Number | `1280` | - | Video ideal width constraint passed to `getUserMedia` |
75
- | format | String | `jpeg` | - | Image format |
76
- | CustomButton | Function | simple button | - | Custom UI of the button. It uses `onClick` and `disabled` as props |
77
- | countdownMode | String `auto/never/always` | `never` | - | Note: `auto` means it will be hidden on mobile and shown on desktop |
78
- | imageType | String `original/cropped` | `original` | - | Cropped image to improve performance on processing from the API |
79
- | isDebug | Boolean | false | - | If `true`, display useful information |
80
- | qualityType | String `high/medium/low` | `high` | - | The quality of the image taken for jpeg format only. High (1) - Medium (0.96) - Low (0.90) |
81
- | language | Language code (\*) | `en` | - | The language code to set the language of the feedback messages |
67
+ ### Props
68
+
69
+ | Property name | Type | Default | Mand | Description |
70
+ | -------------------- | -------------------------- | ------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
71
+ | captureMethod | String `manual/auto` | `auto` | - | The way you capture the photo, either with the button of auto-capture |
72
+ | secure | Boolean | false | - | If `true`, the face capture module will use the [secure mode](#secure-mode) |
73
+ | onSuccess | Function({ img, secure }) | - | Y | Callback which will be called once the result (capture) is complete. The field `secure` is only returned in secure mode (See [secure mode section](#secure-mode)) |
74
+ | onError | Function | - | - | Callback which will be called when there is an error. See Appendix for the list of error codes we currently support. |
75
+ | showOverlay | Boolean | `true` | - | Use a face overlay |
76
+ | widthMinConstraint | Number | `1024` | - | Video min width constraint passed to `getUserMedia` |
77
+ | widthIdealConstraint | Number | `1280` | - | Video ideal width constraint passed to `getUserMedia` |
78
+ | format | String | `jpeg` | - | Image format |
79
+ | CustomManualButton | Function | simple button | - | Custom UI of the manual capture button. It uses `onClick` and `disabled` as props |
80
+ | CustomConsentButton | Function | simple button | - | Custom UI of the consent button. It uses `onClick` and `disabled` as props |
81
+ | countdownMode | String `auto/never/always` | `never` | - | Note: `auto` means it will be hidden on mobile and shown on desktop |
82
+ | imageType | String `original/cropped` | `original` | - | Cropped image to improve performance on processing from the API |
83
+ | isDebug | Boolean | false | - | If `true`, display useful information |
84
+ | qualityType | String `high/medium/low` | `high` | - | The quality of the image taken for jpeg format only. High (1) - Medium (0.96) - Low (0.90) |
85
+ | language | Language code (\*) | `en` | - | The language code to set the language of the feedback messages |
86
+ | a11yLiveRegionMode | String `assertive/polite` | `polite` | - | Determines the [politeness setting of the live region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions#live_regions) used to read out prompts for screen reader users |
87
+ | isConsentRequired | Boolean | `false` | - | Makes sure that the user gives consent to the tool to analyse their face. If it is `true`, a button will appear on the bottom section of the module, asking the user for their consent, and not analysing the user face until the consent is given. After this, the button disappears. |
82
88
 
83
89
  **(\*)**
84
90
  Current languages supported:
85
91
 
86
92
  - `en`: English
93
+ - `ar`: Arabic
87
94
  - `cs`: Czech
88
95
  - `da`: Danish
89
96
  - `de`: German
@@ -98,6 +105,7 @@ Current languages supported:
98
105
  - `ja`: Japanese
99
106
  - `ko`: Korean
100
107
  - `lt`: Lithuanian
108
+ - `lv`: Latvian
101
109
  - `ms`: Malay
102
110
  - `nb`: Norwegian
103
111
  - `nl`: Dutch
@@ -111,7 +119,7 @@ Current languages supported:
111
119
  - `uk`: Ukranian
112
120
  - `vi`: Vietnamese
113
121
 
114
- ### Language fallback
122
+ #### Language fallback
115
123
 
116
124
  Mechanisnm used for the prop `language` to avoid issues when the value passed is wrong. Example: first try exact match (es-es or es-ES, ignore case):
117
125
 
@@ -119,7 +127,7 @@ Mechanisnm used for the prop `language` to avoid issues when the value passed is
119
127
  - If no mainstream, try any other available es-[region] sibling (example: es-419).
120
128
  - If no regional sibling, use the default language: en.
121
129
 
122
- ### Supported error codes
130
+ #### Supported error codes
123
131
 
124
132
  | Error code | Description |
125
133
  | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -130,6 +138,7 @@ Mechanisnm used for the prop `language` to avoid issues when the value passed is
130
138
  | `OVERCONSTRAINED` | The camera constraints are not compatible with any camera device. `Note: One recovery option is to lower the widthMinConstraint value.` |
131
139
  | `FACE_DETECTION_INIT_ERROR` | The face detection has failed to initialise. This usually means that the required model assets are missing from the host application. |
132
140
  | `INTERNAL_ERROR` | Internal error. This can be due to a programming error, or the user using an old unsupported browser. |
141
+ | `CAPTURE_LOAD_ERROR` | The secure module could not be loaded. This usually means your token is not updated, or there is an error on the module provider. |
133
142
 
134
143
  The error codes can be imported as follow:
135
144
 
@@ -137,7 +146,58 @@ The error codes can be imported as follow:
137
146
  import { ERROR_CODE } from '@getyoti/react-face-capture';
138
147
  ```
139
148
 
140
- ## Example
149
+ #### Secure mode
150
+
151
+ The secure mode allows [Yoti back-end
152
+ service](https://developers.yoti.com/age-estimation/integration-guide)
153
+ verifying the image captured on the client-side browser with the FCM hasn't been
154
+ modified in any form. Note the Secure mode of Yoti FCM will request Yoti
155
+ back-end in order to download the encrypted capture package that takes the
156
+ photos and create the secure result request. The secure result information will
157
+ be returned in `onSuccess` callback:
158
+
159
+ ```json
160
+ {
161
+ "img": "<base64_img>",
162
+ "secure": {
163
+ "version": "<fcm_version>",
164
+ "token": "<session_token>",
165
+ "signature": "<result_signature>"
166
+ }
167
+ }
168
+ ```
169
+
170
+ The flow for the secure mode is the following:
171
+
172
+ 1. Request for a session -> `(GET) https://api.yoti.com/ai/sm/v1/secure-fcm/<version>/token`
173
+ 2. Request for the encrypted javascript module -> `(GET) https://api.yoti.com/ai/sm/v1/secure-fcm/<version>/module?s=<token>`
174
+
175
+ Where `<version>` is the current version of the FCM (It is embedded in the
176
+ module) and the `<token>` is the session token the first request returns.
177
+
178
+ ```mermaid
179
+ sequenceDiagram
180
+ participant A as Browser (FCM)
181
+ participant B as Secure Module Server
182
+ participant C as Integrator back-end
183
+ participant D as Yoti Anti Spoofing Service
184
+ A->>B: Request for a session
185
+ B->>A: New session response
186
+ A->>B: Request for the secure capture module
187
+ B->>A: Secure capture module result
188
+ A->>A: Take picture
189
+ A->>C: Send capture result
190
+ C->>D: Propagate request to the Anti Spoofing service
191
+ ```
192
+
193
+ ##### Possible issues
194
+
195
+ The secure mode requests Yoti back-end in order to download the encrypted module
196
+ on demand so the front-end must be able to handle that requests. Keep in mind if
197
+ your front-end uses any mechanism to prevent data injection attacks or
198
+ cross-site scripting like SCP you will need to allow the FCM requests.
199
+
200
+ ### Example
141
201
 
142
202
  ```js
143
203
  import FaceCapture from '@getyoti/react-face-capture';
@@ -186,7 +246,15 @@ Our scripts will give you access to `Yoti.FaceCaptureModule.render` you can pass
186
246
  faceCaptureAssetsRootUrl: '/@getyoti/react-face-capture/vanilla/assets/';
187
247
  };
188
248
 
189
- Yoti.FaceCaptureModule.render(props, document.getElementById('face-capture-module-root'));
249
+ const fcm = Yoti.FaceCaptureModule.render(props, document.getElementById('face-capture-module-root'));
250
+
251
+ function reload() {
252
+ fcm.reload()
253
+ }
254
+
255
+ function unmount() {
256
+ fcm.unmount()
257
+ }
190
258
  </script>
191
259
 
192
260
  <div id="face-capture-module-root"></div>
package/index.css CHANGED
@@ -1 +1 @@
1
- ._1BAMDen_YLcifIe4T1Qv-_{position:absolute;top:0;width:100%;height:100%;display:flex;justify-content:center}._1e9w5ipw5j_XUcEv_CJUlO{position:absolute;margin:auto;display:block;height:100%}._2W6OS2MmM9HFQCXWdJ8ASr{position:absolute;box-sizing:border-box}._2W6OS2MmM9HFQCXWdJ8ASr._2R1kfrIDlFyYzv1nDgZcTN{top:28.3%;height:43.5%}._2W6OS2MmM9HFQCXWdJ8ASr.TwXhRfznW400Ln2BpPUbd{top:11.5%;height:71.7%}._3UWaUYYyQc5VbvW6HKIRHv{position:absolute;top:12px;width:100%;text-align:center;padding:0 23px;box-sizing:border-box;font-weight:900;font-size:24px;font-family:sans-serif;height:2em;display:flex;justify-content:center;align-items:center;color:#333b40}._3UWaUYYyQc5VbvW6HKIRHv._2degJvmXASrj_NvC6CXWqN{top:0}._1Tg9slZrrhpko8KnDP7C6X{background-color:#229dff;letter-spacing:.5px;color:#fff;font-size:14px;text-transform:uppercase;font-weight:500;min-width:134px;outline:none;cursor:pointer;display:block;padding:12px 20px;border-radius:5px;transition:background-color .15s ease-out 0s;border:none;display:flex;align-items:center;justify-content:center;margin:auto;width:100%}@media(min-width:628px){._1Tg9slZrrhpko8KnDP7C6X{max-width:350px;width:45%}}._1Tg9slZrrhpko8KnDP7C6X:hover{background-color:#007ee8}._1Tg9slZrrhpko8KnDP7C6X:disabled{background-color:#88caff}._1Fm1wq10kVJMKVxtWwkZex use{fill:currentColor}._309CoDF8kNC59Cacci2i3u{position:absolute;bottom:-8px;justify-content:center;align-items:center;display:inline-block;text-align:center;width:100%;padding:16px;box-sizing:border-box}.vNKPZsVtPwMoITxtjuu9V{position:absolute}.tUn9t5uXBW0G4uOuaTOqA{padding:16px;font-size:40px;width:100%;text-align:center;display:grid;justify-content:center;grid-template-columns:repeat(3,80px) 50px;box-sizing:border-box;position:absolute;bottom:-8px}._1fIU1q1Zn5Q8C9xn0Ir-dW,._2mwc0c5WhPOqV9wJk9VkGV,._3JRt0WWENWRFRoNQBy35fI{width:51px;height:50px;font-size:40px;font-weight:700;text-align:center;line-height:55px;font-family:sans-serif;color:#333b40}._2mwc0c5WhPOqV9wJk9VkGV{opacity:.5}._1RzxXrRIq2Q9MbP1nZJdM9,._2_g_DOxWE8kqzFMzKyK37t,._3mr2-PKNrqmyEJlyzqUVvx{fill:#333b40}._1RzxXrRIq2Q9MbP1nZJdM9 use,._2_g_DOxWE8kqzFMzKyK37t use,._3mr2-PKNrqmyEJlyzqUVvx use{fill:inherit}._1fIU1q1Zn5Q8C9xn0Ir-dW svg,._2mwc0c5WhPOqV9wJk9VkGV svg,._3JRt0WWENWRFRoNQBy35fI svg{font-size:50px}._1RzxXrRIq2Q9MbP1nZJdM9{opacity:.5}._3GqInLQ5XsRTU_HmqqchW9{box-shadow:0 0 3px 1px rgba(0,0,0,.10980392156862745);transform:scaleX(-1);height:auto}._3Ums-OZ0qWebWj0SZbqYjT{position:relative;overflow:hidden;display:flex;flex-direction:column}.IOOd58zY5WSnpJo3-6iVV{position:relative}
1
+ ._2_U2DYHedfGUyvS1oS5{display:flex;flex-direction:column;overflow:hidden;position:relative}.mteIzegCA0cNMXt96BYN{position:relative}.Ds2gos19dHtdm4Aer1pq,.Va8swWS5S29Uvou7UNnc{height:100%;position:absolute;width:100%}.Ds2gos19dHtdm4Aer1pq{display:flex;justify-content:center;top:0}.x_r8eQXclQHy5Jjno7pU{display:block;height:100%;margin:auto;position:absolute}.HPEPfcUpwWOVOJSPP9R_{box-sizing:border-box;color:#67717f;height:100%;left:0;position:absolute;right:0}.HPEPfcUpwWOVOJSPP9R_._0fft05LhDRetV8QdNSI{color:#39c48e}.HPEPfcUpwWOVOJSPP9R_.JHe4OqVjOOuBZXJn_axE{color:#ffba37}.xsnSbKRs6MZbpP2odJGk{box-sizing:border-box;position:absolute;width:100%}.xsnSbKRs6MZbpP2odJGk.lSsJ_kvBTJOO0shULKLn{height:43.5%;top:28.3%}.xsnSbKRs6MZbpP2odJGk._6X0Zl0a0b8R2wCqGS_K{height:71.7%;top:11.5%}.IpX4dJbHat9i3luoCwef{align-items:start;background-color:#fff;border-radius:.3em;box-shadow:0 8px 15px #333b401a;box-sizing:border-box;color:#333b40;display:flex;font-family:sans-serif;font-size:16px;font-size:var(--message-font-size);font-weight:900;justify-content:start;left:50%;padding:.4em 0;position:absolute;text-align:center}.a_0VmnisbKCGWfubHrmj{margin-bottom:50px;top:4.6%;transform:translate(-50%);width:90%}.CqNtyAmFAcDIeu8mRGPD{top:5.5%;transform:translate(-50%);width:51.25%}.rlF15FcuMGotbEHYe5KW{align-items:start;font-size:calc(var(--message-font-size) + 3px)}._CvVxyqwMB2D7fkKx_NZ{display:flex;justify-content:center;order:1;width:14%}._znJxLRvhRnuCU0KBY3_{order:2;width:72%}.aM6UBOeSFg8vwirw8BEs{position:absolute}.RxkomAqHmrdu47_oGii4{bottom:-8px;box-sizing:border-box;display:grid;font-size:40px;grid-template-columns:repeat(3,80px) 50px;justify-content:center;padding:16px;position:absolute;text-align:center;width:100%}.ZSTtG9h6K6_0_axlDNnV,.__OOQVMtxL3v8uCw9eKy,.hwSkw4zQBundKmrqIwqC{color:#333b40;font-family:sans-serif;font-size:40px;font-weight:700;height:50px;line-height:55px;text-align:center;width:51px}.__OOQVMtxL3v8uCw9eKy{opacity:.5}.Gf_S7QnzULbIZZZ7roY2,.OZI1jG8pdtaOfb2ZsB2n,.XOix2SeWtEFksSSmLt9v{fill:#333b40}.Gf_S7QnzULbIZZZ7roY2 use,.OZI1jG8pdtaOfb2ZsB2n use,.XOix2SeWtEFksSSmLt9v use{fill:inherit}.ZSTtG9h6K6_0_axlDNnV svg,.__OOQVMtxL3v8uCw9eKy svg,.hwSkw4zQBundKmrqIwqC svg{font-size:50px}.Gf_S7QnzULbIZZZ7roY2{opacity:.5}._XKP_3EMO0LKJr53EW21{box-shadow:0 0 3px 1px #0000001c;height:auto;transform:scaleX(-1);width:100%}@keyframes TgYAVlLOGfJ_hl3TBdkC{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.X_Bq5FImnGbO6TLe3Len{align-items:center;display:flex;height:100%;justify-content:center;line-height:0;text-align:center}.WPX6_jcjLpB6aH420ZCd{animation:TgYAVlLOGfJ_hl3TBdkC 1.5s infinite}.bPwt8l_jKvlB2llQ7azY{height:35.71px;width:35.71px}.bPwt8l_jKvlB2llQ7azY use{fill:#333b40}.mtcvKOHbFdRFpAH7ZHwW{align-items:center;background-color:#229dff;border:none;border-radius:5px;color:#fff;cursor:pointer;display:block;display:flex;font-size:14px;font-weight:500;justify-content:center;letter-spacing:.5px;margin:auto;min-width:134px;outline:none;padding:12px 20px;text-transform:uppercase;transition:background-color .15s ease-out 0s;width:100%}.mtcvKOHbFdRFpAH7ZHwW.kYH4ilWb5sFtCcwqD29n{max-width:350px;width:45%}.mtcvKOHbFdRFpAH7ZHwW:hover{background-color:#007ee8}.mtcvKOHbFdRFpAH7ZHwW:disabled{background-color:#88caff}.GusgiqC_1nbmjyHkruu0 use{fill:currentColor}.dDcfK_agfQV9XSYSuuxR{align-items:center;bottom:-8px;box-sizing:border-box;display:inline-block;justify-content:center;padding:16px;position:absolute;text-align:center;width:100%}