@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.js CHANGED
@@ -88,6 +88,11 @@ var SimpleButton = import_styled_components.default.button`
88
88
  cursor: pointer;
89
89
  margin-bottom: 8px;
90
90
  padding: 10px;
91
+
92
+ &:focus-visible {
93
+ outline: 2px solid currentColor;
94
+ outline-offset: 2px;
95
+ }
91
96
  `;
92
97
  var Input = import_styled_components.default.input`
93
98
  height: 48px;
@@ -115,7 +120,8 @@ var Input = import_styled_components.default.input`
115
120
  }
116
121
 
117
122
  &:focus-visible {
118
- outline: none;
123
+ outline: 2px solid ${({ theme: theme2 }) => theme2.color.endeavour};
124
+ outline-offset: 2px;
119
125
  background-color: ${({ theme: theme2 }) => theme2.color.spindle};
120
126
  }
121
127
 
@@ -126,7 +132,6 @@ var Input = import_styled_components.default.input`
126
132
  }
127
133
  `;
128
134
  var H4Styled = import_styled_components.default.h4`
129
- cursor: pointer;
130
135
  user-select: none;
131
136
  ${({ theme: theme2 }) => theme2.mixin.subtitle()};
132
137
  `;
@@ -210,17 +215,17 @@ var ButtonStyled = (0, import_styled_components2.default)(SimpleButton)`
210
215
  justify-content: initial;
211
216
  padding: 0;
212
217
  min-height: unset;
213
- color: ${theme2.color.casper};
218
+ color: ${theme2.color.abbey};
214
219
  width: auto;
215
220
  img {
216
221
  width: 25px;
217
- filter: invert(68%) sepia(13%) saturate(348%) hue-rotate(155deg) brightness(91%) contrast(94%);
222
+ filter: invert(31%) sepia(10%) saturate(313%) hue-rotate(155deg) brightness(96%) contrast(87%);
218
223
  }
219
224
  &:hover {
220
- color: ${theme2.color.abbey};
225
+ color: ${theme2.color.jumbo};
221
226
  background-color: unset;
222
227
  img {
223
- filter: invert(31%) sepia(10%) saturate(313%) hue-rotate(155deg) brightness(96%) contrast(87%);
228
+ filter: invert(49%) sepia(0%) saturate(5%) hue-rotate(29deg) brightness(99%) contrast(83%);
224
229
  }
225
230
  }
226
231
  &:active {
@@ -252,6 +257,11 @@ var ButtonStyled = (0, import_styled_components2.default)(SimpleButton)`
252
257
  color: ${({ theme: theme2 }) => theme2.color.casper};
253
258
  cursor: not-allowed;
254
259
  }
260
+
261
+ &:focus-visible {
262
+ outline: 2px solid ${({ theme: theme2 }) => theme2.color.congressBlue};
263
+ outline-offset: 2px;
264
+ }
255
265
  `;
256
266
 
257
267
  // src/styledComponents/ui/modals.ts
@@ -272,8 +282,9 @@ var hexToRGBa = (hex, opacity) => {
272
282
  return `rgba(${hexToRGBA == null ? void 0 : hexToRGBA.concat(opp).join()})`;
273
283
  };
274
284
  var handleUserKeyPress = (e, onEnter) => {
275
- const { keyCode } = e;
276
- if (keyCode === 13) {
285
+ const target = e.target;
286
+ 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";
287
+ if (e.key === "Enter" && !isInteractive) {
277
288
  onEnter();
278
289
  }
279
290
  };
@@ -341,7 +352,7 @@ var theme = {
341
352
  dodgerBlueLight: "#5e7Bff",
342
353
  royalBlue: "#4461e6",
343
354
  bostonBlue: "#367ab9",
344
- endeavour: "#0459a8",
355
+ endeavour: "#0460af",
345
356
  congressBlue: "#045097",
346
357
  brilliantBlue: "#0075dc",
347
358
  curiousBlue: "#2784da",
@@ -533,7 +544,7 @@ var PageConnectFooterControl = import_styled_components5.default.div`
533
544
  box-sizing: border-box;
534
545
  padding: 16px;
