@incodetech/prizma-core-screens 0.2.7 β†’ 0.2.12

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 (168) 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/DigitalIdUploadErrorScreen.d.ts +31 -0
  12. package/dist/DigitalIdUploadErrorScreen.js +26 -0
  13. package/dist/DigitalIdUploadFileTooLargeScreen.d.ts +27 -0
  14. package/dist/DigitalIdUploadFileTooLargeScreen.js +21 -0
  15. package/dist/DigitalIdUploadReviewScreen.d.ts +57 -0
  16. package/dist/DigitalIdUploadReviewScreen.js +44 -0
  17. package/dist/DigitalIdUploadStrings.d.ts +64 -0
  18. package/dist/DigitalIdUploadStrings.js +19 -0
  19. package/dist/DigitalIdUploadTutorialScreen.d.ts +28 -0
  20. package/dist/DigitalIdUploadTutorialScreen.js +23 -0
  21. package/dist/DocumentCaptureIllustration.d.ts +1 -1
  22. package/dist/EkybCountryScreen.d.ts +6 -6
  23. package/dist/EkybCountryScreen.js +20 -7
  24. package/dist/EkybStrings.d.ts +6 -1
  25. package/dist/ErrorScreensScreen.d.ts +5 -2
  26. package/dist/ErrorScreensScreen.js +15 -4
  27. package/dist/ErrorScreensStrings.d.ts +17 -2
  28. package/dist/ErrorScreensStrings.js +18 -10
  29. package/dist/FaceCaptureCapturingScreen.d.ts +63 -0
  30. package/dist/FaceCaptureCapturingScreen.js +62 -2
  31. package/dist/FaceCaptureLayout.css +69 -4
  32. package/dist/FaceCaptureStrings.d.ts +23 -0
  33. package/dist/FormScreen.css +14 -0
  34. package/dist/FormScreen.d.ts +28 -0
  35. package/dist/FormScreen.js +3 -2
  36. package/dist/IdCaptureLayout.css +165 -2
  37. package/dist/IdCaptureStageScreen.d.ts +47 -0
  38. package/dist/IdCaptureStageScreen.js +39 -3
  39. package/dist/IdCaptureStrings.d.ts +19 -0
  40. package/dist/ListScreen.d.ts +19 -0
  41. package/dist/ListScreen.js +7 -2
  42. package/dist/LoaderScreen.d.ts +7 -5
  43. package/dist/LoaderScreen.js +7 -5
  44. package/dist/LoadersStrings.d.ts +18 -5
  45. package/dist/OcrReviewErrorScreen.d.ts +30 -0
  46. package/dist/OcrReviewErrorScreen.js +24 -0
  47. package/dist/OcrReviewLayout.css +24 -0
  48. package/dist/OcrReviewLoadingScreen.d.ts +25 -0
  49. package/dist/OcrReviewLoadingScreen.js +19 -0
  50. package/dist/OcrReviewScreen.d.ts +76 -0
  51. package/dist/OcrReviewScreen.js +65 -0
  52. package/dist/OcrReviewStrings.d.ts +47 -0
  53. package/dist/OcrReviewStrings.js +17 -0
  54. package/dist/OcrReviewSuccessScreen.d.ts +30 -0
  55. package/dist/OcrReviewSuccessScreen.js +24 -0
  56. package/dist/PermissionsAllowScreen.d.ts +8 -11
  57. package/dist/PermissionsAllowScreen.js +8 -11
  58. package/dist/PermissionsAskScreen.d.ts +41 -0
  59. package/dist/PermissionsAskScreen.js +43 -0
  60. package/dist/PermissionsBrowserStepsScreen.d.ts +9 -2
  61. package/dist/PermissionsBrowserStepsScreen.js +12 -3
  62. package/dist/PermissionsLayout.css +47 -0
  63. package/dist/PermissionsStrings.d.ts +20 -9
  64. package/dist/PermissionsStrings.js +10 -4
  65. package/dist/PhoneInputOtpScreen.d.ts +8 -0
  66. package/dist/PhoneInputOtpScreen.js +26 -19
  67. package/dist/PhoneInputStrings.d.ts +11 -3
  68. package/dist/PhoneInputVerifyScreen.js +21 -5
  69. package/dist/QualifiedSignatureDocumentScreen.d.ts +8 -5
  70. package/dist/QualifiedSignatureDocumentScreen.js +9 -6
  71. package/dist/QualifiedSignatureResultScreen.d.ts +16 -13
  72. package/dist/QualifiedSignatureResultScreen.js +17 -18
  73. package/dist/QualifiedSignatureStrings.d.ts +11 -4
  74. package/dist/ResultScreen.d.ts +8 -0
  75. package/dist/ResultScreen.js +14 -3
  76. package/dist/ReusabilityCredentialSelectionScreen.d.ts +95 -0
  77. package/dist/ReusabilityCredentialSelectionScreen.js +94 -0
  78. package/dist/ReusabilityLayout.css +241 -0
  79. package/dist/ReusabilityPrivacyPolicyScreen.d.ts +55 -0
  80. package/dist/ReusabilityPrivacyPolicyScreen.js +44 -0
  81. package/dist/ReusabilityStrings.d.ts +85 -0
  82. package/dist/ReusabilityStrings.js +37 -0
  83. package/dist/ReviewScreen.d.ts +38 -12
  84. package/dist/ReviewScreen.js +41 -8
  85. package/dist/ScreenLayout.css +382 -6
  86. package/dist/VideoSelfieErrorScreen.js +1 -1
  87. package/dist/VideoSelfieIdCaptureScreen.js +1 -1
  88. package/dist/VideoSelfieLayout.css +304 -2
  89. package/dist/VideoSelfieSelfieCaptureScreen.js +1 -1
  90. package/dist/VideoSelfieSpeakScreen.js +1 -1
  91. package/dist/VideoSelfieStrings.d.ts +4 -1
  92. package/dist/VideoSelfieTurnHeadScreen.js +14 -11
  93. package/dist/VideoSelfieTutorialScreen.d.ts +9 -0
  94. package/dist/VideoSelfieTutorialScreen.js +10 -1
  95. package/dist/VideoSelfieWaveScreen.js +1 -1
  96. package/dist/ViewfinderScreen.css +36 -0
  97. package/dist/flows.d.ts +8 -0
  98. package/dist/flows.js +17 -0
  99. package/dist/index.d.ts +16 -0
  100. package/dist/index.js +12 -0
  101. package/dist/styles.css +3 -0
  102. package/package.json +68 -3
  103. package/samples/video-selfie-camera-wide.jpg +0 -0
  104. package/samples/video-selfie-room-wide.jpg +0 -0
  105. package/src/BiometricConsentScreen.tsx +192 -0
  106. package/src/BiometricConsentStrings.ts +119 -0
  107. package/src/CaptureScreen.tsx +17 -0
  108. package/src/DemoScreensLayout.css +16 -0
  109. package/src/DemoScreensRedirectScreen.tsx +14 -6
  110. package/src/DemoScreensStrings.ts +5 -0
  111. package/src/DigitalIdUploadErrorScreen.tsx +83 -0
  112. package/src/DigitalIdUploadFileTooLargeScreen.tsx +67 -0
  113. package/src/DigitalIdUploadReviewScreen.tsx +119 -0
  114. package/src/DigitalIdUploadStrings.ts +88 -0
  115. package/src/DigitalIdUploadTutorialScreen.tsx +59 -0
  116. package/src/DocumentCaptureIllustration.tsx +1 -1
  117. package/src/EkybCountryScreen.tsx +23 -6
  118. package/src/EkybStrings.ts +6 -1
  119. package/src/ErrorScreensScreen.tsx +15 -4
  120. package/src/ErrorScreensStrings.ts +37 -12
  121. package/src/FaceCaptureCapturingScreen.tsx +102 -13
  122. package/src/FaceCaptureLayout.css +69 -4
  123. package/src/FaceCaptureStrings.ts +24 -0
  124. package/src/FormScreen.css +14 -0
  125. package/src/FormScreen.tsx +34 -0
  126. package/src/IdCaptureLayout.css +165 -2
  127. package/src/IdCaptureStageScreen.tsx +75 -0
  128. package/src/IdCaptureStrings.ts +19 -0
  129. package/src/ListScreen.tsx +48 -9
  130. package/src/LoaderScreen.tsx +7 -5
  131. package/src/LoadersStrings.ts +18 -5
  132. package/src/OcrReviewErrorScreen.tsx +53 -0
  133. package/src/OcrReviewLayout.css +24 -0
  134. package/src/OcrReviewLoadingScreen.tsx +48 -0
  135. package/src/OcrReviewScreen.tsx +190 -0
  136. package/src/OcrReviewStrings.ts +69 -0
  137. package/src/OcrReviewSuccessScreen.tsx +52 -0
  138. package/src/PermissionsAllowScreen.tsx +9 -10
  139. package/src/PermissionsAskScreen.tsx +105 -0
  140. package/src/PermissionsBrowserStepsScreen.tsx +11 -3
  141. package/src/PermissionsLayout.css +47 -0
  142. package/src/PermissionsStrings.ts +42 -12
  143. package/src/PhoneInputOtpScreen.tsx +23 -3
  144. package/src/PhoneInputStrings.ts +11 -3
  145. package/src/PhoneInputVerifyScreen.tsx +24 -4
  146. package/src/QualifiedSignatureDocumentScreen.tsx +9 -7
  147. package/src/QualifiedSignatureResultScreen.tsx +28 -26
  148. package/src/QualifiedSignatureStrings.ts +11 -4
  149. package/src/ResultScreen.tsx +33 -2
  150. package/src/ReusabilityCredentialSelectionScreen.tsx +246 -0
  151. package/src/ReusabilityLayout.css +241 -0
  152. package/src/ReusabilityPrivacyPolicyScreen.tsx +109 -0
  153. package/src/ReusabilityStrings.ts +127 -0
  154. package/src/ReviewScreen.tsx +96 -27
  155. package/src/ScreenLayout.css +382 -6
  156. package/src/VideoSelfieErrorScreen.tsx +1 -1
  157. package/src/VideoSelfieIdCaptureScreen.tsx +9 -1
  158. package/src/VideoSelfieLayout.css +304 -2
  159. package/src/VideoSelfieSelfieCaptureScreen.tsx +9 -1
  160. package/src/VideoSelfieSpeakScreen.tsx +9 -1
  161. package/src/VideoSelfieStrings.ts +4 -2
  162. package/src/VideoSelfieTurnHeadScreen.tsx +25 -14
  163. package/src/VideoSelfieTutorialScreen.tsx +11 -0
  164. package/src/VideoSelfieWaveScreen.tsx +9 -1
  165. package/src/ViewfinderScreen.css +36 -0
  166. package/src/flows.ts +25 -0
  167. package/src/index.ts +74 -3
  168. package/src/styles.css +3 -0
