@myazahq/kyc-sdk-react-native 2.4.0 → 2.5.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.
- package/android/build.gradle +35 -3
- package/android/src/main/java/com/margelo/nitro/myazakyc/HybridMyazaFaceDetector.kt +75 -0
- package/ios/HybridMyazaFaceDetector.swift +8 -0
- package/nitrogen/generated/android/c++/JHybridMyazaFaceDetectorSpec.cpp +23 -0
- package/nitrogen/generated/android/c++/JHybridMyazaFaceDetectorSpec.hpp +2 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/myazakyc/HybridMyazaFaceDetectorSpec.kt +9 -0
- package/nitrogen/generated/ios/KycSdkReactNative-Swift-Cxx-Bridge.cpp +8 -0
- package/nitrogen/generated/ios/KycSdkReactNative-Swift-Cxx-Bridge.hpp +43 -0
- package/nitrogen/generated/ios/c++/HybridMyazaFaceDetectorSpecSwift.hpp +17 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridMyazaFaceDetectorSpec.swift +2 -0
- package/nitrogen/generated/ios/swift/HybridMyazaFaceDetectorSpec_cxx.swift +31 -0
- package/nitrogen/generated/shared/c++/HybridMyazaFaceDetectorSpec.cpp +2 -0
- package/nitrogen/generated/shared/c++/HybridMyazaFaceDetectorSpec.hpp +3 -0
- package/package.json +1 -1
- package/src/MyazaKYC.tsx +12 -0
- package/src/components/DashedBorder.tsx +55 -0
- package/src/components/DialCodePicker.tsx +14 -7
- package/src/components/Icon.tsx +9 -0
- package/src/components/MultiIdProgress.tsx +107 -0
- package/src/components/MyazaInput.tsx +23 -4
- package/src/components/MyazaSelect.tsx +2 -1
- package/src/components/OwnershipSlider.tsx +102 -0
- package/src/components/PhoneNumberInput.tsx +37 -4
- package/src/components/StaggerIn.tsx +63 -0
- package/src/components/StepView.tsx +26 -0
- package/src/components/glass/FloatingSheet.tsx +73 -21
- package/src/components/glass/GlassSheet.tsx +14 -2
- package/src/components/stepHeaderMeta.tsx +3 -1
- package/src/config/business.ts +6 -6
- package/src/config/businessDetailsValidity.ts +52 -0
- package/src/config/businessPrefill.ts +72 -0
- package/src/config/businessSteps.ts +14 -3
- package/src/config/keyPeople.ts +111 -7
- package/src/config/keyPeopleCorporate.ts +19 -0
- package/src/config/keyPeopleOwnerTypes.ts +12 -0
- package/src/config/keyPeopleOwners.ts +26 -0
- package/src/config/keyPeoplePrefill.ts +138 -0
- package/src/config/keyPeopleSectionDefs.ts +65 -0
- package/src/config/keyPeopleSections.ts +167 -0
- package/src/config/registrationHint.ts +1 -1
- package/src/config/stepOrder.ts +24 -4
- package/src/config/theme.ts +8 -2
- package/src/config/website.ts +36 -0
- package/src/config/workflowMerge.ts +5 -0
- package/src/emrtd/activeAuth.ts +100 -0
- package/src/emrtd/extras.ts +76 -0
- package/src/emrtd/files.ts +5 -0
- package/src/emrtd/index.ts +1 -0
- package/src/emrtd/read.ts +8 -1
- package/src/emrtd/session.ts +41 -0
- package/src/emrtd/stages.ts +11 -0
- package/src/lib/contact-recovery.ts +44 -0
- package/src/lib/multi-id.ts +210 -0
- package/src/lib/resubmit.ts +130 -0
- package/src/lib/screen-corners.ts +50 -0
- package/src/lib/step-log.ts +24 -3
- package/src/lib/use-multi-id-plan.ts +29 -0
- package/src/liveness/useModelReady.ts +65 -0
- package/src/liveness/visionCameraFaceDetector.ts +35 -0
- package/src/screens/ApplicantRoleStep.tsx +9 -5
- package/src/screens/BusinessCheckPanel.tsx +89 -0
- package/src/screens/BusinessDetailsFields.tsx +109 -0
- package/src/screens/BusinessDetailsStep.tsx +131 -145
- package/src/screens/BusinessDocumentSlot.tsx +2 -3
- package/src/screens/BusinessDocumentsStep.tsx +1 -1
- package/src/screens/BusinessKeyPeopleStep.tsx +103 -71
- package/src/screens/BusinessPickedCard.tsx +86 -0
- package/src/screens/BusinessPickedSection.tsx +51 -0
- package/src/screens/BusinessRegistryPickers.tsx +67 -0
- package/src/screens/BusinessSandboxToggle.tsx +114 -0
- package/src/screens/BusinessSearch.tsx +199 -0
- package/src/screens/BusinessSearchResults.tsx +115 -0
- package/src/screens/CompanyInfoFields.tsx +86 -51
- package/src/screens/ConsentStep.tsx +31 -0
- package/src/screens/ContactDestinationField.tsx +1 -0
- package/src/screens/ContactVerificationStep.tsx +34 -3
- package/src/screens/IdTypeStep.tsx +12 -5
- package/src/screens/KeepLinksSheet.tsx +88 -0
- package/src/screens/KeyPeopleAwaitCard.tsx +204 -0
- package/src/screens/KeyPeopleAwaitList.tsx +126 -0
- package/src/screens/KeyPeoplePending.tsx +154 -0
- package/src/screens/KeyPeopleSection.tsx +162 -0
- package/src/screens/KeyPeopleSectionsList.tsx +103 -0
- package/src/screens/KeyPeopleUboExemption.tsx +72 -0
- package/src/screens/KeyPersonCard.tsx +36 -4
- package/src/screens/KeyPersonForm.tsx +195 -36
- package/src/screens/KeyPersonKindToggle.tsx +68 -0
- package/src/screens/KeyPersonOwners.tsx +109 -0
- package/src/screens/KeyPersonRoleChips.tsx +68 -0
- package/src/screens/KeyPersonSheet.tsx +92 -108
- package/src/screens/LivenessStep.tsx +18 -0
- package/src/screens/NfcStep.tsx +14 -0
- package/src/screens/ProofOfAddressStep.tsx +6 -3
- package/src/screens/SubmittedStep.tsx +66 -10
- package/src/screens/nfc/NfcReadProgress.tsx +1 -0
- package/src/screens/useAwaitingPeople.ts +90 -0
- package/src/services/api-types.ts +158 -2
- package/src/services/api-verify-types.ts +53 -1
- package/src/services/api.ts +104 -0
- package/src/services/deviceMetadata.ts +1 -1
- package/src/services/errors.ts +10 -2
- package/src/services/workflowGate.ts +1 -0
- package/src/specs/MyazaFaceDetector.nitro.ts +29 -0
- package/src/store/businessCheck.ts +113 -0
- package/src/store/derive.ts +15 -0
- package/src/store/kycStore.ts +241 -14
- package/src/store/serverConfig.ts +2 -0
- package/src/store/session.ts +208 -0
- package/src/store/state.ts +155 -2
- package/src/store/submit.ts +63 -13
- package/src/store/submitApplicant.ts +5 -11
- package/src/types/business.ts +23 -2
- package/src/types/config.ts +22 -1
- package/src/types/verification.ts +1 -1
- package/src/types/workflow.ts +15 -0
- package/src/screens/KeyPeopleInviteLinks.tsx +0 -239
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import { Pressable, Share, View } from 'react-native';
|
|
3
|
-
import * as Clipboard from 'expo-clipboard';
|
|
4
|
-
|
|
5
|
-
import { radius, spacing } from '../config/theme';
|
|
6
|
-
import { useKyc, useTheme } from '../components/runtime';
|
|
7
|
-
import { MyazaText } from '../components/Typography';
|
|
8
|
-
import { Icon } from '../components/Icon';
|
|
9
|
-
import { CountryFlag } from '../components/CountryFlag';
|
|
10
|
-
import { regionCountryName } from '../config/regions';
|
|
11
|
-
import { KEY_PERSON_ROLE_LABELS } from '../config/keyPeople';
|
|
12
|
-
import type { KeyPersonInvite } from '../services/api-types';
|
|
13
|
-
import type { ApplicantRole, KeyPersonRole } from '../types/business';
|
|
14
|
-
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
// "Awaiting users" — the KYB success screen's people section. Every person the
|
|
17
|
-
// review is waiting on, grouped by role, each with a status pill; pending
|
|
18
|
-
// people carry a shareable verification link, and the APPLICANT (who verified
|
|
19
|
-
// in-flow) appears with a green Submitted pill so the picture is complete.
|
|
20
|
-
// Mirrors the web SDK's KeyPeopleInviteLinks 1:1 — mobile shares via the
|
|
21
|
-
// native sheet (reaches WhatsApp/SMS, still offers Copy inside).
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
|
|
24
|
-
type AwaitRole = ApplicantRole;
|
|
25
|
-
|
|
26
|
-
interface AwaitRow {
|
|
27
|
-
name: string;
|
|
28
|
-
role: AwaitRole;
|
|
29
|
-
pct: string | null;
|
|
30
|
-
country: string | null;
|
|
31
|
-
status: 'submitted' | 'pending';
|
|
32
|
-
inviteUrl?: string;
|
|
33
|
-
isApplicant?: boolean;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const ROLE_LABELS: Record<AwaitRole, string> = {
|
|
37
|
-
...KEY_PERSON_ROLE_LABELS,
|
|
38
|
-
authorized_representative: 'Authorized representative',
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const SECTIONS: Array<{ role: AwaitRole; label: string }> = [
|
|
42
|
-
{ role: 'beneficial_owner', label: 'UBOS' },
|
|
43
|
-
{ role: 'director', label: 'DIRECTORS' },
|
|
44
|
-
{ role: 'signatory', label: 'SIGNATORIES' },
|
|
45
|
-
{ role: 'shareholder', label: 'SHAREHOLDERS' },
|
|
46
|
-
{ role: 'authorized_representative', label: 'REPRESENTATIVES' },
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
export function KeyPeopleInviteLinks({
|
|
50
|
-
invites,
|
|
51
|
-
}: {
|
|
52
|
-
invites: KeyPersonInvite[];
|
|
53
|
-
}): React.ReactElement | null {
|
|
54
|
-
const { colors } = useTheme();
|
|
55
|
-
const app = useKyc((s) => s.businessApplication);
|
|
56
|
-
if (invites.length === 0) return null;
|
|
57
|
-
|
|
58
|
-
const rows: AwaitRow[] = [];
|
|
59
|
-
|
|
60
|
-
// The applicant themselves — verified in-flow, nothing more to do.
|
|
61
|
-
if (app.applicantRole) {
|
|
62
|
-
const self =
|
|
63
|
-
app.applicantKeyPersonIndex !== null ? app.keyPeople[app.applicantKeyPersonIndex] : null;
|
|
64
|
-
rows.push({
|
|
65
|
-
name: (self?.name ?? app.applicantName).trim() || 'You',
|
|
66
|
-
role: (self?.role ?? app.applicantRole) as AwaitRole,
|
|
67
|
-
pct: self?.ownershipPct.trim() || null,
|
|
68
|
-
country: self?.country.trim() ? self.country.trim().toUpperCase() : null,
|
|
69
|
-
status: 'submitted',
|
|
70
|
-
isApplicant: true,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Everyone the server minted a link for — enriched from the entered rows.
|
|
75
|
-
for (const invite of invites) {
|
|
76
|
-
const entered = app.keyPeople.find((p) => p.name.trim() === invite.name.trim());
|
|
77
|
-
rows.push({
|
|
78
|
-
name: invite.name,
|
|
79
|
-
role: (entered?.role ?? 'director') as AwaitRole,
|
|
80
|
-
pct: entered?.ownershipPct.trim() || null,
|
|
81
|
-
country: entered?.country.trim() ? entered.country.trim().toUpperCase() : null,
|
|
82
|
-
status: 'pending',
|
|
83
|
-
inviteUrl: invite.inviteUrl,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
<View style={{ width: '100%', marginTop: spacing.lg }}>
|
|
89
|
-
<MyazaText variant="bodySmall" color={colors.textMuted} style={{ textAlign: 'center', marginBottom: spacing.md }}>
|
|
90
|
-
To complete the review, the people below must verify their identity with a KYC check.
|
|
91
|
-
Anyone with an email on file has already been sent their link.
|
|
92
|
-
</MyazaText>
|
|
93
|
-
|
|
94
|
-
{SECTIONS.map(({ role, label }) => {
|
|
95
|
-
const group = rows.filter((r) => r.role === role);
|
|
96
|
-
if (group.length === 0) return null;
|
|
97
|
-
return (
|
|
98
|
-
<View key={role} style={{ marginBottom: spacing.sm }}>
|
|
99
|
-
<MyazaText
|
|
100
|
-
variant="bodySmall"
|
|
101
|
-
color={colors.textMuted}
|
|
102
|
-
style={{ fontWeight: '600', letterSpacing: 1.2, marginBottom: spacing.xs + 2 }}
|
|
103
|
-
>
|
|
104
|
-
{label}
|
|
105
|
-
</MyazaText>
|
|
106
|
-
{group.map((row, i) => (
|
|
107
|
-
<AwaitCard key={`${role}-${i}`} row={row} />
|
|
108
|
-
))}
|
|
109
|
-
</View>
|
|
110
|
-
);
|
|
111
|
-
})}
|
|
112
|
-
|
|
113
|
-
<MyazaText variant="bodySmall" color={colors.textMuted} style={{ textAlign: 'center' }}>
|
|
114
|
-
Links are valid for 14 days.
|
|
115
|
-
</MyazaText>
|
|
116
|
-
</View>
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function AwaitCard({ row }: { row: AwaitRow }): React.ReactElement {
|
|
121
|
-
const { colors } = useTheme();
|
|
122
|
-
const submitted = row.status === 'submitted';
|
|
123
|
-
const [copied, setCopied] = useState(false);
|
|
124
|
-
|
|
125
|
-
const share = (): void => {
|
|
126
|
-
if (!row.inviteUrl) return;
|
|
127
|
-
Share.share({ message: row.inviteUrl }).catch(() => undefined);
|
|
128
|
-
};
|
|
129
|
-
const copy = (): void => {
|
|
130
|
-
if (!row.inviteUrl) return;
|
|
131
|
-
Clipboard.setStringAsync(row.inviteUrl)
|
|
132
|
-
.then(() => {
|
|
133
|
-
setCopied(true);
|
|
134
|
-
setTimeout(() => setCopied(false), 2000);
|
|
135
|
-
})
|
|
136
|
-
.catch(() => undefined);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
<View
|
|
141
|
-
style={{
|
|
142
|
-
backgroundColor: colors.backgroundSecondary,
|
|
143
|
-
borderRadius: radius.md,
|
|
144
|
-
padding: spacing.md,
|
|
145
|
-
marginBottom: spacing.sm,
|
|
146
|
-
}}
|
|
147
|
-
>
|
|
148
|
-
<View style={{ flexDirection: 'row', alignItems: 'flex-start' }}>
|
|
149
|
-
<View style={{ flex: 1, minWidth: 0, marginRight: spacing.sm }}>
|
|
150
|
-
<MyazaText variant="bodyMedium" numberOfLines={1} style={{ fontWeight: '700' }}>
|
|
151
|
-
{row.name}
|
|
152
|
-
{row.isApplicant ? (
|
|
153
|
-
<MyazaText variant="bodySmall" color={colors.textMuted}>
|
|
154
|
-
{' (you)'}
|
|
155
|
-
</MyazaText>
|
|
156
|
-
) : null}
|
|
157
|
-
</MyazaText>
|
|
158
|
-
<View style={{ flexDirection: 'row', alignItems: 'center', flexWrap: 'wrap', marginTop: 2 }}>
|
|
159
|
-
<MyazaText variant="bodySmall" color={colors.textMuted}>
|
|
160
|
-
{ROLE_LABELS[row.role]}
|
|
161
|
-
{row.pct ? ` · ${row.pct}%` : ''}
|
|
162
|
-
{row.country ? ' · ' : ''}
|
|
163
|
-
</MyazaText>
|
|
164
|
-
{row.country ? (
|
|
165
|
-
<>
|
|
166
|
-
<CountryFlag country={row.country} size={14} />
|
|
167
|
-
<MyazaText variant="bodySmall" color={colors.textMuted}>
|
|
168
|
-
{` ${regionCountryName(row.country)}`}
|
|
169
|
-
</MyazaText>
|
|
170
|
-
</>
|
|
171
|
-
) : null}
|
|
172
|
-
</View>
|
|
173
|
-
</View>
|
|
174
|
-
<View
|
|
175
|
-
style={{
|
|
176
|
-
borderRadius: radius.full,
|
|
177
|
-
paddingHorizontal: spacing.sm + 4,
|
|
178
|
-
paddingVertical: spacing.xs,
|
|
179
|
-
backgroundColor: submitted ? colors.successBg : colors.primary100,
|
|
180
|
-
}}
|
|
181
|
-
>
|
|
182
|
-
<MyazaText
|
|
183
|
-
variant="bodySmall"
|
|
184
|
-
color={submitted ? colors.success : colors.primary}
|
|
185
|
-
style={{ fontWeight: '700', fontSize: 11, letterSpacing: 0.6 }}
|
|
186
|
-
>
|
|
187
|
-
{submitted ? 'SUBMITTED' : 'KYC PENDING'}
|
|
188
|
-
</MyazaText>
|
|
189
|
-
</View>
|
|
190
|
-
</View>
|
|
191
|
-
|
|
192
|
-
{row.status === 'pending' && row.inviteUrl ? (
|
|
193
|
-
// Both actions, since it's mobile: Copy for pasting anywhere, Share
|
|
194
|
-
// for the native sheet (WhatsApp/SMS directly).
|
|
195
|
-
<View style={{ flexDirection: 'row', marginTop: spacing.sm + 4 }}>
|
|
196
|
-
<Pressable
|
|
197
|
-
onPress={copy}
|
|
198
|
-
accessibilityRole="button"
|
|
199
|
-
accessibilityLabel={`Copy ${row.name}'s verification link`}
|
|
200
|
-
style={{
|
|
201
|
-
flex: 1,
|
|
202
|
-
flexDirection: 'row',
|
|
203
|
-
alignItems: 'center',
|
|
204
|
-
justifyContent: 'center',
|
|
205
|
-
backgroundColor: colors.primary100,
|
|
206
|
-
borderRadius: radius.full,
|
|
207
|
-
paddingVertical: spacing.sm + 2,
|
|
208
|
-
marginRight: spacing.sm,
|
|
209
|
-
}}
|
|
210
|
-
>
|
|
211
|
-
<Icon name={copied ? 'check' : 'copy'} size={15} color={colors.primary} />
|
|
212
|
-
<MyazaText variant="bodySmall" color={colors.primary} style={{ fontWeight: '700', marginLeft: spacing.xs + 2 }}>
|
|
213
|
-
{copied ? 'Copied' : 'Copy link'}
|
|
214
|
-
</MyazaText>
|
|
215
|
-
</Pressable>
|
|
216
|
-
<Pressable
|
|
217
|
-
onPress={share}
|
|
218
|
-
accessibilityRole="button"
|
|
219
|
-
accessibilityLabel={`Share ${row.name}'s verification link`}
|
|
220
|
-
style={{
|
|
221
|
-
flex: 1,
|
|
222
|
-
flexDirection: 'row',
|
|
223
|
-
alignItems: 'center',
|
|
224
|
-
justifyContent: 'center',
|
|
225
|
-
backgroundColor: colors.primary100,
|
|
226
|
-
borderRadius: radius.full,
|
|
227
|
-
paddingVertical: spacing.sm + 2,
|
|
228
|
-
}}
|
|
229
|
-
>
|
|
230
|
-
<Icon name="share" size={15} color={colors.primary} />
|
|
231
|
-
<MyazaText variant="bodySmall" color={colors.primary} style={{ fontWeight: '700', marginLeft: spacing.xs + 2 }}>
|
|
232
|
-
Share
|
|
233
|
-
</MyazaText>
|
|
234
|
-
</Pressable>
|
|
235
|
-
</View>
|
|
236
|
-
) : null}
|
|
237
|
-
</View>
|
|
238
|
-
);
|
|
239
|
-
}
|