@lalternative/auth 0.8.0 → 0.9.1
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/client.d.ts +13 -8
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +89 -10
- package/dist/index.js +212 -105
- package/dist/index.js.map +1 -1
- package/dist/{invitation-CfZAFUdJ.d.ts → invitation-0CfjrVjI.d.ts} +1 -1
- package/dist/server.d.ts +3 -3
- package/dist/{types-Dmjo9lEL.d.ts → types-DzG-qaSv.d.ts} +102 -16
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ function AuthField({
|
|
|
21
21
|
hint,
|
|
22
22
|
description,
|
|
23
23
|
invalid = false,
|
|
24
|
-
fieldClassName = "border-foreground/
|
|
24
|
+
fieldClassName = "border-foreground/30 bg-background",
|
|
25
25
|
...props
|
|
26
26
|
}) {
|
|
27
27
|
const id = useId();
|
|
@@ -35,7 +35,7 @@ function AuthField({
|
|
|
35
35
|
"label",
|
|
36
36
|
{
|
|
37
37
|
htmlFor: id,
|
|
38
|
-
className: "text-
|
|
38
|
+
className: "text-[0.6875rem] font-semibold uppercase leading-none tracking-[0.09em] text-foreground/70",
|
|
39
39
|
children: label
|
|
40
40
|
}
|
|
41
41
|
),
|
|
@@ -51,13 +51,16 @@ function AuthField({
|
|
|
51
51
|
"aria-invalid": invalid || void 0,
|
|
52
52
|
"aria-describedby": descriptionId,
|
|
53
53
|
className: [
|
|
54
|
-
"h-[52px] w-full rounded-
|
|
55
|
-
"sm:h-
|
|
54
|
+
"h-[52px] w-full rounded-md border px-3.5 text-base",
|
|
55
|
+
"sm:h-[46px] sm:text-[0.9375rem]",
|
|
56
56
|
isPassword ? "pr-12" : "",
|
|
57
|
-
"text-foreground placeholder:text-muted-foreground/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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`,
|
|
61
64
|
"disabled:cursor-not-allowed disabled:opacity-60"
|
|
62
65
|
].filter(Boolean).join(" ")
|
|
63
66
|
}
|
|
@@ -107,7 +110,8 @@ function AuthSubmit({
|
|
|
107
110
|
disabled = false,
|
|
108
111
|
pendingLabel,
|
|
109
112
|
children,
|
|
110
|
-
className = "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
113
|
+
className = "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
114
|
+
spacedAbove = false
|
|
111
115
|
}) {
|
|
112
116
|
return /* @__PURE__ */ jsxs2(
|
|
113
117
|
"button",
|
|
@@ -116,11 +120,16 @@ function AuthSubmit({
|
|
|
116
120
|
disabled: disabled || pending,
|
|
117
121
|
"aria-busy": pending || void 0,
|
|
118
122
|
className: [
|
|
119
|
-
|
|
120
|
-
"
|
|
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]",
|
|
121
129
|
className,
|
|
122
|
-
"
|
|
123
|
-
"
|
|
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)]",
|
|
124
133
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
125
134
|
"disabled:pointer-events-none disabled:opacity-55"
|
|
126
135
|
].join(" "),
|
|
@@ -141,6 +150,12 @@ function AuthSubmit({
|
|
|
141
150
|
// src/components/login-form.tsx
|
|
142
151
|
import { useState as useState2 } from "react";
|
|
143
152
|
|
|
153
|
+
// src/email-not-verified.ts
|
|
154
|
+
function isEmailNotVerified(error) {
|
|
155
|
+
if (!error) return false;
|
|
156
|
+
return error.code === "EMAIL_NOT_VERIFIED" || error.status === 403;
|
|
157
|
+
}
|
|
158
|
+
|
|
144
159
|
// src/components/auth-alert.tsx
|
|
145
160
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
146
161
|
function AuthAlert({ children, tone = "error" }) {
|
|
@@ -245,8 +260,33 @@ function ProviderMark({ provider }) {
|
|
|
245
260
|
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" }) });
|
|
246
261
|
}
|
|
247
262
|
|
|
263
|
+
// src/components/auth-link.tsx
|
|
264
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
265
|
+
function AuthLink({ to, as: Link, className, children }) {
|
|
266
|
+
if (Link) {
|
|
267
|
+
return /* @__PURE__ */ jsx5(Link, { to, className, children });
|
|
268
|
+
}
|
|
269
|
+
return /* @__PURE__ */ jsx5("a", { href: to, className, children });
|
|
270
|
+
}
|
|
271
|
+
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";
|
|
272
|
+
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";
|
|
273
|
+
|
|
274
|
+
// src/invite-token.ts
|
|
275
|
+
var MAX_TOKEN_LENGTH = 128;
|
|
276
|
+
function normalizeInviteToken(value) {
|
|
277
|
+
if (typeof value !== "string") return void 0;
|
|
278
|
+
const trimmed = value.trim();
|
|
279
|
+
if (!trimmed || trimmed.length > MAX_TOKEN_LENGTH) return void 0;
|
|
280
|
+
return trimmed;
|
|
281
|
+
}
|
|
282
|
+
function withInviteToken(href, token) {
|
|
283
|
+
if (!token) return href;
|
|
284
|
+
const separator = href.includes("?") ? "&" : "?";
|
|
285
|
+
return `${href}${separator}invite=${encodeURIComponent(token)}`;
|
|
286
|
+
}
|
|
287
|
+
|
|
248
288
|
// src/components/login-form.tsx
|
|
249
|
-
import { jsx as
|
|
289
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
250
290
|
var DEFAULTS = {
|
|
251
291
|
title: "Connexion",
|
|
252
292
|
subtitle: "Content de te revoir. Entre tes identifiants pour continuer.",
|
|
@@ -260,6 +300,7 @@ var DEFAULTS = {
|
|
|
260
300
|
emailRequired: "Renseigne ton adresse e-mail",
|
|
261
301
|
passwordRequired: "Renseigne ton mot de passe",
|
|
262
302
|
invalidCredentials: "Adresse e-mail ou mot de passe incorrect",
|
|
303
|
+
emailNotVerified: "Ton adresse e-mail n'est pas encore confirm\xE9e. V\xE9rifie ta bo\xEEte de r\xE9ception.",
|
|
263
304
|
// accountLinking is disabled in createPlatformAuth, so a social sign-in on an
|
|
264
305
|
// address already registered with a password is refused with this code.
|
|
265
306
|
// Without a message the button reads as broken rather than as a rejection.
|
|
@@ -269,6 +310,7 @@ var DEFAULTS = {
|
|
|
269
310
|
};
|
|
270
311
|
function LoginForm({
|
|
271
312
|
onSuccess,
|
|
313
|
+
onEmailNotVerified,
|
|
272
314
|
registerUrl = "/register",
|
|
273
315
|
forgotPasswordUrl = "/forgot-password",
|
|
274
316
|
socialCallbackUrl = "/",
|
|
@@ -278,6 +320,8 @@ function LoginForm({
|
|
|
278
320
|
submitClassName,
|
|
279
321
|
fieldClassName,
|
|
280
322
|
error: externalError,
|
|
323
|
+
linkComponent,
|
|
324
|
+
invite,
|
|
281
325
|
authClient
|
|
282
326
|
}) {
|
|
283
327
|
const t = { ...DEFAULTS, ...labels };
|
|
@@ -305,7 +349,13 @@ function LoginForm({
|
|
|
305
349
|
password
|
|
306
350
|
});
|
|
307
351
|
if (res?.error) {
|
|
308
|
-
|
|
352
|
+
if (isEmailNotVerified(res.error) && onEmailNotVerified) {
|
|
353
|
+
onEmailNotVerified(email.trim());
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
setError(
|
|
357
|
+
isEmailNotVerified(res.error) ? t.emailNotVerified : res.error.message ?? t.invalidCredentials
|
|
358
|
+
);
|
|
309
359
|
return;
|
|
310
360
|
}
|
|
311
361
|
if (coreTokenUrl) {
|
|
@@ -323,7 +373,9 @@ function LoginForm({
|
|
|
323
373
|
try {
|
|
324
374
|
await authClient.signIn.social({
|
|
325
375
|
provider,
|
|
326
|
-
|
|
376
|
+
// The invitation rides the callback: an OAuth sign-up leaves the
|
|
377
|
+
// browser, and the auth handler redeems the token on the way back.
|
|
378
|
+
callbackURL: withInviteToken(socialCallbackUrl, invite)
|
|
327
379
|
});
|
|
328
380
|
} catch (err) {
|
|
329
381
|
const code = err instanceof Error ? err.message : "";
|
|
@@ -332,10 +384,10 @@ function LoginForm({
|
|
|
332
384
|
);
|
|
333
385
|
}
|
|
334
386
|
};
|
|
335
|
-
return /* @__PURE__ */ jsxs4("div", { className: "space-y-
|
|
336
|
-
/* @__PURE__ */
|
|
337
|
-
/* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "space-y-
|
|
338
|
-
/* @__PURE__ */
|
|
387
|
+
return /* @__PURE__ */ jsxs4("div", { className: "space-y-7", children: [
|
|
388
|
+
/* @__PURE__ */ jsx6(AuthAlert, { children: error }),
|
|
389
|
+
/* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "space-y-[1.125rem]", noValidate: true, children: [
|
|
390
|
+
/* @__PURE__ */ jsx6(
|
|
339
391
|
AuthField,
|
|
340
392
|
{
|
|
341
393
|
label: t.emailPlaceholder,
|
|
@@ -352,7 +404,7 @@ function LoginForm({
|
|
|
352
404
|
fieldClassName
|
|
353
405
|
}
|
|
354
406
|
),
|
|
355
|
-
/* @__PURE__ */
|
|
407
|
+
/* @__PURE__ */ jsx6(
|
|
356
408
|
AuthField,
|
|
357
409
|
{
|
|
358
410
|
label: t.passwordPlaceholder,
|
|
@@ -364,19 +416,21 @@ function LoginForm({
|
|
|
364
416
|
autoComplete: "current-password",
|
|
365
417
|
invalid: !!error,
|
|
366
418
|
fieldClassName,
|
|
367
|
-
hint: /* @__PURE__ */
|
|
368
|
-
|
|
419
|
+
hint: /* @__PURE__ */ jsx6(
|
|
420
|
+
AuthLink,
|
|
369
421
|
{
|
|
370
|
-
|
|
371
|
-
|
|
422
|
+
to: forgotPasswordUrl,
|
|
423
|
+
as: linkComponent,
|
|
424
|
+
className: AUTH_HINT_LINK_CLASS,
|
|
372
425
|
children: t.forgotPassword
|
|
373
426
|
}
|
|
374
427
|
)
|
|
375
428
|
}
|
|
376
429
|
),
|
|
377
|
-
/* @__PURE__ */
|
|
430
|
+
/* @__PURE__ */ jsx6(
|
|
378
431
|
AuthSubmit,
|
|
379
432
|
{
|
|
433
|
+
spacedAbove: true,
|
|
380
434
|
pending: isPending,
|
|
381
435
|
disabled: !email.trim() || !password,
|
|
382
436
|
pendingLabel: t.submitPending,
|
|
@@ -385,7 +439,7 @@ function LoginForm({
|
|
|
385
439
|
}
|
|
386
440
|
)
|
|
387
441
|
] }),
|
|
388
|
-
/* @__PURE__ */
|
|
442
|
+
/* @__PURE__ */ jsx6(
|
|
389
443
|
SocialButtons,
|
|
390
444
|
{
|
|
391
445
|
providers: socialProviders,
|
|
@@ -396,11 +450,12 @@ function LoginForm({
|
|
|
396
450
|
/* @__PURE__ */ jsxs4("p", { className: "text-center text-sm text-muted-foreground", children: [
|
|
397
451
|
t.noAccount,
|
|
398
452
|
" ",
|
|
399
|
-
/* @__PURE__ */
|
|
400
|
-
|
|
453
|
+
/* @__PURE__ */ jsx6(
|
|
454
|
+
AuthLink,
|
|
401
455
|
{
|
|
402
|
-
|
|
403
|
-
|
|
456
|
+
to: withInviteToken(registerUrl, invite),
|
|
457
|
+
as: linkComponent,
|
|
458
|
+
className: AUTH_LINK_CLASS,
|
|
404
459
|
children: t.register
|
|
405
460
|
}
|
|
406
461
|
)
|
|
@@ -414,7 +469,7 @@ LoginForm.defaults = {
|
|
|
414
469
|
|
|
415
470
|
// src/components/register-form.tsx
|
|
416
471
|
import { useState as useState3 } from "react";
|
|
417
|
-
import { jsx as
|
|
472
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
418
473
|
var MIN_PASSWORD_LENGTH = 8;
|
|
419
474
|
var DEFAULTS2 = {
|
|
420
475
|
title: "Cr\xE9er un compte",
|
|
@@ -444,6 +499,8 @@ function RegisterForm({
|
|
|
444
499
|
submitClassName,
|
|
445
500
|
fieldClassName,
|
|
446
501
|
error: externalError,
|
|
502
|
+
linkComponent,
|
|
503
|
+
invite,
|
|
447
504
|
authClient
|
|
448
505
|
}) {
|
|
449
506
|
const t = { ...DEFAULTS2, ...labels };
|
|
@@ -499,16 +556,18 @@ function RegisterForm({
|
|
|
499
556
|
try {
|
|
500
557
|
await authClient.signIn.social({
|
|
501
558
|
provider,
|
|
502
|
-
|
|
559
|
+
// The invitation rides the callback: an OAuth sign-up leaves the
|
|
560
|
+
// browser, and the auth handler redeems the token on the way back.
|
|
561
|
+
callbackURL: withInviteToken(socialCallbackUrl, invite)
|
|
503
562
|
});
|
|
504
563
|
} catch (err) {
|
|
505
564
|
setError(err instanceof Error ? err.message : t.signUpFailed);
|
|
506
565
|
}
|
|
507
566
|
};
|
|
508
|
-
return /* @__PURE__ */ jsxs5("div", { className: "space-y-
|
|
509
|
-
/* @__PURE__ */
|
|
510
|
-
/* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className: "space-y-
|
|
511
|
-
/* @__PURE__ */
|
|
567
|
+
return /* @__PURE__ */ jsxs5("div", { className: "space-y-7", children: [
|
|
568
|
+
/* @__PURE__ */ jsx7(AuthAlert, { children: error }),
|
|
569
|
+
/* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className: "space-y-[1.125rem]", noValidate: true, children: [
|
|
570
|
+
/* @__PURE__ */ jsx7(
|
|
512
571
|
AuthField,
|
|
513
572
|
{
|
|
514
573
|
label: t.namePlaceholder,
|
|
@@ -521,7 +580,7 @@ function RegisterForm({
|
|
|
521
580
|
fieldClassName
|
|
522
581
|
}
|
|
523
582
|
),
|
|
524
|
-
/* @__PURE__ */
|
|
583
|
+
/* @__PURE__ */ jsx7(
|
|
525
584
|
AuthField,
|
|
526
585
|
{
|
|
527
586
|
label: t.emailPlaceholder,
|
|
@@ -537,7 +596,7 @@ function RegisterForm({
|
|
|
537
596
|
fieldClassName
|
|
538
597
|
}
|
|
539
598
|
),
|
|
540
|
-
/* @__PURE__ */
|
|
599
|
+
/* @__PURE__ */ jsx7(
|
|
541
600
|
AuthField,
|
|
542
601
|
{
|
|
543
602
|
label: t.passwordPlaceholder,
|
|
@@ -552,7 +611,7 @@ function RegisterForm({
|
|
|
552
611
|
fieldClassName
|
|
553
612
|
}
|
|
554
613
|
),
|
|
555
|
-
/* @__PURE__ */
|
|
614
|
+
/* @__PURE__ */ jsx7(
|
|
556
615
|
AuthField,
|
|
557
616
|
{
|
|
558
617
|
label: t.confirmPlaceholder,
|
|
@@ -566,18 +625,19 @@ function RegisterForm({
|
|
|
566
625
|
fieldClassName
|
|
567
626
|
}
|
|
568
627
|
),
|
|
569
|
-
/* @__PURE__ */
|
|
628
|
+
/* @__PURE__ */ jsx7(
|
|
570
629
|
AuthSubmit,
|
|
571
630
|
{
|
|
631
|
+
spacedAbove: true,
|
|
572
632
|
pending: isPending,
|
|
573
633
|
pendingLabel: t.submitPending,
|
|
574
634
|
className: submitClassName,
|
|
575
635
|
children: t.submit
|
|
576
636
|
}
|
|
577
637
|
),
|
|
578
|
-
legal && /* @__PURE__ */
|
|
638
|
+
legal && /* @__PURE__ */ jsx7("p", { className: "text-center text-xs leading-relaxed text-muted-foreground", children: legal })
|
|
579
639
|
] }),
|
|
580
|
-
/* @__PURE__ */
|
|
640
|
+
/* @__PURE__ */ jsx7(
|
|
581
641
|
SocialButtons,
|
|
582
642
|
{
|
|
583
643
|
providers: socialProviders,
|
|
@@ -588,11 +648,12 @@ function RegisterForm({
|
|
|
588
648
|
/* @__PURE__ */ jsxs5("p", { className: "text-center text-sm text-muted-foreground", children: [
|
|
589
649
|
t.haveAccount,
|
|
590
650
|
" ",
|
|
591
|
-
/* @__PURE__ */
|
|
592
|
-
|
|
651
|
+
/* @__PURE__ */ jsx7(
|
|
652
|
+
AuthLink,
|
|
593
653
|
{
|
|
594
|
-
|
|
595
|
-
|
|
654
|
+
to: withInviteToken(loginUrl, invite),
|
|
655
|
+
as: linkComponent,
|
|
656
|
+
className: AUTH_LINK_CLASS,
|
|
596
657
|
children: t.login
|
|
597
658
|
}
|
|
598
659
|
)
|
|
@@ -608,7 +669,7 @@ RegisterForm.defaults = {
|
|
|
608
669
|
import { useState as useState4 } from "react";
|
|
609
670
|
|
|
610
671
|
// src/components/auth-otp-field.tsx
|
|
611
|
-
import { jsx as
|
|
672
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
612
673
|
var OTP_LENGTH = 6;
|
|
613
674
|
function AuthOtpField({
|
|
614
675
|
label,
|
|
@@ -620,7 +681,7 @@ function AuthOtpField({
|
|
|
620
681
|
fieldClassName = "border-foreground/25 bg-background"
|
|
621
682
|
}) {
|
|
622
683
|
return /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
|
|
623
|
-
/* @__PURE__ */
|
|
684
|
+
/* @__PURE__ */ jsx8(
|
|
624
685
|
"label",
|
|
625
686
|
{
|
|
626
687
|
htmlFor: id,
|
|
@@ -628,7 +689,7 @@ function AuthOtpField({
|
|
|
628
689
|
children: label
|
|
629
690
|
}
|
|
630
691
|
),
|
|
631
|
-
/* @__PURE__ */
|
|
692
|
+
/* @__PURE__ */ jsx8(
|
|
632
693
|
"input",
|
|
633
694
|
{
|
|
634
695
|
id,
|
|
@@ -657,7 +718,7 @@ function AuthOtpField({
|
|
|
657
718
|
}
|
|
658
719
|
|
|
659
720
|
// src/components/verify-email-form.tsx
|
|
660
|
-
import { jsx as
|
|
721
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
661
722
|
var DEFAULTS3 = {
|
|
662
723
|
title: "V\xE9rifie ton adresse",
|
|
663
724
|
subtitle: "Entre le code \xE0 6 chiffres envoy\xE9 \xE0",
|
|
@@ -682,6 +743,7 @@ function VerifyEmailForm({
|
|
|
682
743
|
labels,
|
|
683
744
|
submitClassName,
|
|
684
745
|
fieldClassName,
|
|
746
|
+
linkComponent,
|
|
685
747
|
authClient
|
|
686
748
|
}) {
|
|
687
749
|
const t = { ...DEFAULTS3, ...labels };
|
|
@@ -732,11 +794,11 @@ function VerifyEmailForm({
|
|
|
732
794
|
setIsResending(false);
|
|
733
795
|
}
|
|
734
796
|
};
|
|
735
|
-
return /* @__PURE__ */ jsxs7("div", { className: "space-y-
|
|
736
|
-
/* @__PURE__ */
|
|
737
|
-
/* @__PURE__ */
|
|
738
|
-
/* @__PURE__ */ jsxs7("form", { onSubmit: handleVerify, className: "space-y-
|
|
739
|
-
/* @__PURE__ */
|
|
797
|
+
return /* @__PURE__ */ jsxs7("div", { className: "space-y-7", children: [
|
|
798
|
+
/* @__PURE__ */ jsx9(AuthAlert, { children: error }),
|
|
799
|
+
/* @__PURE__ */ jsx9(AuthAlert, { tone: "success", children: resendMessage }),
|
|
800
|
+
/* @__PURE__ */ jsxs7("form", { onSubmit: handleVerify, className: "space-y-[1.125rem]", noValidate: true, children: [
|
|
801
|
+
/* @__PURE__ */ jsx9(
|
|
740
802
|
AuthOtpField,
|
|
741
803
|
{
|
|
742
804
|
id: "verify-email-otp",
|
|
@@ -747,9 +809,10 @@ function VerifyEmailForm({
|
|
|
747
809
|
fieldClassName
|
|
748
810
|
}
|
|
749
811
|
),
|
|
750
|
-
/* @__PURE__ */
|
|
812
|
+
/* @__PURE__ */ jsx9(
|
|
751
813
|
AuthSubmit,
|
|
752
814
|
{
|
|
815
|
+
spacedAbove: true,
|
|
753
816
|
pending: isVerifying,
|
|
754
817
|
disabled: otp.length < OTP_LENGTH,
|
|
755
818
|
pendingLabel: t.submitPending,
|
|
@@ -759,7 +822,7 @@ function VerifyEmailForm({
|
|
|
759
822
|
)
|
|
760
823
|
] }),
|
|
761
824
|
/* @__PURE__ */ jsxs7("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
|
|
762
|
-
/* @__PURE__ */
|
|
825
|
+
/* @__PURE__ */ jsx9(
|
|
763
826
|
"button",
|
|
764
827
|
{
|
|
765
828
|
type: "button",
|
|
@@ -772,11 +835,12 @@ function VerifyEmailForm({
|
|
|
772
835
|
/* @__PURE__ */ jsxs7("p", { children: [
|
|
773
836
|
t.alreadyVerified,
|
|
774
837
|
" ",
|
|
775
|
-
/* @__PURE__ */
|
|
776
|
-
|
|
838
|
+
/* @__PURE__ */ jsx9(
|
|
839
|
+
AuthLink,
|
|
777
840
|
{
|
|
778
|
-
|
|
779
|
-
|
|
841
|
+
to: loginUrl,
|
|
842
|
+
as: linkComponent,
|
|
843
|
+
className: AUTH_LINK_CLASS,
|
|
780
844
|
children: t.login
|
|
781
845
|
}
|
|
782
846
|
)
|
|
@@ -791,7 +855,7 @@ VerifyEmailForm.defaults = {
|
|
|
791
855
|
|
|
792
856
|
// src/components/forgot-password-form.tsx
|
|
793
857
|
import { useState as useState5 } from "react";
|
|
794
|
-
import { jsx as
|
|
858
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
795
859
|
var DEFAULTS4 = {
|
|
796
860
|
title: "Mot de passe oubli\xE9 ?",
|
|
797
861
|
subtitle: "Entre ton adresse e-mail et nous t'enverrons un code pour le r\xE9initialiser.",
|
|
@@ -809,6 +873,7 @@ function ForgotPasswordForm({
|
|
|
809
873
|
labels,
|
|
810
874
|
submitClassName,
|
|
811
875
|
fieldClassName,
|
|
876
|
+
linkComponent,
|
|
812
877
|
authClient
|
|
813
878
|
}) {
|
|
814
879
|
const t = { ...DEFAULTS4, ...labels };
|
|
@@ -839,10 +904,10 @@ function ForgotPasswordForm({
|
|
|
839
904
|
setIsPending(false);
|
|
840
905
|
}
|
|
841
906
|
};
|
|
842
|
-
return /* @__PURE__ */ jsxs8("div", { className: "space-y-
|
|
843
|
-
/* @__PURE__ */
|
|
844
|
-
/* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, className: "space-y-
|
|
845
|
-
/* @__PURE__ */
|
|
907
|
+
return /* @__PURE__ */ jsxs8("div", { className: "space-y-7", children: [
|
|
908
|
+
/* @__PURE__ */ jsx10(AuthAlert, { children: error }),
|
|
909
|
+
/* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, className: "space-y-[1.125rem]", noValidate: true, children: [
|
|
910
|
+
/* @__PURE__ */ jsx10(
|
|
846
911
|
AuthField,
|
|
847
912
|
{
|
|
848
913
|
label: t.emailPlaceholder,
|
|
@@ -858,9 +923,10 @@ function ForgotPasswordForm({
|
|
|
858
923
|
invalid: !!error
|
|
859
924
|
}
|
|
860
925
|
),
|
|
861
|
-
/* @__PURE__ */
|
|
926
|
+
/* @__PURE__ */ jsx10(
|
|
862
927
|
AuthSubmit,
|
|
863
928
|
{
|
|
929
|
+
spacedAbove: true,
|
|
864
930
|
pending: isPending,
|
|
865
931
|
disabled: !email.trim(),
|
|
866
932
|
pendingLabel: t.submitPending,
|
|
@@ -872,11 +938,12 @@ function ForgotPasswordForm({
|
|
|
872
938
|
/* @__PURE__ */ jsxs8("p", { className: "text-center text-sm text-muted-foreground", children: [
|
|
873
939
|
t.rememberPassword,
|
|
874
940
|
" ",
|
|
875
|
-
/* @__PURE__ */
|
|
876
|
-
|
|
941
|
+
/* @__PURE__ */ jsx10(
|
|
942
|
+
AuthLink,
|
|
877
943
|
{
|
|
878
|
-
|
|
879
|
-
|
|
944
|
+
to: loginUrl,
|
|
945
|
+
as: linkComponent,
|
|
946
|
+
className: AUTH_LINK_CLASS,
|
|
880
947
|
children: t.login
|
|
881
948
|
}
|
|
882
949
|
)
|
|
@@ -890,7 +957,7 @@ ForgotPasswordForm.defaults = {
|
|
|
890
957
|
|
|
891
958
|
// src/components/reset-password-form.tsx
|
|
892
959
|
import { useState as useState6 } from "react";
|
|
893
|
-
import { jsx as
|
|
960
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
894
961
|
var MIN_PASSWORD_LENGTH2 = 8;
|
|
895
962
|
var DEFAULTS5 = {
|
|
896
963
|
title: "Nouveau mot de passe",
|
|
@@ -919,6 +986,7 @@ function ResetPasswordForm({
|
|
|
919
986
|
labels,
|
|
920
987
|
submitClassName,
|
|
921
988
|
fieldClassName,
|
|
989
|
+
linkComponent,
|
|
922
990
|
authClient
|
|
923
991
|
}) {
|
|
924
992
|
const t = { ...DEFAULTS5, ...labels };
|
|
@@ -982,11 +1050,11 @@ function ResetPasswordForm({
|
|
|
982
1050
|
setIsResending(false);
|
|
983
1051
|
}
|
|
984
1052
|
};
|
|
985
|
-
return /* @__PURE__ */ jsxs9("div", { className: "space-y-
|
|
986
|
-
/* @__PURE__ */
|
|
987
|
-
/* @__PURE__ */
|
|
988
|
-
/* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "space-y-
|
|
989
|
-
/* @__PURE__ */
|
|
1053
|
+
return /* @__PURE__ */ jsxs9("div", { className: "space-y-7", children: [
|
|
1054
|
+
/* @__PURE__ */ jsx11(AuthAlert, { children: error }),
|
|
1055
|
+
/* @__PURE__ */ jsx11(AuthAlert, { tone: "success", children: resendMessage }),
|
|
1056
|
+
/* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "space-y-[1.125rem]", noValidate: true, children: [
|
|
1057
|
+
/* @__PURE__ */ jsx11(
|
|
990
1058
|
AuthOtpField,
|
|
991
1059
|
{
|
|
992
1060
|
id: "reset-password-otp",
|
|
@@ -997,7 +1065,7 @@ function ResetPasswordForm({
|
|
|
997
1065
|
fieldClassName
|
|
998
1066
|
}
|
|
999
1067
|
),
|
|
1000
|
-
/* @__PURE__ */
|
|
1068
|
+
/* @__PURE__ */ jsx11(
|
|
1001
1069
|
AuthField,
|
|
1002
1070
|
{
|
|
1003
1071
|
label: t.passwordPlaceholder,
|
|
@@ -1011,7 +1079,7 @@ function ResetPasswordForm({
|
|
|
1011
1079
|
invalid: tooShort
|
|
1012
1080
|
}
|
|
1013
1081
|
),
|
|
1014
|
-
/* @__PURE__ */
|
|
1082
|
+
/* @__PURE__ */ jsx11(
|
|
1015
1083
|
AuthField,
|
|
1016
1084
|
{
|
|
1017
1085
|
label: t.confirmPlaceholder,
|
|
@@ -1024,9 +1092,10 @@ function ResetPasswordForm({
|
|
|
1024
1092
|
invalid: mismatch
|
|
1025
1093
|
}
|
|
1026
1094
|
),
|
|
1027
|
-
/* @__PURE__ */
|
|
1095
|
+
/* @__PURE__ */ jsx11(
|
|
1028
1096
|
AuthSubmit,
|
|
1029
1097
|
{
|
|
1098
|
+
spacedAbove: true,
|
|
1030
1099
|
pending: isResetting,
|
|
1031
1100
|
disabled: otp.length < OTP_LENGTH || !password || !confirmPassword,
|
|
1032
1101
|
pendingLabel: t.submitPending,
|
|
@@ -1036,7 +1105,7 @@ function ResetPasswordForm({
|
|
|
1036
1105
|
)
|
|
1037
1106
|
] }),
|
|
1038
1107
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
|
|
1039
|
-
/* @__PURE__ */
|
|
1108
|
+
/* @__PURE__ */ jsx11(
|
|
1040
1109
|
"button",
|
|
1041
1110
|
{
|
|
1042
1111
|
type: "button",
|
|
@@ -1049,11 +1118,12 @@ function ResetPasswordForm({
|
|
|
1049
1118
|
/* @__PURE__ */ jsxs9("p", { children: [
|
|
1050
1119
|
t.rememberPassword,
|
|
1051
1120
|
" ",
|
|
1052
|
-
/* @__PURE__ */
|
|
1053
|
-
|
|
1121
|
+
/* @__PURE__ */ jsx11(
|
|
1122
|
+
AuthLink,
|
|
1054
1123
|
{
|
|
1055
|
-
|
|
1056
|
-
|
|
1124
|
+
to: loginUrl,
|
|
1125
|
+
as: linkComponent,
|
|
1126
|
+
className: AUTH_LINK_CLASS,
|
|
1057
1127
|
children: t.login
|
|
1058
1128
|
}
|
|
1059
1129
|
)
|
|
@@ -1067,20 +1137,20 @@ ResetPasswordForm.defaults = {
|
|
|
1067
1137
|
};
|
|
1068
1138
|
|
|
1069
1139
|
// src/components/auth-heading.tsx
|
|
1070
|
-
import { jsx as
|
|
1140
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1071
1141
|
function AuthHeading({
|
|
1072
1142
|
title,
|
|
1073
1143
|
subtitle,
|
|
1074
|
-
titleClassName = "text-
|
|
1144
|
+
titleClassName = "text-[2rem] font-semibold leading-[1.1] tracking-[-0.03em] sm:text-[2.25rem]"
|
|
1075
1145
|
}) {
|
|
1076
|
-
return /* @__PURE__ */ jsxs10("header", { className: "space-y-
|
|
1077
|
-
/* @__PURE__ */
|
|
1078
|
-
subtitle && /* @__PURE__ */
|
|
1146
|
+
return /* @__PURE__ */ jsxs10("header", { className: "space-y-2.5 text-center", children: [
|
|
1147
|
+
/* @__PURE__ */ jsx12("h1", { className: `text-foreground ${titleClassName}`, children: title }),
|
|
1148
|
+
subtitle && /* @__PURE__ */ jsx12("p", { className: "text-balance text-[0.9375rem] leading-relaxed text-muted-foreground", children: subtitle })
|
|
1079
1149
|
] });
|
|
1080
1150
|
}
|
|
1081
1151
|
|
|
1082
1152
|
// src/components/auth-layout.tsx
|
|
1083
|
-
import { jsx as
|
|
1153
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1084
1154
|
function AuthLayout({
|
|
1085
1155
|
logo,
|
|
1086
1156
|
panel,
|
|
@@ -1090,10 +1160,14 @@ function AuthLayout({
|
|
|
1090
1160
|
children,
|
|
1091
1161
|
footer
|
|
1092
1162
|
}) {
|
|
1093
|
-
return /* @__PURE__ */
|
|
1094
|
-
(logo || title) &&
|
|
1095
|
-
|
|
1096
|
-
|
|
1163
|
+
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: [
|
|
1164
|
+
(logo || title) && // The spacing is composed, not repeated: the mark sits close to the
|
|
1165
|
+
// title it introduces, and the gap down to the card is the largest
|
|
1166
|
+
// on the screen — that step is what separates "who this is" from
|
|
1167
|
+
// "what you do here".
|
|
1168
|
+
/* @__PURE__ */ jsxs11("div", { className: "mb-10 space-y-6", children: [
|
|
1169
|
+
logo && /* @__PURE__ */ jsx13("div", { className: "flex justify-center", children: logo }),
|
|
1170
|
+
title && /* @__PURE__ */ jsx13(
|
|
1097
1171
|
AuthHeading,
|
|
1098
1172
|
{
|
|
1099
1173
|
title,
|
|
@@ -1106,13 +1180,14 @@ function AuthLayout({
|
|
|
1106
1180
|
"div",
|
|
1107
1181
|
{
|
|
1108
1182
|
className: [
|
|
1109
|
-
"sm:rounded-
|
|
1183
|
+
"sm:rounded-xl sm:border sm:border-foreground/[0.08] sm:bg-card",
|
|
1184
|
+
"sm:shadow-[0_1px_2px_rgba(0,0,0,0.04),0_8px_24px_-12px_rgba(0,0,0,0.10)]",
|
|
1110
1185
|
panel ? "sm:overflow-hidden md:grid md:grid-cols-2" : ""
|
|
1111
1186
|
].filter(Boolean).join(" "),
|
|
1112
1187
|
children: [
|
|
1113
1188
|
panel && // Decorative: it must never carry information the form does not,
|
|
1114
1189
|
// so it is hidden from assistive tech rather than described.
|
|
1115
|
-
/* @__PURE__ */
|
|
1190
|
+
/* @__PURE__ */ jsx13(
|
|
1116
1191
|
"div",
|
|
1117
1192
|
{
|
|
1118
1193
|
"aria-hidden": "true",
|
|
@@ -1120,16 +1195,16 @@ function AuthLayout({
|
|
|
1120
1195
|
children: panel
|
|
1121
1196
|
}
|
|
1122
1197
|
),
|
|
1123
|
-
/* @__PURE__ */
|
|
1198
|
+
/* @__PURE__ */ jsx13("div", { className: "sm:px-7 sm:py-8", children })
|
|
1124
1199
|
]
|
|
1125
1200
|
}
|
|
1126
1201
|
),
|
|
1127
|
-
footer && /* @__PURE__ */
|
|
1202
|
+
footer && /* @__PURE__ */ jsx13("div", { className: "mt-8 text-center text-xs leading-relaxed text-muted-foreground", children: footer })
|
|
1128
1203
|
] }) });
|
|
1129
1204
|
}
|
|
1130
1205
|
|
|
1131
1206
|
// src/components/invitation-notice.tsx
|
|
1132
|
-
import { jsx as
|
|
1207
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1133
1208
|
function defaultSupportEmail() {
|
|
1134
1209
|
if (typeof window === "undefined") return void 0;
|
|
1135
1210
|
const host = window.location.hostname;
|
|
@@ -1151,13 +1226,13 @@ function InvitationNotice({
|
|
|
1151
1226
|
const contact = supportEmail ?? defaultSupportEmail();
|
|
1152
1227
|
return /* @__PURE__ */ jsxs12("div", { className: "space-y-8", children: [
|
|
1153
1228
|
/* @__PURE__ */ jsxs12("div", { children: [
|
|
1154
|
-
/* @__PURE__ */
|
|
1155
|
-
/* @__PURE__ */
|
|
1229
|
+
/* @__PURE__ */ jsx14("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
|
|
1230
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-1 text-sm text-muted-foreground", children: REASON_MESSAGE[reason] ?? REASON_MESSAGE.unknown })
|
|
1156
1231
|
] }),
|
|
1157
1232
|
contact ? /* @__PURE__ */ jsxs12("p", { className: "text-sm text-muted-foreground", children: [
|
|
1158
1233
|
"\xC9crivez-nous \xE0",
|
|
1159
1234
|
" ",
|
|
1160
|
-
/* @__PURE__ */
|
|
1235
|
+
/* @__PURE__ */ jsx14(
|
|
1161
1236
|
"a",
|
|
1162
1237
|
{
|
|
1163
1238
|
href: `mailto:${contact}`,
|
|
@@ -1171,9 +1246,35 @@ function InvitationNotice({
|
|
|
1171
1246
|
action
|
|
1172
1247
|
] });
|
|
1173
1248
|
}
|
|
1249
|
+
|
|
1250
|
+
// src/oauth-error.ts
|
|
1251
|
+
function oauthErrorMessage(code, labels) {
|
|
1252
|
+
switch (code) {
|
|
1253
|
+
case "account_not_linked":
|
|
1254
|
+
return labels.accountNotLinked;
|
|
1255
|
+
case "access_denied":
|
|
1256
|
+
return labels.socialCancelled;
|
|
1257
|
+
default:
|
|
1258
|
+
return labels.socialFailed;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
function initialOAuthError(labels, param = "error") {
|
|
1262
|
+
if (typeof window === "undefined") return void 0;
|
|
1263
|
+
const code = new URLSearchParams(window.location.search).get(param);
|
|
1264
|
+
if (!code) return void 0;
|
|
1265
|
+
return oauthErrorMessage(code, labels);
|
|
1266
|
+
}
|
|
1267
|
+
function clearOAuthError(param = "error") {
|
|
1268
|
+
if (typeof window === "undefined") return;
|
|
1269
|
+
const url = new URL(window.location.href);
|
|
1270
|
+
if (!url.searchParams.has(param)) return;
|
|
1271
|
+
url.searchParams.delete(param);
|
|
1272
|
+
window.history.replaceState({}, "", url.toString());
|
|
1273
|
+
}
|
|
1174
1274
|
export {
|
|
1175
1275
|
AuthField,
|
|
1176
1276
|
AuthLayout,
|
|
1277
|
+
AuthLink,
|
|
1177
1278
|
AuthSubmit,
|
|
1178
1279
|
ForgotPasswordForm,
|
|
1179
1280
|
InvitationNotice,
|
|
@@ -1182,8 +1283,14 @@ export {
|
|
|
1182
1283
|
ResetPasswordForm,
|
|
1183
1284
|
SocialButtons,
|
|
1184
1285
|
VerifyEmailForm,
|
|
1286
|
+
clearOAuthError,
|
|
1287
|
+
initialOAuthError,
|
|
1288
|
+
isEmailNotVerified,
|
|
1185
1289
|
isInvitationFailure,
|
|
1290
|
+
normalizeInviteToken,
|
|
1291
|
+
oauthErrorMessage,
|
|
1186
1292
|
useLogout,
|
|
1187
|
-
useSession
|
|
1293
|
+
useSession,
|
|
1294
|
+
withInviteToken
|
|
1188
1295
|
};
|
|
1189
1296
|
//# sourceMappingURL=index.js.map
|