DOT Web Multi-Range Liveness

v7.6.1

Introduction

DOT Web Multi-Range Liveness is set of Non-ui component and Ui component web components providing a semi-passive liveness capture. Components implement advanced Multi-Range Liveness detection that combines passive liveness analysis with active challenge-response verification. The process guides users through multiple detection phases to ensure robust liveness verification while maintaining a smooth user experience.

Non-ui component is a web component that renders the video stream from an available phone or web camera to automatically capture images of a user’s face through multiple liveness detection phases. The component combines passive liveness detection with active challenge to provide comprehensive liveness verification.

Ui component is a web component that renders an overlay over video stream. Overlay includes a placeholders, camera control buttons and instructions to guide the user to position their face correctly.

Both components should always be used together, unlike DOT Web Document Auto Capture or DOT Web Face Auto Capture, Multi-Range Liveness Ui component can not be custom implemented.

Supported Browsers

DOT Web Multi-Range Liveness was tested with:

  • Chrome on desktop (Windows, Mac and Linux) and mobile (Android, iPhone)

  • Firefox on desktop (Windows, Mac and Linux) and mobile (Android)****

  • Edge on Windows

  • Safari on Mac, iPad and iPhone

  • WebView on Android*

  • SafariVC on iPad and iPhone**

  • WKWebView on iPad and iPhone***

Known issues:

* Some older Android phones can experience issues with camera stream initialization using WebRTC. Our web components will work on most of them, but camera stream could be slow and laggy. This issue is caused by device and can be experienced in any website using WebRTC in Android WebView.

** Components are tested with SafariVC on devices iPhone 7 and newer with iOS 15 or iPadOS 15 or newer. Older devices or iOS versions are not officially supported and might experience issues.

*** In order to run DOT Web Multi-Range Liveness in WKWebView on iPhone or iPad, allowsInlineMediaPlayback and mediaTypesRequiringUserActionForPlayback properties on WKWebViewConfiguration must be set to true.

**** Some older and/or low-end Android phones can experience issues with camera stream initialization using WebRTC when using Firefox browser. Our web components might display The webcam is already in use by another application error. This issue is caused by the Firefox’s implementation of initialization of camera and can be experienced in any website using WebRTC in Firefox on Android. It is recommended to use other supported browsers in those cases.

When using components on MacOS with linked iPhone (using Apple ID) and enabled Continuity Camera setting, the camera stream from the iPhone might not get streamed correctly in the case user has an active Firewall protection from third-party Antivirus software.

When using components on Safari on MacOS with linked iPhone (using Apple ID) and enabled Continuity Camera setting, there may be multiple cameras present, which might not work as expected. Switching camera until correct camera is selected fixes the issue.

Privacy and security

This component can only be used in secure contexts due to MediaDevices API used for handling camera access. A secure context is, in short, a page loaded using HTTPS or the file:/// URL scheme, or a page loaded from localhost. Before accessing any camera, the component must always get the user’s permission. Browsers may offer a once-per-domain permission feature, but they must ask at least the first time, and the user has to specifically grant ongoing permission if they choose to do so. Browsers are required to display an indicator that shows that a camera or microphone is in use. More details can be found on MDN docs.

Non-ui component

Requirements

Minimum required camera resolution for appropriate results is 720x720. Anything less is insufficient.

Initialization

DOT Web Multi-Range Liveness can be installed via NPM, yarn or pnpm

npm install @innovatrics/dot-multi-range-liveness

To manually integrate the DOT Web Multi-Range Liveness, download latest version from the Github repository. Then add following line to dependencies in your package.json:

"dependencies": {
    "@innovatrics/dot-multi-range-liveness": "file:innovatrics-dot-multi-range-liveness-[VERSION].tgz"
},

where [VERSION] is the DOT Web Multi-Range Liveness version integrated. This installs dot-multi-range-liveness as an external module that can then be used (just like any other module in the code). For example, one could do import '@innovatrics/dot-multi-range-liveness'; in the app.

Usage

Multi-Range Liveness component is a web component which uses custom HTML <x-dot-multi-range-liveness /> tag. Properties configuration needs to be passed into component after <x-dot-multi-range-liveness /> tag was rendered.

import type {
  Configuration,
  HTMLMultiRangeLivenessElement,
  OnCompleteCallbackImage
} from "@innovatrics/dot-multi-range-liveness";

