idmission-web-sdk 1.0.104 → 1.0.105

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.
@@ -3,6 +3,7 @@ import { ThemeInput } from '../../themes';
3
3
  import { LangOption } from '../../lib/locales';
4
4
  import { SubmissionRequest, SubmissionResponse } from '../../contexts/SubmissionContext';
5
5
  import { DocumentCaptureWizardClassNames } from '../document_capture/DocumentCaptureWizard';
6
+ import { CameraFeedMode } from '../document_capture/DocumentCaptureScreen';
6
7
  export type DocumentCaptureClassNames = DocumentCaptureWizardClassNames;
7
8
  export interface DocumentCaptureProps extends PropsWithChildren {
8
9
  /** Language code to use. Supported values: 'auto' (detect based on user's OS), 'en' (English), 'es' (Spanish). Defaults to auto. */
@@ -11,6 +12,8 @@ export interface DocumentCaptureProps extends PropsWithChildren {
11
12
  submissionToken: string;
12
13
  /** URL to hit with all API requests. Defaults to the value specified in your decoded `submissionToken`. */
13
14
  submissionUrl?: string;
15
+ /** URL to upload captured documents to via Tus. */
16
+ documentServiceUrl?: string;
14
17
  /** Callback function that fires immediately prior to submission, giving the client application an opportunity to specify custom asynchronous logic that mutates the request before it executes. The submission request is passed in as a parameter and a promise resolving to the updated request should be returned. */
15
18
  onBeforeSubmit?: (req: SubmissionRequest) => Promise<SubmissionRequest>;
16
19
  /** Callback function that fires when the user has completed the flow instead of making a call to IDmission's servers, allowing customers to specify their own submission logic. Arguments: the request payload that would have been dispatched to IDmission's API, which contains the images/documents/video submitted by the user. Note that when this parameter is supplied, `onComplete` will never fire, and the customer will need to implement their own error handling/retry logic. Use at your own risk! */
@@ -22,6 +25,7 @@ export interface DocumentCaptureProps extends PropsWithChildren {
22
25
  /** Callback function that fires when the user clicks the exit button from the loading overlay, declining to engage with IDmission. Binding this callback results in the cancel button being rendered on the loading overlay. */
23
26
  onUserCancel?: () => void;
24
27
  aspectRatio?: number;
28
+ cameraFeedMode?: CameraFeedMode;
25
29
  instructions?: ReactNode;
26
30
  /** Name of an included theme or object containing theme properties. **/
27
31
  theme?: ThemeInput;
@@ -7,7 +7,7 @@ export type DocumentCaptureGuideOverlayProps = {
7
7
  borderRadius?: number;
8
8
  borderColor?: string;
9
9
  borderWidth?: number;
10
- maskColor?: string;
10
+ maskColor: string;
11
11
  padding?: number;
12
12
  classNames?: DocumentCaptureGuideOverlayClassNames;
13
13
  };
@@ -0,0 +1,15 @@
1
+ import React, { ReactNode } from 'react';
2
+ export type CameraFeedMode = 'snapToGuides' | 'fullscreen';
3
+ export type DocumentCaptureScreenClassNames = {
4
+ container?: string;
5
+ cameraFeed?: string;
6
+ };
7
+ export type DocumentCaptureScreenProps = {
8
+ aspectRatio?: number;
9
+ cameraFeedMode?: CameraFeedMode;
10
+ classNames?: DocumentCaptureScreenClassNames;
11
+ instructions?: ReactNode;
12
+ onCaptureClicked?: () => void;
13
+ onSuccess?: (blob: Blob) => void;
14
+ };
15
+ export declare const DocumentCaptureScreen: ({ aspectRatio, cameraFeedMode, classNames, instructions, onCaptureClicked, onSuccess, }: DocumentCaptureScreenProps) => React.JSX.Element;
@@ -0,0 +1,68 @@
1
+ import React, { Dispatch, ReactNode } from 'react';
2
+ export type DocumentCaptureState = {
3
+ initialDrawComplete: boolean;
4
+ redrawing: boolean;
5
+ rectX: number;
6
+ rectY: number;
7
+ rectWidth: number;
8
+ rectHeight: number;
9
+ rectOffsetTop: number;
10
+ capturing: boolean;
11
+ imageUrl: string;
12
+ imageBlob: Blob | null;
13
+ uploadState: 'not_started' | 'in_progress' | 'succeeded' | 'failed';
14
+ };
15
+ export declare const documentCaptureInitialState: {
16
+ initialDrawComplete: false;
17
+ redrawing: false;
18
+ capturing: false;
19
+ rectX: number;
20
+ rectY: number;
21
+ rectWidth: number;
22
+ rectHeight: number;
23
+ rectOffsetTop: number;
24
+ imageUrl: string;
25
+ imageBlob: null;
26
+ uploadState: "not_started";
27
+ };
28
+ export declare const DocumentCaptureStateContext: React.Context<DocumentCaptureState>;
29
+ export type DocumentCaptureAction = {
30
+ type: 'redrawRequested';
31
+ } | {
32
+ type: 'redrawInProgress';
33
+ } | {
34
+ type: 'redrawCompleted';
35
+ payload: {
36
+ rectX: number;
37
+ rectY: number;
38
+ rectWidth: number;
39
+ rectHeight: number;
40
+ rectOffsetTop: number;
41
+ };
42
+ } | {
43
+ type: 'captureRequested';
44
+ } | {
45
+ type: 'captureCompleted';
46
+ payload: {
47
+ imageUrl: string;
48
+ imageBlob: Blob;
49
+ };
50
+ } | {
51
+ type: 'retryCapture';
52
+ } | {
53
+ type: 'uploadStarted';
54
+ } | {
55
+ type: 'uploadCompleted';
56
+ } | {
57
+ type: 'uploadFailed';
58
+ };
59
+ export type DocumentCaptureDispatch = Dispatch<DocumentCaptureAction>;
60
+ export declare const DocumentCaptureDispatchContext: React.Context<DocumentCaptureDispatch>;
61
+ export declare const documentCaptureStateReducer: (state: DocumentCaptureState, action: DocumentCaptureAction) => DocumentCaptureState;
62
+ export declare const DocumentCaptureStateProvider: ({ children, }: {
63
+ children: ReactNode;
64
+ }) => React.JSX.Element;
65
+ export declare const useDocumentCaptureState: () => [
66
+ DocumentCaptureState,
67
+ DocumentCaptureDispatch
68
+ ];
@@ -1,14 +1,13 @@
1
1
  import React, { ReactNode } from 'react';
2
- export type DocumentCaptureWizardClassNames = {
3
- container?: string;
4
- cameraFeed?: string;
5
- };
2
+ import { CameraFeedMode, DocumentCaptureScreenClassNames } from './DocumentCaptureScreen';
3
+ export type DocumentCaptureWizardClassNames = DocumentCaptureScreenClassNames;
6
4
  export type DocumentCaptureWizardProps = {
7
5
  onSuccess?: () => void;
8
6
  onExitCapture?: () => void;
9
7
  onUserCancel?: () => void;
10
8
  aspectRatio?: number;
9
+ cameraFeedMode?: CameraFeedMode;
11
10
  instructions?: ReactNode;
12
11
  classNames?: DocumentCaptureWizardClassNames;
13
12
  };
14
- export declare const DocumentCaptureWizard: ({ aspectRatio, instructions, classNames, }: DocumentCaptureWizardProps) => React.JSX.Element;
13
+ export declare const DocumentCaptureWizard: ({ onSuccess, aspectRatio, cameraFeedMode, instructions, classNames, }: DocumentCaptureWizardProps) => React.JSX.Element;
@@ -32,6 +32,7 @@ export type SubmissionState = {
32
32
  setIdCaptureVideoIdFrontImage: (image: string) => void;
33
33
  setIdCaptureVideoIdBackImage: (image: string) => void;
34
34
  setAdditionalDocuments: (uploadedDocuments: UploadedDocument[]) => void;
35
+ uploadDocument: (blob: Blob) => Promise<string>;
35
36
  logIdFrontCaptureAttempt: (attempt: CaptureAttemptMetadata) => void;
36
37
  logIdBackCaptureAttempt: (attempt: CaptureAttemptMetadata) => void;
37
38
  logSelfieCaptureAttempt: (attempt: CaptureAttemptMetadata) => void;
@@ -68,10 +69,11 @@ export type SubmissionProviderProps = {
68
69
  webhooksSendProcessedImages?: boolean;
69
70
  webhooksFireOnReview?: boolean;
70
71
  precapturedDocuments?: CapturedDocuments;
72
+ documentServiceUrl?: string;
71
73
  onSubmit?: (payload: SubmissionRequest) => void;
72
74
  onBeforeSubmit?: (req: SubmissionRequest) => Promise<SubmissionRequest>;
73
75
  onBeforeLivenessCheck?: (req: LivenessCheckRequest) => Promise<LivenessCheckRequest>;
74
76
  onResponseReceived?: (res: SubmissionResponse, req: SubmissionRequest) => void;
75
77
  onRequestFailure?: (err: Error) => void;
76
78
  };
77
- export declare const SubmissionProvider: ({ action, children, url, environment, token, companyId, enrollmentId, personalData, cardData, bypassAgeValidation, bypassNameMatching, needImmediateResponse, manualReviewRequired, idBackImageRequired, idImageResolutionCheck, verifyIdWithExternalDatabases, deduplicationEnabled, deduplicationSynchronous, geolocationEnabled, geolocationRequired, webhooksEnabled, webhooksClientTraceId, webhooksStripSpecialCharacters, webhooksSendInputImages, webhooksSendProcessedImages, webhooksFireOnReview, precapturedDocuments, onSubmit, onBeforeSubmit, onBeforeLivenessCheck, onResponseReceived, onRequestFailure, }: SubmissionProviderProps) => ReactElement;
79
+ export declare const SubmissionProvider: ({ action, children, url, environment, token, companyId, enrollmentId, personalData, cardData, bypassAgeValidation, bypassNameMatching, needImmediateResponse, manualReviewRequired, idBackImageRequired, idImageResolutionCheck, verifyIdWithExternalDatabases, deduplicationEnabled, deduplicationSynchronous, geolocationEnabled, geolocationRequired, webhooksEnabled, webhooksClientTraceId, webhooksStripSpecialCharacters, webhooksSendInputImages, webhooksSendProcessedImages, webhooksFireOnReview, precapturedDocuments, documentServiceUrl, onSubmit, onBeforeSubmit, onBeforeLivenessCheck, onResponseReceived, onRequestFailure, }: SubmissionProviderProps) => ReactElement;
@@ -7,6 +7,7 @@ var React = require('react');
7
7
  var ReactDOM = require('react-dom/client');
8
8
  var styled = require('styled-components');
9
9
  var reactI18next = require('react-i18next');
10
+ var tus = require('tus-js-client');
10
11
  var useResizeObserver = require('use-resize-observer');
11
12
  var tf = require('@tensorflow/tfjs');
12
13
  var LanguageDetector = require('i18next-browser-languagedetector');
@@ -40,15 +41,17 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
40
41
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
41
42
  var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
42
43
  var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled);
44
+ var tus__namespace = /*#__PURE__*/_interopNamespace(tus);
43
45
  var useResizeObserver__default = /*#__PURE__*/_interopDefaultLegacy(useResizeObserver);
44
46
  var tf__namespace = /*#__PURE__*/_interopNamespace(tf);
45
47
  var LanguageDetector__default = /*#__PURE__*/_interopDefaultLegacy(LanguageDetector);
46
48
  var i18n__default = /*#__PURE__*/_interopDefaultLegacy(i18n);
47
49
  var SignatureCanvas__default = /*#__PURE__*/_interopDefaultLegacy(SignatureCanvas);
48
50
 
49
- var webSdkVersion = '1.0.104';
51
+ var webSdkVersion = '1.0.105';
50
52
 
51
53
  function getPlatform() {
54
+ if (typeof window === 'undefined') return;
52
55
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
53
56
  // @ts-ignore
54
57
  return window.platform;
@@ -149,7 +152,7 @@ function attachMetadataToRequest(request, _a) {
149
152
  back: idBackCaptureAttempts,
150
153
  isRealIDCheckRequired: 'false',
151
154
  sdkVersion: "WebSDK_".concat(webSdkVersion),
152
- Resolution: "".concat(window.innerWidth, " x ").concat(window.innerHeight)
155
+ Resolution: typeof window !== 'undefined' ? "".concat(window.innerWidth, " x ").concat(window.innerHeight) : 'unknown'
153
156
  };
154
157
  var platform = getPlatform();
155
158
  if (platform) {
@@ -193,6 +196,7 @@ var PageContainer = /*#__PURE__*/React.forwardRef(function (_a, ref) {
193
196
  dimensionsCalculated = _c[0],
194
197
  setDimensionsCalculated = _c[1];
195
198
  React.useEffect(function () {
199
+ if (typeof window === 'undefined') return;
196
200
  setDimensionsCalculated(false);
197
201
  var calcAppDimensions = function calcAppDimensions() {
198
202
  var doc = document.documentElement;
@@ -663,6 +667,7 @@ var SubmissionContext = /*#__PURE__*/React.createContext({
663
667
  setAdditionalDocuments: function setAdditionalDocuments() {
664
668
  return null;
665
669
  },
670
+ uploadDocument: Promise.resolve,
666
671
  logIdFrontCaptureAttempt: function logIdFrontCaptureAttempt() {
667
672
  return null;
668
673
  },
@@ -729,6 +734,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
729
734
  _t = _a.webhooksFireOnReview,
730
735
  webhooksFireOnReview = _t === void 0 ? false : _t,
731
736
  precapturedDocuments = _a.precapturedDocuments,
737
+ documentServiceUrl = _a.documentServiceUrl,
732
738
  onSubmit = _a.onSubmit,
733
739
  onBeforeSubmit = _a.onBeforeSubmit,
734
740
  onBeforeLivenessCheck = _a.onBeforeLivenessCheck,
@@ -1167,6 +1173,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1167
1173
  tokenError = _17[0],
1168
1174
  setTokenError = _17[1];
1169
1175
  React.useEffect(function () {
1176
+ if (typeof window === 'undefined') return;
1170
1177
  (function () {
1171
1178
  return tslib.__awaiter(void 0, void 0, void 0, function () {
1172
1179
  var parsed, iss, publicKey, resp, e_3, valid, parts, e_4, exp;
@@ -1239,6 +1246,42 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1239
1246
  });
1240
1247
  })();
1241
1248
  }, [token]);
1249
+ var uploadDocument = React.useCallback(function (blob) {
1250
+ return new Promise(function (resolve, reject) {
1251
+ var upload = new tus__namespace.Upload(blob, {
1252
+ endpoint: documentServiceUrl,
1253
+ retryDelays: [0, 3000, 5000, 10000, 20000],
1254
+ metadata: {
1255
+ filename: 'My File',
1256
+ filetype: 'image/jpeg'
1257
+ },
1258
+ headers: {
1259
+ Authorization: "Bearer ".concat(token)
1260
+ },
1261
+ onProgress: function onProgress(bytesUploaded, bytesTotal) {
1262
+ var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
1263
+ console.log(bytesUploaded, bytesTotal, percentage + '%');
1264
+ },
1265
+ onSuccess: function onSuccess() {
1266
+ console.log('Download from %s', upload.url);
1267
+ resolve(upload.url);
1268
+ },
1269
+ onError: function onError(error) {
1270
+ console.log('Failed because: ' + error);
1271
+ reject(error);
1272
+ }
1273
+ });
1274
+ // Check if there are any previous uploads to continue.
1275
+ upload.findPreviousUploads().then(function (previousUploads) {
1276
+ // Found previous uploads so we select the first one.
1277
+ if (previousUploads.length) {
1278
+ upload.resumeFromPreviousUpload(previousUploads[0]);
1279
+ }
1280
+ // Start the upload
1281
+ upload.start();
1282
+ });
1283
+ });
1284
+ }, [token]);
1242
1285
  var value = {
1243
1286
  submit: submit,
1244
1287
  submissionStatus: submissionStatus,
@@ -1266,6 +1309,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1266
1309
  setIdCaptureVideoIdFrontImage: setIdCaptureVideoIdFrontImage,
1267
1310
  setIdCaptureVideoIdBackImage: setIdCaptureVideoIdBackImage,
1268
1311
  setAdditionalDocuments: setAdditionalDocuments,
1312
+ uploadDocument: uploadDocument,
1269
1313
  logIdFrontCaptureAttempt: logIdFrontCaptureAttempt,
1270
1314
  logIdBackCaptureAttempt: logIdBackCaptureAttempt,
1271
1315
  logSelfieCaptureAttempt: logSelfieCaptureAttempt,
@@ -1309,6 +1353,7 @@ function str2ab(str) {
1309
1353
  return buf;
1310
1354
  }
1311
1355
  function importRsaKey(pem) {
1356
+ if (typeof window === 'undefined') throw new Error('window cannot be undefined');
1312
1357
  // fetch the part of the PEM string between header and footer
1313
1358
  var pemHeader = '-----BEGIN PUBLIC KEY-----';
1314
1359
  var pemFooter = '-----END PUBLIC KEY-----';
@@ -10539,7 +10584,7 @@ var CameraVideoTag = function CameraVideoTag(_a) {
10539
10584
  "$isRearFacing": (_b = cameraRef.current) === null || _b === void 0 ? void 0 : _b.isRearFacing
10540
10585
  });
10541
10586
  };
10542
- var FullscreenVideoTag = styled__default['default'].video(templateObject_1$h || (templateObject_1$h = tslib.__makeTemplateObject(["\n transform: ", ";\n min-width: 100%;\n min-height: 100%;\n width: auto;\n height: auto;\n object-fit: cover;\n"], ["\n transform: ", ";\n min-width: 100%;\n min-height: 100%;\n width: auto;\n height: auto;\n object-fit: cover;\n"])), function (props) {
10587
+ var FullscreenVideoTag = styled__default['default'].video(templateObject_1$h || (templateObject_1$h = tslib.__makeTemplateObject(["\n transform: ", ";\n min-width: 100%;\n min-height: 100%;\n width: auto;\n height: auto;\n object-fit: cover;\n background: black;\n"], ["\n transform: ", ";\n min-width: 100%;\n min-height: 100%;\n width: auto;\n height: auto;\n object-fit: cover;\n background: black;\n"])), function (props) {
10543
10588
  return props.$isRearFacing ? '' : 'scaleX(-1)';
10544
10589
  });
10545
10590
  var templateObject_1$h;
@@ -12795,7 +12840,7 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
12795
12840
  var _b = [cameraRef.current.width, cameraRef.current.height],
12796
12841
  w = _b[0],
12797
12842
  h = _b[1];
12798
- var isPortrait = window.innerWidth < window.innerHeight;
12843
+ var isPortrait = typeof window !== 'undefined' && window.innerWidth < window.innerHeight;
12799
12844
  var cameraIsLandscape = w > h;
12800
12845
  if (isPortrait && cameraIsLandscape) _a = [h, w], w = _a[0], h = _a[1];
12801
12846
  outputCanvas.current.width = w;
@@ -13305,7 +13350,7 @@ var IdVideoCaptureGuides = function IdVideoCaptureGuides(_a) {
13305
13350
  idBackInstructionText: 'Display the back of your ID card...'
13306
13351
  });
13307
13352
  var instructionText = requestedAction === 'SHOW_ID_FRONT' ? verbiage.idFrontInstructionText : verbiage.idBackInstructionText;
13308
- var idGuideWidth = window.innerWidth > window.innerHeight ? '30%' : '75%';
13353
+ var idGuideWidth = typeof window !== 'undefined' && window.innerWidth > window.innerHeight ? '30%' : '75%';
13309
13354
  return /*#__PURE__*/React__default['default'].createElement(React__default['default'].Fragment, null, /*#__PURE__*/React__default['default'].createElement("div", {
13310
13355
  style: {
13311
13356
  position: 'absolute',
@@ -13450,7 +13495,7 @@ var ReadTextPromptHeading = styled__default['default'].div(templateObject_2$4 ||
13450
13495
  var _a, _b, _c, _d, _e, _f;
13451
13496
  return ((_c = (_b = (_a = props.theme.idVideoCapture) === null || _a === void 0 ? void 0 : _a.readTextPrompt) === null || _b === void 0 ? void 0 : _b.heading) === null || _c === void 0 ? void 0 : _c.borderRadius) ? "border-radius: ".concat((_f = (_e = (_d = props.theme.idVideoCapture) === null || _d === void 0 ? void 0 : _d.readTextPrompt) === null || _e === void 0 ? void 0 : _e.heading) === null || _f === void 0 ? void 0 : _f.borderRadius, ";") : "";
13452
13497
  });
13453
- var ReadTextPromptText = styled__default['default'].div(templateObject_3$4 || (templateObject_3$4 = tslib.__makeTemplateObject(["\n margin: 0 auto;\n text-align: center;\n padding: 50px;\n font-size: 24px;\n max-width: ", ";\n\n ", ";\n ", ";\n ", ";\n"], ["\n margin: 0 auto;\n text-align: center;\n padding: 50px;\n font-size: 24px;\n max-width: ", ";\n\n ", ";\n ", ";\n ", ";\n"])), window.innerWidth > window.innerHeight ? '40%' : '90%', function (props) {
13498
+ var ReadTextPromptText = styled__default['default'].div(templateObject_3$4 || (templateObject_3$4 = tslib.__makeTemplateObject(["\n margin: 0 auto;\n text-align: center;\n padding: 50px;\n font-size: 24px;\n max-width: ", ";\n\n ", ";\n ", ";\n ", ";\n"], ["\n margin: 0 auto;\n text-align: center;\n padding: 50px;\n font-size: 24px;\n max-width: ", ";\n\n ", ";\n ", ";\n ", ";\n"])), typeof window !== 'undefined' && window.innerWidth > window.innerHeight ? '40%' : '90%', function (props) {
13454
13499
  var _a, _b, _c, _d, _e, _f;
13455
13500
  return ((_c = (_b = (_a = props.theme.idVideoCapture) === null || _a === void 0 ? void 0 : _a.readTextPrompt) === null || _b === void 0 ? void 0 : _b.prompt) === null || _c === void 0 ? void 0 : _c.backgroundColor) ? "background: ".concat((_f = (_e = (_d = props.theme.idVideoCapture) === null || _d === void 0 ? void 0 : _d.readTextPrompt) === null || _e === void 0 ? void 0 : _e.prompt) === null || _f === void 0 ? void 0 : _f.backgroundColor, ";") : "";
13456
13501
  }, function (props) {