@@ -0,0 +1,83 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaCaptureDigitalId } from '@incodetech/prizma-core-web/capture-digital-id';
3
+ import { PrizmaReviewScreen, type PrizmaReviewScreenProps } from './ReviewScreen';
4
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
5
+ import type { DigitalIdUploadStrings } from './DigitalIdUploadStrings';
6
+ import './ScreenLayout.css';
7
+
8
+ export interface DigitalIdUploadErrorScreenProps
9
+ extends Omit<
10
+ PrizmaReviewScreenProps,
11
+ | 'stage'
12
+ | 'title'
13
+ | 'subtitle'
14
+ | 'successTitle'
15
+ | 'analyzingLabel'
16
+ | 'primaryLabel'
17
+ | 'secondaryLabel'
18
+ | 'verifiedLabel'
19
+ | 'children'
20
+ > {
21
+ /** Module copy β€” this screen reads the `error` slice. */
22
+ strings: DigitalIdUploadStrings;
23
+ screenId?: string;
24
+ overrides?: PrizmaScreenOverrides;
25
+ onAction?: PrizmaScreenActionHandler;
26
+ }
27
+
28
+ /**
29
+ * Digital ID Upload β€” the uploaded file was rejected, built on the
30
+ * `PrizmaReviewScreen` archetype's `error` stage (GUIDELINES.md Β§6-H). Figma:
31
+ * `Upload Digital ID` file (wxFsHRvllern4VnjRqM4JO), `Errors` section,
32
+ * `Error` frame (node 25874:11957).
33
+ *
34
+ * Kept separate from `DigitalIdUploadReviewScreen` (the confirm flow) rather
35
+ * than folded into it as a fourth stage of that wrapper β€” same split Document
36
+ * Capture draws between its confirm screens and
37
+ * `DocumentCaptureGenericErrorScreen`, even though here both wrappers happen
38
+ * to share the same archetype under the hood. The media is
39
+ * `PrizmaCaptureDigitalId state="error"` (red 4px border) β€” the same managed
40
+ * component every other stage uses, not a bespoke verdict illustration β€” and
41
+ * the header/footer are hidden exactly like `analyzing`/`success`
42
+ * (`centeredWhenNoNav`, since this Figma frame draws the identical symmetric
43
+ * header/media/CTA skeleton).
44
+ */
45
+ export const DigitalIdUploadErrorScreen = forwardRef<
46
+ HTMLDivElement,
47
+ DigitalIdUploadErrorScreenProps
48
+ >(
49
+ (
50
+ {
51
+ strings,
52
+ screenId = 'digital-id-upload-error',
53
+ showHeader = false,
54
+ showFooter = false,
55
+ overrides,
56
+ onAction,
57
+ ...shell
58
+ },
59
+ ref,
60
+ ) => (
61
+ <PrizmaReviewScreen
62
+ ref={ref}
63
+ stage="error"
64
+ title={strings.error.title}
65
+ subtitle={strings.error.subtitle}
66
+ primaryLabel={strings.error.ctaLabel}
67
+ centeredWhenNoNav
68
+ verifiedLabel={strings.verifiedLabel}
69
+ navLabel={strings.navLabel}
70
+ showHeader={showHeader}
71
+ showFooter={showFooter}
72
+ screenId={screenId}
73
+ overrides={overrides}
74
+ onAction={onAction}
75
+ {...shell}
76
+ >
77
+ <PrizmaCaptureDigitalId state="error" />
78
+ </PrizmaReviewScreen>
79
+ ),
80
+ );
81
+ DigitalIdUploadErrorScreen.displayName = 'DigitalIdUploadErrorScreen';
82
+
83
+ export default DigitalIdUploadErrorScreen;
@@ -0,0 +1,67 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaResultScreen, type PrizmaResultScreenProps } from './ResultScreen';
3
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
4
+ import type { DigitalIdUploadStrings } from './DigitalIdUploadStrings';
5
+ import './ScreenLayout.css';
6
+
7
+ export interface DigitalIdUploadFileTooLargeScreenProps
8
+ extends Omit<
9
+ PrizmaResultScreenProps,
10
+ 'status' | 'title' | 'subtitle' | 'ctaLabel' | 'verifiedLabel' | 'navLabel'
11
+ > {
12
+ /** Module copy β€” this screen reads the `fileTooLarge` slice. */
13
+ strings: DigitalIdUploadStrings;
14
+ screenId?: string;
15
+ overrides?: PrizmaScreenOverrides;
16
+ onAction?: PrizmaScreenActionHandler;
17
+ }
18
+
19
+ /**
20
+ * Digital ID Upload β€” the selected file exceeds the size limit, built on the
21
+ * `PrizmaResultScreen` archetype (GUIDELINES.md Β§6-F). Figma: `Upload Digital
22
+ * ID` file (wxFsHRvllern4VnjRqM4JO), `Errors` section, `File Limit Error`
23
+ * frame (node 26083:3981).
24
+ *
25
+ * Unlike `DigitalIdUploadErrorScreen` (the rejected-document verdict, built on
26
+ * the Review archetype because it reuses `PrizmaCaptureDigitalId`), this
27
+ * screen never had a file to show β€” the size check runs before anything
28
+ * uploads β€” so Figma draws the plain F recipe: status icon + title + subtitle
29
+ * centred in the full height, one CTA pinned near the bottom. No media slot,
30
+ * no card, nothing to reuse from the capture component.
31
+ */
32
+ export const DigitalIdUploadFileTooLargeScreen = forwardRef<
33
+ HTMLDivElement,
34
+ DigitalIdUploadFileTooLargeScreenProps
35
+ >(
36
+ (
37
+ {
38
+ strings,
39
+ screenId = 'digital-id-upload-file-too-large',
40
+ showHeader = false,
41
+ showFooter = false,
42
+ overrides,
43
+ onAction,
44
+ ...shell
45
+ },
46
+ ref,
47
+ ) => (
48
+ <PrizmaResultScreen
49
+ ref={ref}
50
+ status="error"
51
+ title={strings.fileTooLarge.title}
52
+ subtitle={strings.fileTooLarge.subtitle}
53
+ ctaLabel={strings.fileTooLarge.ctaLabel}
54
+ verifiedLabel={strings.verifiedLabel}
55
+ navLabel={strings.navLabel}
56
+ showHeader={showHeader}
57
+ showFooter={showFooter}
58
+ screenId={screenId}
59
+ overrides={overrides}
60
+ onAction={onAction}
61
+ {...shell}
62
+ />
63
+ ),
64
+ );
65
+ DigitalIdUploadFileTooLargeScreen.displayName = 'DigitalIdUploadFileTooLargeScreen';
66
+
67
+ export default DigitalIdUploadFileTooLargeScreen;
@@ -0,0 +1,119 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaCaptureDigitalId } from '@incodetech/prizma-core-web/capture-digital-id';
3
+ import { PrizmaReviewScreen, type PrizmaReviewScreenProps } from './ReviewScreen';
4
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
5
+ import type {
6
+ DigitalIdUploadConfirmStage,
7
+ DigitalIdUploadStrings,
8
+ } from './DigitalIdUploadStrings';
9
+ import './ScreenLayout.css';
10
+
11
+ export interface DigitalIdUploadReviewScreenProps
12
+ extends Omit<
13
+ PrizmaReviewScreenProps,
14
+ | 'title'
15
+ | 'subtitle'
16
+ | 'successTitle'
17
+ | 'analyzingLabel'
18
+ | 'primaryLabel'
19
+ | 'secondaryLabel'
20
+ | 'verifiedLabel'
21
+ | 'children'
22
+ | 'stage'
23
+ > {
24
+ /** Module copy β€” this screen reads the `review` slice. */
25
+ strings: DigitalIdUploadStrings;
26
+ /** Which stage of the confirm flow to render. Default `review`. */
27
+ stage?: DigitalIdUploadConfirmStage;
28
+ /** The uploaded file's name, shown under the card on `review` only. Not
29
+ * copy β€” it is runtime data from the picker, so it stays out of
30
+ * `strings` (same contract as `DocumentCaptureConfirmUploadScreen`). */
31
+ filename?: string;
32
+ /** Loading-bar progress on `analyzing`, 0–100. */
33
+ progress?: number;
34
+ screenId?: string;
35
+ overrides?: PrizmaScreenOverrides;
36
+ onAction?: PrizmaScreenActionHandler;
37
+ }
38
+
39
+ /**
40
+ * Digital ID Upload β€” review / analyzing / success, built on the
41
+ * `PrizmaReviewScreen` archetype (GUIDELINES.md Β§6-H). Figma: `Upload Digital
42
+ * ID` file (wxFsHRvllern4VnjRqM4JO), "Web Happy Path - Light Mode" section β€”
43
+ * `Review Document` / `Analyzing` / `Success` (nodes 25351:14725/6/7).
44
+ *
45
+ * The media stage is Core's `PrizmaCaptureDigitalId` across all three stages
46
+ * β€” its own state enum (`review` / `analyzing` / `success`) maps directly
47
+ * onto the archetype's stage axis, so it already owns the border treatment
48
+ * (neutral on review, green 4px on analyzing/success), the scan-flash sweep
49
+ * and the filename row. Nothing is hand-built here, unlike
50
+ * `DocumentCaptureConfirmUploadScreen`'s bespoke file-card β€” Core ships a
51
+ * purpose-built component for this module.
52
+ *
53
+ * Header/footer visibility is genuinely per-stage in this Figma (logo nav +
54
+ * verified tag show on `review`, both are absent on `analyzing` and
55
+ * `success`) β€” not a layout choice this file invents, just the existing
56
+ * `showHeader`/`showFooter` chrome knobs (owner rule 2026-08-18: header and
57
+ * footer are independently controlled) applied per stage.
58
+ *
59
+ * Always opts into the archetype's `centeredWhenNoNav` β€” it only takes effect
60
+ * while the nav is hidden (`analyzing`/`success` here), where this Figma
61
+ * draws the header + media as one group centred with equal space above and
62
+ * below it, not a pinned header (see ReviewScreen.tsx for the mechanics).
63
+ * `review` always shows its own nav, so the flag is a no-op there, and the
64
+ * default `false` leaves Document Capture's existing analyzing/success
65
+ * screens byte-for-byte unchanged (neither ever hides the nav here).
66
+ *
67
+ * GAP (report, not workaround β€” README rule 2): Figma's `Success` section
68
+ * also shows a subtitle ("Let's continue") under the success title, but the
69
+ * shared `PrizmaReviewScreen` archetype only renders a subtitle on
70
+ * `stage="review"` β€” every other current consumer's success state has none.
71
+ * Left unset here pending an owner call on whether to extend the shared
72
+ * archetype with a `successSubtitle` slot.
73
+ */
74
+ export const DigitalIdUploadReviewScreen = forwardRef<
75
+ HTMLDivElement,
76
+ DigitalIdUploadReviewScreenProps
77
+ >(
78
+ (
79
+ {
80
+ strings,
81
+ stage = 'review',
82
+ filename,
83
+ progress = 45,
84
+ showHeader = stage === 'review',
85
+ showFooter = stage === 'review',
86
+ screenId = `digital-id-upload-${stage}`,
87
+ overrides,
88
+ onAction,
89
+ ...shell
90
+ },
91
+ ref,
92
+ ) => (
93
+ <PrizmaReviewScreen
94
+ ref={ref}
95
+ stage={stage}
96
+ title={strings.review.title}
97
+ subtitle={strings.review.subtitle}
98
+ successTitle={strings.review.successTitle}
99
+ analyzingLabel={strings.review.analyzingLabel}
100
+ centeredWhenNoNav
101
+ progress={progress}
102
+ primaryLabel={strings.review.ctaLabel}
103
+ secondaryLabel={strings.review.replaceLabel}
104
+ verifiedLabel={strings.verifiedLabel}
105
+ navLabel={strings.navLabel}
106
+ showHeader={showHeader}
107
+ showFooter={showFooter}
108
+ screenId={screenId}
109
+ overrides={overrides}
110
+ onAction={onAction}
111
+ {...shell}
112
+ >
113
+ <PrizmaCaptureDigitalId state={stage} filename={filename} />
114
+ </PrizmaReviewScreen>
115
+ ),
116
+ );
117
+ DigitalIdUploadReviewScreen.displayName = 'DigitalIdUploadReviewScreen';
118
+
119
+ export default DigitalIdUploadReviewScreen;
@@ -0,0 +1,88 @@
1
+ // Digital ID Upload module β€” copy contract.
2
+ //
3
+ // Every Digital ID Upload screen receives the SAME `strings:
4
+ // DigitalIdUploadStrings` object (rule: all copy via props, no hardcoded
5
+ // English β€” GUIDELINES.md Β§9).
6
+ //
7
+ // Authoritative screens: the "Web Happy Path - Light Mode" purple section of
8
+ // the Upload Digital ID Figma file (wxFsHRvllern4VnjRqM4JO, node 25351:14721)
9
+ // β€” covers `tutorial` and the `review` / `analyzing` / `success` stages of
10
+ // the confirm flow β€” plus TWO separate `Errors` sections: node 25874:11955
11
+ // (`ID type is not accepted`) and node 26083:3981 (`File Limit Error`, "File
12
+ // is too large"). Three frames of the happy-path section are NOT part of
13
+ // this contract: `1-1-1-how to verify` (a verification-method chooser shared
14
+ // with ID Capture β€” see IdCaptureDocumentSelectionScreen.tsx, which is one
15
+ // row short of this Figma's version), a native iOS file-browser frame (OS
16
+ // chrome, DEVIATIONS.md #DC-20 precedent), and `1-18-1-id-hold-on` (ID
17
+ // Capture's own server-side-wait screen β€” dropped from this module by
18
+ // product decision, not a gap to fill).
19
+
20
+ /** The three stages the confirm flow's screen shares β€” matches
21
+ * `PrizmaReviewScreen`'s own `PrizmaReviewStage` (ReviewScreen.tsx). Kept as
22
+ * a separate module-scoped type rather than importing it, same convention as
23
+ * `DocumentCaptureConfirmStage` (DocumentCaptureStrings.ts). */
24
+ export type DigitalIdUploadConfirmStage = 'review' | 'analyzing' | 'success';
25
+
26
+ export interface DigitalIdUploadStrings {
27
+ /** Accessible name for the logo nav region (i18n β€” no baked-in English). */
28
+ navLabel?: string;
29
+ /** "verified by" attribution copy for the footer tag. */
30
+ verifiedLabel: string;
31
+
32
+ /** `Tutorial Screen` (node 25351:14722). */
33
+ tutorial: {
34
+ title: string;
35
+ subtitle?: string;
36
+ /** "Upload PDF" */
37
+ ctaLabel: string;
38
+ };
39
+
40
+ /** `Review Document` / `Analyzing` / `Success` (nodes
41
+ * 25351:14725/14726/14727) β€” one screen, three stages. */
42
+ review: {
43
+ /** `review` title ("Review document"). */
44
+ title: string;
45
+ /** `review` description. Figma draws no subtitle on `analyzing` or
46
+ * `success` β€” the shared `PrizmaReviewScreen` archetype already only
47
+ * shows one on `review`, so this needs no per-stage handling here. */
48
+ subtitle?: string;
49
+ /** Loading-bar caption on `analyzing` ("Analyzing.."). */
50
+ analyzingLabel: string;
51
+ /** H2 on `success` ("Successfully processed!"). */
52
+ successTitle: string;
53
+ /** Secondary CTA on `review` ("Replace file"). */
54
+ replaceLabel: string;
55
+ /** Primary CTA on `review` / `success` ("Continue"). */
56
+ ctaLabel: string;
57
+ };
58
+
59
+ /** `Errors` section, `Error` frame (node 25874:11957) β€” the uploaded file
60
+ * itself was rejected (wrong document type). Built on the SAME
61
+ * `PrizmaReviewScreen` archetype as `review`, stage `"error"`: the card
62
+ * reuses `PrizmaCaptureDigitalId state="error"` (red 4px border), not a
63
+ * generic archetype-F verdict screen (DigitalIdUploadErrorScreen.tsx). */
64
+ error: {
65
+ /** "ID type is not accepted" */
66
+ title: string;
67
+ /** "Please try scanning a different document" */
68
+ subtitle?: string;
69
+ /** "Scan your ID" */
70
+ ctaLabel: string;
71
+ };
72
+
73
+ /** `Errors` section, `File Limit Error` frame (node 26083:3981) β€” the file
74
+ * was never uploaded at all (client-side size check), so there is no
75
+ * rejected document to show. Built on Archetype F (`PrizmaResultScreen`,
76
+ * ResultScreen.tsx) rather than the review archetype `error` uses above β€”
77
+ * Figma centres the status + title + subtitle in the full available
78
+ * height with no media stage at all, exactly F's shape, not H's
79
+ * header-above-a-card one (DigitalIdUploadFileTooLargeScreen.tsx). */
80
+ fileTooLarge: {
81
+ /** "File is too large" */
82
+ title: string;
83
+ /** "The selected file is larger than 5 MB, please upload a smaller one" */
84
+ subtitle?: string;
85
+ /** "Choose another file" */
86
+ ctaLabel: string;
87
+ };
88
+ }
@@ -0,0 +1,59 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaCaptureDigitalId } from '@incodetech/prizma-core-web/capture-digital-id';
3
+ import { PrizmaTutorialScreen, type PrizmaTutorialScreenProps } from './TutorialScreen';
4
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
5
+ import type { DigitalIdUploadStrings } from './DigitalIdUploadStrings';
6
+ import './ScreenLayout.css';
7
+
8
+ export interface DigitalIdUploadTutorialScreenProps
9
+ extends Omit<
10
+ PrizmaTutorialScreenProps,
11
+ 'title' | 'subtitle' | 'ctaLabel' | 'illustration' | 'verifiedLabel' | 'navLabel'
12
+ > {
13
+ /** Module copy β€” this screen reads the `tutorial` slice (+ shared labels). */
14
+ strings: DigitalIdUploadStrings;
15
+ screenId?: string;
16
+ overrides?: PrizmaScreenOverrides;
17
+ onAction?: PrizmaScreenActionHandler;
18
+ }
19
+
20
+ /**
21
+ * Digital ID Upload β€” tutorial, built on the `PrizmaTutorialScreen` archetype
22
+ * (GUIDELINES.md Β§6-A). Figma: `Upload Digital ID` file
23
+ * (wxFsHRvllern4VnjRqM4JO), "Web Happy Path - Light Mode" section, `Tutorial
24
+ * Screen` (node 25351:14722).
25
+ *
26
+ * The illustration slot is Core's own `PrizmaCaptureDigitalId` in its
27
+ * `tutorial` state β€” the Figma file names this exact instance "Capture /
28
+ * Digital ID" (node 26161:10686, Figma description: "Incode specific
29
+ * component for Digital ID module experience"), the same managed component
30
+ * already shipped as `core/platforms/web/src/CaptureDigitalId.tsx`. No module
31
+ * illustration is drawn here β€” the component owns its own tutorial artwork
32
+ * (`PrizmaIllustrationDigitalId`).
33
+ */
34
+ export const DigitalIdUploadTutorialScreen = forwardRef<
35
+ HTMLDivElement,
36
+ DigitalIdUploadTutorialScreenProps
37
+ >(
38
+ (
39
+ { strings, screenId = 'digital-id-upload-tutorial', overrides, onAction, ...shell },
40
+ ref,
41
+ ) => (
42
+ <PrizmaTutorialScreen
43
+ ref={ref}
44
+ title={strings.tutorial.title}
45
+ subtitle={strings.tutorial.subtitle}
46
+ ctaLabel={strings.tutorial.ctaLabel}
47
+ illustration={<PrizmaCaptureDigitalId state="tutorial" />}
48
+ verifiedLabel={strings.verifiedLabel}
49
+ navLabel={strings.navLabel}
50
+ screenId={screenId}
51
+ overrides={overrides}
52
+ onAction={onAction}
53
+ {...shell}
54
+ />
55
+ ),
56
+ );
57
+ DigitalIdUploadTutorialScreen.displayName = 'DigitalIdUploadTutorialScreen';
58
+
59
+ export default DigitalIdUploadTutorialScreen;
@@ -7,7 +7,7 @@ import './DocumentCaptureLayout.css';
7
7
  *
