@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.
Files changed (84) hide show
  1. package/dist/DemoScreensConfigScreen.d.ts +36 -0
  2. package/dist/DemoScreensConfigScreen.js +30 -0
  3. package/dist/DemoScreensConfigSheetScreen.d.ts +39 -0
  4. package/dist/DemoScreensConfigSheetScreen.js +33 -0
  5. package/dist/DemoScreensEditSheetScreen.d.ts +30 -0
  6. package/dist/DemoScreensEditSheetScreen.js +28 -0
  7. package/dist/DemoScreensEndScreen.d.ts +9 -21
  8. package/dist/DemoScreensEndScreen.js +9 -14
  9. package/dist/DemoScreensLaunchScreen.d.ts +28 -0
  10. package/dist/DemoScreensLaunchScreen.js +26 -0
  11. package/dist/DemoScreensLayout.css +542 -0
  12. package/dist/DemoScreensRedirectScreen.d.ts +50 -0
  13. package/dist/DemoScreensRedirectScreen.js +38 -0
  14. package/dist/DemoScreensResultScreen.d.ts +52 -0
  15. package/dist/DemoScreensResultScreen.js +46 -0
  16. package/dist/DemoScreensRunningScreen.d.ts +22 -0
  17. package/dist/DemoScreensRunningScreen.js +16 -0
  18. package/dist/DemoScreensSettingsScreen.d.ts +37 -0
  19. package/dist/DemoScreensSettingsScreen.js +40 -0
  20. package/dist/DemoScreensSplashScreen.d.ts +27 -0
  21. package/dist/DemoScreensSplashScreen.js +25 -0
  22. package/dist/DemoScreensStartScreen.d.ts +38 -0
  23. package/dist/DemoScreensStartScreen.js +37 -0
  24. package/dist/DemoScreensStrings.d.ts +192 -0
  25. package/dist/DemoScreensStrings.js +11 -11
  26. package/dist/DemoScreensTermsScreen.d.ts +28 -0
  27. package/dist/DemoScreensTermsScreen.js +26 -0
  28. package/dist/EkybAddressDetailsScreen.js +9 -5
  29. package/dist/EkybBusinessDetailsScreen.js +6 -3
  30. package/dist/EkybOwnersScreen.d.ts +4 -0
  31. package/dist/EkybOwnersScreen.js +13 -5
  32. package/dist/EkybStrings.d.ts +12 -1
  33. package/dist/EkycCountryCatalog.d.ts +46 -0
  34. package/dist/EkycCountryCatalog.js +139 -0
  35. package/dist/EkycCountryFormScreen.d.ts +36 -0
  36. package/dist/EkycCountryFormScreen.js +94 -0
  37. package/dist/EkycDetailsScreen.js +11 -4
  38. package/dist/EkycLayout.css +23 -0
  39. package/dist/EkycLicenseScreen.js +7 -3
  40. package/dist/EkycStrings.d.ts +26 -0
  41. package/dist/EmailInputStrings.d.ts +11 -1
  42. package/dist/FaceMatchComparisonScreen.d.ts +4 -2
  43. package/dist/FaceMatchComparisonScreen.js +3 -1
  44. package/dist/FaceMatchLayout.css +53 -3
  45. package/dist/FormScreen.css +74 -0
  46. package/dist/FormScreen.d.ts +17 -0
  47. package/dist/FormScreen.js +12 -1
  48. package/dist/PhoneInputStrings.d.ts +10 -1
  49. package/dist/index.d.ts +15 -2
  50. package/dist/index.js +13 -0
  51. package/dist/styles.css +1 -0
  52. package/package.json +62 -1
  53. package/src/DemoScreensConfigScreen.tsx +101 -0
  54. package/src/DemoScreensConfigSheetScreen.tsx +120 -0
  55. package/src/DemoScreensEditSheetScreen.tsx +103 -0
  56. package/src/DemoScreensEndScreen.tsx +14 -38
  57. package/src/DemoScreensLaunchScreen.tsx +96 -0
  58. package/src/DemoScreensLayout.css +542 -0
  59. package/src/DemoScreensRedirectScreen.tsx +190 -0
  60. package/src/DemoScreensResultScreen.tsx +115 -0
  61. package/src/DemoScreensRunningScreen.tsx +45 -0
  62. package/src/DemoScreensSettingsScreen.tsx +101 -0
  63. package/src/DemoScreensSplashScreen.tsx +47 -0
  64. package/src/DemoScreensStartScreen.tsx +105 -0
  65. package/src/DemoScreensStrings.ts +204 -11
  66. package/src/DemoScreensTermsScreen.tsx +82 -0
  67. package/src/EkybAddressDetailsScreen.tsx +7 -1
  68. package/src/EkybBusinessDetailsScreen.tsx +6 -1
  69. package/src/EkybOwnersScreen.tsx +46 -2
  70. package/src/EkybStrings.ts +12 -0
  71. package/src/EkycCountryCatalog.ts +199 -0
  72. package/src/EkycCountryFormScreen.tsx +184 -0
  73. package/src/EkycDetailsScreen.tsx +29 -20
  74. package/src/EkycLayout.css +23 -0
  75. package/src/EkycLicenseScreen.tsx +22 -16
  76. package/src/EkycStrings.ts +25 -0
  77. package/src/EmailInputStrings.ts +11 -1
  78. package/src/FaceMatchComparisonScreen.tsx +11 -3
  79. package/src/FaceMatchLayout.css +53 -3
  80. package/src/FormScreen.css +74 -0
  81. package/src/FormScreen.tsx +27 -1
  82. package/src/PhoneInputStrings.ts +10 -1
  83. package/src/index.ts +65 -1
  84. package/src/styles.css +1 -0
