@lalternative/auth 0.7.0 → 0.8.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/25 bg-background",
24
25
  ...props
25
26
  }) {
26
27
  const id = useId();
@@ -50,13 +51,13 @@ 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
+ "h-[52px] w-full rounded-lg border px-4 text-base",
54
55
  "sm:h-11 sm:text-sm",
55
56
  isPassword ? "pr-12" : "",
56
57
  "text-foreground placeholder:text-muted-foreground/70",
57
58
  "transition-[border-color,box-shadow] duration-150 ease-out",
58
59
  "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",
60
+ invalid ? "border-destructive bg-background focus-visible:border-destructive focus-visible:ring-destructive/20" : `${fieldClassName} focus-visible:border-ring focus-visible:ring-ring/15`,
60
61
  "disabled:cursor-not-allowed disabled:opacity-60"
61
62
  ].filter(Boolean).join(" ")
62
63
  }
@@ -105,7 +106,8 @@ function AuthSubmit({
105
106
  pending = false,
106
107
  disabled = false,
107
108
  pendingLabel,
108
- children
109
+ children,
110
+ className = "bg-primary text-primary-foreground hover:bg-primary/90"
109
111
  }) {
110
112
  return /* @__PURE__ */ jsxs2(
111
113
  "button",
@@ -114,10 +116,11 @@ function AuthSubmit({
114
116
  disabled: disabled || pending,
115
117
  "aria-busy": pending || void 0,
116
118
  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
+ "relative flex h-[52px] w-full items-center justify-center rounded-lg sm:h-11",
120
+ "text-base font-medium sm:text-sm",
121
+ className,
119
122
  "shadow-sm transition-[background-color,transform,box-shadow] duration-150 ease-out",
120
- "hover:bg-primary/90 active:translate-y-px",
123
+ "active:translate-y-px",
121
124
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
122
125
  "disabled:pointer-events-none disabled:opacity-55"
123
126
  ].join(" "),
@@ -147,7 +150,7 @@ function AuthAlert({ children, tone = "error" }) {
147
150
  role: tone === "error" ? "alert" : "status",
148
151
  "aria-live": tone === "error" ? "assertive" : "polite",
149
152
  className: children ? [
150
- "rounded-xl border px-3.5 py-3 text-sm leading-snug",
153
+ "rounded-lg border px-3.5 py-3 text-sm leading-snug",
151
154
  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
155
  ].join(" ") : void 0,
153
156
  children
@@ -155,21 +158,8 @@ function AuthAlert({ children, tone = "error" }) {
155
158
  );
156
159
  }
157
160
 
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
161
  // src/components/social-buttons.tsx
172
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
162
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
173
163
  var LABELS = {
174
164
  google: "Continuer avec Google",
175
165
  github: "Continuer avec GitHub"
@@ -183,17 +173,17 @@ function SocialButtons({
183
173
  }) {
184
174
  if (providers.length === 0) return null;
185
175
  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" })
176
+ return /* @__PURE__ */ jsxs3("div", { className: "space-y-4", children: [
177
+ /* @__PURE__ */ jsxs3("div", { "aria-hidden": "true", className: "flex items-center gap-3", children: [
178
+ /* @__PURE__ */ jsx4("span", { className: "h-px flex-1 bg-border" }),
179
+ /* @__PURE__ */ jsx4("span", { className: "text-[11px] uppercase tracking-[0.14em] text-muted-foreground", children: separator }),
180
+ /* @__PURE__ */ jsx4("span", { className: "h-px flex-1 bg-border" })
191
181
  ] }),
192
- /* @__PURE__ */ jsx5(
182
+ /* @__PURE__ */ jsx4(
193
183
  "div",
194
184
  {
195
185
  className: providers.length > 1 ? "grid gap-2.5 sm:grid-cols-2" : "grid gap-2.5",
196
- children: providers.map((provider) => /* @__PURE__ */ jsxs4(
186
+ children: providers.map((provider) => /* @__PURE__ */ jsxs3(
197
187
  "button",
198
188
  {
199
189
  type: "button",
@@ -201,16 +191,16 @@ function SocialButtons({
201
191
  disabled,
202
192
  "aria-label": copy[provider] ?? provider,
203
193
  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",
194
+ "flex h-[52px] w-full items-center justify-center gap-2.5 rounded-lg sm:h-11",
195
+ "border border-foreground/25 bg-background text-base font-medium text-foreground sm:text-sm",
206
196
  "transition-[background-color,border-color,transform] duration-150 ease-out",
207
197
  "hover:border-foreground/20 hover:bg-accent active:translate-y-px",
208
198
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
209
199
  "disabled:pointer-events-none disabled:opacity-55"
210
200
  ].join(" "),
211
201
  children: [
212
- /* @__PURE__ */ jsx5(ProviderMark, { provider }),
213
- /* @__PURE__ */ jsx5("span", { className: providers.length > 1 ? "sm:hidden" : "", children: copy[provider] ?? provider })
202
+ /* @__PURE__ */ jsx4(ProviderMark, { provider }),
203
+ /* @__PURE__ */ jsx4("span", { className: providers.length > 1 ? "sm:hidden" : "", children: copy[provider] ?? provider })
214
204
  ]
215
205
  },
216
206
  provider
@@ -221,29 +211,29 @@ function SocialButtons({
221
211
  }
222
212
  function ProviderMark({ provider }) {
223
213
  if (provider === "google") {
224
- return /* @__PURE__ */ jsxs4("svg", { width: "17", height: "17", viewBox: "0 0 18 18", "aria-hidden": "true", children: [
225
- /* @__PURE__ */ jsx5(
214
+ return /* @__PURE__ */ jsxs3("svg", { width: "17", height: "17", viewBox: "0 0 18 18", "aria-hidden": "true", children: [
215
+ /* @__PURE__ */ jsx4(
226
216
  "path",
227
217
  {
228
218
  fill: "#4285F4",
229
219
  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
220
  }
231
221
  ),
232
- /* @__PURE__ */ jsx5(
222
+ /* @__PURE__ */ jsx4(
233
223
  "path",
234
224
  {
235
225
  fill: "#34A853",
236
226
  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
227
  }
238
228
  ),
239
- /* @__PURE__ */ jsx5(
229
+ /* @__PURE__ */ jsx4(
240
230
  "path",
241
231
  {
242
232
  fill: "#FBBC05",
243
233
  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
234
  }
245
235
  ),
246
- /* @__PURE__ */ jsx5(
236
+ /* @__PURE__ */ jsx4(
247
237
  "path",
248
238
  {
249
239
  fill: "#EA4335",
@@ -252,11 +242,11 @@ function ProviderMark({ provider }) {
252
242
  )
253
243
  ] });
254
244
  }
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" }) });
245
+ 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" }) });
256
246
  }
257
247
 
258
248
  // src/components/login-form.tsx
259
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
249
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
260
250
  var DEFAULTS = {
261
251
  title: "Connexion",
262
252
  subtitle: "Content de te revoir. Entre tes identifiants pour continuer.",
@@ -285,7 +275,8 @@ function LoginForm({
285
275
  socialProviders = [],
286
276
  coreTokenUrl = "/api/auth/core-token",
287
277
  labels,
288
- titleClassName,
278
+ submitClassName,
279
+ fieldClassName,
289
280
  error: externalError,
290
281
  authClient
291
282
  }) {
@@ -341,18 +332,10 @@ function LoginForm({
341
332
  );
342
333
  }
343
334
  };
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
- ),
353
- /* @__PURE__ */ jsx6(AuthAlert, { children: error }),
354
- /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
355
- /* @__PURE__ */ jsx6(
335
+ return /* @__PURE__ */ jsxs4("div", { className: "space-y-6", children: [
336
+ /* @__PURE__ */ jsx5(AuthAlert, { children: error }),
337
+ /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
338
+ /* @__PURE__ */ jsx5(
356
339
  AuthField,
357
340
  {
358
341
  label: t.emailPlaceholder,
@@ -365,10 +348,11 @@ function LoginForm({
365
348
  autoComplete: "email",
366
349
  autoCapitalize: "none",
367
350
  spellCheck: false,
368
- invalid: !!error
351
+ invalid: !!error,
352
+ fieldClassName
369
353
  }
370
354
  ),
371
- /* @__PURE__ */ jsx6(
355
+ /* @__PURE__ */ jsx5(
372
356
  AuthField,
373
357
  {
374
358
  label: t.passwordPlaceholder,
@@ -379,7 +363,8 @@ function LoginForm({
379
363
  disabled: isPending,
380
364
  autoComplete: "current-password",
381
365
  invalid: !!error,
382
- hint: /* @__PURE__ */ jsx6(
366
+ fieldClassName,
367
+ hint: /* @__PURE__ */ jsx5(
383
368
  "a",
384
369
  {
385
370
  href: forgotPasswordUrl,
@@ -389,17 +374,18 @@ function LoginForm({
389
374
  )
390
375
  }
391
376
  ),
392
- /* @__PURE__ */ jsx6(
377
+ /* @__PURE__ */ jsx5(
393
378
  AuthSubmit,
394
379
  {
395
380
  pending: isPending,
396
381
  disabled: !email.trim() || !password,
397
382
  pendingLabel: t.submitPending,
383
+ className: submitClassName,
398
384
  children: t.submit
399
385
  }
400
386
  )
401
387
  ] }),
402
- /* @__PURE__ */ jsx6(
388
+ /* @__PURE__ */ jsx5(
403
389
  SocialButtons,
404
390
  {
405
391
  providers: socialProviders,
@@ -407,10 +393,10 @@ function LoginForm({
407
393
  disabled: isPending
408
394
  }
409
395
  ),
410
- /* @__PURE__ */ jsxs5("p", { className: "text-center text-sm text-muted-foreground", children: [
396
+ /* @__PURE__ */ jsxs4("p", { className: "text-center text-sm text-muted-foreground", children: [
411
397
  t.noAccount,
412
398
  " ",
413
- /* @__PURE__ */ jsx6(
399
+ /* @__PURE__ */ jsx5(
414
400
  "a",
415
401
  {
416
402
  href: registerUrl,
@@ -421,10 +407,14 @@ function LoginForm({
421
407
  ] })
422
408
  ] });
423
409
  }
410
+ LoginForm.defaults = {
411
+ title: DEFAULTS.title,
412
+ subtitle: DEFAULTS.subtitle
413
+ };
424
414
 
425
415
  // src/components/register-form.tsx
426
416
  import { useState as useState3 } from "react";
427
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
417
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
428
418
  var MIN_PASSWORD_LENGTH = 8;
429
419
  var DEFAULTS2 = {
430
420
  title: "Cr\xE9er un compte",
@@ -433,6 +423,8 @@ var DEFAULTS2 = {
433
423
  emailPlaceholder: "Adresse e-mail",
434
424
  passwordPlaceholder: "Mot de passe",
435
425
  passwordHint: `Au moins ${MIN_PASSWORD_LENGTH} caract\xE8res.`,
426
+ confirmPlaceholder: "Confirme le mot de passe",
427
+ passwordMismatch: "Les deux mots de passe ne correspondent pas",
436
428
  submit: "Cr\xE9er mon compte",
437
429
  submitPending: "Cr\xE9ation\u2026",
438
430
  haveAccount: "Tu as d\xE9j\xE0 un compte ?",
@@ -449,7 +441,8 @@ function RegisterForm({
449
441
  socialCallbackUrl = "/",
450
442
  socialProviders = [],
451
443
  labels,
452
- titleClassName,
444
+ submitClassName,
445
+ fieldClassName,
453
446
  error: externalError,
454
447
  authClient
455
448
  }) {
@@ -457,11 +450,13 @@ function RegisterForm({
457
450
  const [name, setName] = useState3("");
458
451
  const [email, setEmail] = useState3("");
459
452
  const [password, setPassword] = useState3("");
453
+ const [confirmPassword, setConfirmPassword] = useState3("");
460
454
  const [ownError, setOwnError] = useState3();
461
455
  const [isPending, setIsPending] = useState3(false);
462
456
  const error = ownError ?? externalError;
463
457
  const setError = setOwnError;
464
458
  const tooShort = password.length > 0 && password.length < MIN_PASSWORD_LENGTH;
459
+ const mismatch = confirmPassword.length > 0 && confirmPassword !== password;
465
460
  const handleSubmit = async (e) => {
466
461
  e.preventDefault();
467
462
  if (!name.trim()) {
@@ -476,6 +471,10 @@ function RegisterForm({
476
471
  setError(t.passwordTooShort);
477
472
  return;
478
473
  }
474
+ if (password !== confirmPassword) {
475
+ setError(t.passwordMismatch);
476
+ return;
477
+ }
479
478
  setError(void 0);
480
479
  setIsPending(true);
481
480
  try {
@@ -506,18 +505,10 @@ function RegisterForm({
506
505
  setError(err instanceof Error ? err.message : t.signUpFailed);
507
506
  }
508
507
  };
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
- ),
518
- /* @__PURE__ */ jsx7(AuthAlert, { children: error }),
519
- /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
520
- /* @__PURE__ */ jsx7(
508
+ return /* @__PURE__ */ jsxs5("div", { className: "space-y-6", children: [
509
+ /* @__PURE__ */ jsx6(AuthAlert, { children: error }),
510
+ /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
511
+ /* @__PURE__ */ jsx6(
521
512
  AuthField,
522
513
  {
523
514
  label: t.namePlaceholder,
@@ -526,10 +517,11 @@ function RegisterForm({
526
517
  onChange: (e) => setName(e.target.value),
527
518
  required: true,
528
519
  disabled: isPending,
529
- autoComplete: "name"
520
+ autoComplete: "name",
521
+ fieldClassName
530
522
  }
531
523
  ),
532
- /* @__PURE__ */ jsx7(
524
+ /* @__PURE__ */ jsx6(
533
525
  AuthField,
534
526
  {
535
527
  label: t.emailPlaceholder,
@@ -541,10 +533,11 @@ function RegisterForm({
541
533
  disabled: isPending,
542
534
  autoComplete: "email",
543
535
  autoCapitalize: "none",
544
- spellCheck: false
536
+ spellCheck: false,
537
+ fieldClassName
545
538
  }
546
539
  ),
547
- /* @__PURE__ */ jsx7(
540
+ /* @__PURE__ */ jsx6(
548
541
  AuthField,
549
542
  {
550
543
  label: t.passwordPlaceholder,
@@ -555,13 +548,36 @@ function RegisterForm({
555
548
  disabled: isPending,
556
549
  autoComplete: "new-password",
557
550
  description: t.passwordHint,
558
- invalid: tooShort
551
+ invalid: tooShort,
552
+ fieldClassName
553
+ }
554
+ ),
555
+ /* @__PURE__ */ jsx6(
556
+ AuthField,
557
+ {
558
+ label: t.confirmPlaceholder,
559
+ type: "password",
560
+ value: confirmPassword,
561
+ onChange: (e) => setConfirmPassword(e.target.value),
562
+ required: true,
563
+ disabled: isPending,
564
+ autoComplete: "new-password",
565
+ invalid: mismatch,
566
+ fieldClassName
559
567
  }
560
568
  ),
561
- /* @__PURE__ */ jsx7(AuthSubmit, { pending: isPending, pendingLabel: t.submitPending, children: t.submit }),
562
- legal && /* @__PURE__ */ jsx7("p", { className: "text-center text-xs leading-relaxed text-muted-foreground", children: legal })
569
+ /* @__PURE__ */ jsx6(
570
+ AuthSubmit,
571
+ {
572
+ pending: isPending,
573
+ pendingLabel: t.submitPending,
574
+ className: submitClassName,
575
+ children: t.submit
576
+ }
577
+ ),
578
+ legal && /* @__PURE__ */ jsx6("p", { className: "text-center text-xs leading-relaxed text-muted-foreground", children: legal })
563
579
  ] }),
564
- /* @__PURE__ */ jsx7(
580
+ /* @__PURE__ */ jsx6(
565
581
  SocialButtons,
566
582
  {
567
583
  providers: socialProviders,
@@ -569,10 +585,10 @@ function RegisterForm({
569
585
  disabled: isPending
570
586
  }
571
587
  ),
572
- /* @__PURE__ */ jsxs6("p", { className: "text-center text-sm text-muted-foreground", children: [
588
+ /* @__PURE__ */ jsxs5("p", { className: "text-center text-sm text-muted-foreground", children: [
573
589
  t.haveAccount,
574
590
  " ",
575
- /* @__PURE__ */ jsx7(
591
+ /* @__PURE__ */ jsx6(
576
592
  "a",
577
593
  {
578
594
  href: loginUrl,
@@ -583,12 +599,16 @@ function RegisterForm({
583
599
  ] })
584
600
  ] });
585
601
  }
602
+ RegisterForm.defaults = {
603
+ title: DEFAULTS2.title,
604
+ subtitle: DEFAULTS2.subtitle
605
+ };
586
606
 
587
607
  // src/components/verify-email-form.tsx
588
608
  import { useState as useState4 } from "react";
589
609
 
590
610
  // src/components/auth-otp-field.tsx
591
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
611
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
592
612
  var OTP_LENGTH = 6;
593
613
  function AuthOtpField({
594
614
  label,
@@ -596,10 +616,11 @@ function AuthOtpField({
596
616
  onChange,
597
617
  disabled = false,
598
618
  invalid = false,
599
- id
619
+ id,
620
+ fieldClassName = "border-foreground/25 bg-background"
600
621
  }) {
601
- return /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
602
- /* @__PURE__ */ jsx8(
622
+ return /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
623
+ /* @__PURE__ */ jsx7(
603
624
  "label",
604
625
  {
605
626
  htmlFor: id,
@@ -607,7 +628,7 @@ function AuthOtpField({
607
628
  children: label
608
629
  }
609
630
  ),
610
- /* @__PURE__ */ jsx8(
631
+ /* @__PURE__ */ jsx7(
611
632
  "input",
612
633
  {
613
634
  id,
@@ -622,12 +643,12 @@ function AuthOtpField({
622
643
  autoComplete: "one-time-code",
623
644
  "aria-invalid": invalid || void 0,
624
645
  className: [
625
- "h-[52px] w-full rounded-xl border bg-background px-4 sm:h-11",
646
+ "h-[52px] w-full rounded-lg border px-4 sm:h-11",
626
647
  "text-center font-mono text-lg tracking-[0.4em]",
627
648
  "text-foreground",
628
649
  "transition-[border-color,box-shadow] duration-150 ease-out",
629
650
  "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",
651
+ 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
652
  "disabled:cursor-not-allowed disabled:opacity-60"
632
653
  ].join(" ")
633
654
  }
@@ -636,7 +657,7 @@ function AuthOtpField({
636
657
  }
637
658
 
638
659
  // src/components/verify-email-form.tsx
639
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
660
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
640
661
  var DEFAULTS3 = {
641
662
  title: "V\xE9rifie ton adresse",
642
663
  subtitle: "Entre le code \xE0 6 chiffres envoy\xE9 \xE0",
@@ -659,7 +680,8 @@ function VerifyEmailForm({
659
680
  onSuccess,
660
681
  loginUrl = "/login",
661
682
  labels,
662
- titleClassName,
683
+ submitClassName,
684
+ fieldClassName,
663
685
  authClient
664
686
  }) {
665
687
  const t = { ...DEFAULTS3, ...labels };
@@ -710,40 +732,34 @@ function VerifyEmailForm({
710
732
  setIsResending(false);
711
733
  }
712
734
  };
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
- ),
722
- /* @__PURE__ */ jsx9(AuthAlert, { children: error }),
723
- /* @__PURE__ */ jsx9(AuthAlert, { tone: "success", children: resendMessage }),
724
- /* @__PURE__ */ jsxs8("form", { onSubmit: handleVerify, className: "space-y-5", noValidate: true, children: [
725
- /* @__PURE__ */ jsx9(
735
+ return /* @__PURE__ */ jsxs7("div", { className: "space-y-6", children: [
736
+ /* @__PURE__ */ jsx8(AuthAlert, { children: error }),
737
+ /* @__PURE__ */ jsx8(AuthAlert, { tone: "success", children: resendMessage }),
738
+ /* @__PURE__ */ jsxs7("form", { onSubmit: handleVerify, className: "space-y-5", noValidate: true, children: [
739
+ /* @__PURE__ */ jsx8(
726
740
  AuthOtpField,
727
741
  {
728
742
  id: "verify-email-otp",
729
743
  label: t.codePlaceholder,
730
744
  value: otp,
731
745
  onChange: setOtp,
732
- disabled: isVerifying
746
+ disabled: isVerifying,
747
+ fieldClassName
733
748
  }
734
749
  ),
735
- /* @__PURE__ */ jsx9(
750
+ /* @__PURE__ */ jsx8(
736
751
  AuthSubmit,
737
752
  {
738
753
  pending: isVerifying,
739
754
  disabled: otp.length < OTP_LENGTH,
740
755
  pendingLabel: t.submitPending,
756
+ className: submitClassName,
741
757
  children: t.submit
742
758
  }
743
759
  )
744
760
  ] }),
745
- /* @__PURE__ */ jsxs8("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
746
- /* @__PURE__ */ jsx9(
761
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
762
+ /* @__PURE__ */ jsx8(
747
763
  "button",
748
764
  {
749
765
  type: "button",
@@ -753,10 +769,10 @@ function VerifyEmailForm({
753
769
  children: isResending ? t.resendPending : t.resend
754
770
  }
755
771
  ),
756
- /* @__PURE__ */ jsxs8("p", { children: [
772
+ /* @__PURE__ */ jsxs7("p", { children: [
757
773
  t.alreadyVerified,
758
774
  " ",
759
- /* @__PURE__ */ jsx9(
775
+ /* @__PURE__ */ jsx8(
760
776
  "a",
761
777
  {
762
778
  href: loginUrl,
@@ -768,10 +784,14 @@ function VerifyEmailForm({
768
784
  ] })
769
785
  ] });
770
786
  }
787
+ VerifyEmailForm.defaults = {
788
+ title: DEFAULTS3.title,
789
+ subtitle: DEFAULTS3.subtitle
790
+ };
771
791
 
772
792
  // src/components/forgot-password-form.tsx
773
793
  import { useState as useState5 } from "react";
774
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
794
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
775
795
  var DEFAULTS4 = {
776
796
  title: "Mot de passe oubli\xE9 ?",
777
797
  subtitle: "Entre ton adresse e-mail et nous t'enverrons un code pour le r\xE9initialiser.",
@@ -787,7 +807,8 @@ function ForgotPasswordForm({
787
807
  onSuccess,
788
808
  loginUrl = "/login",
789
809
  labels,
790
- titleClassName,
810
+ submitClassName,
811
+ fieldClassName,
791
812
  authClient
792
813
  }) {
793
814
  const t = { ...DEFAULTS4, ...labels };
@@ -818,18 +839,10 @@ function ForgotPasswordForm({
818
839
  setIsPending(false);
819
840
  }
820
841
  };
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
- ),
830
- /* @__PURE__ */ jsx10(AuthAlert, { children: error }),
831
- /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
832
- /* @__PURE__ */ jsx10(
842
+ return /* @__PURE__ */ jsxs8("div", { className: "space-y-6", children: [
843
+ /* @__PURE__ */ jsx9(AuthAlert, { children: error }),
844
+ /* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
845
+ /* @__PURE__ */ jsx9(
833
846
  AuthField,
834
847
  {
835
848
  label: t.emailPlaceholder,
@@ -845,20 +858,21 @@ function ForgotPasswordForm({
845
858
  invalid: !!error
846
859
  }
847
860
  ),
848
- /* @__PURE__ */ jsx10(
861
+ /* @__PURE__ */ jsx9(
849
862
  AuthSubmit,
850
863
  {
851
864
  pending: isPending,
852
865
  disabled: !email.trim(),
853
866
  pendingLabel: t.submitPending,
867
+ className: submitClassName,
854
868
  children: t.submit
855
869
  }
856
870
  )
857
871
  ] }),
858
- /* @__PURE__ */ jsxs9("p", { className: "text-center text-sm text-muted-foreground", children: [
872
+ /* @__PURE__ */ jsxs8("p", { className: "text-center text-sm text-muted-foreground", children: [
859
873
  t.rememberPassword,
860
874
  " ",
861
- /* @__PURE__ */ jsx10(
875
+ /* @__PURE__ */ jsx9(
862
876
  "a",
863
877
  {
864
878
  href: loginUrl,
@@ -869,10 +883,14 @@ function ForgotPasswordForm({
869
883
  ] })
870
884
  ] });
871
885
  }
886
+ ForgotPasswordForm.defaults = {
887
+ title: DEFAULTS4.title,
888
+ subtitle: DEFAULTS4.subtitle
889
+ };
872
890
 
873
891
  // src/components/reset-password-form.tsx
874
892
  import { useState as useState6 } from "react";
875
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
893
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
876
894
  var MIN_PASSWORD_LENGTH2 = 8;
877
895
  var DEFAULTS5 = {
878
896
  title: "Nouveau mot de passe",
@@ -899,7 +917,8 @@ function ResetPasswordForm({
899
917
  onSuccess,
900
918
  loginUrl = "/login",
901
919
  labels,
902
- titleClassName,
920
+ submitClassName,
921
+ fieldClassName,
903
922
  authClient
904
923
  }) {
905
924
  const t = { ...DEFAULTS5, ...labels };
@@ -963,29 +982,22 @@ function ResetPasswordForm({
963
982
  setIsResending(false);
964
983
  }
965
984
  };
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
- ),
975
- /* @__PURE__ */ jsx11(AuthAlert, { children: error }),
976
- /* @__PURE__ */ jsx11(AuthAlert, { tone: "success", children: resendMessage }),
977
- /* @__PURE__ */ jsxs10("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
978
- /* @__PURE__ */ jsx11(
985
+ return /* @__PURE__ */ jsxs9("div", { className: "space-y-6", children: [
986
+ /* @__PURE__ */ jsx10(AuthAlert, { children: error }),
987
+ /* @__PURE__ */ jsx10(AuthAlert, { tone: "success", children: resendMessage }),
988
+ /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "space-y-5", noValidate: true, children: [
989
+ /* @__PURE__ */ jsx10(
979
990
  AuthOtpField,
980
991
  {
981
992
  id: "reset-password-otp",
982
993
  label: t.codePlaceholder,
983
994
  value: otp,
984
995
  onChange: setOtp,
985
- disabled: isResetting
996
+ disabled: isResetting,
997
+ fieldClassName
986
998
  }
987
999
  ),
988
- /* @__PURE__ */ jsx11(
1000
+ /* @__PURE__ */ jsx10(
989
1001
  AuthField,
990
1002
  {
991
1003
  label: t.passwordPlaceholder,
@@ -999,7 +1011,7 @@ function ResetPasswordForm({
999
1011
  invalid: tooShort
1000
1012
  }
1001
1013
  ),
1002
- /* @__PURE__ */ jsx11(
1014
+ /* @__PURE__ */ jsx10(
1003
1015
  AuthField,
1004
1016
  {
1005
1017
  label: t.confirmPlaceholder,
@@ -1012,18 +1024,19 @@ function ResetPasswordForm({
1012
1024
  invalid: mismatch
1013
1025
  }
1014
1026
  ),
1015
- /* @__PURE__ */ jsx11(
1027
+ /* @__PURE__ */ jsx10(
1016
1028
  AuthSubmit,
1017
1029
  {
1018
1030
  pending: isResetting,
1019
1031
  disabled: otp.length < OTP_LENGTH || !password || !confirmPassword,
1020
1032
  pendingLabel: t.submitPending,
1033
+ className: submitClassName,
1021
1034
  children: t.submit
1022
1035
  }
1023
1036
  )
1024
1037
  ] }),
1025
- /* @__PURE__ */ jsxs10("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
1026
- /* @__PURE__ */ jsx11(
1038
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-4 text-center text-sm text-muted-foreground", children: [
1039
+ /* @__PURE__ */ jsx10(
1027
1040
  "button",
1028
1041
  {
1029
1042
  type: "button",
@@ -1033,10 +1046,10 @@ function ResetPasswordForm({
1033
1046
  children: isResending ? t.resendPending : t.resend
1034
1047
  }
1035
1048
  ),
1036
- /* @__PURE__ */ jsxs10("p", { children: [
1049
+ /* @__PURE__ */ jsxs9("p", { children: [
1037
1050
  t.rememberPassword,
1038
1051
  " ",
1039
- /* @__PURE__ */ jsx11(
1052
+ /* @__PURE__ */ jsx10(
1040
1053
  "a",
1041
1054
  {
1042
1055
  href: loginUrl,
@@ -1048,49 +1061,71 @@ function ResetPasswordForm({
1048
1061
  ] })
1049
1062
  ] });
1050
1063
  }
1064
+ ResetPasswordForm.defaults = {
1065
+ title: DEFAULTS5.title,
1066
+ subtitle: DEFAULTS5.subtitle
1067
+ };
1068
+
1069
+ // src/components/auth-heading.tsx
1070
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1071
+ function AuthHeading({
1072
+ title,
1073
+ subtitle,
1074
+ titleClassName = "text-2xl font-semibold tracking-tight"
1075
+ }) {
1076
+ return /* @__PURE__ */ jsxs10("header", { className: "space-y-1.5 text-center", children: [
1077
+ /* @__PURE__ */ jsx11("h1", { className: `leading-tight text-foreground ${titleClassName}`, children: title }),
1078
+ subtitle && /* @__PURE__ */ jsx11("p", { className: "text-balance text-sm leading-relaxed text-muted-foreground", children: subtitle })
1079
+ ] });
1080
+ }
1051
1081
 
1052
1082
  // src/components/auth-layout.tsx
1053
1083
  import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1054
1084
  function AuthLayout({
1055
1085
  logo,
1056
1086
  panel,
1087
+ title,
1088
+ subtitle,
1089
+ titleClassName,
1057
1090
  children,
1058
1091
  footer
1059
1092
  }) {
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
- ) });
1093
+ 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("div", { className: `mx-auto w-full ${panel ? "max-w-4xl" : "max-w-[420px]"}`, children: [
1094
+ (logo || title) && /* @__PURE__ */ jsxs11("div", { className: "mb-7 space-y-5", children: [
1095
+ logo && /* @__PURE__ */ jsx12("div", { className: "flex justify-center", children: logo }),
1096
+ title && /* @__PURE__ */ jsx12(
1097
+ AuthHeading,
1098
+ {
1099
+ title,
1100
+ subtitle,
1101
+ titleClassName
1102
+ }
1103
+ )
1104
+ ] }),
1105
+ /* @__PURE__ */ jsxs11(
1106
+ "div",
1107
+ {
1108
+ className: [
1109
+ "sm:rounded-lg sm:border sm:border-border/70 sm:bg-card sm:shadow-sm",
1110
+ panel ? "sm:overflow-hidden md:grid md:grid-cols-2" : ""
1111
+ ].filter(Boolean).join(" "),
1112
+ children: [
1113
+ panel && // Decorative: it must never carry information the form does not,
1114
+ // so it is hidden from assistive tech rather than described.
1115
+ /* @__PURE__ */ jsx12(
1116
+ "div",
1117
+ {
1118
+ "aria-hidden": "true",
1119
+ className: "relative hidden overflow-hidden bg-muted md:block [&>*]:absolute [&>*]:inset-0 [&>*]:h-full [&>*]:w-full [&>img]:object-cover",
1120
+ children: panel
1121
+ }
1122
+ ),
1123
+ /* @__PURE__ */ jsx12("div", { className: "flex flex-col justify-center sm:p-8", children })
1124
+ ]
1125
+ }
1126
+ ),
1127
+ footer && /* @__PURE__ */ jsx12("div", { className: "mt-6 text-center text-xs leading-relaxed text-muted-foreground", children: footer })
1128
+ ] }) });
1094
1129
  }
1095
1130
 
1096
1131
  // src/components/invitation-notice.tsx