@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.
- package/dist/BiometricConsentScreen.d.ts +95 -0
- package/dist/BiometricConsentScreen.js +91 -0
- package/dist/BiometricConsentStrings.d.ts +84 -0
- package/dist/BiometricConsentStrings.js +31 -0
- package/dist/CaptureScreen.d.ts +13 -0
- package/dist/CaptureScreen.js +2 -2
- package/dist/DemoScreensLayout.css +16 -0
- package/dist/DemoScreensRedirectScreen.d.ts +6 -1
- package/dist/DemoScreensRedirectScreen.js +3 -2
- package/dist/DemoScreensStrings.d.ts +5 -0
- package/dist/DigitalIdDeviceWalletsDocumentSelectionScreen.d.ts +34 -0
- package/dist/DigitalIdDeviceWalletsDocumentSelectionScreen.js +47 -0
- package/dist/DigitalIdDeviceWalletsResultScreen.d.ts +28 -0
- package/dist/DigitalIdDeviceWalletsResultScreen.js +23 -0
- package/dist/DigitalIdDeviceWalletsStrings.d.ts +55 -0
- package/dist/DigitalIdDeviceWalletsStrings.js +19 -0
- package/dist/DigitalIdProvidersDocumentSelectionScreen.d.ts +31 -0
- package/dist/DigitalIdProvidersDocumentSelectionScreen.js +37 -0
- package/dist/DigitalIdProvidersErrorScreen.d.ts +33 -0
- package/dist/DigitalIdProvidersErrorScreen.js +33 -0
- package/dist/DigitalIdProvidersLayout.css +59 -0
- package/dist/DigitalIdProvidersRedirectScreen.d.ts +24 -0
- package/dist/DigitalIdProvidersRedirectScreen.js +18 -0
- package/dist/DigitalIdProvidersStrings.d.ts +72 -0
- package/dist/DigitalIdProvidersStrings.js +15 -0
- package/dist/DigitalIdUploadErrorScreen.d.ts +31 -0
- package/dist/DigitalIdUploadErrorScreen.js +26 -0
- package/dist/DigitalIdUploadFileTooLargeScreen.d.ts +27 -0
- package/dist/DigitalIdUploadFileTooLargeScreen.js +21 -0
- package/dist/DigitalIdUploadReviewScreen.d.ts +57 -0
- package/dist/DigitalIdUploadReviewScreen.js +44 -0
- package/dist/DigitalIdUploadStrings.d.ts +64 -0
- package/dist/DigitalIdUploadStrings.js +19 -0
- package/dist/DigitalIdUploadTutorialScreen.d.ts +28 -0
- package/dist/DigitalIdUploadTutorialScreen.js +23 -0
- package/dist/DocumentCaptureIllustration.d.ts +1 -1
- package/dist/EkybCountryScreen.d.ts +6 -6
- package/dist/EkybCountryScreen.js +20 -7
- package/dist/EkybStrings.d.ts +6 -1
- package/dist/ErrorScreensScreen.d.ts +5 -2
- package/dist/ErrorScreensScreen.js +15 -4
- package/dist/ErrorScreensStrings.d.ts +17 -2
- package/dist/ErrorScreensStrings.js +18 -10
- package/dist/FaceCaptureCapturingScreen.d.ts +63 -0
- package/dist/FaceCaptureCapturingScreen.js +62 -2
- package/dist/FaceCaptureLayout.css +69 -4
- package/dist/FaceCaptureStrings.d.ts +23 -0
- package/dist/FormScreen.css +14 -0
- package/dist/FormScreen.d.ts +28 -0
- package/dist/FormScreen.js +3 -2
- package/dist/IdCaptureLayout.css +165 -2
- package/dist/IdCaptureStageScreen.d.ts +47 -0
- package/dist/IdCaptureStageScreen.js +39 -3
- package/dist/IdCaptureStrings.d.ts +19 -0
- package/dist/ListScreen.d.ts +19 -0
- package/dist/ListScreen.js +7 -2
- package/dist/LoaderScreen.d.ts +7 -5
- package/dist/LoaderScreen.js +7 -5
- package/dist/LoadersStrings.d.ts +18 -5
- package/dist/OcrReviewErrorScreen.d.ts +30 -0
- package/dist/OcrReviewErrorScreen.js +24 -0
- package/dist/OcrReviewLayout.css +24 -0
- package/dist/OcrReviewLoadingScreen.d.ts +25 -0
- package/dist/OcrReviewLoadingScreen.js +19 -0
- package/dist/OcrReviewScreen.d.ts +76 -0
- package/dist/OcrReviewScreen.js +65 -0
- package/dist/OcrReviewStrings.d.ts +47 -0
- package/dist/OcrReviewStrings.js +17 -0
- package/dist/OcrReviewSuccessScreen.d.ts +30 -0
- package/dist/OcrReviewSuccessScreen.js +24 -0
- package/dist/PermissionsAllowScreen.d.ts +8 -11
- package/dist/PermissionsAllowScreen.js +8 -11
- package/dist/PermissionsAskScreen.d.ts +41 -0
- package/dist/PermissionsAskScreen.js +43 -0
- package/dist/PermissionsBrowserStepsScreen.d.ts +9 -2
- package/dist/PermissionsBrowserStepsScreen.js +12 -3
- package/dist/PermissionsLayout.css +47 -0
- package/dist/PermissionsStrings.d.ts +20 -9
- package/dist/PermissionsStrings.js +10 -4
- package/dist/PhoneInputOtpScreen.d.ts +8 -0
- package/dist/PhoneInputOtpScreen.js +26 -19
- package/dist/PhoneInputStrings.d.ts +11 -3
- package/dist/PhoneInputVerifyScreen.js +21 -5
- package/dist/QualifiedSignatureDocumentScreen.d.ts +8 -5
- package/dist/QualifiedSignatureDocumentScreen.js +9 -6
- package/dist/QualifiedSignatureResultScreen.d.ts +16 -13
- package/dist/QualifiedSignatureResultScreen.js +17 -18
- package/dist/QualifiedSignatureStrings.d.ts +11 -4
- package/dist/ResultScreen.d.ts +8 -0
- package/dist/ResultScreen.js +14 -3
- package/dist/ReusabilityCredentialSelectionScreen.d.ts +95 -0
- package/dist/ReusabilityCredentialSelectionScreen.js +94 -0
- package/dist/ReusabilityLayout.css +241 -0
- package/dist/ReusabilityPrivacyPolicyScreen.d.ts +55 -0
- package/dist/ReusabilityPrivacyPolicyScreen.js +44 -0
- package/dist/ReusabilityStrings.d.ts +85 -0
- package/dist/ReusabilityStrings.js +37 -0
- package/dist/ReviewScreen.d.ts +38 -12
- package/dist/ReviewScreen.js +41 -8
- package/dist/ScreenLayout.css +382 -6
- package/dist/VideoSelfieErrorScreen.js +1 -1
- package/dist/VideoSelfieIdCaptureScreen.js +1 -1
- package/dist/VideoSelfieLayout.css +304 -2
- package/dist/VideoSelfieSelfieCaptureScreen.js +1 -1
- package/dist/VideoSelfieSpeakScreen.js +1 -1
- package/dist/VideoSelfieStrings.d.ts +4 -1
- package/dist/VideoSelfieTurnHeadScreen.js +14 -11
- package/dist/VideoSelfieTutorialScreen.d.ts +9 -0
- package/dist/VideoSelfieTutorialScreen.js +10 -1
- package/dist/VideoSelfieWaveScreen.js +1 -1
- package/dist/ViewfinderScreen.css +36 -0
- package/dist/flows.d.ts +8 -0
- package/dist/flows.js +17 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +17 -0
- package/dist/styles.css +4 -0
- package/package.json +94 -3
- package/samples/video-selfie-camera-wide.jpg +0 -0
- package/samples/video-selfie-room-wide.jpg +0 -0
- package/src/BiometricConsentScreen.tsx +192 -0
- package/src/BiometricConsentStrings.ts +119 -0
- package/src/CaptureScreen.tsx +17 -0
- package/src/DemoScreensLayout.css +16 -0
- package/src/DemoScreensRedirectScreen.tsx +14 -6
- package/src/DemoScreensStrings.ts +5 -0
- package/src/DigitalIdDeviceWalletsDocumentSelectionScreen.tsx +108 -0
- package/src/DigitalIdDeviceWalletsResultScreen.tsx +76 -0
- package/src/DigitalIdDeviceWalletsStrings.ts +80 -0
- package/src/DigitalIdProvidersDocumentSelectionScreen.tsx +112 -0
- package/src/DigitalIdProvidersErrorScreen.tsx +104 -0
- package/src/DigitalIdProvidersLayout.css +59 -0
- package/src/DigitalIdProvidersRedirectScreen.tsx +65 -0
- package/src/DigitalIdProvidersStrings.ts +98 -0
- package/src/DigitalIdUploadErrorScreen.tsx +83 -0
- package/src/DigitalIdUploadFileTooLargeScreen.tsx +67 -0
- package/src/DigitalIdUploadReviewScreen.tsx +119 -0
- package/src/DigitalIdUploadStrings.ts +88 -0
- package/src/DigitalIdUploadTutorialScreen.tsx +59 -0
- package/src/DocumentCaptureIllustration.tsx +1 -1
- package/src/EkybCountryScreen.tsx +23 -6
- package/src/EkybStrings.ts +6 -1
- package/src/ErrorScreensScreen.tsx +15 -4
- package/src/ErrorScreensStrings.ts +37 -12
- package/src/FaceCaptureCapturingScreen.tsx +102 -13
- package/src/FaceCaptureLayout.css +69 -4
- package/src/FaceCaptureStrings.ts +24 -0
- package/src/FormScreen.css +14 -0
- package/src/FormScreen.tsx +34 -0
- package/src/IdCaptureLayout.css +165 -2
- package/src/IdCaptureStageScreen.tsx +75 -0
- package/src/IdCaptureStrings.ts +19 -0
- package/src/ListScreen.tsx +48 -9
- package/src/LoaderScreen.tsx +7 -5
- package/src/LoadersStrings.ts +18 -5
- package/src/OcrReviewErrorScreen.tsx +53 -0
- package/src/OcrReviewLayout.css +24 -0
- package/src/OcrReviewLoadingScreen.tsx +48 -0
- package/src/OcrReviewScreen.tsx +190 -0
- package/src/OcrReviewStrings.ts +69 -0
- package/src/OcrReviewSuccessScreen.tsx +52 -0
- package/src/PermissionsAllowScreen.tsx +9 -10
- package/src/PermissionsAskScreen.tsx +105 -0
- package/src/PermissionsBrowserStepsScreen.tsx +11 -3
- package/src/PermissionsLayout.css +47 -0
- package/src/PermissionsStrings.ts +42 -12
- package/src/PhoneInputOtpScreen.tsx +23 -3
- package/src/PhoneInputStrings.ts +11 -3
- package/src/PhoneInputVerifyScreen.tsx +24 -4
- package/src/QualifiedSignatureDocumentScreen.tsx +9 -7
- package/src/QualifiedSignatureResultScreen.tsx +28 -26
- package/src/QualifiedSignatureStrings.ts +11 -4
- package/src/ResultScreen.tsx +33 -2
- package/src/ReusabilityCredentialSelectionScreen.tsx +246 -0
- package/src/ReusabilityLayout.css +241 -0
- package/src/ReusabilityPrivacyPolicyScreen.tsx +109 -0
- package/src/ReusabilityStrings.ts +127 -0
- package/src/ReviewScreen.tsx +96 -27
- package/src/ScreenLayout.css +382 -6
- package/src/VideoSelfieErrorScreen.tsx +1 -1
- package/src/VideoSelfieIdCaptureScreen.tsx +9 -1
- package/src/VideoSelfieLayout.css +304 -2
- package/src/VideoSelfieSelfieCaptureScreen.tsx +9 -1
- package/src/VideoSelfieSpeakScreen.tsx +9 -1
- package/src/VideoSelfieStrings.ts +4 -2
- package/src/VideoSelfieTurnHeadScreen.tsx +25 -14
- package/src/VideoSelfieTutorialScreen.tsx +11 -0
- package/src/VideoSelfieWaveScreen.tsx +9 -1
- package/src/ViewfinderScreen.css +36 -0
- package/src/flows.ts +25 -0
- package/src/index.ts +116 -3
- package/src/styles.css +4 -0
package/dist/FormScreen.d.ts
CHANGED
|
@@ -50,6 +50,13 @@ export interface PrizmaFormScreenProps extends Omit<PrizmaScreenShellProps, 'dar
|
|
|
50
50
|
* body text.
|
|
51
51
|
*/
|
|
52
52
|
linkLabel?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Renders `linkLabel` in Core's disabled treatment, for a link that exists
|
|
55
|
+
* but cannot be pressed yet — Phone Input's "Resend code in 30s" while the
|
|
56
|
+
* resend timer runs (Figma `phoneNumber.OTP.typing`, Tertiary / Link ·
|
|
57
|
+
* Disabled).
|
|
58
|
+
*/
|
|
59
|
+
linkDisabled?: boolean;
|
|
53
60
|
/**
|
|
54
61
|
* A composed line below the primary: body copy with inline links, e.g. Phone
|
|
55
62
|
* Input's "Didn't receive the code? **Resend code** or **Change phone
|
|
@@ -86,6 +93,27 @@ export interface PrizmaFormScreenProps extends Omit<PrizmaScreenShellProps, 'dar
|
|
|
86
93
|
* eKYB, Data Sharing Consent); it is the archetype's now. DEVIATIONS #DSC-2.
|
|
87
94
|
*/
|
|
88
95
|
scrollFields?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Where the field stack sits in the column when it is SHORTER than the
|
|
98
|
+
* space it has. `start` (the default) hangs it off the title block, which is
|
|
99
|
+
* every form so far. `end` pins it to the CTA band instead, leaving the space
|
|
100
|
+
* between the title and the stack empty — Biometric Consent's section draws
|
|
101
|
+
* exactly that: a `justify-between` middle with the Title at the top and the
|
|
102
|
+
* one consent card flush against Continue, Spacing/16 above it
|
|
103
|
+
* (`biometricConsent.empty`, 2001:16361). Selected here so the module
|
|
104
|
+
* declares no layout of its own; the rule lives once in `FormScreen.css`.
|
|
105
|
+
* DEVIATIONS #BC-1.
|
|
106
|
+
*/
|
|
107
|
+
fieldsAlign?: 'start' | 'end';
|
|
108
|
+
/**
|
|
109
|
+
* A shell-level layer painted OVER the whole screen — the same slot archetype
|
|
110
|
+
* A carries for Document Capture's method sheet (#F-32, #DC-30): a scrim plus
|
|
111
|
+
* Core's `PrizmaBottomSheetContent` or `PrizmaModalContent`, presented on top
|
|
112
|
+
* of the dimmed form. It cannot ride in the content column: it is absolutely
|
|
113
|
+
* positioned against the shell. Biometric Consent's quit confirmation is the
|
|
114
|
+
* first Form consumer (DEVIATIONS #BC-8).
|
|
115
|
+
*/
|
|
116
|
+
overlay?: ReactNode;
|
|
89
117
|
/**
|
|
90
118
|
* Let the field stack change SHAPE on a wide screen: `PrizmaFormRow` pairs
|
|
91
119
|
* become two lanes and Continue + Back share a row, once the shell's own
|
package/dist/FormScreen.js
CHANGED
|
@@ -23,11 +23,12 @@ export function PrizmaFormRow({ children, className }) {
|
|
|
23
23
|
* (typing / filled / loading) are separate screens sharing this identical
|
|
24
24
|
* layout, changing only field content.
|
|
25
25
|
*/
|
|
26
|
-
export const PrizmaFormScreen = forwardRef(({ progress, title, subtitle, ctaLabel, ctaDisabled, ctaLoading = false, ctaLoadingLabel, linkLabel, linkContent, verifiedLabel, children, fieldsOffset, fieldsGap, scrollFields = false, responsive = false, navLabel, screenId, showHeader = true, showFooter = true, overrides, onAction, ...shell }, ref) => (_jsxs(PrizmaScreenShell, { ref: ref, ...shell, className: [shell.className, responsive ? 'prizma-form-screen--responsive' : null]
|
|
26
|
+
export const PrizmaFormScreen = forwardRef(({ progress, title, subtitle, ctaLabel, ctaDisabled, ctaLoading = false, ctaLoadingLabel, linkLabel, linkDisabled, linkContent, verifiedLabel, children, fieldsOffset, fieldsGap, scrollFields = false, fieldsAlign = 'start', overlay, responsive = false, navLabel, screenId, showHeader = true, showFooter = true, overrides, onAction, ...shell }, ref) => (_jsxs(PrizmaScreenShell, { ref: ref, ...shell, className: [shell.className, responsive ? 'prizma-form-screen--responsive' : null]
|
|
27
27
|
.filter(Boolean)
|
|
28
28
|
.join(' ') || undefined, children: [_jsx(PrizmaScreenNav, { reserved: !showHeader, logo: overrides?.logo, navLabel: navLabel }), _jsxs("div", { className: "prizma-screen-layout__content", children: [progress ? (_jsx("div", { className: "prizma-screen-layout__progress", children: progress })) : null, _jsx(PrizmaTitle, { variant: overrides?.align === 'left' ? 'left' : 'centered', title: title, showSubtitle: Boolean(subtitle), subtitle: subtitle }), _jsx("div", { className: [
|
|
29
29
|
'prizma-form-screen__fields',
|
|
30
30
|
scrollFields ? 'prizma-form-screen__fields--scroll' : null,
|
|
31
|
+
fieldsAlign === 'end' ? 'prizma-form-screen__fields--end' : null,
|
|
31
32
|
]
|
|
32
33
|
.filter(Boolean)
|
|
33
34
|
.join(' '),
|
|
@@ -42,6 +43,6 @@ export const PrizmaFormScreen = forwardRef(({ progress, title, subtitle, ctaLabe
|
|
|
42
43
|
? { '--pfs-fields-gap': `var(--prizma-spacing-${fieldsGap})` }
|
|
43
44
|
: null),
|
|
44
45
|
}
|
|
45
|
-
: undefined, children: children }), ctaLabel || linkLabel || linkContent ? (_jsxs("div", { className: "prizma-screen-layout__cta prizma-form-screen__cta", children: [ctaLabel ? (_jsx(PrizmaButton, { variant: "primary", size: "L", disabled: ctaDisabled, loading: ctaLoading, loadingLabel: ctaLoadingLabel, onClick: () => onAction?.({ type: 'cta', screenId }), children: ctaLabel })) : null, linkLabel ? (_jsx(PrizmaButton, { variant: "tertiary-link", size: "L", onClick: () => onAction?.({ type: 'secondary', screenId }), children: linkLabel })) : null, linkContent] })) : null, showFooter ? (_jsx("div", { className: "prizma-screen-layout__footer prizma-screen-layout__footer--pinned", children: _jsx(PrizmaTag, { label: verifiedLabel }) })) : null] })] })));
|
|
46
|
+
: undefined, children: children }), ctaLabel || linkLabel || linkContent ? (_jsxs("div", { className: "prizma-screen-layout__cta prizma-form-screen__cta", children: [ctaLabel ? (_jsx(PrizmaButton, { variant: "primary", size: "L", disabled: ctaDisabled, loading: ctaLoading, loadingLabel: ctaLoadingLabel, onClick: () => onAction?.({ type: 'cta', screenId }), children: ctaLabel })) : null, linkLabel ? (_jsx(PrizmaButton, { variant: "tertiary-link", size: "L", disabled: linkDisabled, onClick: () => onAction?.({ type: 'secondary', screenId }), children: linkLabel })) : null, linkContent] })) : null, showFooter ? (_jsx("div", { className: "prizma-screen-layout__footer prizma-screen-layout__footer--pinned", children: _jsx(PrizmaTag, { label: verifiedLabel }) })) : null] }), overlay] })));
|
|
46
47
|
PrizmaFormScreen.displayName = 'PrizmaFormScreen';
|
|
47
48
|
export default PrizmaFormScreen;
|
package/dist/IdCaptureLayout.css
CHANGED
|
@@ -99,12 +99,89 @@
|
|
|
99
99
|
flex-basis: calc((100cqw - 2 * var(--prizma-spacing-24)) * 420 / 306);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/* ── A notice on the stage: the horizontal frame may give up height too ──────
|
|
103
|
+
* The "Need more time?" offer (`.id-capture-stage__notice`, IDC-32) adds ~90px
|
|
104
|
+
* of content to the bottom band. On the 390 × 844 reference the band has the
|
|
105
|
+
* room and nothing moves. On a short panel it does not: measured 2026-10-15,
|
|
106
|
+
* the horizontal ID frame is aspect-locked and does not shrink, so the column
|
|
107
|
+
* overflowed and the notice ran 10px into the help strip at 320 × 693 and 36px
|
|
108
|
+
* at the closed iPhone Duo (466 × 678). The same recipe as the vertical rule
|
|
109
|
+
* above, applied to the horizontal frames ONLY while a notice is on the stage:
|
|
110
|
+
* the frame starts at its full-width height and gives up height when the
|
|
111
|
+
* column is short, the aspect ratio narrows it to match, the title band keeps
|
|
112
|
+
* its content height. Face Capture makes the identical trade at 320 (its
|
|
113
|
+
* selfie frame gives up Spacing/40 for the notice, ScreenLayout.css) and the
|
|
114
|
+
* owner's rule is explicit that the frame may get smaller (2026-08-18). A
|
|
115
|
+
* stage without a notice is untouched. */
|
|
116
|
+
.prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) {
|
|
117
|
+
min-height: 0;
|
|
118
|
+
}
|
|
119
|
+
.prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) > .id-capture-band--top {
|
|
120
|
+
flex-shrink: 0;
|
|
121
|
+
min-height: min-content;
|
|
122
|
+
}
|
|
123
|
+
.prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) > .prizma-id-capture--horizontal:not(.prizma-id-capture--poa) {
|
|
124
|
+
flex: 0 1 auto;
|
|
125
|
+
min-height: 0;
|
|
126
|
+
}
|
|
127
|
+
.prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) > .prizma-id-capture--horizontal:not(.prizma-id-capture--poa) .prizma-id-capture__frame {
|
|
128
|
+
flex: 0 1 auto;
|
|
129
|
+
min-height: 0;
|
|
130
|
+
width: auto;
|
|
131
|
+
max-width: 100%;
|
|
132
|
+
flex-basis: calc((100cqw - 2 * var(--prizma-spacing-24)) * 220 / 350);
|
|
133
|
+
}
|
|
134
|
+
.prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) > .prizma-id-capture--passport.prizma-id-capture--horizontal .prizma-id-capture__frame {
|
|
135
|
+
flex-basis: calc((100cqw - 2 * var(--prizma-spacing-24)) * 254 / 350);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* ── Short panels: the tutorial art is sized by its halo, not its canvas ─────
|
|
139
|
+
* `PrizmaIllustrationIdTutorial` is a 342 × 392 canvas with the halo centred
|
|
140
|
+
* at r130 (y 66–326) and the hand-and-document artwork inside it (y 100–313;
|
|
141
|
+
* the passport's hand fades out above). The 66 above and below the halo are
|
|
142
|
+
* air at rest; the bottom band is where the hand travels in from during the
|
|
143
|
+
* loop. The selfie illustration is a 296 canvas with the same r130 halo and 18
|
|
144
|
+
* of air: on the 844 reference both halos are 260 and the two tutorials match.
|
|
145
|
+
*
|
|
146
|
+
* On a short panel the tutorial middle is height-limited (ScreenLayout.css,
|
|
147
|
+
* #F-35) and the two canvases scale by height, so the ID halo comes out 18 %
|
|
148
|
+
* smaller than the selfie's (170 vs 209 on the closed iPhone Duo, measured
|
|
149
|
+
* 2026-10-14; Camila: "ID tutorials have illustration a bit too small, no?
|
|
150
|
+
* Compared to the size on the selfie tutorial one"). Fixed by cropping the
|
|
151
|
+
* canvas to the halo band plus Spacing/16 on each side — y 50 to 342, 292
|
|
152
|
+
* units, the same 89 % the selfie's halo takes of its own box — so the halo
|
|
153
|
+
* fills the slot the way the selfie's does. The wrapper takes the slot and
|
|
154
|
+
* clips; the svg is scaled so 292 of its 392 units fill the wrapper and
|
|
155
|
+
* centres, so the crop is symmetric around the halo and the halo's centre
|
|
156
|
+
* does not move. During the loop the entering hand is clipped 50 units
|
|
157
|
+
* earlier than the canvas clips it, which is invisible against the fade.
|
|
158
|
+
* Outside the query nothing exists: the reference renders the full canvas.
|
|
159
|
+
* DEVIATIONS #IDC-31. */
|
|
160
|
+
@container pcs-screen (max-height: 720px) {
|
|
161
|
+
.prizma-screen-layout__flex > .prizma-illustration-tutorial {
|
|
162
|
+
flex: 1 1 0;
|
|
163
|
+
min-height: 0;
|
|
164
|
+
align-self: stretch;
|
|
165
|
+
display: flex;
|
|
166
|
+
align-items: center;
|
|
167
|
+
justify-content: center;
|
|
168
|
+
overflow: hidden;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.prizma-screen-layout__flex > .prizma-illustration-tutorial > svg {
|
|
172
|
+
flex: none;
|
|
173
|
+
height: calc(100% * 392 / 292);
|
|
174
|
+
width: auto;
|
|
175
|
+
max-width: none;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
102
179
|
/* ── Camera stage (dark) ───────────────────────────────────────────────────── */
|
|
103
180
|
|
|
104
181
|
/* The stage's nav row carries only the close X (no logo — the camera owns the
|
|
105
182
|
* screen). The foundation `.prizma-screen-nav` supplies the status-bar reserve,
|
|
106
183
|
* the 44px flow slot and the un-fixing of Core's PrizmaNavigation; the ink is
|
|
107
|
-
* the only thing the camera stage changes: Core's nav icon is the
|
|
184
|
+
* the only thing the camera stage changes: Core's nav icon is the themed
|
|
108
185
|
* `Icon/Neutral/500`, which disappears on the always-dark camera surface, so it
|
|
109
186
|
* takes the camera's own Static ink — the same token PrizmaCaptureManual uses
|
|
110
187
|
* for the shutter and the "?" help control. DEVIATIONS.md #IDC-21. */
|
|
@@ -118,6 +195,44 @@
|
|
|
118
195
|
width: 100%;
|
|
119
196
|
}
|
|
120
197
|
|
|
198
|
+
/* ── The "Need more time?" notice ─────────────────────────────────────────────
|
|
199
|
+
* The Snackbar the stage raises 20 s before auto-capture falls back to the
|
|
200
|
+
* shutter (IdCaptureStageScreen `extendTime`, 2026-10-15). It takes the BOTTOM
|
|
201
|
+
* band — the air between the encrypted row and the strip's reserved space —
|
|
202
|
+
* because, unlike Face Capture, this stage's strip is never empty: the "?" help
|
|
203
|
+
* control rides it on every stage (IDC-29), so the shared rail the selfie notice
|
|
204
|
+
* uses (`.prizma-screen-layout__capture-notice`) would land on top of it.
|
|
205
|
+
*
|
|
206
|
+
* The band is `justify-content: flex-end`, so the notice sits just above the
|
|
207
|
+
* strip's Spacing/12 of breathing and the frame above does not move when the
|
|
208
|
+
* offer arrives. The band is also `flex: 1; min-height: 0`, which on a short
|
|
209
|
+
* panel would let it shrink to nothing and spill the notice upward over the
|
|
210
|
+
* encrypted row; with a notice in it the band keeps its content height and the
|
|
211
|
+
* shortfall goes where this stylesheet already sends it — the vertical frame
|
|
212
|
+
* (the short-panel rule above), which the owner has said may get smaller
|
|
213
|
+
* (2026-08-18). DEVIATIONS #IDC-32. */
|
|
214
|
+
.id-capture-band:has(> .id-capture-stage__notice) {
|
|
215
|
+
flex-shrink: 0;
|
|
216
|
+
min-height: min-content;
|
|
217
|
+
padding-top: var(--prizma-spacing-16);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.id-capture-stage__notice {
|
|
221
|
+
display: flex;
|
|
222
|
+
/* The HUD column centres its copy; the Snackbar's own text is left-set. */
|
|
223
|
+
text-align: left;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* On a 320 phone the notice drops its status glyph — the same call Face
|
|
227
|
+
* Capture made (Camila, 2026-10-05, ScreenLayout.css): 44 of the 272px column
|
|
228
|
+
* on a decorative mark pushed the body to four lines. The icon is
|
|
229
|
+
* `aria-hidden`; the copy carries the meaning without it. */
|
|
230
|
+
@container pcs-screen (max-width: 340px) {
|
|
231
|
+
.id-capture-stage__notice .prizma-snackbar__icon {
|
|
232
|
+
display: none;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
121
236
|
/* The feedback pill replaces the title block on the error stages (Figma
|
|
122
237
|
* `1-5-5 … 1-5-9-id-errors`): same band, same Spacing/40 above the frame. */
|
|
123
238
|
.id-capture-stage__feedback {
|
|
@@ -125,6 +240,54 @@
|
|
|
125
240
|
justify-content: center;
|
|
126
241
|
}
|
|
127
242
|
|
|
243
|
+
/* ── Short or narrow panels: the live cue takes Template B ───────────────────
|
|
244
|
+
* `PrizmaCaptureFeedback` ships two templates on its `showAnimation` axis:
|
|
245
|
+
* A, the 120-ish pill with the illustration and a Headline/H3 title, and B, a
|
|
246
|
+
* 72 pill with no illustration and Headline/H5. The error stages draw A on the
|
|
247
|
+
* 390 × 844 reference. On a closed iPhone Duo (678) A still fits — measured
|
|
248
|
+
* 2026-10-14, the frame lands at 198–473 with the pill above it — but it is
|
|
249
|
+
* the tallest element on a stage that has just lost 166px, and on a 640 phone
|
|
250
|
+
* or a 320 column it does not fit at all. Video Selfie already made this call
|
|
251
|
+
* for its own cues (DEVIATIONS #VS-30, Camila 2026-10-07): under 340 wide or
|
|
252
|
+
* 720 tall the pill is B. The same line here, so the two camera modules agree
|
|
253
|
+
* on when a cue goes compact. Nothing is re-skinned: fill, radius, stroke and
|
|
254
|
+
* shadow are Core's and identical between A and B (capture-feedback.md §4.4);
|
|
255
|
+
* what changes is exactly Template B's four switches, taken from
|
|
256
|
+
* `CaptureFeedback.css`'s own `--compact` modifier.
|
|
257
|
+
*
|
|
258
|
+
* A container query, not the prop: the screen cannot know the panel's height,
|
|
259
|
+
* the shell's `pcs-screen` container can. ONE `or` condition, not two
|
|
260
|
+
* comma-separated queries (lightningcss rejects the latter; see
|
|
261
|
+
* VideoSelfieLayout.css). The 390 reference is unchanged. DEVIATIONS #IDC-30. */
|
|
262
|
+
@container pcs-screen ((max-width: 340px) or (max-height: 720px)) {
|
|
263
|
+
.id-capture-stage__feedback .prizma-capture-feedback__illustration {
|
|
264
|
+
display: none;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Template B: body padding-bottom 12 → 16, itemSpacing 8 → 4. */
|
|
268
|
+
.id-capture-stage__feedback .prizma-capture-feedback__body {
|
|
269
|
+
padding: var(--prizma-spacing-16) 0;
|
|
270
|
+
gap: var(--prizma-spacing-4);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Title Headline/H3 → Headline/H5. */
|
|
274
|
+
.id-capture-stage__feedback .prizma-capture-feedback__title {
|
|
275
|
+
font-weight: var(--prizma-headline-h5-font-weight);
|
|
276
|
+
font-size: var(--prizma-headline-h5-font-size);
|
|
277
|
+
line-height: var(--prizma-headline-h5-line-height);
|
|
278
|
+
letter-spacing: var(--prizma-headline-h5-letter-spacing);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/* Subtitle Headline/H5 → Body/M Regular. */
|
|
282
|
+
.id-capture-stage__feedback .prizma-capture-feedback__subtitle {
|
|
283
|
+
font-family: var(--prizma-body-family);
|
|
284
|
+
font-weight: var(--prizma-body-m-regular-font-weight);
|
|
285
|
+
font-size: var(--prizma-body-m-regular-font-size);
|
|
286
|
+
line-height: var(--prizma-body-m-regular-line-height);
|
|
287
|
+
letter-spacing: var(--prizma-body-m-regular-letter-spacing);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
128
291
|
/* ── Removed: promoted into the foundation ───────────────────────────────────
|
|
129
292
|
* `.id-capture-glyph*` (the non-status glyph slot) is now
|
|
130
293
|
* `ScreenLayout.css`'s `__glyph` — DEVIATIONS #DC-29, closed.
|
|
@@ -142,7 +305,7 @@
|
|
|
142
305
|
*
|
|
143
306
|
* The plate needs no override — Core's own `mode="overlay"` already makes the
|
|
144
307
|
* window transparent, which is what the light screens want. The ink does: the
|
|
145
|
-
* row is re-inked with the
|
|
308
|
+
* row is re-inked with the themed body token so it also survives dark mode,
|
|
146
309
|
* scoped to the light screens only (the camera stage keeps Core's Static white).
|
|
147
310
|
* Core gap — PrizmaIdCapture has no surface-aware encrypted row. DEVIATIONS.md #IDC-28.
|
|
148
311
|
*/
|
|
@@ -32,6 +32,28 @@ export interface IdCaptureStageScreenProps extends Omit<PrizmaScreenShellProps,
|
|
|
32
32
|
still?: ReactNode;
|
|
33
33
|
/** Digit shown by the countdown Timer (`*-countdown` sections 1..3). */
|
|
34
34
|
countdownValue?: 1 | 2 | 3;
|
|
35
|
+
/**
|
|
36
|
+
* Raise the "Need more time?" offer over the feed — the accessibility
|
|
37
|
+
* notification shown 20 s before auto-capture falls back to the shutter.
|
|
38
|
+
*
|
|
39
|
+
* A MODIFIER of whatever stage state is already showing, not a twelfth
|
|
40
|
+
* state: the 30 s fallback timer runs underneath the hint overlay, so the
|
|
41
|
+
* person can be shown the hand-and-document ghost and offered more time in
|
|
42
|
+
* the same frame. Needs `strings.stage.extendTime`; without it the flag is a
|
|
43
|
+
* no-op, which is what a host that has not localized the copy should get
|
|
44
|
+
* rather than English. Same contract as `FaceCaptureCapturingScreen`.
|
|
45
|
+
*/
|
|
46
|
+
extendTime?: boolean;
|
|
47
|
+
/** Tapping "Extend auto-capture". The host resets its own fallback timer. */
|
|
48
|
+
onExtendTime?: () => void;
|
|
49
|
+
/**
|
|
50
|
+
* A notice band of the host's own, in the slot `extendTime` uses. Wins over
|
|
51
|
+
* `extendTime` when both are given. Exists for a host that needs the
|
|
52
|
+
* Snackbar to do something the static one cannot — Core Lab's prototype
|
|
53
|
+
* swaps in a copy whose count actually runs down — without reaching into
|
|
54
|
+
* the screen. The static `extendTime` notice stays the default.
|
|
55
|
+
*/
|
|
56
|
+
notice?: ReactNode;
|
|
35
57
|
screenId?: string;
|
|
36
58
|
overrides?: PrizmaScreenOverrides;
|
|
37
59
|
onAction?: PrizmaScreenActionHandler;
|
|
@@ -64,6 +86,31 @@ export interface IdCaptureStageScreenProps extends Omit<PrizmaScreenShellProps,
|
|
|
64
86
|
* to the column's bottom padding) — no offsets are invented here, and
|
|
65
87
|
* PrizmaIdCapture's own frame→encrypted-row adjacency is left untouched
|
|
66
88
|
* (DEVIATIONS.md #12's lesson: never stack an offset a Core component carries).
|
|
89
|
+
*
|
|
90
|
+
* ── The "Need more time?" offer (`extendTime`) ──────────────────────────────
|
|
91
|
+
*
|
|
92
|
+
* Auto-capture gives up after a configured timeout (30 s in the module's own
|
|
93
|
+
* flow frames) and drops the person onto the shutter. Someone who is
|
|
94
|
+
* struggling — a tremor, low vision, a dark room, a card that will not sit
|
|
95
|
+
* flat — gets moved off the EASIER path precisely because they were slow,
|
|
96
|
+
* which is backwards. So 20 s before the switch, the stage offers to stay on
|
|
97
|
+
* auto. A client turns it on per flow from the dashboard; with it off, nothing
|
|
98
|
+
* about today's capture changes. It is the conformance route for WCAG 2.2.1
|
|
99
|
+
* Timing Adjustable via the *Extend* clause (warn before the limit, ≥20 s to
|
|
100
|
+
* act, ≥10 extensions) — the reasoning, the `role="alert"` decision and the
|
|
101
|
+
* `neutral` state are all Face Capture's (2026-10-05) and are not re-argued
|
|
102
|
+
* here: `FaceCaptureCapturingScreen`'s header is the record. One feature, two
|
|
103
|
+
* modules, one Snackbar.
|
|
104
|
+
*
|
|
105
|
+
* WHERE IT SITS is the one thing this module decides differently. Face
|
|
106
|
+
* Capture anchors the notice on the shutter-strip rail because, there, notice
|
|
107
|
+
* and shutter are alternatives — a capturing screen either raises the offer or
|
|
108
|
+
* shows the button. ID Capture's strip is never free: the "?" help control
|
|
109
|
+
* rides it on every stage, auto or manual (IDC-29). So the notice takes the
|
|
110
|
+
* BOTTOM BAND instead — the flexible air between the encrypted row and the
|
|
111
|
+
* strip's reserved space — which is the one slot on this stage nothing else
|
|
112
|
+
* owns. It bottom-anchors there like the band's other content would, so the
|
|
113
|
+
* frame above does not move when the offer arrives. DEVIATIONS.md #IDC-32.
|
|
67
114
|
*/
|
|
68
115
|
export declare const IdCaptureStageScreen: React.ForwardRefExoticComponent<IdCaptureStageScreenProps & React.RefAttributes<HTMLDivElement>>;
|
|
69
116
|
export default IdCaptureStageScreen;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { PrizmaNavigation } from '@incodetech/prizma-core-web/navigation';
|
|
5
5
|
import { PrizmaIdCapture, } from '@incodetech/prizma-core-web/id-capture';
|
|
6
6
|
import { PrizmaCaptureManual } from '@incodetech/prizma-core-web/capture-manual';
|
|
7
7
|
import { PrizmaCaptureFeedback } from '@incodetech/prizma-core-web/capture-feedback';
|
|
8
|
+
import { PrizmaSnackbar } from '@incodetech/prizma-core-web/snackbar';
|
|
8
9
|
import { PrizmaTag } from '@incodetech/prizma-core-web/tag';
|
|
9
10
|
import { PrizmaScreenShell } from './ScreenShell';
|
|
10
11
|
import './ScreenLayout.css';
|
|
@@ -68,8 +69,33 @@ const STAGE_FEEDBACK = {
|
|
|
68
69
|
* to the column's bottom padding) — no offsets are invented here, and
|
|
69
70
|
* PrizmaIdCapture's own frame→encrypted-row adjacency is left untouched
|
|
70
71
|
* (DEVIATIONS.md #12's lesson: never stack an offset a Core component carries).
|
|
72
|
+
*
|
|
73
|
+
* ── The "Need more time?" offer (`extendTime`) ──────────────────────────────
|
|
74
|
+
*
|
|
75
|
+
* Auto-capture gives up after a configured timeout (30 s in the module's own
|
|
76
|
+
* flow frames) and drops the person onto the shutter. Someone who is
|
|
77
|
+
* struggling — a tremor, low vision, a dark room, a card that will not sit
|
|
78
|
+
* flat — gets moved off the EASIER path precisely because they were slow,
|
|
79
|
+
* which is backwards. So 20 s before the switch, the stage offers to stay on
|
|
80
|
+
* auto. A client turns it on per flow from the dashboard; with it off, nothing
|
|
81
|
+
* about today's capture changes. It is the conformance route for WCAG 2.2.1
|
|
82
|
+
* Timing Adjustable via the *Extend* clause (warn before the limit, ≥20 s to
|
|
83
|
+
* act, ≥10 extensions) — the reasoning, the `role="alert"` decision and the
|
|
84
|
+
* `neutral` state are all Face Capture's (2026-10-05) and are not re-argued
|
|
85
|
+
* here: `FaceCaptureCapturingScreen`'s header is the record. One feature, two
|
|
86
|
+
* modules, one Snackbar.
|
|
87
|
+
*
|
|
88
|
+
* WHERE IT SITS is the one thing this module decides differently. Face
|
|
89
|
+
* Capture anchors the notice on the shutter-strip rail because, there, notice
|
|
90
|
+
* and shutter are alternatives — a capturing screen either raises the offer or
|
|
91
|
+
* shows the button. ID Capture's strip is never free: the "?" help control
|
|
92
|
+
* rides it on every stage, auto or manual (IDC-29). So the notice takes the
|
|
93
|
+
* BOTTOM BAND instead — the flexible air between the encrypted row and the
|
|
94
|
+
* strip's reserved space — which is the one slot on this stage nothing else
|
|
95
|
+
* owns. It bottom-anchors there like the band's other content would, so the
|
|
96
|
+
* frame above does not move when the offer arrives. DEVIATIONS.md #IDC-32.
|
|
71
97
|
*/
|
|
72
|
-
export const IdCaptureStageScreen = forwardRef(({ strings, documentType = 'id', side = 'front', vertical = false, state = 'empty', manual = false, showClose = state !== 'empty', feedback, camera, still, countdownValue = 3, screenId = `id-capture-${documentType}-${side}-${state}`, overrides, onAction, className, ...shell }, ref) => {
|
|
98
|
+
export const IdCaptureStageScreen = forwardRef(({ strings, documentType = 'id', side = 'front', vertical = false, state = 'empty', manual = false, showClose = state !== 'empty', feedback, camera, still, countdownValue = 3, extendTime, onExtendTime, notice, screenId = `id-capture-${documentType}-${side}-${state}`, overrides, onAction, className, ...shell }, ref) => {
|
|
73
99
|
const slice = documentType === 'passport'
|
|
74
100
|
? strings.stage.passport
|
|
75
101
|
: side === 'back'
|
|
@@ -77,12 +103,22 @@ export const IdCaptureStageScreen = forwardRef(({ strings, documentType = 'id',
|
|
|
77
103
|
: strings.stage.front;
|
|
78
104
|
const pillKind = feedback === undefined ? STAGE_FEEDBACK[state] : feedback;
|
|
79
105
|
const pillCopy = pillKind ? strings.feedback[pillKind] : undefined;
|
|
106
|
+
const offer = strings.stage.extendTime;
|
|
107
|
+
// No copy, no notice: a host that has not localized this must not get
|
|
108
|
+
// English, and the flag alone is not permission to invent it.
|
|
109
|
+
const band = notice ??
|
|
110
|
+
(extendTime && offer ? (_jsxs(PrizmaSnackbar, { state: "neutral", isMultiline: true,
|
|
111
|
+
// Assertive on purpose — a polite region can queue behind the
|
|
112
|
+
// stage's own state announcements and be read out after the 20 s
|
|
113
|
+
// has already run out. FaceCaptureCapturingScreen's header has the
|
|
114
|
+
// full reasoning; this instance follows it.
|
|
115
|
+
role: "alert", linkLabel: offer.linkLabel, onLinkClick: onExtendTime, children: [_jsx("strong", { children: offer.title }), _jsx("br", {}), offer.description] })) : undefined);
|
|
80
116
|
return (_jsxs(PrizmaScreenShell, { ref: ref, dark: true, className: className, ...shell, children: [_jsx("div", { className: "prizma-viewfinder__surface", children: camera }), _jsx("header", { className: "prizma-screen-nav id-capture-stage__nav", children: _jsx(PrizmaNavigation, { showIncodeLogo: false, showRightIcon: showClose, closeLabel: strings.closeLabel, "aria-label": strings.navLabel, onRightIconClick: () => onAction?.({ type: 'secondary', screenId }) }) }), _jsxs("div", { className: [
|
|
81
117
|
'prizma-viewfinder__content',
|
|
82
118
|
overrides?.align === 'left' ? 'prizma-viewfinder__content--left' : '',
|
|
83
119
|
]
|
|
84
120
|
.filter(Boolean)
|
|
85
|
-
.join(' '), children: [_jsx("div", { className: "id-capture-band id-capture-band--top", children: pillKind && pillCopy ? (_jsx("div", { className: "id-capture-stage__feedback", children: _jsx(PrizmaCaptureFeedback, { feedback: pillKind, title: pillCopy.title, subtitle: pillCopy.subtitle }) })) : (_jsxs(_Fragment, { children: [_jsx("h2", { className: "prizma-viewfinder__title", children: slice.title }), slice.instruction && !manual ? (_jsx("p", { className: "prizma-viewfinder__instruction", children: slice.instruction })) : null] })) }), _jsx(PrizmaIdCapture, { type: documentType, state: CAPTURE_STATE[state], isVertical: vertical, mode: "overlay", scrim: true, countdownValue: countdownValue, encryptedLabel: strings.encryptedLabel, announcement: strings.stage.stateLabels?.[state], still: still }), _jsx("div", { className: "id-capture-band" })] }), _jsx("div", { className: "prizma-screen-layout__capture-strip", children: _jsx(PrizmaCaptureManual, { className: "id-capture-stage__manual", variant: "id-capture", showButton: manual, showTooltip: manual, showHelpIcon: true, tooltipText: manual ? strings.stage.manualTooltip : undefined, ariaLabel: strings.stage.captureLabel, helpLabel: strings.stage.helpLabel, onCapture: () => onAction?.({ type: 'cta', screenId }), onHelp: () => onAction?.({ type: 'help', screenId }) }) }), _jsx("div", { className: "prizma-screen-layout__footer", children: _jsx(PrizmaTag, { label: strings.verifiedLabel }) })] }));
|
|
121
|
+
.join(' '), children: [_jsx("div", { className: "id-capture-band id-capture-band--top", children: pillKind && pillCopy ? (_jsx("div", { className: "id-capture-stage__feedback", children: _jsx(PrizmaCaptureFeedback, { feedback: pillKind, title: pillCopy.title, subtitle: pillCopy.subtitle }) })) : (_jsxs(_Fragment, { children: [_jsx("h2", { className: "prizma-viewfinder__title", children: slice.title }), slice.instruction && !manual ? (_jsx("p", { className: "prizma-viewfinder__instruction", children: slice.instruction })) : null] })) }), _jsx(PrizmaIdCapture, { type: documentType, state: CAPTURE_STATE[state], isVertical: vertical, mode: "overlay", scrim: true, countdownValue: countdownValue, encryptedLabel: strings.encryptedLabel, announcement: strings.stage.stateLabels?.[state], still: still }), _jsx("div", { className: "id-capture-band", children: band ? _jsx("div", { className: "id-capture-stage__notice", children: band }) : null })] }), _jsx("div", { className: "prizma-screen-layout__capture-strip", children: _jsx(PrizmaCaptureManual, { className: "id-capture-stage__manual", variant: "id-capture", showButton: manual, showTooltip: manual, showHelpIcon: true, tooltipText: manual ? strings.stage.manualTooltip : undefined, ariaLabel: strings.stage.captureLabel, helpLabel: strings.stage.helpLabel, onCapture: () => onAction?.({ type: 'cta', screenId }), onHelp: () => onAction?.({ type: 'help', screenId }) }) }), _jsx("div", { className: "prizma-screen-layout__footer", children: _jsx(PrizmaTag, { label: strings.verifiedLabel }) })] }));
|
|
86
122
|
});
|
|
87
123
|
IdCaptureStageScreen.displayName = 'IdCaptureStageScreen';
|
|
88
124
|
export default IdCaptureStageScreen;
|
|
@@ -102,6 +102,25 @@ export interface IdCaptureStrings {
|
|
|
102
102
|
/** Visually-hidden state announcements, per stage state — forwarded to
|
|
103
103
|
* `PrizmaIdCapture.stateLabels`. */
|
|
104
104
|
stateLabels?: Partial<Record<IdCaptureStageState, string>>;
|
|
105
|
+
/**
|
|
106
|
+
* stage.extendTime — the accessibility offer that rides the camera stage
|
|
107
|
+
* 20 s before auto-capture gives up and hands over to the shutter
|
|
108
|
+
* ("Need more time? / Manual capture starts in 20 s / Extend auto-capture").
|
|
109
|
+
* The same contract as Face Capture's `extendTime`: one feature, two
|
|
110
|
+
* modules, identical copy, so the locale overlay translates both at once.
|
|
111
|
+
*
|
|
112
|
+
* `description` is one localized sentence that CONTAINS the count, not a
|
|
113
|
+
* template — ten locales put the number in ten places. Optional: a host
|
|
114
|
+
* that has not localized it gets no notice rather than English.
|
|
115
|
+
*/
|
|
116
|
+
extendTime?: {
|
|
117
|
+
/** Bold first line — "Need more time?" */
|
|
118
|
+
title: string;
|
|
119
|
+
/** "Manual capture starts in 20 s" — the count lives inside the copy. */
|
|
120
|
+
description: string;
|
|
121
|
+
/** The action that keeps the user on auto — "Extend auto-capture". */
|
|
122
|
+
linkLabel: string;
|
|
123
|
+
};
|
|
105
124
|
};
|
|
106
125
|
/** The on-camera feedback pills the error stages carry. */
|
|
107
126
|
feedback: Partial<Record<IdCaptureFeedbackKind, IdCaptureFeedbackCopy>>;
|
package/dist/ListScreen.d.ts
CHANGED
|
@@ -61,6 +61,25 @@ export interface PrizmaListScreenProps extends Omit<PrizmaScreenShellProps, 'dar
|
|
|
61
61
|
* (common issues) and "Quit process" (permission). Figma draws Core's
|
|
62
62
|
* `tertiary-link` composite in the band's top slot. */
|
|
63
63
|
linkLabel?: string;
|
|
64
|
+
/**
|
|
65
|
+
* A SECOND tertiary link, under the first. Reusability's selection draws
|
|
66
|
+
* "What data will be shared?" over "Incode’s Privacy Policy" with no primary
|
|
67
|
+
* between them — two non-primary actions a host has to tell apart, so this
|
|
68
|
+
* one emits `tertiary` where `linkLabel` emits `secondary` (the #PI-10
|
|
69
|
+
* reasoning). Stacked at the band's flat Spacing/16 like everything else in
|
|
70
|
+
* it. Omit it and nothing renders, so every existing consumer is untouched.
|
|
71
|
+
* DEVIATIONS #RU-4.
|
|
72
|
+
*/
|
|
73
|
+
secondaryLinkLabel?: string;
|
|
74
|
+
/**
|
|
75
|
+
* A shell-level layer painted OVER the whole screen — the same slot
|
|
76
|
+
* archetypes A and E carry (#F-32, #BC-8): a scrim plus Core's
|
|
77
|
+
* `PrizmaBottomSheetContent` or `PrizmaModalContent`, presented on top of the
|
|
78
|
+
* dimmed list. It cannot ride in the content column: it is absolutely
|
|
79
|
+
* positioned against the shell. Reusability's shared-details sheet is the
|
|
80
|
+
* first List consumer (DEVIATIONS #RU-5).
|
|
81
|
+
*/
|
|
82
|
+
overlay?: ReactNode;
|
|
64
83
|
/** "verified by" attribution copy for the footer tag. */
|
|
65
84
|
verifiedLabel: string;
|
|
66
85
|
navLabel?: string;
|
package/dist/ListScreen.js
CHANGED
|
@@ -31,7 +31,7 @@ import './ScreenLayout.css';
|
|
|
31
31
|
* Reach for `PrizmaResultScreen` instead when the middle is a centred verdict
|
|
32
32
|
* rather than a list.
|
|
33
33
|
*/
|
|
34
|
-
export const PrizmaListScreen = forwardRef(({ progress, status = 'none', title, subtitle, glyph, children, listAlign = 'start', scrollList = false, disclaimer, ctaLabel, secondaryCtaLabel, linkLabel, verifiedLabel, navLabel, backLabel, screenId, showHeader = true, showFooter = true, overrides, onAction, ...shell }, ref) => (_jsxs(PrizmaScreenShell, { ref: ref, ...shell, children: [_jsx(PrizmaScreenNav, { reserved: !showHeader, logo: overrides?.logo, navLabel: navLabel, backLabel: backLabel, onBack: () => onAction?.({ type: 'back', screenId }) }), progress ? (_jsx("div", { className: "prizma-screen-layout__progress", children: progress })) : null, _jsxs("div", { className: "prizma-screen-layout__content", children: [glyph, _jsx(PrizmaTitle, { variant: overrides?.align === 'left' ? 'left' : 'centered', title: title, showSubtitle: Boolean(subtitle), subtitle: subtitle, icon: status === 'loading'
|
|
34
|
+
export const PrizmaListScreen = forwardRef(({ progress, status = 'none', title, subtitle, glyph, children, listAlign = 'start', scrollList = false, disclaimer, ctaLabel, secondaryCtaLabel, linkLabel, secondaryLinkLabel, overlay, verifiedLabel, navLabel, backLabel, screenId, showHeader = true, showFooter = true, overrides, onAction, ...shell }, ref) => (_jsxs(PrizmaScreenShell, { ref: ref, ...shell, children: [_jsx(PrizmaScreenNav, { reserved: !showHeader, logo: overrides?.logo, navLabel: navLabel, backLabel: backLabel, onBack: () => onAction?.({ type: 'back', screenId }) }), progress ? (_jsx("div", { className: "prizma-screen-layout__progress", children: progress })) : null, _jsxs("div", { className: "prizma-screen-layout__content", children: [glyph, _jsx(PrizmaTitle, { variant: overrides?.align === 'left' ? 'left' : 'centered', title: title, showSubtitle: Boolean(subtitle), subtitle: subtitle, icon: status === 'loading'
|
|
35
35
|
? { type: 'spinner' }
|
|
36
36
|
: status === 'none'
|
|
37
37
|
? { type: 'none' }
|
|
@@ -41,6 +41,11 @@ export const PrizmaListScreen = forwardRef(({ progress, status = 'none', title,
|
|
|
41
41
|
scrollList ? 'prizma-screen-layout__list--scroll' : '',
|
|
42
42
|
]
|
|
43
43
|
.filter(Boolean)
|
|
44
|
-
.join(' '), children: children }), ctaLabel || secondaryCtaLabel || linkLabel || disclaimer ? (_jsxs("div", { className: "prizma-screen-layout__band", children: [disclaimer ? _jsx(PrizmaDisclaimer, { text: disclaimer }) : null, linkLabel
|
|
44
|
+
.join(' '), children: children }), ctaLabel || secondaryCtaLabel || linkLabel || secondaryLinkLabel || disclaimer ? (_jsxs("div", { className: "prizma-screen-layout__band", children: [disclaimer ? _jsx(PrizmaDisclaimer, { text: disclaimer }) : null, linkLabel || secondaryLinkLabel ? (
|
|
45
|
+
/* The links share ONE band slot, stacked flush: two 56px link
|
|
46
|
+
rows with the band's 16 between them read as two distant
|
|
47
|
+
lines (Camila, 2026-10-13); the row height is already the
|
|
48
|
+
touch target. ScreenLayout.css `__band__links`. */
|
|
49
|
+
_jsxs("div", { className: "prizma-screen-layout__band__links", children: [linkLabel ? (_jsx(PrizmaButton, { variant: "tertiary-link", size: "L", onClick: () => onAction?.({ type: 'secondary', screenId }), children: linkLabel })) : null, secondaryLinkLabel ? (_jsx(PrizmaButton, { variant: "tertiary-link", size: "L", onClick: () => onAction?.({ type: 'tertiary', screenId }), children: secondaryLinkLabel })) : null] })) : null, ctaLabel ? (_jsx(PrizmaButton, { variant: "primary", size: "L", onClick: () => onAction?.({ type: 'cta', screenId }), children: ctaLabel })) : null, secondaryCtaLabel ? (_jsx(PrizmaButton, { variant: "secondary", size: "L", onClick: () => onAction?.({ type: 'secondary', screenId }), children: secondaryCtaLabel })) : null] })) : null] }), showFooter ? (_jsx("div", { className: "prizma-screen-layout__footer", children: _jsx(PrizmaTag, { label: verifiedLabel }) })) : null, overlay] })));
|
|
45
50
|
PrizmaListScreen.displayName = 'PrizmaListScreen';
|
|
46
51
|
export default PrizmaListScreen;
|
package/dist/LoaderScreen.d.ts
CHANGED
|
@@ -17,11 +17,13 @@ export interface LoaderScreenProps extends Omit<PrizmaProcessingScreenProps, 'st
|
|
|
17
17
|
* (GUIDELINES.md §6-C, `PrizmaProcessingScreen`).
|
|
18
18
|
*
|
|
19
19
|
* Figma: `Module Generic Screens` frames `67:2388` ("Processing…") and
|
|
20
|
-
* `67:3593` ("Just a moment…")
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
20
|
+
* `67:3593` ("Just a moment…"), plus the SDK's own "Hold on a sec…" wait that
|
|
21
|
+
* ID Capture, NFC and the Demo App show (`verifyingIdentity`). ONE screen for
|
|
22
|
+
* all of them, and for every module loader after them: logo header → Core's
|
|
23
|
+
* spinner → status line → reassurance line → the verified tag, with no CTA.
|
|
24
|
+
* The archetype already IS this recipe; this component exists so the family
|
|
25
|
+
* has a name a designer can point at and a copy contract a host can fill, not
|
|
26
|
+
* to add layout.
|
|
25
27
|
*
|
|
26
28
|
* Reach for `PrizmaResultScreen` the moment a wait screen needs a button — a
|
|
27
29
|
* loader with a "Cancel" is a result screen, and the missing CTA band here is
|
package/dist/LoaderScreen.js
CHANGED
|
@@ -8,11 +8,13 @@ import './ScreenLayout.css';
|
|
|
8
8
|
* (GUIDELINES.md §6-C, `PrizmaProcessingScreen`).
|
|
9
9
|
*
|
|
10
10
|
* Figma: `Module Generic Screens` frames `67:2388` ("Processing…") and
|
|
11
|
-
* `67:3593` ("Just a moment…")
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* `67:3593` ("Just a moment…"), plus the SDK's own "Hold on a sec…" wait that
|
|
12
|
+
* ID Capture, NFC and the Demo App show (`verifyingIdentity`). ONE screen for
|
|
13
|
+
* all of them, and for every module loader after them: logo header → Core's
|
|
14
|
+
* spinner → status line → reassurance line → the verified tag, with no CTA.
|
|
15
|
+
* The archetype already IS this recipe; this component exists so the family
|
|
16
|
+
* has a name a designer can point at and a copy contract a host can fill, not
|
|
17
|
+
* to add layout.
|
|
16
18
|
*
|
|
17
19
|
* Reach for `PrizmaResultScreen` the moment a wait screen needs a button — a
|
|
18
20
|
* loader with a "Cancel" is a result screen, and the missing CTA band here is
|
package/dist/LoadersStrings.d.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* The copy pairs the family records. The loader is a shape, and each entry
|
|
3
|
+
* here is a way of filling it that more than one module already uses — not a
|
|
4
|
+
* closed set. A module that waits for something else supplies its own pair of
|
|
5
|
+
* strings under a new key.
|
|
6
|
+
*
|
|
7
|
+
* - `processing` — frame `67:2388`. "Processing…" over the generic
|
|
8
|
+
* reassurance line. Watchlist for Business, eKYC, eKYB,
|
|
9
|
+
* Email Input and the signatures all draw this title.
|
|
10
|
+
* - `validating` — frame `67:3593`. "Just a moment…", the documents
|
|
11
|
+
* are being validated.
|
|
12
|
+
* - `verifyingIdentity` — the SDK's own `loadingCircle.holdOn` wait: "Hold on
|
|
13
|
+
* a sec…" over "We're verifying your identity". ID
|
|
14
|
+
* Capture, NFC and the Demo App show it between the
|
|
15
|
+
* last capture and the verdict (Camila, 2026-10-09).
|
|
16
|
+
*
|
|
17
|
+
* Copy rule for every wait title: the ellipsis is the single `…` character,
|
|
18
|
+
* never two or three periods, so the same word reads the same in every module.
|
|
6
19
|
*/
|
|
7
|
-
export type LoadersVariant = 'processing' | 'validating';
|
|
20
|
+
export type LoadersVariant = 'processing' | 'validating' | 'verifyingIdentity';
|
|
8
21
|
export interface LoadersCopy {
|
|
9
22
|
/** H2 status line ("Processing…"). */
|
|
10
23
|
title: string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type PrizmaResultScreenProps } from './ResultScreen';
|
|
3
|
+
import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
|
|
4
|
+
import type { OcrReviewStrings } from './OcrReviewStrings';
|
|
5
|
+
import './ScreenLayout.css';
|
|
6
|
+
export interface OcrReviewErrorScreenProps extends Omit<PrizmaResultScreenProps, 'status' | 'title' | 'ctaLabel' | 'verifiedLabel' | 'navLabel'> {
|
|
7
|
+
/** Module copy — this screen reads the `error` slice. */
|
|
8
|
+
strings: OcrReviewStrings;
|
|
9
|
+
screenId?: string;
|
|
10
|
+
overrides?: PrizmaScreenOverrides;
|
|
11
|
+
onAction?: PrizmaScreenActionHandler;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* OCR Review — "Something went wrong", built on Archetype F (GUIDELINES.md
|
|
15
|
+
* §6-F, `PrizmaResultScreen`). Figma: `OCR Error` (31084:18797), drawn OUTSIDE
|
|
16
|
+
* the Happy Path section and reached off the "Processed successfully?"
|
|
17
|
+
* decision's "No" branch — a plain status + title + "Try again" CTA.
|
|
18
|
+
*
|
|
19
|
+
* Nav and footer tag are left at the archetype's DEFAULT (shown). The frame
|
|
20
|
+
* itself draws neither, matching `DigitalIdUploadFileTooLargeScreen.tsx` —
|
|
21
|
+
* but that screen is the ONE exception in the whole package, not the pattern:
|
|
22
|
+
* every other error screen (`EkycErrorScreen`, `EkybErrorScreen`,
|
|
23
|
+
* `EmailInputErrorScreen`, `FormsErrorScreen`, `IdCaptureDocumentErrorScreen`)
|
|
24
|
+
* keeps both. Hiding them here, with only one CTA to balance the bottom,
|
|
25
|
+
* pushed the status + title below where every sibling error screen centres it
|
|
26
|
+
* (Mili, 2026-10-12 — checked against the system's own screens, not re-derived
|
|
27
|
+
* from the frame).
|
|
28
|
+
*/
|
|
29
|
+
export declare const OcrReviewErrorScreen: React.ForwardRefExoticComponent<OcrReviewErrorScreenProps & React.RefAttributes<HTMLDivElement>>;
|
|
30
|
+
export default OcrReviewErrorScreen;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { PrizmaResultScreen } from './ResultScreen';
|
|
5
|
+
import './ScreenLayout.css';
|
|
6
|
+
/**
|
|
7
|
+
* OCR Review — "Something went wrong", built on Archetype F (GUIDELINES.md
|
|
8
|
+
* §6-F, `PrizmaResultScreen`). Figma: `OCR Error` (31084:18797), drawn OUTSIDE
|
|
9
|
+
* the Happy Path section and reached off the "Processed successfully?"
|
|
10
|
+
* decision's "No" branch — a plain status + title + "Try again" CTA.
|
|
11
|
+
*
|
|
12
|
+
* Nav and footer tag are left at the archetype's DEFAULT (shown). The frame
|
|
13
|
+
* itself draws neither, matching `DigitalIdUploadFileTooLargeScreen.tsx` —
|
|
14
|
+
* but that screen is the ONE exception in the whole package, not the pattern:
|
|
15
|
+
* every other error screen (`EkycErrorScreen`, `EkybErrorScreen`,
|
|
16
|
+
* `EmailInputErrorScreen`, `FormsErrorScreen`, `IdCaptureDocumentErrorScreen`)
|
|
17
|
+
* keeps both. Hiding them here, with only one CTA to balance the bottom,
|
|
18
|
+
* pushed the status + title below where every sibling error screen centres it
|
|
19
|
+
* (Mili, 2026-10-12 — checked against the system's own screens, not re-derived
|
|
20
|
+
* from the frame).
|
|
21
|
+
*/
|
|
22
|
+
export const OcrReviewErrorScreen = forwardRef(({ strings, screenId = 'ocr-review-error', overrides, onAction, ...shell }, ref) => (_jsx(PrizmaResultScreen, { ref: ref, status: "error", title: strings.error.title, ctaLabel: strings.error.ctaLabel, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell })));
|
|
23
|
+
OcrReviewErrorScreen.displayName = 'OcrReviewErrorScreen';
|
|
24
|
+
export default OcrReviewErrorScreen;
|