@incodetech/prizma-core-screens 0.2.7 → 0.2.14

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 (191) hide show
  1. package/dist/BiometricConsentScreen.d.ts +95 -0
  2. package/dist/BiometricConsentScreen.js +91 -0
  3. package/dist/BiometricConsentStrings.d.ts +84 -0
  4. package/dist/BiometricConsentStrings.js +31 -0
  5. package/dist/CaptureScreen.d.ts +13 -0
  6. package/dist/CaptureScreen.js +2 -2
  7. package/dist/DemoScreensLayout.css +16 -0
  8. package/dist/DemoScreensRedirectScreen.d.ts +6 -1
  9. package/dist/DemoScreensRedirectScreen.js +3 -2
  10. package/dist/DemoScreensStrings.d.ts +5 -0
  11. package/dist/DigitalIdDeviceWalletsDocumentSelectionScreen.d.ts +34 -0
  12. package/dist/DigitalIdDeviceWalletsDocumentSelectionScreen.js +47 -0
  13. package/dist/DigitalIdDeviceWalletsResultScreen.d.ts +28 -0
  14. package/dist/DigitalIdDeviceWalletsResultScreen.js +23 -0
  15. package/dist/DigitalIdDeviceWalletsStrings.d.ts +55 -0
  16. package/dist/DigitalIdDeviceWalletsStrings.js +19 -0
  17. package/dist/DigitalIdProvidersDocumentSelectionScreen.d.ts +31 -0
  18. package/dist/DigitalIdProvidersDocumentSelectionScreen.js +37 -0
  19. package/dist/DigitalIdProvidersErrorScreen.d.ts +33 -0
  20. package/dist/DigitalIdProvidersErrorScreen.js +33 -0
  21. package/dist/DigitalIdProvidersLayout.css +59 -0
  22. package/dist/DigitalIdProvidersRedirectScreen.d.ts +24 -0
  23. package/dist/DigitalIdProvidersRedirectScreen.js +18 -0
  24. package/dist/DigitalIdProvidersStrings.d.ts +72 -0
  25. package/dist/DigitalIdProvidersStrings.js +15 -0
  26. package/dist/DigitalIdUploadErrorScreen.d.ts +31 -0
  27. package/dist/DigitalIdUploadErrorScreen.js +26 -0
  28. package/dist/DigitalIdUploadFileTooLargeScreen.d.ts +27 -0
  29. package/dist/DigitalIdUploadFileTooLargeScreen.js +21 -0
  30. package/dist/DigitalIdUploadReviewScreen.d.ts +57 -0
  31. package/dist/DigitalIdUploadReviewScreen.js +44 -0
  32. package/dist/DigitalIdUploadStrings.d.ts +64 -0
  33. package/dist/DigitalIdUploadStrings.js +19 -0
  34. package/dist/DigitalIdUploadTutorialScreen.d.ts +28 -0
  35. package/dist/DigitalIdUploadTutorialScreen.js +23 -0
  36. package/dist/DocumentCaptureIllustration.d.ts +1 -1
  37. package/dist/EkybCountryScreen.d.ts +6 -6
  38. package/dist/EkybCountryScreen.js +20 -7
  39. package/dist/EkybStrings.d.ts +6 -1
  40. package/dist/ErrorScreensScreen.d.ts +5 -2
  41. package/dist/ErrorScreensScreen.js +15 -4
  42. package/dist/ErrorScreensStrings.d.ts +17 -2
  43. package/dist/ErrorScreensStrings.js +18 -10
  44. package/dist/FaceCaptureCapturingScreen.d.ts +63 -0
  45. package/dist/FaceCaptureCapturingScreen.js +62 -2
  46. package/dist/FaceCaptureLayout.css +69 -4
  47. package/dist/FaceCaptureStrings.d.ts +23 -0
  48. package/dist/FormScreen.css +14 -0
  49. package/dist/FormScreen.d.ts +28 -0
  50. package/dist/FormScreen.js +3 -2
  51. package/dist/IdCaptureLayout.css +165 -2
  52. package/dist/IdCaptureStageScreen.d.ts +47 -0
  53. package/dist/IdCaptureStageScreen.js +39 -3
  54. package/dist/IdCaptureStrings.d.ts +19 -0
  55. package/dist/ListScreen.d.ts +19 -0
  56. package/dist/ListScreen.js +7 -2
  57. package/dist/LoaderScreen.d.ts +7 -5
  58. package/dist/LoaderScreen.js +7 -5
  59. package/dist/LoadersStrings.d.ts +18 -5
  60. package/dist/OcrReviewErrorScreen.d.ts +30 -0
  61. package/dist/OcrReviewErrorScreen.js +24 -0
  62. package/dist/OcrReviewLayout.css +24 -0
  63. package/dist/OcrReviewLoadingScreen.d.ts +25 -0
  64. package/dist/OcrReviewLoadingScreen.js +19 -0
  65. package/dist/OcrReviewScreen.d.ts +76 -0
  66. package/dist/OcrReviewScreen.js +65 -0
  67. package/dist/OcrReviewStrings.d.ts +47 -0
  68. package/dist/OcrReviewStrings.js +17 -0
  69. package/dist/OcrReviewSuccessScreen.d.ts +30 -0
  70. package/dist/OcrReviewSuccessScreen.js +24 -0
  71. package/dist/PermissionsAllowScreen.d.ts +8 -11
  72. package/dist/PermissionsAllowScreen.js +8 -11
  73. package/dist/PermissionsAskScreen.d.ts +41 -0
  74. package/dist/PermissionsAskScreen.js +43 -0
  75. package/dist/PermissionsBrowserStepsScreen.d.ts +9 -2
  76. package/dist/PermissionsBrowserStepsScreen.js +12 -3
  77. package/dist/PermissionsLayout.css +47 -0
  78. package/dist/PermissionsStrings.d.ts +20 -9
  79. package/dist/PermissionsStrings.js +10 -4
  80. package/dist/PhoneInputOtpScreen.d.ts +8 -0
  81. package/dist/PhoneInputOtpScreen.js +26 -19
  82. package/dist/PhoneInputStrings.d.ts +11 -3
  83. package/dist/PhoneInputVerifyScreen.js +21 -5
  84. package/dist/QualifiedSignatureDocumentScreen.d.ts +8 -5
  85. package/dist/QualifiedSignatureDocumentScreen.js +9 -6
  86. package/dist/QualifiedSignatureResultScreen.d.ts +16 -13
  87. package/dist/QualifiedSignatureResultScreen.js +17 -18
  88. package/dist/QualifiedSignatureStrings.d.ts +11 -4
  89. package/dist/ResultScreen.d.ts +8 -0
  90. package/dist/ResultScreen.js +14 -3
  91. package/dist/ReusabilityCredentialSelectionScreen.d.ts +95 -0
  92. package/dist/ReusabilityCredentialSelectionScreen.js +94 -0
  93. package/dist/ReusabilityLayout.css +241 -0
  94. package/dist/ReusabilityPrivacyPolicyScreen.d.ts +55 -0
  95. package/dist/ReusabilityPrivacyPolicyScreen.js +44 -0
  96. package/dist/ReusabilityStrings.d.ts +85 -0
  97. package/dist/ReusabilityStrings.js +37 -0
  98. package/dist/ReviewScreen.d.ts +38 -12
  99. package/dist/ReviewScreen.js +41 -8
  100. package/dist/ScreenLayout.css +382 -6
  101. package/dist/VideoSelfieErrorScreen.js +1 -1
  102. package/dist/VideoSelfieIdCaptureScreen.js +1 -1
  103. package/dist/VideoSelfieLayout.css +304 -2
  104. package/dist/VideoSelfieSelfieCaptureScreen.js +1 -1
  105. package/dist/VideoSelfieSpeakScreen.js +1 -1
  106. package/dist/VideoSelfieStrings.d.ts +4 -1
  107. package/dist/VideoSelfieTurnHeadScreen.js +14 -11
  108. package/dist/VideoSelfieTutorialScreen.d.ts +9 -0
  109. package/dist/VideoSelfieTutorialScreen.js +10 -1
  110. package/dist/VideoSelfieWaveScreen.js +1 -1
  111. package/dist/ViewfinderScreen.css +36 -0
  112. package/dist/flows.d.ts +8 -0
  113. package/dist/flows.js +17 -0
  114. package/dist/index.d.ts +23 -0
  115. package/dist/index.js +17 -0
  116. package/dist/styles.css +4 -0
  117. package/package.json +94 -3
  118. package/samples/video-selfie-camera-wide.jpg +0 -0
  119. package/samples/video-selfie-room-wide.jpg +0 -0
  120. package/src/BiometricConsentScreen.tsx +192 -0
  121. package/src/BiometricConsentStrings.ts +119 -0
  122. package/src/CaptureScreen.tsx +17 -0
  123. package/src/DemoScreensLayout.css +16 -0
  124. package/src/DemoScreensRedirectScreen.tsx +14 -6
  125. package/src/DemoScreensStrings.ts +5 -0
  126. package/src/DigitalIdDeviceWalletsDocumentSelectionScreen.tsx +108 -0
  127. package/src/DigitalIdDeviceWalletsResultScreen.tsx +76 -0
  128. package/src/DigitalIdDeviceWalletsStrings.ts +80 -0
  129. package/src/DigitalIdProvidersDocumentSelectionScreen.tsx +112 -0
  130. package/src/DigitalIdProvidersErrorScreen.tsx +104 -0
  131. package/src/DigitalIdProvidersLayout.css +59 -0
  132. package/src/DigitalIdProvidersRedirectScreen.tsx +65 -0
  133. package/src/DigitalIdProvidersStrings.ts +98 -0
  134. package/src/DigitalIdUploadErrorScreen.tsx +83 -0
  135. package/src/DigitalIdUploadFileTooLargeScreen.tsx +67 -0
  136. package/src/DigitalIdUploadReviewScreen.tsx +119 -0
  137. package/src/DigitalIdUploadStrings.ts +88 -0
  138. package/src/DigitalIdUploadTutorialScreen.tsx +59 -0
  139. package/src/DocumentCaptureIllustration.tsx +1 -1
  140. package/src/EkybCountryScreen.tsx +23 -6
  141. package/src/EkybStrings.ts +6 -1
  142. package/src/ErrorScreensScreen.tsx +15 -4
  143. package/src/ErrorScreensStrings.ts +37 -12
  144. package/src/FaceCaptureCapturingScreen.tsx +102 -13
  145. package/src/FaceCaptureLayout.css +69 -4
  146. package/src/FaceCaptureStrings.ts +24 -0
  147. package/src/FormScreen.css +14 -0
  148. package/src/FormScreen.tsx +34 -0
  149. package/src/IdCaptureLayout.css +165 -2
  150. package/src/IdCaptureStageScreen.tsx +75 -0
  151. package/src/IdCaptureStrings.ts +19 -0
  152. package/src/ListScreen.tsx +48 -9
  153. package/src/LoaderScreen.tsx +7 -5
  154. package/src/LoadersStrings.ts +18 -5
  155. package/src/OcrReviewErrorScreen.tsx +53 -0
  156. package/src/OcrReviewLayout.css +24 -0
  157. package/src/OcrReviewLoadingScreen.tsx +48 -0
  158. package/src/OcrReviewScreen.tsx +190 -0
  159. package/src/OcrReviewStrings.ts +69 -0
  160. package/src/OcrReviewSuccessScreen.tsx +52 -0
  161. package/src/PermissionsAllowScreen.tsx +9 -10
  162. package/src/PermissionsAskScreen.tsx +105 -0
  163. package/src/PermissionsBrowserStepsScreen.tsx +11 -3
  164. package/src/PermissionsLayout.css +47 -0
  165. package/src/PermissionsStrings.ts +42 -12
  166. package/src/PhoneInputOtpScreen.tsx +23 -3
  167. package/src/PhoneInputStrings.ts +11 -3
  168. package/src/PhoneInputVerifyScreen.tsx +24 -4
  169. package/src/QualifiedSignatureDocumentScreen.tsx +9 -7
  170. package/src/QualifiedSignatureResultScreen.tsx +28 -26
  171. package/src/QualifiedSignatureStrings.ts +11 -4
  172. package/src/ResultScreen.tsx +33 -2
  173. package/src/ReusabilityCredentialSelectionScreen.tsx +246 -0
  174. package/src/ReusabilityLayout.css +241 -0
  175. package/src/ReusabilityPrivacyPolicyScreen.tsx +109 -0
  176. package/src/ReusabilityStrings.ts +127 -0
  177. package/src/ReviewScreen.tsx +96 -27
  178. package/src/ScreenLayout.css +382 -6
  179. package/src/VideoSelfieErrorScreen.tsx +1 -1
  180. package/src/VideoSelfieIdCaptureScreen.tsx +9 -1
  181. package/src/VideoSelfieLayout.css +304 -2
  182. package/src/VideoSelfieSelfieCaptureScreen.tsx +9 -1
  183. package/src/VideoSelfieSpeakScreen.tsx +9 -1
  184. package/src/VideoSelfieStrings.ts +4 -2
  185. package/src/VideoSelfieTurnHeadScreen.tsx +25 -14
  186. package/src/VideoSelfieTutorialScreen.tsx +11 -0
  187. package/src/VideoSelfieWaveScreen.tsx +9 -1
  188. package/src/ViewfinderScreen.css +36 -0
  189. package/src/flows.ts +25 -0
  190. package/src/index.ts +116 -3
  191. package/src/styles.css +4 -0
