@kwik-id/sdk-react-native 0.0.0-stage → 0.1.0-alpha.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 (269) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +81 -2
  3. package/app.plugin.js +40 -0
  4. package/lib/commonjs/api/api-client.js +213 -0
  5. package/lib/commonjs/api/api-client.js.map +1 -0
  6. package/lib/commonjs/api/api-error.js +29 -0
  7. package/lib/commonjs/api/api-error.js.map +1 -0
  8. package/lib/commonjs/api/index.js +33 -0
  9. package/lib/commonjs/api/index.js.map +1 -0
  10. package/lib/commonjs/api/upload.js +74 -0
  11. package/lib/commonjs/api/upload.js.map +1 -0
  12. package/lib/commonjs/camera/camera-view.js +227 -0
  13. package/lib/commonjs/camera/camera-view.js.map +1 -0
  14. package/lib/commonjs/camera/index.js +20 -0
  15. package/lib/commonjs/camera/index.js.map +1 -0
  16. package/lib/commonjs/camera/photo-capture.js +50 -0
  17. package/lib/commonjs/camera/photo-capture.js.map +1 -0
  18. package/lib/commonjs/crypto/fingerprint.js +43 -0
  19. package/lib/commonjs/crypto/fingerprint.js.map +1 -0
  20. package/lib/commonjs/crypto/hmac.js +150 -0
  21. package/lib/commonjs/crypto/hmac.js.map +1 -0
  22. package/lib/commonjs/crypto/index.js +39 -0
  23. package/lib/commonjs/crypto/index.js.map +1 -0
  24. package/lib/commonjs/crypto/session-manager.js +173 -0
  25. package/lib/commonjs/crypto/session-manager.js.map +1 -0
  26. package/lib/commonjs/i18n/en.js +297 -0
  27. package/lib/commonjs/i18n/en.js.map +1 -0
  28. package/lib/commonjs/i18n/fr.js +294 -0
  29. package/lib/commonjs/i18n/fr.js.map +1 -0
  30. package/lib/commonjs/i18n/index.js +34 -0
  31. package/lib/commonjs/i18n/index.js.map +1 -0
  32. package/lib/commonjs/i18n/locale.js +20 -0
  33. package/lib/commonjs/i18n/locale.js.map +1 -0
  34. package/lib/commonjs/i18n/translator.js +37 -0
  35. package/lib/commonjs/i18n/translator.js.map +1 -0
  36. package/lib/commonjs/index.js +187 -0
  37. package/lib/commonjs/index.js.map +1 -0
  38. package/lib/commonjs/lib/device-detector.js +34 -0
  39. package/lib/commonjs/lib/device-detector.js.map +1 -0
  40. package/lib/commonjs/lib/event-emitter.js +85 -0
  41. package/lib/commonjs/lib/event-emitter.js.map +1 -0
  42. package/lib/commonjs/lib/index.js +63 -0
  43. package/lib/commonjs/lib/index.js.map +1 -0
  44. package/lib/commonjs/lib/kwik-id-rn-sdk.js +156 -0
  45. package/lib/commonjs/lib/kwik-id-rn-sdk.js.map +1 -0
  46. package/lib/commonjs/lib/verification-machine.js +276 -0
  47. package/lib/commonjs/lib/verification-machine.js.map +1 -0
  48. package/lib/commonjs/package.json +1 -0
  49. package/lib/commonjs/types/events.js +6 -0
  50. package/lib/commonjs/types/events.js.map +1 -0
  51. package/lib/commonjs/types/index.js +2 -0
  52. package/lib/commonjs/types/index.js.map +1 -0
  53. package/lib/commonjs/ui/components/KwikIDVerificationModal.js +407 -0
  54. package/lib/commonjs/ui/components/KwikIDVerificationModal.js.map +1 -0
  55. package/lib/commonjs/ui/components/screens.js +338 -0
  56. package/lib/commonjs/ui/components/screens.js.map +1 -0
  57. package/lib/commonjs/ui/context/kwik-id-provider.js +52 -0
  58. package/lib/commonjs/ui/context/kwik-id-provider.js.map +1 -0
  59. package/lib/commonjs/ui/hooks/use-kwik-verification.js +77 -0
  60. package/lib/commonjs/ui/hooks/use-kwik-verification.js.map +1 -0
  61. package/lib/commonjs/ui/index.js +33 -0
  62. package/lib/commonjs/ui/index.js.map +1 -0
  63. package/lib/module/api/api-client.js +208 -0
  64. package/lib/module/api/api-client.js.map +1 -0
  65. package/lib/module/api/api-error.js +24 -0
  66. package/lib/module/api/api-error.js.map +1 -0
  67. package/lib/module/api/index.js +6 -0
  68. package/lib/module/api/index.js.map +1 -0
  69. package/lib/module/api/upload.js +68 -0
  70. package/lib/module/api/upload.js.map +1 -0
  71. package/lib/module/camera/camera-view.js +222 -0
  72. package/lib/module/camera/camera-view.js.map +1 -0
  73. package/lib/module/camera/index.js +5 -0
  74. package/lib/module/camera/index.js.map +1 -0
  75. package/lib/module/camera/photo-capture.js +45 -0
  76. package/lib/module/camera/photo-capture.js.map +1 -0
  77. package/lib/module/crypto/fingerprint.js +37 -0
  78. package/lib/module/crypto/fingerprint.js.map +1 -0
  79. package/lib/module/crypto/hmac.js +143 -0
  80. package/lib/module/crypto/hmac.js.map +1 -0
  81. package/lib/module/crypto/index.js +6 -0
  82. package/lib/module/crypto/index.js.map +1 -0
  83. package/lib/module/crypto/session-manager.js +169 -0
  84. package/lib/module/crypto/session-manager.js.map +1 -0
  85. package/lib/module/i18n/en.js +293 -0
  86. package/lib/module/i18n/en.js.map +1 -0
  87. package/lib/module/i18n/fr.js +290 -0
  88. package/lib/module/i18n/fr.js.map +1 -0
  89. package/lib/module/i18n/index.js +11 -0
  90. package/lib/module/i18n/index.js.map +1 -0
  91. package/lib/module/i18n/locale.js +15 -0
  92. package/lib/module/i18n/locale.js.map +1 -0
  93. package/lib/module/i18n/translator.js +34 -0
  94. package/lib/module/i18n/translator.js.map +1 -0
  95. package/lib/module/index.js +30 -0
  96. package/lib/module/index.js.map +1 -0
  97. package/lib/module/lib/device-detector.js +26 -0
  98. package/lib/module/lib/device-detector.js.map +1 -0
  99. package/lib/module/lib/event-emitter.js +80 -0
  100. package/lib/module/lib/event-emitter.js.map +1 -0
  101. package/lib/module/lib/index.js +6 -0
  102. package/lib/module/lib/index.js.map +1 -0
  103. package/lib/module/lib/kwik-id-rn-sdk.js +150 -0
  104. package/lib/module/lib/kwik-id-rn-sdk.js.map +1 -0
  105. package/lib/module/lib/verification-machine.js +268 -0
  106. package/lib/module/lib/verification-machine.js.map +1 -0
  107. package/lib/module/package.json +1 -0
  108. package/lib/module/types/events.js +4 -0
  109. package/lib/module/types/events.js.map +1 -0
  110. package/lib/module/types/index.js +2 -0
  111. package/lib/module/types/index.js.map +1 -0
  112. package/lib/module/ui/components/KwikIDVerificationModal.js +402 -0
  113. package/lib/module/ui/components/KwikIDVerificationModal.js.map +1 -0
  114. package/lib/module/ui/components/screens.js +328 -0
  115. package/lib/module/ui/components/screens.js.map +1 -0
  116. package/lib/module/ui/context/kwik-id-provider.js +46 -0
  117. package/lib/module/ui/context/kwik-id-provider.js.map +1 -0
  118. package/lib/module/ui/hooks/use-kwik-verification.js +72 -0
  119. package/lib/module/ui/hooks/use-kwik-verification.js.map +1 -0
  120. package/lib/module/ui/index.js +6 -0
  121. package/lib/module/ui/index.js.map +1 -0
  122. package/lib/typescript/commonjs/api/api-client.d.ts +82 -0
  123. package/lib/typescript/commonjs/api/api-client.d.ts.map +1 -0
  124. package/lib/typescript/commonjs/api/api-error.d.ts +13 -0
  125. package/lib/typescript/commonjs/api/api-error.d.ts.map +1 -0
  126. package/lib/typescript/commonjs/api/index.d.ts +6 -0
  127. package/lib/typescript/commonjs/api/index.d.ts.map +1 -0
  128. package/lib/typescript/commonjs/api/upload.d.ts +19 -0
  129. package/lib/typescript/commonjs/api/upload.d.ts.map +1 -0
  130. package/lib/typescript/commonjs/camera/camera-view.d.ts +25 -0
  131. package/lib/typescript/commonjs/camera/camera-view.d.ts.map +1 -0
  132. package/lib/typescript/commonjs/camera/index.d.ts +5 -0
  133. package/lib/typescript/commonjs/camera/index.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/camera/photo-capture.d.ts +9 -0
  135. package/lib/typescript/commonjs/camera/photo-capture.d.ts.map +1 -0
  136. package/lib/typescript/commonjs/crypto/fingerprint.d.ts +3 -0
  137. package/lib/typescript/commonjs/crypto/fingerprint.d.ts.map +1 -0
  138. package/lib/typescript/commonjs/crypto/hmac.d.ts +18 -0
  139. package/lib/typescript/commonjs/crypto/hmac.d.ts.map +1 -0
  140. package/lib/typescript/commonjs/crypto/index.d.ts +4 -0
  141. package/lib/typescript/commonjs/crypto/index.d.ts.map +1 -0
  142. package/lib/typescript/commonjs/crypto/session-manager.d.ts +27 -0
  143. package/lib/typescript/commonjs/crypto/session-manager.d.ts.map +1 -0
  144. package/lib/typescript/commonjs/i18n/en.d.ts +291 -0
  145. package/lib/typescript/commonjs/i18n/en.d.ts.map +1 -0
  146. package/lib/typescript/commonjs/i18n/fr.d.ts +6 -0
  147. package/lib/typescript/commonjs/i18n/fr.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/i18n/index.d.ts +10 -0
  149. package/lib/typescript/commonjs/i18n/index.d.ts.map +1 -0
  150. package/lib/typescript/commonjs/i18n/locale.d.ts +4 -0
  151. package/lib/typescript/commonjs/i18n/locale.d.ts.map +1 -0
  152. package/lib/typescript/commonjs/i18n/translator.d.ts +15 -0
  153. package/lib/typescript/commonjs/i18n/translator.d.ts.map +1 -0
  154. package/lib/typescript/commonjs/index.d.ts +24 -0
  155. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  156. package/lib/typescript/commonjs/lib/device-detector.d.ts +5 -0
  157. package/lib/typescript/commonjs/lib/device-detector.d.ts.map +1 -0
  158. package/lib/typescript/commonjs/lib/event-emitter.d.ts +19 -0
  159. package/lib/typescript/commonjs/lib/event-emitter.d.ts.map +1 -0
  160. package/lib/typescript/commonjs/lib/index.d.ts +5 -0
  161. package/lib/typescript/commonjs/lib/index.d.ts.map +1 -0
  162. package/lib/typescript/commonjs/lib/kwik-id-rn-sdk.d.ts +43 -0
  163. package/lib/typescript/commonjs/lib/kwik-id-rn-sdk.d.ts.map +1 -0
  164. package/lib/typescript/commonjs/lib/verification-machine.d.ts +78 -0
  165. package/lib/typescript/commonjs/lib/verification-machine.d.ts.map +1 -0
  166. package/lib/typescript/commonjs/package.json +1 -0
  167. package/lib/typescript/commonjs/types/events.d.ts +94 -0
  168. package/lib/typescript/commonjs/types/events.d.ts.map +1 -0
  169. package/lib/typescript/commonjs/types/index.d.ts +242 -0
  170. package/lib/typescript/commonjs/types/index.d.ts.map +1 -0
  171. package/lib/typescript/commonjs/ui/components/KwikIDVerificationModal.d.ts +21 -0
  172. package/lib/typescript/commonjs/ui/components/KwikIDVerificationModal.d.ts.map +1 -0
  173. package/lib/typescript/commonjs/ui/components/screens.d.ts +46 -0
  174. package/lib/typescript/commonjs/ui/components/screens.d.ts.map +1 -0
  175. package/lib/typescript/commonjs/ui/context/kwik-id-provider.d.ts +19 -0
  176. package/lib/typescript/commonjs/ui/context/kwik-id-provider.d.ts.map +1 -0
  177. package/lib/typescript/commonjs/ui/hooks/use-kwik-verification.d.ts +29 -0
  178. package/lib/typescript/commonjs/ui/hooks/use-kwik-verification.d.ts.map +1 -0
  179. package/lib/typescript/commonjs/ui/index.d.ts +7 -0
  180. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -0
  181. package/lib/typescript/module/api/api-client.d.ts +82 -0
  182. package/lib/typescript/module/api/api-client.d.ts.map +1 -0
  183. package/lib/typescript/module/api/api-error.d.ts +13 -0
  184. package/lib/typescript/module/api/api-error.d.ts.map +1 -0
  185. package/lib/typescript/module/api/index.d.ts +6 -0
  186. package/lib/typescript/module/api/index.d.ts.map +1 -0
  187. package/lib/typescript/module/api/upload.d.ts +19 -0
  188. package/lib/typescript/module/api/upload.d.ts.map +1 -0
  189. package/lib/typescript/module/camera/camera-view.d.ts +25 -0
  190. package/lib/typescript/module/camera/camera-view.d.ts.map +1 -0
  191. package/lib/typescript/module/camera/index.d.ts +5 -0
  192. package/lib/typescript/module/camera/index.d.ts.map +1 -0
  193. package/lib/typescript/module/camera/photo-capture.d.ts +9 -0
  194. package/lib/typescript/module/camera/photo-capture.d.ts.map +1 -0
  195. package/lib/typescript/module/crypto/fingerprint.d.ts +3 -0
  196. package/lib/typescript/module/crypto/fingerprint.d.ts.map +1 -0
  197. package/lib/typescript/module/crypto/hmac.d.ts +18 -0
  198. package/lib/typescript/module/crypto/hmac.d.ts.map +1 -0
  199. package/lib/typescript/module/crypto/index.d.ts +4 -0
  200. package/lib/typescript/module/crypto/index.d.ts.map +1 -0
  201. package/lib/typescript/module/crypto/session-manager.d.ts +27 -0
  202. package/lib/typescript/module/crypto/session-manager.d.ts.map +1 -0
  203. package/lib/typescript/module/i18n/en.d.ts +291 -0
  204. package/lib/typescript/module/i18n/en.d.ts.map +1 -0
  205. package/lib/typescript/module/i18n/fr.d.ts +6 -0
  206. package/lib/typescript/module/i18n/fr.d.ts.map +1 -0
  207. package/lib/typescript/module/i18n/index.d.ts +10 -0
  208. package/lib/typescript/module/i18n/index.d.ts.map +1 -0
  209. package/lib/typescript/module/i18n/locale.d.ts +4 -0
  210. package/lib/typescript/module/i18n/locale.d.ts.map +1 -0
  211. package/lib/typescript/module/i18n/translator.d.ts +15 -0
  212. package/lib/typescript/module/i18n/translator.d.ts.map +1 -0
  213. package/lib/typescript/module/index.d.ts +24 -0
  214. package/lib/typescript/module/index.d.ts.map +1 -0
  215. package/lib/typescript/module/lib/device-detector.d.ts +5 -0
  216. package/lib/typescript/module/lib/device-detector.d.ts.map +1 -0
  217. package/lib/typescript/module/lib/event-emitter.d.ts +19 -0
  218. package/lib/typescript/module/lib/event-emitter.d.ts.map +1 -0
  219. package/lib/typescript/module/lib/index.d.ts +5 -0
  220. package/lib/typescript/module/lib/index.d.ts.map +1 -0
  221. package/lib/typescript/module/lib/kwik-id-rn-sdk.d.ts +43 -0
  222. package/lib/typescript/module/lib/kwik-id-rn-sdk.d.ts.map +1 -0
  223. package/lib/typescript/module/lib/verification-machine.d.ts +78 -0
  224. package/lib/typescript/module/lib/verification-machine.d.ts.map +1 -0
  225. package/lib/typescript/module/package.json +1 -0
  226. package/lib/typescript/module/types/events.d.ts +94 -0
  227. package/lib/typescript/module/types/events.d.ts.map +1 -0
  228. package/lib/typescript/module/types/index.d.ts +242 -0
  229. package/lib/typescript/module/types/index.d.ts.map +1 -0
  230. package/lib/typescript/module/ui/components/KwikIDVerificationModal.d.ts +21 -0
  231. package/lib/typescript/module/ui/components/KwikIDVerificationModal.d.ts.map +1 -0
  232. package/lib/typescript/module/ui/components/screens.d.ts +46 -0
  233. package/lib/typescript/module/ui/components/screens.d.ts.map +1 -0
  234. package/lib/typescript/module/ui/context/kwik-id-provider.d.ts +19 -0
  235. package/lib/typescript/module/ui/context/kwik-id-provider.d.ts.map +1 -0
  236. package/lib/typescript/module/ui/hooks/use-kwik-verification.d.ts +29 -0
  237. package/lib/typescript/module/ui/hooks/use-kwik-verification.d.ts.map +1 -0
  238. package/lib/typescript/module/ui/index.d.ts +7 -0
  239. package/lib/typescript/module/ui/index.d.ts.map +1 -0
  240. package/package.json +121 -3
  241. package/src/api/api-client.ts +319 -0
  242. package/src/api/api-error.ts +28 -0
  243. package/src/api/index.ts +12 -0
  244. package/src/api/upload.ts +87 -0
  245. package/src/camera/camera-view.tsx +217 -0
  246. package/src/camera/index.ts +4 -0
  247. package/src/camera/photo-capture.ts +58 -0
  248. package/src/crypto/fingerprint.ts +46 -0
  249. package/src/crypto/hmac.ts +172 -0
  250. package/src/crypto/index.ts +3 -0
  251. package/src/crypto/session-manager.ts +200 -0
  252. package/src/i18n/en.ts +315 -0
  253. package/src/i18n/fr.ts +325 -0
  254. package/src/i18n/index.ts +9 -0
  255. package/src/i18n/locale.ts +15 -0
  256. package/src/i18n/translator.ts +37 -0
  257. package/src/index.ts +102 -0
  258. package/src/lib/device-detector.ts +32 -0
  259. package/src/lib/event-emitter.ts +90 -0
  260. package/src/lib/index.ts +15 -0
  261. package/src/lib/kwik-id-rn-sdk.ts +160 -0
  262. package/src/lib/verification-machine.ts +273 -0
  263. package/src/types/events.ts +75 -0
  264. package/src/types/index.ts +309 -0
  265. package/src/ui/components/KwikIDVerificationModal.tsx +450 -0
  266. package/src/ui/components/screens.tsx +283 -0
  267. package/src/ui/context/kwik-id-provider.tsx +72 -0
  268. package/src/ui/hooks/use-kwik-verification.ts +121 -0
  269. package/src/ui/index.ts +9 -0
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Presentational step screens for the Phase 1 verification flow.
3
+ * Plain RN components (no reanimated yet) — kept simple and theme-driven.
4
+ */
5
+ import {
6
+ ActivityIndicator,
7
+ Image,
8
+ Pressable,
9
+ ScrollView,
10
+ StyleSheet,
11
+ Text,
12
+ View,
13
+ } from "react-native";
14
+
15
+ import type { MessageKey, Translate } from "../../i18n";
16
+ import type { CaptureAsset, DocumentType } from "../../types";
17
+
18
+ export interface Theme {
19
+ primary: string;
20
+ background: string;
21
+ foreground: string;
22
+ }
23
+
24
+ const DOC_LABEL_KEYS: Record<DocumentType, MessageKey> = {
25
+ id_card: "documentType.idCard",
26
+ passport: "documentType.passport",
27
+ drivers_license: "documentType.driversLicense",
28
+ voters_card: "documentType.votersCard",
29
+ residence_permit: "documentType.residencePermit",
30
+ };
31
+
32
+ function docLabel(type: DocumentType, t: Translate): string {
33
+ return t(DOC_LABEL_KEYS[type]);
34
+ }
35
+
36
+ function PrimaryButton({
37
+ label,
38
+ onPress,
39
+ theme,
40
+ }: {
41
+ label: string;
42
+ onPress: () => void;
43
+ theme: Theme;
44
+ }) {
45
+ return (
46
+ <Pressable style={[styles.btn, { backgroundColor: theme.primary }]} onPress={onPress}>
47
+ <Text style={styles.btnText}>{label}</Text>
48
+ </Pressable>
49
+ );
50
+ }
51
+
52
+ export function IntroScreen({
53
+ orgName,
54
+ onNext,
55
+ theme,
56
+ t,
57
+ }: {
58
+ orgName?: string;
59
+ onNext: () => void;
60
+ theme: Theme;
61
+ t: Translate;
62
+ }) {
63
+ return (
64
+ <View style={styles.screen}>
65
+ <Text style={[styles.h1, { color: theme.foreground }]}>{t("intro.title")}</Text>
66
+ <Text style={styles.body}>
67
+ {orgName ? `${t("intro.orgUsesKwikID", { orgName })} ` : ""}
68
+ {t("intro.bodyMobile")}
69
+ </Text>
70
+ <View style={styles.spacer} />
71
+ <PrimaryButton label={t("intro.getStarted")} onPress={onNext} theme={theme} />
72
+ </View>
73
+ );
74
+ }
75
+
76
+ export function DocumentTypeScreen({
77
+ allowed,
78
+ onSelect,
79
+ theme,
80
+ t,
81
+ }: {
82
+ allowed: DocumentType[];
83
+ onSelect: (doc: DocumentType) => void;
84
+ theme: Theme;
85
+ t: Translate;
86
+ }) {
87
+ return (
88
+ <ScrollView contentContainerStyle={styles.screen}>
89
+ <Text style={[styles.h1, { color: theme.foreground }]}>
90
+ {t("documentType.chooseTitle")}
91
+ </Text>
92
+ {allowed.map((doc) => (
93
+ <Pressable
94
+ key={doc}
95
+ style={styles.docRow}
96
+ onPress={() => onSelect(doc)}
97
+ accessibilityRole="button"
98
+ >
99
+ <Text style={[styles.docLabel, { color: theme.foreground }]}>
100
+ {docLabel(doc, t)}
101
+ </Text>
102
+ <Text style={[styles.chevron, { color: theme.primary }]}>›</Text>
103
+ </Pressable>
104
+ ))}
105
+ </ScrollView>
106
+ );
107
+ }
108
+
109
+ const PREPARE_COPY_KEYS: Record<
110
+ "front" | "back" | "selfie",
111
+ { title: MessageKey; body: MessageKey }
112
+ > = {
113
+ front: { title: "prepareFront.titleMobile", body: "prepareFront.bodyMobile" },
114
+ back: { title: "prepareBack.titleMobile", body: "prepareBack.bodyMobile" },
115
+ selfie: { title: "prepareSelfie.titleMobile", body: "prepareSelfie.bodyMobile" },
116
+ };
117
+
118
+ export function PrepareScreen({
119
+ kind,
120
+ onNext,
121
+ theme,
122
+ t,
123
+ }: {
124
+ kind: "front" | "back" | "selfie";
125
+ onNext: () => void;
126
+ theme: Theme;
127
+ t: Translate;
128
+ }) {
129
+ const copy = PREPARE_COPY_KEYS[kind];
130
+ return (
131
+ <View style={styles.screen}>
132
+ <Text style={[styles.h1, { color: theme.foreground }]}>{t(copy.title)}</Text>
133
+ <Text style={styles.body}>{t(copy.body)}</Text>
134
+ <View style={styles.spacer} />
135
+ <PrimaryButton label={t("common.imReady")} onPress={onNext} theme={theme} />
136
+ </View>
137
+ );
138
+ }
139
+
140
+ export function ConfirmScreen({
141
+ asset,
142
+ onConfirm,
143
+ onRetake,
144
+ theme,
145
+ t,
146
+ }: {
147
+ asset: CaptureAsset;
148
+ onConfirm: () => void;
149
+ onRetake: () => void;
150
+ theme: Theme;
151
+ t: Translate;
152
+ }) {
153
+ return (
154
+ <View style={styles.screen}>
155
+ <Text style={[styles.h1, { color: theme.foreground }]}>
156
+ {t("confirm.looksGoodTitle")}
157
+ </Text>
158
+ <Image source={{ uri: asset.uri }} style={styles.preview} resizeMode="contain" />
159
+ <View style={styles.spacer} />
160
+ <PrimaryButton label={t("confirm.useThisPhoto")} onPress={onConfirm} theme={theme} />
161
+ <Pressable style={styles.linkBtn} onPress={onRetake}>
162
+ <Text style={[styles.linkText, { color: theme.primary }]}>
163
+ {t("common.retake")}
164
+ </Text>
165
+ </Pressable>
166
+ </View>
167
+ );
168
+ }
169
+
170
+ export function ProcessingScreen({
171
+ progress,
172
+ stage,
173
+ theme,
174
+ t,
175
+ }: {
176
+ progress: number;
177
+ stage: string | null;
178
+ theme: Theme;
179
+ t: Translate;
180
+ }) {
181
+ const label =
182
+ stage === "submitting"
183
+ ? t("processing.submitting")
184
+ : stage === "document_front"
185
+ ? t("processing.uploadingFront")
186
+ : stage === "document_back"
187
+ ? t("processing.uploadingBack")
188
+ : stage === "selfie"
189
+ ? t("processing.uploadingSelfie")
190
+ : t("processing.working");
191
+ return (
192
+ <View style={styles.center}>
193
+ <ActivityIndicator size="large" color={theme.primary} />
194
+ <Text style={[styles.body, { marginTop: 16 }]}>{label}</Text>
195
+ <View style={styles.progressTrack}>
196
+ <View
197
+ style={[
198
+ styles.progressFill,
199
+ { width: `${progress}%`, backgroundColor: theme.primary },
200
+ ]}
201
+ />
202
+ </View>
203
+ </View>
204
+ );
205
+ }
206
+
207
+ export function ResultScreen({
208
+ success,
209
+ message,
210
+ onDone,
211
+ theme,
212
+ t,
213
+ }: {
214
+ success: boolean;
215
+ message: string;
216
+ onDone: () => void;
217
+ theme: Theme;
218
+ t: Translate;
219
+ }) {
220
+ return (
221
+ <View style={styles.center}>
222
+ <View
223
+ style={[styles.resultBadge, { backgroundColor: success ? "#16a34a" : "#dc2626" }]}
224
+ >
225
+ <Text style={styles.resultIcon}>{success ? "✓" : "!"}</Text>
226
+ </View>
227
+ <Text
228
+ style={[styles.h1, { color: theme.foreground, textAlign: "center", marginTop: 16 }]}
229
+ >
230
+ {t(success ? "result.submittedShort" : "result.somethingWrong")}
231
+ </Text>
232
+ <Text style={[styles.body, { textAlign: "center" }]}>{message}</Text>
233
+ <View style={styles.spacer} />
234
+ <PrimaryButton label={t("common.done")} onPress={onDone} theme={theme} />
235
+ </View>
236
+ );
237
+ }
238
+
239
+ const styles = StyleSheet.create({
240
+ screen: { flex: 1, padding: 24 },
241
+ center: { flex: 1, padding: 24, alignItems: "center", justifyContent: "center" },
242
+ h1: { fontSize: 22, fontWeight: "700", marginBottom: 12 },
243
+ body: { fontSize: 15, lineHeight: 22, color: "#4b5563" },
244
+ spacer: { flex: 1, minHeight: 24 },
245
+ btn: { borderRadius: 12, paddingVertical: 16, alignItems: "center" },
246
+ btnText: { color: "#fff", fontSize: 16, fontWeight: "600" },
247
+ linkBtn: { paddingVertical: 14, alignItems: "center" },
248
+ linkText: { fontSize: 15, fontWeight: "600" },
249
+ docRow: {
250
+ flexDirection: "row",
251
+ alignItems: "center",
252
+ justifyContent: "space-between",
253
+ paddingVertical: 18,
254
+ borderBottomWidth: 1,
255
+ borderBottomColor: "#eee",
256
+ },
257
+ docLabel: { fontSize: 16, fontWeight: "500" },
258
+ chevron: { fontSize: 24, fontWeight: "300" },
259
+ preview: {
260
+ flex: 1,
261
+ width: "100%",
262
+ marginVertical: 16,
263
+ borderRadius: 12,
264
+ backgroundColor: "#f3f4f6",
265
+ },
266
+ progressTrack: {
267
+ width: "80%",
268
+ height: 6,
269
+ borderRadius: 3,
270
+ backgroundColor: "#e5e7eb",
271
+ marginTop: 20,
272
+ overflow: "hidden",
273
+ },
274
+ progressFill: { height: 6, borderRadius: 3 },
275
+ resultBadge: {
276
+ width: 64,
277
+ height: 64,
278
+ borderRadius: 32,
279
+ alignItems: "center",
280
+ justifyContent: "center",
281
+ },
282
+ resultIcon: { color: "#fff", fontSize: 32, fontWeight: "700" },
283
+ });
@@ -0,0 +1,72 @@
1
+ /**
2
+ * KwikIDProvider / useKwikID — optional context for advanced integrations that want
3
+ * to share a single SDK instance + theme across custom screens. The imperative
4
+ * `useKwikVerification` hook does NOT require this provider.
5
+ */
6
+ import { createContext, createElement, useContext, useEffect, useMemo, useState } from "react";
7
+
8
+ import { KwikIdRNSDK } from "../../lib/kwik-id-rn-sdk";
9
+ import type {
10
+ DocumentType,
11
+ KwikIdConfig,
12
+ KwikIdTheme,
13
+ LivenessMode,
14
+ SessionInfo,
15
+ } from "../../types";
16
+
17
+ export interface KwikIDContextValue {
18
+ sdk: KwikIdRNSDK;
19
+ sessionInfo: SessionInfo | null;
20
+ orgName?: string;
21
+ allowedDocumentTypes: DocumentType[];
22
+ livenessMode: LivenessMode;
23
+ theme: KwikIdTheme;
24
+ }
25
+
26
+ const KwikIDContext = createContext<KwikIDContextValue | null>(null);
27
+
28
+ export interface KwikIDProviderProps {
29
+ config: KwikIdConfig;
30
+ /** Initialize the session immediately on mount (default true). */
31
+ autoInitialize?: boolean;
32
+ children: React.ReactNode;
33
+ }
34
+
35
+ export function KwikIDProvider({ config, autoInitialize = true, children }: KwikIDProviderProps) {
36
+ const sdk = useMemo(() => new KwikIdRNSDK(config), [config]);
37
+ const [sessionInfo, setSessionInfo] = useState<SessionInfo | null>(null);
38
+
39
+ useEffect(() => {
40
+ if (!autoInitialize) return;
41
+ let active = true;
42
+ sdk.initialize()
43
+ .then((info) => active && setSessionInfo(info))
44
+ .catch(() => undefined);
45
+ return () => {
46
+ active = false;
47
+ sdk.destroy();
48
+ };
49
+ }, [sdk, autoInitialize]);
50
+
51
+ const value = useMemo<KwikIDContextValue>(
52
+ () => ({
53
+ sdk,
54
+ sessionInfo,
55
+ orgName: sessionInfo?.orgName,
56
+ allowedDocumentTypes: sessionInfo?.config.documentTypes ?? [],
57
+ livenessMode: config.livenessMode ?? sessionInfo?.config.livenessMode ?? "passive",
58
+ theme: config.theme ?? {},
59
+ }),
60
+ [sdk, sessionInfo, config.livenessMode, config.theme]
61
+ );
62
+
63
+ return createElement(KwikIDContext.Provider, { value }, children);
64
+ }
65
+
66
+ export function useKwikID(): KwikIDContextValue {
67
+ const ctx = useContext(KwikIDContext);
68
+ if (!ctx) {
69
+ throw new Error("useKwikID must be used within a <KwikIDProvider>");
70
+ }
71
+ return ctx;
72
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * useKwikVerification — imperative entry point (RN analog of the web
3
+ * `openKwikVerification`). Render `<kyc.Modal />` once, then `await kyc.start()`.
4
+ */
5
+ import { createElement, useCallback, useMemo, useRef, useSyncExternalStore } from "react";
6
+
7
+ import type {
8
+ DocumentType,
9
+ KwikIdTheme,
10
+ LivenessMode,
11
+ Locale,
12
+ VerificationOutcome,
13
+ } from "../../types";
14
+ import { KwikIDVerificationModal } from "../components/KwikIDVerificationModal";
15
+
16
+ export interface UseKwikVerificationOptions {
17
+ clientSecret: string;
18
+ baseUrl?: string;
19
+ appName?: string;
20
+ theme?: KwikIdTheme;
21
+ locale?: Locale;
22
+ /**
23
+ * @deprecated Not yet supported: accepted for forward compatibility but ignored.
24
+ * Phase 1 is capture-only; on-device liveness (and this option) lands in Phase 2.
25
+ */
26
+ livenessMode?: LivenessMode;
27
+ documentTypes?: DocumentType[];
28
+ skipRuntimeCheck?: boolean;
29
+ onSubmitted?: (data: { jobId: string }) => void;
30
+ }
31
+
32
+ export interface UseKwikVerification {
33
+ /** Open the flow; resolves when the user reaches a terminal state. */
34
+ start: () => Promise<VerificationOutcome>;
35
+ /** Programmatically dismiss (resolves a pending start() as cancelled). */
36
+ cancel: () => void;
37
+ isOpen: boolean;
38
+ /** Render this once in your tree; the verification UI mounts here. */
39
+ Modal: React.FC;
40
+ }
41
+
42
+ interface Store {
43
+ open: boolean;
44
+ resolve: ((o: VerificationOutcome) => void) | null;
45
+ listeners: Set<() => void>;
46
+ }
47
+
48
+ export function useKwikVerification(options: UseKwikVerificationOptions): UseKwikVerification {
49
+ const storeRef = useRef<Store>(undefined as unknown as Store);
50
+ if (!storeRef.current) {
51
+ storeRef.current = { open: false, resolve: null, listeners: new Set() };
52
+ }
53
+ const store = storeRef.current;
54
+
55
+ const optionsRef = useRef(options);
56
+ optionsRef.current = options;
57
+
58
+ const subscribe = useCallback(
59
+ (cb: () => void) => {
60
+ store.listeners.add(cb);
61
+ return () => store.listeners.delete(cb);
62
+ },
63
+ [store]
64
+ );
65
+ const getSnapshot = useCallback(() => store.open, [store]);
66
+
67
+ const setOpen = useCallback(
68
+ (v: boolean) => {
69
+ store.open = v;
70
+ store.listeners.forEach((l) => l());
71
+ },
72
+ [store]
73
+ );
74
+
75
+ const start = useCallback(
76
+ () =>
77
+ new Promise<VerificationOutcome>((resolve) => {
78
+ store.resolve = resolve;
79
+ setOpen(true);
80
+ }),
81
+ [store, setOpen]
82
+ );
83
+
84
+ const finish = useCallback(
85
+ (outcome: VerificationOutcome) => {
86
+ setOpen(false);
87
+ const resolve = store.resolve;
88
+ store.resolve = null;
89
+ resolve?.(outcome);
90
+ },
91
+ [store, setOpen]
92
+ );
93
+
94
+ const cancel = useCallback(() => finish({ status: "cancelled" }), [finish]);
95
+
96
+ const isOpen = useSyncExternalStore(subscribe, getSnapshot);
97
+
98
+ const Modal = useMemo<React.FC>(() => {
99
+ const KwikModal: React.FC = () => {
100
+ const open = useSyncExternalStore(subscribe, getSnapshot);
101
+ const o = optionsRef.current;
102
+ return createElement(KwikIDVerificationModal, {
103
+ visible: open,
104
+ clientSecret: o.clientSecret,
105
+ baseUrl: o.baseUrl,
106
+ appName: o.appName,
107
+ theme: o.theme,
108
+ locale: o.locale,
109
+ documentTypes: o.documentTypes,
110
+ skipRuntimeCheck: o.skipRuntimeCheck,
111
+ onSubmitted: o.onSubmitted,
112
+ onComplete: finish,
113
+ onClose: () => undefined,
114
+ });
115
+ };
116
+ KwikModal.displayName = "KwikIDModal";
117
+ return KwikModal;
118
+ }, [subscribe, getSnapshot, finish]);
119
+
120
+ return { start, cancel, isOpen, Modal };
121
+ }
@@ -0,0 +1,9 @@
1
+ export { KwikIDVerificationModal } from "./components/KwikIDVerificationModal";
2
+ export type { KwikIDVerificationModalProps } from "./components/KwikIDVerificationModal";
3
+ export { useKwikVerification } from "./hooks/use-kwik-verification";
4
+ export type {
5
+ UseKwikVerification,
6
+ UseKwikVerificationOptions,
7
+ } from "./hooks/use-kwik-verification";
8
+ export { KwikIDProvider, useKwikID } from "./context/kwik-id-provider";
9
+ export type { KwikIDProviderProps, KwikIDContextValue } from "./context/kwik-id-provider";