@learncard/email-templates 1.1.0 → 1.2.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 (81) hide show
  1. package/dist/index.d.ts +2 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/previews/escrow-hold-cancelled-scenarios.d.ts +6 -0
  5. package/dist/previews/escrow-hold-cancelled-scenarios.d.ts.map +1 -0
  6. package/dist/previews/escrow-hold-cancelled-scenarios.js +7 -0
  7. package/dist/previews/escrow-hold-cancelled-scenarios.js.map +1 -0
  8. package/dist/previews/escrow-hold-released-scenarios.d.ts +6 -0
  9. package/dist/previews/escrow-hold-released-scenarios.d.ts.map +1 -0
  10. package/dist/previews/escrow-hold-released-scenarios.js +7 -0
  11. package/dist/previews/escrow-hold-released-scenarios.js.map +1 -0
  12. package/dist/previews/escrow-hold-reminder-scenarios.d.ts +6 -0
  13. package/dist/previews/escrow-hold-reminder-scenarios.d.ts.map +1 -0
  14. package/dist/previews/escrow-hold-reminder-scenarios.js +7 -0
  15. package/dist/previews/escrow-hold-reminder-scenarios.js.map +1 -0
  16. package/dist/previews/escrow-hold-started-scenarios.d.ts +6 -0
  17. package/dist/previews/escrow-hold-started-scenarios.d.ts.map +1 -0
  18. package/dist/previews/escrow-hold-started-scenarios.js +7 -0
  19. package/dist/previews/escrow-hold-started-scenarios.js.map +1 -0
  20. package/dist/previews/escrow-pin-locked-scenarios.d.ts +6 -0
  21. package/dist/previews/escrow-pin-locked-scenarios.d.ts.map +1 -0
  22. package/dist/previews/escrow-pin-locked-scenarios.js +7 -0
  23. package/dist/previews/escrow-pin-locked-scenarios.js.map +1 -0
  24. package/dist/previews/recovery-key-scenarios.d.ts.map +1 -1
  25. package/dist/previews/recovery-key-scenarios.js +1 -1
  26. package/dist/previews/recovery-key-scenarios.js.map +1 -1
  27. package/dist/render.d.ts +38 -0
  28. package/dist/render.d.ts.map +1 -1
  29. package/dist/render.js +48 -1
  30. package/dist/render.js.map +1 -1
  31. package/dist/templates/account-sign-in-changed.d.ts +11 -0
  32. package/dist/templates/account-sign-in-changed.d.ts.map +1 -0
  33. package/dist/templates/account-sign-in-changed.js +70 -0
  34. package/dist/templates/account-sign-in-changed.js.map +1 -0
  35. package/dist/templates/escrow-hold-cancelled.d.ts +23 -0
  36. package/dist/templates/escrow-hold-cancelled.d.ts.map +1 -0
  37. package/dist/templates/escrow-hold-cancelled.js +131 -0
  38. package/dist/templates/escrow-hold-cancelled.js.map +1 -0
  39. package/dist/templates/escrow-hold-released.d.ts +21 -0
  40. package/dist/templates/escrow-hold-released.d.ts.map +1 -0
  41. package/dist/templates/escrow-hold-released.js +92 -0
  42. package/dist/templates/escrow-hold-released.js.map +1 -0
  43. package/dist/templates/escrow-hold-reminder.d.ts +21 -0
  44. package/dist/templates/escrow-hold-reminder.d.ts.map +1 -0
  45. package/dist/templates/escrow-hold-reminder.js +92 -0
  46. package/dist/templates/escrow-hold-reminder.js.map +1 -0
  47. package/dist/templates/escrow-hold-started.d.ts +25 -0
  48. package/dist/templates/escrow-hold-started.d.ts.map +1 -0
  49. package/dist/templates/escrow-hold-started.js +96 -0
  50. package/dist/templates/escrow-hold-started.js.map +1 -0
  51. package/dist/templates/escrow-pin-locked.d.ts +24 -0
  52. package/dist/templates/escrow-pin-locked.d.ts.map +1 -0
  53. package/dist/templates/escrow-pin-locked.js +97 -0
  54. package/dist/templates/escrow-pin-locked.js.map +1 -0
  55. package/dist/templates/index.d.ts +12 -0
  56. package/dist/templates/index.d.ts.map +1 -1
  57. package/dist/templates/index.js +6 -0
  58. package/dist/templates/index.js.map +1 -1
  59. package/dist/templates/recovery-key.d.ts +1 -0
  60. package/dist/templates/recovery-key.d.ts.map +1 -1
  61. package/dist/templates/recovery-key.js +11 -3
  62. package/dist/templates/recovery-key.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/__tests__/i18n.test.ts +39 -2
  65. package/src/__tests__/render.test.ts +195 -0
  66. package/src/index.ts +7 -0
  67. package/src/previews/escrow-hold-cancelled-scenarios.tsx +79 -0
  68. package/src/previews/escrow-hold-released-scenarios.tsx +58 -0
  69. package/src/previews/escrow-hold-reminder-scenarios.tsx +52 -0
  70. package/src/previews/escrow-hold-started-scenarios.tsx +67 -0
  71. package/src/previews/escrow-pin-locked-scenarios.tsx +60 -0
  72. package/src/previews/recovery-key-scenarios.tsx +3 -0
  73. package/src/render.ts +128 -0
  74. package/src/templates/account-sign-in-changed.tsx +113 -0
  75. package/src/templates/escrow-hold-cancelled.tsx +212 -0
  76. package/src/templates/escrow-hold-released.tsx +184 -0
  77. package/src/templates/escrow-hold-reminder.tsx +184 -0
  78. package/src/templates/escrow-hold-started.tsx +216 -0
  79. package/src/templates/escrow-pin-locked.tsx +233 -0
  80. package/src/templates/index.ts +17 -0
  81. package/src/templates/recovery-key.tsx +26 -1
