@lalternative/auth 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ function AuthField({
21
21
  hint,
22
22
  description,
23
23
  invalid = false,
24
+ fieldClassName = "border-foreground/30 bg-background",
24
25
  ...props
25
26
  }) {
26
27
  const id = useId();
@@ -34,7 +35,7 @@ function AuthField({
34
35
  "label",
35
36
  {
36
37
  htmlFor: id,
37
- className: "text-sm font-medium leading-none text-foreground",
38
+ className: "text-[0.6875rem] font-semibold uppercase leading-none tracking-[0.09em] text-foreground/70",
38
39
  children: label
39
40
  }
40
41
  ),
@@ -50,13 +51,16 @@ function AuthField({
50
51
  "aria-invalid": invalid || void 0,
51
52
  "aria-describedby": descriptionId,
52
53
  className: [
53
- "h-[52px] w-full rounded-xl border bg-background px-4 text-base",
54
- "sm:h-11 sm:text-sm",
54
+ "h-[52px] w-full rounded-md border px-3.5 text-base",
55
+ "sm:h-[46px] sm:text-[0.9375rem]",
55
56
  isPassword ? "pr-12" : "",
56
- "text-foreground placeholder:text-muted-foreground/70",
57
- "transition-[border-color,box-shadow] duration-150 ease-out",
58
- "focus-visible:outline-none focus-visible:ring-[3px]",
59
- invalid ? "border-destructive focus-visible:border-destructive focus-visible:ring-destructive/20" : "border-input focus-visible:border-ring focus-visible:ring-ring/15",
57
+ "text-foreground placeholder:text-muted-foreground/60",
58
+ // Focus reads as the border committing rather than as a halo
59
+ // appearing beside it: the ring is tight and the border darkens to
60
+ // full ink in the same 180ms, so the field answers the caret.
61
+ "transition-[border-color,box-shadow] duration-200 ease-out",
62
+ "focus-visible:outline-none focus-visible:ring-2",
63
+ invalid ? "border-destructive bg-background focus-visible:border-destructive focus-visible:ring-destructive/15" : `${fieldClassName} focus-visible:border-foreground focus-visible:ring-foreground/10`,
60
64
  "disabled:cursor-not-allowed disabled:opacity-60"
61
65
  ].filter(Boolean).join(" ")
62
66
  }
@@ -105,7 +109,9 @@ function AuthSubmit({
105
109
  pending = false,
106
110
  disabled = false,
107
111
  pendingLabel,
108
- children
112
+ children,
113
+ className = "bg-primary text-primary-foreground hover:bg-primary/90",
114
+ spacedAbove = false
109
115
  }) {
110
116
  return /* @__PURE__ */ jsxs2(
111
117
  "button",
@@ -114,10 +120,16 @@ function AuthSubmit({
114
120
  disabled: disabled || pending,
115
121
  "aria-busy": pending || void 0,
116
122
  className: [
117
- "relative flex h-[52px] w-full items-center justify-center rounded-xl sm:h-11",
118
- "bg-primary text-base font-medium text-primary-foreground sm:text-sm",
119
- "shadow-sm transition-[background-color,transform,box-shadow] duration-150 ease-out",
120
- "hover:bg-primary/90 active:translate-y-px",
123
+ spacedAbove ? "!mt-7" : "",
124
+ "relative flex h-[52px] w-full items-center justify-center rounded-md sm:h-[46px]",
125
+ // Slightly tracked at this weight: a wide solid button set in plain
126
+ // medium reads as a slab, and the letterspacing is what makes it read
127
+ // as typeset rather than filled in.
128
+ "text-[0.9375rem] font-medium tracking-[0.01em]",
129
+ className,
130
+ "transition-[background-color,transform,box-shadow] duration-200 ease-out",
131
+ "shadow-[0_1px_2px_rgba(0,0,0,0.08)] hover:shadow-[0_2px_8px_rgba(0,0,0,0.12)]",
132
+ "active:translate-y-px active:shadow-[0_1px_2px_rgba(0,0,0,0.08)]",
121
133
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
122
134
  "disabled:pointer-events-none disabled:opacity-55"
123
135
  ].join(" "),
@@ -147,7 +159,7 @@ function AuthAlert({ children, tone = "error" }) {
147
159
  role: tone === "error" ? "alert" : "status",
148
160
  "aria-live": tone === "error" ? "assertive" : "polite",
149
161
  className: children ? [
150
- "rounded-xl border px-3.5 py-3 text-sm leading-snug",
162
+ "rounded-lg border px-3.5 py-3 text-sm leading-snug",
151
163
  tone === "error" ? "border-destructive/25 bg-destructive/10 text-destructive" : "border-emerald-500/25 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400"
152
164
  ].join(" ") : void 0,
153
165
  children
@@ -155,21 +167,8 @@ function AuthAlert({ children, tone = "error" }) {
155
167
  );
156
168
  }
157
169
 
158
- // src/components/auth-heading.tsx
159
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
160
- function AuthHeading({
161
- title,
162
- subtitle,
163
- titleClassName = "text-2xl font-semibold tracking-tight"
164
- }) {
165
- return /* @__PURE__ */ jsxs3("header", { className: "space-y-1.5 text-center", children: [
166
- /* @__PURE__ */ jsx4("h1", { className: `leading-tight text-foreground ${titleClassName}`, children: title }),
167
- subtitle && /* @__PURE__ */ jsx4("p", { className: "text-balance text-sm leading-relaxed text-muted-foreground", children: subtitle })
168
- ] });
169
- }
170
-
171
170
  // src/components/social-buttons.tsx
172
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
171
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
173
172
  var LABELS = {
174
173
  google: "Continuer avec Google",
175
174
  github: "Continuer avec GitHub"
@@ -183,17 +182,17 @@ function SocialButtons({
183
182
  }) {
184
183
  if (providers.length === 0) return null;
185
184
  const copy = { ...LABELS, ...labels };
186
- return /* @__PURE__ */ jsxs4("div", { className: "space-y-4", children: [
187
- /* @__PURE__ */ jsxs4("div", { "aria-hidden": "true", className: "flex items-center gap-3", children: [
188
- /* @__PURE__ */ jsx5("span", { className: "h-px flex-1 bg-border" }),
189
- /* @__PURE__ */ jsx5("span", { className: "text-[11px] uppercase tracking-[0.14em] text-muted-foreground", children: separator }),
190
- /* @__PURE__ */ jsx5("span", { className: "h-px flex-1 bg-border" })
185
+ return /* @__PURE__ */ jsxs3("div", { className: "space-y-4", children: [
186
+ /* @__PURE__ */ jsxs3("div", { "aria-hidden": "true", className: "flex items-center gap-3", children: [
187
+ /* @__PURE__ */ jsx4("span", { className: "h-px flex-1 bg-border" }),
188
+ /* @__PURE__ */ jsx4("span", { className: "text-[11px] uppercase tracking-[0.14em] text-muted-foreground", children: separator }),
189
+ /* @__PURE__ */ jsx4("span", { className: "h-px flex-1 bg-border" })
191
190
  ] }),
192
- /* @__PURE__ */ jsx5(
191
+ /* @__PURE__ */ jsx4(
193
192
  "div",
194
193
  {
195
194
  className: providers.length > 1 ? "grid gap-2.5 sm:grid-cols-2" : "grid gap-2.5",
196
- children: providers.map((provider) => /* @__PURE__ */ jsxs4(
195
+ children: providers.map((provider) => /* @__PURE__ */ jsxs3(
197
196
  "button",
198
197
  {
199
198
  type: "button",
@@ -201,16 +200,16 @@ function SocialButtons({
201
200
  disabled,
202
201
  "aria-label": copy[provider] ?? provider,
203
202
  className: [
204
- "flex h-[52px] w-full items-center justify-center gap-2.5 rounded-xl sm:h-11",
205
- "border border-input bg-background text-base font-medium text-foreground sm:text-sm",
203
+ "flex h-[52px] w-full items-center justify-center gap-2.5 rounded-lg sm:h-11",
204
+ "border border-foreground/25 bg-background text-base font-medium text-foreground sm:text-sm",
206
205
  "transition-[background-color,border-color,transform] duration-150 ease-out",
207
206
  "hover:border-foreground/20 hover:bg-accent active:translate-y-px",
208
207
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
209
208
  "disabled:pointer-events-none disabled:opacity-55"
210
209
  ].join(" "),
211
210
  children: [
212
- /* @__PURE__ */ jsx5(ProviderMark, { provider }),
213
- /* @__PURE__ */ jsx5("span", { className: providers.length > 1 ? "sm:hidden" : "", children: copy[provider] ?? provider })
211
+ /* @__PURE__ */ jsx4(ProviderMark, { provider }),
212
+ /* @__PURE__ */ jsx4("span", { className: providers.length > 1 ? "sm:hidden" : "", children: copy[provider] ?? provider })
214
213
  ]
215
214
  },
216
215
  provider
@@ -221,29 +220,29 @@ function SocialButtons({
221
220
  }
222
221
  function ProviderMark({ provider }) {
223
222
  if (provider === "google") {
224
- return /* @__PURE__ */ jsxs4("svg", { width: "17", height: "17", viewBox: "0 0 18 18", "aria-hidden": "true", children: [
225
- /* @__PURE__ */ jsx5(
223
+ return /* @__PURE__ */ jsxs3("svg", { width: "17", height: "17", viewBox: "0 0 18 18", "aria-hidden": "true", children: [
224
+ /* @__PURE__ */ jsx4(
226
225
  "path",
227
226
  {
228
227
  fill: "#4285F4",
229
228
  d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62Z"
230
229
  }
231
230
  ),
232
- /* @__PURE__ */ jsx5(
231
+ /* @__PURE__ */ jsx4(
233
232
  "path",
234
233
  {
235
234
  fill: "#34A853",
236
235
  d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.02-3.7H.96v2.33A9 9 0 0 0 9 18Z"
237
236
  }
238
237
  ),
239
- /* @__PURE__ */ jsx5(
238
+ /* @__PURE__ */ jsx4(
240
239
  "path",
241
240
  {
242
241
  fill: "#FBBC05",
243
242
  d: "M3.98 10.72a5.4 5.4 0 0 1 0-3.44V4.95H.96a9 9 0 0 0 0 8.1l3.02-2.33Z"
244
243
  }
245
244
  ),
246
- /* @__PURE__ */ jsx5(
245
+ /* @__PURE__ */ jsx4(
247
246
  "path",
248
247
  {
249
248
  fill: "#EA4335",
@@ -252,11 +251,36 @@ function ProviderMark({ provider }) {
252
251
  )
253
252
  ] });
254
253
  }
255
- return /* @__PURE__ */ jsx5("svg", { width: "17", height: "17", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("path", { d: "M8 0a8 8 0 0 0-2.53 15.59c.4.07.55-.17.55-.38l-.01-1.49c-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.4 7.4 0 0 1 4 0c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48l-.01 2.2c0 .21.15.46.55.38A8 8 0 0 0 8 0Z" }) });
254
+ return /* @__PURE__ */ jsx4("svg", { width: "17", height: "17", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx4("path", { d: "M8 0a8 8 0 0 0-2.53 15.59c.4.07.55-.17.55-.38l-.01-1.49c-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.4 7.4 0 0 1 4 0c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48l-.01 2.2c0 .21.15.46.55.38A8 8 0 0 0 8 0Z" }) });
255
+ }
256
+
257
+ // src/components/auth-link.tsx
258
+ import { jsx as jsx5 } from "react/jsx-runtime";
259
+ function AuthLink({ to, as: Link, className, children }) {
260
+ if (Link) {
261
+ return /* @__PURE__ */ jsx5(Link, { to, className, children });
262
+ }
263
+ return /* @__PURE__ */ jsx5("a", { href: to, className, children });
264
+ }
265
+ var AUTH_LINK_CLASS = "rounded font-medium text-foreground underline underline-offset-4 decoration-foreground/25 transition-colors hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
266
+ var AUTH_HINT_LINK_CLASS = "rounded text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
267
+
268
+ // src/invite-token.ts
269
+ var MAX_TOKEN_LENGTH = 128;
270
+ function normalizeInviteToken(value) {
271
+ if (typeof value !== "string") return void 0;
272
+ const trimmed = value.trim();
273
+ if (!trimmed || trimmed.length > MAX_TOKEN_LENGTH) return void 0;
274
+ return trimmed;
275
+ }
276
+ function withInviteToken(href, token) {
277
+ if (!token) return href;
278
+ const separator = href.includes("?") ? "&" : "?";
279
+ return `${href}${separator}invite=${encodeURIComponent(token)}`;
256
280
  }
257
281
 
258
282
  // src/components/login-form.tsx
259
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
283
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
260
284
  var DEFAULTS = {
261
285
  title: "Connexion",
262
286
  subtitle: "Content de te revoir. Entre tes identifiants pour continuer.",
@@ -285,8 +309,11 @@ function LoginForm({
285
309
  socialProviders = [],
286
310
  coreTokenUrl = "/api/auth/core-token",
287
311
  labels,
288
- titleClassName,
312
+ submitClassName,
313
+ fieldClassName,
289
314
  error: externalError,
315
+ linkComponent,
316
+ invite,
290
317
  authClient
291
318
  }) {
292
319
  const t = { ...DEFAULTS, ...labels };
@@ -332,7 +359,9 @@ function LoginForm({
332
359
  try {
333
360
  await authClient.signIn.social({
334
361
  provider,
335
- callbackURL: socialCallbackUrl
362
+ // The invitation rides the callback: an OAuth sign-up leaves the
363
+ // browser, and the auth handler redeems the token on the way back.
364
+ callbackURL: withInviteToken(socialCallbackUrl, invite)
336
365
  });
337
366
  } catch (err) {
338
367
  const code = err instanceof Error ? err.message : "";
@@ -341,17 +370,9 @@ function LoginForm({
341
370
  );
342
371
  }
343
372
  };
344
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-7", children: [
345
- /* @__PURE__ */ jsx6(
346
- AuthHeading,
347
- {
348
- title: t.title,
349
- subtitle: t.subtitle,
350
- titleClassName
351
- }
352
- ),
373
+ return /* @__PURE__ */ jsxs4("div", { className: "space-y-7", children: [
353
374
  /* @__PURE__ */ jsx6(AuthAlert, { children: error }),
354
- /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
375
+ /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "space-y-[1.125rem]", noValidate: true, children: [
355
376
  /* @__PURE__ */ jsx6(
356
377
  AuthField,
357
378
  {
@@ -365,7 +386,8 @@ function LoginForm({
365
386
  autoComplete: "email",
366
387
  autoCapitalize: "none",
367
388
  spellCheck: false,
368
- invalid: !!error
389
+ invalid: !!error,
390
+ fieldClassName
369
391
  }
370
392
  ),
371
393
  /* @__PURE__ */ jsx6(
@@ -379,11 +401,13 @@ function LoginForm({
379
401
  disabled: isPending,
380
402
  autoComplete: "current-password",
381
403
  invalid: !!error,
404
+ fieldClassName,
382
405
  hint: /* @__PURE__ */ jsx6(
383
- "a",
406
+ AuthLink,
384
407
  {
385
- href: forgotPasswordUrl,
386
- className: "rounded text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
408
+ to: forgotPasswordUrl,
409
+ as: linkComponent,
410
+ className: AUTH_HINT_LINK_CLASS,
387
411
  children: t.forgotPassword
388
412
  }
389
413
  )
@@ -392,9 +416,11 @@ function LoginForm({
392
416
  /* @__PURE__ */ jsx6(
393
417
  AuthSubmit,
394
418
  {
419
+ spacedAbove: true,
395
420
  pending: isPending,
396
421
  disabled: !email.trim() || !password,
397
422
  pendingLabel: t.submitPending,
423
+ className: submitClassName,
398
424
  children: t.submit
399
425
  }
400
426
  )
@@ -407,24 +433,29 @@ function LoginForm({
407
433
  disabled: isPending
408
434
  }
409
435
  ),
410
- /* @__PURE__ */ jsxs5("p", { className: "text-center text-sm text-muted-foreground", children: [
436
+ /* @__PURE__ */ jsxs4("p", { className: "text-center text-sm text-muted-foreground", children: [
411
437
  t.noAccount,
412
438
  " ",
413
439
  /* @__PURE__ */ jsx6(
414
- "a",
440
+ AuthLink,
415
441
  {
416
- href: registerUrl,
417
- className: "rounded font-medium text-foreground underline underline-offset-4 decoration-foreground/25 transition-colors hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
442
+ to: withInviteToken(registerUrl, invite),
443
+ as: linkComponent,
444
+ className: AUTH_LINK_CLASS,
418
445
  children: t.register
419
446
  }
420
447
  )
421
448
  ] })
422
449
  ] });
423
450
  }
451
+ LoginForm.defaults = {
452
+ title: DEFAULTS.title,
453
+ subtitle: DEFAULTS.subtitle
454
+ };
424
455
 
425
456
  // src/components/register-form.tsx
426
457
  import { useState as useState3 } from "react";
427
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
458
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
428
459
  var MIN_PASSWORD_LENGTH = 8;
429
460
  var DEFAULTS2 = {
430
461
  title: "Cr\xE9er un compte",
@@ -433,6 +464,8 @@ var DEFAULTS2 = {
433
464
  emailPlaceholder: "Adresse e-mail",
434
465
  passwordPlaceholder: "Mot de passe",
435
466
  passwordHint: `Au moins ${MIN_PASSWORD_LENGTH} caract\xE8res.`,
467
+ confirmPlaceholder: "Confirme le mot de passe",
468
+ passwordMismatch: "Les deux mots de passe ne correspondent pas",
436
469
  submit: "Cr\xE9er mon compte",
437
470
  submitPending: "Cr\xE9ation\u2026",
438
471
  haveAccount: "Tu as d\xE9j\xE0 un compte ?",
@@ -449,19 +482,24 @@ function RegisterForm({
449
482
  socialCallbackUrl = "/",
450
483
  socialProviders = [],
451
484
  labels,
452
- titleClassName,
485
+ submitClassName,
486
+ fieldClassName,
453
487
  error: externalError,
488
+ linkComponent,
489
+ invite,
454
490
  authClient
455
491
  }) {
456
492
  const t = { ...DEFAULTS2, ...labels };
457
493
  const [name, setName] = useState3("");
458
494
  const [email, setEmail] = useState3("");
459
495
  const [password, setPassword] = useState3("");
496
+ const [confirmPassword, setConfirmPassword] = useState3("");
460
497
  const [ownError, setOwnError] = useState3();
461
498
  const [isPending, setIsPending] = useState3(false);
462
499
  const error = ownError ?? externalError;
463
500
  const setError = setOwnError;
464
501
  const tooShort = password.length > 0 && password.length < MIN_PASSWORD_LENGTH;
502
+ const mismatch = confirmPassword.length > 0 && confirmPassword !== password;
465
503
  const handleSubmit = async (e) => {
466
504
  e.preventDefault();
467
505
  if (!name.trim()) {
@@ -476,6 +514,10 @@ function RegisterForm({
476
514
  setError(t.passwordTooShort);
477
515
  return;
478
516
  }
517
+ if (password !== confirmPassword) {
518
+ setError(t.passwordMismatch);
519
+ return;
520
+ }
479
521
  setError(void 0);
480
522
  setIsPending(true);
481
523
  try {
@@ -500,23 +542,17 @@ function RegisterForm({
500
542
  try {
501
543
  await authClient.signIn.social({
502
544
  provider,
503
- callbackURL: socialCallbackUrl
545
+ // The invitation rides the callback: an OAuth sign-up leaves the
546
+ // browser, and the auth handler redeems the token on the way back.
547
+ callbackURL: withInviteToken(socialCallbackUrl, invite)
504
548
  });
505
549
  } catch (err) {
506
550
  setError(err instanceof Error ? err.message : t.signUpFailed);
507
551
  }
508
552
  };
509
- return /* @__PURE__ */ jsxs6("div", { className: "space-y-7", children: [
510
- /* @__PURE__ */ jsx7(
511
- AuthHeading,
512
- {
513
- title: t.title,
514
- subtitle: t.subtitle,
515
- titleClassName
516
- }
517
- ),
553
+ return /* @__PURE__ */ jsxs5("div", { className: "space-y-7", children: [
518
554
  /* @__PURE__ */ jsx7(AuthAlert, { children: error }),
519
- /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
555
+ /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className: "space-y-[1.125rem]", noValidate: true, children: [
520
556
  /* @__PURE__ */ jsx7(
521
557
  AuthField,
522
558
  {
@@ -526,7 +562,8 @@ function RegisterForm({
526
562
  onChange: (e) => setName(e.target.value),
527
563
  required: true,
528
564
  disabled: isPending,
529
- autoComplete: "name"
565
+ autoComplete: "name",
566
+ fieldClassName
530
567
  }
531
568
  ),
532
569
  /* @__PURE__ */ jsx7(
@@ -541,7 +578,8 @@ function RegisterForm({
541
578
  disabled: isPending,
542
579
  autoComplete: "email",
543
580
  autoCapitalize: "none",
544
- spellCheck: false
581
+ spellCheck: false,
582
+ fieldClassName
545
583
  }
546
584
  ),
547
585
  /* @__PURE__ */ jsx7(
@@ -555,10 +593,34 @@ function RegisterForm({
555
593
  disabled: isPending,
556
594
  autoComplete: "new-password",
557
595
  description: t.passwordHint,
558
- invalid: tooShort
596
+ invalid: tooShort,
597
+ fieldClassName
598
+ }
599
+ ),
600
+ /* @__PURE__ */ jsx7(
601
+ AuthField,
602
+ {
603
+ label: t.confirmPlaceholder,
604
+ type: "password",
605
+ value: confirmPassword,
606
+ onChange: (e) => setConfirmPassword(e.target.value),
607
+ required: true,
608
+ disabled: isPending,
609
+ autoComplete: "new-password",
610
+ invalid: mismatch,
611
+ fieldClassName
612
+ }
613
+ ),
614
+ /* @__PURE__ */ jsx7(
615
+ AuthSubmit,
616
+ {
617
+ spacedAbove: true,
618
+ pending: isPending,
619
+ pendingLabel: t.submitPending,
620
+ className: submitClassName,
621
+ children: t.submit
559
622
  }
560
623
  ),
561
- /* @__PURE__ */ jsx7(AuthSubmit, { pending: isPending, pendingLabel: t.submitPending, children: t.submit }),
562
624
  legal && /* @__PURE__ */ jsx7("p", { className: "text-center text-xs leading-relaxed text-muted-foreground", children: legal })
563
625
  ] }),
564
626
  /* @__PURE__ */ jsx7(
@@ -569,26 +631,31 @@ function RegisterForm({
569
631
  disabled: isPending
570
632
  }
571
633
  ),
572
- /* @__PURE__ */ jsxs6("p", { className: "text-center text-sm text-muted-foreground", children: [
634
+ /* @__PURE__ */ jsxs5("p", { className: "text-center text-sm text-muted-foreground", children: [
573
635
  t.haveAccount,
574
636
  " ",
575
637
  /* @__PURE__ */ jsx7(
576
- "a",
638
+ AuthLink,
577
639
  {
578
- href: loginUrl,
579
- className: "rounded font-medium text-foreground underline underline-offset-4 decoration-foreground/25 transition-colors hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
640
+ to: withInviteToken(loginUrl, invite),
641
+ as: linkComponent,
642
+ className: AUTH_LINK_CLASS,
580
643
  children: t.login
581
644
  }
582
645
  )
583
646
  ] })
584
647
  ] });
585
648
  }
649
+ RegisterForm.defaults = {
650
+ title: DEFAULTS2.title,
651
+ subtitle: DEFAULTS2.subtitle
652
+ };
586
653
 
587
654
  // src/components/verify-email-form.tsx
588
655
  import { useState as useState4 } from "react";
589
656
 
590
657
  // src/components/auth-otp-field.tsx
591
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
658
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
592
659
  var OTP_LENGTH = 6;
593
660
  function AuthOtpField({
594
661
  label,
@@ -596,9 +663,10 @@ function AuthOtpField({
596
663
  onChange,
597
664
  disabled = false,
598
665
  invalid = false,
599
- id
666
+ id,
667
+ fieldClassName = "border-foreground/25 bg-background"
600
668
  }) {
601
- return /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
669
+ return /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
602
670
  /* @__PURE__ */ jsx8(
603
671
  "label",
604
672
  {
@@ -622,12 +690,12 @@ function AuthOtpField({
622
690
  autoComplete: "one-time-code",
623
691
  "aria-invalid": invalid || void 0,
624
692
  className: [
625
- "h-[52px] w-full rounded-xl border bg-background px-4 sm:h-11",
693
+ "h-[52px] w-full rounded-lg border px-4 sm:h-11",
626
694
  "text-center font-mono text-lg tracking-[0.4em]",
627
695
  "text-foreground",
628
696
  "transition-[border-color,box-shadow] duration-150 ease-out",
629
697
  "focus-visible:outline-none focus-visible:ring-[3px]",
630
- invalid ? "border-destructive focus-visible:border-destructive focus-visible:ring-destructive/20" : "border-input focus-visible:border-ring focus-visible:ring-ring/15",
698
+ invalid ? "border-destructive bg-background focus-visible:border-destructive focus-visible:ring-destructive/20" : `${fieldClassName} focus-visible:border-ring focus-visible:ring-ring/15`,
631
699
  "disabled:cursor-not-allowed disabled:opacity-60"
632
700
  ].join(" ")
633
701
  }
@@ -636,7 +704,7 @@ function AuthOtpField({
636
704
  }
637
705
 
638
706
  // src/components/verify-email-form.tsx
639
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
707
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
640
708
  var DEFAULTS3 = {
641
709
  title: "V\xE9rifie ton adresse",
642
710
  subtitle: "Entre le code \xE0 6 chiffres envoy\xE9 \xE0",
@@ -659,7 +727,9 @@ function VerifyEmailForm({
659
727
  onSuccess,
660
728
  loginUrl = "/login",
661
729
  labels,
662
- titleClassName,
730
+ submitClassName,
731
+ fieldClassName,
732
+ linkComponent,
663
733
  authClient
664
734
  }) {
665
735
  const t = { ...DEFAULTS3, ...labels };
@@ -710,18 +780,10 @@ function VerifyEmailForm({
710
780
  setIsResending(false);
711
781
  }
712
782
  };
713
- return /* @__PURE__ */ jsxs8("div", { className: "space-y-7", children: [
714
- /* @__PURE__ */ jsx9(
715
- AuthHeading,
716
- {
717
- title: t.title,
718
- subtitle: email ? `${t.subtitle} ${email}.` : t.subtitleNoEmail,
719
- titleClassName
720
- }
721
- ),
783
+ return /* @__PURE__ */ jsxs7("div", { className: "space-y-7", children: [
722
784
  /* @__PURE__ */ jsx9(AuthAlert, { children: error }),
723
785
  /* @__PURE__ */ jsx9(AuthAlert, { tone: "success", children: resendMessage }),
724
- /* @__PURE__ */ jsxs8("form", { onSubmit: handleVerify, className: "space-y-5", noValidate: true, children: [
786
+ /* @__PURE__ */ jsxs7("form", { onSubmit: handleVerify, className: "space-y-[1.125rem]", noValidate: true, children: [
725
787
  /* @__PURE__ */ jsx9(
726
788
  AuthOtpField,
727
789
  {
@@ -729,20 +791,23 @@ function VerifyEmailForm({
729
791
  label: t.codePlaceholder,
730
792
  value: otp,
731
793
  onChange: setOtp,
732
- disabled: isVerifying
794
+ disabled: isVerifying,
795
+ fieldClassName
733
796
  }
734
797
  ),
735
798
  /* @__PURE__ */ jsx9(
736
799
  AuthSubmit,
737
800
  {
801
+ spacedAbove: true,
738
802
  pending: isVerifying,
739
803
  disabled: otp.length < OTP_LENGTH,
740
804
  pendingLabel: t.submitPending,
805
+ className: submitClassName,
741
806
  children: t.submit
742
807
  }
743
808
  )
744
809
  ] }),
745
- /* @__PURE__ */ jsxs8("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
810
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
746
811
  /* @__PURE__ */ jsx9(
747
812
  "button",
748
813
  {
@@ -753,14 +818,15 @@ function VerifyEmailForm({
753
818
  children: isResending ? t.resendPending : t.resend
754
819
  }
755
820
  ),
756
- /* @__PURE__ */ jsxs8("p", { children: [
821
+ /* @__PURE__ */ jsxs7("p", { children: [
757
822
  t.alreadyVerified,
758
823
  " ",
759
824
  /* @__PURE__ */ jsx9(
760
- "a",
825
+ AuthLink,
761
826
  {
762
- href: loginUrl,
763
- className: "rounded font-medium text-foreground underline underline-offset-4 decoration-foreground/25 transition-colors hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
827
+ to: loginUrl,
828
+ as: linkComponent,
829
+ className: AUTH_LINK_CLASS,
764
830
  children: t.login
765
831
  }
766
832
  )
@@ -768,10 +834,14 @@ function VerifyEmailForm({
768
834
  ] })
769
835
  ] });
770
836
  }
837
+ VerifyEmailForm.defaults = {
838
+ title: DEFAULTS3.title,
839
+ subtitle: DEFAULTS3.subtitle
840
+ };
771
841
 
772
842
  // src/components/forgot-password-form.tsx
773
843
  import { useState as useState5 } from "react";
774
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
844
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
775
845
  var DEFAULTS4 = {
776
846
  title: "Mot de passe oubli\xE9 ?",
777
847
  subtitle: "Entre ton adresse e-mail et nous t'enverrons un code pour le r\xE9initialiser.",
@@ -787,7 +857,9 @@ function ForgotPasswordForm({
787
857
  onSuccess,
788
858
  loginUrl = "/login",
789
859
  labels,
790
- titleClassName,
860
+ submitClassName,
861
+ fieldClassName,
862
+ linkComponent,
791
863
  authClient
792
864
  }) {
793
865
  const t = { ...DEFAULTS4, ...labels };
@@ -818,17 +890,9 @@ function ForgotPasswordForm({
818
890
  setIsPending(false);
819
891
  }
820
892
  };
821
- return /* @__PURE__ */ jsxs9("div", { className: "space-y-7", children: [
822
- /* @__PURE__ */ jsx10(
823
- AuthHeading,
824
- {
825
- title: t.title,
826
- subtitle: t.subtitle,
827
- titleClassName
828
- }
829
- ),
893
+ return /* @__PURE__ */ jsxs8("div", { className: "space-y-7", children: [
830
894
  /* @__PURE__ */ jsx10(AuthAlert, { children: error }),
831
- /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
895
+ /* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, className: "space-y-[1.125rem]", noValidate: true, children: [
832
896
  /* @__PURE__ */ jsx10(
833
897
  AuthField,
834
898
  {
@@ -848,31 +912,38 @@ function ForgotPasswordForm({
848
912
  /* @__PURE__ */ jsx10(
849
913
  AuthSubmit,
850
914
  {
915
+ spacedAbove: true,
851
916
  pending: isPending,
852
917
  disabled: !email.trim(),
853
918
  pendingLabel: t.submitPending,
919
+ className: submitClassName,
854
920
  children: t.submit
855
921
  }
856
922
  )
857
923
  ] }),
858
- /* @__PURE__ */ jsxs9("p", { className: "text-center text-sm text-muted-foreground", children: [
924
+ /* @__PURE__ */ jsxs8("p", { className: "text-center text-sm text-muted-foreground", children: [
859
925
  t.rememberPassword,
860
926
  " ",
861
927
  /* @__PURE__ */ jsx10(
862
- "a",
928
+ AuthLink,
863
929
  {
864
- href: loginUrl,
865
- className: "rounded font-medium text-foreground underline underline-offset-4 decoration-foreground/25 transition-colors hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
930
+ to: loginUrl,
931
+ as: linkComponent,
932
+ className: AUTH_LINK_CLASS,
866
933
  children: t.login
867
934
  }
868
935
  )
869
936
  ] })
870
937
  ] });
871
938
  }
939
+ ForgotPasswordForm.defaults = {
940
+ title: DEFAULTS4.title,
941
+ subtitle: DEFAULTS4.subtitle
942
+ };
872
943
 
873
944
  // src/components/reset-password-form.tsx
874
945
  import { useState as useState6 } from "react";
875
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
946
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
876
947
  var MIN_PASSWORD_LENGTH2 = 8;
877
948
  var DEFAULTS5 = {
878
949
  title: "Nouveau mot de passe",
@@ -899,7 +970,9 @@ function ResetPasswordForm({
899
970
  onSuccess,
900
971
  loginUrl = "/login",
901
972
  labels,
902
- titleClassName,
973
+ submitClassName,
974
+ fieldClassName,
975
+ linkComponent,
903
976
  authClient
904
977
  }) {
905
978
  const t = { ...DEFAULTS5, ...labels };
@@ -963,18 +1036,10 @@ function ResetPasswordForm({
963
1036
  setIsResending(false);
964
1037
  }
965
1038
  };
966
- return /* @__PURE__ */ jsxs10("div", { className: "space-y-7", children: [
967
- /* @__PURE__ */ jsx11(
968
- AuthHeading,
969
- {
970
- title: t.title,
971
- subtitle: t.subtitle,
972
- titleClassName
973
- }
974
- ),
1039
+ return /* @__PURE__ */ jsxs9("div", { className: "space-y-7", children: [
975
1040
  /* @__PURE__ */ jsx11(AuthAlert, { children: error }),
976
1041
  /* @__PURE__ */ jsx11(AuthAlert, { tone: "success", children: resendMessage }),
977
- /* @__PURE__ */ jsxs10("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
1042
+ /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "space-y-[1.125rem]", noValidate: true, children: [
978
1043
  /* @__PURE__ */ jsx11(
979
1044
  AuthOtpField,
980
1045
  {
@@ -982,7 +1047,8 @@ function ResetPasswordForm({
982
1047
  label: t.codePlaceholder,
983
1048
  value: otp,
984
1049
  onChange: setOtp,
985
- disabled: isResetting
1050
+ disabled: isResetting,
1051
+ fieldClassName
986
1052
  }
987
1053
  ),
988
1054
  /* @__PURE__ */ jsx11(
@@ -1015,14 +1081,16 @@ function ResetPasswordForm({
1015
1081
  /* @__PURE__ */ jsx11(
1016
1082
  AuthSubmit,
1017
1083
  {
1084
+ spacedAbove: true,
1018
1085
  pending: isResetting,
1019
1086
  disabled: otp.length < OTP_LENGTH || !password || !confirmPassword,
1020
1087
  pendingLabel: t.submitPending,
1088
+ className: submitClassName,
1021
1089
  children: t.submit
1022
1090
  }
1023
1091
  )
1024
1092
  ] }),
1025
- /* @__PURE__ */ jsxs10("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
1093
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
1026
1094
  /* @__PURE__ */ jsx11(
1027
1095
  "button",
1028
1096
  {
@@ -1033,14 +1101,15 @@ function ResetPasswordForm({
1033
1101
  children: isResending ? t.resendPending : t.resend
1034
1102
  }
1035
1103
  ),
1036
- /* @__PURE__ */ jsxs10("p", { children: [
1104
+ /* @__PURE__ */ jsxs9("p", { children: [
1037
1105
  t.rememberPassword,
1038
1106
  " ",
1039
1107
  /* @__PURE__ */ jsx11(
1040
- "a",
1108
+ AuthLink,
1041
1109
  {
1042
- href: loginUrl,
1043
- className: "rounded font-medium text-foreground underline underline-offset-4 decoration-foreground/25 transition-colors hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1110
+ to: loginUrl,
1111
+ as: linkComponent,
1112
+ className: AUTH_LINK_CLASS,
1044
1113
  children: t.login
1045
1114
  }
1046
1115
  )
@@ -1048,53 +1117,80 @@ function ResetPasswordForm({
1048
1117
  ] })
1049
1118
  ] });
1050
1119
  }
1120
+ ResetPasswordForm.defaults = {
1121
+ title: DEFAULTS5.title,
1122
+ subtitle: DEFAULTS5.subtitle
1123
+ };
1124
+
1125
+ // src/components/auth-heading.tsx
1126
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1127
+ function AuthHeading({
1128
+ title,
1129
+ subtitle,
1130
+ titleClassName = "text-[2rem] font-semibold leading-[1.1] tracking-[-0.03em] sm:text-[2.25rem]"
1131
+ }) {
1132
+ return /* @__PURE__ */ jsxs10("header", { className: "space-y-2.5 text-center", children: [
1133
+ /* @__PURE__ */ jsx12("h1", { className: `text-foreground ${titleClassName}`, children: title }),
1134
+ subtitle && /* @__PURE__ */ jsx12("p", { className: "text-balance text-[0.9375rem] leading-relaxed text-muted-foreground", children: subtitle })
1135
+ ] });
1136
+ }
1051
1137
 
1052
1138
  // src/components/auth-layout.tsx
1053
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1139
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1054
1140
  function AuthLayout({
1055
1141
  logo,
1056
1142
  panel,
1143
+ title,
1144
+ subtitle,
1145
+ titleClassName,
1057
1146
  children,
1058
1147
  footer
1059
1148
  }) {
1060
- return /* @__PURE__ */ jsx12("div", { className: "flex min-h-dvh flex-col bg-background px-5 pb-10 pt-12 sm:items-center sm:bg-muted/40 sm:px-6 sm:py-16", children: /* @__PURE__ */ jsxs11(
1061
- "div",
1062
- {
1063
- className: `mx-auto w-full ${panel ? "max-w-4xl" : "max-w-[420px]"}`,
1064
- children: [
1065
- /* @__PURE__ */ jsxs11(
1066
- "div",
1067
- {
1068
- className: [
1069
- "sm:overflow-hidden sm:rounded-2xl sm:border sm:border-border/70 sm:bg-card sm:shadow-lg sm:shadow-black/5",
1070
- panel ? "md:grid md:grid-cols-2" : ""
1071
- ].filter(Boolean).join(" "),
1072
- children: [
1073
- /* @__PURE__ */ jsxs11("div", { className: "sm:p-8", children: [
1074
- logo && /* @__PURE__ */ jsx12("div", { className: "mb-7 flex justify-center", children: logo }),
1075
- children
1076
- ] }),
1077
- panel && // Decorative: it must never carry information the form does not,
1078
- // so it is hidden from assistive tech rather than described.
1079
- /* @__PURE__ */ jsx12(
1080
- "div",
1081
- {
1082
- "aria-hidden": "true",
1083
- className: "hidden bg-muted md:block [&>*]:h-full [&>*]:w-full [&>img]:object-cover",
1084
- children: panel
1085
- }
1086
- )
1087
- ]
1088
- }
1089
- ),
1090
- footer && /* @__PURE__ */ jsx12("div", { className: "mt-6 text-center text-xs leading-relaxed text-muted-foreground", children: footer })
1091
- ]
1092
- }
1093
- ) });
1149
+ return /* @__PURE__ */ jsx13("div", { className: "flex min-h-dvh flex-col bg-background px-5 pb-12 pt-14 sm:items-center sm:bg-muted/30 sm:px-6 sm:py-20", children: /* @__PURE__ */ jsxs11("div", { className: `mx-auto w-full ${panel ? "max-w-4xl" : "max-w-[400px]"}`, children: [
1150
+ (logo || title) && // The spacing is composed, not repeated: the mark sits close to the
1151
+ // title it introduces, and the gap down to the card is the largest
1152
+ // on the screen that step is what separates "who this is" from
1153
+ // "what you do here".
1154
+ /* @__PURE__ */ jsxs11("div", { className: "mb-10 space-y-6", children: [
1155
+ logo && /* @__PURE__ */ jsx13("div", { className: "flex justify-center", children: logo }),
1156
+ title && /* @__PURE__ */ jsx13(
1157
+ AuthHeading,
1158
+ {
1159
+ title,
1160
+ subtitle,
1161
+ titleClassName
1162
+ }
1163
+ )
1164
+ ] }),
1165
+ /* @__PURE__ */ jsxs11(
1166
+ "div",
1167
+ {
1168
+ className: [
1169
+ "sm:rounded-xl sm:border sm:border-foreground/[0.08] sm:bg-card",
1170
+ "sm:shadow-[0_1px_2px_rgba(0,0,0,0.04),0_8px_24px_-12px_rgba(0,0,0,0.10)]",
1171
+ panel ? "sm:overflow-hidden md:grid md:grid-cols-2" : ""
1172
+ ].filter(Boolean).join(" "),
1173
+ children: [
1174
+ panel && // Decorative: it must never carry information the form does not,
1175
+ // so it is hidden from assistive tech rather than described.
1176
+ /* @__PURE__ */ jsx13(
1177
+ "div",
1178
+ {
1179
+ "aria-hidden": "true",
1180
+ className: "relative hidden overflow-hidden bg-muted md:block [&>*]:absolute [&>*]:inset-0 [&>*]:h-full [&>*]:w-full [&>img]:object-cover",
1181
+ children: panel
1182
+ }
1183
+ ),
1184
+ /* @__PURE__ */ jsx13("div", { className: "sm:px-7 sm:py-8", children })
1185
+ ]
1186
+ }
1187
+ ),
1188
+ footer && /* @__PURE__ */ jsx13("div", { className: "mt-8 text-center text-xs leading-relaxed text-muted-foreground", children: footer })
1189
+ ] }) });
1094
1190
  }
1095
1191
 
1096
1192
  // src/components/invitation-notice.tsx
1097
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
1193
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1098
1194
  function defaultSupportEmail() {
1099
1195
  if (typeof window === "undefined") return void 0;
1100
1196
  const host = window.location.hostname;
@@ -1116,13 +1212,13 @@ function InvitationNotice({
1116
1212
  const contact = supportEmail ?? defaultSupportEmail();
1117
1213
  return /* @__PURE__ */ jsxs12("div", { className: "space-y-8", children: [
1118
1214
  /* @__PURE__ */ jsxs12("div", { children: [
1119
- /* @__PURE__ */ jsx13("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
1120
- /* @__PURE__ */ jsx13("p", { className: "mt-1 text-sm text-muted-foreground", children: REASON_MESSAGE[reason] ?? REASON_MESSAGE.unknown })
1215
+ /* @__PURE__ */ jsx14("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
1216
+ /* @__PURE__ */ jsx14("p", { className: "mt-1 text-sm text-muted-foreground", children: REASON_MESSAGE[reason] ?? REASON_MESSAGE.unknown })
1121
1217
  ] }),
1122
1218
  contact ? /* @__PURE__ */ jsxs12("p", { className: "text-sm text-muted-foreground", children: [
1123
1219
  "\xC9crivez-nous \xE0",
1124
1220
  " ",
1125
- /* @__PURE__ */ jsx13(
1221
+ /* @__PURE__ */ jsx14(
1126
1222
  "a",
1127
1223
  {
1128
1224
  href: `mailto:${contact}`,
@@ -1136,9 +1232,35 @@ function InvitationNotice({
1136
1232
  action
1137
1233
  ] });
1138
1234
  }
1235
+
1236
+ // src/oauth-error.ts
1237
+ function oauthErrorMessage(code, labels) {
1238
+ switch (code) {
1239
+ case "account_not_linked":
1240
+ return labels.accountNotLinked;
1241
+ case "access_denied":
1242
+ return labels.socialCancelled;
1243
+ default:
1244
+ return labels.socialFailed;
1245
+ }
1246
+ }
1247
+ function initialOAuthError(labels, param = "error") {
1248
+ if (typeof window === "undefined") return void 0;
1249
+ const code = new URLSearchParams(window.location.search).get(param);
1250
+ if (!code) return void 0;
1251
+ return oauthErrorMessage(code, labels);
1252
+ }
1253
+ function clearOAuthError(param = "error") {
1254
+ if (typeof window === "undefined") return;
1255
+ const url = new URL(window.location.href);
1256
+ if (!url.searchParams.has(param)) return;
1257
+ url.searchParams.delete(param);
1258
+ window.history.replaceState({}, "", url.toString());
1259
+ }
1139
1260
  export {
1140
1261
  AuthField,
1141
1262
  AuthLayout,
1263
+ AuthLink,
1142
1264
  AuthSubmit,
1143
1265
  ForgotPasswordForm,
1144
1266
  InvitationNotice,
@@ -1147,8 +1269,13 @@ export {
1147
1269
  ResetPasswordForm,
1148
1270
  SocialButtons,
1149
1271
  VerifyEmailForm,
1272
+ clearOAuthError,
1273
+ initialOAuthError,
1150
1274
  isInvitationFailure,
1275
+ normalizeInviteToken,
1276
+ oauthErrorMessage,
1151
1277
  useLogout,
1152
- useSession
1278
+ useSession,
1279
+ withInviteToken
1153
1280
  };
1154
1281
  //# sourceMappingURL=index.js.map