@ccatto/auth-ui 0.1.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/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # @ccatto/auth-ui
2
+
3
+ Presentational React forms for authentication flows: sign-in, register, and a `LoginCatto` card wrapper. Designed to slot into the Catto app template (`@ccatto/ui` + `next-intl` + your auth client of choice).
4
+
5
+ The components are **bring-your-own-auth** — they don't import Better Auth, JWT, or any other backend. You pass an `onSubmit` callback that does the auth call (and any navigation that should follow); the form handles the loading state and error display.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ yarn add @ccatto/auth-ui
11
+ ```
12
+
13
+ Peer deps: `react`, `next-intl`, `@ccatto/ui`.
14
+
15
+ ## Usage
16
+
17
+ ```tsx
18
+ // app/[locale]/(public)/signin/page.tsx
19
+ 'use client';
20
+
21
+ import { LoginCatto } from '@ccatto/auth-ui';
22
+ import { signIn } from '@/lib/auth-client-better';
23
+ import { useRouter } from '@/navigation';
24
+
25
+ export default function Page() {
26
+ const router = useRouter();
27
+
28
+ return (
29
+ <LoginCatto
30
+ onSubmit={async ({ email, password }) => {
31
+ const result = await signIn.email({ email, password });
32
+ if (result?.error) throw new Error(result.error.message);
33
+ router.push('/dashboard'); // or '/paddles', or wherever
34
+ }}
35
+ />
36
+ );
37
+ }
38
+ ```
39
+
40
+ ```tsx
41
+ // app/[locale]/(public)/signin/register/page.tsx
42
+ 'use client';
43
+
44
+ import { RegisterUserFormCatto } from '@ccatto/auth-ui';
45
+ import { signUp } from '@/lib/auth-client-better';
46
+ import { useRouter } from '@/navigation';
47
+
48
+ export default function Page() {
49
+ const router = useRouter();
50
+
51
+ return (
52
+ <RegisterUserFormCatto
53
+ onSubmit={async ({ name, email, password }) => {
54
+ const result = await signUp.email({ name, email, password });
55
+ if (result?.error) throw new Error(result.error.message);
56
+ router.push('/dashboard');
57
+ }}
58
+ />
59
+ );
60
+ }
61
+ ```
62
+
63
+ ## Translation keys
64
+
65
+ Default namespace is `auth`; override with the `i18nNamespace` prop. Within the namespace the components expect:
66
+
67
+ ```json
68
+ {
69
+ "signIn": {
70
+ "cardTitle": "Sign in to your account",
71
+ "emailLabel": "Email",
72
+ "passwordLabel": "Password",
73
+ "submit": "Sign in",
74
+ "submitting": "Signing in…",
75
+ "errorGeneric": "Sign in failed. Check your credentials and try again."
76
+ },
77
+ "register": {
78
+ "nameLabel": "Name",
79
+ "emailLabel": "Email",
80
+ "passwordLabel": "Password",
81
+ "submit": "Create account",
82
+ "submitting": "Creating account…",
83
+ "errorGeneric": "Could not create your account. Try again or contact support."
84
+ }
85
+ }
86
+ ```
87
+
88
+ ## Exports
89
+
90
+ - `LoginCatto` — `CardCatto` wrapper around `SignInEmailPassFormCatto`. Same props plus `cardVariant` / `cardWidth`.
91
+ - `SignInEmailPassFormCatto` — email + password form.
92
+ - `RegisterUserFormCatto` — name + email + password form.
93
+
94
+ All forms accept `i18nNamespace?: string` (default `'auth'`) and a required `onSubmit` callback.
package/dist/index.cjs ADDED
@@ -0,0 +1,150 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var ui = require('@ccatto/ui');
5
+ var nextIntl = require('next-intl');
6
+ var react = require('react');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ // src/LoginCatto.tsx
10
+ var SignInEmailPassFormCatto = ({
11
+ onSubmit,
12
+ i18nNamespace = "auth"
13
+ }) => {
14
+ const t = nextIntl.useTranslations(i18nNamespace);
15
+ const [email, setEmail] = react.useState("");
16
+ const [password, setPassword] = react.useState("");
17
+ const [error, setError] = react.useState(null);
18
+ const [submitting, setSubmitting] = react.useState(false);
19
+ const handleSubmit = async (e) => {
20
+ e.preventDefault();
21
+ setError(null);
22
+ setSubmitting(true);
23
+ try {
24
+ await onSubmit({ email, password });
25
+ } catch (err) {
26
+ setError(err instanceof Error ? err.message : t("signIn.errorGeneric"));
27
+ } finally {
28
+ setSubmitting(false);
29
+ }
30
+ };
31
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-4 p-4", children: [
32
+ /* @__PURE__ */ jsxRuntime.jsx(
33
+ ui.InputCatto,
34
+ {
35
+ type: "email",
36
+ label: t("signIn.emailLabel"),
37
+ value: email,
38
+ onChange: (value) => setEmail(value),
39
+ required: true,
40
+ autoComplete: "email"
41
+ }
42
+ ),
43
+ /* @__PURE__ */ jsxRuntime.jsx(
44
+ ui.InputCatto,
45
+ {
46
+ type: "password",
47
+ label: t("signIn.passwordLabel"),
48
+ value: password,
49
+ onChange: (value) => setPassword(value),
50
+ required: true,
51
+ autoComplete: "current-password"
52
+ }
53
+ ),
54
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-red-600 dark:text-red-400", children: error }),
55
+ /* @__PURE__ */ jsxRuntime.jsx(ui.ButtonCatto, { type: "submit", variant: "primary", disabled: submitting, children: submitting ? t("signIn.submitting") : t("signIn.submit") })
56
+ ] });
57
+ };
58
+ var SignInEmailPassFormCatto_default = SignInEmailPassFormCatto;
59
+ var LoginCatto = ({
60
+ cardVariant = "midnightEmber",
61
+ cardWidth = "5xl",
62
+ i18nNamespace = "auth",
63
+ ...formProps
64
+ }) => {
65
+ const t = nextIntl.useTranslations(i18nNamespace);
66
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-6 h-full", children: /* @__PURE__ */ jsxRuntime.jsx(
67
+ ui.CardCatto,
68
+ {
69
+ title: t("signIn.cardTitle"),
70
+ variant: cardVariant,
71
+ width: cardWidth,
72
+ headerComponent: /* @__PURE__ */ jsxRuntime.jsx(
73
+ SignInEmailPassFormCatto_default,
74
+ {
75
+ ...formProps,
76
+ i18nNamespace
77
+ }
78
+ )
79
+ }
80
+ ) });
81
+ };
82
+ var LoginCatto_default = LoginCatto;
83
+ var RegisterUserFormCatto = ({
84
+ onSubmit,
85
+ i18nNamespace = "auth"
86
+ }) => {
87
+ const t = nextIntl.useTranslations(i18nNamespace);
88
+ const [name, setName] = react.useState("");
89
+ const [email, setEmail] = react.useState("");
90
+ const [password, setPassword] = react.useState("");
91
+ const [error, setError] = react.useState(null);
92
+ const [submitting, setSubmitting] = react.useState(false);
93
+ const handleSubmit = async (e) => {
94
+ e.preventDefault();
95
+ setError(null);
96
+ setSubmitting(true);
97
+ try {
98
+ await onSubmit({ name, email, password });
99
+ } catch (err) {
100
+ setError(err instanceof Error ? err.message : t("register.errorGeneric"));
101
+ } finally {
102
+ setSubmitting(false);
103
+ }
104
+ };
105
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-4 p-4", children: [
106
+ /* @__PURE__ */ jsxRuntime.jsx(
107
+ ui.InputCatto,
108
+ {
109
+ type: "text",
110
+ label: t("register.nameLabel"),
111
+ value: name,
112
+ onChange: (value) => setName(value),
113
+ required: true,
114
+ autoComplete: "name"
115
+ }
116
+ ),
117
+ /* @__PURE__ */ jsxRuntime.jsx(
118
+ ui.InputCatto,
119
+ {
120
+ type: "email",
121
+ label: t("register.emailLabel"),
122
+ value: email,
123
+ onChange: (value) => setEmail(value),
124
+ required: true,
125
+ autoComplete: "email"
126
+ }
127
+ ),
128
+ /* @__PURE__ */ jsxRuntime.jsx(
129
+ ui.InputCatto,
130
+ {
131
+ type: "password",
132
+ label: t("register.passwordLabel"),
133
+ value: password,
134
+ onChange: (value) => setPassword(value),
135
+ required: true,
136
+ autoComplete: "new-password",
137
+ minLength: 8
138
+ }
139
+ ),
140
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-red-600 dark:text-red-400", children: error }),
141
+ /* @__PURE__ */ jsxRuntime.jsx(ui.ButtonCatto, { type: "submit", variant: "primary", disabled: submitting, children: submitting ? t("register.submitting") : t("register.submit") })
142
+ ] });
143
+ };
144
+ var RegisterUserFormCatto_default = RegisterUserFormCatto;
145
+
146
+ exports.LoginCatto = LoginCatto_default;
147
+ exports.RegisterUserFormCatto = RegisterUserFormCatto_default;
148
+ exports.SignInEmailPassFormCatto = SignInEmailPassFormCatto_default;
149
+ //# sourceMappingURL=index.cjs.map
150
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/SignInEmailPassFormCatto.tsx","../src/LoginCatto.tsx","../src/RegisterUserFormCatto.tsx"],"names":["useTranslations","useState","jsxs","jsx","InputCatto","ButtonCatto","CardCatto"],"mappings":"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","file":"index.cjs","sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { ButtonCatto, InputCatto } from '@ccatto/ui';\nimport { useTranslations } from 'next-intl';\n\nexport interface SignInValues {\n email: string;\n password: string;\n}\n\nexport interface SignInEmailPassFormCattoProps {\n /**\n * Called with `{ email, password }` when the user submits the form. Throw\n * (or reject) to surface an error message in the form. The component owns\n * its own loading + error UI; the caller owns the auth client and any\n * navigation that should happen on success.\n */\n onSubmit: (values: SignInValues) => Promise<void> | void;\n /**\n * next-intl namespace this form's labels are read from. The keys it expects\n * inside the namespace are `signIn.cardTitle`, `signIn.emailLabel`,\n * `signIn.passwordLabel`, `signIn.submit`, `signIn.submitting`,\n * `signIn.errorGeneric`. Defaults to `auth`.\n */\n i18nNamespace?: string;\n}\n\nconst SignInEmailPassFormCatto = ({\n onSubmit,\n i18nNamespace = 'auth',\n}: SignInEmailPassFormCattoProps) => {\n const t = useTranslations(i18nNamespace);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n await onSubmit({ email, password });\n } catch (err) {\n setError(err instanceof Error ? err.message : t('signIn.errorGeneric'));\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-4 p-4\">\n <InputCatto\n type=\"email\"\n label={t('signIn.emailLabel')}\n value={email}\n onChange={(value) => setEmail(value)}\n required\n autoComplete=\"email\"\n />\n <InputCatto\n type=\"password\"\n label={t('signIn.passwordLabel')}\n value={password}\n onChange={(value) => setPassword(value)}\n required\n autoComplete=\"current-password\"\n />\n {error && (\n <p className=\"text-sm text-red-600 dark:text-red-400\">{error}</p>\n )}\n <ButtonCatto type=\"submit\" variant=\"primary\" disabled={submitting}>\n {submitting ? t('signIn.submitting') : t('signIn.submit')}\n </ButtonCatto>\n </form>\n );\n};\n\nexport default SignInEmailPassFormCatto;\n","'use client';\n\nimport { CardCatto } from '@ccatto/ui';\nimport { useTranslations } from 'next-intl';\nimport SignInEmailPassFormCatto, {\n type SignInEmailPassFormCattoProps,\n} from './SignInEmailPassFormCatto';\n\nexport interface LoginCattoProps extends SignInEmailPassFormCattoProps {\n /** CardCatto variant. Defaults to 'midnightEmber'. */\n cardVariant?: string;\n /** CardCatto width. Defaults to '5xl'. */\n cardWidth?: string;\n}\n\nconst LoginCatto = ({\n cardVariant = 'midnightEmber',\n cardWidth = '5xl',\n i18nNamespace = 'auth',\n ...formProps\n}: LoginCattoProps) => {\n const t = useTranslations(i18nNamespace);\n\n return (\n <div className=\"mt-6 h-full\">\n <CardCatto\n title={t('signIn.cardTitle')}\n // CardCatto's variant + width props are loosely typed here so consumers\n // can pass any of the package's themes without us having to track the\n // union in two places.\n variant={cardVariant as never}\n width={cardWidth as never}\n headerComponent={\n <SignInEmailPassFormCatto\n {...formProps}\n i18nNamespace={i18nNamespace}\n />\n }\n />\n </div>\n );\n};\n\nexport default LoginCatto;\n","'use client';\n\nimport { useState } from 'react';\nimport { ButtonCatto, InputCatto } from '@ccatto/ui';\nimport { useTranslations } from 'next-intl';\n\nexport interface RegisterValues {\n name: string;\n email: string;\n password: string;\n}\n\nexport interface RegisterUserFormCattoProps {\n /**\n * Called with `{ name, email, password }` when the user submits the form.\n * Throw (or reject) to surface an error message. The component owns its\n * own loading + error UI; the caller owns the auth client and any\n * post-register navigation.\n */\n onSubmit: (values: RegisterValues) => Promise<void> | void;\n /**\n * next-intl namespace this form's labels are read from. The keys it expects\n * inside the namespace are `register.nameLabel`, `register.emailLabel`,\n * `register.passwordLabel`, `register.submit`, `register.submitting`,\n * `register.errorGeneric`. Defaults to `auth`.\n */\n i18nNamespace?: string;\n}\n\nconst RegisterUserFormCatto = ({\n onSubmit,\n i18nNamespace = 'auth',\n}: RegisterUserFormCattoProps) => {\n const t = useTranslations(i18nNamespace);\n const [name, setName] = useState('');\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n await onSubmit({ name, email, password });\n } catch (err) {\n setError(err instanceof Error ? err.message : t('register.errorGeneric'));\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-4 p-4\">\n <InputCatto\n type=\"text\"\n label={t('register.nameLabel')}\n value={name}\n onChange={(value) => setName(value)}\n required\n autoComplete=\"name\"\n />\n <InputCatto\n type=\"email\"\n label={t('register.emailLabel')}\n value={email}\n onChange={(value) => setEmail(value)}\n required\n autoComplete=\"email\"\n />\n <InputCatto\n type=\"password\"\n label={t('register.passwordLabel')}\n value={password}\n onChange={(value) => setPassword(value)}\n required\n autoComplete=\"new-password\"\n minLength={8}\n />\n {error && (\n <p className=\"text-sm text-red-600 dark:text-red-400\">{error}</p>\n )}\n <ButtonCatto type=\"submit\" variant=\"primary\" disabled={submitting}>\n {submitting ? t('register.submitting') : t('register.submit')}\n </ButtonCatto>\n </form>\n );\n};\n\nexport default RegisterUserFormCatto;\n"]}
@@ -0,0 +1,56 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface SignInValues {
4
+ email: string;
5
+ password: string;
6
+ }
7
+ interface SignInEmailPassFormCattoProps {
8
+ /**
9
+ * Called with `{ email, password }` when the user submits the form. Throw
10
+ * (or reject) to surface an error message in the form. The component owns
11
+ * its own loading + error UI; the caller owns the auth client and any
12
+ * navigation that should happen on success.
13
+ */
14
+ onSubmit: (values: SignInValues) => Promise<void> | void;
15
+ /**
16
+ * next-intl namespace this form's labels are read from. The keys it expects
17
+ * inside the namespace are `signIn.cardTitle`, `signIn.emailLabel`,
18
+ * `signIn.passwordLabel`, `signIn.submit`, `signIn.submitting`,
19
+ * `signIn.errorGeneric`. Defaults to `auth`.
20
+ */
21
+ i18nNamespace?: string;
22
+ }
23
+ declare const SignInEmailPassFormCatto: ({ onSubmit, i18nNamespace, }: SignInEmailPassFormCattoProps) => react_jsx_runtime.JSX.Element;
24
+
25
+ interface LoginCattoProps extends SignInEmailPassFormCattoProps {
26
+ /** CardCatto variant. Defaults to 'midnightEmber'. */
27
+ cardVariant?: string;
28
+ /** CardCatto width. Defaults to '5xl'. */
29
+ cardWidth?: string;
30
+ }
31
+ declare const LoginCatto: ({ cardVariant, cardWidth, i18nNamespace, ...formProps }: LoginCattoProps) => react_jsx_runtime.JSX.Element;
32
+
33
+ interface RegisterValues {
34
+ name: string;
35
+ email: string;
36
+ password: string;
37
+ }
38
+ interface RegisterUserFormCattoProps {
39
+ /**
40
+ * Called with `{ name, email, password }` when the user submits the form.
41
+ * Throw (or reject) to surface an error message. The component owns its
42
+ * own loading + error UI; the caller owns the auth client and any
43
+ * post-register navigation.
44
+ */
45
+ onSubmit: (values: RegisterValues) => Promise<void> | void;
46
+ /**
47
+ * next-intl namespace this form's labels are read from. The keys it expects
48
+ * inside the namespace are `register.nameLabel`, `register.emailLabel`,
49
+ * `register.passwordLabel`, `register.submit`, `register.submitting`,
50
+ * `register.errorGeneric`. Defaults to `auth`.
51
+ */
52
+ i18nNamespace?: string;
53
+ }
54
+ declare const RegisterUserFormCatto: ({ onSubmit, i18nNamespace, }: RegisterUserFormCattoProps) => react_jsx_runtime.JSX.Element;
55
+
56
+ export { LoginCatto, type LoginCattoProps, RegisterUserFormCatto, type RegisterUserFormCattoProps, type RegisterValues, SignInEmailPassFormCatto, type SignInEmailPassFormCattoProps, type SignInValues };
@@ -0,0 +1,56 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface SignInValues {
4
+ email: string;
5
+ password: string;
6
+ }
7
+ interface SignInEmailPassFormCattoProps {
8
+ /**
9
+ * Called with `{ email, password }` when the user submits the form. Throw
10
+ * (or reject) to surface an error message in the form. The component owns
11
+ * its own loading + error UI; the caller owns the auth client and any
12
+ * navigation that should happen on success.
13
+ */
14
+ onSubmit: (values: SignInValues) => Promise<void> | void;
15
+ /**
16
+ * next-intl namespace this form's labels are read from. The keys it expects
17
+ * inside the namespace are `signIn.cardTitle`, `signIn.emailLabel`,
18
+ * `signIn.passwordLabel`, `signIn.submit`, `signIn.submitting`,
19
+ * `signIn.errorGeneric`. Defaults to `auth`.
20
+ */
21
+ i18nNamespace?: string;
22
+ }
23
+ declare const SignInEmailPassFormCatto: ({ onSubmit, i18nNamespace, }: SignInEmailPassFormCattoProps) => react_jsx_runtime.JSX.Element;
24
+
25
+ interface LoginCattoProps extends SignInEmailPassFormCattoProps {
26
+ /** CardCatto variant. Defaults to 'midnightEmber'. */
27
+ cardVariant?: string;
28
+ /** CardCatto width. Defaults to '5xl'. */
29
+ cardWidth?: string;
30
+ }
31
+ declare const LoginCatto: ({ cardVariant, cardWidth, i18nNamespace, ...formProps }: LoginCattoProps) => react_jsx_runtime.JSX.Element;
32
+
33
+ interface RegisterValues {
34
+ name: string;
35
+ email: string;
36
+ password: string;
37
+ }
38
+ interface RegisterUserFormCattoProps {
39
+ /**
40
+ * Called with `{ name, email, password }` when the user submits the form.
41
+ * Throw (or reject) to surface an error message. The component owns its
42
+ * own loading + error UI; the caller owns the auth client and any
43
+ * post-register navigation.
44
+ */
45
+ onSubmit: (values: RegisterValues) => Promise<void> | void;
46
+ /**
47
+ * next-intl namespace this form's labels are read from. The keys it expects
48
+ * inside the namespace are `register.nameLabel`, `register.emailLabel`,
49
+ * `register.passwordLabel`, `register.submit`, `register.submitting`,
50
+ * `register.errorGeneric`. Defaults to `auth`.
51
+ */
52
+ i18nNamespace?: string;
53
+ }
54
+ declare const RegisterUserFormCatto: ({ onSubmit, i18nNamespace, }: RegisterUserFormCattoProps) => react_jsx_runtime.JSX.Element;
55
+
56
+ export { LoginCatto, type LoginCattoProps, RegisterUserFormCatto, type RegisterUserFormCattoProps, type RegisterValues, SignInEmailPassFormCatto, type SignInEmailPassFormCattoProps, type SignInValues };
package/dist/index.js ADDED
@@ -0,0 +1,146 @@
1
+ "use client";
2
+ import { InputCatto, ButtonCatto, CardCatto } from '@ccatto/ui';
3
+ import { useTranslations } from 'next-intl';
4
+ import { useState } from 'react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ // src/LoginCatto.tsx
8
+ var SignInEmailPassFormCatto = ({
9
+ onSubmit,
10
+ i18nNamespace = "auth"
11
+ }) => {
12
+ const t = useTranslations(i18nNamespace);
13
+ const [email, setEmail] = useState("");
14
+ const [password, setPassword] = useState("");
15
+ const [error, setError] = useState(null);
16
+ const [submitting, setSubmitting] = useState(false);
17
+ const handleSubmit = async (e) => {
18
+ e.preventDefault();
19
+ setError(null);
20
+ setSubmitting(true);
21
+ try {
22
+ await onSubmit({ email, password });
23
+ } catch (err) {
24
+ setError(err instanceof Error ? err.message : t("signIn.errorGeneric"));
25
+ } finally {
26
+ setSubmitting(false);
27
+ }
28
+ };
29
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-4 p-4", children: [
30
+ /* @__PURE__ */ jsx(
31
+ InputCatto,
32
+ {
33
+ type: "email",
34
+ label: t("signIn.emailLabel"),
35
+ value: email,
36
+ onChange: (value) => setEmail(value),
37
+ required: true,
38
+ autoComplete: "email"
39
+ }
40
+ ),
41
+ /* @__PURE__ */ jsx(
42
+ InputCatto,
43
+ {
44
+ type: "password",
45
+ label: t("signIn.passwordLabel"),
46
+ value: password,
47
+ onChange: (value) => setPassword(value),
48
+ required: true,
49
+ autoComplete: "current-password"
50
+ }
51
+ ),
52
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600 dark:text-red-400", children: error }),
53
+ /* @__PURE__ */ jsx(ButtonCatto, { type: "submit", variant: "primary", disabled: submitting, children: submitting ? t("signIn.submitting") : t("signIn.submit") })
54
+ ] });
55
+ };
56
+ var SignInEmailPassFormCatto_default = SignInEmailPassFormCatto;
57
+ var LoginCatto = ({
58
+ cardVariant = "midnightEmber",
59
+ cardWidth = "5xl",
60
+ i18nNamespace = "auth",
61
+ ...formProps
62
+ }) => {
63
+ const t = useTranslations(i18nNamespace);
64
+ return /* @__PURE__ */ jsx("div", { className: "mt-6 h-full", children: /* @__PURE__ */ jsx(
65
+ CardCatto,
66
+ {
67
+ title: t("signIn.cardTitle"),
68
+ variant: cardVariant,
69
+ width: cardWidth,
70
+ headerComponent: /* @__PURE__ */ jsx(
71
+ SignInEmailPassFormCatto_default,
72
+ {
73
+ ...formProps,
74
+ i18nNamespace
75
+ }
76
+ )
77
+ }
78
+ ) });
79
+ };
80
+ var LoginCatto_default = LoginCatto;
81
+ var RegisterUserFormCatto = ({
82
+ onSubmit,
83
+ i18nNamespace = "auth"
84
+ }) => {
85
+ const t = useTranslations(i18nNamespace);
86
+ const [name, setName] = useState("");
87
+ const [email, setEmail] = useState("");
88
+ const [password, setPassword] = useState("");
89
+ const [error, setError] = useState(null);
90
+ const [submitting, setSubmitting] = useState(false);
91
+ const handleSubmit = async (e) => {
92
+ e.preventDefault();
93
+ setError(null);
94
+ setSubmitting(true);
95
+ try {
96
+ await onSubmit({ name, email, password });
97
+ } catch (err) {
98
+ setError(err instanceof Error ? err.message : t("register.errorGeneric"));
99
+ } finally {
100
+ setSubmitting(false);
101
+ }
102
+ };
103
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-4 p-4", children: [
104
+ /* @__PURE__ */ jsx(
105
+ InputCatto,
106
+ {
107
+ type: "text",
108
+ label: t("register.nameLabel"),
109
+ value: name,
110
+ onChange: (value) => setName(value),
111
+ required: true,
112
+ autoComplete: "name"
113
+ }
114
+ ),
115
+ /* @__PURE__ */ jsx(
116
+ InputCatto,
117
+ {
118
+ type: "email",
119
+ label: t("register.emailLabel"),
120
+ value: email,
121
+ onChange: (value) => setEmail(value),
122
+ required: true,
123
+ autoComplete: "email"
124
+ }
125
+ ),
126
+ /* @__PURE__ */ jsx(
127
+ InputCatto,
128
+ {
129
+ type: "password",
130
+ label: t("register.passwordLabel"),
131
+ value: password,
132
+ onChange: (value) => setPassword(value),
133
+ required: true,
134
+ autoComplete: "new-password",
135
+ minLength: 8
136
+ }
137
+ ),
138
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600 dark:text-red-400", children: error }),
139
+ /* @__PURE__ */ jsx(ButtonCatto, { type: "submit", variant: "primary", disabled: submitting, children: submitting ? t("register.submitting") : t("register.submit") })
140
+ ] });
141
+ };
142
+ var RegisterUserFormCatto_default = RegisterUserFormCatto;
143
+
144
+ export { LoginCatto_default as LoginCatto, RegisterUserFormCatto_default as RegisterUserFormCatto, SignInEmailPassFormCatto_default as SignInEmailPassFormCatto };
145
+ //# sourceMappingURL=index.js.map
146
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/SignInEmailPassFormCatto.tsx","../src/LoginCatto.tsx","../src/RegisterUserFormCatto.tsx"],"names":["useTranslations","jsx","useState","jsxs","InputCatto","ButtonCatto"],"mappings":"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","file":"index.js","sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { ButtonCatto, InputCatto } from '@ccatto/ui';\nimport { useTranslations } from 'next-intl';\n\nexport interface SignInValues {\n email: string;\n password: string;\n}\n\nexport interface SignInEmailPassFormCattoProps {\n /**\n * Called with `{ email, password }` when the user submits the form. Throw\n * (or reject) to surface an error message in the form. The component owns\n * its own loading + error UI; the caller owns the auth client and any\n * navigation that should happen on success.\n */\n onSubmit: (values: SignInValues) => Promise<void> | void;\n /**\n * next-intl namespace this form's labels are read from. The keys it expects\n * inside the namespace are `signIn.cardTitle`, `signIn.emailLabel`,\n * `signIn.passwordLabel`, `signIn.submit`, `signIn.submitting`,\n * `signIn.errorGeneric`. Defaults to `auth`.\n */\n i18nNamespace?: string;\n}\n\nconst SignInEmailPassFormCatto = ({\n onSubmit,\n i18nNamespace = 'auth',\n}: SignInEmailPassFormCattoProps) => {\n const t = useTranslations(i18nNamespace);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n await onSubmit({ email, password });\n } catch (err) {\n setError(err instanceof Error ? err.message : t('signIn.errorGeneric'));\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-4 p-4\">\n <InputCatto\n type=\"email\"\n label={t('signIn.emailLabel')}\n value={email}\n onChange={(value) => setEmail(value)}\n required\n autoComplete=\"email\"\n />\n <InputCatto\n type=\"password\"\n label={t('signIn.passwordLabel')}\n value={password}\n onChange={(value) => setPassword(value)}\n required\n autoComplete=\"current-password\"\n />\n {error && (\n <p className=\"text-sm text-red-600 dark:text-red-400\">{error}</p>\n )}\n <ButtonCatto type=\"submit\" variant=\"primary\" disabled={submitting}>\n {submitting ? t('signIn.submitting') : t('signIn.submit')}\n </ButtonCatto>\n </form>\n );\n};\n\nexport default SignInEmailPassFormCatto;\n","'use client';\n\nimport { CardCatto } from '@ccatto/ui';\nimport { useTranslations } from 'next-intl';\nimport SignInEmailPassFormCatto, {\n type SignInEmailPassFormCattoProps,\n} from './SignInEmailPassFormCatto';\n\nexport interface LoginCattoProps extends SignInEmailPassFormCattoProps {\n /** CardCatto variant. Defaults to 'midnightEmber'. */\n cardVariant?: string;\n /** CardCatto width. Defaults to '5xl'. */\n cardWidth?: string;\n}\n\nconst LoginCatto = ({\n cardVariant = 'midnightEmber',\n cardWidth = '5xl',\n i18nNamespace = 'auth',\n ...formProps\n}: LoginCattoProps) => {\n const t = useTranslations(i18nNamespace);\n\n return (\n <div className=\"mt-6 h-full\">\n <CardCatto\n title={t('signIn.cardTitle')}\n // CardCatto's variant + width props are loosely typed here so consumers\n // can pass any of the package's themes without us having to track the\n // union in two places.\n variant={cardVariant as never}\n width={cardWidth as never}\n headerComponent={\n <SignInEmailPassFormCatto\n {...formProps}\n i18nNamespace={i18nNamespace}\n />\n }\n />\n </div>\n );\n};\n\nexport default LoginCatto;\n","'use client';\n\nimport { useState } from 'react';\nimport { ButtonCatto, InputCatto } from '@ccatto/ui';\nimport { useTranslations } from 'next-intl';\n\nexport interface RegisterValues {\n name: string;\n email: string;\n password: string;\n}\n\nexport interface RegisterUserFormCattoProps {\n /**\n * Called with `{ name, email, password }` when the user submits the form.\n * Throw (or reject) to surface an error message. The component owns its\n * own loading + error UI; the caller owns the auth client and any\n * post-register navigation.\n */\n onSubmit: (values: RegisterValues) => Promise<void> | void;\n /**\n * next-intl namespace this form's labels are read from. The keys it expects\n * inside the namespace are `register.nameLabel`, `register.emailLabel`,\n * `register.passwordLabel`, `register.submit`, `register.submitting`,\n * `register.errorGeneric`. Defaults to `auth`.\n */\n i18nNamespace?: string;\n}\n\nconst RegisterUserFormCatto = ({\n onSubmit,\n i18nNamespace = 'auth',\n}: RegisterUserFormCattoProps) => {\n const t = useTranslations(i18nNamespace);\n const [name, setName] = useState('');\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setSubmitting(true);\n try {\n await onSubmit({ name, email, password });\n } catch (err) {\n setError(err instanceof Error ? err.message : t('register.errorGeneric'));\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-4 p-4\">\n <InputCatto\n type=\"text\"\n label={t('register.nameLabel')}\n value={name}\n onChange={(value) => setName(value)}\n required\n autoComplete=\"name\"\n />\n <InputCatto\n type=\"email\"\n label={t('register.emailLabel')}\n value={email}\n onChange={(value) => setEmail(value)}\n required\n autoComplete=\"email\"\n />\n <InputCatto\n type=\"password\"\n label={t('register.passwordLabel')}\n value={password}\n onChange={(value) => setPassword(value)}\n required\n autoComplete=\"new-password\"\n minLength={8}\n />\n {error && (\n <p className=\"text-sm text-red-600 dark:text-red-400\">{error}</p>\n )}\n <ButtonCatto type=\"submit\" variant=\"primary\" disabled={submitting}>\n {submitting ? t('register.submitting') : t('register.submit')}\n </ButtonCatto>\n </form>\n );\n};\n\nexport default RegisterUserFormCatto;\n"]}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@ccatto/auth-ui",
3
+ "version": "0.1.0",
4
+ "description": "Catto Auth UI - presentational React forms (sign-in, register, login) for Catto-based apps. Bring your own auth client.",
5
+ "license": "MIT",
6
+ "author": "Chris Catto",
7
+ "keywords": [
8
+ "react",
9
+ "react-components",
10
+ "authentication",
11
+ "auth-ui",
12
+ "sign-in",
13
+ "register",
14
+ "next-intl",
15
+ "tailwindcss",
16
+ "catto"
17
+ ],
18
+ "homepage": "https://github.com/ccatto/catto-packages/tree/main/packages/auth-ui",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/ccatto/catto-packages.git",
22
+ "directory": "packages/auth-ui"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "type": "module",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js",
32
+ "require": "./dist/index.cjs"
33
+ }
34
+ },
35
+ "main": "./dist/index.cjs",
36
+ "module": "./dist/index.js",
37
+ "types": "./dist/index.d.ts",
38
+ "files": [
39
+ "dist",
40
+ "README.md"
41
+ ],
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "clean": "rimraf dist",
45
+ "dev": "tsup --watch",
46
+ "typecheck": "tsc --noEmit"
47
+ },
48
+ "devDependencies": {
49
+ "@ccatto/ui": "*",
50
+ "@types/react": "^19.0.0",
51
+ "glob": "^13.0.0",
52
+ "next-intl": "^4.0.0",
53
+ "react": "^19.0.0",
54
+ "rimraf": "^6.0.0",
55
+ "tsup": "^8.0.0",
56
+ "typescript": "^5.7.0"
57
+ },
58
+ "peerDependencies": {
59
+ "@ccatto/ui": ">=1.0.0",
60
+ "next-intl": ">=3.0.0",
61
+ "react": ">=18.0.0"
62
+ }
63
+ }