@@ -0,0 +1,97 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * EscrowPinLocked — notifies a user that their recovery PIN has been disabled
4
+ * after too many incorrect attempts. The slower, waiting-period recovery path
5
+ * is unaffected and still available.
6
+ *
7
+ * Used by: lca-api recovery hold routes (templateId: 'escrow-pin-locked')
8
+ */
9
+ import { Text, Section } from '@react-email/components';
10
+ import { DEFAULT_BRANDING } from '../branding';
11
+ import { Layout } from '../components/Layout';
12
+ import { EmailButton } from '../components/EmailButton';
13
+ import { LinkFallback } from '../components/LinkFallback';
14
+ import { resolveCatalogLocale, interpolate, SHARED } from '../i18n';
15
+ const EN = {
16
+ preview: 'Recovery PIN locked',
17
+ heading: 'Recovery PIN Locked',
18
+ body: lockedAt => (_jsxs(_Fragment, { children: ["Too many incorrect PIN attempts were made on ", _jsx("strong", { children: lockedAt }), ". The PIN is now disabled."] })),
19
+ fallbackAvailable: releaseAfter => releaseAfter ? (_jsxs(_Fragment, { children: ["The waiting-period recovery is still available and will complete on", ' ', _jsx("strong", { children: releaseAfter }), " unless you cancel it."] })) : (_jsx(_Fragment, { children: "The waiting-period recovery is still available." })),
20
+ warning: "If this wasn't you, cancel now.",
21
+ button: "This wasn't me \u2014 Cancel recovery",
22
+ sincerely: 'Sincerely,',
23
+ subject: 'Recovery PIN locked',
24
+ };
25
+ const ES = {
26
+ preview: 'PIN de recuperación bloqueado',
27
+ heading: 'PIN de Recuperación Bloqueado',
28
+ body: lockedAt => (_jsxs(_Fragment, { children: ["Se realizaron demasiados intentos incorrectos de PIN el ", _jsx("strong", { children: lockedAt }), ". El PIN est\u00E1 ahora deshabilitado."] })),
29
+ fallbackAvailable: releaseAfter => releaseAfter ? (_jsxs(_Fragment, { children: ["La recuperaci\u00F3n por periodo de espera sigue disponible y se completar\u00E1 el", ' ', _jsx("strong", { children: releaseAfter }), " a menos que la canceles."] })) : (_jsx(_Fragment, { children: "La recuperaci\u00F3n por periodo de espera sigue disponible." })),
30
+ warning: 'Si no fuiste tú, cancélalo ahora.',
31
+ button: 'No fui yo \u2014 Cancelar recuperación',
32
+ sincerely: 'Atentamente,',
33
+ subject: 'PIN de recuperación bloqueado',
34
+ };
35
+ const FR = {
36
+ preview: 'Code PIN de récupération verrouillé',
37
+ heading: 'Code PIN de Récupération Verrouillé',
38
+ body: lockedAt => (_jsxs(_Fragment, { children: ["Un trop grand nombre de tentatives de code PIN incorrectes ont eu lieu le", ' ', _jsx("strong", { children: lockedAt }), ". Le code PIN est d\u00E9sormais d\u00E9sactiv\u00E9."] })),
39
+ fallbackAvailable: releaseAfter => releaseAfter ? (_jsxs(_Fragment, { children: ["La r\u00E9cup\u00E9ration par d\u00E9lai d\\u2019attente reste disponible et se terminera le", ' ', _jsx("strong", { children: releaseAfter }), " sauf si vous l\\u2019annulez."] })) : (_jsx(_Fragment, { children: "La r\u00E9cup\u00E9ration par d\u00E9lai d\\u2019attente reste disponible." })),
40
+ warning: 'Si ce n\u2019était pas vous, annulez dès maintenant.',
41
+ button: 'Ce n\u2019était pas moi \u2014 Annuler la récupération',
42
+ sincerely: 'Cordialement,',
43
+ subject: 'Code PIN de récupération verrouillé',
44
+ };
45
+ const AR = {
46
+ preview: 'تم قفل رمز PIN الخاص بالاستعادة',
47
+ heading: 'تم قفل رمز PIN الخاص بالاستعادة',
48
+ body: lockedAt => (_jsxs(_Fragment, { children: ["\u062A\u0645 \u0625\u062C\u0631\u0627\u0621 \u0639\u062F\u0629 \u0645\u062D\u0627\u0648\u0644\u0627\u062A \u062E\u0627\u0637\u0626\u0629 \u0644\u0625\u062F\u062E\u0627\u0644 \u0631\u0645\u0632 PIN \u0641\u064A ", _jsx("strong", { children: lockedAt }), ". \u062A\u0645 \u0627\u0644\u0622\u0646 \u062A\u0639\u0637\u064A\u0644 \u0631\u0645\u0632 PIN."] })),
49
+ fallbackAvailable: releaseAfter => releaseAfter ? (_jsxs(_Fragment, { children: ["\u0644\u0627 \u062A\u0632\u0627\u0644 \u0627\u0644\u0627\u0633\u062A\u0639\u0627\u062F\u0629 \u0628\u0641\u062A\u0631\u0629 \u0627\u0644\u0627\u0646\u062A\u0638\u0627\u0631 \u0645\u062A\u0627\u062D\u0629 \u0648\u0633\u062A\u0643\u062A\u0645\u0644 \u0641\u064A ", _jsx("strong", { children: releaseAfter }), " \u0645\u0627 \u0644\u0645 \u062A\u0642\u0645 \u0628\u0625\u0644\u063A\u0627\u0626\u0647\u0627."] })) : (_jsx(_Fragment, { children: "\u0644\u0627 \u062A\u0632\u0627\u0644 \u0627\u0644\u0627\u0633\u062A\u0639\u0627\u062F\u0629 \u0628\u0641\u062A\u0631\u0629 \u0627\u0644\u0627\u0646\u062A\u0638\u0627\u0631 \u0645\u062A\u0627\u062D\u0629." })),
50
+ warning: 'إذا لم يكن هذا أنت، ألغِ الطلب الآن.',
51
+ button: 'لم يكن أنا \u2014 إلغاء الاستعادة',
52
+ sincerely: 'مع التحيات،',
53
+ subject: 'تم قفل رمز PIN الخاص بالاستعادة',
54
+ };
55
+ const STRINGS = { en: EN, es: ES, fr: FR, ar: AR };
56
+ export const EscrowPinLocked = ({ branding, lockedAt, releaseAfter, cancelUrl, locale, }) => {
57
+ const s = STRINGS[resolveCatalogLocale(locale)];
58
+ return (_jsxs(Layout, { branding: branding, locale: locale, preview: s.preview, children: [_jsx(Text, { style: heading, children: s.heading }), _jsx(Text, { style: paragraph, children: s.body(lockedAt) }), _jsx(Text, { style: paragraph, children: s.fallbackAvailable(releaseAfter) }), cancelUrl && (_jsxs(_Fragment, { children: [_jsx(Text, { style: warning, children: s.warning }), _jsx(Section, { style: buttonWrapper, children: _jsx(EmailButton, { href: cancelUrl, branding: branding, children: s.button }) })] })), _jsxs(Text, { style: signOff, children: [s.sincerely, _jsx("br", {}), interpolate(SHARED[resolveCatalogLocale(locale)].teamSignature, {
59
+ brandName: branding.brandName,
60
+ })] }), cancelUrl && _jsx(LinkFallback, { href: cancelUrl, locale: locale })] }));
61
+ };
62
+ export const getEscrowPinLockedSubject = (_branding, locale) => STRINGS[resolveCatalogLocale(locale)].subject;
63
+ // ---------------------------------------------------------------------------
64
+ // Styles
65
+ // ---------------------------------------------------------------------------
66
+ const heading = {
67
+ fontSize: 24,
68
+ fontWeight: 600,
69
+ color: '#111827',
70
+ margin: '0 0 24px',
71
+ };
72
+ const paragraph = {
73
+ fontSize: 16,
74
+ color: '#374151',
75
+ lineHeight: '24px',
76
+ margin: '0 0 24px',
77
+ };
78
+ const warning = {
79
+ ...paragraph,
80
+ fontWeight: 600,
81
+ };
82
+ const buttonWrapper = {
83
+ margin: '0 0 24px',
84
+ };
85
+ const signOff = {
86
+ fontSize: 14,
87
+ color: '#374151',
88
+ lineHeight: '20px',
89
+ margin: '24px 0 0',
90
+ };
91
+ // ---------------------------------------------------------------------------
92
+ // Preview
93
+ // ---------------------------------------------------------------------------
94
+ export default function Preview() {
95
+ return (_jsx(EscrowPinLocked, { branding: DEFAULT_BRANDING, lockedAt: "September 25, 2026, 3:00 PM", releaseAfter: "October 2, 2026, 3:00 PM", cancelUrl: "https://learncard.app/recovery/cancel?token=abc123" }));
96
+ }
97
+ //# sourceMappingURL=escrow-pin-locked.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escrow-pin-locked.js","sourceRoot":"","sources":["../../src/templates/escrow-pin-locked.tsx"],"names":[],"mappings":"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"}
@@ -24,4 +24,16 @@ export { EmailVerification, getEmailVerificationSubject } from './email-verifica
24
24
  export type { EmailVerificationProps } from './email-verification';