8
8
  * WHY IT LIVES IN THE MODULE LAYER: `prizma-core-web` ships
9
9
  * `PrizmaIllustrationSelfie`, `…IdTutorial`, `…IdIntro`, `…IdFlip`,
10
- * `…IdHint`, `…IdFeedback`, `…NfcScan`, `…NfcIssue`, `…Geolocation`,
10
+ * `…IdHint`, `…IdFeedback`, `…NfcScan`, `…Geolocation`,
11
11
  * `…DigitalId` and `…Avatar` β€” there is NO document / proof-of-address
12
12
  * illustration. GUIDELINES.md Β§10 is the standing asset rule for that gap
13
13
  * ("Illustrations…: inline SVG React components (Figma-sourced), tintable via
@@ -1,5 +1,6 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import { PrizmaDropdown } from '@incodetech/prizma-core-web/dropdown';
3
+ import { PrizmaCountryFlag } from '@incodetech/prizma-core-web/combined';
3
4
  import { PrizmaFormScreen, type PrizmaFormScreenProps } from './FormScreen';
4
5
  import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
5
6
  import type { EkybCountryState, EkybOption, EkybStrings } from './EkybStrings';
@@ -55,12 +56,12 @@ export interface EkybCountryScreenProps
55
56
  * live interaction) β€” the same mechanism Phone Input's `countryCode` and
