@basiq/connect-auth 1.1.36 → 1.1.40-alpha

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/index.mjs CHANGED
@@ -24,7 +24,7 @@ import React10 from "react";
24
24
  import { ThemeProvider } from "styled-components";
25
25
 
26
26
  // src/App.tsx
27
- import React9, { createRef, useEffect as useEffect2, useState as useState3 } from "react";
27
+ import React9, { createRef, useEffect as useEffect5, useState as useState3 } from "react";
28
28
 
29
29
  // src/styledComponents/ui/basic.ts
30
30
  import styled, { css, keyframes } from "styled-components";
@@ -53,6 +53,11 @@ var SimpleButton = styled.button`
53
53
  cursor: pointer;
54
54
  margin-bottom: 8px;
55
55
  padding: 10px;
56
+
57
+ &:focus-visible {
58
+ outline: 2px solid currentColor;
59
+ outline-offset: 2px;
60
+ }
56
61
  `;
57
62
  var Input = styled.input`
58
63
  height: 48px;
@@ -80,7 +85,8 @@ var Input = styled.input`
80
85
  }
81
86
 
82
87
  &:focus-visible {
83
- outline: none;
88
+ outline: 2px solid ${({ theme: theme2 }) => theme2.color.endeavour};
89
+ outline-offset: 2px;
84
90
  background-color: ${({ theme: theme2 }) => theme2.color.spindle};
85
91
  }
86
92
 
@@ -91,7 +97,6 @@ var Input = styled.input`
91
97
  }
92
98
  `;
93
99
  var H4Styled = styled.h4`
94
- cursor: pointer;
95
100
  user-select: none;
96
101
  ${({ theme: theme2 }) => theme2.mixin.subtitle()};
97
102
  `;
@@ -175,17 +180,17 @@ var ButtonStyled = styled2(SimpleButton)`
175
180
  justify-content: initial;
176
181
  padding: 0;
177
182
  min-height: unset;
178
- color: ${theme2.color.casper};
183
+ color: ${theme2.color.abbey};
179
184
  width: auto;
180
185
  img {
181
186
  width: 25px;
182
- filter: invert(68%) sepia(13%) saturate(348%) hue-rotate(155deg) brightness(91%) contrast(94%);
187
+ filter: invert(31%) sepia(10%) saturate(313%) hue-rotate(155deg) brightness(96%) contrast(87%);
183
188
  }
184
189
  &:hover {
185
- color: ${theme2.color.abbey};
190
+ color: ${theme2.color.jumbo};
186
191
  background-color: unset;
187
192
  img {
188
- filter: invert(31%) sepia(10%) saturate(313%) hue-rotate(155deg) brightness(96%) contrast(87%);
193
+ filter: invert(49%) sepia(0%) saturate(5%) hue-rotate(29deg) brightness(99%) contrast(83%);
189
194
  }
190
195
  }
191
196
  &:active {
@@ -217,6 +222,11 @@ var ButtonStyled = styled2(SimpleButton)`
217
222
  color: ${({ theme: theme2 }) => theme2.color.casper};
218
223
  cursor: not-allowed;
219
224
  }
225
+
226
+ &:focus-visible {
227
+ outline: 2px solid ${({ theme: theme2 }) => theme2.color.congressBlue};
228
+ outline-offset: 2px;
229
+ }
220
230
  `;
221
231
 
222
232
  // src/styledComponents/ui/modals.ts
@@ -237,8 +247,9 @@ var hexToRGBa = (hex, opacity) => {
237
247
  return `rgba(${hexToRGBA == null ? void 0 : hexToRGBA.concat(opp).join()})`;
238
248
  };
239
249
  var handleUserKeyPress = (e, onEnter) => {
240
- const { keyCode } = e;
241
- if (keyCode === 13) {
250
+ const target = e.target;
251
+ const isInteractive = target.tagName === "A" || target.tagName === "BUTTON" || target.tagName === "INPUT" || target.tagName === "SELECT" || target.tagName === "TEXTAREA" || target.getAttribute("role") === "button" || target.getAttribute("role") === "link";
252
+ if (e.key === "Enter" && !isInteractive) {
242
253
  onEnter();
243
254
  }
244
255
  };
@@ -306,7 +317,7 @@ var theme = {
306
317
  dodgerBlueLight: "#5e7Bff",
307
318
  royalBlue: "#4461e6",
308
319
  bostonBlue: "#367ab9",
309
- endeavour: "#0459a8",
320
+ endeavour: "#0460af",
310
321
  congressBlue: "#045097",
311
322
  brilliantBlue: "#0075dc",
312
323
  curiousBlue: "#2784da",
@@ -498,7 +509,7 @@ var PageConnectFooterControl = styled5.div`
498
509
  box-sizing: border-box;