25
25
  export { CredentialUpdated, getCredentialUpdatedSubject } from './credential-updated';
26
26
  export type { CredentialUpdatedProps } from './credential-updated';
27
+ export { AccountSignInChanged, getAccountSignInChangedSubject } from './account-sign-in-changed';
28
+ export type { AccountSignInChangedProps } from './account-sign-in-changed';
29
+ export { EscrowHoldStarted, getEscrowHoldStartedSubject } from './escrow-hold-started';
30
+ export type { EscrowHoldStartedProps } from './escrow-hold-started';
31
+ export { EscrowHoldReminder, getEscrowHoldReminderSubject } from './escrow-hold-reminder';
32
+ export type { EscrowHoldReminderProps } from './escrow-hold-reminder';
33
+ export { EscrowHoldReleased, getEscrowHoldReleasedSubject } from './escrow-hold-released';
34
+ export type { EscrowHoldReleasedProps } from './escrow-hold-released';
35
+ export { EscrowHoldCancelled, getEscrowHoldCancelledSubject } from './escrow-hold-cancelled';
36
+ export type { EscrowHoldCancelledProps, EscrowHoldCancelledReason } from './escrow-hold-cancelled';
37
+ export { EscrowPinLocked, getEscrowPinLockedSubject } from './escrow-pin-locked';
38
+ export type { EscrowPinLockedProps } from './escrow-pin-locked';
27
39
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACnF,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE1F,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACnF,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACzF,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AAEtF,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AACnG,YAAY,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAE5E,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AAEtF,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACpF,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AAEtF,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACtF,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACtF,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACnF,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE1F,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACnF,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACzF,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AAEtF,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AACnG,YAAY,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAE5E,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AAEtF,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACpF,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AAEtF,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACtF,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACtF,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AACjG,YAAY,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAE3E,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACvF,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAC1F,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAC1F,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAC7F,YAAY,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEnG,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACjF,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -11,4 +11,10 @@ export { GuardianEmailOtp, getGuardianEmailOtpSubject } from './guardian-email-o
11
11
  export { GuardianRejectedCredential, getGuardianRejectedCredentialSubject, } from './guardian-rejected-credential';