import { useEffect } from "react";
import "@innovatrics/dot-multi-range-liveness";

const MultiRangeLiveness = (configuration: Configuration) => {
  useEffect(() => {
    const multiRangeHTMLElement = document.getElementById(
        "x-dot-multi-range-liveness"
    ) as HTMLMultiRangeLivenessElement | null;

    if (multiRangeHTMLElement) {
      multiRangeHTMLElement.configuration = configuration;
    }
  });

  return <x-dot-multi-range-liveness id="x-dot-multi-range-liveness" />;
};

const Page = () => {

  const handleOnComplete = (imageData: OnCompleteCallbackImage, content: Uint8Array) => {
    // ...
  };

  const handleError = (error: Error) => {
    alert(error);
  };

  return (
    <MultiRangeLiveness
      onComplete={handleOnComplete}
      onError={handleError}
      sessionToken="1111-222-333-4444"
      transactionCountingToken="provide-the-token-here"
      challengeSequence={["ONE", "THREE", "FIVE", "ZERO"]} // Challenge needs to be obtained from the API call to the Digital Identity Service
    />
  );
};

Alternatively, you can use useRef and useLayoutEffect to render a web component with its configuration.

import type {
  Configuration,
  HTMLMultiRangeLivenessElement
} from "@innovatrics/dot-multi-range-liveness";

import { useLayoutEffect, useRef } from "react";
import "@innovatrics/dot-multi-range-liveness";

const MultiRangeLiveness = (configuration: Configuration) => {
  const ref = useRef<HTMLMultiRangeLivenessElement | null>(null);

  useLayoutEffect(() => {
    const element = ref.current;

    if (element) {
      element.configuration = configuration;
    }
  }, [configuration]);

  return <x-dot-multi-range-liveness id="x-dot-multi-range-liveness" ref={ref} />;
};

iOS - Requesting DeviceMotion Permissions

To utilize the device motion sensor and provide instructions for device_pitched instruction on iOS , it’s necessary to invoke the DeviceMotionEvent.requestPermission() method and acquire user consent. This requirement is set by Apple and isn’t specific to the DOT Web Multi-Range Liveness. The method returns a promise that yields a string – either "granted" or "denied". If the user has already granted permission, the promise will resolve instantly.

Unfortunately DeviceMotionEvent.requestPermission() could only be called on a "user gesture" event, such as a button click. Requesting permission without a user gesture event isn’t feasible. Given that DOT Web Multi-Range Liveness doesn’t produce any suitable user gesture event, the method must be invoked from the parent component when a user gesture event takes place. For example, when user clicks a button "Continue to take selfie". Below is a TypeScript example illustrating the process:

type DeviceMotionEventWithPermissions = {
  requestPermission: () => Promise<PermissionState>;
} & DeviceMotionEvent;

try {
  const { requestPermission } = DeviceMotionEvent as unknown as DeviceMotionEventWithPermissions;

  if (typeof requestPermission === "function") {
    const response = await requestPermission();

    if (response === "granted") {
      // permissions granted
    } else {
      // permissions denied
    }
  }
} catch (error) {
  // handle error in standard way
}

Without this permission, the device_pitched instruction will not be available but the component will still work. Further information on this can be found in this article.

TypeScript

Declaration file is bundled inside package. To use with TypeScript, import types from @innovatrics/dot-multi-range-liveness.

import type { OnCompleteCallback, Configuration } from "@innovatrics/dot-multi-range-liveness";

Multi capture

Multi-Range Liveness component allows you to capture multiple liveness verification sequences without the need to reinitialize the webcam and detector. Component calls onComplete callback after completing all phases of the Multi-Range Liveness detection. When onComplete is called, detection is paused. Camera stream and face detector stay initialized. Component is in waiting state. You can "restart" detection by calling MultiRangeCustomEvent.CONTROL with ControlEventInstruction.CONTINUE_DETECTION instruction. See Control Events section for more details.

Hosting dot-assets files

During the initialization phase of the component, the component loads the required assets files, such as WASM binary files, javascript chunks, license etc, via HTTP fetch request. Please note that we do not provide any hosting for those files. That’s why it is essential that the customer provides the component with all files from our distribution. To do so, please:

  1. copy dot-assets directory from our distribution into your distribution every time you update to new version of the component. If you are using package manager, you can find dot-assets directory in node_modules/@innovatrics/dot-multi-range-liveness/dot-assets.

  2. copy iengine.lic (or license.lic) file into dot-assets folder in your distribution.