56
57
  * CURP's `Gene.dropdown` sections use. The search bar Figma draws inside the
57
58
  * menu is Core's own `searchable`.
58
- * 3. Menu rows and the closed field read the same "πŸ‡ΊπŸ‡Έ United States": flag
59
- * and country name, no dial code. Figma 5707:54174 draws the rows with
60
- * Phone Input's "+1" prefixes, dropped by the owner (Elena, 2026-09-28)
61
- * because a country of registration has no phone prefix. The flag travels
62
- * inside the label text because Core still ships no country-flag primitive
63
- * (#PI-3).
59
+ * 3. Menu rows and the closed field read the same flag + "United States",
60
+ * no dial code. Figma 5707:54174 draws the rows with Phone Input's "+1"
61
+ * prefixes, dropped by the owner (Elena, 2026-09-28) because a country of
62
+ * registration has no phone prefix. The flag is Core's raster in the
63
+ * dropdown's leading slot, not an emoji in the label (Elena, 2026-10-23;
64
+ * #PI-3, the WatchlistBusinessFormScreen precedent).
64
65
  *
65
66
  * This page is the only eKYB form page with NO "Back" secondary and NO Stepper β€”
66
67
  * it is step 0, before the three-step wizard starts.
@@ -135,6 +136,22 @@ export const EkybCountryScreen = forwardRef<HTMLDivElement, EkybCountryScreenPro
135
136
  clearSearchLabel={copy.clearSearchLabel}
136
137
  /* The `dropdown` section IS the open-menu spec state. */
137
138
  forceOpen={state === 'dropdown'}
139
+ /* Core's canonical flag raster in the closed field and every menu
140
+ row (see note 3). A country outside the bank falls back to its
141
+ `flag` emoji. */
142
+ renderLeading={(option) => {
143
+ const match = countries.find((c) => c.value === option.value);
144
+ return match ? (
145
+ <PrizmaCountryFlag
146
+ country={{
147
+ code: match.value,
148
+ name: match.label,
149
+ dialCode: '',
150
+ flag: match.flag ?? '',
151
+ }}
152
+ />
153
+ ) : null;
154
+ }}
138
155
  />
139
156
  </PrizmaFormScreen>
140
157
  );
