@authowl/react 0.22.0 → 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.
@@ -9,7 +9,7 @@ import {
9
9
  useServerError,
10
10
  useSubmitAction,
11
11
  useT
12
- } from "./chunk-PUJV7S6G.js";
12
+ } from "./chunk-E5ZOQHXY.js";
13
13
 
14
14
  // src/components/organization/TeamsSection.tsx
15
15
  import * as React4 from "react";
@@ -151,7 +151,7 @@ function brandRampVars(set) {
151
151
  }
152
152
 
153
153
  // src/hooks.ts
154
- import * as React5 from "react";
154
+ import * as React6 from "react";
155
155
  import {
156
156
  clearInvitationClaim,
157
157
  createMembershipHas,
@@ -159,10 +159,11 @@ import {
159
159
  } from "@authowl/core";
160
160
 
161
161
  // src/provider.tsx
162
- import * as React4 from "react";
162
+ import * as React5 from "react";
163
163
  import {
164
164
  captureInvitationClaim,
165
165
  createAuthOwlClient,
166
+ setActiveLocale,
166
167
  directionFor,
167
168
  getPublicConfig,
168
169
  isLocale,
@@ -367,6 +368,39 @@ function InvitationPrompt() {
367
368
  );
368
369
  }
369
370
 
371
+ // src/last-used-method.ts
372
+ import * as React4 from "react";
373
+ import {
374
+ readLastUsedSignInMethod,
375
+ recordLastUsedSignInMethod,
376
+ rememberPendingSignInMethod,
377
+ settlePendingSignInMethod
378
+ } from "@authowl/core";
379
+ function useLastUsedSignInMethod() {
380
+ const { config } = usePublicConfig();
381
+ const projectId = config?.environmentId ?? null;
382
+ return React4.useMemo(
383
+ () => projectId ? readLastUsedSignInMethod(projectId) : null,
384
+ [projectId]
385
+ );
386
+ }
387
+ function useSignInMethodRecorder() {
388
+ const { config } = usePublicConfig();
389
+ const projectId = config?.environmentId ?? null;
390
+ return React4.useCallback(
391
+ (method, pending) => {
392
+ if (!projectId) return;
393
+ (pending ? rememberPendingSignInMethod : recordLastUsedSignInMethod)(projectId, method);
394
+ },
395
+ [projectId]
396
+ );
397
+ }
398
+ function useConfirmPendingSignInMethod(loaded, signedIn, projectId) {
399
+ React4.useEffect(() => {
400
+ if (loaded && projectId) settlePendingSignInMethod(projectId, signedIn);
401
+ }, [loaded, projectId, signedIn]);
402
+ }
403
+
370
404
  // src/provider.tsx
371
405
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
372
406
  var warnedConfigProjects = /* @__PURE__ */ new Set();
@@ -384,7 +418,13 @@ function warnPublicConfigFailed(resolved, error) {
384
418
  `[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.)`
385
419
  );
386
420
  }