Please note that dot-assets files need to be hosted at the same URL as your app - same-origin. Because of that, we do not recommend using any CDN, as it will probably not function properly.

Structure of the directory in our distribution

@innovatrics/
|__ dot-multi-range-liveness/
    |__ dot-assets/ <-- copy this directory
        |__ multi-range/
            |__ wasm/
                |-- sam.wasm
                |-- sam_simd.wasm
            |-- dot-<CHUNK_HASH>.js
            ...
        |__ wasm/
            |-- dot_embedded_bg.wasm
    |-- package.json
    |-- README.md
    ...

Example of the dot-assets dir structure in integrator’s application

public/
  |__ dot-assets/ <-- do not change the name or structure of this directory (only add folders for another components when needed)
      |__ multi-range/
          |__ wasm/
              |-- sam.wasm
              |-- sam_simd.wasm
          |-- dot-<CHUNK_HASH1>.js
          |-- dot-<CHUNK_HASH2>.js
          ...
      ... <-- if you are using other components (e.g. document), the folders with assets of these components will be here (eg. document/)
      |__ wasm/
          |-- dot_embedded_bg.wasm
      |-- iengine.lic
  ...

By default, the component will try to fetch the desired files from <PROJECT_ORIGIN>/dot-assets/. This can be changed using assetsDirectoryPath property. For example, if assetsDirectoryPath=/my-directory property is provided, the component will try to fetch the desired files from <PROJECT_ORIGIN>/my-directory/dot-assets/. Please note that structure and the name of the directory must be preserved. For more information, check out our samples on Github where you can find real examples of how to host files in various technologies such as React, Angular, Vue, etc.

Please note, that if you use multiple components (e.g. Multi-Range Liveness and Document) you need to make sure, that all of the needed files are present in appropriate folders:

public/
  |__ dot-assets/ <-- do not change the name or structure of this directory (only add folders for another components when needed)
      |__ multi-range/ <-- copied from @innovatrics/dot-multi-range-liveness
          |__ wasm/
              |-- sam.wasm
              |-- sam_simd.wasm
          |-- dot-<CHUNK_HASH1>.js
          |-- dot-<CHUNK_HASH2>.js
      |__ another_component/ <-- copied from another components' node_modules
          |__ wasm/
              |-- sam.wasm
              |-- sam_simd.wasm
          |-- dot-<CHUNK_HASH1>.js
          |-- dot-<CHUNK_HASH2>.js
      ...
  ...

Troubleshooting

If you are having difficulties with hosting wasm files, check your browser console in dev tools. You should see an error message with more details about the problem. It’s also a good idea to look at the network tab in the developer tools and check that the wasm file has been loaded correctly. Please pay close attention to the actual response of the wasm load request, as an HTTP 200 status does not necessarily mean that the wasm file was loaded correctly. If you see application/wasm in response type, then wasm file was loaded correctly. If you see e.g. text/html in response type, then wasm file was not loaded correctly.

Licensing

In order to support wide adoption of the components, a free mode was developed in addition to the premium mode used by licensed customers.

Free mode

Components run in the free mode by default. This mode does not impose any feature limits, it just displays an watermark overlay over the component, to indicate not-licensed deployment. The overlay looks as on the image below:

freemium-overlay

Premium

To run components in premium mode, dot_embedded_bg.wasm and valid license files are needed. Additionally, if transaction reporting is enabled, a valid transaction token needs to be provided as a property (see transactionCountingToken in Properties). To initialize WASM binary file please follow a steps in [Hosting WASM files]. To use your license file you need to copy it to project public directory within dot-assets directory as <PROJECT_ORIGIN>/dot-assets/iengine.lic. By default, the component will try to fetch the desired license file from <PROJECT_ORIGIN>/dot-assets/iengine.lic or <PROJECT_ORIGIN>/dot-assets/license.lic*. This can be changed using assetsDirectoryPath property.

* Please note that fetching license from <PROJECT_ORIGIN>/dot-assets/license.lic by default is deprecated and will be removed in future versions. Please use <PROJECT_ORIGIN>/dot-assets/iengine.lic instead.

If one of the following steps fails, then component will run in [Freemium] mode:

  • WASM binary file not found

  • license file not found

  • license is not valid

  • transaction token is not valid or provided (if transaction reporting is enabled)

