@authowl/react 0.21.2 → 0.23.0

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.cjs CHANGED
@@ -737,6 +737,42 @@ var init_InvitationPrompt = __esm({
737
737
  }
738
738
  });
739
739
 
740
+ // src/last-used-method.ts
741
+ function useLastUsedSignInMethod() {
742
+ const { config } = usePublicConfig();
743
+ const projectId = config?.environmentId ?? null;
744
+ return React5.useMemo(
745
+ () => projectId ? (0, import_core2.readLastUsedSignInMethod)(projectId) : null,
746
+ [projectId]
747
+ );
748
+ }
749
+ function useSignInMethodRecorder() {
750
+ const { config } = usePublicConfig();
751
+ const projectId = config?.environmentId ?? null;
752
+ return React5.useCallback(
753
+ (method, pending) => {
754
+ if (!projectId) return;
755
+ (pending ? import_core2.rememberPendingSignInMethod : import_core2.recordLastUsedSignInMethod)(projectId, method);
756
+ },
757
+ [projectId]
758
+ );
759
+ }
760
+ function useConfirmPendingSignInMethod(loaded, signedIn, projectId) {
761
+ React5.useEffect(() => {
762
+ if (loaded && projectId) (0, import_core2.settlePendingSignInMethod)(projectId, signedIn);
763
+ }, [loaded, projectId, signedIn]);
764
+ }
765
+ var React5, import_core2;
766
+ var init_last_used_method = __esm({
767
+ "src/last-used-method.ts"() {
768
+ "use strict";
769
+ "use client";
770
+ React5 = __toESM(require("react"), 1);
771
+ import_core2 = require("@authowl/core");
772
+ init_hooks();
773
+ }
774
+ });
775
+
740
776
  // src/provider.tsx
741
777
  function warnPublicConfigFailed(resolved, error) {
742
778
  let origin = resolved.apiUrl;
@@ -752,6 +788,12 @@ function warnPublicConfigFailed(resolved, error) {
752
788
  `[AuthOwl] Could not load this project's public config from ${origin} (${reason}). Authentication UI is unavailable until the request succeeds. Likely causes: the API is unreachable, \`apiUrl\` is wrong, or the publishable key points at a missing/mismatched project. Check \`apiUrl\` and \`publishableKey\` on <AuthOwlProvider>. (This warning is dev-only.)`
753
789
  );
754
790
  }
