@incodetech/prizma-core-screens 0.2.3 → 0.2.7
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/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/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 +27 -9
- package/dist/EkybOwnersScreen.d.ts +8 -0
- package/dist/EkybOwnersScreen.js +26 -3
- package/dist/EkybStrings.d.ts +27 -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/FaceMatchComparisonScreen.d.ts +3 -3
- package/dist/FaceMatchLayout.css +21 -12
- package/dist/FormScreen.css +16 -0
- 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 +40 -0
- package/dist/ListScreen.d.ts +2 -0
- package/dist/ListScreen.js +1 -1
- package/dist/PhoneInputLayout.css +10 -9
- package/dist/PhoneInputStrings.d.ts +11 -1
- package/dist/PhoneInputVerifyScreen.d.ts +8 -0
- package/dist/PhoneInputVerifyScreen.js +19 -6
- package/dist/QualifiedSignatureAcceptScreen.js +6 -1
- package/dist/QualifiedSignatureDocumentScreen.d.ts +13 -9
- package/dist/QualifiedSignatureDocumentScreen.js +18 -16
- package/dist/QualifiedSignatureLayout.css +76 -0
- package/dist/QualifiedSignatureStrings.d.ts +10 -0
- package/dist/ScreenNav.css +8 -0
- package/dist/ScreenNav.d.ts +15 -2
- package/dist/ScreenNav.js +10 -3
- package/dist/VideoSelfieIdCaptureScreen.d.ts +10 -3
- package/dist/VideoSelfieIdCaptureScreen.js +44 -13
- package/dist/VideoSelfieLayout.css +164 -33
- package/dist/VideoSelfieSelfieCaptureScreen.d.ts +44 -27
- package/dist/VideoSelfieSelfieCaptureScreen.js +65 -39
- package/dist/VideoSelfieSpeakScreen.js +18 -1
- package/dist/VideoSelfieStrings.d.ts +78 -12
- package/dist/VideoSelfieTurnHeadScreen.d.ts +51 -0
- package/dist/VideoSelfieTurnHeadScreen.js +63 -0
- package/dist/VideoSelfieTutorialScreen.js +13 -5
- package/dist/VideoSelfieWaveScreen.d.ts +53 -0
- package/dist/VideoSelfieWaveScreen.js +62 -0
- package/dist/WatchlistBusinessFormScreen.d.ts +11 -7
- package/dist/WatchlistBusinessFormScreen.js +27 -13
- package/dist/WatchlistBusinessStrings.d.ts +21 -7
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/types.d.ts +3 -1
- package/package.json +14 -3
- package/samples/video-selfie-room.png +0 -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/EkybAddressDetailsScreen.tsx +32 -4
- package/src/EkybBusinessDetailsScreen.tsx +23 -5
- package/src/EkybCountryScreen.tsx +28 -7
- package/src/EkybOwnersScreen.tsx +34 -3
- package/src/EkybStrings.ts +29 -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/FaceMatchComparisonScreen.tsx +3 -3
- package/src/FaceMatchLayout.css +21 -12
- package/src/FormScreen.css +16 -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 +40 -0
- package/src/ListScreen.tsx +10 -1
- package/src/PhoneInputLayout.css +10 -9
- package/src/PhoneInputStrings.ts +12 -1
- package/src/PhoneInputVerifyScreen.tsx +21 -5
- package/src/QualifiedSignatureAcceptScreen.tsx +12 -1
- package/src/QualifiedSignatureDocumentScreen.tsx +27 -17
- package/src/QualifiedSignatureLayout.css +76 -0
- package/src/QualifiedSignatureStrings.ts +10 -0
- package/src/ScreenNav.css +8 -0
- package/src/ScreenNav.tsx +35 -5
- package/src/VideoSelfieIdCaptureScreen.tsx +116 -30
- package/src/VideoSelfieLayout.css +164 -33
- package/src/VideoSelfieSelfieCaptureScreen.tsx +104 -59
- package/src/VideoSelfieSpeakScreen.tsx +25 -14
- package/src/VideoSelfieStrings.ts +85 -12
- package/src/VideoSelfieTurnHeadScreen.tsx +151 -0
- package/src/VideoSelfieTutorialScreen.tsx +34 -23
- package/src/VideoSelfieWaveScreen.tsx +135 -0
- package/src/WatchlistBusinessFormScreen.tsx +35 -16
- package/src/WatchlistBusinessStrings.ts +21 -7
- package/src/index.ts +14 -0
- package/src/types.ts +3 -1
|
@@ -11,8 +11,9 @@ import './ScreenLayout.css';
|
|
|
11
11
|
* (GUIDELINES.md §6-E, `PrizmaFormScreen`).
|
|
12
12
|
*
|
|
13
13
|
* ONE screen for both purple form sections (`watchlist.default` and
|
|
14
|
-
* `watchlist.filled`)
|
|
15
|
-
*
|
|
14
|
+
* `watchlist.filled`), plus the `emptyError` state the GUIDELINES §6-E
|
|
15
|
+
* empty-submit rule adds (Elena 2026-09-30, see note 3): measured against the 390 frames they share an identical
|
|
16
|
+
* skeleton — nav → Title (H2 + the "fields marked with *" H5) → Spacing/32 → Country dropdown,
|
|
16
17
|
* Business Name and Tax ID at Spacing/16 → primary CTA → tag — and differ ONLY
|
|
17
18
|
* in field content and whether the CTA is live.
|
|
18
19
|
*
|
|
@@ -27,11 +28,14 @@ import './ScreenLayout.css';
|
|
|
27
28
|
* and Core's `readOnly`, the other way to make a field inert, paints the
|
|
28
29
|
* DISABLED grey surface on states Figma draws white (DEVIATIONS #PI-6).
|
|
29
30
|
* Neither section greys anything, so `disabled` is set nowhere.
|
|
30
|
-
* 3. The CTA state comes from the SECTION, not from the values
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
31
|
+
* 3. The CTA state comes from the SECTION, not from the values. Under the
|
|
32
|
+
* GUIDELINES §6-E empty-submit rule (Elena 2026-09-30) "Continue" is live
|
|
33
|
+
* on the resting `default` form, so the user can press it, and greys ONLY
|
|
34
|
+
* on `emptyError`, the state that press leads to: Country and Business
|
|
35
|
+
* Name render empty (no placeholder) in Core's error state with
|
|
36
|
+
* `requiredError`. Tax ID never errors — `filled` leaves it empty with the
|
|
37
|
+
* CTA live, which is how we know it does not gate the lookup (DEVIATIONS
|
|
38
|
+
* #WB-2).
|
|
35
39
|
* 4. The country flag is Core's canonical raster (24×18, radius 2) in the
|
|
36
40
|
* dropdown's LEADING slot — `PrizmaCountryFlag` composed into
|
|
37
41
|
* `PrizmaDropdown.renderLeading`, which exists for exactly this case and
|
|
@@ -49,21 +53,29 @@ import './ScreenLayout.css';
|
|
|
49
53
|
*/
|
|
50
54
|
export const WatchlistBusinessFormScreen = forwardRef(({ strings, state = 'default', countries = [], values, screenId = `watchlist-business-form-${state}`, overrides, onAction, ...shell }, ref) => {
|
|
51
55
|
const copy = strings.form;
|
|
52
|
-
//
|
|
53
|
-
// spec, not the field
|
|
54
|
-
|
|
56
|
+
// The CTA greys only after an empty submit; the resting form keeps it live
|
|
57
|
+
// so that submit can happen. The section is the spec, not the field
|
|
58
|
+
// contents (see note 3 above).
|
|
59
|
+
const emptyError = state === 'emptyError';
|
|
60
|
+
const errorText = emptyError ? strings.requiredError : undefined;
|
|
55
61
|
// The label is the country NAME only. The flag is not part of it — it rides
|
|
56
62
|
// the dropdown's leading slot below, where Core paints the raster.
|
|
57
63
|
const options = countries.map((c) => ({
|
|
58
64
|
value: c.value,
|
|
59
65
|
label: c.label,
|
|
60
66
|
}));
|
|
61
|
-
return (_jsxs(PrizmaFormScreen, { ref: ref, title: copy.title, subtitle: copy.subtitle, ctaLabel: copy.ctaLabel, ctaDisabled:
|
|
67
|
+
return (_jsxs(PrizmaFormScreen, { ref: ref, title: copy.title, subtitle: copy.subtitle, ctaLabel: copy.ctaLabel, ctaDisabled: emptyError, ctaLoadingLabel: copy.ctaLoadingLabel,
|
|
62
68
|
/* Figma draws no verified tag on either form section, but GUIDELINES §1
|
|
63
69
|
and the standing owner rule (#F-30, #PI-8) keep header AND footer on
|
|
64
70
|
every non-capture screen — so nothing shifts between the form, the
|
|
65
71
|
spinner and the verdict. DEVIATIONS #WB-1. */
|
|
66
|
-
verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell, children: [_jsx(PrizmaDropdown, { label: copy.country.label,
|
|
72
|
+
verifiedLabel: strings.verifiedLabel, navLabel: strings.navLabel, screenId: screenId, overrides: overrides, onAction: onAction, ...shell, children: [_jsx(PrizmaDropdown, { label: copy.country.label,
|
|
73
|
+
/* Country and Business Name are required and marked (Elena,
|
|
74
|
+
2026-09-30); the H5 explains the asterisk. */
|
|
75
|
+
required: true, requiredHint: strings.requiredHint,
|
|
76
|
+
/* The empty-submit error draws the field with nothing in it, as the
|
|
77
|
+
`FormsFieldScreen` `emptyError` precedent does. */
|
|
78
|
+
placeholder: emptyError ? undefined : copy.country.placeholder, options: options, defaultValue: emptyError ? null : (values?.country ?? null), error: emptyError, errorText: errorText,
|
|
67
79
|
/* A country catalogue is long enough that Core's own search bar is
|
|
68
80
|
the right behaviour; no purple section draws the menu open, so
|
|
69
81
|
nothing about its appearance is being invented here. */
|
|
@@ -79,7 +91,9 @@ export const WatchlistBusinessFormScreen = forwardRef(({ strings, state = 'defau
|
|
|
79
91
|
dialCode: '',
|
|
80
92
|
flag: match.flag ?? '',
|
|
81
93
|
} })) : null;
|
|
82
|
-
} }), _jsx(PrizmaTextField, { label: copy.businessName.label, placeholder: copy.businessName.placeholder, autoComplete: "organization", defaultValue: values?.businessName ?? '' }), _jsx(PrizmaTextField, { label: copy.taxId.label, placeholder: copy.taxId.placeholder, autoComplete: "off", autoCapitalize: "characters", spellCheck: false,
|
|
94
|
+
} }), _jsx(PrizmaTextField, { label: copy.businessName.label, required: true, requiredHint: strings.requiredHint, placeholder: emptyError ? undefined : copy.businessName.placeholder, autoComplete: "organization", defaultValue: emptyError ? '' : (values?.businessName ?? ''), error: emptyError, errorText: errorText }), _jsx(PrizmaTextField, { label: copy.taxId.label, placeholder: copy.taxId.placeholder, autoComplete: "off", autoCapitalize: "characters", spellCheck: false,
|
|
95
|
+
/* Optional (#WB-2): an empty submit leaves it clean. */
|
|
96
|
+
defaultValue: emptyError ? '' : (values?.taxId ?? '') })] }));
|
|
83
97
|
});
|
|
84
98
|
WatchlistBusinessFormScreen.displayName = 'WatchlistBusinessFormScreen';
|
|
85
99
|
export default WatchlistBusinessFormScreen;
|
|
@@ -4,15 +4,18 @@
|
|
|
4
4
|
* in field content and whether the CTA is live, which is exactly what
|
|
5
5
|
* GUIDELINES §6-E means by "states are separate screens sharing the identical
|
|
6
6
|
* layout":
|
|
7
|
-
* - `default`
|
|
8
|
-
* CTA
|
|
9
|
-
* - `filled`
|
|
7
|
+
* - `default` — every field empty (the country dropdown on its placeholder),
|
|
8
|
+
* CTA live so the user can press it (GUIDELINES §6-E empty-submit rule)
|
|
9
|
+
* - `filled` — country selected and business name typed, CTA live
|
|
10
|
+
* - `emptyError` — the user pressed the CTA with the form empty: Country and
|
|
11
|
+
* Business Name render empty in Core's error state with `requiredError`,
|
|
12
|
+
* Tax ID stays clean, CTA greyed (Elena 2026-09-30)
|
|
10
13
|
*
|
|
11
14
|
* Note what `filled` does NOT do: it leaves **Tax ID empty** and still enables
|
|
12
15
|
* the CTA, so the tax identifier is optional and does not gate the lookup
|
|
13
|
-
* (DEVIATIONS #WB-2).
|
|
16
|
+
* (DEVIATIONS #WB-2). That is also why `emptyError` leaves Tax ID alone.
|
|
14
17
|
*/
|
|
15
|
-
export type WatchlistBusinessFormState = 'default' | 'filled';
|
|
18
|
+
export type WatchlistBusinessFormState = 'default' | 'filled' | 'emptyError';
|
|
16
19
|
/**
|
|
17
20
|
* One selectable country of registration. Runtime data, never copy — the host
|
|
18
21
|
* owns the catalogue (a full ISO list is not a string table), exactly as Phone
|
|
@@ -58,11 +61,22 @@ export interface WatchlistBusinessStrings {
|
|
|
58
61
|
verifiedLabel: string;
|
|
59
62
|
/** Accessible name for the logo nav row. */
|
|
60
63
|
navLabel?: string;
|
|
61
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* The error row the REQUIRED fields (Country, Business Name) show on the
|
|
66
|
+
* `emptyError` form state ("This field is required"). Maps to the SDK's
|
|
67
|
+
* `dynamicForms.fieldRequired` key. GUIDELINES §6-E empty-submit rule.
|
|
68
|
+
*/
|
|
69
|
+
requiredError: string;
|
|
70
|
+
/**
|
|
71
|
+
* Required-field marker ("*"), passed to Core's own `requiredHint` prop on
|
|
72
|
+
* Country and Business Name (Elena, 2026-09-30).
|
|
73
|
+
*/
|
|
74
|
+
requiredHint?: string;
|
|
75
|
+
/** watchlist.{default,filled,emptyError} */
|
|
62
76
|
form: {
|
|
63
77
|
/** H2 ("Watchlist for business"). */
|
|
64
78
|
title: string;
|
|
65
|
-
/** H5
|
|
79
|
+
/** H5 ("All fields marked with * are required."), explains the asterisk. */
|
|
66
80
|
subtitle?: string;
|
|
67
81
|
country: WatchlistBusinessFieldStrings & {
|
|
68
82
|
/** Search placeholder inside the open menu. */
|
package/dist/index.d.ts
CHANGED
|
@@ -109,7 +109,7 @@ export { type WatchlistBusinessFormState, type WatchlistBusinessCountry, type Wa
|
|
|
109
109
|
export { WatchlistBusinessFormScreen, type WatchlistBusinessFormScreenProps } from './WatchlistBusinessFormScreen';
|
|
110
110
|
export { WatchlistBusinessProcessingScreen, type WatchlistBusinessProcessingScreenProps } from './WatchlistBusinessProcessingScreen';
|
|
111
111
|
export { WatchlistBusinessSuccessScreen, type WatchlistBusinessSuccessScreenProps } from './WatchlistBusinessSuccessScreen';
|
|
112
|
-
export { type VideoSelfieDocumentType, type VideoSelfieTutorialRow, type VideoSelfieTutorialRowKind, type VideoSelfieFeedbackKind, type VideoSelfieIdSide, type VideoSelfieIdErrorSeverity, type VideoSelfieSpeakFamily, type VideoSelfieStepsOs, type VideoSelfieStepsStrings, type VideoSelfieSpeakStrings, type VideoSelfieStrings, } from './VideoSelfieStrings';
|
|
112
|
+
export { type VideoSelfieDocumentType, type VideoSelfieTutorialRow, type VideoSelfieTutorialRowKind, type VideoSelfieFeedbackKind, type VideoSelfieIdSide, type VideoSelfieConditionCopy, type VideoSelfieIdCondition, type VideoSelfieIdErrorReason, type VideoSelfieIdErrorSeverity, type VideoSelfieTurnDirection, type VideoSelfieSpeakFamily, type VideoSelfieStepsOs, type VideoSelfieStepsStrings, type VideoSelfieSpeakStrings, type VideoSelfieStrings, } from './VideoSelfieStrings';
|
|
113
113
|
export { VideoSelfieCameraStepsScreen, type VideoSelfieCameraStepsScreenProps } from './VideoSelfieCameraStepsScreen';
|
|
114
114
|
export { VideoSelfieErrorScreen, type VideoSelfieErrorVariant, type VideoSelfieErrorScreenProps, } from './VideoSelfieErrorScreen';
|
|
115
115
|
export { VideoSelfieFlipCameraScreen, type VideoSelfieFlipCameraScreenProps } from './VideoSelfieFlipCameraScreen';
|
|
@@ -123,6 +123,8 @@ export { VideoSelfieSelfieCaptureScreen, type VideoSelfieSelfieState, type Video
|
|
|
123
123
|
export { VideoSelfieSpeakScreen, type VideoSelfieSpeakStage, type VideoSelfieSpeakScreenProps, } from './VideoSelfieSpeakScreen';
|
|
124
124
|
export { VideoSelfieSuccessScreen, type VideoSelfieSuccessScreenProps } from './VideoSelfieSuccessScreen';
|
|
125
125
|
export { VideoSelfieTutorialScreen, type VideoSelfieTutorialScreenProps } from './VideoSelfieTutorialScreen';
|
|
126
|
+
export { VideoSelfieTurnHeadScreen, type VideoSelfieTurnStage, type VideoSelfieTurnHeadScreenProps, } from './VideoSelfieTurnHeadScreen';
|
|
127
|
+
export { VideoSelfieWaveScreen, type VideoSelfieWaveStage, type VideoSelfieWaveScreenProps, } from './VideoSelfieWaveScreen';
|
|
126
128
|
export { type NfcDocumentType, type NfcIssueKind, type NfcIssueStrings, type NfcHeadingStrings, type NfcStrings, } from './NfcStrings';
|
|
127
129
|
export { NfcCommonIssuesScreen, type NfcCommonIssuesScreenProps } from './NfcCommonIssuesScreen';
|
|
128
130
|
export { NfcErrorScreen, type NfcErrorVariant, type NfcErrorScreenProps, } from './NfcErrorScreen';
|
package/dist/index.js
CHANGED
|
@@ -112,6 +112,8 @@ export { VideoSelfieSelfieCaptureScreen, } from './VideoSelfieSelfieCaptureScree
|
|
|
112
112
|
export { VideoSelfieSpeakScreen, } from './VideoSelfieSpeakScreen';
|
|
113
113
|
export { VideoSelfieSuccessScreen } from './VideoSelfieSuccessScreen';
|
|
114
114
|
export { VideoSelfieTutorialScreen } from './VideoSelfieTutorialScreen';
|
|
115
|
+
export { VideoSelfieTurnHeadScreen, } from './VideoSelfieTurnHeadScreen';
|
|
116
|
+
export { VideoSelfieWaveScreen, } from './VideoSelfieWaveScreen';
|
|
115
117
|
export { NfcCommonIssuesScreen } from './NfcCommonIssuesScreen';
|
|
116
118
|
export { NfcErrorScreen, } from './NfcErrorScreen';
|
|
117
119
|
export { NfcProcessingScreen } from './NfcProcessingScreen';
|
package/dist/types.d.ts
CHANGED
|
@@ -10,7 +10,9 @@ import type { ReactNode } from 'react';
|
|
|
10
10
|
* they collapsed into one indistinguishable event. DEVIATIONS #PI-10.
|
|
11
11
|
*/
|
|
12
12
|
export interface PrizmaScreenAction {
|
|
13
|
-
|
|
13
|
+
/** `back` — the nav's back chevron, on the screens that opt into one
|
|
14
|
+
* (`PrizmaScreenNav.backLabel`). */
|
|
15
|
+
type: 'cta' | 'secondary' | 'tertiary' | 'auto' | 'help' | 'back';
|
|
14
16
|
/** Stable per-screen identifier, e.g. `face-capture-tutorial`. */
|
|
15
17
|
screenId?: string;
|
|
16
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@incodetech/prizma-core-screens",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Prizma Design System — SDK module screens: composed, responsive, brand-themeable React screens built from @incodetech/prizma-core-web.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -655,11 +655,21 @@
|
|
|
655
655
|
"types": "./dist/VideoSelfieSuccessScreen.d.ts",
|
|
656
656
|
"import": "./dist/VideoSelfieSuccessScreen.js"
|
|
657
657
|
},
|
|
658
|
+
"./video-selfie-turn-head-screen": {
|
|
659
|
+
"source": "./src/VideoSelfieTurnHeadScreen.tsx",
|
|
660
|
+
"types": "./dist/VideoSelfieTurnHeadScreen.d.ts",
|
|
661
|
+
"import": "./dist/VideoSelfieTurnHeadScreen.js"
|
|
662
|
+
},
|
|
658
663
|
"./video-selfie-tutorial-screen": {
|
|
659
664
|
"source": "./src/VideoSelfieTutorialScreen.tsx",
|
|
660
665
|
"types": "./dist/VideoSelfieTutorialScreen.d.ts",
|
|
661
666
|
"import": "./dist/VideoSelfieTutorialScreen.js"
|
|
662
667
|
},
|
|
668
|
+
"./video-selfie-wave-screen": {
|
|
669
|
+
"source": "./src/VideoSelfieWaveScreen.tsx",
|
|
670
|
+
"types": "./dist/VideoSelfieWaveScreen.d.ts",
|
|
671
|
+
"import": "./dist/VideoSelfieWaveScreen.js"
|
|
672
|
+
},
|
|
663
673
|
"./viewfinder-screen": {
|
|
664
674
|
"source": "./src/ViewfinderScreen.tsx",
|
|
665
675
|
"types": "./dist/ViewfinderScreen.d.ts",
|
|
@@ -721,6 +731,7 @@
|
|
|
721
731
|
"./samples/selfie-mask.png": "./samples/selfie-mask.png",
|
|
722
732
|
"./samples/selfie.png": "./samples/selfie.png",
|
|
723
733
|
"./samples/video-selfie-camera.png": "./samples/video-selfie-camera.png",
|
|
734
|
+
"./samples/video-selfie-room.png": "./samples/video-selfie-room.png",
|
|
724
735
|
"./package.json": "./package.json"
|
|
725
736
|
},
|
|
726
737
|
"files": [
|
|
@@ -739,8 +750,8 @@
|
|
|
739
750
|
},
|
|
740
751
|
"dependencies": {
|
|
741
752
|
"@incodetech/prizma-core-icons": "^0.4.0",
|
|
742
|
-
"@incodetech/prizma-core-tokens": "^0.
|
|
743
|
-
"@incodetech/prizma-core-web": "^0.
|
|
753
|
+
"@incodetech/prizma-core-tokens": "^0.13.0",
|
|
754
|
+
"@incodetech/prizma-core-web": "^0.13.0"
|
|
744
755
|
},
|
|
745
756
|
"devDependencies": {
|
|
746
757
|
"@types/react": "^18.3.12",
|
|
Binary file
|
package/src/CurpEnterScreen.tsx
CHANGED
|
@@ -54,6 +54,13 @@ export interface CurpEnterScreenProps
|
|
|
54
54
|
* `linkContent` slot: no primitive is invented, no layout is declared, and the
|
|
55
55
|
* two actions stay distinguishable (`cta` vs `secondary`, the #PI-10 rule).
|
|
56
56
|
* The gap is reported for promotion — see the module's DEVIATIONS rows.
|
|
57
|
+
*
|
|
58
|
+
* `emptyError` is the empty-submit state (rule from Elena, 2026-09-30,
|
|
59
|
+
* GUIDELINES §6-E empty-submit rule): "Continue" was pressed with nothing
|
|
60
|
+
* typed. The field renders empty with no placeholder, in Core's error state
|
|
61
|
+
* with `requiredError`, and the primary CTA is disabled, following the drawn
|
|
62
|
+
* precedent in `FormsFieldScreen`. The resting `default` keeps the CTA enabled
|
|
63
|
+
* so the user can reach this state.
|
|
57
64
|
*/
|
|
58
65
|
export const CurpEnterScreen = forwardRef<HTMLDivElement, CurpEnterScreenProps>(
|
|
59
66
|
(
|
|
@@ -77,6 +84,9 @@ export const CurpEnterScreen = forwardRef<HTMLDivElement, CurpEnterScreenProps>(
|
|
|
77
84
|
// surface.
|
|
78
85
|
const busy = state === 'loading';
|
|
79
86
|
const invalid = state === 'error';
|
|
87
|
+
// Empty submit: the field stays empty, drops its placeholder and takes
|
|
88
|
+
// Core's error state with the shared "required" row; the CTA greys.
|
|
89
|
+
const emptyError = state === 'emptyError';
|
|
80
90
|
const focused = state === 'focused' || state === 'filled';
|
|
81
91
|
|
|
82
92
|
return (
|
|
@@ -100,6 +110,7 @@ export const CurpEnterScreen = forwardRef<HTMLDivElement, CurpEnterScreenProps>(
|
|
|
100
110
|
ctaLabel={strings.enter.ctaLabel}
|
|
101
111
|
/* The `loading` section swaps the CTA label for Core's spinner. */
|
|
102
112
|
ctaLoading={busy}
|
|
113
|
+
ctaDisabled={emptyError}
|
|
103
114
|
ctaLoadingLabel={strings.enter.ctaLoadingLabel}
|
|
104
115
|
linkContent={
|
|
105
116
|
<PrizmaButton
|
|
@@ -125,15 +136,21 @@ export const CurpEnterScreen = forwardRef<HTMLDivElement, CurpEnterScreenProps>(
|
|
|
125
136
|
carry the meaning — so the copy rides `aria-label` rather than
|
|
126
137
|
Core's visible `label` slot (DEVIATIONS #PI-4). */
|
|
127
138
|
aria-label={strings.enter.fieldLabel}
|
|
128
|
-
placeholder={strings.enter.placeholder}
|
|
129
|
-
defaultValue={value ?? ''}
|
|
139
|
+
placeholder={emptyError ? undefined : strings.enter.placeholder}
|
|
140
|
+
defaultValue={emptyError ? '' : value ?? ''}
|
|
130
141
|
/* A CURP is an 18-character uppercase key. */
|
|
131
142
|
autoCapitalize="characters"
|
|
132
143
|
autoComplete="off"
|
|
133
144
|
spellCheck={false}
|
|
134
145
|
disabled={busy}
|
|
135
|
-
error={invalid}
|
|
136
|
-
errorText={
|
|
146
|
+
error={invalid || emptyError}
|
|
147
|
+
errorText={
|
|
148
|
+
invalid
|
|
149
|
+
? strings.enter.errorText
|
|
150
|
+
: emptyError
|
|
151
|
+
? strings.requiredError
|
|
152
|
+
: undefined
|
|
153
|
+
}
|
|
137
154
|
/* The clear ✕ is drawn only on the error section (76:36434); the
|
|
138
155
|
`filled` section (79:1553) draws none. Core still owns WHEN it
|
|
139
156
|
shows — its `--show` state needs a value in the field. */
|
|
@@ -56,6 +56,14 @@ export interface CurpGenerateScreenProps
|
|
|
56
56
|
* The `dropdown` section IS the open-menu spec state, which Core exposes as the
|
|
57
57
|
* documentation-only `forceOpen` (a screen is one static state, never a live
|
|
58
58
|
* interaction) — the same mechanism Phone Input's `countryCode` section uses.
|
|
59
|
+
*
|
|
60
|
+
* `emptyError` is the empty-submit state (rule from Elena, 2026-09-30,
|
|
61
|
+
* GUIDELINES §6-E empty-submit rule): "Generate" was pressed with the form
|
|
62
|
+
* empty. All six fields carry the required `*`, so all six render empty with no
|
|
63
|
+
* placeholder, in Core's error state with `requiredError`; no menu is open and
|
|
64
|
+
* the primary CTA is disabled, following the drawn precedent in
|
|
65
|
+
* `FormsFieldScreen`. The resting `default` keeps the CTA enabled so the user
|
|
66
|
+
* can reach this state.
|
|
59
67
|
*/
|
|
60
68
|
export const CurpGenerateScreen = forwardRef<HTMLDivElement, CurpGenerateScreenProps>(
|
|
61
69
|
(
|
|
@@ -75,21 +83,30 @@ export const CurpGenerateScreen = forwardRef<HTMLDivElement, CurpGenerateScreenP
|
|
|
75
83
|
) => {
|
|
76
84
|
const copy = strings.generate;
|
|
77
85
|
|
|
86
|
+
// Empty submit: every required field drops its value and placeholder and
|
|
87
|
+
// takes Core's error state with the shared "required" row; the CTA greys.
|
|
88
|
+
const emptyError = state === 'emptyError';
|
|
89
|
+
const ph = (placeholder?: string) => (emptyError ? undefined : placeholder);
|
|
90
|
+
const err = {
|
|
91
|
+
error: emptyError,
|
|
92
|
+
errorText: emptyError ? strings.requiredError : undefined,
|
|
93
|
+
};
|
|
94
|
+
|
|
78
95
|
return (
|
|
79
96
|
<PrizmaFormScreen
|
|
80
97
|
ref={ref}
|
|
81
|
-
/*
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
98
|
+
/* The six-field stack scrolls inside the 844 frame through the
|
|
99
|
+
foundation's `scrollFields` (overflow + the Spacing/16 that keeps the
|
|
100
|
+
cut clear of "Generate"). EVERY section gets it, `dropdown` included:
|
|
101
|
+
Figma draws "Generate" clear and unobstructed under the open menu.
|
|
102
|
+
It replaces the module's old `--scroll` rule, which scrolled but
|
|
103
|
+
carried no spacing, so the last field ran flush into the button.
|
|
104
|
+
`--menu-open` (CurpLayout.css) flips Core's absolutely-positioned
|
|
105
|
+
menu above its trigger on the one section that forces it open, so
|
|
106
|
+
the three gender rows stay inside the scrolling column. */
|
|
107
|
+
scrollFields
|
|
90
108
|
className={[
|
|
91
109
|
'curp-generate',
|
|
92
|
-
'curp-generate--scroll',
|
|
93
110
|
state === 'dropdown' ? 'curp-generate--menu-open' : '',
|
|
94
111
|
className,
|
|
95
112
|
]
|
|
@@ -98,6 +115,7 @@ export const CurpGenerateScreen = forwardRef<HTMLDivElement, CurpGenerateScreenP
|
|
|
98
115
|
title={copy.title}
|
|
99
116
|
subtitle={copy.subtitle}
|
|
100
117
|
ctaLabel={copy.ctaLabel}
|
|
118
|
+
ctaDisabled={emptyError}
|
|
101
119
|
ctaLoadingLabel={copy.ctaLoadingLabel}
|
|
102
120
|
verifiedLabel={strings.verifiedLabel}
|
|
103
121
|
navLabel={strings.navLabel}
|
|
@@ -112,54 +130,60 @@ export const CurpGenerateScreen = forwardRef<HTMLDivElement, CurpGenerateScreenP
|
|
|
112
130
|
(DEVIATIONS #PI-6). */}
|
|
113
131
|
<PrizmaTextField
|
|
114
132
|
label={copy.firstName.label}
|
|
115
|
-
placeholder={copy.firstName.placeholder}
|
|
133
|
+
placeholder={ph(copy.firstName.placeholder)}
|
|
116
134
|
required
|
|
117
135
|
requiredHint={strings.requiredHint}
|
|
118
136
|
autoComplete="off"
|
|
119
|
-
defaultValue={values?.firstName ?? ''}
|
|
137
|
+
defaultValue={emptyError ? '' : values?.firstName ?? ''}
|
|
138
|
+
{...err}
|
|
120
139
|
/>
|
|
121
140
|
<PrizmaTextField
|
|
122
141
|
label={copy.firstLastName.label}
|
|
123
|
-
placeholder={copy.firstLastName.placeholder}
|
|
142
|
+
placeholder={ph(copy.firstLastName.placeholder)}
|
|
124
143
|
required
|
|
125
144
|
requiredHint={strings.requiredHint}
|
|
126
145
|
autoComplete="off"
|
|
127
|
-
defaultValue={values?.firstLastName ?? ''}
|
|
146
|
+
defaultValue={emptyError ? '' : values?.firstLastName ?? ''}
|
|
147
|
+
{...err}
|
|
128
148
|
/>
|
|
129
149
|
<PrizmaTextField
|
|
130
150
|
label={copy.secondLastName.label}
|
|
131
|
-
placeholder={copy.secondLastName.placeholder}
|
|
151
|
+
placeholder={ph(copy.secondLastName.placeholder)}
|
|
132
152
|
required
|
|
133
153
|
requiredHint={strings.requiredHint}
|
|
134
154
|
autoComplete="off"
|
|
135
|
-
defaultValue={values?.secondLastName ?? ''}
|
|
155
|
+
defaultValue={emptyError ? '' : values?.secondLastName ?? ''}
|
|
156
|
+
{...err}
|
|
136
157
|
/>
|
|
137
158
|
<PrizmaDropdown
|
|
138
159
|
label={copy.gender.label}
|
|
139
|
-
placeholder={copy.gender.placeholder}
|
|
160
|
+
placeholder={ph(copy.gender.placeholder)}
|
|
140
161
|
required
|
|
141
162
|
requiredHint={strings.requiredHint}
|
|
142
163
|
options={genders}
|
|
143
|
-
defaultValue={values?.gender ?? null}
|
|
164
|
+
defaultValue={emptyError ? null : values?.gender ?? null}
|
|
165
|
+
{...err}
|
|
144
166
|
searchPlaceholder={copy.gender.searchPlaceholder}
|
|
145
167
|
/* The `dropdown` section is the open Gender menu. */
|
|
146
168
|
forceOpen={state === 'dropdown'}
|
|
147
169
|
/>
|
|
148
170
|
<PrizmaDateField
|
|
149
171
|
label={copy.dateOfBirth.label}
|
|
150
|
-
placeholder={copy.dateOfBirth.placeholder}
|
|
172
|
+
placeholder={ph(copy.dateOfBirth.placeholder)}
|
|
151
173
|
required
|
|
152
174
|
requiredHint={strings.requiredHint}
|
|
153
175
|
calendarLabel={copy.dateOfBirth.calendarLabel}
|
|
154
|
-
defaultValue={values?.dateOfBirth ?? ''}
|
|
176
|
+
defaultValue={emptyError ? '' : values?.dateOfBirth ?? ''}
|
|
177
|
+
{...err}
|
|
155
178
|
/>
|
|
156
179
|
<PrizmaDropdown
|
|
157
180
|
label={copy.birthState.label}
|
|
158
|
-
placeholder={copy.birthState.placeholder}
|
|
181
|
+
placeholder={ph(copy.birthState.placeholder)}
|
|
159
182
|
required
|
|
160
183
|
requiredHint={strings.requiredHint}
|
|
161
184
|
options={states}
|
|
162
|
-
defaultValue={values?.birthState ?? null}
|
|
185
|
+
defaultValue={emptyError ? null : values?.birthState ?? null}
|
|
186
|
+
{...err}
|
|
163
187
|
searchable
|
|
164
188
|
searchPlaceholder={copy.birthState.searchPlaceholder}
|
|
165
189
|
/>
|
package/src/CurpLayout.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* CURP — module layout additions.
|
|
2
2
|
*
|
|
3
|
-
*
|
|
3
|
+
* TWO rules, and none of them declares spacing: the content column, the 24px
|
|
4
4
|
* gutters, the title → fields Spacing/32, the field gaps, the CTA column and
|
|
5
5
|
* the anchored footer all stay the foundation's (`ScreenLayout.css`,
|
|
6
6
|
* `FormScreen.css`). Nothing here re-declares an archetype value, invents a
|
|
@@ -10,40 +10,14 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/* ── The generator's field stack is taller than the screen ───────────────────
|
|
13
|
-
* `CURP.Gene.default` is a 1051-tall frame
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* one or two fields — so the surplus is silently clipped by `ScreenShell`'s
|
|
21
|
-
* `overflow: hidden`, and (because the fields cannot shrink below
|
|
22
|
-
* `--prizma-input-size-field-height`) it first PAINTS OVER the sibling CTA.
|
|
23
|
-
* Screens are authored at 390×844 and never reflow (README / DEVIATIONS #17),
|
|
24
|
-
* so growing the frame is not an option either.
|
|
25
|
-
*
|
|
26
|
-
* The stack is therefore allowed to scroll INSIDE the column: the title, the
|
|
27
|
-
* CTA and the anchored tag stay put and the six fields pan, which is the
|
|
28
|
-
* closest a fixed 844 frame gets to Figma's taller page. It adds NO padding, NO
|
|
29
|
-
* gap and NO size of its own.
|
|
30
|
-
*
|
|
31
|
-
* Applied to EVERY `CURP.Gene.*` section including `dropdown`. The earlier
|
|
32
|
-
* build withheld it from `dropdown` to keep Core's absolutely-positioned menu
|
|
33
|
-
* from being clipped, and that traded one clipped element for a worse one: with
|
|
34
|
-
* `overflow: visible` the 548-tall stack overflowed its box and painted the
|
|
35
|
-
* open menu straight across the "Generate" button, which Figma (2058:16373)
|
|
36
|
-
* draws clear and unobstructed under the menu. The CTA is never allowed to be
|
|
37
|
-
* overlapped; the menu is handled by the next rule instead.
|
|
38
|
-
*
|
|
39
|
-
* FOUNDATION REQUEST: promote this to `FormScreen.css` as a
|
|
40
|
-
* `.prizma-form-screen__fields--scroll` variant (or make overflow the default),
|
|
41
|
-
* driven by a `scrollFields` prop on `PrizmaFormScreen`. Every long-form module
|
|
42
|
-
* still to come in Wave 3 — eKYC, eKYB, address entry — will hit the same wall.
|
|
13
|
+
* `CURP.Gene.default` is a 1051-tall frame (six 78px labelled fields at
|
|
14
|
+
* Spacing/16), so at 390×844 the stack scrolls inside the column. That is the
|
|
15
|
+
* foundation's `scrollFields` on `PrizmaFormScreen` now (FormScreen.css
|
|
16
|
+
* `__fields--scroll`), which also carries the Spacing/16 between the cut and
|
|
17
|
+
* the CTA. The module used to hand-roll `overflow-y: auto` here with no
|
|
18
|
+
* spacing, so the last field ran flush into "Generate" (Elena, 2026-09-30).
|
|
19
|
+
* Removed in favour of the foundation rule.
|
|
43
20
|
*/
|
|
44
|
-
.curp-generate--scroll .prizma-form-screen__fields {
|
|
45
|
-
overflow-y: auto;
|
|
46
|
-
}
|
|
47
21
|
|
|
48
22
|
/* ── The open Gender menu must stay inside the scrolling column ──────────────
|
|
49
23
|
* `CURP.Gene.dropdown` exists to show the three gender rows, so they may not be
|
package/src/CurpStrings.ts
CHANGED
|
@@ -27,16 +27,30 @@
|
|
|
27
27
|
* - `error` — negative field + clear ✕ + the "Invalid CURP" row
|
|
28
28
|
* - `loading` — both actions inert while the lookup runs; the spinner rides the
|
|
29
29
|
* CTA, never the field (the Phone Input lesson, DEVIATIONS #PI-5)
|
|
30
|
+
* - `emptyError` — "Continue" pressed with the field still empty: the field
|
|
31
|
+
* stays empty (no placeholder) in Core's error state with `requiredError`,
|
|
32
|
+
* and the CTA is disabled. GUIDELINES §6-E empty-submit rule (Elena,
|
|
33
|
+
* 2026-09-30).
|
|
30
34
|
*/
|
|
31
|
-
export type CurpEnterState =
|
|
35
|
+
export type CurpEnterState =
|
|
36
|
+
| 'default'
|
|
37
|
+
| 'focused'
|
|
38
|
+
| 'filled'
|
|
39
|
+
| 'error'
|
|
40
|
+
| 'loading'
|
|
41
|
+
| 'emptyError';
|
|
32
42
|
|
|
33
43
|
/**
|
|
34
44
|
* The `CURP.Gene.*` form sections — the six-field generator:
|
|
35
45
|
* - `default` — every field empty on its placeholder
|
|
36
46
|
* - `dropdown` — the Gender menu open over the form (Core's `forceOpen`)
|
|
37
47
|
* - `filled` — every field carrying a value
|
|
48
|
+
* - `emptyError` — "Generate" pressed with the form still empty: every required
|
|
49
|
+
* field stays empty (no placeholder) in Core's error state with
|
|
50
|
+
* `requiredError`, no menu is open, and the CTA is disabled. GUIDELINES §6-E
|
|
51
|
+
* empty-submit rule (Elena, 2026-09-30).
|
|
38
52
|
*/
|
|
39
|
-
export type CurpGenerateState = 'default' | 'dropdown' | 'filled';
|
|
53
|
+
export type CurpGenerateState = 'default' | 'dropdown' | 'filled' | 'emptyError';
|
|
40
54
|
|
|
41
55
|
/**
|
|
42
56
|
* The two spinner sections. `verifying` is `CURP.EnterCURP.veryfing` (the
|
|
@@ -96,6 +110,12 @@ export interface CurpStrings {
|
|
|
96
110
|
* the marker is localizable and never hardcoded in a screen.
|
|
97
111
|
*/
|
|
98
112
|
requiredHint?: string;
|
|
113
|
+
/**
|
|
114
|
+
* Error row under every required field left empty when the primary CTA is
|
|
115
|
+
* pressed (the `emptyError` state of the entry and generator forms):
|
|
116
|
+
* "This field is required". SDK key `dynamicForms.fieldRequired`.
|
|
117
|
+
*/
|
|
118
|
+
requiredError: string;
|
|
99
119
|
|
|
100
120
|
/** CURP.EnterCURP.{default,focused,filled,error,loading} */
|
|
101
121
|
enter: {
|
|
@@ -82,6 +82,13 @@ export interface EkybAddressDetailsScreenProps
|
|
|
82
82
|
* segment 2 solid, segment 3 grey) is Core's `PrizmaStepper` at
|
|
83
83
|
* `currentState={2}`, composed into the archetype's `progress` slot. This is
|
|
84
84
|
* step 2 of 3.
|
|
85
|
+
*
|
|
86
|
+
* `emptyError` is Continue pressed with the fields still empty (Elena,
|
|
87
|
+
* 2026-09-30, GUIDELINES §6-E empty-submit rule; precedent `FormsFieldScreen`'s
|
|
88
|
+
* `emptyError`): every field renders empty, the five REQUIRED ones (State
|
|
89
|
+
* included) in Core's `error` state with `requiredError` and no placeholder,
|
|
90
|
+
* Address line 2 unflagged (optional, DEVIATIONS #EKC-6's rule), and Continue
|
|
91
|
+
* disabled. `empty` keeps Continue enabled so the press can happen.
|
|
85
92
|
*/
|
|
86
93
|
export const EkybAddressDetailsScreen = forwardRef<
|
|
87
94
|
HTMLDivElement,
|
|
@@ -91,9 +98,10 @@ export const EkybAddressDetailsScreen = forwardRef<
|
|
|
91
98
|
{
|
|
92
99
|
strings,
|
|
93
100
|
state = 'empty',
|
|
94
|
-
values,
|
|
101
|
+
values: valuesProp,
|
|
95
102
|
states = [],
|
|
96
103
|
screenId = `ekyb-address-${state}`,
|
|
104
|
+
ctaDisabled,
|
|
97
105
|
className,
|
|
98
106
|
overrides,
|
|
99
107
|
onAction,
|
|
@@ -102,6 +110,14 @@ export const EkybAddressDetailsScreen = forwardRef<
|
|
|
102
110
|
ref,
|
|
103
111
|
) => {
|
|
104
112
|
const copy = strings.address;
|
|
113
|
+
const emptyError = state === 'emptyError';
|
|
114
|
+
const values = emptyError ? undefined : valuesProp;
|
|
115
|
+
// Core's own error treatment, spread AFTER each required field's own
|
|
116
|
+
// placeholder so the error state shows none (the `FormsFieldScreen`
|
|
117
|
+
// precedent). Address line 2 never receives it.
|
|
118
|
+
const missing = emptyError
|
|
119
|
+
? { error: true, errorText: strings.requiredError, placeholder: undefined }
|
|
120
|
+
: {};
|
|
105
121
|
|
|
106
122
|
return (
|
|
107
123
|
<PrizmaFormScreen
|
|
@@ -122,6 +138,8 @@ export const EkybAddressDetailsScreen = forwardRef<
|
|
|
122
138
|
title={copy.title}
|
|
123
139
|
subtitle={copy.subtitle}
|
|
124
140
|
ctaLabel={copy.ctaLabel}
|
|
141
|
+
/* Disabled only after the empty submit; `empty` keeps it enabled. */
|
|
142
|
+
ctaDisabled={emptyError || ctaDisabled}
|
|
125
143
|
linkContent={
|
|
126
144
|
<PrizmaButton
|
|
127
145
|
variant="secondary"
|
|
@@ -136,17 +154,20 @@ export const EkybAddressDetailsScreen = forwardRef<
|
|
|
136
154
|
screenId={screenId}
|
|
137
155
|
overrides={{ align: overrides?.align ?? 'left', logo: overrides?.logo }}
|
|
138
156
|
onAction={onAction}
|
|
139
|
-
/* Exploration ekyb-desktop: on a wide frame
|
|
140
|
-
|
|
141
|
-
|
|
157
|
+
/* Exploration ekyb-desktop: on a wide frame the fields pair up in
|
|
158
|
+
three rows, Street + House number, Address line 2 + City (Elena,
|
|
159
|
+
2026-09-28), and State + Postal code (Figma 6407:43637). On the
|
|
160
|
+
phone nothing changes. */
|
|
142
161
|
responsive
|
|
143
162
|
{...shell}
|
|
144
163
|
>
|
|
164
|
+
<PrizmaFormRow>
|
|
145
165
|
<PrizmaTextField
|
|
146
166
|
label={copy.street.label}
|
|
147
167
|
placeholder={copy.street.placeholder}
|
|
148
168
|
required
|
|
149
169
|
requiredHint={strings.requiredHint}
|
|
170
|
+
{...missing}
|
|
150
171
|
autoComplete="off"
|
|
151
172
|
defaultValue={values?.street ?? ''}
|
|
152
173
|
/>
|
|
@@ -155,9 +176,12 @@ export const EkybAddressDetailsScreen = forwardRef<
|
|
|
155
176
|
placeholder={copy.houseNumber.placeholder}
|
|
156
177
|
required
|
|
157
178
|
requiredHint={strings.requiredHint}
|
|
179
|
+
{...missing}
|
|
158
180
|
autoComplete="off"
|
|
159
181
|
defaultValue={values?.houseNumber ?? ''}
|
|
160
182
|
/>
|
|
183
|
+
</PrizmaFormRow>
|
|
184
|
+
<PrizmaFormRow>
|
|
161
185
|
{/* The one field 6340:50731 draws without an asterisk. */}
|
|
162
186
|
<PrizmaTextField
|
|
163
187
|
label={copy.addressLine2.label}
|
|
@@ -170,15 +194,18 @@ export const EkybAddressDetailsScreen = forwardRef<
|
|
|
170
194
|
placeholder={copy.city.placeholder}
|
|
171
195
|
required
|
|
172
196
|
requiredHint={strings.requiredHint}
|
|
197
|
+
{...missing}
|
|
173
198
|
autoComplete="off"
|
|
174
199
|
defaultValue={values?.city ?? ''}
|
|
175
200
|
/>
|
|
201
|
+
</PrizmaFormRow>
|
|
176
202
|
<PrizmaFormRow>
|
|
177
203
|
<PrizmaDropdown
|
|
178
204
|
label={copy.state.label}
|
|
179
205
|
placeholder={copy.state.placeholder}
|
|
180
206
|
required
|
|
181
207
|
requiredHint={strings.requiredHint}
|
|
208
|
+
{...missing}
|
|
182
209
|
options={states}
|
|
183
210
|
/* Both sections draw the placeholder unless the host supplies a
|
|
184
211
|
value — see the docstring note on 6340:38197. */
|
|
@@ -193,6 +220,7 @@ export const EkybAddressDetailsScreen = forwardRef<
|
|
|
193
220
|
placeholder={copy.postalCode.placeholder}
|
|
194
221
|
required
|
|
195
222
|
requiredHint={strings.requiredHint}
|
|
223
|
+
{...missing}
|
|
196
224
|
autoComplete="off"
|
|
197
225
|
defaultValue={values?.postalCode ?? ''}
|
|
198
226
|
/>
|