@getauthui/core 0.1.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.
@@ -0,0 +1,4139 @@
1
+ import { state as d, property as g, customElement as S, query as X } from "lit/decorators.js";
2
+ import { css as A, LitElement as V, nothing as n, html as s, svg as l } from "lit";
3
+ import { Client as Q, Account as J, ID as z, Avatars as tt } from "appwrite";
4
+ const et = {
5
+ signIn: "Sign in",
6
+ signUp: "Sign up",
7
+ signOut: "Sign out",
8
+ continueAsGuest: "Continue as guest",
9
+ email: "Email",
10
+ password: "Password",
11
+ newPassword: "New password",
12
+ confirmPassword: "Confirm password",
13
+ name: "Name",
14
+ phone: "Phone number",
15
+ code: "Code",
16
+ forgotPassword: "Forgot password?",
17
+ noAccount: "Don't have an account?",
18
+ haveAccount: "Already have an account?",
19
+ or: "or",
20
+ continueWith: "Continue with {provider}",
21
+ continueWithEmail: "Continue with email",
22
+ sendEmailCode: "Email me a code",
23
+ continueWithPhone: "Continue with phone",
24
+ sendMagicLink: "Send magic link",
25
+ sendCode: "Send code",
26
+ verifyCode: "Verify code",
27
+ magicLinkSent: "We sent a sign-in link to {email}. Open it on this device to continue.",
28
+ codeSent: "We sent a code to {target}. Enter it below to continue.",
29
+ securityPhrase: "Security phrase",
30
+ securityPhraseHint: "The message we sent includes this phrase. Do not continue if it differs.",
31
+ back: "Back",
32
+ cancel: "Cancel",
33
+ save: "Save",
34
+ update: "Update",
35
+ remove: "Remove",
36
+ close: "Close",
37
+ resetPassword: "Reset password",
38
+ resetLinkSent: "If an account exists for {email}, a reset link is on its way.",
39
+ passwordUpdated: "Your password was updated. You can sign in now.",
40
+ sendResetLink: "Send reset link",
41
+ agreeTo: "By continuing you agree to our",
42
+ terms: "Terms of Service",
43
+ privacy: "Privacy Policy",
44
+ and: "and",
45
+ welcomeBack: "Welcome back",
46
+ createAccount: "Create your account",
47
+ signInTitle: "Sign in to {name}",
48
+ signUpTitle: "Sign up for {name}",
49
+ mfaTitle: "Two-factor authentication",
50
+ mfaDescription: "Confirm it is you with a second factor.",
51
+ mfaUseAuthenticator: "Use authenticator app",
52
+ mfaUseEmail: "Send code to email",
53
+ mfaUsePhone: "Send code by SMS",
54
+ mfaUseRecoveryCode: "Use a recovery code",
55
+ recoveryCode: "Recovery code",
56
+ account: "Account",
57
+ profile: "Profile",
58
+ security: "Security",
59
+ sessions: "Sessions",
60
+ connections: "Connections",
61
+ activity: "Activity",
62
+ dangerZone: "Danger zone",
63
+ verified: "Verified",
64
+ unverified: "Unverified",
65
+ verifyEmail: "Verify email",
66
+ verificationSent: "Verification email sent. Check your inbox.",
67
+ emailVerified: "Your email is verified.",
68
+ changePassword: "Change password",
69
+ currentPassword: "Current password",
70
+ twoFactor: "Two-factor authentication",
71
+ twoFactorDescription: "Require a second factor when signing in to this account.",
72
+ enable: "Enable",
73
+ disable: "Disable",
74
+ authenticatorApp: "Authenticator app",
75
+ authenticatorAdd: "Add authenticator",
76
+ authenticatorScan: "Scan this QR code with your authenticator app, then enter the 6-digit code.",
77
+ authenticatorManual: "Or enter this key manually",
78
+ authenticatorVerify: "Verify and enable",
79
+ recoveryCodes: "Recovery codes",
80
+ recoveryCodesDescription: "Use a recovery code to sign in if you lose access to your other factors.",
81
+ generateRecoveryCodes: "Generate recovery codes",
82
+ regenerateRecoveryCodes: "Regenerate",
83
+ recoveryCodesWarning: "Store these codes somewhere safe. Each code works once.",
84
+ currentSession: "This device",
85
+ signOutSession: "Sign out",
86
+ signOutAllSessions: "Sign out everywhere",
87
+ signOutAllSessionsDescription: "End every session, including this one.",
88
+ noConnections: "No connected accounts.",
89
+ disconnect: "Disconnect",
90
+ noActivity: "No recent activity.",
91
+ deleteAccount: "Delete account",
92
+ deleteAccountDescription: "Your account is disabled and you are signed out. An administrator can restore it.",
93
+ deleteAccountConfirm: "Delete my account",
94
+ loading: "Loading",
95
+ copied: "Copied",
96
+ copy: "Copy",
97
+ done: "Done",
98
+ errorGeneric: "Something went wrong. Please try again.",
99
+ errorInvalidCredentials: "Invalid email or password.",
100
+ errorUserExists: "An account with this email already exists.",
101
+ errorUserBlocked: "This account is blocked. Contact support.",
102
+ errorRateLimit: "Too many attempts. Wait a moment and try again.",
103
+ errorInvalidToken: "This link is invalid or has expired. Request a new one.",
104
+ errorInvalidCode: "That code is not valid. Check it and try again.",
105
+ errorPasswordMismatch: "Passwords do not match.",
106
+ errorPasswordRecentlyUsed: "You used this password recently. Choose a different one.",
107
+ errorPasswordPersonalData: "Password must not contain your name, email or phone.",
108
+ errorPasswordWeak: "Password is too common or too short. Use at least 8 characters.",
109
+ errorPasswordPwned: "This password appeared in a data breach. Choose a different one.",
110
+ errorChallengeRequired: "Confirm a second factor to continue.",
111
+ errorSessionExists: "You are already signed in.",
112
+ errorOAuth: "Sign in with the provider failed. Please try again.",
113
+ errorNetwork: "Could not reach the server. Check your connection.",
114
+ errorMethodDisabled: "This sign-in method is disabled for this project.",
115
+ errorNotConfigured: "Auth UI is not configured. Call AuthUI.init() or add <authui-config>.",
116
+ passwordHint: "At least 8 characters.",
117
+ signedInAs: "Signed in as",
118
+ manageAccount: "Manage account",
119
+ continue: "Continue",
120
+ provider: "Provider",
121
+ lastActive: "Last active",
122
+ guestAccount: "Guest account",
123
+ guestAccountDescription: "Add an email and password to keep your data."
124
+ };
125
+ function it(e, t = {}) {
126
+ return e.replace(
127
+ /\{(\w+)\}/g,
128
+ (i, r) => r in t ? String(t[r]) : `{${r}}`
129
+ );
130
+ }
131
+ const st = {
132
+ amazon: "Amazon",
133
+ apple: "Apple",
134
+ appwrite: "Appwrite",
135
+ auth0: "Auth0",
136
+ authentik: "Authentik",
137
+ autodesk: "Autodesk",
138
+ bitbucket: "Bitbucket",
139
+ bitly: "Bitly",
140
+ box: "Box",
141
+ cloudflare: "Cloudflare",
142
+ dailymotion: "Dailymotion",
143
+ discord: "Discord",
144
+ disqus: "Disqus",
145
+ dropbox: "Dropbox",
146
+ etsy: "Etsy",
147
+ facebook: "Facebook",
148
+ figma: "Figma",
149
+ fusionauth: "FusionAuth",
150
+ github: "GitHub",
151
+ gitlab: "GitLab",
152
+ google: "Google",
153
+ huggingface: "Hugging Face",
154
+ kakao: "Kakao",
155
+ keycloak: "Keycloak",
156
+ kick: "Kick",
157
+ linkedin: "LinkedIn",
158
+ microsoft: "Microsoft",
159
+ notion: "Notion",
160
+ oidc: "OpenID Connect",
161
+ okta: "Okta",
162
+ paypal: "PayPal",
163
+ paypalSandbox: "PayPal Sandbox",
164
+ podio: "Podio",
165
+ resend: "Resend",
166
+ salesforce: "Salesforce",
167
+ slack: "Slack",
168
+ spotify: "Spotify",
169
+ stripe: "Stripe",
170
+ tiktok: "TikTok",
171
+ tradeshift: "Tradeshift",
172
+ tradeshiftBox: "Tradeshift Box",
173
+ twitch: "Twitch",
174
+ wordpress: "WordPress",
175
+ x: "X",
176
+ yahoo: "Yahoo",
177
+ yammer: "Yammer",
178
+ yandex: "Yandex",
179
+ zoho: "Zoho",
180
+ zoom: "Zoom"
181
+ };
182
+ function E(e) {
183
+ return st[e] ?? e.charAt(0).toUpperCase() + e.slice(1);
184
+ }
185
+ const b = {
186
+ moreFactorsRequired: "user_more_factors_required",
187
+ invalidCredentials: "user_invalid_credentials",
188
+ userAlreadyExists: "user_already_exists",
189
+ emailAlreadyExists: "user_email_already_exists",
190
+ phoneAlreadyExists: "user_phone_already_exists",
191
+ userBlocked: "user_blocked",
192
+ rateLimit: "general_rate_limit_exceeded",
193
+ invalidToken: "user_invalid_token",
194
+ invalidCode: "user_invalid_code",
195
+ passwordMismatch: "user_password_mismatch",
196
+ passwordRecentlyUsed: "password_recently_used",
197
+ passwordPersonalData: "password_personal_data",
198
+ passwordWeak: "user_password_weak",
199
+ passwordPwned: "password_pwned",
200
+ challengeRequired: "user_challenge_required",
201
+ recoveryCodesExist: "user_recovery_codes_already_exists",
202
+ recoveryCodesNotFound: "user_recovery_codes_not_found",
203
+ authenticatorNotFound: "user_authenticator_not_found",
204
+ routeNotFound: "general_route_not_found",
205
+ emailAlreadyVerified: "user_email_already_verified",
206
+ sessionNotFound: "user_session_not_found",
207
+ wafChallenged: "waf_request_challenged",
208
+ sessionAlreadyExists: "user_session_already_exists",
209
+ oauthUnauthorized: "user_oauth2_unauthorized",
210
+ oauthBadRequest: "user_oauth2_bad_request",
211
+ unauthorized: "general_unauthorized_scope",
212
+ userUnauthorized: "user_unauthorized",
213
+ authMethodUnsupported: "user_auth_method_unsupported",
214
+ countMaxExceeded: "user_count_exceeded",
215
+ targetAlreadyExists: "user_target_already_exists"
216
+ };
217
+ function _(e) {
218
+ if (e && typeof e == "object") {
219
+ const t = e;
220
+ return {
221
+ message: typeof t.message == "string" ? t.message : "Unknown error",
222
+ type: typeof t.type == "string" ? t.type : "",
223
+ code: typeof t.code == "number" ? t.code : 0
224
+ };
225
+ }
226
+ return { message: String(e), type: "", code: 0 };
227
+ }
228
+ function F(e, t) {
229
+ return _(e).type === t;
230
+ }
231
+ function Z(e, t, i = "link") {
232
+ const r = _(e);
233
+ switch (r.type) {
234
+ case b.invalidCredentials:
235
+ return t.errorInvalidCredentials;
236
+ case b.userAlreadyExists:
237
+ case b.emailAlreadyExists:
238
+ case b.phoneAlreadyExists:
239
+ return t.errorUserExists;
240
+ case b.userBlocked:
241
+ return t.errorUserBlocked;
242
+ case b.rateLimit:
243
+ return t.errorRateLimit;
244
+ case b.invalidToken:
245
+ return i === "code" ? t.errorInvalidCode : t.errorInvalidToken;
246
+ case b.invalidCode:
247
+ return t.errorInvalidCode;
248
+ case b.passwordMismatch:
249
+ return t.errorPasswordMismatch;
250
+ case b.passwordRecentlyUsed:
251
+ return t.errorPasswordRecentlyUsed;
252
+ case b.passwordPersonalData:
253
+ return t.errorPasswordPersonalData;
254
+ case b.passwordWeak:
255
+ return t.errorPasswordWeak;
256
+ case b.passwordPwned:
257
+ return t.errorPasswordPwned;
258
+ case b.challengeRequired:
259
+ return t.errorChallengeRequired;
260
+ case b.sessionAlreadyExists:
261
+ return t.errorSessionExists;
262
+ case b.oauthUnauthorized:
263
+ case b.oauthBadRequest:
264
+ return t.errorOAuth;
265
+ case b.authMethodUnsupported:
266
+ return t.errorMethodDisabled;
267
+ }
268
+ return r.code === 0 && /fetch|network/i.test(r.message) ? t.errorNetwork : r.message || t.errorGeneric;
269
+ }
270
+ function k(e, t, i) {
271
+ for (const r of t) {
272
+ const a = e[r];
273
+ if (typeof a == "function")
274
+ return a.apply(e, i);
275
+ }
276
+ return Promise.reject(
277
+ new Error(`Appwrite SDK is missing ${t[0]}(). Update the appwrite package.`)
278
+ );
279
+ }
280
+ const D = "authui", N = ["userId", "secret", "expire", "project", "error", D], j = () => ({
281
+ status: "loading",
282
+ user: null,
283
+ mfaFactors: null,
284
+ pending: null,
285
+ configured: !1
286
+ });
287
+ class rt {
288
+ constructor() {
289
+ this.client = null, this.account = null, this.config = null, this.state = j(), this.listeners = /* @__PURE__ */ new Map(), this.refreshPromise = null;
290
+ }
291
+ // ───────────────────────────── configuration ─────────────────────────────
292
+ /** Configure the Appwrite client. Safe to call more than once; the last call wins. */
293
+ configure(t) {
294
+ this.config = t, this.client = new Q().setEndpoint(t.endpoint).setProject(t.project), this.account = new J(this.client), this.setState({ configured: !0, status: "loading" }), typeof window < "u" && this.handleRedirect().then(() => this.refresh());
295
+ }
296
+ get isConfigured() {
297
+ return this.config !== null;
298
+ }
299
+ getConfig() {
300
+ return this.config;
301
+ }
302
+ /** The configured Appwrite client, for apps that want to reuse it. */
303
+ getClient() {
304
+ return this.client;
305
+ }
306
+ getStrings() {
307
+ return { ...et, ...this.config?.strings ?? {} };
308
+ }
309
+ getState() {
310
+ return { ...this.state };
311
+ }
312
+ get user() {
313
+ return this.state.user;
314
+ }
315
+ // ─────────────────────────────── events ───────────────────────────────
316
+ on(t, i) {
317
+ let r = this.listeners.get(t);
318
+ return r || (r = /* @__PURE__ */ new Set(), this.listeners.set(t, r)), r.add(i), () => r.delete(i);
319
+ }
320
+ emit(t, i) {
321
+ this.listeners.get(t)?.forEach((r) => {
322
+ try {
323
+ r(i);
324
+ } catch (a) {
325
+ console.error("[authui] listener failed", a);
326
+ }
327
+ }), typeof window < "u" && window.dispatchEvent(new CustomEvent(`authui:${t}`, { detail: i }));
328
+ }
329
+ setState(t) {
330
+ this.state = { ...this.state, ...t }, this.emit("change", this.getState());
331
+ }
332
+ fail(t) {
333
+ const i = _(t);
334
+ throw this.emit("error", i), t;
335
+ }
336
+ acct() {
337
+ if (!this.account) throw new Error(this.getStrings().errorNotConfigured);
338
+ return this.account;
339
+ }
340
+ // ─────────────────────────── session lifecycle ───────────────────────────
341
+ /** Re-fetch the current user and derive status. */
342
+ refresh() {
343
+ return this.refreshPromise ? this.refreshPromise : (this.refreshPromise = (async () => {
344
+ if (!this.account) {
345
+ this.setState({ status: "signed-out", user: null, mfaFactors: null });
346
+ return;
347
+ }
348
+ const t = this.state.status === "signed-in";
349
+ try {
350
+ const i = await this.account.get();
351
+ this.setState({ status: "signed-in", user: i, mfaFactors: null }), t || this.emit("signed-in", i);
352
+ } catch (i) {
353
+ if (F(i, b.moreFactorsRequired)) {
354
+ let r = null;
355
+ try {
356
+ r = await k(
357
+ this.account,
358
+ ["listMFAFactors", "listMfaFactors"],
359
+ []
360
+ );
361
+ } catch {
362
+ }
363
+ this.setState({ status: "mfa-required", user: null, mfaFactors: r });
364
+ } else
365
+ this.setState({ status: "signed-out", user: null, mfaFactors: null }), t && this.emit("signed-out", void 0);
366
+ }
367
+ })().finally(() => {
368
+ this.refreshPromise = null;
369
+ }), this.refreshPromise);
370
+ }
371
+ async afterSignIn() {
372
+ await this.refresh();
373
+ const t = this.config?.successUrl;
374
+ t && this.state.status === "signed-in" && typeof window < "u" && window.location.assign(t);
375
+ }
376
+ // ─────────────────────────────── sign in ───────────────────────────────
377
+ async signInWithEmailPassword(t, i) {
378
+ try {
379
+ await this.acct().createEmailPasswordSession(t.trim(), i);
380
+ } catch (r) {
381
+ this.fail(r);
382
+ }
383
+ await this.afterSignIn();
384
+ }
385
+ async signUp(t, i, r) {
386
+ try {
387
+ await this.acct().create(z.unique(), t.trim(), i, r?.trim() || void 0), await this.acct().createEmailPasswordSession(t.trim(), i);
388
+ } catch (a) {
389
+ this.fail(a);
390
+ }
391
+ await this.afterSignIn();
392
+ }
393
+ async signInAnonymously() {
394
+ try {
395
+ await this.acct().createAnonymousSession();
396
+ } catch (t) {
397
+ this.fail(t);
398
+ }
399
+ await this.afterSignIn();
400
+ }
401
+ /** Redirects the browser to the provider. Never resolves in a browser. */
402
+ signInWithOAuth(t) {
403
+ const i = this.config?.oauthScopes?.[t];
404
+ try {
405
+ this.acct().createOAuth2Token(
406
+ t,
407
+ this.redirectUrl("oauth"),
408
+ this.redirectUrl("oauth-failed"),
409
+ i
410
+ );
411
+ } catch (r) {
412
+ this.fail(r);
413
+ }
414
+ }
415
+ async sendMagicUrl(t) {
416
+ try {
417
+ return await this.acct().createMagicURLToken(
418
+ z.unique(),
419
+ t.trim(),
420
+ this.redirectUrl("magic-url"),
421
+ this.config?.securityPhrase ?? !0
422
+ );
423
+ } catch (i) {
424
+ return this.fail(i);
425
+ }
426
+ }
427
+ async sendEmailOtp(t) {
428
+ try {
429
+ return await this.acct().createEmailToken(
430
+ z.unique(),
431
+ t.trim(),
432
+ this.config?.securityPhrase ?? !0
433
+ );
434
+ } catch (i) {
435
+ return this.fail(i);
436
+ }
437
+ }
438
+ async sendPhoneOtp(t) {
439
+ try {
440
+ return await this.acct().createPhoneToken(z.unique(), t.replace(/[\s()-]/g, ""));
441
+ } catch (i) {
442
+ return this.fail(i);
443
+ }
444
+ }
445
+ /** Redeem any token secret (email OTP, SMS OTP, magic URL, OAuth token). */
446
+ async signInWithToken(t, i) {
447
+ try {
448
+ await this.acct().createSession(t, i.trim());
449
+ } catch (r) {
450
+ this.fail(r);
451
+ }
452
+ await this.afterSignIn();
453
+ }
454
+ // ─────────────────────────────── MFA ───────────────────────────────
455
+ async createMfaChallenge(t) {
456
+ try {
457
+ return await k(
458
+ this.acct(),
459
+ ["createMFAChallenge", "createMfaChallenge"],
460
+ [t]
461
+ );
462
+ } catch (i) {
463
+ return this.fail(i);
464
+ }
465
+ }
466
+ /** Verify a challenge. Completes a pending sign in, or acts as a step-up for protected actions. */
467
+ async completeMfaChallenge(t, i, r = {}) {
468
+ try {
469
+ await k(
470
+ this.acct(),
471
+ ["updateMFAChallenge", "updateMfaChallenge"],
472
+ [t, i.trim()]
473
+ );
474
+ } catch (a) {
475
+ this.fail(a);
476
+ }
477
+ (r.signIn ?? !0) && await this.afterSignIn();
478
+ }
479
+ async listMfaFactors() {
480
+ try {
481
+ return await k(this.acct(), ["listMFAFactors", "listMfaFactors"], []);
482
+ } catch (t) {
483
+ return this.fail(t);
484
+ }
485
+ }
486
+ async setMfaEnabled(t) {
487
+ try {
488
+ await this.acct().updateMFA(t);
489
+ } catch (i) {
490
+ this.fail(i);
491
+ }
492
+ await this.refresh();
493
+ }
494
+ async addAuthenticator() {
495
+ try {
496
+ return await k(
497
+ this.acct(),
498
+ ["createMFAAuthenticator", "createMfaAuthenticator"],
499
+ ["totp"]
500
+ );
501
+ } catch (t) {
502
+ return this.fail(t);
503
+ }
504
+ }
505
+ async verifyAuthenticator(t) {
506
+ try {
507
+ await k(
508
+ this.acct(),
509
+ ["updateMFAAuthenticator", "updateMfaAuthenticator"],
510
+ ["totp", t.trim()]
511
+ );
512
+ } catch (i) {
513
+ this.fail(i);
514
+ }
515
+ await this.refresh();
516
+ }
517
+ /** Requires a recent MFA challenge (server rejects with user_challenge_required otherwise). */
518
+ async removeAuthenticator() {
519
+ try {
520
+ await k(this.acct(), ["deleteMFAAuthenticator", "deleteMfaAuthenticator"], ["totp"]);
521
+ } catch (t) {
522
+ this.fail(t);
523
+ }
524
+ await this.refresh();
525
+ }
526
+ async createRecoveryCodes() {
527
+ try {
528
+ return (await k(
529
+ this.acct(),
530
+ ["createMFARecoveryCodes", "createMfaRecoveryCodes"],
531
+ []
532
+ )).recoveryCodes;
533
+ } catch (t) {
534
+ return this.fail(t);
535
+ }
536
+ }
537
+ /** Requires a recent MFA challenge. */
538
+ async regenerateRecoveryCodes() {
539
+ try {
540
+ return (await k(
541
+ this.acct(),
542
+ ["updateMFARecoveryCodes", "updateMfaRecoveryCodes"],
543
+ []
544
+ )).recoveryCodes;
545
+ } catch (t) {
546
+ return this.fail(t);
547
+ }
548
+ }
549
+ /** Requires a recent MFA challenge. */
550
+ async getRecoveryCodes() {
551
+ try {
552
+ return (await k(
553
+ this.acct(),
554
+ ["getMFARecoveryCodes", "getMfaRecoveryCodes"],
555
+ []
556
+ )).recoveryCodes;
557
+ } catch (t) {
558
+ return this.fail(t);
559
+ }
560
+ }
561
+ // ───────────────────────── password recovery ─────────────────────────
562
+ async sendPasswordRecovery(t) {
563
+ try {
564
+ await this.acct().createRecovery(t.trim(), this.redirectUrl("recovery"));
565
+ } catch (i) {
566
+ this.fail(i);
567
+ }
568
+ }
569
+ async completePasswordRecovery(t, i, r) {
570
+ try {
571
+ await this.acct().updateRecovery(t, i, r);
572
+ } catch (a) {
573
+ this.fail(a);
574
+ }
575
+ this.setState({ pending: null });
576
+ }
577
+ // ───────────────────────────── sign out ─────────────────────────────
578
+ async signOut(t = "current") {
579
+ try {
580
+ await this.acct().deleteSession(t);
581
+ } catch (i) {
582
+ this.fail(i);
583
+ }
584
+ t === "current" && (this.setState({ status: "signed-out", user: null, mfaFactors: null }), this.emit("signed-out", void 0));
585
+ }
586
+ async signOutEverywhere() {
587
+ try {
588
+ await this.acct().deleteSessions();
589
+ } catch (t) {
590
+ this.fail(t);
591
+ }
592
+ this.setState({ status: "signed-out", user: null, mfaFactors: null }), this.emit("signed-out", void 0);
593
+ }
594
+ // ────────────────────────── account management ──────────────────────────
595
+ async listSessions() {
596
+ try {
597
+ return (await this.acct().listSessions()).sessions;
598
+ } catch (t) {
599
+ return this.fail(t);
600
+ }
601
+ }
602
+ async listIdentities() {
603
+ try {
604
+ return (await this.acct().listIdentities()).identities;
605
+ } catch (t) {
606
+ return this.fail(t);
607
+ }
608
+ }
609
+ async deleteIdentity(t) {
610
+ try {
611
+ await this.acct().deleteIdentity(t);
612
+ } catch (i) {
613
+ this.fail(i);
614
+ }
615
+ }
616
+ async listLogs() {
617
+ try {
618
+ return (await this.acct().listLogs()).logs;
619
+ } catch (t) {
620
+ return this.fail(t);
621
+ }
622
+ }
623
+ async updateName(t) {
624
+ try {
625
+ await this.acct().updateName(t.trim());
626
+ } catch (i) {
627
+ this.fail(i);
628
+ }
629
+ await this.refresh();
630
+ }
631
+ async updateEmail(t, i) {
632
+ try {
633
+ await this.acct().updateEmail(t.trim(), i);
634
+ } catch (r) {
635
+ this.fail(r);
636
+ }
637
+ await this.refresh();
638
+ }
639
+ async updatePhone(t, i) {
640
+ try {
641
+ await this.acct().updatePhone(t.replace(/[\s()-]/g, ""), i);
642
+ } catch (r) {
643
+ this.fail(r);
644
+ }
645
+ await this.refresh();
646
+ }
647
+ async updatePassword(t, i) {
648
+ try {
649
+ await this.acct().updatePassword(t, i || void 0);
650
+ } catch (r) {
651
+ this.fail(r);
652
+ }
653
+ await this.refresh();
654
+ }
655
+ /** Turn an anonymous session into a full account. */
656
+ async convertGuest(t, i, r) {
657
+ try {
658
+ await this.acct().updateEmail(t.trim(), i), r?.trim() && await this.acct().updateName(r.trim());
659
+ } catch (a) {
660
+ this.fail(a);
661
+ }
662
+ await this.refresh();
663
+ }
664
+ async sendEmailVerification() {
665
+ try {
666
+ await k(
667
+ this.acct(),
668
+ ["createEmailVerification", "createVerification"],
669
+ [this.redirectUrl("verify-email")]
670
+ );
671
+ } catch (t) {
672
+ this.fail(t);
673
+ }
674
+ }
675
+ async sendPhoneVerification() {
676
+ try {
677
+ await this.acct().createPhoneVerification();
678
+ } catch (t) {
679
+ this.fail(t);
680
+ }
681
+ }
682
+ async confirmPhoneVerification(t) {
683
+ const i = this.state.user?.$id;
684
+ if (i) {
685
+ try {
686
+ await this.acct().updatePhoneVerification(i, t.trim());
687
+ } catch (r) {
688
+ this.fail(r);
689
+ }
690
+ await this.refresh();
691
+ }
692
+ }
693
+ /** Blocks the account and ends the session. Appwrite keeps the record so an admin can restore it. */
694
+ async deleteAccount() {
695
+ try {
696
+ await this.acct().updateStatus();
697
+ } catch (t) {
698
+ this.fail(t);
699
+ }
700
+ this.setState({ status: "signed-out", user: null, mfaFactors: null }), this.emit("signed-out", void 0);
701
+ }
702
+ // ───────────────────────────── redirects ─────────────────────────────
703
+ /** Build the URL Appwrite should send the user back to for a given flow. */
704
+ redirectUrl(t) {
705
+ const i = this.config?.redirectUrl ?? (typeof window < "u" ? window.location.origin + window.location.pathname : ""), r = new URL(i, typeof window < "u" ? window.location.href : void 0);
706
+ for (const a of N) r.searchParams.delete(a);
707
+ return r.searchParams.set(D, t), r.toString();
708
+ }
709
+ setPending(t) {
710
+ this.setState({ pending: t });
711
+ }
712
+ /**
713
+ * Finish a flow that arrived through the URL. Called automatically by `configure()`.
714
+ * Returns true when a redirect was handled.
715
+ */
716
+ async handleRedirect() {
717
+ if (typeof window > "u") return !1;
718
+ const t = new URLSearchParams(window.location.search), i = t.get(D);
719
+ if (!i) return !1;
720
+ const r = t.get("userId") ?? "", a = t.get("secret") ?? "";
721
+ this.cleanUrl();
722
+ try {
723
+ switch (i) {
724
+ case "oauth":
725
+ case "magic-url":
726
+ r && a && await this.acct().createSession(r, a);
727
+ break;
728
+ case "oauth-failed":
729
+ this.setState({ pending: { type: "oauth-failed" } });
730
+ break;
731
+ case "recovery":
732
+ r && a && this.setState({ pending: { type: "reset-password", userId: r, secret: a } });
733
+ break;
734
+ case "verify-email":
735
+ r && a && (await k(
736
+ this.acct(),
737
+ ["updateEmailVerification", "updateVerification"],
738
+ [r, a]
739
+ ), this.setState({
740
+ pending: {
741
+ type: "notice",
742
+ message: this.getStrings().emailVerified,
743
+ tone: "success"
744
+ }
745
+ }));
746
+ break;
747
+ }
748
+ } catch (u) {
749
+ const h = _(u);
750
+ this.emit("error", h), this.setState({ pending: { type: "notice", message: h.message, tone: "error" } });
751
+ }
752
+ return !0;
753
+ }
754
+ cleanUrl() {
755
+ const t = new URL(window.location.href);
756
+ for (const i of N) t.searchParams.delete(i);
757
+ window.history.replaceState(window.history.state, "", t.toString());
758
+ }
759
+ /** Test helper. */
760
+ reset() {
761
+ this.client = null, this.account = null, this.config = null, this.state = j(), this.listeners.clear();
762
+ }
763
+ }
764
+ const o = new rt();
765
+ class at {
766
+ constructor() {
767
+ this.listeners = /* @__PURE__ */ new Set(), this.observer = null, this.media = null, this.notify = () => {
768
+ const t = this.isDark("auto");
769
+ this.listeners.forEach((i) => i(t));
770
+ };
771
+ }
772
+ isDark(t = "auto") {
773
+ if (t === "dark") return !0;
774
+ if (t === "light" || typeof document > "u") return !1;
775
+ const i = document.documentElement.classList;
776
+ return i.contains("dark") ? !0 : i.contains("light") ? !1 : document.documentElement.dataset.theme === "dark" ? !0 : document.documentElement.dataset.theme === "light" ? !1 : typeof window < "u" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
777
+ }
778
+ subscribe(t) {
779
+ return this.listeners.add(t), this.start(), () => {
780
+ this.listeners.delete(t), this.listeners.size === 0 && this.stop();
781
+ };
782
+ }
783
+ start() {
784
+ this.observer || typeof document > "u" || (this.observer = new MutationObserver(this.notify), this.observer.observe(document.documentElement, {
785
+ attributes: !0,
786
+ attributeFilter: ["class", "data-theme"]
787
+ }), typeof window < "u" && window.matchMedia && (this.media = window.matchMedia("(prefers-color-scheme: dark)"), this.media.addEventListener?.("change", this.notify)));
788
+ }
789
+ stop() {
790
+ this.observer?.disconnect(), this.observer = null, this.media?.removeEventListener?.("change", this.notify), this.media = null;
791
+ }
792
+ }
793
+ const W = new at(), G = {
794
+ none: "0px",
795
+ sm: "0.25rem",
796
+ md: "0.625rem",
797
+ lg: "0.875rem",
798
+ xl: "1.125rem",
799
+ full: "1.5rem"
800
+ }, ot = A`
801
+ :host {
802
+ /* Light theme (matches :root in the console) */
803
+ --authui-background: oklch(1 0 0);
804
+ --authui-foreground: oklch(0.141 0.005 285.823);
805
+ --authui-card: oklch(1 0 0);
806
+ --authui-card-foreground: oklch(0.141 0.005 285.823);
807
+ --authui-popover: oklch(1 0 0);
808
+ --authui-popover-foreground: oklch(0.141 0.005 285.823);
809
+ --authui-primary: oklch(0.21 0.006 285.885);
810
+ --authui-primary-foreground: oklch(0.985 0 0);
811
+ --authui-secondary: oklch(0.967 0.001 286.375);
812
+ --authui-secondary-foreground: oklch(0.21 0.006 285.885);
813
+ --authui-muted: oklch(0.967 0.001 286.375);
814
+ --authui-muted-foreground: oklch(0.552 0.016 285.938);
815
+ --authui-accent: oklch(0.967 0.001 286.375);
816
+ --authui-accent-foreground: oklch(0.21 0.006 285.885);
817
+ --authui-destructive: oklch(0.577 0.245 27.325);
818
+ --authui-destructive-foreground: oklch(0.577 0.245 27.325);
819
+ --authui-border: oklch(0.93 0.0035 286.32);
820
+ --authui-input: oklch(0.93 0.0035 286.32);
821
+ --authui-ring: oklch(0.898 0.004 286.286);
822
+ --authui-brand: #fd366e;
823
+ --authui-brand-foreground: #ffffff;
824
+ --authui-success: oklch(0.696 0.17 162.48);
825
+ --authui-success-foreground: #047857;
826
+ --authui-success-bg: rgba(16, 185, 129, 0.1);
827
+ --authui-warning-foreground: #b45309;
828
+ --authui-warning-bg: rgba(245, 158, 11, 0.1);
829
+ --authui-error-foreground: #dc2626;
830
+ --authui-error-bg: rgba(239, 68, 68, 0.1);
831
+ --authui-info-foreground: #475569;
832
+ --authui-info-bg: rgba(100, 116, 139, 0.1);
833
+ --authui-overlay: rgba(0, 0, 0, 0.5);
834
+
835
+ --authui-radius: 0.625rem;
836
+ --authui-radius-sm: calc(var(--authui-radius) - 4px);
837
+ --authui-radius-md: calc(var(--authui-radius) - 2px);
838
+ --authui-radius-lg: var(--authui-radius);
839
+ --authui-radius-xl: calc(var(--authui-radius) + 4px);
840
+
841
+ --authui-font:
842
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans",
843
+ "Droid Sans", "Helvetica Neue", sans-serif;
844
+ --authui-font-mono: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
845
+
846
+ --authui-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
847
+ --authui-z: 110;
848
+ }
849
+
850
+ :host([data-theme="dark"]) {
851
+ --authui-background: #19191c;
852
+ --authui-foreground: oklch(0.985 0 0);
853
+ --authui-card: #1d1d21;
854
+ --authui-card-foreground: oklch(0.985 0 0);
855
+ --authui-popover: #1d1d21;
856
+ --authui-popover-foreground: oklch(0.985 0 0);
857
+ --authui-primary: oklch(0.985 0 0);
858
+ --authui-primary-foreground: oklch(0.21 0.006 285.885);
859
+ --authui-secondary: #2d2d31;
860
+ --authui-secondary-foreground: oklch(0.985 0 0);
861
+ --authui-muted: #2d2d31;
862
+ --authui-muted-foreground: oklch(0.705 0.015 286.067);
863
+ --authui-accent: #2d2d31;
864
+ --authui-accent-foreground: oklch(0.985 0 0);
865
+ --authui-destructive: oklch(0.396 0.141 25.723);
866
+ --authui-destructive-foreground: oklch(0.637 0.237 25.331);
867
+ --authui-border: oklch(0.252 0.005 286.32);
868
+ --authui-input: #2d2d31;
869
+ --authui-ring: oklch(0.448 0.015 285.786);
870
+ --authui-success-foreground: #34d399;
871
+ --authui-warning-foreground: #fbbf24;
872
+ --authui-error-foreground: #f87171;
873
+ --authui-info-foreground: #94a3b8;
874
+ --authui-overlay: rgba(0, 0, 0, 0.6);
875
+ --authui-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -4px rgba(0, 0, 0, 0.5);
876
+ color-scheme: dark;
877
+ }
878
+ `, nt = A`
879
+ *,
880
+ *::before,
881
+ *::after {
882
+ box-sizing: border-box;
883
+ }
884
+
885
+ :host {
886
+ font-family: var(--authui-font);
887
+ color: var(--authui-foreground);
888
+ font-size: 14px;
889
+ line-height: 1.5;
890
+ -webkit-font-smoothing: antialiased;
891
+ -moz-osx-font-smoothing: grayscale;
892
+ text-align: start;
893
+ }
894
+
895
+ [hidden] {
896
+ display: none !important;
897
+ }
898
+
899
+ .sr-only {
900
+ position: absolute;
901
+ width: 1px;
902
+ height: 1px;
903
+ padding: 0;
904
+ margin: -1px;
905
+ overflow: hidden;
906
+ clip: rect(0, 0, 0, 0);
907
+ white-space: nowrap;
908
+ border: 0;
909
+ }
910
+
911
+ /* ── Typography ── */
912
+ .title {
913
+ font-size: 18px;
914
+ line-height: 1.2;
915
+ font-weight: 600;
916
+ letter-spacing: -0.01em;
917
+ margin: 0;
918
+ color: var(--authui-foreground);
919
+ }
920
+ .description {
921
+ font-size: 13px;
922
+ color: var(--authui-muted-foreground);
923
+ margin: 6px 0 0;
924
+ }
925
+ .eyebrow {
926
+ font-size: 12px;
927
+ font-weight: 600;
928
+ text-transform: uppercase;
929
+ letter-spacing: 0.08em;
930
+ color: var(--authui-muted-foreground);
931
+ }
932
+ .muted {
933
+ color: var(--authui-muted-foreground);
934
+ }
935
+ .small {
936
+ font-size: 13px;
937
+ }
938
+ .mono {
939
+ font-family: var(--authui-font-mono);
940
+ }
941
+
942
+ /* ── Button ── */
943
+ .btn {
944
+ display: inline-flex;
945
+ align-items: center;
946
+ justify-content: center;
947
+ gap: 6px;
948
+ white-space: nowrap;
949
+ border-radius: var(--authui-radius-md);
950
+ font-size: 14px;
951
+ font-weight: 500;
952
+ font-family: inherit;
953
+ height: 36px;
954
+ padding: 0 16px;
955
+ border: 1px solid transparent;
956
+ cursor: pointer;
957
+ transition:
958
+ background-color 150ms,
959
+ color 150ms,
960
+ border-color 150ms,
961
+ box-shadow 150ms,
962
+ opacity 150ms;
963
+ outline: none;
964
+ flex-shrink: 0;
965
+ text-decoration: none;
966
+ position: relative;
967
+ }
968
+ .btn:focus-visible {
969
+ border-color: var(--authui-ring);
970
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--authui-ring) 50%, transparent);
971
+ }
972
+ .btn:disabled,
973
+ .btn[aria-disabled="true"] {
974
+ pointer-events: none;
975
+ opacity: 0.5;
976
+ }
977
+ .btn svg {
978
+ width: 16px;
979
+ height: 16px;
980
+ flex-shrink: 0;
981
+ pointer-events: none;
982
+ }
983
+ .btn-primary {
984
+ background: var(--authui-primary);
985
+ color: var(--authui-primary-foreground);
986
+ }
987
+ .btn-primary:hover {
988
+ background: color-mix(in oklab, var(--authui-primary) 90%, transparent);
989
+ }
990
+ .btn-brand {
991
+ background: var(--authui-brand);
992
+ color: var(--authui-brand-foreground);
993
+ }
994
+ .btn-brand:hover {
995
+ opacity: 0.9;
996
+ }
997
+ .btn-outline {
998
+ border-color: var(--authui-border);
999
+ background: transparent;
1000
+ color: var(--authui-foreground);
1001
+ }
1002
+ .btn-outline:hover {
1003
+ background: var(--authui-accent);
1004
+ color: var(--authui-accent-foreground);
1005
+ }
1006
+ .btn-secondary {
1007
+ background: var(--authui-secondary);
1008
+ color: var(--authui-secondary-foreground);
1009
+ }
1010
+ .btn-secondary:hover {
1011
+ background: color-mix(in oklab, var(--authui-secondary) 80%, transparent);
1012
+ }
1013
+ .btn-ghost {
1014
+ background: transparent;
1015
+ color: var(--authui-muted-foreground);
1016
+ }
1017
+ .btn-ghost:hover {
1018
+ background: var(--authui-accent);
1019
+ color: var(--authui-foreground);
1020
+ }
1021
+ .btn-destructive {
1022
+ background: var(--authui-destructive);
1023
+ color: #fff;
1024
+ }
1025
+ .btn-destructive:hover {
1026
+ background: color-mix(in oklab, var(--authui-destructive) 90%, transparent);
1027
+ }
1028
+ .btn-link {
1029
+ height: auto;
1030
+ padding: 0;
1031
+ border: 0;
1032
+ background: none;
1033
+ font-weight: 500;
1034
+ color: color-mix(in oklab, var(--authui-foreground) 85%, transparent);
1035
+ text-decoration: underline;
1036
+ text-decoration-style: dotted;
1037
+ text-decoration-color: color-mix(in oklab, var(--authui-muted-foreground) 38%, transparent);
1038
+ text-underline-offset: 3px;
1039
+ text-decoration-thickness: 1px;
1040
+ border-radius: 2px;
1041
+ }
1042
+ .btn-link:hover {
1043
+ color: var(--authui-foreground);
1044
+ text-decoration-color: color-mix(in oklab, var(--authui-muted-foreground) 58%, transparent);
1045
+ }
1046
+ .btn-sm {
1047
+ height: 32px;
1048
+ padding: 0 12px;
1049
+ font-size: 13px;
1050
+ }
1051
+ .btn-lg {
1052
+ height: 40px;
1053
+ padding: 0 24px;
1054
+ }
1055
+ .btn-icon {
1056
+ width: 36px;
1057
+ height: 36px;
1058
+ padding: 0;
1059
+ }
1060
+ .btn-block {
1061
+ width: 100%;
1062
+ }
1063
+
1064
+ /* ── Form ── */
1065
+ .field {
1066
+ display: flex;
1067
+ flex-direction: column;
1068
+ gap: 6px;
1069
+ }
1070
+ .label {
1071
+ display: flex;
1072
+ align-items: center;
1073
+ justify-content: space-between;
1074
+ gap: 8px;
1075
+ font-size: 14px;
1076
+ line-height: 1;
1077
+ font-weight: 500;
1078
+ user-select: none;
1079
+ }
1080
+ .input {
1081
+ font: inherit;
1082
+ font-size: 14px;
1083
+ height: 36px;
1084
+ width: 100%;
1085
+ min-width: 0;
1086
+ border-radius: var(--authui-radius-md);
1087
+ border: 1px solid var(--authui-input);
1088
+ background: transparent;
1089
+ color: var(--authui-foreground);
1090
+ padding: 4px 12px;
1091
+ outline: none;
1092
+ transition:
1093
+ border-color 150ms,
1094
+ box-shadow 150ms;
1095
+ }
1096
+ :host([data-theme="dark"]) .input {
1097
+ background: color-mix(in oklab, var(--authui-input) 30%, transparent);
1098
+ }
1099
+ .input::placeholder {
1100
+ color: var(--authui-muted-foreground);
1101
+ }
1102
+ .input:focus-visible {
1103
+ border-color: var(--authui-ring);
1104
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--authui-ring) 50%, transparent);
1105
+ }
1106
+ .input[aria-invalid="true"] {
1107
+ border-color: var(--authui-destructive);
1108
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--authui-destructive) 20%, transparent);
1109
+ }
1110
+ .input:disabled {
1111
+ opacity: 0.5;
1112
+ cursor: not-allowed;
1113
+ }
1114
+ .input-wrap {
1115
+ position: relative;
1116
+ display: flex;
1117
+ align-items: center;
1118
+ }
1119
+ .input-wrap .input {
1120
+ padding-inline-end: 40px;
1121
+ }
1122
+ .input-wrap .btn-icon {
1123
+ position: absolute;
1124
+ inset-inline-end: 2px;
1125
+ width: 32px;
1126
+ height: 32px;
1127
+ color: var(--authui-muted-foreground);
1128
+ }
1129
+ .input-otp {
1130
+ letter-spacing: 0.4em;
1131
+ text-align: center;
1132
+ font-family: var(--authui-font-mono);
1133
+ font-size: 18px;
1134
+ height: 44px;
1135
+ }
1136
+ .hint {
1137
+ font-size: 12px;
1138
+ color: var(--authui-muted-foreground);
1139
+ margin: 0;
1140
+ }
1141
+ .form {
1142
+ display: flex;
1143
+ flex-direction: column;
1144
+ gap: 16px;
1145
+ }
1146
+
1147
+ /* ── Alert ── */
1148
+ .alert {
1149
+ position: relative;
1150
+ width: 100%;
1151
+ border-radius: var(--authui-radius-lg);
1152
+ border: 1px solid var(--authui-border);
1153
+ padding: 12px 16px;
1154
+ font-size: 13px;
1155
+ display: grid;
1156
+ grid-template-columns: 16px 1fr;
1157
+ column-gap: 12px;
1158
+ row-gap: 2px;
1159
+ align-items: start;
1160
+ background: var(--authui-card);
1161
+ color: var(--authui-card-foreground);
1162
+ }
1163
+ .alert svg {
1164
+ width: 16px;
1165
+ height: 16px;
1166
+ margin-top: 2px;
1167
+ }
1168
+ .alert-title {
1169
+ grid-column: 2;
1170
+ font-weight: 500;
1171
+ letter-spacing: -0.01em;
1172
+ }
1173
+ .alert-body {
1174
+ grid-column: 2;
1175
+ color: var(--authui-muted-foreground);
1176
+ line-height: 1.55;
1177
+ }
1178
+ .alert-error {
1179
+ color: var(--authui-error-foreground);
1180
+ border-color: color-mix(in oklab, var(--authui-error-foreground) 30%, transparent);
1181
+ background: var(--authui-error-bg);
1182
+ }
1183
+ .alert-error .alert-body {
1184
+ color: color-mix(in oklab, var(--authui-error-foreground) 90%, transparent);
1185
+ }
1186
+ .alert-success {
1187
+ color: var(--authui-success-foreground);
1188
+ border-color: color-mix(in oklab, var(--authui-success-foreground) 30%, transparent);
1189
+ background: var(--authui-success-bg);
1190
+ }
1191
+ .alert-success .alert-body {
1192
+ color: color-mix(in oklab, var(--authui-success-foreground) 90%, transparent);
1193
+ }
1194
+ .alert-info {
1195
+ background: var(--authui-info-bg);
1196
+ }
1197
+ .alert-warning {
1198
+ color: var(--authui-warning-foreground);
1199
+ border-color: color-mix(in oklab, var(--authui-warning-foreground) 30%, transparent);
1200
+ background: var(--authui-warning-bg);
1201
+ }
1202
+
1203
+ /* ── Badge ── */
1204
+ .badge {
1205
+ display: inline-flex;
1206
+ align-items: center;
1207
+ justify-content: center;
1208
+ gap: 4px;
1209
+ border-radius: var(--authui-radius-md);
1210
+ padding: 2px 8px;
1211
+ font-size: 12px;
1212
+ font-weight: 500;
1213
+ white-space: nowrap;
1214
+ width: fit-content;
1215
+ }
1216
+ .badge svg {
1217
+ width: 12px;
1218
+ height: 12px;
1219
+ }
1220
+ .badge-success {
1221
+ background: var(--authui-success-bg);
1222
+ color: var(--authui-success-foreground);
1223
+ }
1224
+ .badge-error {
1225
+ background: var(--authui-error-bg);
1226
+ color: var(--authui-error-foreground);
1227
+ }
1228
+ .badge-warning {
1229
+ background: var(--authui-warning-bg);
1230
+ color: var(--authui-warning-foreground);
1231
+ }
1232
+ .badge-info {
1233
+ background: var(--authui-info-bg);
1234
+ color: var(--authui-info-foreground);
1235
+ }
1236
+ .badge-outline {
1237
+ background: color-mix(in oklab, var(--authui-muted) 60%, transparent);
1238
+ color: color-mix(in oklab, var(--authui-foreground) 80%, transparent);
1239
+ }
1240
+
1241
+ /* ── Separator ── */
1242
+ .separator {
1243
+ height: 1px;
1244
+ width: 100%;
1245
+ background: var(--authui-border);
1246
+ flex-shrink: 0;
1247
+ }
1248
+ .separator-text {
1249
+ display: flex;
1250
+ align-items: center;
1251
+ gap: 12px;
1252
+ font-size: 12px;
1253
+ color: var(--authui-muted-foreground);
1254
+ text-transform: uppercase;
1255
+ letter-spacing: 0.06em;
1256
+ }
1257
+ .separator-text::before,
1258
+ .separator-text::after {
1259
+ content: "";
1260
+ flex: 1;
1261
+ height: 1px;
1262
+ background: var(--authui-border);
1263
+ }
1264
+
1265
+ /* ── Tabs ── */
1266
+ .tabs {
1267
+ display: inline-flex;
1268
+ align-items: center;
1269
+ justify-content: center;
1270
+ height: 36px;
1271
+ width: fit-content;
1272
+ max-width: 100%;
1273
+ overflow-x: auto;
1274
+ border-radius: var(--authui-radius-lg);
1275
+ background: color-mix(in oklab, var(--authui-muted) 50%, transparent);
1276
+ color: var(--authui-muted-foreground);
1277
+ padding: 3px;
1278
+ gap: 2px;
1279
+ scrollbar-width: none;
1280
+ }
1281
+ :host([data-theme="dark"]) .tabs {
1282
+ background: color-mix(in oklab, var(--authui-muted) 80%, transparent);
1283
+ }
1284
+ .tab {
1285
+ display: inline-flex;
1286
+ align-items: center;
1287
+ justify-content: center;
1288
+ gap: 6px;
1289
+ height: 100%;
1290
+ flex: 1;
1291
+ padding: 4px 10px;
1292
+ border-radius: var(--authui-radius-md);
1293
+ border: 1px solid transparent;
1294
+ background: transparent;
1295
+ color: var(--authui-muted-foreground);
1296
+ font: inherit;
1297
+ font-size: 13px;
1298
+ font-weight: 500;
1299
+ white-space: nowrap;
1300
+ cursor: pointer;
1301
+ transition:
1302
+ color 150ms,
1303
+ background-color 150ms,
1304
+ box-shadow 150ms;
1305
+ }
1306
+ .tab:hover {
1307
+ color: var(--authui-foreground);
1308
+ }
1309
+ .tab[aria-selected="true"] {
1310
+ background: var(--authui-background);
1311
+ color: var(--authui-foreground);
1312
+ border-color: var(--authui-input);
1313
+ }
1314
+ .tab:focus-visible {
1315
+ outline: none;
1316
+ box-shadow: inset 0 0 0 3px color-mix(in oklab, var(--authui-ring) 50%, transparent);
1317
+ }
1318
+
1319
+ /* ── Settings card (console "Settings Card Structure") ── */
1320
+ .card {
1321
+ border-radius: var(--authui-radius-xl);
1322
+ border: 1px solid var(--authui-border);
1323
+ background: color-mix(in oklab, var(--authui-card) 50%, transparent);
1324
+ overflow: hidden;
1325
+ }
1326
+ .card-header {
1327
+ padding: 16px 24px;
1328
+ }
1329
+ .card-title {
1330
+ font-size: 15px;
1331
+ font-weight: 600;
1332
+ margin: 0;
1333
+ color: var(--authui-foreground);
1334
+ }
1335
+ .card-description {
1336
+ font-size: 13px;
1337
+ color: var(--authui-muted-foreground);
1338
+ margin: 8px 0 0;
1339
+ }
1340
+ .card-body {
1341
+ padding: 16px 24px;
1342
+ border-top: 1px solid var(--authui-border);
1343
+ }
1344
+ .card-footer {
1345
+ padding: 16px 24px;
1346
+ border-top: 1px solid var(--authui-border);
1347
+ background: color-mix(in oklab, var(--authui-muted) 30%, transparent);
1348
+ display: flex;
1349
+ justify-content: flex-end;
1350
+ gap: 8px;
1351
+ }
1352
+ .card-danger {
1353
+ border-color: color-mix(in oklab, var(--authui-destructive) 40%, transparent);
1354
+ }
1355
+
1356
+ /* ── Lists / rows ── */
1357
+ .row {
1358
+ display: flex;
1359
+ align-items: center;
1360
+ justify-content: space-between;
1361
+ gap: 12px;
1362
+ padding: 12px 0;
1363
+ }
1364
+ .row + .row {
1365
+ border-top: 1px solid var(--authui-border);
1366
+ }
1367
+ .row-main {
1368
+ display: flex;
1369
+ flex-direction: column;
1370
+ gap: 2px;
1371
+ min-width: 0;
1372
+ }
1373
+ .row-title {
1374
+ font-size: 14px;
1375
+ font-weight: 500;
1376
+ display: flex;
1377
+ align-items: center;
1378
+ gap: 8px;
1379
+ flex-wrap: wrap;
1380
+ }
1381
+ .row-sub {
1382
+ font-size: 12px;
1383
+ color: var(--authui-muted-foreground);
1384
+ overflow: hidden;
1385
+ text-overflow: ellipsis;
1386
+ white-space: nowrap;
1387
+ }
1388
+ .row-actions {
1389
+ display: flex;
1390
+ align-items: center;
1391
+ gap: 8px;
1392
+ flex-shrink: 0;
1393
+ }
1394
+
1395
+ /* ── Misc ── */
1396
+ .stack {
1397
+ display: flex;
1398
+ flex-direction: column;
1399
+ gap: 12px;
1400
+ }
1401
+ .stack-sm {
1402
+ display: flex;
1403
+ flex-direction: column;
1404
+ gap: 8px;
1405
+ }
1406
+ .inline {
1407
+ display: flex;
1408
+ align-items: center;
1409
+ gap: 8px;
1410
+ flex-wrap: wrap;
1411
+ }
1412
+ .between {
1413
+ display: flex;
1414
+ align-items: center;
1415
+ justify-content: space-between;
1416
+ gap: 8px;
1417
+ }
1418
+ .center {
1419
+ text-align: center;
1420
+ }
1421
+ .spinner {
1422
+ width: 16px;
1423
+ height: 16px;
1424
+ border-radius: 50%;
1425
+ border: 2px solid color-mix(in oklab, currentColor 30%, transparent);
1426
+ border-top-color: currentColor;
1427
+ animation: authui-spin 0.7s linear infinite;
1428
+ flex-shrink: 0;
1429
+ }
1430
+ @keyframes authui-spin {
1431
+ to {
1432
+ transform: rotate(360deg);
1433
+ }
1434
+ }
1435
+ .avatar {
1436
+ width: 36px;
1437
+ height: 36px;
1438
+ border-radius: 50%;
1439
+ background: var(--authui-muted);
1440
+ color: var(--authui-muted-foreground);
1441
+ display: inline-flex;
1442
+ align-items: center;
1443
+ justify-content: center;
1444
+ font-weight: 600;
1445
+ font-size: 14px;
1446
+ flex-shrink: 0;
1447
+ overflow: hidden;
1448
+ text-transform: uppercase;
1449
+ }
1450
+ .avatar img {
1451
+ width: 100%;
1452
+ height: 100%;
1453
+ object-fit: cover;
1454
+ }
1455
+ .logo {
1456
+ display: block;
1457
+ max-height: 40px;
1458
+ max-width: 160px;
1459
+ margin: 0 auto 16px;
1460
+ }
1461
+ .code {
1462
+ font-family: var(--authui-font-mono);
1463
+ font-size: 13px;
1464
+ border-radius: var(--authui-radius-md);
1465
+ border: 1px solid var(--authui-border);
1466
+ background: color-mix(in oklab, var(--authui-muted) 50%, transparent);
1467
+ padding: 2px 6px;
1468
+ color: color-mix(in oklab, var(--authui-foreground) 85%, transparent);
1469
+ word-break: break-all;
1470
+ user-select: all;
1471
+ }
1472
+ .codes {
1473
+ display: grid;
1474
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1475
+ gap: 8px;
1476
+ }
1477
+ .qr {
1478
+ display: block;
1479
+ width: 168px;
1480
+ height: 168px;
1481
+ margin: 0 auto;
1482
+ border-radius: var(--authui-radius-md);
1483
+ border: 1px solid var(--authui-border);
1484
+ background: #fff;
1485
+ padding: 8px;
1486
+ }
1487
+ .legal {
1488
+ font-size: 12px;
1489
+ color: var(--authui-muted-foreground);
1490
+ text-align: center;
1491
+ margin: 0;
1492
+ line-height: 1.6;
1493
+ }
1494
+ .legal a {
1495
+ color: inherit;
1496
+ text-decoration: underline;
1497
+ text-decoration-style: dotted;
1498
+ text-underline-offset: 3px;
1499
+ }
1500
+ .legal a:hover {
1501
+ color: var(--authui-foreground);
1502
+ }
1503
+ .links {
1504
+ display: flex;
1505
+ justify-content: center;
1506
+ align-items: center;
1507
+ gap: 12px;
1508
+ font-size: 13px;
1509
+ color: var(--authui-muted-foreground);
1510
+ flex-wrap: wrap;
1511
+ }
1512
+ .providers {
1513
+ display: grid;
1514
+ gap: 8px;
1515
+ }
1516
+ .providers.two {
1517
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1518
+ }
1519
+ .providers .btn svg {
1520
+ width: 18px;
1521
+ height: 18px;
1522
+ }
1523
+ .empty {
1524
+ padding: 24px 0;
1525
+ text-align: center;
1526
+ font-size: 13px;
1527
+ color: var(--authui-muted-foreground);
1528
+ }
1529
+ .choice {
1530
+ display: flex;
1531
+ align-items: center;
1532
+ gap: 12px;
1533
+ width: 100%;
1534
+ padding: 12px 14px;
1535
+ border-radius: var(--authui-radius-lg);
1536
+ border: 1px solid var(--authui-border);
1537
+ background: transparent;
1538
+ color: var(--authui-foreground);
1539
+ font: inherit;
1540
+ text-align: start;
1541
+ cursor: pointer;
1542
+ transition:
1543
+ background-color 150ms,
1544
+ border-color 150ms;
1545
+ }
1546
+ .choice:hover {
1547
+ background: var(--authui-accent);
1548
+ }
1549
+ .choice:focus-visible {
1550
+ outline: none;
1551
+ border-color: var(--authui-ring);
1552
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--authui-ring) 50%, transparent);
1553
+ }
1554
+ .choice svg {
1555
+ width: 18px;
1556
+ height: 18px;
1557
+ color: var(--authui-muted-foreground);
1558
+ flex-shrink: 0;
1559
+ }
1560
+ .choice-title {
1561
+ font-weight: 500;
1562
+ font-size: 14px;
1563
+ }
1564
+ .choice-sub {
1565
+ font-size: 12px;
1566
+ color: var(--authui-muted-foreground);
1567
+ }
1568
+ .switch {
1569
+ position: relative;
1570
+ width: 36px;
1571
+ height: 20px;
1572
+ border-radius: 999px;
1573
+ border: 1px solid transparent;
1574
+ background: var(--authui-input);
1575
+ cursor: pointer;
1576
+ transition: background-color 150ms;
1577
+ flex-shrink: 0;
1578
+ padding: 0;
1579
+ }
1580
+ .switch[aria-checked="true"] {
1581
+ background: var(--authui-primary);
1582
+ }
1583
+ .switch::after {
1584
+ content: "";
1585
+ position: absolute;
1586
+ top: 2px;
1587
+ inset-inline-start: 2px;
1588
+ width: 14px;
1589
+ height: 14px;
1590
+ border-radius: 50%;
1591
+ background: var(--authui-background);
1592
+ transition: transform 150ms;
1593
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
1594
+ }
1595
+ .switch[aria-checked="true"]::after {
1596
+ transform: translateX(16px);
1597
+ }
1598
+ .switch:focus-visible {
1599
+ outline: none;
1600
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--authui-ring) 50%, transparent);
1601
+ }
1602
+ .switch:disabled {
1603
+ opacity: 0.5;
1604
+ cursor: not-allowed;
1605
+ }
1606
+ @media (prefers-reduced-motion: reduce) {
1607
+ *,
1608
+ *::before,
1609
+ *::after {
1610
+ transition: none !important;
1611
+ animation-duration: 0.01ms !important;
1612
+ }
1613
+ }
1614
+ `;
1615
+ var ct = Object.defineProperty, lt = (e, t, i, r) => {
1616
+ for (var a = void 0, u = e.length - 1, h; u >= 0; u--)
1617
+ (h = e[u]) && (a = h(t, i, a) || a);
1618
+ return a && ct(t, i, a), a;
1619
+ };
1620
+ const H = class H extends V {
1621
+ constructor() {
1622
+ super(...arguments), this.auth = o.getState(), this.unsubscribeStore = null, this.unsubscribeTheme = null;
1623
+ }
1624
+ connectedCallback() {
1625
+ super.connectedCallback(), this.auth = o.getState(), this.unsubscribeStore = o.on("change", (t) => {
1626
+ this.auth = t, this.applyBranding();
1627
+ }), this.unsubscribeTheme = W.subscribe(() => this.applyBranding()), this.applyBranding();
1628
+ }
1629
+ disconnectedCallback() {
1630
+ super.disconnectedCallback(), this.unsubscribeStore?.(), this.unsubscribeTheme?.(), this.unsubscribeStore = null, this.unsubscribeTheme = null;
1631
+ }
1632
+ get strings() {
1633
+ return o.getStrings();
1634
+ }
1635
+ /** Translate a string key with optional `{placeholders}`. */
1636
+ t(t, i) {
1637
+ return it(this.strings[t], i);
1638
+ }
1639
+ get config() {
1640
+ return o.getConfig();
1641
+ }
1642
+ get productName() {
1643
+ return this.config?.branding?.name ?? "";
1644
+ }
1645
+ /** Push theme and branding from config onto the host element. */
1646
+ applyBranding() {
1647
+ const t = this.config?.branding, i = W.isDark(t?.theme ?? "auto");
1648
+ this.setAttribute("data-theme", i ? "dark" : "light"), t?.primary && (this.style.setProperty("--authui-primary", t.primary), this.style.setProperty(
1649
+ "--authui-primary-foreground",
1650
+ t.primaryForeground ?? "#ffffff"
1651
+ )), t?.radius && G[t.radius] && this.style.setProperty("--authui-radius", G[t.radius]);
1652
+ }
1653
+ /** Emit a composed custom event from this element. */
1654
+ fire(t, i) {
1655
+ this.dispatchEvent(new CustomEvent(t, { detail: i, bubbles: !0, composed: !0 }));
1656
+ }
1657
+ };
1658
+ H.styles = [ot, nt];
1659
+ let x = H;
1660
+ lt([
1661
+ d()
1662
+ ], x.prototype, "auth");
1663
+ var dt = Object.defineProperty, ut = Object.getOwnPropertyDescriptor, w = (e, t, i, r) => {
1664
+ for (var a = r > 1 ? void 0 : r ? ut(t, i) : t, u = e.length - 1, h; u >= 0; u--)
1665
+ (h = e[u]) && (a = (r ? h(t, i, a) : h(a)) || a);
1666
+ return r && a && dt(t, i, a), a;
1667
+ };
1668
+ let v = class extends V {
1669
+ constructor() {
1670
+ super(...arguments), this.endpoint = "", this.project = "", this.redirectUrl = "", this.successUrl = "", this.methods = "email-password", this.signUp = "true", this.requireName = "true", this.mfa = "true", this.securityPhrase = "true", this.name = "", this.logo = "", this.theme = "auto", this.radius = "", this.primary = "", this.primaryForeground = "", this.termsUrl = "", this.privacyUrl = "";
1671
+ }
1672
+ connectedCallback() {
1673
+ super.connectedCallback(), this.configure();
1674
+ }
1675
+ updated() {
1676
+ this.configure();
1677
+ }
1678
+ configure() {
1679
+ if (!this.endpoint || !this.project) return;
1680
+ const e = this.toConfig(), t = o.getConfig();
1681
+ t && JSON.stringify(t) === JSON.stringify(e) || o.configure(e);
1682
+ }
1683
+ toConfig() {
1684
+ const e = { oauth: [] };
1685
+ for (const t of this.methods.split(/[\s,]+/).filter(Boolean))
1686
+ t.startsWith("oauth:") ? e.oauth.push(t.slice(6)) : t === "email-password" ? e.emailPassword = !0 : t === "magic-url" ? e.magicUrl = !0 : t === "email-otp" ? e.emailOtp = !0 : t === "phone" ? e.phone = !0 : (t === "anonymous" || t === "guest") && (e.anonymous = !0);
1687
+ return e.emailPassword === void 0 && !this.methods.trim() && (e.emailPassword = !0), {
1688
+ endpoint: this.endpoint,
1689
+ project: this.project,
1690
+ redirectUrl: this.redirectUrl || void 0,
1691
+ successUrl: this.successUrl || void 0,
1692
+ methods: e,
1693
+ signUp: this.signUp !== "false",
1694
+ requireName: this.requireName !== "false",
1695
+ mfa: this.mfa !== "false",
1696
+ securityPhrase: this.securityPhrase !== "false",
1697
+ branding: {
1698
+ name: this.name || void 0,
1699
+ logo: this.logo || void 0,
1700
+ theme: this.theme || "auto",
1701
+ radius: this.radius || void 0,
1702
+ primary: this.primary || void 0,
1703
+ primaryForeground: this.primaryForeground || void 0
1704
+ },
1705
+ legal: {
1706
+ termsUrl: this.termsUrl || void 0,
1707
+ privacyUrl: this.privacyUrl || void 0
1708
+ }
1709
+ };
1710
+ }
1711
+ };
1712
+ v.styles = A`
1713
+ :host {
1714
+ display: none;
1715
+ }
1716
+ `;
1717
+ w([
1718
+ g({ type: String })
1719
+ ], v.prototype, "endpoint", 2);
1720
+ w([
1721
+ g({ type: String })
1722
+ ], v.prototype, "project", 2);
1723
+ w([
1724
+ g({ type: String, attribute: "redirect-url" })
1725
+ ], v.prototype, "redirectUrl", 2);
1726
+ w([
1727
+ g({ type: String, attribute: "success-url" })
1728
+ ], v.prototype, "successUrl", 2);
1729
+ w([
1730
+ g({ type: String })
1731
+ ], v.prototype, "methods", 2);
1732
+ w([
1733
+ g({ type: String, attribute: "sign-up" })
1734
+ ], v.prototype, "signUp", 2);
1735
+ w([
1736
+ g({ type: String, attribute: "require-name" })
1737
+ ], v.prototype, "requireName", 2);
1738
+ w([
1739
+ g({ type: String })
1740
+ ], v.prototype, "mfa", 2);
1741
+ w([
1742
+ g({ type: String, attribute: "security-phrase" })
1743
+ ], v.prototype, "securityPhrase", 2);
1744
+ w([
1745
+ g({ type: String })
1746
+ ], v.prototype, "name", 2);
1747
+ w([
1748
+ g({ type: String })
1749
+ ], v.prototype, "logo", 2);
1750
+ w([
1751
+ g({ type: String })
1752
+ ], v.prototype, "theme", 2);
1753
+ w([
1754
+ g({ type: String })
1755
+ ], v.prototype, "radius", 2);
1756
+ w([
1757
+ g({ type: String })
1758
+ ], v.prototype, "primary", 2);
1759
+ w([
1760
+ g({ type: String, attribute: "primary-foreground" })
1761
+ ], v.prototype, "primaryForeground", 2);
1762
+ w([
1763
+ g({ type: String, attribute: "terms-url" })
1764
+ ], v.prototype, "termsUrl", 2);
1765
+ w([
1766
+ g({ type: String, attribute: "privacy-url" })
1767
+ ], v.prototype, "privacyUrl", 2);
1768
+ v = w([
1769
+ S("authui-config")
1770
+ ], v);
1771
+ var ht = Object.defineProperty, pt = Object.getOwnPropertyDescriptor, B = (e, t, i, r) => {
1772
+ for (var a = r > 1 ? void 0 : r ? pt(t, i) : t, u = e.length - 1, h; u >= 0; u--)
1773
+ (h = e[u]) && (a = (r ? h(t, i, a) : h(a)) || a);
1774
+ return r && a && ht(t, i, a), a;
1775
+ };
1776
+ if (typeof document < "u" && !document.getElementById("authui-fouc")) {
1777
+ const e = document.createElement("style");
1778
+ e.id = "authui-fouc", e.textContent = "authui-signed-in:not([ready]),authui-signed-out:not([ready]){display:none}", document.head.appendChild(e);
1779
+ }
1780
+ class T extends V {
1781
+ constructor() {
1782
+ super(...arguments), this.show = !1, this.unsubscribe = null;
1783
+ }
1784
+ connectedCallback() {
1785
+ super.connectedCallback(), this.evaluate(o.getState().status), this.unsubscribe = o.on("change", (t) => this.evaluate(t.status));
1786
+ }
1787
+ disconnectedCallback() {
1788
+ super.disconnectedCallback(), this.unsubscribe?.();
1789
+ }
1790
+ evaluate(t) {
1791
+ t !== "loading" && (this.show = this.shouldShow(t), this.setAttribute("ready", ""), this.style.display = "contents");
1792
+ }
1793
+ render() {
1794
+ return this.show ? s`<slot></slot>` : n;
1795
+ }
1796
+ }
1797
+ B([
1798
+ d()
1799
+ ], T.prototype, "show", 2);
1800
+ let Y = class extends T {
1801
+ shouldShow(e) {
1802
+ return e === "signed-in";
1803
+ }
1804
+ };
1805
+ Y = B([
1806
+ S("authui-signed-in")
1807
+ ], Y);
1808
+ let K = class extends T {
1809
+ shouldShow(e) {
1810
+ return e !== "signed-in";
1811
+ }
1812
+ };
1813
+ K = B([
1814
+ S("authui-signed-out")
1815
+ ], K);
1816
+ const ft = A`
1817
+ :host {
1818
+ display: block;
1819
+ width: 100%;
1820
+ max-width: 420px;
1821
+ }
1822
+ .panel {
1823
+ background: var(--authui-card);
1824
+ color: var(--authui-card-foreground);
1825
+ border: 1px solid var(--authui-border);
1826
+ border-radius: var(--authui-radius-xl);
1827
+ padding: 24px;
1828
+ display: flex;
1829
+ flex-direction: column;
1830
+ gap: 20px;
1831
+ box-shadow: var(--authui-shadow-lg);
1832
+ }
1833
+ .panel.embedded {
1834
+ border: 0;
1835
+ box-shadow: none;
1836
+ padding: 0;
1837
+ background: transparent;
1838
+ }
1839
+ .header {
1840
+ text-align: center;
1841
+ display: flex;
1842
+ flex-direction: column;
1843
+ gap: 4px;
1844
+ }
1845
+ .header:empty {
1846
+ display: none;
1847
+ }
1848
+ .alert .dismiss {
1849
+ position: absolute;
1850
+ top: 4px;
1851
+ inset-inline-end: 4px;
1852
+ width: 28px;
1853
+ height: 28px;
1854
+ }
1855
+ .alert .dismiss svg {
1856
+ width: 14px;
1857
+ height: 14px;
1858
+ margin: 0;
1859
+ }
1860
+ `, f = (e) => s`<svg
1861
+ xmlns="http://www.w3.org/2000/svg"
1862
+ viewBox="0 0 24 24"
1863
+ fill="none"
1864
+ stroke="currentColor"
1865
+ stroke-width="2"
1866
+ stroke-linecap="round"
1867
+ stroke-linejoin="round"
1868
+ aria-hidden="true"
1869
+ >
1870
+ ${e}
1871
+ </svg>`, c = {
1872
+ mail: f(
1873
+ l`<rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/>`
1874
+ ),
1875
+ phone: f(
1876
+ l`<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/>`
1877
+ ),
1878
+ user: f(
1879
+ l`<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>`
1880
+ ),
1881
+ userX: f(
1882
+ l`<path d="M2 21a8 8 0 0 1 11.873-7"/><circle cx="10" cy="8" r="5"/><path d="m17 17 5 5"/><path d="m22 17-5 5"/>`
1883
+ ),
1884
+ lock: f(
1885
+ l`<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>`
1886
+ ),
1887
+ key: f(
1888
+ l`<path d="m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4"/><path d="m21 2-9.6 9.6"/><circle cx="7.5" cy="15.5" r="5.5"/>`
1889
+ ),
1890
+ shield: f(
1891
+ l`<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/>`
1892
+ ),
1893
+ shieldCheck: f(
1894
+ l`<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12 2 2 4-4"/>`
1895
+ ),
1896
+ smartphone: f(
1897
+ l`<rect width="14" height="20" x="5" y="2" rx="2" ry="2"/><path d="M12 18h.01"/>`
1898
+ ),
1899
+ monitor: f(
1900
+ l`<rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/>`
1901
+ ),
1902
+ globe: f(
1903
+ l`<circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/>`
1904
+ ),
1905
+ logOut: f(
1906
+ l`<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" x2="9" y1="12" y2="12"/>`
1907
+ ),
1908
+ settings: f(
1909
+ l`<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>`
1910
+ ),
1911
+ x: f(l`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`),
1912
+ check: f(l`<path d="M20 6 9 17l-5-5"/>`),
1913
+ copy: f(
1914
+ l`<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>`
1915
+ ),
1916
+ eye: f(
1917
+ l`<path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/>`
1918
+ ),
1919
+ eyeOff: f(
1920
+ l`<path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"/><path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"/><path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"/><path d="m2 2 20 20"/>`
1921
+ ),
1922
+ arrowLeft: f(l`<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>`),
1923
+ alert: f(
1924
+ l`<circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/>`
1925
+ ),
1926
+ info: f(l`<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>`),
1927
+ checkCircle: f(l`<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>`),
1928
+ link: f(
1929
+ l`<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>`
1930
+ ),
1931
+ activity: f(
1932
+ l`<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"/>`
1933
+ ),
1934
+ trash: f(
1935
+ l`<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>`
1936
+ ),
1937
+ sparkles: f(
1938
+ l`<path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/>`
1939
+ ),
1940
+ refresh: f(
1941
+ l`<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/>`
1942
+ ),
1943
+ chevronDown: f(l`<path d="m6 9 6 6 6-6"/>`),
1944
+ ghost: f(
1945
+ l`<path d="M9 10h.01"/><path d="M15 10h.01"/><path d="M12 2a8 8 0 0 0-8 8v12l3-3 2.5 2.5L12 19l2.5 2.5L17 19l3 3V10a8 8 0 0 0-8-8z"/>`
1946
+ ),
1947
+ qr: f(
1948
+ l`<rect width="5" height="5" x="3" y="3" rx="1"/><rect width="5" height="5" x="16" y="3" rx="1"/><rect width="5" height="5" x="3" y="16" rx="1"/><path d="M21 16h-3a2 2 0 0 0-2 2v3"/><path d="M21 21v.01"/><path d="M12 7v3a2 2 0 0 1-2 2H7"/><path d="M3 12h.01"/><path d="M12 3h.01"/><path d="M12 16v.01"/><path d="M16 12h1"/><path d="M21 12v.01"/><path d="M12 21v-1"/>`
1949
+ )
1950
+ }, y = (e, t = "0 0 24 24") => s`<svg xmlns="http://www.w3.org/2000/svg" viewBox=${t} aria-hidden="true">${e}</svg>`, mt = {
1951
+ google: y(
1952
+ l`<path fill="#4285F4" d="M23.49 12.27c0-.79-.07-1.54-.19-2.27H12v4.51h6.47a5.57 5.57 0 0 1-2.4 3.58v3h3.86c2.26-2.09 3.56-5.17 3.56-8.82z"/><path fill="#34A853" d="M12 24c3.24 0 5.95-1.08 7.93-2.91l-3.86-3c-1.08.72-2.45 1.16-4.07 1.16-3.13 0-5.78-2.11-6.73-4.96H1.29v3.09A11.99 11.99 0 0 0 12 24z"/><path fill="#FBBC05" d="M5.27 14.29A7.2 7.2 0 0 1 4.89 12c0-.8.14-1.57.38-2.29V6.62H1.29A11.97 11.97 0 0 0 0 12c0 1.94.46 3.77 1.29 5.38l3.98-3.09z"/><path fill="#EA4335" d="M12 4.75c1.77 0 3.35.61 4.6 1.8l3.42-3.42C17.95 1.19 15.24 0 12 0 7.31 0 3.26 2.69 1.29 6.62l3.98 3.09C6.22 6.86 8.87 4.75 12 4.75z"/>`
1953
+ ),
1954
+ github: y(
1955
+ l`<path fill="currentColor" d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z"/>`
1956
+ ),
1957
+ apple: y(
1958
+ l`<path fill="currentColor" d="M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z"/>`
1959
+ ),
1960
+ facebook: y(
1961
+ l`<path fill="#1877F2" d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>`
1962
+ ),
1963
+ x: y(
1964
+ l`<path fill="currentColor" d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>`
1965
+ ),
1966
+ microsoft: y(
1967
+ l`<path fill="#F25022" d="M1 1h10v10H1z"/><path fill="#7FBA00" d="M13 1h10v10H13z"/><path fill="#00A4EF" d="M1 13h10v10H1z"/><path fill="#FFB900" d="M13 13h10v10H13z"/>`
1968
+ ),
1969
+ discord: y(
1970
+ l`<path fill="#5865F2" d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/>`
1971
+ ),
1972
+ gitlab: y(
1973
+ l`<path fill="#FC6D26" d="m23.6 9.593-.033-.086L20.3.98a.851.851 0 0 0-.336-.405.876.876 0 0 0-1.001.054.874.874 0 0 0-.29.44l-2.205 6.748H7.535L5.33 1.069a.857.857 0 0 0-.29-.441.876.876 0 0 0-1.001-.054.86.86 0 0 0-.336.405L.436 9.502l-.032.086a6.066 6.066 0 0 0 2.012 7.01l.011.009.03.021 4.976 3.727 2.462 1.863 1.5 1.132a1.009 1.009 0 0 0 1.22 0l1.5-1.132 2.461-1.863 5.006-3.75.013-.01a6.068 6.068 0 0 0 2.006-7.002z"/>`
1974
+ ),
1975
+ linkedin: y(
1976
+ l`<path fill="#0A66C2" d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>`
1977
+ ),
1978
+ slack: y(
1979
+ l`<path fill="#E01E5A" d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313z"/><path fill="#36C5F0" d="M8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312z"/><path fill="#2EB67D" d="M18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.27 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.163 0a2.528 2.528 0 0 1 2.523 2.522v6.312z"/><path fill="#ECB22E" d="M15.163 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.163 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.27a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.315A2.527 2.527 0 0 1 24 15.163a2.528 2.528 0 0 1-2.522 2.523h-6.315z"/>`
1980
+ ),
1981
+ twitch: y(
1982
+ l`<path fill="#9146FF" d="M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0 1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714Z"/>`
1983
+ ),
1984
+ spotify: y(
1985
+ l`<path fill="#1DB954" d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z"/>`
1986
+ ),
1987
+ notion: y(
1988
+ l`<path fill="currentColor" d="M4.459 4.208c.746.606 1.026.56 2.428.466l13.215-.793c.28 0 .047-.28-.046-.326L17.86 1.968c-.42-.326-.981-.7-2.055-.607L3.01 2.295c-.466.046-.56.28-.374.466zm.793 3.08v13.904c0 .747.373 1.027 1.214.98l14.523-.84c.841-.046.935-.56.935-1.167V6.354c0-.606-.233-.933-.748-.887l-15.177.887c-.56.047-.747.327-.747.933zm14.337.745c.093.42 0 .84-.42.888l-.7.14v10.264c-.608.327-1.168.514-1.635.514-.748 0-.935-.234-1.495-.933l-4.577-7.186v6.952L12.21 19s0 .84-1.168.84l-3.222.186c-.093-.186 0-.653.327-.746l.84-.233V9.854L7.822 9.76c-.094-.42.14-1.026.793-1.073l3.456-.233 4.764 7.279v-6.44l-1.215-.139c-.093-.514.28-.887.747-.933zM1.936 1.035l13.31-.98c1.634-.14 2.055-.047 3.082.7l4.249 2.986c.7.513.934.653.934 1.213v16.378c0 1.026-.373 1.634-1.68 1.726l-15.458.934c-.98.047-1.448-.093-1.962-.747l-3.129-4.06c-.56-.747-.793-1.306-.793-1.96V2.667c0-.839.374-1.54 1.447-1.632z"/>`
1989
+ ),
1990
+ dropbox: y(
1991
+ l`<path fill="#0061FF" d="M6 1.807 0 5.629l6 3.822 6.001-3.822L6 1.807zm12 0-6 3.822 6 3.822 6-3.822-6-3.822zM0 13.274l6 3.822 6.001-3.822L6 9.452l-6 3.822zm18-3.822-6 3.822 6 3.822 6-3.822-6-3.822zM6 18.371l6.001 3.822 6-3.822-6-3.822L6 18.371z"/>`
1992
+ ),
1993
+ figma: y(
1994
+ l`<path fill="#F24E1E" d="M8 24a4 4 0 0 0 4-4v-4H8a4 4 0 0 0 0 8z"/><path fill="#A259FF" d="M4 12a4 4 0 0 1 4-4h4v8H8a4 4 0 0 1-4-4z"/><path fill="#FF7262" d="M4 4a4 4 0 0 1 4-4h4v8H8a4 4 0 0 1-4-4z"/><path fill="#1ABCFE" d="M12 0h4a4 4 0 0 1 0 8h-4V0z"/><path fill="#0ACF83" d="M20 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0z"/>`
1995
+ ),
1996
+ bitbucket: y(
1997
+ l`<path fill="#2684FF" d="M.778 1.213a.768.768 0 0 0-.768.892l3.263 19.81c.084.5.515.868 1.022.873H19.95a.772.772 0 0 0 .77-.646l3.27-20.03a.768.768 0 0 0-.768-.891zM14.52 15.53H9.522L8.17 8.466h7.561z"/>`
1998
+ ),
1999
+ amazon: y(
2000
+ l`<path fill="currentColor" d="M.045 18.02c.072-.116.187-.124.348-.022 3.636 2.11 7.594 3.166 11.87 3.166 2.852 0 5.668-.533 8.447-1.595l.315-.14c.138-.06.234-.1.293-.13.226-.088.39-.046.525.13.12.174.09.336-.12.48-.256.19-.6.41-1.006.654-1.244.743-2.64 1.316-4.185 1.726a17.617 17.617 0 0 1-10.951-.577 17.88 17.88 0 0 1-5.43-3.35c-.1-.074-.151-.15-.151-.22 0-.047.021-.09.051-.13zm6.565-6.218c0-1.005.247-1.863.743-2.577.495-.71 1.17-1.25 2.04-1.615.796-.335 1.756-.575 2.912-.72.39-.046 1.033-.103 1.92-.174v-.37c0-.93-.105-1.558-.3-1.875-.302-.43-.78-.65-1.44-.65h-.182c-.48.046-.896.196-1.246.46-.35.27-.575.63-.675 1.096-.06.3-.206.465-.435.51l-2.52-.315c-.248-.06-.372-.18-.372-.39 0-.046.007-.09.022-.15.247-1.29.855-2.25 1.82-2.88.976-.616 2.1-.975 3.39-1.05h.54c1.65 0 2.957.434 3.888 1.29.135.15.27.3.405.48.12.165.224.314.283.45.075.134.15.33.195.57.06.254.105.42.135.51.03.104.062.3.076.615.01.313.02.493.02.553v5.28c0 .376.06.72.165 1.036.105.313.21.54.315.674l.51.674c.09.136.136.256.136.36 0 .12-.06.226-.18.314-1.2 1.05-1.86 1.62-1.963 1.71-.165.135-.373.15-.61.045a6.62 6.62 0 0 1-.526-.496l-.31-.347a9.858 9.858 0 0 1-.317-.42l-.3-.435c-.81.886-1.603 1.44-2.4 1.665-.494.15-1.093.227-1.83.227-1.11 0-2.04-.343-2.76-1.034-.72-.69-1.08-1.665-1.08-2.94l-.05-.076zm3.753-.438c0 .566.14 1.02.425 1.364.285.34.675.512 1.155.512.045 0 .106-.007.195-.02.09-.016.134-.023.166-.023.614-.16 1.08-.553 1.424-1.178.165-.28.285-.58.36-.91.09-.32.12-.59.135-.8.015-.195.015-.54.015-1.005v-.54c-.84 0-1.484.06-1.92.18-1.275.36-1.92 1.17-1.92 2.43l-.035-.01zm9.162 7.027c.03-.06.075-.11.132-.17.362-.243.714-.41 1.05-.5a8.094 8.094 0 0 1 1.612-.24c.14-.012.28 0 .41.03.65.06 1.05.168 1.172.33.063.09.099.228.099.39v.15c0 .51-.149 1.11-.424 1.8-.278.69-.664 1.248-1.156 1.68-.073.06-.14.09-.197.09-.03 0-.06 0-.09-.012-.09-.044-.107-.12-.064-.24.54-1.26.806-2.143.806-2.64 0-.15-.03-.27-.087-.344-.145-.166-.55-.257-1.224-.257-.243 0-.533.016-.87.045-.363.045-.7.09-1 .135-.09 0-.148-.014-.18-.044-.03-.03-.036-.06-.02-.106 0-.014.007-.03.02-.06z"/>`
2001
+ ),
2002
+ paypal: y(
2003
+ l`<path fill="#003087" d="M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.106zm14.146-14.42a3.35 3.35 0 0 0-.607-.541c-.013.076-.026.175-.041.254-.93 4.778-4.005 7.201-9.138 7.201h-2.19a.563.563 0 0 0-.556.479l-1.187 7.527h-.506l-.24 1.516a.56.56 0 0 0 .554.647h3.882c.46 0 .85-.334.922-.788.06-.26.76-4.852.816-5.09a.932.932 0 0 1 .923-.788h.58c3.76 0 6.705-1.528 7.565-5.946.36-1.847.174-3.388-.777-4.471z"/>`
2004
+ )
2005
+ };
2006
+ function L(e) {
2007
+ return mt[e] ?? c.globe;
2008
+ }
2009
+ var gt = Object.defineProperty, bt = Object.getOwnPropertyDescriptor, C = (e, t, i, r) => {
2010
+ for (var a = r > 1 ? void 0 : r ? bt(t, i) : t, u = e.length - 1, h; u >= 0; u--)
2011
+ (h = e[u]) && (a = (r ? h(t, i, a) : h(a)) || a);
2012
+ return r && a && gt(t, i, a), a;
2013
+ };
2014
+ let $ = class extends x {
2015
+ constructor() {
2016
+ super(...arguments), this.view = "sign-in", this.embedded = !1, this.step = "sign-in", this.busy = !1, this.error = "", this.notice = null, this.showPassword = !1, this.token = null, this.challenge = null, this.recovery = null, this.email = "", this.password = "", this.passwordConfirm = "", this.name = "", this.phone = "", this.code = "", this.onSignIn = (e) => {
2017
+ e.preventDefault(), this.run(async () => {
2018
+ await o.signInWithEmailPassword(this.email, this.password), this.password = "", this.fire("authui-success", { method: "email-password" });
2019
+ });
2020
+ }, this.onSignUp = (e) => {
2021
+ e.preventDefault(), this.run(async () => {
2022
+ await o.signUp(this.email, this.password, this.name), this.password = "", this.fire("authui-success", { method: "sign-up" });
2023
+ });
2024
+ }, this.onGuest = () => {
2025
+ this.run(async () => {
2026
+ await o.signInAnonymously(), this.fire("authui-success", { method: "anonymous" });
2027
+ });
2028
+ }, this.onOAuth = (e) => {
2029
+ this.run(async () => {
2030
+ o.signInWithOAuth(e), await new Promise((t) => setTimeout(t, 4e3));
2031
+ });
2032
+ }, this.onForgot = (e) => {
2033
+ e.preventDefault(), this.run(async () => {
2034
+ await o.sendPasswordRecovery(this.email), this.notice = { tone: "success", message: this.t("resetLinkSent", { email: this.email }) };
2035
+ });
2036
+ }, this.onReset = (e) => {
2037
+ if (e.preventDefault(), this.password !== this.passwordConfirm) {
2038
+ this.error = this.t("errorPasswordMismatch");
2039
+ return;
2040
+ }
2041
+ const t = this.recovery;
2042
+ t && this.run(async () => {
2043
+ await o.completePasswordRecovery(t.userId, t.secret, this.password), this.password = "", this.passwordConfirm = "", this.recovery = null, this.notice = { tone: "success", message: this.t("passwordUpdated") }, this.go("sign-in");
2044
+ });
2045
+ }, this.onMagicUrl = (e) => {
2046
+ e.preventDefault(), this.run(async () => {
2047
+ const t = await o.sendMagicUrl(this.email);
2048
+ this.token = {
2049
+ userId: t.userId,
2050
+ kind: "magic-url",
2051
+ target: this.email,
2052
+ phrase: t.phrase
2053
+ };
2054
+ });
2055
+ }, this.onEmailOtp = (e) => {
2056
+ e.preventDefault(), this.run(async () => {
2057
+ const t = await o.sendEmailOtp(this.email);
2058
+ this.token = {
2059
+ userId: t.userId,
2060
+ kind: "email-otp",
2061
+ target: this.email,
2062
+ phrase: t.phrase
2063
+ }, this.code = "";
2064
+ });
2065
+ }, this.onPhoneOtp = (e) => {
2066
+ e.preventDefault(), this.run(async () => {
2067
+ const t = await o.sendPhoneOtp(this.phone);
2068
+ this.token = { userId: t.userId, kind: "phone", target: this.phone }, this.code = "";
2069
+ });
2070
+ }, this.onVerifyCode = (e) => {
2071
+ e.preventDefault();
2072
+ const t = this.token;
2073
+ t && this.run(async () => {
2074
+ await o.signInWithToken(t.userId, this.code), this.code = "", this.fire("authui-success", { method: t.kind });
2075
+ }, "code");
2076
+ }, this.onChooseFactor = (e) => {
2077
+ this.run(async () => {
2078
+ const t = await o.createMfaChallenge(e);
2079
+ this.challenge = { id: t.$id, factor: e }, this.code = "";
2080
+ });
2081
+ }, this.onVerifyFactor = (e) => {
2082
+ e.preventDefault();
2083
+ const t = this.challenge;
2084
+ t && this.run(async () => {
2085
+ await o.completeMfaChallenge(t.id, this.code), this.code = "", this.challenge = null, this.fire("authui-success", { method: "mfa" });
2086
+ }, "code");
2087
+ }, this.onCancelMfa = () => {
2088
+ this.run(async () => {
2089
+ try {
2090
+ await o.signOut();
2091
+ } catch (e) {
2092
+ if (!F(e, b.sessionNotFound)) throw e;
2093
+ }
2094
+ this.go("sign-in");
2095
+ });
2096
+ }, this.onSignOut = () => {
2097
+ this.run(() => o.signOut());
2098
+ };
2099
+ }
2100
+ connectedCallback() {
2101
+ super.connectedCallback(), this.step = this.view, this.syncFromStore();
2102
+ }
2103
+ willUpdate(e) {
2104
+ e.has("view") && e.get("view") !== void 0 && this.go(this.view), e.has("auth") && this.syncFromStore();
2105
+ }
2106
+ updated(e) {
2107
+ e.has("step") && requestAnimationFrame(() => this.firstInput?.focus());
2108
+ }
2109
+ /** React to store transitions: MFA pending, redirect results, sign in. */
2110
+ syncFromStore() {
2111
+ const { status: e, pending: t } = this.auth;
2112
+ e === "mfa-required" && this.step !== "mfa" && this.go("mfa"), t?.type === "reset-password" && this.step !== "reset-password" && (this.recovery = { userId: t.userId, secret: t.secret }, this.go("reset-password")), t?.type === "oauth-failed" && (this.notice = { tone: "error", message: this.t("errorOAuth") }, o.setPending(null)), t?.type === "notice" && (this.notice = {
2113
+ tone: t.tone === "error" ? "error" : t.tone,
2114
+ message: t.message
2115
+ }, o.setPending(null));
2116
+ }
2117
+ /** Navigate between screens and reset transient state. */
2118
+ go(e) {
2119
+ this.step = e, this.error = "", this.busy = !1, this.showPassword = !1, e !== "mfa" && (this.challenge = null), e !== "email-otp" && e !== "phone" && e !== "magic-url" && (this.token = null), this.fire("authui-view", { view: e });
2120
+ }
2121
+ // ───────────────────────────── actions ─────────────────────────────
2122
+ async run(e, t = "link") {
2123
+ if (!this.busy) {
2124
+ this.busy = !0, this.error = "";
2125
+ try {
2126
+ await e();
2127
+ } catch (i) {
2128
+ this.error = Z(i, this.strings, t);
2129
+ } finally {
2130
+ this.busy = !1;
2131
+ }
2132
+ }
2133
+ }
2134
+ bind(e) {
2135
+ return (t) => {
2136
+ this[e] = t.target.value;
2137
+ };
2138
+ }
2139
+ // ───────────────────────────── render ─────────────────────────────
2140
+ render() {
2141
+ const e = this.renderStep();
2142
+ return s`
2143
+ <div class="panel ${this.embedded ? "embedded" : ""}" part="panel">
2144
+ ${this.renderHeader()}
2145
+ ${this.notice ? s`<div class="alert alert-${this.notice.tone}" role="status">
2146
+ ${this.notice.tone === "success" ? c.checkCircle : this.notice.tone === "error" ? c.alert : c.info}
2147
+ <div class="alert-body">${this.notice.message}</div>
2148
+ <button
2149
+ class="btn btn-ghost btn-icon dismiss"
2150
+ @click=${() => this.notice = null}
2151
+ aria-label=${this.t("close")}
2152
+ >
2153
+ ${c.x}
2154
+ </button>
2155
+ </div>` : n}
2156
+ ${e}
2157
+ </div>
2158
+ `;
2159
+ }
2160
+ renderHeader() {
2161
+ const e = this.config?.branding?.logo, t = this.productName;
2162
+ let i = "", r = "";
2163
+ switch (this.step) {
2164
+ case "sign-in":
2165
+ i = this.auth.status === "signed-in" ? this.t("signedInAs") : t ? this.t("signInTitle", { name: t }) : this.t("welcomeBack");
2166
+ break;
2167
+ case "sign-up":
2168
+ i = t ? this.t("signUpTitle", { name: t }) : this.t("createAccount");
2169
+ break;
2170
+ case "forgot-password":
2171
+ case "reset-password":
2172
+ i = this.t("resetPassword");
2173
+ break;
2174
+ case "magic-url":
2175
+ case "email-otp":
2176
+ i = this.t("continueWithEmail");
2177
+ break;
2178
+ case "phone":
2179
+ i = this.t("continueWithPhone");
2180
+ break;
2181
+ case "mfa":
2182
+ i = this.t("mfaTitle"), r = this.t("mfaDescription");
2183
+ break;
2184
+ }
2185
+ return s`
2186
+ <header class="header">
2187
+ ${e ? s`<img class="logo" src=${e} alt=${t || "Logo"} />` : n}
2188
+ <h2 class="title" id="authui-title">${i}</h2>
2189
+ ${r ? s`<p class="description">${r}</p>` : n}
2190
+ </header>
2191
+ `;
2192
+ }
2193
+ renderError() {
2194
+ return this.error ? s`<div class="alert alert-error" role="alert">
2195
+ ${c.alert}
2196
+ <div class="alert-body">${this.error}</div>
2197
+ </div>` : n;
2198
+ }
2199
+ submitButton(e, t = "btn-primary") {
2200
+ return s`<button class="btn ${t} btn-block" type="submit" ?disabled=${this.busy}>
2201
+ ${this.busy ? s`<span class="spinner" aria-hidden="true"></span>` : n} ${e}
2202
+ </button>`;
2203
+ }
2204
+ passwordField(e) {
2205
+ return s`
2206
+ <div class="field">
2207
+ <label class="label" for=${e.id}>
2208
+ ${e.label}
2209
+ ${e.forgot ? s`<button
2210
+ type="button"
2211
+ class="btn btn-link small"
2212
+ @click=${() => this.go("forgot-password")}
2213
+ >
2214
+ ${this.t("forgotPassword")}
2215
+ </button>` : n}
2216
+ </label>
2217
+ <div class="input-wrap">
2218
+ <input
2219
+ class="input"
2220
+ id=${e.id}
2221
+ type=${this.showPassword ? "text" : "password"}
2222
+ autocomplete=${e.autocomplete}
2223
+ required
2224
+ minlength="8"
2225
+ .value=${this[e.field]}
2226
+ @input=${this.bind(e.field)}
2227
+ />
2228
+ <button
2229
+ type="button"
2230
+ class="btn btn-ghost btn-icon"
2231
+ @click=${() => this.showPassword = !this.showPassword}
2232
+ aria-label=${this.showPassword ? "Hide password" : "Show password"}
2233
+ tabindex="-1"
2234
+ >
2235
+ ${this.showPassword ? c.eyeOff : c.eye}
2236
+ </button>
2237
+ </div>
2238
+ ${e.hint ? s`<p class="hint">${e.hint}</p>` : n}
2239
+ </div>
2240
+ `;
2241
+ }
2242
+ emailField(e = "email") {
2243
+ return s`
2244
+ <div class="field">
2245
+ <label class="label" for="authui-email">${this.t("email")}</label>
2246
+ <input
2247
+ class="input"
2248
+ id="authui-email"
2249
+ type="email"
2250
+ autocomplete=${e}
2251
+ required
2252
+ inputmode="email"
2253
+ .value=${this.email}
2254
+ @input=${this.bind("email")}
2255
+ />
2256
+ </div>
2257
+ `;
2258
+ }
2259
+ codeField() {
2260
+ return s`
2261
+ <div class="field">
2262
+ <label class="label" for="authui-code">${this.t("code")}</label>
2263
+ <input
2264
+ class="input input-otp"
2265
+ id="authui-code"
2266
+ type="text"
2267
+ inputmode="numeric"
2268
+ autocomplete="one-time-code"
2269
+ required
2270
+ .value=${this.code}
2271
+ @input=${this.bind("code")}
2272
+ />
2273
+ </div>
2274
+ `;
2275
+ }
2276
+ legal() {
2277
+ const e = this.config?.legal;
2278
+ return !e?.termsUrl && !e?.privacyUrl ? n : s`<p class="legal">
2279
+ ${this.t("agreeTo")}
2280
+ ${e.termsUrl ? s`<a href=${e.termsUrl} target="_blank" rel="noopener">${this.t("terms")}</a>` : n}
2281
+ ${e.termsUrl && e.privacyUrl ? s` ${this.t("and")} ` : n}
2282
+ ${e.privacyUrl ? s`<a href=${e.privacyUrl} target="_blank" rel="noopener">${this.t("privacy")}</a>` : n}.
2283
+ </p>`;
2284
+ }
2285
+ backLink(e = "sign-in") {
2286
+ return s`<div class="links">
2287
+ <button type="button" class="btn btn-link" @click=${() => this.go(e)}>
2288
+ ${c.arrowLeft} ${this.t("back")}
2289
+ </button>
2290
+ </div>`;
2291
+ }
2292
+ renderStep() {
2293
+ if (!this.auth.configured)
2294
+ return s`<div class="alert alert-error" role="alert">
2295
+ ${c.alert}
2296
+ <div class="alert-body">${this.t("errorNotConfigured")}</div>
2297
+ </div>`;
2298
+ if (this.auth.status === "loading")
2299
+ return s`<div class="empty"><span class="spinner"></span></div>`;
2300
+ if (this.auth.status === "signed-in" && this.step !== "mfa") return this.renderSignedIn();
2301
+ switch (this.step) {
2302
+ case "sign-up":
2303
+ return this.renderSignUp();
2304
+ case "forgot-password":
2305
+ return this.renderForgot();
2306
+ case "reset-password":
2307
+ return this.renderReset();
2308
+ case "magic-url":
2309
+ return this.renderMagicUrl();
2310
+ case "email-otp":
2311
+ return this.renderEmailOtp();
2312
+ case "phone":
2313
+ return this.renderPhone();
2314
+ case "mfa":
2315
+ return this.renderMfa();
2316
+ default:
2317
+ return this.renderSignIn();
2318
+ }
2319
+ }
2320
+ renderSignedIn() {
2321
+ const e = this.auth.user, t = e.name || e.email || e.phone || this.t("guestAccount");
2322
+ return s`
2323
+ <div class="stack">
2324
+ <div class="row">
2325
+ <div class="inline">
2326
+ <span class="avatar">${t[0] ?? "?"}</span>
2327
+ <div class="row-main">
2328
+ <span class="row-title">${t}</span>
2329
+ ${e.email && e.name ? s`<span class="row-sub">${e.email}</span>` : n}
2330
+ </div>
2331
+ </div>
2332
+ </div>
2333
+ ${this.renderError()}
2334
+ <div class="stack-sm">
2335
+ ${this.config?.successUrl ? s`<a class="btn btn-primary btn-block" href=${this.config.successUrl}
2336
+ >${this.t("continue")}</a
2337
+ >` : n}
2338
+ <button
2339
+ class="btn btn-outline btn-block"
2340
+ @click=${() => this.fire("authui-open", { view: "account" })}
2341
+ >
2342
+ ${c.settings} ${this.t("manageAccount")}
2343
+ </button>
2344
+ <button class="btn btn-ghost btn-block" @click=${this.onSignOut} ?disabled=${this.busy}>
2345
+ ${c.logOut} ${this.t("signOut")}
2346
+ </button>
2347
+ </div>
2348
+ </div>
2349
+ `;
2350
+ }
2351
+ renderProviders() {
2352
+ const e = this.config?.methods?.oauth ?? [];
2353
+ if (e.length === 0) return n;
2354
+ const t = e.length > 2;
2355
+ return s`
2356
+ <div class="providers ${t ? "two" : ""}">
2357
+ ${e.map(
2358
+ (i) => s`<button
2359
+ type="button"
2360
+ class="btn btn-outline"
2361
+ @click=${() => this.onOAuth(i)}
2362
+ ?disabled=${this.busy}
2363
+ aria-label=${this.t("continueWith", { provider: E(i) })}
2364
+ >
2365
+ ${L(i)}
2366
+ <span
2367
+ >${t ? E(i) : this.t("continueWith", { provider: E(i) })}</span
2368
+ >
2369
+ </button>`
2370
+ )}
2371
+ </div>
2372
+ `;
2373
+ }
2374
+ renderSignIn() {
2375
+ const e = this.config?.methods ?? {}, t = e.emailPassword !== !1, i = (e.oauth?.length ?? 0) > 0, r = [
2376
+ e.magicUrl ? { step: "magic-url", icon: c.link, label: this.t("sendMagicLink") } : null,
2377
+ e.emailOtp ? { step: "email-otp", icon: c.mail, label: this.t("continueWithEmail") } : null,
2378
+ e.phone ? { step: "phone", icon: c.smartphone, label: this.t("continueWithPhone") } : null
2379
+ ].filter(Boolean);
2380
+ return s`
2381
+ <div class="stack">
2382
+ ${this.renderProviders()}
2383
+ ${i && (t || r.length > 0) ? s`<div class="separator-text">${this.t("or")}</div>` : n}
2384
+ ${t ? s`<form class="form" @submit=${this.onSignIn} novalidate>
2385
+ ${this.emailField()}
2386
+ ${this.passwordField({ label: this.t("password"), autocomplete: "current-password", id: "authui-password", field: "password", forgot: !0 })}
2387
+ ${this.renderError()} ${this.submitButton(this.t("signIn"))}
2388
+ </form>` : this.renderError()}
2389
+ ${r.length > 0 ? s`<div class="stack-sm">
2390
+ ${r.map(
2391
+ (a) => s`<button
2392
+ type="button"
2393
+ class="btn btn-secondary btn-block"
2394
+ @click=${() => this.go(a.step)}
2395
+ >
2396
+ ${a.icon} ${a.label}
2397
+ </button>`
2398
+ )}
2399
+ </div>` : n}
2400
+ ${e.anonymous ? s`<button
2401
+ type="button"
2402
+ class="btn btn-ghost btn-block"
2403
+ @click=${this.onGuest}
2404
+ ?disabled=${this.busy}
2405
+ >
2406
+ ${c.ghost} ${this.t("continueAsGuest")}
2407
+ </button>` : n}
2408
+ ${t && this.config?.signUp !== !1 ? s`<div class="links">
2409
+ <span>${this.t("noAccount")}</span>
2410
+ <button type="button" class="btn btn-link" @click=${() => this.go("sign-up")}>
2411
+ ${this.t("signUp")}
2412
+ </button>
2413
+ </div>` : n}
2414
+ ${this.legal()}
2415
+ </div>
2416
+ `;
2417
+ }
2418
+ renderSignUp() {
2419
+ return s`
2420
+ <div class="stack">
2421
+ ${this.renderProviders()}
2422
+ ${(this.config?.methods?.oauth?.length ?? 0) > 0 ? s`<div class="separator-text">${this.t("or")}</div>` : n}
2423
+ <form class="form" @submit=${this.onSignUp} novalidate>
2424
+ ${this.config?.requireName !== !1 ? s`<div class="field">
2425
+ <label class="label" for="authui-name">${this.t("name")}</label>
2426
+ <input
2427
+ class="input"
2428
+ id="authui-name"
2429
+ type="text"
2430
+ autocomplete="name"
2431
+ required
2432
+ .value=${this.name}
2433
+ @input=${this.bind("name")}
2434
+ />
2435
+ </div>` : n}
2436
+ ${this.emailField()}
2437
+ ${this.passwordField({ label: this.t("password"), autocomplete: "new-password", id: "authui-password", field: "password", hint: this.t("passwordHint") })}
2438
+ ${this.renderError()} ${this.submitButton(this.t("createAccount"))}
2439
+ </form>
2440
+ <div class="links">
2441
+ <span>${this.t("haveAccount")}</span>
2442
+ <button type="button" class="btn btn-link" @click=${() => this.go("sign-in")}>
2443
+ ${this.t("signIn")}
2444
+ </button>
2445
+ </div>
2446
+ ${this.legal()}
2447
+ </div>
2448
+ `;
2449
+ }
2450
+ renderForgot() {
2451
+ return s`
2452
+ <div class="stack">
2453
+ <form class="form" @submit=${this.onForgot} novalidate>
2454
+ ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendResetLink"))}
2455
+ </form>
2456
+ ${this.backLink()}
2457
+ </div>
2458
+ `;
2459
+ }
2460
+ renderReset() {
2461
+ return this.recovery ? s`
2462
+ <div class="stack">
2463
+ <form class="form" @submit=${this.onReset} novalidate>
2464
+ ${this.passwordField({ label: this.t("newPassword"), autocomplete: "new-password", id: "authui-password", field: "password", hint: this.t("passwordHint") })}
2465
+ ${this.passwordField({ label: this.t("confirmPassword"), autocomplete: "new-password", id: "authui-password-confirm", field: "passwordConfirm" })}
2466
+ ${this.renderError()} ${this.submitButton(this.t("resetPassword"))}
2467
+ </form>
2468
+ ${this.backLink()}
2469
+ </div>
2470
+ ` : s`<div class="stack">
2471
+ <div class="alert alert-error" role="alert">
2472
+ ${c.alert}
2473
+ <div class="alert-body">${this.t("errorInvalidToken")}</div>
2474
+ </div>
2475
+ ${this.backLink()}
2476
+ </div>`;
2477
+ }
2478
+ phraseBox(e) {
2479
+ return e ? s`<div class="alert alert-info">
2480
+ ${c.shield}
2481
+ <div class="alert-title">
2482
+ ${this.t("securityPhrase")}: <span class="code">${e}</span>
2483
+ </div>
2484
+ <div class="alert-body">${this.t("securityPhraseHint")}</div>
2485
+ </div>` : n;
2486
+ }
2487
+ renderMagicUrl() {
2488
+ return this.token ? s`<div class="stack">
2489
+ <div class="alert alert-success" role="status">
2490
+ ${c.mail}
2491
+ <div class="alert-body">${this.t("magicLinkSent", { email: this.token.target })}</div>
2492
+ </div>
2493
+ ${this.phraseBox(this.token.phrase)} ${this.backLink()}
2494
+ </div>` : s`
2495
+ <div class="stack">
2496
+ <form class="form" @submit=${this.onMagicUrl} novalidate>
2497
+ ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendMagicLink"))}
2498
+ </form>
2499
+ ${this.backLink()}
2500
+ </div>
2501
+ `;
2502
+ }
2503
+ renderCodeEntry() {
2504
+ return s`
2505
+ <div class="alert alert-info" role="status">
2506
+ ${c.mail}
2507
+ <div class="alert-body">${this.t("codeSent", { target: this.token.target })}</div>
2508
+ </div>
2509
+ ${this.phraseBox(this.token.phrase)}
2510
+ <form class="form" @submit=${this.onVerifyCode} novalidate>
2511
+ ${this.codeField()} ${this.renderError()} ${this.submitButton(this.t("verifyCode"))}
2512
+ </form>
2513
+ <div class="links">
2514
+ <button type="button" class="btn btn-link" @click=${() => this.token = null}>
2515
+ ${this.t("sendCode")}
2516
+ </button>
2517
+ <span aria-hidden="true">·</span>
2518
+ <button type="button" class="btn btn-link" @click=${() => this.go("sign-in")}>
2519
+ ${this.t("back")}
2520
+ </button>
2521
+ </div>
2522
+ `;
2523
+ }
2524
+ renderEmailOtp() {
2525
+ return this.token ? s`<div class="stack">${this.renderCodeEntry()}</div>` : s`
2526
+ <div class="stack">
2527
+ <form class="form" @submit=${this.onEmailOtp} novalidate>
2528
+ ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendCode"))}
2529
+ </form>
2530
+ ${this.backLink()}
2531
+ </div>
2532
+ `;
2533
+ }
2534
+ renderPhone() {
2535
+ return this.token ? s`<div class="stack">${this.renderCodeEntry()}</div>` : s`
2536
+ <div class="stack">
2537
+ <form class="form" @submit=${this.onPhoneOtp} novalidate>
2538
+ <div class="field">
2539
+ <label class="label" for="authui-phone">${this.t("phone")}</label>
2540
+ <input
2541
+ class="input"
2542
+ id="authui-phone"
2543
+ type="tel"
2544
+ autocomplete="tel"
2545
+ placeholder="+1 555 000 0000"
2546
+ required
2547
+ .value=${this.phone}
2548
+ @input=${this.bind("phone")}
2549
+ />
2550
+ </div>
2551
+ ${this.renderError()} ${this.submitButton(this.t("sendCode"))}
2552
+ </form>
2553
+ ${this.backLink()}
2554
+ </div>
2555
+ `;
2556
+ }
2557
+ renderMfa() {
2558
+ const e = this.auth.mfaFactors;
2559
+ if (!this.challenge) {
2560
+ const i = [
2561
+ {
2562
+ factor: "totp",
2563
+ icon: c.smartphone,
2564
+ label: this.t("mfaUseAuthenticator"),
2565
+ available: e?.totp ?? !0
2566
+ },
2567
+ {
2568
+ factor: "email",
2569
+ icon: c.mail,
2570
+ label: this.t("mfaUseEmail"),
2571
+ available: e?.email ?? !0
2572
+ },
2573
+ {
2574
+ factor: "phone",
2575
+ icon: c.phone,
2576
+ label: this.t("mfaUsePhone"),
2577
+ available: e?.phone ?? !0
2578
+ },
2579
+ {
2580
+ factor: "recoverycode",
2581
+ icon: c.key,
2582
+ label: this.t("mfaUseRecoveryCode"),
2583
+ available: e?.recoveryCode ?? !0
2584
+ }
2585
+ ];
2586
+ return s`
2587
+ <div class="stack">
2588
+ <div class="stack-sm">
2589
+ ${i.filter((r) => r.available).map(
2590
+ (r) => s`<button
2591
+ type="button"
2592
+ class="choice"
2593
+ @click=${() => this.onChooseFactor(r.factor)}
2594
+ ?disabled=${this.busy}
2595
+ >
2596
+ ${r.icon}<span class="choice-title">${r.label}</span>
2597
+ </button>`
2598
+ )}
2599
+ </div>
2600
+ ${this.renderError()}
2601
+ <div class="links">
2602
+ <button type="button" class="btn btn-link" @click=${this.onCancelMfa}>
2603
+ ${this.t("cancel")}
2604
+ </button>
2605
+ </div>
2606
+ </div>
2607
+ `;
2608
+ }
2609
+ const t = this.challenge.factor === "recoverycode";
2610
+ return s`
2611
+ <div class="stack">
2612
+ <form class="form" @submit=${this.onVerifyFactor} novalidate>
2613
+ ${t ? s`<div class="field">
2614
+ <label class="label" for="authui-code">${this.t("recoveryCode")}</label>
2615
+ <input
2616
+ class="input mono"
2617
+ id="authui-code"
2618
+ type="text"
2619
+ autocomplete="off"
2620
+ required
2621
+ .value=${this.code}
2622
+ @input=${this.bind("code")}
2623
+ />
2624
+ </div>` : this.codeField()}
2625
+ ${this.renderError()} ${this.submitButton(this.t("verifyCode"))}
2626
+ </form>
2627
+ <div class="links">
2628
+ <button type="button" class="btn btn-link" @click=${() => this.challenge = null}>
2629
+ ${c.arrowLeft} ${this.t("back")}
2630
+ </button>
2631
+ <span aria-hidden="true">·</span>
2632
+ <button type="button" class="btn btn-link" @click=${this.onCancelMfa}>
2633
+ ${this.t("cancel")}
2634
+ </button>
2635
+ </div>
2636
+ </div>
2637
+ `;
2638
+ }
2639
+ };
2640
+ $.styles = [...x.styles, ft];
2641
+ C([
2642
+ g({ type: String })
2643
+ ], $.prototype, "view", 2);
2644
+ C([
2645
+ g({ type: Boolean })
2646
+ ], $.prototype, "embedded", 2);
2647
+ C([
2648
+ d()
2649
+ ], $.prototype, "step", 2);
2650
+ C([
2651
+ d()
2652
+ ], $.prototype, "busy", 2);
2653
+ C([
2654
+ d()
2655
+ ], $.prototype, "error", 2);
2656
+ C([
2657
+ d()
2658
+ ], $.prototype, "notice", 2);
2659
+ C([
2660
+ d()
2661
+ ], $.prototype, "showPassword", 2);
2662
+ C([
2663
+ d()
2664
+ ], $.prototype, "token", 2);
2665
+ C([
2666
+ d()
2667
+ ], $.prototype, "challenge", 2);
2668
+ C([
2669
+ d()
2670
+ ], $.prototype, "recovery", 2);
2671
+ C([
2672
+ X("form input:not([type=hidden])")
2673
+ ], $.prototype, "firstInput", 2);
2674
+ $ = C([
2675
+ S("authui-sign-in")
2676
+ ], $);
2677
+ var vt = Object.defineProperty, yt = Object.getOwnPropertyDescriptor, m = (e, t, i, r) => {
2678
+ for (var a = r > 1 ? void 0 : r ? yt(t, i) : t, u = e.length - 1, h; u >= 0; u--)
2679
+ (h = e[u]) && (a = (r ? h(t, i, a) : h(a)) || a);
2680
+ return r && a && vt(t, i, a), a;
2681
+ };
2682
+ let p = class extends x {
2683
+ constructor() {
2684
+ super(...arguments), this.embedded = !1, this.tab = "profile", this.active = "profile", this.busy = "", this.notice = null, this.errors = {}, this.nameInput = "", this.emailInput = "", this.emailPassword = "", this.phoneInput = "", this.phonePassword = "", this.phoneCode = "", this.phoneCodeSent = !1, this.guestName = "", this.oldPassword = "", this.newPassword = "", this.newPasswordConfirm = "", this.authenticator = null, this.authenticatorCode = "", this.factors = null, this.recoveryCodes = null, this.stepUp = null, this.stepUpCode = "", this.copied = !1, this.sessions = null, this.identities = null, this.logs = null, this.logsSupported = !0, this.confirmDelete = !1, this.factorsLoading = !1, this.onUpdateName = (e) => {
2685
+ e.preventDefault(), this.run("name", () => o.updateName(this.nameInput), this.t("done"));
2686
+ }, this.onUpdateEmail = (e) => {
2687
+ e.preventDefault(), this.run(
2688
+ "email",
2689
+ async () => {
2690
+ await o.updateEmail(this.emailInput, this.emailPassword), this.emailPassword = "";
2691
+ },
2692
+ this.t("done")
2693
+ );
2694
+ }, this.onUpdatePhone = (e) => {
2695
+ e.preventDefault(), this.run(
2696
+ "phone",
2697
+ async () => {
2698
+ await o.updatePhone(this.phoneInput, this.phonePassword), this.phonePassword = "";
2699
+ },
2700
+ this.t("done")
2701
+ );
2702
+ }, this.onConvertGuest = (e) => {
2703
+ e.preventDefault(), this.run(
2704
+ "guest",
2705
+ async () => {
2706
+ await o.convertGuest(this.emailInput, this.emailPassword, this.guestName), this.emailPassword = "";
2707
+ },
2708
+ this.t("done")
2709
+ );
2710
+ }, this.onSendVerification = () => {
2711
+ this.run("verify", () => o.sendEmailVerification(), this.t("verificationSent"));
2712
+ }, this.onSendPhoneVerification = () => {
2713
+ this.run("verify-phone", async () => {
2714
+ await o.sendPhoneVerification(), this.phoneCodeSent = !0;
2715
+ });
2716
+ }, this.onConfirmPhoneVerification = (e) => {
2717
+ e.preventDefault(), this.run(
2718
+ "verify-phone-code",
2719
+ async () => {
2720
+ await o.confirmPhoneVerification(this.phoneCode), this.phoneCode = "", this.phoneCodeSent = !1;
2721
+ },
2722
+ this.t("done")
2723
+ );
2724
+ }, this.onChangePassword = (e) => {
2725
+ if (e.preventDefault(), this.newPassword !== this.newPasswordConfirm) {
2726
+ this.errors = { ...this.errors, password: this.t("errorPasswordMismatch") };
2727
+ return;
2728
+ }
2729
+ this.run(
2730
+ "password",
2731
+ async () => {
2732
+ await o.updatePassword(this.newPassword, this.oldPassword), this.oldPassword = this.newPassword = this.newPasswordConfirm = "";
2733
+ },
2734
+ this.t("passwordUpdated")
2735
+ );
2736
+ }, this.onToggleMfa = () => {
2737
+ const e = !this.user?.mfa;
2738
+ this.run("mfa", async () => {
2739
+ await o.setMfaEnabled(e), await this.loadFactors();
2740
+ });
2741
+ }, this.onAddAuthenticator = () => {
2742
+ this.run("authenticator", async () => {
2743
+ this.authenticator = await o.addAuthenticator(), this.authenticatorCode = "";
2744
+ });
2745
+ }, this.onVerifyAuthenticator = (e) => {
2746
+ e.preventDefault(), this.run(
2747
+ "authenticator-code",
2748
+ async () => {
2749
+ await o.verifyAuthenticator(this.authenticatorCode), this.authenticator = null, this.authenticatorCode = "", await this.loadFactors();
2750
+ },
2751
+ this.t("done")
2752
+ );
2753
+ }, this.onRemoveAuthenticator = () => {
2754
+ this.run("remove-authenticator", async () => {
2755
+ await o.removeAuthenticator(), await this.loadFactors();
2756
+ });
2757
+ }, this.onRecoveryCodes = () => {
2758
+ this.run("recovery", async () => {
2759
+ try {
2760
+ this.recoveryCodes = await o.createRecoveryCodes();
2761
+ } catch (e) {
2762
+ if (!F(e, b.recoveryCodesExist)) throw e;
2763
+ this.recoveryCodes = await o.getRecoveryCodes();
2764
+ }
2765
+ await this.loadFactors();
2766
+ });
2767
+ }, this.onRegenerateRecoveryCodes = () => {
2768
+ this.run("recovery", async () => {
2769
+ this.recoveryCodes = await o.regenerateRecoveryCodes();
2770
+ });
2771
+ }, this.onCopyCodes = async () => {
2772
+ if (this.recoveryCodes)
2773
+ try {
2774
+ await navigator.clipboard.writeText(this.recoveryCodes.join(`
2775
+ `)), this.copied = !0, setTimeout(() => this.copied = !1, 1500);
2776
+ } catch {
2777
+ }
2778
+ }, this.onStepUpFactor = (e) => {
2779
+ this.run("stepup", async () => {
2780
+ const t = await o.createMfaChallenge(e);
2781
+ this.stepUp = { ...this.stepUp, challenge: { id: t.$id, factor: e } }, this.stepUpCode = "";
2782
+ });
2783
+ }, this.onStepUpVerify = (e) => {
2784
+ e.preventDefault();
2785
+ const t = this.stepUp;
2786
+ t?.challenge && this.run("stepup-code", async () => {
2787
+ await o.completeMfaChallenge(t.challenge.id, this.stepUpCode, { signIn: !1 }), this.stepUp = null, this.stepUpCode = "", await t.retry();
2788
+ });
2789
+ }, this.onDeleteSession = (e) => {
2790
+ this.run(`session-${e}`, async () => {
2791
+ await o.signOut(e), this.sessions = (this.sessions ?? []).filter((t) => t.$id !== e);
2792
+ });
2793
+ }, this.onSignOutAll = () => {
2794
+ this.run("sessions-all", () => o.signOutEverywhere());
2795
+ }, this.onDeleteIdentity = (e) => {
2796
+ this.run(`identity-${e}`, async () => {
2797
+ await o.deleteIdentity(e), this.identities = (this.identities ?? []).filter((t) => t.$id !== e);
2798
+ });
2799
+ }, this.onDeleteAccount = () => {
2800
+ this.run("delete", () => o.deleteAccount());
2801
+ };
2802
+ }
2803
+ connectedCallback() {
2804
+ super.connectedCallback(), this.active = this.tab, this.hydrate();
2805
+ }
2806
+ willUpdate(e) {
2807
+ e.has("tab") && e.get("tab") !== void 0 && (this.active = this.tab), e.has("auth") && this.hydrate(), this.ensureLoaded();
2808
+ }
2809
+ /** Lazily load data for the active tab once a user is available. */
2810
+ ensureLoaded() {
2811
+ !this.user || this.busy || (this.active === "sessions" && this.sessions === null ? this.loadSessions() : this.active === "connections" && this.identities === null ? this.loadIdentities() : this.active === "activity" && this.logs === null ? this.loadLogs() : this.active === "security" && this.factors === null && this.loadFactors());
2812
+ }
2813
+ hydrate() {
2814
+ const e = this.auth.user;
2815
+ e && (this.nameInput || (this.nameInput = e.name ?? ""), this.emailInput || (this.emailInput = e.email ?? ""), this.phoneInput || (this.phoneInput = e.phone ?? ""));
2816
+ }
2817
+ get user() {
2818
+ return this.auth.user;
2819
+ }
2820
+ get isGuest() {
2821
+ const e = this.user;
2822
+ return !!e && !e.email && !e.phone;
2823
+ }
2824
+ select(e) {
2825
+ this.active = e, this.notice = null, this.errors = {};
2826
+ }
2827
+ /** Run an action with a busy key, surfacing errors under that key. Handles MFA step-up. */
2828
+ async run(e, t, i) {
2829
+ if (!this.busy) {
2830
+ this.busy = e, this.errors = { ...this.errors, [e]: "" };
2831
+ try {
2832
+ await t(), i && (this.notice = { tone: "success", message: i });
2833
+ } catch (r) {
2834
+ F(r, b.challengeRequired) ? this.stepUp = { retry: () => this.run(e, t, i) } : this.errors = {
2835
+ ...this.errors,
2836
+ [e]: Z(r, this.strings, e.includes("code") ? "code" : "link")
2837
+ };
2838
+ } finally {
2839
+ this.busy = "";
2840
+ }
2841
+ }
2842
+ }
2843
+ // ─────────────────────────── loaders ───────────────────────────
2844
+ async loadSessions() {
2845
+ await this.run("sessions", async () => {
2846
+ this.sessions = await o.listSessions();
2847
+ });
2848
+ }
2849
+ async loadIdentities() {
2850
+ await this.run("identities", async () => {
2851
+ this.identities = await o.listIdentities();
2852
+ });
2853
+ }
2854
+ async loadLogs() {
2855
+ this.busy = "logs";
2856
+ try {
2857
+ this.logs = await o.listLogs();
2858
+ } catch {
2859
+ this.logsSupported = !1, this.logs = [];
2860
+ } finally {
2861
+ this.busy = "";
2862
+ }
2863
+ }
2864
+ async loadFactors() {
2865
+ if (!this.factorsLoading) {
2866
+ this.factorsLoading = !0;
2867
+ try {
2868
+ this.factors = await o.listMfaFactors();
2869
+ } catch {
2870
+ this.factors = {
2871
+ totp: !1,
2872
+ phone: !1,
2873
+ email: !1,
2874
+ recoveryCode: !1,
2875
+ custom: !1
2876
+ };
2877
+ } finally {
2878
+ this.factorsLoading = !1;
2879
+ }
2880
+ }
2881
+ }
2882
+ bind(e) {
2883
+ return (t) => {
2884
+ this[e] = t.target.value;
2885
+ };
2886
+ }
2887
+ // ─────────────────────────── render ───────────────────────────
2888
+ render() {
2889
+ if (!this.auth.configured)
2890
+ return s`<div class="alert alert-error" role="alert">
2891
+ ${c.alert}
2892
+ <div class="alert-body">${this.t("errorNotConfigured")}</div>
2893
+ </div>`;
2894
+ if (this.auth.status === "loading")
2895
+ return s`<div class="empty"><span class="spinner"></span></div>`;
2896
+ if (!this.user)
2897
+ return s`<div class="panel ${this.embedded ? "embedded" : ""}">
2898
+ <authui-sign-in embedded></authui-sign-in>
2899
+ </div>`;
2900
+ const e = [
2901
+ { id: "profile", label: this.t("profile") },
2902
+ { id: "security", label: this.t("security") },
2903
+ { id: "sessions", label: this.t("sessions") },
2904
+ { id: "connections", label: this.t("connections") },
2905
+ ...this.logsSupported ? [{ id: "activity", label: this.t("activity") }] : []
2906
+ ];
2907
+ return s`
2908
+ <div class="panel ${this.embedded ? "embedded" : ""}" part="panel">
2909
+ ${this.renderIdentity()}
2910
+ <div class="tabs" role="tablist">
2911
+ ${e.map(
2912
+ (t) => s`<button
2913
+ class="tab"
2914
+ role="tab"
2915
+ aria-selected=${this.active === t.id ? "true" : "false"}
2916
+ @click=${() => this.select(t.id)}
2917
+ >
2918
+ ${t.label}
2919
+ </button>`
2920
+ )}
2921
+ </div>
2922
+ ${this.notice ? s`<div class="alert alert-${this.notice.tone}" role="status">
2923
+ ${this.notice.tone === "success" ? c.checkCircle : c.info}
2924
+ <div class="alert-body">${this.notice.message}</div>
2925
+ </div>` : n}
2926
+ ${this.stepUp ? this.renderStepUp() : this.renderTab()}
2927
+ </div>
2928
+ `;
2929
+ }
2930
+ renderIdentity() {
2931
+ const e = this.user, t = e.name || e.email || e.phone || this.t("guestAccount");
2932
+ return s`
2933
+ <div class="between">
2934
+ <div class="identity">
2935
+ <span class="avatar">${t[0] ?? "?"}</span>
2936
+ <div class="row-main">
2937
+ <span class="row-title">
2938
+ ${t}
2939
+ ${e.mfa ? s`<span class="badge badge-success">${c.shieldCheck} MFA</span>` : n}
2940
+ </span>
2941
+ ${e.email && e.name ? s`<span class="row-sub">${e.email}</span>` : n}
2942
+ </div>
2943
+ </div>
2944
+ <button class="btn btn-outline btn-sm" @click=${() => o.signOut()}>
2945
+ ${c.logOut} ${this.t("signOut")}
2946
+ </button>
2947
+ </div>
2948
+ `;
2949
+ }
2950
+ renderTab() {
2951
+ switch (this.active) {
2952
+ case "security":
2953
+ return this.renderSecurity();
2954
+ case "sessions":
2955
+ return this.renderSessions();
2956
+ case "connections":
2957
+ return this.renderConnections();
2958
+ case "activity":
2959
+ return this.renderActivity();
2960
+ default:
2961
+ return this.renderProfile();
2962
+ }
2963
+ }
2964
+ error(e) {
2965
+ const t = this.errors[e];
2966
+ return t ? s`<div class="alert alert-error" role="alert">
2967
+ ${c.alert}
2968
+ <div class="alert-body">${t}</div>
2969
+ </div>` : n;
2970
+ }
2971
+ spinner(e) {
2972
+ return this.busy === e ? s`<span class="spinner" aria-hidden="true"></span>` : n;
2973
+ }
2974
+ card(e, t, i, r, a = !1) {
2975
+ return s`<section class="card ${a ? "card-danger" : ""}">
2976
+ <div class="card-header">
2977
+ <h3 class="card-title">${e}</h3>
2978
+ ${t ? s`<p class="card-description">${t}</p>` : n}
2979
+ </div>
2980
+ <div class="card-body">${i}</div>
2981
+ ${r ? s`<div class="card-footer">${r}</div>` : n}
2982
+ </section>`;
2983
+ }
2984
+ verifiedBadge(e) {
2985
+ return e ? s`<span class="badge badge-success">${c.check} ${this.t("verified")}</span>` : s`<span class="badge badge-warning">${this.t("unverified")}</span>`;
2986
+ }
2987
+ // ── Profile ──
2988
+ renderProfile() {
2989
+ const e = this.user;
2990
+ return this.isGuest ? s`<div class="section">
2991
+ ${this.card(
2992
+ this.t("guestAccount"),
2993
+ this.t("guestAccountDescription"),
2994
+ s`<form class="form" id="guest-form" @submit=${this.onConvertGuest} novalidate>
2995
+ <div class="field">
2996
+ <label class="label" for="guest-name">${this.t("name")}</label>
2997
+ <input
2998
+ class="input"
2999
+ id="guest-name"
3000
+ .value=${this.guestName}
3001
+ @input=${this.bind("guestName")}
3002
+ autocomplete="name"
3003
+ />
3004
+ </div>
3005
+ <div class="field">
3006
+ <label class="label" for="guest-email">${this.t("email")}</label>
3007
+ <input
3008
+ class="input"
3009
+ id="guest-email"
3010
+ type="email"
3011
+ required
3012
+ .value=${this.emailInput}
3013
+ @input=${this.bind("emailInput")}
3014
+ autocomplete="email"
3015
+ />
3016
+ </div>
3017
+ <div class="field">
3018
+ <label class="label" for="guest-password">${this.t("password")}</label>
3019
+ <input
3020
+ class="input"
3021
+ id="guest-password"
3022
+ type="password"
3023
+ required
3024
+ minlength="8"
3025
+ .value=${this.emailPassword}
3026
+ @input=${this.bind("emailPassword")}
3027
+ autocomplete="new-password"
3028
+ />
3029
+ <p class="hint">${this.t("passwordHint")}</p>
3030
+ </div>
3031
+ ${this.error("guest")}
3032
+ </form>`,
3033
+ s`<button
3034
+ class="btn btn-primary btn-sm"
3035
+ type="submit"
3036
+ form="guest-form"
3037
+ ?disabled=${!!this.busy}
3038
+ >
3039
+ ${this.spinner("guest")} ${this.t("createAccount")}
3040
+ </button>`
3041
+ )}
3042
+ </div>` : s`<div class="section">
3043
+ ${this.card(
3044
+ this.t("name"),
3045
+ void 0,
3046
+ s`<form class="form" id="name-form" @submit=${this.onUpdateName} novalidate>
3047
+ <div class="field">
3048
+ <label class="label" for="acc-name">${this.t("name")}</label>
3049
+ <input
3050
+ class="input"
3051
+ id="acc-name"
3052
+ .value=${this.nameInput}
3053
+ @input=${this.bind("nameInput")}
3054
+ autocomplete="name"
3055
+ required
3056
+ />
3057
+ </div>
3058
+ ${this.error("name")}
3059
+ </form>`,
3060
+ s`<button
3061
+ class="btn btn-primary btn-sm"
3062
+ type="submit"
3063
+ form="name-form"
3064
+ ?disabled=${!!this.busy || this.nameInput === e.name}
3065
+ >
3066
+ ${this.spinner("name")} ${this.t("update")}
3067
+ </button>`
3068
+ )}
3069
+ ${this.card(
3070
+ this.t("email"),
3071
+ void 0,
3072
+ s`<form class="form" id="email-form" @submit=${this.onUpdateEmail} novalidate>
3073
+ <div class="field">
3074
+ <label class="label" for="acc-email"
3075
+ >${this.t("email")}
3076
+ ${e.email ? this.verifiedBadge(e.emailVerification) : n}</label
3077
+ >
3078
+ <input
3079
+ class="input"
3080
+ id="acc-email"
3081
+ type="email"
3082
+ .value=${this.emailInput}
3083
+ @input=${this.bind("emailInput")}
3084
+ autocomplete="email"
3085
+ required
3086
+ />
3087
+ </div>
3088
+ ${this.emailInput !== e.email ? s`<div class="field">
3089
+ <label class="label" for="acc-email-password">${this.t("currentPassword")}</label>
3090
+ <input
3091
+ class="input"
3092
+ id="acc-email-password"
3093
+ type="password"
3094
+ .value=${this.emailPassword}
3095
+ @input=${this.bind("emailPassword")}
3096
+ autocomplete="current-password"
3097
+ required
3098
+ />
3099
+ </div>` : n}
3100
+ ${this.error("email")} ${this.error("verify")}
3101
+ </form>`,
3102
+ s`
3103
+ ${e.email && !e.emailVerification ? s`<button
3104
+ class="btn btn-outline btn-sm"
3105
+ type="button"
3106
+ @click=${this.onSendVerification}
3107
+ ?disabled=${!!this.busy}
3108
+ >
3109
+ ${this.spinner("verify")} ${this.t("verifyEmail")}
3110
+ </button>` : n}
3111
+ <button
3112
+ class="btn btn-primary btn-sm"
3113
+ type="submit"
3114
+ form="email-form"
3115
+ ?disabled=${!!this.busy || this.emailInput === e.email}
3116
+ >
3117
+ ${this.spinner("email")} ${this.t("update")}
3118
+ </button>
3119
+ `
3120
+ )}
3121
+ ${this.card(
3122
+ this.t("phone"),
3123
+ void 0,
3124
+ s`<form class="form" id="phone-form" @submit=${this.onUpdatePhone} novalidate>
3125
+ <div class="field">
3126
+ <label class="label" for="acc-phone"
3127
+ >${this.t("phone")}
3128
+ ${e.phone ? this.verifiedBadge(e.phoneVerification) : n}</label
3129
+ >
3130
+ <input
3131
+ class="input"
3132
+ id="acc-phone"
3133
+ type="tel"
3134
+ placeholder="+1 555 000 0000"
3135
+ .value=${this.phoneInput}
3136
+ @input=${this.bind("phoneInput")}
3137
+ autocomplete="tel"
3138
+ />
3139
+ </div>
3140
+ ${this.phoneInput !== e.phone ? s`<div class="field">
3141
+ <label class="label" for="acc-phone-password">${this.t("currentPassword")}</label>
3142
+ <input
3143
+ class="input"
3144
+ id="acc-phone-password"
3145
+ type="password"
3146
+ .value=${this.phonePassword}
3147
+ @input=${this.bind("phonePassword")}
3148
+ autocomplete="current-password"
3149
+ required
3150
+ />
3151
+ </div>` : n}
3152
+ ${this.phoneCodeSent ? s`<div class="field">
3153
+ <label class="label" for="acc-phone-code">${this.t("code")}</label>
3154
+ <input
3155
+ class="input input-otp"
3156
+ id="acc-phone-code"
3157
+ inputmode="numeric"
3158
+ autocomplete="one-time-code"
3159
+ .value=${this.phoneCode}
3160
+ @input=${this.bind("phoneCode")}
3161
+ />
3162
+ </div>` : n}
3163
+ ${this.error("phone")} ${this.error("verify-phone")} ${this.error("verify-phone-code")}
3164
+ </form>`,
3165
+ s`
3166
+ ${e.phone && !e.phoneVerification && !this.phoneCodeSent ? s`<button
3167
+ class="btn btn-outline btn-sm"
3168
+ type="button"
3169
+ @click=${this.onSendPhoneVerification}
3170
+ ?disabled=${!!this.busy}
3171
+ >
3172
+ ${this.spinner("verify-phone")} ${this.t("sendCode")}
3173
+ </button>` : n}
3174
+ ${this.phoneCodeSent ? s`<button
3175
+ class="btn btn-outline btn-sm"
3176
+ type="button"
3177
+ @click=${this.onConfirmPhoneVerification}
3178
+ ?disabled=${!!this.busy}
3179
+ >
3180
+ ${this.spinner("verify-phone-code")} ${this.t("verifyCode")}
3181
+ </button>` : n}
3182
+ <button
3183
+ class="btn btn-primary btn-sm"
3184
+ type="submit"
3185
+ form="phone-form"
3186
+ ?disabled=${!!this.busy || this.phoneInput === e.phone}
3187
+ >
3188
+ ${this.spinner("phone")} ${this.t("update")}
3189
+ </button>
3190
+ `
3191
+ )}
3192
+ ${this.renderDanger()}
3193
+ </div>`;
3194
+ }
3195
+ renderDanger() {
3196
+ return this.card(
3197
+ this.t("deleteAccount"),
3198
+ this.t("deleteAccountDescription"),
3199
+ s`${this.error("delete")}
3200
+ ${this.confirmDelete ? s`<div class="inline">
3201
+ <button
3202
+ class="btn btn-destructive btn-sm"
3203
+ @click=${this.onDeleteAccount}
3204
+ ?disabled=${!!this.busy}
3205
+ >
3206
+ ${this.spinner("delete")} ${this.t("deleteAccountConfirm")}
3207
+ </button>
3208
+ <button class="btn btn-ghost btn-sm" @click=${() => this.confirmDelete = !1}>
3209
+ ${this.t("cancel")}
3210
+ </button>
3211
+ </div>` : s`<button
3212
+ class="btn btn-outline btn-sm warn"
3213
+ @click=${() => this.confirmDelete = !0}
3214
+ >
3215
+ ${c.userX} ${this.t("deleteAccount")}
3216
+ </button>`}`,
3217
+ void 0,
3218
+ !0
3219
+ );
3220
+ }
3221
+ // ── Security ──
3222
+ renderSecurity() {
3223
+ const e = this.user, t = this.config?.mfa !== !1;
3224
+ return s`<div class="section">
3225
+ ${this.isGuest ? n : this.card(
3226
+ this.t("changePassword"),
3227
+ void 0,
3228
+ s`<form
3229
+ class="form"
3230
+ id="password-form"
3231
+ @submit=${this.onChangePassword}
3232
+ novalidate
3233
+ >
3234
+ ${e.passwordUpdate ? s`<div class="field">
3235
+ <label class="label" for="acc-old-password"
3236
+ >${this.t("currentPassword")}</label
3237
+ >
3238
+ <input
3239
+ class="input"
3240
+ id="acc-old-password"
3241
+ type="password"
3242
+ .value=${this.oldPassword}
3243
+ @input=${this.bind("oldPassword")}
3244
+ autocomplete="current-password"
3245
+ />
3246
+ </div>` : n}
3247
+ <div class="field">
3248
+ <label class="label" for="acc-new-password">${this.t("newPassword")}</label>
3249
+ <input
3250
+ class="input"
3251
+ id="acc-new-password"
3252
+ type="password"
3253
+ required
3254
+ minlength="8"
3255
+ .value=${this.newPassword}
3256
+ @input=${this.bind("newPassword")}
3257
+ autocomplete="new-password"
3258
+ />
3259
+ <p class="hint">${this.t("passwordHint")}</p>
3260
+ </div>
3261
+ <div class="field">
3262
+ <label class="label" for="acc-new-password-confirm"
3263
+ >${this.t("confirmPassword")}</label
3264
+ >
3265
+ <input
3266
+ class="input"
3267
+ id="acc-new-password-confirm"
3268
+ type="password"
3269
+ required
3270
+ minlength="8"
3271
+ .value=${this.newPasswordConfirm}
3272
+ @input=${this.bind("newPasswordConfirm")}
3273
+ autocomplete="new-password"
3274
+ />
3275
+ </div>
3276
+ ${this.error("password")}
3277
+ </form>`,
3278
+ s`<button
3279
+ class="btn btn-primary btn-sm"
3280
+ type="submit"
3281
+ form="password-form"
3282
+ ?disabled=${!!this.busy || !this.newPassword}
3283
+ >
3284
+ ${this.spinner("password")} ${this.t("update")}
3285
+ </button>`
3286
+ )}
3287
+ ${t ? this.renderMfaCard() : n}
3288
+ ${t ? this.renderRecoveryCard() : n}
3289
+ </div>`;
3290
+ }
3291
+ renderMfaCard() {
3292
+ const e = this.user, t = this.factors?.totp ?? !1, i = this.authenticator ? new tt(o.getClient()).getQR(this.authenticator.uri, 400, 1).toString() : "";
3293
+ return this.card(
3294
+ this.t("twoFactor"),
3295
+ this.t("twoFactorDescription"),
3296
+ s`<div class="kv">
3297
+ <div class="toggle-row">
3298
+ <div class="row-main">
3299
+ <span class="row-title">${this.t("twoFactor")}</span>
3300
+ <span class="row-sub">${e.mfa ? this.t("enable") : this.t("disable")}d</span>
3301
+ </div>
3302
+ <button
3303
+ class="switch"
3304
+ role="switch"
3305
+ aria-checked=${e.mfa ? "true" : "false"}
3306
+ @click=${this.onToggleMfa}
3307
+ ?disabled=${!!this.busy}
3308
+ aria-label=${this.t("twoFactor")}
3309
+ ></button>
3310
+ </div>
3311
+ ${this.error("mfa")}
3312
+ <div class="separator"></div>
3313
+ <div class="toggle-row">
3314
+ <div class="row-main">
3315
+ <span class="row-title"
3316
+ >${c.smartphone} ${this.t("authenticatorApp")}
3317
+ ${t ? this.verifiedBadge(!0) : n}</span
3318
+ >
3319
+ </div>
3320
+ ${t ? s`<button
3321
+ class="btn btn-outline btn-sm"
3322
+ @click=${this.onRemoveAuthenticator}
3323
+ ?disabled=${!!this.busy}
3324
+ >
3325
+ ${this.spinner("remove-authenticator")} ${this.t("remove")}
3326
+ </button>` : this.authenticator ? n : s`<button
3327
+ class="btn btn-outline btn-sm"
3328
+ @click=${this.onAddAuthenticator}
3329
+ ?disabled=${!!this.busy}
3330
+ >
3331
+ ${this.spinner("authenticator")} ${this.t("authenticatorAdd")}
3332
+ </button>`}
3333
+ </div>
3334
+ ${this.error("authenticator")} ${this.error("remove-authenticator")}
3335
+ ${this.authenticator ? s`<form class="form" @submit=${this.onVerifyAuthenticator} novalidate>
3336
+ <p class="hint">${this.t("authenticatorScan")}</p>
3337
+ <img class="qr" src=${i} alt="QR code" />
3338
+ <p class="hint center">
3339
+ ${this.t("authenticatorManual")}:
3340
+ <span class="code">${this.authenticator.secret}</span>
3341
+ </p>
3342
+ <div class="field">
3343
+ <label class="label" for="acc-totp">${this.t("code")}</label>
3344
+ <input
3345
+ class="input input-otp"
3346
+ id="acc-totp"
3347
+ inputmode="numeric"
3348
+ autocomplete="one-time-code"
3349
+ required
3350
+ .value=${this.authenticatorCode}
3351
+ @input=${this.bind("authenticatorCode")}
3352
+ />
3353
+ </div>
3354
+ ${this.error("authenticator-code")}
3355
+ <div class="inline">
3356
+ <button class="btn btn-primary btn-sm" type="submit" ?disabled=${!!this.busy}>
3357
+ ${this.spinner("authenticator-code")} ${this.t("authenticatorVerify")}
3358
+ </button>
3359
+ <button
3360
+ class="btn btn-ghost btn-sm"
3361
+ type="button"
3362
+ @click=${() => this.authenticator = null}
3363
+ >
3364
+ ${this.t("cancel")}
3365
+ </button>
3366
+ </div>
3367
+ </form>` : n}
3368
+ </div>`
3369
+ );
3370
+ }
3371
+ renderRecoveryCard() {
3372
+ const e = this.factors?.recoveryCode ?? !1;
3373
+ return this.card(
3374
+ this.t("recoveryCodes"),
3375
+ this.t("recoveryCodesDescription"),
3376
+ s`<div class="kv">
3377
+ ${this.recoveryCodes ? s`<div class="alert alert-warning">
3378
+ ${c.alert}
3379
+ <div class="alert-body">${this.t("recoveryCodesWarning")}</div>
3380
+ </div>
3381
+ <div class="codes">
3382
+ ${this.recoveryCodes.map((t) => s`<span class="code">${t}</span>`)}
3383
+ </div>
3384
+ <div class="inline">
3385
+ <button class="btn btn-outline btn-sm" @click=${this.onCopyCodes}>
3386
+ ${this.copied ? c.check : c.copy}
3387
+ ${this.copied ? this.t("copied") : this.t("copy")}
3388
+ </button>
3389
+ <button class="btn btn-ghost btn-sm" @click=${() => this.recoveryCodes = null}>
3390
+ ${this.t("done")}
3391
+ </button>
3392
+ </div>` : s`<div class="inline">
3393
+ <button
3394
+ class="btn btn-outline btn-sm"
3395
+ @click=${this.onRecoveryCodes}
3396
+ ?disabled=${!!this.busy}
3397
+ >
3398
+ ${this.spinner("recovery")} ${c.key}
3399
+ ${e ? this.t("recoveryCodes") : this.t("generateRecoveryCodes")}
3400
+ </button>
3401
+ ${e ? s`<button class="btn btn-ghost btn-sm" @click=${this.onRegenerateRecoveryCodes} ?disabled=${!!this.busy}>${c.refresh} ${this.t("regenerateRecoveryCodes")}</button>` : n}
3402
+ </div>`}
3403
+ ${this.error("recovery")}
3404
+ </div>`
3405
+ );
3406
+ }
3407
+ /** Inline MFA challenge shown when Appwrite demands a recent factor for a protected action. */
3408
+ renderStepUp() {
3409
+ const e = this.stepUp, t = this.factors, i = [
3410
+ {
3411
+ factor: "totp",
3412
+ icon: c.smartphone,
3413
+ label: this.t("mfaUseAuthenticator"),
3414
+ available: t?.totp ?? !0
3415
+ },
3416
+ {
3417
+ factor: "email",
3418
+ icon: c.mail,
3419
+ label: this.t("mfaUseEmail"),
3420
+ available: t?.email ?? !0
3421
+ },
3422
+ {
3423
+ factor: "phone",
3424
+ icon: c.phone,
3425
+ label: this.t("mfaUsePhone"),
3426
+ available: t?.phone ?? !0
3427
+ },
3428
+ {
3429
+ factor: "recoverycode",
3430
+ icon: c.key,
3431
+ label: this.t("mfaUseRecoveryCode"),
3432
+ available: t?.recoveryCode ?? !0
3433
+ }
3434
+ ];
3435
+ return this.card(
3436
+ this.t("mfaTitle"),
3437
+ this.t("errorChallengeRequired"),
3438
+ s`<div class="kv">
3439
+ ${e.challenge ? s`<form class="form" @submit=${this.onStepUpVerify} novalidate>
3440
+ <div class="field">
3441
+ <label class="label" for="acc-stepup"
3442
+ >${e.challenge.factor === "recoverycode" ? this.t("recoveryCode") : this.t("code")}</label
3443
+ >
3444
+ <input
3445
+ class="input ${e.challenge.factor === "recoverycode" ? "mono" : "input-otp"}"
3446
+ id="acc-stepup"
3447
+ autocomplete="one-time-code"
3448
+ required
3449
+ .value=${this.stepUpCode}
3450
+ @input=${this.bind("stepUpCode")}
3451
+ />
3452
+ </div>
3453
+ <button class="btn btn-primary btn-sm" type="submit" ?disabled=${!!this.busy}>
3454
+ ${this.spinner("stepup-code")} ${this.t("verifyCode")}
3455
+ </button>
3456
+ </form>` : s`<div class="stack-sm">
3457
+ ${i.filter((r) => r.available).map(
3458
+ (r) => s`<button
3459
+ type="button"
3460
+ class="choice"
3461
+ @click=${() => this.onStepUpFactor(r.factor)}
3462
+ ?disabled=${!!this.busy}
3463
+ >
3464
+ ${r.icon}<span class="choice-title">${r.label}</span>
3465
+ </button>`
3466
+ )}
3467
+ </div>`}
3468
+ ${this.error("stepup")} ${this.error("stepup-code")}
3469
+ </div>`,
3470
+ s`<button class="btn btn-ghost btn-sm" @click=${() => this.stepUp = null}>
3471
+ ${this.t("cancel")}
3472
+ </button>`
3473
+ );
3474
+ }
3475
+ // ── Sessions ──
3476
+ deviceIcon(e) {
3477
+ const t = (e.clientType || e.deviceName || "").toLowerCase();
3478
+ return t.includes("smartphone") || t.includes("phone") || t.includes("tablet") ? c.smartphone : t.includes("browser") || t.includes("desktop") ? c.monitor : c.globe;
3479
+ }
3480
+ renderSessions() {
3481
+ const e = this.sessions;
3482
+ return s`<div class="section">
3483
+ ${this.card(
3484
+ this.t("sessions"),
3485
+ void 0,
3486
+ s`${this.error("sessions")}
3487
+ ${e === null ? s`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? s`<div class="empty">${this.t("noActivity")}</div>` : e.map(
3488
+ (t) => s`<div class="row">
3489
+ <div class="inline">
3490
+ <span class="device">${this.deviceIcon(t)}</span>
3491
+ <div class="row-main">
3492
+ <span class="row-title">
3493
+ ${t.clientName || t.provider}
3494
+ ${t.clientVersion ? s`<span class="muted small">${t.clientVersion}</span>` : n}
3495
+ ${t.current ? s`<span class="badge badge-info">${this.t("currentSession")}</span>` : n}
3496
+ </span>
3497
+ <span class="row-sub"
3498
+ >${[t.osName, t.countryName || t.countryCode, t.ip].filter(Boolean).join(" · ")}</span
3499
+ >
3500
+ </div>
3501
+ </div>
3502
+ <div class="row-actions">
3503
+ ${this.busy === `session-${t.$id}` ? s`<span class="spinner"></span>` : n}
3504
+ <button
3505
+ class="btn btn-ghost btn-sm"
3506
+ @click=${() => this.onDeleteSession(t.$id)}
3507
+ ?disabled=${!!this.busy}
3508
+ aria-label=${this.t("signOutSession")}
3509
+ >
3510
+ ${c.logOut}
3511
+ </button>
3512
+ </div>
3513
+ </div>`
3514
+ )}`
3515
+ )}
3516
+ ${this.card(
3517
+ this.t("signOutAllSessions"),
3518
+ this.t("signOutAllSessionsDescription"),
3519
+ s`${this.error("sessions-all")}
3520
+ <button
3521
+ class="btn btn-outline btn-sm warn"
3522
+ @click=${this.onSignOutAll}
3523
+ ?disabled=${!!this.busy}
3524
+ >
3525
+ ${this.spinner("sessions-all")} ${c.logOut} ${this.t("signOutAllSessions")}
3526
+ </button>`,
3527
+ void 0,
3528
+ !0
3529
+ )}
3530
+ </div>`;
3531
+ }
3532
+ // ── Connections ──
3533
+ renderConnections() {
3534
+ const e = this.identities, t = this.config?.methods?.oauth ?? [];
3535
+ return s`<div class="section">
3536
+ ${this.card(
3537
+ this.t("connections"),
3538
+ void 0,
3539
+ s`${this.error("identities")}
3540
+ ${e === null ? s`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? s`<div class="empty">${this.t("noConnections")}</div>` : e.map(
3541
+ (i) => s`<div class="row">
3542
+ <div class="inline">
3543
+ <span class="device">${L(i.provider)}</span>
3544
+ <div class="row-main">
3545
+ <span class="row-title">${E(i.provider)}</span>
3546
+ <span class="row-sub">${i.providerEmail || i.providerUid}</span>
3547
+ </div>
3548
+ </div>
3549
+ <div class="row-actions">
3550
+ <button
3551
+ class="btn btn-ghost btn-sm"
3552
+ @click=${() => this.onDeleteIdentity(i.$id)}
3553
+ ?disabled=${!!this.busy}
3554
+ >
3555
+ ${this.busy === `identity-${i.$id}` ? s`<span class="spinner"></span>` : n}
3556
+ ${this.t("disconnect")}
3557
+ </button>
3558
+ </div>
3559
+ </div>`
3560
+ )}`,
3561
+ t.length > 0 ? s`${t.filter((i) => !(e ?? []).some((r) => r.provider === i)).map(
3562
+ (i) => s`<button
3563
+ class="btn btn-outline btn-sm"
3564
+ @click=${() => o.signInWithOAuth(i)}
3565
+ >
3566
+ ${L(i)} ${E(i)}
3567
+ </button>`
3568
+ )}` : void 0
3569
+ )}
3570
+ </div>`;
3571
+ }
3572
+ // ── Activity ──
3573
+ renderActivity() {
3574
+ const e = this.logs;
3575
+ return s`<div class="section">
3576
+ ${this.card(
3577
+ this.t("activity"),
3578
+ void 0,
3579
+ s`${e === null ? s`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? s`<div class="empty">${this.t("noActivity")}</div>` : e.map(
3580
+ (t) => s`<div class="row">
3581
+ <div class="row-main">
3582
+ <span class="row-title">${t.event}</span>
3583
+ <span class="row-sub"
3584
+ >${[t.clientName, t.osName, t.countryName || t.countryCode, t.ip].filter(Boolean).join(" · ")}</span
3585
+ >
3586
+ </div>
3587
+ <span class="log-time">${new Date(t.time).toLocaleString()}</span>
3588
+ </div>`
3589
+ )}`
3590
+ )}
3591
+ </div>`;
3592
+ }
3593
+ };
3594
+ p.styles = [
3595
+ ...x.styles,
3596
+ A`
3597
+ :host {
3598
+ display: block;
3599
+ width: 100%;
3600
+ max-width: 560px;
3601
+ }
3602
+ .panel {
3603
+ background: var(--authui-card);
3604
+ color: var(--authui-card-foreground);
3605
+ border: 1px solid var(--authui-border);
3606
+ border-radius: var(--authui-radius-xl);
3607
+ padding: 24px;
3608
+ display: flex;
3609
+ flex-direction: column;
3610
+ gap: 20px;
3611
+ box-shadow: var(--authui-shadow-lg);
3612
+ }
3613
+ .panel.embedded {
3614
+ border: 0;
3615
+ box-shadow: none;
3616
+ padding: 0;
3617
+ background: transparent;
3618
+ }
3619
+ .identity {
3620
+ display: flex;
3621
+ align-items: center;
3622
+ gap: 12px;
3623
+ }
3624
+ .identity .avatar {
3625
+ width: 44px;
3626
+ height: 44px;
3627
+ font-size: 16px;
3628
+ }
3629
+ .tabs {
3630
+ width: 100%;
3631
+ }
3632
+ .section {
3633
+ display: flex;
3634
+ flex-direction: column;
3635
+ gap: 16px;
3636
+ }
3637
+ .kv {
3638
+ display: flex;
3639
+ flex-direction: column;
3640
+ gap: 12px;
3641
+ }
3642
+ .toggle-row {
3643
+ display: flex;
3644
+ align-items: center;
3645
+ justify-content: space-between;
3646
+ gap: 16px;
3647
+ }
3648
+ .device {
3649
+ width: 36px;
3650
+ height: 36px;
3651
+ border-radius: var(--authui-radius-md);
3652
+ background: var(--authui-muted);
3653
+ color: var(--authui-muted-foreground);
3654
+ display: inline-flex;
3655
+ align-items: center;
3656
+ justify-content: center;
3657
+ flex-shrink: 0;
3658
+ }
3659
+ .device svg {
3660
+ width: 18px;
3661
+ height: 18px;
3662
+ }
3663
+ .log-time {
3664
+ font-size: 12px;
3665
+ color: var(--authui-muted-foreground);
3666
+ white-space: nowrap;
3667
+ }
3668
+ .warn {
3669
+ color: var(--authui-destructive-foreground);
3670
+ }
3671
+ `
3672
+ ];
3673
+ m([
3674
+ g({ type: Boolean })
3675
+ ], p.prototype, "embedded", 2);
3676
+ m([
3677
+ g({ type: String })
3678
+ ], p.prototype, "tab", 2);
3679
+ m([
3680
+ d()
3681
+ ], p.prototype, "active", 2);
3682
+ m([
3683
+ d()
3684
+ ], p.prototype, "busy", 2);
3685
+ m([
3686
+ d()
3687
+ ], p.prototype, "notice", 2);
3688
+ m([
3689
+ d()
3690
+ ], p.prototype, "errors", 2);
3691
+ m([
3692
+ d()
3693
+ ], p.prototype, "nameInput", 2);
3694
+ m([
3695
+ d()
3696
+ ], p.prototype, "emailInput", 2);
3697
+ m([
3698
+ d()
3699
+ ], p.prototype, "emailPassword", 2);
3700
+ m([
3701
+ d()
3702
+ ], p.prototype, "phoneInput", 2);
3703
+ m([
3704
+ d()
3705
+ ], p.prototype, "phonePassword", 2);
3706
+ m([
3707
+ d()
3708
+ ], p.prototype, "phoneCode", 2);
3709
+ m([
3710
+ d()
3711
+ ], p.prototype, "phoneCodeSent", 2);
3712
+ m([
3713
+ d()
3714
+ ], p.prototype, "guestName", 2);
3715
+ m([
3716
+ d()
3717
+ ], p.prototype, "oldPassword", 2);
3718
+ m([
3719
+ d()
3720
+ ], p.prototype, "newPassword", 2);
3721
+ m([
3722
+ d()
3723
+ ], p.prototype, "newPasswordConfirm", 2);
3724
+ m([
3725
+ d()
3726
+ ], p.prototype, "authenticator", 2);
3727
+ m([
3728
+ d()
3729
+ ], p.prototype, "authenticatorCode", 2);
3730
+ m([
3731
+ d()
3732
+ ], p.prototype, "factors", 2);
3733
+ m([
3734
+ d()
3735
+ ], p.prototype, "recoveryCodes", 2);
3736
+ m([
3737
+ d()
3738
+ ], p.prototype, "stepUp", 2);
3739
+ m([
3740
+ d()
3741
+ ], p.prototype, "stepUpCode", 2);
3742
+ m([
3743
+ d()
3744
+ ], p.prototype, "copied", 2);
3745
+ m([
3746
+ d()
3747
+ ], p.prototype, "sessions", 2);
3748
+ m([
3749
+ d()
3750
+ ], p.prototype, "identities", 2);
3751
+ m([
3752
+ d()
3753
+ ], p.prototype, "logs", 2);
3754
+ m([
3755
+ d()
3756
+ ], p.prototype, "logsSupported", 2);
3757
+ m([
3758
+ d()
3759
+ ], p.prototype, "confirmDelete", 2);
3760
+ p = m([
3761
+ S("authui-account")
3762
+ ], p);
3763
+ var wt = Object.defineProperty, $t = Object.getOwnPropertyDescriptor, U = (e, t, i, r) => {
3764
+ for (var a = r > 1 ? void 0 : r ? $t(t, i) : t, u = e.length - 1, h; u >= 0; u--)
3765
+ (h = e[u]) && (a = (r ? h(t, i, a) : h(a)) || a);
3766
+ return r && a && wt(t, i, a), a;
3767
+ };
3768
+ let P = class extends x {
3769
+ constructor() {
3770
+ super(...arguments), this.open = !1, this.view = "sign-in", this.closeOnSuccess = !0, this.handledPending = null, this.onOpenEvent = (e) => {
3771
+ const t = e.detail ?? {};
3772
+ this.show(t.view);
3773
+ }, this.onCloseEvent = () => this.hide(), this.onSuccess = () => {
3774
+ this.fire("authui-signed-in", this.auth.user), this.closeOnSuccess && !this.config?.successUrl && this.hide();
3775
+ }, this.onInnerOpen = (e) => {
3776
+ const t = e.detail?.view;
3777
+ t && (this.view = t);
3778
+ }, this.onBackdrop = (e) => {
3779
+ e.target === this.dialog && this.hide();
3780
+ };
3781
+ }
3782
+ connectedCallback() {
3783
+ super.connectedCallback(), window.addEventListener("authui:open", this.onOpenEvent), window.addEventListener("authui:close", this.onCloseEvent);
3784
+ }
3785
+ disconnectedCallback() {
3786
+ super.disconnectedCallback(), window.removeEventListener("authui:open", this.onOpenEvent), window.removeEventListener("authui:close", this.onCloseEvent);
3787
+ }
3788
+ show(e) {
3789
+ e ? this.view = e : this.auth.status === "signed-in" && (this.view = "account"), this.open = !0;
3790
+ }
3791
+ hide() {
3792
+ this.open = !1;
3793
+ }
3794
+ updated(e) {
3795
+ if (e.has("open") && this.dialog && (this.open && !this.dialog.open && this.dialog.showModal(), !this.open && this.dialog.open && this.dialog.close()), e.has("auth")) {
3796
+ const t = this.auth.pending;
3797
+ t && t !== this.handledPending && t.type !== "notice" && (this.handledPending = t, this.view = "sign-in", this.open = !0), t?.type === "notice" && t !== this.handledPending && (this.handledPending = t, this.open = !0);
3798
+ }
3799
+ }
3800
+ render() {
3801
+ const e = this.view === "account";
3802
+ return s`
3803
+ <dialog
3804
+ class=${e ? "wide" : ""}
3805
+ aria-labelledby="authui-title"
3806
+ @close=${() => this.open = !1}
3807
+ @cancel=${(t) => {
3808
+ t.preventDefault(), this.hide();
3809
+ }}
3810
+ @click=${this.onBackdrop}
3811
+ @authui-open=${this.onInnerOpen}
3812
+ >
3813
+ <div class="body">
3814
+ <button
3815
+ class="btn btn-ghost btn-icon close"
3816
+ @click=${this.hide}
3817
+ aria-label=${this.t("close")}
3818
+ >
3819
+ ${c.x}
3820
+ </button>
3821
+ ${this.open ? e ? s`<authui-account embedded></authui-account>` : s`<authui-sign-in
3822
+ embedded
3823
+ .view=${this.view}
3824
+ @authui-success=${this.onSuccess}
3825
+ ></authui-sign-in>` : n}
3826
+ </div>
3827
+ </dialog>
3828
+ `;
3829
+ }
3830
+ };
3831
+ P.styles = [
3832
+ ...x.styles,
3833
+ A`
3834
+ :host {
3835
+ display: contents;
3836
+ }
3837
+ dialog {
3838
+ border: 1px solid var(--authui-border);
3839
+ border-radius: var(--authui-radius-lg);
3840
+ background: var(--authui-background);
3841
+ color: var(--authui-foreground);
3842
+ padding: 0;
3843
+ width: calc(100% - 2rem);
3844
+ max-width: 440px;
3845
+ max-height: calc(100dvh - 2rem);
3846
+ box-shadow: var(--authui-shadow-lg);
3847
+ overflow: hidden;
3848
+ z-index: var(--authui-z);
3849
+ }
3850
+ dialog.wide {
3851
+ max-width: 600px;
3852
+ }
3853
+ dialog::backdrop {
3854
+ background: var(--authui-overlay);
3855
+ backdrop-filter: blur(4px);
3856
+ }
3857
+ dialog[open] {
3858
+ animation: authui-in 200ms cubic-bezier(0.16, 1, 0.3, 1);
3859
+ }
3860
+ @keyframes authui-in {
3861
+ from {
3862
+ opacity: 0;
3863
+ transform: scale(0.96);
3864
+ }
3865
+ to {
3866
+ opacity: 1;
3867
+ transform: none;
3868
+ }
3869
+ }
3870
+ .body {
3871
+ padding: 24px;
3872
+ max-height: calc(100dvh - 2rem);
3873
+ overflow-y: auto;
3874
+ }
3875
+ .close {
3876
+ position: absolute;
3877
+ top: 12px;
3878
+ inset-inline-end: 12px;
3879
+ width: 32px;
3880
+ height: 32px;
3881
+ border-radius: var(--authui-radius-sm);
3882
+ opacity: 0.7;
3883
+ }
3884
+ .close:hover {
3885
+ opacity: 1;
3886
+ }
3887
+ authui-sign-in,
3888
+ authui-account {
3889
+ max-width: none;
3890
+ }
3891
+ `
3892
+ ];
3893
+ U([
3894
+ g({ type: Boolean, reflect: !0 })
3895
+ ], P.prototype, "open", 2);
3896
+ U([
3897
+ g({ type: String })
3898
+ ], P.prototype, "view", 2);
3899
+ U([
3900
+ g({ type: Boolean, attribute: "close-on-success" })
3901
+ ], P.prototype, "closeOnSuccess", 2);
3902
+ U([
3903
+ d()
3904
+ ], P.prototype, "handledPending", 2);
3905
+ U([
3906
+ X("dialog")
3907
+ ], P.prototype, "dialog", 2);
3908
+ P = U([
3909
+ S("authui-modal")
3910
+ ], P);
3911
+ function R(e) {
3912
+ typeof document > "u" || (document.querySelector("authui-modal") || document.body.appendChild(document.createElement("authui-modal")), queueMicrotask(() => {
3913
+ window.dispatchEvent(new CustomEvent("authui:open", { detail: { view: e } }));
3914
+ }));
3915
+ }
3916
+ function Ut() {
3917
+ typeof window > "u" || window.dispatchEvent(new CustomEvent("authui:close"));
3918
+ }
3919
+ var xt = Object.defineProperty, kt = Object.getOwnPropertyDescriptor, O = (e, t, i, r) => {
3920
+ for (var a = r > 1 ? void 0 : r ? kt(t, i) : t, u = e.length - 1, h; u >= 0; u--)
3921
+ (h = e[u]) && (a = (r ? h(t, i, a) : h(a)) || a);
3922
+ return r && a && xt(t, i, a), a;
3923
+ };
3924
+ let M = class extends x {
3925
+ constructor() {
3926
+ super(...arguments), this.view = "sign-in", this.variant = "primary", this.size = "md";
3927
+ }
3928
+ render() {
3929
+ const e = this.size === "md" ? "" : `btn-${this.size}`;
3930
+ return s`<button
3931
+ class="btn btn-${this.variant} ${e}"
3932
+ @click=${() => R(this.view)}
3933
+ part="button"
3934
+ >
3935
+ <slot
3936
+ >${this.view === "sign-up" ? this.t("signUp") : this.view === "account" ? this.t("manageAccount") : this.t("signIn")}</slot
3937
+ >
3938
+ </button>`;
3939
+ }
3940
+ };
3941
+ M.styles = [
3942
+ ...x.styles,
3943
+ A`
3944
+ :host {
3945
+ display: inline-block;
3946
+ }
3947
+ .btn {
3948
+ width: 100%;
3949
+ }
3950
+ `
3951
+ ];
3952
+ O([
3953
+ g({ type: String })
3954
+ ], M.prototype, "view", 2);
3955
+ O([
3956
+ g({ type: String })
3957
+ ], M.prototype, "variant", 2);
3958
+ O([
3959
+ g({ type: String })
3960
+ ], M.prototype, "size", 2);
3961
+ M = O([
3962
+ S("authui-button")
3963
+ ], M);
3964
+ var Ct = Object.defineProperty, Pt = Object.getOwnPropertyDescriptor, q = (e, t, i, r) => {
3965
+ for (var a = r > 1 ? void 0 : r ? Pt(t, i) : t, u = e.length - 1, h; u >= 0; u--)
3966
+ (h = e[u]) && (a = (r ? h(t, i, a) : h(a)) || a);
3967
+ return r && a && Ct(t, i, a), a;
3968
+ };
3969
+ let I = class extends x {
3970
+ constructor() {
3971
+ super(...arguments), this.src = "", this.menuOpen = !1, this.onDocumentClick = (e) => {
3972
+ e.composedPath().includes(this) || (this.menuOpen = !1);
3973
+ }, this.onKeydown = (e) => {
3974
+ e.key === "Escape" && (this.menuOpen = !1);
3975
+ };
3976
+ }
3977
+ connectedCallback() {
3978
+ super.connectedCallback(), document.addEventListener("click", this.onDocumentClick, !0), document.addEventListener("keydown", this.onKeydown);
3979
+ }
3980
+ disconnectedCallback() {
3981
+ super.disconnectedCallback(), document.removeEventListener("click", this.onDocumentClick, !0), document.removeEventListener("keydown", this.onKeydown);
3982
+ }
3983
+ render() {
3984
+ const { status: e, user: t } = this.auth;
3985
+ if (e === "loading")
3986
+ return s`<span class="avatar"><span class="spinner"></span></span>`;
3987
+ if (e !== "signed-in" || !t)
3988
+ return s`<button class="btn btn-primary btn-sm" @click=${() => R("sign-in")}>
3989
+ <slot>${this.t("signIn")}</slot>
3990
+ </button>`;
3991
+ const i = t.name || t.email || t.phone || this.t("guestAccount");
3992
+ return s`
3993
+ <button
3994
+ class="trigger"
3995
+ aria-haspopup="menu"
3996
+ aria-expanded=${this.menuOpen ? "true" : "false"}
3997
+ @click=${() => this.menuOpen = !this.menuOpen}
3998
+ aria-label=${i}
3999
+ >
4000
+ <span class="avatar"
4001
+ >${this.src ? s`<img src=${this.src} alt="" />` : i[0] ?? "?"}</span
4002
+ >
4003
+ </button>
4004
+ ${this.menuOpen ? s`<div class="menu" role="menu">
4005
+ <div class="menu-header">
4006
+ <span class="row-title">${i}</span>
4007
+ ${t.email && t.name ? s`<span class="row-sub">${t.email}</span>` : n}
4008
+ </div>
4009
+ <button
4010
+ class="menu-item"
4011
+ role="menuitem"
4012
+ @click=${() => {
4013
+ this.menuOpen = !1, R("account");
4014
+ }}
4015
+ >
4016
+ ${c.settings} ${this.t("manageAccount")}
4017
+ </button>
4018
+ <button
4019
+ class="menu-item"
4020
+ role="menuitem"
4021
+ @click=${() => {
4022
+ this.menuOpen = !1, o.signOut();
4023
+ }}
4024
+ >
4025
+ ${c.logOut} ${this.t("signOut")}
4026
+ </button>
4027
+ </div>` : n}
4028
+ `;
4029
+ }
4030
+ };
4031
+ I.styles = [
4032
+ ...x.styles,
4033
+ A`
4034
+ :host {
4035
+ display: inline-block;
4036
+ position: relative;
4037
+ }
4038
+ .trigger {
4039
+ border: 1px solid transparent;
4040
+ background: transparent;
4041
+ padding: 2px;
4042
+ border-radius: 999px;
4043
+ cursor: pointer;
4044
+ display: inline-flex;
4045
+ transition: border-color 150ms;
4046
+ }
4047
+ .trigger:hover,
4048
+ .trigger[aria-expanded="true"] {
4049
+ border-color: var(--authui-border);
4050
+ }
4051
+ .trigger:focus-visible {
4052
+ outline: none;
4053
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--authui-ring) 50%, transparent);
4054
+ }
4055
+ .menu {
4056
+ position: absolute;
4057
+ top: calc(100% + 6px);
4058
+ inset-inline-end: 0;
4059
+ min-width: 220px;
4060
+ background: var(--authui-popover);
4061
+ color: var(--authui-popover-foreground);
4062
+ border: 1px solid var(--authui-border);
4063
+ border-radius: var(--authui-radius-md);
4064
+ box-shadow: var(--authui-shadow-lg);
4065
+ padding: 4px;
4066
+ z-index: var(--authui-z);
4067
+ display: flex;
4068
+ flex-direction: column;
4069
+ gap: 2px;
4070
+ }
4071
+ .menu-header {
4072
+ padding: 8px 10px 10px;
4073
+ display: flex;
4074
+ flex-direction: column;
4075
+ gap: 2px;
4076
+ border-bottom: 1px solid var(--authui-border);
4077
+ margin-bottom: 4px;
4078
+ }
4079
+ .menu-item {
4080
+ display: flex;
4081
+ align-items: center;
4082
+ gap: 8px;
4083
+ padding: 6px 10px;
4084
+ border-radius: var(--authui-radius-sm);
4085
+ border: 0;
4086
+ background: transparent;
4087
+ color: inherit;
4088
+ font: inherit;
4089
+ font-size: 14px;
4090
+ cursor: pointer;
4091
+ text-align: start;
4092
+ width: 100%;
4093
+ }
4094
+ .menu-item:hover,
4095
+ .menu-item:focus-visible {
4096
+ background: var(--authui-accent);
4097
+ outline: none;
4098
+ }
4099
+ .menu-item svg {
4100
+ width: 16px;
4101
+ height: 16px;
4102
+ color: var(--authui-muted-foreground);
4103
+ }
4104
+ .avatar {
4105
+ width: 32px;
4106
+ height: 32px;
4107
+ font-size: 13px;
4108
+ }
4109
+ `
4110
+ ];
4111
+ q([
4112
+ g({ type: String })
4113
+ ], I.prototype, "src", 2);
4114
+ q([
4115
+ d()
4116
+ ], I.prototype, "menuOpen", 2);
4117
+ I = q([
4118
+ S("authui-user-button")
4119
+ ], I);
4120
+ export {
4121
+ rt as A,
4122
+ b as E,
4123
+ o as a,
4124
+ p as b,
4125
+ Ut as c,
4126
+ M as d,
4127
+ v as e,
4128
+ x as f,
4129
+ P as g,
4130
+ $ as h,
4131
+ Y as i,
4132
+ K as j,
4133
+ I as k,
4134
+ et as l,
4135
+ Z as m,
4136
+ R as o,
4137
+ E as p,
4138
+ _ as t
4139
+ };