499
510
  padding: 16px;
500
511
  `;
501
- var PageConnectFooterText = styled5.span`
512
+ var PageConnectFooterText = styled5.p`
502
513
  color: ${({ theme: theme2 }) => theme2.color.abbey};
503
514
  font-size: 12px;
504
515
  `;
@@ -514,6 +525,11 @@ var InputStyled = styled5.input`
514
525
  box-shadow: none;
515
526
  letter-spacing: 20px;
516
527
  text-indent: 20px;
528
+
529
+ &:focus-visible {
530
+ outline: 2px solid ${({ theme: theme2 }) => theme2.color.endeavour};
531
+ outline-offset: 2px;
532
+ }
517
533
  `;
518
534
  var InputContainer = styled5.div`
519
535
  width: 100%;
@@ -521,10 +537,22 @@ var InputContainer = styled5.div`
521
537
  align-items: center;
522
538
  justify-content: center;
523
539
  `;
524
- var DivAsLink = styled5.div`
540
+ var InlineButton = styled5.button`
525
541
  color: ${({ theme: theme2, disabled }) => disabled ? theme2.color.casper : theme2.color.endeavour};
526
- display: inherit;
542
+ display: inline;
527
543
  cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
544
+ background: none;
545
+ border: none;
546
+ padding: 0;
547
+ font-size: inherit;
548
+ font-family: inherit;
549
+ text-decoration: none;
550
+
551
+ &:focus-visible {
552
+ outline: 2px solid ${({ theme: theme2 }) => theme2.color.endeavour};
553
+ outline-offset: 2px;
554
+ border-radius: 2px;
555
+ }
528
556
  `;
529
557
 
530
558
  // src/styledComponents/pages/start.ts
@@ -583,6 +611,11 @@ var StatusScreenErrorCode = styled7.span`
583
611
  margin-top: 16px;
584
612
  color: ${({ theme: theme2 }) => theme2.color.osloGrey};
585
613
  `;
614
+ var StatusScreenTitle = styled7.h1`
615
+ font-size: 16px;
616
+ font-weight: normal;
617
+ margin: 0 0 4px 0;
618
+ `;
586
619
  var PageSuccessImgContainer = styled7.div`
587
620
  margin-bottom: 24px;
588
621
  width: 64px;
@@ -617,12 +650,16 @@ var Root = styled8.div`
617
650
  text-decoration: none;
618
651
  color: ${({ theme: theme2 }) => theme2.color.endeavour};
619
652
  }
