@incodetech/prizma-core-screens 0.1.2 → 0.2.3
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/DemoScreensConfigScreen.d.ts +36 -0
- package/dist/DemoScreensConfigScreen.js +30 -0
- package/dist/DemoScreensConfigSheetScreen.d.ts +39 -0
- package/dist/DemoScreensConfigSheetScreen.js +33 -0
- package/dist/DemoScreensEditSheetScreen.d.ts +30 -0
- package/dist/DemoScreensEditSheetScreen.js +28 -0
- package/dist/DemoScreensEndScreen.d.ts +9 -21
- package/dist/DemoScreensEndScreen.js +9 -14
- package/dist/DemoScreensLaunchScreen.d.ts +28 -0
- package/dist/DemoScreensLaunchScreen.js +26 -0
- package/dist/DemoScreensLayout.css +542 -0
- package/dist/DemoScreensRedirectScreen.d.ts +50 -0
- package/dist/DemoScreensRedirectScreen.js +38 -0
- package/dist/DemoScreensResultScreen.d.ts +52 -0
- package/dist/DemoScreensResultScreen.js +46 -0
- package/dist/DemoScreensRunningScreen.d.ts +22 -0
- package/dist/DemoScreensRunningScreen.js +16 -0
- package/dist/DemoScreensSettingsScreen.d.ts +37 -0
- package/dist/DemoScreensSettingsScreen.js +40 -0
- package/dist/DemoScreensSplashScreen.d.ts +27 -0
- package/dist/DemoScreensSplashScreen.js +25 -0
- package/dist/DemoScreensStartScreen.d.ts +38 -0
- package/dist/DemoScreensStartScreen.js +37 -0
- package/dist/DemoScreensStrings.d.ts +192 -0
- package/dist/DemoScreensStrings.js +11 -11
- package/dist/DemoScreensTermsScreen.d.ts +28 -0
- package/dist/DemoScreensTermsScreen.js +26 -0
- package/dist/EkybAddressDetailsScreen.js +9 -5
- package/dist/EkybBusinessDetailsScreen.js +6 -3
- package/dist/EkybOwnersScreen.d.ts +4 -0
- package/dist/EkybOwnersScreen.js +13 -5
- package/dist/EkybStrings.d.ts +12 -1
- package/dist/EkycCountryCatalog.d.ts +46 -0
- package/dist/EkycCountryCatalog.js +139 -0
- package/dist/EkycCountryFormScreen.d.ts +36 -0
- package/dist/EkycCountryFormScreen.js +94 -0
- package/dist/EkycDetailsScreen.js +11 -4
- package/dist/EkycLayout.css +23 -0
- package/dist/EkycLicenseScreen.js +7 -3
- package/dist/EkycStrings.d.ts +26 -0
- package/dist/EmailInputStrings.d.ts +11 -1
- package/dist/FaceMatchComparisonScreen.d.ts +4 -2
- package/dist/FaceMatchComparisonScreen.js +3 -1
- package/dist/FaceMatchLayout.css +53 -3
- package/dist/FormScreen.css +74 -0
- package/dist/FormScreen.d.ts +17 -0
- package/dist/FormScreen.js +12 -1
- package/dist/PhoneInputStrings.d.ts +10 -1
- package/dist/index.d.ts +15 -2
- package/dist/index.js +13 -0
- package/dist/styles.css +1 -0
- package/package.json +62 -1
- package/src/DemoScreensConfigScreen.tsx +101 -0
- package/src/DemoScreensConfigSheetScreen.tsx +120 -0
- package/src/DemoScreensEditSheetScreen.tsx +103 -0
- package/src/DemoScreensEndScreen.tsx +14 -38
- package/src/DemoScreensLaunchScreen.tsx +96 -0
- package/src/DemoScreensLayout.css +542 -0
- package/src/DemoScreensRedirectScreen.tsx +190 -0
- package/src/DemoScreensResultScreen.tsx +115 -0
- package/src/DemoScreensRunningScreen.tsx +45 -0
- package/src/DemoScreensSettingsScreen.tsx +101 -0
- package/src/DemoScreensSplashScreen.tsx +47 -0
- package/src/DemoScreensStartScreen.tsx +105 -0
- package/src/DemoScreensStrings.ts +204 -11
- package/src/DemoScreensTermsScreen.tsx +82 -0
- package/src/EkybAddressDetailsScreen.tsx +7 -1
- package/src/EkybBusinessDetailsScreen.tsx +6 -1
- package/src/EkybOwnersScreen.tsx +46 -2
- package/src/EkybStrings.ts +12 -0
- package/src/EkycCountryCatalog.ts +199 -0
- package/src/EkycCountryFormScreen.tsx +184 -0
- package/src/EkycDetailsScreen.tsx +29 -20
- package/src/EkycLayout.css +23 -0
- package/src/EkycLicenseScreen.tsx +22 -16
- package/src/EkycStrings.ts +25 -0
- package/src/EmailInputStrings.ts +11 -1
- package/src/FaceMatchComparisonScreen.tsx +11 -3
- package/src/FaceMatchLayout.css +53 -3
- package/src/FormScreen.css +74 -0
- package/src/FormScreen.tsx +27 -1
- package/src/PhoneInputStrings.ts +10 -1
- package/src/index.ts +65 -1
- package/src/styles.css +1 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import React, { forwardRef, type ReactNode } from 'react';
|
|
2
|
+
import { PrizmaButton } from '@incodetech/prizma-core-web/button';
|
|
3
|
+
import { PrizmaTitle } from '@incodetech/prizma-core-web/title';
|
|
4
|
+
import { PrizmaDisclaimer } from '@incodetech/prizma-core-web/disclaimer';
|
|
5
|
+
import { PrizmaTag } from '@incodetech/prizma-core-web/tag';
|
|
6
|
+
import { PrizmaSnackbar } from '@incodetech/prizma-core-web/snackbar';
|
|
7
|
+
import { PrizmaCombined, type PrizmaCountry } from '@incodetech/prizma-core-web/combined';
|
|
8
|
+
import { PrizmaScreenShell, type PrizmaScreenShellProps } from './ScreenShell';
|
|
9
|
+
import { PrizmaScreenNav } from './ScreenNav';
|
|
10
|
+
import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
|
|
11
|
+
import type { DemoScreensStrings } from './DemoScreensStrings';
|
|
12
|
+
import './ScreenLayout.css';
|
|
13
|
+
import './DemoScreensLayout.css';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Where the redirect page is in its life:
|
|
17
|
+
* - `qr` the QR tab (or the QR-only page)
|
|
18
|
+
* - `sms` the SMS tab, number not typed yet
|
|
19
|
+
* - `smsFilled` the SMS tab, number typed, Send live
|
|
20
|
+
* - `sent` "Link sent!", resend counting down
|
|
21
|
+
* - `resend` "Link sent!", resend available
|
|
22
|
+
* - `resent` "Link sent!" with the "resent" snackbar
|
|
23
|
+
* - `tooMany` "Too many attempts"
|
|
24
|
+
*/
|
|
25
|
+
export type DemoScreensRedirectStage = 'qr' | 'sms' | 'smsFilled' | 'sent' | 'resend' | 'resent' | 'tooMany';
|
|
26
|
+
|
|
27
|
+
export interface DemoScreensRedirectScreenProps
|
|
28
|
+
extends Omit<PrizmaScreenShellProps, 'dark' | 'title' | 'children'> {
|
|
29
|
+
/** Family copy — this screen reads the `redirect` slice. */
|
|
30
|
+
strings: DemoScreensStrings;
|
|
31
|
+
stage?: DemoScreensRedirectStage;
|
|
32
|
+
/** Offer the SMS tab. Off: the `QR Only` section (4272:11388). Default on. */
|
|
33
|
+
sms?: boolean;
|
|
34
|
+
/** Offer "or · Continue on desktop" under the leg. Default on. */
|
|
35
|
+
desktop?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The QR image — a host slot, like every photo on a mock. The screens
|
|
38
|
+
* package draws no QR of its own (it has no encoder and no URL to encode);
|
|
39
|
+
* the hub passes a real one for its sample link.
|
|
40
|
+
*/
|
|
41
|
+
qr?: ReactNode;
|
|
42
|
+
screenId?: string;
|
|
43
|
+
overrides?: PrizmaScreenOverrides;
|
|
44
|
+
onAction?: PrizmaScreenActionHandler;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Demo screens · DESKTOP — the redirect page, `Redirect` (4272:11166) in
|
|
49
|
+
* `Demo App - Latest Design`: a desktop browser opened the link, and the page
|
|
50
|
+
* offers to move the session to a phone. One card centred in the window: the
|
|
51
|
+
* logo nav, a title block, two tabs (Scan QR · Send SMS), the leg's own
|
|
52
|
+
* content, then "or" and a secondary "Continue on desktop", and the tag.
|
|
53
|
+
*
|
|
54
|
+
* Authored at the card's width — 800 on the frame, the content column 752 —
|
|
55
|
+
* so it is the one screen in the family that is not a 390 column; Core Lab
|
|
56
|
+
* lays it on the desktop panel with `adapt.column`. Archetype F's band and
|
|
57
|
+
* footer supply the CTA rhythm; the card, the tabs and the QR well are the
|
|
58
|
+
* page's own (DEVIATIONS #GEN-15 for the tabs — Core has no Tabs yet).
|
|
59
|
+
*/
|
|
60
|
+
export const DemoScreensRedirectScreen = forwardRef<HTMLDivElement, DemoScreensRedirectScreenProps>(
|
|
61
|
+
(
|
|
62
|
+
{
|
|
63
|
+
strings,
|
|
64
|
+
stage = 'qr',
|
|
65
|
+
sms = true,
|
|
66
|
+
desktop = true,
|
|
67
|
+
qr,
|
|
68
|
+
screenId = `demo-screens-redirect-${stage}${sms ? '' : '-qr-only'}${desktop ? '' : '-no-desktop'}`,
|
|
69
|
+
overrides,
|
|
70
|
+
onAction,
|
|
71
|
+
className,
|
|
72
|
+
...shell
|
|
73
|
+
},
|
|
74
|
+
ref,
|
|
75
|
+
) => {
|
|
76
|
+
const r = strings.redirect;
|
|
77
|
+
const onSms = stage !== 'qr';
|
|
78
|
+
const country: PrizmaCountry | undefined = [
|
|
79
|
+
{ code: 'RS', name: 'Serbia', dialCode: '+381', flag: '' },
|
|
80
|
+
].find(c => c.code === r.countryCode);
|
|
81
|
+
const subtitle = sms ? r.subtitle : desktop ? r.subtitleQrDesktop : r.subtitleQrOnly;
|
|
82
|
+
const verdict = stage === 'sent' || stage === 'resend' || stage === 'resent' || stage === 'tooMany';
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<PrizmaScreenShell
|
|
86
|
+
ref={ref}
|
|
87
|
+
data-screen-id={screenId}
|
|
88
|
+
className={['demo-screens-redirect', className ?? ''].filter(Boolean).join(' ')}
|
|
89
|
+
{...shell}
|
|
90
|
+
>
|
|
91
|
+
{stage === 'resent' ? (
|
|
92
|
+
<div className="demo-screens-toast demo-screens-toast--desktop">
|
|
93
|
+
<PrizmaSnackbar state="success">{r.sent.resentSnackbar}</PrizmaSnackbar>
|
|
94
|
+
</div>
|
|
95
|
+
) : null}
|
|
96
|
+
<div className="demo-screens-redirect__card">
|
|
97
|
+
<PrizmaScreenNav logo={overrides?.logo} navLabel={strings.navLabel} />
|
|
98
|
+
<div className="prizma-screen-layout__content demo-screens-redirect__content">
|
|
99
|
+
<PrizmaTitle variant="centered" title={r.title} showSubtitle subtitle={subtitle} />
|
|
100
|
+
{sms ? (
|
|
101
|
+
<div className="demo-screens-tabs" role="tablist">
|
|
102
|
+
<button type="button" role="tab" aria-selected={!onSms} className={['demo-screens-tabs__tab', !onSms ? 'demo-screens-tabs__tab--active' : ''].join(' ')} onClick={() => onAction?.({ type: 'secondary', screenId })}>
|
|
103
|
+
{r.tabs.qr}
|
|
104
|
+
</button>
|
|
105
|
+
<button type="button" role="tab" aria-selected={onSms} className={['demo-screens-tabs__tab', onSms ? 'demo-screens-tabs__tab--active' : ''].join(' ')} onClick={() => onAction?.({ type: 'tertiary', screenId })}>
|
|
106
|
+
{r.tabs.sms}
|
|
107
|
+
</button>
|
|
108
|
+
</div>
|
|
109
|
+
) : null}
|
|
110
|
+
|
|
111
|
+
{stage === 'qr' ? (
|
|
112
|
+
<div className="demo-screens-redirect__leg">
|
|
113
|
+
{sms ? <p className="demo-screens-redirect__hint">{r.qrHint}</p> : null}
|
|
114
|
+
<div className="demo-screens-redirect__qr" aria-label={r.tabs.qr}>{qr}</div>
|
|
115
|
+
</div>
|
|
116
|
+
) : null}
|
|
117
|
+
|
|
118
|
+
{stage === 'sms' || stage === 'smsFilled' ? (
|
|
119
|
+
<div className="demo-screens-redirect__leg demo-screens-redirect__leg--form">
|
|
120
|
+
<p className="demo-screens-redirect__hint">{r.smsHint}</p>
|
|
121
|
+
{/* `defaultValue`, not `readOnly`: Core paints a read-only field
|
|
122
|
+
on the disabled surface (owner definition 2026-07-12), and
|
|
123
|
+
the frame shows a live, empty field — Elena caught the grey
|
|
124
|
+
selector on 2026-09-24. */}
|
|
125
|
+
<PrizmaCombined
|
|
126
|
+
key={stage}
|
|
127
|
+
aria-label={r.phoneLabel}
|
|
128
|
+
placeholder={r.phonePlaceholder}
|
|
129
|
+
defaultValue={stage === 'smsFilled' ? r.phoneValue : ''}
|
|
130
|
+
defaultCountry={country}
|
|
131
|
+
showRequiredMarker={false}
|
|
132
|
+
/>
|
|
133
|
+
<PrizmaButton variant="primary" size="L" disabled={stage !== 'smsFilled'} onClick={() => onAction?.({ type: 'cta', screenId })}>
|
|
134
|
+
{r.sendLabel}
|
|
135
|
+
</PrizmaButton>
|
|
136
|
+
</div>
|
|
137
|
+
) : null}
|
|
138
|
+
|
|
139
|
+
{verdict ? (
|
|
140
|
+
<div className="demo-screens-redirect__leg demo-screens-redirect__leg--verdict">
|
|
141
|
+
{stage === 'tooMany' ? (
|
|
142
|
+
<PrizmaTitle variant="centered" title={r.tooMany.title} showSubtitle subtitle={r.tooMany.subtitle} icon={{ type: 'status', status: 'error' }} />
|
|
143
|
+
) : (
|
|
144
|
+
<PrizmaTitle
|
|
145
|
+
variant="centered"
|
|
146
|
+
title={r.sent.title}
|
|
147
|
+
showSubtitle
|
|
148
|
+
subtitle={`${r.sent.toPrefix} ${country?.dialCode ?? ''} ${r.phoneValue}`.trim()}
|
|
149
|
+
icon={{ type: 'status', status: 'success' }}
|
|
150
|
+
/>
|
|
151
|
+
)}
|
|
152
|
+
{stage === 'tooMany' ? (
|
|
153
|
+
<PrizmaButton variant="tertiary-link" size="L" onClick={() => onAction?.({ type: 'tertiary', screenId })}>
|
|
154
|
+
{r.tooMany.changeLabel}
|
|
155
|
+
</PrizmaButton>
|
|
156
|
+
) : stage === 'sent' || stage === 'resent' ? (
|
|
157
|
+
<PrizmaButton variant="tertiary-link" size="L" disabled>
|
|
158
|
+
{r.sent.resendIn}
|
|
159
|
+
</PrizmaButton>
|
|
160
|
+
) : (
|
|
161
|
+
<PrizmaButton variant="tertiary-link" size="L" onClick={() => onAction?.({ type: 'cta', screenId })}>
|
|
162
|
+
{r.sent.resend}
|
|
163
|
+
</PrizmaButton>
|
|
164
|
+
)}
|
|
165
|
+
</div>
|
|
166
|
+
) : null}
|
|
167
|
+
</div>
|
|
168
|
+
<div className="prizma-screen-layout__band demo-screens-redirect__band">
|
|
169
|
+
{desktop && !verdict ? (
|
|
170
|
+
<>
|
|
171
|
+
<PrizmaDisclaimer text={r.orLabel} />
|
|
172
|
+
<div className="prizma-screen-layout__band__ctas">
|
|
173
|
+
<PrizmaButton variant="secondary" size="L" onClick={() => onAction?.({ type: 'secondary', screenId })}>
|
|
174
|
+
{r.desktopLabel}
|
|
175
|
+
</PrizmaButton>
|
|
176
|
+
</div>
|
|
177
|
+
</>
|
|
178
|
+
) : null}
|
|
179
|
+
<div className="prizma-screen-layout__band__tag">
|
|
180
|
+
<PrizmaTag label={strings.verifiedLabel} />
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</PrizmaScreenShell>
|
|
185
|
+
);
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
DemoScreensRedirectScreen.displayName = 'DemoScreensRedirectScreen';
|
|
189
|
+
|
|
190
|
+
export default DemoScreensRedirectScreen;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { PrizmaResultScreen, type PrizmaResultScreenProps } from './ResultScreen';
|
|
3
|
+
import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
|
|
4
|
+
import type { DemoScreensStrings } from './DemoScreensStrings';
|
|
5
|
+
import './ScreenLayout.css';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The four ways a demo session ends. Named after what the BACKEND says, not
|
|
9
|
+
* after the colour the screen shows, so a host maps its session status straight
|
|
10
|
+
* onto this prop:
|
|
11
|
+
*
|
|
12
|
+
* - `approved` the session passed → green mark, no CTA
|
|
13
|
+
* - `rejected` it did not pass verification → red mark, restart CTA
|
|
14
|
+
* - `inReview` a human still has to decide → no mark, no CTA
|
|
15
|
+
* - `notCompleted` the flow broke before a verdict → red mark, restart CTA
|
|
16
|
+
*
|
|
17
|
+
* Marks and CTAs follow the Demo App dev's spec (2026-09-24, via Elena): a
|
|
18
|
+
* passed session has nowhere to go, so no Restart; a rejection and a broken
|
|
19
|
+
* flow both offer one; a pending review shows neither. The production frames
|
|
20
|
+
* differ in two places (Restart on approved; no mark on not completed) and
|
|
21
|
+
* are superseded by that spec — DEVIATIONS #GEN-14.
|
|
22
|
+
*/
|
|
23
|
+
export type DemoScreensResultStatus = 'approved' | 'rejected' | 'inReview' | 'notCompleted';
|
|
24
|
+
|
|
25
|
+
export interface DemoScreensResultScreenProps
|
|
26
|
+
extends Omit<
|
|
27
|
+
PrizmaResultScreenProps,
|
|
28
|
+
'status' | 'title' | 'subtitle' | 'glyph' | 'ctaLabel' | 'verifiedLabel' | 'navLabel'
|
|
29
|
+
> {
|
|
30
|
+
/** Family copy — this screen reads `result`, `end` and `notCompleted`. */
|
|
31
|
+
strings: DemoScreensStrings;
|
|
32
|
+
status: DemoScreensResultStatus;
|
|
33
|
+
/**
|
|
34
|
+
* Draw the restart CTA. Defaults per status (the verdicts have it, the two
|
|
35
|
+
* end screens do not); a host that wants a way out of an in-review screen,
|
|
36
|
+
* or none out of a rejection, says so here.
|
|
37
|
+
*/
|
|
38
|
+
showRestart?: boolean;
|
|
39
|
+
screenId?: string;
|
|
40
|
+
overrides?: PrizmaScreenOverrides;
|
|
41
|
+
onAction?: PrizmaScreenActionHandler;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const MARK: Record<DemoScreensResultStatus, PrizmaResultScreenProps['status']> = {
|
|
45
|
+
approved: 'success',
|
|
46
|
+
rejected: 'error',
|
|
47
|
+
// No mark while a human decides: a tick or a cross here would claim a
|
|
48
|
+
// verdict the session never reached.
|
|
49
|
+
inReview: 'none',
|
|
50
|
+
// A broken flow reads as an error, not as a pending result (dev spec).
|
|
51
|
+
notCompleted: 'error',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const RESTART_BY_DEFAULT: Record<DemoScreensResultStatus, boolean> = {
|
|
55
|
+
approved: false,
|
|
56
|
+
rejected: true,
|
|
57
|
+
inReview: false,
|
|
58
|
+
notCompleted: true,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Demo screens — the end of a session, on the Result archetype
|
|
63
|
+
* (GUIDELINES §6-F, `PrizmaResultScreen`).
|
|
64
|
+
*
|
|
65
|
+
* Figma:
|
|
66
|
+
* `approved` `demo_7` (2010:5745) "Thank you!" · green mark
|
|
67
|
+
* `rejected` `demo_8` (2010:5808) "Verification failed" · red mark · Restart
|
|
68
|
+
* `inReview` `63:399` "Verification complete!" · bare title
|
|
69
|
+
* `notCompleted` "DemoApp: End Screens" › `Processnotcompleted` · red mark · Restart
|
|
70
|
+
*
|
|
71
|
+
* One component for the four because they are one screen with one axis: the
|
|
72
|
+
* host learns the session status and passes it through. `DemoScreensEndScreen`
|
|
73
|
+
* stays exported as the `inReview` case under its original name.
|
|
74
|
+
*/
|
|
75
|
+
export const DemoScreensResultScreen = forwardRef<HTMLDivElement, DemoScreensResultScreenProps>(
|
|
76
|
+
(
|
|
77
|
+
{
|
|
78
|
+
strings,
|
|
79
|
+
status,
|
|
80
|
+
showRestart = RESTART_BY_DEFAULT[status],
|
|
81
|
+
screenId = `demo-screens-result-${status}`,
|
|
82
|
+
overrides,
|
|
83
|
+
onAction,
|
|
84
|
+
...shell
|
|
85
|
+
},
|
|
86
|
+
ref,
|
|
87
|
+
) => {
|
|
88
|
+
const copy =
|
|
89
|
+
status === 'approved'
|
|
90
|
+
? strings.result.approved
|
|
91
|
+
: status === 'rejected'
|
|
92
|
+
? strings.result.rejected
|
|
93
|
+
: status === 'inReview'
|
|
94
|
+
? strings.end
|
|
95
|
+
: strings.notCompleted;
|
|
96
|
+
return (
|
|
97
|
+
<PrizmaResultScreen
|
|
98
|
+
ref={ref}
|
|
99
|
+
status={MARK[status]}
|
|
100
|
+
title={copy.title}
|
|
101
|
+
subtitle={copy.subtitle}
|
|
102
|
+
ctaLabel={showRestart ? strings.result.restartLabel : undefined}
|
|
103
|
+
verifiedLabel={strings.verifiedLabel}
|
|
104
|
+
navLabel={strings.navLabel}
|
|
105
|
+
screenId={screenId}
|
|
106
|
+
overrides={overrides}
|
|
107
|
+
onAction={onAction}
|
|
108
|
+
{...shell}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
DemoScreensResultScreen.displayName = 'DemoScreensResultScreen';
|
|
114
|
+
|
|
115
|
+
export default DemoScreensResultScreen;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { PrizmaProcessingScreen, type PrizmaProcessingScreenProps } from './ProcessingScreen';
|
|
3
|
+
import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
|
|
4
|
+
import type { DemoScreensStrings } from './DemoScreensStrings';
|
|
5
|
+
import './ScreenLayout.css';
|
|
6
|
+
|
|
7
|
+
export interface DemoScreensRunningScreenProps
|
|
8
|
+
extends Omit<
|
|
9
|
+
PrizmaProcessingScreenProps,
|
|
10
|
+
'status' | 'title' | 'subtitle' | 'verifiedLabel' | 'navLabel'
|
|
11
|
+
> {
|
|
12
|
+
/** Family copy — this screen reads the `running` slice. */
|
|
13
|
+
strings: DemoScreensStrings;
|
|
14
|
+
screenId?: string;
|
|
15
|
+
overrides?: PrizmaScreenOverrides;
|
|
16
|
+
onAction?: PrizmaScreenActionHandler;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Demo screens — "Hold on a sec…", `demo_6` (2010:6180): the wait while the
|
|
21
|
+
* session is scored, between the last module and the verdict.
|
|
22
|
+
*
|
|
23
|
+
* Archetype C (`PrizmaProcessingScreen`, GUIDELINES §6-C) in its pure form:
|
|
24
|
+
* spinner, title, one line under it, the tag. No CTA — there is nothing for
|
|
25
|
+
* the prospect to do but wait, and the frame draws no button.
|
|
26
|
+
*/
|
|
27
|
+
export const DemoScreensRunningScreen = forwardRef<HTMLDivElement, DemoScreensRunningScreenProps>(
|
|
28
|
+
({ strings, screenId = 'demo-screens-running', overrides, onAction, ...shell }, ref) => (
|
|
29
|
+
<PrizmaProcessingScreen
|
|
30
|
+
ref={ref}
|
|
31
|
+
status="loading"
|
|
32
|
+
title={strings.running.title}
|
|
33
|
+
subtitle={strings.running.subtitle}
|
|
34
|
+
verifiedLabel={strings.verifiedLabel}
|
|
35
|
+
navLabel={strings.navLabel}
|
|
36
|
+
screenId={screenId}
|
|
37
|
+
overrides={overrides}
|
|
38
|
+
onAction={onAction}
|
|
39
|
+
{...shell}
|
|
40
|
+
/>
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
|
+
DemoScreensRunningScreen.displayName = 'DemoScreensRunningScreen';
|
|
44
|
+
|
|
45
|
+
export default DemoScreensRunningScreen;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { PrizmaButton } from '@incodetech/prizma-core-web/button';
|
|
3
|
+
import { PrizmaTitle } from '@incodetech/prizma-core-web/title';
|
|
4
|
+
import { PrizmaNavigation } from '@incodetech/prizma-core-web/navigation';
|
|
5
|
+
import { PrizmaDropdown, type PrizmaDropdownOption } from '@incodetech/prizma-core-web/dropdown';
|
|
6
|
+
import { PrizmaCountryFlag } from '@incodetech/prizma-core-web/combined';
|
|
7
|
+
import { PrizmaScreenShell, type PrizmaScreenShellProps } from './ScreenShell';
|
|
8
|
+
import type { PrizmaScreenActionHandler } from './types';
|
|
9
|
+
import type { DemoScreensStrings } from './DemoScreensStrings';
|
|
10
|
+
import './ScreenLayout.css';
|
|
11
|
+
import './DemoScreensLayout.css';
|
|
12
|
+
|
|
13
|
+
export interface DemoScreensSettingsScreenProps
|
|
14
|
+
extends Omit<PrizmaScreenShellProps, 'dark' | 'title' | 'children'> {
|
|
15
|
+
/** Family copy — this screen reads the `settings` slice. */
|
|
16
|
+
strings: DemoScreensStrings;
|
|
17
|
+
/** The selected language, by `DemoScreensLanguage.value`. Defaults to the
|
|
18
|
+
* first one listed. */
|
|
19
|
+
value?: string;
|
|
20
|
+
/** Documentation-only: render the language menu open (`demo_4`). */
|
|
21
|
+
menuOpen?: boolean;
|
|
22
|
+
screenId?: string;
|
|
23
|
+
onAction?: PrizmaScreenActionHandler;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Demo screens — the settings sheet, `demo_3` (2010:6002) closed and `demo_4`
|
|
28
|
+
* (2010:6060) with the language menu open, in `Demo App - Latest Design`.
|
|
29
|
+
*
|
|
30
|
+
* Core's Navigation with the logo off and the close X on, a left-aligned H2,
|
|
31
|
+
* one searchable Dropdown, one CTA. No verified tag — the frame draws none on
|
|
32
|
+
* a settings surface.
|
|
33
|
+
*
|
|
34
|
+
* Archetype E (`PrizmaFormScreen`) is the near miss: it insists on the logo nav
|
|
35
|
+
* (or its reserved row) and has no close affordance, and the frame has neither
|
|
36
|
+
* a logo nor a back chevron. So the shell is composed here with the same
|
|
37
|
+
* layout classes E uses; the Spacing/32 between the title and the field is the
|
|
38
|
+
* one measure the file adds (`DemoScreensLayout.css`).
|
|
39
|
+
*
|
|
40
|
+
* Flags: the option rows draw the canonical raster where the bank has one
|
|
41
|
+
* (`US`, `RS`); rows without one draw the label alone rather than an emoji
|
|
42
|
+
* (DEVIATIONS #GEN-8 — Mexico and Spain are missing from the bank).
|
|
43
|
+
*/
|
|
44
|
+
export const DemoScreensSettingsScreen = forwardRef<HTMLDivElement, DemoScreensSettingsScreenProps>(
|
|
45
|
+
(
|
|
46
|
+
{ strings, value, menuOpen = false, screenId = 'demo-screens-settings', onAction, ...shell },
|
|
47
|
+
ref,
|
|
48
|
+
) => {
|
|
49
|
+
const { settings } = strings;
|
|
50
|
+
const options: PrizmaDropdownOption[] = settings.languages.map(l => ({ value: l.value, label: l.label }));
|
|
51
|
+
const flagFor = (option: PrizmaDropdownOption) => {
|
|
52
|
+
const lang = settings.languages.find(l => l.value === option.value);
|
|
53
|
+
return lang?.countryCode ? (
|
|
54
|
+
<PrizmaCountryFlag
|
|
55
|
+
country={{ code: lang.countryCode, name: lang.label, dialCode: '', flag: '' }}
|
|
56
|
+
/>
|
|
57
|
+
) : null;
|
|
58
|
+
};
|
|
59
|
+
return (
|
|
60
|
+
<PrizmaScreenShell ref={ref} data-screen-id={screenId} {...shell}>
|
|
61
|
+
<div className="demo-screens-settings__nav">
|
|
62
|
+
<PrizmaNavigation
|
|
63
|
+
showIncodeLogo={false}
|
|
64
|
+
showRightIcon
|
|
65
|
+
closeLabel={settings.closeLabel}
|
|
66
|
+
onRightIconClick={() => onAction?.({ type: 'help', screenId })}
|
|
67
|
+
aria-label={strings.navLabel}
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
<div className="prizma-screen-layout__content">
|
|
71
|
+
<PrizmaTitle variant="left" title={settings.title} />
|
|
72
|
+
<div className="demo-screens-settings__fields">
|
|
73
|
+
<PrizmaDropdown
|
|
74
|
+
label={settings.languageLabel}
|
|
75
|
+
options={options}
|
|
76
|
+
defaultValue={value ?? settings.languages[0]?.value ?? null}
|
|
77
|
+
showRequiredMarker={false}
|
|
78
|
+
searchable
|
|
79
|
+
searchPlaceholder={settings.searchPlaceholder}
|
|
80
|
+
clearSearchLabel={settings.clearSearchLabel}
|
|
81
|
+
renderLeading={flagFor}
|
|
82
|
+
forceOpen={menuOpen}
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
{/* Archetype F's CTA band in its `--bare` form — no tag on a settings
|
|
87
|
+
sheet, so the button sits Spacing/24 off the bottom. */}
|
|
88
|
+
<div className="prizma-screen-layout__band prizma-screen-layout__band--bare demo-screens-band">
|
|
89
|
+
<div className="prizma-screen-layout__band__ctas">
|
|
90
|
+
<PrizmaButton variant="primary" size="L" onClick={() => onAction?.({ type: 'cta', screenId })}>
|
|
91
|
+
{settings.ctaLabel}
|
|
92
|
+
</PrizmaButton>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</PrizmaScreenShell>
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
);
|
|
99
|
+
DemoScreensSettingsScreen.displayName = 'DemoScreensSettingsScreen';
|
|
100
|
+
|
|
101
|
+
export default DemoScreensSettingsScreen;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { PrizmaLogo } from '@incodetech/prizma-core-web/logo';
|
|
3
|
+
import { PrizmaScreenShell, type PrizmaScreenShellProps } from './ScreenShell';
|
|
4
|
+
import type { DemoScreensStrings } from './DemoScreensStrings';
|
|
5
|
+
import './ScreenLayout.css';
|
|
6
|
+
import './DemoScreensLayout.css';
|
|
7
|
+
|
|
8
|
+
export interface DemoScreensSplashScreenProps
|
|
9
|
+
extends Omit<PrizmaScreenShellProps, 'dark' | 'title' | 'children'> {
|
|
10
|
+
/** Family copy — this screen reads `appName`. */
|
|
11
|
+
strings: DemoScreensStrings;
|
|
12
|
+
screenId?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Demo screens — the splash, `demo_1` (2010:5868) in `Demo App - Latest Design`.
|
|
17
|
+
*
|
|
18
|
+
* The brand moment before the front door: the whole stage is Surface/Brand/500,
|
|
19
|
+
* the wordmark and the app name sit white in the middle. No nav, no CTA, no
|
|
20
|
+
* verified tag — the frame draws none, and there is nothing to verify yet.
|
|
21
|
+
*
|
|
22
|
+
* Not an archetype (GUIDELINES §6 has no "stage" template), so the shell gets
|
|
23
|
+
* one modifier class and the wordmark block is the same one the start screen
|
|
24
|
+
* draws. The colour goes through the shell's background and Core's two opt-in
|
|
25
|
+
* hooks (`--prizma-logo-fill`, Text/Body/0 static); no hex, no new palette.
|
|
26
|
+
*
|
|
27
|
+
* The desktop frame (2010:6362) is this same stage filling a 1440 browser
|
|
28
|
+
* window; the column does not centre, the colour does.
|
|
29
|
+
*/
|
|
30
|
+
export const DemoScreensSplashScreen = forwardRef<HTMLDivElement, DemoScreensSplashScreenProps>(
|
|
31
|
+
({ strings, screenId = 'demo-screens-splash', className, ...shell }, ref) => (
|
|
32
|
+
<PrizmaScreenShell
|
|
33
|
+
ref={ref}
|
|
34
|
+
data-screen-id={screenId}
|
|
35
|
+
className={['demo-screens-splash', className ?? ''].filter(Boolean).join(' ')}
|
|
36
|
+
{...shell}
|
|
37
|
+
>
|
|
38
|
+
<div className="demo-screens-wordmark">
|
|
39
|
+
<PrizmaLogo variant="incode" />
|
|
40
|
+
<p className="demo-screens-wordmark__caption">{strings.appName}</p>
|
|
41
|
+
</div>
|
|
42
|
+
</PrizmaScreenShell>
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
DemoScreensSplashScreen.displayName = 'DemoScreensSplashScreen';
|
|
46
|
+
|
|
47
|
+
export default DemoScreensSplashScreen;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { PrizmaButton } from '@incodetech/prizma-core-web/button';
|
|
3
|
+
import { PrizmaLogo } from '@incodetech/prizma-core-web/logo';
|
|
4
|
+
import { PrizmaCountryFlag } from '@incodetech/prizma-core-web/combined';
|
|
5
|
+
import { PrizmaScreenShell, type PrizmaScreenShellProps } from './ScreenShell';
|
|
6
|
+
import type { PrizmaScreenActionHandler } from './types';
|
|
7
|
+
import type { DemoScreensStrings } from './DemoScreensStrings';
|
|
8
|
+
import './ScreenLayout.css';
|
|
9
|
+
import './DemoScreensLayout.css';
|
|
10
|
+
|
|
11
|
+
export interface DemoScreensStartScreenProps
|
|
12
|
+
extends Omit<PrizmaScreenShellProps, 'dark' | 'title' | 'children'> {
|
|
13
|
+
/** Family copy — this screen reads `appName`, `start` and `settings.languages`. */
|
|
14
|
+
strings: DemoScreensStrings;
|
|
15
|
+
/** The CTA is pressed and the session is being created (`2082:8743`). */
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
screenId?: string;
|
|
18
|
+
onAction?: PrizmaScreenActionHandler;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Demo screens — the front door, `demo_2` (2010:5925) in `Demo App - Latest
|
|
23
|
+
* Design`, and its loading twin `2082:8743`.
|
|
24
|
+
*
|
|
25
|
+
* Header row: the current language (label over value, the flag from the
|
|
26
|
+
* canonical bank) on the left and the menu affordance on the right. Middle: the
|
|
27
|
+
* wordmark block the splash also draws. Bottom: one primary CTA. No verified
|
|
28
|
+
* tag — the frame draws none; nothing has been verified yet.
|
|
29
|
+
*
|
|
30
|
+
* Not an archetype: §6 has no template with a two-slot header and a centred
|
|
31
|
+
* wordmark, so the row is composed here from the nav row's own measures
|
|
32
|
+
* (`DemoScreensLayout.css`). The menu glyph is drawn locally — the frame's
|
|
33
|
+
* three-dot "Info menu" is not in the canonical bank yet, and the owner asked
|
|
34
|
+
* for the dots rather than a stand-in (Elena, 2026-09-24). It sits in
|
|
35
|
+
* Navigation's own icon button so size, colour and focus are Core's; the
|
|
36
|
+
* geometry is the only new thing, named as such in DEVIATIONS #GEN-10.
|
|
37
|
+
*
|
|
38
|
+
* `onAction`: `cta` when the CTA is pressed, `help` for the menu (the
|
|
39
|
+
* settings sheet is what it opens in the app).
|
|
40
|
+
*/
|
|
41
|
+
/** The three-dot menu glyph, 24 box, currentColor — pending its bank entry. */
|
|
42
|
+
export const MenuDotsGlyph: React.FC = () => (
|
|
43
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
44
|
+
<circle cx="5" cy="12" r="2" fill="currentColor" />
|
|
45
|
+
<circle cx="12" cy="12" r="2" fill="currentColor" />
|
|
46
|
+
<circle cx="19" cy="12" r="2" fill="currentColor" />
|
|
47
|
+
</svg>
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export const DemoScreensStartScreen = forwardRef<HTMLDivElement, DemoScreensStartScreenProps>(
|
|
51
|
+
({ strings, loading = false, screenId = 'demo-screens-start', onAction, ...shell }, ref) => {
|
|
52
|
+
const current = strings.settings.languages.find(l => l.label === strings.start.languageValue);
|
|
53
|
+
return (
|
|
54
|
+
<PrizmaScreenShell ref={ref} data-screen-id={screenId} {...shell}>
|
|
55
|
+
<header className="demo-screens-start__header" aria-label={strings.navLabel}>
|
|
56
|
+
<div className="demo-screens-start__language">
|
|
57
|
+
<span className="demo-screens-start__language-label">{strings.start.languageLabel}</span>
|
|
58
|
+
<span className="demo-screens-start__language-value">
|
|
59
|
+
{current?.countryCode ? (
|
|
60
|
+
<PrizmaCountryFlag
|
|
61
|
+
country={{ code: current.countryCode, name: current.label, dialCode: '', flag: '' }}
|
|
62
|
+
/>
|
|
63
|
+
) : null}
|
|
64
|
+
{strings.start.languageValue}
|
|
65
|
+
</span>
|
|
66
|
+
</div>
|
|
67
|
+
<button
|
|
68
|
+
type="button"
|
|
69
|
+
className="prizma-nav__icon demo-screens-start__menu"
|
|
70
|
+
aria-label={strings.start.menuLabel}
|
|
71
|
+
onClick={() => onAction?.({ type: 'help', screenId })}
|
|
72
|
+
>
|
|
73
|
+
<MenuDotsGlyph />
|
|
74
|
+
</button>
|
|
75
|
+
</header>
|
|
76
|
+
<div className="prizma-screen-layout__content">
|
|
77
|
+
<div className="demo-screens-start__middle">
|
|
78
|
+
<div className="demo-screens-wordmark">
|
|
79
|
+
<PrizmaLogo variant="incode" />
|
|
80
|
+
<p className="demo-screens-wordmark__caption">{strings.appName}</p>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
{/* Archetype F's CTA band in its `--bare` form: this screen carries no
|
|
85
|
+
verified tag, so the button sits Spacing/24 off the bottom, where
|
|
86
|
+
the other modules' tag-less CTAs sit, not up at the tag's height. */}
|
|
87
|
+
<div className="prizma-screen-layout__band prizma-screen-layout__band--bare demo-screens-band">
|
|
88
|
+
<div className="prizma-screen-layout__band__ctas">
|
|
89
|
+
<PrizmaButton
|
|
90
|
+
variant="primary"
|
|
91
|
+
size="L"
|
|
92
|
+
loading={loading}
|
|
93
|
+
onClick={() => onAction?.({ type: 'cta', screenId })}
|
|
94
|
+
>
|
|
95
|
+
{strings.start.ctaLabel}
|
|
96
|
+
</PrizmaButton>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</PrizmaScreenShell>
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
DemoScreensStartScreen.displayName = 'DemoScreensStartScreen';
|
|
104
|
+
|
|
105
|
+
export default DemoScreensStartScreen;
|