@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
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type PrizmaListScreenProps } from './ListScreen';
|
|
3
|
+
import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
|
|
4
|
+
import type { ReusableCredential, ReusabilityStrings } from './ReusabilityStrings';
|
|
5
|
+
import './ScreenLayout.css';
|
|
6
|
+
import './ReusabilityLayout.css';
|
|
7
|
+
/** The sentinel the SDK submits for the capture row (`SCAN_NEW_DOCUMENT`,
|
|
8
|
+
* `identityReuseStateMachine.ts`): `{ accepted: false }`, then ID Capture. */
|
|
9
|
+
export declare const REUSABILITY_SCAN_NEW: "scanNew";
|
|
10
|
+
export type ReusabilitySelection = string | typeof REUSABILITY_SCAN_NEW;
|
|
11
|
+
export interface ReusabilityCredentialSelectionScreenProps extends Omit<PrizmaListScreenProps, 'status' | 'title' | 'subtitle' | 'glyph' | 'children' | 'listAlign' | 'scrollList' | 'disclaimer' | 'ctaLabel' | 'secondaryCtaLabel' | 'linkLabel' | 'secondaryLinkLabel' | 'overlay' | 'verifiedLabel' | 'navLabel'> {
|
|
12
|
+
/** Module copy — this screen reads the `selection` and `sharedDetails` slices. */
|
|
13
|
+
strings: ReusabilityStrings;
|
|
14
|
+
/**
|
|
15
|
+
* The documents the network found for this person, best match FIRST — the
|
|
16
|
+
* backend orders them and the first row wears the "Recommended" pill (SDK
|
|
17
|
+
* `recommended={index === 0}`). One or more; the frame draws two
|
|
18
|
+
* (`Multiple documents`) and one (`Single document`).
|
|
19
|
+
*/
|
|
20
|
+
credentials: ReusableCredential[];
|
|
21
|
+
/**
|
|
22
|
+
* "What data will be shared?" was pressed: Core's bottom sheet listing the
|
|
23
|
+
* recipient's data request is presented over the dimmed selection
|
|
24
|
+
* (`shared info`, 7877:68927). Its one button emits `cta` and closes it.
|
|
25
|
+
*/
|
|
26
|
+
sharedDetails?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Fired with the chosen credential's id, or `REUSABILITY_SCAN_NEW` for the
|
|
29
|
+
* capture row; `onAction` still reports the tap as `cta`. Named like ID
|
|
30
|
+
* Capture's `onDocumentSelect` — `onSelect` is a native <div> event the shell
|
|
31
|
+
* already passes through.
|
|
32
|
+
*/
|
|
33
|
+
onCredentialSelect?: (selection: ReusabilitySelection) => void;
|
|
34
|
+
screenId?: string;
|
|
35
|
+
overrides?: PrizmaScreenOverrides;
|
|
36
|
+
onAction?: PrizmaScreenActionHandler;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Reusability (Incode Bridge) — choose the document to reuse, built on the
|
|
40
|
+
* List archetype (GUIDELINES.md §6-G, `PrizmaListScreen`).
|
|
41
|
+
*
|
|
42
|
+
* ONE screen for three of the section's four frames: `Multiple documents`
|
|
43
|
+
* (7877:68816) and `Single document` (7877:68875) are the same skeleton — nav →
|
|
44
|
+
* Title (H2 + H5) → the credential list → "Scan a new document" → two tertiary
|
|
45
|
+
* links → tag — differing only in how many rows the network returned; and
|
|
46
|
+
* `Shared data` (7877:68927) is that screen with Core's bottom sheet presented
|
|
47
|
+
* over it (`sharedDetails`).
|
|
48
|
+
*
|
|
49
|
+
* WHY ARCHETYPE G. The rows ARE the actions — tapping a document advances the
|
|
50
|
+
* session with no confirm step (consent review 2026-09-16: "remove the confirm
|
|
51
|
+
* button: selecting a document advances the user immediately"; the Web SDK's
|
|
52
|
+
* ENG-57939 built exactly that) — so there is no primary CTA, and G is the one
|
|
53
|
+
* archetype whose band may carry links alone. ID Capture's document chooser is
|
|
54
|
+
* the same shape on the same archetype.
|
|
55
|
+
*
|
|
56
|
+
* Six things are deliberate:
|
|
57
|
+
*
|
|
58
|
+
* 1. The rows are composed here from Core's tokens, not from Core's
|
|
59
|
+
* `PrizmaCardListVerificationOptions`. The frame calls them "Verification
|
|
60
|
+
* options card list", but a reusable credential has a different anatomy —
|
|
61
|
+
* type label + status pill, flag + masked number, verified date — and the
|
|
62
|
+
* capture row is one line with a pill. Core ships neither that row nor a
|
|
63
|
+
* plain status pill; both are proposed (DEVIATIONS #RU-1, #RU-2) and the
|
|
64
|
+
* rules live once in `ReusabilityLayout.css`.
|
|
65
|
+
* 2. Every row is a real `<button>` that emits `cta` and names its credential
|
|
66
|
+
* through `onCredentialSelect` — the one-click rule. No radio, no selected
|
|
67
|
+
* state: the frame draws none and the decision was to drop them. The SDK's
|
|
68
|
+
* shipped `role="radio"` + confirm is the generation BEFORE this frame.
|
|
69
|
+
* 3. The first row wears "Recommended", because the backend sorts best match
|
|
70
|
+
* first; the capture row wears "Slowest". The pills are the frame's own
|
|
71
|
+
* fills on Core tokens; their 12px type is the one value Core's scale
|
|
72
|
+
* cannot express (#RU-2).
|
|
73
|
+
* 4. The flag is Core's raster bank (`PrizmaCountryFlag`, 24×18), never the
|
|
74
|
+
* frame's emoji glyph (owner decision 2026-07-12). A country outside the
|
|
75
|
+
* bank falls back to the emoji the host supplies — Core's own fallback rule
|
|
76
|
+
* (#RU-3).
|
|
77
|
+
* 5. The two links ride the archetype's band: "What data will be shared?" in
|
|
78
|
+
* `linkLabel` (emits `secondary`) and "Incode’s Privacy Policy" in the new
|
|
79
|
+
* `secondaryLinkLabel` slot (emits `tertiary`) — two non-primary actions a
|
|
80
|
+
* host must tell apart (#PI-10), so each has its own action. The band's
|
|
81
|
+
* flat Spacing/16 stands between them where the frame's Button group
|
|
82
|
+
* tightens the pair by 8 (#RU-4).
|
|
83
|
+
* 6. The sheet rides the archetype's new `overlay` slot — the same contract E
|
|
84
|
+
* gained for Biometric Consent (#BC-8): the screen owns the scrim and the
|
|
85
|
+
* anchoring (the foundation's `__sheet-scrim` / `__sheet-panel`), Core owns
|
|
86
|
+
* the panel — `PrizmaBottomSheetContent variant="dialog"` with its H1
|
|
87
|
+
* title, H5 subtitle, the bullet list in `body`, and its own Button Group
|
|
88
|
+
* reduced to "Understood". With the sheet up the rows and links are under
|
|
89
|
+
* the scrim and do not report (#RU-5).
|
|
90
|
+
*
|
|
91
|
+
* The nav keeps the logo and draws no close: the frame's top-right ✕ is the
|
|
92
|
+
* SDK page chrome, not a Prizma screen control (GUIDELINES §3; #RU-6).
|
|
93
|
+
*/
|
|
94
|
+
export declare const ReusabilityCredentialSelectionScreen: React.ForwardRefExoticComponent<ReusabilityCredentialSelectionScreenProps & React.RefAttributes<HTMLDivElement>>;
|
|
95
|
+
export default ReusabilityCredentialSelectionScreen;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { PrizmaBottomSheetContent } from '@incodetech/prizma-core-web/bottom-sheet';
|
|
5
|
+
import { PrizmaCountryFlag } from '@incodetech/prizma-core-web/combined';
|
|
6
|
+
import { PrizmaListScreen } from './ListScreen';
|
|
7
|
+
import './ScreenLayout.css';
|
|
8
|
+
import './ReusabilityLayout.css';
|
|
9
|
+
/** The sentinel the SDK submits for the capture row (`SCAN_NEW_DOCUMENT`,
|
|
10
|
+
* `identityReuseStateMachine.ts`): `{ accepted: false }`, then ID Capture. */
|
|
11
|
+
export const REUSABILITY_SCAN_NEW = 'scanNew';
|
|
12
|
+
/**
|
|
13
|
+
* Reusability (Incode Bridge) — choose the document to reuse, built on the
|
|
14
|
+
* List archetype (GUIDELINES.md §6-G, `PrizmaListScreen`).
|
|
15
|
+
*
|
|
16
|
+
* ONE screen for three of the section's four frames: `Multiple documents`
|
|
17
|
+
* (7877:68816) and `Single document` (7877:68875) are the same skeleton — nav →
|
|
18
|
+
* Title (H2 + H5) → the credential list → "Scan a new document" → two tertiary
|
|
19
|
+
* links → tag — differing only in how many rows the network returned; and
|
|
20
|
+
* `Shared data` (7877:68927) is that screen with Core's bottom sheet presented
|
|
21
|
+
* over it (`sharedDetails`).
|
|
22
|
+
*
|
|
23
|
+
* WHY ARCHETYPE G. The rows ARE the actions — tapping a document advances the
|
|
24
|
+
* session with no confirm step (consent review 2026-09-16: "remove the confirm
|
|
25
|
+
* button: selecting a document advances the user immediately"; the Web SDK's
|
|
26
|
+
* ENG-57939 built exactly that) — so there is no primary CTA, and G is the one
|
|
27
|
+
* archetype whose band may carry links alone. ID Capture's document chooser is
|
|
28
|
+
* the same shape on the same archetype.
|
|
29
|
+
*
|
|
30
|
+
* Six things are deliberate:
|
|
31
|
+
*
|
|
32
|
+
* 1. The rows are composed here from Core's tokens, not from Core's
|
|
33
|
+
* `PrizmaCardListVerificationOptions`. The frame calls them "Verification
|
|
34
|
+
* options card list", but a reusable credential has a different anatomy —
|
|
35
|
+
* type label + status pill, flag + masked number, verified date — and the
|
|
36
|
+
* capture row is one line with a pill. Core ships neither that row nor a
|
|
37
|
+
* plain status pill; both are proposed (DEVIATIONS #RU-1, #RU-2) and the
|
|
38
|
+
* rules live once in `ReusabilityLayout.css`.
|
|
39
|
+
* 2. Every row is a real `<button>` that emits `cta` and names its credential
|
|
40
|
+
* through `onCredentialSelect` — the one-click rule. No radio, no selected
|
|
41
|
+
* state: the frame draws none and the decision was to drop them. The SDK's
|
|
42
|
+
* shipped `role="radio"` + confirm is the generation BEFORE this frame.
|
|
43
|
+
* 3. The first row wears "Recommended", because the backend sorts best match
|
|
44
|
+
* first; the capture row wears "Slowest". The pills are the frame's own
|
|
45
|
+
* fills on Core tokens; their 12px type is the one value Core's scale
|
|
46
|
+
* cannot express (#RU-2).
|
|
47
|
+
* 4. The flag is Core's raster bank (`PrizmaCountryFlag`, 24×18), never the
|
|
48
|
+
* frame's emoji glyph (owner decision 2026-07-12). A country outside the
|
|
49
|
+
* bank falls back to the emoji the host supplies — Core's own fallback rule
|
|
50
|
+
* (#RU-3).
|
|
51
|
+
* 5. The two links ride the archetype's band: "What data will be shared?" in
|
|
52
|
+
* `linkLabel` (emits `secondary`) and "Incode’s Privacy Policy" in the new
|
|
53
|
+
* `secondaryLinkLabel` slot (emits `tertiary`) — two non-primary actions a
|
|
54
|
+
* host must tell apart (#PI-10), so each has its own action. The band's
|
|
55
|
+
* flat Spacing/16 stands between them where the frame's Button group
|
|
56
|
+
* tightens the pair by 8 (#RU-4).
|
|
57
|
+
* 6. The sheet rides the archetype's new `overlay` slot — the same contract E
|
|
58
|
+
* gained for Biometric Consent (#BC-8): the screen owns the scrim and the
|
|
59
|
+
* anchoring (the foundation's `__sheet-scrim` / `__sheet-panel`), Core owns
|
|
60
|
+
* the panel — `PrizmaBottomSheetContent variant="dialog"` with its H1
|
|
61
|
+
* title, H5 subtitle, the bullet list in `body`, and its own Button Group
|
|
62
|
+
* reduced to "Understood". With the sheet up the rows and links are under
|
|
63
|
+
* the scrim and do not report (#RU-5).
|
|
64
|
+
*
|
|
65
|
+
* The nav keeps the logo and draws no close: the frame's top-right ✕ is the
|
|
66
|
+
* SDK page chrome, not a Prizma screen control (GUIDELINES §3; #RU-6).
|
|
67
|
+
*/
|
|
68
|
+
export const ReusabilityCredentialSelectionScreen = forwardRef(({ strings, credentials, sharedDetails = false, onCredentialSelect, screenId = sharedDetails
|
|
69
|
+
? 'reusability-shared-details'
|
|
70
|
+
: `reusability-selection-${credentials.length > 1 ? 'multiple' : 'single'}`, overrides, onAction, ...shell }, ref) => {
|
|
71
|
+
const { selection, sharedDetails: shared } = strings;
|
|
72
|
+
const choose = (choice) => {
|
|
73
|
+
if (sharedDetails)
|
|
74
|
+
return;
|
|
75
|
+
onCredentialSelect?.(choice);
|
|
76
|
+
onAction?.({ type: 'cta', screenId });
|
|
77
|
+
};
|
|
78
|
+
const sheet = sharedDetails ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "prizma-screen-layout__sheet-scrim", "aria-hidden": "true" }), _jsx("div", { className: "prizma-screen-layout__sheet-panel", children: _jsx(PrizmaBottomSheetContent, { variant: "dialog", title: shared.title, subtitle: shared.subtitle, body: _jsx("ul", { className: "reusability-shared-list", children: shared.items.map((item) => (_jsx("li", { children: item }, item))) }), buttonGroupProps: {
|
|
79
|
+
primaryLabel: shared.ctaLabel,
|
|
80
|
+
showSecondary: false,
|
|
81
|
+
onPrimaryClick: () => onAction?.({ type: 'cta', screenId }),
|
|
82
|
+
} }) })] })) : undefined;
|
|
83
|
+
return (_jsx(PrizmaListScreen, { ref: ref, title: selection.title, subtitle: selection.subtitle, linkLabel: selection.sharedDataLink, secondaryLinkLabel: selection.privacyPolicyLink, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides,
|
|
84
|
+
/* With the sheet up, the links are under the scrim and must not
|
|
85
|
+
report: the sheet's "Understood" is the only action. */
|
|
86
|
+
onAction: sharedDetails ? undefined : onAction, overlay: sheet, ...shell, children: _jsxs("div", { className: "reusability-credentials", role: "group", "aria-label": selection.listLabel, children: [_jsx("div", { className: "reusability-credentials__group", children: credentials.map((credential, index) => (_jsxs("button", { type: "button", className: "reusability-credential", onClick: () => choose(credential.id), tabIndex: sharedDetails ? -1 : undefined, children: [_jsxs("span", { className: "reusability-credential__head", children: [_jsx("span", { className: "reusability-credential__type", children: selection.documentType[credential.documentType] }), index === 0 ? (_jsx("span", { className: "reusability-pill reusability-pill--recommended", children: selection.recommendedTag })) : null] }), _jsxs("span", { className: "reusability-credential__number", children: [_jsx("span", { className: "reusability-credential__flag", "aria-hidden": "true", children: _jsx(PrizmaCountryFlag, { country: {
|
|
87
|
+
code: credential.countryCode,
|
|
88
|
+
name: credential.countryCode,
|
|
89
|
+
dialCode: '',
|
|
90
|
+
flag: credential.countryFlag ?? '',
|
|
91
|
+
} }) }), _jsx("span", { children: credential.maskedNumber })] }), _jsxs("span", { className: "reusability-credential__verified", children: [_jsx("span", { children: selection.verifiedPrefix }), " ", _jsx("span", { children: credential.verifiedOn })] })] }, credential.id))) }), _jsx("div", { className: "reusability-credentials__group", children: _jsx("button", { type: "button", className: "reusability-credential", onClick: () => choose(REUSABILITY_SCAN_NEW), tabIndex: sharedDetails ? -1 : undefined, children: _jsxs("span", { className: "reusability-credential__head", children: [_jsx("span", { className: "reusability-credential__type", children: selection.scanNewLabel }), _jsx("span", { className: "reusability-pill reusability-pill--neutral", children: selection.slowestTag })] }) }) })] }) }));
|
|
92
|
+
});
|
|
93
|
+
ReusabilityCredentialSelectionScreen.displayName = 'ReusabilityCredentialSelectionScreen';
|
|
94
|
+
export default ReusabilityCredentialSelectionScreen;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/* Reusability (Incode Bridge) — module layout additions.
|
|
2
|
+
*
|
|
3
|
+
* Three recipes, every value a Prizma token: the credential rows the selection
|
|
4
|
+
* screen lists, the bullet list inside the shared-details sheet, and the framed
|
|
5
|
+
* reader the privacy policy scrolls in. The content column, the 24px gutters,
|
|
6
|
+
* the title → list offset, the CTA band, the sheet scrim and panel and the
|
|
7
|
+
* anchored footer are all the foundation's (`ScreenLayout.css`); the sheet
|
|
8
|
+
* itself, the buttons, the title and the flag raster are Core's.
|
|
9
|
+
*
|
|
10
|
+
* WHY THE ROWS ARE COMPOSED HERE. The frame names the list "Verification
|
|
11
|
+
* options card list", but it is not Core's `Card / Verification options item`
|
|
12
|
+
* (60px card icon + title + chevron): each row is a document-type label with a
|
|
13
|
+
* status pill, the masked number behind a flag, and the date it was verified —
|
|
14
|
+
* and the last row is a single line with a pill. Core ships no card with that
|
|
15
|
+
* anatomy and no plain status pill (its `PrizmaCardTag` is the ⚡ Instant pill,
|
|
16
|
+
* with the glyph baked in). Both are built below from Core's own tokens — no
|
|
17
|
+
* palette, no radius, no spacing invented — and both are logged as component
|
|
18
|
+
* proposals (DEVIATIONS #RU-1, #RU-2). The moment Core ships them, these rules
|
|
19
|
+
* go and the screen imports the component.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/* ── The credential list ─────────────────────────────────────────────────────
|
|
23
|
+
* Two bordered containers, Spacing/16 apart (`options`, 7877:68823): the
|
|
24
|
+
* reusable documents in the first, "Scan a new document" alone in the second.
|
|
25
|
+
* Rows inside a container touch, each drawing a top hairline the way Core's
|
|
26
|
+
* verification-options rows do (`Card.css`); the container clips the corners. */
|
|
27
|
+
.reusability-credentials {
|
|
28
|
+
display: flex;
|
|
29
|
+
flex-direction: column;
|
|
30
|
+
gap: var(--prizma-spacing-16);
|
|
31
|
+
width: 100%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.reusability-credentials__group {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
overflow: hidden;
|
|
38
|
+
box-sizing: border-box;
|
|
39
|
+
width: 100%;
|
|
40
|
+
background-color: var(--prizma-surface-neutral-0);
|
|
41
|
+
border: var(--prizma-border-width-regular) solid var(--prizma-border-neutral-100);
|
|
42
|
+
border-radius: var(--prizma-border-radius-medium);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* The row IS the action — a real <button>, one tap advances (consent review
|
|
46
|
+
* 2026-09-16: "remove the confirm button"). Button reset, then the frame's
|
|
47
|
+
* Spacing/16 padding and Spacing/8 between its lines. */
|
|
48
|
+
.reusability-credential {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
align-items: stretch;
|
|
52
|
+
gap: var(--prizma-spacing-8);
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
width: 100%;
|
|
55
|
+
margin: 0;
|
|
56
|
+
padding: var(--prizma-spacing-16);
|
|
57
|
+
background-color: var(--prizma-surface-neutral-0);
|
|
58
|
+
border: none;
|
|
59
|
+
border-top: var(--prizma-border-width-regular) solid var(--prizma-border-neutral-100);
|
|
60
|
+
color: var(--prizma-text-body-800-primary);
|
|
61
|
+
font-family: var(--prizma-body-family);
|
|
62
|
+
text-align: left;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
-webkit-font-smoothing: antialiased;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.reusability-credentials__group > .reusability-credential:first-child {
|
|
68
|
+
border-top: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Keyboard focus: Core's Button ring, so a row and the links below it light
|
|
72
|
+
* up the same way. Inset, because the group clips its corners. */
|
|
73
|
+
.reusability-credential:focus-visible {
|
|
74
|
+
outline: var(--prizma-button-focus-ring-width) solid var(--prizma-border-status-focus);
|
|
75
|
+
outline-offset: calc(-1 * var(--prizma-button-focus-ring-width));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Line 1: the document-type label, the pill at the far right. */
|
|
79
|
+
.reusability-credential__head {
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
justify-content: space-between;
|
|
83
|
+
gap: var(--prizma-spacing-8);
|
|
84
|
+
width: 100%;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.reusability-credential__type {
|
|
88
|
+
margin: 0;
|
|
89
|
+
color: var(--prizma-text-body-800-primary);
|
|
90
|
+
font-family: var(--prizma-body-family);
|
|
91
|
+
font-size: var(--prizma-body-m-regular-font-size);
|
|
92
|
+
font-weight: var(--prizma-body-m-regular-font-weight);
|
|
93
|
+
line-height: var(--prizma-body-m-regular-line-height);
|
|
94
|
+
letter-spacing: var(--prizma-body-m-regular-letter-spacing);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Line 2: the flag and the masked number, Headline/H5. */
|
|
98
|
+
.reusability-credential__number {
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
gap: var(--prizma-spacing-4);
|
|
102
|
+
margin: 0;
|
|
103
|
+
color: var(--prizma-text-body-800-primary);
|
|
104
|
+
font-family: var(--prizma-headline-family);
|
|
105
|
+
font-size: var(--prizma-headline-h5-font-size);
|
|
106
|
+
font-weight: var(--prizma-headline-h5-font-weight);
|
|
107
|
+
line-height: var(--prizma-headline-h5-line-height);
|
|
108
|
+
letter-spacing: var(--prizma-headline-h5-letter-spacing);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Core's flag raster is 24×18; the frame draws an emoji glyph at the text
|
|
112
|
+
* size. The raster wins (owner decision 2026-07-12: flags are images, never
|
|
113
|
+
* emoji) and keeps its own geometry — DEVIATIONS #RU-3. */
|
|
114
|
+
.reusability-credential__flag {
|
|
115
|
+
display: inline-flex;
|
|
116
|
+
flex: 0 0 auto;
|
|
117
|
+
align-items: center;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Line 3: "Verified Apr 2023", Body/M in the secondary ink. */
|
|
121
|
+
.reusability-credential__verified {
|
|
122
|
+
margin: 0;
|
|
123
|
+
color: var(--prizma-text-body-500-secondary);
|
|
124
|
+
font-family: var(--prizma-body-family);
|
|
125
|
+
font-size: var(--prizma-body-m-regular-font-size);
|
|
126
|
+
font-weight: var(--prizma-body-m-regular-font-weight);
|
|
127
|
+
line-height: var(--prizma-body-m-regular-line-height);
|
|
128
|
+
letter-spacing: var(--prizma-body-m-regular-letter-spacing);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* ── The status pill ─────────────────────────────────────────────────────────
|
|
132
|
+
* "Recommended" on the best match, "Slowest" on the capture row. Surface/Brand/50
|
|
133
|
+
* for the first, inked with Card/Tag/Text — the mode-aware AA pair Core's own
|
|
134
|
+
* ⚡ pill uses (Brand.600 light · Focus.400 dark; owner call 2026-07-14), because
|
|
135
|
+
* the frame's Text/Accent/Brand on Brand/50 is blue on blue in dark mode;
|
|
136
|
+
* Surface/Neutral/50 with a Border/Neutral/200 hairline for the second — the
|
|
137
|
+
* frame's own fills. Radius x-small (4) and Spacing/2 × Spacing/4 padding, as
|
|
138
|
+
* drawn.
|
|
139
|
+
*
|
|
140
|
+
* TYPE: the frame sets the label in Body/S Regular (12px). Core's generated
|
|
141
|
+
* scale has no 12px text step — Body/M and Label/M are 14 — so the pill takes
|
|
142
|
+
* Label/M Regular, the smallest token the scale has. DEVIATIONS #RU-2. */
|
|
143
|
+
.reusability-pill {
|
|
144
|
+
display: inline-flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
flex: 0 0 auto;
|
|
147
|
+
padding: var(--prizma-spacing-2) var(--prizma-spacing-4);
|
|
148
|
+
border-radius: var(--prizma-border-radius-x-small);
|
|
149
|
+
font-family: var(--prizma-body-family);
|
|
150
|
+
font-size: var(--prizma-label-m-regular-font-size);
|
|
151
|
+
font-weight: var(--prizma-label-m-regular-font-weight);
|
|
152
|
+
line-height: var(--prizma-label-m-regular-line-height);
|
|
153
|
+
letter-spacing: var(--prizma-label-m-regular-letter-spacing);
|
|
154
|
+
white-space: nowrap;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.reusability-pill--recommended {
|
|
158
|
+
background-color: var(--prizma-surface-brand-50);
|
|
159
|
+
color: var(--prizma-card-tag-text);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.reusability-pill--neutral {
|
|
163
|
+
background-color: var(--prizma-surface-neutral-50);
|
|
164
|
+
border: var(--prizma-border-width-regular) solid var(--prizma-border-neutral-200);
|
|
165
|
+
color: var(--prizma-text-body-800-primary);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* ── The shared-details list ─────────────────────────────────────────────────
|
|
169
|
+
* Inside Core's dialog sheet (`__body` slot): the recipient's data request as
|
|
170
|
+
* bullets, Headline/H5 in the primary ink, Spacing/8 apart, the browser's own
|
|
171
|
+
* disc marker on a Spacing/24 indent (`Documents list`, 7877:68985). Core's
|
|
172
|
+
* sheet supplies the Spacing/24 above it. */
|
|
173
|
+
.reusability-shared-list {
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-direction: column;
|
|
176
|
+
gap: var(--prizma-spacing-8);
|
|
177
|
+
margin: 0;
|
|
178
|
+
padding: 0 0 0 var(--prizma-spacing-24);
|
|
179
|
+
color: var(--prizma-text-body-800-primary);
|
|
180
|
+
font-family: var(--prizma-headline-family);
|
|
181
|
+
font-size: var(--prizma-headline-h5-font-size);
|
|
182
|
+
font-weight: var(--prizma-headline-h5-font-weight);
|
|
183
|
+
line-height: var(--prizma-headline-h5-line-height);
|
|
184
|
+
letter-spacing: var(--prizma-headline-h5-letter-spacing);
|
|
185
|
+
text-align: left;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.reusability-shared-list > li {
|
|
189
|
+
margin: 0;
|
|
190
|
+
padding: 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* ── The privacy-policy reader ───────────────────────────────────────────────
|
|
194
|
+
* The framed, scrolling document Qualified Signature's viewers draw
|
|
195
|
+
* (`.qualified-signature-document--framed`, DEVIATIONS #QS-n): a hairline
|
|
196
|
+
* frame on radius-small, Spacing/16 inside, Body/M prose with Spacing/12
|
|
197
|
+
* between paragraphs, the dateline first. The frame's `demo_5` draws the text
|
|
198
|
+
* unframed on a 32px gutter; the framed reader is what every document viewer
|
|
199
|
+
* in this package draws (owner call 2026-09-29, "take reference from other
|
|
200
|
+
* screens"), so it is followed here — DEVIATIONS #RU-7.
|
|
201
|
+
*
|
|
202
|
+
* FOUNDATION REQUEST: this is the SECOND module drawing the framed reader.
|
|
203
|
+
* Promote it to `ScreenLayout.css` as `__document` (the #DC-29 / #BC-8 idiom:
|
|
204
|
+
* the third consumer moves the recipe), and both module copies go. */
|
|
205
|
+
.reusability-document {
|
|
206
|
+
flex: 1 1 auto;
|
|
207
|
+
min-height: 0;
|
|
208
|
+
box-sizing: border-box;
|
|
209
|
+
width: 100%;
|
|
210
|
+
overflow-y: auto;
|
|
211
|
+
overscroll-behavior: contain;
|
|
212
|
+
padding: var(--prizma-spacing-16);
|
|
213
|
+
margin-bottom: var(--prizma-spacing-16);
|
|
214
|
+
background-color: var(--prizma-surface-neutral-0);
|
|
215
|
+
border: var(--prizma-border-width-regular) solid var(--prizma-border-neutral-100);
|
|
216
|
+
border-radius: var(--prizma-border-radius-small);
|
|
217
|
+
text-align: start;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.reusability-document > * {
|
|
221
|
+
margin: 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.reusability-document > * + * {
|
|
225
|
+
margin-top: var(--prizma-spacing-12);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.reusability-document__meta,
|
|
229
|
+
.reusability-document__prose {
|
|
230
|
+
color: var(--prizma-text-body-800-primary);
|
|
231
|
+
font-family: var(--prizma-body-family);
|
|
232
|
+
font-size: var(--prizma-body-m-regular-font-size);
|
|
233
|
+
font-weight: var(--prizma-body-m-regular-font-weight);
|
|
234
|
+
line-height: var(--prizma-body-m-regular-line-height);
|
|
235
|
+
letter-spacing: var(--prizma-body-m-regular-letter-spacing);
|
|
236
|
+
text-align: left;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.reusability-document__meta {
|
|
240
|
+
color: var(--prizma-text-body-500-secondary);
|
|
241
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { type ReactNode } from 'react';
|
|
2
|
+
import { type PrizmaListScreenProps } from './ListScreen';
|
|
3
|
+
import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
|
|
4
|
+
import type { ReusabilityStrings } from './ReusabilityStrings';
|
|
5
|
+
import './ScreenLayout.css';
|
|
6
|
+
import './ReusabilityLayout.css';
|
|
7
|
+
export interface ReusabilityPrivacyPolicyScreenProps extends Omit<PrizmaListScreenProps, 'status' | 'title' | 'subtitle' | 'glyph' | 'children' | 'listAlign' | 'scrollList' | 'disclaimer' | 'ctaLabel' | 'secondaryCtaLabel' | 'linkLabel' | 'secondaryLinkLabel' | 'overlay' | 'verifiedLabel' | 'navLabel'> {
|
|
8
|
+
/** Module copy — this screen reads the `privacyPolicy` slice. */
|
|
9
|
+
strings: ReusabilityStrings;
|
|
10
|
+
/**
|
|
11
|
+
* The policy itself. HOST-supplied content, never module copy — the same
|
|
12
|
+
* slot contract Qualified Signature's document viewers use for the contract
|
|
13
|
+
* page (GUIDELINES §10): paragraphs in `.reusability-document__prose`, the
|
|
14
|
+
* dateline in `.reusability-document__meta`. The host supplies it in the
|
|
15
|
+
* session's language; it is legal text and is never machine translated.
|
|
16
|
+
*/
|
|
17
|
+
body?: ReactNode;
|
|
18
|
+
screenId?: string;
|
|
19
|
+
overrides?: PrizmaScreenOverrides;
|
|
20
|
+
onAction?: PrizmaScreenActionHandler;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Reusability (Incode Bridge) — Incode's privacy policy, read inside the flow.
|
|
24
|
+
* Built on the List archetype (GUIDELINES.md §6-G), the way Qualified
|
|
25
|
+
* Signature's document viewers are: the `__list` middle is "content filling the
|
|
26
|
+
* space between the title block and the CTA band", which is what a document is,
|
|
27
|
+
* and the band carries one full-width button.
|
|
28
|
+
*
|
|
29
|
+
* Figma: `demo_5` (7877:68997), the frame the "Incode’s Privacy Policy" link
|
|
30
|
+
* opens — the Demo App's terms layout re-used: the Incode logo top-LEFT on a
|
|
31
|
+
* 32px gutter, "Last Modified: August 5, 2024", the policy as an unframed wall
|
|
32
|
+
* of Body/M text, and a raised white band with "Done".
|
|
33
|
+
*
|
|
34
|
+
* Three deltas from that frame, all the system's (DEVIATIONS #RU-7):
|
|
35
|
+
* 1. The nav is the archetype's — logo centred, no close — and the document
|
|
36
|
+
* sits on the column's 24px gutter like every screen in this package
|
|
37
|
+
* (GUIDELINES §3, §5). The frame's left logo and 32 gutter are the Demo
|
|
38
|
+
* App's chrome, not a module's.
|
|
39
|
+
* 2. The frame draws no heading. GUIDELINES §4 gives every screen exactly one
|
|
40
|
+
* H2 and G has no title-less path (the same delta QS's `viewdoc` records),
|
|
41
|
+
* so the screen carries the link's own label as its title.
|
|
42
|
+
* 3. The policy scrolls inside the framed reader every document viewer here
|
|
43
|
+
* draws (`.reusability-document`, the QS recipe), not unframed to the
|
|
44
|
+
* frame's edge; the title, the button and the tag hold still while it pans.
|
|
45
|
+
*
|
|
46
|
+
* The policy is the host's (`body`), like QS's contract page: the SDK owns no
|
|
47
|
+
* legal text and translates none — the host supplies the document in the
|
|
48
|
+
* session's language. "Done" is the frame's primary and emits `cta`: it
|
|
49
|
+
* closes the policy and returns to the selection, where nothing has changed. On the Web SDK this
|
|
50
|
+
* link opens the policy in a NEW TAB instead (`identityReuse.opensInNewTab`);
|
|
51
|
+
* this screen is the in-flow reading the frame draws, which is what a native
|
|
52
|
+
* host presents.
|
|
53
|
+
*/
|
|
54
|
+
export declare const ReusabilityPrivacyPolicyScreen: React.ForwardRefExoticComponent<ReusabilityPrivacyPolicyScreenProps & React.RefAttributes<HTMLDivElement>>;
|
|
55
|
+
export default ReusabilityPrivacyPolicyScreen;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { PrizmaListScreen } from './ListScreen';
|
|
5
|
+
import './ScreenLayout.css';
|
|
6
|
+
import './ReusabilityLayout.css';
|
|
7
|
+
/**
|
|
8
|
+
* Reusability (Incode Bridge) — Incode's privacy policy, read inside the flow.
|
|
9
|
+
* Built on the List archetype (GUIDELINES.md §6-G), the way Qualified
|
|
10
|
+
* Signature's document viewers are: the `__list` middle is "content filling the
|
|
11
|
+
* space between the title block and the CTA band", which is what a document is,
|
|
12
|
+
* and the band carries one full-width button.
|
|
13
|
+
*
|
|
14
|
+
* Figma: `demo_5` (7877:68997), the frame the "Incode’s Privacy Policy" link
|
|
15
|
+
* opens — the Demo App's terms layout re-used: the Incode logo top-LEFT on a
|
|
16
|
+
* 32px gutter, "Last Modified: August 5, 2024", the policy as an unframed wall
|
|
17
|
+
* of Body/M text, and a raised white band with "Done".
|
|
18
|
+
*
|
|
19
|
+
* Three deltas from that frame, all the system's (DEVIATIONS #RU-7):
|
|
20
|
+
* 1. The nav is the archetype's — logo centred, no close — and the document
|
|
21
|
+
* sits on the column's 24px gutter like every screen in this package
|
|
22
|
+
* (GUIDELINES §3, §5). The frame's left logo and 32 gutter are the Demo
|
|
23
|
+
* App's chrome, not a module's.
|
|
24
|
+
* 2. The frame draws no heading. GUIDELINES §4 gives every screen exactly one
|
|
25
|
+
* H2 and G has no title-less path (the same delta QS's `viewdoc` records),
|
|
26
|
+
* so the screen carries the link's own label as its title.
|
|
27
|
+
* 3. The policy scrolls inside the framed reader every document viewer here
|
|
28
|
+
* draws (`.reusability-document`, the QS recipe), not unframed to the
|
|
29
|
+
* frame's edge; the title, the button and the tag hold still while it pans.
|
|
30
|
+
*
|
|
31
|
+
* The policy is the host's (`body`), like QS's contract page: the SDK owns no
|
|
32
|
+
* legal text and translates none — the host supplies the document in the
|
|
33
|
+
* session's language. "Done" is the frame's primary and emits `cta`: it
|
|
34
|
+
* closes the policy and returns to the selection, where nothing has changed. On the Web SDK this
|
|
35
|
+
* link opens the policy in a NEW TAB instead (`identityReuse.opensInNewTab`);
|
|
36
|
+
* this screen is the in-flow reading the frame draws, which is what a native
|
|
37
|
+
* host presents.
|
|
38
|
+
*/
|
|
39
|
+
export const ReusabilityPrivacyPolicyScreen = forwardRef(({ strings, body, screenId = 'reusability-privacy-policy', overrides, onAction, ...shell }, ref) => {
|
|
40
|
+
const { privacyPolicy } = strings;
|
|
41
|
+
return (_jsx(PrizmaListScreen, { ref: ref, title: privacyPolicy.title, ctaLabel: privacyPolicy.ctaLabel, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell, children: _jsx("div", { className: "reusability-document", role: "region", "aria-label": privacyPolicy.title, tabIndex: 0, children: body }) }));
|
|
42
|
+
});
|
|
43
|
+
ReusabilityPrivacyPolicyScreen.displayName = 'ReusabilityPrivacyPolicyScreen';
|
|
44
|
+
export default ReusabilityPrivacyPolicyScreen;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** The document types the identity-reuse backend returns. The SDK's own
|
|
2
|
+
* vocabulary (`identityReuse.documentType.*`). */
|
|
3
|
+
export type ReusabilityDocumentType = 'passport' | 'idCard' | 'driversLicense';
|
|
4
|
+
/**
|
|
5
|
+
* One reusable credential, as the backend describes it — DATA, not copy. The
|
|
6
|
+
* host formats the date (the SDK composes "Verified" + an `Intl` short date
|
|
7
|
+
* client-side, `identity-reuse.tsx` `formatVerifiedAt`) and masks the number.
|
|
8
|
+
*/
|
|
9
|
+
export interface ReusableCredential {
|
|
10
|
+
/** Stable id the host submits back on selection. */
|
|
11
|
+
id: string;
|
|
12
|
+
documentType: ReusabilityDocumentType;
|
|
13
|
+
/** ISO 3166-1 alpha-2. Resolves to Core's flag raster bank
|
|
14
|
+
* (`PrizmaCountryFlag`, 24×18); a country outside the bundled bank falls back
|
|
15
|
+
* to `countryFlag`. */
|
|
16
|
+
countryCode: string;
|
|
17
|
+
/** Emoji fallback for a country the raster bank does not carry — Core's own
|
|
18
|
+
* fallback rule for the Combined input and the Document List card. */
|
|
19
|
+
countryFlag?: string;
|
|
20
|
+
/** Already masked by the backend ("MP1******3815"). */
|
|
21
|
+
maskedNumber: string;
|
|
22
|
+
/** Already formatted by the host ("Apr 2023"). Rendered after
|
|
23
|
+
* `selection.verifiedPrefix`. */
|
|
24
|
+
verifiedOn: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ReusabilityStrings {
|
|
27
|
+
/** "verified by" attribution in the footer tag. */
|
|
28
|
+
verifiedLabel: string;
|
|
29
|
+
/** Accessible name for the logo nav row. */
|
|
30
|
+
navLabel?: string;
|
|
31
|
+
/** The `doc selection` frames — the one screen of the module. */
|
|
32
|
+
selection: {
|
|
33
|
+
/** H2 ("Share your details for a faster verification"). */
|
|
34
|
+
title: string;
|
|
35
|
+
/** H5 under the title. The frame's recipient placeholder is `{Company B}`;
|
|
36
|
+
* the SDK interpolates `{{companyName}}` (`identityReuse.subtitleWithCompany`). */
|
|
37
|
+
subtitle: string;
|
|
38
|
+
/** Accessible name of the option list. */
|
|
39
|
+
listLabel: string;
|
|
40
|
+
/** The document-type label on each credential row ("Passport"). */
|
|
41
|
+
documentType: Record<ReusabilityDocumentType, string>;
|
|
42
|
+
/** The pill on the first row — the backend orders the list best match
|
|
43
|
+
* first, and the first is tagged ("Recommended"). */
|
|
44
|
+
recommendedTag: string;
|
|
45
|
+
/** The word before the formatted date on each row ("Verified"). The SDK
|
|
46
|
+
* translates only this word and appends the date locally. */
|
|
47
|
+
verifiedPrefix: string;
|
|
48
|
+
/** The last row — capture a document instead of reusing one. */
|
|
49
|
+
scanNewLabel: string;
|
|
50
|
+
/** The pill on that row ("Slowest"). */
|
|
51
|
+
slowestTag: string;
|
|
52
|
+
/** First tertiary link under the list ("What data will be shared?"):
|
|
53
|
+
* opens the shared-details sheet. */
|
|
54
|
+
sharedDataLink: string;
|
|
55
|
+
/** Second tertiary link ("Incode’s Privacy Policy"): opens the policy. */
|
|
56
|
+
privacyPolicyLink: string;
|
|
57
|
+
};
|
|
58
|
+
/** The `shared info` frame — Core's bottom sheet over the selection. */
|
|
59
|
+
sharedDetails: {
|
|
60
|
+
/** Sheet heading, Core's H1 ("Shared details"). */
|
|
61
|
+
title: string;
|
|
62
|
+
/** Under the heading ("Only the following information will be shared with
|
|
63
|
+
* {Company B}."). */
|
|
64
|
+
subtitle: string;
|
|
65
|
+
/** The bullet list — what the recipient asked for. In production these
|
|
66
|
+
* come from the recipient's data-sharing request (ENG-57939 acceptance
|
|
67
|
+
* criteria), so the list is host data rendered through this slot. */
|
|
68
|
+
items: string[];
|
|
69
|
+
/** The sheet's one button ("Understood"). */
|
|
70
|
+
ctaLabel: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The `demo_5` frame — Incode's privacy policy, read inside the flow. The
|
|
74
|
+
* document ITSELF is not here: it is host content (the policy at
|
|
75
|
+
* incode.com/privacy, in the host's language), supplied through the screen's
|
|
76
|
+
* `body` slot the way Qualified Signature's viewers take their contract.
|
|
77
|
+
*/
|
|
78
|
+
privacyPolicy: {
|
|
79
|
+
/** H2 the archetype requires; the frame draws none (DEVIATIONS #RU-7).
|
|
80
|
+
* The link's own label ("Incode’s Privacy Policy") is the natural title. */
|
|
81
|
+
title: string;
|
|
82
|
+
/** Primary under the document ("Done"): back to the selection. */
|
|
83
|
+
ctaLabel: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Reusability (Incode Bridge) — copy contract.
|
|
2
|
+
//
|
|
3
|
+
// The credential-reuse step of an Incode Bridge session: a returning person
|
|
4
|
+
// who already verified with another member of the network is offered the
|
|
5
|
+
// document they verified there, so they can skip ID capture at the company
|
|
6
|
+
// they are onboarding with now. The SDK module is `identity-reuse`
|
|
7
|
+
// (`incode-identity-reuse`, i18n namespace `identityReuse`); the product name
|
|
8
|
+
// is Incode Bridge; the design file calls it Reusability. Bridge is NOT Trust
|
|
9
|
+
// Graph: it moves the person's own credential, with their consent, to remove
|
|
10
|
+
// friction — it makes no fraud claim (MVP spec, Notion, 2026-08-17).
|
|
11
|
+
//
|
|
12
|
+
// Figma: `Reusability - In Experimentation` (f4AsCbOBP29IbTQLxBNgNG), section
|
|
13
|
+
// `Reusability Iterations` (7877:68814) — the iteration Camila shared with the
|
|
14
|
+
// Identity team on 2026-09-19 and that the Web SDK built as ENG-57939 (Dusan,
|
|
15
|
+
// PR #1021, "one-click credential selection with shared-data sheet"). Four
|
|
16
|
+
// frames:
|
|
17
|
+
// · 7877:68816 `doc selection` Multiple documents — two reusable passports
|
|
18
|
+
// and the "Scan a new document" row
|
|
19
|
+
// · 7877:68875 `doc selection` Single document — one passport and the row
|
|
20
|
+
// · 7877:68927 `shared info` Shared data — Core's bottom sheet over the
|
|
21
|
+
// selection listing what will be shared
|
|
22
|
+
// · 7877:68997 `demo_5` Privacy Policy — Incode's policy, read in
|
|
23
|
+
// the flow, Done at the bottom
|
|
24
|
+
//
|
|
25
|
+
// Two product decisions shape the copy (consent review with legal, Granola
|
|
26
|
+
// 2026-09-16; Vlado, #reusability 2026-09-15):
|
|
27
|
+
// 1. The subtitle says WHO holds the data and that Incode only passes it:
|
|
28
|
+
// "A company you previously verified with holds a document you can reuse.
|
|
29
|
+
// Incode only passes it to {Company B}." The donor is never named (it may
|
|
30
|
+
// be a regulated entity); the recipient is.
|
|
31
|
+
// 2. Selecting a document ADVANCES — no confirm button. A mis-tap is
|
|
32
|
+
// recovered with the nav's way back, not with a second step.
|
|
33
|
+
//
|
|
34
|
+
// No hardcoded English anywhere in a screen: every visible string arrives
|
|
35
|
+
// here, so the host's locale pack drives the module. The SDK's `identityReuse`
|
|
36
|
+
// namespace already carries ES and PT for almost every sentence below.
|
|
37
|
+
export {};
|