12
12
  export { EmailVerification, getEmailVerificationSubject } from './email-verification';
13
13
  export { CredentialUpdated, getCredentialUpdatedSubject } from './credential-updated';
14
+ export { AccountSignInChanged, getAccountSignInChangedSubject } from './account-sign-in-changed';
15
+ export { EscrowHoldStarted, getEscrowHoldStartedSubject } from './escrow-hold-started';
16
+ export { EscrowHoldReminder, getEscrowHoldReminderSubject } from './escrow-hold-reminder';
17
+ export { EscrowHoldReleased, getEscrowHoldReleasedSubject } from './escrow-hold-released';
18
+ export { EscrowHoldCancelled, getEscrowHoldCancelledSubject } from './escrow-hold-cancelled';
19
+ export { EscrowPinLocked, getEscrowPinLockedSubject } from './escrow-pin-locked';
14
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAGnF,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGjE,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAGnF,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAGhF,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAGzF,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AAGnG,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAGpF,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAGtF,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAGnF,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGjE,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAGnF,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAGhF,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAGzF,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AAGnG,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAGpF,OAAO,EACH,0BAA0B,EAC1B,oCAAoC,GACvC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAGtF,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAEtF,OAAO,EAAE,oBAAoB,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAGjG,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAGvF,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAG1F,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAG1F,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAG7F,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -8,6 +8,7 @@ import type { TenantBranding } from '../branding';
8
8
  export interface RecoveryKeyProps {
9
9
  branding: TenantBranding;
10
10
  recoveryKey: string;
11
+ confirmationCode: string;
11
12
  /** Recipient locale (BCP-47). Defaults to English. */
12
13
  locale?: string;
13
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"recovery-key.d.ts","sourceRoot":"","sources":["../../src/templates/recovery-key.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOlD,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAkGD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA8BlD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,UAAU,cAAc,EAAE,SAAS,MAAM,KAAG,MACb,CAAC;AAsCtE,MAAM,CAAC,OAAO,UAAU,OAAO,sBAO9B"}
1
+ {"version":3,"file":"recovery-key.d.ts","sourceRoot":"","sources":["../../src/templates/recovery-key.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOlD,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAgHD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAuClD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,UAAU,cAAc,EAAE,SAAS,MAAM,KAAG,MACb,CAAC;AAsCtE,MAAM,CAAC,OAAO,UAAU,OAAO,sBAQ9B"}
@@ -16,6 +16,8 @@ const STRINGS = {
16
16
  greeting: 'Hello,',
17
17
  body: b => `Keep this email safe. You can use the recovery key below to regain access to your ${b} account if you lose your device.`,
18
18
  codeLabel: 'Recovery Key \u2014 do NOT share this with anyone',
19
+ confirmationCodeLabel: 'Confirmation code',
20
+ confirmationInstruction: 'Enter this code in the app to confirm that you received your recovery key.',
19
21
  recoverInstruction: () => (_jsxs(_Fragment, { children: ["To recover your account, choose ", _jsx("strong", { children: "\u201CRecover via Email\u201D" }), " in the app and paste the recovery key above when prompted."] })),
20
22
  notRequested: 'If you did not request this, you can safely ignore this email.',
21
23
  passport: '{brandName} is your private, digital passport for learning and work. It lets you securely collect and share your verified skills and achievements online.',
@@ -28,6 +30,8 @@ const STRINGS = {
28
30
  greeting: 'Hola,',
29
31
  body: b => `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.`,
30
32
  codeLabel: 'Clave de recuperación \u2014 NO la compartas con nadie',
33
+ confirmationCodeLabel: 'Código de confirmación',
34
+ confirmationInstruction: 'Introduce este código en la aplicación para confirmar que recibiste tu clave de recuperación.',
31
35
  recoverInstruction: () => (_jsxs(_Fragment, { children: ["Para recuperar tu cuenta, elige ", _jsx("strong", { children: "\u201CRecuperar por correo\u201D" }), ' ', "en la app y pega la clave de recuperaci\u00F3n anterior cuando se te solicite."] })),
32
36
  notRequested: 'Si no solicitaste esto, puedes ignorar este correo con seguridad.',
33
37
  passport: '{brandName} es tu pasaporte digital y privado para el aprendizaje y el trabajo. Te permite recopilar y compartir de forma segura tus habilidades y logros verificados en línea.',
@@ -40,6 +44,8 @@ const STRINGS = {
40
44
  greeting: 'Bonjour,',
41
45
  body: b => `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.`,
42
46
  codeLabel: 'Clé de récupération \u2014 NE la partagez avec PERSONNE',
47
+ confirmationCodeLabel: 'Code de confirmation',
48
+ confirmationInstruction: 'Saisissez ce code dans l’application pour confirmer que vous avez reçu votre clé de récupération.',
43
49
  recoverInstruction: () => (_jsxs(_Fragment, { children: ["Pour r\u00E9cup\u00E9rer votre compte, choisissez", ' ', _jsx("strong", { children: "\u00AB\u00A0R\u00E9cup\u00E9rer par e-mail\u00A0\u00BB" }), " dans l\\u2019application et collez la cl\u00E9 de r\u00E9cup\u00E9ration ci-dessus lorsque cela vous est demand\u00E9."] })),
44
50
  notRequested: 'Si vous n\u2019êtes pas à l\u2019origine de cette demande, vous pouvez ignorer cet e-mail en toute sécurité.',
45
51
  passport: '{brandName} est votre passeport numérique privé pour l\u2019apprentissage et le travail. Il vous permet de collecter et de partager en toute sécurité vos compétences et réalisations vérifiées en ligne.',
@@ -52,6 +58,8 @@ const STRINGS = {
52
58
  greeting: 'مرحبًا،',
53
59
  body: b => `احتفظ بهذا البريد في مكان آمن. يمكنك استخدام مفتاح الاستعادة أدناه لاستعادة الوصول إلى حسابك في ${b} إذا فقدت جهازك.`,
54
60
  codeLabel: 'مفتاح الاستعادة \u2014 لا تشاركه مع أي شخص إطلاقًا',
61
+ confirmationCodeLabel: 'رمز التأكيد',
62
+ confirmationInstruction: 'أدخل هذا الرمز في التطبيق لتأكيد استلام مفتاح الاستعادة الخاص بك.',
55
63
  recoverInstruction: () => (_jsxs(_Fragment, { children: ["\u0644\u0627\u0633\u062A\u0639\u0627\u062F\u0629 \u062D\u0633\u0627\u0628\u0643\u060C \u0627\u062E\u062A\u0631 ", _jsx("strong", { children: "\u00AB\u0627\u0644\u0627\u0633\u062A\u0639\u0627\u062F\u0629 \u0639\u0628\u0631 \u0627\u0644\u0628\u0631\u064A\u062F\u00BB" }), " \u0641\u064A \u0627\u0644\u062A\u0637\u0628\u064A\u0642 \u0648\u0627\u0644\u0635\u0642 \u0645\u0641\u062A\u0627\u062D \u0627\u0644\u0627\u0633\u062A\u0639\u0627\u062F\u0629 \u0623\u0639\u0644\u0627\u0647 \u0639\u0646\u062F \u0627\u0644\u0645\u0637\u0627\u0644\u0628\u0629 \u0628\u0630\u0644\u0643."] })),
56
64
  notRequested: 'إذا لم تطلب ذلك، يمكنك تجاهل هذه الرسالة بأمان.',
57
65
  passport: '{brandName} هو جواز سفرك الرقمي والخاص للتعلّم والعمل. يتيح لك جمع ومشاركة مهاراتك وإنجازاتك الموثّقة بأمان عبر الإنترنت.',
@@ -59,9 +67,9 @@ const STRINGS = {
59
67
  subject: b => `مفتاح الاستعادة الخاص بك في ${b}`,
60
68
  },
61
69
  };
62
- export const RecoveryKey = ({ branding, recoveryKey, locale }) => {
70
+ export const RecoveryKey = ({ branding, recoveryKey, confirmationCode, locale, }) => {
63
71
  const s = STRINGS[resolveCatalogLocale(locale)];
64
- return (_jsxs(Layout, { branding: branding, locale: locale, preview: s.preview(branding.brandName), children: [_jsx(Text, { style: heading, children: s.heading(branding.brandName) }), _jsx(Text, { style: paragraph, children: s.greeting }), _jsx(Text, { style: paragraph, children: s.body(branding.brandName) }), _jsx(CodeBlock, { code: recoveryKey, label: s.codeLabel, variant: "key" }), _jsx(Text, { style: paragraph, children: s.recoverInstruction() }), _jsx(Text, { style: muted, children: s.notRequested }), _jsx(Text, { style: paragraph, children: interpolate(s.passport, { brandName: branding.brandName }) }), _jsxs(Text, { style: signOff, children: [s.sincerely, _jsx("br", {}), interpolate(SHARED[resolveCatalogLocale(locale)].teamSignature, {
72
+ return (_jsxs(Layout, { branding: branding, locale: locale, preview: s.preview(branding.brandName), children: [_jsx(Text, { style: heading, children: s.heading(branding.brandName) }), _jsx(Text, { style: paragraph, children: s.greeting }), _jsx(Text, { style: paragraph, children: s.body(branding.brandName) }), _jsx(CodeBlock, { code: recoveryKey, label: s.codeLabel, variant: "key" }), _jsx(CodeBlock, { code: confirmationCode, label: s.confirmationCodeLabel, variant: "code" }), _jsx(Text, { style: paragraph, children: s.confirmationInstruction }), _jsx(Text, { style: paragraph, children: s.recoverInstruction() }), _jsx(Text, { style: muted, children: s.notRequested }), _jsx(Text, { style: paragraph, children: interpolate(s.passport, { brandName: branding.brandName }) }), _jsxs(Text, { style: signOff, children: [s.sincerely, _jsx("br", {}), interpolate(SHARED[resolveCatalogLocale(locale)].teamSignature, {
65
73
  brandName: branding.brandName,
66
74
  })] })] }));
67
75
  };
@@ -97,6 +105,6 @@ const signOff = {
97
105
  // Preview
98
106
  // ---------------------------------------------------------------------------
99
107
  export default function Preview() {
100
- return (_jsx(RecoveryKey, { branding: DEFAULT_BRANDING, recoveryKey: "mango-delta-fox-echo-bravo-seven-lima-niner" }));
108
+ return (_jsx(RecoveryKey, { branding: DEFAULT_BRANDING, recoveryKey: "mango-delta-fox-echo-bravo-seven-lima-niner", confirmationCode: "123456" }));
101
109
  }
102
110
  //# sourceMappingURL=recovery-key.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"recovery-key.js","sourceRoot":"","sources":["../../src/templates/recovery-key.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recovery-key.js","sourceRoot":"","sources":["../../src/templates/recovery-key.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@learncard/email-templates",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Git-managed, tenant-branded email and SMS templates for LearnCard services",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -49,8 +49,14 @@ const FIXTURES: { [K in TemplateId]: TemplateDataMap[K] } = {
49
49
  },
50
50
  'account-approved': { user: { displayName: 'New User' } },
51
51
  'account-approved-email': { user: { displayName: 'New User' } },
52
- 'recovery-key': { recoveryKey: 'mango-delta-fox-echo-bravo-seven-lima-niner' },
53
- 'recovery-key-backup': { recoveryKey: 'mango-delta-fox-echo-bravo-seven-lima-niner' },
52
+ 'recovery-key': {
53
+ recoveryKey: 'mango-delta-fox-echo-bravo-seven-lima-niner',
54
+ confirmationCode: '123456',
55
+ },
56
+ 'recovery-key-backup': {
57
+ recoveryKey: 'mango-delta-fox-echo-bravo-seven-lima-niner',
58
+ confirmationCode: '123456',
59
+ },
54
60
  'endorsement-request': {
55
61
  shareLink: 'https://learncard.app/share/xyz',
56
62
  recipient: { name: 'Dr. Emily Chen' },
@@ -85,6 +91,35 @@ const FIXTURES: { [K in TemplateId]: TemplateDataMap[K] } = {
85
91
  credential: { name: 'Perfect Attendance Award' },
86
92
  recipient: { email: 'student@example.com' },
87
93
  },
94
+ 'account-sign-in-changed': {},
95
+
96
+ 'escrow-hold-started': {
97
+ requestedAt: 'September 25, 2026, 3:00 PM',
98
+ releaseAfter: 'October 2, 2026, 3:00 PM',
99
+ cancelUrl: 'https://learncard.app/recovery/cancel?token=abc123',
100
+ deviceHint: 'Chrome on Windows',
101
+ },
102
+
103
+ 'escrow-hold-reminder': {
104
+ releaseAfter: 'October 2, 2026, 3:00 PM',
105
+ cancelUrl: 'https://learncard.app/recovery/cancel?token=abc123',
106
+ },
107
+
108
+ 'escrow-hold-released': {
109
+ completedAt: 'October 2, 2026, 3:00 PM',
110
+ supportUrl: 'https://learncard.app/support',
111
+ },
112
+
113
+ 'escrow-hold-cancelled': {
114
+ cancelledAt: 'September 26, 2026, 9:15 AM',
115
+ reason: 'user',
116
+ },
117
+
118
+ 'escrow-pin-locked': {
119
+ lockedAt: 'September 25, 2026, 3:00 PM',
120
+ releaseAfter: 'October 2, 2026, 3:00 PM',
121
+ cancelUrl: 'https://learncard.app/recovery/cancel?token=abc123',
122
+ },
88
123
  };
89
124
 
90
125
  const ALL_TEMPLATE_IDS = Object.keys(FIXTURES) as TemplateId[];
@@ -125,6 +160,8 @@ describe('i18n — non-EN locales localize content', () => {
125
160
  'guardian-credential-approval',
126
161
  'guardian-email-otp',
127
162
  'credential-awaiting-guardian',
163
+ 'escrow-hold-started',
164
+ 'escrow-hold-cancelled',
128
165
  ];
129
166
 
130
167
  for (const templateId of SAMPLES) {
@@ -83,10 +83,12 @@ const TEMPLATE_FIXTURES: { [K in TemplateId]: TemplateDataMap[K] } = {
83
83
 
84
84
  'recovery-key': {
85
85
  recoveryKey: 'ABCD-EFGH-1234-5678',
86
+ confirmationCode: '123456',
86
87
  },
87
88
 
88
89
  'recovery-key-backup': {
89
90
  recoveryKey: 'WXYZ-9876-LMNO-4321',
91
+ confirmationCode: '654321',
90
92
  },
91
93
 
92
94
  'endorsement-request': {
@@ -135,6 +137,35 @@ const TEMPLATE_FIXTURES: { [K in TemplateId]: TemplateDataMap[K] } = {
135
137
  issuer: { name: 'Inbox Demo School' },
136
138
  credential: { name: 'Introduction to Biology' },
137
139
  },
140
+ 'account-sign-in-changed': {},
141
+
142
+ 'escrow-hold-started': {
143
+ requestedAt: 'September 25, 2026, 3:00 PM',
144
+ releaseAfter: 'October 2, 2026, 3:00 PM',
145
+ cancelUrl: 'https://learncard.app/recovery/cancel?token=abc123',
146
+ deviceHint: 'Chrome on Windows',
147
+ },
148
+
149
+ 'escrow-hold-reminder': {
150
+ releaseAfter: 'October 2, 2026, 3:00 PM',
151
+ cancelUrl: 'https://learncard.app/recovery/cancel?token=abc123',
152
+ },
153
+
154
+ 'escrow-hold-released': {
155
+ completedAt: 'October 2, 2026, 3:00 PM',
156
+ supportUrl: 'https://learncard.app/support',
157
+ },
158
+
159
+ 'escrow-hold-cancelled': {
160
+ cancelledAt: 'September 26, 2026, 9:15 AM',
161
+ reason: 'user',
162
+ },
163
+
164
+ 'escrow-pin-locked': {
165
+ lockedAt: 'September 25, 2026, 3:00 PM',
166
+ releaseAfter: 'October 2, 2026, 3:00 PM',
167
+ cancelUrl: 'https://learncard.app/recovery/cancel?token=abc123',
168
+ },
138
169
  };
139
170
 
140
171
  const ALL_TEMPLATE_IDS = Object.keys(TEMPLATE_FIXTURES) as TemplateId[];
@@ -251,6 +282,7 @@ describe('renderEmail — content assertions', () => {
251
282
  const { html } = await renderEmail('recovery-key', DEFAULT_BRANDING, data);
252
283
 
253
284
  expect(html).toContain('ABCD-EFGH-1234-5678');
285
+ expect(html).toContain('123456');
254
286
  });
255
287
 
256
288
  it('endorsement-request includes the share link and message', async () => {
@@ -382,6 +414,169 @@ describe('renderEmail — credential-updated', () => {
382
414
  });
383
415
  });
384
416
 
417
+ // ---------------------------------------------------------------------------
418
+ // Escrow hold lifecycle (nitro-escrow-enclave, P5.1) — plain-language recovery
419
+ // notifications. No user-facing jargon: never render "wallet", "DID",
420
+ // "share", "enclave", "escrow", "SSS", or "key derivation".
421
+ // ---------------------------------------------------------------------------
422
+
423
+ describe('renderEmail — escrow hold lifecycle', () => {
424
+ const JARGON = ['wallet', 'DID', 'share', 'enclave', 'escrow', 'SSS', 'key derivation'];
425
+
426
+ const assertNoJargon = (text: string) => {
427
+ const lower = text.toLowerCase();
428
+ for (const word of JARGON) {
429
+ expect(lower).not.toContain(word.toLowerCase());
430
+ }
431
+ };
432
+
433
+ it('escrow-hold-started includes the cancel URL, both dates, and the device hint', async () => {
434
+ const data = TEMPLATE_FIXTURES['escrow-hold-started'];
435
+ const { html, text, subject } = await renderEmail(
436
+ 'escrow-hold-started',
437
+ DEFAULT_BRANDING,
438
+ data
439
+ );
440
+
441
+ expect(html).toContain(data.cancelUrl);
442
+ expect(html).toContain(data.requestedAt);
443
+ expect(html).toContain(data.releaseAfter);
444
+ expect(html).toContain(data.deviceHint);
445
+ expect(subject).toBe('Account recovery started');
446
+ assertNoJargon(html);
447
+ assertNoJargon(text);
448
+ assertNoJargon(subject);
449
+ });
450
+
451
+ it('escrow-hold-started renders without the optional device hint', async () => {
452
+ const { html } = await renderEmail('escrow-hold-started', DEFAULT_BRANDING, {
453
+ requestedAt: 'September 25, 2026, 3:00 PM',
454
+ releaseAfter: 'October 2, 2026, 3:00 PM',
455
+ cancelUrl: 'https://learncard.app/recovery/cancel?token=xyz',
456
+ });
457
+
458
+ expect(html).toContain('https://learncard.app/recovery/cancel?token=xyz');
459
+ expect(html).not.toContain('undefined');
460
+ });
461
+
462
+ it('escrow-hold-reminder includes the cancel URL and the release date', async () => {
463
+ const data = TEMPLATE_FIXTURES['escrow-hold-reminder'];
464
+ const { html, text, subject } = await renderEmail(
465
+ 'escrow-hold-reminder',
466
+ DEFAULT_BRANDING,
467
+ data
468
+ );
469
+
470
+ expect(html).toContain(data.cancelUrl);
471
+ expect(html).toContain(data.releaseAfter);
472
+ expect(subject).toBe('Recovery completes tomorrow');
473
+ assertNoJargon(html);
474
+ assertNoJargon(text);
475
+ assertNoJargon(subject);
476
+ });
477
+
478
+ it('escrow-hold-released includes the completion date and the support link when provided', async () => {
479
+ const data = TEMPLATE_FIXTURES['escrow-hold-released'];
480
+ const { html, text, subject } = await renderEmail(
481
+ 'escrow-hold-released',
482
+ DEFAULT_BRANDING,
483
+ data
484
+ );
485
+
486
+ expect(html).toContain(data.completedAt);
487
+ expect(html).toContain(data.supportUrl);
488
+ expect(subject).toBe('Your account was recovered');
489
+ assertNoJargon(html);
490
+ assertNoJargon(text);
491
+ assertNoJargon(subject);
492
+ });
493
+
494
+ it('escrow-hold-released renders without the optional support link', async () => {
495
+ const { html } = await renderEmail('escrow-hold-released', DEFAULT_BRANDING, {
496
+ completedAt: 'October 2, 2026, 3:00 PM',
497
+ });
498
+
499
+ expect(html).toContain('October 2, 2026, 3:00 PM');
500
+ expect(html).not.toContain('undefined');
501
+ });
502
+
503
+ it.each([
504
+ ['user', 'cancelled this request'],
505
+ ['superseded', 'newer recovery request'],
506
+ ['pin-locked', 'incorrect PIN attempts'],
507
+ ['release-failed', 'could not be completed'],
508
+ ] as const)('escrow-hold-cancelled renders reason "%s"', async (reason, expectedSnippet) => {
509
+ const { html, subject } = await renderEmail('escrow-hold-cancelled', DEFAULT_BRANDING, {
510
+ cancelledAt: 'September 26, 2026, 9:15 AM',
511
+ reason,
512
+ });
513
+
514
+ expect(html).toContain('September 26, 2026, 9:15 AM');
515
+ expect(html).toContain(expectedSnippet);
516
+ expect(subject).toBe('Recovery request cancelled');
517
+ assertNoJargon(html);
518
+ });
519
+
520
+ it('escrow-hold-cancelled renders a generic message when reason is omitted', async () => {
521
+ const { html } = await renderEmail('escrow-hold-cancelled', DEFAULT_BRANDING, {
522
+ cancelledAt: 'September 26, 2026, 9:15 AM',
523
+ });
524
+
525
+ expect(html).toContain('No further action is needed');
526
+ });
527
+
528
+ it('escrow-pin-locked includes the locked date, release date, and cancel URL when a hold is pending', async () => {
529
+ const data = TEMPLATE_FIXTURES['escrow-pin-locked'];
530
+ const { html, text, subject } = await renderEmail(
531
+ 'escrow-pin-locked',
532
+ DEFAULT_BRANDING,
533
+ data
534
+ );
535
+
536
+ expect(html).toContain(data.lockedAt);
537
+ expect(html).toContain(data.releaseAfter);
538
+ expect(html).toContain(data.cancelUrl);
539
+ expect(subject).toBe('Recovery PIN locked');
540
+ assertNoJargon(html);
541
+ assertNoJargon(text);
542
+ assertNoJargon(subject);
543
+ });
544
+
545
+ it('escrow-pin-locked renders generic fallback copy with no button when no hold is pending', async () => {
546
+ const { html } = await renderEmail('escrow-pin-locked', DEFAULT_BRANDING, {
547
+ lockedAt: 'September 25, 2026, 3:00 PM',
548
+ });
549
+
550
+ expect(html).toContain('September 25, 2026, 3:00 PM');
551
+ expect(html).toContain('waiting-period recovery is still available');
552
+ expect(html).not.toContain('undefined');
553
+ });
554
+
555
+ it('all escrow hold templates include the "This wasn\'t me" cancel CTA when a cancel URL is present', async () => {
556
+ const started = await renderEmail(
557
+ 'escrow-hold-started',
558
+ DEFAULT_BRANDING,
559
+ TEMPLATE_FIXTURES['escrow-hold-started']
560
+ );
561
+ const reminder = await renderEmail(
562
+ 'escrow-hold-reminder',
563
+ DEFAULT_BRANDING,
564
+ TEMPLATE_FIXTURES['escrow-hold-reminder']
565
+ );
566
+ const pinLocked = await renderEmail(
567
+ 'escrow-pin-locked',
568
+ DEFAULT_BRANDING,
569
+ TEMPLATE_FIXTURES['escrow-pin-locked']
570
+ );
571
+
572
+ // Plain text output has no HTML entity escaping, so the apostrophe is literal.
573
+ for (const { text } of [started, reminder, pinLocked]) {
574
+ expect(text).toContain("This wasn't me");
575
+ expect(text).toContain('Cancel recovery');
576
+ }
577
+ });
578
+ });
579
+
385
580
  // ---------------------------------------------------------------------------
386
581
  // Branding tests — custom branding flows through to rendered output
387
582
  // ---------------------------------------------------------------------------
package/src/index.ts CHANGED
@@ -38,7 +38,14 @@ export type {
38
38
  GuardianEmailOtpData,
39
39
  GuardianRejectedCredentialData,
40
40
  CredentialUpdatedData,
41
+ AccountSignInChangedData,
42
+ EscrowHoldStartedData,
43
+ EscrowHoldReminderData,
44
+ EscrowHoldReleasedData,
45
+ EscrowHoldCancelledData,
46
+ EscrowPinLockedData,
41
47
  } from './render';
48
+ export type { EscrowHoldCancelledReason } from './templates/escrow-hold-cancelled';
42
49
 
43
50
  // SMS rendering
44
51
  export { renderSms } from './sms';