387
- var Context = React4.createContext(null);
421
+ function LastUsedMethodSync() {
422
+ const { config } = usePublicConfig();
423
+ const { isLoaded, isSignedIn } = useUser();
424
+ useConfirmPendingSignInMethod(isLoaded, isSignedIn, config?.environmentId ?? null);
425
+ return null;
426
+ }
427
+ var Context = React5.createContext(null);
388
428
  function detectLocale() {
389
429
  if (typeof document !== "undefined") {
390
430
  const root = document.documentElement;
@@ -409,18 +449,18 @@ function AuthOwlProvider({
409
449
  invitationPrompt = true,
410
450
  children
411
451
  }) {
412
- const fetchRef = React4.useRef(fetch);
452
+ const fetchRef = React5.useRef(fetch);
413
453
  fetchRef.current = fetch;
414
- const resolved = React4.useMemo(
454
+ const resolved = React5.useMemo(
415
455
  () => resolveConfig({ publishableKey, apiUrl, fetch: fetchRef.current }),
416
456
  [publishableKey, apiUrl]
417
457
  );
418
- const client = React4.useMemo(() => createAuthOwlClient(resolved), [resolved]);
419
- const [config, setConfig] = React4.useState(null);
420
- const [configState, setConfigState] = React4.useState("loading");
421
- const [configAttempt, setConfigAttempt] = React4.useState(0);
422
- const retryPublicConfig = React4.useCallback(() => setConfigAttempt((attempt) => attempt + 1), []);
423
- React4.useEffect(() => {
458
+ const client = React5.useMemo(() => createAuthOwlClient(resolved), [resolved]);
459
+ const [config, setConfig] = React5.useState(null);
460
+ const [configState, setConfigState] = React5.useState("loading");
461
+ const [configAttempt, setConfigAttempt] = React5.useState(0);
462
+ const retryPublicConfig = React5.useCallback(() => setConfigAttempt((attempt) => attempt + 1), []);
463
+ React5.useEffect(() => {
424
464
  let active = true;
425
465
  setConfigState("loading");
426
466
  getPublicConfig(resolved).then((c) => {
@@ -438,15 +478,18 @@ function AuthOwlProvider({
438
478
  };
439
479
  }, [resolved, configAttempt]);
440
480
  const merged = resolveAppearance(appearance, config);
441
- const [autoLocale, setAutoLocale] = React4.useState(null);
442
- React4.useEffect(() => {
481
+ const [autoLocale, setAutoLocale] = React5.useState(null);
482
+ React5.useEffect(() => {
443
483
  if (localeProp === "auto") setAutoLocale(detectLocale());
444
484
  }, [localeProp]);
445
485
  const locale = resolveLocale(localeProp, autoLocale, config?.locale);
446
- React4.useEffect(() => {
486
+ React5.useEffect(() => {
487
+ return setActiveLocale(resolved.decoded.projectId, locale);
488
+ }, [locale, resolved.decoded.projectId]);
489
+ React5.useEffect(() => {
447
490
  captureInvitationClaim();
448
491
  }, []);
449
- const ctxValue = React4.useMemo(
492
+ const ctxValue = React5.useMemo(
450
493
  () => ({ client, appearance, config, configState, retryPublicConfig, locale }),
451
494
  [client, appearance, config, configState, retryPublicConfig, locale]
452
495
  );
@@ -460,13 +503,14 @@ function AuthOwlProvider({
460
503
  style: { display: "contents", ...merged.style },
461
504
  children: [
462
505
  children,
506
+ /* @__PURE__ */ jsx4(LastUsedMethodSync, {}),
463
507
  invitationPrompt ? /* @__PURE__ */ jsx4(InvitationPrompt, {}) : null
464
508
  ]
465
509
  }
466
510
  ) });
467
511
  }
468
512
  function useAuthOwlContext() {
469
- const v = React4.useContext(Context);
513
+ const v = React5.useContext(Context);
470
514
  if (!v) {
471
515
  throw new Error("AuthOwl hooks must be used inside <AuthOwlProvider>");
472
516
  }
@@ -501,7 +545,7 @@ function usePublicConfig() {
501
545
  }
502
546
  function useSession() {
503
547
  const client = useAuthClient();
504
- return React5.useSyncExternalStore(
548
+ return React6.useSyncExternalStore(
505
549
  client.sessionStore.subscribe,
506
550
  client.sessionStore.getSnapshot,
507
551
  client.sessionStore.getSnapshot
@@ -531,16 +575,16 @@ function useAuth() {
531
575
  }
532
576
  function useOrganization() {
533
577
  const client = useAuthClient();
534
- const apiRef = React5.useRef(client.organization);
578
+ const apiRef = React6.useRef(client.organization);
535
579
  apiRef.current = client.organization;
536
580
  const { data, isPending } = useSession();
537
581
  const membership = data?.session?.membership ?? null;
538
582
  const activeOrganizationId = data?.session?.activeOrganizationId ?? null;
539
583
  const identity = data?.user?.id ?? null;
540
- const [organization, setOrganization] = React5.useState(null);
541
- const [orgLoaded, setOrgLoaded] = React5.useState(false);
542
- const requestRef = React5.useRef(0);
543
- React5.useEffect(() => {
584
+ const [organization, setOrganization] = React6.useState(null);
585
+ const [orgLoaded, setOrgLoaded] = React6.useState(false);
586
+ const requestRef = React6.useRef(0);
587
+ React6.useEffect(() => {
544
588
  const token = ++requestRef.current;
545
589
  setOrganization(null);
546
590
  setOrgLoaded(false);
@@ -564,7 +608,7 @@ function useOrganization() {
564
608
  requestRef.current += 1;
565
609
  };
566
610
  }, [identity, activeOrganizationId, isPending]);
567
- const bound = React5.useMemo(() => createMembershipHas(membership), [membership]);
611
+ const bound = React6.useMemo(() => createMembershipHas(membership), [membership]);
568
612
  return {
569
613
  organization,
570
614
  membership,
@@ -579,13 +623,13 @@ function useOrganization() {
579
623
  }
580
624
  function useInvitationRecipientHint() {
581
625
  const client = useAuthClient();
582
- const apiRef = React5.useRef(client.organization);
626
+ const apiRef = React6.useRef(client.organization);
583
627
  apiRef.current = client.organization;
584
- const [result, setResult] = React5.useState({
628
+ const [result, setResult] = React6.useState({
585
629
  recipientHint: null,
586
630
  isLoaded: false
587
631
  });
588
- React5.useEffect(() => {
632
+ React6.useEffect(() => {
589
633
  let active = true;
590
634
  const claim = readInvitationClaim();
591
635
  if (!claim) {
@@ -616,18 +660,18 @@ function useInvitationRecipientHint() {
616
660
  }
617
661
  function useOrganizationInvitation() {
618
662
  const client = useAuthClient();
619
- const apiRef = React5.useRef(client.organization);
663
+ const apiRef = React6.useRef(client.organization);
620
664
  apiRef.current = client.organization;
621
665
  const { data, isPending } = useSession();
622
666
  const identity = data?.user?.id ?? null;
623
- const [claim, setClaim] = React5.useState(null);
624
- const [invitation, setInvitation] = React5.useState(null);
625
- const [status, setStatus] = React5.useState("idle");
626
- const requestRef = React5.useRef(0);
627
- React5.useEffect(() => {
667
+ const [claim, setClaim] = React6.useState(null);
668
+ const [invitation, setInvitation] = React6.useState(null);
669
+ const [status, setStatus] = React6.useState("idle");
670
+ const requestRef = React6.useRef(0);
671
+ React6.useEffect(() => {
628
672
  setClaim(readInvitationClaim());
629
673
  }, [identity]);
630
- React5.useEffect(() => {
674
+ React6.useEffect(() => {
631
675
  const token = ++requestRef.current;
632
676
  if (isPending || !claim) return;
633
677
  if (!identity) {
@@ -650,7 +694,7 @@ function useOrganizationInvitation() {
650
694
  requestRef.current += 1;
651
695
  };
652
696
  }, [claim, identity, isPending]);
653
- const accept = React5.useCallback(async () => {
697
+ const accept = React6.useCallback(async () => {
654
698
  const current = readInvitationClaim();
655
699
  if (!current) return false;
656
700
  setStatus("joining");
@@ -672,7 +716,7 @@ function useOrganizationInvitation() {
672
716
  } else setStatus("error");
673
717
  return false;
674
718
  }, []);
675
- const dismiss = React5.useCallback(() => {
719
+ const dismiss = React6.useCallback(() => {
676
720
  clearInvitationClaim();
677
721
  setClaim(null);
678
722
  setInvitation(null);
@@ -733,10 +777,10 @@ function useConsent() {
733
777
  const client = useAuthClient();
734
778
  const { user, isLoaded } = useUser();
735
779
  const userId = user?.id ?? null;
736
- const [status, setStatus] = React5.useState(null);
737
- const [isLoading, setIsLoading] = React5.useState(true);
738
- const reqRef = React5.useRef(0);
739
- const load = React5.useCallback(async () => {
780
+ const [status, setStatus] = React6.useState(null);
781
+ const [isLoading, setIsLoading] = React6.useState(true);
782
+ const reqRef = React6.useRef(0);
783
+ const load = React6.useCallback(async () => {
740
784
  const reqId = ++reqRef.current;
741
785
  setIsLoading(true);
742
786
  let next;
@@ -749,7 +793,7 @@ function useConsent() {
749
793
  setStatus(next);
750
794
  setIsLoading(false);
751
795
  }, [client]);
752
- React5.useEffect(() => {
796
+ React6.useEffect(() => {
753
797
  reqRef.current += 1;
754
798
  setStatus(null);
755
799
  if (!isLoaded) {
@@ -759,7 +803,7 @@ function useConsent() {
759
803
  void load();
760
804
  }, [load, isLoaded, userId]);
761
805
  const version = typeof status?.version === "number" && Number.isFinite(status.version) ? status.version : null;
762
- const accept = React5.useCallback(async () => {
806
+ const accept = React6.useCallback(async () => {
763
807
  if (version == null) return;
764
808
  try {
765
809
  await client.acceptConsent(version);
@@ -783,12 +827,12 @@ function useSignOut() {
783
827
  }
784
828
 
785
829
  // src/components/use-submit-action.ts
786
- import * as React6 from "react";
830
+ import * as React7 from "react";
787
831
  function useSubmitAction() {
788
- const [pending, setPending] = React6.useState(false);
789
- const [error, setError] = React6.useState(null);
832
+ const [pending, setPending] = React7.useState(false);
833
+ const [error, setError] = React7.useState(null);
790
834
  const toMessage = useServerError();
791
- const run = React6.useCallback(
835
+ const run = React7.useCallback(
792
836
  async (action, { failure, onSuccess, mapError, keepPendingOnSuccess }) => {
793
837
  setError(null);
794
838
  setPending(true);
@@ -882,15 +926,15 @@ function teamManagementCapabilities(member, dynamicRoles) {
882
926
  }
883
927
 
884
928
  // src/components/organization/use-organization-roles.ts
885
- import * as React7 from "react";
929
+ import * as React8 from "react";
886
930
  var BUILTIN_ROLES = ["owner", "admin", "member"];
887
931
  function useOrganizationRoles(organizationId) {
888
932
  const api = useAuthClient().organization;
889
- const apiRef = React7.useRef(api);
933
+ const apiRef = React8.useRef(api);
890
934
  apiRef.current = api;
891
- const [dynamicRoles, setDynamicRoles] = React7.useState([]);
892
- const requestRef = React7.useRef(0);
893
- React7.useEffect(() => {
935
+ const [dynamicRoles, setDynamicRoles] = React8.useState([]);
936
+ const requestRef = React8.useRef(0);
937
+ React8.useEffect(() => {
894
938
  const token = ++requestRef.current;
895
939
  setDynamicRoles([]);
896
940
  if (!organizationId) return;
@@ -906,7 +950,7 @@ function useOrganizationRoles(organizationId) {
906
950
  requestRef.current += 1;
907
951
  };
908
952
  }, [organizationId]);
909
- const roles = React7.useMemo(() => {
953
+ const roles = React8.useMemo(() => {
910
954
  const seen = /* @__PURE__ */ new Set();
911
955
  const out = [];
912
956
  for (const candidate of [...BUILTIN_ROLES, ...dynamicRoles.map((entry) => entry.role)]) {
@@ -947,6 +991,8 @@ export {
947
991
  useServerError,
948
992
  ModalSurface,
949
993
  InvitationPrompt,
994
+ useLastUsedSignInMethod,
995
+ useSignInMethodRecorder,
950
996
  AuthOwlProvider,
951
997
  useAuthOwlContext,
952
998
  useSubmitAction,