791
+ function LastUsedMethodSync() {
792
+ const { config } = usePublicConfig();
793
+ const { isLoaded, isSignedIn } = useUser();
794
+ useConfirmPendingSignInMethod(isLoaded, isSignedIn, config?.environmentId ?? null);
795
+ return null;
796
+ }
755
797
  function detectLocale() {
756
798
  if (typeof document !== "undefined") {
757
799
  const root = document.documentElement;
@@ -763,9 +805,9 @@ function detectLocale() {
763
805
  return "en";
764
806
  }
765
807
  function resolveLocale(prop, autoDetected, configLocale) {
766
- if (prop !== "auto" && (0, import_core2.isLocale)(prop)) return prop;
808
+ if (prop !== "auto" && (0, import_core3.isLocale)(prop)) return prop;
767
809
  if (prop === "auto") return autoDetected ?? "en";
768
- return (0, import_core2.isLocale)(configLocale) ? configLocale : "en";
810
+ return (0, import_core3.isLocale)(configLocale) ? configLocale : "en";
769
811
  }
770
812
  function AuthOwlProvider({
771
813
  publishableKey,
@@ -776,21 +818,21 @@ function AuthOwlProvider({
776
818
  invitationPrompt = true,
777
819
  children
778
820
  }) {
779
- const fetchRef = React5.useRef(fetch);
821
+ const fetchRef = React6.useRef(fetch);
780
822
  fetchRef.current = fetch;
781
- const resolved = React5.useMemo(
782
- () => (0, import_core2.resolveConfig)({ publishableKey, apiUrl, fetch: fetchRef.current }),
823
+ const resolved = React6.useMemo(
824
+ () => (0, import_core3.resolveConfig)({ publishableKey, apiUrl, fetch: fetchRef.current }),
783
825
  [publishableKey, apiUrl]
784
826
  );
785
- const client = React5.useMemo(() => (0, import_core2.createAuthOwlClient)(resolved), [resolved]);
786
- const [config, setConfig] = React5.useState(null);
787
- const [configState, setConfigState] = React5.useState("loading");
788
- const [configAttempt, setConfigAttempt] = React5.useState(0);
789
- const retryPublicConfig = React5.useCallback(() => setConfigAttempt((attempt) => attempt + 1), []);
790
- React5.useEffect(() => {
827
+ const client = React6.useMemo(() => (0, import_core3.createAuthOwlClient)(resolved), [resolved]);
828
+ const [config, setConfig] = React6.useState(null);
829
+ const [configState, setConfigState] = React6.useState("loading");
830
+ const [configAttempt, setConfigAttempt] = React6.useState(0);
831
+ const retryPublicConfig = React6.useCallback(() => setConfigAttempt((attempt) => attempt + 1), []);
832
+ React6.useEffect(() => {
791
833
  let active = true;
792
834
  setConfigState("loading");
793
- (0, import_core2.getPublicConfig)(resolved).then((c) => {
835
+ (0, import_core3.getPublicConfig)(resolved).then((c) => {
794
836
  if (!active) return;
795
837
  setConfig(c);
796
838
  setConfigState("ready");
@@ -805,15 +847,18 @@ function AuthOwlProvider({
805
847
  };
806
848
  }, [resolved, configAttempt]);
807
849
  const merged = resolveAppearance(appearance, config);
808
- const [autoLocale, setAutoLocale] = React5.useState(null);
809
- React5.useEffect(() => {
850
+ const [autoLocale, setAutoLocale] = React6.useState(null);
851
+ React6.useEffect(() => {
810
852
  if (localeProp === "auto") setAutoLocale(detectLocale());
811
853
  }, [localeProp]);
812
854
  const locale = resolveLocale(localeProp, autoLocale, config?.locale);
813
- React5.useEffect(() => {
814
- (0, import_core2.captureInvitationClaim)();
855
+ React6.useEffect(() => {
856
+ return (0, import_core3.setActiveLocale)(resolved.decoded.projectId, locale);
857
+ }, [locale, resolved.decoded.projectId]);
858
+ React6.useEffect(() => {
859
+ (0, import_core3.captureInvitationClaim)();
815
860
  }, []);
816
- const ctxValue = React5.useMemo(
861
+ const ctxValue = React6.useMemo(
817
862
  () => ({ client, appearance, config, configState, retryPublicConfig, locale }),
818
863
  [client, appearance, config, configState, retryPublicConfig, locale]
819
864
  );
@@ -823,43 +868,46 @@ function AuthOwlProvider({
823
868
  className: "authowl-root",
824
869
  "data-authowl-theme": merged.theme,
825
870
  "data-authowl-locale": locale,
826
- dir: (0, import_core2.directionFor)(locale),
871
+ dir: (0, import_core3.directionFor)(locale),
827
872
  style: { display: "contents", ...merged.style },
828
873
  children: [
829
874
  children,
875
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LastUsedMethodSync, {}),
830
876
  invitationPrompt ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InvitationPrompt, {}) : null
831
877
  ]
832
878
  }
833
879
  ) });
834
880
  }
835
881
  function useAuthOwlContext() {
836
- const v = React5.useContext(Context);
882
+ const v = React6.useContext(Context);
837
883
  if (!v) {
838
884
  throw new Error("AuthOwl hooks must be used inside <AuthOwlProvider>");
839
885
  }
840
886
  return v;
841
887
  }
842
- var React5, import_core2, import_jsx_runtime4, warnedConfigProjects, Context;
888
+ var React6, import_core3, import_jsx_runtime4, warnedConfigProjects, Context;
843
889
  var init_provider = __esm({
844
890
  "src/provider.tsx"() {
845
891
  "use strict";
846
892
  "use client";
847
- React5 = __toESM(require("react"), 1);
848
- import_core2 = require("@authowl/core");
893
+ React6 = __toESM(require("react"), 1);
894
+ import_core3 = require("@authowl/core");
849
895
  init_appearance();
850
896
  init_InvitationPrompt();
897
+ init_last_used_method();
898
+ init_hooks();
851
899
  import_jsx_runtime4 = require("react/jsx-runtime");
852
900
  warnedConfigProjects = /* @__PURE__ */ new Set();
853
- Context = React5.createContext(null);
901
+ Context = React6.createContext(null);
854
902
  }
855
903
  });
856
904
 
857
905
  // src/components/use-submit-action.ts
858
906
  function useSubmitAction() {
859
- const [pending, setPending] = React6.useState(false);
860
- const [error, setError] = React6.useState(null);
907
+ const [pending, setPending] = React7.useState(false);
908
+ const [error, setError] = React7.useState(null);
861
909
  const toMessage = useServerError();
862
- const run = React6.useCallback(
910
+ const run = React7.useCallback(
863
911
  async (action, { failure, onSuccess, mapError, keepPendingOnSuccess }) => {
864
912
  setError(null);
865
913
  setPending(true);
@@ -881,12 +929,12 @@ function useSubmitAction() {
881
929
  );
882
930
  return { pending, error, setError, run };
883
931
  }
884
- var React6;
932
+ var React7;
885
933
  var init_use_submit_action = __esm({
886
934
  "src/components/use-submit-action.ts"() {
887
935
  "use strict";
888
936
  "use client";
889
- React6 = __toESM(require("react"), 1);
937
+ React7 = __toESM(require("react"), 1);
890
938
  init_i18n();
891
939
  }
892
940
  });
@@ -933,6 +981,159 @@ var init_FormError = __esm({
933
981
  }
934
982
  });
935
983
 
984
+ // src/components/captcha-loader.ts
985
+ var captcha_loader_exports = {};
986
+ __export(captcha_loader_exports, {
987
+ loadCaptcha: () => loadCaptcha
988
+ });
989
+ function providerGlobal(adapter) {
990
+ const api = window[adapter.globalName];
991
+ return typeof api?.render === "function" ? api : void 0;
992
+ }
993
+ function loadCaptcha(adapter) {
994
+ const available = providerGlobal(adapter);
995
+ if (available) return Promise.resolve(available);
996
+ const cached = loaders.get(adapter.scriptUrl);
997
+ if (cached) return cached;
998
+ const loading = new Promise((resolve, reject) => {
999
+ const existing = document.querySelector(
1000
+ `script[src="${adapter.scriptUrl}"]`
1001
+ );
1002
+ const script = existing ?? document.createElement("script");
1003
+ let poll;
1004
+ const cleanup = () => {
1005
+ clearTimeout(timeout);
1006
+ if (poll !== void 0) clearInterval(poll);
1007
+ script.removeEventListener("load", loaded);
1008
+ script.removeEventListener("error", failed);
1009
+ };
1010
+ const resolveWhenPublished = () => {
1011
+ const api = providerGlobal(adapter);
1012
+ if (!api) return false;
1013
+ cleanup();
1014
+ resolve(api);
1015
+ return true;
1016
+ };
1017
+ const loaded = () => {
1018
+ if (!resolveWhenPublished() && poll === void 0) {
1019
+ poll = setInterval(resolveWhenPublished, GLOBAL_POLL_INTERVAL_MS);
1020
+ }
1021
+ };
1022
+ const failed = () => {
1023
+ cleanup();
1024
+ if (!existing) script.remove();
1025
+ reject(new Error(`${adapter.label} failed to load`));
1026
+ };
1027
+ const timeout = setTimeout(failed, SCRIPT_LOAD_TIMEOUT_MS);
1028
+ script.addEventListener("load", loaded, { once: true });
1029
+ script.addEventListener("error", failed, { once: true });
1030
+ if (existing) {
1031
+ loaded();
1032
+ } else {
1033
+ script.src = adapter.scriptUrl;
1034
+ script.async = true;
1035
+ script.defer = true;
1036
+ const nonce = document.querySelector("script[nonce]")?.nonce;
1037
+ if (nonce) script.nonce = nonce;
1038
+ document.head.appendChild(script);
1039
+ }
1040
+ });
1041
+ const retryable = loading.catch((error) => {
1042
+ loaders.delete(adapter.scriptUrl);
1043
+ throw error;
1044
+ });
1045
+ loaders.set(adapter.scriptUrl, retryable);
1046
+ return retryable;
1047
+ }
1048
+ var SCRIPT_LOAD_TIMEOUT_MS, GLOBAL_POLL_INTERVAL_MS, loaders;
1049
+ var init_captcha_loader = __esm({
1050
+ "src/components/captcha-loader.ts"() {
1051
+ "use strict";
1052
+ "use client";
1053
+ SCRIPT_LOAD_TIMEOUT_MS = 1e4;
1054
+ GLOBAL_POLL_INTERVAL_MS = 25;
1055
+ loaders = /* @__PURE__ */ new Map();
1056
+ }
1057
+ });
1058
+
1059
+ // src/components/captcha-providers.ts
1060
+ var captcha_providers_exports = {};
1061
+ __export(captcha_providers_exports, {
1062
+ CAPTCHA_ADAPTERS: () => CAPTCHA_ADAPTERS,
1063
+ captchaAdapterFor: () => captchaAdapterFor
1064
+ });
1065
+ function preferredTheme() {
1066
+ return typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
1067
+ }
1068
+ function teardown(api, widgetId) {
1069
+ if (api.remove) {
1070
+ try {
1071
+ api.remove(widgetId);
1072
+ return;
1073
+ } catch {
1074
+ }
1075
+ }
1076
+ try {
1077
+ api.reset?.(widgetId);
1078
+ } catch {
1079
+ }
1080
+ }
1081
+ function captchaAdapterFor(provider) {
1082
+ return CAPTCHA_ADAPTERS[provider] ?? null;
1083
+ }
1084
+ var CAPTCHA_ADAPTERS;
1085
+ var init_captcha_providers = __esm({
1086
+ "src/components/captcha-providers.ts"() {
1087
+ "use strict";
1088
+ "use client";
1089
+ CAPTCHA_ADAPTERS = {
1090
+ turnstile: {
1091
+ scriptUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",
1092
+ globalName: "turnstile",
1093
+ label: "Cloudflare Turnstile",
1094
+ invisibleRenderOptions: ({ siteKey, theme, action, language }) => ({
1095
+ sitekey: siteKey,
1096
+ theme,
1097
+ action,
1098
+ language,
1099
+ execution: "execute",
1100
+ appearance: "interaction-only",
1101
+ size: "flexible"
1102
+ }),
1103
+ teardown
1104
+ },
1105
+ hcaptcha: {
1106
+ scriptUrl: "https://js.hcaptcha.com/1/api.js?render=explicit",
1107
+ globalName: "hcaptcha",
1108
+ label: "hCaptcha",
1109
+ invisibleRenderOptions: ({ siteKey, theme }) => ({
1110
+ sitekey: siteKey,
1111
+ // 'auto' is Turnstile vocabulary. hCaptcha and reCAPTCHA take light|dark
1112
+ // only and silently fall back to light on anything else, which reads badly
1113
+ // in a dark application.
1114
+ theme: theme === "auto" ? preferredTheme() : theme,
1115
+ size: "invisible"
1116
+ }),
1117
+ teardown
1118
+ },
1119
+ "recaptcha-v2": {
1120
+ scriptUrl: "https://www.google.com/recaptcha/api.js?render=explicit",
1121
+ globalName: "grecaptcha",
1122
+ label: "reCAPTCHA",
1123
+ invisibleRenderOptions: ({ siteKey, theme }) => ({
1124
+ sitekey: siteKey,
1125
+ // 'auto' is Turnstile vocabulary. hCaptcha and reCAPTCHA take light|dark
1126
+ // only and silently fall back to light on anything else, which reads badly
1127
+ // in a dark application.
1128
+ theme: theme === "auto" ? preferredTheme() : theme,
1129
+ size: "invisible"
1130
+ }),
1131
+ teardown
1132
+ }
1133
+ };
1134
+ }
1135
+ });
1136
+
936
1137
  // ../../node_modules/.pnpm/qrcode-generator@2.0.4/node_modules/qrcode-generator/dist/qrcode.mjs
937
1138
  var qrcode, QRMode, QRErrorCorrectionLevel, QRMaskPattern, QRUtil, QRMath, qrPolynomial, QRRSBlock, qrBitBuffer, qrNumber, qrAlphaNum, qr8BitByte, qrKanji, byteArrayOutputStream, base64EncodeOutputStream, base64DecodeInputStream, gifImage, createDataURL, qrcode_default, stringToBytes;
938
1139
  var init_qrcode = __esm({
@@ -2653,11 +2854,11 @@ var init_model = __esm({
2653
2854
  // src/components/organization/use-organization-roles.ts
2654
2855
  function useOrganizationRoles(organizationId) {
2655
2856
  const api = useAuthClient().organization;
2656
- const apiRef = React49.useRef(api);
2857
+ const apiRef = React50.useRef(api);
2657
2858
  apiRef.current = api;
2658
- const [dynamicRoles, setDynamicRoles] = React49.useState([]);
2659
- const requestRef = React49.useRef(0);
2660
- React49.useEffect(() => {
2859
+ const [dynamicRoles, setDynamicRoles] = React50.useState([]);
2860
+ const requestRef = React50.useRef(0);
2861
+ React50.useEffect(() => {
2661
2862
  const token = ++requestRef.current;
2662
2863
  setDynamicRoles([]);
2663
2864
  if (!organizationId) return;
@@ -2673,7 +2874,7 @@ function useOrganizationRoles(organizationId) {
2673
2874
  requestRef.current += 1;
2674
2875
  };
2675
2876
  }, [organizationId]);
2676
- const roles = React49.useMemo(() => {
2877
+ const roles = React50.useMemo(() => {
2677
2878
  const seen = /* @__PURE__ */ new Set();
2678
2879
  const out = [];
2679
2880
  for (const candidate of [...BUILTIN_ROLES, ...dynamicRoles.map((entry) => entry.role)]) {
@@ -2686,12 +2887,12 @@ function useOrganizationRoles(organizationId) {
2686
2887
  }, [dynamicRoles]);
2687
2888
  return { roles, dynamicRoles };
2688
2889
  }
2689
- var React49, BUILTIN_ROLES;
2890
+ var React50, BUILTIN_ROLES;
2690
2891
  var init_use_organization_roles = __esm({
2691
2892
  "src/components/organization/use-organization-roles.ts"() {
2692
2893
  "use strict";
2693
2894
  "use client";
2694
- React49 = __toESM(require("react"), 1);
2895
+ React50 = __toESM(require("react"), 1);
2695
2896
  init_hooks();
2696
2897
  BUILTIN_ROLES = ["owner", "admin", "member"];
2697
2898
  }
@@ -2706,12 +2907,12 @@ function useOrganizationListResource({
2706
2907
  inactiveData = null
2707
2908
  }) {
2708
2909
  const toServerError = useServerError();
2709
- const requestFn = React51.useRef(request);
2910
+ const requestFn = React52.useRef(request);
2710
2911
  requestFn.current = request;
2711
- const [data, setData] = React51.useState(null);
2712
- const [error, setError] = React51.useState(null);
2713
- const requestToken = React51.useRef(0);
2714
- const refresh = React51.useCallback(async () => {
2912
+ const [data, setData] = React52.useState(null);
2913
+ const [error, setError] = React52.useState(null);
2914
+ const requestToken = React52.useRef(0);
2915
+ const refresh = React52.useCallback(async () => {
2715
2916
  const token = ++requestToken.current;
2716
2917
  if (!enabled || !resourceKey) {
2717
2918
  setData(inactiveData);
@@ -2731,7 +2932,7 @@ function useOrganizationListResource({
2731
2932
  if (token === requestToken.current) setError(fallback);
2732
2933
  }
2733
2934
  }, [enabled, fallback, inactiveData, resourceKey, toServerError]);
2734
- React51.useEffect(() => {
2935
+ React52.useEffect(() => {
2735
2936
  setData(enabled && resourceKey ? null : inactiveData);
2736
2937
  setError(null);
2737
2938
  void refresh();
@@ -2741,12 +2942,12 @@ function useOrganizationListResource({
2741
2942
  }, [enabled, inactiveData, refresh, resourceKey]);
2742
2943
  return { data, isLoading: data === null && error === null, error, refresh };
2743
2944
  }
2744
- var React51;
2945
+ var React52;
2745
2946
  var init_use_organization_list_resource = __esm({
2746
2947
  "src/components/organization/use-organization-list-resource.ts"() {
2747
2948
  "use strict";
2748
2949
  "use client";
2749
- React51 = __toESM(require("react"), 1);
2950
+ React52 = __toESM(require("react"), 1);
2750
2951
  init_i18n();
2751
2952
  }
2752
2953
  });
@@ -2754,7 +2955,7 @@ var init_use_organization_list_resource = __esm({
2754
2955
  // src/components/organization/use-team-resources.ts
2755
2956
  function useTeamsResource(organizationId) {
2756
2957
  const api = useAuthClient().organization;
2757
- const apiRef = React52.useRef(api);
2958
+ const apiRef = React53.useRef(api);
2758
2959
  apiRef.current = api;
2759
2960
  const t = useT();
2760
2961
  const resource = useOrganizationListResource({
@@ -2767,7 +2968,7 @@ function useTeamsResource(organizationId) {
2767
2968
  }
2768
2969
  function useTeamMembersResource(selectedTeamId) {
2769
2970
  const api = useAuthClient().organization;
2770
- const apiRef = React52.useRef(api);
2971
+ const apiRef = React53.useRef(api);
2771
2972
  apiRef.current = api;
2772
2973
  const t = useT();
2773
2974
  const resource = useOrganizationListResource({
@@ -2778,12 +2979,12 @@ function useTeamMembersResource(selectedTeamId) {
2778
2979
  });
2779
2980
  return { members: resource.data, error: resource.error, reload: resource.refresh };
2780
2981
  }
2781
- var React52;
2982
+ var React53;
2782
2983
  var init_use_team_resources = __esm({
2783
2984
  "src/components/organization/use-team-resources.ts"() {
2784
2985
  "use strict";
2785
2986
  "use client";
2786
- React52 = __toESM(require("react"), 1);
2987
+ React53 = __toESM(require("react"), 1);
2787
2988
  init_hooks();
2788
2989
  init_i18n();
2789
2990
  init_use_organization_list_resource();
@@ -2800,7 +3001,7 @@ function TeamMembersPanel({
2800
3001
  const t = useT();
2801
3002
  const api = useAuthClient().organization;
2802
3003
  const { pending, error: actionError, run } = useSubmitAction();
2803
- const [userId, setUserId] = React53.useState("");
3004
+ const [userId, setUserId] = React54.useState("");
2804
3005
  const { members, error, reload } = useTeamMembersResource(team.id);
2805
3006
  const assignedUserIds = new Set(members?.map((member) => member.userId));
2806
3007
  const availableMembers = organization.members.filter((member) => !assignedUserIds.has(member.userId));
@@ -2866,12 +3067,12 @@ function TeamMembersPanel({
2866
3067
  }) }) : error ? null : members === null ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ba-skeleton", "aria-label": t("common.loading") }) : members.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "ba-muted", children: t("organization.profile.teams.membersEmpty") }) : null
2867
3068
  ] });
2868
3069
  }
2869
- var React53, import_jsx_runtime59;
3070
+ var React54, import_jsx_runtime59;
2870
3071
  var init_TeamMembersPanel = __esm({
2871
3072
  "src/components/organization/TeamMembersPanel.tsx"() {
2872
3073
  "use strict";
2873
3074
  "use client";
2874
- React53 = __toESM(require("react"), 1);
3075
+ React54 = __toESM(require("react"), 1);
2875
3076
  init_hooks();
2876
3077
  init_i18n();
2877
3078
  init_FormError();
@@ -2896,11 +3097,11 @@ function TeamsSection({
2896
3097
  const { teams, error: teamsError, reload } = useTeamsResource(organization.id);
2897
3098
  const { dynamicRoles } = useOrganizationRoles(organization.id);
2898
3099
  const capabilities = teamManagementCapabilities(membership, dynamicRoles);
2899
- const [name, setName] = React54.useState("");
2900
- const [selectedTeamId, setSelectedTeamId] = React54.useState(null);
2901
- const [editingTeamId, setEditingTeamId] = React54.useState(null);
2902
- const [editingName, setEditingName] = React54.useState("");
2903
- React54.useEffect(() => {
3100
+ const [name, setName] = React55.useState("");
3101
+ const [selectedTeamId, setSelectedTeamId] = React55.useState(null);
3102
+ const [editingTeamId, setEditingTeamId] = React55.useState(null);
3103
+ const [editingName, setEditingName] = React55.useState("");
3104
+ React55.useEffect(() => {
2904
3105
  setSelectedTeamId(null);
2905
3106
  setEditingTeamId(null);
2906
3107
  setEditingName("");
@@ -3002,12 +3203,12 @@ function TeamsSection({
3002
3203
  )
3003
3204
  ] });
3004
3205
  }
3005
- var React54, import_jsx_runtime60;
3206
+ var React55, import_jsx_runtime60;
3006
3207
  var init_TeamsSection = __esm({
3007
3208
  "src/components/organization/TeamsSection.tsx"() {
3008
3209
  "use strict";
3009
3210
  "use client";
3010
- React54 = __toESM(require("react"), 1);
3211
+ React55 = __toESM(require("react"), 1);
3011
3212
  init_hooks();
3012
3213
  init_i18n();
3013
3214
  init_FormError();
@@ -3028,7 +3229,7 @@ __export(index_exports, {
3028
3229
  AuthLoading: () => AuthLoading,
3029
3230
  AuthOwlBadge: () => AuthOwlBadge,
3030
3231
  AuthOwlBranding: () => AuthOwlBranding,
3031
- AuthOwlError: () => import_core7.AuthOwlError,
3232
+ AuthOwlError: () => import_core8.AuthOwlError,
3032
3233
  AuthOwlProvider: () => AuthOwlProvider,
3033
3234
  BackupCodesManager: () => BackupCodesManager,
3034
3235
  Bidi: () => Bidi,
@@ -3039,7 +3240,7 @@ __export(index_exports, {
3039
3240
  EmailOtpForm: () => EmailOtpForm,
3040
3241
  ForgotPassword: () => ForgotPassword,
3041
3242
  GoogleOneTap: () => GoogleOneTap,
3042
- InvalidKeyError: () => import_core7.InvalidKeyError,
3243
+ InvalidKeyError: () => import_core8.InvalidKeyError,
3043
3244
  InvitationPrompt: () => InvitationPrompt,
3044
3245
  KNOWN_METHODS: () => KNOWN_METHODS,
3045
3246
  MFAChallenge: () => MFAChallenge,
@@ -3053,7 +3254,7 @@ __export(index_exports, {
3053
3254
  PasskeyManager: () => PasskeyManager,
3054
3255
  PhoneOTP: () => PhoneOTP,
3055
3256
  Protect: () => Protect,
3056
- RateLimitedError: () => import_core7.RateLimitedError,
3257
+ RateLimitedError: () => import_core8.RateLimitedError,
3057
3258
  ResetPassword: () => ResetPassword,
3058
3259
  SignIn: () => SignIn,
3059
3260
  SignOutButton: () => SignOutButton,
@@ -3067,11 +3268,11 @@ __export(index_exports, {
3067
3268
  VerificationPending: () => VerificationPending,
3068
3269
  VerifyEmail: () => VerifyEmail,
3069
3270
  Waitlist: () => Waitlist,
3070
- createMembershipHas: () => import_core8.createMembershipHas,
3271
+ createMembershipHas: () => import_core9.createMembershipHas,
3071
3272
  emailAutocomplete: () => emailAutocomplete,
3072
- membershipHas: () => import_core8.membershipHas,
3073
- membershipHasPermission: () => import_core8.membershipHasPermission,
3074
- membershipHasTeam: () => import_core8.membershipHasTeam,
3273
+ membershipHas: () => import_core9.membershipHas,
3274
+ membershipHasPermission: () => import_core9.membershipHasPermission,
3275
+ membershipHasTeam: () => import_core9.membershipHasTeam,
3075
3276
  resolveSignInMethods: () => resolveSignInMethods,
3076
3277
  useAccount: () => useAccount,
3077
3278
  useAuth: () => useAuth,
@@ -3080,6 +3281,7 @@ __export(index_exports, {
3080
3281
  useConsent: () => useConsent,
3081
3282
  useEmailVerification: () => useEmailVerification,
3082
3283
  useInvitationRecipientHint: () => useInvitationRecipientHint,
3284
+ useLastUsedSignInMethod: () => useLastUsedSignInMethod,
3083
3285
  useLocale: () => useLocale,
3084
3286
  useMFA: () => useMFA,
3085
3287
  useOrganization: () => useOrganization,
@@ -3101,7 +3303,7 @@ init_brand();
3101
3303
  init_hooks();
3102
3304
 
3103
3305
  // src/project-capabilities.ts
3104
- var import_core3 = require("@authowl/core");
3306
+ var import_core4 = require("@authowl/core");
3105
3307
 
3106
3308
  // src/signin-methods.ts
3107
3309
  var KNOWN_METHODS = [
@@ -3133,7 +3335,7 @@ function resolveSignInMethods(config, pageHost) {
3133
3335
  const methods = config?.enabledMethods ?? ["password"];
3134
3336
  const social = config?.socialProviders ?? [];
3135
3337
  const has = (m) => methods.includes(m);
3136
- const capabilities = (0, import_core3.resolveProjectCapabilities)(config);
3338
+ const capabilities = (0, import_core4.resolveProjectCapabilities)(config);
3137
3339
  const password = capabilities.passwordSignIn;
3138
3340
  const username = capabilities.usernameSignIn;
3139
3341
  const magicLink = capabilities.magicLinkSignIn;
@@ -3172,7 +3374,7 @@ function resolveSignInMethods(config, pageHost) {
3172
3374
  }
3173
3375
 
3174
3376
  // src/components/SignIn.tsx
3175
- var React19 = __toESM(require("react"), 1);
3377
+ var React20 = __toESM(require("react"), 1);
3176
3378
  init_hooks();
3177
3379
  init_i18n();
3178
3380
 
@@ -3238,15 +3440,15 @@ async function finishSignIn(opts) {
3238
3440
  init_use_submit_action();
3239
3441
 
3240
3442
  // src/components/passkey-autofill.ts
3241
- var React7 = __toESM(require("react"), 1);
3443
+ var React8 = __toESM(require("react"), 1);
3242
3444
  init_hooks();
3243
3445
  function usePasskeyAutofill(opts) {
3244
3446
  const { signInPasskey } = useSignIn();
3245
3447
  const { sessionStore } = useAuthClient();
3246
3448
  const { enabled } = opts;
3247
- const ref = React7.useRef({ ...opts, signInPasskey, sessionStore });
3449
+ const ref = React8.useRef({ ...opts, signInPasskey, sessionStore });
3248
3450
  ref.current = { ...opts, signInPasskey, sessionStore };
3249
- React7.useEffect(() => {
3451
+ React8.useEffect(() => {
3250
3452
  if (!enabled || typeof window === "undefined") return;
3251
3453
  const pkc = window.PublicKeyCredential;
3252
3454
  if (!pkc?.isConditionalMediationAvailable) return;
@@ -3264,9 +3466,13 @@ function usePasskeyAutofill(opts) {
3264
3466
  }, [enabled]);
3265
3467
  }
3266
3468
 
3469
+ // src/components/SignIn.tsx
3470
+ init_last_used_method();
3471
+
3267
3472
  // src/components/SocialButtons.tsx
3268
- var React8 = __toESM(require("react"), 1);
3473
+ var React9 = __toESM(require("react"), 1);
3269
3474
  init_hooks();
3475
+ init_last_used_method();
3270
3476
  init_i18n();
3271
3477
 
3272
3478
  // src/components/social-icons.tsx
@@ -3345,9 +3551,10 @@ function SocialButtons({ providers, callbackURL }) {
3345
3551
  const t = useT();
3346
3552
  const toServerError = useServerError();
3347
3553
  const { signInSocial } = useSignIn();
3348
- const [pending, setPending] = React8.useState(null);
3349
- const [error, setError] = React8.useState(null);
3350
- React8.useEffect(() => {
3554
+ const recordSignInMethod = useSignInMethodRecorder();
3555
+ const [pending, setPending] = React9.useState(null);
3556
+ const [error, setError] = React9.useState(null);
3557
+ React9.useEffect(() => {
3351
3558
  if (typeof window === "undefined") return;
3352
3559
  const url = new URL(window.location.href);
3353
3560
  if (!url.searchParams.has("authowl_error")) return;
@@ -3377,6 +3584,8 @@ function SocialButtons({ providers, callbackURL }) {
3377
3584
  if (res?.error) {
3378
3585
  setError(toServerError(res.error, t("social.error.startFailed")));
3379
3586
  setPending(null);
3587
+ } else {
3588
+ recordSignInMethod(`social:${provider}`, true);
3380
3589
  }
3381
3590
  } catch {
3382
3591
  setError(t("social.error.startFailed"));
@@ -3440,100 +3649,16 @@ init_Spinner();
3440
3649
  var React10 = __toESM(require("react"), 1);
3441
3650
  init_hooks();
3442
3651
  init_i18n();
3652
+ init_FormError();
3443
3653
 
3444
- // src/components/Turnstile.tsx
3445
- var React9 = __toESM(require("react"), 1);
3446
- var import_jsx_runtime10 = require("react/jsx-runtime");
3447
- var SCRIPT_URL = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
3448
- var SCRIPT_LOAD_TIMEOUT_MS = 1e4;
3449
- var LOCAL_TURNSTILE_TEST_TOKEN = "XXXX.DUMMY.TOKEN.XXXX";
3450
- var loader = null;
3451
- function loadTurnstile() {
3452
- if (window.turnstile) return Promise.resolve(window.turnstile);
3453
- if (loader) return loader;
3454
- loader = new Promise((resolve, reject) => {
3455
- const existing = document.querySelector(`script[src="${SCRIPT_URL}"]`);
3456
- const script = existing ?? document.createElement("script");
3457
- const cleanup = () => {
3458
- clearTimeout(timeout);
3459
- script.removeEventListener("load", loaded);
3460
- script.removeEventListener("error", failed);
3461
- };
3462
- const loaded = () => {
3463
- cleanup();
3464
- if (window.turnstile) {
3465
- resolve(window.turnstile);
3466
- } else {
3467
- reject(new Error("Turnstile unavailable"));
3468
- }
3469
- };
3470
- const failed = () => {
3471
- cleanup();
3472
- if (!existing) script.remove();
3473
- reject(new Error("Turnstile failed to load"));
3474
- };
3475
- const timeout = setTimeout(failed, SCRIPT_LOAD_TIMEOUT_MS);
3476
- script.addEventListener("load", loaded, { once: true });
3477
- script.addEventListener("error", failed, { once: true });
3478
- if (!existing) {
3479
- script.src = SCRIPT_URL;
3480
- script.async = true;
3481
- script.defer = true;
3482
- const nonce = document.querySelector("script[nonce]")?.nonce;
3483
- if (nonce) script.nonce = nonce;
3484
- document.head.appendChild(script);
3485
- }
3486
- }).catch((error) => {
3487
- loader = null;
3488
- throw error;
3489
- });
3490
- return loader;
3491
- }
3492
- function Turnstile({
3493
- siteKey,
3494
- theme,
3495
- onToken,
3496
- onUnavailable
3497
- }) {
3498
- const container = React9.useRef(null);
3499
- const callbacks = React9.useRef({ onToken, onUnavailable });
3500
- callbacks.current = { onToken, onUnavailable };
3501
- React9.useEffect(() => {
3502
- callbacks.current.onToken(null);
3503
- if (!siteKey) {
3504
- callbacks.current.onToken(LOCAL_TURNSTILE_TEST_TOKEN);
3505
- return;
3506
- }
3507
- let active = true;
3508
- let widget = null;
3509
- void loadTurnstile().then((api) => {
3510
- if (!active || !container.current) return;
3511
- const id = api.render(container.current, {
3512
- sitekey: siteKey,
3513
- theme: theme === "system" ? "auto" : theme,
3514
- size: "flexible",
3515
- callback: (token) => callbacks.current.onToken(token),
3516
- "expired-callback": () => callbacks.current.onToken(null),
3517
- "error-callback": () => {
3518
- callbacks.current.onToken(null);
3519
- callbacks.current.onUnavailable();
3520
- }
3521
- });
3522
- widget = { api, id };
3523
- }).catch(() => {
3524
- if (active) callbacks.current.onUnavailable();
3525
- });
3526
- return () => {
3527
- active = false;
3528
- if (widget) widget.api.remove(widget.id);
3529
- };
3530
- }, [siteKey, theme]);
3531
- if (!siteKey) return null;
3532
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "ba-turnstile", ref: container, "data-testid": "phoneotp-turnstile" });
3654
+ // src/components/captcha-provider-ids.ts
3655
+ var CAPTCHA_PROVIDER_IDS = ["turnstile", "hcaptcha", "recaptcha-v2"];
3656
+ function isSupportedCaptchaProvider(provider) {
3657
+ return CAPTCHA_PROVIDER_IDS.includes(provider);
3533
3658
  }
3534
3659
 
3535
3660
  // src/components/AuthChallenge.tsx
3536
- var import_jsx_runtime11 = require("react/jsx-runtime");
3661
+ var import_jsx_runtime10 = require("react/jsx-runtime");
3537
3662
  var AUTH_CHALLENGE_ACTIONS = {
3538
3663
  signUp: "auth_signup",
3539
3664
  signIn: "auth_signin",
@@ -3548,38 +3673,53 @@ var challengeError = {
3548
3673
  code: "BOT_CHALLENGE_FAILED",
3549
3674
  message: "Human verification failed."
3550
3675
  };
3551
- function turnstileTheme(root, fallback) {
3676
+ function captchaTheme(root, fallback) {
3552
3677
  const rendered = root?.dataset.authowlTheme;
3553
3678
  if (rendered === "light" || rendered === "dark") return rendered;
3554
3679
  if (fallback === "light" || fallback === "dark") return fallback;
3555
3680
  return "auto";
3556
3681
  }
3557
3682
  function useAuthChallenge() {
3558
- const { config, isLoading } = usePublicConfig();
3683
+ const { config, isLoading, retry } = usePublicConfig();
3559
3684
  const t = useT();
3560
3685
  const container = React10.useRef(null);
3561
3686
  const active = React10.useRef(null);
3562
3687
  const [status, setStatus] = React10.useState("idle");
3563
- const siteKey = config?.authTurnstileSiteKey ?? null;
3688
+ const captcha = config?.captcha ?? null;
3689
+ const providerSupported = captcha ? isSupportedCaptchaProvider(captcha.provider) : false;
3690
+ const unavailableProvider = captcha && !providerSupported ? captcha.provider : null;
3691
+ const refetched = React10.useRef(null);
3692
+ const refetchIfConfigMayBeStale = React10.useCallback(() => {
3693
+ if (!config || refetched.current === config) return;
3694
+ refetched.current = config;
3695
+ retry();
3696
+ }, [config, retry]);
3564
3697
  const removeActive = React10.useCallback((reason) => {
3565
3698
  const current = active.current;
3566
3699
  active.current = null;
3567
3700
  if (!current) return;
3568
- current.api.remove(current.id);
3701
+ current.adapter.teardown(current.api, current.id);
3569
3702
  if (reason) current.reject(reason);
3570
3703
  }, []);
3571
3704
  React10.useEffect(
3572
- () => () => removeActive(new Error("Turnstile challenge was cancelled")),
3705
+ () => () => removeActive(new Error("Captcha challenge was cancelled")),
3573
3706
  [removeActive]
3574
3707
  );
3575
3708
  const tokenFor = React10.useCallback(
3576
3709
  async (action) => {
3577
- if (!siteKey) return null;
3710
+ if (!captcha) return null;
3711
+ if (!providerSupported) throw new Error(`Unsupported captcha provider: ${captcha.provider}`);
3578
3712
  setStatus("checking");
3579
- removeActive(new Error("Turnstile challenge was replaced"));
3713
+ removeActive(new Error("Captcha challenge was replaced"));
3580
3714
  try {
3581
- const api = await loadTurnstile();
3582
- if (!container.current) throw new Error("Turnstile container unavailable");
3715
+ const [{ loadCaptcha: loadCaptcha2 }, { captchaAdapterFor: captchaAdapterFor2 }] = await Promise.all([
3716
+ Promise.resolve().then(() => (init_captcha_loader(), captcha_loader_exports)),
3717
+ Promise.resolve().then(() => (init_captcha_providers(), captcha_providers_exports))
3718
+ ]);
3719
+ const adapter = captchaAdapterFor2(captcha.provider);
3720
+ if (!adapter) throw new Error(`Unsupported captcha provider: ${captcha.provider}`);
3721
+ const api = await loadCaptcha2(adapter);
3722
+ if (!container.current) throw new Error("Captcha container unavailable");
3583
3723
  return await new Promise((resolve, reject) => {
3584
3724
  let settled = false;
3585
3725
  const finish = (outcome) => {
@@ -3587,27 +3727,29 @@ function useAuthChallenge() {
3587
3727
  settled = true;
3588
3728
  const current = active.current;
3589
3729
  active.current = null;
3590
- if (current) current.api.remove(current.id);
3730
+ if (current) current.adapter.teardown(current.api, current.id);
3591
3731
  if ("token" in outcome) resolve(outcome.token);
3592
3732
  else reject(outcome.error);
3593
3733
  };
3594
- const fail = () => finish({ error: new Error("Turnstile challenge failed") });
3734
+ const fail = () => finish({ error: new Error("Captcha challenge failed") });
3595
3735
  const root = container.current.closest(".authowl-root");
3736
+ const optionalFailureCallbacks = captcha.provider === "turnstile" ? {
3737
+ "timeout-callback": fail,
3738
+ "unsupported-callback": fail
3739
+ } : {};
3596
3740
  const id = api.render(container.current, {
3597
- sitekey: siteKey,
3598
- theme: turnstileTheme(root, config?.branding?.theme),
3599
- action,
3600
- execution: "execute",
3601
- appearance: "interaction-only",
3602
- size: "flexible",
3603
- language: root?.dataset.authowlLocale ?? config?.locale,
3741
+ ...adapter.invisibleRenderOptions({
3742
+ siteKey: captcha.siteKey,
3743
+ theme: captchaTheme(root, config?.branding?.theme),
3744
+ action,
3745
+ language: root?.dataset.authowlLocale ?? config?.locale
3746
+ }),
3604
3747
  callback: (token) => finish({ token }),
3605
3748
  "expired-callback": fail,
3606
3749
  "error-callback": fail,
3607
- "timeout-callback": fail,
3608
- "unsupported-callback": fail
3750
+ ...optionalFailureCallbacks
3609
3751
  });
3610
- active.current = { api, id, reject };
3752
+ active.current = { adapter, api, id, reject };
3611
3753
  try {
3612
3754
  api.execute(id);
3613
3755
  } catch {
@@ -3618,7 +3760,7 @@ function useAuthChallenge() {
3618
3760
  setStatus("idle");
3619
3761
  }
3620
3762
  },
3621
- [config?.branding?.theme, config?.locale, removeActive, siteKey]
3763
+ [captcha, config?.branding?.theme, config?.locale, providerSupported, removeActive]
3622
3764
  );
3623
3765
  const run = React10.useCallback(
3624
3766
  async (action, request) => {
@@ -3630,27 +3772,30 @@ function useAuthChallenge() {
3630
3772
  }
3631
3773
  try {
3632
3774
  const token = await tokenFor(action);
3633
- return await request(token ? { authChallengeToken: token } : void 0);
3775
+ const result = await request(token ? { authChallengeToken: token } : void 0);
3776
+ if (result?.error?.code === challengeError.code) refetchIfConfigMayBeStale();
3777
+ return result;
3634
3778
  } catch {
3635
3779
  setStatus("failed");
3780
+ refetchIfConfigMayBeStale();
3636
3781
  return {
3637
3782
  data: null,
3638
3783
  error: challengeError
3639
3784
  };
3640
3785
  }
3641
3786
  },
3642
- [isLoading, tokenFor]
3787
+ [isLoading, refetchIfConfigMayBeStale, tokenFor]
3643
3788
  );
3644
- const control = siteKey ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ba-auth-challenge", "data-testid": "auth-challenge", children: [
3645
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ba-turnstile", ref: container }),
3646
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "ba-sr-only", role: "status", "aria-live": "polite", children: status === "checking" ? t("authChallenge.checking") : status === "failed" ? t("authChallenge.error.failed") : "" })
3789
+ const control = captcha ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ba-auth-challenge", "data-testid": "auth-challenge", children: [
3790
+ providerSupported ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "ba-turnstile", ref: container }) : null,
3791
+ unavailableProvider ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(FormError, { "data-testid": "auth-challenge-unsupported", children: t("authChallenge.error.unsupportedProvider", { provider: unavailableProvider }) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "ba-sr-only", role: "status", "aria-live": "polite", children: status === "checking" ? t("authChallenge.checking") : status === "failed" ? t("authChallenge.error.failed") : "" })
3647
3792
  ] }) : null;
3648
3793
  return { run, control, configPending: isLoading };
3649
3794
  }
3650
3795
 
3651
3796
  // src/components/ForgotPassword.tsx
3652
3797
  init_FormError();
3653
- var import_jsx_runtime12 = require("react/jsx-runtime");
3798
+ var import_jsx_runtime11 = require("react/jsx-runtime");
3654
3799
  function ForgotPassword({ resetPasswordUrl, onBack }) {
3655
3800
  const t = useT();
3656
3801
  const { requestPasswordReset } = usePasswordReset();
@@ -3659,12 +3804,12 @@ function ForgotPassword({ resetPasswordUrl, onBack }) {
3659
3804
  const [email, setEmail] = React11.useState("");
3660
3805
  const [sent, setSent] = React11.useState(false);
3661
3806
  if (sent) {
3662
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ba-fields", "data-testid": "forgot-sent", children: [
3663
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "ba-muted", children: richMessage(t("forgotPassword.sent"), { email: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Bidi, { children: email }) }) }),
3664
- onBack && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: "ba-link-button", onClick: onBack, children: t("forgotPassword.backToSignIn") })
3807
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ba-fields", "data-testid": "forgot-sent", children: [
3808
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "ba-muted", children: richMessage(t("forgotPassword.sent"), { email: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Bidi, { children: email }) }) }),
3809
+ onBack && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: "ba-link-button", onClick: onBack, children: t("forgotPassword.backToSignIn") })
3665
3810
  ] });
3666
3811
  }
3667
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3812
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3668
3813
  "form",
3669
3814
  {
3670
3815
  method: "post",
@@ -3678,9 +3823,9 @@ function ForgotPassword({ resetPasswordUrl, onBack }) {
3678
3823
  });
3679
3824
  },
3680
3825
  children: [
3681
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "ba-label", children: [
3826
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "ba-label", children: [
3682
3827
  t("common.emailLabel"),
3683
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3828
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3684
3829
  "input",
3685
3830
  {
3686
3831
  className: "ba-input",
@@ -3693,18 +3838,18 @@ function ForgotPassword({ resetPasswordUrl, onBack }) {
3693
3838
  )
3694
3839
  ] }),
3695
3840
  authChallenge.control,
3696
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormError, { children: error }),
3697
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3841
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(FormError, { children: error }),
3842
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3698
3843
  "button",
3699
3844
  {
3700
3845
  className: "ba-button",
3701
3846
  type: "submit",
3702
3847
  disabled: pending || authChallenge.configPending,
3703
3848
  "aria-busy": pending || void 0,
3704
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Busy, { busy: pending, label: t("common.sending"), children: t("forgotPassword.submit") })
3849
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Busy, { busy: pending, label: t("common.sending"), children: t("forgotPassword.submit") })
3705
3850
  }
3706
3851
  ),
3707
- onBack && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: "ba-link-button", onClick: onBack, children: t("forgotPassword.backToSignIn") })
3852
+ onBack && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: "ba-link-button", onClick: onBack, children: t("forgotPassword.backToSignIn") })
3708
3853
  ]
3709
3854
  }
3710
3855
  );
@@ -3714,7 +3859,7 @@ function ForgotPassword({ resetPasswordUrl, onBack }) {
3714
3859
  init_i18n();
3715
3860
  init_Spinner();
3716
3861
  init_FormError();
3717
- var import_jsx_runtime13 = require("react/jsx-runtime");
3862
+ var import_jsx_runtime12 = require("react/jsx-runtime");
3718
3863
  function OtpCodeForm({
3719
3864
  email,
3720
3865
  code,
@@ -3725,7 +3870,7 @@ function OtpCodeForm({
3725
3870
  error
3726
3871
  }) {
3727
3872
  const t = useT();
3728
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3873
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3729
3874
  "form",
3730
3875
  {
3731
3876
  method: "post",
@@ -3736,9 +3881,9 @@ function OtpCodeForm({
3736
3881
  onSubmit();
3737
3882
  },
3738
3883
  children: [
3739
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ba-label", children: [
3740
- richMessage(t("emailOtp.codeLabel"), { email: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Bidi, { children: email }) }),
3741
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3884
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "ba-label", children: [
3885
+ richMessage(t("emailOtp.codeLabel"), { email: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Bidi, { children: email }) }),
3886
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3742
3887
  "input",
3743
3888
  {
3744
3889
  className: "ba-input",
@@ -3751,9 +3896,9 @@ function OtpCodeForm({
3751
3896
  }
3752
3897
  )
3753
3898
  ] }),
3754
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FormError, { children: error }),
3755
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "ba-button", type: "submit", disabled: pending, "aria-busy": pending || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Busy, { busy: pending, label: t("common.verifying"), children: t("emailOtp.verifySubmit") }) }),
3756
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "ba-link-button", onClick: onChangeEmail, children: t("emailOtp.changeEmail") })
3899
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormError, { children: error }),
3900
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { className: "ba-button", type: "submit", disabled: pending, "aria-busy": pending || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Busy, { busy: pending, label: t("common.verifying"), children: t("emailOtp.verifySubmit") }) }),
3901
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: "ba-link-button", onClick: onChangeEmail, children: t("emailOtp.changeEmail") })
3757
3902
  ]
3758
3903
  }
3759
3904
  );
@@ -3766,7 +3911,7 @@ init_i18n();
3766
3911
  init_use_submit_action();
3767
3912
  init_Spinner();
3768
3913
  init_FormError();
3769
- var import_jsx_runtime14 = require("react/jsx-runtime");
3914
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3770
3915
  function MFAChallenge({ onVerified, allowTrustDevice = true }) {
3771
3916
  const t = useT();
3772
3917
  const { verifyTotp, verifyBackupCode, sendOtp, verifyOtp } = useMFA();
@@ -3796,12 +3941,12 @@ function MFAChallenge({ onVerified, allowTrustDevice = true }) {
3796
3941
  };
3797
3942
  const hint = mode === "totp" ? t("mfa.challenge.totpHint") : mode === "backup" ? t("mfa.challenge.backupHint") : t("mfa.challenge.otpHint");
3798
3943
  const label2 = mode === "totp" ? t("mfa.challenge.totpLabel") : mode === "backup" ? t("mfa.challenge.backupLabel") : t("mfa.challenge.otpLabel");
3799
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("form", { method: "post", className: "ba-fields", "data-testid": "mfa-challenge", onSubmit: submit, children: [
3800
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { className: "ba-title", children: t("mfa.challenge.title") }),
3801
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "ba-muted", children: hint }),
3802
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "ba-label", children: [
3944
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("form", { method: "post", className: "ba-fields", "data-testid": "mfa-challenge", onSubmit: submit, children: [
3945
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: "ba-title", children: t("mfa.challenge.title") }),
3946
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "ba-muted", children: hint }),
3947
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ba-label", children: [
3803
3948
  label2,
3804
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3949
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3805
3950
  "input",
3806
3951
  {
3807
3952
  className: "ba-input",
@@ -3817,18 +3962,18 @@ function MFAChallenge({ onVerified, allowTrustDevice = true }) {
3817
3962
  }
3818
3963
  )
3819
3964
  ] }),
3820
- mode !== "backup" && allowTrustDevice && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "ba-consent ba-consent-centered", children: [
3821
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ba-checkbox-control", children: [
3822
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("input", { className: "ba-checkbox", type: "checkbox", checked: trustDevice, onChange: (e) => setTrustDevice(e.target.checked) }),
3823
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ba-checkbox-visual", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ba-checkbox-check" }) })
3965
+ mode !== "backup" && allowTrustDevice && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ba-consent ba-consent-centered", children: [
3966
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "ba-checkbox-control", children: [
3967
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { className: "ba-checkbox", type: "checkbox", checked: trustDevice, onChange: (e) => setTrustDevice(e.target.checked) }),
3968
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ba-checkbox-visual", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ba-checkbox-check" }) })
3824
3969
  ] }),
3825
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: t("mfa.challenge.trustDevice", { days: 30 }) })
3970
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: t("mfa.challenge.trustDevice", { days: 30 }) })
3826
3971
  ] }),
3827
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormError, { children: error }),
3828
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { className: "ba-button", type: "submit", disabled: pending || !code, "aria-busy": pending || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Busy, { busy: pending, label: t("common.verifying"), children: t("mfa.challenge.submit") }) }),
3829
- mode !== "totp" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "ba-link-button", onClick: () => switchMode("totp"), children: t("mfa.challenge.useTotp") }),
3830
- mode !== "backup" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "ba-link-button", onClick: () => switchMode("backup"), children: t("mfa.challenge.useBackup") }),
3831
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "ba-link-button", disabled: pending, onClick: requestOtp, children: t(mode === "otp" ? "mfa.challenge.resendOtp" : "mfa.challenge.useEmailOtp") })
3972
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FormError, { children: error }),
3973
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "ba-button", type: "submit", disabled: pending || !code, "aria-busy": pending || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Busy, { busy: pending, label: t("common.verifying"), children: t("mfa.challenge.submit") }) }),
3974
+ mode !== "totp" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "ba-link-button", onClick: () => switchMode("totp"), children: t("mfa.challenge.useTotp") }),
3975
+ mode !== "backup" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "ba-link-button", onClick: () => switchMode("backup"), children: t("mfa.challenge.useBackup") }),
3976
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "ba-link-button", disabled: pending, onClick: requestOtp, children: t(mode === "otp" ? "mfa.challenge.resendOtp" : "mfa.challenge.useEmailOtp") })
3832
3977
  ] });