@@ -0,0 +1,542 @@
1
+ /* Demo screens — module layout additions.
2
+ *
3
+ * Two of the five Demo App screens are not an archetype: the SPLASH (a brand
4
+ * stage with the wordmark on it, no nav, no tag) and the START screen (a
5
+ * language block and a menu affordance in the header row, the wordmark in the
6
+ * middle, one CTA). Everything else in the family is archetype C or F and
7
+ * declares nothing here. Every value below is a Core token, or a literal
8
+ * measured off the Figma frame and named as such — the same idiom as
9
+ * `ScreenNav.css`'s 44px row.
10
+ *
11
+ * Figma: `Demo App - Latest Design` (FA4ZXKH3meKQnFmDsBsMdk) · `Web › Mobile`
12
+ * `demo_1` (2010:5868) and `demo_2` (2010:5925); the desktop pair draws the
13
+ * same column centred in a 1440 browser window.
14
+ */
15
+
16
+ /* ── Splash — `demo_1` ───────────────────────────────────────────────────────
17
+ * The whole stage is Surface/Brand/500 (Figma: #006AFF, the brand blue at the
18
+ * time of the frame; the token is what the app ships). The wordmark and the
19
+ * caption go white through the two opt-in hooks Core already exposes:
20
+ * `--prizma-logo-fill` on Logo, Text/Body/0 static on the caption.
21
+ * Doubled selector on purpose: `.prizma-screen-shell` paints Surface/Neutral/0
22
+ * at (0,1,0) and the sheets load in whatever order the bundler picks, so the
23
+ * stage colour has to outrank it rather than out-order it. */
24
+ .prizma-screen-shell.demo-screens-splash {
25
+ background: var(--prizma-surface-brand-500);
26
+ align-items: center;
27
+ justify-content: center;
28
+ }
29
+
30
+ .demo-screens-splash .demo-screens-wordmark {
31
+ --prizma-logo-fill: var(--prizma-text-body-0-static);
32
+ }
33
+
34
+ .demo-screens-splash .demo-screens-wordmark__caption {
35
+ color: var(--prizma-text-body-0-static);
36
+ }
37
+
38
+ /* On a device panel wider than the phone (Core Lab's `screenOnDevice`, the
39
+ * Demo App's desktop) the splash is the whole window, not a blue column on
40
+ * white — `demo_1`'s desktop twin (2010:6362) fills the 1440 frame. The panel
41
+ * paints itself and the column lets go of its 390 (Elena, 2026-09-24: "aquí
42
+ * tiene que ser todo azul"). `:has()` because the panel is the host's element
43
+ * and the screen can only reach it from below; `!important` because the host
44
+ * sizes the column inline. */
45
+ [data-pcs-device-area]:has(> [data-pcs-device-content] > .demo-screens-splash) {
46
+ background: var(--prizma-surface-brand-500) !important;
47
+ }
48
+
49
+ [data-pcs-device-content]:has(> .demo-screens-splash) {
50
+ left: 0 !important;
51
+ width: 100% !important;
52
+ }
53
+
54
+ /* ── The wordmark block — splash and start ──────────────────────────────────
55
+ * Logo 187 × 51 on the frame, caption H4 (18 / 500) at Spacing/4 beneath it
56
+ * (Figma: logo box 60 tall, caption at +65). Core's Logo is authored at 88 × 24
57
+ * and scales with its box, so the width is the ONE literal: 187 is the frame's
58
+ * measure, not a token, and it is written once. */
59
+ .demo-screens-wordmark {
60
+ display: flex;
61
+ flex-direction: column;
62
+ align-items: center;
63
+ gap: var(--prizma-spacing-4);
64
+ }
65
+
66
+ .demo-screens-wordmark .prizma-logo > svg {
67
+ width: 187px; /* measured — Figma `Logo / Incode` 187 × 51 on demo_1 / demo_2 */
68
+ height: auto;
69
+ }
70
+
71
+ .demo-screens-wordmark__caption {
72
+ margin: 0;
73
+ font-family: var(--prizma-body-family);
74
+ font-size: var(--prizma-headline-h4-font-size);
75
+ font-weight: var(--prizma-headline-h4-font-weight);
76
+ line-height: var(--prizma-headline-h4-line-height);
77
+ letter-spacing: var(--prizma-headline-h4-letter-spacing);
78
+ color: var(--prizma-text-body-500-secondary);
79
+ }
80
+
81
+ /* ── Start — `demo_2` header row ─────────────────────────────────────────────
82
+ * Sits where every other screen puts its logo nav (same status-bar offset,
83
+ * same 44 row, same gutters), but carries the language block on the left and
84
+ * the menu affordance on the right instead of a centred wordmark. */
85
+ .demo-screens-start__header {
86
+ flex-shrink: 0;
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: space-between;
90
+ margin-top: calc(var(--pcs-status-bar, 47px) + var(--prizma-spacing-12));
91
+ min-height: 44px; /* the nav row — GUIDELINES §3, same literal as ScreenNav.css */
92
+ padding-inline: var(--prizma-spacing-24);
93
+ }
94
+
95
+ .demo-screens-start__language {
96
+ display: flex;
97
+ flex-direction: column;
98
+ gap: var(--prizma-spacing-2);
99
+ font-family: var(--prizma-body-family);
100
+ }
101
+
102
+ .demo-screens-start__language-label {
103
+ font-size: var(--prizma-label-m-font-size);
104
+ font-weight: var(--prizma-label-m-font-weight);
105
+ line-height: var(--prizma-label-m-line-height);
106
+ letter-spacing: var(--prizma-label-m-letter-spacing);
107
+ color: var(--prizma-text-body-800-primary);
108
+ }
109
+
110
+ .demo-screens-start__language-value {
111
+ display: inline-flex;
112
+ align-items: center;
113
+ gap: var(--prizma-spacing-4);
114
+ font-size: var(--prizma-label-m-regular-font-size);
115
+ font-weight: var(--prizma-label-m-regular-font-weight);
116
+ line-height: var(--prizma-label-m-regular-line-height);
117
+ letter-spacing: var(--prizma-label-m-regular-letter-spacing);
118
+ color: var(--prizma-text-body-500-secondary);
119
+ }
120
+
121
+ .demo-screens-start__language-value img {
122
+ height: 12px; /* the flag raster at the label's cap height — measured, demo_2 */
123
+ width: auto;
124
+ }
125
+
126
+ /* The menu affordance: Core's nav icon button, reused by class so the hit
127
+ * area, the colour and the focus ring are Navigation's own — nothing new. */
128
+ .demo-screens-start__menu {
129
+ margin-inline-end: calc(-1 * var(--prizma-spacing-8));
130
+ }
131
+
132
+ /* The wordmark block fills the flexible middle, centred. */
133
+ .demo-screens-start__middle {
134
+ flex: 1;
135
+ min-height: 0;
136
+ display: flex;
137
+ align-items: center;
138
+ justify-content: center;
139
+ }
140
+
141
+ /* ── Settings — `demo_3` header row ─────────────────────────────────────────
142
+ * Core's Navigation with the logo off and the close X on: the bar keeps the
143
+ * nav row's offset so the title lands where every other screen's first block
144
+ * lands. */
145
+ .demo-screens-settings__nav {
146
+ flex-shrink: 0;
147
+ margin-top: calc(var(--pcs-status-bar, 47px) + var(--prizma-spacing-12));
148
+ height: 44px; /* the nav row — GUIDELINES §3 */
149
+ padding-inline: var(--prizma-spacing-24);
150
+ display: flex;
151
+ align-items: center;
152
+ }
153
+
154
+ .demo-screens-settings__nav .prizma-nav {
155
+ position: static;
156
+ width: 100%;
157
+ }
158
+
159
+ /* Title → dropdown Spacing/32: Figma puts the field 31 under the H2 (113 → 172). */
160
+ .demo-screens-settings__fields {
161
+ display: flex;
162
+ flex-direction: column;
163
+ gap: var(--prizma-spacing-16);
164
+ padding-top: var(--prizma-spacing-32);
165
+ flex: 1;
166
+ min-height: 0;
167
+ }
168
+
169
+ /* The language rows carry the flag raster at the label's cap height. */
170
+ .demo-screens-settings__flag {
171
+ height: 12px; /* measured, demo_4 rows */
172
+ width: auto;
173
+ display: inline-block;
174
+ }
175
+
176
+ /* ── The tag-less CTA band — Start and Settings ──────────────────────────────
177
+ * `__band--bare` gives the Spacing/24 to the bottom; as a shell child the band
178
+ * still needs the column's gutters, which `--result` carries and `--bare` does
179
+ * not. Nothing else: the button is Core's, the gap is the band's. */
180
+ .demo-screens-band {
181
+ padding-inline: var(--prizma-spacing-24);
182
+ }
183
+
184
+ /* ── Native flow ─────────────────────────────────────────────────────────────
185
+ * Figma: `Demo App - Latest Design` › `iOS` (2010:4692). Android draws the same
186
+ * screens; the reference is iOS (Elena, 2026-09-24). */
187
+
188
+ /* Configuration — a field stack under the logo nav, archetype E's own
189
+ * measures: Spacing/16 between fields, the CTA in the bare band. Figma puts
190
+ * the first field 44 under the nav row (62+44 → 148); the content column's
191
+ * 24 plus this 20 reach it. */
192
+ .demo-screens-config__fields {
193
+ display: flex;
194
+ flex-direction: column;
195
+ gap: var(--prizma-spacing-16);
196
+ padding-top: var(--prizma-spacing-20);
197
+ flex: 1;
198
+ min-height: 0;
199
+ }
200
+
201
+ /* Terms — the logo sits LEFT (Figma 32 / 85), the document scrolls, and the
202
+ * consent row + CTA ride the bare band. */
203
+ .demo-screens-terms__header {
204
+ flex-shrink: 0;
205
+ display: flex;
206
+ align-items: center;
207
+ margin-top: calc(var(--pcs-status-bar, 47px) + var(--prizma-spacing-12));
208
+ min-height: 44px; /* the nav row — GUIDELINES §3 */
209
+ padding-inline: var(--prizma-spacing-24);
210
+ }
211
+
212
+ .demo-screens-terms__meta {
213
+ margin: 0;
214
+ font-family: var(--prizma-body-family);
215
+ font-size: var(--prizma-label-m-regular-font-size);
216
+ font-weight: var(--prizma-label-m-regular-font-weight);
217
+ line-height: var(--prizma-label-m-regular-line-height);
218
+ color: var(--prizma-text-body-500-secondary);
219
+ }
220
+
221
+ .demo-screens-terms__body {
222
+ flex: 1;
223
+ min-height: 0;
224
+ overflow-y: auto;
225
+ margin-top: var(--prizma-spacing-16);
226
+ font-family: var(--prizma-body-family);
227
+ font-size: var(--prizma-body-m-regular-font-size);
228
+ font-weight: var(--prizma-body-m-regular-font-weight);
229
+ line-height: var(--prizma-body-m-regular-line-height);
230
+ letter-spacing: var(--prizma-body-m-regular-letter-spacing);
231
+ color: var(--prizma-text-body-800-primary);
232
+ white-space: pre-line;
233
+ }
234
+
235
+ /* The consent row above the CTA takes the band's own Spacing/16. */
236
+ .demo-screens-terms__consent {
237
+ display: flex;
238
+ }
239
+
240
+ /* Launch — the caption under the CTA: "Environment: Stage", value in brand. */
241
+ .demo-screens-launch__env {
242
+ margin: 0;
243
+ text-align: center;
244
+ font-family: var(--prizma-body-family);
245
+ font-size: var(--prizma-label-m-regular-font-size);
246
+ font-weight: var(--prizma-label-m-regular-font-weight);
247
+ line-height: var(--prizma-label-m-regular-line-height);
248
+ color: var(--prizma-text-body-800-primary);
249
+ }
250
+
251
+ .demo-screens-launch__env b {
252
+ font-weight: inherit;
253
+ color: var(--prizma-text-accent-brand);
254
+ }
255
+
256
+ /* The header's left text on Launch ("Flow: Digital ID Flow"). */
257
+ .demo-screens-start__flow {
258
+ font-family: var(--prizma-body-family);
259
+ font-size: var(--prizma-label-m-regular-font-size);
260
+ font-weight: var(--prizma-label-m-regular-font-weight);
261
+ line-height: var(--prizma-label-m-regular-line-height);
262
+ color: var(--prizma-text-body-800-primary);
263
+ }
264
+
265
+ /* A snackbar over the top of a screen (Launch "Flow saved", the sheet's
266
+ * "settings saved"): Core's Snackbar, anchored where the frame draws it — the
267
+ * nav row, full gutter width. */
268
+ .demo-screens-toast {
269
+ position: absolute;
270
+ z-index: 3;
271
+ left: var(--prizma-spacing-24);
272
+ right: var(--prizma-spacing-24);
273
+ top: calc(var(--pcs-status-bar, 47px) + var(--prizma-spacing-8));
274
+ display: flex;
275
+ }
276
+
277
+ .demo-screens-toast .prizma-snackbar {
278
+ width: 100%;
279
+ }
280
+
281
+ /* ── The two sheets ──────────────────────────────────────────────────────────
282
+ * Same idiom as Document Capture's method sheet (DEVIATIONS #DC-30): the
283
+ * screen owns the scrim, Core's `PrizmaBottomSheetContent` owns the panel. The
284
+ * frame draws the sheet from 74 down (grabber at 79), so the panel starts at
285
+ * the status bar plus Spacing/24 and fills to the bottom. */
286
+ .demo-screens-sheet-scrim {
287
+ position: absolute;
288
+ inset: 0;
289
+ z-index: 1;
290
+ background: var(--prizma-surface-overlay);
291
+ }
292
+
293
+ .demo-screens-sheet-panel {
294
+ position: absolute;
295
+ left: 0;
296
+ right: 0;
297
+ bottom: 0;
298
+ top: calc(var(--pcs-status-bar, 47px) + var(--prizma-spacing-24));
299
+ z-index: 2;
300
+ display: flex;
301
+ }
302
+
303
+ .demo-screens-sheet-panel .prizma-bottom-sheet {
304
+ flex: 1;
305
+ min-height: 0;
306
+ }
307
+
308
+ .demo-screens-sheet-panel .prizma-bottom-sheet__content,
309
+ .demo-screens-sheet-panel .prizma-bottom-sheet__body {
310
+ flex: 1;
311
+ min-height: 0;
312
+ display: flex;
313
+ flex-direction: column;
314
+ }
315
+
316
+ .demo-screens-sheet__nav {
317
+ flex-shrink: 0;
318
+ height: 44px; /* the nav row — GUIDELINES §3 */
319
+ display: flex;
320
+ align-items: center;
321
+ }
322
+
323
+ .demo-screens-sheet__nav .prizma-nav {
324
+ position: static;
325
+ width: 100%;
326
+ }
327
+
328
+ /* Title 16 under the nav row (Figma 152 → 168); fields Spacing/32 under the
329
+ * title block, as archetype E. */
330
+ .demo-screens-sheet__title {
331
+ padding-top: var(--prizma-spacing-16);
332
+ }
333
+
334
+ .demo-screens-sheet__fields {
335
+ display: flex;
336
+ flex-direction: column;
337
+ gap: var(--prizma-spacing-16);
338
+ padding-top: var(--prizma-spacing-32);
339
+ flex: 1;
340
+ min-height: 0;
341
+ }
342
+
343
+ /* The two read-only lines under the flow picker. */
344
+ .demo-screens-sheet__line {
345
+ margin: 0;
346
+ font-family: var(--prizma-body-family);
347
+ font-size: var(--prizma-label-m-regular-font-size);
348
+ font-weight: var(--prizma-label-m-regular-font-weight);
349
+ line-height: var(--prizma-label-m-regular-line-height);
350
+ color: var(--prizma-text-body-800-primary);
351
+ }
352
+
353
+ .demo-screens-sheet__lines {
354
+ display: flex;
355
+ flex-direction: column;
356
+ gap: var(--prizma-spacing-8);
357
+ }
358
+
359
+ /* CTA band at the foot of the sheet: primary → tertiary link → build caption,
360
+ * at the band's flat Spacing/16, then Spacing/24 to the bottom (bare). */
361
+ .demo-screens-sheet__band {
362
+ flex-shrink: 0;
363
+ display: flex;
364
+ flex-direction: column;
365
+ gap: var(--prizma-spacing-16);
366
+ padding-bottom: var(--prizma-spacing-24);
367
+ }
368
+
369
+ .demo-screens-sheet__band .prizma-button {
370
+ width: 100%;
371
+ }
372
+
373
+ .demo-screens-build {
374
+ margin: 0;
375
+ text-align: center;
376
+ font-family: var(--prizma-body-family);
377
+ font-size: var(--prizma-label-m-regular-font-size);
378
+ font-weight: var(--prizma-label-m-regular-font-weight);
379
+ line-height: var(--prizma-label-m-regular-line-height);
380
+ color: var(--prizma-text-body-500-secondary);
381
+ }
382
+
383
+ /* ── Redirect — the desktop page (4272:11166) ────────────────────────────────
384
+ * One card, 800 wide on the frame with a 752 content column (24 gutters),
385
+ * centred in the window on a Surface/Neutral/50 page. The shell IS the page;
386
+ * the card is the only thing on it. Inside, archetype F's skeleton: nav →
387
+ * centred title block → the leg → CTA band → tag. */
388
+ .prizma-screen-shell.demo-screens-redirect {
389
+ background: var(--prizma-surface-neutral-50);
390
+ align-items: center;
391
+ justify-content: center;
392
+ }
393
+
394
+ .demo-screens-redirect__card {
395
+ position: relative;
396
+ display: flex;
397
+ flex-direction: column;
398
+ width: 100%;
399
+ max-width: 800px; /* measured — the frame's card */
400
+ background: var(--prizma-surface-neutral-0);
401
+ border: var(--prizma-border-width-regular) solid var(--prizma-border-neutral-100);
402
+ border-radius: var(--prizma-border-radius-medium); /* Figma `Content`: r16 */
403
+ }
404
+
405
+ /* The card's nav row has no status bar above it: the offset collapses to the
406
+ * frame's 24 (logo at 212, card at 188). */
407
+ .demo-screens-redirect__card .prizma-screen-nav {
408
+ margin-top: var(--prizma-spacing-24);
409
+ }
410
+
411
+ /* Doubled selector: the foundation reserves the anchored footer's space on
412
+ * every content column (`:has(.__band__tag)` → 88px of padding-bottom) and
413
+ * flexes it to fill the shell. Here nothing is anchored — the card hugs its
414
+ * content and the tag rides in the band — so the column keeps only its own
415
+ * height and the band's Spacing/24 is the whole gap to the CTA (Elena,
416
+ * 2026-09-24: "hay un spacing innecesario"). */
417
+ .demo-screens-redirect .demo-screens-redirect__content {
418
+ flex: 0 0 auto;
419
+ align-items: center;
420
+ gap: var(--prizma-spacing-32);
421
+ padding-top: var(--prizma-spacing-8);
422
+ padding-bottom: 0;
423
+ }
424
+
425
+ /* Tabs — Core has no Tabs primitive yet (DEVIATIONS #GEN-15). Two text
426
+ * buttons over a hairline; the active one carries the brand underline. Type is
427
+ * the H5 ramp the frame uses (16 / 500), colours the body tokens. */
428
+ .demo-screens-tabs {
429
+ display: flex;
430
+ justify-content: center;
431
+ width: 100%;
432
+ max-width: 676px; /* measured — the frame's `tabs` row inside the 752 column */
433
+ border-bottom: var(--prizma-border-width-regular) solid var(--prizma-border-neutral-100);
434
+ }
435
+
436
+ .demo-screens-tabs__tab {
437
+ appearance: none;
438
+ background: transparent;
439
+ border: 0;
440
+ margin: 0;
441
+ padding: var(--prizma-spacing-8) var(--prizma-spacing-12);
442
+ margin-bottom: calc(-1 * var(--prizma-border-width-regular));
443
+ border-bottom: var(--prizma-border-width-bold) solid transparent;
444
+ cursor: pointer;
445
+ font-family: var(--prizma-body-family);
446
+ font-size: var(--prizma-headline-h5-font-size);
447
+ font-weight: var(--prizma-headline-h5-font-weight);
448
+ line-height: var(--prizma-headline-h5-line-height);
449
+ letter-spacing: var(--prizma-headline-h5-letter-spacing);
450
+ color: var(--prizma-text-body-500-secondary);
451
+ }
452
+
453
+ .demo-screens-tabs__tab--active {
454
+ color: var(--prizma-text-body-800-primary);
455
+ border-bottom-color: var(--prizma-border-brand-500);
456
+ }
457
+
458
+ .demo-screens-redirect__leg {
459
+ display: flex;
460
+ flex-direction: column;
461
+ align-items: center;
462
+ gap: var(--prizma-spacing-16);
463
+ width: 100%;
464
+ }
465
+
466
+ /* The phone leg lines up with the CTA band below it: one 352 column for the
467
+ * field, the Send button and "Continue on desktop" (Figma draws the form at
468
+ * 326 and the CTAs at 352; Elena, 2026-09-24: keep the longer one, but make
469
+ * everything match). */
470
+ .demo-screens-redirect__leg--form {
471
+ max-width: 352px; /* the CTAs group on the frame — the form joins it */
472
+ }
473
+
474
+ .demo-screens-redirect__leg--form .prizma-button {
475
+ width: 100%;
476
+ }
477
+
478
+ .demo-screens-redirect__hint {
479
+ margin: 0;
480
+ text-align: center;
481
+ font-family: var(--prizma-body-family);
482
+ font-size: var(--prizma-headline-h5-font-size);
483
+ font-weight: var(--prizma-headline-h5-font-weight);
484
+ line-height: var(--prizma-headline-h5-line-height);
485
+ letter-spacing: var(--prizma-headline-h5-letter-spacing);
486
+ color: var(--prizma-text-body-500-secondary);
487
+ }
488
+
489
+ /* The QR well: 200 square, a hairline, radius small (Figma 312 → 512). The
490
+ * image inside is the host's. */
491
+ .demo-screens-redirect__qr {
492
+ width: 200px; /* measured — the frame's QR well */
493
+ height: 200px;
494
+ display: flex;
495
+ align-items: center;
496
+ justify-content: center;
497
+ padding: var(--prizma-spacing-12);
498
+ border: var(--prizma-border-width-regular) solid var(--prizma-border-neutral-100);
499
+ border-radius: var(--prizma-border-radius-small);
500
+ background: var(--prizma-surface-neutral-0);
501
+ }
502
+
503
+ .demo-screens-redirect__qr > * {
504
+ width: 100%;
505
+ height: 100%;
506
+ }
507
+
508
+ /* The CTA band inside the card: F's own band, static (the card hugs its
509
+ * content, nothing is anchored), at the field's 352 (Figma 544 → 896) and
510
+ * Spacing/24 to the card's bottom. The tag rides in the band, as on F. */
511
+ .demo-screens-redirect__band {
512
+ align-self: stretch;
513
+ align-items: center;
514
+ /* The band carries the column's 24 gutters itself (it is a shell child, not
515
+ * inside the content column), so on the phone its 352 clips to the same 342
516
+ * the form gets — the button and the field share one edge (Elena,
517
+ * 2026-09-24: "el botón está más alargado que el resto"). */
518
+ padding: var(--prizma-spacing-24) var(--prizma-spacing-24) var(--prizma-spacing-24);
519
+ }
520
+
521
+ .demo-screens-redirect__band > * {
522
+ width: 100%;
523
+ max-width: 352px; /* measured — the CTAs group on the frame */
524
+ }
525
+
526
+ .demo-screens-redirect__band .prizma-screen-layout__band__tag {
527
+ position: static;
528
+ display: flex;
529
+ justify-content: center;
530
+ }
531
+
532
+ /* The snackbar on a desktop page: hugging, centred, 32 from the top (Figma). */
533
+ .demo-screens-toast--desktop {
534
+ left: 0;
535
+ right: 0;
536
+ top: var(--prizma-spacing-32);
537
+ justify-content: center;
538
+ }
539
+
540
+ .demo-screens-toast--desktop .prizma-snackbar {
541
+ width: auto;
542
+ }
@@ -0,0 +1,50 @@
1
+ import React, { type ReactNode } from 'react';
2
+ import { type PrizmaScreenShellProps } from './ScreenShell';
3
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
4
+ import type { DemoScreensStrings } from './DemoScreensStrings';
5
+ import './ScreenLayout.css';
6
+ import './DemoScreensLayout.css';
7
+ /**
8
+ * Where the redirect page is in its life:
9
+ * - `qr` the QR tab (or the QR-only page)
10
+ * - `sms` the SMS tab, number not typed yet
11
+ * - `smsFilled` the SMS tab, number typed, Send live
12
+ * - `sent` "Link sent!", resend counting down
13
+ * - `resend` "Link sent!", resend available
14
+ * - `resent` "Link sent!" with the "resent" snackbar
15
+ * - `tooMany` "Too many attempts"
16
+ */
17
+ export type DemoScreensRedirectStage = 'qr' | 'sms' | 'smsFilled' | 'sent' | 'resend' | 'resent' | 'tooMany';
18
+ export interface DemoScreensRedirectScreenProps extends Omit<PrizmaScreenShellProps, 'dark' | 'title' | 'children'> {
19
+ /** Family copy — this screen reads the `redirect` slice. */
20
+ strings: DemoScreensStrings;
21
+ stage?: DemoScreensRedirectStage;
22
+ /** Offer the SMS tab. Off: the `QR Only` section (4272:11388). Default on. */
23
+ sms?: boolean;
24
+ /** Offer "or · Continue on desktop" under the leg. Default on. */
25
+ desktop?: boolean;
26
+ /**
27
+ * The QR image — a host slot, like every photo on a mock. The screens
28
+ * package draws no QR of its own (it has no encoder and no URL to encode);
29
+ * the hub passes a real one for its sample link.
30
+ */
31
+ qr?: ReactNode;
32
+ screenId?: string;
33
+ overrides?: PrizmaScreenOverrides;
34
+ onAction?: PrizmaScreenActionHandler;
35
+ }
36
+ /**
37
+ * Demo screens · DESKTOP — the redirect page, `Redirect` (4272:11166) in
38
+ * `Demo App - Latest Design`: a desktop browser opened the link, and the page
39
+ * offers to move the session to a phone. One card centred in the window: the
40
+ * logo nav, a title block, two tabs (Scan QR · Send SMS), the leg's own
41
+ * content, then "or" and a secondary "Continue on desktop", and the tag.
42
+ *
43
+ * Authored at the card's width — 800 on the frame, the content column 752 —
44
+ * so it is the one screen in the family that is not a 390 column; Core Lab
45
+ * lays it on the desktop panel with `adapt.column`. Archetype F's band and
46
+ * footer supply the CTA rhythm; the card, the tabs and the QR well are the
47
+ * page's own (DEVIATIONS #GEN-15 for the tabs — Core has no Tabs yet).
48
+ */
49
+ export declare const DemoScreensRedirectScreen: React.ForwardRefExoticComponent<DemoScreensRedirectScreenProps & React.RefAttributes<HTMLDivElement>>;
50
+ export default DemoScreensRedirectScreen;
@@ -0,0 +1,38 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { forwardRef } from 'react';
4
+ import { PrizmaButton } from '@incodetech/prizma-core-web/button';
5
+ import { PrizmaTitle } from '@incodetech/prizma-core-web/title';
6
+ import { PrizmaDisclaimer } from '@incodetech/prizma-core-web/disclaimer';
7
+ import { PrizmaTag } from '@incodetech/prizma-core-web/tag';
8
+ import { PrizmaSnackbar } from '@incodetech/prizma-core-web/snackbar';
9
+ import { PrizmaCombined } from '@incodetech/prizma-core-web/combined';
10
+ import { PrizmaScreenShell } from './ScreenShell';
11
+ import { PrizmaScreenNav } from './ScreenNav';
12
+ import './ScreenLayout.css';
13
+ import './DemoScreensLayout.css';
14
+ /**
15
+ * Demo screens · DESKTOP — the redirect page, `Redirect` (4272:11166) in
16
+ * `Demo App - Latest Design`: a desktop browser opened the link, and the page
17
+ * offers to move the session to a phone. One card centred in the window: the
18
+ * logo nav, a title block, two tabs (Scan QR · Send SMS), the leg's own
19
+ * content, then "or" and a secondary "Continue on desktop", and the tag.
20
+ *
21
+ * Authored at the card's width — 800 on the frame, the content column 752 —
22
+ * so it is the one screen in the family that is not a 390 column; Core Lab
23
+ * lays it on the desktop panel with `adapt.column`. Archetype F's band and
24
+ * footer supply the CTA rhythm; the card, the tabs and the QR well are the
25
+ * page's own (DEVIATIONS #GEN-15 for the tabs — Core has no Tabs yet).
26
+ */
27
+ export const DemoScreensRedirectScreen = forwardRef(({ strings, stage = 'qr', sms = true, desktop = true, qr, screenId = `demo-screens-redirect-${stage}${sms ? '' : '-qr-only'}${desktop ? '' : '-no-desktop'}`, overrides, onAction, className, ...shell }, ref) => {
28
+ const r = strings.redirect;
29
+ const onSms = stage !== 'qr';
30
+ const country = [
31
+ { code: 'RS', name: 'Serbia', dialCode: '+381', flag: '' },
32
+ ].find(c => c.code === r.countryCode);
33
+ const subtitle = sms ? r.subtitle : desktop ? r.subtitleQrDesktop : r.subtitleQrOnly;
34
+ const verdict = stage === 'sent' || stage === 'resend' || stage === 'resent' || stage === 'tooMany';
35
+ return (_jsxs(PrizmaScreenShell, { ref: ref, "data-screen-id": screenId, className: ['demo-screens-redirect', className ?? ''].filter(Boolean).join(' '), ...shell, children: [stage === 'resent' ? (_jsx("div", { className: "demo-screens-toast demo-screens-toast--desktop", children: _jsx(PrizmaSnackbar, { state: "success", children: r.sent.resentSnackbar }) })) : null, _jsxs("div", { className: "demo-screens-redirect__card", children: [_jsx(PrizmaScreenNav, { logo: overrides?.logo, navLabel: strings.navLabel }), _jsxs("div", { className: "prizma-screen-layout__content demo-screens-redirect__content", children: [_jsx(PrizmaTitle, { variant: "centered", title: r.title, showSubtitle: true, subtitle: subtitle }), sms ? (_jsxs("div", { className: "demo-screens-tabs", role: "tablist", children: [_jsx("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 }), children: r.tabs.qr }), _jsx("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 }), children: r.tabs.sms })] })) : null, stage === 'qr' ? (_jsxs("div", { className: "demo-screens-redirect__leg", children: [sms ? _jsx("p", { className: "demo-screens-redirect__hint", children: r.qrHint }) : null, _jsx("div", { className: "demo-screens-redirect__qr", "aria-label": r.tabs.qr, children: qr })] })) : null, stage === 'sms' || stage === 'smsFilled' ? (_jsxs("div", { className: "demo-screens-redirect__leg demo-screens-redirect__leg--form", children: [_jsx("p", { className: "demo-screens-redirect__hint", children: r.smsHint }), _jsx(PrizmaCombined, { "aria-label": r.phoneLabel, placeholder: r.phonePlaceholder, defaultValue: stage === 'smsFilled' ? r.phoneValue : '', defaultCountry: country, showRequiredMarker: false }, stage), _jsx(PrizmaButton, { variant: "primary", size: "L", disabled: stage !== 'smsFilled', onClick: () => onAction?.({ type: 'cta', screenId }), children: r.sendLabel })] })) : null, verdict ? (_jsxs("div", { className: "demo-screens-redirect__leg demo-screens-redirect__leg--verdict", children: [stage === 'tooMany' ? (_jsx(PrizmaTitle, { variant: "centered", title: r.tooMany.title, showSubtitle: true, subtitle: r.tooMany.subtitle, icon: { type: 'status', status: 'error' } })) : (_jsx(PrizmaTitle, { variant: "centered", title: r.sent.title, showSubtitle: true, subtitle: `${r.sent.toPrefix} ${country?.dialCode ?? ''} ${r.phoneValue}`.trim(), icon: { type: 'status', status: 'success' } })), stage === 'tooMany' ? (_jsx(PrizmaButton, { variant: "tertiary-link", size: "L", onClick: () => onAction?.({ type: 'tertiary', screenId }), children: r.tooMany.changeLabel })) : stage === 'sent' || stage === 'resent' ? (_jsx(PrizmaButton, { variant: "tertiary-link", size: "L", disabled: true, children: r.sent.resendIn })) : (_jsx(PrizmaButton, { variant: "tertiary-link", size: "L", onClick: () => onAction?.({ type: 'cta', screenId }), children: r.sent.resend }))] })) : null] }), _jsxs("div", { className: "prizma-screen-layout__band demo-screens-redirect__band", children: [desktop && !verdict ? (_jsxs(_Fragment, { children: [_jsx(PrizmaDisclaimer, { text: r.orLabel }), _jsx("div", { className: "prizma-screen-layout__band__ctas", children: _jsx(PrizmaButton, { variant: "secondary", size: "L", onClick: () => onAction?.({ type: 'secondary', screenId }), children: r.desktopLabel }) })] })) : null, _jsx("div", { className: "prizma-screen-layout__band__tag", children: _jsx(PrizmaTag, { label: strings.verifiedLabel }) })] })] })] }));
36
+ });
37
+ DemoScreensRedirectScreen.displayName = 'DemoScreensRedirectScreen';
38
+ export default DemoScreensRedirectScreen;
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import { type PrizmaResultScreenProps } from './ResultScreen';
3
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
4
+ import type { DemoScreensStrings } from './DemoScreensStrings';
5
+ import './ScreenLayout.css';
6
+ /**
7
+ * The four ways a demo session ends. Named after what the BACKEND says, not
8
+ * after the colour the screen shows, so a host maps its session status straight
9
+ * onto this prop:
10
+ *
11
+ * - `approved` the session passed → green mark, no CTA
12
+ * - `rejected` it did not pass verification → red mark, restart CTA
13
+ * - `inReview` a human still has to decide → no mark, no CTA
14
+ * - `notCompleted` the flow broke before a verdict → red mark, restart CTA
15
+ *
16
+ * Marks and CTAs follow the Demo App dev's spec (2026-09-24, via Elena): a
17
+ * passed session has nowhere to go, so no Restart; a rejection and a broken
18
+ * flow both offer one; a pending review shows neither. The production frames
19
+ * differ in two places (Restart on approved; no mark on not completed) and
20
+ * are superseded by that spec — DEVIATIONS #GEN-14.
21
+ */
22
+ export type DemoScreensResultStatus = 'approved' | 'rejected' | 'inReview' | 'notCompleted';
23
+ export interface DemoScreensResultScreenProps extends Omit<PrizmaResultScreenProps, 'status' | 'title' | 'subtitle' | 'glyph' | 'ctaLabel' | 'verifiedLabel' | 'navLabel'> {
24
+ /** Family copy — this screen reads `result`, `end` and `notCompleted`. */
25
+ strings: DemoScreensStrings;
26
+ status: DemoScreensResultStatus;
27
+ /**
28
+ * Draw the restart CTA. Defaults per status (the verdicts have it, the two
29
+ * end screens do not); a host that wants a way out of an in-review screen,
30
+ * or none out of a rejection, says so here.
31
+ */
32
+ showRestart?: boolean;
33
+ screenId?: string;
34
+ overrides?: PrizmaScreenOverrides;
35
+ onAction?: PrizmaScreenActionHandler;
36
+ }
37
+ /**
38
+ * Demo screens — the end of a session, on the Result archetype
39
+ * (GUIDELINES §6-F, `PrizmaResultScreen`).
40
+ *
41
+ * Figma:
42
+ * `approved` `demo_7` (2010:5745) "Thank you!" · green mark
43
+ * `rejected` `demo_8` (2010:5808) "Verification failed" · red mark · Restart
44
+ * `inReview` `63:399` "Verification complete!" · bare title
45
+ * `notCompleted` "DemoApp: End Screens" › `Processnotcompleted` · red mark · Restart
46
+ *
47
+ * One component for the four because they are one screen with one axis: the
48
+ * host learns the session status and passes it through. `DemoScreensEndScreen`
49
+ * stays exported as the `inReview` case under its original name.
50
+ */
51
+ export declare const DemoScreensResultScreen: React.ForwardRefExoticComponent<DemoScreensResultScreenProps & React.RefAttributes<HTMLDivElement>>;
52
+ export default DemoScreensResultScreen;