In order to obtain the license (and/or transaction token), please contact your Innovatrics’ representative.

Properties

  • function onComplete - Callback on successful completion of all liveness detection phases

  • function onError – Callback in the case that an error occurred (see Handling errors)

    • (e: Error) ⇒ void

  • Array<MultiRangeLivenessChallengeItemValues> challengeSequence – Array defining the sequence of liveness challenge items obtained from the API call to the Digital Identity Service to perform (required)

  • (Optional) string sessionToken – Unique identifier of the session

  • (Optional) string transactionCountingToken – Unique identifier for the transaction counting feature

  • (Optional) string assetsDirectoryPath - Path to the dot-assets directory

  • (Optional) HTMLElement styleTarget - Provide an alternate DOM node to inject styles. DOM node has to exist inside DOM before auto-capture component is initialized. This is useful when rendering components in a shadow DOM. By default, the styles are injected into the <head> element of the document. See [style-target] example for more details.

Callback parameters

  • object imageData

    • Blob image – Final image captured after completing all liveness phases

    • object data

      • object detection - Object contains all detection parameters and their values from all completed phases

      • object imageResolution - Width and height of the captured image

  • Uint8Array content - output for DOT Digital Identity Service

Handling errors

When an error occurs, we call onError callback with one parameter of type Error. We set name property to AutoCaptureError, and also message with more details. Component renders default UI for error state, but is not customizable, and integrator should implement own error handling. Component uses the MediaDevices API that provides access to connected media input devices like cameras and microphones. If the user denies permission to access or the webcam is not present, an error is thrown. We provide original error thrown by browser inside cause property of the error object. List of possible errors can be found on MDN docs.

Error example:

{
  name: "AutoCaptureError",
  message: "The webcam is already in use by another application",
  cause: DOMException: Could not start video source // Original error thrown by browser MediaDevices API
}

Ui component

Requirements

Both components must be wrapped in parent div with position: relative and overflow: hidden.

<div style={{position: "relative", overflow: "hidden"}}>
  <MultiRangeLivenessUi showCameraButtons/>
  <MultiRangeLiveness
      onComplete={handleOnComplete}
      onError={handleError}
      challengeSequence={["ONE", "THREE", "FIVE", "ZERO"]} // Challenge needs to be obtained from the API call to the Digital Identity Service
      transactionCountingToken="provide-the-token-here"
  />
</div>

Initialization

UI component can be installed via NPM, yarn or pnpm

npm install @innovatrics/dot-auto-capture-ui

To manually integrate UI component, download latest version from the Github repository. Add following line to dependencies in your package.json:

"dependencies": {
    "@innovatrics/dot-auto-capture-ui": "file:innovatrics-dot-auto-capture-ui-[VERSION].tgz",
}

where [VERSION] is the DOT Web Multi-Range Liveness version integrated. This installs dot-auto-capture-ui as an external module that can be used (just like any other module in the code). For example, one could do import '@innovatrics/dot-auto-capture-ui'; in the app.

Usage

Multi-Range Liveness UI component is an web component which uses custom HTML <x-dot-multi-range-liveness-ui /> tag. Properties props needs to be passed into component after <x-dot-multi-range-liveness-ui /> tag was rendered.

import type {
  MultiRangeUiProps,
  HTMLMultiRangeLivenessUiElement
} from "@innovatrics/dot-auto-capture-ui/multi-range";

import { useEffect } from "react";
import "@innovatrics/dot-auto-capture-ui/multi-range";

const MultiRangeLivenessUi = (props: MultiRangeUiProps) => {
  useEffect(() => {
    const uiElement = document.getElementById(
      "x-dot-multi-range-liveness-ui"
    ) as HTMLMultiRangeLivenessUiElement | null;

    if (uiElement) {
      uiElement.props = props;
    }
  });

  return <x-dot-multi-range-liveness-ui id="x-dot-multi-range-liveness-ui" />;
};

Alternatively, you can use useRef and useLayoutEffect to render a web component with its props.

import type {
  MultiRangeUiProps,
  HTMLMultiRangeLivenessUiElement
} from "@innovatrics/dot-auto-capture-ui/multi-range";

import { useLayoutEffect, useRef } from "react";
import "@innovatrics/dot-auto-capture-ui/multi-range";