3833
3978
  }
3834
3979
 
@@ -3853,7 +3998,7 @@ function shouldDiscardSetup(args) {
3853
3998
  // src/components/QrCode.tsx
3854
3999
  var React13 = __toESM(require("react"), 1);
3855
4000
  init_i18n();
3856
- var import_jsx_runtime15 = require("react/jsx-runtime");
4001
+ var import_jsx_runtime14 = require("react/jsx-runtime");
3857
4002
  function QrCode({ value, size = 200 }) {
3858
4003
  const t = useT();
3859
4004
  const [path, setPath] = React13.useState(null);
@@ -3875,7 +4020,7 @@ function QrCode({ value, size = 200 }) {
3875
4020
  if (!path) return null;
3876
4021
  const margin = 4;
3877
4022
  const dim = path.count + margin * 2;
3878
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4023
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3879
4024
  "svg",
3880
4025
  {
3881
4026
  width: size,
@@ -3886,8 +4031,8 @@ function QrCode({ value, size = 200 }) {
3886
4031
  shapeRendering: "crispEdges",
3887
4032
  className: "ba-qr",
3888
4033
  children: [
3889
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("rect", { width: dim, height: dim, fill: "#ffffff" }),
3890
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("g", { transform: `translate(${margin} ${margin})`, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: path.d, fill: "#000000" }) })
4034
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("rect", { width: dim, height: dim, fill: "#ffffff" }),
4035
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("g", { transform: `translate(${margin} ${margin})`, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: path.d, fill: "#000000" }) })
3891
4036
  ]
3892
4037
  }
