@getauthui/core 0.1.1 → 0.1.3

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.
@@ -1,13 +1,16 @@
1
- import { state as d, property as f, customElement as I, query as rt } from "lit/decorators.js";
2
- import { css as E, LitElement as K, nothing as o, html as s, svg as l } from "lit";
3
- import { Client as nt, Account as ot, ID as L, Avatars as ct } from "appwrite";
4
- const lt = {
1
+ import { state as d, property as m, customElement as O, query as ct } from "lit/decorators.js";
2
+ import { css as I, LitElement as X, nothing as c, html as r, svg as l } from "lit";
3
+ import { Client as tt, Account as et, ID as L, Avatars as dt } from "appwrite";
4
+ const ht = {
5
5
  signIn: "Sign in",
6
+ dialogSignIn: "Sign in",
6
7
  signUp: "Sign up",
7
8
  signOut: "Sign out",
8
9
  continueAsGuest: "Continue as guest",
9
10
  email: "Email",
10
11
  password: "Password",
12
+ showPassword: "Show password",
13
+ hidePassword: "Hide password",
11
14
  newPassword: "New password",
12
15
  confirmPassword: "Confirm password",
13
16
  name: "Name",
@@ -23,6 +26,9 @@ const lt = {
23
26
  continueWithPhone: "Continue with phone",
24
27
  sendMagicLink: "Send magic link",
25
28
  sendCode: "Send code",
29
+ resendCode: "Resend code",
30
+ useDifferentEmail: "Use a different email",
31
+ useDifferentPhone: "Use a different phone number",
26
32
  verifyCode: "Verify code",
27
33
  magicLinkSent: "We sent a sign-in link to {email}. Open it on this device to continue.",
28
34
  codeSent: "We sent a code to {target}. Enter it below to continue.",
@@ -38,6 +44,7 @@ const lt = {
38
44
  resetLinkSent: "If an account exists for {email}, a reset link is on its way.",
39
45
  passwordUpdated: "Your password was updated. You can sign in now.",
40
46
  sendResetLink: "Send reset link",
47
+ requestNewLink: "Request a new link",
41
48
  agreeTo: "By continuing you agree to our",
42
49
  terms: "Terms of Service",
43
50
  privacy: "Privacy Policy",
@@ -63,21 +70,28 @@ const lt = {
63
70
  verified: "Verified",
64
71
  unverified: "Unverified",
65
72
  verifyEmail: "Verify email",
73
+ verificationResendIn: "Sent. You can resend in {seconds} s",
66
74
  verificationSent: "Verification email sent. Check your inbox.",
67
75
  emailVerified: "Your email is verified.",
68
76
  changePassword: "Change password",
69
77
  currentPassword: "Current password",
70
78
  twoFactor: "Two-factor authentication",
79
+ mfaBadge: "MFA",
71
80
  twoFactorDescription: "Require a second factor when signing in to this account.",
81
+ mfaNoFactorWarning: "Turn on an authenticator, or verify your email or phone, before enabling two-factor authentication. Without a factor, this setting does not protect the account.",
72
82
  enable: "Enable",
73
83
  disable: "Disable",
74
84
  authenticatorApp: "Authenticator app",
75
85
  authenticatorAdd: "Add authenticator",
76
86
  authenticatorScan: "Scan this QR code with your authenticator app, then enter the 6-digit code.",
87
+ qrCodeAlt: "QR code",
77
88
  authenticatorManual: "Or enter this key manually",
89
+ authenticatorCopyKey: "Copy key",
78
90
  authenticatorVerify: "Verify and enable",
79
91
  recoveryCodes: "Recovery codes",
92
+ viewRecoveryCodes: "View recovery codes",
80
93
  recoveryCodesDescription: "Use a recovery code to sign in if you lose access to your other factors.",
94
+ recoveryCodesOnceHint: "Recovery codes can be viewed only once after they are generated. Viewing them again requires a recent second factor.",
81
95
  generateRecoveryCodes: "Generate recovery codes",
82
96
  regenerateRecoveryCodes: "Regenerate",
83
97
  recoveryCodesWarning: "Store these codes somewhere safe. Each code works once.",
@@ -87,16 +101,34 @@ const lt = {
87
101
  signOutAllSessionsDescription: "End every session, including this one.",
88
102
  noConnections: "No connected accounts.",
89
103
  disconnect: "Disconnect",
104
+ connectProvider: "Connect {provider}",
90
105
  noActivity: "No recent activity.",
106
+ noSessions: "No active sessions.",
91
107
  deleteAccount: "Delete account",
92
- deleteAccountDescription: "Your account is disabled and you are signed out. An administrator can restore it.",
108
+ deleteAccountDescription: "Deleting disables your account and signs you out everywhere. An administrator can restore it.",
93
109
  deleteAccountConfirm: "Delete my account",
94
110
  loading: "Loading",
95
111
  copied: "Copied",
112
+ copyFailed: "Could not copy. Select the text and copy it manually.",
96
113
  copy: "Copy",
97
114
  done: "Done",
115
+ nameUpdated: "Name updated.",
116
+ emailUpdated: "Email updated. Verify the new address.",
117
+ phoneUpdated: "Phone number updated.",
118
+ phoneVerified: "Phone verified.",
119
+ authenticatorAdded: "Authenticator added.",
120
+ accountConverted: "Account created.",
121
+ enabled: "Enabled",
122
+ disabled: "Disabled",
123
+ createPassword: "Create a password",
124
+ createPasswordHint: "This becomes your sign-in password.",
125
+ errorCurrentPassword: "Current password is incorrect.",
98
126
  errorGeneric: "Something went wrong. Please try again.",
99
127
  errorInvalidCredentials: "Invalid email or password.",
128
+ errorInvalidEmail: "Enter a valid email address.",
129
+ errorInvalidPassword: "Password must be between 8 and 256 characters.",
130
+ errorInvalidPhone: "Enter a phone number in E.164 format, starting with +.",
131
+ errorInvalidName: "Enter a name.",
100
132
  errorUserExists: "An account with this email already exists.",
101
133
  errorUserBlocked: "This account is blocked. Contact support.",
102
134
  errorRateLimit: "Too many attempts. Wait a moment and try again.",
@@ -116,6 +148,7 @@ const lt = {
116
148
  passwordHint: "At least 8 characters.",
117
149
  signedInAs: "Signed in as",
118
150
  manageAccount: "Manage account",
151
+ dialogAccount: "Account",
119
152
  continue: "Continue",
120
153
  provider: "Provider",
121
154
  lastActive: "Last active",
@@ -123,13 +156,13 @@ const lt = {
123
156
  guestAccountDescription: "Add an email and password to keep your data.",
124
157
  preview: "Preview"
125
158
  };
126
- function dt(e, t = {}) {
159
+ function ut(e, t = {}) {
127
160
  return e.replace(
128
161
  /\{(\w+)\}/g,
129
- (i, r) => r in t ? String(t[r]) : `{${r}}`
162
+ (i, s) => s in t ? String(t[s]) : `{${s}}`
130
163
  );
131
164
  }
132
- const ht = {
165
+ const pt = {
133
166
  amazon: "Amazon",
134
167
  apple: "Apple",
135
168
  appwrite: "Appwrite",
@@ -180,10 +213,10 @@ const ht = {
180
213
  zoho: "Zoho",
181
214
  zoom: "Zoom"
182
215
  };
183
- function O(e) {
184
- return ht[e] ?? e.charAt(0).toUpperCase() + e.slice(1);
216
+ function R(e) {
217
+ return pt[e] ?? e.charAt(0).toUpperCase() + e.slice(1);
185
218
  }
186
- const V = (e, t, i = 401) => Object.assign(new Error(t), { type: e, code: i }), S = () => (/* @__PURE__ */ new Date()).toISOString(), M = (e) => new Date(Date.now() - e * 6e4).toISOString(), q = [
219
+ const T = (e, t, i = 401) => Object.assign(new Error(t), { type: e, code: i }), P = () => (/* @__PURE__ */ new Date()).toISOString(), U = (e) => new Date(Date.now() - e * 6e4).toISOString(), N = [
187
220
  "amber",
188
221
  "brave",
189
222
  "calm",
@@ -196,13 +229,13 @@ const V = (e, t, i = 401) => Object.assign(new Error(t), { type: e, code: i }),
196
229
  "juniper",
197
230
  "kite",
198
231
  "lumen"
199
- ], Z = () => `${q[Math.floor(Math.random() * q.length)]}-${q[Math.floor(Math.random() * q.length)]}`, _ = () => Math.random().toString(36).slice(2, 12), J = () => Array.from({ length: 2 }, () => Math.random().toString(36).slice(2, 7)).join("-"), ut = {
232
+ ], it = () => `${N[Math.floor(Math.random() * N.length)]}-${N[Math.floor(Math.random() * N.length)]}`, F = () => Math.random().toString(36).slice(2, 12), st = () => Array.from({ length: 2 }, () => Math.random().toString(36).slice(2, 7)).join("-"), ft = {
200
233
  name: "Ada Lovelace",
201
234
  email: "ada@example.com",
202
235
  phone: "+15550100"
203
236
  };
204
- class pt {
205
- constructor(t = ut) {
237
+ class mt {
238
+ constructor(t = ft) {
206
239
  this.seed = t, this.user = null, this.mfaPending = !1, this.mfaEnabled = !1, this.totpEnrolled = !1, this.recoveryCodes = [], this.lastChallenge = 0, this.sessions = [], this.identities = [], this.logs = [], this.tokens = /* @__PURE__ */ new Map(), this.pendingAuthenticator = null;
207
240
  }
208
241
  // ───────────────────────── helpers ─────────────────────────
@@ -210,13 +243,13 @@ class pt {
210
243
  const i = t.anonymous ?? !1;
211
244
  return this.user = {
212
245
  $id: "preview-user",
213
- $createdAt: M(1440 * 30),
214
- $updatedAt: S(),
246
+ $createdAt: U(1440 * 30),
247
+ $updatedAt: P(),
215
248
  name: i ? "" : t.name ?? this.seed.name,
216
- registration: M(1440 * 30),
249
+ registration: U(1440 * 30),
217
250
  status: !0,
218
251
  labels: [],
219
- passwordUpdate: i ? "" : M(1440 * 7),
252
+ passwordUpdate: i ? "" : U(1440 * 7),
220
253
  email: i ? "" : t.email ?? this.seed.email,
221
254
  phone: i ? "" : t.phone ?? this.seed.phone,
222
255
  emailVerification: !i,
@@ -224,14 +257,14 @@ class pt {
224
257
  mfa: this.mfaEnabled,
225
258
  prefs: {},
226
259
  targets: [],
227
- accessedAt: S()
260
+ accessedAt: P()
228
261
  }, this.seedActivity(i ? "anonymous" : "email"), this.user;
229
262
  }
230
263
  seedActivity(t) {
231
264
  if (this.sessions.length > 0) return;
232
265
  const i = {
233
- $createdAt: S(),
234
- $updatedAt: S(),
266
+ $createdAt: P(),
267
+ $updatedAt: P(),
235
268
  userId: "preview-user",
236
269
  expire: new Date(Date.now() + 365 * 864e5).toISOString(),
237
270
  providerUid: "",
@@ -266,8 +299,8 @@ class pt {
266
299
  },
267
300
  {
268
301
  ...i,
269
- $id: _(),
270
- $createdAt: M(300),
302
+ $id: F(),
303
+ $createdAt: U(300),
271
304
  provider: t,
272
305
  ip: "198.51.100.7",
273
306
  osCode: "IOS",
@@ -283,8 +316,8 @@ class pt {
283
316
  },
284
317
  {
285
318
  ...i,
286
- $id: _(),
287
- $createdAt: M(1440 * 3),
319
+ $id: F(),
320
+ $createdAt: U(1440 * 3),
288
321
  provider: "oauth2",
289
322
  ip: "192.0.2.90",
290
323
  osCode: "WIN",
@@ -299,8 +332,8 @@ class pt {
299
332
  ], this.identities = [
300
333
  {
301
334
  $id: "identity-github",
302
- $createdAt: M(1440 * 20),
303
- $updatedAt: M(1440 * 20),
335
+ $createdAt: U(1440 * 20),
336
+ $updatedAt: U(1440 * 20),
304
337
  userId: "preview-user",
305
338
  provider: "github",
306
339
  providerUid: "8675309",
@@ -312,7 +345,7 @@ class pt {
312
345
  ], this.logs = [
313
346
  {
314
347
  event: "session.create",
315
- time: S(),
348
+ time: P(),
316
349
  clientName: "Chrome",
317
350
  osName: "macOS",
318
351
  countryName: "Germany",
@@ -320,7 +353,7 @@ class pt {
320
353
  },
321
354
  {
322
355
  event: "user.update.name",
323
- time: M(1440 * 2),
356
+ time: U(1440 * 2),
324
357
  clientName: "Safari",
325
358
  osName: "iOS",
326
359
  countryName: "Germany",
@@ -328,7 +361,7 @@ class pt {
328
361
  },
329
362
  {
330
363
  event: "session.create",
331
- time: M(1440 * 3),
364
+ time: U(1440 * 3),
332
365
  clientName: "Firefox",
333
366
  osName: "Windows",
334
367
  countryName: "United States",
@@ -338,9 +371,9 @@ class pt {
338
371
  }
339
372
  requireUser() {
340
373
  if (!this.user)
341
- throw V("general_unauthorized_scope", "User (role: guests) missing scope (account)");
374
+ throw T("general_unauthorized_scope", "User (role: guests) missing scope (account)");
342
375
  if (this.mfaPending)
343
- throw V(
376
+ throw T(
344
377
  "user_more_factors_required",
345
378
  "More factors are required to complete the sign in process."
346
379
  );
@@ -348,7 +381,7 @@ class pt {
348
381
  }
349
382
  requireRecentChallenge() {
350
383
  if (Date.now() - this.lastChallenge > 30 * 6e4)
351
- throw V(
384
+ throw T(
352
385
  "user_challenge_required",
353
386
  "A recently successful challenge is required to complete this action."
354
387
  );
@@ -358,7 +391,7 @@ class pt {
358
391
  this.mfaPending = !!(this.user?.mfa && t);
359
392
  }
360
393
  async delay(t, i = 150) {
361
- return await new Promise((r) => setTimeout(r, i)), typeof t == "function" ? t() : t;
394
+ return await new Promise((s) => setTimeout(s, i)), typeof t == "function" ? t() : t;
362
395
  }
363
396
  /** Sign the preview user in directly (used by the playground). */
364
397
  signInDirectly() {
@@ -368,7 +401,7 @@ class pt {
368
401
  async get() {
369
402
  return this.delay(() => this.requireUser(), 120);
370
403
  }
371
- async create(t, i, r, a) {
404
+ async create(t, i, s, a) {
372
405
  return this.delay(() => this.makeUser({ email: i, name: a || i.split("@")[0] }));
373
406
  }
374
407
  async createEmailPasswordSession(t) {
@@ -384,26 +417,26 @@ class pt {
384
417
  }
385
418
  async createMagicURLToken(t, i) {
386
419
  return this.tokens.set(t, { email: i }), this.delay({
387
- $id: _(),
388
- $createdAt: S(),
420
+ $id: F(),
421
+ $createdAt: P(),
389
422
  userId: t,
390
423
  secret: "",
391
424
  expire: "",
392
- phrase: Z()
425
+ phrase: it()
393
426
  });
394
427
  }
395
428
  async createEmailToken(t, i) {
396
429
  return this.tokens.set(t, { email: i }), this.delay({
397
- $id: _(),
398
- $createdAt: S(),
430
+ $id: F(),
431
+ $createdAt: P(),
399
432
  userId: t,
400
433
  secret: "",
401
434
  expire: "",
402
- phrase: Z()
435
+ phrase: it()
403
436
  });
404
437
  }
405
438
  async createPhoneToken(t, i) {
406
- return this.tokens.set(t, { phone: i }), this.delay({ $id: _(), $createdAt: S(), userId: t, secret: "", expire: "", phrase: "" });
439
+ return this.tokens.set(t, { phone: i }), this.delay({ $id: F(), $createdAt: P(), userId: t, secret: "", expire: "", phrase: "" });
407
440
  }
408
441
  async createSession(t) {
409
442
  return this.delay(() => {
@@ -444,7 +477,7 @@ class pt {
444
477
  async updateEmail(t) {
445
478
  return this.delay(() => {
446
479
  const i = this.requireUser();
447
- return i.email = t, i.emailVerification = !1, i.passwordUpdate = S(), i;
480
+ return i.email = t, i.emailVerification = !1, i.passwordUpdate = P(), i;
448
481
  });
449
482
  }
450
483
  async updatePhone(t) {
@@ -456,7 +489,7 @@ class pt {
456
489
  async updatePassword() {
457
490
  return this.delay(() => {
458
491
  const t = this.requireUser();
459
- return t.passwordUpdate = S(), t;
492
+ return t.passwordUpdate = P(), t;
460
493
  });
461
494
  }
462
495
  async updateStatus() {
@@ -467,7 +500,10 @@ class pt {
467
500
  return this.delay(() => (this.requireUser(), { total: this.sessions.length, sessions: this.sessions }));
468
501
  }
469
502
  async deleteSession(t = "current") {
470
- return this.delay(() => (t === "current" ? this.reset() : this.sessions = this.sessions.filter((i) => i.$id !== t), {}));
503
+ return this.delay(() => {
504
+ const i = this.sessions.find((s) => s.$id === t);
505
+ return t === "current" || i?.current ? this.reset() : this.sessions = this.sessions.filter((s) => s.$id !== t), {};
506
+ });
471
507
  }
472
508
  async deleteSessions() {
473
509
  return this.delay(() => (this.reset(), {}));
@@ -492,7 +528,7 @@ class pt {
492
528
  });
493
529
  }
494
530
  async createMFAChallenge() {
495
- return this.delay({ $id: _(), $createdAt: S(), userId: "preview-user", expire: "" });
531
+ return this.delay({ $id: F(), $createdAt: P(), userId: "preview-user", expire: "" });
496
532
  }
497
533
  async updateMFAChallenge() {
498
534
  return this.delay(() => (this.mfaPending = !1, this.lastChallenge = Date.now(), this.sessions[0]));
@@ -521,33 +557,33 @@ class pt {
521
557
  async createMFARecoveryCodes() {
522
558
  return this.delay(() => {
523
559
  if (this.recoveryCodes.length > 0)
524
- throw V("user_recovery_codes_already_exists", "Recovery codes already generated.", 409);
525
- return this.recoveryCodes = Array.from({ length: 6 }, J), { recoveryCodes: this.recoveryCodes };
560
+ throw T("user_recovery_codes_already_exists", "Recovery codes already generated.", 409);
561
+ return this.recoveryCodes = Array.from({ length: 6 }, st), { recoveryCodes: this.recoveryCodes };
526
562
  });
527
563
  }
528
564
  async getMFARecoveryCodes() {
529
565
  return this.delay(() => (this.requireRecentChallenge(), { recoveryCodes: this.recoveryCodes }));
530
566
  }
531
567
  async updateMFARecoveryCodes() {
532
- return this.delay(() => (this.requireRecentChallenge(), this.recoveryCodes = Array.from({ length: 6 }, J), { recoveryCodes: this.recoveryCodes }));
568
+ return this.delay(() => (this.requireRecentChallenge(), this.recoveryCodes = Array.from({ length: 6 }, st), { recoveryCodes: this.recoveryCodes }));
533
569
  }
534
570
  /** Forget everything, as a sign out would. */
535
571
  reset() {
536
572
  this.user = null, this.mfaPending = !1, this.sessions = [], this.identities = [], this.logs = [], this.tokens.clear();
537
573
  }
538
574
  }
539
- function ft(e) {
575
+ function gt(e) {
540
576
  let t = 2166136261;
541
577
  const i = () => (t ^= t << 13, t ^= t >>> 17, t ^= t << 5, (t >>> 0) / 4294967296);
542
- for (const k of e) t = (t ^ k.charCodeAt(0)) * 16777619;
543
- const r = 25;
578
+ for (const x of e) t = (t ^ x.charCodeAt(0)) * 16777619;
579
+ const s = 25;
544
580
  let a = "";
545
- const h = (k, A) => `<rect x="${k}" y="${A}" width="7" height="7"/><rect x="${k + 1}" y="${A + 1}" width="5" height="5" fill="#fff"/><rect x="${k + 2}" y="${A + 2}" width="3" height="3"/>`;
546
- for (let k = 0; k < r; k++)
547
- for (let A = 0; A < r; A++)
548
- !(A < 8 && k < 8 || A >= r - 8 && k < 8 || A < 8 && k >= r - 8) && i() < 0.45 && (a += `<rect x="${A}" y="${k}" width="1" height="1"/>`);
549
- const u = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${r} ${r}" shape-rendering="crispEdges"><rect width="${r}" height="${r}" fill="#fff"/><g fill="#000">${h(0, 0)}${h(r - 7, 0)}${h(0, r - 7)}${a}</g></svg>`;
550
- return `data:image/svg+xml;utf8,${encodeURIComponent(u)}`;
581
+ const h = (x, C) => `<rect x="${x}" y="${C}" width="7" height="7"/><rect x="${x + 1}" y="${C + 1}" width="5" height="5" fill="#fff"/><rect x="${x + 2}" y="${C + 2}" width="3" height="3"/>`;
582
+ for (let x = 0; x < s; x++)
583
+ for (let C = 0; C < s; C++)
584
+ !(C < 8 && x < 8 || C >= s - 8 && x < 8 || C < 8 && x >= s - 8) && i() < 0.45 && (a += `<rect x="${C}" y="${x}" width="1" height="1"/>`);
585
+ const p = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${s} ${s}" shape-rendering="crispEdges"><rect width="${s}" height="${s}" fill="#fff"/><g fill="#000">${h(0, 0)}${h(s - 7, 0)}${h(0, s - 7)}${a}</g></svg>`;
586
+ return `data:image/svg+xml;utf8,${encodeURIComponent(p)}`;
551
587
  }
552
588
  const v = {
553
589
  moreFactorsRequired: "user_more_factors_required",
@@ -579,27 +615,29 @@ const v = {
579
615
  userUnauthorized: "user_unauthorized",
580
616
  authMethodUnsupported: "user_auth_method_unsupported",
581
617
  countMaxExceeded: "user_count_exceeded",
582
- targetAlreadyExists: "user_target_already_exists"
618
+ targetAlreadyExists: "user_target_already_exists",
619
+ argumentInvalid: "general_argument_invalid"
583
620
  };
584
- function T(e) {
621
+ function B(e) {
585
622
  if (e && typeof e == "object") {
586
623
  const t = e;
587
- return {
588
- message: typeof t.message == "string" ? t.message : "Unknown error",
624
+ let i = typeof t.message == "string" ? t.message : "Unknown error";
625
+ return /^\s*<(!doctype|html)/i.test(i) && (i = ""), {
626
+ message: i,
589
627
  type: typeof t.type == "string" ? t.type : "",
590
628
  code: typeof t.code == "number" ? t.code : 0
591
629
  };
592
630
  }
593
631
  return { message: String(e), type: "", code: 0 };
594
632
  }
595
- function N(e, t) {
596
- return T(e).type === t;
633
+ function z(e, t) {
634
+ return B(e).type === t;
597
635
  }
598
- function at(e, t, i = "link") {
599
- const r = T(e);
600
- switch (r.type) {
636
+ function Z(e, t, i = "link") {
637
+ const s = B(e);
638
+ switch (s.type) {
601
639
  case v.invalidCredentials:
602
- return t.errorInvalidCredentials;
640
+ return i === "password" ? t.errorCurrentPassword : t.errorInvalidCredentials;
603
641
  case v.userAlreadyExists:
604
642
  case v.emailAlreadyExists:
605
643
  case v.phoneAlreadyExists:
@@ -632,11 +670,15 @@ function at(e, t, i = "link") {
632
670
  case v.authMethodUnsupported:
633
671
  return t.errorMethodDisabled;
634
672
  }
635
- return r.code === 0 && /fetch|network/i.test(r.message) ? t.errorNetwork : r.message || t.errorGeneric;
673
+ if (s.type === v.argumentInvalid || /Invalid `\w+` param/i.test(s.message)) {
674
+ const a = s.message.match(/Invalid `([^`]+)` param/i)?.[1]?.toLowerCase();
675
+ return a === "email" ? t.errorInvalidEmail : a === "password" ? t.errorInvalidPassword : a === "phone" ? t.errorInvalidPhone : a === "name" ? t.errorInvalidName : t.errorGeneric;
676
+ }
677
+ return s.code === 0 && /fetch|network/i.test(s.message) ? t.errorNetwork : /Invalid `\w+` param/i.test(s.message) || /^\s*<(!doctype|html)/i.test(s.message) ? t.errorGeneric : s.message || t.errorGeneric;
636
678
  }
637
- function C(e, t, i) {
638
- for (const r of t) {
639
- const a = e[r];
679
+ function S(e, t, i) {
680
+ for (const s of t) {
681
+ const a = e[s];
640
682
  if (typeof a == "function")
641
683
  return a.apply(e, i);
642
684
  }
@@ -644,21 +686,21 @@ function C(e, t, i) {
644
686
  new Error(`Appwrite SDK is missing ${t[0]}(). Update the appwrite package.`)
645
687
  );
646
688
  }
647
- const W = "authui", tt = ["userId", "secret", "expire", "project", "error", W], et = () => ({
689
+ const K = "authui", rt = ["userId", "secret", "expire", "project", "error", K], at = () => ({
648
690
  status: "loading",
649
691
  user: null,
650
692
  mfaFactors: null,
651
693
  pending: null,
652
694
  configured: !1
653
695
  });
654
- class mt {
696
+ class vt {
655
697
  constructor() {
656
- this.client = null, this.account = null, this.config = null, this.state = et(), this.listeners = /* @__PURE__ */ new Map(), this.refreshPromise = null, this.preview = null;
698
+ this.client = null, this.account = null, this.config = null, this.state = at(), this.listeners = /* @__PURE__ */ new Map(), this.refreshPromise = null, this.preview = null;
657
699
  }
658
700
  // ───────────────────────────── configuration ─────────────────────────────
659
701
  /** Configure the Appwrite client. Safe to call more than once; the last call wins. */
660
702
  configure(t) {
661
- this.config = t, this.client = new nt().setEndpoint(t.endpoint).setProject(t.project), this.preview = t.preview ? new pt() : null, this.account = this.preview ? this.preview : new ot(this.client), this.setState({ configured: !0, status: "loading" }), this.preview ? this.refresh() : typeof window < "u" && this.handleRedirect().then(() => this.refresh());
703
+ this.config = t, this.client = new tt().setEndpoint(t.endpoint).setProject(t.project), this.preview = t.preview ? new mt() : null, this.account = this.preview ? this.preview : new et(this.client), this.setState({ configured: !0, status: "loading" }), this.preview ? this.refresh() : typeof window < "u" && this.handleRedirect().then(() => this.refresh());
662
704
  }
663
705
  get isConfigured() {
664
706
  return this.config !== null;
@@ -686,7 +728,7 @@ class mt {
686
728
  return this.account;
687
729
  }
688
730
  getStrings() {
689
- return { ...lt, ...this.config?.strings ?? {} };
731
+ return { ...ht, ...this.config?.strings ?? {} };
690
732
  }
691
733
  getState() {
692
734
  return { ...this.state };
@@ -696,13 +738,13 @@ class mt {
696
738
  }
697
739
  // ─────────────────────────────── events ───────────────────────────────
698
740
  on(t, i) {
699
- let r = this.listeners.get(t);
700
- return r || (r = /* @__PURE__ */ new Set(), this.listeners.set(t, r)), r.add(i), () => r.delete(i);
741
+ let s = this.listeners.get(t);
742
+ return s || (s = /* @__PURE__ */ new Set(), this.listeners.set(t, s)), s.add(i), () => s.delete(i);
701
743
  }
702
744
  emit(t, i) {
703
- this.listeners.get(t)?.forEach((r) => {
745
+ this.listeners.get(t)?.forEach((s) => {
704
746
  try {
705
- r(i);
747
+ s(i);
706
748
  } catch (a) {
707
749
  console.error("[authui] listener failed", a);
708
750
  }
@@ -712,7 +754,7 @@ class mt {
712
754
  this.state = { ...this.state, ...t }, this.emit("change", this.getState());
713
755
  }
714
756
  fail(t) {
715
- const i = T(t);
757
+ const i = B(t);
716
758
  throw this.emit("error", i), t;
717
759
  }
718
760
  acct() {
@@ -732,41 +774,76 @@ class mt {
732
774
  const i = await this.account.get();
733
775
  this.setState({ status: "signed-in", user: i, mfaFactors: null }), t || this.emit("signed-in", i);
734
776
  } catch (i) {
735
- if (N(i, v.moreFactorsRequired)) {
736
- let r = null;
777
+ if (z(i, v.moreFactorsRequired)) {
778
+ let s = null;
737
779
  try {
738
- r = await C(
780
+ s = await S(
739
781
  this.account,
740
782
  ["listMFAFactors", "listMfaFactors"],
741
783
  []
742
784
  );
743
785
  } catch {
744
786
  }
745
- this.setState({ status: "mfa-required", user: null, mfaFactors: r });
746
- } else
747
- this.setState({ status: "signed-out", user: null, mfaFactors: null }), t && this.emit("signed-out", void 0);
787
+ this.setState({ status: "mfa-required", user: null, mfaFactors: s });
788
+ } else z(i, v.userBlocked) ? (await this.purgeLocalSession(), this.setState({
789
+ status: "signed-out",
790
+ user: null,
791
+ mfaFactors: null,
792
+ pending: {
793
+ type: "notice",
794
+ tone: "error",
795
+ message: this.getStrings().errorUserBlocked
796
+ }
797
+ }), t && this.emit("signed-out", void 0)) : (this.setState({ status: "signed-out", user: null, mfaFactors: null }), t && this.emit("signed-out", void 0));
748
798
  }
749
799
  })().finally(() => {
750
800
  this.refreshPromise = null;
751
801
  }), this.refreshPromise);
752
802
  }
753
803
  async afterSignIn() {
754
- await this.refresh();
804
+ if (await this.refresh(), this.state.status !== "signed-in" && this.state.status !== "mfa-required") {
805
+ const i = this.state.pending;
806
+ if (i?.type === "notice" && i.tone === "error")
807
+ throw Object.assign(new Error(i.message), {
808
+ type: v.userBlocked,
809
+ code: 401
810
+ });
811
+ }
755
812
  const t = this.config?.successUrl;
756
813
  t && this.state.status === "signed-in" && typeof window < "u" && window.location.assign(t);
757
814
  }
815
+ /**
816
+ * Drop a poisoned Appwrite session (e.g. after user_blocked). Deletes the
817
+ * current session when possible and clears the SDK fallback without reading it.
818
+ */
819
+ async purgeLocalSession() {
820
+ try {
821
+ await this.account?.deleteSession("current");
822
+ } catch {
823
+ }
824
+ try {
825
+ this.client?.setSession("");
826
+ } catch {
827
+ }
828
+ if (typeof localStorage < "u")
829
+ try {
830
+ localStorage.removeItem("cookieFallback");
831
+ } catch {
832
+ }
833
+ this.config && !this.preview && (this.client = new tt().setEndpoint(this.config.endpoint).setProject(this.config.project), this.account = new et(this.client));
834
+ }
758
835
  // ─────────────────────────────── sign in ───────────────────────────────
759
836
  async signInWithEmailPassword(t, i) {
760
837
  try {
761
838
  await this.acct().createEmailPasswordSession(t.trim(), i);
762
- } catch (r) {
763
- this.fail(r);
839
+ } catch (s) {
840
+ this.fail(s);
764
841
  }
765
842
  await this.afterSignIn();
766
843
  }
767
- async signUp(t, i, r) {
844
+ async signUp(t, i, s) {
768
845
  try {
769
- await this.acct().create(L.unique(), t.trim(), i, r?.trim() || void 0), await this.acct().createEmailPasswordSession(t.trim(), i);
846
+ await this.acct().create(L.unique(), t.trim(), i, s?.trim() || void 0), await this.acct().createEmailPasswordSession(t.trim(), i);
770
847
  } catch (a) {
771
848
  this.fail(a);
772
849
  }
@@ -786,9 +863,9 @@ class mt {
786
863
  */
787
864
  async signInWithOAuth(t) {
788
865
  const i = this.config?.oauthScopes?.[t];
789
- let r;
866
+ let s;
790
867
  try {
791
- r = this.acct().createOAuth2Token(
868
+ s = this.acct().createOAuth2Token(
792
869
  t,
793
870
  this.redirectUrl("oauth"),
794
871
  this.redirectUrl("oauth-failed"),
@@ -797,9 +874,9 @@ class mt {
797
874
  } catch (a) {
798
875
  this.fail(a);
799
876
  }
800
- if (r && typeof r.then == "function") {
877
+ if (s && typeof s.then == "function") {
801
878
  try {
802
- await r;
879
+ await s;
803
880
  } catch (a) {
804
881
  this.fail(a);
805
882
  }
@@ -840,15 +917,15 @@ class mt {
840
917
  async signInWithToken(t, i) {
841
918
  try {
842
919
  await this.acct().createSession(t, i.trim());
843
- } catch (r) {
844
- this.fail(r);
920
+ } catch (s) {
921
+ this.fail(s);
845
922
  }
846
923
  await this.afterSignIn();
847
924
  }
848
925
  // ─────────────────────────────── MFA ───────────────────────────────
849
926
  async createMfaChallenge(t) {
850
927
  try {
851
- return await C(
928
+ return await S(
852
929
  this.acct(),
853
930
  ["createMFAChallenge", "createMfaChallenge"],
854
931
  [t]
@@ -858,9 +935,9 @@ class mt {
858
935
  }
859
936
  }
860
937
  /** Verify a challenge. Completes a pending sign in, or acts as a step-up for protected actions. */
861
- async completeMfaChallenge(t, i, r = {}) {
938
+ async completeMfaChallenge(t, i, s = {}) {
862
939
  try {
863
- await C(
940
+ await S(
864
941
  this.acct(),
865
942
  ["updateMFAChallenge", "updateMfaChallenge"],
866
943
  [t, i.trim()]
@@ -868,11 +945,11 @@ class mt {
868
945
  } catch (a) {
869
946
  this.fail(a);
870
947
  }
871
- (r.signIn ?? !0) && await this.afterSignIn();
948
+ (s.signIn ?? !0) && await this.afterSignIn();
872
949
  }
873
950
  async listMfaFactors() {
874
951
  try {
875
- return await C(this.acct(), ["listMFAFactors", "listMfaFactors"], []);
952
+ return await S(this.acct(), ["listMFAFactors", "listMfaFactors"], []);
876
953
  } catch (t) {
877
954
  return this.fail(t);
878
955
  }
@@ -887,7 +964,7 @@ class mt {
887
964
  }
888
965
  async addAuthenticator() {
889
966
  try {
890
- return await C(
967
+ return await S(
891
968
  this.acct(),
892
969
  ["createMFAAuthenticator", "createMfaAuthenticator"],
893
970
  ["totp"]
@@ -898,7 +975,7 @@ class mt {
898
975
  }
899
976
  async verifyAuthenticator(t) {
900
977
  try {
901
- await C(
978
+ await S(
902
979
  this.acct(),
903
980
  ["updateMFAAuthenticator", "updateMfaAuthenticator"],
904
981
  ["totp", t.trim()]
@@ -911,7 +988,7 @@ class mt {
911
988
  /** Requires a recent MFA challenge (server rejects with user_challenge_required otherwise). */
912
989
  async removeAuthenticator() {
913
990
  try {
914
- await C(this.acct(), ["deleteMFAAuthenticator", "deleteMfaAuthenticator"], ["totp"]);
991
+ await S(this.acct(), ["deleteMFAAuthenticator", "deleteMfaAuthenticator"], ["totp"]);
915
992
  } catch (t) {
916
993
  this.fail(t);
917
994
  }
@@ -919,7 +996,7 @@ class mt {
919
996
  }
920
997
  async createRecoveryCodes() {
921
998
  try {
922
- return (await C(
999
+ return (await S(
923
1000
  this.acct(),
924
1001
  ["createMFARecoveryCodes", "createMfaRecoveryCodes"],
925
1002
  []
@@ -931,7 +1008,7 @@ class mt {
931
1008
  /** Requires a recent MFA challenge. */
932
1009
  async regenerateRecoveryCodes() {
933
1010
  try {
934
- return (await C(
1011
+ return (await S(
935
1012
  this.acct(),
936
1013
  ["updateMFARecoveryCodes", "updateMfaRecoveryCodes"],
937
1014
  []
@@ -943,7 +1020,7 @@ class mt {
943
1020
  /** Requires a recent MFA challenge. */
944
1021
  async getRecoveryCodes() {
945
1022
  try {
946
- return (await C(
1023
+ return (await S(
947
1024
  this.acct(),
948
1025
  ["getMFARecoveryCodes", "getMfaRecoveryCodes"],
949
1026
  []
@@ -960,9 +1037,9 @@ class mt {
960
1037
  this.fail(i);
961
1038
  }
962
1039
  }
963
- async completePasswordRecovery(t, i, r) {
1040
+ async completePasswordRecovery(t, i, s) {
964
1041
  try {
965
- await this.acct().updateRecovery(t, i, r);
1042
+ await this.acct().updateRecovery(t, i, s);
966
1043
  } catch (a) {
967
1044
  this.fail(a);
968
1045
  }
@@ -975,7 +1052,15 @@ class mt {
975
1052
  } catch (i) {
976
1053
  this.fail(i);
977
1054
  }
978
- t === "current" && (this.setState({ status: "signed-out", user: null, mfaFactors: null }), this.emit("signed-out", void 0));
1055
+ if (t === "current") {
1056
+ this.setState({ status: "signed-out", user: null, mfaFactors: null }), this.emit("signed-out", void 0);
1057
+ return;
1058
+ }
1059
+ try {
1060
+ await this.acct().get();
1061
+ } catch {
1062
+ this.setState({ status: "signed-out", user: null, mfaFactors: null }), this.emit("signed-out", void 0);
1063
+ }
979
1064
  }
980
1065
  async signOutEverywhere() {
981
1066
  try {
@@ -1025,31 +1110,31 @@ class mt {
1025
1110
  async updateEmail(t, i) {
1026
1111
  try {
1027
1112
  await this.acct().updateEmail(t.trim(), i);
1028
- } catch (r) {
1029
- this.fail(r);
1113
+ } catch (s) {
1114
+ this.fail(s);
1030
1115
  }
1031
1116
  await this.refresh();
1032
1117
  }
1033
1118
  async updatePhone(t, i) {
1034
1119
  try {
1035
1120
  await this.acct().updatePhone(t.replace(/[\s()-]/g, ""), i);
1036
- } catch (r) {
1037
- this.fail(r);
1121
+ } catch (s) {
1122
+ this.fail(s);
1038
1123
  }
1039
1124
  await this.refresh();
1040
1125
  }
1041
1126
  async updatePassword(t, i) {
1042
1127
  try {
1043
1128
  await this.acct().updatePassword(t, i || void 0);
1044
- } catch (r) {
1045
- this.fail(r);
1129
+ } catch (s) {
1130
+ this.fail(s);
1046
1131
  }
1047
1132
  await this.refresh();
1048
1133
  }
1049
1134
  /** Turn an anonymous session into a full account. */
1050
- async convertGuest(t, i, r) {
1135
+ async convertGuest(t, i, s) {
1051
1136
  try {
1052
- await this.acct().updateEmail(t.trim(), i), r?.trim() && await this.acct().updateName(r.trim());
1137
+ await this.acct().updateEmail(t.trim(), i), s?.trim() && await this.acct().updateName(s.trim());
1053
1138
  } catch (a) {
1054
1139
  this.fail(a);
1055
1140
  }
@@ -1057,7 +1142,7 @@ class mt {
1057
1142
  }
1058
1143
  async sendEmailVerification() {
1059
1144
  try {
1060
- await C(
1145
+ await S(
1061
1146
  this.acct(),
1062
1147
  ["createEmailVerification", "createVerification"],
1063
1148
  [this.redirectUrl("verify-email")]
@@ -1078,8 +1163,8 @@ class mt {
1078
1163
  if (i) {
1079
1164
  try {
1080
1165
  await this.acct().updatePhoneVerification(i, t.trim());
1081
- } catch (r) {
1082
- this.fail(r);
1166
+ } catch (s) {
1167
+ this.fail(s);
1083
1168
  }
1084
1169
  await this.refresh();
1085
1170
  }
@@ -1096,9 +1181,9 @@ class mt {
1096
1181
  // ───────────────────────────── redirects ─────────────────────────────
1097
1182
  /** Build the URL Appwrite should send the user back to for a given flow. */
1098
1183
  redirectUrl(t) {
1099
- 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);
1100
- for (const a of tt) r.searchParams.delete(a);
1101
- return r.searchParams.set(W, t), r.toString();
1184
+ const i = this.config?.redirectUrl ?? (typeof window < "u" ? window.location.origin + window.location.pathname : ""), s = new URL(i, typeof window < "u" ? window.location.href : void 0);
1185
+ for (const a of rt) s.searchParams.delete(a);
1186
+ return s.searchParams.set(K, t), s.toString();
1102
1187
  }
1103
1188
  setPending(t) {
1104
1189
  this.setState({ pending: t });
@@ -1109,54 +1194,63 @@ class mt {
1109
1194
  */
1110
1195
  async handleRedirect() {
1111
1196
  if (typeof window > "u") return !1;
1112
- const t = new URLSearchParams(window.location.search), i = t.get(W);
1197
+ const t = new URLSearchParams(window.location.search), i = t.get(K);
1113
1198
  if (!i) return !1;
1114
- const r = t.get("userId") ?? "", a = t.get("secret") ?? "";
1199
+ const s = t.get("userId") ?? "", a = t.get("secret") ?? "";
1115
1200
  this.cleanUrl();
1201
+ const h = () => {
1202
+ this.setState({
1203
+ pending: {
1204
+ type: "notice",
1205
+ message: this.getStrings().errorInvalidToken,
1206
+ tone: "error"
1207
+ }
1208
+ });
1209
+ };
1116
1210
  try {
1117
1211
  switch (i) {
1118
1212
  case "oauth":
1119
1213
  case "magic-url":
1120
- r && a && await this.acct().createSession(r, a);
1214
+ s && a ? await this.acct().createSession(s, a) : h();
1121
1215
  break;
1122
1216
  case "oauth-failed":
1123
1217
  this.setState({ pending: { type: "oauth-failed" } });
1124
1218
  break;
1125
1219
  case "recovery":
1126
- r && a && this.setState({ pending: { type: "reset-password", userId: r, secret: a } });
1220
+ s && a ? this.setState({ pending: { type: "reset-password", userId: s, secret: a } }) : h();
1127
1221
  break;
1128
1222
  case "verify-email":
1129
- r && a && (await C(
1223
+ s && a ? (await S(
1130
1224
  this.acct(),
1131
1225
  ["updateEmailVerification", "updateVerification"],
1132
- [r, a]
1226
+ [s, a]
1133
1227
  ), this.setState({
1134
1228
  pending: {
1135
1229
  type: "notice",
1136
1230
  message: this.getStrings().emailVerified,
1137
1231
  tone: "success"
1138
1232
  }
1139
- }));
1233
+ })) : h();
1140
1234
  break;
1141
1235
  }
1142
- } catch (h) {
1143
- const u = T(h);
1144
- this.emit("error", u), this.setState({ pending: { type: "notice", message: u.message, tone: "error" } });
1236
+ } catch (p) {
1237
+ const x = B(p), C = Z(p, this.getStrings(), "link");
1238
+ this.emit("error", x), this.setState({ pending: { type: "notice", message: C, tone: "error" } });
1145
1239
  }
1146
1240
  return !0;
1147
1241
  }
1148
1242
  cleanUrl() {
1149
1243
  const t = new URL(window.location.href);
1150
- for (const i of tt) t.searchParams.delete(i);
1244
+ for (const i of rt) t.searchParams.delete(i);
1151
1245
  window.history.replaceState(window.history.state, "", t.toString());
1152
1246
  }
1153
1247
  /** Test helper. */
1154
1248
  reset() {
1155
- this.client = null, this.account = null, this.preview = null, this.config = null, this.state = et(), this.listeners.clear();
1249
+ this.client = null, this.account = null, this.preview = null, this.config = null, this.state = at(), this.listeners.clear();
1156
1250
  }
1157
1251
  }
1158
- const n = new mt();
1159
- class gt {
1252
+ const n = new vt();
1253
+ class bt {
1160
1254
  constructor() {
1161
1255
  this.listeners = /* @__PURE__ */ new Set(), this.observer = null, this.media = null, this.notify = () => {
1162
1256
  const t = this.isDark("auto");
@@ -1184,14 +1278,14 @@ class gt {
1184
1278
  this.observer?.disconnect(), this.observer = null, this.media?.removeEventListener?.("change", this.notify), this.media = null;
1185
1279
  }
1186
1280
  }
1187
- const it = new gt(), st = {
1281
+ const nt = new bt(), ot = {
1188
1282
  none: "0px",
1189
1283
  sm: "0.25rem",
1190
1284
  md: "0.625rem",
1191
1285
  lg: "0.875rem",
1192
1286
  xl: "1.125rem",
1193
1287
  full: "1.5rem"
1194
- }, vt = E`
1288
+ }, yt = I`
1195
1289
  :host {
1196
1290
  /* Light theme (matches :root in the console) */
1197
1291
  --authui-background: oklch(1 0 0);
@@ -1269,7 +1363,7 @@ const it = new gt(), st = {
1269
1363
  --authui-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -4px rgba(0, 0, 0, 0.5);
1270
1364
  color-scheme: dark;
1271
1365
  }
1272
- `, bt = E`
1366
+ `, wt = I`
1273
1367
  *,
1274
1368
  *::before,
1275
1369
  *::after {
@@ -1284,6 +1378,8 @@ const it = new gt(), st = {
1284
1378
  -webkit-font-smoothing: antialiased;
1285
1379
  -moz-osx-font-smoothing: grayscale;
1286
1380
  text-align: start;
1381
+ min-width: 0;
1382
+ max-width: 100%;
1287
1383
  }
1288
1384
 
1289
1385
  [hidden] {
@@ -1539,6 +1635,9 @@ const it = new gt(), st = {
1539
1635
  }
1540
1636
 
1541
1637
  /* ── Alert ── */
1638
+ .alert:has(.dismiss) {
1639
+ padding-inline-end: 36px;
1640
+ }
1542
1641
  .alert {
1543
1642
  position: relative;
1544
1643
  width: 100%;
@@ -1660,7 +1759,7 @@ const it = new gt(), st = {
1660
1759
  .tabs {
1661
1760
  display: inline-flex;
1662
1761
  align-items: center;
1663
- justify-content: center;
1762
+ justify-content: flex-start;
1664
1763
  height: 36px;
1665
1764
  width: fit-content;
1666
1765
  max-width: 100%;
@@ -1671,6 +1770,7 @@ const it = new gt(), st = {
1671
1770
  padding: 3px;
1672
1771
  gap: 2px;
1673
1772
  scrollbar-width: none;
1773
+ -webkit-overflow-scrolling: touch;
1674
1774
  }
1675
1775
  :host([data-theme="dark"]) .tabs {
1676
1776
  background: color-mix(in oklab, var(--authui-muted) 80%, transparent);
@@ -1681,7 +1781,7 @@ const it = new gt(), st = {
1681
1781
  justify-content: center;
1682
1782
  gap: 6px;
1683
1783
  height: 100%;
1684
- flex: 1;
1784
+ flex: 0 0 auto;
1685
1785
  padding: 4px 10px;
1686
1786
  border-radius: var(--authui-radius-md);
1687
1787
  border: 1px solid transparent;
@@ -1808,6 +1908,8 @@ const it = new gt(), st = {
1808
1908
  align-items: center;
1809
1909
  gap: 8px;
1810
1910
  flex-wrap: wrap;
1911
+ min-width: 0;
1912
+ flex: 1;
1811
1913
  }
1812
1914
  .between {
1813
1915
  display: flex;
@@ -1916,6 +2018,9 @@ const it = new gt(), st = {
1916
2018
  .providers.two {
1917
2019
  grid-template-columns: repeat(2, minmax(0, 1fr));
1918
2020
  }
2021
+ .providers.two > :last-child:nth-child(odd) {
2022
+ grid-column: 1 / -1;
2023
+ }
1919
2024
  .providers .btn svg {
1920
2025
  width: 18px;
1921
2026
  height: 18px;
@@ -2012,29 +2117,33 @@ const it = new gt(), st = {
2012
2117
  }
2013
2118
  }
2014
2119
  `;
2015
- var yt = Object.defineProperty, wt = (e, t, i, r) => {
2016
- for (var a = void 0, h = e.length - 1, u; h >= 0; h--)
2017
- (u = e[h]) && (a = u(t, i, a) || a);
2018
- return a && yt(t, i, a), a;
2019
- };
2020
- const Q = class Q extends K {
2120
+ var $t = Object.defineProperty, xt = (e, t, i, s) => {
2121
+ for (var a = void 0, h = e.length - 1, p; h >= 0; h--)
2122
+ (p = e[h]) && (a = p(t, i, a) || a);
2123
+ return a && $t(t, i, a), a;
2124
+ }, E;
2125
+ const lt = (E = class extends X {
2021
2126
  constructor() {
2022
- super(...arguments), this.auth = n.getState(), this.unsubscribeStore = null, this.unsubscribeTheme = null;
2127
+ super(...arguments), this.auth = n.getState(), this.unsubscribeStore = null, this.unsubscribeTheme = null, this.stopKeys = (t) => t.stopPropagation();
2023
2128
  }
2024
2129
  connectedCallback() {
2025
- super.connectedCallback(), this.auth = n.getState(), this.unsubscribeStore = n.on("change", (t) => {
2130
+ super.connectedCallback();
2131
+ for (const t of E.KEY_EVENTS) this.addEventListener(t, this.stopKeys);
2132
+ this.auth = n.getState(), this.unsubscribeStore = n.on("change", (t) => {
2026
2133
  this.auth = t, this.applyBranding();
2027
- }), this.unsubscribeTheme = it.subscribe(() => this.applyBranding()), this.applyBranding();
2134
+ }), this.unsubscribeTheme = nt.subscribe(() => this.applyBranding()), this.applyBranding();
2028
2135
  }
2029
2136
  disconnectedCallback() {
2030
- super.disconnectedCallback(), this.unsubscribeStore?.(), this.unsubscribeTheme?.(), this.unsubscribeStore = null, this.unsubscribeTheme = null;
2137
+ super.disconnectedCallback();
2138
+ for (const t of E.KEY_EVENTS) this.removeEventListener(t, this.stopKeys);
2139
+ this.unsubscribeStore?.(), this.unsubscribeTheme?.(), this.unsubscribeStore = null, this.unsubscribeTheme = null;
2031
2140
  }
2032
2141
  get strings() {
2033
2142
  return n.getStrings();
2034
2143
  }
2035
2144
  /** Translate a string key with optional `{placeholders}`. */
2036
2145
  t(t, i) {
2037
- return dt(this.strings[t], i);
2146
+ return ut(this.strings[t], i);
2038
2147
  }
2039
2148
  get config() {
2040
2149
  return n.getConfig();
@@ -2044,28 +2153,27 @@ const Q = class Q extends K {
2044
2153
  }
2045
2154
  /** Push theme and branding from config onto the host element. */
2046
2155
  applyBranding() {
2047
- const t = this.config?.branding, i = it.isDark(t?.theme ?? "auto");
2156
+ const t = this.config?.branding, i = nt.isDark(t?.theme ?? "auto");
2048
2157
  this.setAttribute("data-theme", i ? "dark" : "light"), t?.primary && (this.style.setProperty("--authui-primary", t.primary), this.style.setProperty(
2049
2158
  "--authui-primary-foreground",
2050
2159
  t.primaryForeground ?? "#ffffff"
2051
- )), t?.radius && st[t.radius] && this.style.setProperty("--authui-radius", st[t.radius]);
2160
+ )), t?.radius && ot[t.radius] && this.style.setProperty("--authui-radius", ot[t.radius]);
2052
2161
  }
2053
2162
  /** Emit a composed custom event from this element. */
2054
2163
  fire(t, i) {
2055
2164
  this.dispatchEvent(new CustomEvent(t, { detail: i, bubbles: !0, composed: !0 }));
2056
2165
  }
2057
- };
2058
- Q.styles = [vt, bt];
2059
- let x = Q;
2060
- wt([
2166
+ }, E.styles = [yt, wt], E.KEY_EVENTS = ["keydown", "keyup", "keypress"], E);
2167
+ xt([
2061
2168
  d()
2062
- ], x.prototype, "auth");
2063
- var $t = Object.defineProperty, xt = Object.getOwnPropertyDescriptor, y = (e, t, i, r) => {
2064
- for (var a = r > 1 ? void 0 : r ? xt(t, i) : t, h = e.length - 1, u; h >= 0; h--)
2065
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
2066
- return r && a && $t(t, i, a), a;
2169
+ ], lt.prototype, "auth");
2170
+ let A = lt;
2171
+ var kt = Object.defineProperty, Ct = Object.getOwnPropertyDescriptor, y = (e, t, i, s) => {
2172
+ for (var a = s > 1 ? void 0 : s ? Ct(t, i) : t, h = e.length - 1, p; h >= 0; h--)
2173
+ (p = e[h]) && (a = (s ? p(t, i, a) : p(a)) || a);
2174
+ return s && a && kt(t, i, a), a;
2067
2175
  };
2068
- let b = class extends K {
2176
+ let b = class extends X {
2069
2177
  constructor() {
2070
2178
  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 = "", this.preview = "";
2071
2179
  }
@@ -2081,10 +2189,10 @@ let b = class extends K {
2081
2189
  t && JSON.stringify(t) === JSON.stringify(e) || n.configure(e);
2082
2190
  }
2083
2191
  toConfig() {
2084
- const e = { oauth: [] };
2085
- for (const t of this.methods.split(/[\s,]+/).filter(Boolean))
2086
- 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);
2087
- return e.emailPassword === void 0 && !this.methods.trim() && (e.emailPassword = !0), {
2192
+ const e = { oauth: [] }, t = this.methods.split(/[\s,]+/).filter(Boolean);
2193
+ for (const i of t)
2194
+ i.startsWith("oauth:") ? e.oauth.push(i.slice(6)) : i === "email-password" ? e.emailPassword = !0 : i === "magic-url" ? e.magicUrl = !0 : i === "email-otp" ? e.emailOtp = !0 : i === "phone" ? e.phone = !0 : (i === "anonymous" || i === "guest") && (e.anonymous = !0);
2195
+ return e.emailPassword = t.length > 0 ? t.includes("email-password") : !0, {
2088
2196
  endpoint: this.endpoint,
2089
2197
  project: this.project,
2090
2198
  redirectUrl: this.redirectUrl || void 0,
@@ -2110,82 +2218,82 @@ let b = class extends K {
2110
2218
  };
2111
2219
  }
2112
2220
  };
2113
- b.styles = E`
2221
+ b.styles = I`
2114
2222
  :host {
2115
2223
  display: none;
2116
2224
  }
2117
2225
  `;
2118
2226
  y([
2119
- f({ type: String })
2227
+ m({ type: String })
2120
2228
  ], b.prototype, "endpoint", 2);
2121
2229
  y([
2122
- f({ type: String })
2230
+ m({ type: String })
2123
2231
  ], b.prototype, "project", 2);
2124
2232
  y([
2125
- f({ type: String, attribute: "redirect-url" })
2233
+ m({ type: String, attribute: "redirect-url" })
2126
2234
  ], b.prototype, "redirectUrl", 2);
2127
2235
  y([
2128
- f({ type: String, attribute: "success-url" })
2236
+ m({ type: String, attribute: "success-url" })
2129
2237
  ], b.prototype, "successUrl", 2);
2130
2238
  y([
2131
- f({ type: String })
2239
+ m({ type: String })
2132
2240
  ], b.prototype, "methods", 2);
2133
2241
  y([
2134
- f({ type: String, attribute: "sign-up" })
2242
+ m({ type: String, attribute: "sign-up" })
2135
2243
  ], b.prototype, "signUp", 2);
2136
2244
  y([
2137
- f({ type: String, attribute: "require-name" })
2245
+ m({ type: String, attribute: "require-name" })
2138
2246
  ], b.prototype, "requireName", 2);
2139
2247
  y([
2140
- f({ type: String })
2248
+ m({ type: String })
2141
2249
  ], b.prototype, "mfa", 2);
2142
2250
  y([
2143
- f({ type: String, attribute: "security-phrase" })
2251
+ m({ type: String, attribute: "security-phrase" })
2144
2252
  ], b.prototype, "securityPhrase", 2);
2145
2253
  y([
2146
- f({ type: String })
2254
+ m({ type: String })
2147
2255
  ], b.prototype, "name", 2);
2148
2256
  y([
2149
- f({ type: String })
2257
+ m({ type: String })
2150
2258
  ], b.prototype, "logo", 2);
2151
2259
  y([
2152
- f({ type: String })
2260
+ m({ type: String })
2153
2261
  ], b.prototype, "theme", 2);
2154
2262
  y([
2155
- f({ type: String })
2263
+ m({ type: String })
2156
2264
  ], b.prototype, "radius", 2);
2157
2265
  y([
2158
- f({ type: String })
2266
+ m({ type: String })
2159
2267
  ], b.prototype, "primary", 2);
2160
2268
  y([
2161
- f({ type: String, attribute: "primary-foreground" })
2269
+ m({ type: String, attribute: "primary-foreground" })
2162
2270
  ], b.prototype, "primaryForeground", 2);
2163
2271
  y([
2164
- f({ type: String, attribute: "terms-url" })
2272
+ m({ type: String, attribute: "terms-url" })
2165
2273
  ], b.prototype, "termsUrl", 2);
2166
2274
  y([
2167
- f({ type: String, attribute: "privacy-url" })
2275
+ m({ type: String, attribute: "privacy-url" })
2168
2276
  ], b.prototype, "privacyUrl", 2);
2169
2277
  y([
2170
- f({ type: String })
2278
+ m({ type: String })
2171
2279
  ], b.prototype, "preview", 2);
2172
2280
  b = y([
2173
- I("authui-config")
2281
+ O("authui-config")
2174
2282
  ], b);
2175
- var kt = Object.defineProperty, Ct = Object.getOwnPropertyDescriptor, B = (e, t, i, r) => {
2176
- for (var a = r > 1 ? void 0 : r ? Ct(t, i) : t, h = e.length - 1, u; h >= 0; h--)
2177
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
2178
- return r && a && kt(t, i, a), a;
2283
+ var St = Object.defineProperty, Pt = Object.getOwnPropertyDescriptor, j = (e, t, i, s) => {
2284
+ for (var a = s > 1 ? void 0 : s ? Pt(t, i) : t, h = e.length - 1, p; h >= 0; h--)
2285
+ (p = e[h]) && (a = (s ? p(t, i, a) : p(a)) || a);
2286
+ return s && a && St(t, i, a), a;
2179
2287
  };
2180
2288
  if (typeof document < "u" && !document.getElementById("authui-fouc")) {
2181
2289
  const e = document.createElement("style");
2182
2290
  e.id = "authui-fouc", e.textContent = "authui-show:not([ready]){display:none}", document.head.appendChild(e);
2183
2291
  }
2184
- const Pt = ["loading", "signed-out", "signed-in", "mfa-required"];
2185
- function j(e) {
2186
- return e ? e.split(/[\s,]+/).map((t) => t.trim()).filter((t) => Pt.includes(t)) : [];
2292
+ const At = ["loading", "signed-out", "signed-in", "mfa-required"];
2293
+ function G(e) {
2294
+ return e ? e.split(/[\s,]+/).map((t) => t.trim()).filter((t) => At.includes(t)) : [];
2187
2295
  }
2188
- let D = class extends K {
2296
+ let V = class extends X {
2189
2297
  constructor() {
2190
2298
  super(...arguments), this.when = "", this.unless = "", this.status = n.getState().status, this.unsubscribe = null;
2191
2299
  }
@@ -2197,35 +2305,38 @@ let D = class extends K {
2197
2305
  }
2198
2306
  /** Whether the current status satisfies `when` and `unless`. */
2199
2307
  get visible() {
2200
- const e = j(this.when), t = j(this.unless);
2308
+ const e = G(this.when), t = G(this.unless);
2201
2309
  return !(this.status === "loading" && !e.includes("loading") || e.length > 0 && !e.includes(this.status) || t.includes(this.status));
2202
2310
  }
2203
2311
  updated() {
2204
- (this.status !== "loading" || j(this.when).includes("loading")) && (this.setAttribute("ready", ""), this.style.display = "contents");
2312
+ (this.status !== "loading" || G(this.when).includes("loading")) && (this.setAttribute("ready", ""), this.style.display = "contents");
2205
2313
  }
2206
2314
  render() {
2207
- return this.visible ? s`<slot></slot>` : o;
2315
+ return this.visible ? r`<slot></slot>` : c;
2208
2316
  }
2209
2317
  };
2210
- B([
2211
- f({ type: String })
2212
- ], D.prototype, "when", 2);
2213
- B([
2214
- f({ type: String })
2215
- ], D.prototype, "unless", 2);
2216
- B([
2318
+ j([
2319
+ m({ type: String })
2320
+ ], V.prototype, "when", 2);
2321
+ j([
2322
+ m({ type: String })
2323
+ ], V.prototype, "unless", 2);
2324
+ j([
2217
2325
  d()
2218
- ], D.prototype, "status", 2);
2219
- D = B([
2220
- I("authui-show")
2221
- ], D);
2222
- const St = E`
2326
+ ], V.prototype, "status", 2);
2327
+ V = j([
2328
+ O("authui-show")
2329
+ ], V);
2330
+ const Ut = I`
2223
2331
  :host {
2224
2332
  display: block;
2225
2333
  width: 100%;
2226
2334
  max-width: 420px;
2335
+ min-width: 0;
2227
2336
  }
2228
2337
  .panel {
2338
+ min-width: 0;
2339
+ overflow: hidden;
2229
2340
  background: var(--authui-card);
2230
2341
  color: var(--authui-card-foreground);
2231
2342
  border: 1px solid var(--authui-border);
@@ -2255,6 +2366,9 @@ const St = E`
2255
2366
  align-self: center;
2256
2367
  margin-bottom: 4px;
2257
2368
  }
2369
+ .alert:has(.dismiss) {
2370
+ padding-inline-end: 36px;
2371
+ }
2258
2372
  .alert .dismiss {
2259
2373
  position: absolute;
2260
2374
  top: 4px;
@@ -2267,7 +2381,7 @@ const St = E`
2267
2381
  height: 14px;
2268
2382
  margin: 0;
2269
2383
  }
2270
- `, m = (e) => s`<svg
2384
+ `, g = (e) => r`<svg
2271
2385
  xmlns="http://www.w3.org/2000/svg"
2272
2386
  viewBox="0 0 24 24"
2273
2387
  fill="none"
@@ -2278,86 +2392,86 @@ const St = E`
2278
2392
  aria-hidden="true"
2279
2393
  >
2280
2394
  ${e}
2281
- </svg>`, c = {
2282
- mail: m(
2395
+ </svg>`, o = {
2396
+ mail: g(
2283
2397
  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"/>`
2284
2398
  ),
2285
- phone: m(
2399
+ phone: g(
2286
2400
  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"/>`
2287
2401
  ),
2288
- user: m(
2402
+ user: g(
2289
2403
  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"/>`
2290
2404
  ),
2291
- userX: m(
2405
+ userX: g(
2292
2406
  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"/>`
2293
2407
  ),
2294
- lock: m(
2408
+ lock: g(
2295
2409
  l`<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>`
2296
2410
  ),
2297
- key: m(
2411
+ key: g(
2298
2412
  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"/>`
2299
2413
  ),
2300
- shield: m(
2414
+ shield: g(
2301
2415
  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"/>`
2302
2416
  ),
2303
- shieldCheck: m(
2417
+ shieldCheck: g(
2304
2418
  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"/>`
2305
2419
  ),
2306
- smartphone: m(
2420
+ smartphone: g(
2307
2421
  l`<rect width="14" height="20" x="5" y="2" rx="2" ry="2"/><path d="M12 18h.01"/>`
2308
2422
  ),
2309
- monitor: m(
2423
+ monitor: g(
2310
2424
  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"/>`
2311
2425
  ),
2312
- globe: m(
2426
+ globe: g(
2313
2427
  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"/>`
2314
2428
  ),
2315
- logOut: m(
2429
+ logOut: g(
2316
2430
  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"/>`
2317
2431
  ),
2318
- settings: m(
2432
+ settings: g(
2319
2433
  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"/>`
2320
2434
  ),
2321
- x: m(l`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`),
2322
- check: m(l`<path d="M20 6 9 17l-5-5"/>`),
2323
- copy: m(
2435
+ x: g(l`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`),
2436
+ check: g(l`<path d="M20 6 9 17l-5-5"/>`),
2437
+ copy: g(
2324
2438
  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"/>`
2325
2439
  ),
2326
- eye: m(
2440
+ eye: g(
2327
2441
  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"/>`
2328
2442
  ),
2329
- eyeOff: m(
2443
+ eyeOff: g(
2330
2444
  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"/>`
2331
2445
  ),
2332
- arrowLeft: m(l`<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>`),
2333
- alert: m(
2446
+ arrowLeft: g(l`<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>`),
2447
+ alert: g(
2334
2448
  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"/>`
2335
2449
  ),
2336
- info: m(l`<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>`),
2337
- checkCircle: m(l`<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>`),
2338
- link: m(
2450
+ info: g(l`<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>`),
2451
+ checkCircle: g(l`<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>`),
2452
+ link: g(
2339
2453
  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"/>`
2340
2454
  ),
2341
- activity: m(
2455
+ activity: g(
2342
2456
  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"/>`
2343
2457
  ),
2344
- trash: m(
2458
+ trash: g(
2345
2459
  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"/>`
2346
2460
  ),
2347
- sparkles: m(
2461
+ sparkles: g(
2348
2462
  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"/>`
2349
2463
  ),
2350
- refresh: m(
2464
+ refresh: g(
2351
2465
  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"/>`
2352
2466
  ),
2353
- chevronDown: m(l`<path d="m6 9 6 6 6-6"/>`),
2354
- ghost: m(
2467
+ chevronDown: g(l`<path d="m6 9 6 6 6-6"/>`),
2468
+ ghost: g(
2355
2469
  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"/>`
2356
2470
  ),
2357
- qr: m(
2471
+ qr: g(
2358
2472
  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"/>`
2359
2473
  )
2360
- }, w = (e, t = "0 0 24 24") => s`<svg xmlns="http://www.w3.org/2000/svg" viewBox=${t} aria-hidden="true">${e}</svg>`, At = {
2474
+ }, w = (e, t = "0 0 24 24") => r`<svg xmlns="http://www.w3.org/2000/svg" viewBox=${t} aria-hidden="true">${e}</svg>`, Et = {
2361
2475
  google: w(
2362
2476
  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"/>`
2363
2477
  ),
@@ -2413,22 +2527,34 @@ const St = E`
2413
2527
  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"/>`
2414
2528
  )
2415
2529
  };
2416
- function G(e) {
2417
- return At[e] ?? c.globe;
2530
+ function Y(e) {
2531
+ return Et[e] ?? o.globe;
2532
+ }
2533
+ function Q(e) {
2534
+ const t = (e.trim()[0] ?? "?").toUpperCase();
2535
+ return /[A-Z0-9]/i.test(t) ? t : o.user;
2536
+ }
2537
+ function H(e) {
2538
+ typeof document > "u" || (document.querySelector("authui-modal") || document.body.appendChild(document.createElement("authui-modal")), queueMicrotask(() => {
2539
+ window.dispatchEvent(new CustomEvent("authui:open", { detail: { view: e } }));
2540
+ }));
2418
2541
  }
2419
- var Mt = Object.defineProperty, Ut = Object.getOwnPropertyDescriptor, P = (e, t, i, r) => {
2420
- for (var a = r > 1 ? void 0 : r ? Ut(t, i) : t, h = e.length - 1, u; h >= 0; h--)
2421
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
2422
- return r && a && Mt(t, i, a), a;
2542
+ function Ht() {
2543
+ typeof window > "u" || window.dispatchEvent(new CustomEvent("authui:close"));
2544
+ }
2545
+ var Mt = Object.defineProperty, It = Object.getOwnPropertyDescriptor, k = (e, t, i, s) => {
2546
+ for (var a = s > 1 ? void 0 : s ? It(t, i) : t, h = e.length - 1, p; h >= 0; h--)
2547
+ (p = e[h]) && (a = (s ? p(t, i, a) : p(a)) || a);
2548
+ return s && a && Mt(t, i, a), a;
2423
2549
  };
2424
- let $ = class extends x {
2550
+ let $ = class extends A {
2425
2551
  constructor() {
2426
- 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) => {
2427
- e.preventDefault(), this.run(async () => {
2552
+ 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.focusOnStep = !1, this.resendCooldownUntil = 0, this.challenge = null, this.recovery = null, this.email = "", this.password = "", this.passwordConfirm = "", this.name = "", this.phone = "", this.code = "", this.onSignIn = (e) => {
2553
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2428
2554
  await n.signInWithEmailPassword(this.email, this.password), this.password = "", this.fire("authui-success", { method: "email-password" });
2429
2555
  });
2430
2556
  }, this.onSignUp = (e) => {
2431
- e.preventDefault(), this.run(async () => {
2557
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2432
2558
  await n.signUp(this.email, this.password, this.name), this.password = "", this.fire("authui-success", { method: "sign-up" });
2433
2559
  });
2434
2560
  }, this.onGuest = () => {
@@ -2444,20 +2570,21 @@ let $ = class extends x {
2444
2570
  await new Promise((t) => setTimeout(t, 4e3));
2445
2571
  });
2446
2572
  }, this.onForgot = (e) => {
2447
- e.preventDefault(), this.run(async () => {
2573
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2448
2574
  await n.sendPasswordRecovery(this.email), this.notice = { tone: "success", message: this.t("resetLinkSent", { email: this.email }) };
2449
2575
  });
2450
2576
  }, this.onReset = (e) => {
2451
- if (e.preventDefault(), this.password !== this.passwordConfirm) {
2577
+ if (e.preventDefault(), !this.requireValid(e)) return;
2578
+ if (this.password !== this.passwordConfirm) {
2452
2579
  this.error = this.t("errorPasswordMismatch");
2453
2580
  return;
2454
2581
  }
2455
2582
  const t = this.recovery;
2456
2583
  t && this.run(async () => {
2457
- await n.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");
2584
+ await n.completePasswordRecovery(t.userId, t.secret, this.password), this.password = "", this.passwordConfirm = "", this.recovery = null, this.auth.pending?.type === "reset-password" && n.setPending(null), this.notice = { tone: "success", message: this.t("passwordUpdated") }, this.go("sign-in");
2458
2585
  });
2459
2586
  }, this.onMagicUrl = (e) => {
2460
- e.preventDefault(), this.run(async () => {
2587
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2461
2588
  const t = await n.sendMagicUrl(this.email);
2462
2589
  this.token = {
2463
2590
  userId: t.userId,
@@ -2467,7 +2594,7 @@ let $ = class extends x {
2467
2594
  };
2468
2595
  });
2469
2596
  }, this.onEmailOtp = (e) => {
2470
- e.preventDefault(), this.run(async () => {
2597
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2471
2598
  const t = await n.sendEmailOtp(this.email);
2472
2599
  this.token = {
2473
2600
  userId: t.userId,
@@ -2477,15 +2604,15 @@ let $ = class extends x {
2477
2604
  }, this.code = "";
2478
2605
  });
2479
2606
  }, this.onPhoneOtp = (e) => {
2480
- e.preventDefault(), this.run(async () => {
2607
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2481
2608
  const t = await n.sendPhoneOtp(this.phone);
2482
2609
  this.token = { userId: t.userId, kind: "phone", target: this.phone }, this.code = "";
2483
2610
  });
2484
2611
  }, this.onVerifyCode = (e) => {
2485
- e.preventDefault();
2612
+ if (e.preventDefault(), !this.requireValid(e)) return;
2486
2613
  const t = this.token;
2487
2614
  t && this.run(async () => {
2488
- await n.signInWithToken(t.userId, this.code), this.code = "", this.fire("authui-success", { method: t.kind });
2615
+ await n.signInWithToken(t.userId, this.code), this.code = "", this.token = null, this.fire("authui-success", { method: t.kind });
2489
2616
  }, "code");
2490
2617
  }, this.onChooseFactor = (e) => {
2491
2618
  this.run(async () => {
@@ -2493,17 +2620,17 @@ let $ = class extends x {
2493
2620
  this.challenge = { id: t.$id, factor: e }, this.code = "";
2494
2621
  });
2495
2622
  }, this.onVerifyFactor = (e) => {
2496
- e.preventDefault();
2623
+ if (e.preventDefault(), !this.requireValid(e)) return;
2497
2624
  const t = this.challenge;
2498
2625
  t && this.run(async () => {
2499
- await n.completeMfaChallenge(t.id, this.code), this.code = "", this.challenge = null, this.fire("authui-success", { method: "mfa" });
2626
+ await n.completeMfaChallenge(t.id, this.code), this.code = "", this.challenge = null, this.go("sign-in"), this.fire("authui-success", { method: "mfa" });
2500
2627
  }, "code");
2501
2628
  }, this.onCancelMfa = () => {
2502
2629
  this.run(async () => {
2503
2630
  try {
2504
2631
  await n.signOut();
2505
2632
  } catch (e) {
2506
- if (!N(e, v.sessionNotFound)) throw e;
2633
+ if (!z(e, v.sessionNotFound)) throw e;
2507
2634
  }
2508
2635
  this.go("sign-in");
2509
2636
  });
@@ -2518,19 +2645,24 @@ let $ = class extends x {
2518
2645
  e.has("view") && e.get("view") !== void 0 && this.go(this.view), e.has("auth") && this.syncFromStore();
2519
2646
  }
2520
2647
  updated(e) {
2521
- e.has("step") && requestAnimationFrame(() => this.firstInput?.focus());
2648
+ e.has("step") && (this.focusOnStep || this.embedded) && (this.focusOnStep = !1, requestAnimationFrame(() => this.firstInput?.focus()));
2522
2649
  }
2523
2650
  /** React to store transitions: MFA pending, redirect results, sign in. */
2524
2651
  syncFromStore() {
2525
2652
  const { status: e, pending: t } = this.auth;
2526
- 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") }, n.setPending(null)), t?.type === "notice" && (this.notice = {
2653
+ e === "mfa-required" && this.step !== "mfa" && this.go("mfa");
2654
+ const i = this.step === "reset-password" || t?.type === "reset-password" || this.recovery !== null;
2655
+ (e === "signed-in" || e === "signed-out") && !i && (this.step === "mfa" || this.step === "phone" || this.step === "email-otp" || this.step === "magic-url" || this.step === "forgot-password" || this.token !== null || this.challenge !== null || e === "signed-out") && (this.token = null, this.challenge = null, this.code = "", this.password = "", this.notice = null, this.go(this.view === "sign-up" ? "sign-up" : "sign-in")), 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") }, n.setPending(null)), t?.type === "notice" && !this.notice && (this.notice = {
2527
2656
  tone: t.tone === "error" ? "error" : t.tone,
2528
2657
  message: t.message
2529
- }, n.setPending(null));
2658
+ });
2530
2659
  }
2531
2660
  /** Navigate between screens and reset transient state. */
2661
+ dismissNotice() {
2662
+ this.notice = null, this.auth.pending?.type === "notice" && n.setPending(null);
2663
+ }
2532
2664
  go(e) {
2533
- 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 });
2665
+ e === "sign-up" && this.config?.signUp === !1 && (e = "sign-in"), this.focusOnStep = !0, this.step = e, this.error = "", this.notice = null, this.auth.pending?.type === "notice" && n.setPending(null), this.busy = !1, this.showPassword = !1, this.password = "", this.passwordConfirm = "", e !== "mfa" && (this.challenge = null), e !== "email-otp" && e !== "phone" && e !== "magic-url" && (this.token = null), this.fire("authui-view", { view: e });
2534
2666
  }
2535
2667
  // ───────────────────────────── actions ─────────────────────────────
2536
2668
  async run(e, t = "link") {
@@ -2539,12 +2671,17 @@ let $ = class extends x {
2539
2671
  try {
2540
2672
  await e();
2541
2673
  } catch (i) {
2542
- this.error = at(i, this.strings, t);
2674
+ this.error = Z(i, this.strings, t);
2543
2675
  } finally {
2544
2676
  this.busy = !1;
2545
2677
  }
2546
2678
  }
2547
2679
  }
2680
+ /** Honour native constraint validation before calling Appwrite. */
2681
+ requireValid(e) {
2682
+ const t = e.target;
2683
+ return !(t && typeof t.reportValidity == "function" && !t.reportValidity());
2684
+ }
2548
2685
  bind(e) {
2549
2686
  return (t) => {
2550
2687
  this[e] = t.target.value;
@@ -2553,81 +2690,91 @@ let $ = class extends x {
2553
2690
  // ───────────────────────────── render ─────────────────────────────
2554
2691
  render() {
2555
2692
  const e = this.renderStep();
2556
- return s`
2693
+ return r`
2557
2694
  <div class="panel ${this.embedded ? "embedded" : ""}" part="panel">
2558
2695
  ${this.renderHeader()}
2559
- ${this.notice ? s`<div class="alert alert-${this.notice.tone}" role="status">
2560
- ${this.notice.tone === "success" ? c.checkCircle : this.notice.tone === "error" ? c.alert : c.info}
2696
+ ${this.notice ? r`<div class="alert alert-${this.notice.tone}" role="status">
2697
+ ${this.notice.tone === "success" ? o.checkCircle : this.notice.tone === "error" ? o.alert : o.info}
2561
2698
  <div class="alert-body">${this.notice.message}</div>
2562
2699
  <button
2563
2700
  class="btn btn-ghost btn-icon dismiss"
2564
- @click=${() => this.notice = null}
2701
+ @click=${() => this.dismissNotice()}
2565
2702
  aria-label=${this.t("close")}
2566
2703
  >
2567
- ${c.x}
2704
+ ${o.x}
2568
2705
  </button>
2569
- </div>` : o}
2706
+ </div>` : c}
2570
2707
  ${e}
2571
2708
  </div>
2572
2709
  `;
2573
2710
  }
2574
2711
  renderHeader() {
2575
2712
  const e = this.config?.branding?.logo, t = this.productName;
2576
- let i = "", r = "";
2577
- switch (this.step) {
2578
- case "sign-in":
2579
- i = this.auth.status === "signed-in" ? this.t("signedInAs") : t ? this.t("signInTitle", { name: t }) : this.t("welcomeBack");
2580
- break;
2581
- case "sign-up":
2582
- i = t ? this.t("signUpTitle", { name: t }) : this.t("createAccount");
2583
- break;
2584
- case "forgot-password":
2585
- case "reset-password":
2586
- i = this.t("resetPassword");
2587
- break;
2588
- case "magic-url":
2589
- case "email-otp":
2590
- i = this.t("continueWithEmail");
2591
- break;
2592
- case "phone":
2593
- i = this.t("continueWithPhone");
2594
- break;
2595
- case "mfa":
2596
- i = this.t("mfaTitle"), r = this.t("mfaDescription");
2597
- break;
2598
- }
2599
- return s`
2600
- <header class="header">
2601
- ${e ? s`<img class="logo" src=${e} alt=${t || "Logo"} />` : o}
2602
- ${n.isPreview ? s`<span class="badge badge-info preview">${this.t("preview")}</span>` : o}
2713
+ let i = "", s = "";
2714
+ if (this.auth.status === "signed-in")
2715
+ i = this.t("signedInAs");
2716
+ else
2717
+ switch (this.step) {
2718
+ case "sign-in":
2719
+ i = t ? this.t("signInTitle", { name: t }) : this.t("welcomeBack");
2720
+ break;
2721
+ case "sign-up":
2722
+ i = t ? this.t("signUpTitle", { name: t }) : this.t("createAccount");
2723
+ break;
2724
+ case "forgot-password":
2725
+ case "reset-password":
2726
+ i = this.t("resetPassword");
2727
+ break;
2728
+ case "magic-url":
2729
+ case "email-otp":
2730
+ i = this.t("continueWithEmail");
2731
+ break;
2732
+ case "phone":
2733
+ i = this.t("continueWithPhone");
2734
+ break;
2735
+ case "mfa":
2736
+ i = this.t("mfaTitle"), s = this.t("mfaDescription");
2737
+ break;
2738
+ }
2739
+ return r`
2740
+ <div class="header">
2741
+ ${e ? r`<img
2742
+ class="logo"
2743
+ src=${e}
2744
+ alt=""
2745
+ @error=${(a) => {
2746
+ a.target.hidden = !0;
2747
+ }}
2748
+ />` : c}
2749
+ ${n.isPreview ? r`<span class="badge badge-info preview">${this.t("preview")}</span>` : c}
2603
2750
  <h2 class="title" id="authui-title">${i}</h2>
2604
- ${r ? s`<p class="description">${r}</p>` : o}
2605
- </header>
2751
+ ${s ? r`<p class="description">${s}</p>` : c}
2752
+ </div>
2606
2753
  `;
2607
2754
  }
2608
2755
  renderError() {
2609
- return this.error ? s`<div class="alert alert-error" role="alert">
2610
- ${c.alert}
2756
+ return this.error ? r`<div class="alert alert-error" role="alert">
2757
+ ${o.alert}
2611
2758
  <div class="alert-body">${this.error}</div>
2612
- </div>` : o;
2759
+ </div>` : c;
2613
2760
  }
2614
2761
  submitButton(e, t = "btn-primary") {
2615
- return s`<button class="btn ${t} btn-block" type="submit" ?disabled=${this.busy}>
2616
- ${this.busy ? s`<span class="spinner" aria-hidden="true"></span>` : o} ${e}
2762
+ return r`<button class="btn ${t} btn-block" type="submit" ?disabled=${this.busy}>
2763
+ ${this.busy ? r`<span class="spinner" aria-hidden="true"></span>` : c} ${e}
2617
2764
  </button>`;
2618
2765
  }
2619
2766
  passwordField(e) {
2620
- return s`
2767
+ return r`
2621
2768
  <div class="field">
2622
2769
  <label class="label" for=${e.id}>
2623
2770
  ${e.label}
2624
- ${e.forgot ? s`<button
2771
+ ${e.forgot ? r`<button
2625
2772
  type="button"
2626
2773
  class="btn btn-link small"
2627
2774
  @click=${() => this.go("forgot-password")}
2628
2775
  >
2629
2776
  ${this.t("forgotPassword")}
2630
- </button>` : o}
2777
+ </button>` : c}
2631
2778
  </label>
2632
2779
  <div class="input-wrap">
2633
2780
  <input
@@ -2644,18 +2791,18 @@ let $ = class extends x {
2644
2791
  type="button"
2645
2792
  class="btn btn-ghost btn-icon"
2646
2793
  @click=${() => this.showPassword = !this.showPassword}
2647
- aria-label=${this.showPassword ? "Hide password" : "Show password"}
2794
+ aria-label=${this.showPassword ? this.t("hidePassword") : this.t("showPassword")}
2648
2795
  tabindex="-1"
2649
2796
  >
2650
- ${this.showPassword ? c.eyeOff : c.eye}
2797
+ ${this.showPassword ? o.eyeOff : o.eye}
2651
2798
  </button>
2652
2799
  </div>
2653
- ${e.hint ? s`<p class="hint">${e.hint}</p>` : o}
2800
+ ${e.hint ? r`<p class="hint">${e.hint}</p>` : c}
2654
2801
  </div>
2655
2802
  `;
2656
2803
  }
2657
2804
  emailField(e = "email") {
2658
- return s`
2805
+ return r`
2659
2806
  <div class="field">
2660
2807
  <label class="label" for="authui-email">${this.t("email")}</label>
2661
2808
  <input
@@ -2672,7 +2819,7 @@ let $ = class extends x {
2672
2819
  `;
2673
2820
  }
2674
2821
  codeField() {
2675
- return s`
2822
+ return r`
2676
2823
  <div class="field">
2677
2824
  <label class="label" for="authui-code">${this.t("code")}</label>
2678
2825
  <input
@@ -2681,6 +2828,8 @@ let $ = class extends x {
2681
2828
  type="text"
2682
2829
  inputmode="numeric"
2683
2830
  autocomplete="one-time-code"
2831
+ maxlength="6"
2832
+ pattern="[0-9]*"
2684
2833
  required
2685
2834
  .value=${this.code}
2686
2835
  @input=${this.bind("code")}
@@ -2690,32 +2839,32 @@ let $ = class extends x {
2690
2839
  }
2691
2840
  legal() {
2692
2841
  const e = this.config?.legal;
2693
- return !e?.termsUrl && !e?.privacyUrl ? o : s`<p class="legal">
2842
+ return !e?.termsUrl && !e?.privacyUrl ? c : r`<p class="legal">
2694
2843
  ${this.t("agreeTo")}
2695
- ${e.termsUrl ? s`<a href=${e.termsUrl} target="_blank" rel="noopener">${this.t("terms")}</a>` : o}
2696
- ${e.termsUrl && e.privacyUrl ? s` ${this.t("and")} ` : o}
2697
- ${e.privacyUrl ? s`<a href=${e.privacyUrl} target="_blank" rel="noopener">${this.t("privacy")}</a>` : o}.
2844
+ ${e.termsUrl ? r`<a href=${e.termsUrl} target="_blank" rel="noopener">${this.t("terms")}</a>` : c}
2845
+ ${e.termsUrl && e.privacyUrl ? r` ${this.t("and")} ` : c}
2846
+ ${e.privacyUrl ? r`<a href=${e.privacyUrl} target="_blank" rel="noopener">${this.t("privacy")}</a>` : c}.
2698
2847
  </p>`;
2699
2848
  }
2700
2849
  backLink(e = "sign-in") {
2701
- return s`<div class="links">
2850
+ return r`<div class="links">
2702
2851
  <button type="button" class="btn btn-link" @click=${() => this.go(e)}>
2703
- ${c.arrowLeft} ${this.t("back")}
2852
+ ${o.arrowLeft} ${this.t("back")}
2704
2853
  </button>
2705
2854
  </div>`;
2706
2855
  }
2707
2856
  renderStep() {
2708
2857
  if (!this.auth.configured)
2709
- return s`<div class="alert alert-error" role="alert">
2710
- ${c.alert}
2858
+ return r`<div class="alert alert-error" role="alert">
2859
+ ${o.alert}
2711
2860
  <div class="alert-body">${this.t("errorNotConfigured")}</div>
2712
2861
  </div>`;
2713
2862
  if (this.auth.status === "loading")
2714
- return s`<div class="empty"><span class="spinner"></span></div>`;
2863
+ return r`<div class="empty"><span class="spinner"></span></div>`;
2715
2864
  if (this.auth.status === "signed-in" && this.step !== "mfa") return this.renderSignedIn();
2716
2865
  switch (this.step) {
2717
2866
  case "sign-up":
2718
- return this.renderSignUp();
2867
+ return this.config?.signUp === !1 ? this.renderSignIn() : this.renderSignUp();
2719
2868
  case "forgot-password":
2720
2869
  return this.renderForgot();
2721
2870
  case "reset-password":
@@ -2734,30 +2883,32 @@ let $ = class extends x {
2734
2883
  }
2735
2884
  renderSignedIn() {
2736
2885
  const e = this.auth.user, t = e.name || e.email || e.phone || this.t("guestAccount");
2737
- return s`
2886
+ return r`
2738
2887
  <div class="stack">
2739
2888
  <div class="row">
2740
2889
  <div class="inline">
2741
- <span class="avatar">${t[0] ?? "?"}</span>
2890
+ <span class="avatar">${Q(t)}</span>
2742
2891
  <div class="row-main">
2743
- <span class="row-title">${t}</span>
2744
- ${e.email && e.name ? s`<span class="row-sub">${e.email}</span>` : o}
2892
+ <span class="row-title" title=${t}>${t}</span>
2893
+ ${e.email && e.name ? r`<span class="row-sub" title=${e.email}>${e.email}</span>` : c}
2745
2894
  </div>
2746
2895
  </div>
2747
2896
  </div>
2748
2897
  ${this.renderError()}
2749
2898
  <div class="stack-sm">
2750
- ${this.config?.successUrl ? s`<a class="btn btn-primary btn-block" href=${this.config.successUrl}
2899
+ ${this.config?.successUrl ? r`<a class="btn btn-primary btn-block" href=${this.config.successUrl}
2751
2900
  >${this.t("continue")}</a
2752
- >` : o}
2901
+ >` : c}
2753
2902
  <button
2754
2903
  class="btn btn-outline btn-block"
2755
- @click=${() => this.fire("authui-open", { view: "account" })}
2904
+ @click=${() => {
2905
+ this.embedded ? this.fire("authui-open", { view: "account" }) : H("account");
2906
+ }}
2756
2907
  >
2757
- ${c.settings} ${this.t("manageAccount")}
2908
+ ${o.settings} ${this.t("manageAccount")}
2758
2909
  </button>
2759
2910
  <button class="btn btn-ghost btn-block" @click=${this.onSignOut} ?disabled=${this.busy}>
2760
- ${c.logOut} ${this.t("signOut")}
2911
+ ${o.logOut} ${this.t("signOut")}
2761
2912
  </button>
2762
2913
  </div>
2763
2914
  </div>
@@ -2765,21 +2916,21 @@ let $ = class extends x {
2765
2916
  }
2766
2917
  renderProviders() {
2767
2918
  const e = this.config?.methods?.oauth ?? [];
2768
- if (e.length === 0) return o;
2919
+ if (e.length === 0) return c;
2769
2920
  const t = e.length > 2;
2770
- return s`
2921
+ return r`
2771
2922
  <div class="providers ${t ? "two" : ""}">
2772
2923
  ${e.map(
2773
- (i) => s`<button
2924
+ (i) => r`<button
2774
2925
  type="button"
2775
2926
  class="btn btn-outline"
2776
2927
  @click=${() => this.onOAuth(i)}
2777
2928
  ?disabled=${this.busy}
2778
- aria-label=${this.t("continueWith", { provider: O(i) })}
2929
+ aria-label=${this.t("continueWith", { provider: R(i) })}
2779
2930
  >
2780
- ${G(i)}
2931
+ ${Y(i)}
2781
2932
  <span
2782
- >${t ? O(i) : this.t("continueWith", { provider: O(i) })}</span
2933
+ >${t ? R(i) : this.t("continueWith", { provider: R(i) })}</span
2783
2934
  >
2784
2935
  </button>`
2785
2936
  )}
@@ -2787,23 +2938,23 @@ let $ = class extends x {
2787
2938
  `;
2788
2939
  }
2789
2940
  renderSignIn() {
2790
- const e = this.config?.methods ?? {}, t = e.emailPassword !== !1, i = (e.oauth?.length ?? 0) > 0, r = [
2791
- e.magicUrl ? { step: "magic-url", icon: c.link, label: this.t("sendMagicLink") } : null,
2792
- e.emailOtp ? { step: "email-otp", icon: c.mail, label: this.t("continueWithEmail") } : null,
2793
- e.phone ? { step: "phone", icon: c.smartphone, label: this.t("continueWithPhone") } : null
2941
+ const e = this.config?.methods ?? {}, t = e.emailPassword !== !1, i = (e.oauth?.length ?? 0) > 0, s = [
2942
+ e.magicUrl ? { step: "magic-url", icon: o.link, label: this.t("sendMagicLink") } : null,
2943
+ e.emailOtp ? { step: "email-otp", icon: o.mail, label: this.t("continueWithEmail") } : null,
2944
+ e.phone ? { step: "phone", icon: o.smartphone, label: this.t("continueWithPhone") } : null
2794
2945
  ].filter(Boolean);
2795
- return s`
2946
+ return r`
2796
2947
  <div class="stack">
2797
2948
  ${this.renderProviders()}
2798
- ${i && (t || r.length > 0) ? s`<div class="separator-text">${this.t("or")}</div>` : o}
2799
- ${t ? s`<form class="form" @submit=${this.onSignIn} novalidate>
2949
+ ${i && (t || s.length > 0) ? r`<div class="separator-text">${this.t("or")}</div>` : c}
2950
+ ${t ? r`<form class="form" @submit=${this.onSignIn} novalidate>
2800
2951
  ${this.emailField()}
2801
2952
  ${this.passwordField({ label: this.t("password"), autocomplete: "current-password", id: "authui-password", field: "password", forgot: !0 })}
2802
2953
  ${this.renderError()} ${this.submitButton(this.t("signIn"))}
2803
2954
  </form>` : this.renderError()}
2804
- ${r.length > 0 ? s`<div class="stack-sm">
2805
- ${r.map(
2806
- (a) => s`<button
2955
+ ${s.length > 0 ? r`<div class="stack-sm">
2956
+ ${s.map(
2957
+ (a) => r`<button
2807
2958
  type="button"
2808
2959
  class="btn btn-secondary btn-block"
2809
2960
  @click=${() => this.go(a.step)}
@@ -2811,32 +2962,32 @@ let $ = class extends x {
2811
2962
  ${a.icon} ${a.label}
2812
2963
  </button>`
2813
2964
  )}
2814
- </div>` : o}
2815
- ${e.anonymous ? s`<button
2965
+ </div>` : c}
2966
+ ${e.anonymous ? r`<button
2816
2967
  type="button"
2817
2968
  class="btn btn-ghost btn-block"
2818
2969
  @click=${this.onGuest}
2819
2970
  ?disabled=${this.busy}
2820
2971
  >
2821
- ${c.ghost} ${this.t("continueAsGuest")}
2822
- </button>` : o}
2823
- ${t && this.config?.signUp !== !1 ? s`<div class="links">
2972
+ ${o.ghost} ${this.t("continueAsGuest")}
2973
+ </button>` : c}
2974
+ ${t && this.config?.signUp !== !1 ? r`<div class="links">
2824
2975
  <span>${this.t("noAccount")}</span>
2825
2976
  <button type="button" class="btn btn-link" @click=${() => this.go("sign-up")}>
2826
2977
  ${this.t("signUp")}
2827
2978
  </button>
2828
- </div>` : o}
2979
+ </div>` : c}
2829
2980
  ${this.legal()}
2830
2981
  </div>
2831
2982
  `;
2832
2983
  }
2833
2984
  renderSignUp() {
2834
- return s`
2985
+ return r`
2835
2986
  <div class="stack">
2836
2987
  ${this.renderProviders()}
2837
- ${(this.config?.methods?.oauth?.length ?? 0) > 0 ? s`<div class="separator-text">${this.t("or")}</div>` : o}
2988
+ ${(this.config?.methods?.oauth?.length ?? 0) > 0 ? r`<div class="separator-text">${this.t("or")}</div>` : c}
2838
2989
  <form class="form" @submit=${this.onSignUp} novalidate>
2839
- ${this.config?.requireName !== !1 ? s`<div class="field">
2990
+ ${this.config?.requireName !== !1 ? r`<div class="field">
2840
2991
  <label class="label" for="authui-name">${this.t("name")}</label>
2841
2992
  <input
2842
2993
  class="input"
@@ -2847,7 +2998,7 @@ let $ = class extends x {
2847
2998
  .value=${this.name}
2848
2999
  @input=${this.bind("name")}
2849
3000
  />
2850
- </div>` : o}
3001
+ </div>` : c}
2851
3002
  ${this.emailField()}
2852
3003
  ${this.passwordField({ label: this.t("password"), autocomplete: "new-password", id: "authui-password", field: "password", hint: this.t("passwordHint") })}
2853
3004
  ${this.renderError()} ${this.submitButton(this.t("createAccount"))}
@@ -2863,7 +3014,7 @@ let $ = class extends x {
2863
3014
  `;
2864
3015
  }
2865
3016
  renderForgot() {
2866
- return s`
3017
+ return r`
2867
3018
  <div class="stack">
2868
3019
  <form class="form" @submit=${this.onForgot} novalidate>
2869
3020
  ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendResetLink"))}
@@ -2873,52 +3024,91 @@ let $ = class extends x {
2873
3024
  `;
2874
3025
  }
2875
3026
  renderReset() {
2876
- return this.recovery ? s`
3027
+ return this.recovery ? r`
2877
3028
  <div class="stack">
2878
3029
  <form class="form" @submit=${this.onReset} novalidate>
2879
3030
  ${this.passwordField({ label: this.t("newPassword"), autocomplete: "new-password", id: "authui-password", field: "password", hint: this.t("passwordHint") })}
2880
3031
  ${this.passwordField({ label: this.t("confirmPassword"), autocomplete: "new-password", id: "authui-password-confirm", field: "passwordConfirm" })}
2881
3032
  ${this.renderError()} ${this.submitButton(this.t("resetPassword"))}
2882
3033
  </form>
2883
- ${this.backLink()}
3034
+ <div class="links">
3035
+ <button
3036
+ type="button"
3037
+ class="btn btn-link"
3038
+ @click=${() => {
3039
+ this.step = "sign-in", this.error = "", this.notice = null, this.focusOnStep = !0, this.fire("authui-view", { view: "sign-in" });
3040
+ }}
3041
+ >
3042
+ ${o.arrowLeft} ${this.t("back")}
3043
+ </button>
3044
+ </div>
2884
3045
  </div>
2885
- ` : s`<div class="stack">
3046
+ ` : r`<div class="stack">
2886
3047
  <div class="alert alert-error" role="alert">
2887
- ${c.alert}
3048
+ ${o.alert}
2888
3049
  <div class="alert-body">${this.t("errorInvalidToken")}</div>
2889
3050
  </div>
2890
- ${this.backLink()}
3051
+ <div class="links">
3052
+ <button
3053
+ type="button"
3054
+ class="btn btn-link"
3055
+ @click=${() => {
3056
+ this.go("forgot-password");
3057
+ }}
3058
+ >
3059
+ ${this.t("requestNewLink")}
3060
+ </button>
3061
+ </div>
2891
3062
  </div>`;
2892
3063
  }
2893
3064
  phraseBox(e) {
2894
- return e ? s`<div class="alert alert-info">
2895
- ${c.shield}
3065
+ return e ? r`<div class="alert alert-info">
3066
+ ${o.shield}
2896
3067
  <div class="alert-title">
2897
3068
  ${this.t("securityPhrase")}: <span class="code">${e}</span>
2898
3069
  </div>
2899
3070
  <div class="alert-body">${this.t("securityPhraseHint")}</div>
2900
- </div>` : o;
3071
+ </div>` : c;
2901
3072
  }
2902
3073
  renderMagicUrl() {
2903
- return this.token ? s`<div class="stack">
3074
+ return this.token ? r`<div class="stack">
2904
3075
  <div class="alert alert-success" role="status">
2905
- ${c.mail}
3076
+ ${o.mail}
2906
3077
  <div class="alert-body">${this.t("magicLinkSent", { email: this.token.target })}</div>
2907
3078
  </div>
2908
3079
  ${this.phraseBox(this.token.phrase)} ${this.backLink()}
2909
- </div>` : s`
3080
+ </div>` : r`
2910
3081
  <div class="stack">
2911
3082
  <form class="form" @submit=${this.onMagicUrl} novalidate>
2912
3083
  ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendMagicLink"))}
2913
3084
  </form>
2914
- ${this.backLink()}
3085
+ ${this.backLink()} ${this.legal()}
2915
3086
  </div>
2916
3087
  `;
2917
3088
  }
3089
+ async onResendCode() {
3090
+ const e = this.token;
3091
+ !e || Date.now() < this.resendCooldownUntil || (this.error = "", await this.run(async () => {
3092
+ if (e.kind === "phone") {
3093
+ const t = await n.sendPhoneOtp(e.target);
3094
+ this.token = { userId: t.userId, kind: "phone", target: e.target };
3095
+ } else {
3096
+ const t = await n.sendEmailOtp(e.target);
3097
+ this.token = {
3098
+ userId: t.userId,
3099
+ kind: "email-otp",
3100
+ target: e.target,
3101
+ phrase: t.phrase
3102
+ };
3103
+ }
3104
+ this.resendCooldownUntil = Date.now() + 3e4, window.setTimeout(() => this.requestUpdate(), 3e4);
3105
+ }));
3106
+ }
2918
3107
  renderCodeEntry() {
2919
- return s`
3108
+ const e = this.token?.kind === "phone", t = Date.now() < this.resendCooldownUntil;
3109
+ return r`
2920
3110
  <div class="alert alert-info" role="status">
2921
- ${c.mail}
3111
+ ${e ? o.smartphone : o.mail}
2922
3112
  <div class="alert-body">${this.t("codeSent", { target: this.token.target })}</div>
2923
3113
  </div>
2924
3114
  ${this.phraseBox(this.token.phrase)}
@@ -2926,28 +3116,41 @@ let $ = class extends x {
2926
3116
  ${this.codeField()} ${this.renderError()} ${this.submitButton(this.t("verifyCode"))}
2927
3117
  </form>
2928
3118
  <div class="links">
2929
- <button type="button" class="btn btn-link" @click=${() => this.token = null}>
2930
- ${this.t("sendCode")}
3119
+ <button
3120
+ type="button"
3121
+ class="btn btn-link"
3122
+ ?disabled=${t || this.busy}
3123
+ @click=${() => {
3124
+ this.onResendCode();
3125
+ }}
3126
+ >
3127
+ ${this.t("resendCode")}
2931
3128
  </button>
2932
3129
  <span aria-hidden="true">·</span>
2933
- <button type="button" class="btn btn-link" @click=${() => this.go("sign-in")}>
2934
- ${this.t("back")}
3130
+ <button
3131
+ type="button"
3132
+ class="btn btn-link"
3133
+ @click=${() => {
3134
+ this.token = null, this.error = "";
3135
+ }}
3136
+ >
3137
+ ${e ? this.t("useDifferentPhone") : this.t("useDifferentEmail")}
2935
3138
  </button>
2936
3139
  </div>
2937
3140
  `;
2938
3141
  }
2939
3142
  renderEmailOtp() {
2940
- return this.token ? s`<div class="stack">${this.renderCodeEntry()}</div>` : s`
3143
+ return this.token ? r`<div class="stack">${this.renderCodeEntry()}</div>` : r`
2941
3144
  <div class="stack">
2942
3145
  <form class="form" @submit=${this.onEmailOtp} novalidate>
2943
3146
  ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendCode"))}
2944
3147
  </form>
2945
- ${this.backLink()}
3148
+ ${this.backLink()} ${this.legal()}
2946
3149
  </div>
2947
3150
  `;
2948
3151
  }
2949
3152
  renderPhone() {
2950
- return this.token ? s`<div class="stack">${this.renderCodeEntry()}</div>` : s`
3153
+ return this.token ? r`<div class="stack">${this.renderCodeEntry()}</div>` : r`
2951
3154
  <div class="stack">
2952
3155
  <form class="form" @submit=${this.onPhoneOtp} novalidate>
2953
3156
  <div class="field">
@@ -2965,7 +3168,7 @@ let $ = class extends x {
2965
3168
  </div>
2966
3169
  ${this.renderError()} ${this.submitButton(this.t("sendCode"))}
2967
3170
  </form>
2968
- ${this.backLink()}
3171
+ ${this.backLink()} ${this.legal()}
2969
3172
  </div>
2970
3173
  `;
2971
3174
  }
@@ -2975,40 +3178,40 @@ let $ = class extends x {
2975
3178
  const i = [
2976
3179
  {
2977
3180
  factor: "totp",
2978
- icon: c.smartphone,
3181
+ icon: o.smartphone,
2979
3182
  label: this.t("mfaUseAuthenticator"),
2980
3183
  available: e?.totp ?? !0
2981
3184
  },
2982
3185
  {
2983
3186
  factor: "email",
2984
- icon: c.mail,
3187
+ icon: o.mail,
2985
3188
  label: this.t("mfaUseEmail"),
2986
3189
  available: e?.email ?? !0
2987
3190
  },
2988
3191
  {
2989
3192
  factor: "phone",
2990
- icon: c.phone,
3193
+ icon: o.phone,
2991
3194
  label: this.t("mfaUsePhone"),
2992
3195
  available: e?.phone ?? !0
2993
3196
  },
2994
3197
  {
2995
3198
  factor: "recoverycode",
2996
- icon: c.key,
3199
+ icon: o.key,
2997
3200
  label: this.t("mfaUseRecoveryCode"),
2998
3201
  available: e?.recoveryCode ?? !0
2999
3202
  }
3000
3203
  ];
3001
- return s`
3204
+ return r`
3002
3205
  <div class="stack">
3003
3206
  <div class="stack-sm">
3004
- ${i.filter((r) => r.available).map(
3005
- (r) => s`<button
3207
+ ${i.filter((s) => s.available).map(
3208
+ (s) => r`<button
3006
3209
  type="button"
3007
3210
  class="choice"
3008
- @click=${() => this.onChooseFactor(r.factor)}
3211
+ @click=${() => this.onChooseFactor(s.factor)}
3009
3212
  ?disabled=${this.busy}
3010
3213
  >
3011
- ${r.icon}<span class="choice-title">${r.label}</span>
3214
+ ${s.icon}<span class="choice-title">${s.label}</span>
3012
3215
  </button>`
3013
3216
  )}
3014
3217
  </div>
@@ -3022,10 +3225,10 @@ let $ = class extends x {
3022
3225
  `;
3023
3226
  }
3024
3227
  const t = this.challenge.factor === "recoverycode";
3025
- return s`
3228
+ return r`
3026
3229
  <div class="stack">
3027
3230
  <form class="form" @submit=${this.onVerifyFactor} novalidate>
3028
- ${t ? s`<div class="field">
3231
+ ${t ? r`<div class="field">
3029
3232
  <label class="label" for="authui-code">${this.t("recoveryCode")}</label>
3030
3233
  <input
3031
3234
  class="input mono"
@@ -3041,7 +3244,7 @@ let $ = class extends x {
3041
3244
  </form>
3042
3245
  <div class="links">
3043
3246
  <button type="button" class="btn btn-link" @click=${() => this.challenge = null}>
3044
- ${c.arrowLeft} ${this.t("back")}
3247
+ ${o.arrowLeft} ${this.t("back")}
3045
3248
  </button>
3046
3249
  <span aria-hidden="true">·</span>
3047
3250
  <button type="button" class="btn btn-link" @click=${this.onCancelMfa}>
@@ -3052,102 +3255,127 @@ let $ = class extends x {
3052
3255
  `;
3053
3256
  }
3054
3257
  };
3055
- $.styles = [...x.styles, St];
3056
- P([
3057
- f({ type: String })
3258
+ $.styles = [...A.styles, Ut];
3259
+ k([
3260
+ m({ type: String })
3058
3261
  ], $.prototype, "view", 2);
3059
- P([
3060
- f({ type: Boolean })
3262
+ k([
3263
+ m({ type: Boolean })
3061
3264
  ], $.prototype, "embedded", 2);
3062
- P([
3265
+ k([
3063
3266
  d()
3064
3267
  ], $.prototype, "step", 2);
3065
- P([
3268
+ k([
3066
3269
  d()
3067
3270
  ], $.prototype, "busy", 2);
3068
- P([
3271
+ k([
3069
3272
  d()
3070
3273
  ], $.prototype, "error", 2);
3071
- P([
3274
+ k([
3072
3275
  d()
3073
3276
  ], $.prototype, "notice", 2);
3074
- P([
3277
+ k([
3075
3278
  d()
3076
3279
  ], $.prototype, "showPassword", 2);
3077
- P([
3280
+ k([
3078
3281
  d()
3079
3282
  ], $.prototype, "token", 2);
3080
- P([
3283
+ k([
3284
+ d()
3285
+ ], $.prototype, "resendCooldownUntil", 2);
3286
+ k([
3081
3287
  d()
3082
3288
  ], $.prototype, "challenge", 2);
3083
- P([
3289
+ k([
3084
3290
  d()
3085
3291
  ], $.prototype, "recovery", 2);
3086
- P([
3087
- rt("form input:not([type=hidden])")
3292
+ k([
3293
+ ct("form input:not([type=hidden])")
3088
3294
  ], $.prototype, "firstInput", 2);
3089
- $ = P([
3090
- I("authui-sign-in")
3295
+ $ = k([
3296
+ O("authui-sign-in")
3091
3297
  ], $);
3092
- var Et = Object.defineProperty, It = Object.getOwnPropertyDescriptor, g = (e, t, i, r) => {
3093
- for (var a = r > 1 ? void 0 : r ? It(t, i) : t, h = e.length - 1, u; h >= 0; h--)
3094
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
3095
- return r && a && Et(t, i, a), a;
3298
+ var Ot = Object.defineProperty, Ft = Object.getOwnPropertyDescriptor, f = (e, t, i, s) => {
3299
+ for (var a = s > 1 ? void 0 : s ? Ft(t, i) : t, h = e.length - 1, p; h >= 0; h--)
3300
+ (p = e[h]) && (a = (s ? p(t, i, a) : p(a)) || a);
3301
+ return s && a && Ot(t, i, a), a;
3096
3302
  };
3097
- let p = class extends x {
3303
+ let u = class extends A {
3098
3304
  constructor() {
3099
- 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) => {
3100
- e.preventDefault(), this.run("name", () => n.updateName(this.nameInput), this.t("done"));
3305
+ 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 = null, this.logsProbeStarted = !1, this.confirmDelete = !1, this.confirmRegenerate = !1, this.confirmRemoveAuthenticator = !1, this.confirmSignOutAll = !1, this.confirmDisconnectId = null, this.verifyEmailCooldownUntil = 0, this.onTabsKeydown = (e) => {
3306
+ const t = [...this.renderRoot?.querySelectorAll('[role="tab"]') ?? []];
3307
+ if (!t.length) return;
3308
+ const i = t.findIndex((h) => h.getAttribute("aria-selected") === "true");
3309
+ let s = i;
3310
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") s = (i + 1) % t.length;
3311
+ else if (e.key === "ArrowLeft" || e.key === "ArrowUp")
3312
+ s = (i - 1 + t.length) % t.length;
3313
+ else if (e.key === "Home") s = 0;
3314
+ else if (e.key === "End") s = t.length - 1;
3315
+ else return;
3316
+ e.preventDefault();
3317
+ const a = t[s].id.replace("authui-tab-", "");
3318
+ this.select(a), requestAnimationFrame(() => t[s]?.focus());
3319
+ }, this.noticeTimer = null, this.factorsLoading = !1, this.onUpdateName = (e) => {
3320
+ e.preventDefault(), this.requireValid(e) && this.run("name", () => n.updateName(this.nameInput), this.t("nameUpdated"));
3101
3321
  }, this.onUpdateEmail = (e) => {
3102
- e.preventDefault(), this.run(
3322
+ e.preventDefault(), this.requireValid(e) && this.run(
3103
3323
  "email",
3104
3324
  async () => {
3105
3325
  await n.updateEmail(this.emailInput, this.emailPassword), this.emailPassword = "";
3106
3326
  },
3107
- this.t("done")
3327
+ this.t("emailUpdated")
3108
3328
  );
3109
3329
  }, this.onUpdatePhone = (e) => {
3110
- e.preventDefault(), this.run(
3330
+ e.preventDefault(), this.requireValid(e) && this.run(
3111
3331
  "phone",
3112
3332
  async () => {
3113
3333
  await n.updatePhone(this.phoneInput, this.phonePassword), this.phonePassword = "";
3114
3334
  },
3115
- this.t("done")
3335
+ this.t("phoneUpdated")
3116
3336
  );
3117
3337
  }, this.onConvertGuest = (e) => {
3118
- e.preventDefault(), this.run(
3338
+ e.preventDefault(), this.requireValid(e) && this.run(
3119
3339
  "guest",
3120
3340
  async () => {
3121
3341
  await n.convertGuest(this.emailInput, this.emailPassword, this.guestName), this.emailPassword = "";
3122
3342
  },
3123
- this.t("done")
3343
+ this.t("accountConverted")
3124
3344
  );
3125
3345
  }, this.onSendVerification = () => {
3126
- this.run("verify", () => n.sendEmailVerification(), this.t("verificationSent"));
3346
+ Date.now() < this.verifyEmailCooldownUntil || this.run(
3347
+ "verify",
3348
+ async () => {
3349
+ await n.sendEmailVerification(), this.verifyEmailCooldownUntil = Date.now() + 45e3, window.setTimeout(() => this.requestUpdate(), 45e3);
3350
+ },
3351
+ this.t("verificationSent")
3352
+ );
3127
3353
  }, this.onSendPhoneVerification = () => {
3128
3354
  this.run("verify-phone", async () => {
3129
3355
  await n.sendPhoneVerification(), this.phoneCodeSent = !0;
3130
3356
  });
3131
3357
  }, this.onConfirmPhoneVerification = (e) => {
3132
- e.preventDefault(), this.run(
3358
+ e.preventDefault(), this.requireValid(e) && this.run(
3133
3359
  "verify-phone-code",
3134
3360
  async () => {
3135
3361
  await n.confirmPhoneVerification(this.phoneCode), this.phoneCode = "", this.phoneCodeSent = !1;
3136
3362
  },
3137
- this.t("done")
3363
+ this.t("phoneVerified")
3138
3364
  );
3139
3365
  }, this.onChangePassword = (e) => {
3140
- if (e.preventDefault(), this.newPassword !== this.newPasswordConfirm) {
3141
- this.errors = { ...this.errors, password: this.t("errorPasswordMismatch") };
3142
- return;
3366
+ if (e.preventDefault(), !!this.requireValid(e)) {
3367
+ if (this.newPassword !== this.newPasswordConfirm) {
3368
+ this.errors = { ...this.errors, password: this.t("errorPasswordMismatch") };
3369
+ return;
3370
+ }
3371
+ this.run(
3372
+ "password",
3373
+ async () => {
3374
+ await n.updatePassword(this.newPassword, this.oldPassword), this.oldPassword = this.newPassword = this.newPasswordConfirm = "";
3375
+ },
3376
+ this.t("passwordUpdated")
3377
+ );
3143
3378
  }
3144
- this.run(
3145
- "password",
3146
- async () => {
3147
- await n.updatePassword(this.newPassword, this.oldPassword), this.oldPassword = this.newPassword = this.newPasswordConfirm = "";
3148
- },
3149
- this.t("passwordUpdated")
3150
- );
3151
3379
  }, this.onToggleMfa = () => {
3152
3380
  const e = !this.user?.mfa;
3153
3381
  this.run("mfa", async () => {
@@ -3158,15 +3386,19 @@ let p = class extends x {
3158
3386
  this.authenticator = await n.addAuthenticator(), this.authenticatorCode = "";
3159
3387
  });
3160
3388
  }, this.onVerifyAuthenticator = (e) => {
3161
- e.preventDefault(), this.run(
3389
+ e.preventDefault(), this.requireValid(e) && this.run(
3162
3390
  "authenticator-code",
3163
3391
  async () => {
3164
3392
  await n.verifyAuthenticator(this.authenticatorCode), this.authenticator = null, this.authenticatorCode = "", await this.loadFactors();
3165
3393
  },
3166
- this.t("done")
3394
+ this.t("authenticatorAdded")
3167
3395
  );
3168
3396
  }, this.onRemoveAuthenticator = () => {
3169
- this.run("remove-authenticator", async () => {
3397
+ if (!this.confirmRemoveAuthenticator) {
3398
+ this.confirmRemoveAuthenticator = !0;
3399
+ return;
3400
+ }
3401
+ this.confirmRemoveAuthenticator = !1, this.run("remove-authenticator", async () => {
3170
3402
  await n.removeAuthenticator(), await this.loadFactors();
3171
3403
  });
3172
3404
  }, this.onRecoveryCodes = () => {
@@ -3174,13 +3406,17 @@ let p = class extends x {
3174
3406
  try {
3175
3407
  this.recoveryCodes = await n.createRecoveryCodes();
3176
3408
  } catch (e) {
3177
- if (!N(e, v.recoveryCodesExist)) throw e;
3409
+ if (!z(e, v.recoveryCodesExist)) throw e;
3178
3410
  this.recoveryCodes = await n.getRecoveryCodes();
3179
3411
  }
3180
3412
  await this.loadFactors();
3181
3413
  });
3182
3414
  }, this.onRegenerateRecoveryCodes = () => {
3183
- this.run("recovery", async () => {
3415
+ if (!this.confirmRegenerate) {
3416
+ this.confirmRegenerate = !0;
3417
+ return;
3418
+ }
3419
+ this.confirmRegenerate = !1, this.run("recovery", async () => {
3184
3420
  this.recoveryCodes = await n.regenerateRecoveryCodes();
3185
3421
  });
3186
3422
  }, this.onCopyCodes = async () => {
@@ -3189,6 +3425,15 @@ let p = class extends x {
3189
3425
  await navigator.clipboard.writeText(this.recoveryCodes.join(`
3190
3426
  `)), this.copied = !0, setTimeout(() => this.copied = !1, 1500);
3191
3427
  } catch {
3428
+ this.setNotice("error", this.t("copyFailed"));
3429
+ }
3430
+ }, this.onCopySecret = async () => {
3431
+ const e = this.authenticator?.secret;
3432
+ if (e)
3433
+ try {
3434
+ await navigator.clipboard.writeText(e), this.copied = !0, setTimeout(() => this.copied = !1, 1500);
3435
+ } catch {
3436
+ this.setNotice("error", this.t("copyFailed"));
3192
3437
  }
3193
3438
  }, this.onStepUpFactor = (e) => {
3194
3439
  this.run("stepup", async () => {
@@ -3196,19 +3441,31 @@ let p = class extends x {
3196
3441
  this.stepUp = { ...this.stepUp, challenge: { id: t.$id, factor: e } }, this.stepUpCode = "";
3197
3442
  });
3198
3443
  }, this.onStepUpVerify = (e) => {
3199
- e.preventDefault();
3444
+ if (e.preventDefault(), !this.requireValid(e)) return;
3200
3445
  const t = this.stepUp;
3201
3446
  t?.challenge && this.run("stepup-code", async () => {
3202
3447
  await n.completeMfaChallenge(t.challenge.id, this.stepUpCode, { signIn: !1 }), this.stepUp = null, this.stepUpCode = "", await t.retry();
3203
3448
  });
3204
3449
  }, this.onDeleteSession = (e) => {
3205
3450
  this.run(`session-${e}`, async () => {
3206
- await n.signOut(e), this.sessions = (this.sessions ?? []).filter((t) => t.$id !== e);
3451
+ if ((this.sessions ?? []).some((i) => i.$id === e && i.current)) {
3452
+ await n.signOut(), this.sessions = [];
3453
+ return;
3454
+ }
3455
+ await n.signOut(e), this.sessions = (this.sessions ?? []).filter((i) => i.$id !== e);
3207
3456
  });
3208
3457
  }, this.onSignOutAll = () => {
3209
- this.run("sessions-all", () => n.signOutEverywhere());
3458
+ if (!this.confirmSignOutAll) {
3459
+ this.confirmSignOutAll = !0;
3460
+ return;
3461
+ }
3462
+ this.confirmSignOutAll = !1, this.run("sessions-all", () => n.signOutEverywhere());
3210
3463
  }, this.onDeleteIdentity = (e) => {
3211
- this.run(`identity-${e}`, async () => {
3464
+ if (this.confirmDisconnectId !== e) {
3465
+ this.confirmDisconnectId = e;
3466
+ return;
3467
+ }
3468
+ this.confirmDisconnectId = null, this.run(`identity-${e}`, async () => {
3212
3469
  await n.deleteIdentity(e), this.identities = (this.identities ?? []).filter((t) => t.$id !== e);
3213
3470
  });
3214
3471
  }, this.onDeleteAccount = () => {
@@ -3223,7 +3480,7 @@ let p = class extends x {
3223
3480
  }
3224
3481
  /** Lazily load data for the active tab once a user is available. */
3225
3482
  ensureLoaded() {
3226
- !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());
3483
+ !this.user || this.busy || (this.logsProbeStarted || this.probeLogsSupport(), this.active === "sessions" && this.sessions === null ? this.loadSessions() : this.active === "connections" && this.identities === null ? this.loadIdentities() : this.active === "activity" && this.logsSupported === !0 && this.logs === null ? this.loadLogs() : this.active === "activity" && this.logsSupported === !1 ? this.active = "profile" : this.active === "security" && this.factors === null && this.loadFactors());
3227
3484
  }
3228
3485
  hydrate() {
3229
3486
  const e = this.auth.user;
@@ -3239,16 +3496,36 @@ let p = class extends x {
3239
3496
  select(e) {
3240
3497
  this.active = e, this.notice = null, this.errors = {};
3241
3498
  }
3242
- /** Run an action with a busy key, surfacing errors under that key. Handles MFA step-up. */
3499
+ updated(e) {
3500
+ e.has("active") && requestAnimationFrame(() => {
3501
+ const t = this.renderRoot.querySelector(
3502
+ '.tab[aria-selected="true"]'
3503
+ );
3504
+ t && typeof t.scrollIntoView == "function" && t.scrollIntoView({ inline: "nearest", block: "nearest", behavior: "smooth" });
3505
+ });
3506
+ }
3507
+ setNotice(e, t) {
3508
+ this.notice = { tone: e, message: t }, this.noticeTimer && clearTimeout(this.noticeTimer), this.noticeTimer = setTimeout(() => {
3509
+ this.notice = null, this.noticeTimer = null;
3510
+ }, 8e3);
3511
+ }
3512
+ requireValid(e) {
3513
+ const t = e.target;
3514
+ return !(t && typeof t.reportValidity == "function" && !t.reportValidity());
3515
+ }
3243
3516
  async run(e, t, i) {
3244
3517
  if (!this.busy) {
3245
- this.busy = e, this.errors = { ...this.errors, [e]: "" };
3518
+ this.busy = e, this.errors = { ...this.errors, [e]: "" }, this.notice = null;
3246
3519
  try {
3247
- await t(), i && (this.notice = { tone: "success", message: i });
3248
- } catch (r) {
3249
- N(r, v.challengeRequired) ? this.stepUp = { retry: () => this.run(e, t, i) } : this.errors = {
3520
+ await t(), i && this.setNotice("success", i);
3521
+ } catch (s) {
3522
+ z(s, v.challengeRequired) ? this.stepUp = { retry: () => this.run(e, t, i) } : this.errors = {
3250
3523
  ...this.errors,
3251
- [e]: at(r, this.strings, e.includes("code") ? "code" : "link")
3524
+ [e]: Z(
3525
+ s,
3526
+ this.strings,
3527
+ e.includes("code") ? "code" : e === "password" ? "password" : "link"
3528
+ )
3252
3529
  };
3253
3530
  } finally {
3254
3531
  this.busy = "";
@@ -3266,12 +3543,27 @@ let p = class extends x {
3266
3543
  this.identities = await n.listIdentities();
3267
3544
  });
3268
3545
  }
3546
+ /** Probe once so Activity is never shown on servers without /account/logs. */
3547
+ async probeLogsSupport() {
3548
+ if (!this.logsProbeStarted) {
3549
+ this.logsProbeStarted = !0;
3550
+ try {
3551
+ this.logs = await n.listLogs(), this.logsSupported = !0;
3552
+ } catch {
3553
+ this.logsSupported = !1, this.logs = [], this.active === "activity" && (this.active = "profile");
3554
+ }
3555
+ }
3556
+ }
3269
3557
  async loadLogs() {
3558
+ if (this.logsSupported === !1) {
3559
+ this.active === "activity" && (this.active = "profile");
3560
+ return;
3561
+ }
3270
3562
  this.busy = "logs";
3271
3563
  try {
3272
3564
  this.logs = await n.listLogs();
3273
3565
  } catch {
3274
- this.logsSupported = !1, this.logs = [];
3566
+ this.logsSupported = !1, this.logs = [], this.active === "activity" && (this.active = "profile");
3275
3567
  } finally {
3276
3568
  this.busy = "";
3277
3569
  }
@@ -3302,14 +3594,16 @@ let p = class extends x {
3302
3594
  // ─────────────────────────── render ───────────────────────────
3303
3595
  render() {
3304
3596
  if (!this.auth.configured)
3305
- return s`<div class="alert alert-error" role="alert">
3306
- ${c.alert}
3597
+ return r`<div class="alert alert-error" role="alert">
3598
+ ${o.alert}
3307
3599
  <div class="alert-body">${this.t("errorNotConfigured")}</div>
3308
3600
  </div>`;
3309
3601
  if (this.auth.status === "loading")
3310
- return s`<div class="empty"><span class="spinner"></span></div>`;
3602
+ return r`<div class="panel ${this.embedded ? "embedded" : ""}" part="panel">
3603
+ <div class="empty"><span class="spinner"></span></div>
3604
+ </div>`;
3311
3605
  if (!this.user)
3312
- return s`<div class="panel ${this.embedded ? "embedded" : ""}">
3606
+ return r`<div class="panel ${this.embedded ? "embedded" : ""}">
3313
3607
  <authui-sign-in embedded></authui-sign-in>
3314
3608
  </div>`;
3315
3609
  const e = [
@@ -3319,46 +3613,65 @@ let p = class extends x {
3319
3613
  { id: "connections", label: this.t("connections") },
3320
3614
  ...this.logsSupported ? [{ id: "activity", label: this.t("activity") }] : []
3321
3615
  ];
3322
- return s`
3616
+ return r`
3323
3617
  <div class="panel ${this.embedded ? "embedded" : ""}" part="panel">
3324
3618
  ${this.renderIdentity()}
3325
- <div class="tabs" role="tablist">
3619
+ <div class="tabs" role="tablist" @keydown=${this.onTabsKeydown}>
3326
3620
  ${e.map(
3327
- (t) => s`<button
3621
+ (t) => r`<button
3328
3622
  class="tab"
3329
3623
  role="tab"
3624
+ id=${`authui-tab-${t.id}`}
3625
+ aria-controls=${`authui-panel-${t.id}`}
3330
3626
  aria-selected=${this.active === t.id ? "true" : "false"}
3627
+ tabindex=${this.active === t.id ? "0" : "-1"}
3331
3628
  @click=${() => this.select(t.id)}
3332
3629
  >
3333
3630
  ${t.label}
3334
3631
  </button>`
3335
3632
  )}
3336
3633
  </div>
3337
- ${this.notice ? s`<div class="alert alert-${this.notice.tone}" role="status">
3338
- ${this.notice.tone === "success" ? c.checkCircle : c.info}
3634
+ ${this.notice ? r`<div class="alert alert-${this.notice.tone}" role="status">
3635
+ ${this.notice.tone === "success" ? o.checkCircle : o.info}
3339
3636
  <div class="alert-body">${this.notice.message}</div>
3340
- </div>` : o}
3341
- ${this.stepUp ? this.renderStepUp() : this.renderTab()}
3637
+ <button
3638
+ class="btn btn-ghost btn-icon dismiss"
3639
+ @click=${() => {
3640
+ this.notice = null, this.noticeTimer && (clearTimeout(this.noticeTimer), this.noticeTimer = null);
3641
+ }}
3642
+ aria-label=${this.t("close")}
3643
+ >
3644
+ ${o.x}
3645
+ </button>
3646
+ </div>` : c}
3647
+ ${this.stepUp ? this.renderStepUp() : r`<div
3648
+ class="tabpanel"
3649
+ role="tabpanel"
3650
+ id=${`authui-panel-${this.active}`}
3651
+ aria-labelledby=${`authui-tab-${this.active}`}
3652
+ >
3653
+ ${this.renderTab()}
3654
+ </div>`}
3342
3655
  </div>
3343
3656
  `;
3344
3657
  }
3345
3658
  renderIdentity() {
3346
3659
  const e = this.user, t = e.name || e.email || e.phone || this.t("guestAccount");
3347
- return s`
3660
+ return r`
3348
3661
  <div class="between">
3349
3662
  <div class="identity">
3350
- <span class="avatar">${t[0] ?? "?"}</span>
3663
+ <span class="avatar">${Q(t)}</span>
3351
3664
  <div class="row-main">
3352
- <span class="row-title">
3665
+ <span class="row-title" title=${t}>
3353
3666
  ${t}
3354
- ${e.mfa ? s`<span class="badge badge-success">${c.shieldCheck} MFA</span>` : o}
3355
- ${n.isPreview ? s`<span class="badge badge-info">${this.t("preview")}</span>` : o}
3667
+ ${e.mfa ? r`<span class="badge badge-success">${o.shieldCheck} ${this.t("mfaBadge")}</span>` : c}
3668
+ ${n.isPreview ? r`<span class="badge badge-info">${this.t("preview")}</span>` : c}
3356
3669
  </span>
3357
- ${e.email && e.name ? s`<span class="row-sub">${e.email}</span>` : o}
3670
+ ${e.email && e.name ? r`<span class="row-sub" title=${e.email}>${e.email}</span>` : c}
3358
3671
  </div>
3359
3672
  </div>
3360
3673
  <button class="btn btn-outline btn-sm" @click=${() => n.signOut()}>
3361
- ${c.logOut} ${this.t("signOut")}
3674
+ ${o.logOut} ${this.t("signOut")}
3362
3675
  </button>
3363
3676
  </div>
3364
3677
  `;
@@ -3379,35 +3692,35 @@ let p = class extends x {
3379
3692
  }
3380
3693
  error(e) {
3381
3694
  const t = this.errors[e];
3382
- return t ? s`<div class="alert alert-error" role="alert">
3383
- ${c.alert}
3695
+ return t ? r`<div class="alert alert-error" role="alert">
3696
+ ${o.alert}
3384
3697
  <div class="alert-body">${t}</div>
3385
- </div>` : o;
3698
+ </div>` : c;
3386
3699
  }
3387
3700
  spinner(e) {
3388
- return this.busy === e ? s`<span class="spinner" aria-hidden="true"></span>` : o;
3701
+ return this.busy === e ? r`<span class="spinner" aria-hidden="true"></span>` : c;
3389
3702
  }
3390
- card(e, t, i, r, a = !1) {
3391
- return s`<section class="card ${a ? "card-danger" : ""}">
3703
+ card(e, t, i, s, a = !1) {
3704
+ return r`<section class="card ${a ? "card-danger" : ""}">
3392
3705
  <div class="card-header">
3393
3706
  <h3 class="card-title">${e}</h3>
3394
- ${t ? s`<p class="card-description">${t}</p>` : o}
3707
+ ${t ? r`<p class="card-description">${t}</p>` : c}
3395
3708
  </div>
3396
3709
  <div class="card-body">${i}</div>
3397
- ${r ? s`<div class="card-footer">${r}</div>` : o}
3710
+ ${s ? r`<div class="card-footer">${s}</div>` : c}
3398
3711
  </section>`;
3399
3712
  }
3400
3713
  verifiedBadge(e) {
3401
- return e ? s`<span class="badge badge-success">${c.check} ${this.t("verified")}</span>` : s`<span class="badge badge-warning">${this.t("unverified")}</span>`;
3714
+ return e ? r`<span class="badge badge-success">${o.check} ${this.t("verified")}</span>` : r`<span class="badge badge-warning">${this.t("unverified")}</span>`;
3402
3715
  }
3403
3716
  // ── Profile ──
3404
3717
  renderProfile() {
3405
3718
  const e = this.user;
3406
- return this.isGuest ? s`<div class="section">
3719
+ return this.isGuest ? r`<div class="section">
3407
3720
  ${this.card(
3408
3721
  this.t("guestAccount"),
3409
3722
  this.t("guestAccountDescription"),
3410
- s`<form class="form" id="guest-form" @submit=${this.onConvertGuest} novalidate>
3723
+ r`<form class="form" id="guest-form" @submit=${this.onConvertGuest} novalidate>
3411
3724
  <div class="field">
3412
3725
  <label class="label" for="guest-name">${this.t("name")}</label>
3413
3726
  <input
@@ -3446,7 +3759,7 @@ let p = class extends x {
3446
3759
  </div>
3447
3760
  ${this.error("guest")}
3448
3761
  </form>`,
3449
- s`<button
3762
+ r`<button
3450
3763
  class="btn btn-primary btn-sm"
3451
3764
  type="submit"
3452
3765
  form="guest-form"
@@ -3455,11 +3768,11 @@ let p = class extends x {
3455
3768
  ${this.spinner("guest")} ${this.t("createAccount")}
3456
3769
  </button>`
3457
3770
  )}
3458
- </div>` : s`<div class="section">
3771
+ </div>` : r`<div class="section">
3459
3772
  ${this.card(
3460
3773
  this.t("name"),
3461
3774
  void 0,
3462
- s`<form class="form" id="name-form" @submit=${this.onUpdateName} novalidate>
3775
+ r`<form class="form" id="name-form" @submit=${this.onUpdateName} novalidate>
3463
3776
  <div class="field">
3464
3777
  <label class="label" for="acc-name">${this.t("name")}</label>
3465
3778
  <input
@@ -3473,11 +3786,11 @@ let p = class extends x {
3473
3786
  </div>
3474
3787
  ${this.error("name")}
3475
3788
  </form>`,
3476
- s`<button
3789
+ r`<button
3477
3790
  class="btn btn-primary btn-sm"
3478
3791
  type="submit"
3479
3792
  form="name-form"
3480
- ?disabled=${!!this.busy || this.nameInput === e.name}
3793
+ ?disabled=${!!this.busy || !this.nameInput.trim() || this.nameInput === e.name}
3481
3794
  >
3482
3795
  ${this.spinner("name")} ${this.t("update")}
3483
3796
  </button>`
@@ -3485,11 +3798,11 @@ let p = class extends x {
3485
3798
  ${this.card(
3486
3799
  this.t("email"),
3487
3800
  void 0,
3488
- s`<form class="form" id="email-form" @submit=${this.onUpdateEmail} novalidate>
3801
+ r`<form class="form" id="email-form" @submit=${this.onUpdateEmail} novalidate>
3489
3802
  <div class="field">
3490
3803
  <label class="label" for="acc-email"
3491
3804
  >${this.t("email")}
3492
- ${e.email ? this.verifiedBadge(e.emailVerification) : o}</label
3805
+ ${e.email ? this.verifiedBadge(e.emailVerification) : c}</label
3493
3806
  >
3494
3807
  <input
3495
3808
  class="input"
@@ -3501,34 +3814,43 @@ let p = class extends x {
3501
3814
  required
3502
3815
  />
3503
3816
  </div>
3504
- ${this.emailInput !== e.email ? s`<div class="field">
3505
- <label class="label" for="acc-email-password">${this.t("currentPassword")}</label>
3817
+ ${this.emailInput !== e.email ? r`<div class="field">
3818
+ <label class="label" for="acc-email-password"
3819
+ >${e.passwordUpdate ? this.t("currentPassword") : this.t("createPassword")}</label
3820
+ >
3506
3821
  <input
3507
3822
  class="input"
3508
3823
  id="acc-email-password"
3509
3824
  type="password"
3510
3825
  .value=${this.emailPassword}
3511
3826
  @input=${this.bind("emailPassword")}
3512
- autocomplete="current-password"
3827
+ autocomplete=${e.passwordUpdate ? "current-password" : "new-password"}
3513
3828
  required
3514
3829
  />
3515
- </div>` : o}
3830
+ ${e.passwordUpdate ? c : r`<p class="hint">${this.t("createPasswordHint")}</p>`}
3831
+ </div>` : c}
3516
3832
  ${this.error("email")} ${this.error("verify")}
3517
3833
  </form>`,
3518
- s`
3519
- ${e.email && !e.emailVerification ? s`<button
3834
+ r`
3835
+ ${e.email && !e.emailVerification ? r`<button
3520
3836
  class="btn btn-outline btn-sm"
3521
3837
  type="button"
3522
3838
  @click=${this.onSendVerification}
3523
- ?disabled=${!!this.busy}
3839
+ ?disabled=${!!this.busy || Date.now() < this.verifyEmailCooldownUntil}
3524
3840
  >
3525
- ${this.spinner("verify")} ${this.t("verifyEmail")}
3526
- </button>` : o}
3841
+ ${this.spinner("verify")}
3842
+ ${Date.now() < this.verifyEmailCooldownUntil ? this.t("verificationResendIn", {
3843
+ seconds: Math.max(
3844
+ 1,
3845
+ Math.ceil((this.verifyEmailCooldownUntil - Date.now()) / 1e3)
3846
+ )
3847
+ }) : this.t("verifyEmail")}
3848
+ </button>` : c}
3527
3849
  <button
3528
3850
  class="btn btn-primary btn-sm"
3529
3851
  type="submit"
3530
3852
  form="email-form"
3531
- ?disabled=${!!this.busy || this.emailInput === e.email}
3853
+ ?disabled=${!!this.busy || !this.emailInput.trim() || this.emailInput === e.email}
3532
3854
  >
3533
3855
  ${this.spinner("email")} ${this.t("update")}
3534
3856
  </button>
@@ -3537,11 +3859,11 @@ let p = class extends x {
3537
3859
  ${this.card(
3538
3860
  this.t("phone"),
3539
3861
  void 0,
3540
- s`<form class="form" id="phone-form" @submit=${this.onUpdatePhone} novalidate>
3862
+ r`<form class="form" id="phone-form" @submit=${this.onUpdatePhone} novalidate>
3541
3863
  <div class="field">
3542
3864
  <label class="label" for="acc-phone"
3543
3865
  >${this.t("phone")}
3544
- ${e.phone ? this.verifiedBadge(e.phoneVerification) : o}</label
3866
+ ${e.phone ? this.verifiedBadge(e.phoneVerification) : c}</label
3545
3867
  >
3546
3868
  <input
3547
3869
  class="input"
@@ -3553,53 +3875,62 @@ let p = class extends x {
3553
3875
  autocomplete="tel"
3554
3876
  />
3555
3877
  </div>
3556
- ${this.phoneInput !== e.phone ? s`<div class="field">
3557
- <label class="label" for="acc-phone-password">${this.t("currentPassword")}</label>
3878
+ ${this.phoneInput !== e.phone ? r`<div class="field">
3879
+ <label class="label" for="acc-phone-password"
3880
+ >${e.passwordUpdate ? this.t("currentPassword") : this.t("createPassword")}</label
3881
+ >
3558
3882
  <input
3559
3883
  class="input"
3560
3884
  id="acc-phone-password"
3561
3885
  type="password"
3562
3886
  .value=${this.phonePassword}
3563
3887
  @input=${this.bind("phonePassword")}
3564
- autocomplete="current-password"
3888
+ autocomplete=${e.passwordUpdate ? "current-password" : "new-password"}
3565
3889
  required
3566
3890
  />
3567
- </div>` : o}
3568
- ${this.phoneCodeSent ? s`<div class="field">
3891
+ ${e.passwordUpdate ? c : r`<p class="hint">${this.t("createPasswordHint")}</p>`}
3892
+ </div>` : c}
3893
+ ${this.phoneCodeSent ? r`<div class="field">
3569
3894
  <label class="label" for="acc-phone-code">${this.t("code")}</label>
3570
3895
  <input
3571
3896
  class="input input-otp"
3572
3897
  id="acc-phone-code"
3573
3898
  inputmode="numeric"
3574
3899
  autocomplete="one-time-code"
3900
+ maxlength="6"
3901
+ pattern="[0-9]*"
3902
+ required
3575
3903
  .value=${this.phoneCode}
3576
3904
  @input=${this.bind("phoneCode")}
3905
+ @keydown=${(t) => {
3906
+ t.key === "Enter" && (t.preventDefault(), this.onConfirmPhoneVerification(t));
3907
+ }}
3577
3908
  />
3578
- </div>` : o}
3909
+ </div>` : c}
3579
3910
  ${this.error("phone")} ${this.error("verify-phone")} ${this.error("verify-phone-code")}
3580
3911
  </form>`,
3581
- s`
3582
- ${e.phone && !e.phoneVerification && !this.phoneCodeSent ? s`<button
3912
+ r`
3913
+ ${e.phone && !e.phoneVerification && !this.phoneCodeSent ? r`<button
3583
3914
  class="btn btn-outline btn-sm"
3584
3915
  type="button"
3585
3916
  @click=${this.onSendPhoneVerification}
3586
3917
  ?disabled=${!!this.busy}
3587
3918
  >
3588
3919
  ${this.spinner("verify-phone")} ${this.t("sendCode")}
3589
- </button>` : o}
3590
- ${this.phoneCodeSent ? s`<button
3920
+ </button>` : c}
3921
+ ${this.phoneCodeSent ? r`<button
3591
3922
  class="btn btn-outline btn-sm"
3592
3923
  type="button"
3593
3924
  @click=${this.onConfirmPhoneVerification}
3594
3925
  ?disabled=${!!this.busy}
3595
3926
  >
3596
3927
  ${this.spinner("verify-phone-code")} ${this.t("verifyCode")}
3597
- </button>` : o}
3928
+ </button>` : c}
3598
3929
  <button
3599
3930
  class="btn btn-primary btn-sm"
3600
3931
  type="submit"
3601
3932
  form="phone-form"
3602
- ?disabled=${!!this.busy || this.phoneInput === e.phone}
3933
+ ?disabled=${!!this.busy || !this.phoneInput.trim() || this.phoneInput === e.phone}
3603
3934
  >
3604
3935
  ${this.spinner("phone")} ${this.t("update")}
3605
3936
  </button>
@@ -3612,10 +3943,10 @@ let p = class extends x {
3612
3943
  return this.card(
3613
3944
  this.t("deleteAccount"),
3614
3945
  this.t("deleteAccountDescription"),
3615
- s`${this.error("delete")}
3616
- ${this.confirmDelete ? s`<div class="inline">
3946
+ r`${this.error("delete")}
3947
+ ${this.confirmDelete ? r`<div class="inline">
3617
3948
  <button
3618
- class="btn btn-destructive btn-sm"
3949
+ class="btn btn-outline btn-sm warn"
3619
3950
  @click=${this.onDeleteAccount}
3620
3951
  ?disabled=${!!this.busy}
3621
3952
  >
@@ -3624,11 +3955,11 @@ let p = class extends x {
3624
3955
  <button class="btn btn-ghost btn-sm" @click=${() => this.confirmDelete = !1}>
3625
3956
  ${this.t("cancel")}
3626
3957
  </button>
3627
- </div>` : s`<button
3958
+ </div>` : r`<button
3628
3959
  class="btn btn-outline btn-sm warn"
3629
3960
  @click=${() => this.confirmDelete = !0}
3630
3961
  >
3631
- ${c.userX} ${this.t("deleteAccount")}
3962
+ ${o.userX} ${this.t("deleteAccount")}
3632
3963
  </button>`}`,
3633
3964
  void 0,
3634
3965
  !0
@@ -3637,17 +3968,17 @@ let p = class extends x {
3637
3968
  // ── Security ──
3638
3969
  renderSecurity() {
3639
3970
  const e = this.user, t = this.config?.mfa !== !1;
3640
- return s`<div class="section">
3641
- ${this.isGuest ? o : this.card(
3971
+ return r`<div class="section">
3972
+ ${this.isGuest ? c : this.card(
3642
3973
  this.t("changePassword"),
3643
3974
  void 0,
3644
- s`<form
3975
+ r`<form
3645
3976
  class="form"
3646
3977
  id="password-form"
3647
3978
  @submit=${this.onChangePassword}
3648
3979
  novalidate
3649
3980
  >
3650
- ${e.passwordUpdate ? s`<div class="field">
3981
+ ${e.passwordUpdate ? r`<div class="field">
3651
3982
  <label class="label" for="acc-old-password"
3652
3983
  >${this.t("currentPassword")}</label
3653
3984
  >
@@ -3658,8 +3989,9 @@ let p = class extends x {
3658
3989
  .value=${this.oldPassword}
3659
3990
  @input=${this.bind("oldPassword")}
3660
3991
  autocomplete="current-password"
3992
+ required
3661
3993
  />
3662
- </div>` : o}
3994
+ </div>` : c}
3663
3995
  <div class="field">
3664
3996
  <label class="label" for="acc-new-password">${this.t("newPassword")}</label>
3665
3997
  <input
@@ -3691,7 +4023,7 @@ let p = class extends x {
3691
4023
  </div>
3692
4024
  ${this.error("password")}
3693
4025
  </form>`,
3694
- s`<button
4026
+ r`<button
3695
4027
  class="btn btn-primary btn-sm"
3696
4028
  type="submit"
3697
4029
  form="password-form"
@@ -3700,20 +4032,20 @@ let p = class extends x {
3700
4032
  ${this.spinner("password")} ${this.t("update")}
3701
4033
  </button>`
3702
4034
  )}
3703
- ${t ? this.renderMfaCard() : o}
3704
- ${t ? this.renderRecoveryCard() : o}
4035
+ ${t ? this.renderMfaCard() : c}
4036
+ ${t ? this.renderRecoveryCard() : c}
3705
4037
  </div>`;
3706
4038
  }
3707
4039
  renderMfaCard() {
3708
- const e = this.user, t = this.factors?.totp ?? !1, i = this.authenticator ? n.isPreview ? ft(this.authenticator.uri) : new ct(n.getClient()).getQR(this.authenticator.uri, 400, 1).toString() : "";
4040
+ const e = this.user, t = this.factors?.totp ?? !1, i = this.authenticator ? n.isPreview ? gt(this.authenticator.uri) : new dt(n.getClient()).getQR(this.authenticator.uri, 400, 1).toString() : "";
3709
4041
  return this.card(
3710
4042
  this.t("twoFactor"),
3711
4043
  this.t("twoFactorDescription"),
3712
- s`<div class="kv">
4044
+ r`<div class="kv">
3713
4045
  <div class="toggle-row">
3714
4046
  <div class="row-main">
3715
4047
  <span class="row-title">${this.t("twoFactor")}</span>
3716
- <span class="row-sub">${e.mfa ? this.t("enable") : this.t("disable")}d</span>
4048
+ <span class="row-sub">${e.mfa ? this.t("enabled") : this.t("disabled")}</span>
3717
4049
  </div>
3718
4050
  <button
3719
4051
  class="switch"
@@ -3724,22 +4056,52 @@ let p = class extends x {
3724
4056
  aria-label=${this.t("twoFactor")}
3725
4057
  ></button>
3726
4058
  </div>
4059
+ ${e.mfa && !(this.factors?.totp || e.emailVerification || e.phoneVerification) ? r`<div class="alert alert-warning" role="status">
4060
+ ${o.alert}
4061
+ <div class="alert-body">
4062
+ ${this.t("mfaNoFactorWarning")}
4063
+ ${this.factors?.totp ? c : r`<div class="links">
4064
+ <button
4065
+ type="button"
4066
+ class="btn btn-link"
4067
+ @click=${this.onAddAuthenticator}
4068
+ ?disabled=${!!this.busy || !!this.authenticator}
4069
+ >
4070
+ ${this.t("authenticatorAdd")}
4071
+ </button>
4072
+ </div>`}
4073
+ </div>
4074
+ </div>` : c}
3727
4075
  ${this.error("mfa")}
3728
4076
  <div class="separator"></div>
3729
4077
  <div class="toggle-row">
3730
4078
  <div class="row-main">
3731
4079
  <span class="row-title"
3732
- >${c.smartphone} ${this.t("authenticatorApp")}
3733
- ${t ? this.verifiedBadge(!0) : o}</span
4080
+ >${o.smartphone} ${this.t("authenticatorApp")}
4081
+ ${t ? this.verifiedBadge(!0) : c}</span
3734
4082
  >
3735
4083
  </div>
3736
- ${t ? s`<button
3737
- class="btn btn-outline btn-sm"
3738
- @click=${this.onRemoveAuthenticator}
3739
- ?disabled=${!!this.busy}
3740
- >
3741
- ${this.spinner("remove-authenticator")} ${this.t("remove")}
3742
- </button>` : this.authenticator ? o : s`<button
4084
+ ${t ? this.confirmRemoveAuthenticator ? r`<div class="inline">
4085
+ <button
4086
+ class="btn btn-outline btn-sm warn"
4087
+ @click=${this.onRemoveAuthenticator}
4088
+ ?disabled=${!!this.busy}
4089
+ >
4090
+ ${this.spinner("remove-authenticator")} ${this.t("remove")}
4091
+ </button>
4092
+ <button
4093
+ class="btn btn-ghost btn-sm"
4094
+ @click=${() => this.confirmRemoveAuthenticator = !1}
4095
+ >
4096
+ ${this.t("cancel")}
4097
+ </button>
4098
+ </div>` : r`<button
4099
+ class="btn btn-outline btn-sm"
4100
+ @click=${this.onRemoveAuthenticator}
4101
+ ?disabled=${!!this.busy}
4102
+ >
4103
+ ${this.spinner("remove-authenticator")} ${this.t("remove")}
4104
+ </button>` : this.authenticator ? c : r`<button
3743
4105
  class="btn btn-outline btn-sm"
3744
4106
  @click=${this.onAddAuthenticator}
3745
4107
  ?disabled=${!!this.busy}
@@ -3748,13 +4110,25 @@ let p = class extends x {
3748
4110
  </button>`}
3749
4111
  </div>
3750
4112
  ${this.error("authenticator")} ${this.error("remove-authenticator")}
3751
- ${this.authenticator ? s`<form class="form" @submit=${this.onVerifyAuthenticator} novalidate>
4113
+ ${this.authenticator ? r`<form class="form" @submit=${this.onVerifyAuthenticator} novalidate>
3752
4114
  <p class="hint">${this.t("authenticatorScan")}</p>
3753
- <img class="qr" src=${i} alt="QR code" />
3754
- <p class="hint center">
3755
- ${this.t("authenticatorManual")}:
3756
- <span class="code">${this.authenticator.secret}</span>
3757
- </p>
4115
+ <img class="qr" src=${i} alt=${this.t("qrCodeAlt")} />
4116
+ <p class="hint center">${this.t("authenticatorManual")}</p>
4117
+ <div class="inline">
4118
+ <span class="code"
4119
+ >${this.authenticator.secret.match(/.{1,4}/g)?.join(" ") ?? this.authenticator.secret}</span
4120
+ >
4121
+ <button
4122
+ class="btn btn-ghost btn-sm"
4123
+ type="button"
4124
+ @click=${() => {
4125
+ this.onCopySecret();
4126
+ }}
4127
+ >
4128
+ ${this.copied ? o.check : o.copy}
4129
+ ${this.copied ? this.t("copied") : this.t("authenticatorCopyKey")}
4130
+ </button>
4131
+ </div>
3758
4132
  <div class="field">
3759
4133
  <label class="label" for="acc-totp">${this.t("code")}</label>
3760
4134
  <input
@@ -3762,6 +4136,8 @@ let p = class extends x {
3762
4136
  id="acc-totp"
3763
4137
  inputmode="numeric"
3764
4138
  autocomplete="one-time-code"
4139
+ maxlength="6"
4140
+ pattern="[0-9]*"
3765
4141
  required
3766
4142
  .value=${this.authenticatorCode}
3767
4143
  @input=${this.bind("authenticatorCode")}
@@ -3780,7 +4156,7 @@ let p = class extends x {
3780
4156
  ${this.t("cancel")}
3781
4157
  </button>
3782
4158
  </div>
3783
- </form>` : o}
4159
+ </form>` : c}
3784
4160
  </div>`
3785
4161
  );
3786
4162
  }
@@ -3788,33 +4164,53 @@ let p = class extends x {
3788
4164
  const e = this.factors?.recoveryCode ?? !1;
3789
4165
  return this.card(
3790
4166
  this.t("recoveryCodes"),
3791
- this.t("recoveryCodesDescription"),
3792
- s`<div class="kv">
3793
- ${this.recoveryCodes ? s`<div class="alert alert-warning">
3794
- ${c.alert}
4167
+ this.t("recoveryCodesDescription") + " " + this.t("recoveryCodesOnceHint"),
4168
+ r`<div class="kv">
4169
+ ${this.recoveryCodes ? r`<div class="alert alert-warning">
4170
+ ${o.alert}
3795
4171
  <div class="alert-body">${this.t("recoveryCodesWarning")}</div>
3796
4172
  </div>
3797
4173
  <div class="codes">
3798
- ${this.recoveryCodes.map((t) => s`<span class="code">${t}</span>`)}
4174
+ ${this.recoveryCodes.map((t) => r`<span class="code">${t}</span>`)}
3799
4175
  </div>
3800
4176
  <div class="inline">
3801
4177
  <button class="btn btn-outline btn-sm" @click=${this.onCopyCodes}>
3802
- ${this.copied ? c.check : c.copy}
4178
+ ${this.copied ? o.check : o.copy}
3803
4179
  ${this.copied ? this.t("copied") : this.t("copy")}
3804
4180
  </button>
3805
4181
  <button class="btn btn-ghost btn-sm" @click=${() => this.recoveryCodes = null}>
3806
4182
  ${this.t("done")}
3807
4183
  </button>
3808
- </div>` : s`<div class="inline">
4184
+ </div>` : r`<div class="inline">
3809
4185
  <button
3810
4186
  class="btn btn-outline btn-sm"
3811
4187
  @click=${this.onRecoveryCodes}
3812
4188
  ?disabled=${!!this.busy}
3813
4189
  >
3814
- ${this.spinner("recovery")} ${c.key}
3815
- ${e ? this.t("recoveryCodes") : this.t("generateRecoveryCodes")}
4190
+ ${this.spinner("recovery")} ${o.key}
4191
+ ${e ? this.t("viewRecoveryCodes") : this.t("generateRecoveryCodes")}
3816
4192
  </button>
3817
- ${e ? s`<button class="btn btn-ghost btn-sm" @click=${this.onRegenerateRecoveryCodes} ?disabled=${!!this.busy}>${c.refresh} ${this.t("regenerateRecoveryCodes")}</button>` : o}
4193
+ ${e ? this.confirmRegenerate ? r`<div class="inline">
4194
+ <button
4195
+ class="btn btn-outline btn-sm warn"
4196
+ @click=${this.onRegenerateRecoveryCodes}
4197
+ ?disabled=${!!this.busy}
4198
+ >
4199
+ ${o.refresh} ${this.t("regenerateRecoveryCodes")}
4200
+ </button>
4201
+ <button
4202
+ class="btn btn-ghost btn-sm"
4203
+ @click=${() => this.confirmRegenerate = !1}
4204
+ >
4205
+ ${this.t("cancel")}
4206
+ </button>
4207
+ </div>` : r`<button
4208
+ class="btn btn-ghost btn-sm"
4209
+ @click=${this.onRegenerateRecoveryCodes}
4210
+ ?disabled=${!!this.busy}
4211
+ >
4212
+ ${o.refresh} ${this.t("regenerateRecoveryCodes")}
4213
+ </button>` : c}
3818
4214
  </div>`}
3819
4215
  ${this.error("recovery")}
3820
4216
  </div>`
@@ -3825,25 +4221,25 @@ let p = class extends x {
3825
4221
  const e = this.stepUp, t = this.factors, i = [
3826
4222
  {
3827
4223
  factor: "totp",
3828
- icon: c.smartphone,
4224
+ icon: o.smartphone,
3829
4225
  label: this.t("mfaUseAuthenticator"),
3830
4226
  available: t?.totp ?? !0
3831
4227
  },
3832
4228
  {
3833
4229
  factor: "email",
3834
- icon: c.mail,
4230
+ icon: o.mail,
3835
4231
  label: this.t("mfaUseEmail"),
3836
4232
  available: t?.email ?? !0
3837
4233
  },
3838
4234
  {
3839
4235
  factor: "phone",
3840
- icon: c.phone,
4236
+ icon: o.phone,
3841
4237
  label: this.t("mfaUsePhone"),
3842
4238
  available: t?.phone ?? !0
3843
4239
  },
3844
4240
  {
3845
4241
  factor: "recoverycode",
3846
- icon: c.key,
4242
+ icon: o.key,
3847
4243
  label: this.t("mfaUseRecoveryCode"),
3848
4244
  available: t?.recoveryCode ?? !0
3849
4245
  }
@@ -3851,8 +4247,8 @@ let p = class extends x {
3851
4247
  return this.card(
3852
4248
  this.t("mfaTitle"),
3853
4249
  this.t("errorChallengeRequired"),
3854
- s`<div class="kv">
3855
- ${e.challenge ? s`<form class="form" @submit=${this.onStepUpVerify} novalidate>
4250
+ r`<div class="kv">
4251
+ ${e.challenge ? r`<form class="form" @submit=${this.onStepUpVerify} novalidate>
3856
4252
  <div class="field">
3857
4253
  <label class="label" for="acc-stepup"
3858
4254
  >${e.challenge.factor === "recoverycode" ? this.t("recoveryCode") : this.t("code")}</label
@@ -3860,6 +4256,9 @@ let p = class extends x {
3860
4256
  <input
3861
4257
  class="input ${e.challenge.factor === "recoverycode" ? "mono" : "input-otp"}"
3862
4258
  id="acc-stepup"
4259
+ inputmode=${e.challenge.factor === "recoverycode" ? "text" : "numeric"}
4260
+ maxlength=${e.challenge.factor === "recoverycode" ? "64" : "6"}
4261
+ pattern=${e.challenge.factor === "recoverycode" ? ".*" : "[0-9]*"}
3863
4262
  autocomplete="one-time-code"
3864
4263
  required
3865
4264
  .value=${this.stepUpCode}
@@ -3869,21 +4268,21 @@ let p = class extends x {
3869
4268
  <button class="btn btn-primary btn-sm" type="submit" ?disabled=${!!this.busy}>
3870
4269
  ${this.spinner("stepup-code")} ${this.t("verifyCode")}
3871
4270
  </button>
3872
- </form>` : s`<div class="stack-sm">
3873
- ${i.filter((r) => r.available).map(
3874
- (r) => s`<button
4271
+ </form>` : r`<div class="stack-sm">
4272
+ ${i.filter((s) => s.available).map(
4273
+ (s) => r`<button
3875
4274
  type="button"
3876
4275
  class="choice"
3877
- @click=${() => this.onStepUpFactor(r.factor)}
4276
+ @click=${() => this.onStepUpFactor(s.factor)}
3878
4277
  ?disabled=${!!this.busy}
3879
4278
  >
3880
- ${r.icon}<span class="choice-title">${r.label}</span>
4279
+ ${s.icon}<span class="choice-title">${s.label}</span>
3881
4280
  </button>`
3882
4281
  )}
3883
4282
  </div>`}
3884
4283
  ${this.error("stepup")} ${this.error("stepup-code")}
3885
4284
  </div>`,
3886
- s`<button class="btn btn-ghost btn-sm" @click=${() => this.stepUp = null}>
4285
+ r`<button class="btn btn-ghost btn-sm" @click=${() => this.stepUp = null}>
3887
4286
  ${this.t("cancel")}
3888
4287
  </button>`
3889
4288
  );
@@ -3891,24 +4290,24 @@ let p = class extends x {
3891
4290
  // ── Sessions ──
3892
4291
  deviceIcon(e) {
3893
4292
  const t = (e.deviceName || "").toLowerCase(), i = (e.osName || e.osCode || "").toLowerCase();
3894
- return /phone|tablet|mobile/.test(t) || /ios|android|ipados/.test(i) ? c.smartphone : /desktop|browser/.test(t) || /mac|windows|linux|chrome os/.test(i) ? c.monitor : c.globe;
4293
+ return /phone|tablet|mobile/.test(t) || /ios|android|ipados/.test(i) ? o.smartphone : /desktop|browser/.test(t) || /mac|windows|linux|chrome os/.test(i) ? o.monitor : o.globe;
3895
4294
  }
3896
4295
  renderSessions() {
3897
4296
  const e = this.sessions;
3898
- return s`<div class="section">
4297
+ return r`<div class="section">
3899
4298
  ${this.card(
3900
4299
  this.t("sessions"),
3901
4300
  void 0,
3902
- s`${this.error("sessions")}
3903
- ${e === null ? s`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? s`<div class="empty">${this.t("noActivity")}</div>` : e.map(
3904
- (t) => s`<div class="row">
4301
+ r`${this.error("sessions")}
4302
+ ${e === null ? r`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? r`<div class="empty">${this.t("noSessions")}</div>` : e.map(
4303
+ (t) => r`<div class="row">
3905
4304
  <div class="inline">
3906
4305
  <span class="device">${this.deviceIcon(t)}</span>
3907
4306
  <div class="row-main">
3908
4307
  <span class="row-title">
3909
4308
  ${t.clientName || t.provider}
3910
- ${t.clientVersion ? s`<span class="muted small">${t.clientVersion}</span>` : o}
3911
- ${t.current ? s`<span class="badge badge-info">${this.t("currentSession")}</span>` : o}
4309
+ ${t.clientVersion ? r`<span class="muted small">${t.clientVersion}</span>` : c}
4310
+ ${t.current ? r`<span class="badge badge-info">${this.t("currentSession")}</span>` : c}
3912
4311
  </span>
3913
4312
  <span class="row-sub"
3914
4313
  >${[t.osName, t.countryName || t.countryCode, t.ip].filter(Boolean).join(" · ")}</span
@@ -3916,14 +4315,14 @@ let p = class extends x {
3916
4315
  </div>
3917
4316
  </div>
3918
4317
  <div class="row-actions">
3919
- ${this.busy === `session-${t.$id}` ? s`<span class="spinner"></span>` : o}
4318
+ ${this.busy === `session-${t.$id}` ? r`<span class="spinner"></span>` : c}
3920
4319
  <button
3921
4320
  class="btn btn-ghost btn-sm"
3922
4321
  @click=${() => this.onDeleteSession(t.$id)}
3923
4322
  ?disabled=${!!this.busy}
3924
4323
  aria-label=${this.t("signOutSession")}
3925
4324
  >
3926
- ${c.logOut}
4325
+ ${o.logOut}
3927
4326
  </button>
3928
4327
  </div>
3929
4328
  </div>`
@@ -3932,14 +4331,28 @@ let p = class extends x {
3932
4331
  ${this.card(
3933
4332
  this.t("signOutAllSessions"),
3934
4333
  this.t("signOutAllSessionsDescription"),
3935
- s`${this.error("sessions-all")}
3936
- <button
3937
- class="btn btn-outline btn-sm warn"
3938
- @click=${this.onSignOutAll}
3939
- ?disabled=${!!this.busy}
3940
- >
3941
- ${this.spinner("sessions-all")} ${c.logOut} ${this.t("signOutAllSessions")}
3942
- </button>`,
4334
+ r`${this.error("sessions-all")}
4335
+ ${this.confirmSignOutAll ? r`<div class="inline">
4336
+ <button
4337
+ class="btn btn-outline btn-sm warn"
4338
+ @click=${this.onSignOutAll}
4339
+ ?disabled=${!!this.busy}
4340
+ >
4341
+ ${this.spinner("sessions-all")} ${o.logOut} ${this.t("signOutAllSessions")}
4342
+ </button>
4343
+ <button
4344
+ class="btn btn-ghost btn-sm"
4345
+ @click=${() => this.confirmSignOutAll = !1}
4346
+ >
4347
+ ${this.t("cancel")}
4348
+ </button>
4349
+ </div>` : r`<button
4350
+ class="btn btn-outline btn-sm warn"
4351
+ @click=${this.onSignOutAll}
4352
+ ?disabled=${!!this.busy}
4353
+ >
4354
+ ${this.spinner("sessions-all")} ${o.logOut} ${this.t("signOutAllSessions")}
4355
+ </button>`}`,
3943
4356
  void 0,
3944
4357
  !0
3945
4358
  )}
@@ -3948,38 +4361,57 @@ let p = class extends x {
3948
4361
  // ── Connections ──
3949
4362
  renderConnections() {
3950
4363
  const e = this.identities, t = this.config?.methods?.oauth ?? [];
3951
- return s`<div class="section">
4364
+ return r`<div class="section">
3952
4365
  ${this.card(
3953
4366
  this.t("connections"),
3954
4367
  void 0,
3955
- s`${this.error("identities")}
3956
- ${e === null ? s`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? s`<div class="empty">${this.t("noConnections")}</div>` : e.map(
3957
- (i) => s`<div class="row">
4368
+ r`${this.error("identities")}
4369
+ ${e === null ? r`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? r`<div class="empty">${this.t("noConnections")}</div>` : e.map(
4370
+ (i) => r`<div class="row">
3958
4371
  <div class="inline">
3959
- <span class="device">${G(i.provider)}</span>
4372
+ <span class="device">${Y(i.provider)}</span>
3960
4373
  <div class="row-main">
3961
- <span class="row-title">${O(i.provider)}</span>
4374
+ <span class="row-title">${R(i.provider)}</span>
3962
4375
  <span class="row-sub">${i.providerEmail || i.providerUid}</span>
3963
4376
  </div>
3964
4377
  </div>
3965
4378
  <div class="row-actions">
3966
- <button
3967
- class="btn btn-ghost btn-sm"
3968
- @click=${() => this.onDeleteIdentity(i.$id)}
3969
- ?disabled=${!!this.busy}
3970
- >
3971
- ${this.busy === `identity-${i.$id}` ? s`<span class="spinner"></span>` : o}
3972
- ${this.t("disconnect")}
3973
- </button>
4379
+ ${this.confirmDisconnectId === i.$id ? r`<div class="inline">
4380
+ <button
4381
+ class="btn btn-outline btn-sm warn"
4382
+ @click=${() => this.onDeleteIdentity(i.$id)}
4383
+ ?disabled=${!!this.busy}
4384
+ >
4385
+ ${this.busy === `identity-${i.$id}` ? r`<span class="spinner"></span>` : c}
4386
+ ${this.t("disconnect")}
4387
+ </button>
4388
+ <button
4389
+ class="btn btn-ghost btn-sm"
4390
+ @click=${() => this.confirmDisconnectId = null}
4391
+ >
4392
+ ${this.t("cancel")}
4393
+ </button>
4394
+ </div>` : r`<button
4395
+ class="btn btn-ghost btn-sm"
4396
+ @click=${() => this.onDeleteIdentity(i.$id)}
4397
+ ?disabled=${!!this.busy}
4398
+ >
4399
+ ${this.busy === `identity-${i.$id}` ? r`<span class="spinner"></span>` : c}
4400
+ ${this.t("disconnect")}
4401
+ </button>`}
3974
4402
  </div>
3975
4403
  </div>`
3976
4404
  )}`,
3977
- t.length > 0 ? s`${t.filter((i) => !(e ?? []).some((r) => r.provider === i)).map(
3978
- (i) => s`<button
4405
+ t.length > 0 ? r`${t.filter((i) => !(e ?? []).some((s) => s.provider === i)).map(
4406
+ (i) => r`<button
3979
4407
  class="btn btn-outline btn-sm"
3980
- @click=${() => n.signInWithOAuth(i)}
4408
+ @click=${() => {
4409
+ this.run(`connect-${i}`, () => n.signInWithOAuth(i));
4410
+ }}
4411
+ ?disabled=${!!this.busy}
3981
4412
  >
3982
- ${G(i)} ${O(i)}
4413
+ ${this.spinner(`connect-${i}`)} ${Y(i)}
4414
+ ${this.t("connectProvider", { provider: R(i) })}
3983
4415
  </button>`
3984
4416
  )}` : void 0
3985
4417
  )}
@@ -3988,12 +4420,12 @@ let p = class extends x {
3988
4420
  // ── Activity ──
3989
4421
  renderActivity() {
3990
4422
  const e = this.logs;
3991
- return s`<div class="section">
4423
+ return r`<div class="section">
3992
4424
  ${this.card(
3993
4425
  this.t("activity"),
3994
4426
  void 0,
3995
- 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(
3996
- (t) => s`<div class="row">
4427
+ r`${e === null ? r`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? r`<div class="empty">${this.t("noActivity")}</div>` : e.map(
4428
+ (t) => r`<div class="row">
3997
4429
  <div class="row-main">
3998
4430
  <span class="row-title">${t.event}</span>
3999
4431
  <span class="row-sub"
@@ -4007,15 +4439,18 @@ let p = class extends x {
4007
4439
  </div>`;
4008
4440
  }
4009
4441
  };
4010
- p.styles = [
4011
- ...x.styles,
4012
- E`
4442
+ u.styles = [
4443
+ ...A.styles,
4444
+ I`
4013
4445
  :host {
4014
4446
  display: block;
4015
4447
  width: 100%;
4016
4448
  max-width: 560px;
4449
+ min-width: 0;
4017
4450
  }
4018
4451
  .panel {
4452
+ min-width: 0;
4453
+ overflow: hidden;
4019
4454
  background: var(--authui-card);
4020
4455
  color: var(--authui-card-foreground);
4021
4456
  border: 1px solid var(--authui-border);
@@ -4036,6 +4471,22 @@ p.styles = [
4036
4471
  display: flex;
4037
4472
  align-items: center;
4038
4473
  gap: 12px;
4474
+ min-width: 0;
4475
+ flex: 1;
4476
+ }
4477
+ .identity .row-title {
4478
+ display: block;
4479
+ overflow: hidden;
4480
+ text-overflow: ellipsis;
4481
+ white-space: nowrap;
4482
+ }
4483
+ .identity .row-title .badge {
4484
+ display: inline-flex;
4485
+ vertical-align: middle;
4486
+ margin-inline-start: 6px;
4487
+ }
4488
+ .between > .btn {
4489
+ flex-shrink: 0;
4039
4490
  }
4040
4491
  .identity .avatar {
4041
4492
  width: 44px;
@@ -4086,102 +4537,117 @@ p.styles = [
4086
4537
  }
4087
4538
  `
4088
4539
  ];
4089
- g([
4090
- f({ type: Boolean })
4091
- ], p.prototype, "embedded", 2);
4092
- g([
4093
- f({ type: String })
4094
- ], p.prototype, "tab", 2);
4095
- g([
4540
+ f([
4541
+ m({ type: Boolean })
4542
+ ], u.prototype, "embedded", 2);
4543
+ f([
4544
+ m({ type: String })
4545
+ ], u.prototype, "tab", 2);
4546
+ f([
4547
+ d()
4548
+ ], u.prototype, "active", 2);
4549
+ f([
4550
+ d()
4551
+ ], u.prototype, "busy", 2);
4552
+ f([
4096
4553
  d()
4097
- ], p.prototype, "active", 2);
4098
- g([
4554
+ ], u.prototype, "notice", 2);
4555
+ f([
4099
4556
  d()
4100
- ], p.prototype, "busy", 2);
4101
- g([
4557
+ ], u.prototype, "errors", 2);
4558
+ f([
4102
4559
  d()
4103
- ], p.prototype, "notice", 2);
4104
- g([
4560
+ ], u.prototype, "nameInput", 2);
4561
+ f([
4105
4562
  d()
4106
- ], p.prototype, "errors", 2);
4107
- g([
4563
+ ], u.prototype, "emailInput", 2);
4564
+ f([
4108
4565
  d()
4109
- ], p.prototype, "nameInput", 2);
4110
- g([
4566
+ ], u.prototype, "emailPassword", 2);
4567
+ f([
4111
4568
  d()
4112
- ], p.prototype, "emailInput", 2);
4113
- g([
4569
+ ], u.prototype, "phoneInput", 2);
4570
+ f([
4114
4571
  d()
4115
- ], p.prototype, "emailPassword", 2);
4116
- g([
4572
+ ], u.prototype, "phonePassword", 2);
4573
+ f([
4117
4574
  d()
4118
- ], p.prototype, "phoneInput", 2);
4119
- g([
4575
+ ], u.prototype, "phoneCode", 2);
4576
+ f([
4120
4577
  d()
4121
- ], p.prototype, "phonePassword", 2);
4122
- g([
4578
+ ], u.prototype, "phoneCodeSent", 2);
4579
+ f([
4123
4580
  d()
4124
- ], p.prototype, "phoneCode", 2);
4125
- g([
4581
+ ], u.prototype, "guestName", 2);
4582
+ f([
4126
4583
  d()
4127
- ], p.prototype, "phoneCodeSent", 2);
4128
- g([
4584
+ ], u.prototype, "oldPassword", 2);
4585
+ f([
4129
4586
  d()
4130
- ], p.prototype, "guestName", 2);
4131
- g([
4587
+ ], u.prototype, "newPassword", 2);
4588
+ f([
4132
4589
  d()
4133
- ], p.prototype, "oldPassword", 2);
4134
- g([
4590
+ ], u.prototype, "newPasswordConfirm", 2);
4591
+ f([
4135
4592
  d()
4136
- ], p.prototype, "newPassword", 2);
4137
- g([
4593
+ ], u.prototype, "authenticator", 2);
4594
+ f([
4138
4595
  d()
4139
- ], p.prototype, "newPasswordConfirm", 2);
4140
- g([
4596
+ ], u.prototype, "authenticatorCode", 2);
4597
+ f([
4141
4598
  d()
4142
- ], p.prototype, "authenticator", 2);
4143
- g([
4599
+ ], u.prototype, "factors", 2);
4600
+ f([
4144
4601
  d()
4145
- ], p.prototype, "authenticatorCode", 2);
4146
- g([
4602
+ ], u.prototype, "recoveryCodes", 2);
4603
+ f([
4147
4604
  d()
4148
- ], p.prototype, "factors", 2);
4149
- g([
4605
+ ], u.prototype, "stepUp", 2);
4606
+ f([
4150
4607
  d()
4151
- ], p.prototype, "recoveryCodes", 2);
4152
- g([
4608
+ ], u.prototype, "stepUpCode", 2);
4609
+ f([
4153
4610
  d()
4154
- ], p.prototype, "stepUp", 2);
4155
- g([
4611
+ ], u.prototype, "copied", 2);
4612
+ f([
4156
4613
  d()
4157
- ], p.prototype, "stepUpCode", 2);
4158
- g([
4614
+ ], u.prototype, "sessions", 2);
4615
+ f([
4159
4616
  d()
4160
- ], p.prototype, "copied", 2);
4161
- g([
4617
+ ], u.prototype, "identities", 2);
4618
+ f([
4162
4619
  d()
4163
- ], p.prototype, "sessions", 2);
4164
- g([
4620
+ ], u.prototype, "logs", 2);
4621
+ f([
4165
4622
  d()
4166
- ], p.prototype, "identities", 2);
4167
- g([
4623
+ ], u.prototype, "logsSupported", 2);
4624
+ f([
4168
4625
  d()
4169
- ], p.prototype, "logs", 2);
4170
- g([
4626
+ ], u.prototype, "confirmDelete", 2);
4627
+ f([
4171
4628
  d()
4172
- ], p.prototype, "logsSupported", 2);
4173
- g([
4629
+ ], u.prototype, "confirmRegenerate", 2);
4630
+ f([
4174
4631
  d()
4175
- ], p.prototype, "confirmDelete", 2);
4176
- p = g([
4177
- I("authui-account")
4178
- ], p);
4179
- var _t = Object.defineProperty, Ft = Object.getOwnPropertyDescriptor, z = (e, t, i, r) => {
4180
- for (var a = r > 1 ? void 0 : r ? Ft(t, i) : t, h = e.length - 1, u; h >= 0; h--)
4181
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
4182
- return r && a && _t(t, i, a), a;
4632
+ ], u.prototype, "confirmRemoveAuthenticator", 2);
4633
+ f([
4634
+ d()
4635
+ ], u.prototype, "confirmSignOutAll", 2);
4636
+ f([
4637
+ d()
4638
+ ], u.prototype, "confirmDisconnectId", 2);
4639
+ f([
4640
+ d()
4641
+ ], u.prototype, "verifyEmailCooldownUntil", 2);
4642
+ u = f([
4643
+ O("authui-account")
4644
+ ], u);
4645
+ var Dt = Object.defineProperty, _t = Object.getOwnPropertyDescriptor, _ = (e, t, i, s) => {
4646
+ for (var a = s > 1 ? void 0 : s ? _t(t, i) : t, h = e.length - 1, p; h >= 0; h--)
4647
+ (p = e[h]) && (a = (s ? p(t, i, a) : p(a)) || a);
4648
+ return s && a && Dt(t, i, a), a;
4183
4649
  };
4184
- let U = class extends x {
4650
+ let M = class extends A {
4185
4651
  constructor() {
4186
4652
  super(...arguments), this.open = !1, this.view = "sign-in", this.closeOnSuccess = !0, this.handledPending = null, this.onOpenEvent = (e) => {
4187
4653
  const t = e.detail ?? {};
@@ -4202,29 +4668,38 @@ let U = class extends x {
4202
4668
  super.disconnectedCallback(), window.removeEventListener("authui:open", this.onOpenEvent), window.removeEventListener("authui:close", this.onCloseEvent);
4203
4669
  }
4204
4670
  show(e) {
4205
- e ? this.view = e : this.auth.status === "signed-in" && (this.view = "account"), this.open = !0;
4671
+ e === "account" && this.auth.status !== "signed-in" ? this.view = "sign-in" : e ? this.view = e : this.auth.status === "signed-in" ? this.view = "account" : this.view = "sign-in", this.open = !0;
4206
4672
  }
4207
4673
  hide() {
4208
4674
  this.open = !1;
4209
4675
  }
4210
4676
  updated(e) {
4211
- 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")) {
4677
+ if (e.has("open") && this.dialog && (this.open && !this.dialog.open && (this.dialog.showModal(), requestAnimationFrame(() => this.focusPrimary())), !this.open && this.dialog.open && this.dialog.close()), e.has("auth")) {
4212
4678
  const t = this.auth.pending;
4213
- 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);
4679
+ 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), this.open && this.view === "account" && this.auth.status !== "signed-in" && (this.view = "sign-in"), this.open && this.auth.status === "signed-out" && this.view === "account" && (this.view = "sign-in");
4214
4680
  }
4215
4681
  }
4682
+ focusPrimary() {
4683
+ const e = this.dialog;
4684
+ if (!e) return;
4685
+ const i = e.querySelector("authui-sign-in, authui-account")?.shadowRoot;
4686
+ (i?.querySelector(".alert[role=alert], .alert[role=status]") ?? i?.querySelector(
4687
+ "input:not([type=hidden]), button.choice, [role=tab]"
4688
+ ))?.focus?.();
4689
+ }
4216
4690
  render() {
4217
- const e = this.view === "account";
4218
- return s`
4691
+ const e = this.auth.status === "signed-in", t = this.view === "account" && e;
4692
+ return r`
4219
4693
  <dialog
4220
- class=${e ? "wide" : ""}
4221
- aria-labelledby="authui-title"
4694
+ class=${t ? "wide" : ""}
4695
+ aria-label=${t ? this.t("dialogAccount") : this.t("dialogSignIn")}
4222
4696
  @close=${() => this.open = !1}
4223
- @cancel=${(t) => {
4224
- t.preventDefault(), this.hide();
4697
+ @cancel=${(i) => {
4698
+ i.preventDefault(), this.hide();
4225
4699
  }}
4226
4700
  @click=${this.onBackdrop}
4227
4701
  @authui-open=${this.onInnerOpen}
4702
+ @authui-success=${this.onSuccess}
4228
4703
  >
4229
4704
  <div class="body">
4230
4705
  <button
@@ -4232,21 +4707,20 @@ let U = class extends x {
4232
4707
  @click=${this.hide}
4233
4708
  aria-label=${this.t("close")}
4234
4709
  >
4235
- ${c.x}
4710
+ ${o.x}
4236
4711
  </button>
4237
- ${this.open ? e ? s`<authui-account embedded></authui-account>` : s`<authui-sign-in
4712
+ ${this.open ? t ? r`<authui-account embedded></authui-account>` : r`<authui-sign-in
4238
4713
  embedded
4239
- .view=${this.view}
4240
- @authui-success=${this.onSuccess}
4241
- ></authui-sign-in>` : o}
4714
+ .view=${this.view === "account" ? "sign-in" : this.view}
4715
+ ></authui-sign-in>` : c}
4242
4716
  </div>
4243
4717
  </dialog>
4244
4718
  `;
4245
4719
  }
4246
4720
  };
4247
- U.styles = [
4248
- ...x.styles,
4249
- E`
4721
+ M.styles = [
4722
+ ...A.styles,
4723
+ I`
4250
4724
  :host {
4251
4725
  display: contents;
4252
4726
  }
@@ -4306,46 +4780,38 @@ U.styles = [
4306
4780
  }
4307
4781
  `
4308
4782
  ];
4309
- z([
4310
- f({ type: Boolean, reflect: !0 })
4311
- ], U.prototype, "open", 2);
4312
- z([
4313
- f({ type: String })
4314
- ], U.prototype, "view", 2);
4315
- z([
4316
- f({ type: Boolean, attribute: "close-on-success" })
4317
- ], U.prototype, "closeOnSuccess", 2);
4318
- z([
4783
+ _([
4784
+ m({ type: Boolean, reflect: !0 })
4785
+ ], M.prototype, "open", 2);
4786
+ _([
4787
+ m({ type: String })
4788
+ ], M.prototype, "view", 2);
4789
+ _([
4790
+ m({ type: Boolean, attribute: "close-on-success" })
4791
+ ], M.prototype, "closeOnSuccess", 2);
4792
+ _([
4319
4793
  d()
4320
- ], U.prototype, "handledPending", 2);
4321
- z([
4322
- rt("dialog")
4323
- ], U.prototype, "dialog", 2);
4324
- U = z([
4325
- I("authui-modal")
4326
- ], U);
4327
- function Y(e) {
4328
- typeof document > "u" || (document.querySelector("authui-modal") || document.body.appendChild(document.createElement("authui-modal")), queueMicrotask(() => {
4329
- window.dispatchEvent(new CustomEvent("authui:open", { detail: { view: e } }));
4330
- }));
4331
- }
4332
- function Nt() {
4333
- typeof window > "u" || window.dispatchEvent(new CustomEvent("authui:close"));
4334
- }
4335
- var zt = Object.defineProperty, Ot = Object.getOwnPropertyDescriptor, H = (e, t, i, r) => {
4336
- for (var a = r > 1 ? void 0 : r ? Ot(t, i) : t, h = e.length - 1, u; h >= 0; h--)
4337
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
4338
- return r && a && zt(t, i, a), a;
4794
+ ], M.prototype, "handledPending", 2);
4795
+ _([
4796
+ ct("dialog")
4797
+ ], M.prototype, "dialog", 2);
4798
+ M = _([
4799
+ O("authui-modal")
4800
+ ], M);
4801
+ var Rt = Object.defineProperty, zt = Object.getOwnPropertyDescriptor, W = (e, t, i, s) => {
4802
+ for (var a = s > 1 ? void 0 : s ? zt(t, i) : t, h = e.length - 1, p; h >= 0; h--)
4803
+ (p = e[h]) && (a = (s ? p(t, i, a) : p(a)) || a);
4804
+ return s && a && Rt(t, i, a), a;
4339
4805
  };
4340
- let F = class extends x {
4806
+ let D = class extends A {
4341
4807
  constructor() {
4342
4808
  super(...arguments), this.view = "sign-in", this.variant = "primary", this.size = "md";
4343
4809
  }
4344
4810
  render() {
4345
4811
  const e = this.size === "md" ? "" : `btn-${this.size}`;
4346
- return s`<button
4812
+ return r`<button
4347
4813
  class="btn btn-${this.variant} ${e}"
4348
- @click=${() => Y(this.view)}
4814
+ @click=${() => H(this.view)}
4349
4815
  part="button"
4350
4816
  >
4351
4817
  <slot
@@ -4354,9 +4820,9 @@ let F = class extends x {
4354
4820
  </button>`;
4355
4821
  }
4356
4822
  };
4357
- F.styles = [
4358
- ...x.styles,
4359
- E`
4823
+ D.styles = [
4824
+ ...A.styles,
4825
+ I`
4360
4826
  :host {
4361
4827
  display: inline-block;
4362
4828
  }
@@ -4365,47 +4831,68 @@ F.styles = [
4365
4831
  }
4366
4832
  `
4367
4833
  ];
4368
- H([
4369
- f({ type: String })
4370
- ], F.prototype, "view", 2);
4371
- H([
4372
- f({ type: String })
4373
- ], F.prototype, "variant", 2);
4374
- H([
4375
- f({ type: String })
4376
- ], F.prototype, "size", 2);
4377
- F = H([
4378
- I("authui-button")
4379
- ], F);
4380
- var Dt = Object.defineProperty, Rt = Object.getOwnPropertyDescriptor, X = (e, t, i, r) => {
4381
- for (var a = r > 1 ? void 0 : r ? Rt(t, i) : t, h = e.length - 1, u; h >= 0; h--)
4382
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
4383
- return r && a && Dt(t, i, a), a;
4834
+ W([
4835
+ m({ type: String })
4836
+ ], D.prototype, "view", 2);
4837
+ W([
4838
+ m({ type: String })
4839
+ ], D.prototype, "variant", 2);
4840
+ W([
4841
+ m({ type: String })
4842
+ ], D.prototype, "size", 2);
4843
+ D = W([
4844
+ O("authui-button")
4845
+ ], D);
4846
+ var Vt = Object.defineProperty, qt = Object.getOwnPropertyDescriptor, J = (e, t, i, s) => {
4847
+ for (var a = s > 1 ? void 0 : s ? qt(t, i) : t, h = e.length - 1, p; h >= 0; h--)
4848
+ (p = e[h]) && (a = (s ? p(t, i, a) : p(a)) || a);
4849
+ return s && a && Vt(t, i, a), a;
4384
4850
  };
4385
- let R = class extends x {
4851
+ let q = class extends A {
4386
4852
  constructor() {
4387
4853
  super(...arguments), this.src = "", this.menuOpen = !1, this.onDocumentClick = (e) => {
4388
4854
  e.composedPath().includes(this) || (this.menuOpen = !1);
4389
4855
  }, this.onKeydown = (e) => {
4390
- e.key === "Escape" && (this.menuOpen = !1);
4856
+ if (!this.menuOpen) {
4857
+ (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") && e.target === this.renderRoot?.querySelector(".trigger") && e.key === "ArrowDown" && (e.preventDefault(), this.menuOpen = !0, requestAnimationFrame(() => this.focusMenuItem(0)));
4858
+ return;
4859
+ }
4860
+ const t = [
4861
+ ...this.renderRoot?.querySelectorAll('[role="menuitem"]') ?? []
4862
+ ], i = t.findIndex((s) => s === this.shadowRoot?.activeElement);
4863
+ if (e.key === "Escape") {
4864
+ e.preventDefault(), this.menuOpen = !1, this.renderRoot?.querySelector(".trigger")?.focus();
4865
+ return;
4866
+ }
4867
+ e.key === "ArrowDown" ? (e.preventDefault(), this.focusMenuItem(i < 0 ? 0 : (i + 1) % t.length)) : e.key === "ArrowUp" ? (e.preventDefault(), this.focusMenuItem(
4868
+ i < 0 ? t.length - 1 : (i - 1 + t.length) % t.length
4869
+ )) : e.key === "Home" ? (e.preventDefault(), this.focusMenuItem(0)) : e.key === "End" && (e.preventDefault(), this.focusMenuItem(t.length - 1));
4391
4870
  };
4392
4871
  }
4393
4872
  connectedCallback() {
4394
- super.connectedCallback(), document.addEventListener("click", this.onDocumentClick, !0), document.addEventListener("keydown", this.onKeydown);
4873
+ super.connectedCallback(), document.addEventListener("click", this.onDocumentClick, !0), document.addEventListener("keydown", this.onKeydown), this.addEventListener("keydown", this.onKeydown);
4395
4874
  }
4396
4875
  disconnectedCallback() {
4397
- super.disconnectedCallback(), document.removeEventListener("click", this.onDocumentClick, !0), document.removeEventListener("keydown", this.onKeydown);
4876
+ super.disconnectedCallback(), document.removeEventListener("click", this.onDocumentClick, !0), document.removeEventListener("keydown", this.onKeydown), this.removeEventListener("keydown", this.onKeydown);
4877
+ }
4878
+ focusMenuItem(e) {
4879
+ [
4880
+ ...this.renderRoot?.querySelectorAll('[role="menuitem"]') ?? []
4881
+ ][e]?.focus();
4882
+ }
4883
+ updated(e) {
4884
+ e.has("menuOpen") && this.menuOpen && requestAnimationFrame(() => this.focusMenuItem(0));
4398
4885
  }
4399
4886
  render() {
4400
4887
  const { status: e, user: t } = this.auth;
4401
4888
  if (e === "loading")
4402
- return s`<span class="avatar"><span class="spinner"></span></span>`;
4889
+ return r`<span class="avatar"><span class="spinner"></span></span>`;
4403
4890
  if (e !== "signed-in" || !t)
4404
- return s`<button class="btn btn-primary btn-sm" @click=${() => Y("sign-in")}>
4891
+ return r`<button class="btn btn-primary btn-sm" @click=${() => H("sign-in")}>
4405
4892
  <slot>${this.t("signIn")}</slot>
4406
4893
  </button>`;
4407
4894
  const i = t.name || t.email || t.phone || this.t("guestAccount");
4408
- return s`
4895
+ return r`
4409
4896
  <button
4410
4897
  class="trigger"
4411
4898
  aria-haspopup="menu"
@@ -4414,22 +4901,22 @@ let R = class extends x {
4414
4901
  aria-label=${i}
4415
4902
  >
4416
4903
  <span class="avatar"
4417
- >${this.src ? s`<img src=${this.src} alt="" />` : i[0] ?? "?"}</span
4904
+ >${this.src ? r`<img src=${this.src} alt="" />` : Q(i)}</span
4418
4905
  >
4419
4906
  </button>
4420
- ${this.menuOpen ? s`<div class="menu" role="menu">
4907
+ ${this.menuOpen ? r`<div class="menu" role="menu">
4421
4908
  <div class="menu-header">
4422
- <span class="row-title">${i}</span>
4423
- ${t.email && t.name ? s`<span class="row-sub">${t.email}</span>` : o}
4909
+ <span class="row-title" title=${i}>${i}</span>
4910
+ ${t.email && t.name ? r`<span class="row-sub" title=${t.email}>${t.email}</span>` : c}
4424
4911
  </div>
4425
4912
  <button
4426
4913
  class="menu-item"
4427
4914
  role="menuitem"
4428
4915
  @click=${() => {
4429
- this.menuOpen = !1, Y("account");
4916
+ this.menuOpen = !1, H("account");
4430
4917
  }}
4431
4918
  >
4432
- ${c.settings} ${this.t("manageAccount")}
4919
+ ${o.settings} ${this.t("manageAccount")}
4433
4920
  </button>
4434
4921
  <button
4435
4922
  class="menu-item"
@@ -4438,15 +4925,15 @@ let R = class extends x {
4438
4925
  this.menuOpen = !1, n.signOut();
4439
4926
  }}
4440
4927
  >
4441
- ${c.logOut} ${this.t("signOut")}
4928
+ ${o.logOut} ${this.t("signOut")}
4442
4929
  </button>
4443
- </div>` : o}
4930
+ </div>` : c}
4444
4931
  `;
4445
4932
  }
4446
4933
  };
4447
- R.styles = [
4448
- ...x.styles,
4449
- E`
4934
+ q.styles = [
4935
+ ...A.styles,
4936
+ I`
4450
4937
  :host {
4451
4938
  display: inline-block;
4452
4939
  position: relative;
@@ -4473,6 +4960,7 @@ R.styles = [
4473
4960
  top: calc(100% + 6px);
4474
4961
  inset-inline-end: 0;
4475
4962
  min-width: 220px;
4963
+ max-width: min(320px, 90vw);
4476
4964
  background: var(--authui-popover);
4477
4965
  color: var(--authui-popover-foreground);
4478
4966
  border: 1px solid var(--authui-border);
@@ -4485,6 +4973,8 @@ R.styles = [
4485
4973
  gap: 2px;
4486
4974
  }
4487
4975
  .menu-header {
4976
+ min-width: 0;
4977
+ overflow: hidden;
4488
4978
  padding: 8px 10px 10px;
4489
4979
  display: flex;
4490
4980
  flex-direction: column;
@@ -4492,6 +4982,14 @@ R.styles = [
4492
4982
  border-bottom: 1px solid var(--authui-border);
4493
4983
  margin-bottom: 4px;
4494
4984
  }
4985
+ .menu .row-title,
4986
+ .menu .row-sub {
4987
+ display: block;
4988
+ overflow: hidden;
4989
+ text-overflow: ellipsis;
4990
+ white-space: nowrap;
4991
+ }
4992
+
4495
4993
  .menu-item {
4496
4994
  display: flex;
4497
4995
  align-items: center;
@@ -4524,32 +5022,32 @@ R.styles = [
4524
5022
  }
4525
5023
  `
4526
5024
  ];
4527
- X([
4528
- f({ type: String })
4529
- ], R.prototype, "src", 2);
4530
- X([
5025
+ J([
5026
+ m({ type: String })
5027
+ ], q.prototype, "src", 2);
5028
+ J([
4531
5029
  d()
4532
- ], R.prototype, "menuOpen", 2);
4533
- R = X([
4534
- I("authui-user-button")
4535
- ], R);
5030
+ ], q.prototype, "menuOpen", 2);
5031
+ q = J([
5032
+ O("authui-user-button")
5033
+ ], q);
4536
5034
  export {
4537
- mt as A,
5035
+ vt as A,
4538
5036
  v as E,
4539
- pt as P,
5037
+ mt as P,
4540
5038
  n as a,
4541
- p as b,
4542
- Nt as c,
4543
- F as d,
5039
+ u as b,
5040
+ Ht as c,
5041
+ D as d,
4544
5042
  b as e,
4545
- x as f,
4546
- U as g,
4547
- D as h,
5043
+ A as f,
5044
+ M as g,
5045
+ V as h,
4548
5046
  $ as i,
4549
- R as j,
4550
- lt as k,
4551
- at as l,
4552
- Y as o,
4553
- O as p,
4554
- T as t
5047
+ q as j,
5048
+ ht as k,
5049
+ Z as l,
5050
+ H as o,
5051
+ R as p,
5052
+ B as t
4555
5053
  };