@incodetech/prizma-core-screens 0.2.14 → 0.2.20

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 (59) hide show
  1. package/dist/DigitalIdProvidersDocumentSelectionScreen.d.ts +3 -3
  2. package/dist/DigitalIdProvidersDocumentSelectionScreen.js +4 -3
  3. package/dist/DigitalIdProvidersLayout.css +0 -12
  4. package/dist/DigitalIdProvidersRedirectScreen.d.ts +2 -3
  5. package/dist/DigitalIdProvidersRedirectScreen.js +3 -4
  6. package/dist/DigitalIdProvidersStrings.d.ts +4 -0
  7. package/dist/FaceCaptureLayout.css +150 -0
  8. package/dist/FormScreen.css +35 -0
  9. package/dist/IdCaptureLayout.css +63 -0
  10. package/dist/RotateToPortraitScreen.css +162 -0
  11. package/dist/RotateToPortraitScreen.d.ts +64 -0
  12. package/dist/RotateToPortraitScreen.js +68 -0
  13. package/dist/RotateToPortraitStrings.d.ts +8 -0
  14. package/dist/RotateToPortraitStrings.js +20 -0
  15. package/dist/ScreenLayout.css +200 -0
  16. package/dist/ScreenShell.css +13 -0
  17. package/dist/TutorialScreen.js +1 -1
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +1 -0
  20. package/dist/styles.css +1 -0
  21. package/package.json +9 -3
  22. package/samples/digital-id-providers/audkenni.png +0 -0
  23. package/samples/digital-id-providers/bankid-cz.png +0 -0
  24. package/samples/digital-id-providers/bankid-se.png +0 -0
  25. package/samples/digital-id-providers/ca-dmv-wallet.png +0 -0
  26. package/samples/digital-id-providers/digidentity.png +0 -0
  27. package/samples/digital-id-providers/diia.png +0 -0
  28. package/samples/digital-id-providers/edo.png +0 -0
  29. package/samples/digital-id-providers/eparaksts.png +0 -0
  30. package/samples/digital-id-providers/evrotrust.png +0 -0
  31. package/samples/digital-id-providers/freja.png +0 -0
  32. package/samples/digital-id-providers/ftn.png +0 -0
  33. package/samples/digital-id-providers/handy-signatur.png +0 -0
  34. package/samples/digital-id-providers/idin.png +0 -0
  35. package/samples/digital-id-providers/itsme.png +0 -0
  36. package/samples/digital-id-providers/mitid.png +0 -0
  37. package/samples/digital-id-providers/mobile-id.png +0 -0
  38. package/samples/digital-id-providers/mojeid.png +0 -0
  39. package/samples/digital-id-providers/oneid.png +0 -0
  40. package/samples/digital-id-providers/smart-id.png +0 -0
  41. package/samples/digital-id-providers/spid.png +0 -0
  42. package/samples/digital-id-providers/swissid.png +0 -0
  43. package/samples/digital-id-providers/uae-pass.png +0 -0
  44. package/samples/digital-id-providers/verimi.png +0 -0
  45. package/src/DigitalIdProvidersDocumentSelectionScreen.tsx +4 -3
  46. package/src/DigitalIdProvidersLayout.css +0 -12
  47. package/src/DigitalIdProvidersRedirectScreen.tsx +2 -9
  48. package/src/DigitalIdProvidersStrings.ts +4 -0
  49. package/src/FaceCaptureLayout.css +150 -0
  50. package/src/FormScreen.css +35 -0
  51. package/src/IdCaptureLayout.css +63 -0
  52. package/src/RotateToPortraitScreen.css +162 -0
  53. package/src/RotateToPortraitScreen.tsx +162 -0
  54. package/src/RotateToPortraitStrings.ts +28 -0
  55. package/src/ScreenLayout.css +200 -0
  56. package/src/ScreenShell.css +13 -0
  57. package/src/TutorialScreen.tsx +4 -1
  58. package/src/index.ts +11 -0
  59. package/src/styles.css +1 -0
@@ -829,6 +829,206 @@
829
829
  }
830
830
  }
831
831
 