3893
4038
  );
@@ -3895,7 +4040,7 @@ function QrCode({ value, size = 200 }) {
3895
4040
 
3896
4041
  // src/components/MFAEnrollment.tsx
3897
4042
  init_FormError();
3898
- var import_jsx_runtime16 = require("react/jsx-runtime");
4043
+ var import_jsx_runtime15 = require("react/jsx-runtime");
3899
4044
  function secretFromUri(uri) {
3900
4045
  try {
3901
4046
  return new URL(uri).searchParams.get("secret");
@@ -3929,22 +4074,22 @@ function MFAEnrollment({ onEnrolled, title }) {
3929
4074
  }
3930
4075
  }, [stale]);
3931
4076
  if (done) {
3932
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ba-fields", "data-testid": "mfa-enroll-done", children: [
3933
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: "ba-title", children: t("mfa.enroll.doneTitle") }),
3934
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "ba-muted", children: t("mfa.enroll.doneBody") })
4077
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "ba-fields", "data-testid": "mfa-enroll-done", children: [
4078
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { className: "ba-title", children: t("mfa.enroll.doneTitle") }),
4079
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "ba-muted", children: t("mfa.enroll.doneBody") })
3935
4080
  ] });
3936
4081
  }
3937
4082
  if (!activeSetup) {
3938
4083
  if (!isLoaded) {
3939
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ba-fields", "data-testid": "mfa-enroll-loading", "aria-busy": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ba-skeleton" }) });
4084
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "ba-fields", "data-testid": "mfa-enroll-loading", "aria-busy": "true", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "ba-skeleton" }) });
3940
4085
  }
3941
4086
  if (user?.twoFactorEnabled) {
3942
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ba-fields", "data-testid": "mfa-enroll-active", children: [
3943
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: "ba-title", children: t("mfa.enroll.activeTitle") }),
3944
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "ba-muted", children: t("mfa.enroll.activeBody") })
4087
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "ba-fields", "data-testid": "mfa-enroll-active", children: [
4088
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { className: "ba-title", children: t("mfa.enroll.activeTitle") }),
4089
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "ba-muted", children: t("mfa.enroll.activeBody") })
3945
4090
  ] });
3946
4091
  }
3947
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4092
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3948
4093
  "form",
3949
4094
  {
3950
4095
  method: "post",
@@ -3961,11 +4106,11 @@ function MFAEnrollment({ onEnrolled, title }) {
3961
4106
  });
3962
4107
  },
3963
4108
  children: [
3964
- title !== null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: "ba-title", children: title ?? t("mfa.enroll.title") }),
3965
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "ba-muted", children: t("mfa.enroll.passwordHint") }),
3966
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "ba-label", children: [
4109
+ title !== null && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { className: "ba-title", children: title ?? t("mfa.enroll.title") }),
4110
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "ba-muted", children: t("mfa.enroll.passwordHint") }),
4111
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "ba-label", children: [
3967
4112
  t("common.passwordLabel"),
3968
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4113
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3969
4114
  "input",
3970
4115
  {
3971
4116
  className: "ba-input",
@@ -3977,29 +4122,29 @@ function MFAEnrollment({ onEnrolled, title }) {
3977
4122
  }
3978
4123
  )
3979
4124
  ] }),
3980
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FormError, { children: error }),
3981
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { className: "ba-button", type: "submit", disabled: pending || !password, "aria-busy": pending || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Busy, { busy: pending, label: t("mfa.enroll.startPending"), children: t("common.continue") }) })
4125
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormError, { children: error }),
4126
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { className: "ba-button", type: "submit", disabled: pending || !password, "aria-busy": pending || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Busy, { busy: pending, label: t("mfa.enroll.startPending"), children: t("common.continue") }) })
3982
4127
  ]
3983
4128
  }
3984
4129
  );
3985
4130
  }
3986
4131
  const secret = secretFromUri(activeSetup.totpURI);
3987
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ba-fields", "data-testid": "mfa-enroll-verify", children: [
3988
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: "ba-title", children: t("mfa.enroll.scanQrTitle") }),
3989
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "ba-muted", children: t("mfa.enroll.scanQrHint") }),
3990
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(QrCode, { value: activeSetup.totpURI }),
3991
- secret && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "ba-muted", children: richMessage(t("mfa.enroll.manualKey"), {
3992
- secret: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("code", { className: "ba-code", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Bidi, { children: secret }) })
4132
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "ba-fields", "data-testid": "mfa-enroll-verify", children: [
4133
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { className: "ba-title", children: t("mfa.enroll.scanQrTitle") }),
4134
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "ba-muted", children: t("mfa.enroll.scanQrHint") }),
4135
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(QrCode, { value: activeSetup.totpURI }),
4136
+ secret && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "ba-muted", children: richMessage(t("mfa.enroll.manualKey"), {
4137
+ secret: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("code", { className: "ba-code", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Bidi, { children: secret }) })
3993
4138
  }) }),
3994
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
3995
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("p", { className: "ba-muted", children: [
3996
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: t("mfa.enroll.backupCodesWarningStrong") }),
4139
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
4140
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { className: "ba-muted", children: [
4141
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: t("mfa.enroll.backupCodesWarningStrong") }),
3997
4142
  " ",
3998
4143
  t("mfa.enroll.backupCodesWarningRest")
3999
4144
  ] }),
4000
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("ul", { className: "ba-backup-codes", "data-testid": "mfa-backup-codes", children: activeSetup.backupCodes.map((c) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("code", { className: "ba-code", children: c }) }, c)) })
4145
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { className: "ba-backup-codes", "data-testid": "mfa-backup-codes", children: activeSetup.backupCodes.map((c) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("code", { className: "ba-code", children: c }) }, c)) })
4001
4146
  ] }),
4002
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4147
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4003
4148
  "form",
4004
4149
  {
4005
4150
  method: "post",
@@ -4017,9 +4162,9 @@ function MFAEnrollment({ onEnrolled, title }) {
4017
4162
  });
4018
4163
  },
4019
4164
  children: [
4020
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "ba-label", children: [
4165
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "ba-label", children: [
4021
4166
  t("mfa.enroll.codeLabel"),
4022
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4167
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4023
4168
  "input",
4024
4169
  {
4025
4170
  className: "ba-input",
@@ -4031,8 +4176,8 @@ function MFAEnrollment({ onEnrolled, title }) {
4031
4176
  }
4032
4177
  )
4033
4178
  ] }),
4034
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FormError, { children: error }),
4035
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { className: "ba-button", type: "submit", disabled: pending || !code, "aria-busy": pending || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Busy, { busy: pending, label: t("common.verifying"), children: t("mfa.enroll.activateSubmit") }) })
4179
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormError, { children: error }),
4180
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { className: "ba-button", type: "submit", disabled: pending || !code, "aria-busy": pending || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Busy, { busy: pending, label: t("common.verifying"), children: t("mfa.enroll.activateSubmit") }) })
4036
4181
  ]
4037
4182
  }
4038
4183
  )
@@ -4040,7 +4185,7 @@ function MFAEnrollment({ onEnrolled, title }) {
4040
4185
  }
4041
4186
 
4042
4187
  // src/components/mfa-enrollment-step.tsx
4043
- var import_jsx_runtime17 = require("react/jsx-runtime");
4188
+ var import_jsx_runtime16 = require("react/jsx-runtime");
4044
4189
  function useConfirmedMfaPending(onUnknown = "pending") {
4045
4190
  const client = useAuthClient();
4046
4191
  const { needsMfaEnrollment } = useUser();
@@ -4070,32 +4215,32 @@ function useConfirmedMfaPending(onUnknown = "pending") {
4070
4215
  function MfaEnrollmentStep({ title }) {
4071
4216
  const t = useT();
4072
4217
  const { refetch } = useSession();
4073
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4074
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h2", { className: "ba-title", children: title ?? t("mfaGate.title") }),
4075
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "ba-muted", children: t("mfaGate.body") }),
4076
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MFAEnrollment, { onEnrolled: () => refetch({ query: { disableCookieCache: true } }) })
4218
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
4219
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: "ba-title", children: title ?? t("mfaGate.title") }),
4220
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "ba-muted", children: t("mfaGate.body") }),
4221
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MFAEnrollment, { onEnrolled: () => refetch({ query: { disableCookieCache: true } }) })
4077
4222
  ] });
4078
4223
  }
4079
4224
 
4080
4225
  // src/components/AuthOwlBadge.tsx
4081
4226
  init_hooks();
4082
4227
  init_i18n();
4083
- var import_jsx_runtime18 = require("react/jsx-runtime");
4228
+ var import_jsx_runtime17 = require("react/jsx-runtime");
4084
4229
  function OwlMark() {
4085
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("svg", { className: "ba-badge-mark", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: [
4086
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#F5B84C" }),
4087
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("circle", { cx: "8.4", cy: "10", r: "3", fill: "#fff" }),
4088
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("circle", { cx: "15.6", cy: "10", r: "3", fill: "#fff" }),
4089
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("circle", { cx: "8.4", cy: "10", r: "1.4", fill: "#1f1300" }),
4090
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("circle", { cx: "15.6", cy: "10", r: "1.4", fill: "#1f1300" }),
4091
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("path", { d: "M12 13.1l1.5 2.1h-3z", fill: "#1f1300" })
4230
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { className: "ba-badge-mark", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: [
4231
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#F5B84C" }),
4232
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "8.4", cy: "10", r: "3", fill: "#fff" }),
4233
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "15.6", cy: "10", r: "3", fill: "#fff" }),
4234
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "8.4", cy: "10", r: "1.4", fill: "#1f1300" }),
4235
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "15.6", cy: "10", r: "1.4", fill: "#1f1300" }),
4236
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M12 13.1l1.5 2.1h-3z", fill: "#1f1300" })
4092
4237
  ] });
4093
4238
  }
4094
4239
  function AuthOwlBadge({ href = "https://authowl.dev", force } = {}) {
4095
4240
  const t = useT();
4096
4241
  const { config } = usePublicConfig();
4097
4242
  if (!force && !config?.badge) return null;
4098
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4243
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
4099
4244
  "a",
4100
4245
  {
4101
4246
  className: "ba-badge",
@@ -4104,9 +4249,9 @@ function AuthOwlBadge({ href = "https://authowl.dev", force } = {}) {
4104
4249
  rel: "noopener noreferrer",
4105
4250
  "data-testid": "authowl-badge",
4106
4251
  children: [
4107
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(OwlMark, {}),
4108
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: richMessage(t("badge.securedBy"), {
4109
- brand: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ba-badge-brand", children: "AuthOwl" })
4252
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(OwlMark, {}),
4253
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: richMessage(t("badge.securedBy"), {
4254
+ brand: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ba-badge-brand", children: "AuthOwl" })
4110
4255
  }) })
4111
4256
  ]
4112
4257
  }
@@ -4117,8 +4262,8 @@ function AuthOwlBadge({ href = "https://authowl.dev", force } = {}) {
4117
4262
  init_Spinner();
4118
4263
 
4119
4264
  // src/components/PhoneOTP.tsx
4120
- var React16 = __toESM(require("react"), 1);
4121
- var import_core4 = require("@authowl/core");
4265
+ var React17 = __toESM(require("react"), 1);
4266
+ var import_core5 = require("@authowl/core");
4122
4267
  init_hooks();
4123
4268
  init_i18n();
4124
4269
 
@@ -4127,19 +4272,19 @@ init_i18n();
4127
4272
 
4128
4273
  // src/components/ConsentDocLinks.tsx
4129
4274
  init_i18n();
4130
- var import_jsx_runtime19 = require("react/jsx-runtime");
4275
+ var import_jsx_runtime18 = require("react/jsx-runtime");
4131
4276
  function ConsentDocLinks({ termsUrl, privacyUrl }) {
4132
4277
  const t = useT();
4133
4278
  if (!termsUrl && !privacyUrl) return null;
4134
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
4135
- termsUrl && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("a", { href: termsUrl, target: "_blank", rel: "noopener noreferrer", children: t("consent.termsOfService") }),
4279
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4280
+ termsUrl && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("a", { href: termsUrl, target: "_blank", rel: "noopener noreferrer", children: t("consent.termsOfService") }),
4136
4281
  termsUrl && privacyUrl && t("consent.docJoiner"),
4137
- privacyUrl && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("a", { href: privacyUrl, target: "_blank", rel: "noopener noreferrer", children: t("consent.privacyPolicy") })
4282
+ privacyUrl && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("a", { href: privacyUrl, target: "_blank", rel: "noopener noreferrer", children: t("consent.privacyPolicy") })
4138
4283
  ] });
4139
4284
  }