@@ -98,8 +98,13 @@ export interface EkybOption {
98
98
  label: string;
99
99
  /** Compact face for the CLOSED field when it differs from the menu row β€”
100
100
  * Core's own `PrizmaDropdownOption.fieldLabel`. The eKYB country list
101
- * does not need it: rows and field both read "πŸ‡ΊπŸ‡Έ United States". */
101
+ * does not need it: rows and field both read "United States" after the
102
+ * flag. */
102
103
  fieldLabel?: string;
104
+ /** Country menus only: the emoji fallback for a `value` outside Core's
105
+ * flag raster bank. The country screen draws the bank's flag by `value`,
106
+ * so this never travels inside `label`. */
107
+ flag?: string;
103
108
  }
104
109
 
105
110
  /** The values the business-identity page carries. Runtime data, never copy. */
@@ -38,7 +38,7 @@ export interface ErrorScreensScreenProps
38
38
  * Error screens β€” the session-level failures, built on the Result archetype
39
39
  * (GUIDELINES.md Β§6-F, `PrizmaResultScreen`).
40
40
  *
41
- * ONE screen for all three generic sections. They draw the identical skeleton β€”
41
+ * ONE screen for all four generic sections. They draw the identical skeleton β€”
42
42
  * a centred mark + title + supporting line over a CTA band β€” and differ only in
