@myazahq/kyc-sdk-react-native 2.2.0 → 2.4.0

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 (51) hide show
  1. package/package.json +1 -2
  2. package/src/components/BrandBar.tsx +137 -0
  3. package/src/components/DialCodePicker.tsx +11 -17
  4. package/src/components/DocumentReviewSide.tsx +34 -14
  5. package/src/components/Icon.tsx +5 -0
  6. package/src/components/KycSheet.tsx +161 -180
  7. package/src/components/MediaSourceSheet.tsx +7 -37
  8. package/src/components/MyazaDateField.tsx +6 -20
  9. package/src/components/MyazaInput.tsx +6 -1
  10. package/src/components/MyazaSelect.tsx +20 -39
  11. package/src/components/PoweredBy.tsx +20 -15
  12. package/src/components/ProgressBar.tsx +91 -0
  13. package/src/components/SandboxBanner.tsx +92 -0
  14. package/src/components/StepHeader.tsx +15 -2
  15. package/src/components/StepIndicator.tsx +145 -31
  16. package/src/components/fonts.ts +23 -0
  17. package/src/components/glass/ChromeGlass.tsx +65 -0
  18. package/src/components/glass/FloatingSheet.tsx +190 -0
  19. package/src/components/glass/GlassSheet.tsx +38 -0
  20. package/src/components/glass/GlassSurface.tsx +31 -3
  21. package/src/components/viewfinder/ImmersiveBottomBar.tsx +28 -17
  22. package/src/components/viewfinder/ImmersiveControls.tsx +26 -14
  23. package/src/components/viewfinder/ViewfinderControls.tsx +29 -7
  24. package/src/config/questionnaire.ts +45 -4
  25. package/src/config/workflowMerge.ts +1 -0
  26. package/src/emrtd/crypto.ts +1 -1
  27. package/src/emrtd/dg1.ts +55 -0
  28. package/src/emrtd/ec-curves.ts +142 -0
  29. package/src/emrtd/ec.ts +196 -0
  30. package/src/emrtd/index.ts +1 -0
  31. package/src/emrtd/mrzKey.ts +21 -1
  32. package/src/emrtd/open.ts +169 -0
  33. package/src/emrtd/pace-params.ts +169 -0
  34. package/src/emrtd/pace.ts +295 -0
  35. package/src/emrtd/secureMessaging.ts +32 -14
  36. package/src/emrtd/session.ts +124 -20
  37. package/src/emrtd/suites.ts +99 -0
  38. package/src/index.ts +1 -0
  39. package/src/lib/step-log.ts +43 -0
  40. package/src/lib/step-window.ts +96 -0
  41. package/src/liveness/useLiveness.ts +1 -1
  42. package/src/screens/IdTypeStep.tsx +15 -2
  43. package/src/screens/NfcStep.tsx +12 -0
  44. package/src/screens/QuestionnaireField.tsx +30 -0
  45. package/src/screens/QuestionnaireStep.tsx +3 -1
  46. package/src/screens/nfc/NfcSuccessPanel.tsx +13 -6
  47. package/src/services/deviceMetadata.ts +9 -1
  48. package/src/store/derive.ts +7 -0
  49. package/src/store/kycStore.ts +25 -1
  50. package/src/types/config.ts +22 -0
  51. package/src/types/workflow.ts +10 -0
@@ -27,6 +27,7 @@ import {
27
27
  type KycStore,
28
28
  } from './state';
29
29
  import { nextStepAfter, nfcDecision, previousStepBefore } from './derive';
30
+ import { recordStep, resetStepLog } from '../lib/step-log';
30
31
  import { buildVerifyRequest } from './submit';
31
32
  import { applicantMediaCaptured, buildApplicantVerifyRequest } from './submitApplicant';
32
33
 
