├── .babelrc ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .nojekyll ├── .nvmrc ├── .travis.yml ├── CHANGELOG.md ├── README.md ├── client-library ├── .gitignore ├── README.md ├── examples │ ├── example.cloud.html │ ├── example.self-hosted.html │ └── style.css ├── package-lock.json ├── package.json ├── rollup.config.js ├── src │ ├── Client.ts │ ├── data-structures.ts │ ├── service.cloud.ts │ ├── service.self-hosted.ts │ └── util.ts └── tsconfig.json ├── examples ├── README.md ├── blinkid-camera │ ├── javascript │ │ ├── app.js │ │ ├── index.html │ │ └── style.css │ └── typescript │ │ ├── .gitignore │ │ ├── package.json │ │ ├── public │ │ ├── index.html │ │ └── style.css │ │ ├── rollup.config.js │ │ ├── src │ │ └── app.ts │ │ └── tsconfig.json ├── blinkid-file │ ├── javascript │ │ ├── app.js │ │ ├── index.html │ │ └── style.css │ └── typescript │ │ ├── .gitignore │ │ ├── package.json │ │ ├── public │ │ ├── index.html │ │ └── style.css │ │ ├── rollup.config.js │ │ ├── src │ │ └── app.ts │ │ └── tsconfig.json ├── combined-file │ ├── javascript │ │ ├── app.js │ │ ├── index.html │ │ └── style.css │ └── typescript │ │ ├── .gitignore │ │ ├── package.json │ │ ├── public │ │ ├── index.html │ │ └── style.css │ │ ├── rollup.config.js │ │ ├── src │ │ └── app.ts │ │ └── tsconfig.json └── combined │ ├── javascript │ ├── app.js │ ├── index.html │ └── style.css │ └── typescript │ ├── .gitignore │ ├── package.json │ ├── public │ ├── index.html │ └── style.css │ ├── rollup.config.js │ ├── src │ └── app.ts │ └── tsconfig.json ├── oss-dependencies ├── c++-advanced.json ├── c++-basic.json └── npm.txt ├── package-lock.json ├── package.json ├── resources-lightweight ├── BlinkIDImageCaptureWasmSDK.worker.min.js ├── advanced-threads │ ├── BlinkIDImageCaptureWasmSDK.data │ ├── BlinkIDImageCaptureWasmSDK.js │ ├── BlinkIDImageCaptureWasmSDK.wasm │ └── BlinkIDImageCaptureWasmSDK.worker.js ├── advanced │ ├── BlinkIDImageCaptureWasmSDK.data │ ├── BlinkIDImageCaptureWasmSDK.js │ └── BlinkIDImageCaptureWasmSDK.wasm └── basic │ ├── BlinkIDImageCaptureWasmSDK.data │ ├── BlinkIDImageCaptureWasmSDK.js │ └── BlinkIDImageCaptureWasmSDK.wasm ├── resources ├── BlinkIDImageCaptureWasmSDK.worker.min.js ├── advanced-threads │ ├── BlinkIDImageCaptureWasmSDK.data │ ├── BlinkIDImageCaptureWasmSDK.js │ ├── BlinkIDImageCaptureWasmSDK.wasm │ └── BlinkIDImageCaptureWasmSDK.worker.js ├── advanced │ ├── BlinkIDImageCaptureWasmSDK.data │ ├── BlinkIDImageCaptureWasmSDK.js │ └── BlinkIDImageCaptureWasmSDK.wasm └── basic │ ├── BlinkIDImageCaptureWasmSDK.data │ ├── BlinkIDImageCaptureWasmSDK.js │ └── BlinkIDImageCaptureWasmSDK.wasm ├── rollup.config.js ├── src ├── MicroblinkSDK │ ├── CameraUtils.ts │ ├── ClearTimeoutCallback.ts │ ├── DataStructures.ts │ ├── DeviceUtils.ts │ ├── ErrorTypes.ts │ ├── FrameCapture.ts │ ├── Geometry.ts │ ├── License.ts │ ├── LoadProgressUtils.ts │ ├── MetadataCallbacks.ts │ ├── MicroblinkSDK.ts │ ├── PThreadHelper.ts │ ├── SDKError.ts │ ├── Utils.ts │ ├── VideoRecognizer.ts │ ├── WasmLoadSettings.ts │ ├── WasmLoadUtils.ts │ ├── WasmType.ts │ ├── local │ │ └── LocalSDKBackend.ts │ └── worker │ │ ├── Messages.ts │ │ ├── MicroblinkSDK.worker.ts │ │ └── WorkerSDKBackend.ts ├── Recognizers │ ├── BlinkID │ │ ├── Generic │ │ │ ├── ClassInfo.ts │ │ │ ├── ImageAnalysisResult.ts │ │ │ ├── ProcessingStatus.ts │ │ │ └── RecognitionModeFilter.ts │ │ ├── ImageCapture │ │ │ └── ImageCaptureRecognizer.ts │ │ └── ImageOptions.ts │ └── SuccessFrameGrabberRecognizer.ts ├── defaultWasmModule.ts ├── index.ts └── worker.ts ├── tsconfig.json └── ui ├── .editorconfig ├── README.md ├── demo.html ├── docs └── components │ ├── blinkid-imagecapture-in-browser │ └── readme.md │ └── shared │ ├── mb-api-process-status │ └── readme.md │ ├── mb-button-classic │ └── readme.md │ ├── mb-button │ └── readme.md │ ├── mb-camera-experience │ └── readme.md │ ├── mb-camera-selection │ └── readme.md │ ├── mb-camera-toolbar │ └── readme.md │ ├── mb-completed │ └── readme.md │ ├── mb-component │ └── readme.md │ ├── mb-container │ └── readme.md │ ├── mb-feedback │ └── readme.md │ ├── mb-image-box │ └── readme.md │ ├── mb-modal │ └── readme.md │ ├── mb-overlay │ └── readme.md │ ├── mb-screen │ └── readme.md │ ├── mb-spinner │ └── readme.md │ └── mb-tooltip │ └── readme.md ├── examples ├── README.md ├── javascript-combined │ └── index.html ├── javascript │ └── index.html └── typescript │ ├── .gitignore │ ├── package.json │ ├── public │ ├── index.html │ └── style.css │ ├── rollup.config.js │ ├── src │ └── app.ts │ └── tsconfig.json ├── package-lock.json ├── package.json ├── src ├── components.d.ts ├── components │ ├── blinkid-imagecapture-in-browser │ │ ├── blinkid-imagecapture-in-browser.scss │ │ ├── blinkid-imagecapture-in-browser.tsx │ │ └── test │ │ │ ├── blinkid-imagecapture-in-browser.e2e.ts │ │ │ └── blinkid-imagecapture-in-browser.spec.tsx │ └── shared │ │ ├── .editorconfig │ │ ├── mb-api-process-status │ │ ├── mb-api-process-status.scss │ │ ├── mb-api-process-status.tsx │ │ └── test │ │ │ ├── mb-api-process-status.e2e.ts │ │ │ └── mb-api-process-status.spec.tsx │ │ ├── mb-button-classic │ │ ├── mb-button-classic.scss │ │ ├── mb-button-classic.tsx │ │ └── test │ │ │ ├── mb-button-classic.e2e.ts │ │ │ └── mb-button-classic.spec.tsx │ │ ├── mb-button │ │ ├── mb-button.scss │ │ ├── mb-button.tsx │ │ └── test │ │ │ ├── mb-button.e2e.ts │ │ │ └── mb-button.spec.tsx │ │ ├── mb-camera-experience │ │ ├── mb-camera-experience.scss │ │ ├── mb-camera-experience.tsx │ │ ├── mb-camera-experience.utils.ts │ │ └── test │ │ │ ├── mb-camera-experience.e2e.ts │ │ │ └── mb-camera-experience.spec.tsx │ │ ├── mb-camera-selection │ │ ├── mb-camera-selection.scss │ │ ├── mb-camera-selection.tsx │ │ └── test │ │ │ ├── mb-camera-selection.e2e.ts │ │ │ └── mb-camera-selection.spec.tsx │ │ ├── mb-camera-toolbar │ │ ├── mb-camera-toolbar.scss │ │ ├── mb-camera-toolbar.tsx │ │ └── test │ │ │ ├── mb-camera-toolbar.e2e.ts │ │ │ └── mb-camera-toolbar.spec.tsx │ │ ├── mb-completed │ │ ├── mb-completed.scss │ │ ├── mb-completed.tsx │ │ └── test │ │ │ ├── mb-completed.e2e.ts │ │ │ └── mb-completed.spec.tsx │ │ ├── mb-component │ │ ├── mb-component.scss │ │ ├── mb-component.tsx │ │ ├── mb-component.utils.ts │ │ └── test │ │ │ ├── mb-component.e2e.ts │ │ │ └── mb-component.spec.tsx │ │ ├── mb-container │ │ ├── mb-container.scss │ │ ├── mb-container.tsx │ │ └── test │ │ │ ├── mb-container.e2e.ts │ │ │ └── mb-container.spec.tsx │ │ ├── mb-feedback │ │ ├── mb-feedback.scss │ │ ├── mb-feedback.tsx │ │ ├── mb-feedback.utils.ts │ │ └── test │ │ │ ├── mb-feedback.e2e.ts │ │ │ └── mb-feedback.spec.tsx │ │ ├── mb-image-box │ │ ├── mb-image-box.scss │ │ ├── mb-image-box.tsx │ │ └── test │ │ │ ├── mb-image-box.e2e.ts │ │ │ └── mb-image-box.spec.tsx │ │ ├── mb-modal │ │ ├── mb-modal.scss │ │ ├── mb-modal.tsx │ │ └── test │ │ │ ├── mb-modal.e2e.ts │ │ │ └── mb-modal.spec.tsx │ │ ├── mb-overlay │ │ ├── mb-overlay.scss │ │ ├── mb-overlay.tsx │ │ └── test │ │ │ ├── mb-overlay.e2e.ts │ │ │ └── mb-overlay.spec.tsx │ │ ├── mb-screen │ │ ├── mb-screen.scss │ │ ├── mb-screen.tsx │ │ └── test │ │ │ ├── mb-screen.e2e.ts │ │ │ └── mb-screen.spec.tsx │ │ ├── mb-spinner │ │ ├── mb-spinner.scss │ │ ├── mb-spinner.tsx │ │ └── test │ │ │ ├── mb-spinner.e2e.ts │ │ │ └── mb-spinner.spec.tsx │ │ ├── mb-tooltip │ │ ├── mb-tooltip.scss │ │ ├── mb-tooltip.tsx │ │ └── test │ │ │ ├── mb-tooltip.e2e.ts │ │ │ └── mb-tooltip.spec.tsx │ │ └── styles │ │ ├── _barcode-rectangle.scss │ │ ├── _globals-sass.scss │ │ ├── _globals.scss │ │ ├── _payment-card-rectangle.scss │ │ └── _reticle.scss ├── index.html ├── index.ts └── utils │ ├── data-structures.ts │ ├── device.helpers.ts │ ├── error-structures.ts │ ├── generic.helpers.ts │ ├── sdk.service.ts │ └── translation.service.ts ├── stencil.config.ts └── tsconfig.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # Tab indentation 12 | [*.{js,ts,md}] 13 | indent_style = space 14 | indent_size = 4 -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "browser": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:@typescript-eslint/recommended-requiring-type-checking" 10 | ], 11 | "parser": "@typescript-eslint/parser", 12 | "parserOptions": { 13 | "ecmaVersion": 6, 14 | "sourceType": "module", 15 | "project": ["./tsconfig.json"] 16 | }, 17 | "plugins": [ "@typescript-eslint" ], 18 | "rules": { 19 | "brace-style": ["error", "allman", { "allowSingleLine": true }], 20 | "eol-last": ["error", "always"], 21 | "eqeqeq": ["error", "always"], 22 | "indent": ["error", 4, { "SwitchCase": 1 }], 23 | "linebreak-style": ["error", "unix"], 24 | "lines-between-class-members": ["error", "always"], 25 | "max-len": ["error", { "code": 120 }], 26 | "new-cap": "error", 27 | "no-irregular-whitespace": ["off"], 28 | "no-multiple-empty-lines": "error", 29 | "no-nested-ternary": "error", 30 | "no-trailing-spaces": "error", 31 | "no-unexpected-multiline": ["off"], 32 | "object-curly-spacing": ["error", "always"], 33 | "object-property-newline": "error", 34 | "one-var": ["error", "never"], 35 | "quotes": ["error", "double"], 36 | "semi": ["error", "always"], 37 | "space-before-blocks": ["error", "always"], 38 | "space-in-parens": ["error", "always"], 39 | "spaced-comment": ["error", "always", { 40 | "block": { "balanced": true }, 41 | "exceptions": [] 42 | }], 43 | "@typescript-eslint/no-empty-interface": ["error", { "allowSingleExtends": true }], 44 | "@typescript-eslint/no-explicit-any": ["error"], 45 | "@typescript-eslint/no-floating-promises": ["error"], 46 | "@typescript-eslint/no-non-null-assertion": ["error"], 47 | "@typescript-eslint/no-unsafe-assignment": ["error"], 48 | "@typescript-eslint/no-unsafe-call": ["error"], 49 | "@typescript-eslint/no-unsafe-member-access": ["error"], 50 | "@typescript-eslint/no-unsafe-return": ["error"], 51 | "@typescript-eslint/no-unused-vars": ["error"], 52 | "@typescript-eslint/restrict-template-expressions": ["error"] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | es/ 3 | lib/ 4 | types/ 5 | 6 | # Generic 7 | *~ 8 | *.sw[mnpcod] 9 | *.log 10 | *.lock 11 | *.tmp 12 | *.tmp.* 13 | log.txt 14 | *.sublime-project 15 | *.sublime-workspace 16 | 17 | .stencil/ 18 | .idea/ 19 | .vscode/ 20 | .sass-cache/ 21 | .versions/ 22 | node_modules/ 23 | $RECYCLE.BIN/ 24 | 25 | .DS_Store 26 | Thumbs.db 27 | UserInterfaceState.xcuserstate 28 | .env 29 | 30 | # UI components 31 | demo/ 32 | ui/loader/ 33 | ui/resources/ 34 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/.nojekyll -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 16.3.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "16.3" 4 | script: 5 | - npm run prepublishOnly 6 | - npm run build 7 | -------------------------------------------------------------------------------- /client-library/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | dist 4 | es 5 | lib 6 | types -------------------------------------------------------------------------------- /client-library/examples/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | margin: 0; 14 | padding: 0; 15 | } 16 | 17 | html 18 | { 19 | font-size: 16px; 20 | font-family: "Avenir Next", sans-serif; 21 | line-height: 1.5rem; 22 | } 23 | 24 | section 25 | { 26 | width: 100%; 27 | max-width: 640px; 28 | 29 | margin: 1.5rem auto; 30 | } 31 | 32 | h2 33 | { 34 | background-color: #000; 35 | color: #fff; 36 | 37 | font-size: 1.5rem; 38 | line-height: 3rem; 39 | 40 | text-align: center; 41 | } 42 | 43 | label, 44 | textarea 45 | { 46 | display: block; 47 | } 48 | 49 | textarea 50 | { 51 | width: 100%; 52 | padding: 0.25rem 0.5rem; 53 | 54 | font-size: 1rem; 55 | line-height: 1.5rem; 56 | } 57 | -------------------------------------------------------------------------------- /client-library/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "lib/client-library.js", 3 | "module": "es/client-library.js", 4 | "types": "types/src/Client.d.ts", 5 | "files": [ 6 | "dist", 7 | "es", 8 | "lib", 9 | "types" 10 | ], 11 | "scripts": { 12 | "build": "rollup -c", 13 | "check-types": "tsc --noEmit", 14 | "clean": "rimraf dist es lib types" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.12.3", 18 | "@rollup/plugin-babel": "^5.2.1", 19 | "@rollup/plugin-node-resolve": "^9.0.0", 20 | "rimraf": "^3.0.2", 21 | "rollup": "^2.32.0", 22 | "rollup-plugin-terser": "^7.0.2", 23 | "rollup-plugin-typescript2": "^0.28.0", 24 | "typescript": "^4.0.3" 25 | }, 26 | "private": true 27 | } 28 | -------------------------------------------------------------------------------- /client-library/rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from "@rollup/plugin-babel"; 2 | import nodeResolve from "@rollup/plugin-node-resolve"; 3 | import typescript from "rollup-plugin-typescript2"; 4 | import { terser } from "rollup-plugin-terser"; 5 | 6 | 7 | const bannerMsg = `/*! **************************************************************************** 8 | Copyright (c) Microblink. All rights reserved. 9 | 10 | THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 | KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 12 | WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 13 | MERCHANTABLITY OR NON-INFRINGEMENT. 14 | ***************************************************************************** */`; 15 | 16 | const terserConfig = { 17 | compress: 18 | { 19 | pure_getters: true, 20 | unsafe: true, 21 | unsafe_comps: true, 22 | warnings: false 23 | } 24 | } 25 | 26 | const config = { 27 | cjs: 28 | { 29 | input: "src/Client.ts", 30 | output: 31 | { 32 | file: "lib/client-library.js", 33 | format: "cjs", 34 | indent: false, 35 | banner: bannerMsg 36 | }, 37 | plugins: 38 | [ 39 | nodeResolve(), 40 | typescript( { useTsconfigDeclarationDir: true } ), 41 | babel( { babelHelpers: "bundled" } ) 42 | ] 43 | }, 44 | es: 45 | { 46 | input: "src/Client.ts", 47 | output: 48 | { 49 | file: "es/client-library.js", 50 | format: "es", 51 | indent: false, 52 | sourcemap: true, 53 | banner: bannerMsg 54 | }, 55 | plugins: 56 | [ 57 | nodeResolve(), 58 | typescript( { tsconfigOverride: { compilerOptions: { declaration: false, sourceMap: true } } } ), 59 | babel( { babelHelpers: "bundled" } ) 60 | ] 61 | }, 62 | esModule: 63 | { 64 | input: "src/Client.ts", 65 | output: 66 | { 67 | file: "es/client-library.mjs", 68 | format: "es", 69 | indent: false, 70 | banner: bannerMsg 71 | }, 72 | plugins: 73 | [ 74 | nodeResolve(), 75 | typescript( { tsconfigOverride: { compilerOptions: { declaration: false } } } ), 76 | babel( { babelHelpers: "bundled" } ), 77 | terser( terserConfig ) 78 | ] 79 | }, 80 | umdDev: 81 | { 82 | input: "src/Client.ts", 83 | output: 84 | { 85 | file: "dist/client-library.js", 86 | format: "umd", 87 | name: "Client", 88 | indent: false, 89 | sourcemap: true, 90 | banner: bannerMsg 91 | }, 92 | plugins: 93 | [ 94 | nodeResolve(), 95 | typescript( { tsconfigOverride: { compilerOptions: { declaration: false, sourceMap: true } } } ), 96 | babel( { babelHelpers: "bundled" } ) 97 | ] 98 | }, 99 | umdProd: 100 | { 101 | input: "src/Client.ts", 102 | output: 103 | { 104 | file: "dist/client-library.min.js", 105 | format: "umd", 106 | name: "Client", 107 | indent: false, 108 | banner: bannerMsg 109 | }, 110 | plugins: 111 | [ 112 | nodeResolve(), 113 | typescript( { tsconfigOverride: { compilerOptions: { declaration: false } } } ), 114 | babel( { babelHelpers: "bundled" } ), 115 | terser( terserConfig ) 116 | ] 117 | } 118 | } 119 | 120 | const tasks = [ 121 | config.cjs, 122 | config.es, 123 | config.esModule, 124 | config.umdDev, 125 | config.umdProd 126 | ] 127 | 128 | 129 | export default tasks; 130 | -------------------------------------------------------------------------------- /client-library/src/data-structures.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | export enum ApiType 6 | { 7 | Cloud = "cloud", 8 | SelfHosted = "self-hosted" 9 | } 10 | 11 | export interface Configuration 12 | { 13 | /** 14 | * API location. 15 | * 16 | * Default value for all API types is "http://localhost". 17 | * 18 | * If you're using Cloud API, check official documentation for exact 19 | * location. 20 | */ 21 | apiLocation?: string; 22 | 23 | /** 24 | * Healthcheck endpoint used in `getHealthcheck` method to check if backend 25 | * is available. 26 | * 27 | * This endpoint should return HTTP status 200 if everything is OK. 28 | * 29 | * Default value is "/v2/hc". 30 | */ 31 | healthcheckEndpoint?: string; 32 | 33 | /** 34 | * Default headers which are added to every request. This is useful for 35 | * setting global authorization headers. 36 | * 37 | * If not set, request will not contain any provisional headers. 38 | */ 39 | headers?: { [ key: string ]: string }; 40 | 41 | /** 42 | * Override default error messages for specific API type. It's not necessary 43 | * to provide all error messages, but rather only those which should be 44 | * modified. 45 | * 46 | * Default error messages are located in `src/service.cloud.ts` and 47 | * `src/service.self-hosted.ts` files. 48 | * 49 | * Keep in mind that these messages are merged with generic error messages 50 | * defined in `src/data-structures.ts` file. 51 | */ 52 | messages?: { [ key: string ]: string }; 53 | } 54 | 55 | export const GenericMessages = 56 | { 57 | "GENERIC_ERROR": "There was an error during scan action.", 58 | "UNKNOWN_ERROR": "Oops, something went wrong." 59 | } 60 | 61 | export interface ResponseError 62 | { 63 | code : string; 64 | message : string; 65 | } 66 | 67 | export interface RequestPayload 68 | {} 69 | 70 | export interface ResponseRecognition 71 | { 72 | status : boolean; 73 | response: HttpResponse; 74 | error? : ResponseError; 75 | } 76 | 77 | export interface ResponseHealthcheck 78 | { 79 | status : boolean; 80 | response? : HttpResponse; 81 | } 82 | 83 | export interface HttpResponse 84 | { 85 | data? : any; 86 | headers : { [ key: string ]: string }; 87 | httpStatus : number; 88 | } 89 | 90 | export interface ApiService 91 | { 92 | getHealthcheckResponse(): Promise< HttpResponse >; 93 | recognize( 94 | endpoint: string, 95 | payload : RequestPayload, 96 | method? : string 97 | ): Promise< HttpResponse >; 98 | } 99 | -------------------------------------------------------------------------------- /client-library/src/service.cloud.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import 6 | { 7 | ApiService, 8 | HttpResponse, 9 | RequestPayload 10 | } from "./data-structures"; 11 | 12 | import * as Util from "./util"; 13 | 14 | export const CloudMessages = 15 | { 16 | "API_ROLE_IS_NOT_FOUND": "API role is not found", 17 | "AUTHORIZATION_HEADER_IS_NOT_VALID": "Authorization header is not valid", 18 | "BAD_REQUEST": "Bad request", 19 | "FORBIDDEN_RECOGNIZER": "Forbidden recognizer", 20 | "IMAGE_IS_NOT_ABLE_TO_CONVERT_TO_RAW_PIXELS": "Image is not able to convert to raw pixels", 21 | "IMAGE_IS_NOT_VALID": "Image is not valid", 22 | "IMAGE_IS_NOT_VALID_BASE64_STRING": "Image is not valid base64 string", 23 | "IMAGE_SIZE_IS_TOO_BIG": "Image size is too big", 24 | "INSUFFICIENT_BALANCE": "Insufficient balance", 25 | "INTERNAL_SERVER_ERROR": "Internal server error", 26 | "INVALID_LICENSE_KEY": "Invalid license key", 27 | "NOT_ALLOWED_TO_EXECUTE_REQUESTED_RECOGNIZER": "Not allowed to execute requested recognizer", 28 | "SERVER_CANCELED_REQUEST": "Server canceled request", 29 | "SERVER_TOO_BUSY": "Server too busy" 30 | } 31 | 32 | const DefaultHeaders = 33 | { 34 | "Accept": "application/json", 35 | "Content-Type": "application/json" 36 | } 37 | 38 | export class ServiceCloud implements ApiService 39 | { 40 | private apiLocation : string; 41 | private healthcheckEndpoint : string; 42 | private headers : { [ key: string ]: string }; 43 | 44 | constructor( 45 | apiLocation : string, 46 | healthcheckEndpoint : string, 47 | headers : { [ key: string ]: string } 48 | ) 49 | { 50 | this.apiLocation = apiLocation; 51 | this.healthcheckEndpoint = healthcheckEndpoint; 52 | this.headers = Object.assign( DefaultHeaders, headers ); 53 | 54 | // HTTP header must contain header field and value 55 | // @see https://tools.ietf.org/html/rfc7230#section-3.2 56 | for ( const key in this.headers ) 57 | { 58 | if ( !key || !this.headers[ key ] ) 59 | { 60 | delete this.headers[ key ]; 61 | } 62 | } 63 | } 64 | 65 | public getHealthcheckResponse(): Promise< HttpResponse > 66 | { 67 | const requestUrl = Util.getSafeUrl( this.apiLocation, this.healthcheckEndpoint ); 68 | return Util.httpClient( "GET", requestUrl, this.headers ); 69 | } 70 | 71 | public recognize( endpoint: string, payload: RequestPayload, method = "POST" ): Promise< HttpResponse > 72 | { 73 | const requestUrl = Util.getSafeUrl( this.apiLocation, endpoint ); 74 | return Util.httpClient( method, requestUrl, this.headers, payload ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /client-library/src/service.self-hosted.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import 6 | { 7 | ApiService, 8 | HttpResponse, 9 | RequestPayload 10 | } from "./data-structures"; 11 | 12 | import * as Util from "./util"; 13 | 14 | export const SelfHostedMessages = 15 | { 16 | "API_ROLE_IS_NOT_FOUND": "API role is not found", 17 | "AUTHORIZATION_HEADER_IS_NOT_VALID": "Authorization header is not valid", 18 | "BAD_REQUEST": "Bad request", 19 | "FORBIDDEN_RECOGNIZER": "Forbidden recognizer", 20 | "IMAGE_IS_NOT_ABLE_TO_CONVERT_TO_RAW_PIXELS": "Image is not able to convert to raw pixels", 21 | "IMAGE_IS_NOT_VALID": "Image is not valid", 22 | "IMAGE_IS_NOT_VALID_BASE64_STRING": "Image is not valid base64 string", 23 | "IMAGE_SIZE_IS_TOO_BIG": "Image size is too big", 24 | "INTERNAL_SERVER_ERROR": "Internal server error", 25 | "INVALID_LICENSE_KEY": "Invalid license key", 26 | "NOT_ALLOWED_TO_EXECUTE_REQUESTED_RECOGNIZER": "Not allowed to execute requested recognizer", 27 | "SERVER_CANCELED_REQUEST": "Server canceled request", 28 | "SERVER_TOO_BUSY": "Server too busy" 29 | } 30 | 31 | const DefaultHeaders = 32 | { 33 | "Accept": "application/json", 34 | "Content-Type": "application/json" 35 | } 36 | 37 | export class ServiceSelfHosted implements ApiService 38 | { 39 | private apiLocation : string; 40 | private healthcheckEndpoint : string; 41 | private headers : { [ key: string ]: string }; 42 | 43 | constructor( 44 | apiLocation : string, 45 | healthcheckEndpoint : string, 46 | headers : { [ key: string ]: string } 47 | ) 48 | { 49 | this.apiLocation = apiLocation; 50 | this.healthcheckEndpoint = healthcheckEndpoint; 51 | this.headers = Object.assign( DefaultHeaders, headers ); 52 | 53 | // HTTP header must contain header field and value 54 | // @see https://tools.ietf.org/html/rfc7230#section-3.2 55 | for ( const key in this.headers ) 56 | { 57 | if ( !key || !this.headers[ key ] ) 58 | { 59 | delete this.headers[ key ]; 60 | } 61 | } 62 | } 63 | 64 | public getHealthcheckResponse(): Promise< HttpResponse > 65 | { 66 | const requestUrl = Util.getSafeUrl( this.apiLocation, this.healthcheckEndpoint ); 67 | return Util.httpClient( "GET", requestUrl, this.headers ); 68 | } 69 | 70 | public recognize( endpoint: string, payload: RequestPayload, method = "POST" ): Promise< HttpResponse > 71 | { 72 | const requestUrl = Util.getSafeUrl( this.apiLocation, endpoint ); 73 | return Util.httpClient( method, requestUrl, this.headers, payload ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /client-library/src/util.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { HttpResponse } from "./data-structures"; 6 | 7 | export function getSafeUrl( base: string, ...args: string[] ): string 8 | { 9 | const impureUrl = [ ...args ].join( "/" ); 10 | const pureUrl = safeReplaceAll( impureUrl, "//", "/" ); 11 | 12 | const safeBase = base.endsWith( "/" ) ? base.slice( 0, -1 ) : base; 13 | const endpoint = pureUrl.startsWith( "/" ) ? pureUrl : "/" + pureUrl; 14 | 15 | return safeBase + endpoint; 16 | } 17 | 18 | export function safeReplaceAll( input: string, substr: string, newSubstr: string ): string 19 | { 20 | input = input || ""; 21 | substr = substr || ""; 22 | newSubstr = newSubstr || ""; 23 | 24 | while ( input.indexOf( substr ) > -1 ) 25 | { 26 | input = input.replace( substr, newSubstr ); 27 | } 28 | 29 | return input; 30 | } 31 | 32 | interface FetchConfiguration 33 | { 34 | method : string, 35 | headers : { [ key: string ]: string }, 36 | body? : any 37 | } 38 | 39 | export function httpClient( 40 | method : string, 41 | url : string, 42 | headers : { [ key: string ]: string }, 43 | payload?: any 44 | ): Promise< HttpResponse > 45 | { 46 | return new Promise( ( resolve, reject ) => 47 | { 48 | const fetchConfiguration: FetchConfiguration = 49 | { 50 | method, 51 | headers 52 | } 53 | 54 | if ( payload ) 55 | { 56 | fetchConfiguration[ "body" ] = JSON.stringify( payload ); 57 | } 58 | 59 | window.fetch( url, fetchConfiguration ) 60 | .then( ( response: Response ) => 61 | { 62 | const headerEntries = response.headers.entries(); 63 | const headers: { [ key: string ]: string } = {}; 64 | 65 | for ( const entry of headerEntries ) 66 | { 67 | headers[ entry[ 0 ] ] = entry[ 1 ]; 68 | } 69 | 70 | const httpResponse: HttpResponse = { 71 | httpStatus: response.status, 72 | headers 73 | } 74 | 75 | response.text() 76 | .then( ( data ) => 77 | { 78 | try 79 | { 80 | const jsonData = JSON.parse( data ); 81 | httpResponse[ "data" ] = jsonData; 82 | } 83 | catch 84 | { 85 | httpResponse[ "data" ] = data; 86 | } 87 | 88 | resolve( httpResponse ); 89 | } ) 90 | .catch( ( error ) => 91 | { 92 | httpResponse[ "data" ] = error; 93 | reject( httpResponse ); 94 | } ); 95 | } ) 96 | .catch( error => 97 | { 98 | reject( { 99 | httpStatus: -1, 100 | headers: {}, 101 | data: error 102 | } ); 103 | }); 104 | } ); 105 | } 106 | 107 | export function imageDataToBase64( imageData: ImageData ): string 108 | { 109 | const canvas = document.createElement( "canvas" ); 110 | 111 | canvas.width = imageData.width; 112 | canvas.height = imageData.height; 113 | 114 | const context = canvas.getContext( "2d" ); 115 | context?.putImageData( imageData, 0, 0 ); 116 | 117 | return canvas.toDataURL(); 118 | } 119 | -------------------------------------------------------------------------------- /client-library/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "declaration": true, 7 | "declarationDir": "./types", 8 | "forceConsistentCasingInFileNames": true, 9 | "noImplicitReturns": true, 10 | "strict": true, 11 | "noUnusedLocals": true, 12 | "types": [] 13 | }, 14 | "include": ["./src/**/*"] 15 | } 16 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Provided examples should help you with integration of this SDK with your app. 4 | 5 | 1. Scan identity document from camera - `blinkid-camera`. 6 | 2. Scan identity document from file - `blinkid-file`. 7 | 3. Scan both sides of an identity document from camera - `combined`. 8 | 9 | Each example has JavaScript and TypeScript version. 10 | 11 | Deployment: 12 | 13 | * When accessing examples via web browser always use `localhost` instead of `127.0.0.1`. 14 | * Examples should be served via HTTPS. 15 | * We recommend usage of NPM package [https-localhost](https://www.npmjs.com/package/https-localhost) for simple local deployment. 16 | 17 | ## TypeScript Examples 18 | 19 | To run TypeScript examples: 20 | 21 | 1. Install example dependencies and build an application: 22 | ``` 23 | # Make sure you're in the 'examples//typescript' folder 24 | 25 | # Install dependencies 26 | npm install 27 | 28 | # Build an application in folder 'dist/' 29 | npm run build 30 | ``` 31 | 2. Runtime resources are copied to `dist/` folder during build action, check `rollup.config.js` or `webpack.config.js` files. 32 | 3. Serve `dist/` folder, e.g. `serve dist/`. 33 | 34 | ## JavaScript Examples 35 | 36 | To run JavaScript examples: 37 | 38 | 1. Serve `javascript/` folder, e.g. `serve javascript/`. 39 | * Make sure to have internet connection since runtime resources are loaded from the CDN. 40 | * Alternatively, change resource paths and provide JS bundles. 41 | -------------------------------------------------------------------------------- /examples/blinkid-camera/javascript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture Scan From Camera 5 | 6 | 7 | 8 | 9 |
10 |