535
546
  `;
536
- var PageConnectFooterText = import_styled_components5.default.span`
547
+ var PageConnectFooterText = import_styled_components5.default.p`
537
548
  color: ${({ theme: theme2 }) => theme2.color.abbey};
538
549
  font-size: 12px;
539
550
  `;
@@ -549,6 +560,11 @@ var InputStyled = import_styled_components5.default.input`
549
560
  box-shadow: none;
550
561
  letter-spacing: 20px;
551
562
  text-indent: 20px;
563
+
564
+ &:focus-visible {
565
+ outline: 2px solid ${({ theme: theme2 }) => theme2.color.endeavour};
566
+ outline-offset: 2px;
567
+ }
552
568
  `;
553
569
  var InputContainer = import_styled_components5.default.div`
554
570
  width: 100%;
@@ -556,10 +572,22 @@ var InputContainer = import_styled_components5.default.div`
556
572
  align-items: center;
557
573
  justify-content: center;
558
574
  `;
559
- var DivAsLink = import_styled_components5.default.div`
575
+ var InlineButton = import_styled_components5.default.button`
560
576
  color: ${({ theme: theme2, disabled }) => disabled ? theme2.color.casper : theme2.color.endeavour};
561
- display: inherit;
577
+ display: inline;
562
578
  cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
579
+ background: none;
580
+ border: none;
581
+ padding: 0;
582
+ font-size: inherit;
583
+ font-family: inherit;
584
+ text-decoration: none;
585
+
586
+ &:focus-visible {
587
+ outline: 2px solid ${({ theme: theme2 }) => theme2.color.endeavour};
588
+ outline-offset: 2px;
589
+ border-radius: 2px;
590
+ }
563
591
  `;
564
592
 
565
593
  // src/styledComponents/pages/start.ts
@@ -618,6 +646,11 @@ var StatusScreenErrorCode = import_styled_components7.default.span`
618
646
  margin-top: 16px;
619
647
  color: ${({ theme: theme2 }) => theme2.color.osloGrey};
620
648
  `;
649
+ var StatusScreenTitle = import_styled_components7.default.h1`
650
+ font-size: 16px;
651
+ font-weight: normal;
652
+ margin: 0 0 4px 0;
653
+ `;
621
654
  var PageSuccessImgContainer = import_styled_components7.default.div`
622
655
  margin-bottom: 24px;
623
656
  width: 64px;
@@ -652,12 +685,16 @@ var Root = import_styled_components8.default.div`
652
685
  text-decoration: none;
653
686
  color: ${({ theme: theme2 }) => theme2.color.endeavour};
654
687
  }