832
+ /* ── Landscape phones: the stack keeps its order, the ring changes axis ──────
833
+ * WCAG 2.1 SC 1.3.4 Orientation (AA) asks every screen to work held sideways,
834
+ * and a phone held sideways is 375 to 440 tall (the phone catalog rotated:
835
+ * iPhone SE 667 x 375, the 844 x 390 reference, Large Android 915 x 412,
836
+ * Pro Max 956 x 440). Measured against the stacks the short-panel rules fit
837
+ * into 626: a capture screen needs ~557, a tutorial ~700. So two things give
838
+ * ground that no short panel asked for: the tutorial loses its illustration,
839
+ * and the capture screen turns its ring and its instruction side by side
840
+ * (FaceCaptureLayout.css). Everything else keeps the portrait order, title
841
+ * over copy over button, compacted (Camila, 2026-10-21: top-down, not side by
842
+ * side; the tag always centred; the button closer to the bottom).
843
+ *
844
+ * THE LINE is the shell's own shape, never the browser viewport (a 390 shell
845
+ * in a 1400 window is portrait): `orientation: landscape` with a 500 height
846
+ * cap. The cap keeps the rules off tablets, desktop windows and the iPhone
847
+ * Duo open full screen (626), which already have their own answers (#21,
848
+ * #VS-32, #F-37) and are wider than they are tall. 500 has slack above the
849
+ * 440 ceiling and under the 626 floor. Every rule below lives inside the one
850
+ * query, so outside it not one declaration exists and the portrait render is
851
+ * byte-identical. Exploration `face-capture-landscape` (Camila, 2026-10-20);
852
+ * the developer-facing list is LANDSCAPE.md. DEVIATIONS #F-39.
853
+ *
854
+ * What never changes, in either orientation: the H2, the CTA, the live
855
+ * instruction and where it lives (#12/#14), the status and verdict copy, and
856
+ * the tag's seat: bottom centre, Spacing/16 up, on every screen that has one. */
857
+ @container pcs-screen ((orientation: landscape) and (max-height: 500px)) {
858
+ /* The status-bar reserve STAYS (`--pcs-status-bar`, 47 by default, the
859
+ * host's own value otherwise). Round 2 had zeroed it on the argument that an
860
+ * iPhone draws no status bar in landscape; Camila's QA of the canvas
861
+ * (2026-10-21) found the result screens' status mark sitting in the system
862
+ * bar's row (the Lab's pills at 25 to 35, Elena's landscape reference keeps
863
+ * a 54 bar), which no device would allow. The reserve is the one line every
864
+ * screen already respects in portrait, so it is kept rather than replaced
865
+ * by a landscape-only offset. The capture screens are unaffected: their nav
866
+ * is hidden below and the ring is placed on the panel's height. */
867
+
868
+ /* Capture screens drop the nav row entirely. It is already reserved and
869
+ * empty on a feed-open capture screen (the 2026-08-18 header rule), and a
870
+ * 335 ring plus the 56 row does not fit in 375. A client logo opt-in goes
871
+ * with it in landscape: there is no row to hold it. */
872
+ .prizma-screen-shell:has(> .prizma-screen-layout__content--capture) > .prizma-screen-nav {
873
+ display: none;
874
+ }
875
+
876
+ /* …and the capture column stops reserving the footer under the ring: with
877
+ * the reserve the ring had 328 to sit in. (0,3,0), the reserve's own
878
+ * specificity, later in the file. FaceCaptureLayout.css says what happens
879
+ * to the tag there. */
880
+ .prizma-screen-shell .prizma-screen-layout__content.prizma-screen-layout__content--capture {
881
+ padding-bottom: 0;
882
+ }
883
+
884
+ /* ARCHETYPE A (tutorial). The illustration goes: it is the one element that
885
+ * carries no task information (step 1 of the order), and in landscape it is
886
+ * also the only one that cannot fit above a title block and a CTA at any
887
+ * size that still reads (Camila, 2026-10-21: "remove it to have more space,
888
+ * it's not adding essential information"). Its slot stays as the flexible
889
+ * middle, so the band keeps sitting at the bottom of the column, above the
890
+ * tag, where the portrait has it; the title block stays under the logo nav.
891
+ * Measured on the SE (375): nav 56, title block 77, disclaimer and CTA 105,
892
+ * the tag's reserve 62, Spacing/16 twice: 316. The disclaimer fit, and
893
+ * stayed until 2026-11-03, when Camila took it off the landscape tutorial
894
+ * as well (below): with the art gone the line between the subtitle and the
895
+ * CTA read as a second subtitle, and the task is in the title block.
896
+ * Addressed by the archetype's own `--tutorial` class (TutorialScreen.tsx),
897
+ * not by `:has()` on the illustration slot: Core Lab's converter drops
898
+ * hidden subtrees before the scene is laid out, so a rule that needed the
899
+ * hidden art to match would vanish on the canvas. */
900
+ .prizma-screen-shell .prizma-screen-layout__content--tutorial {
901
+ /* The logo nav is gone in landscape (below), so the column reserves the
902
+ * status bar itself, Spacing/8 under it like the result screens. */
903
+ padding-top: calc(var(--pcs-status-bar, 47px) + var(--prizma-spacing-8));
904
+ /* The column centres its children (the band below is the one that is
905
+ * narrower than the column). `align-items` on the parent rather than
906
+ * `align-self` or `margin-inline: auto` on the band: Core Lab's converter
907
+ * reads a flex container's alignment and ignores per-child margins and
908
+ * `align-self`, so the first take drew the 420 band at the left edge on
909
+ * the canvas while the browser centred it (Camila, 2026-10-21). */
910
+ align-items: center;
911
+ }
912
+
913
+ /* Every other child keeps the full column: `align-items: center` would
914
+ * otherwise shrink the title block to its content. */
915
+ .prizma-screen-layout__content--tutorial > :not(.prizma-screen-layout__band) {
916
+ width: 100%;
917
+ }
918
+
919
+ .prizma-screen-layout__content--tutorial > .prizma-screen-layout__flex > [class*='prizma-illustration-'] {
920
+ display: none;
921
+ }
922
+
923
+ /* The disclaimer goes with the art (Camila, 2026-11-03): title, subtitle,
924
+ * CTA. Portrait keeps it; outside the query this rule does not exist. */
925
+ .prizma-screen-layout__content--tutorial > .prizma-screen-layout__band > .prizma-disclaimer {
926
+ display: none;
927
+ }
928
+
929
+ /* The slot that held the art keeps only its flexible height, not its
930
+ * Spacing/16 padding above and below: with the illustration gone those 32
931
+ * are empty, and on the SE they were what pushed the CTA onto the tag once
932
+ * the status bar came back (QA 2026-10-21). SE budget: nav 91, Spacing/16,
933
+ * title block 76, band 109, the tag's reserve 62: 354 of 375. */
934
+ .prizma-screen-shell .prizma-screen-layout__content--tutorial > .prizma-screen-layout__flex {
935
+ padding-block: 0;
936
+ }
937
+
938
+ /* The actions take Elena's landscape column: 420, centred (Core Lab
939
+ * recipes, landscape, read off the Document Capture reference 6701:8042).
940
+ * A CTA stretched across 796 reads as a bar, not a button; 420 is the
941
+ * Title's own max width, so the axis is one. The band's tag is anchored to
942
+ * the shell and already centres. */
943
+ /* (0,3,0) on purpose: Core Lab's device CSS caps `.prizma-screen-layout__band`
944
+ * at the panel's column with a (0,2,0) rule declared later, and at 844 that
945
+ * read as "no cap" on the canvas while the browser kept 420. */
946
+ .prizma-screen-shell .prizma-screen-layout__content--tutorial > .prizma-screen-layout__band {
947
+ width: 100%;
948
+ max-width: 420px; /* hardcoded — the actions column of Elena's landscape reference, equal to Core's Title max width */
949
+ gap: var(--prizma-spacing-8); /* Elena's first concession, the same rhythm as the result band below */
950
+ }
951
+
952
+ /* ARCHETYPE F (result with a CTA band). The logo nav goes instead of the
953
+ * status mark: the mark is the one thing that tells a warning from a
954
+ * failure, the logo is the client's presence and comes back on the next
955
+ * screen (Camila, 2026-10-21: remove the logo or the icon, keep the text,
956
+ * bring the button down). The title block centres in what is left above the
957
+ * band; the band keeps its portrait seat at the bottom, above the tag, with
958
+ * #F-37's compact rhythm already in force under 720. Measured on the SE:
959
+ * title block with its mark 153, band 101, the tag's reserve 62, Spacing/16:
960
+ * 332 in 375. The genericErrors family has no nav to begin with. */
961
+ .prizma-screen-shell:has(> .prizma-screen-layout__band--result) > .prizma-screen-nav {
962
+ display: none;
963
+ }
964
+
965
+ /* The title block sits at a FIXED offset under the status bar and the band
966
+ * at the bottom: Spacing/8 under the reserve clears the bar on both frames
967
+ * (mark at 55 with 47; Elena's bar ends at 54). Not `safe center`: the
968
+ * portrait column centres the title block in the free height, which on the
969
+ * SE left the mark 2.9 px inside the bar and 12.1 when the subtitle wrapped,
970
+ * and Core Lab's converter does not centre a column's children at all, so
971
+ * the canvas and the browser disagreed about where the mark was. A fixed
972
+ * seat is the same on both. SE budget, worst case (two-line subtitle):
973
+ * 55 + 132 + 16 + 109 + 62 = 374 of 375, with the band's gap conceded
974
+ * below. */
975
+ .prizma-screen-shell:has(> .prizma-screen-layout__band--result) > .prizma-screen-layout__content {
976
+ padding-top: calc(var(--pcs-status-bar, 47px) + var(--prizma-spacing-8));
977
+ justify-content: flex-start;
978
+ }
979
+
980
+ /* Same 420 column for the result band, centred. The band stays full width
981
+ * and centres its own rows (disclaimer, CTAs, extra content), each capped
982
+ * at 420: `align-items` on a flex column is what Core Lab's converter reads,
983
+ * while `margin-inline: auto` on the band, or `align-items` on the shell
984
+ * (whose anchored footer and tag it lays out by hand), centred in the
985
+ * browser and pinned the band left on the canvas (Camila, 2026-10-21).
986
+ * (0,3,0) for the same reason as the tutorial band above. */
987
+ .prizma-screen-shell:has(> .prizma-screen-layout__band--result) > .prizma-screen-layout__band--result {
988
+ width: 100%;
989
+ align-items: center;
990
+ box-sizing: border-box;
991
+ /* Elena's first concession (Core Lab recipes, landscape): gaps 16 to 8
992
+ * before anything else goes. It is what keeps the two-line result stack
993
+ * inside the 375 SE under the restored status bar. */
994
+ gap: var(--prizma-spacing-8);
995
+ }
996
+
997
+ .prizma-screen-shell:has(> .prizma-screen-layout__band--result) > .prizma-screen-layout__band--result > * {
998
+ width: 100%;
999
+ max-width: 420px; /* hardcoded — Elena's actions column, equal to Core's Title max width */
1000
+ }
1001
+
1002
+ /* NO LOGO, NO TAG on any landscape screen (Camila, 2026-10-23: "they take
1003
+ * up space that could be used by the content"). The nav row (the client
1004
+ * logo's seat) and the verified tag go on every family; the capture screens
1005
+ * had already dropped both. The columns that reserved the tag's 62 at the
1006
+ * bottom keep Spacing/16 instead, and the result band sits Spacing/16 off
1007
+ * the bottom; the capture column keeps its 0 so the ring's centre does not
1008
+ * move. The status bar stays reserved by the columns themselves. */
1009
+ .prizma-screen-shell > .prizma-screen-nav,
1010
+ .prizma-screen-shell .prizma-screen-layout__footer,
1011
+ .prizma-screen-shell .prizma-screen-layout__band__tag {
1012
+ display: none;
1013
+ }
1014
+
1015
+ .prizma-screen-shell:has(.prizma-screen-layout__band__tag) .prizma-screen-layout__content:not(.prizma-screen-layout__content--capture) {
1016
+ padding-bottom: var(--prizma-spacing-16);
1017
+ }
1018
+
1019
+ .prizma-screen-shell:has(> .prizma-screen-layout__band--result) > .prizma-screen-layout__band--result {
1020
+ margin-bottom: var(--prizma-spacing-16);
1021
+ }
1022
+
1023
+ /* The band's disclaimer ("2 attempts remaining", "Stay still…") stays on
1024
+ * one line: in the 420 column every disclaimer the module ships fits, and
1025
+ * Core Lab's converter wrapped it to its first word otherwise (Camila,
1026
+ * 2026-10-23: "remaining attempts should always be in one line"). */
1027
+ .prizma-screen-layout__band .prizma-disclaimer__text {
1028
+ white-space: nowrap;
1029
+ }
1030
+ }
1031
+
832
1032
  /* ── Anchored-chrome layering ─────────────────────────────────────────────────
833
1033
  * The camera HUD bands lift themselves to `z-index: 1` so their copy paints
834
1034
  * above `PrizmaIdCapture`'s scrim (an absolutely positioned box-shadow that
@@ -25,6 +25,19 @@
25
25
  * layout paint` does both without forcing a composited layer the way
26
26
  * `transform` would. */