4140
4285
 
4141
4286
  // src/components/LegalConsentCheckbox.tsx
4142
- var import_jsx_runtime20 = require("react/jsx-runtime");
4287
+ var import_jsx_runtime19 = require("react/jsx-runtime");
4143
4288
  function LegalConsentCheckbox({
4144
4289
  legal,
4145
4290
  accepted,
@@ -4148,9 +4293,9 @@ function LegalConsentCheckbox({
4148
4293
  }) {
4149
4294
  const t = useT();
4150
4295
  if (!legal.required) return null;
4151
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("label", { className: "ba-consent", "data-testid": testId, children: [
4152
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "ba-checkbox-control", children: [
4153
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4296
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "ba-consent", "data-testid": testId, children: [
4297
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ba-checkbox-control", children: [
4298
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4154
4299
  "input",
4155
4300
  {
4156
4301
  className: "ba-checkbox",
@@ -4159,14 +4304,69 @@ function LegalConsentCheckbox({
4159
4304
  onChange: (event) => onAcceptedChange(event.target.checked)
4160
4305
  }
4161
4306
  ),
4162
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ba-checkbox-visual", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ba-checkbox-check" }) })
4307
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ba-checkbox-visual", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ba-checkbox-check" }) })
4163
4308
  ] }),
4164
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: richMessage(t("signUp.consentLabel"), {
4165
- links: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ConsentDocLinks, { termsUrl: legal.termsUrl, privacyUrl: legal.privacyUrl })
4309
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: richMessage(t("signUp.consentLabel"), {
4310
+ links: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ConsentDocLinks, { termsUrl: legal.termsUrl, privacyUrl: legal.privacyUrl })
4166
4311
  }) })
4167
4312
  ] });
4168
4313
  }
4169
4314
 
4315
+ // src/components/Turnstile.tsx
4316
+ var React16 = __toESM(require("react"), 1);
4317
+ var import_jsx_runtime20 = require("react/jsx-runtime");
4318
+ var LOCAL_TURNSTILE_TEST_TOKEN = "XXXX.DUMMY.TOKEN.XXXX";
4319
+ async function loadTurnstile() {
4320
+ const [{ loadCaptcha: loadCaptcha2 }, { CAPTCHA_ADAPTERS: CAPTCHA_ADAPTERS2 }] = await Promise.all([
4321
+ Promise.resolve().then(() => (init_captcha_loader(), captcha_loader_exports)),
4322
+ Promise.resolve().then(() => (init_captcha_providers(), captcha_providers_exports))
4323
+ ]);
4324
+ const adapter = CAPTCHA_ADAPTERS2.turnstile;
4325
+ return { api: await loadCaptcha2(adapter), adapter };
4326
+ }
4327
+ function Turnstile({
4328
+ siteKey,
4329
+ theme,
4330
+ onToken,
4331
+ onUnavailable
4332
+ }) {
4333
+ const container = React16.useRef(null);
4334
+ const callbacks = React16.useRef({ onToken, onUnavailable });
4335
+ callbacks.current = { onToken, onUnavailable };
4336
+ React16.useEffect(() => {
4337
+ callbacks.current.onToken(null);
4338
+ if (!siteKey) {
4339
+ callbacks.current.onToken(LOCAL_TURNSTILE_TEST_TOKEN);
4340
+ return;
4341
+ }
4342
+ let active = true;
4343
+ let widget = null;
4344
+ void loadTurnstile().then(({ api, adapter }) => {
4345
+ if (!active || !container.current) return;
4346
+ const id = api.render(container.current, {
4347
+ sitekey: siteKey,
4348
+ theme: theme === "system" ? "auto" : theme,
4349
+ size: "flexible",
4350
+ callback: (token) => callbacks.current.onToken(token),
4351
+ "expired-callback": () => callbacks.current.onToken(null),
4352
+ "error-callback": () => {
4353
+ callbacks.current.onToken(null);
4354
+ callbacks.current.onUnavailable();
4355
+ }
4356
+ });
4357
+ widget = { api, adapter, id };
4358
+ }).catch(() => {
4359
+ if (active) callbacks.current.onUnavailable();
4360
+ });
4361
+ return () => {
4362
+ active = false;
4363
+ if (widget) widget.adapter.teardown(widget.api, widget.id);
4364
+ };
4365
+ }, [siteKey, theme]);
4366
+ if (!siteKey) return null;
4367
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "ba-turnstile", ref: container, "data-testid": "phoneotp-turnstile" });
4368
+ }
4369
+
4170
4370
  // src/components/PhoneOTP.tsx
4171
4371
  init_use_submit_action();
4172
4372
  init_Spinner();