655
- h3 {
688
+ h1 {
656
689
  font-weight: normal;
657
690
  ${({ theme: theme2 }) => theme2.mixin.title()};
658
691
  strong {
659
692
  ${({ theme: theme2 }) => theme2.mixin.title()};
660
693
  }
694
+ &:focus,
695
+ &:focus-visible {
696
+ outline: none;
697
+ }
661
698
  }
662
699
  ${devices.phone} {
663
700
  width: 100%;
@@ -736,6 +773,18 @@ body * {
736
773
  font-size: 14px;
737
774
  font-style: normal;
738
775
  }
776
+
777
+ .visually-hidden {
778
+ position: absolute;
779
+ width: 1px;
780
+ height: 1px;
781
+ padding: 0;
782
+ margin: -1px;
783
+ overflow: hidden;
784
+ clip: rect(0, 0, 0, 0);
785
+ white-space: nowrap;
786
+ border: 0;
787
+ }
739
788
  `;
740
789
 
741
790
  // src/components/pages/Page.tsx
@@ -751,7 +800,7 @@ var back_default = 'data:image/svg+xml,<svg width="21" height="21" viewBox="0 0
751
800
  // src/components/ui/Button.tsx
752
801
  function Button(props) {
753
802
  const { onClick, label, buttonType, disabled } = props;
754
- return /* @__PURE__ */ import_react2.default.createElement(ButtonStyled, { buttonType, disabled: disabled || false, onClick }, buttonType === "back" && /* @__PURE__ */ import_react2.default.createElement("img", { src: back_default, alt: "" }), /* @__PURE__ */ import_react2.default.createElement(ButtonLabel, null, " ", label || ""));
803
+ return /* @__PURE__ */ import_react2.default.createElement(ButtonStyled, { type: "button", buttonType, disabled: disabled || false, onClick }, buttonType === "back" && /* @__PURE__ */ import_react2.default.createElement("img", { src: back_default, alt: "" }), /* @__PURE__ */ import_react2.default.createElement(ButtonLabel, null, " ", label || ""));
755
804
  }
756
805
  var Button_default = Button;
757
806
 
@@ -760,7 +809,14 @@ function Page(props) {
760
809
  var _a;
761
810
  const { buttons, children, title, subTitle, shadow, onBack, backDisabled } = props;
762
811
  const { t } = (0, import_react_i18next.useTranslation)();
763
- return /* @__PURE__ */ import_react3.default.createElement(PageStyled, { buttonCount: buttons == null ? void 0 : buttons.length }, onBack && /* @__PURE__ */ import_react3.default.createElement(Button_default, { onClick: onBack, label: t("back"), buttonType: "back", disabled: backDisabled }), title && /* @__PURE__ */ import_react3.default.createElement("h3", null, title), subTitle && /* @__PURE__ */ import_react3.default.createElement(PageSubtitle, null, subTitle), /* @__PURE__ */ import_react3.default.createElement(PageMainContainer, null, children), /* @__PURE__ */ import_react3.default.createElement(PageControlsSection, { notEmpty: ((_a = buttons == null ? void 0 : buttons.length) != null ? _a : 0) > 0 }, /* @__PURE__ */ import_react3.default.createElement(PageShadowWrapper, null, shadow && /* @__PURE__ */ import_react3.default.createElement(PageShadow, null), buttons == null ? void 0 : buttons.map((b, index) => /* @__PURE__ */ import_react3.default.createElement(Button_default, { key: index, onClick: b.onClick, label: b.label, buttonType: b.buttonType, disabled: b.disabled })))));
812
+ const headingRef = (0, import_react3.useRef)(null);
813
+ (0, import_react3.useEffect)(() => {
814
+ var _a2;
815
+ if (title) {
816
+ (_a2 = headingRef.current) == null ? void 0 : _a2.focus();
817
+ }
818
+ }, []);
819
+ return /* @__PURE__ */ import_react3.default.createElement(PageStyled, { buttonCount: buttons == null ? void 0 : buttons.length }, onBack && /* @__PURE__ */ import_react3.default.createElement(Button_default, { onClick: onBack, label: t("back"), buttonType: "back", disabled: backDisabled }), title && /* @__PURE__ */ import_react3.default.createElement("h1", { ref: headingRef, tabIndex: -1 }, title), subTitle && /* @__PURE__ */ import_react3.default.createElement(PageSubtitle, { as: "p" }, subTitle), /* @__PURE__ */ import_react3.default.createElement("main", null, /* @__PURE__ */ import_react3.default.createElement(PageMainContainer, null, children)), /* @__PURE__ */ import_react3.default.createElement(PageControlsSection, { notEmpty: ((_a = buttons == null ? void 0 : buttons.length) != null ? _a : 0) > 0 }, /* @__PURE__ */ import_react3.default.createElement(PageShadowWrapper, null, shadow && /* @__PURE__ */ import_react3.default.createElement(PageShadow, null), buttons == null ? void 0 : buttons.map((b, index) => /* @__PURE__ */ import_react3.default.createElement(Button_default, { key: index, onClick: b.onClick, label: b.label, buttonType: b.buttonType, disabled: b.disabled })))));
764
820
  }
765
821
  var Page_default = Page;
766
822
 
@@ -771,8 +827,8 @@ var import_react_i18next2 = require("react-i18next");
771
827
  // src/components/ui/icon.tsx
772
828
  var import_react4 = __toESM(require("react"));
773
829
  function Icon(props) {
774
- const { rotating, img } = props;
775
- return /* @__PURE__ */ import_react4.default.createElement(IconWrapper, { rotating }, /* @__PURE__ */ import_react4.default.createElement("img", { src: img, alt: "" }));
830
+ const { rotating, img, alt = "" } = props;
831
+ return /* @__PURE__ */ import_react4.default.createElement(IconWrapper, { rotating }, /* @__PURE__ */ import_react4.default.createElement("img", { src: img, alt }));
776
832
  }
777
833
  var icon_default = Icon;
778
834
 
@@ -782,7 +838,7 @@ var error_default = 'data:image/svg+xml,<!-- Generated by IcoMoon.io -->%0A<svg
782
838
  // src/components/pages/NotFound.tsx
783
839
  function NotFound({ messageCode = "404" }) {
784
840
  const { t } = (0, import_react_i18next2.useTranslation)();
785
- return /* @__PURE__ */ import_react5.default.createElement(Page_default, { shadow: false }, /* @__PURE__ */ import_react5.default.createElement(PageStyled, null, /* @__PURE__ */ import_react5.default.createElement(PageStatusScreenMain, null, /* @__PURE__ */ import_react5.default.createElement(PageStyled, null, /* @__PURE__ */ import_react5.default.createElement(PageStatusScreenContent, null, /* @__PURE__ */ import_react5.default.createElement(StatusScreenCircleContainer, { type: "warning" }, /* @__PURE__ */ import_react5.default.createElement(icon_default, { img: error_default, rotating: false })), /* @__PURE__ */ import_react5.default.createElement("span", null, t("page_not_found")), /* @__PURE__ */ import_react5.default.createElement(StatusScreenErrorCode, null, `${t("error")}: ${messageCode}`)))), /* @__PURE__ */ import_react5.default.createElement(PageControlsSection, { notEmpty: false }, /* @__PURE__ */ import_react5.default.createElement(PageShadowWrapper, null))));
841
+ return /* @__PURE__ */ import_react5.default.createElement(Page_default, { shadow: false }, /* @__PURE__ */ import_react5.default.createElement(PageStyled, null, /* @__PURE__ */ import_react5.default.createElement(PageStatusScreenMain, null, /* @__PURE__ */ import_react5.default.createElement(PageStyled, null, /* @__PURE__ */ import_react5.default.createElement(PageStatusScreenContent, null, /* @__PURE__ */ import_react5.default.createElement(StatusScreenCircleContainer, { type: "warning" }, /* @__PURE__ */ import_react5.default.createElement(icon_default, { img: error_default, rotating: false })), /* @__PURE__ */ import_react5.default.createElement(StatusScreenTitle, null, t("page_not_found")), /* @__PURE__ */ import_react5.default.createElement(StatusScreenErrorCode, null, `${t("error")}: ${messageCode}`)))), /* @__PURE__ */ import_react5.default.createElement(PageControlsSection, { notEmpty: false }, /* @__PURE__ */ import_react5.default.createElement(PageShadowWrapper, null))));
786
842
  }
787
843
  var NotFound_default = NotFound;
788
844
 
@@ -877,13 +933,66 @@ var import_react_i18next3 = require("react-i18next");
877
933
  // src/components/ui/Modal.tsx
878
934
  var import_react6 = __toESM(require("react"));
879
935
  function Modal(props) {
880
- const { children, onClose, isOpen, disableTransparency } = props;
936
+ const { children, onClose, isOpen, disableTransparency, role = "dialog", ariaLabel, ariaLive } = props;
937
+ const modalRef = (0, import_react6.useRef)(null);
938
+ const previousFocusRef = (0, import_react6.useRef)(null);
939
+ (0, import_react6.useEffect)(() => {
940
+ var _a, _b;
941
+ if (isOpen) {
942
+ previousFocusRef.current = document.activeElement;
943
+ (_a = modalRef.current) == null ? void 0 : _a.focus();
944
+ } else {
945
+ (_b = previousFocusRef.current) == null ? void 0 : _b.focus();
946
+ previousFocusRef.current = null;
947
+ }
948
+ }, [isOpen]);
881
949
  const handleOutsideClick = (e) => {
882
950
  if (onClose && e.target.id === "ui-modal") {
883
951
  onClose();
884
952
  }
885
953
  };
886
- return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, isOpen ? /* @__PURE__ */ import_react6.default.createElement(ModalStyled, { id: "ui-modal", disableTransparency, onClick: handleOutsideClick }, children) : null);
954
+ const handleKeyDown = (e) => {
955
+ if (e.key === "Escape" && onClose) {
956
+ e.stopPropagation();
957
+ onClose();
958
+ return;
959
+ }
960
+ if (!modalRef.current) return;
961
+ const focusable = modalRef.current.querySelectorAll(
962
+ 'a[href], button:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex="-1"])'
963
+ );
964
+ if (focusable.length === 0) {
965
+ if (e.key === "Tab") e.preventDefault();
966
+ return;
967
+ }
968
+ const first = focusable[0];
969
+ const last = focusable[focusable.length - 1];
970
+ if (e.key === "Tab") {
971
+ if (e.shiftKey && document.activeElement === first) {
972
+ e.preventDefault();
973
+ last.focus();
974
+ } else if (!e.shiftKey && document.activeElement === last) {
975
+ e.preventDefault();
976
+ first.focus();
977
+ }
978
+ }
979
+ };
980
+ return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, isOpen ? /* @__PURE__ */ import_react6.default.createElement(
981
+ ModalStyled,
982
+ {
983
+ id: "ui-modal",
984
+ ref: modalRef,
985
+ tabIndex: -1,
986
+ disableTransparency,
987
+ onClick: handleOutsideClick,
988
+ onKeyDown: handleKeyDown,
989
+ role,
990
+ "aria-modal": role === "dialog" ? true : void 0,
991
+ "aria-label": ariaLabel,
992
+ "aria-live": ariaLive
993
+ },
994
+ children
995
+ ) : null);
887
996
  }
888
997
  var Modal_default = Modal;
889
998
 
@@ -894,7 +1003,8 @@ var loading_indicator_default = 'data:image/svg+xml,<!-- Generated by IcoMoon.io
894
1003
  function LoadingModal(props) {
895
1004
  const { isOpen, disableTransparency, loadingText } = props;
896
1005
  const { t } = (0, import_react_i18next3.useTranslation)();
897
- return /* @__PURE__ */ import_react7.default.createElement(Modal_default, { isOpen, disableTransparency: !!disableTransparency }, /* @__PURE__ */ import_react7.default.createElement(LoadingModalStyled, { disableTransparency: !!disableTransparency }, /* @__PURE__ */ import_react7.default.createElement(icon_default, { img: loading_indicator_default, rotating: true }), /* @__PURE__ */ import_react7.default.createElement(LoadingModalText, null, loadingText || t("loading"))));
1006
+ const label = loadingText || t("loading");
1007
+ return /* @__PURE__ */ import_react7.default.createElement(Modal_default, { isOpen, disableTransparency: !!disableTransparency, role: "status", ariaLabel: label, ariaLive: "polite" }, /* @__PURE__ */ import_react7.default.createElement(LoadingModalStyled, { disableTransparency: !!disableTransparency }, /* @__PURE__ */ import_react7.default.createElement(icon_default, { img: loading_indicator_default, rotating: true, alt: "" }), /* @__PURE__ */ import_react7.default.createElement(LoadingModalText, { "aria-hidden": "true" }, label)));
898
1008
  }
899
1009
  var LoadingModal_default = LoadingModal;
900
1010
 
@@ -903,13 +1013,7 @@ function StartScreen(props) {
903
1013
  const { onContinue, appName, shadow, authRequestId, showErrorScreen, smsSent, setSmsSent, test } = props;
904
1014
  const [loading, setLoading] = (0, import_react8.useState)(false);
905
1015
  const { t } = (0, import_react_i18next4.useTranslation)();
906
- (0, import_react8.useEffect)(() => {
907
- window.addEventListener("keydown", (e) => handleUserKeyPress(e, onContinue));
908
- return () => {
909
- window.removeEventListener("keydown", (e) => handleUserKeyPress(e, onContinue));
910
- };
911
- }, []);
912
- const handleContinue = () => __async(null, null, function* () {
1016
+ const handleContinue = (0, import_react8.useCallback)(() => __async(null, null, function* () {
913
1017
  setLoading(true);
914
1018
  if (authRequestId && !smsSent) {
915
1019
  const response = yield authUser({ authRequestId, test });
@@ -924,7 +1028,14 @@ function StartScreen(props) {
924
1028
  setLoading(false);
925
1029
  onContinue();
926
1030
  }
927
- });
1031
+ }), [authRequestId, smsSent, test, onContinue, showErrorScreen, setSmsSent]);
1032
+ (0, import_react8.useEffect)(() => {
1033
+ const handler = (e) => handleUserKeyPress(e, handleContinue);
1034
+ window.addEventListener("keydown", handler);
1035
+ return () => {
1036
+ window.removeEventListener("keydown", handler);
1037
+ };
1038
+ }, [handleContinue]);
928
1039
  const buttons = [
929
1040
  {
930
1041
  label: t("continue"),
@@ -938,7 +1049,7 @@ function StartScreen(props) {
938
1049
  shadow,
939
1050
  buttons
940
1051
  },
941
- /* @__PURE__ */ import_react8.default.createElement(InnerContainer, null, /* @__PURE__ */ import_react8.default.createElement(Spacer, null), /* @__PURE__ */ import_react8.default.createElement(H4Styled, null, t("to_do_this_we_will_ask_you_to")), /* @__PURE__ */ import_react8.default.createElement("ul", null, /* @__PURE__ */ import_react8.default.createElement("li", null, /* @__PURE__ */ import_react8.default.createElement(import_react_i18next4.Trans, { t, i18nKey: "verify_your_mobile_number_bold", components: { bold: /* @__PURE__ */ import_react8.default.createElement("strong", null) } })), /* @__PURE__ */ import_react8.default.createElement("li", null, /* @__PURE__ */ import_react8.default.createElement(import_react_i18next4.Trans, { t, i18nKey: "consent_to_share_your_data_with_us", components: { bold: /* @__PURE__ */ import_react8.default.createElement("strong", null) } })), /* @__PURE__ */ import_react8.default.createElement("li", null, /* @__PURE__ */ import_react8.default.createElement(import_react_i18next4.Trans, { t, i18nKey: "share_your_financial_data", components: { bold: /* @__PURE__ */ import_react8.default.createElement("strong", null) } }))), /* @__PURE__ */ import_react8.default.createElement(H4Styled, null, t("things_you_should_know")), /* @__PURE__ */ import_react8.default.createElement("ul", null, /* @__PURE__ */ import_react8.default.createElement("li", null, t("we_dont_share_your_data_without_your_consent")), /* @__PURE__ */ import_react8.default.createElement("li", null, t("you_can_easily_stop_sharing_your_data_at_any_time")), /* @__PURE__ */ import_react8.default.createElement("li", null, t("you_can_choose_to_delete_shared_data_when_we_no_longer_need_it"))), /* @__PURE__ */ import_react8.default.createElement(Spacer, null), /* @__PURE__ */ import_react8.default.createElement("span", null, /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, t("by_proceeding_you_agree_to_the"), " ", /* @__PURE__ */ import_react8.default.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__ */ import_react8.default.createElement("a", { href: "https://docs.basiq.io/en/articles/382581-basiq-privacy-policy", rel: "noreferrer", target: "_blank" }, t("privacy_notice")))), /* @__PURE__ */ import_react8.default.createElement(LoadingModal_default, { isOpen: loading }))
1052
+ /* @__PURE__ */ import_react8.default.createElement(InnerContainer, null, /* @__PURE__ */ import_react8.default.createElement(Spacer, null), /* @__PURE__ */ import_react8.default.createElement("section", { "aria-labelledby": "steps-heading" }, /* @__PURE__ */ import_react8.default.createElement(H4Styled, { id: "steps-heading" }, t("to_do_this_we_will_ask_you_to")), /* @__PURE__ */ import_react8.default.createElement("ul", null, /* @__PURE__ */ import_react8.default.createElement("li", null, /* @__PURE__ */ import_react8.default.createElement(import_react_i18next4.Trans, { t, i18nKey: "verify_your_mobile_number_bold", components: { bold: /* @__PURE__ */ import_react8.default.createElement("strong", null) } })), /* @__PURE__ */ import_react8.default.createElement("li", null, /* @__PURE__ */ import_react8.default.createElement(import_react_i18next4.Trans, { t, i18nKey: "consent_to_share_your_data_with_us", components: { bold: /* @__PURE__ */ import_react8.default.createElement("strong", null) } })), /* @__PURE__ */ import_react8.default.createElement("li", null, /* @__PURE__ */ import_react8.default.createElement(import_react_i18next4.Trans, { t, i18nKey: "share_your_financial_data", components: { bold: /* @__PURE__ */ import_react8.default.createElement("strong", null) } })))), /* @__PURE__ */ import_react8.default.createElement("section", { "aria-labelledby": "info-heading" }, /* @__PURE__ */ import_react8.default.createElement(H4Styled, { id: "info-heading" }, t("things_you_should_know")), /* @__PURE__ */ import_react8.default.createElement("ul", null, /* @__PURE__ */ import_react8.default.createElement("li", null, t("we_dont_share_your_data_without_your_consent")), /* @__PURE__ */ import_react8.default.createElement("li", null, t("you_can_easily_stop_sharing_your_data_at_any_time")), /* @__PURE__ */ import_react8.default.createElement("li", null, t("you_can_choose_to_delete_shared_data_when_we_no_longer_need_it")))), /* @__PURE__ */ import_react8.default.createElement(Spacer, null), /* @__PURE__ */ import_react8.default.createElement("p", null, t("by_proceeding_you_agree_to_the"), " ", /* @__PURE__ */ import_react8.default.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__ */ import_react8.default.createElement("a", { href: "https://docs.basiq.io/en/articles/382581-basiq-privacy-policy", rel: "noreferrer noopener", target: "_blank" }, t("privacy_notice"))), /* @__PURE__ */ import_react8.default.createElement(LoadingModal_default, { isOpen: loading }))
942
1053
  );
943
1054
  }
944
1055
  var StartScreen_default = StartScreen;
@@ -954,6 +1065,13 @@ function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }
954
1065
  const [resendLoading, setResendLoading] = (0, import_react9.useState)(false);
955
1066
  const [loading, setLoading] = (0, import_react9.useState)(false);
956
1067
  const [tooManyAttempts, setTooManyAttempts] = (0, import_react9.useState)(false);
1068
+ const inputRef = (0, import_react9.useRef)(null);
1069
+ (0, import_react9.useEffect)(() => {
1070
+ var _a;
1071
+ if (error) {
1072
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
1073
+ }
1074
+ }, [error]);
957
1075
  const handleCodeApply = (0, import_react9.useCallback)(
958
1076
  (e) => __async(null, null, function* () {
959
1077
  var _a;
@@ -1001,6 +1119,10 @@ function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }
1001
1119
  setSmsCode(e.target.value);
1002
1120
  }
1003
1121
  };
1122
+ const inputId = "sms-code-input";
1123
+ const errorId = "sms-code-error";
1124
+ const statusId = "sms-code-status";
1125
+ const describedBy = [error ? errorId : "", resend ? statusId : ""].filter(Boolean).join(" ") || void 0;
1004
1126
  return /* @__PURE__ */ import_react9.default.createElement(
1005
1127
  Page_default,
1006
1128
  {
@@ -1011,9 +1133,11 @@ function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }
1011
1133
  onBack,
1012
1134
  backDisabled: tooManyAttempts
1013
1135
  },
1014
- /* @__PURE__ */ import_react9.default.createElement(InnerContainer, null, /* @__PURE__ */ import_react9.default.createElement(InputContainer, null, /* @__PURE__ */ import_react9.default.createElement(
1136
+ /* @__PURE__ */ import_react9.default.createElement(InnerContainer, null, /* @__PURE__ */ import_react9.default.createElement(InputContainer, null, /* @__PURE__ */ import_react9.default.createElement("label", { htmlFor: inputId, className: "visually-hidden" }, t("sms_code_label")), /* @__PURE__ */ import_react9.default.createElement(
1015
1137
  InputStyled,
1016
1138
  {
1139
+ ref: inputRef,
1140
+ id: inputId,
1017
1141
  pattern: "\\d{6}",
1018
1142
  inputMode: "numeric",
1019
1143
  autoComplete: "one-time-code",
@@ -1024,9 +1148,21 @@ function AuthScreen({ onBack, number, authRequestId, shadow, test, queryString }
1024
1148
  filled: smsCode.length === 6,
1025
1149
  error: tooManyAttempts || !!error,
1026
1150
  disabled: tooManyAttempts,
1027
- onKeyDown: handleCodeApply
1151
+ onKeyDown: handleCodeApply,
1152
+ "aria-required": "true",
1153
+ "aria-invalid": tooManyAttempts || !!error,
1154
+ "aria-describedby": describedBy
1028
1155
  }
1029
- )), /* @__PURE__ */ import_react9.default.createElement(PageConnectFooterControl, null, resend && /* @__PURE__ */ import_react9.default.createElement(StatusMessage, null, t("new_sms_code_has_been_sent")), !!error && /* @__PURE__ */ import_react9.default.createElement(StatusMessage, { error: true }, error), /* @__PURE__ */ import_react9.default.createElement(PageConnectFooterText, null, /* @__PURE__ */ import_react9.default.createElement("span", null, /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, t("didnt_receive_the_code"), " ", /* @__PURE__ */ import_react9.default.createElement(DivAsLink, { disabled: tooManyAttempts || resendLoading, onClick: () => !tooManyAttempts && !resendLoading && handleResend() }, t("resend_sms")))))), /* @__PURE__ */ import_react9.default.createElement(LoadingModal_default, { isOpen: loading }))
1156
+ )), /* @__PURE__ */ import_react9.default.createElement(PageConnectFooterControl, null, resend && /* @__PURE__ */ import_react9.default.createElement(StatusMessage, { id: statusId, role: "status", "aria-live": "polite" }, t("new_sms_code_has_been_sent")), !!error && /* @__PURE__ */ import_react9.default.createElement(StatusMessage, { id: errorId, error: true, role: "alert", "aria-live": "assertive" }, error), /* @__PURE__ */ import_react9.default.createElement(PageConnectFooterText, null, t("didnt_receive_the_code"), " ", /* @__PURE__ */ import_react9.default.createElement(
1157
+ InlineButton,
1158
+ {
1159
+ disabled: tooManyAttempts || resendLoading,
1160
+ onClick: () => !tooManyAttempts && !resendLoading && handleResend(),
1161
+ type: "button",
1162
+ "aria-busy": resendLoading
1163
+ },
1164
+ t("resend_sms")
1165
+ ))), /* @__PURE__ */ import_react9.default.createElement(LoadingModal_default, { isOpen: loading }))
1030
1166
  );
1031
1167
  }
1032
1168
  var AuthScreen_default = AuthScreen;
@@ -1107,7 +1243,7 @@ function App(props) {
1107
1243
  return /* @__PURE__ */ import_react10.default.createElement(NotFound_default, { messageCode: errorCode });
1108
1244
  }
1109
1245
  };
1110
- return /* @__PURE__ */ import_react10.default.createElement(Root, null, /* @__PURE__ */ import_react10.default.createElement(styles_default, null), /* @__PURE__ */ import_react10.default.createElement(AppContainerWrapper, null, /* @__PURE__ */ import_react10.default.createElement(AppContainer, { onScroll: handleConnectionsScroll, ref }, logo && /* @__PURE__ */ import_react10.default.createElement(PageHeader, null, /* @__PURE__ */ import_react10.default.createElement("img", { src: logo, alt: "logo" })), /* @__PURE__ */ import_react10.default.createElement(AppContainerPage, null, getScreen()))));
1246
+ return /* @__PURE__ */ import_react10.default.createElement(Root, null, /* @__PURE__ */ import_react10.default.createElement(styles_default, null), /* @__PURE__ */ import_react10.default.createElement(AppContainerWrapper, null, /* @__PURE__ */ import_react10.default.createElement(AppContainer, { onScroll: handleConnectionsScroll, ref }, logo && /* @__PURE__ */ import_react10.default.createElement(PageHeader, null, /* @__PURE__ */ import_react10.default.createElement("img", { src: logo, alt: appName ? `${appName} logo` : "Partner logo" })), /* @__PURE__ */ import_react10.default.createElement(AppContainerPage, null, getScreen()))));
1111
1247
  }
1112
1248
  var App_default = App;
1113
1249
 
@@ -1144,7 +1280,8 @@ var translation_default = {
1144
1280
  failed_to_send_sms: "Failed to send SMS.",
1145
1281
  page_not_found: "Page not found",
1146
1282
  missing_authentication_token: "Missing Authentication Token",
1147
- too_many_attempts: "Too many attempts. Please use a new link to try again."
1283
+ too_many_attempts: "Too many attempts. Please use a new link to try again.",
1284
+ sms_code_label: "SMS verification code"
1148
1285
  };
1149
1286
 
1150
1287
  // src/locales/i18n.ts