@learncard/email-templates 1.0.6 → 1.2.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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/previews/credential-updated-scenarios.d.ts +9 -0
- package/dist/previews/credential-updated-scenarios.d.ts.map +1 -0
- package/dist/previews/credential-updated-scenarios.js +7 -0
- package/dist/previews/credential-updated-scenarios.js.map +1 -0
- package/dist/previews/recovery-key-scenarios.d.ts.map +1 -1
- package/dist/previews/recovery-key-scenarios.js +1 -1
- package/dist/previews/recovery-key-scenarios.js.map +1 -1
- package/dist/render.d.ts +16 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +16 -1
- package/dist/render.js.map +1 -1
- package/dist/templates/account-sign-in-changed.d.ts +11 -0
- package/dist/templates/account-sign-in-changed.d.ts.map +1 -0
- package/dist/templates/account-sign-in-changed.js +70 -0
- package/dist/templates/account-sign-in-changed.js.map +1 -0
- package/dist/templates/credential-updated.d.ts +33 -0
- package/dist/templates/credential-updated.d.ts.map +1 -0
- package/dist/templates/credential-updated.js +104 -0
- package/dist/templates/credential-updated.js.map +1 -0
- package/dist/templates/index.d.ts +7 -3
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +5 -3
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/recovery-key.d.ts +1 -0
- package/dist/templates/recovery-key.d.ts.map +1 -1
- package/dist/templates/recovery-key.js +11 -3
- package/dist/templates/recovery-key.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/i18n.test.ts +9 -2
- package/src/__tests__/render.test.ts +151 -26
- package/src/index.ts +2 -0
- package/src/previews/credential-updated-scenarios.tsx +61 -0
- package/src/previews/recovery-key-scenarios.tsx +3 -0
- package/src/render.ts +39 -0
- package/src/templates/account-sign-in-changed.tsx +113 -0
- package/src/templates/credential-updated.tsx +309 -0
- package/src/templates/index.ts +17 -3
- package/src/templates/recovery-key.tsx +26 -1
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CredentialUpdated — privacy-minimal notice that an issuer published a new
|
|
3
|
+
* version of a credential.
|
|
4
|
+
*
|
|
5
|
+
* Used by: brain-service credential-refresh publication (templateId:
|
|
6
|
+
* 'credential-updated').
|
|
7
|
+
*
|
|
8
|
+
* Deliberately minimal context: the issuer display name and the credential
|
|
9
|
+
* display title are the only dynamic values. No grades, subject/recipient
|
|
10
|
+
* details, evidence, body, or issuer-authored update summary is rendered. The
|
|
11
|
+
* CTA points at the recipient's own notifications page (never a claim URL and
|
|
12
|
+
* never a bearer token), so a forwarded email cannot be used to access the
|
|
13
|
+
* credential.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { Text, Section } from '@react-email/components';
|
|
17
|
+
import * as React from 'react';
|
|
18
|
+
|
|
19
|
+
import type { TenantBranding } from '../branding';
|
|
20
|
+
import { DEFAULT_BRANDING } from '../branding';
|
|
21
|
+
import { Layout } from '../components/Layout';
|
|
22
|
+
import { EmailButton } from '../components/EmailButton';
|
|
23
|
+
import { IssuerLogo } from '../components/IssuerLogo';
|
|
24
|
+
import { LinkFallback } from '../components/LinkFallback';
|
|
25
|
+
import type { NotificationLocale } from '../i18n';
|
|
26
|
+
import { resolveCatalogLocale, interpolate, SHARED } from '../i18n';
|
|
27
|
+
|
|
28
|
+
export interface CredentialUpdatedProps {
|
|
29
|
+
branding: TenantBranding;
|
|
30
|
+
issuer?: {
|
|
31
|
+
name?: string;
|
|
32
|
+
logoUrl?: string;
|
|
33
|
+
};
|
|
34
|
+
/** Bounded credential display title. Omitted when unavailable. */
|
|
35
|
+
credential?: {
|
|
36
|
+
name?: string;
|
|
37
|
+
};
|
|
38
|
+
/** Recipient locale (BCP-47). Defaults to English. */
|
|
39
|
+
locale?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const ldquo = '\u201C';
|
|
43
|
+
const rdquo = '\u201D';
|
|
44
|
+
|
|
45
|
+
type Strings = {
|
|
46
|
+
preview: string;
|
|
47
|
+
heading: string;
|
|
48
|
+
body: (issuerName: string | undefined, credentialName: string | undefined) => React.ReactNode;
|
|
49
|
+
signIn: string;
|
|
50
|
+
button: string;
|
|
51
|
+
sincerely: string;
|
|
52
|
+
subject: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const EN: Strings = {
|
|
56
|
+
preview: 'Your credential has been updated',
|
|
57
|
+
heading: 'Your credential was updated',
|
|
58
|
+
body: (issuerName, credentialName) =>
|
|
59
|
+
issuerName ? (
|
|
60
|
+
credentialName ? (
|
|
61
|
+
<>
|
|
62
|
+
<strong>{issuerName}</strong> updated your{' '}
|
|
63
|
+
<strong>
|
|
64
|
+
{ldquo}
|
|
65
|
+
{credentialName}
|
|
66
|
+
{rdquo}
|
|
67
|
+
</strong>{' '}
|
|
68
|
+
certificate.
|
|
69
|
+
</>
|
|
70
|
+
) : (
|
|
71
|
+
<>
|
|
72
|
+
<strong>{issuerName}</strong> updated one of your credentials.
|
|
73
|
+
</>
|
|
74
|
+
)
|
|
75
|
+
) : credentialName ? (
|
|
76
|
+
<>
|
|
77
|
+
Your{' '}
|
|
78
|
+
<strong>
|
|
79
|
+
{ldquo}
|
|
80
|
+
{credentialName}
|
|
81
|
+
{rdquo}
|
|
82
|
+
</strong>{' '}
|
|
83
|
+
certificate was updated.
|
|
84
|
+
</>
|
|
85
|
+
) : (
|
|
86
|
+
<>One of your credentials was updated.</>
|
|
87
|
+
),
|
|
88
|
+
signIn: 'Sign in to view the latest version.',
|
|
89
|
+
button: 'View Updates',
|
|
90
|
+
sincerely: 'Sincerely,',
|
|
91
|
+
subject: 'Your credential was updated',
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const ES: Strings = {
|
|
95
|
+
preview: 'Tu credencial se ha actualizado',
|
|
96
|
+
heading: 'Tu credencial se actualizó',
|
|
97
|
+
body: (issuerName, credentialName) =>
|
|
98
|
+
issuerName ? (
|
|
99
|
+
credentialName ? (
|
|
100
|
+
<>
|
|
101
|
+
<strong>{issuerName}</strong> actualizó tu certificado{' '}
|
|
102
|
+
<strong>
|
|
103
|
+
{ldquo}
|
|
104
|
+
{credentialName}
|
|
105
|
+
{rdquo}
|
|
106
|
+
</strong>
|
|
107
|
+
.
|
|
108
|
+
</>
|
|
109
|
+
) : (
|
|
110
|
+
<>
|
|
111
|
+
<strong>{issuerName}</strong> actualizó una de tus credenciales.
|
|
112
|
+
</>
|
|
113
|
+
)
|
|
114
|
+
) : credentialName ? (
|
|
115
|
+
<>
|
|
116
|
+
Tu certificado{' '}
|
|
117
|
+
<strong>
|
|
118
|
+
{ldquo}
|
|
119
|
+
{credentialName}
|
|
120
|
+
{rdquo}
|
|
121
|
+
</strong>{' '}
|
|
122
|
+
se actualizó.
|
|
123
|
+
</>
|
|
124
|
+
) : (
|
|
125
|
+
<>Una de tus credenciales se actualizó.</>
|
|
126
|
+
),
|
|
127
|
+
signIn: 'Inicia sesión para ver la última versión.',
|
|
128
|
+
button: 'Ver actualizaciones',
|
|
129
|
+
sincerely: 'Atentamente,',
|
|
130
|
+
subject: 'Tu credencial se actualizó',
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const FR: Strings = {
|
|
134
|
+
preview: 'Votre titre a été mis à jour',
|
|
135
|
+
heading: 'Votre titre a été mis à jour',
|
|
136
|
+
body: (issuerName, credentialName) =>
|
|
137
|
+
issuerName ? (
|
|
138
|
+
credentialName ? (
|
|
139
|
+
<>
|
|
140
|
+
<strong>{issuerName}</strong> a mis à jour votre certificat{' '}
|
|
141
|
+
<strong>
|
|
142
|
+
{ldquo}
|
|
143
|
+
{credentialName}
|
|
144
|
+
{rdquo}
|
|
145
|
+
</strong>
|
|
146
|
+
.
|
|
147
|
+
</>
|
|
148
|
+
) : (
|
|
149
|
+
<>
|
|
150
|
+
<strong>{issuerName}</strong> a mis à jour l'un de vos titres.
|
|
151
|
+
</>
|
|
152
|
+
)
|
|
153
|
+
) : credentialName ? (
|
|
154
|
+
<>
|
|
155
|
+
Votre certificat{' '}
|
|
156
|
+
<strong>
|
|
157
|
+
{ldquo}
|
|
158
|
+
{credentialName}
|
|
159
|
+
{rdquo}
|
|
160
|
+
</strong>{' '}
|
|
161
|
+
a été mis à jour.
|
|
162
|
+
</>
|
|
163
|
+
) : (
|
|
164
|
+
<>L'un de vos titres a été mis à jour.</>
|
|
165
|
+
),
|
|
166
|
+
signIn: 'Connectez-vous pour voir la dernière version.',
|
|
167
|
+
button: 'Voir les mises à jour',
|
|
168
|
+
sincerely: 'Cordialement,',
|
|
169
|
+
subject: 'Votre titre a été mis à jour',
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const AR: Strings = {
|
|
173
|
+
preview: 'تم تحديث شهادتك',
|
|
174
|
+
heading: 'تم تحديث شهادتك',
|
|
175
|
+
body: (issuerName, credentialName) =>
|
|
176
|
+
issuerName ? (
|
|
177
|
+
credentialName ? (
|
|
178
|
+
<>
|
|
179
|
+
قام <strong>{issuerName}</strong> بتحديث شهادتك{' '}
|
|
180
|
+
<strong>
|
|
181
|
+
{ldquo}
|
|
182
|
+
{credentialName}
|
|
183
|
+
{rdquo}
|
|
184
|
+
</strong>
|
|
185
|
+
.
|
|
186
|
+
</>
|
|
187
|
+
) : (
|
|
188
|
+
<>
|
|
189
|
+
قام <strong>{issuerName}</strong> بتحديث إحدى شهاداتك.
|
|
190
|
+
</>
|
|
191
|
+
)
|
|
192
|
+
) : credentialName ? (
|
|
193
|
+
<>
|
|
194
|
+
تم تحديث شهادتك{' '}
|
|
195
|
+
<strong>
|
|
196
|
+
{ldquo}
|
|
197
|
+
{credentialName}
|
|
198
|
+
{rdquo}
|
|
199
|
+
</strong>
|
|
200
|
+
.
|
|
201
|
+
</>
|
|
202
|
+
) : (
|
|
203
|
+
<>تم تحديث إحدى شهاداتك.</>
|
|
204
|
+
),
|
|
205
|
+
signIn: 'سجّل الدخول لعرض أحدث إصدار.',
|
|
206
|
+
button: 'عرض التحديثات',
|
|
207
|
+
sincerely: 'مع التحيات،',
|
|
208
|
+
subject: 'تم تحديث شهادتك',
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const STRINGS: Record<NotificationLocale, Strings> = { en: EN, es: ES, fr: FR, ar: AR };
|
|
212
|
+
|
|
213
|
+
/** Notifications page of the configured app (never a claim or token URL). */
|
|
214
|
+
const notificationsUrl = (branding: TenantBranding): string =>
|
|
215
|
+
`${branding.appUrl.replace(/\/+$/, '')}/notifications`;
|
|
216
|
+
|
|
217
|
+
export const CredentialUpdated: React.FC<CredentialUpdatedProps> = ({
|
|
218
|
+
branding,
|
|
219
|
+
issuer,
|
|
220
|
+
credential,
|
|
221
|
+
locale,
|
|
222
|
+
}) => {
|
|
223
|
+
const s = STRINGS[resolveCatalogLocale(locale)];
|
|
224
|
+
const issuerName = issuer?.name;
|
|
225
|
+
const credentialName = credential?.name;
|
|
226
|
+
const updatesUrl = notificationsUrl(branding);
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<Layout
|
|
230
|
+
branding={branding}
|
|
231
|
+
locale={locale}
|
|
232
|
+
preview={s.preview}
|
|
233
|
+
showHeaderLogo={!issuer?.logoUrl}
|
|
234
|
+
>
|
|
235
|
+
<IssuerLogo
|
|
236
|
+
logoUrl={issuer?.logoUrl}
|
|
237
|
+
alt={issuerName ? `${issuerName} logo` : undefined}
|
|
238
|
+
/>
|
|
239
|
+
|
|
240
|
+
<Text style={heading}>{s.heading}</Text>
|
|
241
|
+
|
|
242
|
+
<Text style={paragraph}>{s.body(issuerName, credentialName)}</Text>
|
|
243
|
+
|
|
244
|
+
<Text style={paragraph}>{s.signIn}</Text>
|
|
245
|
+
|
|
246
|
+
<Section style={buttonWrapper}>
|
|
247
|
+
<EmailButton href={updatesUrl} branding={branding}>
|
|
248
|
+
{s.button}
|
|
249
|
+
</EmailButton>
|
|
250
|
+
</Section>
|
|
251
|
+
|
|
252
|
+
<Text style={signOff}>
|
|
253
|
+
{s.sincerely}
|
|
254
|
+
<br />
|
|
255
|
+
{interpolate(SHARED[resolveCatalogLocale(locale)].teamSignature, {
|
|
256
|
+
brandName: branding.brandName,
|
|
257
|
+
})}
|
|
258
|
+
</Text>
|
|
259
|
+
|
|
260
|
+
<LinkFallback href={updatesUrl} locale={locale} />
|
|
261
|
+
</Layout>
|
|
262
|
+
);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
export const getCredentialUpdatedSubject = (_branding: TenantBranding, locale?: string): string =>
|
|
266
|
+
STRINGS[resolveCatalogLocale(locale)].subject;
|
|
267
|
+
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
// Styles
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
|
|
272
|
+
const heading: React.CSSProperties = {
|
|
273
|
+
fontSize: 24,
|
|
274
|
+
fontWeight: 600,
|
|
275
|
+
color: '#111827',
|
|
276
|
+
margin: '0 0 24px',
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const paragraph: React.CSSProperties = {
|
|
280
|
+
fontSize: 16,
|
|
281
|
+
color: '#374151',
|
|
282
|
+
lineHeight: '24px',
|
|
283
|
+
margin: '0 0 24px',
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const buttonWrapper: React.CSSProperties = {
|
|
287
|
+
margin: '0 0 24px',
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const signOff: React.CSSProperties = {
|
|
291
|
+
fontSize: 14,
|
|
292
|
+
color: '#374151',
|
|
293
|
+
lineHeight: '20px',
|
|
294
|
+
margin: '24px 0 0',
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// ---------------------------------------------------------------------------
|
|
298
|
+
// Preview
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
|
|
301
|
+
export default function Preview() {
|
|
302
|
+
return (
|
|
303
|
+
<CredentialUpdated
|
|
304
|
+
branding={DEFAULT_BRANDING}
|
|
305
|
+
issuer={{ name: 'Inbox Demo School' }}
|
|
306
|
+
credential={{ name: 'Introduction to Biology' }}
|
|
307
|
+
/>
|
|
308
|
+
);
|
|
309
|
+
}
|
package/src/templates/index.ts
CHANGED
|
@@ -16,20 +16,34 @@ export type { RecoveryKeyProps } from './recovery-key';
|
|
|
16
16
|
export { EndorsementRequest, getEndorsementRequestSubject } from './endorsement-request';
|
|
17
17
|
export type { EndorsementRequestProps } from './endorsement-request';
|
|
18
18
|
|
|
19
|
-
export {
|
|
19
|
+
export {
|
|
20
|
+
CredentialAwaitingGuardian,
|
|
21
|
+
getCredentialAwaitingGuardianSubject,
|
|
22
|
+
} from './credential-awaiting-guardian';
|
|
20
23
|
export type { CredentialAwaitingGuardianProps } from './credential-awaiting-guardian';
|
|
21
24
|
|
|
22
25
|
export { GuardianApprovedClaim, getGuardianApprovedClaimSubject } from './guardian-approved-claim';
|
|
23
26
|
export type { GuardianApprovedClaimProps } from './guardian-approved-claim';
|
|
24
27
|
|
|
25
|
-
export {
|
|
28
|
+
export {
|
|
29
|
+
GuardianCredentialApproval,
|
|
30
|
+
getGuardianCredentialApprovalSubject,
|
|
31
|
+
} from './guardian-credential-approval';
|
|
26
32
|
export type { GuardianCredentialApprovalProps } from './guardian-credential-approval';
|
|
27
33
|
|
|
28
34
|
export { GuardianEmailOtp, getGuardianEmailOtpSubject } from './guardian-email-otp';
|
|
29
35
|
export type { GuardianEmailOtpProps } from './guardian-email-otp';
|
|
30
36
|
|
|
31
|
-
export {
|
|
37
|
+
export {
|
|
38
|
+
GuardianRejectedCredential,
|
|
39
|
+
getGuardianRejectedCredentialSubject,
|
|
40
|
+
} from './guardian-rejected-credential';
|
|
32
41
|
export type { GuardianRejectedCredentialProps } from './guardian-rejected-credential';
|
|
33
42
|
|
|
34
43
|
export { EmailVerification, getEmailVerificationSubject } from './email-verification';
|
|
35
44
|
export type { EmailVerificationProps } from './email-verification';
|
|
45
|
+
|
|
46
|
+
export { CredentialUpdated, getCredentialUpdatedSubject } from './credential-updated';
|
|
47
|
+
export type { CredentialUpdatedProps } from './credential-updated';
|
|
48
|
+
export { AccountSignInChanged, getAccountSignInChangedSubject } from './account-sign-in-changed';
|
|
49
|
+
export type { AccountSignInChangedProps } from './account-sign-in-changed';
|
|
@@ -17,6 +17,7 @@ import { resolveCatalogLocale, interpolate, SHARED } from '../i18n';
|
|
|
17
17
|
export interface RecoveryKeyProps {
|
|
18
18
|
branding: TenantBranding;
|
|
19
19
|
recoveryKey: string;
|
|
20
|
+
confirmationCode: string;
|
|
20
21
|
/** Recipient locale (BCP-47). Defaults to English. */
|
|
21
22
|
locale?: string;
|
|
22
23
|
}
|
|
@@ -29,6 +30,8 @@ const STRINGS: Record<
|
|
|
29
30
|
greeting: string;
|
|
30
31
|
body: (brandName: string) => string;
|
|
31
32
|
codeLabel: string;
|
|
33
|
+
confirmationCodeLabel: string;
|
|
34
|
+
confirmationInstruction: string;
|
|
32
35
|
recoverInstruction: () => React.ReactNode;
|
|
33
36
|
notRequested: string;
|
|
34
37
|
passport: string;
|
|
@@ -43,6 +46,9 @@ const STRINGS: Record<
|
|
|
43
46
|
body: b =>
|
|
44
47
|
`Keep this email safe. You can use the recovery key below to regain access to your ${b} account if you lose your device.`,
|
|
45
48
|
codeLabel: 'Recovery Key \u2014 do NOT share this with anyone',
|
|
49
|
+
confirmationCodeLabel: 'Confirmation code',
|
|
50
|
+
confirmationInstruction:
|
|
51
|
+
'Enter this code in the app to confirm that you received your recovery key.',
|
|
46
52
|
recoverInstruction: () => (
|
|
47
53
|
<>
|
|
48
54
|
To recover your account, choose <strong>“Recover via Email”</strong> in
|
|
@@ -62,6 +68,9 @@ const STRINGS: Record<
|
|
|
62
68
|
body: b =>
|
|
63
69
|
`Guarda este correo en un lugar seguro. Puedes usar la clave de recuperación siguiente para recuperar el acceso a tu cuenta de ${b} si pierdes tu dispositivo.`,
|
|
64
70
|
codeLabel: 'Clave de recuperación \u2014 NO la compartas con nadie',
|
|
71
|
+
confirmationCodeLabel: 'Código de confirmación',
|
|
72
|
+
confirmationInstruction:
|
|
73
|
+
'Introduce este código en la aplicación para confirmar que recibiste tu clave de recuperación.',
|
|
65
74
|
recoverInstruction: () => (
|
|
66
75
|
<>
|
|
67
76
|
Para recuperar tu cuenta, elige <strong>“Recuperar por correo”</strong>{' '}
|
|
@@ -81,6 +90,9 @@ const STRINGS: Record<
|
|
|
81
90
|
body: b =>
|
|
82
91
|
`Conservez cet e-mail en sécurité. Vous pouvez utiliser la clé de récupération ci-dessous pour retrouver l\u2019accès à votre compte ${b} si vous perdez votre appareil.`,
|
|
83
92
|
codeLabel: 'Clé de récupération \u2014 NE la partagez avec PERSONNE',
|
|
93
|
+
confirmationCodeLabel: 'Code de confirmation',
|
|
94
|
+
confirmationInstruction:
|
|
95
|
+
'Saisissez ce code dans l’application pour confirmer que vous avez reçu votre clé de récupération.',
|
|
84
96
|
recoverInstruction: () => (
|
|
85
97
|
<>
|
|
86
98
|
Pour récupérer votre compte, choisissez{' '}
|
|
@@ -103,6 +115,9 @@ const STRINGS: Record<
|
|
|
103
115
|
body: b =>
|
|
104
116
|
`احتفظ بهذا البريد في مكان آمن. يمكنك استخدام مفتاح الاستعادة أدناه لاستعادة الوصول إلى حسابك في ${b} إذا فقدت جهازك.`,
|
|
105
117
|
codeLabel: 'مفتاح الاستعادة \u2014 لا تشاركه مع أي شخص إطلاقًا',
|
|
118
|
+
confirmationCodeLabel: 'رمز التأكيد',
|
|
119
|
+
confirmationInstruction:
|
|
120
|
+
'أدخل هذا الرمز في التطبيق لتأكيد استلام مفتاح الاستعادة الخاص بك.',
|
|
106
121
|
recoverInstruction: () => (
|
|
107
122
|
<>
|
|
108
123
|
لاستعادة حسابك، اختر <strong>«الاستعادة عبر البريد»</strong> في التطبيق
|
|
@@ -117,7 +132,12 @@ const STRINGS: Record<
|
|
|
117
132
|
},
|
|
118
133
|
};
|
|
119
134
|
|
|
120
|
-
export const RecoveryKey: React.FC<RecoveryKeyProps> = ({
|
|
135
|
+
export const RecoveryKey: React.FC<RecoveryKeyProps> = ({
|
|
136
|
+
branding,
|
|
137
|
+
recoveryKey,
|
|
138
|
+
confirmationCode,
|
|
139
|
+
locale,
|
|
140
|
+
}) => {
|
|
121
141
|
const s = STRINGS[resolveCatalogLocale(locale)];
|
|
122
142
|
|
|
123
143
|
return (
|
|
@@ -130,6 +150,10 @@ export const RecoveryKey: React.FC<RecoveryKeyProps> = ({ branding, recoveryKey,
|
|
|
130
150
|
|
|
131
151
|
<CodeBlock code={recoveryKey} label={s.codeLabel} variant="key" />
|
|
132
152
|
|
|
153
|
+
<CodeBlock code={confirmationCode} label={s.confirmationCodeLabel} variant="code" />
|
|
154
|
+
|
|
155
|
+
<Text style={paragraph}>{s.confirmationInstruction}</Text>
|
|
156
|
+
|
|
133
157
|
<Text style={paragraph}>{s.recoverInstruction()}</Text>
|
|
134
158
|
|
|
135
159
|
<Text style={muted}>{s.notRequested}</Text>
|
|
@@ -193,6 +217,7 @@ export default function Preview() {
|
|
|
193
217
|
<RecoveryKey
|
|
194
218
|
branding={DEFAULT_BRANDING}
|
|
195
219
|
recoveryKey="mango-delta-fox-echo-bravo-seven-lima-niner"
|
|
220
|
+
confirmationCode="123456"
|
|
196
221
|
/>
|
|
197
222
|
);
|
|
198
223
|
}
|