const MultiRangeLivenessUi = (props: MultiRangeUiProps) => {
  const ref = useRef<HTMLMultiRangeLivenessUiElement | null>(null);

  useLayoutEffect(() => {
    const element = ref.current;

    if (element) {
      element.props = props;
    }
  }, [props]);

  return <x-dot-multi-range-liveness-ui id="x-dot-multi-range-liveness-ui" ref={ref} />
};

TypeScript

Declaration files are bundled inside package. Just import types from @innovatrics/dot-auto-capture-ui/multi-range.

Escalated Instructions

The Multi-Range Liveness UI component supports escalated instructions to improve user guidance when users struggle with specific positioning requirements. When a user remains in the same problematic state (such as being too close or too far from the camera) for an extended period, the component automatically escalates the instruction to provide more explicit guidance.

Currently supported escalated instructions:

  • face_too_close - Escalates to a more direct message when user’s face remains too close to the camera

  • face_too_far - Escalates to a more direct message when user’s face remains too far from the camera

Escalation helps reduce user frustration by providing clearer, more actionable feedback when the default instructions are not being followed successfully.

Properties

  • (Optional) object instructions - Modification of default messages for localization or customization

    • (Optional) ['Stay still…'] string candidate_selection - Shown when all validations are passed, i.e. the image is suitable for capture

    • (Optional) ['Move back'] string face_too_close - Shown when the face is too close to the camera

    • (Optional) ['Move closer'] string face_too_far - Shown when the face is too far from the camera

    • (Optional) ['Center your face'] string face_centering - Shown when the face is not centered in the placeholder

    • (Optional) ['Position your face into the circle'] string face_not_present - Shown when no face is detected

    • (Optional) ['Position your face into the circle'] string left_eye_not_present - Shown when left eye is not detected

    • (Optional) ['Position your face into the circle'] string right_eye_not_present - Shown when right eye is not detected

    • (Optional) ['Turn face against light'] string sharpness_too_low - Shown when the face in the image is not sharp enough

    • (Optional) ['Turn face against light'] string brightness_too_low - Shown when the image is too dark

    • (Optional) ['Less light needed'] string brightness_too_high - Shown when the image is too bright

    • (Optional) ['Hold your phone at eye level'] string device_pitched - Shown when the device is pitched too much

  • (Optional) object escalatedInstructions - Modification of default messages for escalated instructions. Escalated instructions are shown when users remain in the same problematic state for an extended period.

    • (Optional) ['Move your face back'] string face_too_close - Shown when face_too_close instruction is escalated

    • (Optional) ['Move your face closer'] string face_too_far - Shown when face_too_far instruction is escalated

  • (Optional) string backdropColor - To customize the color of the placeholder backdrop. E.g.:

    • 'rgba(10, 10, 10, 0.5)'

If you prefer not to use the backdrop, you can set the backdropColor to 'none'.

  • (Optional) theme - Modification of theme properties.

    • (Optional) colors - To customize colors of following properties

      • (Optional) ['white'] color placeholderColor - Color of the placeholder lines

      • (Optional) ['#00BFB2'] color placeholderColorSuccess - Color of the placeholder lines when all validations are passed

      • (Optional) ['white'] color instructionColor - Instruction background color

      • (Optional) ['#00BFB2'] color instructionColorSuccess - Instruction background color when all validations are passed

      • (Optional) ['black'] color instructionTextColor - Instruction text color

    • (Optional) font - To customize font with following properties

      • (Optional) ['Montserrat'] string family - Font family. Please note that the chosen font must be installed and available in the styles of the web components for it to display correctly.

      • (Optional) [14] number minimumSize - Minimum font size, from which the actual font size is calculated relative to the component width/height

      • (Optional) ['normal'] string style - Font style

      • (Optional) [600] string|number weight - Font weight

  • (Optional) appStateInstructions - Modification of default messages for component state

    • (Optional) loading - Component loading state

      • (Optional) ['Loading. Please wait.'] string text - Text shown while component is loading

      • (Optional) [true] boolean visible - Show/hide loading instruction while component is loading

    • (Optional) done - Component finished capturing image

      • (Optional) ['Waiting for input'] string text - Text shown while component is waiting

      • (Optional) [true] boolean visible - Show/hide waiting instruction while component is waiting

  • (Optional) [false] boolean showCameraButtons - Show/hide camera buttons (switch camera and toggle mirror) on top of component

  • (Optional) HTMLElement styleTarget - Provide an alternate DOM node to inject styles. DOM node has to exist inside DOM before auto-capture component is initialized. This is useful when rendering components in a shadow DOM. By default, the styles are injected into the <head> element of the document. See [style-target] example for more details.