27
27
  contain: layout paint;
28
+ /* And it is the WINDOW Core's presenters size their overlays to. The Modal
29
+ * and Bottom sheet presenters draw their scrim `position: fixed` with
30
+ * `height: var(--prizma-overlay-height, 100dvh)` and pin the panel to the
31
+ * scrim's bottom, so a host whose fixed children land inside a box smaller
32
+ * than the viewport has to say so. Unsaid, the scrim inside this shell was
33
+ * the browser's height and the sheet sat at the browser's bottom edge, below
34
+ * the frame: on the closed iPhone Duo (678) Qualified Signature's certificate
35
+ * popups showed only the sheet's title peeking in at the bottom, on the open
36
+ * panel (626) nothing but scrim (measured 2026-10-29). 100% of the shell is
37
+ * the window, whatever the panel; on a real device the shell IS the viewport
38
+ * and the value reads the same. DEVIATIONS #F-41. */
39
+ --prizma-overlay-top: 0px;
40
+ --prizma-overlay-height: 100%;
28
41
  }
29
42
 
30
43
  /* Camera viewfinder screens — always a dark stage regardless of theme.
@@ -109,7 +109,10 @@ export const PrizmaTutorialScreen = forwardRef<HTMLDivElement, PrizmaTutorialScr
109
109
  {progress ? (
110
110
  <div className="prizma-screen-layout__progress">{progress}</div>
111
111
  ) : null}
112
- <div className="prizma-screen-layout__content">
112
+ {/* `--tutorial` names the archetype on the column so the landscape rule
113
+ in ScreenLayout.css (#F-39) can address it without `:has()` on the
114
+ illustration slot, which that rule hides. Portrait styles none of it. */}
115
+ <div className="prizma-screen-layout__content prizma-screen-layout__content--tutorial">
113
116
  <PrizmaTitle
