@forjio/auth-ui 0.5.0 → 0.7.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/AuthForm.cjs +38 -30
- package/dist/AuthForm.cjs.map +1 -1
- package/dist/AuthForm.d.cts +2 -2
- package/dist/AuthForm.d.ts +2 -2
- package/dist/AuthForm.js +38 -30
- package/dist/AuthForm.js.map +1 -1
- package/dist/ForgotPasswordForm.cjs +11 -6
- package/dist/ForgotPasswordForm.cjs.map +1 -1
- package/dist/ForgotPasswordForm.d.cts +2 -2
- package/dist/ForgotPasswordForm.d.ts +2 -2
- package/dist/ForgotPasswordForm.js +11 -6
- package/dist/ForgotPasswordForm.js.map +1 -1
- package/dist/ResetPasswordForm.cjs +8 -5
- package/dist/ResetPasswordForm.cjs.map +1 -1
- package/dist/ResetPasswordForm.d.cts +2 -2
- package/dist/ResetPasswordForm.d.ts +2 -2
- package/dist/ResetPasswordForm.js +8 -5
- package/dist/ResetPasswordForm.js.map +1 -1
- package/dist/components/ui/button.cjs +84 -0
- package/dist/components/ui/button.cjs.map +1 -0
- package/dist/components/ui/button.d.cts +14 -0
- package/dist/components/ui/button.d.ts +14 -0
- package/dist/components/ui/button.js +49 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/input.cjs +58 -0
- package/dist/components/ui/input.cjs.map +1 -0
- package/dist/components/ui/input.d.cts +5 -0
- package/dist/components/ui/input.d.ts +5 -0
- package/dist/components/ui/input.js +24 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/label.cjs +56 -0
- package/dist/components/ui/label.cjs.map +1 -0
- package/dist/components/ui/label.d.cts +8 -0
- package/dist/components/ui/label.d.ts +8 -0
- package/dist/components/ui/label.js +22 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/lib/utils.cjs +33 -0
- package/dist/lib/utils.cjs.map +1 -0
- package/dist/lib/utils.d.cts +9 -0
- package/dist/lib/utils.d.ts +9 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/useTurnstileTheme.cjs +44 -0
- package/dist/useTurnstileTheme.cjs.map +1 -0
- package/dist/useTurnstileTheme.d.cts +3 -0
- package/dist/useTurnstileTheme.d.ts +3 -0
- package/dist/useTurnstileTheme.js +20 -0
- package/dist/useTurnstileTheme.js.map +1 -0
- package/package.json +7 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ForgotPasswordForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport Link from 'next/link';\nimport { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { Turnstile } from '@marsidev/react-turnstile';\nimport { defaultEndpoints, type AuthEndpoints } from './types';\n\n// Enabled family-wide via NEXT_PUBLIC_TURNSTILE_SITE_KEY (see AuthForm).\nconst TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;\n\nexport interface ForgotPasswordFormProps {\n endpoints?: Partial<AuthEndpoints>;\n}\n\nexport function ForgotPasswordForm({ endpoints }: ForgotPasswordFormProps = {}) {\n const ep: AuthEndpoints = { ...defaultEndpoints, ...endpoints };\n const [email, setEmail] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [sent, setSent] = useState(false);\n const [turnstileToken, setTurnstileToken] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n const res = await fetch(ep.forgotPassword, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email,\n ...(TURNSTILE_SITE_KEY ? { 'cf-turnstile-response': turnstileToken } : {}),\n }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n throw new Error(payload?.error?.message ?? `Request failed (${res.status})`);\n }\n setSent(true);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n }\n\n if (sent) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-2 rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-sm text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 shrink-0 mt-0.5 text-primary\" />\n <span>\n If <strong>{email}</strong> has a Huudis account, we’ve sent a reset link. It expires in 1 hour.\n </span>\n </div>\n <Link href=\"/login\" className=\"block text-center text-sm font-medium text-foreground hover:underline\">\n Back to sign in\n </Link>\n </div>\n );\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{error}</span>\n </div>\n )}\n <div>\n <
|
|
1
|
+
{"version":3,"sources":["../src/ForgotPasswordForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport Link from 'next/link';\nimport { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { Turnstile } from '@marsidev/react-turnstile';\nimport { useTurnstileTheme } from './useTurnstileTheme';\nimport { Button } from './components/ui/button';\nimport { Input } from './components/ui/input';\nimport { Label } from './components/ui/label';\nimport { defaultEndpoints, type AuthEndpoints } from './types';\n\n// Enabled family-wide via NEXT_PUBLIC_TURNSTILE_SITE_KEY (see AuthForm).\nconst TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;\n\nexport interface ForgotPasswordFormProps {\n endpoints?: Partial<AuthEndpoints>;\n}\n\nexport function ForgotPasswordForm({ endpoints }: ForgotPasswordFormProps = {}) {\n const ep: AuthEndpoints = { ...defaultEndpoints, ...endpoints };\n const [email, setEmail] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [sent, setSent] = useState(false);\n const [turnstileToken, setTurnstileToken] = useState('');\n const turnstileTheme = useTurnstileTheme();\n const [error, setError] = useState<string | null>(null);\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n const res = await fetch(ep.forgotPassword, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email,\n ...(TURNSTILE_SITE_KEY ? { 'cf-turnstile-response': turnstileToken } : {}),\n }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n throw new Error(payload?.error?.message ?? `Request failed (${res.status})`);\n }\n setSent(true);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n }\n\n if (sent) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-2 rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-sm text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 shrink-0 mt-0.5 text-primary\" />\n <span>\n If <strong>{email}</strong> has a Huudis account, we’ve sent a reset link. It expires in 1 hour.\n </span>\n </div>\n <Link href=\"/login\" className=\"block text-center text-sm font-medium text-foreground hover:underline\">\n Back to sign in\n </Link>\n </div>\n );\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{error}</span>\n </div>\n )}\n <div>\n <Label className=\"mb-1 block text-xs leading-4 text-muted-foreground\">Email</Label>\n <Input\n type=\"email\"\n required\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n autoComplete=\"email\"\n autoFocus\n className=\"h-auto border-border bg-background py-2 text-sm shadow-none focus:outline-none focus:ring-1 focus:ring-primary\"\n />\n </div>\n {TURNSTILE_SITE_KEY && (\n <div className=\"flex justify-center py-1\">\n <Turnstile\n siteKey={TURNSTILE_SITE_KEY}\n onSuccess={setTurnstileToken}\n onError={() => setError('Security check failed.')}\n options={{ theme: turnstileTheme }}\n />\n </div>\n )}\n <Button\n type=\"submit\"\n disabled={submitting}\n className=\"flex h-auto w-full py-2.5 shadow-none hover:opacity-90\"\n >\n {submitting && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {submitting ? 'Sending…' : 'Send reset link'}\n </Button>\n <div className=\"text-center text-xs text-muted-foreground\">\n Remembered it?{' '}\n <Link href=\"/login\" className=\"font-medium text-foreground hover:underline\">\n Sign in\n </Link>\n </div>\n </form>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDU;AAvDV,mBAAyB;AACzB,kBAAiB;AACjB,0BAAmD;AACnD,6BAA0B;AAC1B,+BAAkC;AAClC,oBAAuB;AACvB,mBAAsB;AACtB,mBAAsB;AACtB,mBAAqD;AAGrD,MAAM,qBAAqB,QAAQ,IAAI;AAMhC,SAAS,mBAAmB,EAAE,UAAU,IAA6B,CAAC,GAAG;AAC9E,QAAM,KAAoB,EAAE,GAAG,+BAAkB,GAAG,UAAU;AAC9D,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAS,EAAE;AACrC,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,KAAK;AAClD,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,KAAK;AACtC,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,uBAAS,EAAE;AACvD,QAAM,qBAAiB,4CAAkB;AACzC,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB,IAAI;AAEtD,iBAAe,OAAO,GAAoB;AACxC,MAAE,eAAe;AACjB,aAAS,IAAI;AACb,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,gBAAgB;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,GAAI,qBAAqB,EAAE,yBAAyB,eAAe,IAAI,CAAC;AAAA,QAC1E,CAAC;AAAA,MACH,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,UAAW,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAClD,cAAM,IAAI,MAAM,SAAS,OAAO,WAAW,mBAAmB,IAAI,MAAM,GAAG;AAAA,MAC7E;AACA,cAAQ,IAAI;AAAA,IACd,SAAS,KAAK;AACZ,eAAU,IAAc,OAAO;AAAA,IACjC,UAAE;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF;AAEA,MAAI,MAAM;AACR,WACE,6CAAC,SAAI,WAAU,aACb;AAAA,mDAAC,SAAI,WAAU,8GACb;AAAA,oDAAC,oCAAa,WAAU,wCAAuC;AAAA,QAC/D,6CAAC,UAAK;AAAA;AAAA,UACD,4CAAC,YAAQ,iBAAM;AAAA,UAAS;AAAA,WAC7B;AAAA,SACF;AAAA,MACA,4CAAC,YAAAA,SAAA,EAAK,MAAK,UAAS,WAAU,yEAAwE,6BAEtG;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,6CAAC,UAAK,UAAU,QAAQ,WAAU,aAC/B;AAAA,aACC,6CAAC,SAAI,WAAU,uHACb;AAAA,kDAAC,mCAAY,WAAU,2BAA0B;AAAA,MACjD,4CAAC,UAAM,iBAAM;AAAA,OACf;AAAA,IAEF,6CAAC,SACC;AAAA,kDAAC,sBAAM,WAAU,sDAAqD,mBAAK;AAAA,MAC3E;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,UAAQ;AAAA,UACR,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,UACxC,cAAa;AAAA,UACb,WAAS;AAAA,UACT,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IACC,sBACC,4CAAC,SAAI,WAAU,4BACb;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAW;AAAA,QACX,SAAS,MAAM,SAAS,wBAAwB;AAAA,QAChD,SAAS,EAAE,OAAO,eAAe;AAAA;AAAA,IACnC,GACF;AAAA,IAEF;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,UAAU;AAAA,QACV,WAAU;AAAA,QAET;AAAA,wBAAc,4CAAC,+BAAQ,WAAU,wBAAuB;AAAA,UACxD,aAAa,kBAAa;AAAA;AAAA;AAAA,IAC7B;AAAA,IACA,6CAAC,SAAI,WAAU,6CAA4C;AAAA;AAAA,MAC1C;AAAA,MACf,4CAAC,YAAAA,SAAA,EAAK,MAAK,UAAS,WAAU,+CAA8C,qBAE5E;AAAA,OACF;AAAA,KACF;AAEJ;","names":["Link"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import { AuthEndpoints } from './types.cjs';
|
|
3
3
|
|
|
4
4
|
interface ForgotPasswordFormProps {
|
|
5
5
|
endpoints?: Partial<AuthEndpoints>;
|
|
6
6
|
}
|
|
7
|
-
declare function ForgotPasswordForm({ endpoints }?: ForgotPasswordFormProps):
|
|
7
|
+
declare function ForgotPasswordForm({ endpoints }?: ForgotPasswordFormProps): React.JSX.Element;
|
|
8
8
|
|
|
9
9
|
export { ForgotPasswordForm, type ForgotPasswordFormProps };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import { AuthEndpoints } from './types.js';
|
|
3
3
|
|
|
4
4
|
interface ForgotPasswordFormProps {
|
|
5
5
|
endpoints?: Partial<AuthEndpoints>;
|
|
6
6
|
}
|
|
7
|
-
declare function ForgotPasswordForm({ endpoints }?: ForgotPasswordFormProps):
|
|
7
|
+
declare function ForgotPasswordForm({ endpoints }?: ForgotPasswordFormProps): React.JSX.Element;
|
|
8
8
|
|
|
9
9
|
export { ForgotPasswordForm, type ForgotPasswordFormProps };
|
|
@@ -4,6 +4,10 @@ import { useState } from "react";
|
|
|
4
4
|
import Link from "next/link";
|
|
5
5
|
import { Loader2, AlertCircle, CheckCircle2 } from "lucide-react";
|
|
6
6
|
import { Turnstile } from "@marsidev/react-turnstile";
|
|
7
|
+
import { useTurnstileTheme } from "./useTurnstileTheme";
|
|
8
|
+
import { Button } from "./components/ui/button";
|
|
9
|
+
import { Input } from "./components/ui/input";
|
|
10
|
+
import { Label } from "./components/ui/label";
|
|
7
11
|
import { defaultEndpoints } from "./types";
|
|
8
12
|
const TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;
|
|
9
13
|
function ForgotPasswordForm({ endpoints } = {}) {
|
|
@@ -12,6 +16,7 @@ function ForgotPasswordForm({ endpoints } = {}) {
|
|
|
12
16
|
const [submitting, setSubmitting] = useState(false);
|
|
13
17
|
const [sent, setSent] = useState(false);
|
|
14
18
|
const [turnstileToken, setTurnstileToken] = useState("");
|
|
19
|
+
const turnstileTheme = useTurnstileTheme();
|
|
15
20
|
const [error, setError] = useState(null);
|
|
16
21
|
async function submit(e) {
|
|
17
22
|
e.preventDefault();
|
|
@@ -56,9 +61,9 @@ function ForgotPasswordForm({ endpoints } = {}) {
|
|
|
56
61
|
/* @__PURE__ */ jsx("span", { children: error })
|
|
57
62
|
] }),
|
|
58
63
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
59
|
-
/* @__PURE__ */ jsx(
|
|
64
|
+
/* @__PURE__ */ jsx(Label, { className: "mb-1 block text-xs leading-4 text-muted-foreground", children: "Email" }),
|
|
60
65
|
/* @__PURE__ */ jsx(
|
|
61
|
-
|
|
66
|
+
Input,
|
|
62
67
|
{
|
|
63
68
|
type: "email",
|
|
64
69
|
required: true,
|
|
@@ -66,7 +71,7 @@ function ForgotPasswordForm({ endpoints } = {}) {
|
|
|
66
71
|
onChange: (e) => setEmail(e.target.value),
|
|
67
72
|
autoComplete: "email",
|
|
68
73
|
autoFocus: true,
|
|
69
|
-
className: "
|
|
74
|
+
className: "h-auto border-border bg-background py-2 text-sm shadow-none focus:outline-none focus:ring-1 focus:ring-primary"
|
|
70
75
|
}
|
|
71
76
|
)
|
|
72
77
|
] }),
|
|
@@ -76,15 +81,15 @@ function ForgotPasswordForm({ endpoints } = {}) {
|
|
|
76
81
|
siteKey: TURNSTILE_SITE_KEY,
|
|
77
82
|
onSuccess: setTurnstileToken,
|
|
78
83
|
onError: () => setError("Security check failed."),
|
|
79
|
-
options: { theme:
|
|
84
|
+
options: { theme: turnstileTheme }
|
|
80
85
|
}
|
|
81
86
|
) }),
|
|
82
87
|
/* @__PURE__ */ jsxs(
|
|
83
|
-
|
|
88
|
+
Button,
|
|
84
89
|
{
|
|
85
90
|
type: "submit",
|
|
86
91
|
disabled: submitting,
|
|
87
|
-
className: "flex w-full
|
|
92
|
+
className: "flex h-auto w-full py-2.5 shadow-none hover:opacity-90",
|
|
88
93
|
children: [
|
|
89
94
|
submitting && /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
90
95
|
submitting ? "Sending\u2026" : "Send reset link"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ForgotPasswordForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport Link from 'next/link';\nimport { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { Turnstile } from '@marsidev/react-turnstile';\nimport { defaultEndpoints, type AuthEndpoints } from './types';\n\n// Enabled family-wide via NEXT_PUBLIC_TURNSTILE_SITE_KEY (see AuthForm).\nconst TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;\n\nexport interface ForgotPasswordFormProps {\n endpoints?: Partial<AuthEndpoints>;\n}\n\nexport function ForgotPasswordForm({ endpoints }: ForgotPasswordFormProps = {}) {\n const ep: AuthEndpoints = { ...defaultEndpoints, ...endpoints };\n const [email, setEmail] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [sent, setSent] = useState(false);\n const [turnstileToken, setTurnstileToken] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n const res = await fetch(ep.forgotPassword, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email,\n ...(TURNSTILE_SITE_KEY ? { 'cf-turnstile-response': turnstileToken } : {}),\n }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n throw new Error(payload?.error?.message ?? `Request failed (${res.status})`);\n }\n setSent(true);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n }\n\n if (sent) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-2 rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-sm text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 shrink-0 mt-0.5 text-primary\" />\n <span>\n If <strong>{email}</strong> has a Huudis account, we’ve sent a reset link. It expires in 1 hour.\n </span>\n </div>\n <Link href=\"/login\" className=\"block text-center text-sm font-medium text-foreground hover:underline\">\n Back to sign in\n </Link>\n </div>\n );\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{error}</span>\n </div>\n )}\n <div>\n <
|
|
1
|
+
{"version":3,"sources":["../src/ForgotPasswordForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport Link from 'next/link';\nimport { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { Turnstile } from '@marsidev/react-turnstile';\nimport { useTurnstileTheme } from './useTurnstileTheme';\nimport { Button } from './components/ui/button';\nimport { Input } from './components/ui/input';\nimport { Label } from './components/ui/label';\nimport { defaultEndpoints, type AuthEndpoints } from './types';\n\n// Enabled family-wide via NEXT_PUBLIC_TURNSTILE_SITE_KEY (see AuthForm).\nconst TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY;\n\nexport interface ForgotPasswordFormProps {\n endpoints?: Partial<AuthEndpoints>;\n}\n\nexport function ForgotPasswordForm({ endpoints }: ForgotPasswordFormProps = {}) {\n const ep: AuthEndpoints = { ...defaultEndpoints, ...endpoints };\n const [email, setEmail] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [sent, setSent] = useState(false);\n const [turnstileToken, setTurnstileToken] = useState('');\n const turnstileTheme = useTurnstileTheme();\n const [error, setError] = useState<string | null>(null);\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n const res = await fetch(ep.forgotPassword, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email,\n ...(TURNSTILE_SITE_KEY ? { 'cf-turnstile-response': turnstileToken } : {}),\n }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n throw new Error(payload?.error?.message ?? `Request failed (${res.status})`);\n }\n setSent(true);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n }\n\n if (sent) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-2 rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-sm text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 shrink-0 mt-0.5 text-primary\" />\n <span>\n If <strong>{email}</strong> has a Huudis account, we’ve sent a reset link. It expires in 1 hour.\n </span>\n </div>\n <Link href=\"/login\" className=\"block text-center text-sm font-medium text-foreground hover:underline\">\n Back to sign in\n </Link>\n </div>\n );\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{error}</span>\n </div>\n )}\n <div>\n <Label className=\"mb-1 block text-xs leading-4 text-muted-foreground\">Email</Label>\n <Input\n type=\"email\"\n required\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n autoComplete=\"email\"\n autoFocus\n className=\"h-auto border-border bg-background py-2 text-sm shadow-none focus:outline-none focus:ring-1 focus:ring-primary\"\n />\n </div>\n {TURNSTILE_SITE_KEY && (\n <div className=\"flex justify-center py-1\">\n <Turnstile\n siteKey={TURNSTILE_SITE_KEY}\n onSuccess={setTurnstileToken}\n onError={() => setError('Security check failed.')}\n options={{ theme: turnstileTheme }}\n />\n </div>\n )}\n <Button\n type=\"submit\"\n disabled={submitting}\n className=\"flex h-auto w-full py-2.5 shadow-none hover:opacity-90\"\n >\n {submitting && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {submitting ? 'Sending…' : 'Send reset link'}\n </Button>\n <div className=\"text-center text-xs text-muted-foreground\">\n Remembered it?{' '}\n <Link href=\"/login\" className=\"font-medium text-foreground hover:underline\">\n Sign in\n </Link>\n </div>\n </form>\n );\n}\n"],"mappings":";AAyDU,cACA,YADA;AAvDV,SAAS,gBAAgB;AACzB,OAAO,UAAU;AACjB,SAAS,SAAS,aAAa,oBAAoB;AACnD,SAAS,iBAAiB;AAC1B,SAAS,yBAAyB;AAClC,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,wBAA4C;AAGrD,MAAM,qBAAqB,QAAQ,IAAI;AAMhC,SAAS,mBAAmB,EAAE,UAAU,IAA6B,CAAC,GAAG;AAC9E,QAAM,KAAoB,EAAE,GAAG,kBAAkB,GAAG,UAAU;AAC9D,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,EAAE;AACvD,QAAM,iBAAiB,kBAAkB;AACzC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,iBAAe,OAAO,GAAoB;AACxC,MAAE,eAAe;AACjB,aAAS,IAAI;AACb,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,gBAAgB;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,GAAI,qBAAqB,EAAE,yBAAyB,eAAe,IAAI,CAAC;AAAA,QAC1E,CAAC;AAAA,MACH,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,UAAW,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAClD,cAAM,IAAI,MAAM,SAAS,OAAO,WAAW,mBAAmB,IAAI,MAAM,GAAG;AAAA,MAC7E;AACA,cAAQ,IAAI;AAAA,IACd,SAAS,KAAK;AACZ,eAAU,IAAc,OAAO;AAAA,IACjC,UAAE;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF;AAEA,MAAI,MAAM;AACR,WACE,qBAAC,SAAI,WAAU,aACb;AAAA,2BAAC,SAAI,WAAU,8GACb;AAAA,4BAAC,gBAAa,WAAU,wCAAuC;AAAA,QAC/D,qBAAC,UAAK;AAAA;AAAA,UACD,oBAAC,YAAQ,iBAAM;AAAA,UAAS;AAAA,WAC7B;AAAA,SACF;AAAA,MACA,oBAAC,QAAK,MAAK,UAAS,WAAU,yEAAwE,6BAEtG;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,qBAAC,UAAK,UAAU,QAAQ,WAAU,aAC/B;AAAA,aACC,qBAAC,SAAI,WAAU,uHACb;AAAA,0BAAC,eAAY,WAAU,2BAA0B;AAAA,MACjD,oBAAC,UAAM,iBAAM;AAAA,OACf;AAAA,IAEF,qBAAC,SACC;AAAA,0BAAC,SAAM,WAAU,sDAAqD,mBAAK;AAAA,MAC3E;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,UAAQ;AAAA,UACR,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,UACxC,cAAa;AAAA,UACb,WAAS;AAAA,UACT,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IACC,sBACC,oBAAC,SAAI,WAAU,4BACb;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAW;AAAA,QACX,SAAS,MAAM,SAAS,wBAAwB;AAAA,QAChD,SAAS,EAAE,OAAO,eAAe;AAAA;AAAA,IACnC,GACF;AAAA,IAEF;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,UAAU;AAAA,QACV,WAAU;AAAA,QAET;AAAA,wBAAc,oBAAC,WAAQ,WAAU,wBAAuB;AAAA,UACxD,aAAa,kBAAa;AAAA;AAAA;AAAA,IAC7B;AAAA,IACA,qBAAC,SAAI,WAAU,6CAA4C;AAAA;AAAA,MAC1C;AAAA,MACf,oBAAC,QAAK,MAAK,UAAS,WAAU,+CAA8C,qBAE5E;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -37,6 +37,9 @@ var import_react = require("react");
|
|
|
37
37
|
var import_navigation = require("next/navigation");
|
|
38
38
|
var import_link = __toESM(require("next/link"), 1);
|
|
39
39
|
var import_lucide_react = require("lucide-react");
|
|
40
|
+
var import_button = require("./components/ui/button");
|
|
41
|
+
var import_input = require("./components/ui/input");
|
|
42
|
+
var import_label = require("./components/ui/label");
|
|
40
43
|
var import_types = require("./types");
|
|
41
44
|
function ResetPasswordForm({ endpoints } = {}) {
|
|
42
45
|
const ep = { ...import_types.defaultEndpoints, ...endpoints };
|
|
@@ -91,9 +94,9 @@ function ResetPasswordForm({ endpoints } = {}) {
|
|
|
91
94
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: error })
|
|
92
95
|
] }),
|
|
93
96
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
94
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
97
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { className: "mb-1 block text-xs leading-4 text-muted-foreground", children: "New password" }),
|
|
95
98
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
96
|
-
|
|
99
|
+
import_input.Input,
|
|
97
100
|
{
|
|
98
101
|
type: "password",
|
|
99
102
|
required: true,
|
|
@@ -102,17 +105,17 @@ function ResetPasswordForm({ endpoints } = {}) {
|
|
|
102
105
|
onChange: (e) => setPassword(e.target.value),
|
|
103
106
|
autoComplete: "new-password",
|
|
104
107
|
autoFocus: true,
|
|
105
|
-
className: "
|
|
108
|
+
className: "h-auto border-border bg-background py-2 text-sm shadow-none focus:outline-none focus:ring-1 focus:ring-primary"
|
|
106
109
|
}
|
|
107
110
|
),
|
|
108
111
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-1 text-[11px] text-muted-foreground", children: "At least 10 characters, with a letter and a number." })
|
|
109
112
|
] }),
|
|
110
113
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
111
|
-
|
|
114
|
+
import_button.Button,
|
|
112
115
|
{
|
|
113
116
|
type: "submit",
|
|
114
117
|
disabled: submitting,
|
|
115
|
-
className: "flex w-full
|
|
118
|
+
className: "flex h-auto w-full py-2.5 shadow-none hover:opacity-90",
|
|
116
119
|
children: [
|
|
117
120
|
submitting && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
118
121
|
submitting ? "Updating\u2026" : "Update password"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ResetPasswordForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { useRouter, useSearchParams } from 'next/navigation';\nimport Link from 'next/link';\nimport { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { defaultEndpoints, type AuthEndpoints } from './types';\n\nexport interface ResetPasswordFormProps {\n endpoints?: Partial<AuthEndpoints>;\n}\n\nexport function ResetPasswordForm({ endpoints }: ResetPasswordFormProps = {}) {\n const ep: AuthEndpoints = { ...defaultEndpoints, ...endpoints };\n const router = useRouter();\n const params = useSearchParams();\n const token = params?.get('token') ?? '';\n const [password, setPassword] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [done, setDone] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n const res = await fetch(ep.resetPassword, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, password }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n throw new Error(payload?.error?.message ?? `Request failed (${res.status})`);\n }\n setDone(true);\n setTimeout(() => router.push('/login'), 1500);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n }\n\n if (!token) {\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>\n Missing or invalid reset link. <Link href=\"/forgot-password\" className=\"font-medium underline\">Request a new one</Link>.\n </span>\n </div>\n </div>\n );\n }\n\n if (done) {\n return (\n <div className=\"flex items-start gap-2 rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-sm text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 shrink-0 mt-0.5 text-primary\" />\n <span>Password updated. Taking you to sign in…</span>\n </div>\n );\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{error}</span>\n </div>\n )}\n <div>\n <
|
|
1
|
+
{"version":3,"sources":["../src/ResetPasswordForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { useRouter, useSearchParams } from 'next/navigation';\nimport Link from 'next/link';\nimport { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { Button } from './components/ui/button';\nimport { Input } from './components/ui/input';\nimport { Label } from './components/ui/label';\nimport { defaultEndpoints, type AuthEndpoints } from './types';\n\nexport interface ResetPasswordFormProps {\n endpoints?: Partial<AuthEndpoints>;\n}\n\nexport function ResetPasswordForm({ endpoints }: ResetPasswordFormProps = {}) {\n const ep: AuthEndpoints = { ...defaultEndpoints, ...endpoints };\n const router = useRouter();\n const params = useSearchParams();\n const token = params?.get('token') ?? '';\n const [password, setPassword] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [done, setDone] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n const res = await fetch(ep.resetPassword, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, password }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n throw new Error(payload?.error?.message ?? `Request failed (${res.status})`);\n }\n setDone(true);\n setTimeout(() => router.push('/login'), 1500);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n }\n\n if (!token) {\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>\n Missing or invalid reset link. <Link href=\"/forgot-password\" className=\"font-medium underline\">Request a new one</Link>.\n </span>\n </div>\n </div>\n );\n }\n\n if (done) {\n return (\n <div className=\"flex items-start gap-2 rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-sm text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 shrink-0 mt-0.5 text-primary\" />\n <span>Password updated. Taking you to sign in…</span>\n </div>\n );\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{error}</span>\n </div>\n )}\n <div>\n <Label className=\"mb-1 block text-xs leading-4 text-muted-foreground\">New password</Label>\n <Input\n type=\"password\"\n required\n minLength={10}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n autoComplete=\"new-password\"\n autoFocus\n className=\"h-auto border-border bg-background py-2 text-sm shadow-none focus:outline-none focus:ring-1 focus:ring-primary\"\n />\n <p className=\"mt-1 text-[11px] text-muted-foreground\">At least 10 characters, with a letter and a number.</p>\n </div>\n <Button\n type=\"submit\"\n disabled={submitting}\n className=\"flex h-auto w-full py-2.5 shadow-none hover:opacity-90\"\n >\n {submitting && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {submitting ? 'Updating…' : 'Update password'}\n </Button>\n </form>\n );\n}\n"],"mappings":"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","names":["Link"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import { AuthEndpoints } from './types.cjs';
|
|
3
3
|
|
|
4
4
|
interface ResetPasswordFormProps {
|
|
5
5
|
endpoints?: Partial<AuthEndpoints>;
|
|
6
6
|
}
|
|
7
|
-
declare function ResetPasswordForm({ endpoints }?: ResetPasswordFormProps):
|
|
7
|
+
declare function ResetPasswordForm({ endpoints }?: ResetPasswordFormProps): React.JSX.Element;
|
|
8
8
|
|
|
9
9
|
export { ResetPasswordForm, type ResetPasswordFormProps };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import { AuthEndpoints } from './types.js';
|
|
3
3
|
|
|
4
4
|
interface ResetPasswordFormProps {
|
|
5
5
|
endpoints?: Partial<AuthEndpoints>;
|
|
6
6
|
}
|
|
7
|
-
declare function ResetPasswordForm({ endpoints }?: ResetPasswordFormProps):
|
|
7
|
+
declare function ResetPasswordForm({ endpoints }?: ResetPasswordFormProps): React.JSX.Element;
|
|
8
8
|
|
|
9
9
|
export { ResetPasswordForm, type ResetPasswordFormProps };
|
|
@@ -4,6 +4,9 @@ import { useState } from "react";
|
|
|
4
4
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
5
5
|
import Link from "next/link";
|
|
6
6
|
import { Loader2, AlertCircle, CheckCircle2 } from "lucide-react";
|
|
7
|
+
import { Button } from "./components/ui/button";
|
|
8
|
+
import { Input } from "./components/ui/input";
|
|
9
|
+
import { Label } from "./components/ui/label";
|
|
7
10
|
import { defaultEndpoints } from "./types";
|
|
8
11
|
function ResetPasswordForm({ endpoints } = {}) {
|
|
9
12
|
const ep = { ...defaultEndpoints, ...endpoints };
|
|
@@ -58,9 +61,9 @@ function ResetPasswordForm({ endpoints } = {}) {
|
|
|
58
61
|
/* @__PURE__ */ jsx("span", { children: error })
|
|
59
62
|
] }),
|
|
60
63
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
61
|
-
/* @__PURE__ */ jsx(
|
|
64
|
+
/* @__PURE__ */ jsx(Label, { className: "mb-1 block text-xs leading-4 text-muted-foreground", children: "New password" }),
|
|
62
65
|
/* @__PURE__ */ jsx(
|
|
63
|
-
|
|
66
|
+
Input,
|
|
64
67
|
{
|
|
65
68
|
type: "password",
|
|
66
69
|
required: true,
|
|
@@ -69,17 +72,17 @@ function ResetPasswordForm({ endpoints } = {}) {
|
|
|
69
72
|
onChange: (e) => setPassword(e.target.value),
|
|
70
73
|
autoComplete: "new-password",
|
|
71
74
|
autoFocus: true,
|
|
72
|
-
className: "
|
|
75
|
+
className: "h-auto border-border bg-background py-2 text-sm shadow-none focus:outline-none focus:ring-1 focus:ring-primary"
|
|
73
76
|
}
|
|
74
77
|
),
|
|
75
78
|
/* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-muted-foreground", children: "At least 10 characters, with a letter and a number." })
|
|
76
79
|
] }),
|
|
77
80
|
/* @__PURE__ */ jsxs(
|
|
78
|
-
|
|
81
|
+
Button,
|
|
79
82
|
{
|
|
80
83
|
type: "submit",
|
|
81
84
|
disabled: submitting,
|
|
82
|
-
className: "flex w-full
|
|
85
|
+
className: "flex h-auto w-full py-2.5 shadow-none hover:opacity-90",
|
|
83
86
|
children: [
|
|
84
87
|
submitting && /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
85
88
|
submitting ? "Updating\u2026" : "Update password"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ResetPasswordForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { useRouter, useSearchParams } from 'next/navigation';\nimport Link from 'next/link';\nimport { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { defaultEndpoints, type AuthEndpoints } from './types';\n\nexport interface ResetPasswordFormProps {\n endpoints?: Partial<AuthEndpoints>;\n}\n\nexport function ResetPasswordForm({ endpoints }: ResetPasswordFormProps = {}) {\n const ep: AuthEndpoints = { ...defaultEndpoints, ...endpoints };\n const router = useRouter();\n const params = useSearchParams();\n const token = params?.get('token') ?? '';\n const [password, setPassword] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [done, setDone] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n const res = await fetch(ep.resetPassword, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, password }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n throw new Error(payload?.error?.message ?? `Request failed (${res.status})`);\n }\n setDone(true);\n setTimeout(() => router.push('/login'), 1500);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n }\n\n if (!token) {\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>\n Missing or invalid reset link. <Link href=\"/forgot-password\" className=\"font-medium underline\">Request a new one</Link>.\n </span>\n </div>\n </div>\n );\n }\n\n if (done) {\n return (\n <div className=\"flex items-start gap-2 rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-sm text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 shrink-0 mt-0.5 text-primary\" />\n <span>Password updated. Taking you to sign in…</span>\n </div>\n );\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{error}</span>\n </div>\n )}\n <div>\n <
|
|
1
|
+
{"version":3,"sources":["../src/ResetPasswordForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { useRouter, useSearchParams } from 'next/navigation';\nimport Link from 'next/link';\nimport { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { Button } from './components/ui/button';\nimport { Input } from './components/ui/input';\nimport { Label } from './components/ui/label';\nimport { defaultEndpoints, type AuthEndpoints } from './types';\n\nexport interface ResetPasswordFormProps {\n endpoints?: Partial<AuthEndpoints>;\n}\n\nexport function ResetPasswordForm({ endpoints }: ResetPasswordFormProps = {}) {\n const ep: AuthEndpoints = { ...defaultEndpoints, ...endpoints };\n const router = useRouter();\n const params = useSearchParams();\n const token = params?.get('token') ?? '';\n const [password, setPassword] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [done, setDone] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n const res = await fetch(ep.resetPassword, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, password }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n throw new Error(payload?.error?.message ?? `Request failed (${res.status})`);\n }\n setDone(true);\n setTimeout(() => router.push('/login'), 1500);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n }\n\n if (!token) {\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>\n Missing or invalid reset link. <Link href=\"/forgot-password\" className=\"font-medium underline\">Request a new one</Link>.\n </span>\n </div>\n </div>\n );\n }\n\n if (done) {\n return (\n <div className=\"flex items-start gap-2 rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-sm text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 shrink-0 mt-0.5 text-primary\" />\n <span>Password updated. Taking you to sign in…</span>\n </div>\n );\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n {error && (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{error}</span>\n </div>\n )}\n <div>\n <Label className=\"mb-1 block text-xs leading-4 text-muted-foreground\">New password</Label>\n <Input\n type=\"password\"\n required\n minLength={10}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n autoComplete=\"new-password\"\n autoFocus\n className=\"h-auto border-border bg-background py-2 text-sm shadow-none focus:outline-none focus:ring-1 focus:ring-primary\"\n />\n <p className=\"mt-1 text-[11px] text-muted-foreground\">At least 10 characters, with a letter and a number.</p>\n </div>\n <Button\n type=\"submit\"\n disabled={submitting}\n className=\"flex h-auto w-full py-2.5 shadow-none hover:opacity-90\"\n >\n {submitting && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {submitting ? 'Updating…' : 'Update password'}\n </Button>\n </form>\n );\n}\n"],"mappings":";AAoDU,cACA,YADA;AAlDV,SAAS,gBAAgB;AACzB,SAAS,WAAW,uBAAuB;AAC3C,OAAO,UAAU;AACjB,SAAS,SAAS,aAAa,oBAAoB;AACnD,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,wBAA4C;AAM9C,SAAS,kBAAkB,EAAE,UAAU,IAA4B,CAAC,GAAG;AAC5E,QAAM,KAAoB,EAAE,GAAG,kBAAkB,GAAG,UAAU;AAC9D,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,gBAAgB;AAC/B,QAAM,QAAQ,QAAQ,IAAI,OAAO,KAAK;AACtC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,EAAE;AAC3C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,iBAAe,OAAO,GAAoB;AACxC,MAAE,eAAe;AACjB,aAAS,IAAI;AACb,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,eAAe;AAAA,QACxC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC;AAAA,MAC1C,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,UAAW,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAClD,cAAM,IAAI,MAAM,SAAS,OAAO,WAAW,mBAAmB,IAAI,MAAM,GAAG;AAAA,MAC7E;AACA,cAAQ,IAAI;AACZ,iBAAW,MAAM,OAAO,KAAK,QAAQ,GAAG,IAAI;AAAA,IAC9C,SAAS,KAAK;AACZ,eAAU,IAAc,OAAO;AAAA,IACjC,UAAE;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF;AAEA,MAAI,CAAC,OAAO;AACV,WACE,oBAAC,SAAI,WAAU,aACb,+BAAC,SAAI,WAAU,uHACb;AAAA,0BAAC,eAAY,WAAU,2BAA0B;AAAA,MACjD,qBAAC,UAAK;AAAA;AAAA,QAC2B,oBAAC,QAAK,MAAK,oBAAmB,WAAU,yBAAwB,+BAAiB;AAAA,QAAO;AAAA,SACzH;AAAA,OACF,GACF;AAAA,EAEJ;AAEA,MAAI,MAAM;AACR,WACE,qBAAC,SAAI,WAAU,8GACb;AAAA,0BAAC,gBAAa,WAAU,wCAAuC;AAAA,MAC/D,oBAAC,UAAK,2DAAwC;AAAA,OAChD;AAAA,EAEJ;AAEA,SACE,qBAAC,UAAK,UAAU,QAAQ,WAAU,aAC/B;AAAA,aACC,qBAAC,SAAI,WAAU,uHACb;AAAA,0BAAC,eAAY,WAAU,2BAA0B;AAAA,MACjD,oBAAC,UAAM,iBAAM;AAAA,OACf;AAAA,IAEF,qBAAC,SACC;AAAA,0BAAC,SAAM,WAAU,sDAAqD,0BAAY;AAAA,MAClF;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,UAAQ;AAAA,UACR,WAAW;AAAA,UACX,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,UAC3C,cAAa;AAAA,UACb,WAAS;AAAA,UACT,WAAU;AAAA;AAAA,MACZ;AAAA,MACA,oBAAC,OAAE,WAAU,0CAAyC,iEAAmD;AAAA,OAC3G;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,UAAU;AAAA,QACV,WAAU;AAAA,QAET;AAAA,wBAAc,oBAAC,WAAQ,WAAU,wBAAuB;AAAA,UACxD,aAAa,mBAAc;AAAA;AAAA;AAAA,IAC9B;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var button_exports = {};
|
|
30
|
+
__export(button_exports, {
|
|
31
|
+
Button: () => Button,
|
|
32
|
+
buttonVariants: () => buttonVariants
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(button_exports);
|
|
35
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
|
+
var React = __toESM(require("react"), 1);
|
|
37
|
+
var import_react_slot = require("@radix-ui/react-slot");
|
|
38
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
39
|
+
var import_utils = require("../../lib/utils");
|
|
40
|
+
const buttonVariants = (0, import_class_variance_authority.cva)(
|
|
41
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
42
|
+
{
|
|
43
|
+
variants: {
|
|
44
|
+
variant: {
|
|
45
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
46
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
47
|
+
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
48
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
49
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
50
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
51
|
+
},
|
|
52
|
+
size: {
|
|
53
|
+
default: "h-9 px-4 py-2",
|
|
54
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
55
|
+
lg: "h-10 rounded-md px-8",
|
|
56
|
+
icon: "h-9 w-9"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
defaultVariants: {
|
|
60
|
+
variant: "default",
|
|
61
|
+
size: "default"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
const Button = React.forwardRef(
|
|
66
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
67
|
+
const Comp = asChild ? import_react_slot.Slot : "button";
|
|
68
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
69
|
+
Comp,
|
|
70
|
+
{
|
|
71
|
+
className: (0, import_utils.cn)(buttonVariants({ variant, size, className })),
|
|
72
|
+
ref,
|
|
73
|
+
...props
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
Button.displayName = "Button";
|
|
79
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
80
|
+
0 && (module.exports = {
|
|
81
|
+
Button,
|
|
82
|
+
buttonVariants
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=button.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/button.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '../../lib/utils';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default:\n 'bg-primary text-primary-foreground shadow hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',\n outline:\n 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 rounded-md px-3 text-xs',\n lg: 'h-10 rounded-md px-8',\n icon: 'h-9 w-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n );\n }\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8CM;AA9CN,YAAuB;AACvB,wBAAqB;AACrB,sCAAuC;AAEvC,mBAAmB;AAEnB,MAAM,qBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,aACE;AAAA,QACF,SACE;AAAA,QACF,WACE;AAAA,QACF,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAQA,MAAM,SAAS,MAAM;AAAA,EACnB,CAAC,EAAE,WAAW,SAAS,MAAM,UAAU,OAAO,GAAG,MAAM,GAAG,QAAQ;AAChE,UAAM,OAAO,UAAU,yBAAO;AAC9B,WACE;AAAA,MAAC;AAAA;AAAA,QACC,eAAW,iBAAG,eAAe,EAAE,SAAS,MAAM,UAAU,CAAC,CAAC;AAAA,QAC1D;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AACA,OAAO,cAAc;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
declare const buttonVariants: (props?: ({
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
7
|
+
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
8
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
10
|
+
asChild?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
13
|
+
|
|
14
|
+
export { Button, type ButtonProps, buttonVariants };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
declare const buttonVariants: (props?: ({
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
7
|
+
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
8
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
10
|
+
asChild?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
13
|
+
|
|
14
|
+
export { Button, type ButtonProps, buttonVariants };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import { cn } from "../../lib/utils";
|
|
6
|
+
const buttonVariants = cva(
|
|
7
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
12
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
13
|
+
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
14
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
15
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
16
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
default: "h-9 px-4 py-2",
|
|
20
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
21
|
+
lg: "h-10 rounded-md px-8",
|
|
22
|
+
icon: "h-9 w-9"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
variant: "default",
|
|
27
|
+
size: "default"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
const Button = React.forwardRef(
|
|
32
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
33
|
+
const Comp = asChild ? Slot : "button";
|
|
34
|
+
return /* @__PURE__ */ jsx(
|
|
35
|
+
Comp,
|
|
36
|
+
{
|
|
37
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
38
|
+
ref,
|
|
39
|
+
...props
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
Button.displayName = "Button";
|
|
45
|
+
export {
|
|
46
|
+
Button,
|
|
47
|
+
buttonVariants
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/button.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '../../lib/utils';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default:\n 'bg-primary text-primary-foreground shadow hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',\n outline:\n 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 rounded-md px-3 text-xs',\n lg: 'h-10 rounded-md px-8',\n icon: 'h-9 w-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n );\n }\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n"],"mappings":"AA8CM;AA9CN,YAAY,WAAW;AACvB,SAAS,YAAY;AACrB,SAAS,WAA8B;AAEvC,SAAS,UAAU;AAEnB,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,aACE;AAAA,QACF,SACE;AAAA,QACF,WACE;AAAA,QACF,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAQA,MAAM,SAAS,MAAM;AAAA,EACnB,CAAC,EAAE,WAAW,SAAS,MAAM,UAAU,OAAO,GAAG,MAAM,GAAG,QAAQ;AAChE,UAAM,OAAO,UAAU,OAAO;AAC9B,WACE;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,GAAG,eAAe,EAAE,SAAS,MAAM,UAAU,CAAC,CAAC;AAAA,QAC1D;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AACA,OAAO,cAAc;","names":[]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var input_exports = {};
|
|
30
|
+
__export(input_exports, {
|
|
31
|
+
Input: () => Input
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(input_exports);
|
|
34
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
+
var React = __toESM(require("react"), 1);
|
|
36
|
+
var import_utils = require("../../lib/utils");
|
|
37
|
+
const Input = React.forwardRef(
|
|
38
|
+
({ className, type, ...props }, ref) => {
|
|
39
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
40
|
+
"input",
|
|
41
|
+
{
|
|
42
|
+
type,
|
|
43
|
+
className: (0, import_utils.cn)(
|
|
44
|
+
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
45
|
+
className
|
|
46
|
+
),
|
|
47
|
+
ref,
|
|
48
|
+
...props
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
Input.displayName = "Input";
|
|
54
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
55
|
+
0 && (module.exports = {
|
|
56
|
+
Input
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=input.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../../lib/utils';\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n 'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\nInput.displayName = 'Input';\n\nexport { Input };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOM;AAPN,YAAuB;AAEvB,mBAAmB;AAEnB,MAAM,QAAQ,MAAM;AAAA,EAClB,CAAC,EAAE,WAAW,MAAM,GAAG,MAAM,GAAG,QAAQ;AACtC,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,eAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AACA,MAAM,cAAc;","names":[]}
|