Loading...

11 | 12 |
13 | 14 | 17 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/blinkid-camera/javascript/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | html 18 | { 19 | margin: 0; 20 | padding: 0; 21 | font-size: 16px; 22 | line-height: 24px; 23 | font-family: sans-serif; 24 | } 25 | 26 | body 27 | { 28 | display: flex; 29 | min-height: 100%; 30 | margin: 0; 31 | padding: 1.5rem; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | #screen-initial, 37 | #screen-scanning 38 | { 39 | display: block; 40 | width: 100%; 41 | height: 100%; 42 | } 43 | 44 | /* Rules for better readability */ 45 | img 46 | { 47 | display: block; 48 | width: 100%; 49 | max-width: 320px; 50 | height: auto; 51 | } 52 | 53 | video 54 | { 55 | width: 100%; 56 | height: 100%; 57 | } 58 | 59 | textarea 60 | { 61 | display: block; 62 | } 63 | 64 | /* Camera feedback */ 65 | #screen-scanning 66 | { 67 | position: relative; 68 | } 69 | 70 | #camera-feedback 71 | { 72 | position: absolute; 73 | top: 0; 74 | left: 0; 75 | right: 0; 76 | bottom: 0; 77 | 78 | width: 100%; 79 | height: 100%; 80 | } 81 | 82 | #camera-guides 83 | { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | right: 0; 88 | text-align: center; 89 | font-weight: bold; 90 | } 91 | 92 | /* Auxiliary classes */ 93 | .hidden 94 | { 95 | display: none !important; 96 | } 97 | -------------------------------------------------------------------------------- /examples/blinkid-camera/typescript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /examples/blinkid-camera/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-integration-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "rollup -c" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "private": true, 13 | "devDependencies": { 14 | "@rollup/plugin-node-resolve": "^8.0.1", 15 | "rollup": "^2.15.0", 16 | "rollup-plugin-copy": "^3.3.0", 17 | "rollup-plugin-terser": "^6.1.0", 18 | "rollup-plugin-typescript2": "^0.27.1", 19 | "typescript": "^3.9.5" 20 | }, 21 | "dependencies": { 22 | "@microblink/blinkid-imagecapture-in-browser-sdk": "~6.0.0" 23 | } 24 | } -------------------------------------------------------------------------------- /examples/blinkid-camera/typescript/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture Scan From Camera 5 | 6 | 7 | 8 | 9 |
10 |

Loading...

11 | 12 |
13 | 14 | 17 | 18 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/blinkid-camera/typescript/public/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | html 18 | { 19 | margin: 0; 20 | padding: 0; 21 | font-size: 16px; 22 | line-height: 24px; 23 | font-family: sans-serif; 24 | } 25 | 26 | body 27 | { 28 | display: flex; 29 | min-height: 100%; 30 | margin: 0; 31 | padding: 1.5rem; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | #screen-initial, 37 | #screen-scanning 38 | { 39 | display: block; 40 | width: 100%; 41 | height: 100%; 42 | } 43 | 44 | /* Rules for better readability */ 45 | img 46 | { 47 | display: block; 48 | width: 100%; 49 | max-width: 320px; 50 | height: auto; 51 | } 52 | 53 | video 54 | { 55 | width: 100%; 56 | height: 100%; 57 | } 58 | 59 | textarea 60 | { 61 | display: block; 62 | } 63 | 64 | /* Camera feedback */ 65 | #screen-scanning 66 | { 67 | position: relative; 68 | } 69 | 70 | #camera-feedback 71 | { 72 | position: absolute; 73 | top: 0; 74 | left: 0; 75 | right: 0; 76 | bottom: 0; 77 | 78 | width: 100%; 79 | height: 100%; 80 | } 81 | 82 | #camera-guides 83 | { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | right: 0; 88 | text-align: center; 89 | font-weight: bold; 90 | } 91 | 92 | /* Auxiliary classes */ 93 | .hidden 94 | { 95 | display: none !important; 96 | } 97 | -------------------------------------------------------------------------------- /examples/blinkid-camera/typescript/rollup.config.js: -------------------------------------------------------------------------------- 1 | import copy from "rollup-plugin-copy"; 2 | import nodeResolve from "@rollup/plugin-node-resolve"; 3 | import typescript from "rollup-plugin-typescript2"; 4 | import { terser } from "rollup-plugin-terser"; 5 | 6 | export default [ 7 | { 8 | input: "src/app.ts", 9 | output: 10 | { 11 | file: "dist/app.js", 12 | format: "iife" 13 | }, 14 | plugins: [ 15 | nodeResolve(), 16 | typescript(), 17 | terser({ 18 | compress: 19 | { 20 | pure_getters: true, 21 | unsafe: true, 22 | unsafe_comps: true, 23 | warnings: false 24 | } 25 | }), 26 | copy({ 27 | targets: [ 28 | { src: "public/*", dest: "dist" }, 29 | { src: "node_modules/@microblink/blinkid-imagecapture-in-browser-sdk/resources/*", dest: "dist" } 30 | ] 31 | }) 32 | ] 33 | } 34 | ]; 35 | -------------------------------------------------------------------------------- /examples/blinkid-camera/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "forceConsistentCasingInFileNames": true, 7 | "noImplicitReturns": true, 8 | "strict": true, 9 | "noUnusedLocals": true 10 | }, 11 | "include": ["./src/*"] 12 | } 13 | -------------------------------------------------------------------------------- /examples/blinkid-file/javascript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture Upload File 5 | 6 | 7 | 8 | 9 |
10 |

Loading...

11 | 12 |
13 | 14 | 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/blinkid-file/javascript/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | html 18 | { 19 | margin: 0; 20 | padding: 0; 21 | font-size: 16px; 22 | line-height: 24px; 23 | font-family: sans-serif; 24 | } 25 | 26 | body 27 | { 28 | display: flex; 29 | min-height: 100%; 30 | margin: 0; 31 | padding: 1.5rem; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | #screen-initial, 37 | #screen-scanning 38 | { 39 | display: block; 40 | width: 100%; 41 | height: 100%; 42 | } 43 | 44 | /* Rules for better readability */ 45 | img 46 | { 47 | display: block; 48 | width: 100%; 49 | max-width: 320px; 50 | height: auto; 51 | } 52 | 53 | video 54 | { 55 | width: 100%; 56 | height: 100%; 57 | } 58 | 59 | textarea 60 | { 61 | display: block; 62 | } 63 | 64 | /* Camera feedback */ 65 | #screen-scanning 66 | { 67 | position: relative; 68 | } 69 | 70 | #camera-feedback 71 | { 72 | position: absolute; 73 | top: 0; 74 | left: 0; 75 | right: 0; 76 | bottom: 0; 77 | 78 | width: 100%; 79 | height: 100%; 80 | } 81 | 82 | #camera-guides 83 | { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | right: 0; 88 | text-align: center; 89 | font-weight: bold; 90 | } 91 | 92 | /* Auxiliary classes */ 93 | .hidden 94 | { 95 | display: none !important; 96 | } 97 | -------------------------------------------------------------------------------- /examples/blinkid-file/typescript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /examples/blinkid-file/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-integration-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "rollup -c" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "private": true, 13 | "devDependencies": { 14 | "@rollup/plugin-node-resolve": "^8.0.1", 15 | "rollup": "^2.15.0", 16 | "rollup-plugin-copy": "^3.3.0", 17 | "rollup-plugin-terser": "^6.1.0", 18 | "rollup-plugin-typescript2": "^0.27.1", 19 | "typescript": "^3.9.5" 20 | }, 21 | "dependencies": { 22 | "@microblink/blinkid-imagecapture-in-browser-sdk": "~6.0.0" 23 | } 24 | } -------------------------------------------------------------------------------- /examples/blinkid-file/typescript/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture Upload File 5 | 6 | 7 | 8 | 9 |
10 |

Loading...

11 | 12 |
13 | 14 | 18 | 19 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/blinkid-file/typescript/public/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | html 18 | { 19 | margin: 0; 20 | padding: 0; 21 | font-size: 16px; 22 | line-height: 24px; 23 | font-family: sans-serif; 24 | } 25 | 26 | body 27 | { 28 | display: flex; 29 | min-height: 100%; 30 | margin: 0; 31 | padding: 1.5rem; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | #screen-initial, 37 | #screen-scanning 38 | { 39 | display: block; 40 | width: 100%; 41 | height: 100%; 42 | } 43 | 44 | /* Rules for better readability */ 45 | img 46 | { 47 | display: block; 48 | width: 100%; 49 | max-width: 320px; 50 | height: auto; 51 | } 52 | 53 | video 54 | { 55 | width: 100%; 56 | height: 100%; 57 | } 58 | 59 | textarea 60 | { 61 | display: block; 62 | } 63 | 64 | /* Camera feedback */ 65 | #screen-scanning 66 | { 67 | position: relative; 68 | } 69 | 70 | #camera-feedback 71 | { 72 | position: absolute; 73 | top: 0; 74 | left: 0; 75 | right: 0; 76 | bottom: 0; 77 | 78 | width: 100%; 79 | height: 100%; 80 | } 81 | 82 | #camera-guides 83 | { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | right: 0; 88 | text-align: center; 89 | font-weight: bold; 90 | } 91 | 92 | /* Auxiliary classes */ 93 | .hidden 94 | { 95 | display: none !important; 96 | } 97 | -------------------------------------------------------------------------------- /examples/blinkid-file/typescript/rollup.config.js: -------------------------------------------------------------------------------- 1 | import copy from "rollup-plugin-copy"; 2 | import nodeResolve from "@rollup/plugin-node-resolve"; 3 | import typescript from "rollup-plugin-typescript2"; 4 | import { terser } from "rollup-plugin-terser"; 5 | 6 | export default [ 7 | { 8 | input: "src/app.ts", 9 | output: 10 | { 11 | file: "dist/app.js", 12 | format: "iife" 13 | }, 14 | plugins: [ 15 | nodeResolve(), 16 | typescript(), 17 | terser({ 18 | compress: 19 | { 20 | pure_getters: true, 21 | unsafe: true, 22 | unsafe_comps: true, 23 | warnings: false 24 | } 25 | }), 26 | copy({ 27 | targets: [ 28 | { src: "public/*", dest: "dist" }, 29 | { src: "node_modules/@microblink/blinkid-imagecapture-in-browser-sdk/resources/*", dest: "dist" } 30 | ] 31 | }) 32 | ] 33 | } 34 | ]; 35 | -------------------------------------------------------------------------------- /examples/blinkid-file/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "forceConsistentCasingInFileNames": true, 7 | "noImplicitReturns": true, 8 | "strict": true, 9 | "noUnusedLocals": true 10 | }, 11 | "include": ["./src/*"] 12 | } 13 | -------------------------------------------------------------------------------- /examples/combined-file/javascript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture Combined File 5 | 6 | 7 | 8 | 9 |
10 |

Loading...

11 | 12 |
13 | 14 | 25 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /examples/combined-file/javascript/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | html 18 | { 19 | margin: 0; 20 | padding: 0; 21 | font-size: 16px; 22 | line-height: 24px; 23 | font-family: sans-serif; 24 | } 25 | 26 | body 27 | { 28 | display: flex; 29 | min-height: 100%; 30 | margin: 0; 31 | padding: 1.5rem; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | #screen-initial, 37 | #screen-scanning 38 | { 39 | display: block; 40 | width: 100%; 41 | height: 100%; 42 | } 43 | 44 | /* Rules for better readability */ 45 | img 46 | { 47 | display: block; 48 | width: 100%; 49 | max-width: 320px; 50 | height: auto; 51 | } 52 | 53 | video 54 | { 55 | width: 100%; 56 | height: 100%; 57 | } 58 | 59 | textarea 60 | { 61 | display: block; 62 | } 63 | 64 | /* Camera feedback */ 65 | #screen-scanning 66 | { 67 | position: relative; 68 | } 69 | 70 | #camera-feedback 71 | { 72 | position: absolute; 73 | top: 0; 74 | left: 0; 75 | right: 0; 76 | bottom: 0; 77 | 78 | width: 100%; 79 | height: 100%; 80 | } 81 | 82 | #camera-guides 83 | { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | right: 0; 88 | text-align: center; 89 | font-weight: bold; 90 | } 91 | 92 | /* Auxiliary classes */ 93 | .hidden 94 | { 95 | display: none !important; 96 | } 97 | -------------------------------------------------------------------------------- /examples/combined-file/typescript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /examples/combined-file/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-integration-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "rollup -c" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "private": true, 13 | "devDependencies": { 14 | "@rollup/plugin-node-resolve": "^8.0.1", 15 | "rollup": "^2.15.0", 16 | "rollup-plugin-copy": "^3.3.0", 17 | "rollup-plugin-terser": "^6.1.0", 18 | "rollup-plugin-typescript2": "^0.27.1", 19 | "typescript": "^3.9.5" 20 | }, 21 | "dependencies": { 22 | "@microblink/blinkid-imagecapture-in-browser-sdk": "~6.0.0" 23 | } 24 | } -------------------------------------------------------------------------------- /examples/combined-file/typescript/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture Combined File 5 | 6 | 7 | 8 | 9 |
10 |

Loading...

11 | 12 |
13 | 14 | 25 | 26 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/combined-file/typescript/public/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | html 18 | { 19 | margin: 0; 20 | padding: 0; 21 | font-size: 16px; 22 | line-height: 24px; 23 | font-family: sans-serif; 24 | } 25 | 26 | body 27 | { 28 | display: flex; 29 | min-height: 100%; 30 | margin: 0; 31 | padding: 1.5rem; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | #screen-initial, 37 | #screen-scanning 38 | { 39 | display: block; 40 | width: 100%; 41 | height: 100%; 42 | } 43 | 44 | /* Rules for better readability */ 45 | img 46 | { 47 | display: block; 48 | width: 100%; 49 | max-width: 320px; 50 | height: auto; 51 | } 52 | 53 | video 54 | { 55 | width: 100%; 56 | height: 100%; 57 | } 58 | 59 | textarea 60 | { 61 | display: block; 62 | } 63 | 64 | /* Camera feedback */ 65 | #screen-scanning 66 | { 67 | position: relative; 68 | } 69 | 70 | #camera-feedback 71 | { 72 | position: absolute; 73 | top: 0; 74 | left: 0; 75 | right: 0; 76 | bottom: 0; 77 | 78 | width: 100%; 79 | height: 100%; 80 | } 81 | 82 | #camera-guides 83 | { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | right: 0; 88 | text-align: center; 89 | font-weight: bold; 90 | } 91 | 92 | /* Auxiliary classes */ 93 | .hidden 94 | { 95 | display: none !important; 96 | } 97 | -------------------------------------------------------------------------------- /examples/combined-file/typescript/rollup.config.js: -------------------------------------------------------------------------------- 1 | import copy from "rollup-plugin-copy"; 2 | import nodeResolve from "@rollup/plugin-node-resolve"; 3 | import typescript from "rollup-plugin-typescript2"; 4 | import { terser } from "rollup-plugin-terser"; 5 | 6 | export default [ 7 | { 8 | input: "src/app.ts", 9 | output: 10 | { 11 | file: "dist/app.js", 12 | format: "iife" 13 | }, 14 | plugins: [ 15 | nodeResolve(), 16 | typescript(), 17 | terser({ 18 | compress: 19 | { 20 | pure_getters: true, 21 | unsafe: true, 22 | unsafe_comps: true, 23 | warnings: false 24 | } 25 | }), 26 | copy({ 27 | targets: [ 28 | { src: "public/*", dest: "dist" }, 29 | { src: "node_modules/@microblink/blinkid-imagecapture-in-browser-sdk/resources/*", dest: "dist" } 30 | ] 31 | }) 32 | ] 33 | } 34 | ]; 35 | -------------------------------------------------------------------------------- /examples/combined-file/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "forceConsistentCasingInFileNames": true, 7 | "noImplicitReturns": true, 8 | "strict": true, 9 | "noUnusedLocals": true 10 | }, 11 | "include": ["./src/*"] 12 | } 13 | -------------------------------------------------------------------------------- /examples/combined/javascript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture Combined Experience 5 | 6 | 7 | 8 | 9 |
10 |

Loading...

11 | 12 |
13 | 14 | 17 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/combined/javascript/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | html 18 | { 19 | margin: 0; 20 | padding: 0; 21 | font-size: 16px; 22 | line-height: 24px; 23 | font-family: sans-serif; 24 | } 25 | 26 | body 27 | { 28 | display: flex; 29 | min-height: 100%; 30 | margin: 0; 31 | padding: 1.5rem; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | #loading 37 | { 38 | display: block; 39 | } 40 | 41 | #view-landing, 42 | #view-scan-from-camera, 43 | #view-scan-from-file, 44 | #view-results 45 | { 46 | display: block; 47 | width: 100%; 48 | height: 100%; 49 | } 50 | 51 | /* Rules for better readability */ 52 | img 53 | { 54 | display: block; 55 | width: 100%; 56 | max-width: 320px; 57 | height: auto; 58 | } 59 | 60 | video 61 | { 62 | width: 100%; 63 | height: 100%; 64 | } 65 | 66 | textarea 67 | { 68 | display: block; 69 | } 70 | 71 | /* Camera feedback */ 72 | #screen-scanning 73 | { 74 | position: relative; 75 | } 76 | 77 | #view-scan-from-camera 78 | { 79 | position: relative; 80 | } 81 | 82 | #camera-feedback 83 | { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | right: 0; 88 | bottom: 0; 89 | 90 | width: 100%; 91 | height: 100%; 92 | } 93 | 94 | #camera-guides 95 | { 96 | position: absolute; 97 | top: 0; 98 | left: 0; 99 | right: 0; 100 | text-align: center; 101 | font-weight: bold; 102 | } 103 | 104 | /* Auxiliary classes */ 105 | .hidden 106 | { 107 | display: none !important; 108 | } 109 | -------------------------------------------------------------------------------- /examples/combined/typescript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /examples/combined/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-integration-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "rollup -c" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "private": true, 13 | "devDependencies": { 14 | "@rollup/plugin-node-resolve": "^8.0.1", 15 | "rollup": "^2.15.0", 16 | "rollup-plugin-copy": "^3.3.0", 17 | "rollup-plugin-terser": "^6.1.0", 18 | "rollup-plugin-typescript2": "^0.27.1", 19 | "typescript": "^3.9.5" 20 | }, 21 | "dependencies": { 22 | "@microblink/blinkid-imagecapture-in-browser-sdk": "~6.0.0" 23 | } 24 | } -------------------------------------------------------------------------------- /examples/combined/typescript/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture Combined Experience 5 | 6 | 7 | 8 | 9 |
10 |

Loading...

11 | 12 |
13 | 14 | 17 | 18 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/combined/typescript/public/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body 12 | { 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | html 18 | { 19 | margin: 0; 20 | padding: 0; 21 | font-size: 16px; 22 | line-height: 24px; 23 | font-family: sans-serif; 24 | } 25 | 26 | body 27 | { 28 | display: flex; 29 | min-height: 100%; 30 | margin: 0; 31 | padding: 1.5rem; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | #loading 37 | { 38 | display: block; 39 | } 40 | 41 | #view-landing, 42 | #view-scan-from-camera, 43 | #view-scan-from-file, 44 | #view-results 45 | { 46 | display: block; 47 | width: 100%; 48 | height: 100%; 49 | } 50 | 51 | /* Rules for better readability */ 52 | img 53 | { 54 | display: block; 55 | width: 100%; 56 | max-width: 320px; 57 | height: auto; 58 | } 59 | 60 | video 61 | { 62 | width: 100%; 63 | height: 100%; 64 | } 65 | 66 | textarea 67 | { 68 | display: block; 69 | } 70 | 71 | /* Camera feedback */ 72 | #screen-scanning 73 | { 74 | position: relative; 75 | } 76 | 77 | #view-scan-from-camera 78 | { 79 | position: relative; 80 | } 81 | 82 | #camera-feedback 83 | { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | right: 0; 88 | bottom: 0; 89 | 90 | width: 100%; 91 | height: 100%; 92 | } 93 | 94 | #camera-guides 95 | { 96 | position: absolute; 97 | top: 0; 98 | left: 0; 99 | right: 0; 100 | text-align: center; 101 | font-weight: bold; 102 | } 103 | 104 | /* Auxiliary classes */ 105 | .hidden 106 | { 107 | display: none !important; 108 | } 109 | -------------------------------------------------------------------------------- /examples/combined/typescript/rollup.config.js: -------------------------------------------------------------------------------- 1 | import copy from "rollup-plugin-copy"; 2 | import nodeResolve from "@rollup/plugin-node-resolve"; 3 | import typescript from "rollup-plugin-typescript2"; 4 | import { terser } from "rollup-plugin-terser"; 5 | 6 | export default [ 7 | { 8 | input: "src/app.ts", 9 | output: 10 | { 11 | file: "dist/app.js", 12 | format: "iife" 13 | }, 14 | plugins: [ 15 | nodeResolve(), 16 | typescript(), 17 | terser({ 18 | compress: 19 | { 20 | pure_getters: true, 21 | unsafe: true, 22 | unsafe_comps: true, 23 | warnings: false 24 | } 25 | }), 26 | copy({ 27 | targets: [ 28 | { src: "public/*", dest: "dist" }, 29 | { src: "node_modules/@microblink/blinkid-imagecapture-in-browser-sdk/resources/*", dest: "dist" } 30 | ] 31 | }) 32 | ] 33 | } 34 | ]; 35 | -------------------------------------------------------------------------------- /examples/combined/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "forceConsistentCasingInFileNames": true, 7 | "noImplicitReturns": true, 8 | "strict": true, 9 | "noUnusedLocals": true 10 | }, 11 | "include": ["./src/*"] 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@microblink/blinkid-imagecapture-in-browser-sdk", 3 | "version": "6.0.0", 4 | "description": "A smart image capturing library for WebAssembly-enabled browsers.", 5 | "homepage": "https://github.com/BlinkID/blinkid-imagecapture-in-browser", 6 | "repository": "github:BlinkID/blinkid-imagecapture-in-browser", 7 | "bugs": "https://github.com/BlinkID/blinkid-imagecapture-in-browser/issues", 8 | "keywords": [ 9 | "webassembly", 10 | "browser" 11 | ], 12 | "engines": { 13 | "node": ">=16.3.0" 14 | }, 15 | "main": "lib/blinkid-imagecapture-sdk.js", 16 | "module": "es/blinkid-imagecapture-sdk.js", 17 | "types": "types/index.d.ts", 18 | "files": [ 19 | "ui/dist", 20 | "ui/loader", 21 | "ui/src", 22 | "client-library/dist", 23 | "client-library/es", 24 | "client-library/lib", 25 | "client-library/types", 26 | "dist", 27 | "es", 28 | "lib", 29 | "resources", 30 | "resources-lightweight", 31 | "src", 32 | "types" 33 | ], 34 | "scripts": { 35 | "build": "npm run build:api && npm run build:ui && npm run build:client", 36 | "build:api": "rollup -c", 37 | "build:client": "cd client-library && npm install && npm run build", 38 | "build:ui": "cd ui && npm install && npm run build", 39 | "check-types": "tsc --noEmit", 40 | "clean": "npm run clean:api && npm run clean:ui && npm run clean:client", 41 | "clean:api": "rimraf dist es lib types", 42 | "clean:client": "cd client-library && npm run clean", 43 | "clean:ui": "cd ui && npm run clean", 44 | "lint": "eslint --ext ts -c .eslintrc.json src", 45 | "pretest": "npm run build", 46 | "prepublishOnly": "npm run clean && npm run check-types && npm run lint && npm test", 47 | "test": "echo \"Not implemented!\"" 48 | }, 49 | "devDependencies": { 50 | "@babel/cli": "7.15.4", 51 | "@babel/core": "7.15.5", 52 | "@babel/preset-env": "7.15.6", 53 | "@rollup/plugin-babel": "5.2.1", 54 | "@rollup/plugin-node-resolve": "11.1.0", 55 | "@typescript-eslint/eslint-plugin": "4.31.1", 56 | "@typescript-eslint/parser": "4.31.1", 57 | "eslint": "7.32.0", 58 | "rimraf": "^3.0.2", 59 | "rollup": "2.38.1", 60 | "rollup-plugin-terser": "7.0.2", 61 | "rollup-plugin-typescript2": "0.27.1", 62 | "tslib": "2.0.0", 63 | "typescript": "4.0.3", 64 | "wasm-feature-detect": "1.2.11" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /resources-lightweight/advanced-threads/BlinkIDImageCaptureWasmSDK.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources-lightweight/advanced-threads/BlinkIDImageCaptureWasmSDK.data -------------------------------------------------------------------------------- /resources-lightweight/advanced-threads/BlinkIDImageCaptureWasmSDK.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources-lightweight/advanced-threads/BlinkIDImageCaptureWasmSDK.wasm -------------------------------------------------------------------------------- /resources-lightweight/advanced-threads/BlinkIDImageCaptureWasmSDK.worker.js: -------------------------------------------------------------------------------- 1 | "use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=((info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports});self.onmessage=(e=>{try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}BlinkIDImageCaptureWasmSDK(Module).then(function(instance){Module=instance})}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0,/*canBlock=*/1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["__emscripten_thread_exit"](result)}}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processProxyingQueue"){if(Module["_pthread_self"]()){Module["_emscripten_proxy_execute_queue"](e.data.queue)}Atomics.sub(HEAP32,e.data.queue>>2,1)}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}); 2 | -------------------------------------------------------------------------------- /resources-lightweight/advanced/BlinkIDImageCaptureWasmSDK.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources-lightweight/advanced/BlinkIDImageCaptureWasmSDK.data -------------------------------------------------------------------------------- /resources-lightweight/advanced/BlinkIDImageCaptureWasmSDK.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources-lightweight/advanced/BlinkIDImageCaptureWasmSDK.wasm -------------------------------------------------------------------------------- /resources-lightweight/basic/BlinkIDImageCaptureWasmSDK.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources-lightweight/basic/BlinkIDImageCaptureWasmSDK.data -------------------------------------------------------------------------------- /resources-lightweight/basic/BlinkIDImageCaptureWasmSDK.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources-lightweight/basic/BlinkIDImageCaptureWasmSDK.wasm -------------------------------------------------------------------------------- /resources/advanced-threads/BlinkIDImageCaptureWasmSDK.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources/advanced-threads/BlinkIDImageCaptureWasmSDK.data -------------------------------------------------------------------------------- /resources/advanced-threads/BlinkIDImageCaptureWasmSDK.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources/advanced-threads/BlinkIDImageCaptureWasmSDK.wasm -------------------------------------------------------------------------------- /resources/advanced-threads/BlinkIDImageCaptureWasmSDK.worker.js: -------------------------------------------------------------------------------- 1 | "use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=((info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports});self.onmessage=(e=>{try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}BlinkIDImageCaptureWasmSDK(Module).then(function(instance){Module=instance})}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0,/*canBlock=*/1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["__emscripten_thread_exit"](result)}}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processProxyingQueue"){if(Module["_pthread_self"]()){Module["_emscripten_proxy_execute_queue"](e.data.queue)}Atomics.sub(HEAP32,e.data.queue>>2,1)}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}); 2 | -------------------------------------------------------------------------------- /resources/advanced/BlinkIDImageCaptureWasmSDK.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources/advanced/BlinkIDImageCaptureWasmSDK.data -------------------------------------------------------------------------------- /resources/advanced/BlinkIDImageCaptureWasmSDK.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources/advanced/BlinkIDImageCaptureWasmSDK.wasm -------------------------------------------------------------------------------- /resources/basic/BlinkIDImageCaptureWasmSDK.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources/basic/BlinkIDImageCaptureWasmSDK.data -------------------------------------------------------------------------------- /resources/basic/BlinkIDImageCaptureWasmSDK.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlinkID/blinkid-imagecapture-in-browser/ead7aec5ccf295731a3160553b8dc71bc050ad05/resources/basic/BlinkIDImageCaptureWasmSDK.wasm -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from '@rollup/plugin-babel' 2 | import nodeResolve from '@rollup/plugin-node-resolve' 3 | import typescript from 'rollup-plugin-typescript2' 4 | import { terser } from 'rollup-plugin-terser' 5 | 6 | const bannerMsg = `/*! **************************************************************************** 7 | Copyright (c) Microblink. All rights reserved. 8 | 9 | THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 10 | KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 11 | WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 12 | MERCHANTABLITY OR NON-INFRINGEMENT. 13 | ***************************************************************************** */` 14 | 15 | const terserConfig = { 16 | compress: { 17 | pure_getters: true, 18 | unsafe: true, 19 | unsafe_comps: true, 20 | warnings: false 21 | } 22 | } 23 | 24 | const config = { 25 | worker: { 26 | input: 'src/worker.ts', 27 | output: { 28 | file: 'resources/BlinkIDImageCaptureWasmSDK.worker.min.js', 29 | format: 'iife' 30 | }, 31 | plugins: [ 32 | nodeResolve(), 33 | typescript({ tsconfigOverride: { compilerOptions: { declaration: false } } }), 34 | babel({ babelHelpers: 'bundled' }), 35 | terser(terserConfig) 36 | ] 37 | }, 38 | cjs: { 39 | input: 'src/index.ts', 40 | output: { 41 | file: 'lib/blinkid-imagecapture-sdk.js', 42 | format: 'cjs', 43 | indent: false, 44 | banner: bannerMsg 45 | }, 46 | plugins: [ 47 | nodeResolve(), 48 | typescript({ useTsconfigDeclarationDir: true }), 49 | babel({ babelHelpers: 'bundled' }) 50 | ] 51 | }, 52 | es: { 53 | input: 'src/index.ts', 54 | output: { 55 | file: 'es/blinkid-imagecapture-sdk.js', 56 | format: 'es', 57 | indent: false, 58 | sourcemap: true, 59 | banner: bannerMsg 60 | }, 61 | plugins: [ 62 | nodeResolve(), 63 | typescript({ tsconfigOverride: { compilerOptions: { declaration: false, sourceMap: true } } }), 64 | babel({ babelHelpers: 'bundled' }) 65 | ] 66 | }, 67 | esModule: { 68 | input: 'src/index.ts', 69 | output: { 70 | file: 'es/blinkid-imagecapture-sdk.mjs', 71 | format: 'es', 72 | indent: false, 73 | banner: bannerMsg 74 | }, 75 | plugins: [ 76 | nodeResolve(), 77 | typescript({ tsconfigOverride: { compilerOptions: { declaration: false } } }), 78 | babel({ babelHelpers: 'bundled' }), 79 | terser(terserConfig) 80 | ] 81 | }, 82 | umdDev: { 83 | input: 'src/index.ts', 84 | output: { 85 | file: 'dist/blinkid-imagecapture-sdk.js', 86 | format: 'umd', 87 | name: 'BlinkIDImageCaptureSDK', 88 | indent: false, 89 | sourcemap: true, 90 | banner: bannerMsg 91 | }, 92 | plugins: [ 93 | nodeResolve(), 94 | typescript({ tsconfigOverride: { compilerOptions: { declaration: false, sourceMap: true } } }), 95 | babel({ babelHelpers: 'bundled' }) 96 | ] 97 | }, 98 | umdProd: { 99 | input: 'src/index.ts', 100 | output: { 101 | file: 'dist/blinkid-imagecapture-sdk.min.js', 102 | format: 'umd', 103 | name: 'BlinkIDImageCaptureSDK', 104 | indent: false, 105 | banner: bannerMsg 106 | }, 107 | plugins: [ 108 | nodeResolve(), 109 | typescript({ tsconfigOverride: { compilerOptions: { declaration: false } } }), 110 | babel({ babelHelpers: 'bundled' }), 111 | terser(terserConfig) 112 | ] 113 | } 114 | } 115 | 116 | export default [ 117 | config.worker, 118 | config.cjs, 119 | config.es, 120 | config.esModule, 121 | config.umdDev, 122 | config.umdProd 123 | ] 124 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/ClearTimeoutCallback.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | /** 6 | * @hidden 7 | * Private interface for letting RecognizerRunner inform VideoRecognizer when it 8 | * needs to clear timeout. This is usually required when multi-side recognizer has 9 | * finished scanning of the first side and needs a clean timeout start for the 10 | * recognition of the back side. 11 | */ 12 | export interface ClearTimeoutCallback 13 | { 14 | /** 15 | * Called when recognition process wants to clear any timeouts imposed on it. 16 | */ 17 | onClearTimeout(): void; 18 | } 19 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/DeviceUtils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | /** 6 | * Checks if browser is supported by the SDK. The minimum requirements for the browser is 7 | * the support for WebAssembly. If your browser does not support executing WebAssembly, 8 | * this function will return `false`. 9 | */ 10 | export function isBrowserSupported(): boolean 11 | { 12 | // based on https://stackoverflow.com/a/47880734 13 | try 14 | { 15 | if ( typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function" ) 16 | { 17 | const module = new WebAssembly.Module( Uint8Array.of( 0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00 ) ); 18 | if ( module instanceof WebAssembly.Module ) 19 | return new WebAssembly.Instance( module ) instanceof WebAssembly.Instance; 20 | } 21 | } 22 | catch ( ignored ) 23 | { 24 | return false; 25 | } 26 | return false; 27 | } 28 | 29 | /** 30 | * Check if current browser is in-app / embedded. 31 | * Detects Instagram, Facebook, LinkedIn, Twitter, WeChat, Whatsapp, and Tiktok. 32 | * @returns Boolean whether the browser is in-app or not 33 | */ 34 | export function isInAppBrowser(): boolean 35 | { 36 | const inAppRegex = /(instagram|fbav|linkedinapp|twitter|micromessenger|whatsapp|tiktok)[/\s]?([\w.]*)/i; 37 | const userAgent = navigator.userAgent || navigator.vendor; 38 | 39 | return !!inAppRegex.exec( userAgent ); 40 | } 41 | 42 | /** 43 | * Check if browser supports ES6, which is prerequisite for this SDK to execute. 44 | * 45 | * IMPORTANT: it's not possible to run this function from MicroblinkSDK if browser doesn't support 46 | * ES6 since this file won't be able to load. 47 | * 48 | * This function is here as a placeholder so it can be copied to standalone JS file or directly into 'index.html'. 49 | */ 50 | // export function isES6Supported(): boolean 51 | // { 52 | // if ( typeof Symbol === "undefined" ) 53 | // { 54 | // return false; 55 | // } 56 | // try 57 | // { 58 | // eval( "class Foo {}" ); 59 | // eval( "var bar = (x) => x+1" ); 60 | // } 61 | // catch ( e ) 62 | // { 63 | // return false; 64 | // } 65 | // return true; 66 | // } 67 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/FrameCapture.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { SDKError } from "./SDKError"; 6 | import { ImageOrientation } from "./DataStructures"; 7 | import * as ErrorTypes from "./ErrorTypes"; 8 | 9 | // ============================================ / 10 | // Frame capture and camera management support. / 11 | // ============================================ / 12 | 13 | let canvas : HTMLCanvasElement; 14 | 15 | /** 16 | * Represents a captured frame from HTMLVideoElement. 17 | */ 18 | export class CapturedFrame 19 | { 20 | /** Instance of ImageData object - contains pixels and metadata about the captured image. */ 21 | readonly imageData: ImageData; 22 | 23 | /** Orientation of the captured frame */ 24 | readonly orientation: ImageOrientation; 25 | 26 | /** Indicates whether captured frame originated from still image or video stream. */ 27 | readonly videoFrame: boolean; 28 | 29 | constructor( imageData: ImageData, orientation: ImageOrientation, videoFrame: boolean ) 30 | { 31 | this.imageData = imageData; 32 | this.orientation = orientation; 33 | this.videoFrame = videoFrame; 34 | } 35 | } 36 | 37 | /** 38 | * Captures a frame from any CanvasImageSource, such as HTMLVideoElement or HTMLImageElement. 39 | * @param imageSource image source from which frame should be captured 40 | * @returns instance of CapturedFrame 41 | */ 42 | export function captureFrame( imageSource: CanvasImageSource, shouldCrop = false ): CapturedFrame 43 | { 44 | let imageWidth: number; 45 | let imageHeight: number; 46 | let videoFrame = false; 47 | if ( imageSource instanceof HTMLVideoElement ) 48 | { 49 | imageWidth = imageSource.videoWidth; 50 | imageHeight = imageSource.videoHeight; 51 | videoFrame = true; 52 | } 53 | else if ( imageSource instanceof HTMLImageElement ) 54 | { 55 | imageWidth = imageSource.naturalWidth; 56 | imageHeight = imageSource.naturalHeight; 57 | } 58 | else if ( imageSource instanceof SVGImageElement ) 59 | { 60 | throw new SDKError( ErrorTypes.frameCaptureErrors.svgUnsupported ); 61 | } 62 | else 63 | { 64 | imageWidth = imageSource.width; 65 | imageHeight = imageSource.height; 66 | } 67 | 68 | canvas = canvas || document.createElement( "canvas" ); 69 | canvas.width = imageWidth; 70 | canvas.height = imageHeight; 71 | const ctx = canvas.getContext( "2d", { willReadFrequently: true } ) as CanvasRenderingContext2D; 72 | 73 | if ( !ctx ) 74 | { 75 | throw new SDKError( ErrorTypes.frameCaptureErrors.canvasMissing ); 76 | } 77 | 78 | ctx.drawImage( imageSource, 0, 0, canvas.width, canvas.height ); 79 | 80 | /** 81 | * Take full image or cropped image based on focus problems. 82 | * 83 | * iPhone 14 Pro has focus problems, i.e. user should place a document somehow 84 | * far away from the camera to get the proper focus. 85 | * 86 | * In that case we're getting much bigger images (4K), and we're cropping the center 87 | * of the image which is then sent to processing - rectangle that is 66% size of the 88 | * original image is cropped from the image center. 89 | */ 90 | const cropFactor = shouldCrop ? 0.66 : 1; 91 | const targetWidth = canvas.width * cropFactor; 92 | const targetHeight = canvas.height * cropFactor; 93 | const targetX = ( canvas.width - targetWidth ) / 2; 94 | const targetY = ( canvas.height - targetHeight ) / 2; 95 | const pixelData = ctx.getImageData( targetX, targetY, targetWidth, targetHeight ); 96 | 97 | return new CapturedFrame 98 | ( 99 | pixelData, 100 | // TODO: https://developer.mozilla.org/en-US/docs/Web/API/Screen/orientation 101 | // or https://developer.mozilla.org/en-US/docs/Web/API/Window/orientation 102 | ImageOrientation.NoRotation, 103 | videoFrame 104 | ); 105 | } 106 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/Geometry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | /** 6 | * Interface representing a point in image. 7 | */ 8 | export interface Point 9 | { 10 | /** X-coordinate of the point */ 11 | x: number 12 | 13 | /** Y-coordinate of the point */ 14 | y: number 15 | } 16 | 17 | /** 18 | * Interface representing a quadrilateral 19 | */ 20 | export interface Quadrilateral 21 | { 22 | /** Top-left point of the quadrilateral */ 23 | topLeft: Point 24 | 25 | /** Top-right point of the quadrilateral */ 26 | topRight: Point 27 | 28 | /** Bottom-left point of the quadrilateral */ 29 | bottomLeft: Point 30 | 31 | /** Bottom-right point of the quadrilateral */ 32 | bottomRight: Point 33 | } 34 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/LoadProgressUtils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | export function convertEmscriptenStatusToProgress( emStatus: string ): number 6 | { 7 | // roughly based on https://github.com/emscripten-core/emscripten/blob/1.39.11/src/shell.html#L1259 8 | if ( emStatus === "Running..." ) 9 | { 10 | // download has completed, wasm execution has started 11 | return 100; 12 | } 13 | else if ( emStatus.length === 0 ) 14 | { 15 | // empty message 16 | return 0; 17 | } 18 | 19 | const regExp = RegExp( /([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/ ); 20 | const match = regExp.exec( emStatus ); 21 | if ( match ) 22 | { 23 | const currentValue = parseInt( match[ 2 ] ); 24 | const maxValue = parseInt( match[ 4 ] ); 25 | return currentValue * 100 / maxValue; 26 | } 27 | else 28 | { 29 | // Cannot parse emscripten status 30 | return NaN; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/MetadataCallbacks.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { Point, Quadrilateral } from "./Geometry"; 6 | 7 | /** 8 | * Interface representing possible events that can occur during image processing. 9 | * All functions in this interface are optional and will be called only if they are 10 | * implemented. 11 | */ 12 | export interface MetadataCallbacks 13 | { 14 | /** 15 | * Called when recognition process wants to display some debug text information. 16 | * @param debugTest Debug text information to be displayed. 17 | */ 18 | onDebugText?( debugTest: string ): void 19 | 20 | /** 21 | * Called when all recognizers in RecognizerRunner have failed to detect anything on the image. 22 | */ 23 | onDetectionFailed?(): void 24 | 25 | /** 26 | * Called when recognition process wants to display some quadrilateral. 27 | * @param quad Quadrilateral to be displayed. 28 | */ 29 | onQuadDetection?( quad: DisplayableQuad ): void 30 | 31 | /** 32 | * Called when recognition process wants to display some points. 33 | * @param pointSet Points to be displayed. 34 | */ 35 | onPointsDetection?( pointSet: DisplayablePoints ): void 36 | 37 | /** 38 | * Called when first side recognition with the multi-side recognizer completes. 39 | */ 40 | onFirstSideResult?(): void 41 | 42 | /** 43 | * Called when glare detection has completed with result whether glare has been found or not. 44 | * @param hasGlare indicates whether glare has been found on the input image or not 45 | */ 46 | onGlare?( hasGlare: boolean ): void; 47 | } 48 | 49 | /** 50 | * Detection status of the specific detected object. 51 | */ 52 | export enum DetectionStatus 53 | { 54 | /** Detection failed, form not detected */ 55 | Fail = 0, 56 | /** Object was successfully detected */ 57 | Success, 58 | /** Object detected, but the camera is too far above it */ 59 | CameraTooHigh, 60 | /** Fallback detection of an object was successful */ 61 | FallbackSuccess, 62 | /** Object is detected, but parts of it are not in image */ 63 | Partial, 64 | /** Object detected, but camera is at too big angle */ 65 | CameraAtAngle, 66 | /** Object detected, but the camera is too near to it */ 67 | CameraTooNear, 68 | /** Document detected, but document is too close to the edge of the frame */ 69 | DocumentTooCloseToEdge 70 | } 71 | 72 | /** 73 | * Interface representing any displayable object. 74 | */ 75 | export interface Displayable 76 | { 77 | /** Detection status of the displayable object. */ 78 | detectionStatus: DetectionStatus 79 | 80 | /** 81 | * 3x3 transformation matrix from the image's coordinate system to view's coordinate system. 82 | */ 83 | transformMatrix: Float32Array 84 | } 85 | 86 | /** 87 | * Interface representing quadrilateral in image. 88 | */ 89 | export interface DisplayableQuad extends Displayable, Quadrilateral 90 | {} 91 | 92 | /** 93 | * Interface representing list of points in image. 94 | */ 95 | export interface DisplayablePoints extends Displayable 96 | { 97 | /** Array of points */ 98 | points: Point[] 99 | } 100 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/PThreadHelper.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { WasmType } from "./WasmType"; 6 | 7 | /* eslint-disable @typescript-eslint/no-unsafe-assignment, 8 | @typescript-eslint/no-unsafe-call, 9 | @typescript-eslint/no-explicit-any, 10 | @typescript-eslint/no-unsafe-return, 11 | @typescript-eslint/no-unsafe-assignment, 12 | @typescript-eslint/explicit-module-boundary-types, 13 | @typescript-eslint/no-unsafe-member-access */ 14 | export function setupModule( module: any, allowedThreads: number | null, jsPath: string | null ): any 15 | { 16 | if ( allowedThreads && allowedThreads > 0 ) 17 | { 18 | module = Object.assign 19 | ( 20 | module, 21 | { 22 | allowedThreads: allowedThreads 23 | } 24 | ); 25 | } 26 | if ( jsPath !== null ) 27 | { 28 | module = Object.assign 29 | ( 30 | module, 31 | { 32 | mainScriptUrlOrBlob: jsPath 33 | } 34 | ); 35 | } 36 | return module; 37 | } 38 | 39 | export async function waitForThreadWorkers( wasmModule: any ) 40 | { 41 | if ( wasmModule[ "threadWorkersReadyPromise" ] ) 42 | { 43 | await wasmModule[ "threadWorkersReadyPromise" ]; 44 | } 45 | } 46 | /* eslint-enable @typescript-eslint/no-unsafe-assignment, 47 | @typescript-eslint/no-unsafe-call, 48 | @typescript-eslint/no-unsafe-return, 49 | @typescript-eslint/no-unsafe-assignment, 50 | @typescript-eslint/explicit-module-boundary-types, 51 | @typescript-eslint/no-unsafe-member-access */ 52 | 53 | export function supportsThreads( wasmType: WasmType ): boolean 54 | { 55 | return wasmType === WasmType.AdvancedWithThreads; 56 | } 57 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/SDKError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | /* eslint-disable @typescript-eslint/no-explicit-any, 6 | @typescript-eslint/no-unsafe-assignment, 7 | @typescript-eslint/explicit-module-boundary-types */ 8 | export class SDKError 9 | { 10 | code: string; 11 | 12 | message: string; 13 | 14 | details?: any; 15 | 16 | constructor( error: { code: string, message: string }, details?: any ) 17 | { 18 | if ( !error.code || !error.message ) 19 | { 20 | throw new Error( "Instance of SDKError is required to have code and message." ); 21 | } 22 | 23 | this.message = error.message; 24 | this.code = error.code; 25 | this.details = details; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/Utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | /** 6 | * Returns safe path, i.e. URL for given path and filename (file path). 7 | * 8 | * @param path String representing file path. 9 | * @param fileName String representing file name. 10 | * @returns String representing URL for specified resource. 11 | */ 12 | export function getSafePath( path: string, fileName: string ): string 13 | { 14 | // Since this function is called by Emscripten module, make sure to set default values 15 | path = path || ""; 16 | fileName = fileName || ""; 17 | 18 | if ( path === "" ) 19 | { 20 | return fileName; 21 | } 22 | else if ( path.endsWith( "/" ) ) 23 | { 24 | if ( fileName.startsWith( "/" ) ) 25 | { 26 | return path + fileName.substring( 1 ); 27 | } 28 | else 29 | { 30 | return path + fileName; 31 | } 32 | } 33 | else if ( fileName.startsWith( "/" ) ) 34 | { 35 | return path + fileName; 36 | } 37 | else 38 | { 39 | return path + "/" + fileName; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/WasmLoadUtils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import * as WasmFeatureDetect from "wasm-feature-detect"; 6 | import { WasmType } from "./WasmType"; 7 | 8 | /* eslint-disable max-len */ 9 | /** 10 | * Safari 16 shipped with WASM threads support, but it didn't ship with nested 11 | * workers support, so an extra check is needed 12 | * https://github.com/GoogleChromeLabs/squoosh/pull/1325/files#diff-904900db64cd3f48b0e765dbbdc6a218a7ea74a199671bde82a8944a904db86f 13 | */ 14 | /* eslint-enable max-len */ 15 | export default async function checkThreadsSupport(): Promise 16 | { 17 | const supportsWasmThreads = await WasmFeatureDetect.threads(); 18 | if ( !supportsWasmThreads ) return false; 19 | 20 | if ( !( "importScripts" in self ) ) 21 | { 22 | throw Error( "Not implemented" ); 23 | } 24 | 25 | return "Worker" in self; 26 | } 27 | 28 | export async function detectWasmType(): Promise 29 | { 30 | // determine if all features required for advanced WASM are available 31 | // currently, advanced wasm requires SIMD 32 | 33 | const haveSIMD = await WasmFeatureDetect.simd(); 34 | 35 | const threadsSupported = await checkThreadsSupport(); 36 | 37 | if ( haveSIMD ) 38 | { 39 | if ( threadsSupported ) 40 | { 41 | return WasmType.AdvancedWithThreads; 42 | } 43 | else 44 | { 45 | return WasmType.Advanced; 46 | } 47 | } 48 | else 49 | { 50 | return WasmType.Basic; 51 | } 52 | } 53 | 54 | export function wasmFolder( wasmType: WasmType ): string 55 | { 56 | switch ( wasmType ) 57 | { 58 | case WasmType.AdvancedWithThreads: 59 | return "advanced-threads"; 60 | case WasmType.Advanced: 61 | return "advanced"; 62 | case WasmType.Basic: 63 | return "basic"; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/MicroblinkSDK/WasmType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | /** 6 | * Defines the type of the WASM that will be loaded. 7 | */ 8 | export enum WasmType 9 | { 10 | /** 11 | * The WASM that will be loaded will be most compatible with all browsers that 12 | * support the WASM, but will lack features that could be used to improve performance. 13 | */ 14 | Basic = "BASIC", 15 | 16 | /** 17 | * The WASM that will be loaded will be built with advanced WASM features, such as 18 | * bulk memory, SIMD, non-trapping floating point and sign extension. Such WASM can only 19 | * be executed in browsers that support those features. Attempting to run this 20 | * WASM in a non-compatible browser will crash your app. 21 | */ 22 | Advanced = "ADVANCED", 23 | 24 | /** 25 | * The WASM that will be loaded will be build with advanced WASM features, just 26 | * like above. Additionally, it will be also built with support for multi-threaded 27 | * processing. This feature requires a browser with support for both advanced WASM 28 | * features and `SharedArrayBuffer` 29 | */ 30 | AdvancedWithThreads = "ADVANCED_WITH_THREADS" 31 | } 32 | -------------------------------------------------------------------------------- /src/Recognizers/BlinkID/Generic/ImageAnalysisResult.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | export interface ImageAnalysisResult 6 | { 7 | /** 8 | * Whether the image is blurred. 9 | */ 10 | readonly blurred: boolean; 11 | 12 | /** 13 | * Orientation of the card detected on the scanned image. 14 | */ 15 | readonly cardOrientation: CardOrientation; 16 | 17 | /** 18 | * The color status determined from scanned image. 19 | */ 20 | readonly documentImageColorStatus: DocumentImageColorStatus; 21 | 22 | /** 23 | * The Moire pattern detection status determined from the scanned image. 24 | */ 25 | readonly documentImageMoireStatus: ImageAnalysisDetectionStatus; 26 | 27 | /** 28 | * Face detection status determined from the scanned image. 29 | */ 30 | readonly faceDetectionStatus: ImageAnalysisDetectionStatus; 31 | 32 | /** 33 | * Mrz detection status determined from the scanned image. 34 | */ 35 | readonly mrzDetectionStatus: ImageAnalysisDetectionStatus; 36 | 37 | /** 38 | * Barcode detection status determined from the scanned image. 39 | */ 40 | readonly barcodeDetectionStatus: ImageAnalysisDetectionStatus; 41 | } 42 | 43 | /** 44 | * DocumentImageColorStatus enum defines possible color statuses determined from scanned image. 45 | */ 46 | export enum DocumentImageColorStatus 47 | { 48 | /** Determining image color status was not performed */ 49 | NotAvailable = 0, 50 | 51 | /** Black-and-white image scanned */ 52 | BlackAndWhite, 53 | 54 | /** Color image scanned */ 55 | Color 56 | } 57 | 58 | /** 59 | * ImageAnalysisDetectionStatus enum defines possible states of specific image object detection. 60 | */ 61 | export enum ImageAnalysisDetectionStatus 62 | { 63 | /** Detection was not performed */ 64 | NotAvailable = 0, 65 | 66 | /** Object not detected on input image */ 67 | NotDetected, 68 | 69 | /** Object detected on input image */ 70 | Detected 71 | } 72 | 73 | /** 74 | * CardOrientation enum defines possible states of card orientation. 75 | */ 76 | export enum CardOrientation 77 | { 78 | /** Card is horizontally placed inside the camera frame */ 79 | Horizontal = 0, 80 | 81 | /** Card is vertically placed inside the camera frame */ 82 | Vertical 83 | } 84 | -------------------------------------------------------------------------------- /src/Recognizers/BlinkID/Generic/ProcessingStatus.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | /** Detailed information about the recognition process. */ 6 | export enum ProcessingStatus 7 | { 8 | /** The document was fully scanned and data was extracted as expected. */ 9 | Success = 0, 10 | 11 | /** The document was not found on the image. */ 12 | DetectionFailed, 13 | 14 | /** Preprocessing of the input image has failed. */ 15 | ImagePreprocessingFailed, 16 | 17 | /** 18 | * Stability is achieved when the same document is provided on consecutive frames, 19 | * resulting in a consistent recognition between frames prior to data extraction. 20 | * Valid only for video feed. 21 | */ 22 | StabilityTestFailed, 23 | 24 | /** 25 | * The wrong side of the document is scanned. Front side scan is completed and back side is expected, but not 26 | * provided by the end-user. 27 | * 28 | * Possible also if front is expected at the start of the scanning process and back is presented first 29 | * by the end-user. 30 | */ 31 | ScanningWrongSide, 32 | 33 | /** Unexpected fields are present on the document and removed from the final result. */ 34 | FieldIdentificationFailed, 35 | 36 | /** Fields expected to appear on the scanned document have not been found. */ 37 | MandatoryFieldMissing, 38 | 39 | /** 40 | * One of the extracted fields contains a character which does not satisfy the rule defined for that 41 | * specific field. 42 | * 43 | * This processing status can only occur if validateResultCharacters setting is set to true. 44 | */ 45 | InvalidCharactersFound, 46 | 47 | /** Failed to return a requested image. */ 48 | ImageReturnFailed, 49 | 50 | /** Reading or parsing of the barcode has failed. */ 51 | BarcodeRecognitionFailed, 52 | 53 | /** Parsing of the MRZ has failed. */ 54 | MrzParsingFailed, 55 | 56 | /** 57 | * Currently scanned document has been filtered out by its class. 58 | * Occurrence of this processing status is affected by classFilter setting. 59 | */ 60 | ClassFiltered, 61 | 62 | /** Document currently not supported by the recognizer. */ 63 | UnsupportedClass, 64 | 65 | /** Document class is not included in the issued license. */ 66 | UnsupportedByLicense, 67 | 68 | /** 69 | * Front side recognition has completed successfully, and recognizer is waiting for the other side to be scanned. 70 | */ 71 | AwaitingOtherSide, 72 | 73 | /** If front side recognition has not completed successfully, the back side is not scanned. */ 74 | NotScanned, 75 | 76 | /** Number of possible processing statuses. */ 77 | Count 78 | } 79 | -------------------------------------------------------------------------------- /src/Recognizers/BlinkID/Generic/RecognitionModeFilter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | * 4 | * RecognitionModeFilter is used to enable/disable recognition of specific document groups. 5 | * Setting is taken into account only if the right for that document is purchased. 6 | */ 7 | export class RecognitionModeFilter 8 | { 9 | /** Enable scanning of MRZ IDs. Setting is taken into account only if the mrz_id right is purchased. */ 10 | enableMrzId = true; 11 | 12 | /** Enable scanning of Passport MRZ. Setting is taken into account only if the passport right is purchased. */ 13 | enableMrzPassport = true; 14 | 15 | /** Enable scanning of visa MRZ. Setting is taken into account only if the visa right is purchased. */ 16 | enableMrzVisa = true; 17 | 18 | /** Enable scanning of Photo ID. Setting is taken into account only if the photo_id right is purchased. */ 19 | enablePhotoId = true; 20 | 21 | /** 22 | * Enable scanning of barcode IDs. Setting is taken into account only if the barcode right to 23 | * scan that barcode is purchased. 24 | */ 25 | enableBarcodeId = true; 26 | 27 | /** 28 | * Enable full document recognition. Setting is taken into account only if the document right to 29 | * scan that document is purchased. 30 | */ 31 | enableFullDocumentRecognition = true; 32 | } 33 | -------------------------------------------------------------------------------- /src/Recognizers/SuccessFrameGrabberRecognizer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import 6 | { 7 | Recognizer, 8 | RecognizerResult, 9 | WasmSDK, 10 | ImageOrientation 11 | } from "../MicroblinkSDK/DataStructures"; 12 | 13 | /** 14 | * The result object of the SuccessFrameGrabberRecognizer. 15 | */ 16 | export interface SuccessFrameGrabberRecognizerResult extends RecognizerResult 17 | { 18 | /** 19 | * Camera frame on which given recognizer's result ha become valid. 20 | * If given recognizer's result never became valid, contains null. 21 | */ 22 | readonly successFrame: ImageData | null; 23 | 24 | /** 25 | * Orientation of the success frame. 26 | */ 27 | readonly frameOrientation: ImageOrientation; 28 | } 29 | 30 | /** 31 | * Recognizer that can wrap another recognizer and capture the frame on which 32 | * the wrapped recognizer has succeeded to recognize. 33 | */ 34 | export interface SuccessFrameGrabberRecognizer< T extends Recognizer > extends Recognizer 35 | { 36 | /** 37 | * Reference to recognizer that is being wrapped by this 38 | * SuccessFrameGrabberRecognizer. 39 | */ 40 | readonly wrappedRecognizer: T; 41 | 42 | /** 43 | * Returns the current result of the recognition. Note that result will not 44 | * contain the result of the wrapped recognizer. To obtain that result, call 45 | * getResult on wrapped recognizer. 46 | */ 47 | getResult(): Promise< SuccessFrameGrabberRecognizerResult >; 48 | 49 | /** 50 | * Cleans up the object from the WebAssembly heap. 51 | */ 52 | delete(): Promise< void >; 53 | } 54 | 55 | /** 56 | * Creates a new instance of `SuccessFrameGrabberRecognizer`. 57 | * @param wasmSDK Instance of WasmSDK which will be used to communicate with the 58 | * WebAssembly module. 59 | * @param slaveRecognizer Instance of Recognizer that will be wrapped. 60 | */ 61 | export async function createSuccessFrameGrabberRecognizer< T extends Recognizer > 62 | ( 63 | wasmSDK: WasmSDK, 64 | slaveRecognizer: T 65 | ): Promise< SuccessFrameGrabberRecognizer < T > > 66 | { 67 | // taken from https://stackoverflow.com/a/53615996 68 | const sfgr = await wasmSDK.mbWasmModule.newRecognizer 69 | ( 70 | "SuccessFrameGrabberRecognizer", 71 | slaveRecognizer 72 | ) as SuccessFrameGrabberRecognizer< T >; 73 | type MutableSFGR = { 74 | -readonly [ K in keyof SuccessFrameGrabberRecognizer< T > ]: SuccessFrameGrabberRecognizer< T >[ K ] 75 | } 76 | const mutableSFGR: MutableSFGR = sfgr; 77 | mutableSFGR.wrappedRecognizer = slaveRecognizer; 78 | return sfgr; 79 | } 80 | -------------------------------------------------------------------------------- /src/defaultWasmModule.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | export const defaultWasmModuleName = "BlinkIDImageCaptureWasmSDK"; 6 | export const nativeJsonizationEnabled = false; 7 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | export * from "./MicroblinkSDK/MicroblinkSDK"; 6 | 7 | // export all recognizers 8 | export * from "./Recognizers/BlinkID/ImageCapture/ImageCaptureRecognizer"; 9 | export * from "./Recognizers/SuccessFrameGrabberRecognizer"; 10 | -------------------------------------------------------------------------------- /src/worker.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import MicroblinkWorker from "./MicroblinkSDK/worker/MicroblinkSDK.worker"; 6 | 7 | new MicroblinkWorker(); 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "declaration": true, 7 | "declarationDir": "./types", 8 | "forceConsistentCasingInFileNames": true, 9 | "noImplicitReturns": true, 10 | "strict": true, 11 | "noUnusedLocals": true, 12 | "types": [] 13 | }, 14 | "include": ["./src/**/*"] 15 | } 16 | -------------------------------------------------------------------------------- /ui/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-api-process-status/readme.md: -------------------------------------------------------------------------------- 1 | # mb-api-process-status 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | -------------------- | --------- | ------------------------------------------------------------------------------------ | --------------------------------------------- | ----------- | 12 | | `state` | `state` | State value of API processing received from parent element ('loading' or 'success'). | `"ERROR" \| "LOADING" \| "NONE" \| "SUCCESS"` | `undefined` | 13 | | `translationService` | -- | Instance of TranslationService passed from parent component. | `TranslationService` | `undefined` | 14 | | `visible` | `visible` | Element visibility, default is 'false'. | `boolean` | `false` | 15 | 16 | 17 | ## Events 18 | 19 | | Event | Description | Type | 20 | | ---------------- | ------------------------------------------- | ------------------- | 21 | | `closeFromStart` | Emitted when user clicks on 'x' button. | `CustomEvent` | 22 | | `closeTryAgain` | Emitted when user clicks on 'Retry' button. | `CustomEvent` | 23 | 24 | 25 | ## Dependencies 26 | 27 | ### Used by 28 | 29 | - [mb-component](../mb-component) 30 | 31 | ### Depends on 32 | 33 | - [mb-modal](../mb-modal) 34 | 35 | ### Graph 36 | ```mermaid 37 | graph TD; 38 | mb-api-process-status --> mb-modal 39 | mb-component --> mb-api-process-status 40 | style mb-api-process-status fill:#f9f,stroke:#333,stroke-width:4px 41 | ``` 42 | 43 | ---------------------------------------------- 44 | 45 | *Built with [StencilJS](https://stenciljs.com/)* 46 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-button-classic/readme.md: -------------------------------------------------------------------------------- 1 | # mb-button-classic 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | --------------------------- | ----------------- | ---------------------------------------------------------------------------------------- | ----------------------- | ----------- | 12 | | `clickHandler` _(required)_ | -- | Function to call on click | `(ev: UIEvent) => void` | `undefined` | 13 | | `disabled` | `disabled` | Set to 'true' if button should be disabled, and if click events should not be triggered. | `boolean` | `false` | 14 | | `inverted` | `inverted` | Set to 'true' if button should be inverted style. | `boolean` | `false` | 15 | | `preventDefault` | `prevent-default` | Set to 'true' if default event should be prevented. | `boolean` | `false` | 16 | 17 | 18 | ## Dependencies 19 | 20 | ### Used by 21 | 22 | - [mb-component](../mb-component) 23 | 24 | ### Graph 25 | ```mermaid 26 | graph TD; 27 | mb-component --> mb-button-classic 28 | style mb-button-classic fill:#f9f,stroke:#333,stroke-width:4px 29 | ``` 30 | 31 | ---------------------------------------------- 32 | 33 | *Built with [StencilJS](https://stenciljs.com/)* 34 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-button/readme.md: -------------------------------------------------------------------------------- 1 | # mb-button 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | ------------------------------ | ------------------- | ---------------------------------------------------------------------------------------- | ----------------------- | ----------- | 12 | | `buttonTitle` _(required)_ | `button-title` | | `string` | `undefined` | 13 | | `clickHandler` _(required)_ | -- | Function to call on click | `(ev: UIEvent) => void` | `undefined` | 14 | | `disabled` | `disabled` | Set to 'true' if button should be disabled, and if click events should not be triggered. | `boolean` | `false` | 15 | | `imageAlt` | `image-alt` | Passed description text for image element from parent component. | `string` | `''` | 16 | | `imageSrcActive` _(required)_ | `image-src-active` | Passed image from parent component. | `string` | `undefined` | 17 | | `imageSrcDefault` _(required)_ | `image-src-default` | Passed image from parent component. | `string` | `undefined` | 18 | | `label` | `label` | Set to string which should be displayed below the icon. If omitted, nothing will show. | `string` | `''` | 19 | | `selected` | `selected` | Set to 'true' if button should enter 'selected' state. | `boolean` | `false` | 20 | | `visible` | `visible` | Set to 'true' if button should be visible. | `boolean` | `false` | 21 | 22 | 23 | ## Dependencies 24 | 25 | ### Used by 26 | 27 | - [mb-component](../mb-component) 28 | 29 | ### Graph 30 | ```mermaid 31 | graph TD; 32 | mb-component --> mb-button 33 | style mb-button fill:#f9f,stroke:#333,stroke-width:4px 34 | ``` 35 | 36 | ---------------------------------------------- 37 | 38 | *Built with [StencilJS](https://stenciljs.com/)* 39 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-camera-selection/readme.md: -------------------------------------------------------------------------------- 1 | # mb-camera-selection 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | --------------------- | ------------------------ | ----------- | --------- | ------- | 12 | | `clearIsCameraActive` | `clear-is-camera-active` | | `boolean` | `false` | 13 | 14 | 15 | ## Events 16 | 17 | | Event | Description | Type | 18 | | -------------------- | ---------------------------------------------------- | -------------------------- | 19 | | `changeCameraDevice` | Emitted when user selects a different camera device. | `CustomEvent` | 20 | | `setIsCameraActive` | Emitted when camera stream becomes active. | `CustomEvent` | 21 | 22 | 23 | ## Methods 24 | 25 | ### `populateCameraDevices() => Promise` 26 | 27 | Populate list of camera devices. 28 | 29 | #### Returns 30 | 31 | Type: `Promise` 32 | 33 | 34 | 35 | ### `setActiveCamera(cameraId: string) => Promise` 36 | 37 | Change active camera. 38 | 39 | #### Returns 40 | 41 | Type: `Promise` 42 | 43 | 44 | 45 | 46 | ## Dependencies 47 | 48 | ### Used by 49 | 50 | - [mb-camera-toolbar](../mb-camera-toolbar) 51 | 52 | ### Graph 53 | ```mermaid 54 | graph TD; 55 | mb-camera-toolbar --> mb-camera-selection 56 | style mb-camera-selection fill:#f9f,stroke:#333,stroke-width:4px 57 | ``` 58 | 59 | ---------------------------------------------- 60 | 61 | *Built with [StencilJS](https://stenciljs.com/)* 62 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-camera-toolbar/readme.md: -------------------------------------------------------------------------------- 1 | # mb-camera-toolbar 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | --------------------- | ------------------------ | ---------------------------------------------------------------------------- | --------- | ------- | 12 | | `cameraFlipped` | `camera-flipped` | Whether the camera is flipped, this property will be flip the relevant icon. | `boolean` | `false` | 13 | | `clearIsCameraActive` | `clear-is-camera-active` | | `boolean` | `false` | 14 | | `enableCameraFlip` | `enable-camera-flip` | Whether to show 'Camera flip' button. | `boolean` | `false` | 15 | | `showClose` | `show-close` | Set to `true` if close button should be displayed. | `boolean` | `false` | 16 | 17 | 18 | ## Events 19 | 20 | | Event | Description | Type | 21 | | -------------------- | ------------------------------------------------------------ | -------------------------- | 22 | | `changeCameraDevice` | Emitted when user selects a different camera device. | `CustomEvent` | 23 | | `closeEvent` | Event which is triggered when close button is clicked. | `CustomEvent` | 24 | | `flipEvent` | Event which is triggered when flip camera button is clicked. | `CustomEvent` | 25 | | `setIsCameraActive` | Emitted when camera stream becomes active. | `CustomEvent` | 26 | 27 | 28 | ## Methods 29 | 30 | ### `populateCameraDevices() => Promise` 31 | 32 | Populate list of camera devices. 33 | 34 | #### Returns 35 | 36 | Type: `Promise` 37 | 38 | 39 | 40 | ### `setActiveCamera(cameraId: string) => Promise` 41 | 42 | Change active camera. 43 | 44 | #### Returns 45 | 46 | Type: `Promise` 47 | 48 | 49 | 50 | 51 | ## Dependencies 52 | 53 | ### Used by 54 | 55 | - [mb-camera-experience](../mb-camera-experience) 56 | 57 | ### Depends on 58 | 59 | - [mb-camera-selection](../mb-camera-selection) 60 | 61 | ### Graph 62 | ```mermaid 63 | graph TD; 64 | mb-camera-toolbar --> mb-camera-selection 65 | mb-camera-experience --> mb-camera-toolbar 66 | style mb-camera-toolbar fill:#f9f,stroke:#333,stroke-width:4px 67 | ``` 68 | 69 | ---------------------------------------------- 70 | 71 | *Built with [StencilJS](https://stenciljs.com/)* 72 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-completed/readme.md: -------------------------------------------------------------------------------- 1 | # mb-completed 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | -------- | --------- | ------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 12 | | `icon` | `icon` | Value of `src` attribute for element. | `string` | `'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjUiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNSAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMS4yMDcxIDYuMjkyODlDMjEuNTk3NiA2LjY4MzQyIDIxLjU5NzYgNy4zMTY1OCAyMS4yMDcxIDcuNzA3MTFMMTEuMjA3MSAxNy43MDcxQzEwLjgxNjYgMTguMDk3NiAxMC4xODM0IDE4LjA5NzYgOS43OTI4OSAxNy43MDcxTDQuNzkyODkgMTIuNzA3MUM0LjQwMjM3IDEyLjMxNjYgNC40MDIzNyAxMS42ODM0IDQuNzkyODkgMTEuMjkyOUM1LjE4MzQyIDEwLjkwMjQgNS44MTY1OCAxMC45MDI0IDYuMjA3MTEgMTEuMjkyOUwxMC41IDE1LjU4NThMMTkuNzkyOSA2LjI5Mjg5QzIwLjE4MzQgNS45MDIzNyAyMC44MTY2IDUuOTAyMzcgMjEuMjA3MSA2LjI5Mjg5WiIgZmlsbD0iIzAwNjJGMiIvPgo8L3N2Zz4K'` | 13 | 14 | 15 | ## Dependencies 16 | 17 | ### Used by 18 | 19 | - [mb-component](../mb-component) 20 | 21 | ### Graph 22 | ```mermaid 23 | graph TD; 24 | mb-component --> mb-completed 25 | style mb-completed fill:#f9f,stroke:#333,stroke-width:4px 26 | ``` 27 | 28 | ---------------------------------------------- 29 | 30 | *Built with [StencilJS](https://stenciljs.com/)* 31 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-container/readme.md: -------------------------------------------------------------------------------- 1 | # mb-container 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Dependencies 9 | 10 | ### Used by 11 | 12 | - [blinkid-imagecapture-in-browser](../../blinkid-imagecapture-in-browser) 13 | 14 | ### Graph 15 | ```mermaid 16 | graph TD; 17 | blinkid-imagecapture-in-browser --> mb-container 18 | style mb-container fill:#f9f,stroke:#333,stroke-width:4px 19 | ``` 20 | 21 | ---------------------------------------------- 22 | 23 | *Built with [StencilJS](https://stenciljs.com/)* 24 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-feedback/readme.md: -------------------------------------------------------------------------------- 1 | # mb-feedback 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | --------- | --------- | --------------------------------------------- | --------- | ------- | 12 | | `visible` | `visible` | Set to 'true' if component should be visible. | `boolean` | `false` | 13 | 14 | 15 | ## Methods 16 | 17 | ### `show(feedback: FeedbackMessage) => Promise` 18 | 19 | Call when FeedbackMessage which should be displayed. 20 | 21 | #### Returns 22 | 23 | Type: `Promise` 24 | 25 | 26 | 27 | 28 | ## Dependencies 29 | 30 | ### Used by 31 | 32 | - [blinkid-imagecapture-in-browser](../../blinkid-imagecapture-in-browser) 33 | 34 | ### Graph 35 | ```mermaid 36 | graph TD; 37 | blinkid-imagecapture-in-browser --> mb-feedback 38 | style mb-feedback fill:#f9f,stroke:#333,stroke-width:4px 39 | ``` 40 | 41 | ---------------------------------------------- 42 | 43 | *Built with [StencilJS](https://stenciljs.com/)* 44 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-image-box/readme.md: -------------------------------------------------------------------------------- 1 | # mb-image-box 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | ------------ | ------------- | ------------------------------------------------------------------------------------------- | -------- | ----------- | 12 | | `anchorText` | `anchor-text` | Text which should be displayed inside 'Add image' anchor element when file is not selected. | `string` | `undefined` | 13 | | `boxTitle` | `box-title` | Text which represents name of the image. | `string` | `undefined` | 14 | 15 | 16 | ## Events 17 | 18 | | Event | Description | Type | 19 | | ------------- | ------------------------------------------------------------- | ----------------------- | 20 | | `imageChange` | Event which is triggered when selected image file is changed. | `CustomEvent` | 21 | 22 | 23 | ## Methods 24 | 25 | ### `clear() => Promise` 26 | 27 | Clear input image. 28 | 29 | #### Returns 30 | 31 | Type: `Promise` 32 | 33 | 34 | 35 | 36 | ## Dependencies 37 | 38 | ### Used by 39 | 40 | - [mb-component](../mb-component) 41 | 42 | ### Graph 43 | ```mermaid 44 | graph TD; 45 | mb-component --> mb-image-box 46 | style mb-image-box fill:#f9f,stroke:#333,stroke-width:4px 47 | ``` 48 | 49 | ---------------------------------------------- 50 | 51 | *Built with [StencilJS](https://stenciljs.com/)* 52 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-modal/readme.md: -------------------------------------------------------------------------------- 1 | # mb-modal 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | ----------------- | ------------------ | ------------------------------------------ | --------- | ------- | 12 | | `centered` | `centered` | Center component | `boolean` | `false` | 13 | | `content` | `content` | Passed body content from parent component | `string` | `""` | 14 | | `contentCentered` | `content-centered` | Center content inside modal | `boolean` | `true` | 15 | | `elevated` | `elevated` | Show shadow drop | `boolean` | `false` | 16 | | `hideFooter` | `hide-footer` | Whether to hide the footer or not | `boolean` | `false` | 17 | | `modalTitle` | `modal-title` | Passed title content from parent component | `string` | `""` | 18 | | `showBackButton` | `show-back-button` | Whether to show back arrow or not | `boolean` | `false` | 19 | | `visible` | `visible` | Show modal content | `boolean` | `false` | 20 | 21 | 22 | ## Events 23 | 24 | | Event | Description | Type | 25 | | ------- | ------------------------------------------------ | ------------------- | 26 | | `back` | Emitted when user clicks on 'Back Arrow' button. | `CustomEvent` | 27 | | `close` | Emitted when user clicks on 'X' button. | `CustomEvent` | 28 | 29 | 30 | ## Shadow Parts 31 | 32 | | Part | Description | 33 | | ------------------ | ----------- | 34 | | `"mb-modal-inner"` | | 35 | 36 | 37 | ## Dependencies 38 | 39 | ### Used by 40 | 41 | - [mb-api-process-status](../mb-api-process-status) 42 | - [mb-component](../mb-component) 43 | 44 | ### Graph 45 | ```mermaid 46 | graph TD; 47 | mb-api-process-status --> mb-modal 48 | mb-component --> mb-modal 49 | style mb-modal fill:#f9f,stroke:#333,stroke-width:4px 50 | ``` 51 | 52 | ---------------------------------------------- 53 | 54 | *Built with [StencilJS](https://stenciljs.com/)* 55 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-overlay/readme.md: -------------------------------------------------------------------------------- 1 | # mb-overlay 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | ------------ | ------------ | -------------------------------------------------------- | --------- | ------- | 12 | | `fullscreen` | `fullscreen` | Set to 'false' if overlay should not cover whole screen. | `boolean` | `true` | 13 | | `visible` | `visible` | Set to 'true' if overlay should be visible. | `boolean` | `false` | 14 | 15 | 16 | ## Dependencies 17 | 18 | ### Used by 19 | 20 | - [mb-component](../mb-component) 21 | 22 | ### Graph 23 | ```mermaid 24 | graph TD; 25 | mb-component --> mb-overlay 26 | style mb-overlay fill:#f9f,stroke:#333,stroke-width:4px 27 | ``` 28 | 29 | ---------------------------------------------- 30 | 31 | *Built with [StencilJS](https://stenciljs.com/)* 32 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-screen/readme.md: -------------------------------------------------------------------------------- 1 | # mb-screen 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | --------- | --------- | ------------------------------------------ | --------- | ------- | 12 | | `visible` | `visible` | Set to 'true' if screen should be visible. | `boolean` | `false` | 13 | 14 | 15 | ## Dependencies 16 | 17 | ### Used by 18 | 19 | - [mb-component](../mb-component) 20 | 21 | ### Graph 22 | ```mermaid 23 | graph TD; 24 | mb-component --> mb-screen 25 | style mb-screen fill:#f9f,stroke:#333,stroke-width:4px 26 | ``` 27 | 28 | ---------------------------------------------- 29 | 30 | *Built with [StencilJS](https://stenciljs.com/)* 31 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-spinner/readme.md: -------------------------------------------------------------------------------- 1 | # mb-spinner 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | -------- | --------- | ------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 12 | | `icon` | `icon` | Value of `src` attribute for element. | `string` | `'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA2IiBoZWlnaHQ9IjEwNiIgdmlld0JveD0iMCAwIDEwNiAxMDYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxjaXJjbGUgY3g9IjUzIiBjeT0iNTMiIHI9IjUwIiBzdHJva2U9IiNEQ0VBRkYiIHN0cm9rZS13aWR0aD0iNiIvPgo8cGF0aCBkPSJNMyA1M0MzIDI1LjM4NTggMjUuMzg1OCAzIDUzIDMiIHN0cm9rZT0iIzAwNjJGMiIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+Cg=='` | 13 | | `size` | `size` | Spinner size, can be 'default' or 'large'. | `string` | `'default'` | 14 | 15 | 16 | ## Dependencies 17 | 18 | ### Used by 19 | 20 | - [mb-component](../mb-component) 21 | 22 | ### Graph 23 | ```mermaid 24 | graph TD; 25 | mb-component --> mb-spinner 26 | style mb-spinner fill:#f9f,stroke:#333,stroke-width:4px 27 | ``` 28 | 29 | ---------------------------------------------- 30 | 31 | *Built with [StencilJS](https://stenciljs.com/)* 32 | -------------------------------------------------------------------------------- /ui/docs/components/shared/mb-tooltip/readme.md: -------------------------------------------------------------------------------- 1 | # mb-tooltip 2 | 3 | 4 | 5 | 6 | 7 | 8 | ## Properties 9 | 10 | | Property | Attribute | Description | Type | Default | 11 | | ----------------- | ------------------- | ----------- | ----------------------------------------------------------------------------- | ----------- | 12 | | `arrowPosition` | `arrow-position` | | `"arrow-down" \| "arrow-left" \| "arrow-none" \| "arrow-right" \| "arrow-up"` | `undefined` | 13 | | `containerWidth` | `container-width` | | `string` | `undefined` | 14 | | `message` | `message` | | `string` | `undefined` | 15 | | `show` | `show` | | `boolean` | `undefined` | 16 | | `showInfoIcon` | `show-info-icon` | | `boolean` | `undefined` | 17 | | `showWarningIcon` | `show-warning-icon` | | `boolean` | `undefined` | 18 | | `textAlign` | `text-align` | | `"text-center" \| "text-left" \| "text-right"` | `undefined` | 19 | 20 | 21 | ## Shadow Parts 22 | 23 | | Part | Description | 24 | | ----------- | ----------- | 25 | | `"tooltip"` | | 26 | 27 | 28 | ---------------------------------------------- 29 | 30 | *Built with [StencilJS](https://stenciljs.com/)* 31 | -------------------------------------------------------------------------------- /ui/examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Provided examples should help you with integration of this SDK with your app. 4 | 5 | Deployment: 6 | 7 | * When accessing examples via web browser always use `localhost` instead of `127.0.0.1`. 8 | * Examples should be served via HTTPS. 9 | * We recommend usage of NPM package [https-localhost](https://www.npmjs.com/package/https-localhost) for simple local deployment. 10 | 11 | ## TypeScript Example 12 | 13 | To run TypeScript example: 14 | 15 | 1. Install example dependencies and build an application: 16 | ``` 17 | # Make sure you're in the 'ui/examples/typescript' folder 18 | 19 | # Install dependencies 20 | npm install 21 | 22 | # Build an application in folder 'dist/' 23 | npm run build 24 | ``` 25 | 2. Runtime resources are copied to `dist/` folder during build action, check `rollup.config.js` file. 26 | 3. Serve `dist/` folder, e.g. `serve dist/`. 27 | 28 | ## JavaScript Example 29 | 30 | To run JavaScript examples: 31 | 32 | 1. Serve `javascript/` folder, e.g. `serve javascript/`. 33 | * Make sure to have internet connection since runtime resources are loaded from the CDN. 34 | * Alternatively, change resource paths and provide JS bundles. -------------------------------------------------------------------------------- /ui/examples/typescript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /ui/examples/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ui-ts", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "rollup -c" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "private": true, 13 | "devDependencies": { 14 | "@rollup/plugin-node-resolve": "^8.0.1", 15 | "rollup": "^2.15.0", 16 | "rollup-plugin-copy": "^3.3.0", 17 | "rollup-plugin-terser": "^6.1.0", 18 | "rollup-plugin-typescript2": "^0.27.1", 19 | "typescript": "^3.9.5" 20 | }, 21 | "dependencies": { 22 | "@microblink/blinkid-imagecapture-in-browser-sdk": "~6.0.0" 23 | } 24 | } -------------------------------------------------------------------------------- /ui/examples/typescript/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example: BlinkID ImageCapture UI 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ui/examples/typescript/public/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | * 6 | { 7 | box-sizing: border-box; 8 | } 9 | 10 | html 11 | { 12 | width: 100%; 13 | height: 100%; 14 | margin: 0; 15 | padding: 0; 16 | font-family: sans-serif; 17 | font-size: 16px; 18 | line-height: 24px; 19 | } 20 | 21 | body 22 | { 23 | max-width: 960px; 24 | min-height: 100%; 25 | margin: 0 auto; 26 | padding: 3rem 1.5rem; 27 | background-color: #eee; 28 | } 29 | 30 | blinkid-imagecapture-in-browser 31 | { 32 | max-width: 400px; 33 | 34 | /* Customization of UI - see variables in src/components/shared/styles/_globals.scss */ 35 | /* 36 | --mb-component-background: red; 37 | --mb-component-action-label: none; 38 | --mb-component-border-width: 0; 39 | --mb-component-action-buttons-width: 100%; 40 | --mb-component-action-buttons-justify-content: space-evenly; 41 | --mb-component-button-size: 48px; 42 | --mb-component-button-border-radius: 24px; 43 | */ 44 | } 45 | -------------------------------------------------------------------------------- /ui/examples/typescript/rollup.config.js: -------------------------------------------------------------------------------- 1 | import copy from "rollup-plugin-copy"; 2 | import nodeResolve from "@rollup/plugin-node-resolve"; 3 | import typescript from "rollup-plugin-typescript2"; 4 | import { terser } from "rollup-plugin-terser"; 5 | 6 | export default [ 7 | { 8 | input: "src/app.ts", 9 | output: 10 | { 11 | file: "dist/app.js", 12 | format: "iife" 13 | }, 14 | plugins: [ 15 | nodeResolve(), 16 | typescript(), 17 | terser({ 18 | compress: 19 | { 20 | pure_getters: true, 21 | unsafe: true, 22 | unsafe_comps: true, 23 | warnings: false 24 | } 25 | }), 26 | copy({ 27 | targets: [ 28 | { src: "public/*", dest: "dist" }, 29 | 30 | // Copy WASM resources to public location 31 | { 32 | src: "node_modules/@microblink/blinkid-imagecapture-in-browser-sdk/resources/*", 33 | dest: "dist" 34 | }, 35 | 36 | // Copy UI resources to public location 37 | { 38 | src: "node_modules/@microblink/blinkid-imagecapture-in-browser-sdk/ui/dist/blinkid-imagecapture-in-browser/", 39 | dest: "dist" 40 | } 41 | ] 42 | }) 43 | ] 44 | } 45 | ]; 46 | -------------------------------------------------------------------------------- /ui/examples/typescript/src/app.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | // Import typings for UI component 6 | import "@microblink/blinkid-imagecapture-in-browser-sdk/ui"; 7 | 8 | // Import typings for custom events 9 | import { SDKError, EventScanError, EventScanSuccess } from "@microblink/blinkid-imagecapture-in-browser-sdk/ui/dist/types/utils/data-structures"; 10 | 11 | // Import client library for simple communication with backend services 12 | import { ApiType, Client } from "@microblink/blinkid-imagecapture-in-browser-sdk/client-library"; 13 | 14 | // [OPTIONAL] Include WASM library if filtering by document type is required 15 | import { BlinkIdImageCaptureRecognizerResult, Country } from "@microblink/blinkid-imagecapture-in-browser-sdk"; 16 | function initializeUiComponent() { 17 | const el = document.querySelector("blinkid-imagecapture-in-browser") as HTMLBlinkidImagecaptureInBrowserElement; 18 | if (!el) { 19 | throw "Could not find UI component!"; 20 | } 21 | el.licenseKey = "sRwAAAYJbG9jYWxob3N0r/lOPgo/w35CpGFWKcUTzWfFms+1HtOJBLOa0Z9jQdHUQo1EWP1afmump3DAd/zRkoNODh6Y9FtA1eYVaya36wQmmWpLEliFyV9va44nCIrCRqyoUzeQolAjPINbKGqHklMsfYekNYLDA2i+7zfxUF8Ac3eQ3FiDhrN3d1l+36UjfUfU9e6omHNFxdqysdOxvgVw9bNH8fjbKRmI1CJHbJmb1AWmi2YGwk0="; 22 | el.engineLocation = window.location.origin; 23 | el.workerLocation = window.location.origin + "/BlinkIDImageCaptureWasmSDK.worker.min.js"; 24 | el.recognizers = ["BlinkIdImageCaptureRecognizer"]; 25 | 26 | // Create instance of client library - for more information see `client-library/README.md` file 27 | const client = new Client(ApiType.SelfHosted, { 28 | apiLocation: "https://demoapi.microblink.com" 29 | }); 30 | /** 31 | * UI component will extract a document image, which can be recognized on the backend. 32 | */ 33 | el.addEventListener("scanSuccess", (ev: CustomEventInit) => { 34 | console.log("scanSuccess: extracted image from WASM library", ev.detail); 35 | if (!ev.detail) { 36 | el.setUiState("ERROR"); 37 | return; 38 | } 39 | const results = ev.detail.recognizer as BlinkIdImageCaptureRecognizerResult; 40 | /** 41 | * [OPTIONAL] Filter document based on provided class info. 42 | * 43 | * Keep in mind that enums with codes for country, region and document types are 44 | * included in the WASM library. 45 | */ 46 | if (results.classInfo.country === Country.CROATIA) { 47 | console.log("What should I do with Croatian document?"); 48 | } 49 | 50 | // Show error or loading screen in UI component based on extracted image 51 | if (results.frontCameraFrame.frame) { 52 | el.setUiState("ERROR"); 53 | return; 54 | } 55 | else { 56 | el.setUiState("LOADING"); 57 | } 58 | 59 | // Send image to web API for processing 60 | const payload = { 61 | 62 | // Image from WASM library should be converted to Base64 from ImageData format. 63 | "imageSource": client.imageDataToBase64(results.frontCameraFrame.frame) 64 | }; 65 | client.recognize("/v2/recognizers/blinkid-single-side", payload) 66 | .then((results) => { 67 | const recognitionResults = results.response.data.result; 68 | console.log("API recognition results", recognitionResults); 69 | if (recognitionResults.recognitionStatus === "EMPTY") { 70 | console.warn("API processing returned empty results."); 71 | el.setUiState("ERROR"); 72 | return; 73 | } 74 | 75 | // Do something with the results and notify the user 76 | el.setUiState("SUCCESS"); 77 | }) 78 | .catch((error) => { 79 | console.error("API recognition error", error); 80 | el.setUiState("ERROR"); 81 | }); 82 | }); 83 | el.addEventListener("fatalError", (ev: CustomEventInit) => { 84 | const fatalError = ev.detail; 85 | console.log("Could not load UI component", fatalError); 86 | }); 87 | el.addEventListener("scanError", (ev: CustomEventInit) => { 88 | const scanError = ev.detail; 89 | console.log("Could not scan a document", scanError); 90 | }); 91 | } 92 | 93 | window.addEventListener("DOMContentLoaded", () => initializeUiComponent()); 94 | -------------------------------------------------------------------------------- /ui/examples/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "forceConsistentCasingInFileNames": true, 7 | "noImplicitReturns": true, 8 | "strict": true, 9 | "noUnusedLocals": true 10 | }, 11 | "include": ["./src/*"] 12 | } 13 | -------------------------------------------------------------------------------- /ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "dist/index.cjs.js", 3 | "module": "dist/index.js", 4 | "collection": "dist/collection/collection-manifest.json", 5 | "types": "dist/types/components.d.ts", 6 | "files": [ 7 | "dist", 8 | "loader", 9 | "src" 10 | ], 11 | "scripts": { 12 | "build": "stencil build --docs --config=stencil.config.ts", 13 | "check-types": "tsc --p ./tsconfig.json --noEmit", 14 | "clean": "rimraf demo dist docs loader resources resources-lightweight client-dist", 15 | "prepare-assets": "cp -r ../resources/ resources && cp -r ../resources-lightweight/ resources-lightweight && cp -r ../client-library/dist/ client-dist", 16 | "generate": "stencil generate", 17 | "start": "stencil build --dev --watch --serve --config=stencil.config.ts", 18 | "test": "stencil test --spec --e2e", 19 | "test.watch": "stencil test --spec --e2e --watchAll" 20 | }, 21 | "devDependencies": { 22 | "@microblink/blinkid-imagecapture-in-browser-sdk": "file:../", 23 | "@stencil/core": "2.12.0", 24 | "@stencil/postcss": "2.1.0", 25 | "@stencil/sass": "1.5.2", 26 | "autoprefixer": "^10.2.5", 27 | "rimraf": "^3.0.2", 28 | "typescript": "^4.0.5" 29 | }, 30 | "private": true 31 | } 32 | -------------------------------------------------------------------------------- /ui/src/components/blinkid-imagecapture-in-browser/blinkid-imagecapture-in-browser.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../shared/styles/globals"; 6 | 7 | :host { 8 | display: block; 9 | width: 100%; 10 | } 11 | -------------------------------------------------------------------------------- /ui/src/components/blinkid-imagecapture-in-browser/test/blinkid-imagecapture-in-browser.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('blinkid-imagecapture-in-browser', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('blinkid-imagecapture-in-browser'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/blinkid-imagecapture-in-browser/test/blinkid-imagecapture-in-browser.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { BlinkidImageCaptureInBrowser } from '../blinkid-imagecapture-in-browser'; 7 | 8 | describe('blinkid-imagecapture-in-browser', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [BlinkidImageCaptureInBrowser], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-api-process-status/mb-api-process-status.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/_globals-sass"; 6 | @import "../styles/reticle"; 7 | 8 | *::after, 9 | *::before { 10 | box-sizing: border-box; 11 | } 12 | 13 | :host { 14 | 15 | .message { 16 | display: block; 17 | 18 | position: absolute; 19 | top: 100%; 20 | left: 50%; 21 | transform-origin: center; 22 | transform: translate(-50%, 0); 23 | 24 | margin: 2 * $base-unit 0 0 0; 25 | margin-top: 20px; 26 | padding: 2 * $base-unit 3 * $base-unit; 27 | 28 | font-weight: 500; 29 | text-align: center; 30 | text-shadow: 0px 1px 4px rgba(0, 0, 0, 0.1); 31 | white-space: nowrap; 32 | 33 | color: #fff; 34 | background-color: map-get(map-get(map-get($base-colors, text-quaternary), onlight), foreground); 35 | 36 | -webkit-backdrop-filter: blur(var(--mb-blur-filter)); 37 | backdrop-filter: blur(var(--mb-blur-filter)); 38 | 39 | border-radius: 2 * $base-unit; 40 | } 41 | 42 | .reticle-container { 43 | position: absolute; 44 | top: 50%; 45 | left: 50%; 46 | 47 | width: 96px; 48 | height: 96px; 49 | transform-origin: center; 50 | transform: translate(-50%, -50%); 51 | 52 | perspective: 600px; 53 | } 54 | 55 | } 56 | 57 | :host button.modal-action-button { 58 | width: 126px; 59 | height: 32px; 60 | border-radius: 0; 61 | border: 0; 62 | background: #48B2E8; 63 | color: #ffffff; 64 | cursor: pointer; 65 | } 66 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-api-process-status/test/mb-api-process-status.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-api-process-status', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-api-process-status'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-api-process-status/test/mb-api-process-status.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbApiProcessStatus } from '../mb-api-process-status'; 7 | 8 | describe('mb-api-process-status', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbApiProcessStatus], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-button-classic/mb-button-classic.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/globals-sass"; 6 | 7 | :host { 8 | box-sizing: border-box; 9 | display: block; 10 | 11 | button { 12 | display: block; 13 | border: none; 14 | 15 | margin: 0; 16 | padding: 7px 16px; 17 | 18 | color: var(--mb-component-button-classic-text-color); 19 | background: var(--mb-component-button-classic-background); 20 | border: 1px solid var(--mb-component-button-classic-background); 21 | 22 | border-radius: var(--mb-component-button-classic-border-radius); 23 | 24 | font-family: var(--mb-font-family); 25 | font-size: var(--mb-component-button-classic-font-size); 26 | font-weight: var(--mb-component-button-classic-font-weight); 27 | 28 | &:not([disabled]) { 29 | cursor: pointer; 30 | } 31 | 32 | &[disabled] { 33 | opacity: 0.5; 34 | pointer-events: none; 35 | } 36 | } 37 | } 38 | 39 | :host(.inverted) { 40 | a { 41 | background-color: white; 42 | color: var(--mb-component-button-classic-inverted-text-color); 43 | border: 1px solid var(--mb-component-button-classic-inverted-border-color); 44 | } 45 | 46 | a:hover, 47 | a:active, 48 | a:focus { 49 | cursor: pointer; 50 | background-color: var(--mb-component-button-classic-inverted-hover-background); 51 | } 52 | 53 | a:focus { 54 | border-color: var(--mb-component-button-classic-focused-border-color); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-button-classic/mb-button-classic.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { 6 | Component, 7 | Element, 8 | Host, 9 | h, 10 | Prop 11 | } from '@stencil/core'; 12 | 13 | import { setWebComponentParts } from '../../../utils/generic.helpers'; 14 | 15 | @Component({ 16 | tag: 'mb-button-classic', 17 | styleUrl: 'mb-button-classic.scss', 18 | shadow: true, 19 | }) 20 | export class MbButtonClassic { 21 | 22 | /** 23 | * Set to 'true' if button should be inverted style. 24 | */ 25 | @Prop() inverted: boolean = false; 26 | 27 | /** 28 | * Set to 'true' if button should be disabled, and if click events should not be triggered. 29 | */ 30 | @Prop() disabled: boolean = false; 31 | 32 | /** 33 | * Set to 'true' if default event should be prevented. 34 | */ 35 | @Prop() preventDefault: boolean = false; 36 | 37 | /** 38 | * Event which is triggered when user clicks on button element. This event is not triggered 39 | * when the button is disabled. 40 | */ 41 | 42 | /** Function to call on click */ 43 | @Prop() clickHandler!: (ev: UIEvent) => void; 44 | 45 | /** 46 | * Host element as variable for manipulation 47 | */ 48 | @Element() hostEl: HTMLElement; 49 | 50 | connectedCallback() { 51 | setWebComponentParts(this.hostEl); 52 | } 53 | 54 | render() { 55 | return ( 56 | 57 | 60 | 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-button-classic/test/mb-button-classic.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-button-classic', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-button-classic'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-button-classic/test/mb-button-classic.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbButtonClassic } from '../mb-button-classic'; 7 | 8 | describe('mb-button-classic', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbButtonClassic], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-button/mb-button.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/globals-sass"; 6 | 7 | :host { 8 | box-sizing: border-box; 9 | display: none; 10 | } 11 | 12 | button { 13 | display: grid; 14 | place-items: center; 15 | position: relative; 16 | 17 | width: calc(var(--mb-component-button-size) - 2 * var(--mb-component-button-border-width)); 18 | height: calc(var(--mb-component-button-size) - 2 * var(--mb-component-button-border-width)); 19 | padding: 0; 20 | 21 | background-color: var(--mb-component-button-background); 22 | border-color: var(--mb-component-button-border-color); 23 | 24 | border-radius: var(--mb-component-button-border-radius); 25 | border-style: var(--mb-component-button-border-style); 26 | border-width: var(--mb-component-button-border-width); 27 | 28 | box-shadow: var(--mb-component-button-box-shadow); 29 | 30 | text-decoration: none; 31 | appearance: none; 32 | cursor: pointer; 33 | 34 | > * { 35 | user-select: none; 36 | pointer-events: none; 37 | } 38 | 39 | .icon-active { 40 | display: none; 41 | } 42 | 43 | &:focus-visible { 44 | border-color: var(--mb-component-button-border-color--visible); 45 | } 46 | 47 | &:hover, &:active { 48 | border-color: var(--mb-component-button-border-color-hover); 49 | 50 | .icon-active { 51 | display: block; 52 | } 53 | 54 | .icon-default { 55 | display: none; 56 | } 57 | } 58 | 59 | &:active { 60 | box-shadow: 0px 1px 6px rgba(0, 0, 0, 0.3); 61 | } 62 | 63 | &[disabled] { 64 | border-color: var(--mb-component-button-border-color-disabled); 65 | box-shadow: var(--mb-component-button-box-shadow-disabled); 66 | pointer-events: none; 67 | cursor: default; 68 | 69 | &::before { 70 | opacity: 0.5; 71 | } 72 | } 73 | } 74 | 75 | :host(.visible) { 76 | display: flex; 77 | flex-direction: column; 78 | align-items: center; 79 | } 80 | 81 | :host(.selected) { 82 | button { 83 | background-color: var(--mb-component-button-background-selected); 84 | border-color: var(--mb-component-button-border-color-selected); 85 | } 86 | } 87 | 88 | /** 89 | * Action buttons 90 | */ 91 | 92 | label { 93 | cursor: inherit; 94 | } 95 | 96 | /** 97 | * Action labels 98 | */ 99 | span { 100 | display: block; 101 | padding-top: $padding-unit-medium; 102 | 103 | font-size: var(--mb-component-font-size); 104 | font-weight: var(--mb-font-weight); 105 | line-height: var(--mb-line-height); 106 | 107 | color: var(--mb-feedback-font-color-info); 108 | } 109 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-button/mb-button.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { 6 | Component, 7 | Element, 8 | Host, 9 | h, 10 | Prop, 11 | } from '@stencil/core'; 12 | 13 | import { setWebComponentParts, classNames } from '../../../utils/generic.helpers'; 14 | 15 | @Component({ 16 | tag: 'mb-button', 17 | styleUrl: 'mb-button.scss', 18 | shadow: true, 19 | }) 20 | export class MbButton { 21 | 22 | /** Function to call on click */ 23 | @Prop() clickHandler!: (ev: UIEvent) => void; 24 | 25 | /** 26 | * Set to 'true' if button should be disabled, and if click events should not be triggered. 27 | */ 28 | @Prop() disabled: boolean = false; 29 | 30 | /** 31 | * Set to 'true' if button should be visible. 32 | */ 33 | @Prop() visible: boolean = false; 34 | 35 | /** 36 | * Set to 'true' if button should enter 'selected' state. 37 | */ 38 | @Prop() selected: boolean = false; 39 | 40 | /** 41 | * Passed image from parent component. 42 | */ 43 | @Prop() imageSrcDefault!: string; 44 | 45 | /** 46 | * Passed image from parent component. 47 | */ 48 | @Prop() imageSrcActive!: string; 49 | 50 | /** 51 | * Passed description text for image element from parent component. 52 | */ 53 | @Prop() imageAlt: string = ''; 54 | 55 | /** 56 | * Set to string which should be displayed below the icon. 57 | * 58 | * If omitted, nothing will show. 59 | */ 60 | @Prop() label: string = ''; 61 | 62 | @Prop() buttonTitle!: string; 63 | 64 | /** 65 | * Host element as variable for manipulation 66 | */ 67 | @Element() hostEl: HTMLElement; 68 | 69 | connectedCallback() { 70 | setWebComponentParts(this.hostEl); 71 | } 72 | 73 | render() { 74 | return ( 75 | 81 | 85 | {this.label !== "" && {this.label}} 86 | 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-button/test/mb-button.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-button', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-button'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-button/test/mb-button.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbButton } from '../mb-button'; 7 | 8 | describe('mb-button', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbButton], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-experience/mb-camera-experience.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { CameraExperienceState } from '../../../utils/data-structures'; 6 | 7 | function getStateClass(state: CameraExperienceState): string { 8 | let stateClass = 'is-default'; 9 | 10 | switch (state) { 11 | case CameraExperienceState.Classification: 12 | stateClass = 'is-classification'; 13 | break; 14 | 15 | case CameraExperienceState.Default: 16 | stateClass = 'is-default'; 17 | break; 18 | 19 | case CameraExperienceState.Detection: 20 | stateClass = 'is-detection'; 21 | break; 22 | 23 | case CameraExperienceState.MoveFarther: 24 | stateClass = 'is-error-move-farther'; 25 | break; 26 | 27 | case CameraExperienceState.MoveCloser: 28 | stateClass = 'is-error-move-closer'; 29 | break; 30 | 31 | case CameraExperienceState.AdjustAngle: 32 | stateClass = 'is-error-adjust-angle'; 33 | break; 34 | 35 | case CameraExperienceState.Flip: 36 | stateClass = 'is-flip'; 37 | break; 38 | 39 | case CameraExperienceState.Done: 40 | stateClass = 'is-done'; 41 | break; 42 | 43 | case CameraExperienceState.DoneAll: 44 | stateClass = 'is-done-all'; 45 | break; 46 | 47 | default: 48 | // Reset class 49 | } 50 | 51 | return stateClass; 52 | } 53 | 54 | export { getStateClass }; 55 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-experience/test/mb-camera-experience.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-camera-experience', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-camera-experience'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-experience/test/mb-camera-experience.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbCameraExperience } from '../mb-camera-experience'; 7 | 8 | describe('mb-camera-experience', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbCameraExperience], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-selection/mb-camera-selection.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/_globals-sass"; 6 | 7 | :host { 8 | * { 9 | box-sizing: border-box; 10 | } 11 | 12 | display: block; 13 | font-family: inherit; 14 | font-size: var(--mb-font-size); 15 | 16 | .active-camera { 17 | all: unset; 18 | box-sizing: border-box; 19 | display: block; 20 | 21 | // Width + border 22 | width: var(--mb-toolbar-selection-width); 23 | 24 | // Line height + padding + border 25 | height: calc(var(--mb-line-height) + #{ $padding-unit-small * 2 } + 2px); 26 | 27 | margin: 0 auto; 28 | 29 | color: var(--mb-toolbar-color); 30 | line-height: var(--mb-line-height); 31 | 32 | text-align: center; 33 | text-decoration: none; 34 | 35 | border: 1px solid transparent; 36 | border-radius: var(--mb-toolbar-border-radius); 37 | 38 | .icon, 39 | .name { 40 | display: inline-block; 41 | vertical-align: middle; 42 | } 43 | 44 | .icon { 45 | width: 20px; 46 | height: 20px; 47 | 48 | svg { 49 | width: 20px; 50 | height: 20px; 51 | } 52 | } 53 | 54 | .name { 55 | // width = 100% - padding width - 2 * width of an icon 56 | max-width: calc(100% - #{ 2 * $padding-unit-medium } - 40px); 57 | 58 | font-weight: var(--mb-toolbar-camera-name-font-weight); 59 | 60 | padding: 0 $padding-unit-medium 0 $padding-unit-small; 61 | 62 | overflow: hidden; 63 | text-overflow: ellipsis; 64 | white-space: nowrap; 65 | } 66 | 67 | // States 68 | & { 69 | padding: $padding-unit-small $padding-unit-large; 70 | background-color: transparent; 71 | } 72 | 73 | &:hover, 74 | &:active, 75 | &:focus { 76 | background-color: rgba(map-get(map-get(map-get($base-colors, text-secondary), onlight), foreground), 0.3); 77 | } 78 | 79 | &.active, 80 | &:active, 81 | &:focus { 82 | padding: $padding-unit-small $padding-unit-large; 83 | border-color: var(--mb-toolbar-border-color); 84 | } 85 | } 86 | 87 | #list-background { 88 | display: none; 89 | 90 | position: fixed; 91 | top: 0; 92 | left: 0; 93 | 94 | width: 100vw; 95 | height: 100vh; 96 | 97 | &.visible { 98 | display: block; 99 | } 100 | } 101 | 102 | .list { 103 | display: none; 104 | 105 | position: absolute; 106 | top: calc(var(--mb-font-size) * 1.5 + #{ $padding-unit-small * 2 * 2 }); 107 | left: calc(50% - var(--mb-toolbar-selection-width) / 2); 108 | 109 | width: var(--mb-toolbar-selection-width); 110 | 111 | padding: 0; 112 | 113 | background-color: var(--mb-toolbar-list-background); 114 | border-radius: var(--mb-toolbar-border-radius); 115 | box-shadow: var(--mb-toolbar-list-shadow); 116 | 117 | &.visible { 118 | display: block; 119 | } 120 | 121 | svg, 122 | .name, 123 | .spacer { 124 | display: inline-block; 125 | vertical-align: middle; 126 | } 127 | 128 | .spacer, 129 | svg { 130 | width: 24px; 131 | height: 20px; 132 | } 133 | 134 | .name { 135 | max-width: calc(100% - 24px); 136 | 137 | overflow: hidden; 138 | text-overflow: ellipsis; 139 | } 140 | 141 | ul { 142 | margin: 0; 143 | padding: $padding-unit-medium; 144 | 145 | border-radius: var(--mb-toolbar-list-border-radius); 146 | 147 | list-style: none; 148 | 149 | li { 150 | display: block; 151 | &.active { 152 | color: map-get(map-get(map-get($base-colors, primary-blue), onlight), background); 153 | } 154 | } 155 | 156 | button { 157 | all: unset; 158 | box-sizing: border-box; 159 | display: block; 160 | width: 100%; 161 | appearance: none; 162 | 163 | border-radius: var(--mb-toolbar-list-item-border-radius); 164 | 165 | padding: $padding-unit-small $padding-unit-large; 166 | line-height: var(--mb-line-height); 167 | cursor: pointer; 168 | 169 | &:hover, 170 | &:focus { 171 | background-color: rgba(map-get(map-get(map-get($base-colors, fill-quaternary), onlight), foreground), 0.08); 172 | } 173 | } 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-selection/test/mb-camera-selection.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-camera-selection', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-camera-selection'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-selection/test/mb-camera-selection.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbCameraSelection } from '../mb-camera-selection'; 7 | 8 | describe('mb-camera-selection', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbCameraSelection], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-toolbar/mb-camera-toolbar.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/_globals-sass"; 6 | 7 | :host { 8 | position: absolute; 9 | top: 0; 10 | left: 0; 11 | right: 0; 12 | 13 | background-color: rgba(map-get(map-get(map-get($base-colors, text-secondary), onlight), foreground), 0.7); 14 | -webkit-backdrop-filter: blur(var(--mb-blur-filter)); 15 | backdrop-filter: blur(var(--mb-blur-filter)); 16 | 17 | header { 18 | display: flex; 19 | height: 44px; 20 | align-items: center; 21 | padding-inline: #{ $padding-unit-large * 2 }; 22 | } 23 | 24 | header > * { 25 | display: block; 26 | flex-grow: 1; 27 | } 28 | 29 | .camera-selection-wrapper { 30 | position: relative; 31 | } 32 | 33 | mb-camera-selection { 34 | display: none; 35 | 36 | &.visible { 37 | display: block; 38 | } 39 | } 40 | } 41 | 42 | // TODO: see if breakpoints are actually required in the toolbar 43 | @media only screen and (min-width: $breakpoint-width-laptop-1280) { 44 | :host { 45 | header { 46 | max-width: 1024px; 47 | margin: 0 auto; 48 | padding-left: 0; 49 | padding-right: 0; 50 | } 51 | } 52 | } 53 | 54 | /** 55 | * Toolbar buttons 56 | */ 57 | $button-size: 40px; 58 | 59 | :host { 60 | .toolbar-button { 61 | all: unset; 62 | appearance: none; 63 | cursor: pointer; 64 | width: $button-size; 65 | height: $button-size; 66 | box-sizing: border-box; 67 | border-radius: var(--mb-toolbar-border-radius); 68 | display: grid; 69 | place-content: center; 70 | 71 | svg { 72 | filter: drop-shadow(0px 1px 4px rgba(0, 0, 0, 0.4)); 73 | } 74 | 75 | &:hover { 76 | background-color: rgba(map-get(map-get(map-get($base-colors, text-secondary), onlight), foreground), 0.3); 77 | box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.1); 78 | } 79 | 80 | &:focus, 81 | &:active { 82 | box-shadow: 0 0 0 1px var(--mb-toolbar-border-color); 83 | } 84 | } 85 | 86 | .flip-button { 87 | transform-style: preserve-3d; 88 | perspective: 600px; 89 | transition: transform 800ms; 90 | z-index: 1; 91 | 92 | &.flipped { 93 | transform: rotateY(180deg); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-toolbar/test/mb-camera-toolbar.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | import { newE2EPage } from '@stencil/core/testing'; 5 | 6 | describe('mb-camera-toolbar', () => { 7 | it('renders', async () => { 8 | const page = await newE2EPage(); 9 | await page.setContent(''); 10 | 11 | const element = await page.find('mb-camera-toolbar'); 12 | expect(element).toHaveClass('hydrated'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-camera-toolbar/test/mb-camera-toolbar.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | import { newSpecPage } from '@stencil/core/testing'; 5 | import { MbCameraToolbar } from '../mb-camera-toolbar'; 6 | 7 | describe('mb-camera-toolbar', () => { 8 | it('renders', async () => { 9 | const page = await newSpecPage({ 10 | components: [MbCameraToolbar], 11 | html: ``, 12 | }); 13 | expect(page.root).toEqualHtml(` 14 | 15 | 16 | 17 | 18 | 19 | `); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-completed/mb-completed.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/_globals-sass"; 6 | 7 | :host { 8 | display: block; 9 | 10 | padding: 0; 11 | 12 | img { 13 | display: block; 14 | width: 24px; 15 | height: 24px; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-completed/mb-completed.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { 6 | Component, 7 | Element, 8 | Host, 9 | h, 10 | Prop 11 | } from '@stencil/core'; 12 | 13 | import { setWebComponentParts } from '../../../utils/generic.helpers'; 14 | 15 | @Component({ 16 | tag: 'mb-completed', 17 | styleUrl: 'mb-completed.scss', 18 | shadow: true, 19 | }) 20 | export class MbCompleted { 21 | 22 | /** 23 | * Value of `src` attribute for element. 24 | */ 25 | @Prop() icon: string = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjUiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNSAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMS4yMDcxIDYuMjkyODlDMjEuNTk3NiA2LjY4MzQyIDIxLjU5NzYgNy4zMTY1OCAyMS4yMDcxIDcuNzA3MTFMMTEuMjA3MSAxNy43MDcxQzEwLjgxNjYgMTguMDk3NiAxMC4xODM0IDE4LjA5NzYgOS43OTI4OSAxNy43MDcxTDQuNzkyODkgMTIuNzA3MUM0LjQwMjM3IDEyLjMxNjYgNC40MDIzNyAxMS42ODM0IDQuNzkyODkgMTEuMjkyOUM1LjE4MzQyIDEwLjkwMjQgNS44MTY1OCAxMC45MDI0IDYuMjA3MTEgMTEuMjkyOUwxMC41IDE1LjU4NThMMTkuNzkyOSA2LjI5Mjg5QzIwLjE4MzQgNS45MDIzNyAyMC44MTY2IDUuOTAyMzcgMjEuMjA3MSA2LjI5Mjg5WiIgZmlsbD0iIzAwNjJGMiIvPgo8L3N2Zz4K'; 26 | 27 | /** 28 | * Host element as variable for manipulation 29 | */ 30 | @Element() hostEl: HTMLElement; 31 | 32 | componentDidLoad() { 33 | setWebComponentParts(this.hostEl); 34 | } 35 | 36 | render() { 37 | return ( 38 | 39 | 40 | 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-completed/test/mb-completed.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-completed', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-completed'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-completed/test/mb-completed.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbCompleted } from '../mb-completed'; 7 | 8 | describe('mb-completed', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbCompleted], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-component/mb-component.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import * as BlinkIDImageCaptureSDK from '../../../../../es/blinkid-imagecapture-sdk'; 6 | 7 | function getSDKWasmType(wasmType: string): BlinkIDImageCaptureSDK.WasmType | null { 8 | switch (wasmType) { 9 | case 'BASIC': 10 | return BlinkIDImageCaptureSDK.WasmType.Basic; 11 | case 'ADVANCED': 12 | return BlinkIDImageCaptureSDK.WasmType.Advanced; 13 | case 'ADVANCED_WITH_THREADS': 14 | return BlinkIDImageCaptureSDK.WasmType.AdvancedWithThreads; 15 | default: 16 | return null; 17 | } 18 | } 19 | 20 | export { getSDKWasmType } 21 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-component/test/mb-component.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-component', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-component'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-component/test/mb-component.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbComponent } from '../mb-component'; 7 | 8 | describe('mb-component', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbComponent], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-container/mb-container.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | :host { 6 | display: block; 7 | min-width: 280px; 8 | width: 100%; 9 | height: 100%; 10 | 11 | font-family: var(--mb-font-family); 12 | } 13 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-container/mb-container.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { 6 | Component, 7 | Element, 8 | Host, 9 | h 10 | } from '@stencil/core'; 11 | 12 | import { setWebComponentParts } from '../../../utils/generic.helpers'; 13 | 14 | @Component({ 15 | tag: 'mb-container', 16 | styleUrl: 'mb-container.scss', 17 | shadow: true, 18 | }) 19 | export class MbContainer { 20 | 21 | /** 22 | * Host element as variable for manipulation 23 | */ 24 | @Element() hostEl: HTMLElement; 25 | 26 | componentDidLoad() { 27 | setWebComponentParts(this.hostEl); 28 | } 29 | 30 | render() { 31 | return ( 32 | 33 | 34 | 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-container/test/mb-container.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-container', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-container'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-container/test/mb-container.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbContainer } from '../mb-container'; 7 | 8 | describe('mb-container', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbContainer], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-feedback/mb-feedback.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/globals-sass"; 6 | 7 | :host { 8 | display: none; 9 | 10 | p { 11 | margin: $padding-unit-small $padding-unit-large; 12 | 13 | font-family: var(--mb-font-family); 14 | font-size: var(--mb-feedback-font-size); 15 | font-style: var(--mb-feedback-font-style); 16 | font-weight: var(--mb-feedback-font-weight); 17 | 18 | letter-spacing: var(--mb-feedback-letter-spacing); 19 | line-height: var(--mb-feedback-line-height); 20 | 21 | text-align: right; 22 | text-transform: var(--mb-feedback-text-transform); 23 | 24 | &.info { 25 | color: var(--mb-feedback-font-color-info); 26 | } 27 | 28 | &.error { 29 | color: var(--mb-feedback-font-color-error); 30 | } 31 | } 32 | } 33 | 34 | :host(.visible) { 35 | display: block; 36 | } 37 | 38 | :host([dir="rtl"]) { 39 | p { 40 | text-align: left; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-feedback/mb-feedback.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { 6 | Component, 7 | Element, 8 | Host, 9 | h, 10 | Method, 11 | Prop, 12 | State 13 | } from '@stencil/core'; 14 | 15 | import { FeedbackMessage } from '../../../utils/data-structures'; 16 | 17 | import { setWebComponentParts, classNames } from '../../../utils/generic.helpers'; 18 | 19 | import * as Utils from './mb-feedback.utils'; 20 | 21 | @Component({ 22 | tag: 'mb-feedback', 23 | styleUrl: 'mb-feedback.scss', 24 | shadow: true, 25 | }) 26 | export class MbFeedback { 27 | 28 | @State() paragraphClassName: string; 29 | 30 | @State() paragraphValue: string; 31 | 32 | /** 33 | * Set to 'true' if component should be visible. 34 | */ 35 | @Prop() visible: boolean = false; 36 | 37 | /** 38 | * Call when FeedbackMessage which should be displayed. 39 | */ 40 | @Method() 41 | async show(feedback: FeedbackMessage) { 42 | this.paragraphValue = feedback.message; 43 | this.paragraphClassName = Utils.getFeedbackClassName(feedback.state); 44 | } 45 | 46 | /** 47 | * Host element as variable for manipulation 48 | */ 49 | @Element() hostEl: HTMLElement; 50 | 51 | componentDidLoad() { 52 | setWebComponentParts(this.hostEl); 53 | } 54 | 55 | render() { 56 | return ( 57 | 58 |

{ this.paragraphValue }

59 |
60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-feedback/mb-feedback.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | function getFeedbackClassName(state: 'FEEDBACK_ERROR' | 'FEEDBACK_INFO' | 'FEEDBACK_OK'): string { 6 | switch (state) { 7 | case 'FEEDBACK_ERROR': 8 | return 'error'; 9 | 10 | case 'FEEDBACK_INFO': 11 | return 'info'; 12 | 13 | default: 14 | return ''; 15 | } 16 | } 17 | 18 | export { getFeedbackClassName } 19 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-feedback/test/mb-feedback.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-feedback', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-feedback'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-feedback/test/mb-feedback.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbFeedback } from '../mb-feedback'; 7 | 8 | describe('mb-feedback', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbFeedback], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-image-box/mb-image-box.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/globals-sass"; 6 | 7 | :host { 8 | display: block; 9 | 10 | padding: $padding-unit-medium; 11 | 12 | border: var(--mb-component-image-box-border-width) solid var(--mb-component-image-box-border-color); 13 | border-radius: var(--mb-component-image-box-border-radius); 14 | 15 | .label { 16 | margin: 0; 17 | padding: 0 0 $padding-unit-small 0; 18 | 19 | height: var(--mb-component-image-box-label-height); 20 | line-height: var(--mb-component-image-box-label-height); 21 | 22 | color: var(--mb-component-image-box-label-color); 23 | 24 | font-family: var(--mb-font-family); 25 | font-size: var(--mb-component-image-box-label-font-size); 26 | font-weight: var(--mb-component-image-box-label-font-weight); 27 | } 28 | 29 | .cta { 30 | all: unset; 31 | box-sizing: border-box; 32 | display: block; 33 | height: var(--mb-component-image-box-cta-height); 34 | 35 | color: var(--mb-component-image-box-cta-color); 36 | 37 | text-decoration: none; 38 | 39 | font-family: var(--mb-font-family); 40 | font-size: var(--mb-component-image-box-cta-font-size); 41 | font-weight: var(--mb-component-image-box-cta-font-weight); 42 | 43 | .cta-label, 44 | svg { 45 | vertical-align: middle; 46 | } 47 | 48 | .cta-label { 49 | display: inline-block; 50 | 51 | max-width: calc(100% - #{$padding-unit-medium + 20px}); 52 | height: var(--mb-component-image-box-cta-label-height); 53 | line-height: var(--mb-component-image-box-cta-label-height); 54 | 55 | margin: 0; 56 | padding: 0 $padding-unit-medium 0 0; 57 | 58 | &.filename { 59 | max-width: unset; 60 | width: calc(100% - 20px); 61 | padding: 0; 62 | color: var(--mb-component-image-box-file-color); 63 | font-weight: var(--mb-component-image-box-file-font-weight); 64 | 65 | text-overflow: ellipsis; 66 | overflow: hidden; 67 | } 68 | } 69 | 70 | svg { 71 | display: none; 72 | 73 | width: 20px; 74 | height: 20px; 75 | margin: 0; 76 | 77 | &.visible { 78 | display: inline-block; 79 | } 80 | } 81 | } 82 | } 83 | 84 | :host input[type="file"] { 85 | position: absolute; 86 | width: 0; 87 | height: 0; 88 | opacity: 0; 89 | clip: rect(1px, 1px, 1px, 1px); 90 | } 91 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-image-box/test/mb-image-box.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-image-box', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-image-box'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-image-box/test/mb-image-box.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbImageBox } from '../mb-image-box'; 7 | 8 | describe('mb-image-box', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbImageBox], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-modal/mb-modal.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | :host { 6 | position: absolute; 7 | top: 0; 8 | left: 0; 9 | right: 0; 10 | bottom: 0; 11 | opacity: 0; 12 | 13 | visibility: hidden; 14 | 15 | display: flex; 16 | justify-content: center; 17 | align-items: flex-start; 18 | overflow: hidden; 19 | overflow-y: auto; 20 | padding: 24px; 21 | 22 | .mb-modal { 23 | width: 100%; 24 | 25 | border-radius: var(--mb-modal-border-radius); 26 | 27 | position: relative; 28 | background-color: var(--mb-modal-background); 29 | color: var(--mb-component-font-color); 30 | 31 | .inner { 32 | padding: 24px; 33 | } 34 | 35 | .footer { 36 | padding: 24px; 37 | background-color: rgba(116, 116, 128, 0.08); 38 | } 39 | 40 | .close-wrapper { 41 | position: absolute; 42 | right: 24px; 43 | top: 24px; 44 | cursor: pointer; 45 | 46 | svg { 47 | width: 20px; 48 | height: 20px; 49 | } 50 | } 51 | 52 | .back-wrapper { 53 | position: absolute; 54 | left: 24px; 55 | top: 20px; 56 | cursor: pointer; 57 | 58 | svg { 59 | width: 20px; 60 | height: 20px; 61 | } 62 | } 63 | 64 | .title { 65 | text-align: center; 66 | font-weight: 400; 67 | font-size: var(--mb-modal-title-font-size); 68 | line-height: var(--mb-modal-title-line-height); 69 | } 70 | 71 | .content { 72 | margin: 24px 0; 73 | font-weight: 400; 74 | font-size: var(--mb-modal-content-font-size); 75 | line-height: var(--mb-modal-content-line-height); 76 | 77 | &.centered { 78 | text-align: center; 79 | } 80 | } 81 | 82 | .actions { 83 | display: flex; 84 | justify-content: center; 85 | 86 | button { 87 | width: 126px; 88 | height: 32px; 89 | border-radius: 0; 90 | border: 0; 91 | background: #48B2E8; 92 | color: #ffffff; 93 | cursor: pointer; 94 | } 95 | } 96 | } 97 | } 98 | 99 | :host(.visible) { 100 | visibility: visible; 101 | opacity: 1; 102 | } 103 | 104 | :host(.elevated) { 105 | .mb-modal { 106 | box-shadow: 0px 2px 24px 0px #0000001A; 107 | box-shadow: 0px 2px 8px 0px #0000000D; 108 | } 109 | } 110 | 111 | :host(.centered) { 112 | align-items: center; 113 | justify-content: center; 114 | } -------------------------------------------------------------------------------- /ui/src/components/shared/mb-modal/test/mb-modal.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-modal', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-modal'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-modal/test/mb-modal.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbModal } from '../mb-modal'; 7 | 8 | describe('mb-modal', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbModal], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-overlay/mb-overlay.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/globals-sass"; 6 | 7 | :host { 8 | display: block; 9 | width: 100%; 10 | height: 100%; 11 | 12 | position: fixed; 13 | top: 0; 14 | left: 0; 15 | z-index: -1; 16 | 17 | opacity: 0; 18 | border-radius: 0px; 19 | 20 | visibility: hidden; 21 | overflow: hidden; 22 | 23 | background-color: transparent; 24 | border-style: none; 25 | border-color: transparent; 26 | 27 | transform: translate(0, 0); 28 | transform-origin: center; 29 | 30 | transition: background-color 0.2s ease 0.4s, 31 | border-style 0.2s ease 0.4s, 32 | border-color 0.2s ease 0.4s, 33 | opacity 0.2s ease 0.4s, 34 | visibility 0.1s ease 0.5s, 35 | z-index 0.7s; 36 | } 37 | 38 | :host(.visible) { 39 | z-index: 200; 40 | 41 | visibility: visible; 42 | opacity: 1; 43 | 44 | background-color: transparent; 45 | 46 | transform: translate(0, 0); 47 | 48 | transition: opacity 0.2s ease, visibility 0.1s ease; 49 | } 50 | 51 | :host(.non-fullscreen) { 52 | width: auto; 53 | height: auto; 54 | 55 | position: absolute; 56 | 57 | top: calc(0px - var(--mb-component-border-width)); 58 | bottom: calc(0px - var(--mb-component-border-width)); 59 | left: calc(0px - var(--mb-component-border-width)); 60 | right: calc(0px - var(--mb-component-border-width)); 61 | } 62 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-overlay/mb-overlay.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { 6 | Component, 7 | Element, 8 | Host, 9 | h, 10 | Prop 11 | } from '@stencil/core'; 12 | 13 | import { setWebComponentParts, classNames } from '../../../utils/generic.helpers'; 14 | 15 | @Component({ 16 | tag: 'mb-overlay', 17 | styleUrl: 'mb-overlay.scss', 18 | shadow: true, 19 | }) 20 | export class MbOverlay { 21 | 22 | /** 23 | * Set to 'false' if overlay should not cover whole screen. 24 | */ 25 | @Prop() fullscreen: boolean = true; 26 | 27 | /** 28 | * Set to 'true' if overlay should be visible. 29 | */ 30 | @Prop() visible: boolean = false; 31 | 32 | /** 33 | * Host element as variable for manipulation 34 | */ 35 | @Element() hostEl: HTMLElement; 36 | 37 | componentDidLoad() { 38 | setWebComponentParts(this.hostEl); 39 | } 40 | 41 | getHostClassNames(): string { 42 | const classNames = []; 43 | 44 | this.hostEl.classList.forEach((value) => { 45 | if (value !== 'visible' && value !== 'non-fullscreen') { 46 | classNames.push(value); 47 | } 48 | }); 49 | 50 | return classNames.join(' '); 51 | } 52 | 53 | render() { 54 | return ( 55 | 56 | 57 | 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-overlay/test/mb-overlay.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-overlay', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-overlay'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-overlay/test/mb-overlay.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbOverlay } from '../mb-overlay'; 7 | 8 | describe('mb-overlay', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbOverlay], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-screen/mb-screen.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/globals-sass"; 6 | 7 | :host { 8 | box-sizing: border-box; 9 | width: 100%; 10 | height: 100%; 11 | padding: $padding-unit-medium $padding-unit-large; 12 | display: grid; 13 | } 14 | 15 | :host(:not(.visible)) { 16 | display: none !important; 17 | } 18 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-screen/mb-screen.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { 6 | Component, 7 | Element, 8 | Host, 9 | h, 10 | Prop 11 | } from '@stencil/core'; 12 | 13 | import { setWebComponentParts, classNames } from '../../../utils/generic.helpers'; 14 | 15 | @Component({ 16 | tag: 'mb-screen', 17 | styleUrl: 'mb-screen.scss', 18 | shadow: true, 19 | }) 20 | export class MbScreen { 21 | 22 | /** 23 | * Set to 'true' if screen should be visible. 24 | */ 25 | @Prop() visible: boolean = false; 26 | 27 | /** 28 | * Host element as variable for manipulation 29 | */ 30 | @Element() hostEl: HTMLElement; 31 | 32 | componentDidLoad() { 33 | setWebComponentParts(this.hostEl); 34 | } 35 | 36 | render() { 37 | return ( 38 | 39 | 40 | 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-screen/test/mb-screen.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-screen', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-screen'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-screen/test/mb-screen.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbScreen } from '../mb-screen'; 7 | 8 | describe('mb-screen', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbScreen], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-spinner/mb-spinner.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | @import "../styles/_globals-sass"; 6 | 7 | :host { 8 | display: block; 9 | 10 | padding: 0; 11 | 12 | img { 13 | display: block; 14 | width: 24px; 15 | height: 24px; 16 | 17 | animation: rotation 700ms linear infinite; 18 | } 19 | } 20 | 21 | :host(.large) { 22 | img { 23 | width: 100px; 24 | height: 100px; 25 | } 26 | } 27 | 28 | @keyframes rotation { 29 | 100% { 30 | transform-origin: center; 31 | transform: rotate(360deg); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-spinner/mb-spinner.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { 6 | Component, 7 | Element, 8 | Host, 9 | h, 10 | Prop 11 | } from '@stencil/core'; 12 | 13 | import { setWebComponentParts } from '../../../utils/generic.helpers'; 14 | 15 | @Component({ 16 | tag: 'mb-spinner', 17 | styleUrl: 'mb-spinner.scss', 18 | shadow: true, 19 | }) 20 | export class MbSpinner { 21 | 22 | /** 23 | * Value of `src` attribute for element. 24 | */ 25 | @Prop() icon: string = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA2IiBoZWlnaHQ9IjEwNiIgdmlld0JveD0iMCAwIDEwNiAxMDYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxjaXJjbGUgY3g9IjUzIiBjeT0iNTMiIHI9IjUwIiBzdHJva2U9IiNEQ0VBRkYiIHN0cm9rZS13aWR0aD0iNiIvPgo8cGF0aCBkPSJNMyA1M0MzIDI1LjM4NTggMjUuMzg1OCAzIDUzIDMiIHN0cm9rZT0iIzAwNjJGMiIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+Cg=='; 26 | 27 | /** 28 | * Spinner size, can be 'default' or 'large'. 29 | */ 30 | @Prop() size: string = 'default'; 31 | 32 | /** 33 | * Host element as variable for manipulation 34 | */ 35 | @Element() hostEl: HTMLElement; 36 | 37 | componentDidLoad() { 38 | setWebComponentParts(this.hostEl); 39 | } 40 | 41 | render() { 42 | return ( 43 | 44 | 45 | 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-spinner/test/mb-spinner.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-spinner', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-spinner'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-spinner/test/mb-spinner.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbSpinner } from '../mb-spinner'; 7 | 8 | describe('mb-spinner', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbSpinner], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-tooltip/mb-tooltip.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | :host { 6 | display: block; 7 | } 8 | 9 | .mb-tooltip { 10 | display: none; 11 | position: absolute; 12 | margin: 2px 40px 2px 32px; 13 | padding: 8px; 14 | font-size: 12px; 15 | line-height: 16px; 16 | color: #374151; 17 | background-color: #fff; 18 | border: 1px solid rgba(120, 120, 128, 0.2); 19 | filter: drop-shadow(0px 2px 4px rgba(31, 41, 55, 0.06)) drop-shadow(0px 4px 6px rgba(31, 41, 55, 0.1)); 20 | border-radius: 4px; 21 | 22 | &.text-center { 23 | text-align: center; 24 | } 25 | &.text-left { 26 | text-align: left; 27 | } 28 | &.text-right { 29 | text-align: right; 30 | } 31 | 32 | svg { 33 | display: block; 34 | float: left; 35 | margin: 6px 14px 6px 6px; 36 | } 37 | 38 | &::after { 39 | position: absolute; 40 | display: block; 41 | content: " "; 42 | background-color: #fff; 43 | width: 10px; 44 | height: 10px; 45 | transform: rotate(-45deg); 46 | } 47 | 48 | &.arrow-none::after { 49 | display: none; 50 | } 51 | 52 | &.arrow-left::after { 53 | left: -3px; 54 | top: calc(50% - 5px); 55 | } 56 | 57 | &.arrow-right::after { 58 | right: -3px; 59 | top: calc(50% - 5px); 60 | } 61 | 62 | &.arrow-up::after { 63 | top: -3px; 64 | left: calc(50% - 5px); 65 | } 66 | 67 | &.arrow-down::after { 68 | bottom: -3px; 69 | left: calc(50% - 5px); 70 | } 71 | 72 | &.visible { 73 | display: block; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-tooltip/mb-tooltip.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { Component, Host, h, Prop } from '@stencil/core'; 6 | 7 | @Component({ 8 | tag: 'mb-tooltip', 9 | styleUrl: 'mb-tooltip.scss', 10 | shadow: true, 11 | }) 12 | export class MbTooltip { 13 | @Prop() show: boolean; 14 | 15 | @Prop() message: string; 16 | 17 | @Prop() arrowPosition?: 'arrow-left' | 'arrow-right' | 'arrow-up' | 'arrow-down' | 'arrow-none'; 18 | 19 | @Prop() showWarningIcon?: boolean; 20 | 21 | @Prop() showInfoIcon?: boolean; 22 | 23 | @Prop() textAlign?: 'text-center' | 'text-left' | 'text-right'; 24 | 25 | @Prop() containerWidth?: string; 26 | 27 | render() { 28 | return ( 29 | 30 |

31 | {this.message} 32 |

33 |
34 | ); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-tooltip/test/mb-tooltip.e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newE2EPage } from '@stencil/core/testing'; 6 | 7 | describe('mb-tooltip', () => { 8 | it('renders', async () => { 9 | const page = await newE2EPage(); 10 | await page.setContent(''); 11 | 12 | const element = await page.find('mb-tooltip'); 13 | expect(element).toHaveClass('hydrated'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ui/src/components/shared/mb-tooltip/test/mb-tooltip.spec.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import { newSpecPage } from '@stencil/core/testing'; 6 | import { MbTooltip } from '../mb-tooltip'; 7 | 8 | describe('mb-tooltip', () => { 9 | it('renders', async () => { 10 | const page = await newSpecPage({ 11 | components: [MbTooltip], 12 | html: ``, 13 | }); 14 | expect(page.root).toEqualHtml(` 15 | 16 | 17 | 18 | 19 | 20 | `); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /ui/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BlinkID ImageCapture UI Component 7 | 8 | 9 | 49 | 50 | 51 | 52 | 53 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ui/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | export * from './components'; 6 | -------------------------------------------------------------------------------- /ui/src/utils/device.helpers.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | import * as BlinkIDImageCaptureSDK from "../../../es/blinkid-imagecapture-sdk"; 6 | 7 | export function hasVideoDevices(): Promise { 8 | return new Promise((resolve) => { 9 | if ( 10 | !window.navigator || 11 | !window.navigator.mediaDevices || 12 | typeof window.navigator.mediaDevices.enumerateDevices !== 'function' 13 | ) { 14 | resolve(false); 15 | return; 16 | } 17 | 18 | window.navigator.mediaDevices.enumerateDevices().then((devices) => { 19 | devices = devices || []; 20 | 21 | for (const device of devices) { 22 | if (device && device.kind === 'videoinput') { 23 | resolve(true); 24 | return; 25 | } 26 | } 27 | 28 | resolve(false); 29 | }); 30 | }); 31 | } 32 | 33 | export function isWasmSupported(): Promise { 34 | return new Promise((resolve) => { 35 | const wasmSupport = BlinkIDImageCaptureSDK.isBrowserSupported(); 36 | 37 | resolve(wasmSupport); 38 | }); 39 | } 40 | 41 | export async function checkMandatoryCapabilites(): Promise { 42 | const wasmSupport = await isWasmSupported(); 43 | 44 | return wasmSupport; 45 | } 46 | 47 | /** 48 | * Determine whether this is a desktop device based on the screen resolution. 49 | */ 50 | export function isDesktop(): boolean { 51 | return !(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)); 52 | } 53 | -------------------------------------------------------------------------------- /ui/src/utils/error-structures.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | /* eslint-disable max-len */ 6 | 7 | /** 8 | * Structures of Error Codes, Error Messages, and CustomError compatible objects for the Error Generator utility. 9 | * Error Code convention: SECTION_OBJECT_(ACTION)_PROBLEM 10 | */ 11 | 12 | export enum ErrorCodes { 13 | BrowserNotSupported = 'BROWSER_NOT_SUPPORTED', 14 | LicenseError = 'LICENSE_ERROR', 15 | SdkLoadFailed = 'SDK_LOAD_FAILED', 16 | InternetNotAvailable = 'INTERNET_NOT_AVAILABLE', 17 | InvalidRecognizers = 'INVALID_RECOGNIZERS', 18 | } 19 | 20 | 21 | export enum ErrorMessages { 22 | BrowserNotSupported = 'Browser is not supported!', 23 | LicenseError = 'Something is wrong with the license.', 24 | SdkLoadFailed = 'Failed to load SDK!', 25 | } 26 | 27 | export const componentErrors = { 28 | browserNotSupported: { 29 | code: ErrorCodes.BrowserNotSupported, 30 | message: ErrorMessages.BrowserNotSupported, 31 | }, 32 | licenseError: { 33 | code: ErrorCodes.LicenseError, 34 | message: ErrorMessages.LicenseError, 35 | }, 36 | sdkLoadFailed: { 37 | code: ErrorCodes.SdkLoadFailed, 38 | message: ErrorMessages.SdkLoadFailed, 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /ui/src/utils/generic.helpers.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | export function stringToArray(inputString: string): Array { 5 | if (!inputString || !inputString.length) { 6 | return []; 7 | } 8 | 9 | return inputString.split(',').map(el => el.trim()); 10 | } 11 | 12 | export function stringToObject(inputString: string): { [key: string]: any } { 13 | if (!inputString || !inputString.length) { 14 | return {}; 15 | } 16 | 17 | return JSON.parse(inputString); 18 | } 19 | 20 | export function hasSupportedImageFiles(files: FileList): boolean { 21 | const imageRegex = RegExp(/^image\//); 22 | 23 | for (let i = 0; i < files.length; ++i) { 24 | if (imageRegex.exec(files[i].type)) { 25 | return true; 26 | } 27 | } 28 | 29 | return false; 30 | } 31 | 32 | export function extractFilenameFromPath(path: string): string { 33 | return path.split('\\').pop(); 34 | } 35 | 36 | export function getImageFile(fileList: FileList): File|null { 37 | if (fileList === null) { 38 | return null; 39 | } 40 | 41 | let image = null; 42 | const imageRegex = RegExp(/^image\//); 43 | 44 | for (let i = 0; i < fileList.length; ++i) { 45 | if (imageRegex.exec(fileList[i].type)) { 46 | image = fileList[i]; 47 | } 48 | } 49 | 50 | return image; 51 | } 52 | 53 | /** 54 | * Inspired by https://github.com/JedWatson/classnames. 55 | * @param classes Class names and their conditions. 56 | * @returns Joined string of class names. 57 | */ 58 | export function classNames(classes: Record) { 59 | const result = []; 60 | const keys = Object.keys(classes); 61 | 62 | keys.forEach((key) => { 63 | if (classes[key]) { 64 | result.push(key); 65 | } 66 | }); 67 | 68 | return result.join(' '); 69 | } 70 | 71 | /** 72 | * @param root shadowroot to apply the query from 73 | * @returns array of part selectors 74 | */ 75 | export function getWebComponentParts(root: ShadowRoot): string[] { 76 | const nodesWithPart = root.querySelectorAll('[part]'); 77 | 78 | const parts = new Set(); 79 | 80 | nodesWithPart.forEach((el: Element) => { 81 | const partsArray = el.getAttribute('part').split(' '); 82 | partsArray.forEach(partName => parts.add(partName)) 83 | }); 84 | 85 | return [...parts]; 86 | } 87 | 88 | export function getWebComponentExportedParts(root: ShadowRoot): string[] { 89 | const nodesWithPart = root.querySelectorAll('[exportparts]'); 90 | 91 | const exportedParts = new Set(); 92 | 93 | nodesWithPart.forEach((el: Element) => { 94 | const exportedPartsArray = el.getAttribute('exportparts').split(' '); 95 | exportedPartsArray.forEach(partName => exportedParts.add(partName)) 96 | }); 97 | 98 | return [...exportedParts]; 99 | } 100 | 101 | export function setWebComponentParts(hostEl: Element): void { 102 | const partParts = [ 103 | hostEl.tagName.toLowerCase(), 104 | hostEl.getAttribute('id') 105 | ]; 106 | hostEl.setAttribute('part', partParts.join(' ').trim() ); 107 | } 108 | 109 | export function uuidv4(): string { 110 | return ( ( [1e7] as any )+-1e3+-4e3+-8e3+-1e11 ).replace( /[018]/g, ( c: any ) => 111 | ( c ^ crypto.getRandomValues( new Uint8Array( 1 ) )[0] & 15 >> c / 4 ).toString( 16 ) 112 | ); 113 | } 114 | -------------------------------------------------------------------------------- /ui/src/utils/translation.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | 5 | export const defaultTranslations: { [key: string]: string|Array } = { 6 | 7 | 8 | 'action-alt-camera': 'Device camera', 9 | 'action-alt-gallery': 'From gallery', 10 | 'action-message': 'Scan or choose from gallery', 11 | 'action-message-camera': 'Device camera', 12 | 'action-message-camera-disabled': 'Camera disabled', 13 | 'action-message-camera-not-allowed': 'Camera not allowed', 14 | 'action-message-camera-in-use': 'Camera in use', 15 | 'action-message-image': 'From gallery', 16 | 'action-message-image-not-supported': 'Not supported', 17 | 'camera-disabled': 'Camera disabled', 18 | 'camera-not-allowed': 'Cannot access camera.', 19 | 'camera-in-use': 'Camera is already used by another application.', 20 | 'camera-generic-error': 'Cannot access camera.', 21 | 'camera-feedback-scan-front': ['Scan the front side', 'of a document'], 22 | 'camera-feedback-scan-back': ['Scan the back side', 'of a document'], 23 | 'camera-feedback-flip': 'Flip to the back side', 24 | 'camera-feedback-barcode-message': 'Scan the barcode', 25 | 'camera-feedback-move-farther': 'Move farther', 26 | 'camera-feedback-move-closer': 'Move closer', 27 | 'camera-feedback-adjust-angle': 'Adjust the angle', 28 | 'drop-info': 'Drop image here', 29 | 'drop-error': 'Whoops, we don\'t support that image format. Please upload a JPEG or PNG file.', 30 | 'initialization-error': 'Failed to load component. Try using another device or update your browser.', 31 | 'process-image-box-first': 'Front side image', 32 | 'process-image-box-second': 'Back side image', 33 | 'process-image-box-add': 'Add image', 34 | 'process-image-upload-cta': 'Upload', 35 | 'process-image-message': 'Just a moment.', 36 | 'process-image-message-inline': 'Processing', 37 | 'process-image-message-inline-done': 'Processing done', 38 | 'process-api-message': 'Just a moment', 39 | 'process-api-retry': 'Retry', 40 | 'feedback-scan-unsuccessful-title': 'Scan unsuccessful', 41 | 'feedback-scan-unsuccessful': 'We weren\'t able to recognize your document. Please try again.', 42 | 'feedback-error-generic': 'Whoops, that didn\'t work. Please give it another go.', 43 | 'check-internet-connection': 'Check internet connection.', 44 | 'network-error': 'Network error.', 45 | 'scanning-not-available': 'Scanning not available.', 46 | 'modal-window-close': 'Close', 47 | } 48 | 49 | export class TranslationService { 50 | public translations: { [key: string]: string|Array }; 51 | 52 | constructor(alternativeTranslations?: { [key: string]: string|Array }) { 53 | this.translations = defaultTranslations; 54 | 55 | for (const key in alternativeTranslations) { 56 | if (key in defaultTranslations) { 57 | if (this.isExpectedValue(alternativeTranslations[key])) { 58 | this.translations[key] = alternativeTranslations[key]; 59 | } 60 | } 61 | } 62 | } 63 | 64 | public i(key: string): string|Array { 65 | if (this.translations[key]) { 66 | if (Array.isArray(this.translations[key])) { 67 | return JSON.parse(JSON.stringify(this.translations[key])); 68 | } 69 | return this.translations[key]; 70 | } 71 | } 72 | 73 | private isExpectedValue(value: string | Array): boolean { 74 | if (Array.isArray(value)) { 75 | const notValidFound = value.filter(item => typeof item !== 'string'); 76 | return notValidFound.length == 0; 77 | } 78 | return typeof value === 'string'; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /ui/stencil.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microblink Ltd. All rights reserved. 3 | */ 4 | import { Config } from '@stencil/core'; 5 | import { postcss } from '@stencil/postcss'; 6 | import { sass } from '@stencil/sass'; 7 | 8 | import autoprefixer from 'autoprefixer'; 9 | 10 | export const config: Config = { 11 | namespace: 'blinkid-imagecapture-in-browser', 12 | taskQueue: 'async', 13 | outputTargets: [ 14 | { 15 | type: 'dist', 16 | esmLoaderPath: '../loader' 17 | }, 18 | { 19 | type: 'docs-readme', 20 | dir: 'docs', 21 | strict: true 22 | } 23 | ], 24 | plugins: [ 25 | sass({ 26 | // Add path to global SCSS files which should be included in every stylesheet 27 | injectGlobalPaths: [] 28 | }), 29 | postcss({ 30 | plugins: [autoprefixer()] 31 | }) 32 | ] 33 | }; 34 | -------------------------------------------------------------------------------- /ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "allowUnreachableCode": false, 5 | "declaration": false, 6 | "experimentalDecorators": true, 7 | "lib": [ 8 | "dom", 9 | "es2017" 10 | ], 11 | "moduleResolution": "node", 12 | "module": "esnext", 13 | "target": "es2017", 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "jsx": "react", 17 | "jsxFactory": "h" 18 | }, 19 | "include": [ 20 | "./src/**/*", 21 | "./types/jsx.d.ts" 22 | ], 23 | "exclude": [ 24 | "./src/components/shared/**/test", 25 | "./src/components/**/test", 26 | "./src/**/test", 27 | "./src/test" 28 | ] 29 | } 30 | --------------------------------------------------------------------------------