620
- h3 {
653
+ h1 {
621
654
  font-weight: normal;
622
655
  ${({ theme: theme2 }) => theme2.mixin.title()};
623
656
  strong {
624
657
  ${({ theme: theme2 }) => theme2.mixin.title()};
625
658
  }
659
+ &:focus,
660
+ &:focus-visible {
661
+ outline: none;
662
+ }
626
663
  }
627
664
  ${devices.phone} {
628
665
  width: 100%;
@@ -701,10 +738,22 @@ body * {
701
738
  font-size: 14px;
702
739
  font-style: normal;
703
740
  }
741
+
742
+ .visually-hidden {
743
+ position: absolute;
744
+ width: 1px;
745
+ height: 1px;
746
+ padding: 0;
747
+ margin: -1px;
748
+ overflow: hidden;
749
+ clip: rect(0, 0, 0, 0);
750
+ white-space: nowrap;
751
+ border: 0;
752
+ }
704
753
  `;
705
754
 
706
755
  // src/components/pages/Page.tsx
707
- import React2 from "react";
756
+ import React2, { useEffect, useRef as useRef2 } from "react";
708
757
  import { useTranslation } from "react-i18next";
709
758
 
710
759
  // src/components/ui/Button.tsx
@@ -716,7 +765,7 @@ var back_default = 'data:image/svg+xml,<svg width="21" height="21" viewBox="0 0
716
765
  // src/components/ui/Button.tsx
717
766
  function Button(props) {
718
767
  const { onClick, label, buttonType, disabled } = props;
719
- return /* @__PURE__ */ React.createElement(ButtonStyled, { buttonType, disabled: disabled || false, onClick }, buttonType === "back" && /* @__PURE__ */ React.createElement("img", { src: back_default, alt: "" }), /* @__PURE__ */ React.createElement(ButtonLabel, null, " ", label || ""));
768
+ return /* @__PURE__ */ React.createElement(ButtonStyled, { type: "button", buttonType, disabled: disabled || false, onClick }, buttonType === "back" && /* @__PURE__ */ React.createElement("img", { src: back_default, alt: "" }), /* @__PURE__ */ React.createElement(ButtonLabel, null, " ", label || ""));
720
769
  }
721
770
  var Button_default = Button;
722
771
 
@@ -725,7 +774,14 @@ function Page(props) {
725
774
  var _a;
726
775
  const { buttons, children, title, subTitle, shadow, onBack, backDisabled } = props;
727
776
  const { t } = useTranslation();
728
- return /* @__PURE__ */ React2.createElement(PageStyled, { buttonCount: buttons == null ? void 0 : buttons.length }, onBack && /* @__PURE__ */ React2.createElement(Button_default, { onClick: onBack, label: t("back"), buttonType: "back", disabled: backDisabled }), title && /* @__PURE__ */ React2.createElement("h3", null, title), subTitle && /* @__PURE__ */ React2.createElement(PageSubtitle, null, subTitle), /* @__PURE__ */ React2.createElement(PageMainContainer, null, children), /* @__PURE__ */ React2.createElement(PageControlsSection, { notEmpty: ((_a = buttons == null ? void 0 : buttons.length) != null ? _a : 0) > 0 }, /* @__PURE__ */ React2.createElement(PageShadowWrapper, null, shadow && /* @__PURE__ */ React2.createElement(PageShadow, null), buttons == null ? void 0 : buttons.map((b, index) => /* @__PURE__ */ React2.createElement(Button_default, { key: index, onClick: b.onClick, label: b.label, buttonType: b.buttonType, disabled: b.disabled })))));
777
+ const headingRef = useRef2(null);
778
+ useEffect(() => {
779
+ var _a2;
780
+ if (title) {
781
+ (_a2 = headingRef.current) == null ? void 0 : _a2.focus();
782
+ }
783
+ }, []);
784
+ return /* @__PURE__ */ React2.createElement(PageStyled, { buttonCount: buttons == null ? void 0 : buttons.length }, onBack && /* @__PURE__ */ React2.createElement(Button_default, { onClick: onBack, label: t("back"), buttonType: "back", disabled: backDisabled }), title && /* @__PURE__ */ React2.createElement("h1", { ref: headingRef, tabIndex: -1 }, title), subTitle && /* @__PURE__ */ React2.createElement(PageSubtitle, { as: "p" }, subTitle), /* @__PURE__ */ React2.createElement("main", null, /* @__PURE__ */ React2.createElement(PageMainContainer, null, children)), /* @__PURE__ */ React2.createElement(PageControlsSection, { notEmpty: ((_a = buttons == null ? void 0 : buttons.length) != null ? _a : 0) > 0 }, /* @__PURE__ */ React2.createElement(PageShadowWrapper, null, shadow && /* @__PURE__ */ React2.createElement(PageShadow, null), buttons == null ? void 0 : buttons.map((b, index) => /* @__PURE__ */ React2.createElement(Button_default, { key: index, onClick: b.onClick, label: b.label, buttonType: b.buttonType, disabled: b.disabled })))));
729
785
  }
730
786
  var Page_default = Page;
731
787
 
@@ -736,8 +792,8 @@ import { useTranslation as useTranslation2 } from "react-i18next";
736
792
  // src/components/ui/icon.tsx
737
793
  import React3 from "react";
738
794
  function Icon(props) {
739
- const { rotating, img } = props;
740
- return /* @__PURE__ */ React3.createElement(IconWrapper, { rotating }, /* @__PURE__ */ React3.createElement("img", { src: img, alt: "" }));
795
+ const { rotating, img, alt = "" } = props;
796
+ return /* @__PURE__ */ React3.createElement(IconWrapper, { rotating }, /* @__PURE__ */ React3.createElement("img", { src: img, alt }));
741
797
  }
742
798
  var icon_default = Icon;
743
799
 
@@ -747,12 +803,12 @@ var error_default = 'data:image/svg+xml,<!-- Generated by IcoMoon.io -->%0A<svg
747
803
  // src/components/pages/NotFound.tsx
748
804
  function NotFound({ messageCode = "404" }) {
749
805
  const { t } = useTranslation2();
750
- return /* @__PURE__ */ React4.createElement(Page_default, { shadow: false }, /* @__PURE__ */ React4.createElement(PageStyled, null, /* @__PURE__ */ React4.createElement(PageStatusScreenMain, null, /* @__PURE__ */ React4.createElement(PageStyled, null, /* @__PURE__ */ React4.createElement(PageStatusScreenContent, null, /* @__PURE__ */ React4.createElement(StatusScreenCircleContainer, { type: "warning" }, /* @__PURE__ */ React4.createElement(icon_default, { img: error_default, rotating: false })), /* @__PURE__ */ React4.createElement("span", null, t("page_not_found")), /* @__PURE__ */ React4.createElement(StatusScreenErrorCode, null, `${t("error")}: ${messageCode}`)))), /* @__PURE__ */ React4.createElement(PageControlsSection, { notEmpty: false }, /* @__PURE__ */ React4.createElement(PageShadowWrapper, null))));
806
+ return /* @__PURE__ */ React4.createElement(Page_default, { shadow: false }, /* @__PURE__ */ React4.createElement(PageStyled, null, /* @__PURE__ */ React4.createElement(PageStatusScreenMain, null, /* @__PURE__ */ React4.createElement(PageStyled, null, /* @__PURE__ */ React4.createElement(PageStatusScreenContent, null, /* @__PURE__ */ React4.createElement(StatusScreenCircleContainer, { type: "warning" }, /* @__PURE__ */ React4.createElement(icon_default, { img: error_default, rotating: false })), /* @__PURE__ */ React4.createElement(StatusScreenTitle, null, t("page_not_found")), /* @__PURE__ */ React4.createElement(StatusScreenErrorCode, null, `${t("error")}: ${messageCode}`)))), /* @__PURE__ */ React4.createElement(PageControlsSection, { notEmpty: false }, /* @__PURE__ */ React4.createElement(PageShadowWrapper, null))));
751
807
  }
752
808
  var NotFound_default = NotFound;
753
809
 
754
810
  // src/components/pages/StartScreen.tsx
755
- import React7, { useEffect, useState } from "react";
811
+ import React7, { useCallback, useEffect as useEffect3, useState } from "react";
756
812
  import { Trans, useTranslation as useTranslation4 } from "react-i18next";
757
813
 
758
814
  // src/actions/actions.ts
@@ -840,15 +896,68 @@ import React6 from "react";
840
896
  import { useTranslation as useTranslation3 } from "react-i18next";
841
897
 
842
898
  // src/components/ui/Modal.tsx
843
- import React5 from "react";
899
+ import React5, { useEffect as useEffect2, useRef as useRef3 } from "react";
844
900
  function Modal(props) {
845
- const { children, onClose, isOpen, disableTransparency } = props;
901
+ const { children, onClose, isOpen, disableTransparency, role = "dialog", ariaLabel, ariaLive } = props;
902
+ const modalRef = useRef3(null);
903
+ const previousFocusRef = useRef3(null);
904
+ useEffect2(() => {
905
+ var _a, _b;
906
+ if (isOpen) {
907
+ previousFocusRef.current = document.activeElement;
908
+ (_a = modalRef.current) == null ? void 0 : _a.focus();
909
+ } else {
910
+ (_b = previousFocusRef.current) == null ? void 0 : _b.focus();
911
+ previousFocusRef.current = null;
912
+ }
913
+ }, [isOpen]);
846
914
  const handleOutsideClick = (e) => {
847
915
  if (onClose && e.target.id === "ui-modal") {
848
916
  onClose();
849
917
  }
850
918
  };
851
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, isOpen ? /* @__PURE__ */ React5.createElement(ModalStyled, { id: "ui-modal", disableTransparency, onClick: handleOutsideClick }, children) : null);
919
+ const handleKeyDown = (e) => {
920
+ if (e.key === "Escape" && onClose) {
921
+ e.stopPropagation();
922
+ onClose();
923
+ return;
924
+ }
925
+ if (!modalRef.current) return;
926
+ const focusable = modalRef.current.querySelectorAll(
927
+ 'a[href], button:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex="-1"])'
928
+ );
929
+ if (focusable.length === 0) {
930
+ if (e.key === "Tab") e.preventDefault();
931
+ return;
932
+ }
933
+ const first = focusable[0];
934
+ const last = focusable[focusable.length - 1];
935
+ if (e.key === "Tab") {
936
+ if (e.shiftKey && document.activeElement === first) {
937
+ e.preventDefault();
938
+ last.focus();
939
+ } else if (!e.shiftKey && document.activeElement === last) {
940
+ e.preventDefault();
941
+ first.focus();
942
+ }
943
+ }
944
+ };
945
+ return /* @__PURE__ */ React5.createElement(React5.Fragment, null, isOpen ? /* @__PURE__ */ React5.createElement(
946
+ ModalStyled,
947
+ {
948
+ id: "ui-modal",
949
+ ref: modalRef,
950
+ tabIndex: -1,
951
+ disableTransparency,
952
+ onClick: handleOutsideClick,
953
+ onKeyDown: handleKeyDown,
954
+ role,
955
+ "aria-modal": role === "dialog" ? true : void 0,
956
+ "aria-label": ariaLabel,
957
+ "aria-live": ariaLive
958
+ },
959
+ children
960
+ ) : null);
852
961
  }
853
962
  var Modal_default = Modal;
854
963
 
@@ -859,7 +968,8 @@ var loading_indicator_default = 'data:image/svg+xml,<!-- Generated by IcoMoon.io
859
968
  function LoadingModal(props) {
860
969
  const { isOpen, disableTransparency, loadingText } = props;
861
970
  const { t } = useTranslation3();
862
- return /* @__PURE__ */ React6.createElement(Modal_default, { isOpen, disableTransparency: !!disableTransparency }, /* @__PURE__ */ React6.createElement(LoadingModalStyled, { disableTransparency: !!disableTransparency }, /* @__PURE__ */ React6.createElement(icon_default, { img: loading_indicator_default, rotating: true }), /* @__PURE__ */ React6.createElement(LoadingModalText, null, loadingText || t("loading"))));
971
+ const label = loadingText || t("loading");
972
+ return /* @__PURE__ */ React6.createElement(Modal_default, { isOpen, disableTransparency: !!disableTransparency, role: "status", ariaLabel: label, ariaLive: "polite" }, /* @__PURE__ */ React6.createElement(LoadingModalStyled, { disableTransparency: !!disableTransparency }, /* @__PURE__ */ React6.createElement(icon_default, { img: loading_indicator_default, rotating: true, alt: "" }), /* @__PURE__ */ React6.createElement(LoadingModalText, { "aria-hidden": "true" }, label)));
863
973
  }
864
974
  var LoadingModal_default = LoadingModal;
865
975
 
@@ -868,13 +978,7 @@ function StartScreen(props) {
868
978
  const { onContinue, appName, shadow, authRequestId, showErrorScreen, smsSent, setSmsSent, test } = props;
869
979
  const [loading, setLoading] = useState(false);
870
980
  const { t } = useTranslation4();
871
- useEffect(() => {
872
- window.addEventListener("keydown", (e) => handleUserKeyPress(e, onContinue));
873
- return () => {
874
- window.removeEventListener("keydown", (e) => handleUserKeyPress(e, onContinue));
875
- };
876
- }, []);
877
- const handleContinue = () => __async(null, null, function* () {
981
+ const handleContinue = useCallback(() => __async(null, null, function* () {
878
982
  setLoading(true);
879
983
  if (authRequestId && !smsSent) {
880
984
  const response = yield authUser({ authRequestId, test });
@@ -889,7 +993,14 @@ function StartScreen(props) {
889
993
  setLoading(false);
890
994
  onContinue();
891
995
  }
892
- });
996
+ }), [authRequestId, smsSent, test, onContinue, showErrorScreen, setSmsSent]);
997
+ useEffect3(() => {
998
+ const handler = (e) => handleUserKeyPress(e, handleContinue);
999
+ window.addEventListener("keydown", handler);
1000
+ return () => {
1001
+ window.removeEventListener("keydown", handler);
1002
+ };
1003
+ }, [handleContinue]);
893
1004
  const buttons = [
894
1005
  {
895
1006
  label: t("continue"),
@@ -903,13 +1014,13 @@ function StartScreen(props) {
903
1014
  shadow,
904
1015
  buttons
905
1016
  },
906
- /* @__PURE__ */ React7.createElement(InnerContainer, null, /* @__PURE__ */ React7.createElement(Spacer, null), /* @__PURE__ */ React7.createElement(H4Styled, null, t("to_do_this_we_will_ask_you_to")), /* @__PURE__ */ React7.createElement("ul", null, /* @__PURE__ */ React7.createElement("li", null, /* @__PURE__ */ React7.createElement(Trans, { t, i18nKey: "verify_your_mobile_number_bold", components: { bold: /* @__PURE__ */ React7.createElement("strong", null) } })), /* @__PURE__ */ React7.createElement("li", null, /* @__PURE__ */ React7.createElement(Trans, { t, i18nKey: "consent_to_share_your_data_with_us", components: { bold: /* @__PURE__ */ React7.createElement("strong", null) } })), /* @__PURE__ */ React7.createElement("li", null, /* @__PURE__ */ React7.createElement(Trans, { t, i18nKey: "share_your_financial_data", components: { bold: /* @__PURE__ */ React7.createElement("strong", null) } }))), /* @__PURE__ */ React7.createElement(H4Styled, null, t("things_you_should_know")), /* @__PURE__ */ React7.createElement("ul", null, /* @__PURE__ */ React7.createElement("li", null, t("we_dont_share_your_data_without_your_consent")), /* @__PURE__ */ React7.createElement("li", null, t("you_can_easily_stop_sharing_your_data_at_any_time")), /* @__PURE__ */ React7.createElement("li", null, t("you_can_choose_to_delete_shared_data_when_we_no_longer_need_it"))), /* @__PURE__ */ React7.createElement(Spacer, null), /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement(React7.Fragment, null, t("by_proceeding_you_agree_to_the"), " ", /* @__PURE__ */ React7.createElement("a", { href: "https://docs.basiq.io/en/articles/415750-basiq-terms-of-service", rel: "noreferrer", target: "_blank" }, t("terms_of_service")), " ", t("and"), " ", /* @__PURE__ */ React7.createElement("a", { href: "https://docs.basiq.io/en/articles/382581-basiq-privacy-policy", rel: "noreferrer", target: "_blank" }, t("privacy_notice")))), /* @__PURE__ */ React7.createElement(LoadingModal_default, { isOpen: loading }))
1017
+ /* @__PURE__ */ React7.createElement(InnerContainer, null, /* @__PURE__ */ React7.createElement(Spacer, null), /* @__PURE__ */ React7.createElement("section", { "aria-labelledby": "steps-heading" }, /* @__PURE__ */ React7.createElement(H4Styled, { id: "steps-heading" }, t("to_do_this_we_will_ask_you_to")), /* @__PURE__ */ React7.createElement("ul", null, /* @__PURE__ */ React7.createElement("li", null, /* @__PURE__ */ React7.createElement(Trans, { t, i18nKey: "verify_your_mobile_number_bold", components: { bold: /* @__PURE__ */ React7.createElement("strong", null) } })), /* @__PURE__ */ React7.createElement("li", null, /* @__PURE__ */ React7.createElement(Trans, { t, i18nKey: "consent_to_share_your_data_with_us", components: { bold: /* @__PURE__ */ React7.createElement("strong", null) } })), /* @__PURE__ */ React7.createElement("li", null, /* @__PURE__ */ React7.createElement(Trans, { t, i18nKey: "share_your_financial_data", components: { bold: /* @__PURE__ */ React7.createElement("strong", null) } })))), /* @__PURE__ */ React7.createElement("section", { "aria-labelledby": "info-heading" }, /* @__PURE__ */ React7.createElement(H4Styled, { id: "info-heading" }, t("things_you_should_know")), /* @__PURE__ */ React7.createElement("ul", null, /* @__PURE__ */ React7.createElement("li", null, t("we_dont_share_your_data_without_your_consent")), /* @__PURE__ */ React7.createElement("li", null, t("you_can_easily_stop_sharing_your_data_at_any_time")), /* @__PURE__ */ React7.createElement("li", null, t("you_can_choose_to_delete_shared_data_when_we_no_longer_need_it")))), /* @__PURE__ */ React7.createElement(Spacer, null), /* @__PURE__ */ React7.createElement("p", null, t("by_proceeding_you_agree_to_the"), " ", /* @__PURE__ */ React7.createElement("a", { href: "https://docs.basiq.io/en/articles/415750-basiq-terms-of-service", rel: "noreferrer noopener", target: "_blank" }, t("terms_of_service")), " ", t("and"), " ", /* @__PURE__ */ React7.createElement("a", { href: "https://docs.basiq.io/en/articles/382581-basiq-privacy-policy", rel: "noreferrer noopener", target: "_blank" }, t("privacy_notice"))), /* @__PURE__ */ React7.createElement(LoadingModal_default, { isOpen: loading }))
907
1018
  );
908
1019
  }
909
1020
  var StartScreen_default = StartScreen;
910
1021
 
911
1022
  // src/components/pages/AuthScreen.tsx
912
- import React8, { useCallback, useState as useState2 } from "react";
1023
+ import React8, { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef4, useState as useState2 } from "react";
913
1024
  import { useTranslation as useTranslation5 } from "react-i18next";
914
1025
  function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }) {
915
1026
  const { t } = useTranslation5();
@@ -919,7 +1030,14 @@ function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }
919
1030
  const [resendLoading, setResendLoading] = useState2(false);
920
1031
  const [loading, setLoading] = useState2(false);
921
1032
  const [tooManyAttempts, setTooManyAttempts] = useState2(false);
922
- const handleCodeApply = useCallback(
1033
+ const inputRef = useRef4(null);
1034
+ useEffect4(() => {
1035
+ var _a;
1036
+ if (error) {
1037
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
1038
+ }
1039
+ }, [error]);
1040
+ const handleCodeApply = useCallback2(
923
1041
  (e) => __async(null, null, function* () {
924
1042
  var _a;
925
1043
  if (smsCode.length === 6 && error.length === 0 && (!e || (e == null ? void 0 : e.key) === "Enter")) {
@@ -966,6 +1084,10 @@ function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }
966
1084
  setSmsCode(e.target.value);
967
1085
  }
968
1086
  };
1087
+ const inputId = "sms-code-input";
1088
+ const errorId = "sms-code-error";
1089
+ const statusId = "sms-code-status";
1090
+ const describedBy = [error ? errorId : "", resend ? statusId : ""].filter(Boolean).join(" ") || void 0;
969
1091
  return /* @__PURE__ */ React8.createElement(
970
1092
  Page_default,
971
1093
  {
@@ -976,9 +1098,11 @@ function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }
976
1098
  onBack,
977
1099
  backDisabled: tooManyAttempts
978
1100
  },
979
- /* @__PURE__ */ React8.createElement(InnerContainer, null, /* @__PURE__ */ React8.createElement(InputContainer, null, /* @__PURE__ */ React8.createElement(
1101
+ /* @__PURE__ */ React8.createElement(InnerContainer, null, /* @__PURE__ */ React8.createElement(InputContainer, null, /* @__PURE__ */ React8.createElement("label", { htmlFor: inputId, className: "visually-hidden" }, t("sms_code_label")), /* @__PURE__ */ React8.createElement(
980
1102
  InputStyled,
981
1103
  {
1104
+ ref: inputRef,
1105
+ id: inputId,
982
1106
  pattern: "\\d{6}",
983
1107
  inputMode: "numeric",
984
1108
  autoComplete: "one-time-code",
@@ -989,9 +1113,21 @@ function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }
989
1113
  filled: smsCode.length === 6,
990
1114
  error: tooManyAttempts || !!error,
991
1115
  disabled: tooManyAttempts,
992
- onKeyDown: handleCodeApply
1116
+ onKeyDown: handleCodeApply,
1117
+ "aria-required": "true",
1118
+ "aria-invalid": tooManyAttempts || !!error,
1119
+ "aria-describedby": describedBy
993
1120
  }
994
- )), /* @__PURE__ */ React8.createElement(PageConnectFooterControl, null, resend && /* @__PURE__ */ React8.createElement(StatusMessage, null, t("new_sms_code_has_been_sent")), !!error && /* @__PURE__ */ React8.createElement(StatusMessage, { error: true }, error), /* @__PURE__ */ React8.createElement(PageConnectFooterText, null, /* @__PURE__ */ React8.createElement("span", null, /* @__PURE__ */ React8.createElement(React8.Fragment, null, t("didnt_receive_the_code"), " ", /* @__PURE__ */ React8.createElement(DivAsLink, { disabled: tooManyAttempts || resendLoading, onClick: () => !tooManyAttempts && !resendLoading && handleResend() }, t("resend_sms")))))), /* @__PURE__ */ React8.createElement(LoadingModal_default, { isOpen: loading }))
1121
+ )), /* @__PURE__ */ React8.createElement(PageConnectFooterControl, null, resend && /* @__PURE__ */ React8.createElement(StatusMessage, { id: statusId, role: "status", "aria-live": "polite" }, t("new_sms_code_has_been_sent")), !!error && /* @__PURE__ */ React8.createElement(StatusMessage, { id: errorId, error: true, role: "alert", "aria-live": "assertive" }, error), /* @__PURE__ */ React8.createElement(PageConnectFooterText, null, t("didnt_receive_the_code"), " ", /* @__PURE__ */ React8.createElement(
1122
+ InlineButton,
1123
+ {
1124
+ disabled: tooManyAttempts || resendLoading,
1125
+ onClick: () => !tooManyAttempts && !resendLoading && handleResend(),
1126
+ type: "button",
1127
+ "aria-busy": resendLoading
1128
+ },
1129
+ t("resend_sms")
1130
+ ))), /* @__PURE__ */ React8.createElement(LoadingModal_default, { isOpen: loading }))
995
1131
  );
996
1132
  }
997
1133
  var AuthScreen_default = AuthScreen;
@@ -1017,7 +1153,7 @@ function App(props) {
1017
1153
  setErrorCode(code);
1018
1154
  setCurrentScreen(3);
1019
1155
  };
1020
- useEffect2(() => {
1156
+ useEffect5(() => {
1021
1157
  const getData = () => __async(null, null, function* () {
1022
1158
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1023
1159
  const id = (_b = (_a = window.location.pathname) == null ? void 0 : _a.substring(1)) == null ? void 0 : _b.split("?")[0];
@@ -1072,7 +1208,7 @@ function App(props) {
1072
1208
  return /* @__PURE__ */ React9.createElement(NotFound_default, { messageCode: errorCode });
1073
1209
  }
1074
1210
  };
1075
- return /* @__PURE__ */ React9.createElement(Root, null, /* @__PURE__ */ React9.createElement(styles_default, null), /* @__PURE__ */ React9.createElement(AppContainerWrapper, null, /* @__PURE__ */ React9.createElement(AppContainer, { onScroll: handleConnectionsScroll, ref }, logo && /* @__PURE__ */ React9.createElement(PageHeader, null, /* @__PURE__ */ React9.createElement("img", { src: logo, alt: "logo" })), /* @__PURE__ */ React9.createElement(AppContainerPage, null, getScreen()))));
1211
+ return /* @__PURE__ */ React9.createElement(Root, null, /* @__PURE__ */ React9.createElement(styles_default, null), /* @__PURE__ */ React9.createElement(AppContainerWrapper, null, /* @__PURE__ */ React9.createElement(AppContainer, { onScroll: handleConnectionsScroll, ref }, logo && /* @__PURE__ */ React9.createElement(PageHeader, null, /* @__PURE__ */ React9.createElement("img", { src: logo, alt: appName ? `${appName} logo` : "Partner logo" })), /* @__PURE__ */ React9.createElement(AppContainerPage, null, getScreen()))));
1076
1212
  }
1077
1213
  var App_default = App;
1078
1214
 
@@ -1109,7 +1245,8 @@ var translation_default = {
1109
1245
  failed_to_send_sms: "Failed to send SMS.",
1110
1246
  page_not_found: "Page not found",
1111
1247
  missing_authentication_token: "Missing Authentication Token",
1112
- too_many_attempts: "Too many attempts. Please use a new link to try again."
1248
+ too_many_attempts: "Too many attempts. Please use a new link to try again.",
1249
+ sms_code_label: "SMS verification code"
1113
1250
  };
1114
1251
 
1115
1252
  // src/locales/i18n.ts