@microblink/blinkid-ux-manager 7.3.2 → 7.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/blinkid-ux-manager.js +277 -47
  2. package/dist/blinkid-ux-manager.js.map +1 -1
  3. package/package.json +3 -3
  4. package/types/core/BlinkIdProcessingError.d.ts +5 -0
  5. package/types/core/BlinkIdProcessingError.d.ts.map +1 -1
  6. package/types/core/BlinkIdUxManager.d.ts +86 -25
  7. package/types/core/BlinkIdUxManager.d.ts.map +1 -1
  8. package/types/core/DocumentClassFilter.d.ts +5 -3
  9. package/types/core/DocumentClassFilter.d.ts.map +1 -1
  10. package/types/core/blinkid-ui-state.d.ts +38 -0
  11. package/types/core/blinkid-ui-state.d.ts.map +1 -1
  12. package/types/core/utils.d.ts +18 -0
  13. package/types/core/utils.d.ts.map +1 -1
  14. package/types/index.d.ts +14 -0
  15. package/types/index.d.ts.map +1 -1
  16. package/types/index.rollup.d.ts +267 -35
  17. package/types/ui/BlinkIdFeedbackUi.d.ts +8 -0
  18. package/types/ui/BlinkIdFeedbackUi.d.ts.map +1 -1
  19. package/types/ui/BlinkIdUiStoreContext.d.ts +59 -0
  20. package/types/ui/BlinkIdUiStoreContext.d.ts.map +1 -1
  21. package/types/ui/LocalizationContext.d.ts +14 -0
  22. package/types/ui/LocalizationContext.d.ts.map +1 -1
  23. package/types/ui/UiFeedbackOverlay.d.ts +6 -0
  24. package/types/ui/UiFeedbackOverlay.d.ts.map +1 -1
  25. package/types/ui/createBlinkIdFeedbackUi.d.ts +34 -1
  26. package/types/ui/createBlinkIdFeedbackUi.d.ts.map +1 -1
  27. package/types/ui/dialogs/ErrorModal.d.ts +9 -0
  28. package/types/ui/dialogs/ErrorModal.d.ts.map +1 -1
  29. package/types/ui/dialogs/HelpModal.d.ts +11 -0
  30. package/types/ui/dialogs/HelpModal.d.ts.map +1 -1
  31. package/types/ui/dialogs/OnboardingGuideModal.d.ts +5 -0
  32. package/types/ui/dialogs/OnboardingGuideModal.d.ts.map +1 -1
  33. package/types/ui/feedbackMessages.d.ts +3 -0
  34. package/types/ui/feedbackMessages.d.ts.map +1 -1
  35. package/types/ui/locales/en.d.ts +3 -0
  36. package/types/ui/locales/en.d.ts.map +1 -1
@@ -698,33 +698,75 @@ function getKeyWithHighestValue(obj) {
698
698
  return maxKey;
699
699
  }