43
43
  * copy, in which mark leads, and in what the band carries:
44
44
  *
@@ -46,8 +46,11 @@ export interface ErrorScreensScreenProps
46
46
  * - `noConnection` β€” Wi-Fi glyph, "Refresh"
47
47
  * - `unsupportedBrowser` β€” canonical negative mark, the session URL above
48
48
  * "Copy link", with "Continue anyways" under it
49
+ * - `somethingWentWrong` β€” canonical negative mark, "Try again" when the copy
50
+ * carries a CTA, "Quit process" under it when it
51
+ * carries a quit label; a dead end when it has neither
49
52
  *
50
- * Chrome is CONSTANT. All three frames are drawn without the logo header and
53
+ * Chrome is CONSTANT. All the frames are drawn without the logo header and
51
54
  * without the verified tag; both are kept here, because the owner rule of
52
55
  * 2026-08-18 (#F-30, #F-34) makes the chrome the same on every screen so
53
56
  * nothing shifts between states, and every module's connectivity screen must
@@ -91,11 +94,19 @@ export const ErrorScreensScreen = forwardRef<HTMLDivElement, ErrorScreensScreenP
91
94
  ) => {
92
95
  const unsupported = variant === 'unsupportedBrowser';
93
96
  const noConnection = variant === 'noConnection';
97
+ const generic = variant === 'somethingWentWrong';
94
98
  const copy = unsupported
95
99
  ? strings.unsupportedBrowser
96
100
  : noConnection
97
101
  ? strings.noConnection
98
- : strings.sessionExpired;
102
+ : generic
103
+ ? strings.somethingWentWrong
104
+ : strings.sessionExpired;
105
+ const linkLabel = unsupported
106
+ ? strings.unsupportedBrowser.continueLabel
107
+ : generic
108
+ ? strings.somethingWentWrong.quitLabel
109
+ : undefined;
99
110
 
100
111
  return (
101
112
  <PrizmaResultScreen
@@ -133,7 +144,7 @@ export const ErrorScreensScreen = forwardRef<HTMLDivElement, ErrorScreensScreenP
133
144
  : undefined
134
145
  }
135
146
  ctaLabel={copy.ctaLabel}
136
- linkLabel={unsupported ? strings.unsupportedBrowser.continueLabel : undefined}
147
+ linkLabel={linkLabel}
137
148
  verifiedLabel={strings.verifiedLabel}
138
149
  navLabel={strings.navLabel}
139
150
  screenId={screenId}
@@ -6,19 +6,27 @@
6
6
  // 214:3357 Geolocation.error.noNetwork β†’ `noConnection`
7
7
  // 240:154 Error screen - Unsupported browser β†’ `unsupportedBrowser`
8
8
  //
9
- // The three failures that belong to the SESSION rather than to any module: the
10
- // link has expired, the network went away, the browser cannot run the SDK.
11
- // Every module can hit all three, which is why they are drawn once in the
12
- // generic file β€” a user who sees three different "no internet" screens in one
13
- // journey reads them as three different products.
9
+ // plus the one failure every module draws for itself and the file never did:
10
+ //
11
+ // β€” <module>.error "Something went wrong" β†’ `somethingWentWrong`
12
+ //
13
+ // The failures that belong to the SESSION rather than to any module: the link
14
+ // has expired, the network went away, the browser cannot run the SDK, the
15
+ // server said no for a reason the user cannot act on. Every module can hit all
16
+ // four, which is why they are recorded once in the generic family β€” a user who
17
+ // sees three different "no internet" screens in one journey reads them as three
18
+ // different products.
14
19
  //
15
20
  // `noConnection` is deliberately the same screen every module already ships
16
21
  // (`FaceCaptureNoConnectionScreen`, `IdCaptureNoConnectionScreen`,
17
- // `DocumentCaptureNoConnectionScreen`, `GeolocationErrorScreen`'s `noNetwork`).
18
- // The generic entry is where the shape is DOCUMENTED; the module copies stay
19
- // put until someone retires them deliberately, because deleting four exported
20
- // components to save one screen is a breaking change for every host that
21
- // imports them. Flagged for the owner.
22
+ // `DocumentCaptureNoConnectionScreen`, `GeolocationErrorScreen`'s `noNetwork`,
23
+ // Phone Input's and Video Selfie's `noConnection`). `somethingWentWrong` is the
24
+ // same screen eKYC, eKYB, Forms, Email Input, Phone Input, Certificate
25
+ // Issuance, both signatures and Video Selfie already ship. The generic entry is
26
+ // where the shape and the copy are DOCUMENTED; the module copies stay put until
27
+ // someone retires them deliberately, because deleting exported components to
28
+ // save one screen is a breaking change for every host that imports them.
29
+ // Flagged for the owner (DEVIATIONS #GEN-7, #GEN-18).
22
30
  //
23
31
  // The family has no flow of its own: each of these is entered from wherever the
24
32
  // session broke and exits to a retry or to nothing. Core Lab lists it as a
@@ -27,15 +35,17 @@
27
35
  // No hardcoded English anywhere in a screen: every visible string arrives here.
28
36
 
29
37
  /**
30
- * The three sections.
38
+ * The four sections.
31
39
  * - `sessionExpired` β€” the link is dead; the user must go back to the provider
32
40
  * - `noConnection` β€” the network went away; retry when it returns
33
41
  * - `unsupportedBrowser` β€” the SDK cannot run here; copy the link and move
42
+ * - `somethingWentWrong` β€” the generic failure; try again, or nothing, or quit
34
43
  */
35
44
  export type ErrorScreensVariant =
36
45
  | 'sessionExpired'
37
46
  | 'noConnection'
38
- | 'unsupportedBrowser';
47
+ | 'unsupportedBrowser'
48
+ | 'somethingWentWrong';
39
49
 
40
50
  export interface ErrorScreensCopy {
41
51
  title: string;
@@ -63,4 +73,19 @@ export interface ErrorScreensStrings {
63
73
  /** Snackbar copy after the link is copied β€” the frame's second state. */
64
74
  copiedLabel: string;
65
75
  };
76
+
77
+ /**
78
+ * The generic failure. Three ways the modules fill it, all the same screen:
79
+ * `ctaLabel` "Try again" (eKYC, eKYB, Forms, Email Input);
80
+ * no `ctaLabel`, a dead end (Certificate Issuance, Qualified Signature);
81
+ * `ctaLabel` plus `quitLabel`, the way out under the retry (Video Selfie).
82
+ * Phone Input's `unknown` fills it with "Continue" instead, because a retry
83
+ * may not be possible there (owner, 2026-10-09) β€” the CTA is the module's
84
+ * call; the shape and the title are what the family fixes.
85
+ * The title never carries an ellipsis β€” a failure is not in progress.
86
+ */
87
+ somethingWentWrong: ErrorScreensCopy & {
88
+ /** Tertiary link under the CTA β€” "Quit process". Omit for no way out. */
89
+ quitLabel?: string;
90
+ };
66
91
  }