@getauthui/core 0.1.2 → 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 _, query as rt } from "lit/decorators.js";
2
- import { css as I, LitElement as X, nothing as o, html as s, svg as l } from "lit";
3
- import { Client as ot, Account as ct, ID as V, Avatars as lt } from "appwrite";
4
- const dt = {
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 dt = {
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 dt = {
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 dt = {
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 dt = {
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 dt = {
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 dt = {
123
156
  guestAccountDescription: "Add an email and password to keep your data.",
124
157
  preview: "Preview"
125
158
  };
126
- function ht(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 ut = {
165
+ const pt = {
133
166
  amazon: "Amazon",
134
167
  apple: "Apple",
135
168
  appwrite: "Appwrite",
@@ -180,10 +213,10 @@ const ut = {
180
213
  zoho: "Zoho",
181
214
  zoom: "Zoom"
182
215
  };
183
- function D(e) {
184
- return ut[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 q = (e, t, i = 401) => Object.assign(new Error(t), { type: e, code: i }), P = () => (/* @__PURE__ */ new Date()).toISOString(), M = (e) => new Date(Date.now() - e * 6e4).toISOString(), T = [
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 q = (e, t, i = 401) => Object.assign(new Error(t), { type: e, code: i }),
196
229
  "juniper",
197
230
  "kite",
198
231
  "lumen"
199
- ], Z = () => `${T[Math.floor(Math.random() * T.length)]}-${T[Math.floor(Math.random() * T.length)]}`, F = () => Math.random().toString(36).slice(2, 12), J = () => Array.from({ length: 2 }, () => Math.random().toString(36).slice(2, 7)).join("-"), pt = {
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 ft {
205
- constructor(t = pt) {
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 ft {
210
243
  const i = t.anonymous ?? !1;
211
244
  return this.user = {
212
245
  $id: "preview-user",
213
- $createdAt: M(1440 * 30),
246
+ $createdAt: U(1440 * 30),
214
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,
@@ -267,7 +300,7 @@ class ft {
267
300
  {
268
301
  ...i,
269
302
  $id: F(),
270
- $createdAt: M(300),
303
+ $createdAt: U(300),
271
304
  provider: t,
272
305
  ip: "198.51.100.7",
273
306
  osCode: "IOS",
@@ -284,7 +317,7 @@ class ft {
284
317
  {
285
318
  ...i,
286
319
  $id: F(),
287
- $createdAt: M(1440 * 3),
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 ft {
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",
@@ -320,7 +353,7 @@ class ft {
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 ft {
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 ft {
338
371
  }
339
372
  requireUser() {
340
373
  if (!this.user)
341
- throw q("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 q(
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 ft {
348
381
  }
349
382
  requireRecentChallenge() {
350
383
  if (Date.now() - this.lastChallenge > 30 * 6e4)
351
- throw q(
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 ft {
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 ft {
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) {
@@ -389,7 +422,7 @@ class ft {
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) {
@@ -399,7 +432,7 @@ class ft {
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) {
@@ -467,7 +500,10 @@ class ft {
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(), {}));
@@ -521,33 +557,33 @@ class ft {
521
557
  async createMFARecoveryCodes() {
522
558
  return this.delay(() => {
523
559
  if (this.recoveryCodes.length > 0)
524
- throw q("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 mt(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
578
  for (const x of e) t = (t ^ x.charCodeAt(0)) * 16777619;
543
- const r = 25;
579
+ const s = 25;
544
580
  let a = "";
545
- const h = (x, S) => `<rect x="${x}" y="${S}" width="7" height="7"/><rect x="${x + 1}" y="${S + 1}" width="5" height="5" fill="#fff"/><rect x="${x + 2}" y="${S + 2}" width="3" height="3"/>`;
546
- for (let x = 0; x < r; x++)
547
- for (let S = 0; S < r; S++)
548
- !(S < 8 && x < 8 || S >= r - 8 && x < 8 || S < 8 && x >= r - 8) && i() < 0.45 && (a += `<rect x="${S}" y="${x}" 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 N(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 B(e, t) {
596
- return N(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 = N(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 k(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 k(e, t, i) {
644
686
  new Error(`Appwrite SDK is missing ${t[0]}(). Update the appwrite package.`)
645
687
  );
646
688
  }
647
- const G = "authui", tt = ["userId", "secret", "expire", "project", "error", G], 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 gt {
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 ot().setEndpoint(t.endpoint).setProject(t.project), this.preview = t.preview ? new ft() : null, this.account = this.preview ? this.preview : new ct(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 gt {
686
728
  return this.account;
687
729
  }
688
730
  getStrings() {
689
- return { ...dt, ...this.config?.strings ?? {} };
731
+ return { ...ht, ...this.config?.strings ?? {} };
690
732
  }
691
733
  getState() {
692
734
  return { ...this.state };
@@ -696,13 +738,13 @@ class gt {
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 gt {
712
754
  this.state = { ...this.state, ...t }, this.emit("change", this.getState());
713
755
  }
714
756
  fail(t) {
715
- const i = N(t);
757
+ const i = B(t);
716
758
  throw this.emit("error", i), t;
717
759
  }
718
760
  acct() {
@@ -732,41 +774,76 @@ class gt {
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 (B(i, v.moreFactorsRequired)) {
736
- let r = null;
777
+ if (z(i, v.moreFactorsRequired)) {
778
+ let s = null;
737
779
  try {
738
- r = await k(
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(V.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 gt {
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 gt {
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
  }
@@ -809,7 +886,7 @@ class gt {
809
886
  async sendMagicUrl(t) {
810
887
  try {
811
888
  return await this.acct().createMagicURLToken(
812
- V.unique(),
889
+ L.unique(),
813
890
  t.trim(),
814
891
  this.redirectUrl("magic-url"),
815
892
  this.config?.securityPhrase ?? !0
@@ -821,7 +898,7 @@ class gt {
821
898
  async sendEmailOtp(t) {
822
899
  try {
823
900
  return await this.acct().createEmailToken(
824
- V.unique(),
901
+ L.unique(),
825
902
  t.trim(),
826
903
  this.config?.securityPhrase ?? !0
827
904
  );
@@ -831,7 +908,7 @@ class gt {
831
908
  }
832
909
  async sendPhoneOtp(t) {
833
910
  try {
834
- return await this.acct().createPhoneToken(V.unique(), t.replace(/[\s()-]/g, ""));
911
+ return await this.acct().createPhoneToken(L.unique(), t.replace(/[\s()-]/g, ""));
835
912
  } catch (i) {
836
913
  return this.fail(i);
837
914
  }
@@ -840,15 +917,15 @@ class gt {
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 k(
928
+ return await S(
852
929
  this.acct(),
853
930
  ["createMFAChallenge", "createMfaChallenge"],
854
931
  [t]
@@ -858,9 +935,9 @@ class gt {
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 k(
940
+ await S(
864
941
  this.acct(),
865
942
  ["updateMFAChallenge", "updateMfaChallenge"],
866
943
  [t, i.trim()]
@@ -868,11 +945,11 @@ class gt {
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 k(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 gt {
887
964
  }
888
965
  async addAuthenticator() {
889
966
  try {
890
- return await k(
967
+ return await S(
891
968
  this.acct(),
892
969
  ["createMFAAuthenticator", "createMfaAuthenticator"],
893
970
  ["totp"]
@@ -898,7 +975,7 @@ class gt {
898
975
  }
899
976
  async verifyAuthenticator(t) {
900
977
  try {
901
- await k(
978
+ await S(
902
979
  this.acct(),
903
980
  ["updateMFAAuthenticator", "updateMfaAuthenticator"],
904
981
  ["totp", t.trim()]
@@ -911,7 +988,7 @@ class gt {
911
988
  /** Requires a recent MFA challenge (server rejects with user_challenge_required otherwise). */
912
989
  async removeAuthenticator() {
913
990
  try {
914
- await k(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 gt {
919
996
  }
920
997
  async createRecoveryCodes() {
921
998
  try {
922
- return (await k(
999
+ return (await S(
923
1000
  this.acct(),
924
1001
  ["createMFARecoveryCodes", "createMfaRecoveryCodes"],
925
1002
  []
@@ -931,7 +1008,7 @@ class gt {
931
1008
  /** Requires a recent MFA challenge. */
932
1009
  async regenerateRecoveryCodes() {
933
1010
  try {
934
- return (await k(
1011
+ return (await S(
935
1012
  this.acct(),
936
1013
  ["updateMFARecoveryCodes", "updateMfaRecoveryCodes"],
937
1014
  []
@@ -943,7 +1020,7 @@ class gt {
943
1020
  /** Requires a recent MFA challenge. */
944
1021
  async getRecoveryCodes() {
945
1022
  try {
946
- return (await k(
1023
+ return (await S(
947
1024
  this.acct(),
948
1025
  ["getMFARecoveryCodes", "getMfaRecoveryCodes"],
949
1026
  []
@@ -960,9 +1037,9 @@ class gt {
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 gt {
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 gt {
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 gt {
1057
1142
  }
1058
1143
  async sendEmailVerification() {
1059
1144
  try {
1060
- await k(
1145
+ await S(
1061
1146
  this.acct(),
1062
1147
  ["createEmailVerification", "createVerification"],
1063
1148
  [this.redirectUrl("verify-email")]
@@ -1078,8 +1163,8 @@ class gt {
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 gt {
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(G, 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 gt {
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(G);
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 k(
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 = N(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 gt();
1159
- class vt {
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 vt {
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 vt(), 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
- }, bt = I`
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 vt(), 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
- `, yt = I`
1366
+ `, wt = I`
1273
1367
  *,
1274
1368
  *::before,
1275
1369
  *::after {
@@ -1284,6 +1378,8 @@ const it = new vt(), 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 vt(), 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 vt(), 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 vt(), 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 vt(), 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 vt(), 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 vt(), 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,25 +2117,25 @@ const it = new vt(), st = {
2012
2117
  }
2013
2118
  }
2014
2119
  `;
2015
- var wt = Object.defineProperty, $t = (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 && wt(t, i, a), a;
2019
- }, U;
2020
- const nt = (U = class extends X {
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
2127
  super(...arguments), this.auth = n.getState(), this.unsubscribeStore = null, this.unsubscribeTheme = null, this.stopKeys = (t) => t.stopPropagation();
2023
2128
  }
2024
2129
  connectedCallback() {
2025
2130
  super.connectedCallback();
2026
- for (const t of U.KEY_EVENTS) this.addEventListener(t, this.stopKeys);
2131
+ for (const t of E.KEY_EVENTS) this.addEventListener(t, this.stopKeys);
2027
2132
  this.auth = n.getState(), this.unsubscribeStore = n.on("change", (t) => {
2028
2133
  this.auth = t, this.applyBranding();
2029
- }), this.unsubscribeTheme = it.subscribe(() => this.applyBranding()), this.applyBranding();
2134
+ }), this.unsubscribeTheme = nt.subscribe(() => this.applyBranding()), this.applyBranding();
2030
2135
  }
2031
2136
  disconnectedCallback() {
2032
2137
  super.disconnectedCallback();
2033
- for (const t of U.KEY_EVENTS) this.removeEventListener(t, this.stopKeys);
2138
+ for (const t of E.KEY_EVENTS) this.removeEventListener(t, this.stopKeys);
2034
2139
  this.unsubscribeStore?.(), this.unsubscribeTheme?.(), this.unsubscribeStore = null, this.unsubscribeTheme = null;
2035
2140
  }
2036
2141
  get strings() {
@@ -2038,7 +2143,7 @@ const nt = (U = class extends X {
2038
2143
  }
2039
2144
  /** Translate a string key with optional `{placeholders}`. */
2040
2145
  t(t, i) {
2041
- return ht(this.strings[t], i);
2146
+ return ut(this.strings[t], i);
2042
2147
  }
2043
2148
  get config() {
2044
2149
  return n.getConfig();
@@ -2048,25 +2153,25 @@ const nt = (U = class extends X {
2048
2153
  }
2049
2154
  /** Push theme and branding from config onto the host element. */
2050
2155
  applyBranding() {
2051
- const t = this.config?.branding, i = it.isDark(t?.theme ?? "auto");
2156
+ const t = this.config?.branding, i = nt.isDark(t?.theme ?? "auto");
2052
2157
  this.setAttribute("data-theme", i ? "dark" : "light"), t?.primary && (this.style.setProperty("--authui-primary", t.primary), this.style.setProperty(
2053
2158
  "--authui-primary-foreground",
2054
2159
  t.primaryForeground ?? "#ffffff"
2055
- )), 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]);
2056
2161
  }
2057
2162
  /** Emit a composed custom event from this element. */
2058
2163
  fire(t, i) {
2059
2164
  this.dispatchEvent(new CustomEvent(t, { detail: i, bubbles: !0, composed: !0 }));
2060
2165
  }
2061
- }, U.styles = [bt, yt], U.KEY_EVENTS = ["keydown", "keyup", "keypress"], U);
2062
- $t([
2166
+ }, E.styles = [yt, wt], E.KEY_EVENTS = ["keydown", "keyup", "keypress"], E);
2167
+ xt([
2063
2168
  d()
2064
- ], nt.prototype, "auth");
2065
- let A = nt;
2066
- var xt = Object.defineProperty, kt = Object.getOwnPropertyDescriptor, y = (e, t, i, r) => {
2067
- for (var a = r > 1 ? void 0 : r ? kt(t, i) : t, h = e.length - 1, u; h >= 0; h--)
2068
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
2069
- return r && a && xt(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;
2070
2175
  };
2071
2176
  let b = class extends X {
2072
2177
  constructor() {
@@ -2084,10 +2189,10 @@ let b = class extends X {
2084
2189
  t && JSON.stringify(t) === JSON.stringify(e) || n.configure(e);
2085
2190
  }
2086
2191
  toConfig() {
2087
- const e = { oauth: [] };
2088
- for (const t of this.methods.split(/[\s,]+/).filter(Boolean))
2089
- 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);
2090
- 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, {
2091
2196
  endpoint: this.endpoint,
2092
2197
  project: this.project,
2093
2198
  redirectUrl: this.redirectUrl || void 0,
@@ -2119,76 +2224,76 @@ b.styles = I`
2119
2224
  }
2120
2225
  `;
2121
2226
  y([
2122
- f({ type: String })
2227
+ m({ type: String })
2123
2228
  ], b.prototype, "endpoint", 2);
2124
2229
  y([
2125
- f({ type: String })
2230
+ m({ type: String })
2126
2231
  ], b.prototype, "project", 2);
2127
2232
  y([
2128
- f({ type: String, attribute: "redirect-url" })
2233
+ m({ type: String, attribute: "redirect-url" })
2129
2234
  ], b.prototype, "redirectUrl", 2);
2130
2235
  y([
2131
- f({ type: String, attribute: "success-url" })
2236
+ m({ type: String, attribute: "success-url" })
2132
2237
  ], b.prototype, "successUrl", 2);
2133
2238
  y([
2134
- f({ type: String })
2239
+ m({ type: String })
2135
2240
  ], b.prototype, "methods", 2);
2136
2241
  y([
2137
- f({ type: String, attribute: "sign-up" })
2242
+ m({ type: String, attribute: "sign-up" })
2138
2243
  ], b.prototype, "signUp", 2);
2139
2244
  y([
2140
- f({ type: String, attribute: "require-name" })
2245
+ m({ type: String, attribute: "require-name" })
2141
2246
  ], b.prototype, "requireName", 2);
2142
2247
  y([
2143
- f({ type: String })
2248
+ m({ type: String })
2144
2249
  ], b.prototype, "mfa", 2);
2145
2250
  y([
2146
- f({ type: String, attribute: "security-phrase" })
2251
+ m({ type: String, attribute: "security-phrase" })
2147
2252
  ], b.prototype, "securityPhrase", 2);
2148
2253
  y([
2149
- f({ type: String })
2254
+ m({ type: String })
2150
2255
  ], b.prototype, "name", 2);
2151
2256
  y([
2152
- f({ type: String })
2257
+ m({ type: String })
2153
2258
  ], b.prototype, "logo", 2);
2154
2259
  y([
2155
- f({ type: String })
2260
+ m({ type: String })
2156
2261
  ], b.prototype, "theme", 2);
2157
2262
  y([
2158
- f({ type: String })
2263
+ m({ type: String })
2159
2264
  ], b.prototype, "radius", 2);
2160
2265
  y([
2161
- f({ type: String })
2266
+ m({ type: String })
2162
2267
  ], b.prototype, "primary", 2);
2163
2268
  y([
2164
- f({ type: String, attribute: "primary-foreground" })
2269
+ m({ type: String, attribute: "primary-foreground" })
2165
2270
  ], b.prototype, "primaryForeground", 2);
2166
2271
  y([
2167
- f({ type: String, attribute: "terms-url" })
2272
+ m({ type: String, attribute: "terms-url" })
2168
2273
  ], b.prototype, "termsUrl", 2);
2169
2274
  y([
2170
- f({ type: String, attribute: "privacy-url" })
2275
+ m({ type: String, attribute: "privacy-url" })
2171
2276
  ], b.prototype, "privacyUrl", 2);
2172
2277
  y([
2173
- f({ type: String })
2278
+ m({ type: String })
2174
2279
  ], b.prototype, "preview", 2);
2175
2280
  b = y([
2176
- _("authui-config")
2281
+ O("authui-config")
2177
2282
  ], b);
2178
- var Ct = Object.defineProperty, Pt = Object.getOwnPropertyDescriptor, H = (e, t, i, r) => {
2179
- for (var a = r > 1 ? void 0 : r ? Pt(t, i) : t, h = e.length - 1, u; h >= 0; h--)
2180
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
2181
- return r && a && Ct(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;
2182
2287
  };
2183
2288
  if (typeof document < "u" && !document.getElementById("authui-fouc")) {
2184
2289
  const e = document.createElement("style");
2185
2290
  e.id = "authui-fouc", e.textContent = "authui-show:not([ready]){display:none}", document.head.appendChild(e);
2186
2291
  }
2187
- const St = ["loading", "signed-out", "signed-in", "mfa-required"];
2188
- function W(e) {
2189
- return e ? e.split(/[\s,]+/).map((t) => t.trim()).filter((t) => St.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)) : [];
2190
2295
  }
2191
- let L = class extends X {
2296
+ let V = class extends X {
2192
2297
  constructor() {
2193
2298
  super(...arguments), this.when = "", this.unless = "", this.status = n.getState().status, this.unsubscribe = null;
2194
2299
  }
@@ -2200,35 +2305,38 @@ let L = class extends X {
2200
2305
  }
2201
2306
  /** Whether the current status satisfies `when` and `unless`. */
2202
2307
  get visible() {
2203
- const e = W(this.when), t = W(this.unless);
2308
+ const e = G(this.when), t = G(this.unless);
2204
2309
  return !(this.status === "loading" && !e.includes("loading") || e.length > 0 && !e.includes(this.status) || t.includes(this.status));
2205
2310
  }
2206
2311
  updated() {
2207
- (this.status !== "loading" || W(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");
2208
2313
  }
2209
2314
  render() {
2210
- return this.visible ? s`<slot></slot>` : o;
2315
+ return this.visible ? r`<slot></slot>` : c;
2211
2316
  }
2212
2317
  };
2213
- H([
2214
- f({ type: String })
2215
- ], L.prototype, "when", 2);
2216
- H([
2217
- f({ type: String })
2218
- ], L.prototype, "unless", 2);
2219
- H([
2318
+ j([
2319
+ m({ type: String })
2320
+ ], V.prototype, "when", 2);
2321
+ j([
2322
+ m({ type: String })
2323
+ ], V.prototype, "unless", 2);
2324
+ j([
2220
2325
  d()
2221
- ], L.prototype, "status", 2);
2222
- L = H([
2223
- _("authui-show")
2224
- ], L);
2225
- const At = I`
2326
+ ], V.prototype, "status", 2);
2327
+ V = j([
2328
+ O("authui-show")
2329
+ ], V);
2330
+ const Ut = I`
2226
2331
  :host {
2227
2332
  display: block;
2228
2333
  width: 100%;
2229
2334
  max-width: 420px;
2335
+ min-width: 0;
2230
2336
  }
2231
2337
  .panel {
2338
+ min-width: 0;
2339
+ overflow: hidden;
2232
2340
  background: var(--authui-card);
2233
2341
  color: var(--authui-card-foreground);
2234
2342
  border: 1px solid var(--authui-border);
@@ -2258,6 +2366,9 @@ const At = I`
2258
2366
  align-self: center;
2259
2367
  margin-bottom: 4px;
2260
2368
  }
2369
+ .alert:has(.dismiss) {
2370
+ padding-inline-end: 36px;
2371
+ }
2261
2372
  .alert .dismiss {
2262
2373
  position: absolute;
2263
2374
  top: 4px;
@@ -2270,7 +2381,7 @@ const At = I`
2270
2381
  height: 14px;
2271
2382
  margin: 0;
2272
2383
  }
2273
- `, m = (e) => s`<svg
2384
+ `, g = (e) => r`<svg
2274
2385
  xmlns="http://www.w3.org/2000/svg"
2275
2386
  viewBox="0 0 24 24"
2276
2387
  fill="none"
@@ -2281,86 +2392,86 @@ const At = I`
2281
2392
  aria-hidden="true"
2282
2393
  >
2283
2394
  ${e}
2284
- </svg>`, c = {
2285
- mail: m(
2395
+ </svg>`, o = {
2396
+ mail: g(
2286
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"/>`
2287
2398
  ),
2288
- phone: m(
2399
+ phone: g(
2289
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"/>`
2290
2401
  ),
2291
- user: m(
2402
+ user: g(
2292
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"/>`
2293
2404
  ),
2294
- userX: m(
2405
+ userX: g(
2295
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"/>`
2296
2407
  ),
2297
- lock: m(
2408
+ lock: g(
2298
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"/>`
2299
2410
  ),
2300
- key: m(
2411
+ key: g(
2301
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"/>`
2302
2413
  ),
2303
- shield: m(
2414
+ shield: g(
2304
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"/>`
2305
2416
  ),
2306
- shieldCheck: m(
2417
+ shieldCheck: g(
2307
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"/>`
2308
2419
  ),
2309
- smartphone: m(
2420
+ smartphone: g(
2310
2421
  l`<rect width="14" height="20" x="5" y="2" rx="2" ry="2"/><path d="M12 18h.01"/>`
2311
2422
  ),
2312
- monitor: m(
2423
+ monitor: g(
2313
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"/>`
2314
2425
  ),
2315
- globe: m(
2426
+ globe: g(
2316
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"/>`
2317
2428
  ),
2318
- logOut: m(
2429
+ logOut: g(
2319
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"/>`
2320
2431
  ),
2321
- settings: m(
2432
+ settings: g(
2322
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"/>`
2323
2434
  ),
2324
- x: m(l`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`),
2325
- check: m(l`<path d="M20 6 9 17l-5-5"/>`),
2326
- 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(
2327
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"/>`
2328
2439
  ),
2329
- eye: m(
2440
+ eye: g(
2330
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"/>`
2331
2442
  ),
2332
- eyeOff: m(
2443
+ eyeOff: g(
2333
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"/>`
2334
2445
  ),
2335
- arrowLeft: m(l`<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>`),
2336
- alert: m(
2446
+ arrowLeft: g(l`<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>`),
2447
+ alert: g(
2337
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"/>`
2338
2449
  ),
2339
- info: m(l`<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>`),
2340
- checkCircle: m(l`<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>`),
2341
- 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(
2342
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"/>`
2343
2454
  ),
2344
- activity: m(
2455
+ activity: g(
2345
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"/>`
2346
2457
  ),
2347
- trash: m(
2458
+ trash: g(
2348
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"/>`
2349
2460
  ),
2350
- sparkles: m(
2461
+ sparkles: g(
2351
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"/>`
2352
2463
  ),
2353
- refresh: m(
2464
+ refresh: g(
2354
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"/>`
2355
2466
  ),
2356
- chevronDown: m(l`<path d="m6 9 6 6 6-6"/>`),
2357
- ghost: m(
2467
+ chevronDown: g(l`<path d="m6 9 6 6 6-6"/>`),
2468
+ ghost: g(
2358
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"/>`
2359
2470
  ),
2360
- qr: m(
2471
+ qr: g(
2361
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"/>`
2362
2473
  )
2363
- }, w = (e, t = "0 0 24 24") => s`<svg xmlns="http://www.w3.org/2000/svg" viewBox=${t} aria-hidden="true">${e}</svg>`, Mt = {
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 = {
2364
2475
  google: w(
2365
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"/>`
2366
2477
  ),
@@ -2416,22 +2527,34 @@ const At = I`
2416
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"/>`
2417
2528
  )
2418
2529
  };
2419
- function K(e) {
2420
- return Mt[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;
2421
2536
  }
2422
- var Ut = Object.defineProperty, Et = Object.getOwnPropertyDescriptor, C = (e, t, i, r) => {
2423
- for (var a = r > 1 ? void 0 : r ? Et(t, i) : t, h = e.length - 1, u; h >= 0; h--)
2424
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
2425
- return r && a && Ut(t, i, a), a;
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
+ }));
2541
+ }
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;
2426
2549
  };
2427
2550
  let $ = class extends A {
2428
2551
  constructor() {
2429
- 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) => {
2430
- 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 () => {
2431
2554
  await n.signInWithEmailPassword(this.email, this.password), this.password = "", this.fire("authui-success", { method: "email-password" });
2432
2555
  });
2433
2556
  }, this.onSignUp = (e) => {
2434
- e.preventDefault(), this.run(async () => {
2557
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2435
2558
  await n.signUp(this.email, this.password, this.name), this.password = "", this.fire("authui-success", { method: "sign-up" });
2436
2559
  });
2437
2560
  }, this.onGuest = () => {
@@ -2447,20 +2570,21 @@ let $ = class extends A {
2447
2570
  await new Promise((t) => setTimeout(t, 4e3));
2448
2571
  });
2449
2572
  }, this.onForgot = (e) => {
2450
- e.preventDefault(), this.run(async () => {
2573
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2451
2574
  await n.sendPasswordRecovery(this.email), this.notice = { tone: "success", message: this.t("resetLinkSent", { email: this.email }) };
2452
2575
  });
2453
2576
  }, this.onReset = (e) => {
2454
- if (e.preventDefault(), this.password !== this.passwordConfirm) {
2577
+ if (e.preventDefault(), !this.requireValid(e)) return;
2578
+ if (this.password !== this.passwordConfirm) {
2455
2579
  this.error = this.t("errorPasswordMismatch");
2456
2580
  return;
2457
2581
  }
2458
2582
  const t = this.recovery;
2459
2583
  t && this.run(async () => {
2460
- 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");
2461
2585
  });
2462
2586
  }, this.onMagicUrl = (e) => {
2463
- e.preventDefault(), this.run(async () => {
2587
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2464
2588
  const t = await n.sendMagicUrl(this.email);
2465
2589
  this.token = {
2466
2590
  userId: t.userId,
@@ -2470,7 +2594,7 @@ let $ = class extends A {
2470
2594
  };
2471
2595
  });
2472
2596
  }, this.onEmailOtp = (e) => {
2473
- e.preventDefault(), this.run(async () => {
2597
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2474
2598
  const t = await n.sendEmailOtp(this.email);
2475
2599
  this.token = {
2476
2600
  userId: t.userId,
@@ -2480,15 +2604,15 @@ let $ = class extends A {
2480
2604
  }, this.code = "";
2481
2605
  });
2482
2606
  }, this.onPhoneOtp = (e) => {
2483
- e.preventDefault(), this.run(async () => {
2607
+ e.preventDefault(), this.requireValid(e) && this.run(async () => {
2484
2608
  const t = await n.sendPhoneOtp(this.phone);
2485
2609
  this.token = { userId: t.userId, kind: "phone", target: this.phone }, this.code = "";
2486
2610
  });
2487
2611
  }, this.onVerifyCode = (e) => {
2488
- e.preventDefault();
2612
+ if (e.preventDefault(), !this.requireValid(e)) return;
2489
2613
  const t = this.token;
2490
2614
  t && this.run(async () => {
2491
- 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 });
2492
2616
  }, "code");
2493
2617
  }, this.onChooseFactor = (e) => {
2494
2618
  this.run(async () => {
@@ -2496,17 +2620,17 @@ let $ = class extends A {
2496
2620
  this.challenge = { id: t.$id, factor: e }, this.code = "";
2497
2621
  });
2498
2622
  }, this.onVerifyFactor = (e) => {
2499
- e.preventDefault();
2623
+ if (e.preventDefault(), !this.requireValid(e)) return;
2500
2624
  const t = this.challenge;
2501
2625
  t && this.run(async () => {
2502
- 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" });
2503
2627
  }, "code");
2504
2628
  }, this.onCancelMfa = () => {
2505
2629
  this.run(async () => {
2506
2630
  try {
2507
2631
  await n.signOut();
2508
2632
  } catch (e) {
2509
- if (!B(e, v.sessionNotFound)) throw e;
2633
+ if (!z(e, v.sessionNotFound)) throw e;
2510
2634
  }
2511
2635
  this.go("sign-in");
2512
2636
  });
@@ -2521,19 +2645,24 @@ let $ = class extends A {
2521
2645
  e.has("view") && e.get("view") !== void 0 && this.go(this.view), e.has("auth") && this.syncFromStore();
2522
2646
  }
2523
2647
  updated(e) {
2524
- e.has("step") && requestAnimationFrame(() => this.firstInput?.focus());
2648
+ e.has("step") && (this.focusOnStep || this.embedded) && (this.focusOnStep = !1, requestAnimationFrame(() => this.firstInput?.focus()));
2525
2649
  }
2526
2650
  /** React to store transitions: MFA pending, redirect results, sign in. */
2527
2651
  syncFromStore() {
2528
2652
  const { status: e, pending: t } = this.auth;
2529
- 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 = {
2530
2656
  tone: t.tone === "error" ? "error" : t.tone,
2531
2657
  message: t.message
2532
- }, n.setPending(null));
2658
+ });
2533
2659
  }
2534
2660
  /** Navigate between screens and reset transient state. */
2661
+ dismissNotice() {
2662
+ this.notice = null, this.auth.pending?.type === "notice" && n.setPending(null);
2663
+ }
2535
2664
  go(e) {
2536
- 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 });
2537
2666
  }
2538
2667
  // ───────────────────────────── actions ─────────────────────────────
2539
2668
  async run(e, t = "link") {
@@ -2542,12 +2671,17 @@ let $ = class extends A {
2542
2671
  try {
2543
2672
  await e();
2544
2673
  } catch (i) {
2545
- this.error = at(i, this.strings, t);
2674
+ this.error = Z(i, this.strings, t);
2546
2675
  } finally {
2547
2676
  this.busy = !1;
2548
2677
  }
2549
2678
  }
2550
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
+ }
2551
2685
  bind(e) {
2552
2686
  return (t) => {
2553
2687
  this[e] = t.target.value;
@@ -2556,81 +2690,91 @@ let $ = class extends A {
2556
2690
  // ───────────────────────────── render ─────────────────────────────
2557
2691
  render() {
2558
2692
  const e = this.renderStep();
2559
- return s`
2693
+ return r`
2560
2694
  <div class="panel ${this.embedded ? "embedded" : ""}" part="panel">
2561
2695
  ${this.renderHeader()}
2562
- ${this.notice ? s`<div class="alert alert-${this.notice.tone}" role="status">
2563
- ${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}
2564
2698
  <div class="alert-body">${this.notice.message}</div>
2565
2699
  <button
2566
2700
  class="btn btn-ghost btn-icon dismiss"
2567
- @click=${() => this.notice = null}
2701
+ @click=${() => this.dismissNotice()}
2568
2702
  aria-label=${this.t("close")}
2569
2703
  >
2570
- ${c.x}
2704
+ ${o.x}
2571
2705
  </button>
2572
- </div>` : o}
2706
+ </div>` : c}
2573
2707
  ${e}
2574
2708
  </div>
2575
2709
  `;
2576
2710
  }
2577
2711
  renderHeader() {
2578
2712
  const e = this.config?.branding?.logo, t = this.productName;
2579
- let i = "", r = "";
2580
- switch (this.step) {
2581
- case "sign-in":
2582
- i = this.auth.status === "signed-in" ? this.t("signedInAs") : t ? this.t("signInTitle", { name: t }) : this.t("welcomeBack");
2583
- break;
2584
- case "sign-up":
2585
- i = t ? this.t("signUpTitle", { name: t }) : this.t("createAccount");
2586
- break;
2587
- case "forgot-password":
2588
- case "reset-password":
2589
- i = this.t("resetPassword");
2590
- break;
2591
- case "magic-url":
2592
- case "email-otp":
2593
- i = this.t("continueWithEmail");
2594
- break;
2595
- case "phone":
2596
- i = this.t("continueWithPhone");
2597
- break;
2598
- case "mfa":
2599
- i = this.t("mfaTitle"), r = this.t("mfaDescription");
2600
- break;
2601
- }
2602
- return s`
2603
- <header class="header">
2604
- ${e ? s`<img class="logo" src=${e} alt=${t || "Logo"} />` : o}
2605
- ${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}
2606
2750
  <h2 class="title" id="authui-title">${i}</h2>
2607
- ${r ? s`<p class="description">${r}</p>` : o}
2608
- </header>
2751
+ ${s ? r`<p class="description">${s}</p>` : c}
2752
+ </div>
2609
2753
  `;
2610
2754
  }
2611
2755
  renderError() {
2612
- return this.error ? s`<div class="alert alert-error" role="alert">
2613
- ${c.alert}
2756
+ return this.error ? r`<div class="alert alert-error" role="alert">
2757
+ ${o.alert}
2614
2758
  <div class="alert-body">${this.error}</div>
2615
- </div>` : o;
2759
+ </div>` : c;
2616
2760
  }
2617
2761
  submitButton(e, t = "btn-primary") {
2618
- return s`<button class="btn ${t} btn-block" type="submit" ?disabled=${this.busy}>
2619
- ${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}
2620
2764
  </button>`;
2621
2765
  }
2622
2766
  passwordField(e) {
2623
- return s`
2767
+ return r`
2624
2768
  <div class="field">
2625
2769
  <label class="label" for=${e.id}>
2626
2770
  ${e.label}
2627
- ${e.forgot ? s`<button
2771
+ ${e.forgot ? r`<button
2628
2772
  type="button"
2629
2773
  class="btn btn-link small"
2630
2774
  @click=${() => this.go("forgot-password")}
2631
2775
  >
2632
2776
  ${this.t("forgotPassword")}
2633
- </button>` : o}
2777
+ </button>` : c}
2634
2778
  </label>
2635
2779
  <div class="input-wrap">
2636
2780
  <input
@@ -2647,18 +2791,18 @@ let $ = class extends A {
2647
2791
  type="button"
2648
2792
  class="btn btn-ghost btn-icon"
2649
2793
  @click=${() => this.showPassword = !this.showPassword}
2650
- aria-label=${this.showPassword ? "Hide password" : "Show password"}
2794
+ aria-label=${this.showPassword ? this.t("hidePassword") : this.t("showPassword")}
2651
2795
  tabindex="-1"
2652
2796
  >
2653
- ${this.showPassword ? c.eyeOff : c.eye}
2797
+ ${this.showPassword ? o.eyeOff : o.eye}
2654
2798
  </button>
2655
2799
  </div>
2656
- ${e.hint ? s`<p class="hint">${e.hint}</p>` : o}
2800
+ ${e.hint ? r`<p class="hint">${e.hint}</p>` : c}
2657
2801
  </div>
2658
2802
  `;
2659
2803
  }
2660
2804
  emailField(e = "email") {
2661
- return s`
2805
+ return r`
2662
2806
  <div class="field">
2663
2807
  <label class="label" for="authui-email">${this.t("email")}</label>
2664
2808
  <input
@@ -2675,7 +2819,7 @@ let $ = class extends A {
2675
2819
  `;
2676
2820
  }
2677
2821
  codeField() {
2678
- return s`
2822
+ return r`
2679
2823
  <div class="field">
2680
2824
  <label class="label" for="authui-code">${this.t("code")}</label>
2681
2825
  <input
@@ -2684,6 +2828,8 @@ let $ = class extends A {
2684
2828
  type="text"
2685
2829
  inputmode="numeric"
2686
2830
  autocomplete="one-time-code"
2831
+ maxlength="6"
2832
+ pattern="[0-9]*"
2687
2833
  required
2688
2834
  .value=${this.code}
2689
2835
  @input=${this.bind("code")}
@@ -2693,32 +2839,32 @@ let $ = class extends A {
2693
2839
  }
2694
2840
  legal() {
2695
2841
  const e = this.config?.legal;
2696
- return !e?.termsUrl && !e?.privacyUrl ? o : s`<p class="legal">
2842
+ return !e?.termsUrl && !e?.privacyUrl ? c : r`<p class="legal">
2697
2843
  ${this.t("agreeTo")}
2698
- ${e.termsUrl ? s`<a href=${e.termsUrl} target="_blank" rel="noopener">${this.t("terms")}</a>` : o}
2699
- ${e.termsUrl && e.privacyUrl ? s` ${this.t("and")} ` : o}
2700
- ${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}.
2701
2847
  </p>`;
2702
2848
  }
2703
2849
  backLink(e = "sign-in") {
2704
- return s`<div class="links">
2850
+ return r`<div class="links">
2705
2851
  <button type="button" class="btn btn-link" @click=${() => this.go(e)}>
2706
- ${c.arrowLeft} ${this.t("back")}
2852
+ ${o.arrowLeft} ${this.t("back")}
2707
2853
  </button>
2708
2854
  </div>`;
2709
2855
  }
2710
2856
  renderStep() {
2711
2857
  if (!this.auth.configured)
2712
- return s`<div class="alert alert-error" role="alert">
2713
- ${c.alert}
2858
+ return r`<div class="alert alert-error" role="alert">
2859
+ ${o.alert}
2714
2860
  <div class="alert-body">${this.t("errorNotConfigured")}</div>
2715
2861
  </div>`;
2716
2862
  if (this.auth.status === "loading")
2717
- return s`<div class="empty"><span class="spinner"></span></div>`;
2863
+ return r`<div class="empty"><span class="spinner"></span></div>`;
2718
2864
  if (this.auth.status === "signed-in" && this.step !== "mfa") return this.renderSignedIn();
2719
2865
  switch (this.step) {
2720
2866
  case "sign-up":
2721
- return this.renderSignUp();
2867
+ return this.config?.signUp === !1 ? this.renderSignIn() : this.renderSignUp();
2722
2868
  case "forgot-password":
2723
2869
  return this.renderForgot();
2724
2870
  case "reset-password":
@@ -2737,30 +2883,32 @@ let $ = class extends A {
2737
2883
  }
2738
2884
  renderSignedIn() {
2739
2885
  const e = this.auth.user, t = e.name || e.email || e.phone || this.t("guestAccount");
2740
- return s`
2886
+ return r`
2741
2887
  <div class="stack">
2742
2888
  <div class="row">
2743
2889
  <div class="inline">
2744
- <span class="avatar">${t[0] ?? "?"}</span>
2890
+ <span class="avatar">${Q(t)}</span>
2745
2891
  <div class="row-main">
2746
- <span class="row-title">${t}</span>
2747
- ${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}
2748
2894
  </div>
2749
2895
  </div>
2750
2896
  </div>
2751
2897
  ${this.renderError()}
2752
2898
  <div class="stack-sm">
2753
- ${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}
2754
2900
  >${this.t("continue")}</a
2755
- >` : o}
2901
+ >` : c}
2756
2902
  <button
2757
2903
  class="btn btn-outline btn-block"
2758
- @click=${() => this.fire("authui-open", { view: "account" })}
2904
+ @click=${() => {
2905
+ this.embedded ? this.fire("authui-open", { view: "account" }) : H("account");
2906
+ }}
2759
2907
  >
2760
- ${c.settings} ${this.t("manageAccount")}
2908
+ ${o.settings} ${this.t("manageAccount")}
2761
2909
  </button>
2762
2910
  <button class="btn btn-ghost btn-block" @click=${this.onSignOut} ?disabled=${this.busy}>
2763
- ${c.logOut} ${this.t("signOut")}
2911
+ ${o.logOut} ${this.t("signOut")}
2764
2912
  </button>
2765
2913
  </div>
2766
2914
  </div>
@@ -2768,21 +2916,21 @@ let $ = class extends A {
2768
2916
  }
2769
2917
  renderProviders() {
2770
2918
  const e = this.config?.methods?.oauth ?? [];
2771
- if (e.length === 0) return o;
2919
+ if (e.length === 0) return c;
2772
2920
  const t = e.length > 2;
2773
- return s`
2921
+ return r`
2774
2922
  <div class="providers ${t ? "two" : ""}">
2775
2923
  ${e.map(
2776
- (i) => s`<button
2924
+ (i) => r`<button
2777
2925
  type="button"
2778
2926
  class="btn btn-outline"
2779
2927
  @click=${() => this.onOAuth(i)}
2780
2928
  ?disabled=${this.busy}
2781
- aria-label=${this.t("continueWith", { provider: D(i) })}
2929
+ aria-label=${this.t("continueWith", { provider: R(i) })}
2782
2930
  >
2783
- ${K(i)}
2931
+ ${Y(i)}
2784
2932
  <span
2785
- >${t ? D(i) : this.t("continueWith", { provider: D(i) })}</span
2933
+ >${t ? R(i) : this.t("continueWith", { provider: R(i) })}</span
2786
2934
  >
2787
2935
  </button>`
2788
2936
  )}
@@ -2790,23 +2938,23 @@ let $ = class extends A {
2790
2938
  `;
2791
2939
  }
2792
2940
  renderSignIn() {
2793
- const e = this.config?.methods ?? {}, t = e.emailPassword !== !1, i = (e.oauth?.length ?? 0) > 0, r = [
2794
- e.magicUrl ? { step: "magic-url", icon: c.link, label: this.t("sendMagicLink") } : null,
2795
- e.emailOtp ? { step: "email-otp", icon: c.mail, label: this.t("continueWithEmail") } : null,
2796
- 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
2797
2945
  ].filter(Boolean);
2798
- return s`
2946
+ return r`
2799
2947
  <div class="stack">
2800
2948
  ${this.renderProviders()}
2801
- ${i && (t || r.length > 0) ? s`<div class="separator-text">${this.t("or")}</div>` : o}
2802
- ${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>
2803
2951
  ${this.emailField()}
2804
2952
  ${this.passwordField({ label: this.t("password"), autocomplete: "current-password", id: "authui-password", field: "password", forgot: !0 })}
2805
2953
  ${this.renderError()} ${this.submitButton(this.t("signIn"))}
2806
2954
  </form>` : this.renderError()}
2807
- ${r.length > 0 ? s`<div class="stack-sm">
2808
- ${r.map(
2809
- (a) => s`<button
2955
+ ${s.length > 0 ? r`<div class="stack-sm">
2956
+ ${s.map(
2957
+ (a) => r`<button
2810
2958
  type="button"
2811
2959
  class="btn btn-secondary btn-block"
2812
2960
  @click=${() => this.go(a.step)}
@@ -2814,32 +2962,32 @@ let $ = class extends A {
2814
2962
  ${a.icon} ${a.label}
2815
2963
  </button>`
2816
2964
  )}
2817
- </div>` : o}
2818
- ${e.anonymous ? s`<button
2965
+ </div>` : c}
2966
+ ${e.anonymous ? r`<button
2819
2967
  type="button"
2820
2968
  class="btn btn-ghost btn-block"
2821
2969
  @click=${this.onGuest}
2822
2970
  ?disabled=${this.busy}
2823
2971
  >
2824
- ${c.ghost} ${this.t("continueAsGuest")}
2825
- </button>` : o}
2826
- ${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">
2827
2975
  <span>${this.t("noAccount")}</span>
2828
2976
  <button type="button" class="btn btn-link" @click=${() => this.go("sign-up")}>
2829
2977
  ${this.t("signUp")}
2830
2978
  </button>
2831
- </div>` : o}
2979
+ </div>` : c}
2832
2980
  ${this.legal()}
2833
2981
  </div>
2834
2982
  `;
2835
2983
  }
2836
2984
  renderSignUp() {
2837
- return s`
2985
+ return r`
2838
2986
  <div class="stack">
2839
2987
  ${this.renderProviders()}
2840
- ${(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}
2841
2989
  <form class="form" @submit=${this.onSignUp} novalidate>
2842
- ${this.config?.requireName !== !1 ? s`<div class="field">
2990
+ ${this.config?.requireName !== !1 ? r`<div class="field">
2843
2991
  <label class="label" for="authui-name">${this.t("name")}</label>
2844
2992
  <input
2845
2993
  class="input"
@@ -2850,7 +2998,7 @@ let $ = class extends A {
2850
2998
  .value=${this.name}
2851
2999
  @input=${this.bind("name")}
2852
3000
  />
2853
- </div>` : o}
3001
+ </div>` : c}
2854
3002
  ${this.emailField()}
2855
3003
  ${this.passwordField({ label: this.t("password"), autocomplete: "new-password", id: "authui-password", field: "password", hint: this.t("passwordHint") })}
2856
3004
  ${this.renderError()} ${this.submitButton(this.t("createAccount"))}
@@ -2866,7 +3014,7 @@ let $ = class extends A {
2866
3014
  `;
2867
3015
  }
2868
3016
  renderForgot() {
2869
- return s`
3017
+ return r`
2870
3018
  <div class="stack">
2871
3019
  <form class="form" @submit=${this.onForgot} novalidate>
2872
3020
  ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendResetLink"))}
@@ -2876,52 +3024,91 @@ let $ = class extends A {
2876
3024
  `;
2877
3025
  }
2878
3026
  renderReset() {
2879
- return this.recovery ? s`
3027
+ return this.recovery ? r`
2880
3028
  <div class="stack">
2881
3029
  <form class="form" @submit=${this.onReset} novalidate>
2882
3030
  ${this.passwordField({ label: this.t("newPassword"), autocomplete: "new-password", id: "authui-password", field: "password", hint: this.t("passwordHint") })}
2883
3031
  ${this.passwordField({ label: this.t("confirmPassword"), autocomplete: "new-password", id: "authui-password-confirm", field: "passwordConfirm" })}
2884
3032
  ${this.renderError()} ${this.submitButton(this.t("resetPassword"))}
2885
3033
  </form>
2886
- ${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>
2887
3045
  </div>
2888
- ` : s`<div class="stack">
3046
+ ` : r`<div class="stack">
2889
3047
  <div class="alert alert-error" role="alert">
2890
- ${c.alert}
3048
+ ${o.alert}
2891
3049
  <div class="alert-body">${this.t("errorInvalidToken")}</div>
2892
3050
  </div>
2893
- ${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>
2894
3062
  </div>`;
2895
3063
  }
2896
3064
  phraseBox(e) {
2897
- return e ? s`<div class="alert alert-info">
2898
- ${c.shield}
3065
+ return e ? r`<div class="alert alert-info">
3066
+ ${o.shield}
2899
3067
  <div class="alert-title">
2900
3068
  ${this.t("securityPhrase")}: <span class="code">${e}</span>
2901
3069
  </div>
2902
3070
  <div class="alert-body">${this.t("securityPhraseHint")}</div>
2903
- </div>` : o;
3071
+ </div>` : c;
2904
3072
  }
2905
3073
  renderMagicUrl() {
2906
- return this.token ? s`<div class="stack">
3074
+ return this.token ? r`<div class="stack">
2907
3075
  <div class="alert alert-success" role="status">
2908
- ${c.mail}
3076
+ ${o.mail}
2909
3077
  <div class="alert-body">${this.t("magicLinkSent", { email: this.token.target })}</div>
2910
3078
  </div>
2911
3079
  ${this.phraseBox(this.token.phrase)} ${this.backLink()}
2912
- </div>` : s`
3080
+ </div>` : r`
2913
3081
  <div class="stack">
2914
3082
  <form class="form" @submit=${this.onMagicUrl} novalidate>
2915
3083
  ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendMagicLink"))}
2916
3084
  </form>
2917
- ${this.backLink()}
3085
+ ${this.backLink()} ${this.legal()}
2918
3086
  </div>
2919
3087
  `;
2920
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
+ }
2921
3107
  renderCodeEntry() {
2922
- return s`
3108
+ const e = this.token?.kind === "phone", t = Date.now() < this.resendCooldownUntil;
3109
+ return r`
2923
3110
  <div class="alert alert-info" role="status">
2924
- ${c.mail}
3111
+ ${e ? o.smartphone : o.mail}
2925
3112
  <div class="alert-body">${this.t("codeSent", { target: this.token.target })}</div>
2926
3113
  </div>
2927
3114
  ${this.phraseBox(this.token.phrase)}
@@ -2929,28 +3116,41 @@ let $ = class extends A {
2929
3116
  ${this.codeField()} ${this.renderError()} ${this.submitButton(this.t("verifyCode"))}
2930
3117
  </form>
2931
3118
  <div class="links">
2932
- <button type="button" class="btn btn-link" @click=${() => this.token = null}>
2933
- ${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")}
2934
3128
  </button>
2935
3129
  <span aria-hidden="true">·</span>
2936
- <button type="button" class="btn btn-link" @click=${() => this.go("sign-in")}>
2937
- ${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")}
2938
3138
  </button>
2939
3139
  </div>
2940
3140
  `;
2941
3141
  }
2942
3142
  renderEmailOtp() {
2943
- return this.token ? s`<div class="stack">${this.renderCodeEntry()}</div>` : s`
3143
+ return this.token ? r`<div class="stack">${this.renderCodeEntry()}</div>` : r`
2944
3144
  <div class="stack">
2945
3145
  <form class="form" @submit=${this.onEmailOtp} novalidate>
2946
3146
  ${this.emailField()} ${this.renderError()} ${this.submitButton(this.t("sendCode"))}
2947
3147
  </form>
2948
- ${this.backLink()}
3148
+ ${this.backLink()} ${this.legal()}
2949
3149
  </div>
2950
3150
  `;
2951
3151
  }
2952
3152
  renderPhone() {
2953
- return this.token ? s`<div class="stack">${this.renderCodeEntry()}</div>` : s`
3153
+ return this.token ? r`<div class="stack">${this.renderCodeEntry()}</div>` : r`
2954
3154
  <div class="stack">
2955
3155
  <form class="form" @submit=${this.onPhoneOtp} novalidate>
2956
3156
  <div class="field">
@@ -2968,7 +3168,7 @@ let $ = class extends A {
2968
3168
  </div>
2969
3169
  ${this.renderError()} ${this.submitButton(this.t("sendCode"))}
2970
3170
  </form>
2971
- ${this.backLink()}
3171
+ ${this.backLink()} ${this.legal()}
2972
3172
  </div>
2973
3173
  `;
2974
3174
  }
@@ -2978,40 +3178,40 @@ let $ = class extends A {
2978
3178
  const i = [
2979
3179
  {
2980
3180
  factor: "totp",
2981
- icon: c.smartphone,
3181
+ icon: o.smartphone,
2982
3182
  label: this.t("mfaUseAuthenticator"),
2983
3183
  available: e?.totp ?? !0
2984
3184
  },
2985
3185
  {
2986
3186
  factor: "email",
2987
- icon: c.mail,
3187
+ icon: o.mail,
2988
3188
  label: this.t("mfaUseEmail"),
2989
3189
  available: e?.email ?? !0
2990
3190
  },
2991
3191
  {
2992
3192
  factor: "phone",
2993
- icon: c.phone,
3193
+ icon: o.phone,
2994
3194
  label: this.t("mfaUsePhone"),
2995
3195
  available: e?.phone ?? !0
2996
3196
  },
2997
3197
  {
2998
3198
  factor: "recoverycode",
2999
- icon: c.key,
3199
+ icon: o.key,
3000
3200
  label: this.t("mfaUseRecoveryCode"),
3001
3201
  available: e?.recoveryCode ?? !0
3002
3202
  }
3003
3203
  ];
3004
- return s`
3204
+ return r`
3005
3205
  <div class="stack">
3006
3206
  <div class="stack-sm">
3007
- ${i.filter((r) => r.available).map(
3008
- (r) => s`<button
3207
+ ${i.filter((s) => s.available).map(
3208
+ (s) => r`<button
3009
3209
  type="button"
3010
3210
  class="choice"
3011
- @click=${() => this.onChooseFactor(r.factor)}
3211
+ @click=${() => this.onChooseFactor(s.factor)}
3012
3212
  ?disabled=${this.busy}
3013
3213
  >
3014
- ${r.icon}<span class="choice-title">${r.label}</span>
3214
+ ${s.icon}<span class="choice-title">${s.label}</span>
3015
3215
  </button>`
3016
3216
  )}
3017
3217
  </div>
@@ -3025,10 +3225,10 @@ let $ = class extends A {
3025
3225
  `;
3026
3226
  }
3027
3227
  const t = this.challenge.factor === "recoverycode";
3028
- return s`
3228
+ return r`
3029
3229
  <div class="stack">
3030
3230
  <form class="form" @submit=${this.onVerifyFactor} novalidate>
3031
- ${t ? s`<div class="field">
3231
+ ${t ? r`<div class="field">
3032
3232
  <label class="label" for="authui-code">${this.t("recoveryCode")}</label>
3033
3233
  <input
3034
3234
  class="input mono"
@@ -3044,7 +3244,7 @@ let $ = class extends A {
3044
3244
  </form>
3045
3245
  <div class="links">
3046
3246
  <button type="button" class="btn btn-link" @click=${() => this.challenge = null}>
3047
- ${c.arrowLeft} ${this.t("back")}
3247
+ ${o.arrowLeft} ${this.t("back")}
3048
3248
  </button>
3049
3249
  <span aria-hidden="true">·</span>
3050
3250
  <button type="button" class="btn btn-link" @click=${this.onCancelMfa}>
@@ -3055,102 +3255,127 @@ let $ = class extends A {
3055
3255
  `;
3056
3256
  }
3057
3257
  };
3058
- $.styles = [...A.styles, At];
3059
- C([
3060
- f({ type: String })
3258
+ $.styles = [...A.styles, Ut];
3259
+ k([
3260
+ m({ type: String })
3061
3261
  ], $.prototype, "view", 2);
3062
- C([
3063
- f({ type: Boolean })
3262
+ k([
3263
+ m({ type: Boolean })
3064
3264
  ], $.prototype, "embedded", 2);
3065
- C([
3265
+ k([
3066
3266
  d()
3067
3267
  ], $.prototype, "step", 2);
3068
- C([
3268
+ k([
3069
3269
  d()
3070
3270
  ], $.prototype, "busy", 2);
3071
- C([
3271
+ k([
3072
3272
  d()
3073
3273
  ], $.prototype, "error", 2);
3074
- C([
3274
+ k([
3075
3275
  d()
3076
3276
  ], $.prototype, "notice", 2);
3077
- C([
3277
+ k([
3078
3278
  d()
3079
3279
  ], $.prototype, "showPassword", 2);
3080
- C([
3280
+ k([
3081
3281
  d()
3082
3282
  ], $.prototype, "token", 2);
3083
- C([
3283
+ k([
3284
+ d()
3285
+ ], $.prototype, "resendCooldownUntil", 2);
3286
+ k([
3084
3287
  d()
3085
3288
  ], $.prototype, "challenge", 2);
3086
- C([
3289
+ k([
3087
3290
  d()
3088
3291
  ], $.prototype, "recovery", 2);
3089
- C([
3090
- rt("form input:not([type=hidden])")
3292
+ k([
3293
+ ct("form input:not([type=hidden])")
3091
3294
  ], $.prototype, "firstInput", 2);
3092
- $ = C([
3093
- _("authui-sign-in")
3295
+ $ = k([
3296
+ O("authui-sign-in")
3094
3297
  ], $);
3095
- var It = Object.defineProperty, _t = Object.getOwnPropertyDescriptor, g = (e, t, i, r) => {
3096
- for (var a = r > 1 ? void 0 : r ? _t(t, i) : t, h = e.length - 1, u; h >= 0; h--)
3097
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
3098
- return r && a && It(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;
3099
3302
  };
3100
- let p = class extends A {
3303
+ let u = class extends A {
3101
3304
  constructor() {
3102
- 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) => {
3103
- 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"));
3104
3321
  }, this.onUpdateEmail = (e) => {
3105
- e.preventDefault(), this.run(
3322
+ e.preventDefault(), this.requireValid(e) && this.run(
3106
3323
  "email",
3107
3324
  async () => {
3108
3325
  await n.updateEmail(this.emailInput, this.emailPassword), this.emailPassword = "";
3109
3326
  },
3110
- this.t("done")
3327
+ this.t("emailUpdated")
3111
3328
  );
3112
3329
  }, this.onUpdatePhone = (e) => {
3113
- e.preventDefault(), this.run(
3330
+ e.preventDefault(), this.requireValid(e) && this.run(
3114
3331
  "phone",
3115
3332
  async () => {
3116
3333
  await n.updatePhone(this.phoneInput, this.phonePassword), this.phonePassword = "";
3117
3334
  },
3118
- this.t("done")
3335
+ this.t("phoneUpdated")
3119
3336
  );
3120
3337
  }, this.onConvertGuest = (e) => {
3121
- e.preventDefault(), this.run(
3338
+ e.preventDefault(), this.requireValid(e) && this.run(
3122
3339
  "guest",
3123
3340
  async () => {
3124
3341
  await n.convertGuest(this.emailInput, this.emailPassword, this.guestName), this.emailPassword = "";
3125
3342
  },
3126
- this.t("done")
3343
+ this.t("accountConverted")
3127
3344
  );
3128
3345
  }, this.onSendVerification = () => {
3129
- 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
+ );
3130
3353
  }, this.onSendPhoneVerification = () => {
3131
3354
  this.run("verify-phone", async () => {
3132
3355
  await n.sendPhoneVerification(), this.phoneCodeSent = !0;
3133
3356
  });
3134
3357
  }, this.onConfirmPhoneVerification = (e) => {
3135
- e.preventDefault(), this.run(
3358
+ e.preventDefault(), this.requireValid(e) && this.run(
3136
3359
  "verify-phone-code",
3137
3360
  async () => {
3138
3361
  await n.confirmPhoneVerification(this.phoneCode), this.phoneCode = "", this.phoneCodeSent = !1;
3139
3362
  },
3140
- this.t("done")
3363
+ this.t("phoneVerified")
3141
3364
  );
3142
3365
  }, this.onChangePassword = (e) => {
3143
- if (e.preventDefault(), this.newPassword !== this.newPasswordConfirm) {
3144
- this.errors = { ...this.errors, password: this.t("errorPasswordMismatch") };
3145
- 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
+ );
3146
3378
  }
3147
- this.run(
3148
- "password",
3149
- async () => {
3150
- await n.updatePassword(this.newPassword, this.oldPassword), this.oldPassword = this.newPassword = this.newPasswordConfirm = "";
3151
- },
3152
- this.t("passwordUpdated")
3153
- );
3154
3379
  }, this.onToggleMfa = () => {
3155
3380
  const e = !this.user?.mfa;
3156
3381
  this.run("mfa", async () => {
@@ -3161,15 +3386,19 @@ let p = class extends A {
3161
3386
  this.authenticator = await n.addAuthenticator(), this.authenticatorCode = "";
3162
3387
  });
3163
3388
  }, this.onVerifyAuthenticator = (e) => {
3164
- e.preventDefault(), this.run(
3389
+ e.preventDefault(), this.requireValid(e) && this.run(
3165
3390
  "authenticator-code",
3166
3391
  async () => {
3167
3392
  await n.verifyAuthenticator(this.authenticatorCode), this.authenticator = null, this.authenticatorCode = "", await this.loadFactors();
3168
3393
  },
3169
- this.t("done")
3394
+ this.t("authenticatorAdded")
3170
3395
  );
3171
3396
  }, this.onRemoveAuthenticator = () => {
3172
- 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 () => {
3173
3402
  await n.removeAuthenticator(), await this.loadFactors();
3174
3403
  });
3175
3404
  }, this.onRecoveryCodes = () => {
@@ -3177,13 +3406,17 @@ let p = class extends A {
3177
3406
  try {
3178
3407
  this.recoveryCodes = await n.createRecoveryCodes();
3179
3408
  } catch (e) {
3180
- if (!B(e, v.recoveryCodesExist)) throw e;
3409
+ if (!z(e, v.recoveryCodesExist)) throw e;
3181
3410
  this.recoveryCodes = await n.getRecoveryCodes();
3182
3411
  }
3183
3412
  await this.loadFactors();
3184
3413
  });
3185
3414
  }, this.onRegenerateRecoveryCodes = () => {
3186
- this.run("recovery", async () => {
3415
+ if (!this.confirmRegenerate) {
3416
+ this.confirmRegenerate = !0;
3417
+ return;
3418
+ }
3419
+ this.confirmRegenerate = !1, this.run("recovery", async () => {
3187
3420
  this.recoveryCodes = await n.regenerateRecoveryCodes();
3188
3421
  });
3189
3422
  }, this.onCopyCodes = async () => {
@@ -3192,6 +3425,15 @@ let p = class extends A {
3192
3425
  await navigator.clipboard.writeText(this.recoveryCodes.join(`
3193
3426
  `)), this.copied = !0, setTimeout(() => this.copied = !1, 1500);
3194
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"));
3195
3437
  }
3196
3438
  }, this.onStepUpFactor = (e) => {
3197
3439
  this.run("stepup", async () => {
@@ -3199,19 +3441,31 @@ let p = class extends A {
3199
3441
  this.stepUp = { ...this.stepUp, challenge: { id: t.$id, factor: e } }, this.stepUpCode = "";
3200
3442
  });
3201
3443
  }, this.onStepUpVerify = (e) => {
3202
- e.preventDefault();
3444
+ if (e.preventDefault(), !this.requireValid(e)) return;
3203
3445
  const t = this.stepUp;
3204
3446
  t?.challenge && this.run("stepup-code", async () => {
3205
3447
  await n.completeMfaChallenge(t.challenge.id, this.stepUpCode, { signIn: !1 }), this.stepUp = null, this.stepUpCode = "", await t.retry();
3206
3448
  });
3207
3449
  }, this.onDeleteSession = (e) => {
3208
3450
  this.run(`session-${e}`, async () => {
3209
- 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);
3210
3456
  });
3211
3457
  }, this.onSignOutAll = () => {
3212
- 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());
3213
3463
  }, this.onDeleteIdentity = (e) => {
3214
- 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 () => {
3215
3469
  await n.deleteIdentity(e), this.identities = (this.identities ?? []).filter((t) => t.$id !== e);
3216
3470
  });
3217
3471
  }, this.onDeleteAccount = () => {
@@ -3226,7 +3480,7 @@ let p = class extends A {
3226
3480
  }
3227
3481
  /** Lazily load data for the active tab once a user is available. */
3228
3482
  ensureLoaded() {
3229
- !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());
3230
3484
  }
3231
3485
  hydrate() {
3232
3486
  const e = this.auth.user;
@@ -3242,16 +3496,36 @@ let p = class extends A {
3242
3496
  select(e) {
3243
3497
  this.active = e, this.notice = null, this.errors = {};
3244
3498
  }
3245
- /** 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
+ }
3246
3516
  async run(e, t, i) {
3247
3517
  if (!this.busy) {
3248
- this.busy = e, this.errors = { ...this.errors, [e]: "" };
3518
+ this.busy = e, this.errors = { ...this.errors, [e]: "" }, this.notice = null;
3249
3519
  try {
3250
- await t(), i && (this.notice = { tone: "success", message: i });
3251
- } catch (r) {
3252
- B(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 = {
3253
3523
  ...this.errors,
3254
- [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
+ )
3255
3529
  };
3256
3530
  } finally {
3257
3531
  this.busy = "";
@@ -3269,12 +3543,27 @@ let p = class extends A {
3269
3543
  this.identities = await n.listIdentities();
3270
3544
  });
3271
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
+ }
3272
3557
  async loadLogs() {
3558
+ if (this.logsSupported === !1) {
3559
+ this.active === "activity" && (this.active = "profile");
3560
+ return;
3561
+ }
3273
3562
  this.busy = "logs";
3274
3563
  try {
3275
3564
  this.logs = await n.listLogs();
3276
3565
  } catch {
3277
- this.logsSupported = !1, this.logs = [];
3566
+ this.logsSupported = !1, this.logs = [], this.active === "activity" && (this.active = "profile");
3278
3567
  } finally {
3279
3568
  this.busy = "";
3280
3569
  }
@@ -3305,14 +3594,16 @@ let p = class extends A {
3305
3594
  // ─────────────────────────── render ───────────────────────────
3306
3595
  render() {
3307
3596
  if (!this.auth.configured)
3308
- return s`<div class="alert alert-error" role="alert">
3309
- ${c.alert}
3597
+ return r`<div class="alert alert-error" role="alert">
3598
+ ${o.alert}
3310
3599
  <div class="alert-body">${this.t("errorNotConfigured")}</div>
3311
3600
  </div>`;
3312
3601
  if (this.auth.status === "loading")
3313
- 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>`;
3314
3605
  if (!this.user)
3315
- return s`<div class="panel ${this.embedded ? "embedded" : ""}">
3606
+ return r`<div class="panel ${this.embedded ? "embedded" : ""}">
3316
3607
  <authui-sign-in embedded></authui-sign-in>
3317
3608
  </div>`;
3318
3609
  const e = [
@@ -3322,46 +3613,65 @@ let p = class extends A {
3322
3613
  { id: "connections", label: this.t("connections") },
3323
3614
  ...this.logsSupported ? [{ id: "activity", label: this.t("activity") }] : []
3324
3615
  ];
3325
- return s`
3616
+ return r`
3326
3617
  <div class="panel ${this.embedded ? "embedded" : ""}" part="panel">
3327
3618
  ${this.renderIdentity()}
3328
- <div class="tabs" role="tablist">
3619
+ <div class="tabs" role="tablist" @keydown=${this.onTabsKeydown}>
3329
3620
  ${e.map(
3330
- (t) => s`<button
3621
+ (t) => r`<button
3331
3622
  class="tab"
3332
3623
  role="tab"
3624
+ id=${`authui-tab-${t.id}`}
3625
+ aria-controls=${`authui-panel-${t.id}`}
3333
3626
  aria-selected=${this.active === t.id ? "true" : "false"}
3627
+ tabindex=${this.active === t.id ? "0" : "-1"}
3334
3628
  @click=${() => this.select(t.id)}
3335
3629
  >
3336
3630
  ${t.label}
3337
3631
  </button>`
3338
3632
  )}
3339
3633
  </div>
3340
- ${this.notice ? s`<div class="alert alert-${this.notice.tone}" role="status">
3341
- ${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}
3342
3636
  <div class="alert-body">${this.notice.message}</div>
3343
- </div>` : o}
3344
- ${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>`}
3345
3655
  </div>
3346
3656
  `;
3347
3657
  }
3348
3658
  renderIdentity() {
3349
3659
  const e = this.user, t = e.name || e.email || e.phone || this.t("guestAccount");
3350
- return s`
3660
+ return r`
3351
3661
  <div class="between">
3352
3662
  <div class="identity">
3353
- <span class="avatar">${t[0] ?? "?"}</span>
3663
+ <span class="avatar">${Q(t)}</span>
3354
3664
  <div class="row-main">
3355
- <span class="row-title">
3665
+ <span class="row-title" title=${t}>
3356
3666
  ${t}
3357
- ${e.mfa ? s`<span class="badge badge-success">${c.shieldCheck} MFA</span>` : o}
3358
- ${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}
3359
3669
  </span>
3360
- ${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}
3361
3671
  </div>
3362
3672
  </div>
3363
3673
  <button class="btn btn-outline btn-sm" @click=${() => n.signOut()}>
3364
- ${c.logOut} ${this.t("signOut")}
3674
+ ${o.logOut} ${this.t("signOut")}
3365
3675
  </button>
3366
3676
  </div>
3367
3677
  `;
@@ -3382,35 +3692,35 @@ let p = class extends A {
3382
3692
  }
3383
3693
  error(e) {
3384
3694
  const t = this.errors[e];
3385
- return t ? s`<div class="alert alert-error" role="alert">
3386
- ${c.alert}
3695
+ return t ? r`<div class="alert alert-error" role="alert">
3696
+ ${o.alert}
3387
3697
  <div class="alert-body">${t}</div>
3388
- </div>` : o;
3698
+ </div>` : c;
3389
3699
  }
3390
3700
  spinner(e) {
3391
- 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;
3392
3702
  }
3393
- card(e, t, i, r, a = !1) {
3394
- 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" : ""}">
3395
3705
  <div class="card-header">
3396
3706
  <h3 class="card-title">${e}</h3>
3397
- ${t ? s`<p class="card-description">${t}</p>` : o}
3707
+ ${t ? r`<p class="card-description">${t}</p>` : c}
3398
3708
  </div>
3399
3709
  <div class="card-body">${i}</div>
3400
- ${r ? s`<div class="card-footer">${r}</div>` : o}
3710
+ ${s ? r`<div class="card-footer">${s}</div>` : c}
3401
3711
  </section>`;
3402
3712
  }
3403
3713
  verifiedBadge(e) {
3404
- 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>`;
3405
3715
  }
3406
3716
  // ── Profile ──
3407
3717
  renderProfile() {
3408
3718
  const e = this.user;
3409
- return this.isGuest ? s`<div class="section">
3719
+ return this.isGuest ? r`<div class="section">
3410
3720
  ${this.card(
3411
3721
  this.t("guestAccount"),
3412
3722
  this.t("guestAccountDescription"),
3413
- s`<form class="form" id="guest-form" @submit=${this.onConvertGuest} novalidate>
3723
+ r`<form class="form" id="guest-form" @submit=${this.onConvertGuest} novalidate>
3414
3724
  <div class="field">
3415
3725
  <label class="label" for="guest-name">${this.t("name")}</label>
3416
3726
  <input
@@ -3449,7 +3759,7 @@ let p = class extends A {
3449
3759
  </div>
3450
3760
  ${this.error("guest")}
3451
3761
  </form>`,
3452
- s`<button
3762
+ r`<button
3453
3763
  class="btn btn-primary btn-sm"
3454
3764
  type="submit"
3455
3765
  form="guest-form"
@@ -3458,11 +3768,11 @@ let p = class extends A {
3458
3768
  ${this.spinner("guest")} ${this.t("createAccount")}
3459
3769
  </button>`
3460
3770
  )}
3461
- </div>` : s`<div class="section">
3771
+ </div>` : r`<div class="section">
3462
3772
  ${this.card(
3463
3773
  this.t("name"),
3464
3774
  void 0,
3465
- s`<form class="form" id="name-form" @submit=${this.onUpdateName} novalidate>
3775
+ r`<form class="form" id="name-form" @submit=${this.onUpdateName} novalidate>
3466
3776
  <div class="field">
3467
3777
  <label class="label" for="acc-name">${this.t("name")}</label>
3468
3778
  <input
@@ -3476,11 +3786,11 @@ let p = class extends A {
3476
3786
  </div>
3477
3787
  ${this.error("name")}
3478
3788
  </form>`,
3479
- s`<button
3789
+ r`<button
3480
3790
  class="btn btn-primary btn-sm"
3481
3791
  type="submit"
3482
3792
  form="name-form"
3483
- ?disabled=${!!this.busy || this.nameInput === e.name}
3793
+ ?disabled=${!!this.busy || !this.nameInput.trim() || this.nameInput === e.name}
3484
3794
  >
3485
3795
  ${this.spinner("name")} ${this.t("update")}
3486
3796
  </button>`
@@ -3488,11 +3798,11 @@ let p = class extends A {
3488
3798
  ${this.card(
3489
3799
  this.t("email"),
3490
3800
  void 0,
3491
- s`<form class="form" id="email-form" @submit=${this.onUpdateEmail} novalidate>
3801
+ r`<form class="form" id="email-form" @submit=${this.onUpdateEmail} novalidate>
3492
3802
  <div class="field">
3493
3803
  <label class="label" for="acc-email"
3494
3804
  >${this.t("email")}
3495
- ${e.email ? this.verifiedBadge(e.emailVerification) : o}</label
3805
+ ${e.email ? this.verifiedBadge(e.emailVerification) : c}</label
3496
3806
  >
3497
3807
  <input
3498
3808
  class="input"
@@ -3504,34 +3814,43 @@ let p = class extends A {
3504
3814
  required
3505
3815
  />
3506
3816
  </div>
3507
- ${this.emailInput !== e.email ? s`<div class="field">
3508
- <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
+ >
3509
3821
  <input
3510
3822
  class="input"
3511
3823
  id="acc-email-password"
3512
3824
  type="password"
3513
3825
  .value=${this.emailPassword}
3514
3826
  @input=${this.bind("emailPassword")}
3515
- autocomplete="current-password"
3827
+ autocomplete=${e.passwordUpdate ? "current-password" : "new-password"}
3516
3828
  required
3517
3829
  />
3518
- </div>` : o}
3830
+ ${e.passwordUpdate ? c : r`<p class="hint">${this.t("createPasswordHint")}</p>`}
3831
+ </div>` : c}
3519
3832
  ${this.error("email")} ${this.error("verify")}
3520
3833
  </form>`,
3521
- s`
3522
- ${e.email && !e.emailVerification ? s`<button
3834
+ r`
3835
+ ${e.email && !e.emailVerification ? r`<button
3523
3836
  class="btn btn-outline btn-sm"
3524
3837
  type="button"
3525
3838
  @click=${this.onSendVerification}
3526
- ?disabled=${!!this.busy}
3839
+ ?disabled=${!!this.busy || Date.now() < this.verifyEmailCooldownUntil}
3527
3840
  >
3528
- ${this.spinner("verify")} ${this.t("verifyEmail")}
3529
- </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}
3530
3849
  <button
3531
3850
  class="btn btn-primary btn-sm"
3532
3851
  type="submit"
3533
3852
  form="email-form"
3534
- ?disabled=${!!this.busy || this.emailInput === e.email}
3853
+ ?disabled=${!!this.busy || !this.emailInput.trim() || this.emailInput === e.email}
3535
3854
  >
3536
3855
  ${this.spinner("email")} ${this.t("update")}
3537
3856
  </button>
@@ -3540,11 +3859,11 @@ let p = class extends A {
3540
3859
  ${this.card(
3541
3860
  this.t("phone"),
3542
3861
  void 0,
3543
- s`<form class="form" id="phone-form" @submit=${this.onUpdatePhone} novalidate>
3862
+ r`<form class="form" id="phone-form" @submit=${this.onUpdatePhone} novalidate>
3544
3863
  <div class="field">
3545
3864
  <label class="label" for="acc-phone"
3546
3865
  >${this.t("phone")}
3547
- ${e.phone ? this.verifiedBadge(e.phoneVerification) : o}</label
3866
+ ${e.phone ? this.verifiedBadge(e.phoneVerification) : c}</label
3548
3867
  >
3549
3868
  <input
3550
3869
  class="input"
@@ -3556,53 +3875,62 @@ let p = class extends A {
3556
3875
  autocomplete="tel"
3557
3876
  />
3558
3877
  </div>
3559
- ${this.phoneInput !== e.phone ? s`<div class="field">
3560
- <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
+ >
3561
3882
  <input
3562
3883
  class="input"
3563
3884
  id="acc-phone-password"
3564
3885
  type="password"
3565
3886
  .value=${this.phonePassword}
3566
3887
  @input=${this.bind("phonePassword")}
3567
- autocomplete="current-password"
3888
+ autocomplete=${e.passwordUpdate ? "current-password" : "new-password"}
3568
3889
  required
3569
3890
  />
3570
- </div>` : o}
3571
- ${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">
3572
3894
  <label class="label" for="acc-phone-code">${this.t("code")}</label>
3573
3895
  <input
3574
3896
  class="input input-otp"
3575
3897
  id="acc-phone-code"
3576
3898
  inputmode="numeric"
3577
3899
  autocomplete="one-time-code"
3900
+ maxlength="6"
3901
+ pattern="[0-9]*"
3902
+ required
3578
3903
  .value=${this.phoneCode}
3579
3904
  @input=${this.bind("phoneCode")}
3905
+ @keydown=${(t) => {
3906
+ t.key === "Enter" && (t.preventDefault(), this.onConfirmPhoneVerification(t));
3907
+ }}
3580
3908
  />
3581
- </div>` : o}
3909
+ </div>` : c}
3582
3910
  ${this.error("phone")} ${this.error("verify-phone")} ${this.error("verify-phone-code")}
3583
3911
  </form>`,
3584
- s`
3585
- ${e.phone && !e.phoneVerification && !this.phoneCodeSent ? s`<button
3912
+ r`
3913
+ ${e.phone && !e.phoneVerification && !this.phoneCodeSent ? r`<button
3586
3914
  class="btn btn-outline btn-sm"
3587
3915
  type="button"
3588
3916
  @click=${this.onSendPhoneVerification}
3589
3917
  ?disabled=${!!this.busy}
3590
3918
  >
3591
3919
  ${this.spinner("verify-phone")} ${this.t("sendCode")}
3592
- </button>` : o}
3593
- ${this.phoneCodeSent ? s`<button
3920
+ </button>` : c}
3921
+ ${this.phoneCodeSent ? r`<button
3594
3922
  class="btn btn-outline btn-sm"
3595
3923
  type="button"
3596
3924
  @click=${this.onConfirmPhoneVerification}
3597
3925
  ?disabled=${!!this.busy}
3598
3926
  >
3599
3927
  ${this.spinner("verify-phone-code")} ${this.t("verifyCode")}
3600
- </button>` : o}
3928
+ </button>` : c}
3601
3929
  <button
3602
3930
  class="btn btn-primary btn-sm"
3603
3931
  type="submit"
3604
3932
  form="phone-form"
3605
- ?disabled=${!!this.busy || this.phoneInput === e.phone}
3933
+ ?disabled=${!!this.busy || !this.phoneInput.trim() || this.phoneInput === e.phone}
3606
3934
  >
3607
3935
  ${this.spinner("phone")} ${this.t("update")}
3608
3936
  </button>
@@ -3615,10 +3943,10 @@ let p = class extends A {
3615
3943
  return this.card(
3616
3944
  this.t("deleteAccount"),
3617
3945
  this.t("deleteAccountDescription"),
3618
- s`${this.error("delete")}
3619
- ${this.confirmDelete ? s`<div class="inline">
3946
+ r`${this.error("delete")}
3947
+ ${this.confirmDelete ? r`<div class="inline">
3620
3948
  <button
3621
- class="btn btn-destructive btn-sm"
3949
+ class="btn btn-outline btn-sm warn"
3622
3950
  @click=${this.onDeleteAccount}
3623
3951
  ?disabled=${!!this.busy}
3624
3952
  >
@@ -3627,11 +3955,11 @@ let p = class extends A {
3627
3955
  <button class="btn btn-ghost btn-sm" @click=${() => this.confirmDelete = !1}>
3628
3956
  ${this.t("cancel")}
3629
3957
  </button>
3630
- </div>` : s`<button
3958
+ </div>` : r`<button
3631
3959
  class="btn btn-outline btn-sm warn"
3632
3960
  @click=${() => this.confirmDelete = !0}
3633
3961
  >
3634
- ${c.userX} ${this.t("deleteAccount")}
3962
+ ${o.userX} ${this.t("deleteAccount")}
3635
3963
  </button>`}`,
3636
3964
  void 0,
3637
3965
  !0
@@ -3640,17 +3968,17 @@ let p = class extends A {
3640
3968
  // ── Security ──
3641
3969
  renderSecurity() {
3642
3970
  const e = this.user, t = this.config?.mfa !== !1;
3643
- return s`<div class="section">
3644
- ${this.isGuest ? o : this.card(
3971
+ return r`<div class="section">
3972
+ ${this.isGuest ? c : this.card(
3645
3973
  this.t("changePassword"),
3646
3974
  void 0,
3647
- s`<form
3975
+ r`<form
3648
3976
  class="form"
3649
3977
  id="password-form"
3650
3978
  @submit=${this.onChangePassword}
3651
3979
  novalidate
3652
3980
  >
3653
- ${e.passwordUpdate ? s`<div class="field">
3981
+ ${e.passwordUpdate ? r`<div class="field">
3654
3982
  <label class="label" for="acc-old-password"
3655
3983
  >${this.t("currentPassword")}</label
3656
3984
  >
@@ -3661,8 +3989,9 @@ let p = class extends A {
3661
3989
  .value=${this.oldPassword}
3662
3990
  @input=${this.bind("oldPassword")}
3663
3991
  autocomplete="current-password"
3992
+ required
3664
3993
  />
3665
- </div>` : o}
3994
+ </div>` : c}
3666
3995
  <div class="field">
3667
3996
  <label class="label" for="acc-new-password">${this.t("newPassword")}</label>
3668
3997
  <input
@@ -3694,7 +4023,7 @@ let p = class extends A {
3694
4023
  </div>
3695
4024
  ${this.error("password")}
3696
4025
  </form>`,
3697
- s`<button
4026
+ r`<button
3698
4027
  class="btn btn-primary btn-sm"
3699
4028
  type="submit"
3700
4029
  form="password-form"
@@ -3703,20 +4032,20 @@ let p = class extends A {
3703
4032
  ${this.spinner("password")} ${this.t("update")}
3704
4033
  </button>`
3705
4034
  )}
3706
- ${t ? this.renderMfaCard() : o}
3707
- ${t ? this.renderRecoveryCard() : o}
4035
+ ${t ? this.renderMfaCard() : c}
4036
+ ${t ? this.renderRecoveryCard() : c}
3708
4037
  </div>`;
3709
4038
  }
3710
4039
  renderMfaCard() {
3711
- const e = this.user, t = this.factors?.totp ?? !1, i = this.authenticator ? n.isPreview ? mt(this.authenticator.uri) : new lt(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() : "";
3712
4041
  return this.card(
3713
4042
  this.t("twoFactor"),
3714
4043
  this.t("twoFactorDescription"),
3715
- s`<div class="kv">
4044
+ r`<div class="kv">
3716
4045
  <div class="toggle-row">
3717
4046
  <div class="row-main">
3718
4047
  <span class="row-title">${this.t("twoFactor")}</span>
3719
- <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>
3720
4049
  </div>
3721
4050
  <button
3722
4051
  class="switch"
@@ -3727,22 +4056,52 @@ let p = class extends A {
3727
4056
  aria-label=${this.t("twoFactor")}
3728
4057
  ></button>
3729
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}
3730
4075
  ${this.error("mfa")}
3731
4076
  <div class="separator"></div>
3732
4077
  <div class="toggle-row">
3733
4078
  <div class="row-main">
3734
4079
  <span class="row-title"
3735
- >${c.smartphone} ${this.t("authenticatorApp")}
3736
- ${t ? this.verifiedBadge(!0) : o}</span
4080
+ >${o.smartphone} ${this.t("authenticatorApp")}
4081
+ ${t ? this.verifiedBadge(!0) : c}</span
3737
4082
  >
3738
4083
  </div>
3739
- ${t ? s`<button
3740
- class="btn btn-outline btn-sm"
3741
- @click=${this.onRemoveAuthenticator}
3742
- ?disabled=${!!this.busy}
3743
- >
3744
- ${this.spinner("remove-authenticator")} ${this.t("remove")}
3745
- </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
3746
4105
  class="btn btn-outline btn-sm"
3747
4106
  @click=${this.onAddAuthenticator}
3748
4107
  ?disabled=${!!this.busy}
@@ -3751,13 +4110,25 @@ let p = class extends A {
3751
4110
  </button>`}
3752
4111
  </div>
3753
4112
  ${this.error("authenticator")} ${this.error("remove-authenticator")}
3754
- ${this.authenticator ? s`<form class="form" @submit=${this.onVerifyAuthenticator} novalidate>
4113
+ ${this.authenticator ? r`<form class="form" @submit=${this.onVerifyAuthenticator} novalidate>
3755
4114
  <p class="hint">${this.t("authenticatorScan")}</p>
3756
- <img class="qr" src=${i} alt="QR code" />
3757
- <p class="hint center">
3758
- ${this.t("authenticatorManual")}:
3759
- <span class="code">${this.authenticator.secret}</span>
3760
- </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>
3761
4132
  <div class="field">
3762
4133
  <label class="label" for="acc-totp">${this.t("code")}</label>
3763
4134
  <input
@@ -3765,6 +4136,8 @@ let p = class extends A {
3765
4136
  id="acc-totp"
3766
4137
  inputmode="numeric"
3767
4138
  autocomplete="one-time-code"
4139
+ maxlength="6"
4140
+ pattern="[0-9]*"
3768
4141
  required
3769
4142
  .value=${this.authenticatorCode}
3770
4143
  @input=${this.bind("authenticatorCode")}
@@ -3783,7 +4156,7 @@ let p = class extends A {
3783
4156
  ${this.t("cancel")}
3784
4157
  </button>
3785
4158
  </div>
3786
- </form>` : o}
4159
+ </form>` : c}
3787
4160
  </div>`
3788
4161
  );
3789
4162
  }
@@ -3791,33 +4164,53 @@ let p = class extends A {
3791
4164
  const e = this.factors?.recoveryCode ?? !1;
3792
4165
  return this.card(
3793
4166
  this.t("recoveryCodes"),
3794
- this.t("recoveryCodesDescription"),
3795
- s`<div class="kv">
3796
- ${this.recoveryCodes ? s`<div class="alert alert-warning">
3797
- ${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}
3798
4171
  <div class="alert-body">${this.t("recoveryCodesWarning")}</div>
3799
4172
  </div>
3800
4173
  <div class="codes">
3801
- ${this.recoveryCodes.map((t) => s`<span class="code">${t}</span>`)}
4174
+ ${this.recoveryCodes.map((t) => r`<span class="code">${t}</span>`)}
3802
4175
  </div>
3803
4176
  <div class="inline">
3804
4177
  <button class="btn btn-outline btn-sm" @click=${this.onCopyCodes}>
3805
- ${this.copied ? c.check : c.copy}
4178
+ ${this.copied ? o.check : o.copy}
3806
4179
  ${this.copied ? this.t("copied") : this.t("copy")}
3807
4180
  </button>
3808
4181
  <button class="btn btn-ghost btn-sm" @click=${() => this.recoveryCodes = null}>
3809
4182
  ${this.t("done")}
3810
4183
  </button>
3811
- </div>` : s`<div class="inline">
4184
+ </div>` : r`<div class="inline">
3812
4185
  <button
3813
4186
  class="btn btn-outline btn-sm"
3814
4187
  @click=${this.onRecoveryCodes}
3815
4188
  ?disabled=${!!this.busy}
3816
4189
  >
3817
- ${this.spinner("recovery")} ${c.key}
3818
- ${e ? this.t("recoveryCodes") : this.t("generateRecoveryCodes")}
4190
+ ${this.spinner("recovery")} ${o.key}
4191
+ ${e ? this.t("viewRecoveryCodes") : this.t("generateRecoveryCodes")}
3819
4192
  </button>
3820
- ${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}
3821
4214
  </div>`}
3822
4215
  ${this.error("recovery")}
3823
4216
  </div>`
@@ -3828,25 +4221,25 @@ let p = class extends A {
3828
4221
  const e = this.stepUp, t = this.factors, i = [
3829
4222
  {
3830
4223
  factor: "totp",
3831
- icon: c.smartphone,
4224
+ icon: o.smartphone,
3832
4225
  label: this.t("mfaUseAuthenticator"),
3833
4226
  available: t?.totp ?? !0
3834
4227
  },
3835
4228
  {
3836
4229
  factor: "email",
3837
- icon: c.mail,
4230
+ icon: o.mail,
3838
4231
  label: this.t("mfaUseEmail"),
3839
4232
  available: t?.email ?? !0
3840
4233
  },
3841
4234
  {
3842
4235
  factor: "phone",
3843
- icon: c.phone,
4236
+ icon: o.phone,
3844
4237
  label: this.t("mfaUsePhone"),
3845
4238
  available: t?.phone ?? !0
3846
4239
  },
3847
4240
  {
3848
4241
  factor: "recoverycode",
3849
- icon: c.key,
4242
+ icon: o.key,
3850
4243
  label: this.t("mfaUseRecoveryCode"),
3851
4244
  available: t?.recoveryCode ?? !0
3852
4245
  }
@@ -3854,8 +4247,8 @@ let p = class extends A {
3854
4247
  return this.card(
3855
4248
  this.t("mfaTitle"),
3856
4249
  this.t("errorChallengeRequired"),
3857
- s`<div class="kv">
3858
- ${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>
3859
4252
  <div class="field">
3860
4253
  <label class="label" for="acc-stepup"
3861
4254
  >${e.challenge.factor === "recoverycode" ? this.t("recoveryCode") : this.t("code")}</label
@@ -3863,6 +4256,9 @@ let p = class extends A {
3863
4256
  <input
3864
4257
  class="input ${e.challenge.factor === "recoverycode" ? "mono" : "input-otp"}"
3865
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]*"}
3866
4262
  autocomplete="one-time-code"
3867
4263
  required
3868
4264
  .value=${this.stepUpCode}
@@ -3872,21 +4268,21 @@ let p = class extends A {
3872
4268
  <button class="btn btn-primary btn-sm" type="submit" ?disabled=${!!this.busy}>
3873
4269
  ${this.spinner("stepup-code")} ${this.t("verifyCode")}
3874
4270
  </button>
3875
- </form>` : s`<div class="stack-sm">
3876
- ${i.filter((r) => r.available).map(
3877
- (r) => s`<button
4271
+ </form>` : r`<div class="stack-sm">
4272
+ ${i.filter((s) => s.available).map(
4273
+ (s) => r`<button
3878
4274
  type="button"
3879
4275
  class="choice"
3880
- @click=${() => this.onStepUpFactor(r.factor)}
4276
+ @click=${() => this.onStepUpFactor(s.factor)}
3881
4277
  ?disabled=${!!this.busy}
3882
4278
  >
3883
- ${r.icon}<span class="choice-title">${r.label}</span>
4279
+ ${s.icon}<span class="choice-title">${s.label}</span>
3884
4280
  </button>`
3885
4281
  )}
3886
4282
  </div>`}
3887
4283
  ${this.error("stepup")} ${this.error("stepup-code")}
3888
4284
  </div>`,
3889
- 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}>
3890
4286
  ${this.t("cancel")}
3891
4287
  </button>`
3892
4288
  );
@@ -3894,24 +4290,24 @@ let p = class extends A {
3894
4290
  // ── Sessions ──
3895
4291
  deviceIcon(e) {
3896
4292
  const t = (e.deviceName || "").toLowerCase(), i = (e.osName || e.osCode || "").toLowerCase();
3897
- 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;
3898
4294
  }
3899
4295
  renderSessions() {
3900
4296
  const e = this.sessions;
3901
- return s`<div class="section">
4297
+ return r`<div class="section">
3902
4298
  ${this.card(
3903
4299
  this.t("sessions"),
3904
4300
  void 0,
3905
- s`${this.error("sessions")}
3906
- ${e === null ? s`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? s`<div class="empty">${this.t("noActivity")}</div>` : e.map(
3907
- (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">
3908
4304
  <div class="inline">
3909
4305
  <span class="device">${this.deviceIcon(t)}</span>
3910
4306
  <div class="row-main">
3911
4307
  <span class="row-title">
3912
4308
  ${t.clientName || t.provider}
3913
- ${t.clientVersion ? s`<span class="muted small">${t.clientVersion}</span>` : o}
3914
- ${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}
3915
4311
  </span>
3916
4312
  <span class="row-sub"
3917
4313
  >${[t.osName, t.countryName || t.countryCode, t.ip].filter(Boolean).join(" · ")}</span
@@ -3919,14 +4315,14 @@ let p = class extends A {
3919
4315
  </div>
3920
4316
  </div>
3921
4317
  <div class="row-actions">
3922
- ${this.busy === `session-${t.$id}` ? s`<span class="spinner"></span>` : o}
4318
+ ${this.busy === `session-${t.$id}` ? r`<span class="spinner"></span>` : c}
3923
4319
  <button
3924
4320
  class="btn btn-ghost btn-sm"
3925
4321
  @click=${() => this.onDeleteSession(t.$id)}
3926
4322
  ?disabled=${!!this.busy}
3927
4323
  aria-label=${this.t("signOutSession")}
3928
4324
  >
3929
- ${c.logOut}
4325
+ ${o.logOut}
3930
4326
  </button>
3931
4327
  </div>
3932
4328
  </div>`
@@ -3935,14 +4331,28 @@ let p = class extends A {
3935
4331
  ${this.card(
3936
4332
  this.t("signOutAllSessions"),
3937
4333
  this.t("signOutAllSessionsDescription"),
3938
- s`${this.error("sessions-all")}
3939
- <button
3940
- class="btn btn-outline btn-sm warn"
3941
- @click=${this.onSignOutAll}
3942
- ?disabled=${!!this.busy}
3943
- >
3944
- ${this.spinner("sessions-all")} ${c.logOut} ${this.t("signOutAllSessions")}
3945
- </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>`}`,
3946
4356
  void 0,
3947
4357
  !0
3948
4358
  )}
@@ -3951,38 +4361,57 @@ let p = class extends A {
3951
4361
  // ── Connections ──
3952
4362
  renderConnections() {
3953
4363
  const e = this.identities, t = this.config?.methods?.oauth ?? [];
3954
- return s`<div class="section">
4364
+ return r`<div class="section">
3955
4365
  ${this.card(
3956
4366
  this.t("connections"),
3957
4367
  void 0,
3958
- s`${this.error("identities")}
3959
- ${e === null ? s`<div class="empty"><span class="spinner"></span></div>` : e.length === 0 ? s`<div class="empty">${this.t("noConnections")}</div>` : e.map(
3960
- (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">
3961
4371
  <div class="inline">
3962
- <span class="device">${K(i.provider)}</span>
4372
+ <span class="device">${Y(i.provider)}</span>
3963
4373
  <div class="row-main">
3964
- <span class="row-title">${D(i.provider)}</span>
4374
+ <span class="row-title">${R(i.provider)}</span>
3965
4375
  <span class="row-sub">${i.providerEmail || i.providerUid}</span>
3966
4376
  </div>
3967
4377
  </div>
3968
4378
  <div class="row-actions">
3969
- <button
3970
- class="btn btn-ghost btn-sm"
3971
- @click=${() => this.onDeleteIdentity(i.$id)}
3972
- ?disabled=${!!this.busy}
3973
- >
3974
- ${this.busy === `identity-${i.$id}` ? s`<span class="spinner"></span>` : o}
3975
- ${this.t("disconnect")}
3976
- </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>`}
3977
4402
  </div>
3978
4403
  </div>`
3979
4404
  )}`,
3980
- t.length > 0 ? s`${t.filter((i) => !(e ?? []).some((r) => r.provider === i)).map(
3981
- (i) => s`<button
4405
+ t.length > 0 ? r`${t.filter((i) => !(e ?? []).some((s) => s.provider === i)).map(
4406
+ (i) => r`<button
3982
4407
  class="btn btn-outline btn-sm"
3983
- @click=${() => n.signInWithOAuth(i)}
4408
+ @click=${() => {
4409
+ this.run(`connect-${i}`, () => n.signInWithOAuth(i));
4410
+ }}
4411
+ ?disabled=${!!this.busy}
3984
4412
  >
3985
- ${K(i)} ${D(i)}
4413
+ ${this.spinner(`connect-${i}`)} ${Y(i)}
4414
+ ${this.t("connectProvider", { provider: R(i) })}
3986
4415
  </button>`
3987
4416
  )}` : void 0
3988
4417
  )}
@@ -3991,12 +4420,12 @@ let p = class extends A {
3991
4420
  // ── Activity ──
3992
4421
  renderActivity() {
3993
4422
  const e = this.logs;
3994
- return s`<div class="section">
4423
+ return r`<div class="section">
3995
4424
  ${this.card(
3996
4425
  this.t("activity"),
3997
4426
  void 0,
3998
- 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(
3999
- (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">
4000
4429
  <div class="row-main">
4001
4430
  <span class="row-title">${t.event}</span>
4002
4431
  <span class="row-sub"
@@ -4010,15 +4439,18 @@ let p = class extends A {
4010
4439
  </div>`;
4011
4440
  }
4012
4441
  };
4013
- p.styles = [
4442
+ u.styles = [
4014
4443
  ...A.styles,
4015
4444
  I`
4016
4445
  :host {
4017
4446
  display: block;
4018
4447
  width: 100%;
4019
4448
  max-width: 560px;
4449
+ min-width: 0;
4020
4450
  }
4021
4451
  .panel {
4452
+ min-width: 0;
4453
+ overflow: hidden;
4022
4454
  background: var(--authui-card);
4023
4455
  color: var(--authui-card-foreground);
4024
4456
  border: 1px solid var(--authui-border);
@@ -4039,6 +4471,22 @@ p.styles = [
4039
4471
  display: flex;
4040
4472
  align-items: center;
4041
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;
4042
4490
  }
4043
4491
  .identity .avatar {
4044
4492
  width: 44px;
@@ -4089,102 +4537,117 @@ p.styles = [
4089
4537
  }
4090
4538
  `
4091
4539
  ];
4092
- g([
4093
- f({ type: Boolean })
4094
- ], p.prototype, "embedded", 2);
4095
- g([
4096
- f({ type: String })
4097
- ], p.prototype, "tab", 2);
4098
- 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([
4099
4547
  d()
4100
- ], p.prototype, "active", 2);
4101
- g([
4548
+ ], u.prototype, "active", 2);
4549
+ f([
4102
4550
  d()
4103
- ], p.prototype, "busy", 2);
4104
- g([
4551
+ ], u.prototype, "busy", 2);
4552
+ f([
4105
4553
  d()
4106
- ], p.prototype, "notice", 2);
4107
- g([
4554
+ ], u.prototype, "notice", 2);
4555
+ f([
4108
4556
  d()
4109
- ], p.prototype, "errors", 2);
4110
- g([
4557
+ ], u.prototype, "errors", 2);
4558
+ f([
4111
4559
  d()
4112
- ], p.prototype, "nameInput", 2);
4113
- g([
4560
+ ], u.prototype, "nameInput", 2);
4561
+ f([
4114
4562
  d()
4115
- ], p.prototype, "emailInput", 2);
4116
- g([
4563
+ ], u.prototype, "emailInput", 2);
4564
+ f([
4117
4565
  d()
4118
- ], p.prototype, "emailPassword", 2);
4119
- g([
4566
+ ], u.prototype, "emailPassword", 2);
4567
+ f([
4120
4568
  d()
4121
- ], p.prototype, "phoneInput", 2);
4122
- g([
4569
+ ], u.prototype, "phoneInput", 2);
4570
+ f([
4123
4571
  d()
4124
- ], p.prototype, "phonePassword", 2);
4125
- g([
4572
+ ], u.prototype, "phonePassword", 2);
4573
+ f([
4126
4574
  d()
4127
- ], p.prototype, "phoneCode", 2);
4128
- g([
4575
+ ], u.prototype, "phoneCode", 2);
4576
+ f([
4129
4577
  d()
4130
- ], p.prototype, "phoneCodeSent", 2);
4131
- g([
4578
+ ], u.prototype, "phoneCodeSent", 2);
4579
+ f([
4132
4580
  d()
4133
- ], p.prototype, "guestName", 2);
4134
- g([
4581
+ ], u.prototype, "guestName", 2);
4582
+ f([
4135
4583
  d()
4136
- ], p.prototype, "oldPassword", 2);
4137
- g([
4584
+ ], u.prototype, "oldPassword", 2);
4585
+ f([
4138
4586
  d()
4139
- ], p.prototype, "newPassword", 2);
4140
- g([
4587
+ ], u.prototype, "newPassword", 2);
4588
+ f([
4141
4589
  d()
4142
- ], p.prototype, "newPasswordConfirm", 2);
4143
- g([
4590
+ ], u.prototype, "newPasswordConfirm", 2);
4591
+ f([
4144
4592
  d()
4145
- ], p.prototype, "authenticator", 2);
4146
- g([
4593
+ ], u.prototype, "authenticator", 2);
4594
+ f([
4147
4595
  d()
4148
- ], p.prototype, "authenticatorCode", 2);
4149
- g([
4596
+ ], u.prototype, "authenticatorCode", 2);
4597
+ f([
4150
4598
  d()
4151
- ], p.prototype, "factors", 2);
4152
- g([
4599
+ ], u.prototype, "factors", 2);
4600
+ f([
4153
4601
  d()
4154
- ], p.prototype, "recoveryCodes", 2);
4155
- g([
4602
+ ], u.prototype, "recoveryCodes", 2);
4603
+ f([
4156
4604
  d()
4157
- ], p.prototype, "stepUp", 2);
4158
- g([
4605
+ ], u.prototype, "stepUp", 2);
4606
+ f([
4159
4607
  d()
4160
- ], p.prototype, "stepUpCode", 2);
4161
- g([
4608
+ ], u.prototype, "stepUpCode", 2);
4609
+ f([
4162
4610
  d()
4163
- ], p.prototype, "copied", 2);
4164
- g([
4611
+ ], u.prototype, "copied", 2);
4612
+ f([
4165
4613
  d()
4166
- ], p.prototype, "sessions", 2);
4167
- g([
4614
+ ], u.prototype, "sessions", 2);
4615
+ f([
4168
4616
  d()
4169
- ], p.prototype, "identities", 2);
4170
- g([
4617
+ ], u.prototype, "identities", 2);
4618
+ f([
4171
4619
  d()
4172
- ], p.prototype, "logs", 2);
4173
- g([
4620
+ ], u.prototype, "logs", 2);
4621
+ f([
4174
4622
  d()
4175
- ], p.prototype, "logsSupported", 2);
4176
- g([
4623
+ ], u.prototype, "logsSupported", 2);
4624
+ f([
4177
4625
  d()
4178
- ], p.prototype, "confirmDelete", 2);
4179
- p = g([
4180
- _("authui-account")
4181
- ], p);
4182
- var Ft = Object.defineProperty, zt = Object.getOwnPropertyDescriptor, O = (e, t, i, r) => {
4183
- for (var a = r > 1 ? void 0 : r ? zt(t, i) : t, h = e.length - 1, u; h >= 0; h--)
4184
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
4185
- return r && a && Ft(t, i, a), a;
4626
+ ], u.prototype, "confirmDelete", 2);
4627
+ f([
4628
+ d()
4629
+ ], u.prototype, "confirmRegenerate", 2);
4630
+ f([
4631
+ d()
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;
4186
4649
  };
4187
- let E = class extends A {
4650
+ let M = class extends A {
4188
4651
  constructor() {
4189
4652
  super(...arguments), this.open = !1, this.view = "sign-in", this.closeOnSuccess = !0, this.handledPending = null, this.onOpenEvent = (e) => {
4190
4653
  const t = e.detail ?? {};
@@ -4205,29 +4668,38 @@ let E = class extends A {
4205
4668
  super.disconnectedCallback(), window.removeEventListener("authui:open", this.onOpenEvent), window.removeEventListener("authui:close", this.onCloseEvent);
4206
4669
  }
4207
4670
  show(e) {
4208
- 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;
4209
4672
  }
4210
4673
  hide() {
4211
4674
  this.open = !1;
4212
4675
  }
4213
4676
  updated(e) {
4214
- 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")) {
4215
4678
  const t = this.auth.pending;
4216
- 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");
4217
4680
  }
4218
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
+ }
4219
4690
  render() {
4220
- const e = this.view === "account";
4221
- return s`
4691
+ const e = this.auth.status === "signed-in", t = this.view === "account" && e;
4692
+ return r`
4222
4693
  <dialog
4223
- class=${e ? "wide" : ""}
4224
- aria-labelledby="authui-title"
4694
+ class=${t ? "wide" : ""}
4695
+ aria-label=${t ? this.t("dialogAccount") : this.t("dialogSignIn")}
4225
4696
  @close=${() => this.open = !1}
4226
- @cancel=${(t) => {
4227
- t.preventDefault(), this.hide();
4697
+ @cancel=${(i) => {
4698
+ i.preventDefault(), this.hide();
4228
4699
  }}
4229
4700
  @click=${this.onBackdrop}
4230
4701
  @authui-open=${this.onInnerOpen}
4702
+ @authui-success=${this.onSuccess}
4231
4703
  >
4232
4704
  <div class="body">
4233
4705
  <button
@@ -4235,19 +4707,18 @@ let E = class extends A {
4235
4707
  @click=${this.hide}
4236
4708
  aria-label=${this.t("close")}
4237
4709
  >
4238
- ${c.x}
4710
+ ${o.x}
4239
4711
  </button>
4240
- ${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
4241
4713
  embedded
4242
- .view=${this.view}
4243
- @authui-success=${this.onSuccess}
4244
- ></authui-sign-in>` : o}
4714
+ .view=${this.view === "account" ? "sign-in" : this.view}
4715
+ ></authui-sign-in>` : c}
4245
4716
  </div>
4246
4717
  </dialog>
4247
4718
  `;
4248
4719
  }
4249
4720
  };
4250
- E.styles = [
4721
+ M.styles = [
4251
4722
  ...A.styles,
4252
4723
  I`
4253
4724
  :host {
@@ -4309,46 +4780,38 @@ E.styles = [
4309
4780
  }
4310
4781
  `
4311
4782
  ];
4312
- O([
4313
- f({ type: Boolean, reflect: !0 })
4314
- ], E.prototype, "open", 2);
4315
- O([
4316
- f({ type: String })
4317
- ], E.prototype, "view", 2);
4318
- O([
4319
- f({ type: Boolean, attribute: "close-on-success" })
4320
- ], E.prototype, "closeOnSuccess", 2);
4321
- O([
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
+ _([
4322
4793
  d()
4323
- ], E.prototype, "handledPending", 2);
4324
- O([
4325
- rt("dialog")
4326
- ], E.prototype, "dialog", 2);
4327
- E = O([
4328
- _("authui-modal")
4329
- ], E);
4330
- function Y(e) {
4331
- typeof document > "u" || (document.querySelector("authui-modal") || document.body.appendChild(document.createElement("authui-modal")), queueMicrotask(() => {
4332
- window.dispatchEvent(new CustomEvent("authui:open", { detail: { view: e } }));
4333
- }));
4334
- }
4335
- function Bt() {
4336
- typeof window > "u" || window.dispatchEvent(new CustomEvent("authui:close"));
4337
- }
4338
- var Ot = Object.defineProperty, Dt = Object.getOwnPropertyDescriptor, j = (e, t, i, r) => {
4339
- for (var a = r > 1 ? void 0 : r ? Dt(t, i) : t, h = e.length - 1, u; h >= 0; h--)
4340
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
4341
- return r && a && Ot(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;
4342
4805
  };
4343
- let z = class extends A {
4806
+ let D = class extends A {
4344
4807
  constructor() {
4345
4808
  super(...arguments), this.view = "sign-in", this.variant = "primary", this.size = "md";
4346
4809
  }
4347
4810
  render() {
4348
4811
  const e = this.size === "md" ? "" : `btn-${this.size}`;
4349
- return s`<button
4812
+ return r`<button
4350
4813
  class="btn btn-${this.variant} ${e}"
4351
- @click=${() => Y(this.view)}
4814
+ @click=${() => H(this.view)}
4352
4815
  part="button"
4353
4816
  >
4354
4817
  <slot
@@ -4357,7 +4820,7 @@ let z = class extends A {
4357
4820
  </button>`;
4358
4821
  }
4359
4822
  };
4360
- z.styles = [
4823
+ D.styles = [
4361
4824
  ...A.styles,
4362
4825
  I`
4363
4826
  :host {
@@ -4368,29 +4831,42 @@ z.styles = [
4368
4831
  }
4369
4832
  `
4370
4833
  ];
4371
- j([
4372
- f({ type: String })
4373
- ], z.prototype, "view", 2);
4374
- j([
4375
- f({ type: String })
4376
- ], z.prototype, "variant", 2);
4377
- j([
4378
- f({ type: String })
4379
- ], z.prototype, "size", 2);
4380
- z = j([
4381
- _("authui-button")
4382
- ], z);
4383
- var Lt = Object.defineProperty, Rt = Object.getOwnPropertyDescriptor, Q = (e, t, i, r) => {
4384
- for (var a = r > 1 ? void 0 : r ? Rt(t, i) : t, h = e.length - 1, u; h >= 0; h--)
4385
- (u = e[h]) && (a = (r ? u(t, i, a) : u(a)) || a);
4386
- return r && a && Lt(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;
4387
4850
  };
4388
- let R = class extends A {
4851
+ let q = class extends A {
4389
4852
  constructor() {
4390
4853
  super(...arguments), this.src = "", this.menuOpen = !1, this.onDocumentClick = (e) => {
4391
4854
  e.composedPath().includes(this) || (this.menuOpen = !1);
4392
4855
  }, this.onKeydown = (e) => {
4393
- 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));
4394
4870
  };
4395
4871
  }
4396
4872
  connectedCallback() {
@@ -4399,16 +4875,24 @@ let R = class extends A {
4399
4875
  disconnectedCallback() {
4400
4876
  super.disconnectedCallback(), document.removeEventListener("click", this.onDocumentClick, !0), document.removeEventListener("keydown", this.onKeydown), this.removeEventListener("keydown", this.onKeydown);
4401
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));
4885
+ }
4402
4886
  render() {
4403
4887
  const { status: e, user: t } = this.auth;
4404
4888
  if (e === "loading")
4405
- return s`<span class="avatar"><span class="spinner"></span></span>`;
4889
+ return r`<span class="avatar"><span class="spinner"></span></span>`;
4406
4890
  if (e !== "signed-in" || !t)
4407
- 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")}>
4408
4892
  <slot>${this.t("signIn")}</slot>
4409
4893
  </button>`;
4410
4894
  const i = t.name || t.email || t.phone || this.t("guestAccount");
4411
- return s`
4895
+ return r`
4412
4896
  <button
4413
4897
  class="trigger"
4414
4898
  aria-haspopup="menu"
@@ -4417,22 +4901,22 @@ let R = class extends A {
4417
4901
  aria-label=${i}
4418
4902
  >
4419
4903
  <span class="avatar"
4420
- >${this.src ? s`<img src=${this.src} alt="" />` : i[0] ?? "?"}</span
4904
+ >${this.src ? r`<img src=${this.src} alt="" />` : Q(i)}</span
4421
4905
  >
4422
4906
  </button>
4423
- ${this.menuOpen ? s`<div class="menu" role="menu">
4907
+ ${this.menuOpen ? r`<div class="menu" role="menu">
4424
4908
  <div class="menu-header">
4425
- <span class="row-title">${i}</span>
4426
- ${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}
4427
4911
  </div>
4428
4912
  <button
4429
4913
  class="menu-item"
4430
4914
  role="menuitem"
4431
4915
  @click=${() => {
4432
- this.menuOpen = !1, Y("account");
4916
+ this.menuOpen = !1, H("account");
4433
4917
  }}
4434
4918
  >
4435
- ${c.settings} ${this.t("manageAccount")}
4919
+ ${o.settings} ${this.t("manageAccount")}
4436
4920
  </button>
4437
4921
  <button
4438
4922
  class="menu-item"
@@ -4441,13 +4925,13 @@ let R = class extends A {
4441
4925
  this.menuOpen = !1, n.signOut();
4442
4926
  }}
4443
4927
  >
4444
- ${c.logOut} ${this.t("signOut")}
4928
+ ${o.logOut} ${this.t("signOut")}
4445
4929
  </button>
4446
- </div>` : o}
4930
+ </div>` : c}
4447
4931
  `;
4448
4932
  }
4449
4933
  };
4450
- R.styles = [
4934
+ q.styles = [
4451
4935
  ...A.styles,
4452
4936
  I`
4453
4937
  :host {
@@ -4476,6 +4960,7 @@ R.styles = [
4476
4960
  top: calc(100% + 6px);
4477
4961
  inset-inline-end: 0;
4478
4962
  min-width: 220px;
4963
+ max-width: min(320px, 90vw);
4479
4964
  background: var(--authui-popover);
4480
4965
  color: var(--authui-popover-foreground);
4481
4966
  border: 1px solid var(--authui-border);
@@ -4488,6 +4973,8 @@ R.styles = [
4488
4973
  gap: 2px;
4489
4974
  }
4490
4975
  .menu-header {
4976
+ min-width: 0;
4977
+ overflow: hidden;
4491
4978
  padding: 8px 10px 10px;
4492
4979
  display: flex;
4493
4980
  flex-direction: column;
@@ -4495,6 +4982,14 @@ R.styles = [
4495
4982
  border-bottom: 1px solid var(--authui-border);
4496
4983
  margin-bottom: 4px;
4497
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
+
4498
4993
  .menu-item {
4499
4994
  display: flex;
4500
4995
  align-items: center;
@@ -4527,32 +5022,32 @@ R.styles = [
4527
5022
  }
4528
5023
  `
4529
5024
  ];
4530
- Q([
4531
- f({ type: String })
4532
- ], R.prototype, "src", 2);
4533
- Q([
5025
+ J([
5026
+ m({ type: String })
5027
+ ], q.prototype, "src", 2);
5028
+ J([
4534
5029
  d()
4535
- ], R.prototype, "menuOpen", 2);
4536
- R = Q([
4537
- _("authui-user-button")
4538
- ], R);
5030
+ ], q.prototype, "menuOpen", 2);
5031
+ q = J([
5032
+ O("authui-user-button")
5033
+ ], q);
4539
5034
  export {
4540
- gt as A,
5035
+ vt as A,
4541
5036
  v as E,
4542
- ft as P,
5037
+ mt as P,
4543
5038
  n as a,
4544
- p as b,
4545
- Bt as c,
4546
- z as d,
5039
+ u as b,
5040
+ Ht as c,
5041
+ D as d,
4547
5042
  b as e,
4548
5043
  A as f,
4549
- E as g,
4550
- L as h,
5044
+ M as g,
5045
+ V as h,
4551
5046
  $ as i,
4552
- R as j,
4553
- dt as k,
4554
- at as l,
4555
- Y as o,
4556
- D as p,
4557
- N 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
4558
5053
  };