@passflow/react 0.2.8 → 0.3.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.js +4 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +655 -6
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/flow/passflow/index.d.ts.map +1 -1
- package/dist/src/components/flow/two-factor-verify/index.d.ts +1 -0
- package/dist/src/components/flow/two-factor-verify/index.d.ts.map +1 -1
- package/dist/src/components/form/cli-browser-auth/index.d.ts +2 -0
- package/dist/src/components/form/cli-browser-auth/index.d.ts.map +1 -0
- package/dist/src/components/form/cli-qr-auth/index.d.ts +2 -0
- package/dist/src/components/form/cli-qr-auth/index.d.ts.map +1 -0
- package/dist/src/components/form/index.d.ts +3 -0
- package/dist/src/components/form/index.d.ts.map +1 -1
- package/dist/src/components/form/two-factor-challenge/index.d.ts +10 -0
- package/dist/src/components/form/two-factor-challenge/index.d.ts.map +1 -0
- package/dist/src/components/form/two-factor-challenge/method-selector.d.ts +12 -0
- package/dist/src/components/form/two-factor-challenge/method-selector.d.ts.map +1 -0
- package/dist/src/components/form/two-factor-challenge/otp-input.d.ts +12 -0
- package/dist/src/components/form/two-factor-challenge/otp-input.d.ts.map +1 -0
- package/dist/src/context/auth-context.d.ts +10 -1
- package/dist/src/context/auth-context.d.ts.map +1 -1
- package/dist/src/context/router-context.d.ts +6 -0
- package/dist/src/context/router-context.d.ts.map +1 -1
- package/dist/src/hooks/index.d.ts +4 -0
- package/dist/src/hooks/index.d.ts.map +1 -1
- package/dist/src/hooks/use-cli-auth.d.ts +9 -0
- package/dist/src/hooks/use-cli-auth.d.ts.map +1 -0
- package/dist/src/hooks/use-session-expired.d.ts +49 -0
- package/dist/src/hooks/use-session-expired.d.ts.map +1 -0
- package/dist/src/hooks/use-two-factor-challenge.d.ts +16 -0
- package/dist/src/hooks/use-two-factor-challenge.d.ts.map +1 -0
- package/dist/src/hooks/use-two-factor-methods.d.ts +14 -0
- package/dist/src/hooks/use-two-factor-methods.d.ts.map +1 -0
- package/dist/src/types/index.d.ts +18 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -2
package/dist/index.es.js
CHANGED
|
@@ -6,6 +6,8 @@ import clsx from 'clsx';
|
|
|
6
6
|
import { twMerge } from 'tailwind-merge';
|
|
7
7
|
import * as React from 'react';
|
|
8
8
|
import { useState, useEffect, forwardRef, createContext, useCallback, useContext, useRef, useLayoutEffect, useMemo, useReducer } from 'react';
|
|
9
|
+
import { PassflowEvent, parseToken, Passflow } from '@passflow/core';
|
|
10
|
+
export * from '@passflow/core';
|
|
9
11
|
import queryString from 'query-string';
|
|
10
12
|
import { getCountryForTimezone } from 'countries-and-timezones';
|
|
11
13
|
import { usePhoneInput, defaultCountries, parseCountry, FlagImage } from 'react-international-phone';
|
|
@@ -16,11 +18,9 @@ import { HelmetProvider, Helmet } from 'react-helmet-async';
|
|
|
16
18
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
17
19
|
import { phone as phone$1 } from 'phone';
|
|
18
20
|
import { useForm, Controller } from 'react-hook-form';
|
|
19
|
-
import { parseToken, Passflow } from '@passflow/core';
|
|
20
|
-
export * from '@passflow/core';
|
|
21
21
|
import 'react-dom';
|
|
22
22
|
|
|
23
|
-
const version = "0.
|
|
23
|
+
const version = "0.3.0";
|
|
24
24
|
|
|
25
25
|
window.passflowReactAppVersion = () => {
|
|
26
26
|
console.log(`App Version: ${version}`);
|
|
@@ -769,6 +769,12 @@ const routes = {
|
|
|
769
769
|
},
|
|
770
770
|
two_factor_setup_magic_link: {
|
|
771
771
|
path: "/two-factor-setup-magic-link/:token"
|
|
772
|
+
},
|
|
773
|
+
cli_browser: {
|
|
774
|
+
path: "/cli/browser/:sessionId"
|
|
775
|
+
},
|
|
776
|
+
cli_qr: {
|
|
777
|
+
path: "/cli/auth/:sessionId"
|
|
772
778
|
}
|
|
773
779
|
};
|
|
774
780
|
|
|
@@ -787,9 +793,27 @@ const NavigationContext$1 = createContext({
|
|
|
787
793
|
});
|
|
788
794
|
|
|
789
795
|
const AuthContext = createContext(void 0);
|
|
790
|
-
const AuthProvider = ({ children }) => {
|
|
796
|
+
const AuthProvider = ({ children, onSessionExpired }) => {
|
|
791
797
|
const passflow = usePassflow();
|
|
792
798
|
const [isLoading, setIsLoading] = useState(false);
|
|
799
|
+
const [isSessionExpired, setIsSessionExpired] = useState(false);
|
|
800
|
+
useEffect(() => {
|
|
801
|
+
const subscriber = {
|
|
802
|
+
onAuthChange: (eventType, payload) => {
|
|
803
|
+
if (eventType === PassflowEvent.SessionExpired) {
|
|
804
|
+
const reason = payload?.reason ?? "refresh_failed";
|
|
805
|
+
setIsSessionExpired(true);
|
|
806
|
+
onSessionExpired?.(reason);
|
|
807
|
+
} else if (eventType === PassflowEvent.SignIn || eventType === PassflowEvent.Register) {
|
|
808
|
+
setIsSessionExpired(false);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
passflow.subscribe(subscriber, [PassflowEvent.SessionExpired, PassflowEvent.SignIn, PassflowEvent.Register]);
|
|
813
|
+
return () => {
|
|
814
|
+
passflow.unsubscribe(subscriber);
|
|
815
|
+
};
|
|
816
|
+
}, [passflow, onSessionExpired]);
|
|
793
817
|
const isAuthenticated = useCallback(() => passflow.isAuthenticated(), [passflow]);
|
|
794
818
|
const getTokens = useCallback(
|
|
795
819
|
async (doRefresh) => {
|
|
@@ -819,6 +843,7 @@ const AuthProvider = ({ children }) => {
|
|
|
819
843
|
isAuthenticated,
|
|
820
844
|
logout,
|
|
821
845
|
isLoading,
|
|
846
|
+
isSessionExpired,
|
|
822
847
|
getTokens
|
|
823
848
|
};
|
|
824
849
|
return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children });
|
|
@@ -1789,6 +1814,281 @@ const useTwoFactorSetupMagicLink = (token) => {
|
|
|
1789
1814
|
};
|
|
1790
1815
|
};
|
|
1791
1816
|
|
|
1817
|
+
const useTwoFactorChallenge = () => {
|
|
1818
|
+
const passflow = usePassflow();
|
|
1819
|
+
const [challenge, setChallenge] = useState(null);
|
|
1820
|
+
const [selectedMethod, setSelectedMethod] = useState(null);
|
|
1821
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
1822
|
+
const [error, setError] = useState(null);
|
|
1823
|
+
const requestChallenge = useCallback(
|
|
1824
|
+
async (firstFactorMethod) => {
|
|
1825
|
+
setIsLoading(true);
|
|
1826
|
+
setError(null);
|
|
1827
|
+
try {
|
|
1828
|
+
const response = await passflow.twoFactor.requestChallenge({
|
|
1829
|
+
first_factor_method: firstFactorMethod
|
|
1830
|
+
});
|
|
1831
|
+
setChallenge(response);
|
|
1832
|
+
setSelectedMethod(response.method);
|
|
1833
|
+
} catch (e) {
|
|
1834
|
+
setError(e);
|
|
1835
|
+
setChallenge(null);
|
|
1836
|
+
} finally {
|
|
1837
|
+
setIsLoading(false);
|
|
1838
|
+
}
|
|
1839
|
+
},
|
|
1840
|
+
[passflow]
|
|
1841
|
+
);
|
|
1842
|
+
const verify = useCallback(
|
|
1843
|
+
async (response, trustDevice = false) => {
|
|
1844
|
+
if (!challenge?.challenge_id) {
|
|
1845
|
+
setError(new Error("No active challenge session"));
|
|
1846
|
+
return null;
|
|
1847
|
+
}
|
|
1848
|
+
setIsLoading(true);
|
|
1849
|
+
setError(null);
|
|
1850
|
+
try {
|
|
1851
|
+
const result = await passflow.twoFactor.verifyV2({
|
|
1852
|
+
challenge_id: challenge.challenge_id,
|
|
1853
|
+
method: selectedMethod || challenge.method,
|
|
1854
|
+
response,
|
|
1855
|
+
trust_device: trustDevice
|
|
1856
|
+
});
|
|
1857
|
+
return result;
|
|
1858
|
+
} catch (e) {
|
|
1859
|
+
setError(e);
|
|
1860
|
+
return null;
|
|
1861
|
+
} finally {
|
|
1862
|
+
setIsLoading(false);
|
|
1863
|
+
}
|
|
1864
|
+
},
|
|
1865
|
+
[passflow, challenge, selectedMethod]
|
|
1866
|
+
);
|
|
1867
|
+
const switchMethod = useCallback(
|
|
1868
|
+
async (method) => {
|
|
1869
|
+
if (!challenge?.challenge_id) {
|
|
1870
|
+
setError(new Error("No active challenge session"));
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
setIsLoading(true);
|
|
1874
|
+
setError(null);
|
|
1875
|
+
try {
|
|
1876
|
+
const response = await passflow.twoFactor.switchToAlternative({
|
|
1877
|
+
challenge_id: challenge.challenge_id,
|
|
1878
|
+
method
|
|
1879
|
+
});
|
|
1880
|
+
setChallenge(response);
|
|
1881
|
+
setSelectedMethod(method);
|
|
1882
|
+
} catch (e) {
|
|
1883
|
+
setError(e);
|
|
1884
|
+
} finally {
|
|
1885
|
+
setIsLoading(false);
|
|
1886
|
+
}
|
|
1887
|
+
},
|
|
1888
|
+
[passflow, challenge]
|
|
1889
|
+
);
|
|
1890
|
+
const reset = useCallback(() => {
|
|
1891
|
+
setChallenge(null);
|
|
1892
|
+
setSelectedMethod(null);
|
|
1893
|
+
setError(null);
|
|
1894
|
+
setIsLoading(false);
|
|
1895
|
+
}, []);
|
|
1896
|
+
return {
|
|
1897
|
+
challenge,
|
|
1898
|
+
isLoading,
|
|
1899
|
+
error,
|
|
1900
|
+
requestChallenge,
|
|
1901
|
+
verify,
|
|
1902
|
+
switchMethod,
|
|
1903
|
+
selectedMethod,
|
|
1904
|
+
reset
|
|
1905
|
+
};
|
|
1906
|
+
};
|
|
1907
|
+
|
|
1908
|
+
const useTwoFactorMethods = () => {
|
|
1909
|
+
const passflow = usePassflow();
|
|
1910
|
+
const [availableMethods, setAvailableMethods] = useState([]);
|
|
1911
|
+
const [registeredMethods, setRegisteredMethods] = useState([]);
|
|
1912
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
1913
|
+
const [error, setError] = useState(null);
|
|
1914
|
+
const refresh = useCallback(async () => {
|
|
1915
|
+
setIsLoading(true);
|
|
1916
|
+
setError(null);
|
|
1917
|
+
try {
|
|
1918
|
+
const methods = await passflow.twoFactor.getRegisteredMethods();
|
|
1919
|
+
setRegisteredMethods(methods);
|
|
1920
|
+
const available = methods.map((m) => m.method);
|
|
1921
|
+
setAvailableMethods(available);
|
|
1922
|
+
} catch (e) {
|
|
1923
|
+
setError(e);
|
|
1924
|
+
setRegisteredMethods([]);
|
|
1925
|
+
setAvailableMethods([]);
|
|
1926
|
+
} finally {
|
|
1927
|
+
setIsLoading(false);
|
|
1928
|
+
}
|
|
1929
|
+
}, [passflow]);
|
|
1930
|
+
const removeMethod = useCallback(
|
|
1931
|
+
async (methodId) => {
|
|
1932
|
+
setIsLoading(true);
|
|
1933
|
+
setError(null);
|
|
1934
|
+
try {
|
|
1935
|
+
await passflow.twoFactor.removeMethod?.(methodId);
|
|
1936
|
+
await refresh();
|
|
1937
|
+
} catch (e) {
|
|
1938
|
+
setError(e);
|
|
1939
|
+
} finally {
|
|
1940
|
+
setIsLoading(false);
|
|
1941
|
+
}
|
|
1942
|
+
},
|
|
1943
|
+
[passflow, refresh]
|
|
1944
|
+
);
|
|
1945
|
+
return {
|
|
1946
|
+
availableMethods,
|
|
1947
|
+
registeredMethods,
|
|
1948
|
+
isLoading,
|
|
1949
|
+
error,
|
|
1950
|
+
refresh,
|
|
1951
|
+
removeMethod
|
|
1952
|
+
};
|
|
1953
|
+
};
|
|
1954
|
+
|
|
1955
|
+
function useSessionExpired(options) {
|
|
1956
|
+
const passflow = usePassflow();
|
|
1957
|
+
const [isSessionExpired, setIsSessionExpired] = useState(false);
|
|
1958
|
+
const [expiredReason, setExpiredReason] = useState(null);
|
|
1959
|
+
useEffect(() => {
|
|
1960
|
+
const subscriber = {
|
|
1961
|
+
onAuthChange: (eventType, payload) => {
|
|
1962
|
+
if (eventType === PassflowEvent.SessionExpired) {
|
|
1963
|
+
const reason = payload?.reason ?? "refresh_failed";
|
|
1964
|
+
setIsSessionExpired(true);
|
|
1965
|
+
setExpiredReason(reason);
|
|
1966
|
+
options?.onSessionExpired?.(reason);
|
|
1967
|
+
} else if (eventType === PassflowEvent.SignIn || eventType === PassflowEvent.Register) {
|
|
1968
|
+
setIsSessionExpired(false);
|
|
1969
|
+
setExpiredReason(null);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
passflow.subscribe(subscriber, [PassflowEvent.SessionExpired, PassflowEvent.SignIn, PassflowEvent.Register]);
|
|
1974
|
+
return () => {
|
|
1975
|
+
passflow.unsubscribe(subscriber);
|
|
1976
|
+
};
|
|
1977
|
+
}, [passflow, options?.onSessionExpired]);
|
|
1978
|
+
const resetSessionExpired = () => {
|
|
1979
|
+
setIsSessionExpired(false);
|
|
1980
|
+
setExpiredReason(null);
|
|
1981
|
+
};
|
|
1982
|
+
return {
|
|
1983
|
+
isSessionExpired,
|
|
1984
|
+
expiredReason,
|
|
1985
|
+
resetSessionExpired
|
|
1986
|
+
};
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
const useCLIAuth = (sessionId) => {
|
|
1990
|
+
const [state, setState] = useState("loading");
|
|
1991
|
+
const [error, setError] = useState(null);
|
|
1992
|
+
const [expiresAt, setExpiresAt] = useState(null);
|
|
1993
|
+
const [challenge, setChallenge] = useState(null);
|
|
1994
|
+
const serverUrl = window.location.origin;
|
|
1995
|
+
const fetchStatus = useCallback(async () => {
|
|
1996
|
+
try {
|
|
1997
|
+
const response = await fetch(`${serverUrl}/cli/auth/status/${sessionId}`);
|
|
1998
|
+
if (!response.ok) {
|
|
1999
|
+
throw new Error(`Failed to fetch CLI auth status: ${response.statusText}`);
|
|
2000
|
+
}
|
|
2001
|
+
const data = await response.json();
|
|
2002
|
+
setExpiresAt(data.expires_at || null);
|
|
2003
|
+
switch (data.status) {
|
|
2004
|
+
case "pending":
|
|
2005
|
+
setState("pending");
|
|
2006
|
+
setChallenge(data.challenge || null);
|
|
2007
|
+
break;
|
|
2008
|
+
case "completed":
|
|
2009
|
+
setState("completed");
|
|
2010
|
+
break;
|
|
2011
|
+
case "expired":
|
|
2012
|
+
setState("expired");
|
|
2013
|
+
setError("This authentication session has expired. Please start a new one from your terminal.");
|
|
2014
|
+
break;
|
|
2015
|
+
case "failed":
|
|
2016
|
+
setState("error");
|
|
2017
|
+
setError(data.error || "Authentication failed");
|
|
2018
|
+
break;
|
|
2019
|
+
}
|
|
2020
|
+
} catch (err) {
|
|
2021
|
+
setState("error");
|
|
2022
|
+
setError(err instanceof Error ? err.message : "Failed to load authentication status");
|
|
2023
|
+
}
|
|
2024
|
+
}, [sessionId, serverUrl]);
|
|
2025
|
+
const authenticate = useCallback(async () => {
|
|
2026
|
+
if (!challenge) {
|
|
2027
|
+
setError("No challenge available for authentication");
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
2030
|
+
setState("authenticating");
|
|
2031
|
+
setError(null);
|
|
2032
|
+
try {
|
|
2033
|
+
const { startAuthentication } = await import('@simplewebauthn/browser');
|
|
2034
|
+
const optionsJSON = challenge.publicKey || challenge;
|
|
2035
|
+
const webauthnResponse = await startAuthentication({ optionsJSON });
|
|
2036
|
+
const completeResponse = await fetch(`${serverUrl}/auth/passkey/authenticate/complete`, {
|
|
2037
|
+
method: "POST",
|
|
2038
|
+
headers: {
|
|
2039
|
+
"Content-Type": "application/json"
|
|
2040
|
+
},
|
|
2041
|
+
body: JSON.stringify(webauthnResponse)
|
|
2042
|
+
});
|
|
2043
|
+
if (!completeResponse.ok) {
|
|
2044
|
+
throw new Error(`Passkey authentication failed: ${completeResponse.statusText}`);
|
|
2045
|
+
}
|
|
2046
|
+
const authData = await completeResponse.json();
|
|
2047
|
+
if (!authData.access_token || !authData.refresh_token) {
|
|
2048
|
+
throw new Error("Invalid authentication response: missing tokens");
|
|
2049
|
+
}
|
|
2050
|
+
const cliCompleteRequest = {
|
|
2051
|
+
session_id: sessionId,
|
|
2052
|
+
access_token: authData.access_token,
|
|
2053
|
+
refresh_token: authData.refresh_token,
|
|
2054
|
+
user_id: authData.user_id,
|
|
2055
|
+
expires_in: authData.expires_in
|
|
2056
|
+
};
|
|
2057
|
+
const cliCompleteResponse = await fetch(`${serverUrl}/cli/auth/complete`, {
|
|
2058
|
+
method: "POST",
|
|
2059
|
+
headers: {
|
|
2060
|
+
"Content-Type": "application/json"
|
|
2061
|
+
},
|
|
2062
|
+
body: JSON.stringify(cliCompleteRequest)
|
|
2063
|
+
});
|
|
2064
|
+
if (!cliCompleteResponse.ok) {
|
|
2065
|
+
throw new Error(`CLI authentication completion failed: ${cliCompleteResponse.statusText}`);
|
|
2066
|
+
}
|
|
2067
|
+
setState("completed");
|
|
2068
|
+
} catch (err) {
|
|
2069
|
+
setState("error");
|
|
2070
|
+
if (err instanceof Error) {
|
|
2071
|
+
if (err.name === "NotAllowedError") {
|
|
2072
|
+
setError("Authentication was cancelled or not allowed");
|
|
2073
|
+
} else {
|
|
2074
|
+
setError(err.message);
|
|
2075
|
+
}
|
|
2076
|
+
} else {
|
|
2077
|
+
setError("Authentication failed");
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
}, [challenge, sessionId, serverUrl]);
|
|
2081
|
+
useEffect(() => {
|
|
2082
|
+
void fetchStatus();
|
|
2083
|
+
}, [fetchStatus]);
|
|
2084
|
+
return {
|
|
2085
|
+
authenticate,
|
|
2086
|
+
state,
|
|
2087
|
+
error,
|
|
2088
|
+
expiresAt
|
|
2089
|
+
};
|
|
2090
|
+
};
|
|
2091
|
+
|
|
1792
2092
|
const FieldPhone = ({ id, onChange, isError = false, className = "" }) => {
|
|
1793
2093
|
const [show, setShow] = useState(false);
|
|
1794
2094
|
const [filterValue, setFilterValue] = useState("");
|
|
@@ -2190,6 +2490,245 @@ const TwoFactorSetupFlow = ({
|
|
|
2190
2490
|
return /* @__PURE__ */ jsx(TwoFactorSetupForm, { onComplete: handleSetupComplete, onCancel: handleCancel });
|
|
2191
2491
|
};
|
|
2192
2492
|
|
|
2493
|
+
const methodLabels = {
|
|
2494
|
+
totp: "Authenticator App",
|
|
2495
|
+
email_otp: "Email Code",
|
|
2496
|
+
sms_otp: "SMS Code",
|
|
2497
|
+
passkey: "Passkey",
|
|
2498
|
+
recovery_codes: "Recovery Code",
|
|
2499
|
+
push_fcm: "Push Notification (FCM)",
|
|
2500
|
+
push_webpush: "Push Notification (Web)"
|
|
2501
|
+
};
|
|
2502
|
+
const methodIcons = {
|
|
2503
|
+
totp: "📱",
|
|
2504
|
+
email_otp: "✉️",
|
|
2505
|
+
sms_otp: "💬",
|
|
2506
|
+
passkey: "🔑",
|
|
2507
|
+
recovery_codes: "🔒",
|
|
2508
|
+
push_fcm: "🔔",
|
|
2509
|
+
push_webpush: "🔔"
|
|
2510
|
+
};
|
|
2511
|
+
const MethodSelector = ({
|
|
2512
|
+
availableMethods,
|
|
2513
|
+
currentMethod,
|
|
2514
|
+
onSelectMethod,
|
|
2515
|
+
isOpen,
|
|
2516
|
+
onClose
|
|
2517
|
+
}) => {
|
|
2518
|
+
const handleSelect = (method) => {
|
|
2519
|
+
onSelectMethod(method);
|
|
2520
|
+
onClose();
|
|
2521
|
+
};
|
|
2522
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
|
|
2523
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: "pf-dialog-overlay" }),
|
|
2524
|
+
/* @__PURE__ */ jsxs(DialogPrimitive.Content, { className: "pf-dialog-content pf-method-selector-dialog", children: [
|
|
2525
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Title, { className: "pf-dialog-title", children: "Choose Verification Method" }),
|
|
2526
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Description, { className: "pf-dialog-description", children: "Select an alternative method to verify your identity" }),
|
|
2527
|
+
/* @__PURE__ */ jsx("div", { className: "pf-method-selector-list", children: availableMethods.map((method) => /* @__PURE__ */ jsxs(
|
|
2528
|
+
"button",
|
|
2529
|
+
{
|
|
2530
|
+
type: "button",
|
|
2531
|
+
className: `pf-method-selector-item ${method === currentMethod ? "pf-method-selector-item-active" : ""}`,
|
|
2532
|
+
onClick: () => handleSelect(method),
|
|
2533
|
+
disabled: method === currentMethod,
|
|
2534
|
+
children: [
|
|
2535
|
+
/* @__PURE__ */ jsx("span", { className: "pf-method-icon", children: methodIcons[method] || "🔐" }),
|
|
2536
|
+
/* @__PURE__ */ jsx("span", { className: "pf-method-label", children: methodLabels[method] || method }),
|
|
2537
|
+
method === currentMethod && /* @__PURE__ */ jsx("span", { className: "pf-method-current-badge", children: "Current" })
|
|
2538
|
+
]
|
|
2539
|
+
},
|
|
2540
|
+
method
|
|
2541
|
+
)) }),
|
|
2542
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx("button", { type: "button", className: "pf-dialog-close", "aria-label": "Close", children: "×" }) })
|
|
2543
|
+
] })
|
|
2544
|
+
] }) });
|
|
2545
|
+
};
|
|
2546
|
+
|
|
2547
|
+
const OtpInputComponent = ({
|
|
2548
|
+
value,
|
|
2549
|
+
onChange,
|
|
2550
|
+
numInputs = 6,
|
|
2551
|
+
error,
|
|
2552
|
+
disabled = false,
|
|
2553
|
+
autoFocus = true
|
|
2554
|
+
}) => {
|
|
2555
|
+
const containerRef = useRef(null);
|
|
2556
|
+
useEffect(() => {
|
|
2557
|
+
if (autoFocus && containerRef.current) {
|
|
2558
|
+
const firstInput = containerRef.current.querySelector("input");
|
|
2559
|
+
if (firstInput) {
|
|
2560
|
+
firstInput.focus();
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
}, [autoFocus]);
|
|
2564
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "pf-otp-input-container", children: [
|
|
2565
|
+
/* @__PURE__ */ jsx(
|
|
2566
|
+
OtpInput,
|
|
2567
|
+
{
|
|
2568
|
+
value,
|
|
2569
|
+
onChange,
|
|
2570
|
+
numInputs,
|
|
2571
|
+
renderSeparator: /* @__PURE__ */ jsx("span", { className: "pf-otp-separator" }),
|
|
2572
|
+
renderInput: (props) => /* @__PURE__ */ jsx(
|
|
2573
|
+
"input",
|
|
2574
|
+
{
|
|
2575
|
+
...props,
|
|
2576
|
+
className: `pf-otp-input ${error ? "pf-otp-input-error" : ""} ${disabled ? "pf-otp-input-disabled" : ""}`,
|
|
2577
|
+
disabled
|
|
2578
|
+
}
|
|
2579
|
+
),
|
|
2580
|
+
inputType: "tel",
|
|
2581
|
+
shouldAutoFocus: autoFocus
|
|
2582
|
+
}
|
|
2583
|
+
),
|
|
2584
|
+
error && /* @__PURE__ */ jsx("div", { className: "pf-otp-error", children: error })
|
|
2585
|
+
] });
|
|
2586
|
+
};
|
|
2587
|
+
|
|
2588
|
+
const TwoFactorChallenge = ({
|
|
2589
|
+
firstFactorMethod,
|
|
2590
|
+
onSuccess,
|
|
2591
|
+
onError,
|
|
2592
|
+
trustDevice = false
|
|
2593
|
+
}) => {
|
|
2594
|
+
const { challenge, isLoading, error, requestChallenge, verify, switchMethod, selectedMethod } = useTwoFactorChallenge();
|
|
2595
|
+
const [otpValue, setOtpValue] = useState("");
|
|
2596
|
+
const [isMethodSelectorOpen, setIsMethodSelectorOpen] = useState(false);
|
|
2597
|
+
useEffect(() => {
|
|
2598
|
+
requestChallenge(firstFactorMethod);
|
|
2599
|
+
}, [requestChallenge, firstFactorMethod]);
|
|
2600
|
+
useEffect(() => {
|
|
2601
|
+
if (error && onError) {
|
|
2602
|
+
onError(error);
|
|
2603
|
+
}
|
|
2604
|
+
}, [error, onError]);
|
|
2605
|
+
const handleVerify = async () => {
|
|
2606
|
+
if (!otpValue) {
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
const result = await verify(otpValue, trustDevice);
|
|
2610
|
+
if (result) {
|
|
2611
|
+
onSuccess?.();
|
|
2612
|
+
}
|
|
2613
|
+
};
|
|
2614
|
+
const handleSwitchMethod = async (method) => {
|
|
2615
|
+
setOtpValue("");
|
|
2616
|
+
await switchMethod(method);
|
|
2617
|
+
};
|
|
2618
|
+
const handleOtpChange = (value) => {
|
|
2619
|
+
setOtpValue(value);
|
|
2620
|
+
if (value.length === 6) {
|
|
2621
|
+
setTimeout(() => {
|
|
2622
|
+
verify(value, trustDevice).then((result) => {
|
|
2623
|
+
if (result) {
|
|
2624
|
+
onSuccess?.();
|
|
2625
|
+
}
|
|
2626
|
+
});
|
|
2627
|
+
}, 100);
|
|
2628
|
+
}
|
|
2629
|
+
};
|
|
2630
|
+
if (!challenge) {
|
|
2631
|
+
return /* @__PURE__ */ jsx("div", { className: "pf-two-factor-challenge pf-loading", children: /* @__PURE__ */ jsx("p", { children: "Loading challenge..." }) });
|
|
2632
|
+
}
|
|
2633
|
+
const currentMethod = selectedMethod || challenge.method;
|
|
2634
|
+
const availableMethods = [challenge.method, ...challenge.alternative_methods || []];
|
|
2635
|
+
const renderChallengeInput = () => {
|
|
2636
|
+
switch (currentMethod) {
|
|
2637
|
+
case "totp":
|
|
2638
|
+
case "email_otp":
|
|
2639
|
+
case "sms_otp":
|
|
2640
|
+
return /* @__PURE__ */ jsxs("div", { className: "pf-challenge-input-wrapper", children: [
|
|
2641
|
+
/* @__PURE__ */ jsx(
|
|
2642
|
+
OtpInputComponent,
|
|
2643
|
+
{
|
|
2644
|
+
value: otpValue,
|
|
2645
|
+
onChange: handleOtpChange,
|
|
2646
|
+
numInputs: 6,
|
|
2647
|
+
error: error?.message,
|
|
2648
|
+
disabled: isLoading,
|
|
2649
|
+
autoFocus: true
|
|
2650
|
+
}
|
|
2651
|
+
),
|
|
2652
|
+
currentMethod === "email_otp" && challenge.code_sent_to && /* @__PURE__ */ jsxs("p", { className: "pf-challenge-hint", children: [
|
|
2653
|
+
"Code sent to ",
|
|
2654
|
+
challenge.code_sent_to
|
|
2655
|
+
] }),
|
|
2656
|
+
currentMethod === "sms_otp" && challenge.code_sent_to && /* @__PURE__ */ jsxs("p", { className: "pf-challenge-hint", children: [
|
|
2657
|
+
"Code sent to ",
|
|
2658
|
+
challenge.code_sent_to
|
|
2659
|
+
] }),
|
|
2660
|
+
/* @__PURE__ */ jsx(
|
|
2661
|
+
"button",
|
|
2662
|
+
{
|
|
2663
|
+
type: "button",
|
|
2664
|
+
onClick: handleVerify,
|
|
2665
|
+
disabled: isLoading || otpValue.length !== 6,
|
|
2666
|
+
className: "pf-button pf-button-primary",
|
|
2667
|
+
children: isLoading ? "Verifying..." : "Verify"
|
|
2668
|
+
}
|
|
2669
|
+
)
|
|
2670
|
+
] });
|
|
2671
|
+
case "passkey":
|
|
2672
|
+
return /* @__PURE__ */ jsx("div", { className: "pf-challenge-input-wrapper", children: /* @__PURE__ */ jsx("button", { type: "button", onClick: handleVerify, disabled: isLoading, className: "pf-button pf-button-primary", children: isLoading ? "Verifying..." : "Use Passkey" }) });
|
|
2673
|
+
case "recovery_codes":
|
|
2674
|
+
return /* @__PURE__ */ jsxs("div", { className: "pf-challenge-input-wrapper", children: [
|
|
2675
|
+
/* @__PURE__ */ jsx(
|
|
2676
|
+
"input",
|
|
2677
|
+
{
|
|
2678
|
+
type: "text",
|
|
2679
|
+
value: otpValue,
|
|
2680
|
+
onChange: (e) => setOtpValue(e.target.value),
|
|
2681
|
+
placeholder: "Enter recovery code",
|
|
2682
|
+
disabled: isLoading,
|
|
2683
|
+
className: "pf-input"
|
|
2684
|
+
}
|
|
2685
|
+
),
|
|
2686
|
+
/* @__PURE__ */ jsx(
|
|
2687
|
+
"button",
|
|
2688
|
+
{
|
|
2689
|
+
type: "button",
|
|
2690
|
+
onClick: handleVerify,
|
|
2691
|
+
disabled: isLoading || !otpValue,
|
|
2692
|
+
className: "pf-button pf-button-primary",
|
|
2693
|
+
children: isLoading ? "Verifying..." : "Verify"
|
|
2694
|
+
}
|
|
2695
|
+
)
|
|
2696
|
+
] });
|
|
2697
|
+
default:
|
|
2698
|
+
return /* @__PURE__ */ jsxs("p", { children: [
|
|
2699
|
+
"Unsupported method: ",
|
|
2700
|
+
currentMethod
|
|
2701
|
+
] });
|
|
2702
|
+
}
|
|
2703
|
+
};
|
|
2704
|
+
return /* @__PURE__ */ jsxs("div", { className: "pf-two-factor-challenge", children: [
|
|
2705
|
+
/* @__PURE__ */ jsxs("div", { className: "pf-challenge-method-info", children: [
|
|
2706
|
+
/* @__PURE__ */ jsx("h3", { children: "Two-Factor Authentication" }),
|
|
2707
|
+
/* @__PURE__ */ jsx("p", { children: "Enter the verification code" })
|
|
2708
|
+
] }),
|
|
2709
|
+
renderChallengeInput(),
|
|
2710
|
+
availableMethods.length > 1 && /* @__PURE__ */ jsx(
|
|
2711
|
+
"button",
|
|
2712
|
+
{
|
|
2713
|
+
type: "button",
|
|
2714
|
+
onClick: () => setIsMethodSelectorOpen(true),
|
|
2715
|
+
className: "pf-button pf-button-secondary pf-button-switch-method",
|
|
2716
|
+
children: "Use different method"
|
|
2717
|
+
}
|
|
2718
|
+
),
|
|
2719
|
+
/* @__PURE__ */ jsx(
|
|
2720
|
+
MethodSelector,
|
|
2721
|
+
{
|
|
2722
|
+
availableMethods,
|
|
2723
|
+
currentMethod,
|
|
2724
|
+
onSelectMethod: handleSwitchMethod,
|
|
2725
|
+
isOpen: isMethodSelectorOpen,
|
|
2726
|
+
onClose: () => setIsMethodSelectorOpen(false)
|
|
2727
|
+
}
|
|
2728
|
+
)
|
|
2729
|
+
] });
|
|
2730
|
+
};
|
|
2731
|
+
|
|
2193
2732
|
const TwoFactorVerifyForm = ({
|
|
2194
2733
|
onSuccess,
|
|
2195
2734
|
onUseRecovery,
|
|
@@ -2477,7 +3016,8 @@ const TwoFactorRecoveryForm = ({
|
|
|
2477
3016
|
const TwoFactorVerifyFlow = ({
|
|
2478
3017
|
successAuthRedirect,
|
|
2479
3018
|
signInPath = routes.signin.path,
|
|
2480
|
-
twoFactorSetupPath = routes.two_factor_setup?.path
|
|
3019
|
+
twoFactorSetupPath = routes.two_factor_setup?.path,
|
|
3020
|
+
useV2Flow = false
|
|
2481
3021
|
}) => {
|
|
2482
3022
|
const [mode, setMode] = useState("verify");
|
|
2483
3023
|
const [shouldBlockRender, setShouldBlockRender] = useState(false);
|
|
@@ -2530,6 +3070,9 @@ const TwoFactorVerifyFlow = ({
|
|
|
2530
3070
|
if (!passflow.isTwoFactorVerificationRequired() && TwoFactorLoopPrevention.canRedirect()) {
|
|
2531
3071
|
return null;
|
|
2532
3072
|
}
|
|
3073
|
+
if (useV2Flow) {
|
|
3074
|
+
return /* @__PURE__ */ jsx(TwoFactorChallenge, { onSuccess: handleSuccess });
|
|
3075
|
+
}
|
|
2533
3076
|
return /* @__PURE__ */ jsx(Fragment, { children: mode === "verify" ? /* @__PURE__ */ jsx(
|
|
2534
3077
|
TwoFactorVerifyForm,
|
|
2535
3078
|
{
|
|
@@ -6031,6 +6574,110 @@ const index = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
|
6031
6574
|
useRoutes
|
|
6032
6575
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
6033
6576
|
|
|
6577
|
+
const CLIBrowserAuthForm = () => {
|
|
6578
|
+
const { sessionId } = useParams();
|
|
6579
|
+
if (!sessionId) {
|
|
6580
|
+
throw new Error("Session ID is required");
|
|
6581
|
+
}
|
|
6582
|
+
const { authenticate, state, error } = useCLIAuth(sessionId);
|
|
6583
|
+
const handleAuthenticate = async () => {
|
|
6584
|
+
await authenticate();
|
|
6585
|
+
};
|
|
6586
|
+
return /* @__PURE__ */ jsx(Wrapper, { title: "CLI Authentication", subtitle: "Authenticate your CLI tool", className: "passflow-cli-auth-wrapper", children: /* @__PURE__ */ jsxs("div", { className: "passflow-form", children: [
|
|
6587
|
+
state === "loading" && /* @__PURE__ */ jsx("div", { className: "passflow-form-container", children: /* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "Loading authentication session..." }) }),
|
|
6588
|
+
state === "pending" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6589
|
+
/* @__PURE__ */ jsx("div", { className: "passflow-form-container", children: /* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "Click the button below to authenticate with your passkey." }) }),
|
|
6590
|
+
/* @__PURE__ */ jsxs(
|
|
6591
|
+
Button,
|
|
6592
|
+
{
|
|
6593
|
+
size: "big",
|
|
6594
|
+
variant: "dark",
|
|
6595
|
+
type: "button",
|
|
6596
|
+
className: "passflow-button-passkey",
|
|
6597
|
+
withIcon: true,
|
|
6598
|
+
onClick: handleAuthenticate,
|
|
6599
|
+
children: [
|
|
6600
|
+
/* @__PURE__ */ jsx(Icon, { id: "key", size: "small", type: "general", className: "icon-white passflow-button-passkey-icon" }),
|
|
6601
|
+
"Authenticate with Passkey"
|
|
6602
|
+
]
|
|
6603
|
+
}
|
|
6604
|
+
)
|
|
6605
|
+
] }),
|
|
6606
|
+
state === "authenticating" && /* @__PURE__ */ jsx("div", { className: "passflow-form-container", children: /* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "Authenticating..." }) }),
|
|
6607
|
+
state === "completed" && /* @__PURE__ */ jsxs("div", { className: "passflow-form-container", children: [
|
|
6608
|
+
/* @__PURE__ */ jsxs("div", { className: "passflow-form-success", children: [
|
|
6609
|
+
/* @__PURE__ */ jsx(Icon, { size: "small", id: "check", type: "general", className: "icon-success" }),
|
|
6610
|
+
/* @__PURE__ */ jsx("p", { className: "passflow-form-success-text", children: "Authentication successful!" })
|
|
6611
|
+
] }),
|
|
6612
|
+
/* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "You can close this window and return to your terminal." })
|
|
6613
|
+
] }),
|
|
6614
|
+
state === "expired" && /* @__PURE__ */ jsxs("div", { className: "passflow-form-container", children: [
|
|
6615
|
+
/* @__PURE__ */ jsxs("div", { className: "passflow-form-error", children: [
|
|
6616
|
+
/* @__PURE__ */ jsx(Icon, { size: "small", id: "warning", type: "general", className: "icon-warning" }),
|
|
6617
|
+
/* @__PURE__ */ jsx("span", { className: "passflow-form-error-text", children: "Session Expired" })
|
|
6618
|
+
] }),
|
|
6619
|
+
/* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "This authentication session has expired. Please start a new one from your terminal." })
|
|
6620
|
+
] }),
|
|
6621
|
+
state === "error" && error && /* @__PURE__ */ jsx("div", { className: "passflow-form-container", children: /* @__PURE__ */ jsxs("div", { className: "passflow-form-error", children: [
|
|
6622
|
+
/* @__PURE__ */ jsx(Icon, { size: "small", id: "warning", type: "general", className: "icon-warning" }),
|
|
6623
|
+
/* @__PURE__ */ jsx("span", { className: "passflow-form-error-text", children: error })
|
|
6624
|
+
] }) })
|
|
6625
|
+
] }) });
|
|
6626
|
+
};
|
|
6627
|
+
const CLIBrowserAuth = withError(CLIBrowserAuthForm, ErrorComponent);
|
|
6628
|
+
|
|
6629
|
+
const CLIQRAuthForm = () => {
|
|
6630
|
+
const { sessionId } = useParams();
|
|
6631
|
+
if (!sessionId) {
|
|
6632
|
+
throw new Error("Session ID is required");
|
|
6633
|
+
}
|
|
6634
|
+
const { authenticate, state, error } = useCLIAuth(sessionId);
|
|
6635
|
+
const handleAuthenticate = async () => {
|
|
6636
|
+
await authenticate();
|
|
6637
|
+
};
|
|
6638
|
+
return /* @__PURE__ */ jsx(Wrapper, { title: "CLI Authentication", subtitle: "Authenticate for your CLI application", className: "passflow-cli-auth-wrapper", children: /* @__PURE__ */ jsxs("div", { className: "passflow-form", children: [
|
|
6639
|
+
state === "loading" && /* @__PURE__ */ jsx("div", { className: "passflow-form-container", children: /* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "Loading authentication session..." }) }),
|
|
6640
|
+
state === "pending" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6641
|
+
/* @__PURE__ */ jsx("div", { className: "passflow-form-container", children: /* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "Tap the button below to authenticate with your passkey." }) }),
|
|
6642
|
+
/* @__PURE__ */ jsxs(
|
|
6643
|
+
Button,
|
|
6644
|
+
{
|
|
6645
|
+
size: "big",
|
|
6646
|
+
variant: "dark",
|
|
6647
|
+
type: "button",
|
|
6648
|
+
className: "passflow-button-passkey",
|
|
6649
|
+
withIcon: true,
|
|
6650
|
+
onClick: handleAuthenticate,
|
|
6651
|
+
children: [
|
|
6652
|
+
/* @__PURE__ */ jsx(Icon, { id: "key", size: "small", type: "general", className: "icon-white passflow-button-passkey-icon" }),
|
|
6653
|
+
"Authenticate with Passkey"
|
|
6654
|
+
]
|
|
6655
|
+
}
|
|
6656
|
+
)
|
|
6657
|
+
] }),
|
|
6658
|
+
state === "authenticating" && /* @__PURE__ */ jsx("div", { className: "passflow-form-container", children: /* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "Authenticating..." }) }),
|
|
6659
|
+
state === "completed" && /* @__PURE__ */ jsxs("div", { className: "passflow-form-container", children: [
|
|
6660
|
+
/* @__PURE__ */ jsxs("div", { className: "passflow-form-success", children: [
|
|
6661
|
+
/* @__PURE__ */ jsx(Icon, { size: "small", id: "check", type: "general", className: "icon-success" }),
|
|
6662
|
+
/* @__PURE__ */ jsx("p", { className: "passflow-form-success-text", children: "Authentication successful!" })
|
|
6663
|
+
] }),
|
|
6664
|
+
/* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "You can close this app and return to your terminal." })
|
|
6665
|
+
] }),
|
|
6666
|
+
state === "expired" && /* @__PURE__ */ jsxs("div", { className: "passflow-form-container", children: [
|
|
6667
|
+
/* @__PURE__ */ jsxs("div", { className: "passflow-form-error", children: [
|
|
6668
|
+
/* @__PURE__ */ jsx(Icon, { size: "small", id: "warning", type: "general", className: "icon-warning" }),
|
|
6669
|
+
/* @__PURE__ */ jsx("span", { className: "passflow-form-error-text", children: "Session Expired" })
|
|
6670
|
+
] }),
|
|
6671
|
+
/* @__PURE__ */ jsx("p", { className: "passflow-form-text", children: "This authentication session has expired. Please start a new one from your terminal." })
|
|
6672
|
+
] }),
|
|
6673
|
+
state === "error" && error && /* @__PURE__ */ jsx("div", { className: "passflow-form-container", children: /* @__PURE__ */ jsxs("div", { className: "passflow-form-error", children: [
|
|
6674
|
+
/* @__PURE__ */ jsx(Icon, { size: "small", id: "warning", type: "general", className: "icon-warning" }),
|
|
6675
|
+
/* @__PURE__ */ jsx("span", { className: "passflow-form-error-text", children: error })
|
|
6676
|
+
] }) })
|
|
6677
|
+
] }) });
|
|
6678
|
+
};
|
|
6679
|
+
const CLIQRAuth = withError(CLIQRAuthForm, ErrorComponent);
|
|
6680
|
+
|
|
6034
6681
|
const normalizePathPrefix = (path) => {
|
|
6035
6682
|
if (!path) return "";
|
|
6036
6683
|
const pathReplace = path.replace(/^\/+|\/+$/g, "");
|
|
@@ -6211,6 +6858,8 @@ const PassflowWrapper = ({
|
|
|
6211
6858
|
)
|
|
6212
6859
|
}
|
|
6213
6860
|
),
|
|
6861
|
+
/* @__PURE__ */ jsx(Route, { path: routes.cli_browser.path, element: /* @__PURE__ */ jsx(CLIBrowserAuth, {}) }),
|
|
6862
|
+
/* @__PURE__ */ jsx(Route, { path: routes.cli_qr.path, element: /* @__PURE__ */ jsx(CLIQRAuth, {}) }),
|
|
6214
6863
|
/* @__PURE__ */ jsx(
|
|
6215
6864
|
Route,
|
|
6216
6865
|
{
|
|
@@ -6408,5 +7057,5 @@ const PassflowProvider = ({
|
|
|
6408
7057
|
return /* @__PURE__ */ jsx(PassflowContext.Provider, { value: passflowValue, children: /* @__PURE__ */ jsx(NavigationContext$1.Provider, { value: navigationValue, children: /* @__PURE__ */ jsx(AuthProvider, { children }) }) });
|
|
6409
7058
|
};
|
|
6410
7059
|
|
|
6411
|
-
export { Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FieldPassword, FieldPhone, FieldText, ForgotPassword, ForgotPasswordSuccess, Icon, InvitationJoin, Link, PassflowFlow, PassflowProvider, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProvidersBox, ResetPassword, SignIn, SignInForm, SignUp, SignUpForm, Switch, TwoFactorRecoveryForm, TwoFactorSetupForm, TwoFactorSetupMagicLinkFlow, TwoFactorVerifyForm, VerifyChallengeMagicLink, VerifyChallengeOTP, Wrapper, useAppSettings, useAuth, useAuthCloudRedirect, useForgotPassword, useJoinInvite, useLogout, useNavigation, useOutsideClick, usePassflow, usePasswordlessComplete, useProvider, useResetPassword, useSignIn, useSignUp, useTwoFactorManage, useTwoFactorSetup, useTwoFactorSetupMagicLink, useTwoFactorStatus, useTwoFactorVerify, useUserPasskeys };
|
|
7060
|
+
export { Button, CLIBrowserAuth, CLIQRAuth, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FieldPassword, FieldPhone, FieldText, ForgotPassword, ForgotPasswordSuccess, Icon, InvitationJoin, Link, PassflowFlow, PassflowProvider, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProvidersBox, ResetPassword, SignIn, SignInForm, SignUp, SignUpForm, Switch, TwoFactorChallenge, TwoFactorRecoveryForm, TwoFactorSetupForm, TwoFactorSetupMagicLinkFlow, TwoFactorVerifyForm, VerifyChallengeMagicLink, VerifyChallengeOTP, Wrapper, useAppSettings, useAuth, useAuthCloudRedirect, useCLIAuth, useForgotPassword, useJoinInvite, useLogout, useNavigation, useOutsideClick, usePassflow, usePasswordlessComplete, useProvider, useResetPassword, useSessionExpired, useSignIn, useSignUp, useTwoFactorChallenge, useTwoFactorManage, useTwoFactorMethods, useTwoFactorSetup, useTwoFactorSetupMagicLink, useTwoFactorStatus, useTwoFactorVerify, useUserPasskeys };
|
|
6412
7061
|
//# sourceMappingURL=index.es.js.map
|