@incodetech/prizma-core-screens 0.2.4 โ 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/CurpEnterScreen.d.ts +7 -0
- package/dist/CurpEnterScreen.js +17 -3
- package/dist/CurpGenerateScreen.d.ts +8 -0
- package/dist/CurpGenerateScreen.js +28 -13
- package/dist/CurpLayout.css +8 -34
- package/dist/CurpStrings.d.ts +16 -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/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/EkybAddressDetailsScreen.d.ts +7 -0
- package/dist/EkybAddressDetailsScreen.js +25 -7
- package/dist/EkybBusinessDetailsScreen.d.ts +6 -0
- package/dist/EkybBusinessDetailsScreen.js +23 -6
- package/dist/EkybCountryScreen.d.ts +13 -5
- package/dist/EkybCountryScreen.js +41 -10
- package/dist/EkybOwnersScreen.d.ts +8 -0
- package/dist/EkybOwnersScreen.js +26 -3
- package/dist/EkybStrings.d.ts +32 -10
- package/dist/EkycCountryCatalog.d.ts +4 -1
- package/dist/EkycCountryCatalog.js +5 -3
- package/dist/EkycCountryFormScreen.d.ts +12 -3
- package/dist/EkycCountryFormScreen.js +28 -10
- package/dist/EkycDetailsScreen.d.ts +7 -0
- package/dist/EkycDetailsScreen.js +21 -4
- package/dist/EkycStrings.d.ts +14 -2
- package/dist/ElectronicSignatureLayout.css +6 -0
- package/dist/EmailInputStrings.d.ts +11 -1
- package/dist/EmailInputVerifyScreen.d.ts +7 -0
- package/dist/EmailInputVerifyScreen.js +17 -3
- 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/FaceMatchComparisonScreen.d.ts +3 -3
- package/dist/FaceMatchLayout.css +21 -12
- package/dist/FormScreen.css +30 -0
- package/dist/FormScreen.d.ts +28 -0
- package/dist/FormScreen.js +3 -2
- package/dist/FormsLongFormScreen.d.ts +8 -0
- package/dist/FormsLongFormScreen.js +34 -13
- package/dist/FormsStrings.d.ts +11 -1
- package/dist/GeolocationBrowserStepsScreen.d.ts +6 -2
- package/dist/GeolocationBrowserStepsScreen.js +7 -3
- package/dist/GeolocationStrings.d.ts +3 -0
- package/dist/IdCaptureLayout.css +205 -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 +21 -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/PhoneInputLayout.css +10 -9
- package/dist/PhoneInputOtpScreen.d.ts +8 -0
- package/dist/PhoneInputOtpScreen.js +26 -19
- package/dist/PhoneInputStrings.d.ts +22 -4
- package/dist/PhoneInputVerifyScreen.d.ts +8 -0
- package/dist/PhoneInputVerifyScreen.js +36 -7
- package/dist/QualifiedSignatureAcceptScreen.js +6 -1
- package/dist/QualifiedSignatureDocumentScreen.d.ts +17 -10
- package/dist/QualifiedSignatureDocumentScreen.js +22 -17
- package/dist/QualifiedSignatureLayout.css +76 -0
- package/dist/QualifiedSignatureResultScreen.d.ts +16 -13
- package/dist/QualifiedSignatureResultScreen.js +17 -18
- package/dist/QualifiedSignatureStrings.d.ts +19 -2
- 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/ScreenNav.css +8 -0
- package/dist/ScreenNav.d.ts +15 -2
- package/dist/ScreenNav.js +10 -3
- package/dist/VideoSelfieErrorScreen.js +1 -1
- package/dist/VideoSelfieIdCaptureScreen.d.ts +10 -3
- package/dist/VideoSelfieIdCaptureScreen.js +45 -14
- package/dist/VideoSelfieLayout.css +467 -34
- package/dist/VideoSelfieSelfieCaptureScreen.d.ts +44 -27
- package/dist/VideoSelfieSelfieCaptureScreen.js +65 -39
- package/dist/VideoSelfieSpeakScreen.js +19 -2
- package/dist/VideoSelfieStrings.d.ts +82 -13
- package/dist/VideoSelfieTurnHeadScreen.d.ts +51 -0
- package/dist/VideoSelfieTurnHeadScreen.js +66 -0
- package/dist/VideoSelfieTutorialScreen.d.ts +9 -0
- package/dist/VideoSelfieTutorialScreen.js +22 -5
- package/dist/VideoSelfieWaveScreen.d.ts +53 -0
- package/dist/VideoSelfieWaveScreen.js +62 -0
- package/dist/ViewfinderScreen.css +36 -0
- package/dist/WatchlistBusinessFormScreen.d.ts +11 -7
- package/dist/WatchlistBusinessFormScreen.js +27 -13
- package/dist/WatchlistBusinessStrings.d.ts +21 -7
- package/dist/flows.d.ts +8 -0
- package/dist/flows.js +17 -0
- package/dist/index.d.ts +19 -1
- package/dist/index.js +14 -0
- package/dist/styles.css +3 -0
- package/dist/types.d.ts +3 -1
- package/package.json +79 -3
- package/samples/video-selfie-camera-wide.jpg +0 -0
- package/samples/video-selfie-room-wide.jpg +0 -0
- package/samples/video-selfie-room.png +0 -0
- package/src/BiometricConsentScreen.tsx +192 -0
- package/src/BiometricConsentStrings.ts +119 -0
- package/src/CaptureScreen.tsx +17 -0
- package/src/CurpEnterScreen.tsx +21 -4
- package/src/CurpGenerateScreen.tsx +46 -22
- package/src/CurpLayout.css +8 -34
- package/src/CurpStrings.ts +22 -2
- package/src/DemoScreensLayout.css +16 -0
- package/src/DemoScreensRedirectScreen.tsx +14 -6
- package/src/DemoScreensStrings.ts +5 -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/EkybAddressDetailsScreen.tsx +32 -4
- package/src/EkybBusinessDetailsScreen.tsx +23 -5
- package/src/EkybCountryScreen.tsx +45 -7
- package/src/EkybOwnersScreen.tsx +34 -3
- package/src/EkybStrings.ts +34 -10
- package/src/EkycCountryCatalog.ts +9 -4
- package/src/EkycCountryFormScreen.tsx +51 -12
- package/src/EkycDetailsScreen.tsx +22 -1
- package/src/EkycStrings.ts +14 -2
- package/src/ElectronicSignatureLayout.css +6 -0
- package/src/EmailInputStrings.ts +12 -1
- package/src/EmailInputVerifyScreen.tsx +21 -4
- 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/FaceMatchComparisonScreen.tsx +3 -3
- package/src/FaceMatchLayout.css +21 -12
- package/src/FormScreen.css +30 -0
- package/src/FormScreen.tsx +34 -0
- package/src/FormsLongFormScreen.tsx +41 -13
- package/src/FormsStrings.ts +12 -1
- package/src/GeolocationBrowserStepsScreen.tsx +6 -3
- package/src/GeolocationStrings.ts +3 -0
- package/src/IdCaptureLayout.css +205 -2
- package/src/IdCaptureStageScreen.tsx +75 -0
- package/src/IdCaptureStrings.ts +19 -0
- package/src/ListScreen.tsx +58 -10
- 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/PhoneInputLayout.css +10 -9
- package/src/PhoneInputOtpScreen.tsx +23 -3
- package/src/PhoneInputStrings.ts +23 -4
- package/src/PhoneInputVerifyScreen.tsx +41 -5
- package/src/QualifiedSignatureAcceptScreen.tsx +12 -1
- package/src/QualifiedSignatureDocumentScreen.tsx +31 -19
- package/src/QualifiedSignatureLayout.css +76 -0
- package/src/QualifiedSignatureResultScreen.tsx +28 -26
- package/src/QualifiedSignatureStrings.ts +19 -2
- 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/ScreenNav.css +8 -0
- package/src/ScreenNav.tsx +35 -5
- package/src/VideoSelfieErrorScreen.tsx +1 -1
- package/src/VideoSelfieIdCaptureScreen.tsx +125 -31
- package/src/VideoSelfieLayout.css +467 -34
- package/src/VideoSelfieSelfieCaptureScreen.tsx +110 -57
- package/src/VideoSelfieSpeakScreen.tsx +34 -15
- package/src/VideoSelfieStrings.ts +89 -14
- package/src/VideoSelfieTurnHeadScreen.tsx +162 -0
- package/src/VideoSelfieTutorialScreen.tsx +45 -23
- package/src/VideoSelfieWaveScreen.tsx +143 -0
- package/src/ViewfinderScreen.css +36 -0
- package/src/WatchlistBusinessFormScreen.tsx +35 -16
- package/src/WatchlistBusinessStrings.ts +21 -7
- package/src/flows.ts +25 -0
- package/src/index.ts +88 -3
- package/src/styles.css +3 -0
- package/src/types.ts +3 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { PrizmaBottomSheetContent } from '@incodetech/prizma-core-web/bottom-sheet';
|
|
5
|
+
import { PrizmaModalContent } from '@incodetech/prizma-core-web/modal';
|
|
6
|
+
import { PrizmaScreenShell } from './ScreenShell';
|
|
7
|
+
import './ScreenLayout.css';
|
|
8
|
+
import './PermissionsLayout.css';
|
|
9
|
+
/**
|
|
10
|
+
* Permissions โ the pre-permission sheet, "Allow camera access".
|
|
11
|
+
*
|
|
12
|
+
* Figma: `1-3-1-id-permission-modal` (qGJjfL4O0JSjz1x4tOjJn8), the first frame
|
|
13
|
+
* of all three full-flow boards (Web 3:620, iOS 3:7788, Android 4:11304). It is
|
|
14
|
+
* the SDK's own sheet, not the browser's prompt: Core's Bottom Sheet `dialog`
|
|
15
|
+
* (handle, title, supporting line) carrying a horizontal Button Group with
|
|
16
|
+
* "Don't allow" (secondary) left of "Allow" (primary), which is
|
|
17
|
+
* `horizontal-v1`'s order. "Allow" is what raises the real OS prompt.
|
|
18
|
+
*
|
|
19
|
+
* On desktop (`presentation="dialog"`) the same ask is Core's Modal `default`
|
|
20
|
+
* variant, centred over the scrim the way NFC's settings dialog is: Core
|
|
21
|
+
* renders the card and its Button Group (its own `vertical-v1` default, Allow
|
|
22
|
+
* over Don't allow), the screen adds only the scrim and the centring. No close
|
|
23
|
+
* icon: the two buttons are the only answers the ask has.
|
|
24
|
+
*
|
|
25
|
+
* Nothing is drawn behind the sheet: every board shows the sheet over an empty
|
|
26
|
+
* frame, so the screen is the scrim alone. Same scrim + panel split as
|
|
27
|
+
* Document Capture's method sheet (#DC-30).
|
|
28
|
+
*/
|
|
29
|
+
export const PermissionsAskScreen = forwardRef(({ strings, presentation = 'sheet', screenId = presentation === 'dialog' ? 'permissions-ask-dialog' : 'permissions-ask', onAction, ...shell }, ref) => (_jsxs(PrizmaScreenShell, { ref: ref, "data-screen-id": screenId, "data-pcs-overlay": presentation === 'dialog' ? 'window' : undefined, ...shell, children: [_jsx("div", { className: "permissions-sheet-scrim", "aria-hidden": "true" }), presentation === 'dialog' ? (_jsx("div", { className: "permissions-dialog-panel", children: _jsx(PrizmaModalContent, { title: strings.ask.title, subtitle: strings.ask.subtitle, showCloseIcon: false, buttonGroupProps: {
|
|
30
|
+
primaryLabel: strings.ask.allowLabel,
|
|
31
|
+
secondaryLabel: strings.ask.denyLabel,
|
|
32
|
+
onPrimaryClick: () => onAction?.({ type: 'cta', screenId }),
|
|
33
|
+
onSecondaryClick: () => onAction?.({ type: 'secondary', screenId }),
|
|
34
|
+
} }) })) : (_jsx("div", { className: "permissions-sheet-panel", children: _jsx(PrizmaBottomSheetContent, { variant: "dialog", ariaLabel: strings.ask.title, title: strings.ask.title, subtitle: strings.ask.subtitle, buttonGroupProps: {
|
|
35
|
+
orientation: 'horizontal-v1',
|
|
36
|
+
primaryLabel: strings.ask.allowLabel,
|
|
37
|
+
secondaryLabel: strings.ask.denyLabel,
|
|
38
|
+
showTertiary: false,
|
|
39
|
+
onPrimaryClick: () => onAction?.({ type: 'cta', screenId }),
|
|
40
|
+
onSecondaryClick: () => onAction?.({ type: 'secondary', screenId }),
|
|
41
|
+
} }) }))] })));
|
|
42
|
+
PermissionsAskScreen.displayName = 'PermissionsAskScreen';
|
|
43
|
+
export default PermissionsAskScreen;
|
|
@@ -18,15 +18,22 @@ export interface PermissionsBrowserStepsScreenProps extends Omit<PrizmaListScree
|
|
|
18
18
|
*
|
|
19
19
|
* Figma: `1-4-2-id` of the `Permissions` section, plus the four
|
|
20
20
|
* `Android browsers` frames of the Web full-flow board (4:8159 โ Chrome,
|
|
21
|
-
* Firefox, Samsung Internet, Opera).
|
|
21
|
+
* Firefox, Samsung Internet, Opera). The browser set and every step path are
|
|
22
|
+
* Geolocation's (`GeolocationBrowserStepsScreen`), nine browsers, with the
|
|
23
|
+
* camera in place of the location. ONE screen for all of them: they draw the
|
|
22
24
|
* identical skeleton โ title block โ a step list filling the middle โ the
|
|
23
25
|
* refresh CTA โ and differ only in the rows, because re-enabling the camera is
|
|
24
|
-
* a different journey in each browser.
|
|
26
|
+
* a different journey in each browser. Nine files would have been nine chances
|
|
25
27
|
* to drift.
|
|
26
28
|
*
|
|
27
29
|
* The rows are Core's `PrizmaCardListCommonIssues` verbatim; only the leading
|
|
28
30
|
* glyph is chosen here, from the canonical bank (see `STEP_ICONS`).
|
|
29
31
|
*
|
|
32
|
+
* No subtitle: none of the frames draws the browser name under the title,
|
|
33
|
+
* and the same call was made for Geolocation's step lists (owner call, Elena
|
|
34
|
+
* 2026-09-30). `label` stays in the strings as the section's identifier for
|
|
35
|
+
* hosts and catalogs; the screen itself shows title + steps.
|
|
36
|
+
*
|
|
30
37
|
* The title block is LEFT-aligned for this whole family. Every frame starts the
|
|
31
38
|
* two-line headline flush at the gutter over left-led step rows; a centred
|
|
32
39
|
* headline above a left-aligned list reads as a mistake. The screen therefore
|
|
@@ -15,6 +15,7 @@ import './ScreenLayout.css';
|
|
|
15
15
|
* both forbidden (rule 1, GUIDELINES ยง10), so each row takes the nearest
|
|
16
16
|
* canonical glyph:
|
|
17
17
|
*
|
|
18
|
+
* addressBar โ IconTextAi the address bar's page / site control
|
|
18
19
|
* settings โ IconLock site settings sit behind the address-bar lock
|
|
19
20
|
* browser โ IconTextAi Safari's "AA" is the address-bar text control
|
|
20
21
|
* menu โ IconNumberedList the โฎ overflow opens a menu list
|
|
@@ -31,6 +32,7 @@ import './ScreenLayout.css';
|
|
|
31
32
|
* glyphs or bless the substitutions โ one decision covers both families.
|
|
32
33
|
*/
|
|
33
34
|
const STEP_ICONS = {
|
|
35
|
+
addressBar: _jsx(IconTextAi, { size: "m" }),
|
|
34
36
|
settings: _jsx(IconLock, { size: "m" }),
|
|
35
37
|
browser: _jsx(IconTextAi, { size: "m" }),
|
|
36
38
|
menu: _jsx(IconNumberedList, { size: "m" }),
|
|
@@ -47,15 +49,22 @@ const STEP_ICONS = {
|
|
|
47
49
|
*
|
|
48
50
|
* Figma: `1-4-2-id` of the `Permissions` section, plus the four
|
|
49
51
|
* `Android browsers` frames of the Web full-flow board (4:8159 โ Chrome,
|
|
50
|
-
* Firefox, Samsung Internet, Opera).
|
|
52
|
+
* Firefox, Samsung Internet, Opera). The browser set and every step path are
|
|
53
|
+
* Geolocation's (`GeolocationBrowserStepsScreen`), nine browsers, with the
|
|
54
|
+
* camera in place of the location. ONE screen for all of them: they draw the
|
|
51
55
|
* identical skeleton โ title block โ a step list filling the middle โ the
|
|
52
56
|
* refresh CTA โ and differ only in the rows, because re-enabling the camera is
|
|
53
|
-
* a different journey in each browser.
|
|
57
|
+
* a different journey in each browser. Nine files would have been nine chances
|
|
54
58
|
* to drift.
|
|
55
59
|
*
|
|
56
60
|
* The rows are Core's `PrizmaCardListCommonIssues` verbatim; only the leading
|
|
57
61
|
* glyph is chosen here, from the canonical bank (see `STEP_ICONS`).
|
|
58
62
|
*
|
|
63
|
+
* No subtitle: none of the frames draws the browser name under the title,
|
|
64
|
+
* and the same call was made for Geolocation's step lists (owner call, Elena
|
|
65
|
+
* 2026-09-30). `label` stays in the strings as the section's identifier for
|
|
66
|
+
* hosts and catalogs; the screen itself shows title + steps.
|
|
67
|
+
*
|
|
59
68
|
* The title block is LEFT-aligned for this whole family. Every frame starts the
|
|
60
69
|
* two-line headline flush at the gutter over left-led step rows; a centred
|
|
61
70
|
* headline above a left-aligned list reads as a mistake. The screen therefore
|
|
@@ -76,7 +85,7 @@ export const PermissionsBrowserStepsScreen = forwardRef(({ strings, browser = 's
|
|
|
76
85
|
...overrides,
|
|
77
86
|
align: overrides?.align ?? 'left',
|
|
78
87
|
};
|
|
79
|
-
return (_jsx(PrizmaListScreen, { ref: ref, showHeader: showHeader, title: strings.browserSteps.title,
|
|
88
|
+
return (_jsx(PrizmaListScreen, { ref: ref, showHeader: showHeader, title: strings.browserSteps.title, ctaLabel: strings.browserSteps.ctaLabel, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: alignedOverrides, onAction: onAction, ...shell, children: _jsx(PrizmaCardListCommonIssues, { items: (slice?.steps ?? []).map((step) => ({
|
|
80
89
|
icon: STEP_ICONS[step.kind],
|
|
81
90
|
title: step.label,
|
|
82
91
|
showSubtitle: false,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* Permissions โ the pre-permission sheet (`PermissionsAskScreen`).
|
|
2
|
+
*
|
|
3
|
+
* Same idiom as Document Capture's method sheet (DEVIATIONS #DC-30): Core's
|
|
4
|
+
* `PrizmaBottomSheetContent` owns the panel (handle, radius, padding, title,
|
|
5
|
+
* button group); the screen owns the scrim, because the safe presenter portals
|
|
6
|
+
* to `document.body` and would escape the 390 ร 844 frame. The scrim drinks
|
|
7
|
+
* Core's own `Surface/Overlay` token. No animation: a screen is one static
|
|
8
|
+
* spec state. */
|
|
9
|
+
.permissions-sheet-scrim {
|
|
10
|
+
position: absolute;
|
|
11
|
+
inset: 0;
|
|
12
|
+
z-index: 1;
|
|
13
|
+
background: var(--prizma-surface-overlay);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.permissions-sheet-panel {
|
|
17
|
+
position: absolute;
|
|
18
|
+
left: 0;
|
|
19
|
+
right: 0;
|
|
20
|
+
bottom: 0;
|
|
21
|
+
z-index: 2;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* The frame's `System UI Bottom Bar` (34) sits INSIDE the sheet. Core reserves
|
|
25
|
+
* it as `env(safe-area-inset-bottom, var(--prizma-sheet-size-safe-area))`, but
|
|
26
|
+
* a browser defines the inset as 0 on a flat screen, so the fallback never
|
|
27
|
+
* applies and the CTAs drop to 12px off the frame's bottom. Screens in this
|
|
28
|
+
* package reserve device chrome as fixed values (`--pcs-status-bar`), so the
|
|
29
|
+
* sheet takes Core's own Sheet/Size/Safe-area token directly here. */
|
|
30
|
+
.permissions-sheet-panel .prizma-bottom-sheet__safe-area {
|
|
31
|
+
height: var(--prizma-sheet-size-safe-area);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Desktop: the same ask as Core's centred Modal (`presentation="dialog"`).
|
|
35
|
+
* Same split as NFC's settings dialog: Core's `PrizmaModalContent` is the card
|
|
36
|
+
* (width 100% up to its own Modal/Size/Max-width), this only centres it with
|
|
37
|
+
* the Spacing/12 gutter. */
|
|
38
|
+
.permissions-dialog-panel {
|
|
39
|
+
position: absolute;
|
|
40
|
+
inset: 0;
|
|
41
|
+
z-index: 2;
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
padding-inline: var(--prizma-spacing-12);
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
}
|
|
@@ -11,13 +11,14 @@ export interface PermissionsReasonRow {
|
|
|
11
11
|
description?: string;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* Which browser's "turn it back on" journey to show.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
14
|
+
* Which browser's "turn it back on" journey to show. The SAME nine browsers,
|
|
15
|
+
* keys and order as Geolocation's (`GeolocationBrowser`), because a refused
|
|
16
|
+
* camera and a refused location are the same journey through the same browser
|
|
17
|
+
* settings; only the permission's name changes (Camila, 2026-10-07). The
|
|
18
|
+
* Permissions Figma draws five of them (`1-4-2-id` for Safari plus the four
|
|
19
|
+
* `Android browsers` frames, 4:8159); the other four follow Geolocation.
|
|
19
20
|
*/
|
|
20
|
-
export type PermissionsBrowser = 'safariIos' | 'chromeAndroid' | 'firefoxAndroid' | 'samsungAndroid' | '
|
|
21
|
+
export type PermissionsBrowser = 'safariIos' | 'chromeIos' | 'firefoxIos' | 'operaIos' | 'chromeAndroid' | 'firefoxAndroid' | 'operaAndroid' | 'samsungAndroid' | 'unrecognizedAndroid' | 'chromeDesktop' | 'edgeDesktop' | 'firefoxDesktop' | 'safariMac';
|
|
21
22
|
/**
|
|
22
23
|
* Step kind โ canonical bank glyph, resolved in
|
|
23
24
|
* `PermissionsBrowserStepsScreen`. Figma leads every row with OS/browser chrome
|
|
@@ -28,14 +29,14 @@ export type PermissionsBrowser = 'safariIos' | 'chromeAndroid' | 'firefoxAndroid
|
|
|
28
29
|
* escalated (`GeolocationBrowserStepsScreen`); this family reuses it rather
|
|
29
30
|
* than inventing a second one.
|
|
30
31
|
*/
|
|
31
|
-
export type PermissionsStepKind = 'settings' | 'browser' | 'menu' | 'permissions' | 'camera' | 'toggle' | 'device' | 'apps' | 'return';
|
|
32
|
+
export type PermissionsStepKind = 'addressBar' | 'settings' | 'browser' | 'menu' | 'permissions' | 'camera' | 'toggle' | 'device' | 'apps' | 'return';
|
|
32
33
|
export interface PermissionsStep {
|
|
33
34
|
kind: PermissionsStepKind;
|
|
34
35
|
label: string;
|
|
35
36
|
}
|
|
36
37
|
export interface PermissionsBrowserSteps {
|
|
37
38
|
/** Names the browser under the headline. Figma labels the section, not the
|
|
38
|
-
* screen; the label keeps
|
|
39
|
+
* screen; the label keeps nine otherwise near-identical cards apart. */
|
|
39
40
|
label: string;
|
|
40
41
|
steps: PermissionsStep[];
|
|
41
42
|
}
|
|
@@ -44,6 +45,16 @@ export interface PermissionsStrings {
|
|
|
44
45
|
navLabel?: string;
|
|
45
46
|
/** "verified by" attribution copy for the footer tag. */
|
|
46
47
|
verifiedLabel: string;
|
|
48
|
+
/** `1-3-1-id-permission-modal` โ the pre-permission sheet, the very first
|
|
49
|
+
* ask. Its "Allow" is what raises the real OS prompt. */
|
|
50
|
+
ask: {
|
|
51
|
+
title: string;
|
|
52
|
+
subtitle?: string;
|
|
53
|
+
/** Primary โ raises the OS prompt. */
|
|
54
|
+
allowLabel: string;
|
|
55
|
+
/** Secondary โ declines; the flow moves on to `required`. */
|
|
56
|
+
denyLabel: string;
|
|
57
|
+
};
|
|
47
58
|
/** `1-3-2-id` โ the permission was refused and the flow explains why it needs it. */
|
|
48
59
|
required: {
|
|
49
60
|
title: string;
|
|
@@ -54,7 +65,7 @@ export interface PermissionsStrings {
|
|
|
54
65
|
quitLabel: string;
|
|
55
66
|
ctaLabel: string;
|
|
56
67
|
};
|
|
57
|
-
/** `1-3-2-id-allow-camera` โ the
|
|
68
|
+
/** `1-3-2-id-allow-camera` โ the softer ask after the REAL OS prompt was refused. */
|
|
58
69
|
allow: {
|
|
59
70
|
title: string;
|
|
60
71
|
subtitle?: string;
|
|
@@ -12,20 +12,26 @@
|
|
|
12
12
|
// is the ID Capture-flavoured copy of the same skeleton; it stays where it is so
|
|
13
13
|
// nothing that imports it breaks (DEVIATIONS #IDC-26).
|
|
14
14
|
//
|
|
15
|
-
// The section's seven frames collapse onto
|
|
15
|
+
// The section's seven frames collapse onto FOUR built screens:
|
|
16
16
|
//
|
|
17
|
+
// 1-3-1-id-permission-modal โ PermissionsAskScreen (the sheet)
|
|
17
18
|
// 1-3-2-id โ PermissionsRequiredScreen (reason rows)
|
|
18
19
|
// 1-3-2-id-allow-camera โ PermissionsAllowScreen (subtitle)
|
|
19
20
|
// 1-4-2-id (+ 4 Android siblings) โ PermissionsBrowserStepsScreen
|
|
20
21
|
//
|
|
21
|
-
// The other
|
|
22
|
+
// The other three are OS chrome and are NOT built:
|
|
22
23
|
//
|
|
23
|
-
// 1-3-1-id-permission-modal the browser's own "Allow camera access" sheet
|
|
24
24
|
// 1-4-1-id the iOS "โฆWould Like to Access the Camera" alert
|
|
25
25
|
// 1-3-2-id-quit-process an iOS confirm alert layered over 1-3-2-id
|
|
26
26
|
// 1-3-2-id-allow-camera-quit the same alert layered over the allow screen
|
|
27
27
|
//
|
|
28
|
-
//
|
|
28
|
+
// `1-3-1-id-permission-modal` was on this list until 2026-10-07. It is not the
|
|
29
|
+
// browser's prompt: it is the SDK's own camera pre-permission sheet (the SDK
|
|
30
|
+
// release notes call it "the camera permission sheet", shown by every module
|
|
31
|
+
// that asks for the camera), drawn with Core's Bottom Sheet dialog and Button
|
|
32
|
+
// Group. So it is built, from those two components (DEVIATIONS #GEN-1).
|
|
33
|
+
//
|
|
34
|
+
// None of the remaining three is a Prizma surface: their chrome does not exist in Core and
|
|
29
35
|
// rebuilding it would mean inventing primitives and shipping platform rasters,
|
|
30
36
|
// both forbidden (rule 1, GUIDELINES ยง10). Same call as Document Capture's iOS
|
|
31
37
|
// action sheets (#DC-20) and Geolocation's system alert. Core Lab draws them as
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
align-items: flex-start;
|
|
22
22
|
gap: var(--prizma-spacing-8);
|
|
23
23
|
width: 100%;
|
|
24
|
+
position: relative; /* the country menu's containing block โ see below */
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
/* The dial-code dropdown hugs its content ("๐ท๐ธ +381"), as Figma draws it.
|
|
@@ -47,15 +48,15 @@
|
|
|
47
48
|
min-width: 0;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
/* The open menu
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
51
|
+
/* The open menu spans the WHOLE row (dial code + number field), as Figma's
|
|
52
|
+
* `Input / Combined` draws it: Core anchors the menu overlay to the trigger's
|
|
53
|
+
* `__anchor` (`position: relative`, Dropdown.css), so once the trigger hugs
|
|
54
|
+
* "๐ท๐ธ +381" the menu came out as narrow as the dial code. Releasing the
|
|
55
|
+
* anchor's positioning hands the overlay's `left: 0; right: 0` to the row
|
|
56
|
+
* above (`position: relative`), so the menu matches the row's width exactly.
|
|
57
|
+
* Core's own overlay offset (`top: 100% + Spacing/8`) is left untouched.
|
|
55
58
|
* DEVIATIONS #PI-1 (same root cause as the hug).
|
|
56
59
|
*/
|
|
57
|
-
.phone-input-combined__country .prizma-
|
|
58
|
-
|
|
59
|
-
min-width: 100%;
|
|
60
|
-
max-width: 342px;
|
|
60
|
+
.phone-input-combined__country .prizma-dropdown__anchor {
|
|
61
|
+
position: static;
|
|
61
62
|
}
|
|
@@ -13,6 +13,14 @@ export interface PhoneInputOtpScreenProps extends Omit<PrizmaFormScreenProps, 't
|
|
|
13
13
|
value?: string;
|
|
14
14
|
/** How many digits the code carries. Default 6. */
|
|
15
15
|
length?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Seconds left before the code can be resent. While it is above 0 (and the
|
|
18
|
+
* copy carries `otp.resendCountdownLabel`), the resend line becomes one
|
|
19
|
+
* disabled link, "Resend code in 30s", exactly as Figma draws
|
|
20
|
+
* `phoneNumber.OTP.typing`. The host owns the timer; the screen only draws
|
|
21
|
+
* the number it is given.
|
|
22
|
+
*/
|
|
23
|
+
resendIn?: number;
|
|
16
24
|
screenId?: string;
|
|
17
25
|
overrides?: PrizmaScreenOverrides;
|
|
18
26
|
onAction?: PrizmaScreenActionHandler;
|
|
@@ -21,24 +21,31 @@ import './PhoneInputLayout.css';
|
|
|
21
21
|
* wins; `PrizmaOtp.loading` stays correct for hosts that want the in-field
|
|
22
22
|
* spinner. DEVIATIONS #PI-5.
|
|
23
23
|
*/
|
|
24
|
-
export const PhoneInputOtpScreen = forwardRef(({ strings, state = 'typing', value, length = 6, screenId = `phone-input-otp-${state}`, overrides, onAction, ...shell }, ref) =>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
24
|
+
export const PhoneInputOtpScreen = forwardRef(({ strings, state = 'typing', value, length = 6, resendIn, screenId = `phone-input-otp-${state}`, overrides, onAction, ...shell }, ref) => {
|
|
25
|
+
const counting = (resendIn ?? 0) > 0 && Boolean(strings.otp.resendCountdownLabel);
|
|
26
|
+
return (_jsx(PrizmaFormScreen, { ref: ref, title: strings.otp.title, subtitle: strings.otp.subtitle, ctaLabel: strings.otp.ctaLabel,
|
|
27
|
+
/* Figma greys the CTA until the code is complete. */
|
|
28
|
+
ctaDisabled: state === 'typing',
|
|
29
|
+
/* The spinner rides the CTA, not the field (see the note above). */
|
|
30
|
+
ctaLoading: state === 'processing', ctaLoadingLabel: strings.otp.ctaLoadingLabel,
|
|
31
|
+
/* "Didn't receive the code? Resend code or Change phone number" โ drawn
|
|
32
|
+
under the CTA on every OTP section. ONE sentence, TWO independently
|
|
33
|
+
actionable links, so it uses the archetype's composed-line slot rather
|
|
34
|
+
than `linkLabel` (a full-width 56px button cannot sit inside a line of
|
|
35
|
+
body text, and one button could not tell the two actions apart โ
|
|
36
|
+
DEVIATIONS #PI-10). */
|
|
37
|
+
/* While the resend timer runs, the line is ONE disabled link (Figma
|
|
38
|
+
`OTP.typing`: Tertiary / Link ยท Disabled), not the composed sentence. */
|
|
39
|
+
linkLabel: counting
|
|
40
|
+
? strings.otp.resendCountdownLabel.replace('{{time}}', String(resendIn))
|
|
41
|
+
: undefined, linkDisabled: counting, linkContent: !counting && strings.otp.resendPrompt ? (_jsxs("p", { className: "prizma-screen-layout__inline-prompt", children: [strings.otp.resendPrompt, ' ', strings.otp.resendLabel ? (_jsx("button", { type: "button", className: "prizma-screen-layout__inline-link", onClick: () => onAction?.({ type: 'secondary', screenId }), children: strings.otp.resendLabel })) : null, strings.otp.changeNumberLabel ? (_jsxs(_Fragment, { children: [' ', strings.otp.resendSeparator, ' ', _jsx("button", { type: "button", className: "prizma-screen-layout__inline-link", onClick: () => onAction?.({ type: 'tertiary', screenId }), children: strings.otp.changeNumberLabel })] })) : null] })) : undefined, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell, children: _jsx(PrizmaOtp, { length: length,
|
|
42
|
+
/* Uncontrolled, for the same reason as the phone field: `readOnly`
|
|
43
|
+
would paint Core's DISABLED surface on the resting states, which is
|
|
44
|
+
grey Figma does not draw there (DEVIATIONS #PI-6). */
|
|
45
|
+
defaultValue: value ?? '',
|
|
46
|
+
/* `processing` is the one section Figma greys โ the code stays legible
|
|
47
|
+
while the check runs. */
|
|
48
|
+
disabled: state === 'processing', error: state === 'error', errorText: state === 'error' ? strings.otp.errorText : undefined }) }));
|
|
49
|
+
});
|
|
43
50
|
PhoneInputOtpScreen.displayName = 'PhoneInputOtpScreen';
|
|
44
51
|
export default PhoneInputOtpScreen;
|
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
* - `typing` โ partial value, focused field
|
|
8
8
|
* - `filled` โ complete value
|
|
9
9
|
* - `loading` โ CTA in its loading treatment while the code is requested
|
|
10
|
+
* - `emptyError` โ "Continue" pressed with no number typed: the phone field
|
|
11
|
+
* stays empty (no placeholder) in Core's error state with `requiredError`,
|
|
12
|
+
* and the CTA is disabled. The dial code always carries a selection, so it
|
|
13
|
+
* takes no error. GUIDELINES ยง6-E empty-submit rule (Elena, 2026-09-30).
|
|
10
14
|
*/
|
|
11
|
-
export type PhoneInputVerifyState = 'default' | 'countryCode' | 'typing' | 'filled' | 'loading';
|
|
15
|
+
export type PhoneInputVerifyState = 'default' | 'countryCode' | 'typing' | 'filled' | 'loading' | 'emptyError';
|
|
12
16
|
/**
|
|
13
17
|
* The `phoneNumber.OTP.*` sections โ same layout, different field state:
|
|
14
18
|
* - `typing` โ partial code
|
|
@@ -24,8 +28,9 @@ export type PhoneInputOtpState = 'typing' | 'filled' | 'processing' | 'error';
|
|
|
24
28
|
*/
|
|
25
29
|
export type PhoneInputErrorVariant = 'tryAgain' | 'unknown' | 'noNetwork';
|
|
26
30
|
/** One selectable country in the dial-code dropdown. Runtime data, not copy โ
|
|
27
|
-
* the host supplies its own list
|
|
28
|
-
*
|
|
31
|
+
* the host supplies its own list. The screen draws the flag from Core's
|
|
32
|
+
* raster bank by `value` (`PrizmaCountryFlag`, DEVIATIONS #PI-3); `flag` is
|
|
33
|
+
* only the emoji fallback for a country outside the bank. */
|
|
29
34
|
export interface PhoneInputCountry {
|
|
30
35
|
/** Stable value, e.g. an ISO 3166-1 alpha-2 code. */
|
|
31
36
|
value: string;
|
|
@@ -33,7 +38,7 @@ export interface PhoneInputCountry {
|
|
|
33
38
|
dialCode: string;
|
|
34
39
|
/** Country name for the open menu row. */
|
|
35
40
|
label: string;
|
|
36
|
-
/** Emoji
|
|
41
|
+
/** Emoji fallback, e.g. `๐ท๐ธ`, drawn only when the bank has no raster. */
|
|
37
42
|
flag?: string;
|
|
38
43
|
}
|
|
39
44
|
export interface PhoneInputStrings {
|
|
@@ -41,6 +46,12 @@ export interface PhoneInputStrings {
|
|
|
41
46
|
verifiedLabel: string;
|
|
42
47
|
/** Accessible name for the logo nav row. */
|
|
43
48
|
navLabel?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Error row under the required field when the primary CTA is pressed with it
|
|
51
|
+
* still empty (the verify screen's `emptyError` state): "This field is
|
|
52
|
+
* required". SDK key `dynamicForms.fieldRequired`.
|
|
53
|
+
*/
|
|
54
|
+
requiredError: string;
|
|
44
55
|
/** phoneNumber.verify.* */
|
|
45
56
|
verify: {
|
|
46
57
|
/** H2 ("Verify your phone number"). */
|
|
@@ -92,6 +103,13 @@ export interface PhoneInputStrings {
|
|
|
92
103
|
resendSeparator?: string;
|
|
93
104
|
/** Second link โ returns to phone entry. Emits `tertiary`. */
|
|
94
105
|
changeNumberLabel?: string;
|
|
106
|
+
/**
|
|
107
|
+
* While the resend timer runs, the resend line is replaced by ONE disabled
|
|
108
|
+
* link: "Resend code in {{time}}s" (Figma `phoneNumber.OTP.typing`). The
|
|
109
|
+
* `{{time}}` placeholder is the SDK's own (`otp.resendCountdown`) and is
|
|
110
|
+
* filled with the screen's `resendIn` seconds.
|
|
111
|
+
*/
|
|
112
|
+
resendCountdownLabel?: string;
|
|
95
113
|
/** Primary CTA. */
|
|
96
114
|
ctaLabel: string;
|
|
97
115
|
/** Accessible / visible busy copy while the code is checked (`processing`). */
|
|
@@ -36,6 +36,14 @@ export interface PhoneInputVerifyScreenProps extends Omit<PrizmaFormScreenProps,
|
|
|
36
36
|
* primitives (`PrizmaDropdown`, `PrizmaTextField`) at the designed 56px min
|
|
37
37
|
* height and `Border/Radius/small`, so the module layer contributes only the
|
|
38
38
|
* row that pairs them (`PhoneInputLayout.css`) โ no primitive is re-implemented.
|
|
39
|
+
*
|
|
40
|
+
* `emptyError` is the empty-submit state (rule from Elena, 2026-09-30,
|
|
41
|
+
* GUIDELINES ยง6-E empty-submit rule): "Continue" was pressed with no number
|
|
42
|
+
* typed. The phone field renders empty with no placeholder, in Core's error
|
|
43
|
+
* state with `requiredError`, and the primary CTA is disabled, following the
|
|
44
|
+
* drawn precedent in `FormsFieldScreen`. The dial code always carries a
|
|
45
|
+
* selection, so it takes no error. The resting `default` keeps the CTA enabled
|
|
46
|
+
* so the user can reach this state.
|
|
39
47
|
*/
|
|
40
48
|
export declare const PhoneInputVerifyScreen: React.ForwardRefExoticComponent<PhoneInputVerifyScreenProps & React.RefAttributes<HTMLDivElement>>;
|
|
41
49
|
export default PhoneInputVerifyScreen;
|
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { PrizmaTextField } from '@incodetech/prizma-core-web/text-field';
|
|
5
5
|
import { PrizmaDropdown } from '@incodetech/prizma-core-web/dropdown';
|
|
6
|
+
import { PrizmaCountryFlag } from '@incodetech/prizma-core-web/combined';
|
|
6
7
|
import { PrizmaFormScreen } from './FormScreen';
|
|
7
8
|
import './ScreenLayout.css';
|
|
8
9
|
import './PhoneInputLayout.css';
|
|
@@ -29,14 +30,27 @@ const DEFAULT_COUNTRIES = [
|
|
|
29
30
|
* primitives (`PrizmaDropdown`, `PrizmaTextField`) at the designed 56px min
|
|
30
31
|
* height and `Border/Radius/small`, so the module layer contributes only the
|
|
31
32
|
* row that pairs them (`PhoneInputLayout.css`) โ no primitive is re-implemented.
|
|
33
|
+
*
|
|
34
|
+
* `emptyError` is the empty-submit state (rule from Elena, 2026-09-30,
|
|
35
|
+
* GUIDELINES ยง6-E empty-submit rule): "Continue" was pressed with no number
|
|
36
|
+
* typed. The phone field renders empty with no placeholder, in Core's error
|
|
37
|
+
* state with `requiredError`, and the primary CTA is disabled, following the
|
|
38
|
+
* drawn precedent in `FormsFieldScreen`. The dial code always carries a
|
|
39
|
+
* selection, so it takes no error. The resting `default` keeps the CTA enabled
|
|
40
|
+
* so the user can reach this state.
|
|
32
41
|
*/
|
|
33
42
|
export const PhoneInputVerifyScreen = forwardRef(({ strings, state = 'default', countries = DEFAULT_COUNTRIES, country, value, screenId = `phone-input-verify-${state}`, overrides, onAction, ...shell }, ref) => {
|
|
34
43
|
const selected = country ?? countries[0]?.value;
|
|
35
44
|
const options = countries.map((c) => ({
|
|
36
45
|
value: c.value,
|
|
37
|
-
// The
|
|
38
|
-
// ("
|
|
39
|
-
|
|
46
|
+
// The open menu row reads flag + dial code + country name
|
|
47
|
+
// ("+381 Serbia" after the flag); the closed field keeps only flag +
|
|
48
|
+
// dial code ("+381") through Core's `fieldLabel`, as Figma draws it.
|
|
49
|
+
// The flag is not text: it rides the leading slot below (DEVIATIONS
|
|
50
|
+
// #PI-3), so it is Core's raster on every OS instead of an emoji that
|
|
51
|
+
// Windows draws as the letters "RS".
|
|
52
|
+
label: [c.dialCode, c.label].join(' '),
|
|
53
|
+
fieldLabel: c.dialCode,
|
|
40
54
|
}));
|
|
41
55
|
// Figma treats the states as three distinct field treatments, not one:
|
|
42
56
|
// `loading` greys BOTH fields (the request is in flight and the form is
|
|
@@ -47,11 +61,26 @@ export const PhoneInputVerifyScreen = forwardRef(({ strings, state = 'default',
|
|
|
47
61
|
// for none of them โ it would grey the resting states too (DEVIATIONS #PI-6).
|
|
48
62
|
const busy = state === 'loading';
|
|
49
63
|
const focused = state === 'typing';
|
|
64
|
+
// Empty submit: the number field drops its placeholder and takes Core's
|
|
65
|
+
// error state with the shared "required" row; the CTA greys.
|
|
66
|
+
const emptyError = state === 'emptyError';
|
|
50
67
|
return (_jsx(PrizmaFormScreen, { ref: ref, title: strings.verify.title, subtitle: strings.verify.subtitle, ctaLabel: strings.verify.ctaLabel,
|
|
51
68
|
/* Figma's `loading` section swaps the CTA label for Core's spinner. */
|
|
52
|
-
ctaLoading: busy, ctaLoadingLabel: strings.verify.ctaLoadingLabel, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell, children: _jsxs("div", { className: "phone-input-combined", children: [_jsx(PrizmaDropdown, { className: "phone-input-combined__country", "aria-label": strings.verify.countryLabel, options: options, value: selected, searchable: true, searchPlaceholder: strings.verify.countrySearchPlaceholder,
|
|
69
|
+
ctaLoading: busy, ctaDisabled: emptyError, ctaLoadingLabel: strings.verify.ctaLoadingLabel, verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell, children: _jsxs("div", { className: "phone-input-combined", children: [_jsx(PrizmaDropdown, { className: "phone-input-combined__country", "aria-label": strings.verify.countryLabel, options: options, value: selected, searchable: true, searchPlaceholder: strings.verify.countrySearchPlaceholder,
|
|
53
70
|
/* The `countryCode` section IS the open-menu spec state. */
|
|
54
|
-
forceOpen: state === 'countryCode',
|
|
71
|
+
forceOpen: state === 'countryCode',
|
|
72
|
+
/* Core's canonical flag raster in the closed field and every menu
|
|
73
|
+
row, the WatchlistBusinessFormScreen precedent. A country
|
|
74
|
+
outside the bank falls back to its `flag` emoji. */
|
|
75
|
+
renderLeading: (option) => {
|
|
76
|
+
const match = countries.find((c) => c.value === option.value);
|
|
77
|
+
return match ? (_jsx(PrizmaCountryFlag, { country: {
|
|
78
|
+
code: match.value,
|
|
79
|
+
name: match.label,
|
|
80
|
+
dialCode: match.dialCode,
|
|
81
|
+
flag: match.flag ?? '',
|
|
82
|
+
} })) : null;
|
|
83
|
+
}, disabled: busy }), _jsx(PrizmaTextField, { className: [
|
|
55
84
|
'phone-input-combined__number',
|
|
56
85
|
/* Core's own static-focus modifier โ the same mechanism the
|
|
57
86
|
Dropdown exposes as `forceState`, which `PrizmaTextField` has
|
|
@@ -59,11 +88,11 @@ export const PhoneInputVerifyScreen = forwardRef(({ strings, state = 'default',
|
|
|
59
88
|
focused ? 'prizma-input-textfield--focused' : '',
|
|
60
89
|
]
|
|
61
90
|
.filter(Boolean)
|
|
62
|
-
.join(' '), type: "tel", inputMode: "tel", "aria-label": strings.verify.fieldLabel, placeholder: strings.verify.placeholder,
|
|
91
|
+
.join(' '), type: "tel", inputMode: "tel", "aria-label": strings.verify.fieldLabel, placeholder: emptyError ? undefined : strings.verify.placeholder,
|
|
63
92
|
/* Uncontrolled: a screen is one static spec state, and `value`
|
|
64
93
|
without `onChange` would either warn or force `readOnly`, whose
|
|
65
94
|
disabled surface is exactly the grey Figma does NOT draw here. */
|
|
66
|
-
defaultValue: value ?? '', disabled: busy,
|
|
95
|
+
defaultValue: emptyError ? '' : value ?? '', disabled: busy, error: emptyError, errorText: emptyError ? strings.requiredError : undefined,
|
|
67
96
|
/* Figma draws the clear โ only while the field is focused. */
|
|
68
97
|
clearable: focused })] }) }));
|
|
69
98
|
});
|
|
@@ -62,6 +62,7 @@ export const QualifiedSignatureAcceptScreen = forwardRef(({ strings, variant = '
|
|
|
62
62
|
// `loading` makes the whole form inert.
|
|
63
63
|
const busy = state === 'loading';
|
|
64
64
|
const ticked = state !== 'default';
|
|
65
|
+
const requiredHint = strings.accept.requiredHint;
|
|
65
66
|
return (_jsxs(PrizmaFormScreen, { ref: ref, className: ['qualified-signature-accept', className].filter(Boolean).join(' '), title: copy.title, subtitle: copy.subtitle, ctaLabel: copy.ctaLabel, ctaDisabled: !ticked, ctaLoading: busy, ctaLoadingLabel: copy.ctaLoadingLabel,
|
|
66
67
|
/* The clause stack pans inside the column โ the archetype owns this now
|
|
67
68
|
(`--scroll`), so the module declares no overflow of its own. #QS-1 */
|
|
@@ -80,7 +81,11 @@ export const QualifiedSignatureAcceptScreen = forwardRef(({ strings, variant = '
|
|
|
80
81
|
action outright while the partner's `loading` frame greys it. Two
|
|
81
82
|
Figma readings of one inert state; Core models inert as disabled,
|
|
82
83
|
so both take the greyed treatment and the removal is logged. */
|
|
83
|
-
_jsx(PrizmaCardDocumentContainer, { filename: filename, actionLabel: strings.accept.viewLabel, actionDisabled: busy, onAction: () => onAction?.({ type: 'tertiary', screenId }) })) : null,
|
|
84
|
+
_jsx(PrizmaCardDocumentContainer, { filename: filename, actionLabel: strings.accept.viewLabel, actionDisabled: busy, onAction: () => onAction?.({ type: 'tertiary', screenId }) })) : null, _jsxs("div", { className: "qualified-signature-terms", role: "group", "aria-label": strings.accept.termsLabel, children: [requiredHint && strings.accept.requiredLegend ? (_jsx("p", { className: "qualified-signature-terms__legend", children: strings.accept.requiredLegend })) : null, terms.map((term) => (_jsx(PrizmaCheckbox, { size: "L", name: term.id, value: term.id, checked: ticked, disabled: busy, required: Boolean(requiredHint),
|
|
85
|
+
/* The `*` rides the END of the clause copy, the Data Sharing
|
|
86
|
+
Consent idiom โ the L card paints no marker of its own beside
|
|
87
|
+
the box (owner, 2026-09-02). */
|
|
88
|
+
segments: requiredHint ? [...term.segments, ` ${requiredHint}`] : term.segments }, term.id)))] })] }));
|
|
84
89
|
});
|
|
85
90
|
QualifiedSignatureAcceptScreen.displayName = 'QualifiedSignatureAcceptScreen';
|
|
86
91
|
export default QualifiedSignatureAcceptScreen;
|
|
@@ -35,16 +35,21 @@ export interface QualifiedSignatureDocumentScreenProps extends Omit<PrizmaListSc
|
|
|
35
35
|
*
|
|
36
36
|
* Archetype G is the fit: its `__list` middle is "content filling the space
|
|
37
37
|
* between the title block and the CTA band", which is exactly what a document
|
|
38
|
-
* page is, and
|
|
38
|
+
* page is, and the band carries only the "Back" secondary (delta 1). The
|
|
39
39
|
* body is allowed to scroll inside that middle โ one module rule RELEASING an
|
|
40
40
|
* overflow constraint, declaring no spacing or size, the same idiom as CURP's
|
|
41
41
|
* taller-than-844 form (DEVIATIONS #CURP-1).
|
|
42
42
|
*
|
|
43
|
-
* THREE deltas from the frames
|
|
44
|
-
* 1. Both sections draw a back chevron at the nav's left
|
|
45
|
-
* the
|
|
46
|
-
*
|
|
47
|
-
*
|
|
43
|
+
* THREE deltas from the frames:
|
|
44
|
+
* 1. Both sections draw a back chevron at the nav's left. These are viewers
|
|
45
|
+
* the user opened from the accept screen, so they need a way back (owner
|
|
46
|
+
* call 2026-09-29). It ships as a full-width SECONDARY "Back" button in the
|
|
47
|
+
* CTA band instead, emitting `secondary` (owner call 2026-10-08): the person
|
|
48
|
+
* reads and returns to sign, and a real button at the thumb is easier to
|
|
49
|
+
* find than a chevron. "Back" over "Done" because nothing is finished here;
|
|
50
|
+
* the signature still waits on the accept screen. The nav stays logo-only.
|
|
51
|
+
* `terms` replacing the logo row with a chevron + heading bar is still not
|
|
52
|
+
* followed โ the title stays the archetype's H2 below the nav.
|
|
48
53
|
* 2. `viewdoc` draws NO heading. GUIDELINES ยง4 is explicit that every screen has
|
|
49
54
|
* exactly one H2, and archetype G has no title-less path, so the screen
|
|
50
55
|
* carries one and the Figma frame is the side to change. (An archetype
|
|
@@ -53,10 +58,12 @@ export interface QualifiedSignatureDocumentScreenProps extends Omit<PrizmaListSc
|
|
|
53
58
|
* for attribution chrome (#PI-8, #F-30, #F-34), so both variants keep the
|
|
54
59
|
* header and the footer and nothing shifts between states.
|
|
55
60
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* an
|
|
61
|
+
* Both variants frame the page in the box Electronic Signature's review screen
|
|
62
|
+
* uses, so the title is CENTRED on both, like that screen (owner call
|
|
63
|
+
* 2026-09-29, "take reference from other screens"). Figma's `QSign.T&C` draws
|
|
64
|
+
* the title left over an unframed wall of text; once the text sits in its own
|
|
65
|
+
* left-aligned frame the centred title no longer reads as a mistake. An
|
|
66
|
+
* explicit `overrides.align` from the host still wins.
|
|
60
67
|
*/
|
|
61
68
|
export declare const QualifiedSignatureDocumentScreen: React.ForwardRefExoticComponent<QualifiedSignatureDocumentScreenProps & React.RefAttributes<HTMLDivElement>>;
|
|
62
69
|
export default QualifiedSignatureDocumentScreen;
|