rswag-online/frontend/vendor/@encryptid/sdk/ui/react/index.js

161 lines
5.1 KiB
JavaScript

import {
EncryptIDClient
} from "../../index-7egxprg9.js";
import"../../index-2cp5044h.js";
// src/ui/react/EncryptIDProvider.tsx
import React, { createContext, useContext, useEffect, useState, useCallback } from "react";
var EncryptIDContext = createContext(null);
var TOKEN_KEY = "encryptid_token";
function EncryptIDProvider({ children, serverUrl }) {
const [client] = useState(() => new EncryptIDClient(serverUrl));
const [token, setToken] = useState(null);
const [claims, setClaims] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const stored = localStorage.getItem(TOKEN_KEY);
if (stored) {
client.verifySession(stored).then((res) => {
if (res.valid) {
setToken(stored);
try {
const payload = JSON.parse(atob(stored.split(".")[1]));
setClaims(payload);
} catch {}
} else {
localStorage.removeItem(TOKEN_KEY);
}
}).catch(() => {
localStorage.removeItem(TOKEN_KEY);
}).finally(() => setLoading(false));
} else {
setLoading(false);
}
}, [client]);
const register = useCallback(async (username, displayName) => {
setLoading(true);
try {
const result = await client.register(username, displayName);
setToken(result.token);
localStorage.setItem(TOKEN_KEY, result.token);
try {
setClaims(JSON.parse(atob(result.token.split(".")[1])));
} catch {}
} finally {
setLoading(false);
}
}, [client]);
const login = useCallback(async (credentialId) => {
setLoading(true);
try {
const result = await client.authenticate(credentialId);
setToken(result.token);
localStorage.setItem(TOKEN_KEY, result.token);
try {
setClaims(JSON.parse(atob(result.token.split(".")[1])));
} catch {}
} finally {
setLoading(false);
}
}, [client]);
const logout = useCallback(() => {
setToken(null);
setClaims(null);
localStorage.removeItem(TOKEN_KEY);
localStorage.removeItem("encryptid_session");
}, []);
const value = {
isAuthenticated: !!token,
token,
claims,
did: claims?.did || claims?.sub || null,
username: claims?.username || null,
loading,
register,
login,
logout,
client
};
return React.createElement(EncryptIDContext.Provider, { value }, children);
}
function useEncryptID() {
const ctx = useContext(EncryptIDContext);
if (!ctx)
throw new Error("useEncryptID must be used within <EncryptIDProvider>");
return ctx;
}
// src/ui/react/LoginButton.tsx
import React2, { useState as useState2, useCallback as useCallback2 } from "react";
function LoginButton({
label = "Sign in with Passkey",
size = "medium",
variant = "primary",
onSuccess,
onError,
onRegisterNeeded,
className = ""
}) {
const { login, isAuthenticated, did, logout, loading: contextLoading } = useEncryptID();
const [loading, setLoading] = useState2(false);
const handleClick = useCallback2(async () => {
if (isAuthenticated) {
logout();
return;
}
setLoading(true);
try {
await login();
const token = localStorage.getItem("encryptid_token") || "";
const currentDid = did || "";
onSuccess?.({ token, did: currentDid });
} catch (error) {
if (error.name === "NotAllowedError") {
onRegisterNeeded?.();
} else {
onError?.(error);
}
} finally {
setLoading(false);
}
}, [login, logout, isAuthenticated, did, onSuccess, onError, onRegisterNeeded]);
const isLoading = loading || contextLoading;
const sizeStyles = {
small: { padding: "8px 16px", fontSize: "0.875rem" },
medium: { padding: "12px 24px", fontSize: "1rem" },
large: { padding: "16px 32px", fontSize: "1.125rem" }
};
const baseStyle = {
display: "inline-flex",
alignItems: "center",
gap: "12px",
border: "none",
borderRadius: "8px",
fontWeight: 500,
cursor: isLoading ? "not-allowed" : "pointer",
opacity: isLoading ? 0.6 : 1,
transition: "all 0.2s",
fontFamily: "system-ui, -apple-system, sans-serif",
...sizeStyles[size],
...variant === "primary" ? { background: "#06b6d4", color: "white" } : { background: "transparent", border: "2px solid #06b6d4", color: "#06b6d4" }
};
return React2.createElement("button", {
onClick: handleClick,
disabled: isLoading,
style: baseStyle,
className
}, isLoading ? React2.createElement("span", null, "Authenticating...") : React2.createElement(React2.Fragment, null, React2.createElement("svg", {
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
strokeWidth: 2,
strokeLinecap: "round",
strokeLinejoin: "round",
style: { width: "24px", height: "24px" }
}, React2.createElement("circle", { cx: 12, cy: 10, r: 3 }), React2.createElement("path", { d: "M12 13v8" }), React2.createElement("path", { d: "M9 18h6" }), React2.createElement("circle", { cx: 12, cy: 10, r: 7 })), React2.createElement("span", null, isAuthenticated ? "Sign Out" : label)));
}
export {
useEncryptID,
LoginButton,
EncryptIDProvider
};