Example how to use UI properties:

<MultiRangeLivenessUi
  theme={{ colors: { placeholderColor: "green" }, font: { style: 'italic' } }}
  backdropColor="rgba(10, 10, 10, 0.5)"
  instructions={{ candidate_selection: "Candidate selection" }}
  escalatedInstructions={{
    face_too_close: "Please step back from the camera",
    face_too_far: "Please move closer to the camera"
  }}
  appStateInstructions={{ loading: { text: "Component is loading", visible: true } }}
  showCameraButtons
/>

Example how to import fonts (using head in main html file):

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="" href="" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <!-- import font in the head -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" rel="stylesheet">
    <!------->
  </head>
</html>

Example of using components together

import type { OnCompleteCallback } from "@innovatrics/dot-multi-range-liveness";

import MultiRangeLivenessUi from "./MultiRangeLivenessUi";
import MultiRangeLiveness from "./MultiRangeLiveness";

const MultiRange = () => {
  const handleOnComplete: OnCompleteCallback = async (
    imageData,
    content,
  ) => {
    console.log(imageData.metadata, imageData.image)
  };

  const handleError = (error: Error) => {
    alert(error);
  };

  return (
    <div style={{ position: "relative", overflow: "hidden" }}>
      <MultiRangeLivenessUi showCameraButtons />
      <MultiRangeLiveness
        onComplete={handleOnComplete}
        onError={handleError}
        challengeSequence={["ONE", "THREE", "FIVE", "ZERO"]} // Challenge needs to be obtained from the API call to the Digital Identity Service
        transactionCountingToken="provide-the-token-here"
      />
    </div>
  );
};

Example how to use styleTarget prop with Ui component when using Shadow DOM: This approach also works for Non-ui component.

import type {
  MultiRangeUiProps,
  HTMLMultiRangeLivenessUiElement
} from "@innovatrics/dot-auto-capture-ui/multi-range";
import { useEffect } from "react";
import "@innovatrics/dot-auto-capture-ui/multi-range";

const MultiRangeLivenessUi = (props: MultiRangeUiProps) => {
  useEffect(() => {
    const uiElement = document.getElementById(
      "x-dot-multi-range-liveness-ui"
    ) as HTMLMultiRangeLivenessUiElement | null;

    const styleNode = document.createElement('div');

    uiElement?.shadowRoot?.append(styleNode);

    if (uiElement) {
       uiElement.props = {
        ...props,
        styleTarget: styleNode,
      };
    }
  });

  return <x-dot-multi-range-liveness-ui id="x-dot-multi-range-liveness-ui" />;
};

HTML of example above will look like this:

<x-dot-multi-range-liveness-ui id="x-dot-multi-range-liveness-ui">
  #shadow-root (open)
    <div>
      <style data-styled="active" data-styled-version="6.1.0">
        /* CSS styles will be injected here*/
      </style>
    </div>
</x-dot-multi-range-liveness-ui>

Custom Events - Optional

Communication between components is based on custom events. Ui component is mostly listening to events dispatched by Non-ui component.

Type of Events

Currently most of the events used are described in this section. You can create custom UI parts using these events.

  • enum MultiRangeCustomEvent - Event names dispatched by components

    • PHASE_CHANGED = 'multi-range-auto-capture:phase-changed' - Notifies UI when phase of Non-ui component has changed

    • INSTRUCTION_CHANGED = 'multi-range-auto-capture:instruction-changed' - Notifies UI when instruction changes

    • INSTRUCTION_ESCALATED = 'multi-range-auto-capture:instruction-escalated' - Notifies UI when an instruction becomes escalated

    • CONTROL = 'multi-range-auto-capture:control' - Events dispatched to control ui and non-ui components

    • VIDEO_ELEMENT_SIZE = 'multi-range-auto-capture:video-element-size' - Notifies UI when video element size changes

    • CAMERA_PROPS_CHANGED = 'multi-range-auto-capture:camera-props-changed' - Notifies UI when camera props change

Usage

Import '@innovatrics/dot-multi-range-liveness/events' to use event types.

Listening to the Events

All event listeners are already implemented in default Ui component. Skip this section if you are using default Ui component.