@@ -21,8 +21,13 @@ import './DemoScreensLayout.css';
21
21
  * - `resend` "Link sent!", resend available
22
22
  * - `resent` "Link sent!" with the "resent" snackbar
23
23
  * - `tooMany` "Too many attempts"
24
+ * - `invalidUuid` the link's UUID was rejected (expired or unknown): no leg
25
+ * to offer, only the error. One message for Flows and
26
+ * Workflows alike, since the backend answers the same way for
27
+ * both (Elena, 2026-10-21: web SDK 2.0 showed "QR code
28
+ * expired" for Flows and "Session expired" with 2.0 off).
24
29
  */
25
- export type DemoScreensRedirectStage = 'qr' | 'sms' | 'smsFilled' | 'sent' | 'resend' | 'resent' | 'tooMany';
30
+ export type DemoScreensRedirectStage = 'qr' | 'sms' | 'smsFilled' | 'sent' | 'resend' | 'resent' | 'tooMany' | 'invalidUuid';
26
31
 
27
32
  export interface DemoScreensRedirectScreenProps
28
33
  extends Omit<PrizmaScreenShellProps, 'dark' | 'title' | 'children'> {
@@ -79,7 +84,8 @@ export const DemoScreensRedirectScreen = forwardRef<HTMLDivElement, DemoScreensR
79
84
  { code: 'RS', name: 'Serbia', dialCode: '+381', flag: '' },
80
85
  ].find(c => c.code === r.countryCode);
81
86
  const subtitle = sms ? r.subtitle : desktop ? r.subtitleQrDesktop : r.subtitleQrOnly;
82
- const verdict = stage === 'sent' || stage === 'resend' || stage === 'resent' || stage === 'tooMany';
87
+ const invalid = stage === 'invalidUuid';
88
+ const verdict = stage === 'sent' || stage === 'resend' || stage === 'resent' || stage === 'tooMany' || invalid;
83
89
 
84
90
  return (
85
91
  <PrizmaScreenShell
@@ -96,8 +102,8 @@ export const DemoScreensRedirectScreen = forwardRef<HTMLDivElement, DemoScreensR
96
102
  <div className="demo-screens-redirect__card">
97
103
  <PrizmaScreenNav logo={overrides?.logo} navLabel={strings.navLabel} />
98
104
  <div className="prizma-screen-layout__content demo-screens-redirect__content">
99
- <PrizmaTitle variant="centered" title={r.title} showSubtitle subtitle={subtitle} />
100
- {sms ? (
105
+ {invalid ? null : <PrizmaTitle variant="centered" title={r.title} showSubtitle subtitle={subtitle} />}
106
+ {sms && !invalid ? (
101
107
  <div className="demo-screens-tabs" role="tablist">
102
108
  <button type="button" role="tab" aria-selected={!onSms} className={['demo-screens-tabs__tab', !onSms ? 'demo-screens-tabs__tab--active' : ''].join(' ')} onClick={() => onAction?.({ type: 'secondary', screenId })}>
103
109
  {r.tabs.qr}
@@ -138,7 +144,9 @@ export const DemoScreensRedirectScreen = forwardRef<HTMLDivElement, DemoScreensR
138
144
 
139
145
  {verdict ? (
140
146
  <div className="demo-screens-redirect__leg demo-screens-redirect__leg--verdict">
141
- {stage === 'tooMany' ? (
147
+ {invalid ? (
148
+ <PrizmaTitle variant="centered" title={r.invalidUuid.title} showSubtitle subtitle={r.invalidUuid.subtitle} icon={{ type: 'status', status: 'error' }} />
149
+ ) : stage === 'tooMany' ? (
142
150
  <PrizmaTitle variant="centered" title={r.tooMany.title} showSubtitle subtitle={r.tooMany.subtitle} icon={{ type: 'status', status: 'error' }} />
143
151
  ) : (
144
152
  <PrizmaTitle
@@ -149,7 +157,7 @@ export const DemoScreensRedirectScreen = forwardRef<HTMLDivElement, DemoScreensR
149
157
  icon={{ type: 'status', status: 'success' }}
150
158
  />
151
159
  )}
152
- {stage === 'tooMany' ? (
160
+ {invalid ? null : stage === 'tooMany' ? (
153
161
  <PrizmaButton variant="tertiary-link" size="L" onClick={() => onAction?.({ type: 'tertiary', screenId })}>
154
162
  {r.tooMany.changeLabel}
155
163
  </PrizmaButton>
@@ -171,6 +171,11 @@ export interface DemoScreensStrings {
171
171
  subtitle: string;
172
172
  changeLabel: string;
173
173
  };
174
+ /** The link's UUID was rejected: the same copy for Flows and Workflows. */
175
+ invalidUuid: {
176
+ title: string;
177
+ subtitle: string;
178
+ };
174
179
  };
175
180
 
176
181
  /** WEB · `demo_2` — the front door: language, the wordmark, one CTA. */
@@ -0,0 +1,108 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaCardListVerificationOptions } from '@incodetech/prizma-core-web/card-list';
3
+ import { PrizmaListScreen, type PrizmaListScreenProps } from './ListScreen';
4
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
5
+ import type {
6
+ DigitalIdDeviceWalletsOption,
7
+ DigitalIdDeviceWalletsPlatformWallet,
8
+ DigitalIdDeviceWalletsStrings,
9
+ } from './DigitalIdDeviceWalletsStrings';
10
+ import './ScreenLayout.css';
11
+
12
+ export interface DigitalIdDeviceWalletsDocumentSelectionScreenProps
13
+ extends Omit<
14
+ PrizmaListScreenProps,
15
+ 'title' | 'subtitle' | 'children' | 'listAlign' | 'verifiedLabel' | 'navLabel'
16
+ > {
17
+ /** Module copy — this screen reads the `documentSelection` slice. */
18
+ strings: DigitalIdDeviceWalletsStrings;
19
+ /** Which wallet row the list carries. Default `apple` (iOS); `google` on
20
+ * Android; `digital-id` on web, where the row comes last with no tag. */
21
+ wallet?: DigitalIdDeviceWalletsPlatformWallet;
22
+ /** Fired with the chosen option; `onAction` still reports the tap. Named
23
+ * `onOptionSelect`, not `onSelect` — the latter is a native <div> event the
24
+ * shell already passes through. */
25
+ onOptionSelect?: (option: DigitalIdDeviceWalletsOption) => void;
26
+ screenId?: string;
27
+ overrides?: PrizmaScreenOverrides;
28
+ onAction?: PrizmaScreenActionHandler;
29
+ }
30
+
31
+ /**
32
+ * Digital ID Device Wallets — choose how to verify, with the device wallet
33
+ * first, built on the `PrizmaListScreen` archetype (GUIDELINES.md §6-G).
34
+ * Figma: `Digital IDs - Latest Design` (u7N5Zq4bfOwiVbpKHKmSPE), section
35
+ * `iOS Apple Wallet`, frame `1-1-1-how to verify` (26106:12647).
36
+ *
37
+ * The same screen as `IdCaptureDocumentSelectionScreen` with one more row: on
38
+ * iOS and Android the wallet on top, carrying Core's ⚡ Instant tag; on web a
39
+ * plain Digital ID row last (`[Web] Device Wallets`, 26106:13011). It is its own screen rather
40
+ * than a flag on ID Capture's so that ID Capture's chooser stays exactly what
41
+ * that module ships. Every piece is Core's — the row, the tag and the
42
+ * `apple-wallet` / `google-wallet` card icons (§10).
43
+ */
44
+ export const DigitalIdDeviceWalletsDocumentSelectionScreen = forwardRef<
45
+ HTMLDivElement,
46
+ DigitalIdDeviceWalletsDocumentSelectionScreenProps
47
+ >(
48
+ (
49
+ {
50
+ strings,
51
+ wallet = 'apple',
52
+ onOptionSelect,
53
+ screenId = 'digital-id-device-wallets-document-selection',
54
+ overrides,
55
+ onAction,
56
+ ...shell
57
+ },
58
+ ref,
59
+ ) => {
60
+ const choose = (option: DigitalIdDeviceWalletsOption) => {
61
+ onOptionSelect?.(option);
62
+ onAction?.({ type: 'cta', screenId });
63
+ };
64
+ const copy = strings.documentSelection;
65
+
66
+ return (
67
+ <PrizmaListScreen
68
+ ref={ref}
69
+ title={copy.title}
70
+ subtitle={copy.subtitle}
71
+ listAlign="end"
72
+ verifiedLabel={strings.verifiedLabel}
73
+ navLabel={strings.navLabel}
74
+ screenId={screenId}
75
+ overrides={overrides}
76
+ onAction={onAction}
77
+ {...shell}
78
+ >
79
+ <PrizmaCardListVerificationOptions
80
+ items={
81
+ wallet === 'digital-id'
82
+ ? [
83
+ // Web: the documents first, the plain Digital ID row last.
84
+ { icon: 'id', title: copy.idLabel, onClick: () => choose('id') },
85
+ { icon: 'passport', title: copy.passportLabel, onClick: () => choose('passport') },
86
+ { icon: 'digital-id', title: copy.digitalIdLabel, onClick: () => choose('wallet') },
87
+ ]
88
+ : [
89
+ {
90
+ icon: wallet === 'apple' ? 'apple-wallet' : 'google-wallet',
91
+ title: wallet === 'apple' ? copy.appleWalletLabel : copy.googleWalletLabel,
92
+ hasTag: true,
93
+ tagLabel: copy.instantLabel,
94
+ onClick: () => choose('wallet'),
95
+ },
96
+ { icon: 'id', title: copy.idLabel, onClick: () => choose('id') },
97
+ { icon: 'passport', title: copy.passportLabel, onClick: () => choose('passport') },
98
+ ]
99
+ }
100
+ />
101
+ </PrizmaListScreen>
102
+ );
103
+ },
104
+ );
105
+ DigitalIdDeviceWalletsDocumentSelectionScreen.displayName =
106
+ 'DigitalIdDeviceWalletsDocumentSelectionScreen';
107
+
108
+ export default DigitalIdDeviceWalletsDocumentSelectionScreen;
@@ -0,0 +1,76 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaResultScreen, type PrizmaResultScreenProps } from './ResultScreen';
3
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
4
+ import type {
5
+ DigitalIdDeviceWalletsResultState,
6
+ DigitalIdDeviceWalletsStrings,
7
+ } from './DigitalIdDeviceWalletsStrings';
8
+ import './ScreenLayout.css';
9
+
10
+ export interface DigitalIdDeviceWalletsResultScreenProps
11
+ extends Omit<
12
+ PrizmaResultScreenProps,
13
+ 'status' | 'title' | 'subtitle' | 'ctaLabel' | 'secondaryCtaLabel' | 'verifiedLabel' | 'navLabel'
14
+ > {
15
+ /** Module copy — this screen reads the `success` or `error` slice. */
16
+ strings: DigitalIdDeviceWalletsStrings;
17
+ /** Which verdict the wallet hand-back landed on. */
18
+ state: DigitalIdDeviceWalletsResultState;
19
+ screenId?: string;
20
+ overrides?: PrizmaScreenOverrides;
21
+ onAction?: PrizmaScreenActionHandler;
22
+ }
23
+
24
+ /**
25
+ * Digital ID Device Wallets — the verdict after the wallet hands the ID back,
26
+ * built on the `PrizmaResultScreen` archetype (GUIDELINES.md §6-F).
27
+ *
28
+ * `error` is `Digital ID Generic Error` (26540:5685): status icon, title and
29
+ * subtitle centred in the full height, one CTA near the bottom, no logo nav and
30
+ * no verified tag. `success` has no frame — the section's `Success?` decision
31
+ * goes straight to the next module — so it is the same recipe with the
32
+ * positive mark and no button: it moves on by itself after 3 s, the way Face
33
+ * Capture's success does (DEVIATIONS.md #DIW-1). On web the error can carry a
34
+ * second button, "Choose another method", back to the chooser (#DIW-5).
35
+ */
36
+ export const DigitalIdDeviceWalletsResultScreen = forwardRef<
37
+ HTMLDivElement,
38
+ DigitalIdDeviceWalletsResultScreenProps
39
+ >(
40
+ (
41
+ {
42
+ strings,
43
+ state,
44
+ screenId = `digital-id-device-wallets-${state}`,
45
+ showHeader = false,
46
+ showFooter = false,
47
+ overrides,
48
+ onAction,
49
+ ...shell
50
+ },
51
+ ref,
52
+ ) => {
53
+ const copy = state === 'success' ? strings.success : strings.error;
54
+ return (
55
+ <PrizmaResultScreen
56
+ ref={ref}
57
+ status={state}
58
+ title={copy.title}
59
+ subtitle={copy.subtitle}
60
+ ctaLabel={copy.ctaLabel}
61
+ secondaryCtaLabel={state === 'error' ? strings.error.secondaryCtaLabel : undefined}
62
+ verifiedLabel={strings.verifiedLabel}
63
+ navLabel={strings.navLabel}
64
+ showHeader={showHeader}
65
+ showFooter={showFooter}
66
+ screenId={screenId}
67
+ overrides={overrides}
68
+ onAction={onAction}
69
+ {...shell}
70
+ />
71
+ );
72
+ },
73
+ );
74
+ DigitalIdDeviceWalletsResultScreen.displayName = 'DigitalIdDeviceWalletsResultScreen';
75
+
76
+ export default DigitalIdDeviceWalletsResultScreen;
@@ -0,0 +1,80 @@
1
+ // Digital ID Device Wallets module — copy contract.
2
+ //
3
+ // Every Digital ID Device Wallets screen receives the SAME `strings:
4
+ // DigitalIdDeviceWalletsStrings` object (rule: all copy via props, no hardcoded
5
+ // English — GUIDELINES.md §9).
6
+ //
7
+ // Authoritative screens: the `iOS Apple Wallet` section of the Digital IDs -
8
+ // Latest Design Figma file (u7N5Zq4bfOwiVbpKHKmSPE, node 26103:3689) —
9
+ // `1-1-1-how to verify` (26106:12647, the chooser with the Apple Wallet row)
10
+ // and `Digital ID Generic Error` (26540:5685). Two frames of the section are
11
+ // NOT part of this contract: `Apple Wallet System Modal` (26597:14667) is the
12
+ // OS's own sheet — OS chrome, DEVIATIONS.md #DC-20 precedent, mocked on the
13
+ // Core Lab canvas instead — and `1-2-1-id` / `2-2-1-id` are ID Capture's own
14
+ // tutorials, which the Identity Card and Passport rows hand off to.
15
+ //
16
+ // The success state has no frame: the section's `Success?` decision goes
17
+ // straight to `Next module/screen`. It is built as the error's mirror on the
18
+ // same archetype and recorded as added, not traced (DEVIATIONS.md #DIW-1).
19
+
20
+ /** Which wallet row the chooser offers. iOS shows Apple Wallet and Android
21
+ * Google Wallet, first and tagged Instant; web shows a plain Digital ID row
22
+ * last (`[Web] Device Wallets`, 26106:13011), which opens the browser's
23
+ * wallet sheet. */
24
+ export type DigitalIdDeviceWalletsPlatformWallet = 'apple' | 'google' | 'digital-id';
25
+
26
+ /** The two verdicts the wallet hand-back can land on. */
27
+ export type DigitalIdDeviceWalletsResultState = 'success' | 'error';
28
+
29
+ /** What the person picked on the chooser. `wallet` stays in this module; `id`
30
+ * and `passport` hand off to ID Capture. */
31
+ export type DigitalIdDeviceWalletsOption = 'wallet' | 'id' | 'passport';
32
+
33
+ export interface DigitalIdDeviceWalletsStrings {
34
+ /** Accessible name for the logo nav region (i18n — no baked-in English). */
35
+ navLabel?: string;
36
+ /** "verified by" attribution copy for the footer tag. */
37
+ verifiedLabel: string;
38
+
39
+ /** `1-1-1-how to verify` (node 26106:12647). */
40
+ documentSelection: {
41
+ /** "Select how to verify" */
42
+ title: string;
43
+ subtitle?: string;
44
+ /** "Apple Wallet" */
45
+ appleWalletLabel: string;
46
+ /** "Google Wallet" — the Android row. */
47
+ googleWalletLabel: string;
48
+ /** "Digital ID" — the web row. */
49
+ digitalIdLabel: string;
50
+ /** "Instant" — the tag under the wallet row. */
51
+ instantLabel: string;
52
+ /** "Identity Card" */
53
+ idLabel: string;
54
+ /** "Passport" */
55
+ passportLabel: string;
56
+ };
57
+
58
+ /** `Successfully verified` (node 26598:16374) — no button (DEVIATIONS.md #DIW-1). */
59
+ success: {
60
+ /** "Identity successfully verified" — the NFC / OCR Review success title. */
61
+ title: string;
62
+ subtitle?: string;
63
+ /** No button by default: like Face Capture's success, the flow moves on by
64
+ * itself after 3 s. Set it only for a host that waits for a tap. */
65
+ ctaLabel?: string;
66
+ };
67
+
68
+ /** `Digital ID Generic Error` (node 26540:5685). */
69
+ error: {
70
+ /** "Couldn't verify your ID" */
71
+ title: string;
72
+ /** "Please try again" */
73
+ subtitle?: string;
74
+ /** "Try again" */
75
+ ctaLabel: string;
76
+ /** "Choose another method" — web only: back to the chooser, the SDK's
77
+ * `deviceWalletUseAnotherMethod()`. Absent, the screen has one button. */
78
+ secondaryCtaLabel?: string;
79
+ };
80
+ }
@@ -0,0 +1,112 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaCardListVerificationOptions } from '@incodetech/prizma-core-web/card-list';
3
+ import { PrizmaCountryFlag } from '@incodetech/prizma-core-web/combined';
4
+ import { PrizmaListScreen, type PrizmaListScreenProps } from './ListScreen';
5
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
6
+ import type {
7
+ DigitalIdProvidersSelection,
8
+ DigitalIdProvidersStrings,
9
+ } from './DigitalIdProvidersStrings';
10
+ import './ScreenLayout.css';
11
+ import './DigitalIdProvidersLayout.css';
12
+
13
+ export interface DigitalIdProvidersDocumentSelectionScreenProps
14
+ extends Omit<
15
+ PrizmaListScreenProps,
16
+ 'title' | 'subtitle' | 'children' | 'listAlign' | 'verifiedLabel' | 'navLabel'
17
+ > {
18
+ /** Module copy — this screen reads the `documentSelection` slice. */
19
+ strings: DigitalIdProvidersStrings;
20
+ /** How many providers to list; all of them when absent. The frame's first
21
+ * state (27753:8099) shows six, the full list (27703:4895) scrolls. */
22
+ providerCount?: number;
23
+ /** Fired with what was picked; `onAction` still reports the tap. */
24
+ onOptionSelect?: (selection: DigitalIdProvidersSelection) => void;
25
+ screenId?: string;
26
+ overrides?: PrizmaScreenOverrides;
27
+ onAction?: PrizmaScreenActionHandler;
28
+ }
29
+
30
+ /**
31
+ * Digital ID Providers — choose how to verify: your own ID, or a Digital ID
32
+ * provider, on the `PrizmaListScreen` archetype (GUIDELINES.md §6-G).
33
+ * Figma: `Document Chooser` (27753:8099) and the full list (27703:4895).
34
+ *
35
+ * Two of Core's card lists, each under a section label, after a "Viewing
36
+ * options for" country line with Core's flag. Every row is Core's; the
37
+ * providers carry Core's generic `digital-id-web` card icon until their logos
38
+ * arrive from the backend catalog (DEVIATIONS #DIP-1), and the Identity Card
39
+ * row has no second line, which Core's row cannot draw (#DIP-3).
40
+ */
41
+ export const DigitalIdProvidersDocumentSelectionScreen = forwardRef<
42
+ HTMLDivElement,
43
+ DigitalIdProvidersDocumentSelectionScreenProps
44
+ >(
45
+ (
46
+ {
47
+ strings,
48
+ providerCount,
49
+ onOptionSelect,
50
+ screenId = 'digital-id-providers-document-selection',
51
+ overrides,
52
+ onAction,
53
+ ...shell
54
+ },
55
+ ref,
56
+ ) => {
57
+ const copy = strings.documentSelection;
58
+ const providers =
59
+ providerCount === undefined ? copy.providers : copy.providers.slice(0, providerCount);
60
+ const choose = (selection: DigitalIdProvidersSelection) => {
61
+ onOptionSelect?.(selection);
62
+ onAction?.({ type: 'cta', screenId });
63
+ };
64
+
65
+ return (
66
+ <PrizmaListScreen
67
+ ref={ref}
68
+ title={copy.title}
69
+ listAlign="start"
70
+ scrollList
71
+ verifiedLabel={strings.verifiedLabel}
72
+ navLabel={strings.navLabel}
73
+ screenId={screenId}
74
+ overrides={overrides}
75
+ onAction={onAction}
76
+ {...shell}
77
+ >
78
+ <div className="digital-id-providers-chooser">
79
+ <p className="digital-id-providers-country">
80
+ {copy.countryLabel}
81
+ <PrizmaCountryFlag
82
+ country={{ code: copy.countryCode, name: copy.countryName, dialCode: '', flag: '' }}
83
+ />
84
+ <span className="digital-id-providers-country__name">{copy.countryName}</span>
85
+ </p>
86
+ <section className="digital-id-providers-section">
87
+ <p className="digital-id-providers-section__label">{copy.idSectionLabel}</p>
88
+ <PrizmaCardListVerificationOptions
89
+ items={[
90
+ { icon: 'id', title: copy.idLabel, onClick: () => choose({ kind: 'id' }) },
91
+ { icon: 'passport', title: copy.passportLabel, onClick: () => choose({ kind: 'passport' }) },
92
+ ]}
93
+ />
94
+ </section>
95
+ <section className="digital-id-providers-section">
96
+ <p className="digital-id-providers-section__label">{copy.providersSectionLabel}</p>
97
+ <PrizmaCardListVerificationOptions
98
+ items={providers.map(provider => ({
99
+ icon: 'digital-id-web' as const,
100
+ title: provider.label,
101
+ onClick: () => choose({ kind: 'provider', providerId: provider.id }),
102
+ }))}
103
+ />
104
+ </section>
105
+ </div>
106
+ </PrizmaListScreen>
107
+ );
108
+ },
109
+ );
110
+ DigitalIdProvidersDocumentSelectionScreen.displayName = 'DigitalIdProvidersDocumentSelectionScreen';
111
+
112
+ export default DigitalIdProvidersDocumentSelectionScreen;
@@ -0,0 +1,104 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaCardDocumentList } from '@incodetech/prizma-core-web/card';
3
+ import { PrizmaResultScreen, type PrizmaResultScreenProps } from './ResultScreen';
4
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
5
+ import type {
6
+ DigitalIdProvidersErrorState,
7
+ DigitalIdProvidersStrings,
8
+ } from './DigitalIdProvidersStrings';
9
+ import './ScreenLayout.css';
10
+
11
+ export interface DigitalIdProvidersErrorScreenProps
12
+ extends Omit<
13
+ PrizmaResultScreenProps,
14
+ | 'status'
15
+ | 'title'
16
+ | 'subtitle'
17
+ | 'children'
18
+ | 'ctaLabel'
19
+ | 'secondaryCtaLabel'
20
+ | 'verifiedLabel'
21
+ | 'navLabel'
22
+ > {
23
+ /** Module copy — this screen reads the `errors` slice for its `state`, and
24
+ * `acceptedDocuments` on the two document states. */
25
+ strings: DigitalIdProvidersStrings;
26
+ state: DigitalIdProvidersErrorState;
27
+ screenId?: string;
28
+ overrides?: PrizmaScreenOverrides;
29
+ onAction?: PrizmaScreenActionHandler;
30
+ }
31
+
32
+ /** The two states that list the documents accepted instead. */
33
+ const LISTS_DOCUMENTS: ReadonlySet<DigitalIdProvidersErrorState> = new Set(['not-accepted', 'expired']);
34
+
35
+ /**
36
+ * Digital ID Providers — the five failures of a provider run, on the
37
+ * `PrizmaResultScreen` archetype (GUIDELINES.md §6-F). Figma: `Errors`
38
+ * (27707:9338).
39
+ *
40
+ * unavailable the provider could not be reached — Scan ID instead
41
+ * consent-denied the person did not grant sharing at the provider
42
+ * timed-out the provider session did not finish in time
43
+ * not-accepted the ID behind the provider is not one the flow accepts
44
+ * expired the ID behind the provider has expired
45
+ *
46
+ * Every state has two buttons, the second "Choose another method" (#DIP-4).
47
+ * The two document states carry Core's `PrizmaCardDocumentList` in the
48
+ * archetype's `children` slot, the same recipe ID Capture's document error
49
+ * uses. The first three keep the footer tag as drawn; the two document states
50
+ * drop it, as drawn.
51
+ */
52
+ export const DigitalIdProvidersErrorScreen = forwardRef<
53
+ HTMLDivElement,
54
+ DigitalIdProvidersErrorScreenProps
55
+ >(
56
+ (
57
+ {
58
+ strings,
59
+ state,
60
+ screenId = `digital-id-providers-error-${state}`,
61
+ showHeader = false,
62
+ showFooter,
63
+ overrides,
64
+ onAction,
65
+ ...shell
66
+ },
67
+ ref,
68
+ ) => {
69
+ const copy = strings.errors[state];
70
+ const listsDocuments = LISTS_DOCUMENTS.has(state);
71
+ const docs = strings.acceptedDocuments;
72
+ return (
73
+ <PrizmaResultScreen
74
+ ref={ref}
75
+ status="error"
76
+ title={copy.title}
77
+ subtitle={copy.subtitle}
78
+ ctaLabel={copy.ctaLabel}
79
+ secondaryCtaLabel={copy.secondaryCtaLabel}
80
+ verifiedLabel={strings.verifiedLabel}
81
+ navLabel={strings.navLabel}
82
+ showHeader={showHeader}
83
+ showFooter={showFooter ?? !listsDocuments}
84
+ screenId={screenId}
85
+ overrides={overrides}
86
+ onAction={onAction}
87
+ {...shell}
88
+ >
89
+ {listsDocuments ? (
90
+ <PrizmaCardDocumentList
91
+ state="default"
92
+ countryCode={docs.countryCode}
93
+ flag={docs.flag}
94
+ country={docs.country}
95
+ documents={docs.documents}
96
+ />
97
+ ) : null}
98
+ </PrizmaResultScreen>
99
+ );
100
+ },
101
+ );
102
+ DigitalIdProvidersErrorScreen.displayName = 'DigitalIdProvidersErrorScreen';
103
+
104
+ export default DigitalIdProvidersErrorScreen;
@@ -0,0 +1,59 @@
1
+ /* Digital ID Providers — the chooser's country line and section labels.
2
+ *
3
+ * Archetype G has one list slot and no section-label recipe; the provider
4
+ * chooser (27753:8099) groups two Core card lists under labels ("Use your ID",
5
+ * "Digital ID verification") with a "Viewing options for 🇺🇸 US" line under the
6
+ * title. Composed here from tokens only, like Reusability's rows (#RU-1);
7
+ * DEVIATIONS #DIP-2 asks for a foundation recipe. */
8
+
9
+ .digital-id-providers-chooser {
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: var(--prizma-spacing-24);
13
+ }
14
+
15
+ .digital-id-providers-country {
16
+ display: flex;
17
+ align-items: center;
18
+ justify-content: center;
19
+ gap: var(--prizma-spacing-8);
20
+ color: var(--prizma-text-body-500-secondary);
21
+ font-family: var(--prizma-body-family);
22
+ font-size: var(--prizma-body-m-regular-font-size);
23
+ font-weight: var(--prizma-body-m-regular-font-weight);
24
+ line-height: var(--prizma-body-m-regular-line-height);
25
+ letter-spacing: var(--prizma-body-m-regular-letter-spacing);
26
+ }
27
+
28
+ .digital-id-providers-country__name {
29
+ color: var(--prizma-text-body-800-primary);
30
+ text-decoration: underline;
31
+ }
32
+
33
+ .digital-id-providers-section {
34
+ display: flex;
35
+ flex-direction: column;
36
+ gap: var(--prizma-spacing-8);
37
+ }
38
+
39
+ .digital-id-providers-section__label {
40
+ margin: 0;
41
+ color: var(--prizma-text-body-500-secondary);
42
+ font-family: var(--prizma-body-family);
43
+ font-size: var(--prizma-body-m-regular-font-size);
44
+ font-weight: var(--prizma-body-m-regular-font-weight);
45
+ line-height: var(--prizma-body-m-regular-line-height);
46
+ letter-spacing: var(--prizma-body-m-regular-letter-spacing);
47
+ }
48
+
49
+ /* Redirecting — the spinner and its copy sit at the middle of the screen.
50
+ * With the header hidden, archetype C still reserves the nav row above the
51
+ * content and centres the column in what is left, so the block lands ~63px
52
+ * low. Mirroring that reserve below — status bar, the nav's gap and height,
53
+ * the column's own top padding (ScreenNav.css, ScreenLayout.css) — balances
54
+ * it on the shell's midline. */
55
+ .digital-id-providers-redirect .prizma-screen-layout__content--centered {
56
+ padding-bottom: calc(
57
+ var(--pcs-status-bar, 47px) + var(--prizma-spacing-12) + 44px + var(--prizma-spacing-24)
58
+ );
59
+ }
@@ -0,0 +1,65 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaProcessingScreen, type PrizmaProcessingScreenProps } from './ProcessingScreen';
3
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
4
+ import type { DigitalIdProvidersStrings } from './DigitalIdProvidersStrings';
5
+ import './ScreenLayout.css';
6
+ import './DigitalIdProvidersLayout.css';
7
+
8
+ export interface DigitalIdProvidersRedirectScreenProps
9
+ extends Omit<
10
+ PrizmaProcessingScreenProps,
11
+ 'status' | 'title' | 'subtitle' | 'verifiedLabel' | 'navLabel'
12
+ > {
13
+ /** Module copy — this screen reads the `redirecting` slice. */
14
+ strings: DigitalIdProvidersStrings;
15
+ screenId?: string;
16
+ overrides?: PrizmaScreenOverrides;
17
+ onAction?: PrizmaScreenActionHandler;
18
+ }
19
+
20
+ /**
21
+ * Digital ID Providers — "Redirecting for verification…", the wait before the
22
+ * browser leaves for the provider's site, on the `PrizmaProcessingScreen`
23
+ * archetype (GUIDELINES.md §6-C). Figma: the `1-18-1-id-hold-on` instance in
24
+ * the web full flow (27707:9281), with the module's own copy. The Web SDK's
25
+ * `digitalIdRedirect` phases `loading` and `redirecting` both look like this.
26
+ * The block is centred on the whole screen, not below the hidden nav's
27
+ * reserved row (DigitalIdProvidersLayout.css).
28
+ */
29
+ export const DigitalIdProvidersRedirectScreen = forwardRef<
30
+ HTMLDivElement,
31
+ DigitalIdProvidersRedirectScreenProps
32
+ >(
33
+ (
34
+ {
35
+ strings,
36
+ screenId = 'digital-id-providers-redirecting',
37
+ showHeader = false,
38
+ showFooter = false,
39
+ overrides,
40
+ onAction,
41
+ className,
42
+ ...shell
43
+ },
44
+ ref,
45
+ ) => (
46
+ <PrizmaProcessingScreen
47
+ ref={ref}
48
+ status="loading"
49
+ title={strings.redirecting.title}
50
+ subtitle={strings.redirecting.subtitle}
51
+ verifiedLabel={strings.verifiedLabel}
52
+ navLabel={strings.navLabel}
53
+ showHeader={showHeader}
54
+ showFooter={showFooter}
55
+ screenId={screenId}
56
+ overrides={overrides}
57
+ onAction={onAction}
58
+ className={['digital-id-providers-redirect', className].filter(Boolean).join(' ')}
59
+ {...shell}
60
+ />
61
+ ),
62
+ );
63
+ DigitalIdProvidersRedirectScreen.displayName = 'DigitalIdProvidersRedirectScreen';
64
+
65
+ export default DigitalIdProvidersRedirectScreen;