700
700
  class FeedbackStabilizer {
701
+ /** The initial key. */
701
702
  initialKey;
703
+ /** The UI state map. */
702
704
  uiStateMap;
705
+ /** Time window (in ms) for considering UI state events. */
703
706
  timeWindow = 3e3;
707
+ /** The decay rate. */
708
+ /** Rate at which event weights decay over time */
704
709
  decayRate = 0.95;
710
+ /** Queue of regular UI state events within the time window */
705
711
  eventQueue = [];
706
- /** this is a special queue as min duration of the event can be longer than the `timeWindow` */
712
+ /** Special queue for single-emit events that bypass normal stabilization */
707
713
  singleEventQueue = [];
708
- // used for tracking current state
714
+ /** Currently displayed state key */
709
715
  currentKey;
716
+ /** Timestamp when current state started displaying */
710
717
  currentStateStartTime = performance.now();
718
+ /** Accumulated scores for each state in current calculation */
711
719
  summedScores = {};
720
+ /** History of scores for each state */
712
721
  scoreBoard = {};
722
+ /**
723
+ * Gets the currently active UI state configuration.
724
+ *
725
+ * @returns The currently active UI state configuration.
726
+ */
713
727
  get currentState() {
714
728
  return this.uiStateMap[this.currentKey];
715
729
  }
730
+ /**
731
+ * Gets a copy of the current event queue for debugging.
732
+ *
733
+ * @returns A copy of the current event queue.
734
+ */
716
735
  getEventQueue() {
717
736
  return structuredClone(this.eventQueue);
718
737
  }
738
+ /**
739
+ * Gets the current summed scores for each state.
740
+ *
741
+ * @returns The current summed scores for each state.
742
+ */
719
743
  getScores() {
720
744
  return structuredClone(this.summedScores);
721
745
  }
746
+ /**
747
+ * Gets the score history for each state.
748
+ *
749
+ * @returns The score history for each state.
750
+ */
722
751
  getScoreBoard() {
723
752
  return structuredClone(this.scoreBoard);
724
753
  }
754
+ /**
755
+ * Updates the time window used for state stabilization
756
+ *
757
+ * @param timeWindow - New time window in milliseconds
758
+ */
725
759
  setTimeWindow(timeWindow) {
726
760
  this.timeWindow = timeWindow;
727
761
  }
762
+ /**
763
+ * Creates a new FeedbackStabilizer instance.
764
+ *
765
+ * @param uiStateMap - Map of all possible UI states and their configurations
766
+ * @param initialKey - Key of the initial UI state to display
767
+ * @param timeWindow - Optional custom time window (in ms) for state averaging
768
+ * @param decayRate - Optional custom decay rate for event weights
769
+ */
728
770
  constructor(uiStateMap, initialKey, timeWindow, decayRate) {
729
771
  this.uiStateMap = uiStateMap;
730
772
  this.initialKey = initialKey;
@@ -737,17 +779,35 @@ class FeedbackStabilizer {
737
779
  this.decayRate = decayRate;
738
780
  }
739
781
  }
782
+ /**
783
+ * Resets the stabilizer to its initial state.
784
+ *
785
+ * @returns The initial state.
786
+ */
740
787
  reset() {
741
788
  this.currentKey = this.initialKey;
742
789
  this.eventQueue = [];
743
790
  this.singleEventQueue = [];
744
791
  this.summedScores = {};
745
792
  }
793
+ /**
794
+ * Checks if enough time has passed to show a new UI state
795
+ *
796
+ * @returns true if the current state's minimum duration has elapsed
797
+ */
746
798
  canShowNewUiState = () => {
747
799
  return performance.now() - this.currentStateStartTime >= this.currentState.minDuration;
748
800
  };
749
801
  /**
750
- * Returns a weighted UI state based on the history
802
+ * Processes a new UI state event and determines the state to display.
803
+ *
804
+ * This method:
805
+ * 1. Handles single-emit events that bypass normal stabilization
806
+ * 2. Maintains a time-windowed queue of regular events
807
+ * 3. Applies temporal averaging with decay to determine the winning state
808
+ *
809
+ * @param incomingUiStateKey - Key of the new UI state event
810
+ * @returns The UI state that should be displayed.
751
811
  */
752
812
  getNewUiState(incomingUiStateKey) {
753
813
  const now = performance.now();
@@ -814,8 +874,11 @@ async function sleep(ms) {
814
874
  return new Promise((resolve) => setTimeout(resolve, ms));
815
875
  }
816
876
  class BlinkIdUxManager {
877
+ /** The success process result. */
817
878
  #successProcessResult;
879
+ /** Whether the thread is busy. */
818
880
  #threadBusy = false;
881
+ /** The scanning session timeout ID. */
819
882
  #timeoutId;
820
883
  /** Timeout duration in ms for the scanning session. If null, timeout won't be triggered ever. */
821
884
  #timeoutDuration = 1e4;
@@ -826,12 +889,24 @@ class BlinkIdUxManager {
826
889
  /** Time in ms before the help tooltip is hidden. If null, tooltip won't be auto hidden. */
827
890
  #helpTooltipHideDelay = 5e3;
828
891
  // 5s
892
+ /** The callbacks for when the UI state changes. */
829
893
  #onUiStateChangedCallbacks = /* @__PURE__ */ new Set();
894
+ /** The callbacks for when a scan result is available. */
830
895
  #onResultCallbacks = /* @__PURE__ */ new Set();
896
+ /** The callbacks for when a frame is processed. */
831
897
  #onFrameProcessCallbacks = /* @__PURE__ */ new Set();
898
+ /** The callbacks for when an error occurs during processing. */
832
899
  #onErrorCallbacks = /* @__PURE__ */ new Set();
900
+ /** The callbacks for when a document is filtered. */
833
901
  #onDocumentFilteredCallbacks = /* @__PURE__ */ new Set();
902
+ /** The document class filter. */
834
903
  #documentClassFilter;
904
+ /**
905
+ * The constructor for the BlinkIdUxManager class.
906
+ *
907
+ * @param cameraManager - The camera manager.
908
+ * @param scanningSession - The scanning session.
909
+ */
835
910
  constructor(cameraManager, scanningSession) {
836
911
  this.cameraManager = cameraManager;
837
912
  this.scanningSession = scanningSession;
@@ -864,56 +939,58 @@ class BlinkIdUxManager {
864
939
  }
865
940
  }
866
941
  );
867
- const unsubscribeVideoObserver = cameraManager.subscribe(
942
+ const unsubscribeVideoObserver = this.cameraManager.subscribe(
868
943
  (s2) => s2.videoElement,
869
944
  (videoElement) => {
870
945
  if (!videoElement) {
871
- console.debug("Removing timeout subscriptions");
946
+ console.debug("Removing camera manager subscriptions");
872
947
  this.reset();
873
948
  unsubscribeVideoObserver();
874
949
  unsubscribePlaybackState();
875
950
  }
876
951
  }
877
952
  );
878
- cameraManager.addFrameCaptureCallback(this.#frameCaptureCallback);
953
+ this.cameraManager.addFrameCaptureCallback(this.#frameCaptureCallback);
879
954
  }
880
955
  /**
881
- * Indicates whether the UI should display the demo overlay. Controlled by the license property.
956
+ * Indicates whether the UI should display the demo overlay. Controlled by the
957
+ * license property.
882
958
  */
883
959
  getShowDemoOverlay() {
884
960
  return this.showDemoOverlay;
885
961
  }
886
962
  /**
887
- * Indicates whether the UI should display the production overlay. Controlled by the license property.
963
+ * Indicates whether the UI should display the production overlay. Controlled by
964
+ * the license property.
888
965
  */
889
966
  getShowProductionOverlay() {
890
967
  return this.showProductionOverlay;
891
968
  }
892
969
  /**
893
970
  * Returns the timeout duration in ms. Null if timeout won't be triggered ever.
894
- * @returns The timeout duration in ms.
895
971
  */
896
972
  getTimeoutDuration() {
897
973
  return this.#timeoutDuration;
898
974
  }
899
975
  /**
900
976
  * Returns the time in ms before the help tooltip is shown. Null if tooltip won't be auto shown.
901
- * @returns The time in ms before the help tooltip is shown.
902
977
  */
903
978
  getHelpTooltipShowDelay() {
904
979
  return this.#helpTooltipShowDelay;
905
980
  }
906
981
  /**
907
982
  * Returns the time in ms before the help tooltip is hidden. Null if tooltip won't be auto hidden.
908
- * @returns The time in ms before the help tooltip is hidden.
909
983
  */
910
984
  getHelpTooltipHideDelay() {
911
985
  return this.#helpTooltipHideDelay;
912
986
  }
913
987
  /**
914
988
  * Adds a callback function to be executed when the UI state changes.
915
- * @param callback - Function to be called when UI state changes. Receives the new UI state as parameter.
989
+ *
990
+ * @param callback - Function to be called when UI state changes. Receives the
991
+ * new UI state as parameter.
916
992
  * @returns A cleanup function that removes the callback when called.
993
+ *
917
994
  * @example
918
995
  * const cleanup = manager.addOnUiStateChangedCallback((newState) => {
919
996
  * console.log('UI state changed to:', newState);
@@ -929,8 +1006,10 @@ class BlinkIdUxManager {
929
1006
  }
930
1007
  /**
931
1008
  * Registers a callback function to be called when a scan result is available.
1009
+ *
932
1010
  * @param callback - A function that will be called with the scan result.
933
- * @returns A cleanup function that, when called, will remove the registered callback.
1011
+ * @returns A cleanup function that, when called, will remove the registered
1012
+ * callback.
934
1013
  *
935
1014
  * @example
936
1015
  *
@@ -949,8 +1028,11 @@ class BlinkIdUxManager {
949
1028
  }
950
1029
  /**
951
1030
  * Registers a callback function to filter document classes.
952
- * @param callback - A function that will be called with the document class info.
953
- * @returns A cleanup function that, when called, will remove the registered callback.
1031
+ *
1032
+ * @param callback - A function that will be called with the document class
1033
+ * info.
1034
+ * @returns A cleanup function that, when called, will remove the registered
1035
+ * callback.
954
1036
  *
955
1037
  * @example
956
1038
  * const cleanup = manager.addDocumentClassFilter((docClassInfo) => {
@@ -968,8 +1050,11 @@ class BlinkIdUxManager {
968
1050
  }
969
1051
  /**
970
1052
  * Registers a callback function to be called when a frame is processed.
971
- * @param callback - A function that will be called with the frame analysis result.
972
- * @returns A cleanup function that, when called, will remove the registered callback.
1053
+ *
1054
+ * @param callback - A function that will be called with the frame analysis
1055
+ * result.
1056
+ * @returns A cleanup function that, when called, will remove the registered
1057
+ * callback.
973
1058
  *
974
1059
  * @example
975
1060
  * const cleanup = manager.addOnFrameProcessCallback((frameResult) => {
@@ -986,9 +1071,12 @@ class BlinkIdUxManager {
986
1071
  };
987
1072
  }
988
1073
  /**
989
- * Registers a callback function to be called when an error occurs during processing.
1074
+ * Registers a callback function to be called when an error occurs during
1075
+ * processing.
1076
+ *
990
1077
  * @param callback - A function that will be called with the error state.
991
- * @returns A cleanup function that, when called, will remove the registered callback.
1078
+ * @returns A cleanup function that, when called, will remove the registered
1079
+ * callback.
992
1080
  *
993
1081
  * @example
994
1082
  * const cleanup = manager.addOnErrorCallback((error) => {
@@ -1004,6 +1092,11 @@ class BlinkIdUxManager {
1004
1092
  this.#onErrorCallbacks.delete(callback);
1005
1093
  };
1006
1094
  }
1095
+ /**
1096
+ * Invokes the onError callbacks.
1097
+ *
1098
+ * @param errorState - The error state.
1099
+ */
1007
1100
  #invokeOnErrorCallbacks = (errorState) => {
1008
1101
  for (const callback of this.#onErrorCallbacks) {
1009
1102
  try {
@@ -1013,12 +1106,33 @@ class BlinkIdUxManager {
1013
1106
  }
1014
1107
  }
1015
1108
  };
1109
+ /**
1110
+ * Registers a callback function to be called when a document is filtered.
1111
+ *
1112
+ * @param callback - A function that will be called with the document class
1113
+ * info.
1114
+ * @returns A cleanup function that, when called, will remove the registered
1115
+ * callback.
1116
+ *
1117
+ * @example
1118
+ * const cleanup = manager.addOnDocumentFilteredCallback((docClassInfo) => {
1119
+ * console.log('Document filtered:', docClassInfo);
1120
+ * });
1121
+ *
1122
+ * // Later, to remove the callback:
1123
+ * cleanup();
1124
+ */
1016
1125
  addOnDocumentFilteredCallback(callback) {
1017
1126
  this.#onDocumentFilteredCallbacks.add(callback);
1018
1127
  return () => {
1019
1128
  this.#onDocumentFilteredCallbacks.delete(callback);
1020
1129
  };
1021
1130
  }
1131
+ /**
1132
+ * Invokes the onDocumentFiltered callbacks.
1133
+ *
1134
+ * @param documentClassInfo - The document class info.
1135
+ */
1022
1136
  #invokeOnDocumentFilteredCallbacks = (documentClassInfo) => {
1023
1137
  for (const callback of this.#onDocumentFilteredCallbacks) {
1024
1138
  try {
@@ -1028,6 +1142,11 @@ class BlinkIdUxManager {
1028
1142
  }
1029
1143
  }
1030
1144
  };
1145
+ /**
1146
+ * Invokes the onResult callbacks.
1147
+ *
1148
+ * @param result - The scan result.
1149
+ */
1031
1150
  #invokeOnResultCallbacks = (result) => {
1032
1151
  for (const callback of this.#onResultCallbacks) {
1033
1152
  try {
@@ -1037,6 +1156,11 @@ class BlinkIdUxManager {
1037
1156
  }
1038
1157
  }
1039
1158
  };
1159
+ /**
1160
+ * Invokes the onFrameProcess callbacks.
1161
+ *
1162
+ * @param frameResult - The frame result.
1163
+ */
1040
1164
  #invokeOnFrameProcessCallbacks = (frameResult) => {
1041
1165
  for (const callback of this.#onFrameProcessCallbacks) {
1042
1166
  try {
@@ -1046,6 +1170,11 @@ class BlinkIdUxManager {
1046
1170
  }
1047
1171
  }
1048
1172
  };
1173
+ /**
1174
+ * Invokes the onUiStateChanged callbacks.
1175
+ *
1176
+ * @param uiState - The UI state.
1177
+ */
1049
1178
  #invokeOnUiStateChangedCallbacks = (uiState) => {
1050
1179
  for (const callback of this.#onUiStateChangedCallbacks) {
1051
1180
  try {
@@ -1055,6 +1184,33 @@ class BlinkIdUxManager {
1055
1184
  }
1056
1185
  }
1057
1186
  };
1187
+ /**
1188
+ * Handles document class filtering if configured.
1189
+ * Returns true if the document should be processed, false if it was filtered out.
1190
+ *
1191
+ * @param processResult - The result of processing the current frame
1192
+ * @returns boolean indicating if the document should be processed
1193
+ */
1194
+ #handleDocumentClassFiltering(processResult) {
1195
+ if (this.#documentClassFilter === void 0) {
1196
+ return true;
1197
+ }
1198
+ const documentClassInfo = this.#extractDocumentClassInfo(processResult);
1199
+ if (!this.#isDocumentClassified(documentClassInfo) || this.#documentClassFilter(documentClassInfo)) {
1200
+ return true;
1201
+ }
1202
+ this.cameraManager.stopFrameCapture();
1203
+ this.#invokeOnDocumentFilteredCallbacks(documentClassInfo);
1204
+ this.#invokeOnFrameProcessCallbacks(processResult);
1205
+ return false;
1206
+ }
1207
+ /**
1208
+ * The frame capture callback. This is the main function that is called when a
1209
+ * new frame is captured. It is responsible for processing the frame and
1210
+ * updating the UI state.
1211
+ *
1212
+ * @param imageData - The image data.
1213
+ */
1058
1214
  #frameCaptureCallback = async (imageData) => {
1059
1215
  if (this.#threadBusy) {
1060
1216
  return;
@@ -1077,22 +1233,23 @@ class BlinkIdUxManager {
1077
1233
  }
1078
1234
  const processResult = await this.scanningSession.process(imageDataLike);
1079
1235
  this.#threadBusy = false;
1080
- if (this.#documentClassFilter !== void 0) {
1081
- const documentClassInfo = this.#extractDocumentClassInfo(processResult);
1082
- if (this.#isDocumentClassified(documentClassInfo) && !this.#documentClassFilter(documentClassInfo)) {
1083
- this.#invokeOnDocumentFilteredCallbacks(documentClassInfo);
1084
- }
1236
+ if (!this.#handleDocumentClassFiltering(processResult)) {
1237
+ return processResult.arrayBuffer;
1085
1238
  }
1086
1239
  this.#handleUiStateChanges(processResult);
1087
1240
  this.#invokeOnFrameProcessCallbacks(processResult);
1088
1241
  return processResult.arrayBuffer;
1089
1242
  };
1090
1243
  /**
1091
- * Sets the duration after which the scanning session will timeout. The timeout can occur in various scenarios
1092
- * and may be restarted by different scanning events.
1244
+ * Sets the duration after which the scanning session will timeout. The
1245
+ * timeout can occur in various scenarios and may be restarted by different
1246
+ * scanning events.
1093
1247
  *
1094
- * @param duration The timeout duration in milliseconds. If null, timeout won't be triggered ever.
1095
- * @param setHelpTooltipShowDelay If true, also sets the help tooltip show delay to half of the provided duration. If timeout duration is null, help tooltip show delay will be set to null. Defaults to true.
1248
+ * @param duration The timeout duration in milliseconds. If null, timeout won't
1249
+ * be triggered ever.
1250
+ * @param setHelpTooltipShowDelay If true, also sets the help tooltip show
1251
+ * delay to half of the provided duration. If timeout duration is null, help
1252
+ * tooltip show delay will be set to null. Defaults to true.
1096
1253
  * @throws {Error} Throws an error if duration is less than or equal to 0 when not null.
1097
1254
  */
1098
1255
  setTimeoutDuration(duration, setHelpTooltipShowDelay = true) {
@@ -1107,8 +1264,11 @@ class BlinkIdUxManager {
1107
1264
  /**
1108
1265
  * Sets the duration in milliseconds before the help tooltip is shown.
1109
1266
  * A value of null means the help tooltip will not be auto shown.
1110
- * @param duration The duration in milliseconds before the help tooltip is shown. If null, tooltip won't be auto shown.
1111
- * @throws {Error} Throws an error if duration is less than or equal to 0 when not null.
1267
+ *
1268
+ * @param duration The duration in milliseconds before the help tooltip is
1269
+ * shown. If null, tooltip won't be auto shown.
1270
+ * @throws {Error} Throws an error if duration is less than or equal to 0 when
1271
+ * not null.
1112
1272
  */
1113
1273
  setHelpTooltipShowDelay(duration) {
1114
1274
  if (duration !== null && duration <= 0) {
@@ -1119,8 +1279,11 @@ class BlinkIdUxManager {
1119
1279
  /**
1120
1280
  * Sets the duration in milliseconds before the help tooltip is hidden.
1121
1281
  * A value of null means the help tooltip will not be auto hidden.
1122
- * @param duration The duration in milliseconds before the help tooltip is hidden. If null, tooltip won't be auto hidden.
1123
- * @throws {Error} Throws an error if duration is less than or equal to 0 when not null.
1282
+ *
1283
+ * @param duration The duration in milliseconds before the help tooltip is
1284
+ * hidden. If null, tooltip won't be auto hidden.
1285
+ * @throws {Error} Throws an error if duration is less than or equal to 0 when
1286
+ * not null.
1124
1287
  */
1125
1288
  setHelpTooltipHideDelay(duration) {
1126
1289
  if (duration !== null && duration <= 0) {
@@ -1128,6 +1291,11 @@ class BlinkIdUxManager {
1128
1291
  }
1129
1292
  this.#helpTooltipHideDelay = duration;
1130
1293
  }
1294
+ /**
1295
+ * Sets the timeout for the scanning session.
1296
+ *
1297
+ * @param uiState - The UI state.
1298
+ */
1131
1299
  #setTimeout = (uiState) => {
1132
1300
  if (this.#timeoutDuration === null) {
1133
1301
  console.debug("⏳🟢 timeout duration is null, not starting timeout");
@@ -1139,10 +1307,16 @@ class BlinkIdUxManager {
1139
1307
  console.debug("⏳🟢 timeout triggered");
1140
1308
  this.cameraManager.stopFrameCapture();
1141
1309
  this.#invokeOnErrorCallbacks("timeout");
1142
- this.feedbackStabilizer.reset();
1143
- this.uiState = this.feedbackStabilizer.currentState;
1310
+ this.#resetUiState();
1144
1311
  }, this.#timeoutDuration);
1145
1312
  };
1313
+ /**
1314
+ * Handles the UI state changes. This is the main function that is called
1315
+ * when a new frame is processed. It is responsible for updating the UI state,
1316
+ * handling the timeout, and handling the first side captured states.
1317
+ *
1318
+ * @param processResult - The process result.
1319
+ */
1146
1320
  #handleUiStateChanges = (processResult) => {
1147
1321
  const nextUiStateKey = getUiStateKey(
1148
1322
  processResult,
@@ -1160,7 +1334,14 @@ class BlinkIdUxManager {
1160
1334
  this.#invokeOnUiStateChangedCallbacks(newUiState);
1161
1335
  void this.#handleUiStateChange(newUiState);
1162
1336
  };
1163
- // Side-effects are handled here
1337
+ /**
1338
+ * Handles the UI state change. This is the main function that is called
1339
+ * when a new UI state is set. It is responsible for handling the timeout,
1340
+ * handling the first side captured states, and handling the UNSUPPORTED_DOCUMENT
1341
+ * state.
1342
+ *
1343
+ * @param uiState - The UI state.
1344
+ */
1164
1345
  #handleUiStateChange = async (uiState) => {
1165
1346
  if (this.#timeoutDuration !== null) {
1166
1347
  this.#setTimeout(uiState);
@@ -1185,14 +1366,34 @@ class BlinkIdUxManager {
1185
1366
  return;
1186
1367
  }
1187
1368
  };
1369
+ /**
1370
+ * Extracts the document class info from the process result.
1371
+ *
1372
+ * @param processResult - The process result.
1373
+ * @returns The document class info.
1374
+ */
1188
1375
  #extractDocumentClassInfo(processResult) {
1189
1376
  return processResult.inputImageAnalysisResult.documentClassInfo;
1190
1377
  }
1378
+ /**
1379
+ * Checks if the document class is classified.
1380
+ *
1381
+ * @param documentClassInfo - The document class info.
1382
+ * @returns Whether the document class is classified.
1383
+ */
1191
1384
  #isDocumentClassified(documentClassInfo) {
1192
1385
  return documentClassInfo?.country !== void 0 && documentClassInfo?.type !== void 0;
1193
1386
  }
1194
1387
  /**
1195
- * Clears any active timeout.
1388
+ * Resets the feedback stabilizer and invokes the onUiStateChanged callbacks.
1389
+ */
1390
+ #resetUiState = () => {
1391
+ this.feedbackStabilizer.reset();
1392
+ this.uiState = this.feedbackStabilizer.currentState;
1393
+ this.#invokeOnUiStateChangedCallbacks(this.uiState);
1394
+ };
1395
+ /**
1396
+ * Clears the scanning session timeout.
1196
1397
  */
1197
1398
  clearScanTimeout = () => {
1198
1399
  if (!this.#timeoutId) {
@@ -1202,11 +1403,31 @@ class BlinkIdUxManager {
1202
1403
  window.clearTimeout(this.#timeoutId);
1203
1404
  };
1204
1405
  /**
1205
- * Resets the manager and clears all callbacks.
1406
+ * Resets the scanning session.
1206
1407
  *
1207
- * Does not reset the camera manager or the BlinkID core instance.
1408
+ * @param startFrameCapture Whether to start frame processing.
1409
+ */
1410
+ async resetScanningSession(startFrameCapture = true) {
1411
+ console.debug("🔁 Resetting scanning session");
1412
+ this.clearScanTimeout();
1413
+ this.#threadBusy = false;
1414
+ this.#successProcessResult = void 0;
1415
+ this.#resetUiState();
1416
+ await this.scanningSession.reset();
1417
+ if (startFrameCapture) {
1418
+ if (!this.cameraManager.isActive) {
1419
+ await this.cameraManager.startCameraStream();
1420
+ }
1421
+ await this.cameraManager.startFrameCapture();
1422
+ }
1423
+ }
1424
+ /**
1425
+ * Resets the BlinkIdUxManager. Clears all callbacks.
1426
+ *
1427
+ * Does not reset the camera manager or the scanning session.
1208
1428
  */
1209
1429
  reset() {
1430
+ console.debug("🔁 Resetting BlinkIdUxManager");
1210
1431
  this.clearScanTimeout();
1211
1432
  this.#threadBusy = false;
1212
1433
  this.#successProcessResult = void 0;
@@ -2874,6 +3095,9 @@ const BlinkIdUiStoreProvider = (props) => {
2874
3095
  showOnboardingGuide: props.showOnboardingGuide,
2875
3096
  showHelpTooltipTimeout: props.showHelpTooltipTimeout,
2876
3097
  showHelpButton: props.showHelpButton,
3098
+ showDocumentFilteredModal: props.showDocumentFilteredModal,
3099
+ showTimeoutModal: props.showTimeoutModal,
3100
+ showUnsupportedDocumentModal: props.showUnsupportedDocumentModal,
2877
3101
  dismountFeedbackUi: props.dismountFeedbackUi
2878
3102
  /* eslint-enable solid/reactivity */
2879
3103
  });
@@ -3532,7 +3756,8 @@ const ErrorModal = (props) => {
3532
3756
  } = useBlinkIdUiStore();
3533
3757
  const hideModal = () => {
3534
3758
  updateStore({
3535
- errorState: void 0
3759
+ errorState: void 0,
3760
+ documentFiltered: false
3536
3761
  });
3537
3762
  };
3538
3763
  const dismountCameraManagerUi = () => {
@@ -3541,7 +3766,7 @@ const ErrorModal = (props) => {
3541
3766
  const handlePrimaryClick = async () => {
3542
3767
  hideModal();
3543
3768
  if (props.shouldResetScanningSession) {
3544
- await store.blinkIdUxManager.scanningSession.reset();
3769
+ await store.blinkIdUxManager.resetScanningSession(false);
3545
3770
  }
3546
3771
  await store.blinkIdUxManager.cameraManager.startFrameCapture();
3547
3772
  };
@@ -3600,13 +3825,12 @@ const BlinkIdFeedbackUi = (props) => {
3600
3825
  onCleanup(() => errorCallbackCleanup());
3601
3826
  });
3602
3827
  createEffect(() => {
3603
- const errorCallbackCleanup = store.blinkIdUxManager.addOnDocumentFilteredCallback((_2) => {
3604
- store.blinkIdUxManager.cameraManager.stopFrameCapture();
3828
+ const documentFilteredCallbackCleanup = store.blinkIdUxManager.addOnDocumentFilteredCallback((_2) => {
3605
3829
  updateStore({
3606
3830
  documentFiltered: true
3607
3831
  });
3608
3832
  });
3609
- onCleanup(() => errorCallbackCleanup());
3833
+ onCleanup(() => documentFilteredCallbackCleanup());
3610
3834
  });
3611
3835
  const playbackState = createWithSignal(cameraManagerStore)((s2) => s2.playbackState);
3612
3836
  const isProcessing = () => playbackState() === "capturing";
@@ -3646,7 +3870,7 @@ const BlinkIdFeedbackUi = (props) => {
3646
3870
  get children() {
3647
3871
  return [createComponent(Match, {
3648
3872
  get when() {
3649
- return store.errorState === "timeout";
3873
+ return store.showTimeoutModal && store.errorState === "timeout";
3650
3874
  },
3651
3875
  get children() {
3652
3876
  return createComponent(ErrorModal, {
@@ -3661,7 +3885,7 @@ const BlinkIdFeedbackUi = (props) => {
3661
3885
  }
3662
3886
  }), createComponent(Match, {
3663
3887
  get when() {
3664
- return uiState().key === "UNSUPPORTED_DOCUMENT";
3888
+ return memo(() => !!store.showUnsupportedDocumentModal)() && uiState().key === "UNSUPPORTED_DOCUMENT";
3665
3889
  },
3666
3890
  get children() {
3667
3891
  return createComponent(ErrorModal, {
@@ -3676,7 +3900,7 @@ const BlinkIdFeedbackUi = (props) => {
3676
3900
  }
3677
3901
  }), createComponent(Match, {
3678
3902
  get when() {
3679
- return store.documentFiltered;
3903
+ return store.showDocumentFilteredModal && store.documentFiltered;
3680
3904
  },
3681
3905
  get children() {
3682
3906
  return createComponent(ErrorModal, {
@@ -3750,7 +3974,10 @@ function createBlinkIdFeedbackUi(blinkIdUxManager, cameraManagerComponent, {
3750
3974
  // todo - implement this
3751
3975
  preserveSdkInstance,
3752
3976
  showOnboardingGuide = true,
3753
- showHelpButton = true
3977
+ showHelpButton = true,
3978
+ showDocumentFilteredModal = true,
3979
+ showTimeoutModal = true,
3980
+ showUnsupportedDocumentModal = true
3754
3981
  } = {}) {
3755
3982
  const dismountFeedbackUiRef = {
3756
3983
  current: () => {
@@ -3764,6 +3991,9 @@ function createBlinkIdFeedbackUi(blinkIdUxManager, cameraManagerComponent, {
3764
3991
  cameraManagerComponent,
3765
3992
  showOnboardingGuide,
3766
3993
  showHelpButton,
3994
+ showDocumentFilteredModal,
3995
+ showTimeoutModal,
3996
+ showUnsupportedDocumentModal,
3767
3997
  dismountFeedbackUi: () => dismountFeedbackUiRef.current(),
3768
3998
  get children() {
3769
3999
  return createComponent(BlinkIdFeedbackUi, {