All documented MultiRangeCustomEvent events are dispatched by Non-ui component. Ui component listens to these events to make appropriate changes. See the example below how to register event listeners.

import { MultiRangeCustomEvent } from '@innovatrics/dot-multi-range-liveness/events';
import { useEffect, useState } from 'react';

const Events = () => {
  const [multiRangePhase, setMultiRangePhase] = useState<string | undefined>();
  const [instruction, setInstruction] = useState<string | undefined>();
  const [isInstructionEscalated, setIsInstructionEscalated] = useState<boolean>(false);

  useEffect(() => {
    const handlePhaseChanged = (event: CustomEvent) => {
      setMultiRangePhase(event.detail.phase);
    };

    const handleInstructionChanged = (event: CustomEvent) => {
      setInstruction(event.detail.instructionCode);
      setIsInstructionEscalated(event.detail.isEscalated || false);
    };

    // Or you can listen to the event directly
    const handleInstructionEscalated = (event: CustomEvent) => {
      console.log('Instruction escalated:', event.detail.instructionCode);
      setIsInstructionEscalated(true);
    };

    document.addEventListener(MultiRangeCustomEvent.PHASE_CHANGED, handlePhaseChanged);
    document.addEventListener(MultiRangeCustomEvent.INSTRUCTION_CHANGED, handleInstructionChanged);
    document.addEventListener(MultiRangeCustomEvent.INSTRUCTION_ESCALATED, handleInstructionEscalated);

    return () => {
      document.removeEventListener(MultiRangeCustomEvent.PHASE_CHANGED, handlePhaseChanged);
      document.removeEventListener(MultiRangeCustomEvent.INSTRUCTION_CHANGED, handleInstructionChanged);
      document.removeEventListener(MultiRangeCustomEvent.INSTRUCTION_ESCALATED, handleInstructionEscalated);
    };
  }, []);
};

Without importing @innovatrics/dot-multi-range-liveness/events you can use values of MultiRangeCustomEvent directly.

const phaseChangeEvent = "multi-range-auto-capture:phase-changed";
const instructionChangeEvent = "multi-range-auto-capture:instruction-changed";
const instructionEscalatedEvent = "multi-range-auto-capture:instruction-escalated";

function handlePhaseChange(event) {
  console.log(event.detail.phase)
}

function handleInstructionChange(event) {
  console.log(event.detail.instructionCode)
  console.log('Is escalated:', event.detail.isEscalated)
}

function handleInstructionEscalated(event) {
  console.log('Instruction escalated:', event.detail.instructionCode)
}

document.addEventListener(phaseChangeEvent, handlePhaseChange);
document.addEventListener(instructionChangeEvent, handleInstructionChange);
document.addEventListener(instructionEscalatedEvent, handleInstructionEscalated);

/**
 * remove event listeners when you're done
 */
document.removeEventListener(phaseChangeEvent, handlePhaseChange);
document.removeEventListener(instructionChangeEvent, handleInstructionChange);
document.removeEventListener(instructionEscalatedEvent, handleInstructionEscalated);

Control Events

Control events are dispatched from outside of Non-ui component to control it.

MultiRangeCustomEvent.CONTROL

Events are dispatched from Ui component to control Non-ui component.

  • enum ControlEventInstruction

    • CONTINUE_DETECTION = 'continue-detection' - Controls Multi capture

import { dispatchControlEvent, MultiRangeCustomEvent, ControlEventInstruction } from "@innovatrics/dot-multi-range-liveness/events";

export const Dispatch = () => {

  const continueDetection = () => {
    dispatchControlEvent(MultiRangeCustomEvent.CONTROL, ControlEventInstruction.CONTINUE_DETECTION)
  }

  return (
    <div>
      <button onClick={continueDetection}>Continue detection</button>
    </div>
  )
}

Without importing @innovatrics/dot-multi-range-liveness/events you can use values of MultiRangeCustomEvent and ControlEventInstruction directly.

const continueDetection = () => {
  document.dispatchEvent(
    new CustomEvent("multi-range-auto-capture:control", {
      detail: { instruction: "continue-detection" },
    }),
  );
}

Code Samples

See also DOT Web Samples showing the usage of DOT Web Auto Capture components in different front-end technologies like React, Angular…​

Appendix

Changelog

7.6.1 - 2025-10-17

  • Incremental version upgrade

7.6.0 - 2025-10-16

  • First released version