@@ -54,7 +55,7 @@ export function createKycStore(
54
55
  const baseUrl = resolveBaseUrl(config.apiKey, config.devUrl);
55
56
  const api = createKYCApi(baseUrl, config.apiKey);
56
57
 
57
- return createStore<KycState>((set, get) => {
58
+ const store = createStore<KycState>((set, get) => {
58
59
  function emitStepChange(step: KYCStep): void {
59
60
  config.onStepChange?.(step);
60
61
  }
@@ -354,6 +355,11 @@ export function createKycStore(
354
355
  },
355
356
 
356
357
  reset() {
358
+ // Fresh step journey per session; the explicit record covers a store
359
+ // already sitting on 'consent' (the subscribe below only fires on
360
+ // change, and recordStep dedupes if it fires too).
361
+ resetStepLog();
362
+ recordStep('consent');
357
363
  set({
358
364
  currentStep: 'consent',
359
365
  selectedCountry: null,
@@ -383,6 +389,24 @@ export function createKycStore(
383
389
  },
384
390
  };
385
391
  });
392
+
393
+ // Step journey log — records every step the user reaches (the subscription
394
+ // catches ALL currentStep writes, whatever action made them; recordStep
395
+ // collapses consecutive duplicates). Rides the submission as
396
+ // metadata.device.stepLog for the dashboard timeline.
397
+ store.subscribe((s, prev) => {
398
+ if (s.currentStep !== prev.currentStep) recordStep(s.currentStep);
399
+ });
400
+
401
+ // A fresh store IS a fresh session: the runtime provider creates one per
402
+ // modal launch and reset() is NOT part of the open path, so the journey
403
+ // starts here — and the opening step must be recorded explicitly (the
404
+ // subscription above only fires on CHANGE, and a new store already sits on
405
+ // 'consent').
406
+ resetStepLog();
407
+ recordStep(store.getState().currentStep);
408
+
409
+ return store;
386
410
  }
387
411
 
388
412
  // Re-export the flow helpers for tests + screens that need to reason about
@@ -61,6 +61,9 @@ export type KYCStep =
61
61
  // Client-side SDK config (MyazaKYC.show() / useMyazaKYC options)
62
62
  // ---------------------------------------------------------------------------
63
63
 
64
+ /** How flow progress is drawn — see {@link MyazaKYCConfig.progressStyle}. */
65
+ export type ProgressStyle = 'steps' | 'bar' | 'none';
66
+
64
67
  export interface MyazaKYCConfig<C extends SupportedCountry = SupportedCountry> {
65
68
  /**
66
69
  * Bearer token. The key prefix is the single source of truth for the
@@ -203,6 +206,25 @@ export interface MyazaKYCConfig<C extends SupportedCountry = SupportedCountry> {
203
206
  /** Show a light/dark mode toggle button inside the modal header. Default `true`. */
204
207
  showThemeToggle?: boolean;
205
208
 
209
+ /**
210
+ * How progress through the flow is drawn in the header.
211
+ *
212
+ * • `'steps'` (default) — numbered circles, one per step, connected. Shows
213
+ * WHICH step you are on and how many there are, and collapses to a window
214
+ * when they no longer fit.
215
+ * • `'bar'` — a single thin bar pinned to the bottom edge of the header.
216
+ * Quieter, and unaffected by step count, so it suits long flows and hosts
217
+ * who would rather the chrome said less.
218
+ * • `'none'` — no progress in the header at all. For hosts whose own
219
+ * surface already communicates progress, or short flows where a
220
+ * step count is more noise than reassurance. The header keeps its
221
+ * brand row and controls; only the progress element is dropped.
222
+ *
223
+ * `'steps'` and `'bar'` convey the same fraction; the choice is how much room
224
+ * it takes. `'none'` opts out of conveying it here.
225
+ */
226
+ progressStyle?: ProgressStyle;
227
+
206
228
  /**
207
229
  * Hide the close (X) button and block all user-initiated dismissal of the
208
230
  * sheet — the X button, Android hardware back, and the iOS swipe-down drag.
@@ -82,6 +82,16 @@ export interface PhoneVerificationConfig {
82
82
  export interface QuestionnaireFieldOption {
83
83
  value: string;
84
84
  label: string;
85
+ /**
86
+ * Marks a choice that is not an answer on its own — an "Other". Selecting it
87
+ * reveals a required free-text input, stored as the `<key>_other` companion
88
+ * answer (the same shape as a money field's `<key>_currency`).
89
+ */
90
+ requiresDetail?: boolean;
91
+ /** Label for the detail input (default "Please specify"). */
92
+ detailLabel?: string;
93
+ /** Placeholder for the detail input (default `Tell us more about "<label>"`). */
94
+ detailPlaceholder?: string;
85
95
  }
86
96
 
87
97
  export interface QuestionnaireField {