114
117
  variant={overrides?.align === 'left' ? 'left' : 'centered'}
115
118
  title={title}
package/src/index.ts CHANGED
@@ -690,6 +690,17 @@ export {
690
690
  } from './ErrorScreensStrings';
691
691
  export { ErrorScreensScreen, type ErrorScreensScreenProps } from './ErrorScreensScreen';
692
692
 
693
+ // Rotate to portrait — the one prompt every capture module shows while the
694
+ // phone is held sideways; capture screens stay portrait (Camila, 2026-11-03).
695
+ // Not in the generic Figma file: born in the playground
696
+ // `artefactos/playgrounds/2026-10-29__rotate-to-portrait-prompt`. DEVIATIONS #F-42.
697
+ export { type RotateToPortraitStrings } from './RotateToPortraitStrings';
698
+ export {
699
+ RotateToPortraitScreen,
700
+ type RotateToPortraitScreenProps,
701
+ type RotateToPortraitTopEdge,
702
+ } from './RotateToPortraitScreen';
703
+
693
704
  // Demo screens — the end screen; the start screen is owner-owned and pending.
694
705
  export {
695
706
  type DemoScreensStrings,
package/src/styles.css CHANGED
@@ -31,6 +31,7 @@
31
31
  @import './PhoneInputLayout.css';
32
32
  @import './QualifiedSignatureLayout.css';
33
33
  @import './ReusabilityLayout.css';
34
+ @import './RotateToPortraitScreen.css';
34
35
  @import './ScreenLayout.css';
35
36
  @import './ScreenNav.css';
36
37
  @import './ScreenShell.css';