import {
getGuardianTypeInfo,
getKeyManager,
getRecoveryManager,
getSessionManager
} from "../index-24r9wkfe.js";
import {
authenticatePasskey,
detectCapabilities,
registerPasskey,
startConditionalUI
} from "../index-2cp5044h.js";
import {
AuthLevel
} from "../index-5c1t4ftn.js";
// src/ui/login-button.ts
var PASSKEY_ICON = ``;
var styles = `
:host { --eid-primary: #06b6d4; --eid-primary-hover: #0891b2; --eid-bg: #0f172a; --eid-bg-hover: #1e293b; --eid-text: #f1f5f9; --eid-text-secondary: #94a3b8; --eid-radius: 8px; display: inline-block; font-family: system-ui, -apple-system, sans-serif; }
.login-btn { display: flex; align-items: center; gap: 12px; padding: 12px 24px; background: var(--eid-primary); color: white; border: none; border-radius: var(--eid-radius); font-size: 1rem; font-weight: 500; cursor: pointer; transition: all 0.2s; box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.3); }
.login-btn:hover { background: var(--eid-primary-hover); transform: translateY(-1px); }
.login-btn:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }
.login-btn.outline { background: transparent; border: 2px solid var(--eid-primary); color: var(--eid-primary); }
.login-btn.outline:hover { background: var(--eid-primary); color: white; }
.login-btn.small { padding: 8px 16px; font-size: 0.875rem; }
.login-btn.large { padding: 16px 32px; font-size: 1.125rem; }
.passkey-icon { width: 24px; height: 24px; }
.user-info { display: flex; align-items: center; gap: 12px; padding: 8px 16px; background: var(--eid-bg); border-radius: var(--eid-radius); color: var(--eid-text); cursor: pointer; }
.user-avatar { width: 36px; height: 36px; border-radius: 50%; background: var(--eid-primary); display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 0.875rem; }
.user-did { font-size: 0.75rem; color: var(--eid-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; }
.auth-level { font-size: 0.625rem; padding: 2px 6px; border-radius: 4px; }
.auth-level.elevated { background: rgba(34, 197, 94, 0.2); color: #22c55e; }
.auth-level.standard { background: rgba(234, 179, 8, 0.2); color: #eab308; }
.dropdown { position: absolute; top: 100%; right: 0; margin-top: 8px; background: var(--eid-bg); border-radius: var(--eid-radius); box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.3); min-width: 200px; z-index: 100; overflow: hidden; }
.dropdown-item { display: flex; align-items: center; gap: 12px; padding: 12px 16px; color: var(--eid-text); cursor: pointer; transition: background 0.2s; }
.dropdown-item:hover { background: var(--eid-bg-hover); }
.dropdown-item.danger { color: #ef4444; }
.dropdown-divider { height: 1px; background: #334155; margin: 4px 0; }
.loading-spinner { width: 20px; height: 20px; border: 2px solid transparent; border-top-color: currentColor; border-radius: 50%; animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
`;
class EncryptIDLoginButton extends HTMLElement {
shadow;
loading = false;
showDropdown = false;
capabilities = null;
static get observedAttributes() {
return ["size", "variant", "label", "show-user"];
}
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
async connectedCallback() {
this.capabilities = await detectCapabilities();
if (this.capabilities.conditionalUI)
this.startConditionalAuth();
this.render();
document.addEventListener("click", (e) => {
if (!this.contains(e.target)) {
this.showDropdown = false;
this.render();
}
});
}
attributeChangedCallback() {
this.render();
}
get size() {
return this.getAttribute("size") || "medium";
}
get variant() {
return this.getAttribute("variant") || "primary";
}
get label() {
return this.getAttribute("label") || "Sign in with Passkey";
}
get showUser() {
return this.hasAttribute("show-user");
}
render() {
const session = getSessionManager();
const isLoggedIn = session.isValid();
const did = session.getDID();
const authLevel = session.getAuthLevel();
this.shadow.innerHTML = `
${isLoggedIn && this.showUser ? this.renderUserInfo(did, authLevel) : this.renderLoginButton()}
${this.showDropdown ? this.renderDropdown() : ""}
`;
this.attachEventListeners();
}
renderLoginButton() {
const sizeClass = this.size === "medium" ? "" : this.size;
const variantClass = this.variant === "primary" ? "" : this.variant;
return ``;
}
renderUserInfo(did, authLevel) {
const shortDID = did.slice(0, 20) + "..." + did.slice(-8);
const initial = did.slice(8, 10).toUpperCase();
const levelName = AuthLevel[authLevel].toLowerCase();
return ``;
}
renderDropdown() {
return `
Profile
Recovery Settings
Upgrade Auth Level
Sign Out
`;
}
attachEventListeners() {
const session = getSessionManager();
if (session.isValid() && this.showUser) {
this.shadow.querySelector(".user-info")?.addEventListener("click", () => {
this.showDropdown = !this.showDropdown;
this.render();
});
this.shadow.querySelectorAll(".dropdown-item").forEach((item) => {
item.addEventListener("click", (e) => {
e.stopPropagation();
this.handleDropdownAction(item.dataset.action);
});
});
} else {
this.shadow.querySelector(".login-btn")?.addEventListener("click", () => this.handleLogin());
}
}
async handleLogin() {
if (this.loading)
return;
this.loading = true;
this.render();
try {
const result = await authenticatePasskey();
const keyManager = getKeyManager();
if (result.prfOutput)
await keyManager.initFromPRF(result.prfOutput);
const keys = await keyManager.getKeys();
await getSessionManager().createSession(result, keys.did, { encrypt: true, sign: true, wallet: false });
this.dispatchEvent(new CustomEvent("login-success", { detail: { did: keys.did, credentialId: result.credentialId, prfAvailable: !!result.prfOutput }, bubbles: true }));
} catch (error) {
if (error.name === "NotAllowedError" || error.message?.includes("No credential")) {
this.dispatchEvent(new CustomEvent("login-register-needed", { bubbles: true }));
} else {
this.dispatchEvent(new CustomEvent("login-error", { detail: { error: error.message }, bubbles: true }));
}
} finally {
this.loading = false;
this.render();
}
}
async handleDropdownAction(action) {
this.showDropdown = false;
if (action === "logout") {
getSessionManager().clearSession();
getKeyManager().clear();
this.dispatchEvent(new CustomEvent("logout", { bubbles: true }));
} else if (action === "upgrade") {
try {
await authenticatePasskey();
getSessionManager().upgradeAuthLevel(3 /* ELEVATED */);
this.dispatchEvent(new CustomEvent("auth-upgraded", { detail: { level: 3 /* ELEVATED */ }, bubbles: true }));
} catch {}
} else {
this.dispatchEvent(new CustomEvent("navigate", { detail: { path: `/${action}` }, bubbles: true }));
}
this.render();
}
async startConditionalAuth() {
try {
const result = await startConditionalUI();
if (result) {
const keyManager = getKeyManager();
if (result.prfOutput)
await keyManager.initFromPRF(result.prfOutput);
const keys = await keyManager.getKeys();
await getSessionManager().createSession(result, keys.did, { encrypt: true, sign: true, wallet: false });
this.dispatchEvent(new CustomEvent("login-success", { detail: { did: keys.did, credentialId: result.credentialId, viaConditionalUI: true }, bubbles: true }));
this.render();
}
} catch {}
}
async register(username, displayName) {
this.loading = true;
this.render();
try {
const credential = await registerPasskey(username, displayName);
this.dispatchEvent(new CustomEvent("register-success", { detail: { credentialId: credential.credentialId, prfSupported: credential.prfSupported }, bubbles: true }));
await this.handleLogin();
} catch (error) {
this.dispatchEvent(new CustomEvent("register-error", { detail: { error: error.message }, bubbles: true }));
} finally {
this.loading = false;
this.render();
}
}
}
customElements.define("encryptid-login", EncryptIDLoginButton);
// src/ui/guardian-setup.ts
class GuardianSetupElement extends HTMLElement {
shadow;
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const manager = getRecoveryManager();
const config = manager.getConfig();
if (!config) {
manager.initializeRecovery(3).then(() => this.render());
} else {
this.render();
}
}
render() {
const manager = getRecoveryManager();
const config = manager.getConfig();
const guardians = config?.guardians ?? [];
const threshold = config?.threshold ?? 3;
const totalWeight = guardians.reduce((sum, g) => sum + g.weight, 0);
const isConfigured = totalWeight >= threshold;
this.shadow.innerHTML = `
Social Recovery
Set up guardians to recover your account without seed phrases
${isConfigured ? "Recovery Configured" : "Setup Incomplete"}
${totalWeight}/${threshold} guardians
${guardians.map((g) => {
const info = getGuardianTypeInfo(g.type);
return `
${info.icon === "key" ? "\uD83D\uDD11" : info.icon === "user" ? "\uD83D\uDC64" : info.icon === "shield" ? "\uD83D\uDEE1️" : info.icon === "building" ? "\uD83C\uDFE2" : "⏰"}
`;
}).join("")}
`;
}
}
customElements.define("encryptid-guardian-setup", GuardianSetupElement);
export {
GuardianSetupElement,
EncryptIDLoginButton
};