diff --git a/README.md b/README.md
index dc4fb42..0201bd5 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@
1. [Controller sample](#controller-sample)
1. [UI-components sample](#ui-components-sample)
1. [Switch to mobile sample](#switch-to-mobile-sample)
+1. [Manual multi-page sample](#manual-multi-page-sample)
1. [CodePen samples](#codepen-samples)
---
@@ -122,6 +123,14 @@ The ```switch-to-mobile``` folder contains an example of using Document reader c
Follow the steps as in [Webpack sample](#webpack-sample).
+## Manual multi-page sample
+
+The ```manual-multi-page``` folder contains an example of using Document reader component for manual control of document page scanning.
+
+### Example installation
+
+Follow the steps as in [Webpack sample](#webpack-sample).
+
## CodePen samples
### Camera snapshot component
diff --git a/manual-multi-page/backend-reprocessing/index.html b/manual-multi-page/backend-reprocessing/index.html
new file mode 100644
index 0000000..6ca766a
--- /dev/null
+++ b/manual-multi-page/backend-reprocessing/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ My app
+
+
+
+ Start new document
+ Start new page
+
+Press "Start new document" to start scanning document.
+
+
+
diff --git a/manual-multi-page/backend-reprocessing/index.ts b/manual-multi-page/backend-reprocessing/index.ts
new file mode 100644
index 0000000..d2c77b1
--- /dev/null
+++ b/manual-multi-page/backend-reprocessing/index.ts
@@ -0,0 +1,106 @@
+import {
+ defineComponents,
+ DocumentReaderService,
+ InternalScenarios,
+ DocumentReaderWebComponent,
+ DocumentReaderDetailType,
+ TransactionEvent,
+ EventActions,
+ ResponseCode,
+} from '@regulaforensics/vp-frontend-document-components';
+import './styles.css';
+
+const newDocumentButton = document.querySelector('#new-document') as HTMLButtonElement;
+const nextPageButton = document.querySelector('#new-page') as HTMLButtonElement;
+const info = document.querySelector('.info') as HTMLDivElement;
+
+window.RegulaDocumentSDK = new DocumentReaderService();
+window.RegulaDocumentSDK.recognizerProcessParam = {
+ processParam: {
+ scenario: InternalScenarios.MrzAndLocate,
+ multipageProcessing: true,
+ backendProcessing: {
+ serviceURL: 'YOUR_SERVICE_URL',
+ httpHeaders: { // you can set http headers if necessary
+ key1: 'header1',
+ key2: 'header2',
+ key3: 'header3'
+ }
+ },
+ },
+};
+window.RegulaDocumentSDK.imageProcessParam = {
+ processParam: {
+ scenario: InternalScenarios.MrzAndLocate,
+ },
+};
+
+defineComponents().then(() => window.RegulaDocumentSDK.initialize());
+// To use the document-reader component on test environments, you have to set the base64 license
+// defineComponents().then(() => window.RegulaDocumentSDK.initialize({ license: 'YOUR_BASE64_LICENSE_KEY' }));
+
+function createDocumentReader() {
+ const documentReaderElement = document.createElement('document-reader') as DocumentReaderWebComponent;
+ const container = document.createElement('div');
+ documentReaderElement.setAttribute('new-layout', 'true');
+ container.setAttribute('class', 'reader-container');
+ container.append(documentReaderElement);
+
+ documentReaderElement.settings = {
+ uploadFileButton: false,
+ manualMultipageMode: true,
+ }
+
+ return container;
+}
+
+function documentReaderListener(data: CustomEvent) {
+ const reader = document.querySelector('.reader-container');
+ const action = data.detail.action;
+
+ if (action === EventActions.PROCESS_FINISHED) {
+ const status = data.detail.data?.status;
+ const isFinishStatus = status === ResponseCode.OK || status === ResponseCode.TIMEOUT;
+ const responseData = data.detail.data;
+
+ if (isFinishStatus && responseData?.response) {
+ const isMorePagesAvailable = !!responseData.response.rawResponse.morePagesAvailable;
+
+ info.textContent = 'Check your result in the console. ';
+
+ if (isMorePagesAvailable) {
+ nextPageButton.disabled = false;
+ info.textContent += 'More pages are available, click "Start new page" ' +
+ 'to continue scanning, or start scanning a new document by clicking "Start new document".';
+ } else {
+ void window.RegulaDocumentSDK.finalizePackage();
+ }
+ console.log(responseData.response);
+
+ reader?.remove();
+ }
+ }
+ if (action === EventActions.CAMERA_PROCESS_CLOSED) reader?.remove();
+}
+
+function newDocumentButtonListener() {
+ if (!window.RegulaDocumentSDK) return;
+
+ info.textContent = '';
+ nextPageButton.disabled = true;
+ void window.RegulaDocumentSDK.createBackendTransaction();
+ document.body.append(createDocumentReader());
+}
+
+function nextPageButtonListener() {
+ if (!window.RegulaDocumentSDK) return;
+
+ info.textContent = '';
+ nextPageButton.disabled = true;
+ void window.RegulaDocumentSDK.startNewPage();
+ document.body.append(createDocumentReader());
+}
+
+newDocumentButton?.addEventListener('click', newDocumentButtonListener);
+nextPageButton?.addEventListener('click', nextPageButtonListener);
+document.body.addEventListener('document-reader', documentReaderListener);
diff --git a/manual-multi-page/backend-reprocessing/package.json b/manual-multi-page/backend-reprocessing/package.json
new file mode 100644
index 0000000..585979f
--- /dev/null
+++ b/manual-multi-page/backend-reprocessing/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "sample",
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "serve": "vite",
+ "build": "vite build"
+ },
+ "dependencies": {
+ "@regulaforensics/vp-frontend-document-components": "*"
+ },
+ "devDependencies": {
+ "typescript": "^5.9.3",
+ "vite": "^7.2.6"
+ }
+}
diff --git a/manual-multi-page/backend-reprocessing/styles.css b/manual-multi-page/backend-reprocessing/styles.css
new file mode 100644
index 0000000..a8bca30
--- /dev/null
+++ b/manual-multi-page/backend-reprocessing/styles.css
@@ -0,0 +1,42 @@
+.reader-container {
+ position: absolute;
+ inset: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.buttons {
+ display: flex;
+ justify-content: center;
+ column-gap: 15px;
+ padding-bottom: 20px;
+}
+
+.button {
+ padding: 8px 15px;
+ border: 1px solid black;
+ background: #fff;
+ font-family: Arial, sans-serif;
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 135%;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: .1s;
+}
+
+.button:hover:not(:disabled) {
+ background: #efefef;
+}
+
+.button:disabled {
+ cursor: not-allowed;
+ border: 1px solid lightgrey;
+}
+
+.info {
+ max-width: 600px;
+ text-align: center;
+ line-height: 24px;
+ margin: 0 auto;
+}
diff --git a/manual-multi-page/backend-reprocessing/tsconfig.json b/manual-multi-page/backend-reprocessing/tsconfig.json
new file mode 100644
index 0000000..5dd35f0
--- /dev/null
+++ b/manual-multi-page/backend-reprocessing/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "types": ["vite/client"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ }
+}
diff --git a/manual-multi-page/react/package.json b/manual-multi-page/react/package.json
index c4e58f9..dd5985e 100644
--- a/manual-multi-page/react/package.json
+++ b/manual-multi-page/react/package.json
@@ -7,8 +7,8 @@
"build": "vite build"
},
"dependencies": {
- "@regulaforensics/ui-components": "nightly",
- "@regulaforensics/vp-frontend-document-components": "nightly",
+ "@regulaforensics/ui-components": "*",
+ "@regulaforensics/vp-frontend-document-components": "*",
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
diff --git a/manual-multi-page/typescript/package.json b/manual-multi-page/typescript/package.json
index f78d9d1..585979f 100644
--- a/manual-multi-page/typescript/package.json
+++ b/manual-multi-page/typescript/package.json
@@ -7,7 +7,7 @@
"build": "vite build"
},
"dependencies": {
- "@regulaforensics/vp-frontend-document-components": "nightly"
+ "@regulaforensics/vp-frontend-document-components": "*"
},
"devDependencies": {
"typescript": "^5.9.3",