@@ -4183,20 +4383,20 @@ function PhoneOTP({
4183
4383
  const { config, isLoading } = usePublicConfig();
4184
4384
  const { preparePhoneOtp, startPhoneOtp, verifyPhoneOtp } = useSignIn();
4185
4385
  const { pending, error, setError, run } = useSubmitAction();
4186
- const [stage, setStage] = React16.useState("phone");
4187
- const [phoneNumber, setPhoneNumber] = React16.useState("");
4188
- const [code, setCode] = React16.useState("");
4189
- const [turnstileToken, setTurnstileToken] = React16.useState(null);
4190
- const [guardState, setGuardState] = React16.useState({ status: "loading" });
4191
- const [accepted, setAccepted] = React16.useState(false);
4192
- const attempt = React16.useRef(null);
4193
- const guardRequest = React16.useRef(0);
4386
+ const [stage, setStage] = React17.useState("phone");
4387
+ const [phoneNumber, setPhoneNumber] = React17.useState("");
4388
+ const [code, setCode] = React17.useState("");
4389
+ const [turnstileToken, setTurnstileToken] = React17.useState(null);
4390
+ const [guardState, setGuardState] = React17.useState({ status: "loading" });
4391
+ const [accepted, setAccepted] = React17.useState(false);
4392
+ const attempt = React17.useRef(null);
4393
+ const guardRequest = React17.useRef(0);
4194
4394
  const legal = config?.legal;
4195
4395
  const consentBlocked = Boolean(legal?.required && !accepted);
4196
4396
  const guard = guardState.status === "ready" ? guardState.data : null;
4197
4397
  const turnstileBlocked = guardState.status === "ready" && guardState.data.kind === "authowl_turnstile" && !turnstileToken;
4198
4398
  const humanCheckError = t("phoneOtp.error.humanCheck");
4199
- const loadGuard = React16.useCallback(async () => {
4399
+ const loadGuard = React17.useCallback(async () => {
4200
4400
  const request = ++guardRequest.current;
4201
4401
  setGuardState({ status: "loading" });
4202
4402
  setError(null);
@@ -4215,7 +4415,7 @@ function PhoneOTP({
4215
4415
  setError(humanCheckError);
4216
4416
  }
4217
4417
  }, [humanCheckError, preparePhoneOtp, setError]);
4218
- React16.useEffect(() => {
4418
+ React17.useEffect(() => {
4219
4419
  void loadGuard();
4220
4420
  return () => {
4221
4421
  guardRequest.current += 1;
@@ -4324,7 +4524,7 @@ function PhoneOTP({
4324
4524
  return;
4325
4525
  }
4326
4526
  if (!attempt.current || attempt.current.phoneNumber !== phoneNumber) {
4327
- attempt.current = { phoneNumber, idempotencyKey: (0, import_core4.createIdempotencyKey)() };
4527
+ attempt.current = { phoneNumber, idempotencyKey: (0, import_core5.createIdempotencyKey)() };
4328
4528
  }
4329
4529
  const idempotencyKey = attempt.current.idempotencyKey;
4330
4530
  void run(
@@ -4337,7 +4537,7 @@ function PhoneOTP({
4337
4537
  const current = selected?.data ?? guard;
4338
4538
  if (selected?.data) setGuardState({ status: "ready", data: selected.data });
4339
4539
  if (current?.kind === "akedly_shield_v1_2") {
4340
- const akedlyShield = await (0, import_core4.solvePhoneOtpChallenge)(current);
4540
+ const akedlyShield = await (0, import_core5.solvePhoneOtpChallenge)(current);
4341
4541
  return startPhoneOtp({ phoneNumber, akedlyShield, idempotencyKey });
4342
4542
  }
4343
4543
  if (current?.kind === "authowl_turnstile" && turnstileToken) {
@@ -4422,7 +4622,7 @@ function PhoneOTP({
4422
4622
  init_FormError();
4423
4623
 
4424
4624
  // src/components/AuthOwlBranding.tsx
4425
- var React17 = __toESM(require("react"), 1);
4625
+ var React18 = __toESM(require("react"), 1);
4426
4626
  init_hooks();
4427
4627
  init_i18n();
4428
4628
  var import_jsx_runtime22 = require("react/jsx-runtime");
@@ -4433,8 +4633,8 @@ function AuthOwlBranding({ href, showEnvironment = true } = {}) {
4433
4633
  const appName = config?.branding?.appName?.trim() ?? "";
4434
4634
  const showAppName = config?.branding?.showAppName !== false && appName.length > 0;
4435
4635
  const alignment = config?.branding?.alignment ?? "left";
4436
- const [logoFailed, setLogoFailed] = React17.useState(false);
4437
- React17.useEffect(() => setLogoFailed(false), [logoUrl]);
4636
+ const [logoFailed, setLogoFailed] = React18.useState(false);
4637
+ React18.useEffect(() => setLogoFailed(false), [logoUrl]);
4438
4638
  if (!config) return null;
4439
4639
  if (!logoUrl && !showAppName && (!showEnvironment || !config.environmentType)) return null;
4440
4640
  const identity = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ba-branding-identity", children: [
@@ -4474,15 +4674,15 @@ function AuthOwlBranding({ href, showEnvironment = true } = {}) {
4474
4674
  }
4475
4675
 
4476
4676
  // src/components/InvitationBanner.tsx
4477
- var React18 = __toESM(require("react"), 1);
4478
- var import_core5 = require("@authowl/core");
4677
+ var React19 = __toESM(require("react"), 1);
4678
+ var import_core6 = require("@authowl/core");
4479
4679
  init_i18n();
4480
4680
  var import_jsx_runtime23 = require("react/jsx-runtime");
4481
4681
  function InvitationBanner() {
4482
4682
  const t = useT();
4483
- const [pending, setPending] = React18.useState(false);
4484
- React18.useEffect(() => {
4485
- setPending((0, import_core5.readInvitationClaim)() !== null);
4683
+ const [pending, setPending] = React19.useState(false);
4684
+ React19.useEffect(() => {
4685
+ setPending((0, import_core6.readInvitationClaim)() !== null);
4486
4686
  }, []);
4487
4687
  if (!pending) return null;
4488
4688
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "ba-muted", "data-testid": "authowl-invitation-banner", children: t("organization.invitationBanner") });
@@ -4529,18 +4729,27 @@ function SignIn({
4529
4729
  const { config, isLoading, isError } = usePublicConfig();
4530
4730
  const { pending, error, setError, run } = useSubmitAction();
4531
4731
  const authChallenge = useAuthChallenge();
4532
- const [email, setEmail] = React19.useState("");
4533
- const [username, setUsername] = React19.useState("");
4534
- const [password, setPassword] = React19.useState("");
4535
- const [credentialMode, setCredentialMode] = React19.useState("email");
4536
- const [otp, setOtp] = React19.useState("");
4537
- const [view, setView] = React19.useState(
4732
+ const [email, setEmail] = React20.useState("");
4733
+ const [username, setUsername] = React20.useState("");
4734
+ const [password, setPassword] = React20.useState("");
4735
+ const [credentialMode, setCredentialMode] = React20.useState("email");
4736
+ const [otp, setOtp] = React20.useState("");
4737
+ const [view, setView] = React20.useState(
4538
4738
  "sign-in"
4539
4739
  );
4540
- const [inFlight, setInFlight] = React19.useState(null);
4541
- const [challenge, setChallenge] = React19.useState(false);
4740
+ const [inFlight, setInFlight] = React20.useState(null);
4741
+ const [challenge, setChallenge] = React20.useState(false);
4542
4742
  const mfaEnrolment = useConfirmedMfaPending("clear");
4543
- const emailRef = React19.useRef(null);
4743
+ const emailRef = React20.useRef(null);
4744
+ const recordSignInMethod = useSignInMethodRecorder();
4745
+ const onPasskeySignedIn = React20.useCallback(() => {
4746
+ recordSignInMethod("passkey");
4747
+ onSignedIn?.();
4748
+ }, [onSignedIn, recordSignInMethod]);
4749
+ const onPhoneOtpSignedIn = React20.useCallback(() => {
4750
+ recordSignInMethod("phone-otp");
4751
+ onSignedIn?.();
4752
+ }, [onSignedIn, recordSignInMethod]);
4544
4753
  const plan = resolveSignInMethods(
4545
4754
  config,
4546
4755
  typeof window === "undefined" ? void 0 : window.location.hostname
@@ -4548,7 +4757,7 @@ function SignIn({
4548
4757
  usePasskeyAutofill({
4549
4758
  enabled: credentialMode === "email" && plan.autofillHost !== null,
4550
4759
  redirectTo,
4551
- onSignedIn
4760
+ onSignedIn: onPasskeySignedIn
4552
4761
  });
4553
4762
  const badge = /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AuthOwlBadge, { force: showBadge });
4554
4763
  const branding = showBranding ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AuthOwlBranding, {}) : null;
@@ -4600,7 +4809,10 @@ function SignIn({
4600
4809
  error,
4601
4810
  onSubmit: () => void run(() => signInEmailOtp({ email, otp }), {
4602
4811
  failure: t("emailOtp.error.invalidCode"),
4603
- onSuccess: () => finishSignIn({ sessionStore, redirectTo, onSignedIn })
4812
+ onSuccess: () => {
4813
+ recordSignInMethod("email-otp");
4814
+ finishSignIn({ sessionStore, redirectTo, onSignedIn });
4815
+ }
4604
4816
  }),
4605
4817
  onChangeEmail: () => {
4606
4818
  setOtp("");
@@ -4628,7 +4840,7 @@ function SignIn({
4628
4840
  PhoneOTP,
4629
4841
  {
4630
4842
  redirectTo,
4631
- onSignedIn,
4843
+ onSignedIn: onPhoneOtpSignedIn,
4632
4844
  onBack: () => setView("sign-in"),
4633
4845
  onMfaPasswordRequired: () => {
4634
4846
  setView("sign-in");
@@ -4656,6 +4868,7 @@ function SignIn({
4656
4868
  failure: t("signIn.error.failed"),
4657
4869
  onSuccess: (res) => {
4658
4870
  const data = res.data;
4871
+ recordSignInMethod(credentialMode === "username" ? "username" : "password");
4659
4872
  if (data && "twoFactorRedirect" in data && data.twoFactorRedirect) {
4660
4873
  setChallenge(true);
4661
4874
  } else {
@@ -4668,7 +4881,10 @@ function SignIn({
4668
4881
  "magic",
4669
4882
  () => void run(() => authChallenge.run(AUTH_CHALLENGE_ACTIONS.passwordless, (options) => signInMagicLink({ email, callbackURL: redirectTo }, options)), {
4670
4883
  failure: t("magicLink.error.sendFailed"),
4671
- onSuccess: () => setView("magic-sent")
4884
+ onSuccess: () => {
4885
+ recordSignInMethod("magic-link", true);
4886
+ setView("magic-sent");
4887
+ }
4672
4888
  })
4673
4889
  );
4674
4890
  const doRequestOtp = () => start(
@@ -4685,6 +4901,7 @@ function SignIn({
4685
4901
  {
4686
4902
  failure: t("sso.error.startFailed"),
4687
4903
  mapError: (error2) => error2.status === 404 ? t("sso.error.notFound") : null,
4904
+ onSuccess: () => recordSignInMethod("sso", true),
4688
4905
  // SSO always redirects the browser to the IdP; keep the spinner up
4689
4906
  // through that navigation instead of flashing back to idle.
4690
4907
  keepPendingOnSuccess: true
@@ -4823,7 +5040,7 @@ function SignIn({
4823
5040
  ]
4824
5041
  }
4825
5042
  ),
4826
- plan.passkey && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PasskeyButton, { redirectTo, onSignedIn }),
5043
+ plan.passkey && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PasskeyButton, { redirectTo, onSignedIn: onPasskeySignedIn }),
4827
5044
  plan.phoneOtp && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4828
5045
  "button",
4829
5046
  {
@@ -4839,12 +5056,12 @@ function SignIn({
4839
5056
  }
4840
5057
 
4841
5058
  // src/components/SignUp.tsx
4842
- var React23 = __toESM(require("react"), 1);
5059
+ var React24 = __toESM(require("react"), 1);
4843
5060
  init_hooks();
4844
5061
  init_i18n();
4845
5062
 
4846
5063
  // src/components/VerificationPending.tsx
4847
- var React20 = __toESM(require("react"), 1);
5064
+ var React21 = __toESM(require("react"), 1);
4848
5065
  init_hooks();
4849
5066
  init_i18n();
4850
5067
  init_use_submit_action();
@@ -4864,9 +5081,9 @@ function VerificationPending({
4864
5081
  } = useEmailVerification();
4865
5082
  const { pending, error, run } = useSubmitAction();
4866
5083
  const authChallenge = useAuthChallenge();
4867
- const [resent, setResent] = React20.useState(false);
4868
- const [code, setCode] = React20.useState("");
4869
- const [verified, setVerified] = React20.useState(false);
5084
+ const [resent, setResent] = React21.useState(false);
5085
+ const [code, setCode] = React21.useState("");
5086
+ const [verified, setVerified] = React21.useState(false);
4870
5087
  if (verified) {
4871
5088
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "ba-success", role: "status", "data-testid": "verify-code-success", children: t("verifyEmail.success") });
4872
5089
  }
@@ -4969,7 +5186,7 @@ function VerificationPending({
4969
5186
  }
4970
5187
 
4971
5188
  // src/components/PasswordlessSignUp.tsx
4972
- var React21 = __toESM(require("react"), 1);
5189
+ var React22 = __toESM(require("react"), 1);
4973
5190
  init_hooks();
4974
5191
  init_i18n();
4975
5192
  init_use_submit_action();
@@ -4981,9 +5198,9 @@ function PasswordlessSignUp({ onAuthenticated }) {
4981
5198
  const { sendEmailOtp, signInEmailOtp } = useSignIn();
4982
5199
  const { pending, error, setError, run } = useSubmitAction();
4983
5200
  const authChallenge = useAuthChallenge();
4984
- const [email, setEmail] = React21.useState("");
4985
- const [code, setCode] = React21.useState("");
4986
- const [codeSent, setCodeSent] = React21.useState(false);
5201
+ const [email, setEmail] = React22.useState("");
5202
+ const [code, setCode] = React22.useState("");
5203
+ const [codeSent, setCodeSent] = React22.useState(false);
4987
5204
  if (codeSent) {
4988
5205
  return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ba-fields", "data-testid": "signup-emailotp-code", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4989
5206
  OtpCodeForm,
@@ -5088,7 +5305,7 @@ init_Spinner();
5088
5305
  init_FormError();
5089
5306
 
5090
5307
  // src/components/Waitlist.tsx
5091
- var React22 = __toESM(require("react"), 1);
5308
+ var React23 = __toESM(require("react"), 1);
5092
5309
  init_hooks();
5093
5310
  init_i18n();
5094
5311
  init_FormError();
@@ -5100,8 +5317,8 @@ function Waitlist({ onJoined, showBadge, showBranding = true } = {}) {
5100
5317
  const { join } = useWaitlist();
5101
5318
  const { pending, error, run } = useSubmitAction();
5102
5319
  const authChallenge = useAuthChallenge();
5103
- const [email, setEmail] = React22.useState("");
5104
- const [joined, setJoined] = React22.useState(false);
5320
+ const [email, setEmail] = React23.useState("");
5321
+ const [joined, setJoined] = React23.useState(false);
5105
5322
  if (joined) {
5106
5323
  return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "ba-form", "data-testid": "waitlist-accepted", children: [
5107
5324
  showBranding ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(AuthOwlBranding, {}) : null,
@@ -5185,24 +5402,24 @@ function SignUp({
5185
5402
  const { signUp } = useSignUp();
5186
5403
  const { config, isLoading, isError } = usePublicConfig();
5187
5404
  const authChallenge = useAuthChallenge();
5188
- const [email, setEmail] = React23.useState("");
5189
- const [password, setPassword] = React23.useState("");
5190
- const [name, setName] = React23.useState("");
5191
- const [firstName, setFirstName] = React23.useState("");
5192
- const [lastName, setLastName] = React23.useState("");
5193
- const [username, setUsername] = React23.useState("");
5194
- const [error, setError] = React23.useState(null);
5195
- const [submitting, setSubmitting] = React23.useState(false);
5196
- const [accepted, setAccepted] = React23.useState(false);
5405
+ const [email, setEmail] = React24.useState("");
5406
+ const [password, setPassword] = React24.useState("");
5407
+ const [name, setName] = React24.useState("");
5408
+ const [firstName, setFirstName] = React24.useState("");
5409
+ const [lastName, setLastName] = React24.useState("");
5410
+ const [username, setUsername] = React24.useState("");
5411
+ const [error, setError] = React24.useState(null);
5412
+ const [submitting, setSubmitting] = React24.useState(false);
5413
+ const [accepted, setAccepted] = React24.useState(false);
5197
5414
  const legal = config?.legal;
5198
5415
  const consentRequired = Boolean(legal?.required);
5199
5416
  const consentBlocked = consentRequired && !accepted;
5200
- const capabilities = (0, import_core3.resolveProjectCapabilities)(config);
5417
+ const capabilities = (0, import_core4.resolveProjectCapabilities)(config);
5201
5418
  const passwordMinLength = capabilities.passwordMinLength;
5202
5419
  const passwordMaxLength = capabilities.passwordMaxLength;
5203
5420
  const passkeysEnabled = capabilities.passkeyAdd;
5204
- const [pendingEmail, setPendingEmail] = React23.useState(null);
5205
- const [completeWithPasskey, setCompleteWithPasskey] = React23.useState(false);
5421
+ const [pendingEmail, setPendingEmail] = React24.useState(null);
5422
+ const [completeWithPasskey, setCompleteWithPasskey] = React24.useState(false);
5206
5423
  function finishSignUp() {
5207
5424
  onSignedUp?.();
5208
5425
  if (redirectTo) window.location.assign(redirectTo);
@@ -5489,7 +5706,7 @@ function MFARequiredGate({ children, title }) {
5489
5706
  }
5490
5707
 
5491
5708
  // src/components/BackupCodesManager.tsx
5492
- var React24 = __toESM(require("react"), 1);
5709
+ var React25 = __toESM(require("react"), 1);
5493
5710
  init_hooks();
5494
5711
  init_i18n();
5495
5712
  init_use_submit_action();
@@ -5501,8 +5718,8 @@ function BackupCodesManager({ title }) {
5501
5718
  const { user } = useUser();
5502
5719
  const { regenerateBackupCodes } = useMFA();
5503
5720
  const { pending, error, run } = useSubmitAction();
5504
- const [password, setPassword] = React24.useState("");
5505
- const [codes, setCodes] = React24.useState(null);
5721
+ const [password, setPassword] = React25.useState("");
5722
+ const [codes, setCodes] = React25.useState(null);
5506
5723
  if (!user?.twoFactorEnabled) return null;
5507
5724
  const submit = (e) => {
5508
5725
  e.preventDefault();
@@ -5546,7 +5763,7 @@ function BackupCodesManager({ title }) {
5546
5763
  }
5547
5764
 
5548
5765
  // src/components/MagicLinkForm.tsx
5549
- var React25 = __toESM(require("react"), 1);
5766
+ var React26 = __toESM(require("react"), 1);
5550
5767
  init_hooks();
5551
5768
  init_i18n();
5552
5769
  init_use_submit_action();
@@ -5558,8 +5775,8 @@ function MagicLinkForm({ callbackURL, webauthnAutofill }) {
5558
5775
  const { signInMagicLink } = useSignIn();
5559
5776
  const { pending, error, run } = useSubmitAction();
5560
5777
  const authChallenge = useAuthChallenge();
5561
- const [email, setEmail] = React25.useState("");
5562
- const [sent, setSent] = React25.useState(false);
5778
+ const [email, setEmail] = React26.useState("");
5779
+ const [sent, setSent] = React26.useState(false);
5563
5780
  if (sent) {
5564
5781
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "ba-muted", "data-testid": "magiclink-sent", children: t("magicLink.sent") });
5565
5782
  }
@@ -5609,7 +5826,7 @@ function MagicLinkForm({ callbackURL, webauthnAutofill }) {
5609
5826
  }
5610
5827
 
5611
5828
  // src/components/EmailOtpForm.tsx
5612
- var React26 = __toESM(require("react"), 1);
5829
+ var React27 = __toESM(require("react"), 1);
5613
5830
  init_hooks();
5614
5831
  init_i18n();
5615
5832
  init_use_submit_action();
@@ -5622,9 +5839,9 @@ function EmailOtpForm({ redirectTo, onSignedIn, webauthnAutofill }) {
5622
5839
  const { sendEmailOtp, signInEmailOtp } = useSignIn();
5623
5840
  const { pending, error, setError, run } = useSubmitAction();
5624
5841
  const authChallenge = useAuthChallenge();
5625
- const [email, setEmail] = React26.useState("");
5626
- const [otp, setOtp] = React26.useState("");
5627
- const [stage, setStage] = React26.useState("email");
5842
+ const [email, setEmail] = React27.useState("");
5843
+ const [otp, setOtp] = React27.useState("");
5844
+ const [stage, setStage] = React27.useState("email");
5628
5845
  if (stage === "code") {
5629
5846
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
5630
5847
  OtpCodeForm,
@@ -5698,7 +5915,7 @@ function EmailOtpForm({ redirectTo, onSignedIn, webauthnAutofill }) {
5698
5915
  }
5699
5916
 
5700
5917
  // src/components/ResetPassword.tsx
5701
- var React27 = __toESM(require("react"), 1);
5918
+ var React28 = __toESM(require("react"), 1);
5702
5919
  init_hooks();
5703
5920
  init_i18n();
5704
5921
  init_use_submit_action();
@@ -5709,15 +5926,15 @@ function ResetPassword({ token: tokenProp, redirectTo, onReset }) {
5709
5926
  const t = useT();
5710
5927
  const { resetPassword } = usePasswordReset();
5711
5928
  const { config } = usePublicConfig();
5712
- const capabilities = (0, import_core3.resolveProjectCapabilities)(config);
5929
+ const capabilities = (0, import_core4.resolveProjectCapabilities)(config);
5713
5930
  const { passwordMinLength, passwordMaxLength } = capabilities;
5714
5931
  const { pending, error, setError, run } = useSubmitAction();
5715
- const [token, setToken] = React27.useState(tokenProp ?? null);
5716
- const [ready, setReady] = React27.useState(tokenProp != null);
5717
- const [password, setPassword] = React27.useState("");
5718
- const [confirm, setConfirm] = React27.useState("");
5719
- const [done, setDone] = React27.useState(false);
5720
- React27.useEffect(() => {
5932
+ const [token, setToken] = React28.useState(tokenProp ?? null);
5933
+ const [ready, setReady] = React28.useState(tokenProp != null);
5934
+ const [password, setPassword] = React28.useState("");
5935
+ const [confirm, setConfirm] = React28.useState("");
5936
+ const [done, setDone] = React28.useState(false);
5937
+ React28.useEffect(() => {
5721
5938
  if (tokenProp != null) return;
5722
5939
  const params = new URLSearchParams(window.location.search);
5723
5940
  setToken(params.get("token"));
@@ -5804,7 +6021,7 @@ function ResetPassword({ token: tokenProp, redirectTo, onReset }) {
5804
6021
  }
5805
6022
 
5806
6023
  // src/components/VerifyEmail.tsx
5807
- var React28 = __toESM(require("react"), 1);
6024
+ var React29 = __toESM(require("react"), 1);
5808
6025
  init_hooks();
5809
6026
  init_i18n();
5810
6027
  init_use_submit_action();
@@ -5816,11 +6033,11 @@ function VerifyEmail({ redirectTo, onVerified, callbackURL }) {
5816
6033
  const { sendVerificationEmail } = useEmailVerification();
5817
6034
  const { pending, error, run } = useSubmitAction();
5818
6035
  const authChallenge = useAuthChallenge();
5819
- const [ready, setReady] = React28.useState(false);
5820
- const [failed, setFailed] = React28.useState(false);
5821
- const [email, setEmail] = React28.useState("");
5822
- const [resent, setResent] = React28.useState(false);
5823
- React28.useEffect(() => {
6036
+ const [ready, setReady] = React29.useState(false);
6037
+ const [failed, setFailed] = React29.useState(false);
6038
+ const [email, setEmail] = React29.useState("");
6039
+ const [resent, setResent] = React29.useState(false);
6040
+ React29.useEffect(() => {
5824
6041
  const didFail = new URLSearchParams(window.location.search).has("error");
5825
6042
  setFailed(didFail);
5826
6043
  setReady(true);
@@ -5885,7 +6102,7 @@ function VerifyEmail({ redirectTo, onVerified, callbackURL }) {
5885
6102
  }
5886
6103
 
5887
6104
  // src/components/PasskeyManager.tsx
5888
- var React29 = __toESM(require("react"), 1);
6105
+ var React30 = __toESM(require("react"), 1);
5889
6106
  init_hooks();
5890
6107
  init_i18n();
5891
6108
  init_use_submit_action();
@@ -5910,12 +6127,12 @@ function PasskeyManagerBody({
5910
6127
  const t = useT();
5911
6128
  const toServerError = useServerError();
5912
6129
  const api = usePasskeys();
5913
- const apiRef = React29.useRef(api);
6130
+ const apiRef = React30.useRef(api);
5914
6131
  apiRef.current = api;
5915
6132
  const { pending, error, setError, run } = useSubmitAction();
5916
- const [passkeys, setPasskeys] = React29.useState(null);
5917
- const loadTokenRef = React29.useRef(0);
5918
- const load = React29.useCallback(async () => {
6133
+ const [passkeys, setPasskeys] = React30.useState(null);
6134
+ const loadTokenRef = React30.useRef(0);
6135
+ const load = React30.useCallback(async () => {
5919
6136
  const token = ++loadTokenRef.current;
5920
6137
  try {
5921
6138
  const res = await apiRef.current.listPasskeys();
@@ -5931,7 +6148,7 @@ function PasskeyManagerBody({
5931
6148
  setError(t("passkeys.error.loadFailed"));
5932
6149
  }
5933
6150
  }, [setError, toServerError, t]);
5934
- React29.useEffect(() => {
6151
+ React30.useEffect(() => {
5935
6152
  void load();
5936
6153
  }, [load]);
5937
6154
  function onRename(id, current) {
@@ -6002,7 +6219,7 @@ function PasskeyManagerBody({
6002
6219
  }
6003
6220
 
6004
6221
  // src/components/control.tsx
6005
- var import_core6 = require("@authowl/core");
6222
+ var import_core7 = require("@authowl/core");
6006
6223
  init_hooks();
6007
6224
  init_i18n();
6008
6225
  init_Spinner();
@@ -6027,7 +6244,7 @@ function Protect({
6027
6244
  const membership = useSession().data?.session?.membership ?? null;
6028
6245
  if (!isLoaded) return null;
6029
6246
  if (!isSignedIn || !user) return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_jsx_runtime39.Fragment, { children: fallback });
6030
- if ((role !== void 0 || permission !== void 0 || teamId !== void 0) && !(0, import_core6.membershipHas)(membership, { role, permission, teamId })) {
6247
+ if ((role !== void 0 || permission !== void 0 || teamId !== void 0) && !(0, import_core7.membershipHas)(membership, { role, permission, teamId })) {
6031
6248
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_jsx_runtime39.Fragment, { children: fallback });
6032
6249
  }
6033
6250
  if (condition && !condition(user)) return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_jsx_runtime39.Fragment, { children: fallback });
@@ -6051,7 +6268,7 @@ function AuthLoaded({ children }) {
6051
6268
  init_Spinner();
6052
6269
 
6053
6270
  // src/components/SignOutButton.tsx
6054
- var React30 = __toESM(require("react"), 1);
6271
+ var React31 = __toESM(require("react"), 1);
6055
6272
  init_hooks();
6056
6273
  init_i18n();
6057
6274
  init_Spinner();
@@ -6059,7 +6276,7 @@ var import_jsx_runtime40 = require("react/jsx-runtime");
6059
6276
  function SignOutButton({ children, redirectTo, onSignedOut, className }) {
6060
6277
  const t = useT();
6061
6278
  const { signOut } = useSignOut();
6062
- const [pending, setPending] = React30.useState(false);
6279
+ const [pending, setPending] = React31.useState(false);
6063
6280
  const content = children ?? t("signOut.button");
6064
6281
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
6065
6282
  "button",
@@ -6085,17 +6302,17 @@ function SignOutButton({ children, redirectTo, onSignedOut, className }) {
6085
6302
  }
6086
6303
 
6087
6304
  // src/components/UserButton.tsx
6088
- var React43 = __toESM(require("react"), 1);
6305
+ var React44 = __toESM(require("react"), 1);
6089
6306
  init_hooks();
6090
6307
  init_i18n();
6091
6308
 
6092
6309
  // src/components/UserProfile.tsx
6093
- var React42 = __toESM(require("react"), 1);
6310
+ var React43 = __toESM(require("react"), 1);
6094
6311
  init_hooks();
6095
6312
  init_i18n();
6096
6313
 
6097
6314
  // src/components/user-profile/EmailSection.tsx
6098
- var React31 = __toESM(require("react"), 1);
6315
+ var React32 = __toESM(require("react"), 1);
6099
6316
  init_hooks();
6100
6317
  init_i18n();
6101
6318
  init_use_submit_action();
@@ -6107,9 +6324,9 @@ function EmailSection({ allowChange }) {
6107
6324
  const account = useAccount();
6108
6325
  const { user } = useUser();
6109
6326
  const { pending, error, run } = useSubmitAction();
6110
- const [newEmail, setNewEmail] = React31.useState("");
6111
- const [sent, setSent] = React31.useState(false);
6112
- const titleId = React31.useId();
6327
+ const [newEmail, setNewEmail] = React32.useState("");
6328
+ const [sent, setSent] = React32.useState(false);
6329
+ const titleId = React32.useId();
6113
6330
  if (!user?.email) {
6114
6331
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("section", { className: "ba-profile-section", "aria-labelledby": titleId, children: [
6115
6332
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h2", { id: titleId, className: "ba-title", children: t("userProfile.email.title") }),
@@ -6174,7 +6391,7 @@ function EmailSection({ allowChange }) {
6174
6391
  }
6175
6392
 
6176
6393
  // src/components/user-profile/DeleteAccountSection.tsx
6177
- var React32 = __toESM(require("react"), 1);
6394
+ var React33 = __toESM(require("react"), 1);
6178
6395
  init_hooks();
6179
6396
  init_i18n();
6180
6397
  init_use_submit_action();
@@ -6187,8 +6404,8 @@ function DeleteAccountSection({ onDeleted }) {
6187
6404
  const session = useSession();
6188
6405
  const { user } = useUser();
6189
6406
  const { pending, error, run } = useSubmitAction();
6190
- const [confirmation, setConfirmation] = React32.useState("");
6191
- const titleId = React32.useId();
6407
+ const [confirmation, setConfirmation] = React33.useState("");
6408
+ const titleId = React33.useId();
6192
6409
  const identifier = user?.email ?? user?.phoneNumber ?? user?.id ?? "";
6193
6410
  const confirmed = identifier.length > 0 && confirmation.trim().toLowerCase() === identifier.toLowerCase();
6194
6411
  const submit = (event) => {
@@ -6246,7 +6463,7 @@ function DeleteAccountSection({ onDeleted }) {
6246
6463
  }
6247
6464
 
6248
6465
  // src/components/user-profile/MfaSection.tsx
6249
- var React33 = __toESM(require("react"), 1);
6466
+ var React34 = __toESM(require("react"), 1);
6250
6467
  init_hooks();
6251
6468
  init_i18n();
6252
6469
  init_use_submit_action();
@@ -6260,10 +6477,10 @@ function MfaSection() {
6260
6477
  const { config } = usePublicConfig();
6261
6478
  const { disable } = useMFA();
6262
6479
  const { pending, error, run } = useSubmitAction();
6263
- const [password, setPassword] = React33.useState("");
6264
- const [showDisable, setShowDisable] = React33.useState(false);
6265
- const titleId = React33.useId();
6266
- const required = (0, import_core3.resolveProjectCapabilities)(config).mfaRequired;
6480
+ const [password, setPassword] = React34.useState("");
6481
+ const [showDisable, setShowDisable] = React34.useState(false);
6482
+ const titleId = React34.useId();
6483
+ const required = (0, import_core4.resolveProjectCapabilities)(config).mfaRequired;
6267
6484
  if (!user?.twoFactorEnabled) {
6268
6485
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("section", { className: "ba-profile-section", "aria-labelledby": titleId, children: [
6269
6486
  /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("header", { className: "ba-profile-section-header", children: [
@@ -6357,7 +6574,7 @@ function MfaSection() {
6357
6574
  }
6358
6575
 
6359
6576
  // src/components/user-profile/PasswordSection.tsx
6360
- var React34 = __toESM(require("react"), 1);
6577
+ var React35 = __toESM(require("react"), 1);
6361
6578
  init_hooks();
6362
6579
  init_i18n();
6363
6580
  init_use_submit_action();
@@ -6368,13 +6585,13 @@ function PasswordSection() {
6368
6585
  const t = useT();
6369
6586
  const account = useAccount();
6370
6587
  const { config } = usePublicConfig();
6371
- const { passwordMinLength, passwordMaxLength } = (0, import_core3.resolveProjectCapabilities)(config);
6588
+ const { passwordMinLength, passwordMaxLength } = (0, import_core4.resolveProjectCapabilities)(config);
6372
6589
  const { pending, error, setError, run } = useSubmitAction();
6373
- const [currentPassword, setCurrentPassword] = React34.useState("");
6374
- const [newPassword, setNewPassword] = React34.useState("");
6375
- const [confirmPassword, setConfirmPassword] = React34.useState("");
6376
- const [saved, setSaved] = React34.useState(false);
6377
- const titleId = React34.useId();
6590
+ const [currentPassword, setCurrentPassword] = React35.useState("");
6591
+ const [newPassword, setNewPassword] = React35.useState("");
6592
+ const [confirmPassword, setConfirmPassword] = React35.useState("");
6593
+ const [saved, setSaved] = React35.useState(false);
6594
+ const titleId = React35.useId();
6378
6595
  const submit = (event) => {
6379
6596
  event.preventDefault();
6380
6597
  setSaved(false);
@@ -6443,12 +6660,12 @@ function PasswordSection() {
6443
6660
  }
6444
6661
 
6445
6662
  // src/components/user-profile/PasskeysSection.tsx
6446
- var React35 = __toESM(require("react"), 1);
6663
+ var React36 = __toESM(require("react"), 1);
6447
6664
  init_i18n();
6448
6665
  var import_jsx_runtime45 = require("react/jsx-runtime");
6449
6666
  function PasskeysSection({ allowAdd }) {
6450
6667
  const t = useT();
6451
- const titleId = React35.useId();
6668
+ const titleId = React36.useId();
6452
6669
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("section", { className: "ba-profile-section", "aria-labelledby": titleId, children: [
6453
6670
  /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("header", { className: "ba-profile-section-header", children: [
6454
6671
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("h2", { id: titleId, className: "ba-title", children: t("userProfile.passkeys.title") }),
@@ -6459,7 +6676,7 @@ function PasskeysSection({ allowAdd }) {
6459
6676
  }
6460
6677
 
6461
6678
  // src/components/user-profile/ProfileSection.tsx
6462
- var React36 = __toESM(require("react"), 1);
6679
+ var React37 = __toESM(require("react"), 1);
6463
6680
  init_hooks();
6464
6681
  init_i18n();
6465
6682
  init_use_submit_action();
@@ -6476,15 +6693,15 @@ function ProfileSection({
6476
6693
  const { user } = useUser();
6477
6694
  const session = useSession();
6478
6695
  const { pending, error, run } = useSubmitAction();
6479
- const [name, setName] = React36.useState(user?.name ?? "");
6480
- const [firstName, setFirstName] = React36.useState(user?.firstName ?? "");
6481
- const [lastName, setLastName] = React36.useState(user?.lastName ?? "");
6482
- const [username, setUsername] = React36.useState(
6696
+ const [name, setName] = React37.useState(user?.name ?? "");
6697
+ const [firstName, setFirstName] = React37.useState(user?.firstName ?? "");
6698
+ const [lastName, setLastName] = React37.useState(user?.lastName ?? "");
6699
+ const [username, setUsername] = React37.useState(
6483
6700
  user?.displayUsername ?? user?.username ?? ""
6484
6701
  );
6485
- const [image, setImage] = React36.useState(user?.image ?? "");
6486
- const [saved, setSaved] = React36.useState(false);
6487
- const titleId = React36.useId();
6702
+ const [image, setImage] = React37.useState(user?.image ?? "");
6703
+ const [saved, setSaved] = React37.useState(false);
6704
+ const titleId = React37.useId();
6488
6705
  const submit = (event) => {
6489
6706
  event.preventDefault();
6490
6707
  setSaved(false);
@@ -6594,14 +6811,14 @@ function ProfileSection({
6594
6811
  }
6595
6812
 
6596
6813
  // src/components/user-profile/RecoverySection.tsx
6597
- var React37 = __toESM(require("react"), 1);
6814
+ var React38 = __toESM(require("react"), 1);
6598
6815
  init_hooks();
6599
6816
  init_i18n();
6600
6817
  var import_jsx_runtime47 = require("react/jsx-runtime");
6601
6818
  function RecoverySection() {
6602
6819
  const t = useT();
6603
6820
  const { user } = useUser();
6604
- const titleId = React37.useId();
6821
+ const titleId = React38.useId();
6605
6822
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("section", { className: "ba-profile-section", "aria-labelledby": titleId, children: [
6606
6823
  /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("header", { className: "ba-profile-section-header", children: [
6607
6824
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h2", { id: titleId, className: "ba-title", children: t("userProfile.recovery.title") }),
@@ -6619,7 +6836,7 @@ function RecoverySection() {
6619
6836
  }
6620
6837
 
6621
6838
  // src/components/user-profile/SessionsSection.tsx
6622
- var React39 = __toESM(require("react"), 1);
6839
+ var React40 = __toESM(require("react"), 1);
6623
6840
  init_hooks();
6624
6841
  init_i18n();
6625
6842
  init_use_submit_action();
@@ -6669,19 +6886,19 @@ function formatSessionTime(date, locale) {
6669
6886
  }
6670
6887
 
6671
6888
  // src/components/user-profile/use-account-resource.ts
6672
- var React38 = __toESM(require("react"), 1);
6889
+ var React39 = __toESM(require("react"), 1);
6673
6890
  init_i18n();
6674
- function useAccountResource(loader2, failure) {
6675
- const loaderRef = React38.useRef(loader2);
6676
- loaderRef.current = loader2;
6677
- const failureRef = React38.useRef(failure);
6891
+ function useAccountResource(loader, failure) {
6892
+ const loaderRef = React39.useRef(loader);
6893
+ loaderRef.current = loader;
6894
+ const failureRef = React39.useRef(failure);
6678
6895
  failureRef.current = failure;
6679
6896
  const toServerError = useServerError();
6680
- const [data, setData] = React38.useState(null);
6681
- const [error, setError] = React38.useState(null);
6682
- const [loading, setLoading] = React38.useState(true);
6683
- const requestRef = React38.useRef(0);
6684
- const load = React38.useCallback(async () => {
6897
+ const [data, setData] = React39.useState(null);
6898
+ const [error, setError] = React39.useState(null);
6899
+ const [loading, setLoading] = React39.useState(true);
6900
+ const requestRef = React39.useRef(0);
6901
+ const load = React39.useCallback(async () => {
6685
6902
  const request = ++requestRef.current;
6686
6903
  setLoading(true);
6687
6904
  try {
@@ -6700,7 +6917,7 @@ function useAccountResource(loader2, failure) {
6700
6917
  if (request === requestRef.current) setLoading(false);
6701
6918
  }
6702
6919
  }, [toServerError]);
6703
- React38.useEffect(() => {
6920
+ React39.useEffect(() => {
6704
6921
  void load();
6705
6922
  return () => {
6706
6923
  requestRef.current += 1;
@@ -6718,7 +6935,7 @@ function SessionsSection() {
6718
6935
  const account = useAccount();
6719
6936
  const sessionState = useSession();
6720
6937
  const mutation = useSubmitAction();
6721
- const titleId = React39.useId();
6938
+ const titleId = React40.useId();
6722
6939
  const resource = useAccountResource(
6723
6940
  () => account.listSessions(),
6724
6941
  t("userProfile.sessions.loadError")
@@ -6789,7 +7006,7 @@ function SessionsSection() {
6789
7006
  }
6790
7007
 
6791
7008
  // src/components/user-profile/SocialSection.tsx
6792
- var React40 = __toESM(require("react"), 1);
7009
+ var React41 = __toESM(require("react"), 1);
6793
7010
  init_hooks();
6794
7011
  init_i18n();
6795
7012
  init_use_submit_action();
@@ -6803,7 +7020,7 @@ function SocialSection() {
6803
7020
  const account = useAccount();
6804
7021
  const { config } = usePublicConfig();
6805
7022
  const mutation = useSubmitAction();
6806
- const titleId = React40.useId();
7023
+ const titleId = React41.useId();
6807
7024
  const resource = useAccountResource(
6808
7025
  () => account.listSocialAccounts(),
6809
7026
  t("userProfile.social.loadError")
@@ -6875,7 +7092,7 @@ function SocialSection() {
6875
7092
  }
6876
7093
 
6877
7094
  // src/components/user-profile/UserProfileModal.tsx
6878
- var React41 = __toESM(require("react"), 1);
7095
+ var React42 = __toESM(require("react"), 1);
6879
7096
  init_i18n();
6880
7097
  init_ModalSurface();
6881
7098
  var import_jsx_runtime50 = require("react/jsx-runtime");
@@ -6885,7 +7102,7 @@ function UserProfileModal({
6885
7102
  branding
6886
7103
  }) {
6887
7104
  const t = useT();
6888
- const titleId = React41.useId();
7105
+ const titleId = React42.useId();
6889
7106
  return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
6890
7107
  ModalSurface,
6891
7108
  {
@@ -6958,16 +7175,16 @@ function UserProfile(props = {}) {
6958
7175
  const t = useT();
6959
7176
  const { user, isLoaded, isSignedIn } = useUser();
6960
7177
  const { config } = usePublicConfig();
6961
- const [internalSection, setInternalSection] = React42.useState(() => initialSection(defaultSection));
7178
+ const [internalSection, setInternalSection] = React43.useState(() => initialSection(defaultSection));
6962
7179
  const active = section ?? internalSection;
6963
- const capabilities = (0, import_core3.resolveProjectCapabilities)(config);
7180
+ const capabilities = (0, import_core4.resolveProjectCapabilities)(config);
6964
7181
  const passwordEnabled = config !== null && capabilities.passwordSignIn;
6965
7182
  const passkeysEnabled = capabilities.passkeySignIn || capabilities.passkeyAdd;
6966
7183
  const mfaEnabled = capabilities.totp;
6967
7184
  const recoveryEnabled = capabilities.backupCodes && user?.twoFactorEnabled === true;
6968
7185
  const deletionEnabled = capabilities.accountDeletion;
6969
7186
  const socialEnabled = (config?.socialProviders?.length ?? 0) > 0;
6970
- const sections = React42.useMemo(
7187
+ const sections = React43.useMemo(
6971
7188
  () => userProfileSectionsFor({
6972
7189
  password: passwordEnabled,
6973
7190
  passkeys: passkeysEnabled,
@@ -6978,7 +7195,7 @@ function UserProfile(props = {}) {
6978
7195
  }),
6979
7196
  [deletionEnabled, mfaEnabled, passkeysEnabled, passwordEnabled, recoveryEnabled, socialEnabled]
6980
7197
  );
6981
- React42.useEffect(() => {
7198
+ React43.useEffect(() => {
6982
7199
  if (section || mode !== "page") return;
6983
7200
  const onHashChange = () => {
6984
7201
  const next = userProfileSectionFromHash(window.location.hash);
@@ -7077,10 +7294,10 @@ function UserButton() {
7077
7294
  const t = useT();
7078
7295
  const { user, isLoaded } = useUser();
7079
7296
  const { signOut } = useSignOut();
7080
- const [open, setOpen] = React43.useState(false);
7081
- const [profileOpen, setProfileOpen] = React43.useState(false);
7082
- const [failedImage, setFailedImage] = React43.useState(null);
7083
- const triggerRef = React43.useRef(null);
7297
+ const [open, setOpen] = React44.useState(false);
7298
+ const [profileOpen, setProfileOpen] = React44.useState(false);
7299
+ const [failedImage, setFailedImage] = React44.useState(null);
7300
+ const triggerRef = React44.useRef(null);
7084
7301
  if (!isLoaded || !user) return null;
7085
7302
  const identity = user.email ?? user.phoneNumber ?? user.name ?? "?";
7086
7303
  const image = user.image ?? null;
@@ -7136,12 +7353,12 @@ function UserButton() {
7136
7353
  }
7137
7354
 
7138
7355
  // src/components/OrganizationSwitcher.tsx
7139
- var React56 = __toESM(require("react"), 1);
7356
+ var React57 = __toESM(require("react"), 1);
7140
7357
  init_hooks();
7141
7358
  init_i18n();
7142
7359
 
7143
7360
  // src/components/CreateOrganization.tsx
7144
- var React44 = __toESM(require("react"), 1);
7361
+ var React45 = __toESM(require("react"), 1);
7145
7362
  init_hooks();
7146
7363
  init_i18n();
7147
7364
  init_model();
@@ -7155,10 +7372,10 @@ function CreateOrganization({ onCreated, title } = {}) {
7155
7372
  const { isLoaded, isSignedIn } = useUser();
7156
7373
  const api = useAuthClient().organization;
7157
7374
  const { pending, error, run } = useSubmitAction();
7158
- const [name, setName] = React44.useState("");
7159
- const [slug, setSlug] = React44.useState("");
7160
- const [logo, setLogo] = React44.useState("");
7161
- const [slugTouched, setSlugTouched] = React44.useState(false);
7375
+ const [name, setName] = React45.useState("");
7376
+ const [slug, setSlug] = React45.useState("");
7377
+ const [logo, setLogo] = React45.useState("");
7378
+ const [slugTouched, setSlugTouched] = React45.useState(false);
7162
7379
  if (configLoading || !isLoaded) {
7163
7380
  return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "ba-skeleton", "aria-label": t("organization.loading") });
7164
7381
  }
@@ -7258,7 +7475,7 @@ function CreateOrganization({ onCreated, title } = {}) {
7258
7475
  }
7259
7476
 
7260
7477
  // src/components/organization/OrganizationModal.tsx
7261
- var React45 = __toESM(require("react"), 1);
7478
+ var React46 = __toESM(require("react"), 1);
7262
7479
  init_i18n();
7263
7480
  init_ModalSurface();
7264
7481
  var import_jsx_runtime54 = require("react/jsx-runtime");
@@ -7269,7 +7486,7 @@ function OrganizationModal({
7269
7486
  children
7270
7487
  }) {
7271
7488
  const t = useT();
7272
- const titleId = React45.useId();
7489
+ const titleId = React46.useId();
7273
7490
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
7274
7491
  ModalSurface,
7275
7492
  {
@@ -7300,21 +7517,21 @@ function OrganizationModal({
7300
7517
  }
7301
7518
 
7302
7519
  // src/components/organization/use-organizations-resource.ts
7303
- var React46 = __toESM(require("react"), 1);
7520
+ var React47 = __toESM(require("react"), 1);
7304
7521
  init_hooks();
7305
7522
  init_i18n();
7306
7523
  function useOrganizationsResource(enabled = true) {
7307
7524
  const api = useAuthClient().organization;
7308
- const apiRef = React46.useRef(api);
7525
+ const apiRef = React47.useRef(api);
7309
7526
  apiRef.current = api;
7310
7527
  const { user, isLoaded, isSignedIn } = useUser();
7311
7528
  const t = useT();
7312
7529
  const toServerError = useServerError();
7313
- const [organizations, setOrganizations] = React46.useState(null);
7314
- const [error, setError] = React46.useState(null);
7315
- const requestRef = React46.useRef(0);
7530
+ const [organizations, setOrganizations] = React47.useState(null);
7531
+ const [error, setError] = React47.useState(null);
7532
+ const requestRef = React47.useRef(0);
7316
7533
  const identity = user?.id ?? null;
7317
- const refresh = React46.useCallback(async () => {
7534
+ const refresh = React47.useCallback(async () => {
7318
7535
  const token = ++requestRef.current;
7319
7536
  if (!enabled || !identity || !isSignedIn) {
7320
7537
  setOrganizations([]);
@@ -7334,7 +7551,7 @@ function useOrganizationsResource(enabled = true) {
7334
7551
  if (token === requestRef.current) setError(t("organization.error.load"));
7335
7552
  }
7336
7553
  }, [enabled, identity, isSignedIn, t, toServerError]);
7337
- React46.useEffect(() => {
7554
+ React47.useEffect(() => {
7338
7555
  setOrganizations(null);
7339
7556
  setError(null);
7340
7557
  if (!isLoaded) return;
@@ -7343,7 +7560,7 @@ function useOrganizationsResource(enabled = true) {
7343
7560
  requestRef.current += 1;
7344
7561
  };
7345
7562
  }, [identity, isLoaded, refresh]);
7346
- React46.useEffect(
7563
+ React47.useEffect(
7347
7564
  () => api.subscribe(() => void refresh()),
7348
7565
  [api, refresh]
7349
7566
  );
@@ -7356,12 +7573,12 @@ function useOrganizationsResource(enabled = true) {
7356
7573
  }
7357
7574
 
7358
7575
  // src/components/OrganizationProfile.tsx
7359
- var React55 = __toESM(require("react"), 1);
7576
+ var React56 = __toESM(require("react"), 1);
7360
7577
  init_hooks();
7361
7578
  init_i18n();
7362
7579
 
7363
7580
  // src/components/organization/DangerSection.tsx
7364
- var React47 = __toESM(require("react"), 1);
7581
+ var React48 = __toESM(require("react"), 1);
7365
7582
  init_hooks();
7366
7583
  init_i18n();
7367
7584
  init_use_submit_action();
@@ -7379,7 +7596,7 @@ function DangerSection({
7379
7596
  const api = useAuthClient().organization;
7380
7597
  const session = useSession();
7381
7598
  const { pending, error, run } = useSubmitAction();
7382
- const [confirmation, setConfirmation] = React47.useState("");
7599
+ const [confirmation, setConfirmation] = React48.useState("");
7383
7600
  const isOwner = hasOrganizationRole(membership, "owner");
7384
7601
  const confirmed = confirmation.trim().toLowerCase() === organization.slug.toLowerCase();
7385
7602
  const leave = () => {
@@ -7444,7 +7661,7 @@ function DangerSection({
7444
7661
  }
7445
7662
 
7446
7663
  // src/components/organization/GeneralSection.tsx
7447
- var React48 = __toESM(require("react"), 1);
7664
+ var React49 = __toESM(require("react"), 1);
7448
7665
  init_hooks();
7449
7666
  init_i18n();
7450
7667
  init_use_submit_action();
@@ -7460,10 +7677,10 @@ function GeneralSection({
7460
7677
  const t = useT();
7461
7678
  const api = useAuthClient().organization;
7462
7679
  const { pending, error, run } = useSubmitAction();
7463
- const [name, setName] = React48.useState(organization.name);
7464
- const [slug, setSlug] = React48.useState(organization.slug);
7465
- const [logo, setLogo] = React48.useState(organization.logo ?? "");
7466
- React48.useEffect(() => {
7680
+ const [name, setName] = React49.useState(organization.name);
7681
+ const [slug, setSlug] = React49.useState(organization.slug);
7682
+ const [logo, setLogo] = React49.useState(organization.logo ?? "");
7683
+ React49.useEffect(() => {
7467
7684
  setName(organization.name);
7468
7685
  setSlug(organization.slug);
7469
7686
  setLogo(organization.logo ?? "");
@@ -7540,7 +7757,7 @@ function GeneralSection({
7540
7757
  }
7541
7758
 
7542
7759
  // src/components/organization/InvitationsSection.tsx
7543
- var React50 = __toESM(require("react"), 1);
7760
+ var React51 = __toESM(require("react"), 1);
7544
7761
  init_hooks();
7545
7762
  init_i18n();
7546
7763
  init_use_submit_action();
@@ -7571,8 +7788,8 @@ function InvitationsSection({
7571
7788
  const api = useAuthClient().organization;
7572
7789
  const { pending, error, run } = useSubmitAction();
7573
7790
  const { roles } = useOrganizationRoles(organization.id);
7574
- const [email, setEmail] = React50.useState("");
7575
- const [role, setRole] = React50.useState("member");
7791
+ const [email, setEmail] = React51.useState("");
7792
+ const [role, setRole] = React51.useState("member");
7576
7793
  const invitations = organization.invitations.filter((invitation) => invitation.status === "pending");
7577
7794
  const invite = (event) => {
7578
7795
  event.preventDefault();
@@ -7713,7 +7930,7 @@ var SECTION_KEYS2 = {
7713
7930
  invitations: "organization.profile.nav.invitations",
7714
7931
  danger: "organization.profile.nav.danger"
7715
7932
  };
7716
- var TeamsSection2 = React55.lazy(() => Promise.resolve().then(() => (init_TeamsSection(), TeamsSection_exports)));
7933
+ var TeamsSection2 = React56.lazy(() => Promise.resolve().then(() => (init_TeamsSection(), TeamsSection_exports)));
7717
7934
  function OrganizationProfile({ organizationId, defaultSection = "general", onDeleted, onLeft } = {}) {
7718
7935
  const t = useT();
7719
7936
  const toServerError = useServerError();
@@ -7721,17 +7938,17 @@ function OrganizationProfile({ organizationId, defaultSection = "general", onDel
7721
7938
  const { user, isLoaded, isSignedIn } = useUser();
7722
7939
  const session = useSession();
7723
7940
  const api = useAuthClient().organization;
7724
- const apiRef = React55.useRef(api);
7941
+ const apiRef = React56.useRef(api);
7725
7942
  apiRef.current = api;
7726
7943
  const activeOrganizationId = session.data?.session.activeOrganizationId ?? null;
7727
7944
  const requestedId = organizationId ?? activeOrganizationId;
7728
7945
  const enabled = config?.organizations === true && isSignedIn;
7729
- const [organization, setOrganization] = React55.useState(null);
7730
- const [error, setError] = React55.useState(null);
7731
- const [wasRemoved, setWasRemoved] = React55.useState(false);
7732
- const [section, setSection] = React55.useState(defaultSection);
7733
- const requestRef = React55.useRef(0);
7734
- const load = React55.useCallback(async () => {
7946
+ const [organization, setOrganization] = React56.useState(null);
7947
+ const [error, setError] = React56.useState(null);
7948
+ const [wasRemoved, setWasRemoved] = React56.useState(false);
7949
+ const [section, setSection] = React56.useState(defaultSection);
7950
+ const requestRef = React56.useRef(0);
7951
+ const load = React56.useCallback(async () => {
7735
7952
  const token = ++requestRef.current;
7736
7953
  if (!enabled || !requestedId) {
7737
7954
  setOrganization(null);
@@ -7751,7 +7968,7 @@ function OrganizationProfile({ organizationId, defaultSection = "general", onDel
7751
7968
  if (token === requestRef.current) setError(t("organization.profile.loadError"));
7752
7969
  }
7753
7970
  }, [enabled, requestedId, t, toServerError]);
7754
- React55.useEffect(() => {
7971
+ React56.useEffect(() => {
7755
7972
  setOrganization(null);
7756
7973
  setError(null);
7757
7974
  setWasRemoved(false);
@@ -7805,7 +8022,7 @@ function OrganizationProfile({ organizationId, defaultSection = "general", onDel
7805
8022
  /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ba-organization-profile-content", children: [
7806
8023
  activeSection === "general" && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(GeneralSection, { organization, canManage, onChanged: load }),
7807
8024
  activeSection === "members" && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(MembersSection, { organization, userId: user.id, canManage, onChanged: load }),
7808
- activeSection === "teams" && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(React55.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(TeamsSection2, { organization, membership }) }),
8025
+ activeSection === "teams" && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(React56.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(TeamsSection2, { organization, membership }) }),
7809
8026
  activeSection === "invitations" && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(InvitationsSection, { organization, onChanged: load }),
7810
8027
  activeSection === "danger" && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
7811
8028
  DangerSection,
@@ -7834,15 +8051,15 @@ function OrganizationSwitcher({ showPersonalWorkspace = true, onOrganizationChan
7834
8051
  const enabled = config?.organizations === true && isSignedIn;
7835
8052
  const { organizations, isLoading, error: loadError, refresh } = useOrganizationsResource(enabled);
7836
8053
  const { pending, error, run } = useSubmitAction();
7837
- const [open, setOpen] = React56.useState(false);
7838
- const [dialog, setDialog] = React56.useState(null);
7839
- const rootRef = React56.useRef(null);
7840
- const triggerRef = React56.useRef(null);
7841
- const menuRef = React56.useRef(null);
7842
- const menuId = React56.useId();
8054
+ const [open, setOpen] = React57.useState(false);
8055
+ const [dialog, setDialog] = React57.useState(null);
8056
+ const rootRef = React57.useRef(null);
8057
+ const triggerRef = React57.useRef(null);
8058
+ const menuRef = React57.useRef(null);
8059
+ const menuId = React57.useId();
7843
8060
  const activeId = session.data?.session.activeOrganizationId ?? null;
7844
8061
  const active = organizations?.find((organization) => organization.id === activeId) ?? null;
7845
- React56.useEffect(() => {
8062
+ React57.useEffect(() => {
7846
8063
  if (!open) return;
7847
8064
  const onPointerDown = (event) => {
7848
8065
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -7979,7 +8196,7 @@ function OrganizationSwitcher({ showPersonalWorkspace = true, onOrganizationChan
7979
8196
  init_InvitationPrompt();
7980
8197
 
7981
8198
  // src/components/OrganizationList.tsx
7982
- var React57 = __toESM(require("react"), 1);
8199
+ var React58 = __toESM(require("react"), 1);
7983
8200
  init_hooks();
7984
8201
  init_i18n();
7985
8202
  init_use_submit_action();
@@ -7992,19 +8209,19 @@ function OrganizationList({ onOrganizationChange } = {}) {
7992
8209
  const { user, isLoaded, isSignedIn } = useUser();
7993
8210
  const session = useSession();
7994
8211
  const api = useAuthClient().organization;
7995
- const apiRef = React57.useRef(api);
8212
+ const apiRef = React58.useRef(api);
7996
8213
  apiRef.current = api;
7997
8214
  const enabled = config?.organizations === true && isSignedIn;
7998
8215
  const { organizations, isLoading, error: organizationError, refresh } = useOrganizationsResource(enabled);
7999
8216
  const { pending, error, run } = useSubmitAction();
8000
- const [invitations, setInvitations] = React57.useState(null);
8001
- const [invitationError, setInvitationError] = React57.useState(null);
8002
- const [dialog, setDialog] = React57.useState(null);
8003
- const [profileId, setProfileId] = React57.useState(null);
8004
- const dialogReturnFocusRef = React57.useRef(null);
8005
- const invitationRequestRef = React57.useRef(0);
8217
+ const [invitations, setInvitations] = React58.useState(null);
8218
+ const [invitationError, setInvitationError] = React58.useState(null);
8219
+ const [dialog, setDialog] = React58.useState(null);
8220
+ const [profileId, setProfileId] = React58.useState(null);
8221
+ const dialogReturnFocusRef = React58.useRef(null);
8222
+ const invitationRequestRef = React58.useRef(0);
8006
8223
  const activeId = session.data?.session.activeOrganizationId ?? null;
8007
- const loadInvitations = React57.useCallback(async () => {
8224
+ const loadInvitations = React58.useCallback(async () => {
8008
8225
  const token = ++invitationRequestRef.current;
8009
8226
  if (!enabled) {
8010
8227
  setInvitations([]);
@@ -8024,7 +8241,7 @@ function OrganizationList({ onOrganizationChange } = {}) {
8024
8241
  if (token === invitationRequestRef.current) setInvitationError(t("organization.list.invitationsError"));
8025
8242
  }
8026
8243
  }, [enabled, t, toServerError]);
8027
- React57.useEffect(() => {
8244
+ React58.useEffect(() => {
8028
8245
  setInvitations(null);
8029
8246
  setInvitationError(null);
8030
8247
  if (!isLoaded) return;
@@ -8140,7 +8357,7 @@ function OrganizationList({ onOrganizationChange } = {}) {
8140
8357
  }
8141
8358
 
8142
8359
  // src/components/GoogleOneTap.tsx
8143
- var React58 = __toESM(require("react"), 1);
8360
+ var React59 = __toESM(require("react"), 1);
8144
8361
  init_hooks();
8145
8362
 
8146
8363
  // src/components/google-one-tap.ts
@@ -8290,6 +8507,14 @@ function normalizeDismissReason(reason) {
8290
8507
  }
8291
8508
  return "unknown";
8292
8509
  }
8510
+ var warnedMissingNonce = /* @__PURE__ */ new Set();
8511
+ function warnOneTapWithoutNonce(clientId) {
8512
+ if (warnedMissingNonce.has(clientId)) return;
8513
+ warnedMissingNonce.add(clientId);
8514
+ console.warn(
8515
+ "[AuthOwl] <GoogleOneTap/> is running without a `nonce`. Google\u2019s ID token is then not bound to a value chosen for this prompt. Generate a fresh random value per prompt and pass it as `nonce`; AuthOwl forwards it to Google and verifies the match. The direct browser exchange does not keep separate one-time server state, so do not treat this prop by itself as replay protection. (This warning is dev-only.)"
8516
+ );
8517
+ }
8293
8518
  function GoogleOneTap({
8294
8519
  disabled = false,
8295
8520
  nonce,
@@ -8309,11 +8534,16 @@ function GoogleOneTap({
8309
8534
  const { config, isLoading: configLoading, isError: configError } = usePublicConfig();
8310
8535
  const { user, isLoaded: sessionLoaded } = useUser();
8311
8536
  const { signInSocial } = useSignIn();
8312
- const callbacks = React58.useRef({ onSignedIn, onSkipped, onDismissed, onError });
8537
+ const callbacks = React59.useRef({ onSignedIn, onSkipped, onDismissed, onError });
8313
8538
  callbacks.current = { onSignedIn, onSkipped, onDismissed, onError };
8314
8539
  const googleEnabled = config?.socialProviders.includes("google") === true;
8315
8540
  const clientId = config?.socialProviderClientIds?.google;
8316
- React58.useEffect(() => {
8541
+ React59.useEffect(() => {
8542
+ if (process.env.NODE_ENV === "production") return;
8543
+ if (disabled || !googleEnabled || !clientId || nonce) return;
8544
+ warnOneTapWithoutNonce(clientId);
8545
+ }, [clientId, disabled, googleEnabled, nonce]);
8546
+ React59.useEffect(() => {
8317
8547
  if (configLoading || !sessionLoaded) return;
8318
8548
  if (disabled) {
8319
8549
  callbacks.current.onSkipped?.("disabled");
@@ -8429,8 +8659,9 @@ function GoogleOneTap({
8429
8659
  }
8430
8660
 
8431
8661
  // src/index.ts
8432
- var import_core7 = require("@authowl/core");
8433
8662
  var import_core8 = require("@authowl/core");
8663
+ var import_core9 = require("@authowl/core");
8664
+ init_last_used_method();
8434
8665
  // Annotate the CommonJS export names for ESM import in node:
8435
8666
  0 && (module.exports = {
8436
8667
  AuthLoaded,
@@ -8489,6 +8720,7 @@ var import_core8 = require("@authowl/core");
8489
8720
  useConsent,
8490
8721
  useEmailVerification,
8491
8722
  useInvitationRecipientHint,
8723
+ useLastUsedSignInMethod,
8492
8724
  useLocale,
8493
8725
  useMFA,
8494
8726
  useOrganization,