diff --git a/dist/react/index.js b/dist/react/index.js index 4f8e572..68f5f97 100644 --- a/dist/react/index.js +++ b/dist/react/index.js @@ -1,8 +1,85 @@ // react/AuthGuard.tsx import { useEffect, useState } from "react"; -import { Center, Spinner } from "@chakra-ui/react"; -import { Navigate } from "react-router-dom"; -import { Fragment, jsx } from "react/jsx-runtime"; + +// react/chakra-compat.tsx +import { + Alert as ChakraAlert, + Box as ChakraBox, + Button as ChakraButton, + Center as ChakraCenter, + HStack as ChakraHStack, + Icon as ChakraIcon, + Input as ChakraInput, + Spinner as ChakraSpinner, + Stack as ChakraStack, + Text as ChakraText +} from "@chakra-ui/react"; +import { jsx, jsxs } from "react/jsx-runtime"; +function normalizeSpacingProps(props) { + const next = { ...props }; + if (next.spacing !== void 0 && next.gap === void 0) { + next.gap = next.spacing; + } + delete next.spacing; + return next; +} +function normalizeInteractiveProps(props) { + const next = normalizeSpacingProps(props); + if (next.isDisabled !== void 0 && next.disabled === void 0) { + next.disabled = next.isDisabled; + } + if (next.isLoading !== void 0 && next.loading === void 0) { + next.loading = next.isLoading; + } + delete next.isDisabled; + delete next.isLoading; + return next; +} +var Center = ChakraCenter; +var Icon = ChakraIcon; +var Input = ChakraInput; +var Spinner = ChakraSpinner; +function Stack(props) { + return /* @__PURE__ */ jsx(ChakraStack, { ...normalizeSpacingProps(props) }); +} +function HStack(props) { + return /* @__PURE__ */ jsx(ChakraHStack, { ...normalizeSpacingProps(props) }); +} +function Text(props) { + const next = { ...props }; + if (next.noOfLines !== void 0 && next.lineClamp === void 0) { + next.lineClamp = next.noOfLines; + } + delete next.noOfLines; + return /* @__PURE__ */ jsx(ChakraText, { ...next }); +} +function Button(props) { + const { leftIcon, rightIcon, children, ...rest } = normalizeInteractiveProps(props); + return /* @__PURE__ */ jsx(ChakraButton, { ...rest, children: /* @__PURE__ */ jsxs(ChakraHStack, { gap: 2, children: [ + leftIcon ?? null, + /* @__PURE__ */ jsx("span", { children }), + rightIcon ?? null + ] }) }); +} +function Alert({ children, status = "info", ...props }) { + return /* @__PURE__ */ jsx(ChakraAlert.Root, { status, ...props, children }); +} +function AlertIcon() { + return /* @__PURE__ */ jsx(ChakraAlert.Indicator, {}); +} +function AlertDescription({ children, ...props }) { + return /* @__PURE__ */ jsx(ChakraAlert.Description, { ...props, children }); +} +function FormControl({ children, ...props }) { + return /* @__PURE__ */ jsx(ChakraStack, { gap: 2, ...normalizeSpacingProps(props), children }); +} +function FormLabel(props) { + return /* @__PURE__ */ jsx(ChakraBox, { as: "label", fontWeight: "medium", ...props }); +} + +// react/AuthGuard.tsx +import { Navigate } from "react-router"; +import { Fragment, jsx as jsx2 } from "react/jsx-runtime"; function AuthGuard({ children, fetchCurrentUser, @@ -30,12 +107,12 @@ function AuthGuard({ }; }, [fetchCurrentUser]); if (state.loading) { - return /* @__PURE__ */ jsx(Fragment, { children: loadingFallback ?? /* @__PURE__ */ jsx(Center, { h: "var(--app-height)", children: /* @__PURE__ */ jsx(Spinner, { size: "xl" }) }) }); + return /* @__PURE__ */ jsx2(Fragment, { children: loadingFallback ?? /* @__PURE__ */ jsx2(Center, { h: "var(--app-height)", children: /* @__PURE__ */ jsx2(Spinner, { size: "xl" }) }) }); } if (!state.authenticated) { - return /* @__PURE__ */ jsx(Navigate, { to: redirectTo, replace: true }); + return /* @__PURE__ */ jsx2(Navigate, { to: redirectTo, replace: true }); } - return /* @__PURE__ */ jsx(Fragment, { children: authenticatedWrapper ? authenticatedWrapper(children) : children }); + return /* @__PURE__ */ jsx2(Fragment, { children: authenticatedWrapper ? authenticatedWrapper(children) : children }); } // react/client.ts @@ -172,9 +249,8 @@ function createAuthClient(options) { } // react/LoginForm.tsx -import { Alert, AlertDescription, AlertIcon, Button, Center as Center2, FormControl, FormLabel, HStack, Icon, Input, Stack } from "@chakra-ui/react"; import { FcGoogle } from "react-icons/fc"; -import { jsx as jsx2, jsxs } from "react/jsx-runtime"; +import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime"; function LoginForm({ mode, texts, @@ -202,37 +278,37 @@ function LoginForm({ passwordConfirm: String(form.get("passwordConfirm") ?? "") }); } - return /* @__PURE__ */ jsxs(Stack, { spacing: 5, children: [ - errorMessage ? /* @__PURE__ */ jsxs(Alert, { status: "error", borderRadius: "md", children: [ - /* @__PURE__ */ jsx2(AlertIcon, {}), - /* @__PURE__ */ jsx2(AlertDescription, { children: errorMessage }) + return /* @__PURE__ */ jsxs2(Stack, { spacing: 5, children: [ + errorMessage ? /* @__PURE__ */ jsxs2(Alert, { status: "error", borderRadius: "md", children: [ + /* @__PURE__ */ jsx3(AlertIcon, {}), + /* @__PURE__ */ jsx3(AlertDescription, { children: errorMessage }) ] }) : null, - successMessage ? /* @__PURE__ */ jsxs(Alert, { status: "success", borderRadius: "md", children: [ - /* @__PURE__ */ jsx2(AlertIcon, {}), - /* @__PURE__ */ jsx2(AlertDescription, { children: successMessage }) + successMessage ? /* @__PURE__ */ jsxs2(Alert, { status: "success", borderRadius: "md", children: [ + /* @__PURE__ */ jsx3(AlertIcon, {}), + /* @__PURE__ */ jsx3(AlertDescription, { children: successMessage }) ] }) : null, - /* @__PURE__ */ jsx2("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Stack, { spacing: 4, children: [ - registerMode ? /* @__PURE__ */ jsxs(FormControl, { isRequired: true, children: [ - /* @__PURE__ */ jsx2(FormLabel, { children: texts.nameLabel }), - /* @__PURE__ */ jsx2(Input, { name: "name", placeholder: namePlaceholder }) + /* @__PURE__ */ jsx3("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs2(Stack, { spacing: 4, children: [ + registerMode ? /* @__PURE__ */ jsxs2(FormControl, { isRequired: true, children: [ + /* @__PURE__ */ jsx3(FormLabel, { children: texts.nameLabel }), + /* @__PURE__ */ jsx3(Input, { name: "name", placeholder: namePlaceholder }) ] }) : null, - /* @__PURE__ */ jsxs(FormControl, { isRequired: true, children: [ - /* @__PURE__ */ jsx2(FormLabel, { children: texts.emailLabel }), - /* @__PURE__ */ jsx2(Input, { name: "email", type: "email", placeholder: emailPlaceholder }) + /* @__PURE__ */ jsxs2(FormControl, { isRequired: true, children: [ + /* @__PURE__ */ jsx3(FormLabel, { children: texts.emailLabel }), + /* @__PURE__ */ jsx3(Input, { name: "email", type: "email", placeholder: emailPlaceholder }) ] }), - /* @__PURE__ */ jsxs(FormControl, { isRequired: true, children: [ - /* @__PURE__ */ jsx2(FormLabel, { children: texts.passwordLabel }), - /* @__PURE__ */ jsx2(Input, { name: "password", type: "password", minLength: 8 }) + /* @__PURE__ */ jsxs2(FormControl, { isRequired: true, children: [ + /* @__PURE__ */ jsx3(FormLabel, { children: texts.passwordLabel }), + /* @__PURE__ */ jsx3(Input, { name: "password", type: "password", minLength: 8 }) ] }), - !registerMode && forgotPasswordLink ? /* @__PURE__ */ jsx2(Stack, { align: "flex-end", children: forgotPasswordLink }) : null, - registerMode ? /* @__PURE__ */ jsxs(FormControl, { isRequired: true, children: [ - /* @__PURE__ */ jsx2(FormLabel, { children: texts.passwordConfirmLabel }), - /* @__PURE__ */ jsx2(Input, { name: "passwordConfirm", type: "password", minLength: 8 }) + !registerMode && forgotPasswordLink ? /* @__PURE__ */ jsx3(Stack, { align: "flex-end", children: forgotPasswordLink }) : null, + registerMode ? /* @__PURE__ */ jsxs2(FormControl, { isRequired: true, children: [ + /* @__PURE__ */ jsx3(FormLabel, { children: texts.passwordConfirmLabel }), + /* @__PURE__ */ jsx3(Input, { name: "passwordConfirm", type: "password", minLength: 8 }) ] }) : null, - /* @__PURE__ */ jsx2(Button, { type: "submit", isLoading: loading, children: registerMode ? texts.submitRegisterLabel : texts.submitSignInLabel }) + /* @__PURE__ */ jsx3(Button, { type: "submit", isLoading: loading, children: registerMode ? texts.submitRegisterLabel : texts.submitSignInLabel }) ] }) }), - registerMode || !onOAuthSignIn || !providers?.google && !providers?.slack ? null : /* @__PURE__ */ jsxs(HStack, { children: [ - providers.google ? /* @__PURE__ */ jsx2( + registerMode || !onOAuthSignIn || !providers?.google && !providers?.slack ? null : /* @__PURE__ */ jsxs2(HStack, { children: [ + providers.google ? /* @__PURE__ */ jsx3( Button, { flex: 1, @@ -245,7 +321,7 @@ function LoginForm({ fontSize: { base: "md", md: "lg" }, fontWeight: "semibold", iconSpacing: 4, - leftIcon: /* @__PURE__ */ jsx2(Center2, { boxSize: "40px", bg: "white", borderRadius: "full", boxShadow: "sm", children: /* @__PURE__ */ jsx2(Icon, { as: FcGoogle, boxSize: 6 }) }), + leftIcon: /* @__PURE__ */ jsx3(Center, { boxSize: "40px", bg: "white", borderRadius: "full", boxShadow: "sm", children: /* @__PURE__ */ jsx3(Icon, { as: FcGoogle, boxSize: 6 }) }), _hover: { bg: "gray.300" }, _active: { bg: "gray.300" }, isLoading: oauthLoadingProvider === "google", @@ -253,7 +329,7 @@ function LoginForm({ children: texts.googleLabel } ) : null, - providers.slack ? /* @__PURE__ */ jsx2( + providers.slack ? /* @__PURE__ */ jsx3( Button, { flex: 1, @@ -264,25 +340,13 @@ function LoginForm({ } ) : null ] }), - /* @__PURE__ */ jsx2(Button, { variant: "ghost", onClick: onModeToggle, children: registerMode ? texts.toggleToSignInLabel : texts.toggleToRegisterLabel }), + /* @__PURE__ */ jsx3(Button, { variant: "ghost", onClick: onModeToggle, children: registerMode ? texts.toggleToSignInLabel : texts.toggleToRegisterLabel }), footer ?? null ] }); } // react/PasswordResetForms.tsx -import { - Alert as Alert2, - AlertDescription as AlertDescription2, - AlertIcon as AlertIcon2, - Button as Button2, - FormControl as FormControl2, - FormLabel as FormLabel2, - Input as Input2, - Spinner as Spinner2, - Stack as Stack2, - Text -} from "@chakra-ui/react"; -import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime"; +import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime"; function PasswordResetRequestForm({ texts, helperText, @@ -298,18 +362,18 @@ function PasswordResetRequestForm({ email: String(form.get("email") ?? "") }); } - return /* @__PURE__ */ jsxs2(Stack2, { spacing: 5, children: [ - requestSent ? /* @__PURE__ */ jsxs2(Alert2, { status: "success", borderRadius: "md", children: [ - /* @__PURE__ */ jsx3(AlertIcon2, {}), - /* @__PURE__ */ jsx3(AlertDescription2, { children: texts.requestSentMessage }) + return /* @__PURE__ */ jsxs3(Stack, { spacing: 5, children: [ + requestSent ? /* @__PURE__ */ jsxs3(Alert, { status: "success", borderRadius: "md", children: [ + /* @__PURE__ */ jsx4(AlertIcon, {}), + /* @__PURE__ */ jsx4(AlertDescription, { children: texts.requestSentMessage }) ] }) : null, - /* @__PURE__ */ jsx3("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs2(Stack2, { spacing: 4, children: [ - /* @__PURE__ */ jsxs2(FormControl2, { isRequired: true, children: [ - /* @__PURE__ */ jsx3(FormLabel2, { children: texts.emailLabel }), - /* @__PURE__ */ jsx3(Input2, { name: "email", type: "email", placeholder: emailPlaceholder }) + /* @__PURE__ */ jsx4("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs3(Stack, { spacing: 4, children: [ + /* @__PURE__ */ jsxs3(FormControl, { isRequired: true, children: [ + /* @__PURE__ */ jsx4(FormLabel, { children: texts.emailLabel }), + /* @__PURE__ */ jsx4(Input, { name: "email", type: "email", placeholder: emailPlaceholder }) ] }), - /* @__PURE__ */ jsx3(Text, { fontSize: "sm", color: "gray.600", children: helperText }), - /* @__PURE__ */ jsx3(Button2, { type: "submit", isLoading: loading, children: texts.submitLabel }) + /* @__PURE__ */ jsx4(Text, { fontSize: "sm", color: "gray.600", children: helperText }), + /* @__PURE__ */ jsx4(Button, { type: "submit", isLoading: loading, children: texts.submitLabel }) ] }) }) ] }); } @@ -329,35 +393,35 @@ function PasswordResetConfirmForm({ }); } if (tokenState.status === "loading") { - return /* @__PURE__ */ jsxs2(Stack2, { align: "center", py: 6, spacing: 3, children: [ - /* @__PURE__ */ jsx3(Spinner2, {}), - /* @__PURE__ */ jsx3(Text, { color: "gray.600", children: texts.loadingLabel }) + return /* @__PURE__ */ jsxs3(Stack, { align: "center", py: 6, spacing: 3, children: [ + /* @__PURE__ */ jsx4(Spinner, {}), + /* @__PURE__ */ jsx4(Text, { color: "gray.600", children: texts.loadingLabel }) ] }); } if (tokenState.status === "invalid") { - return /* @__PURE__ */ jsxs2(Alert2, { status: "error", borderRadius: "md", children: [ - /* @__PURE__ */ jsx3(AlertIcon2, {}), - /* @__PURE__ */ jsx3(AlertDescription2, { children: tokenState.error || texts.invalidLinkLabel }) + return /* @__PURE__ */ jsxs3(Alert, { status: "error", borderRadius: "md", children: [ + /* @__PURE__ */ jsx4(AlertIcon, {}), + /* @__PURE__ */ jsx4(AlertDescription, { children: tokenState.error || texts.invalidLinkLabel }) ] }); } if (completedMode !== null) { - return /* @__PURE__ */ jsxs2(Alert2, { status: "success", borderRadius: "md", children: [ - /* @__PURE__ */ jsx3(AlertIcon2, {}), - /* @__PURE__ */ jsx3(AlertDescription2, { children: completedMode === "create" ? texts.createSuccessLabel : texts.resetSuccessLabel }) + return /* @__PURE__ */ jsxs3(Alert, { status: "success", borderRadius: "md", children: [ + /* @__PURE__ */ jsx4(AlertIcon, {}), + /* @__PURE__ */ jsx4(AlertDescription, { children: completedMode === "create" ? texts.createSuccessLabel : texts.resetSuccessLabel }) ] }); } - return /* @__PURE__ */ jsxs2(Stack2, { spacing: 4, children: [ - /* @__PURE__ */ jsx3(Text, { fontSize: "sm", color: "gray.600", children: tokenState.email }), - /* @__PURE__ */ jsx3("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs2(Stack2, { spacing: 4, children: [ - /* @__PURE__ */ jsxs2(FormControl2, { isRequired: true, children: [ - /* @__PURE__ */ jsx3(FormLabel2, { children: texts.passwordLabel }), - /* @__PURE__ */ jsx3(Input2, { name: "password", type: "password", minLength: 8 }) + return /* @__PURE__ */ jsxs3(Stack, { spacing: 4, children: [ + /* @__PURE__ */ jsx4(Text, { fontSize: "sm", color: "gray.600", children: tokenState.email }), + /* @__PURE__ */ jsx4("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs3(Stack, { spacing: 4, children: [ + /* @__PURE__ */ jsxs3(FormControl, { isRequired: true, children: [ + /* @__PURE__ */ jsx4(FormLabel, { children: texts.passwordLabel }), + /* @__PURE__ */ jsx4(Input, { name: "password", type: "password", minLength: 8 }) ] }), - /* @__PURE__ */ jsxs2(FormControl2, { isRequired: true, children: [ - /* @__PURE__ */ jsx3(FormLabel2, { children: texts.passwordConfirmLabel }), - /* @__PURE__ */ jsx3(Input2, { name: "passwordConfirm", type: "password", minLength: 8 }) + /* @__PURE__ */ jsxs3(FormControl, { isRequired: true, children: [ + /* @__PURE__ */ jsx4(FormLabel, { children: texts.passwordConfirmLabel }), + /* @__PURE__ */ jsx4(Input, { name: "passwordConfirm", type: "password", minLength: 8 }) ] }), - /* @__PURE__ */ jsx3(Button2, { type: "submit", isLoading: loading, children: tokenState.mode === "create" ? texts.createSubmitLabel : texts.resetSubmitLabel }) + /* @__PURE__ */ jsx4(Button, { type: "submit", isLoading: loading, children: tokenState.mode === "create" ? texts.createSubmitLabel : texts.resetSubmitLabel }) ] }) }) ] }); } diff --git a/dist/react/index.js.map b/dist/react/index.js.map index a3ae9b0..1be915a 100644 --- a/dist/react/index.js.map +++ b/dist/react/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../react/AuthGuard.tsx","../../react/client.ts","../../react/LoginForm.tsx","../../react/PasswordResetForms.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { Center, Spinner } from \"@chakra-ui/react\";\nimport { Navigate } from \"react-router-dom\";\n\ntype AuthGuardProps = {\n children: React.ReactNode;\n fetchCurrentUser: () => Promise;\n redirectTo?: string;\n loadingFallback?: React.ReactNode;\n authenticatedWrapper?: (children: React.ReactNode) => React.ReactNode;\n};\n\nexport function AuthGuard({\n children,\n fetchCurrentUser,\n redirectTo = \"/login\",\n loadingFallback,\n authenticatedWrapper\n}: AuthGuardProps) {\n const [state, setState] = useState<{ loading: boolean; authenticated: boolean }>({\n loading: true,\n authenticated: false\n });\n\n useEffect(() => {\n let cancelled = false;\n\n fetchCurrentUser()\n .then(() => {\n if (!cancelled) {\n setState({ loading: false, authenticated: true });\n }\n })\n .catch(() => {\n if (!cancelled) {\n setState({ loading: false, authenticated: false });\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [fetchCurrentUser]);\n\n if (state.loading) {\n return (\n <>\n {loadingFallback ?? (\n
\n \n
\n )}\n \n );\n }\n\n if (!state.authenticated) {\n return ;\n }\n\n return <>{authenticatedWrapper ? authenticatedWrapper(children) : children};\n}\n","import type { AuthProviderAvailability, PasswordResetMode } from \"./types\";\n\ntype CreateAuthClientOptions = {\n apiUrl: (path: string) => string;\n authUrl?: (path: string) => string;\n fetchImpl?: typeof fetch;\n credentials?: RequestCredentials;\n defaultOAuthCallbackUrl?: string | (() => string);\n};\n\ntype LoginInput = {\n email: string;\n password: string;\n};\n\ntype RegisterInput = LoginInput & {\n name: string;\n};\n\ntype PasswordResetValidationPayload = {\n email?: string;\n mode?: PasswordResetMode;\n error?: string;\n};\n\ntype JsonErrorPayload = {\n error?: string;\n};\n\nasync function readJsonError(response: Response, fallback: string): Promise {\n const payload = (await response.json().catch(() => null)) as JsonErrorPayload | null;\n return new Error(payload?.error ?? fallback);\n}\n\nexport function createAuthClient(options: CreateAuthClientOptions) {\n const fetchImpl = options.fetchImpl ?? fetch;\n const authUrl = options.authUrl ?? options.apiUrl;\n const credentials = options.credentials ?? \"include\";\n\n function resolveDefaultOAuthCallbackUrl(): string {\n const configured = options.defaultOAuthCallbackUrl;\n if (typeof configured === \"function\") {\n return configured();\n }\n if (typeof configured === \"string\" && configured.trim().length > 0) {\n return configured;\n }\n return `${window.location.origin}/chat`;\n }\n\n async function request(path: string, init?: RequestInit): Promise {\n return fetchImpl(options.apiUrl(path), {\n ...init,\n credentials,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(init?.headers ?? {})\n }\n });\n }\n\n return {\n async getProviders(): Promise {\n const response = await request(\"/api/auth/providers\");\n if (!response.ok) {\n throw await readJsonError(response, \"providers_unavailable\");\n }\n return (await response.json()) as AuthProviderAvailability;\n },\n\n async getCurrentUser(): Promise {\n const response = await request(\"/api/me\");\n if (!response.ok) {\n throw await readJsonError(response, \"Unauthorized\");\n }\n const payload = (await response.json()) as { user: TUser };\n return payload.user;\n },\n\n async register(input: RegisterInput): Promise {\n const response = await request(\"/api/auth/register\", {\n method: \"POST\",\n body: JSON.stringify(input)\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Registration failed\");\n }\n },\n\n async login(input: LoginInput): Promise {\n const response = await request(\"/api/auth/login\", {\n method: \"POST\",\n body: JSON.stringify(input)\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Sign in failed\");\n }\n },\n\n async requestPasswordReset(email: string): Promise {\n const response = await request(\"/api/auth/password-reset/request\", {\n method: \"POST\",\n body: JSON.stringify({ email })\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Password reset request failed\");\n }\n },\n\n async validatePasswordResetToken(token: string): Promise<{ email: string; mode: PasswordResetMode }> {\n const response = await request(`/api/auth/password-reset/validate?token=${encodeURIComponent(token)}`, {\n headers: {}\n });\n const payload = (await response.json().catch(() => null)) as PasswordResetValidationPayload | null;\n if (!response.ok || !payload?.email || (payload.mode !== \"reset\" && payload.mode !== \"create\")) {\n throw new Error(payload?.error ?? \"Invalid reset link\");\n }\n return {\n email: payload.email,\n mode: payload.mode\n };\n },\n\n async confirmPasswordReset(input: { token: string; password: string }): Promise {\n const response = await request(\"/api/auth/password-reset/confirm\", {\n method: \"POST\",\n body: JSON.stringify(input)\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Invalid reset link\");\n }\n },\n\n async logout(): Promise {\n const response = await request(\"/api/auth/logout\", {\n method: \"POST\"\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Logout failed\");\n }\n },\n\n async startOAuthSignIn(provider: string, callbackUrl = resolveDefaultOAuthCallbackUrl()): Promise {\n const response = await fetchImpl(authUrl(\"/auth/csrf\"), {\n credentials\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Sign in failed\");\n }\n\n const payload = (await response.json()) as { csrfToken?: string };\n if (!payload.csrfToken) {\n throw new Error(\"Sign in failed\");\n }\n\n const form = document.createElement(\"form\");\n form.method = \"POST\";\n form.action = authUrl(`/auth/signin/${provider}`);\n form.style.display = \"none\";\n\n const csrfInput = document.createElement(\"input\");\n csrfInput.type = \"hidden\";\n csrfInput.name = \"csrfToken\";\n csrfInput.value = payload.csrfToken;\n form.appendChild(csrfInput);\n\n const callbackInput = document.createElement(\"input\");\n callbackInput.type = \"hidden\";\n callbackInput.name = \"callbackUrl\";\n callbackInput.value = callbackUrl;\n form.appendChild(callbackInput);\n\n document.body.appendChild(form);\n form.submit();\n }\n };\n}\n","import type { FormEvent, ReactNode } from \"react\";\nimport { Alert, AlertDescription, AlertIcon, Button, Center, FormControl, FormLabel, HStack, Icon, Input, Stack } from \"@chakra-ui/react\";\nimport { FcGoogle } from \"react-icons/fc\";\nimport type { AuthProviderAvailability, AuthProviderKey, AuthSubmitValues, LoginMode } from \"./types\";\n\ntype LoginFormTexts = {\n nameLabel: string;\n emailLabel: string;\n passwordLabel: string;\n passwordConfirmLabel: string;\n submitRegisterLabel: string;\n submitSignInLabel: string;\n toggleToRegisterLabel: string;\n toggleToSignInLabel: string;\n forgotPasswordLabel: string;\n googleLabel: string;\n slackLabel: string;\n};\n\ntype LoginFormProps = {\n mode: LoginMode;\n texts: LoginFormTexts;\n onSubmit: (values: AuthSubmitValues) => void | Promise;\n onModeToggle: () => void;\n loading?: boolean;\n oauthLoadingProvider?: AuthProviderKey | null;\n providers?: AuthProviderAvailability;\n onOAuthSignIn?: (provider: AuthProviderKey) => void | Promise;\n errorMessage?: string | null;\n successMessage?: string | null;\n footer?: ReactNode;\n forgotPasswordLink?: ReactNode;\n emailPlaceholder?: string;\n namePlaceholder?: string;\n};\n\nexport function LoginForm({\n mode,\n texts,\n onSubmit,\n onModeToggle,\n loading = false,\n oauthLoadingProvider = null,\n providers,\n onOAuthSignIn,\n errorMessage,\n successMessage,\n footer,\n forgotPasswordLink,\n emailPlaceholder = \"you@example.com\",\n namePlaceholder = \"Jane Doe\"\n}: LoginFormProps) {\n const registerMode = mode === \"register\";\n\n function handleSubmit(event: FormEvent) {\n event.preventDefault();\n const form = new FormData(event.currentTarget);\n void onSubmit({\n name: String(form.get(\"name\") ?? \"\"),\n email: String(form.get(\"email\") ?? \"\"),\n password: String(form.get(\"password\") ?? \"\"),\n passwordConfirm: String(form.get(\"passwordConfirm\") ?? \"\")\n });\n }\n\n return (\n \n {errorMessage ? (\n \n \n {errorMessage}\n \n ) : null}\n\n {successMessage ? (\n \n \n {successMessage}\n \n ) : null}\n\n
\n \n {registerMode ? (\n \n {texts.nameLabel}\n \n \n ) : null}\n\n \n {texts.emailLabel}\n \n \n\n \n {texts.passwordLabel}\n \n \n\n {!registerMode && forgotPasswordLink ? {forgotPasswordLink} : null}\n\n {registerMode ? (\n \n {texts.passwordConfirmLabel}\n \n \n ) : null}\n\n \n \n
\n\n {registerMode || !onOAuthSignIn || (!providers?.google && !providers?.slack) ? null : (\n \n {providers.google ? (\n \n \n \n }\n _hover={{ bg: \"gray.300\" }}\n _active={{ bg: \"gray.300\" }}\n isLoading={oauthLoadingProvider === \"google\"}\n onClick={() => void onOAuthSignIn(\"google\")}\n >\n {texts.googleLabel}\n \n ) : null}\n {providers.slack ? (\n void onOAuthSignIn(\"slack\")}\n >\n {texts.slackLabel}\n \n ) : null}\n \n )}\n\n \n\n {footer ?? null}\n
\n );\n}\n","import type { FormEvent, ReactNode } from \"react\";\nimport {\n Alert,\n AlertDescription,\n AlertIcon,\n Button,\n FormControl,\n FormLabel,\n Input,\n Spinner,\n Stack,\n Text\n} from \"@chakra-ui/react\";\nimport type { PasswordResetMode, PasswordResetTokenState } from \"./types\";\n\ntype PasswordResetRequestTexts = {\n emailLabel: string;\n submitLabel: string;\n requestSentMessage: string;\n};\n\ntype PasswordResetRequestFormProps = {\n texts: PasswordResetRequestTexts;\n helperText: ReactNode;\n loading?: boolean;\n requestSent?: boolean;\n onSubmit: (values: { email: string }) => void | Promise;\n emailPlaceholder?: string;\n};\n\ntype PasswordResetConfirmTexts = {\n loadingLabel: string;\n passwordLabel: string;\n passwordConfirmLabel: string;\n invalidLinkLabel: string;\n resetSubmitLabel: string;\n createSubmitLabel: string;\n resetSuccessLabel: string;\n createSuccessLabel: string;\n};\n\ntype PasswordResetConfirmFormProps = {\n texts: PasswordResetConfirmTexts;\n tokenState: PasswordResetTokenState;\n loading?: boolean;\n completedMode?: PasswordResetMode | null;\n onSubmit: (values: { password: string; passwordConfirm: string }) => void | Promise;\n};\n\nexport function PasswordResetRequestForm({\n texts,\n helperText,\n loading = false,\n requestSent = false,\n onSubmit,\n emailPlaceholder = \"you@example.com\"\n}: PasswordResetRequestFormProps) {\n function handleSubmit(event: FormEvent) {\n event.preventDefault();\n const form = new FormData(event.currentTarget);\n void onSubmit({\n email: String(form.get(\"email\") ?? \"\")\n });\n }\n\n return (\n \n {requestSent ? (\n \n \n {texts.requestSentMessage}\n \n ) : null}\n\n
\n \n \n {texts.emailLabel}\n \n \n\n \n {helperText}\n \n\n \n \n
\n
\n );\n}\n\nexport function PasswordResetConfirmForm({\n texts,\n tokenState,\n loading = false,\n completedMode = null,\n onSubmit\n}: PasswordResetConfirmFormProps) {\n function handleSubmit(event: FormEvent) {\n event.preventDefault();\n const form = new FormData(event.currentTarget);\n void onSubmit({\n password: String(form.get(\"password\") ?? \"\"),\n passwordConfirm: String(form.get(\"passwordConfirm\") ?? \"\")\n });\n }\n\n if (tokenState.status === \"loading\") {\n return (\n \n \n {texts.loadingLabel}\n \n );\n }\n\n if (tokenState.status === \"invalid\") {\n return (\n \n \n {tokenState.error || texts.invalidLinkLabel}\n \n );\n }\n\n if (completedMode !== null) {\n return (\n \n \n {completedMode === \"create\" ? texts.createSuccessLabel : texts.resetSuccessLabel}\n \n );\n }\n\n return (\n \n \n {tokenState.email}\n \n\n
\n \n \n {texts.passwordLabel}\n \n \n\n \n {texts.passwordConfirmLabel}\n \n \n\n \n \n
\n
\n );\n}\n"],"mappings":"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","names":["Center","jsx","Alert","AlertDescription","AlertIcon","Button","FormControl","FormLabel","Input","Spinner","Stack","jsx","jsxs"]} \ No newline at end of file +{"version":3,"sources":["../../react/AuthGuard.tsx","../../react/chakra-compat.tsx","../../react/client.ts","../../react/LoginForm.tsx","../../react/PasswordResetForms.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { Center, Spinner } from \"./chakra-compat\";\nimport { Navigate } from \"react-router\";\n\ntype AuthGuardProps = {\n children: React.ReactNode;\n fetchCurrentUser: () => Promise;\n redirectTo?: string;\n loadingFallback?: React.ReactNode;\n authenticatedWrapper?: (children: React.ReactNode) => React.ReactNode;\n};\n\nexport function AuthGuard({\n children,\n fetchCurrentUser,\n redirectTo = \"/login\",\n loadingFallback,\n authenticatedWrapper\n}: AuthGuardProps) {\n const [state, setState] = useState<{ loading: boolean; authenticated: boolean }>({\n loading: true,\n authenticated: false\n });\n\n useEffect(() => {\n let cancelled = false;\n\n fetchCurrentUser()\n .then(() => {\n if (!cancelled) {\n setState({ loading: false, authenticated: true });\n }\n })\n .catch(() => {\n if (!cancelled) {\n setState({ loading: false, authenticated: false });\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [fetchCurrentUser]);\n\n if (state.loading) {\n return (\n <>\n {loadingFallback ?? (\n
\n \n
\n )}\n \n );\n }\n\n if (!state.authenticated) {\n return ;\n }\n\n return <>{authenticatedWrapper ? authenticatedWrapper(children) : children};\n}\n","import {\n Alert as ChakraAlert,\n Box as ChakraBox,\n Button as ChakraButton,\n Center as ChakraCenter,\n HStack as ChakraHStack,\n Icon as ChakraIcon,\n Input as ChakraInput,\n Spinner as ChakraSpinner,\n Stack as ChakraStack,\n Text as ChakraText\n} from \"@chakra-ui/react\";\nimport type { ReactNode } from \"react\";\n\ntype AnyProps = Record;\n\nfunction normalizeSpacingProps(props: AnyProps) {\n const next = { ...props };\n if (next.spacing !== undefined && next.gap === undefined) {\n next.gap = next.spacing;\n }\n delete next.spacing;\n return next;\n}\n\nfunction normalizeInteractiveProps(props: AnyProps) {\n const next = normalizeSpacingProps(props);\n if (next.isDisabled !== undefined && next.disabled === undefined) {\n next.disabled = next.isDisabled;\n }\n if (next.isLoading !== undefined && next.loading === undefined) {\n next.loading = next.isLoading;\n }\n delete next.isDisabled;\n delete next.isLoading;\n return next;\n}\n\nexport const Center = ChakraCenter as any;\nexport const Icon = ChakraIcon as any;\nexport const Input = ChakraInput as any;\nexport const Spinner = ChakraSpinner as any;\n\nexport function Stack(props: AnyProps) {\n return ;\n}\n\nexport function HStack(props: AnyProps) {\n return ;\n}\n\nexport function Text(props: AnyProps) {\n const next = { ...props };\n if (next.noOfLines !== undefined && next.lineClamp === undefined) {\n next.lineClamp = next.noOfLines;\n }\n delete next.noOfLines;\n return ;\n}\n\nexport function Button(props: AnyProps) {\n const { leftIcon, rightIcon, children, ...rest } = normalizeInteractiveProps(props);\n return (\n \n \n {leftIcon ?? null}\n {children}\n {rightIcon ?? null}\n \n \n );\n}\n\nexport function Alert({ children, status = \"info\", ...props }: AnyProps) {\n return (\n \n {children}\n \n );\n}\n\nexport function AlertIcon() {\n return ;\n}\n\nexport function AlertDescription({ children, ...props }: { children: ReactNode } & AnyProps) {\n return {children};\n}\n\nexport function FormControl({ children, ...props }: AnyProps) {\n return {children};\n}\n\nexport function FormLabel(props: AnyProps) {\n return ;\n}\n","import type { AuthProviderAvailability, PasswordResetMode } from \"./types\";\n\ntype CreateAuthClientOptions = {\n apiUrl: (path: string) => string;\n authUrl?: (path: string) => string;\n fetchImpl?: typeof fetch;\n credentials?: RequestCredentials;\n defaultOAuthCallbackUrl?: string | (() => string);\n};\n\ntype LoginInput = {\n email: string;\n password: string;\n};\n\ntype RegisterInput = LoginInput & {\n name: string;\n};\n\ntype PasswordResetValidationPayload = {\n email?: string;\n mode?: PasswordResetMode;\n error?: string;\n};\n\ntype JsonErrorPayload = {\n error?: string;\n};\n\nasync function readJsonError(response: Response, fallback: string): Promise {\n const payload = (await response.json().catch(() => null)) as JsonErrorPayload | null;\n return new Error(payload?.error ?? fallback);\n}\n\nexport function createAuthClient(options: CreateAuthClientOptions) {\n const fetchImpl = options.fetchImpl ?? fetch;\n const authUrl = options.authUrl ?? options.apiUrl;\n const credentials = options.credentials ?? \"include\";\n\n function resolveDefaultOAuthCallbackUrl(): string {\n const configured = options.defaultOAuthCallbackUrl;\n if (typeof configured === \"function\") {\n return configured();\n }\n if (typeof configured === \"string\" && configured.trim().length > 0) {\n return configured;\n }\n return `${window.location.origin}/chat`;\n }\n\n async function request(path: string, init?: RequestInit): Promise {\n return fetchImpl(options.apiUrl(path), {\n ...init,\n credentials,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(init?.headers ?? {})\n }\n });\n }\n\n return {\n async getProviders(): Promise {\n const response = await request(\"/api/auth/providers\");\n if (!response.ok) {\n throw await readJsonError(response, \"providers_unavailable\");\n }\n return (await response.json()) as AuthProviderAvailability;\n },\n\n async getCurrentUser(): Promise {\n const response = await request(\"/api/me\");\n if (!response.ok) {\n throw await readJsonError(response, \"Unauthorized\");\n }\n const payload = (await response.json()) as { user: TUser };\n return payload.user;\n },\n\n async register(input: RegisterInput): Promise {\n const response = await request(\"/api/auth/register\", {\n method: \"POST\",\n body: JSON.stringify(input)\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Registration failed\");\n }\n },\n\n async login(input: LoginInput): Promise {\n const response = await request(\"/api/auth/login\", {\n method: \"POST\",\n body: JSON.stringify(input)\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Sign in failed\");\n }\n },\n\n async requestPasswordReset(email: string): Promise {\n const response = await request(\"/api/auth/password-reset/request\", {\n method: \"POST\",\n body: JSON.stringify({ email })\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Password reset request failed\");\n }\n },\n\n async validatePasswordResetToken(token: string): Promise<{ email: string; mode: PasswordResetMode }> {\n const response = await request(`/api/auth/password-reset/validate?token=${encodeURIComponent(token)}`, {\n headers: {}\n });\n const payload = (await response.json().catch(() => null)) as PasswordResetValidationPayload | null;\n if (!response.ok || !payload?.email || (payload.mode !== \"reset\" && payload.mode !== \"create\")) {\n throw new Error(payload?.error ?? \"Invalid reset link\");\n }\n return {\n email: payload.email,\n mode: payload.mode\n };\n },\n\n async confirmPasswordReset(input: { token: string; password: string }): Promise {\n const response = await request(\"/api/auth/password-reset/confirm\", {\n method: \"POST\",\n body: JSON.stringify(input)\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Invalid reset link\");\n }\n },\n\n async logout(): Promise {\n const response = await request(\"/api/auth/logout\", {\n method: \"POST\"\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Logout failed\");\n }\n },\n\n async startOAuthSignIn(provider: string, callbackUrl = resolveDefaultOAuthCallbackUrl()): Promise {\n const response = await fetchImpl(authUrl(\"/auth/csrf\"), {\n credentials\n });\n if (!response.ok) {\n throw await readJsonError(response, \"Sign in failed\");\n }\n\n const payload = (await response.json()) as { csrfToken?: string };\n if (!payload.csrfToken) {\n throw new Error(\"Sign in failed\");\n }\n\n const form = document.createElement(\"form\");\n form.method = \"POST\";\n form.action = authUrl(`/auth/signin/${provider}`);\n form.style.display = \"none\";\n\n const csrfInput = document.createElement(\"input\");\n csrfInput.type = \"hidden\";\n csrfInput.name = \"csrfToken\";\n csrfInput.value = payload.csrfToken;\n form.appendChild(csrfInput);\n\n const callbackInput = document.createElement(\"input\");\n callbackInput.type = \"hidden\";\n callbackInput.name = \"callbackUrl\";\n callbackInput.value = callbackUrl;\n form.appendChild(callbackInput);\n\n document.body.appendChild(form);\n form.submit();\n }\n };\n}\n","import type { FormEvent, ReactNode } from \"react\";\nimport { Alert, AlertDescription, AlertIcon, Button, Center, FormControl, FormLabel, HStack, Icon, Input, Stack } from \"./chakra-compat\";\nimport { FcGoogle } from \"react-icons/fc\";\nimport type { AuthProviderAvailability, AuthProviderKey, AuthSubmitValues, LoginMode } from \"./types\";\n\ntype LoginFormTexts = {\n nameLabel: string;\n emailLabel: string;\n passwordLabel: string;\n passwordConfirmLabel: string;\n submitRegisterLabel: string;\n submitSignInLabel: string;\n toggleToRegisterLabel: string;\n toggleToSignInLabel: string;\n forgotPasswordLabel: string;\n googleLabel: string;\n slackLabel: string;\n};\n\ntype LoginFormProps = {\n mode: LoginMode;\n texts: LoginFormTexts;\n onSubmit: (values: AuthSubmitValues) => void | Promise;\n onModeToggle: () => void;\n loading?: boolean;\n oauthLoadingProvider?: AuthProviderKey | null;\n providers?: AuthProviderAvailability;\n onOAuthSignIn?: (provider: AuthProviderKey) => void | Promise;\n errorMessage?: string | null;\n successMessage?: string | null;\n footer?: ReactNode;\n forgotPasswordLink?: ReactNode;\n emailPlaceholder?: string;\n namePlaceholder?: string;\n};\n\nexport function LoginForm({\n mode,\n texts,\n onSubmit,\n onModeToggle,\n loading = false,\n oauthLoadingProvider = null,\n providers,\n onOAuthSignIn,\n errorMessage,\n successMessage,\n footer,\n forgotPasswordLink,\n emailPlaceholder = \"you@example.com\",\n namePlaceholder = \"Jane Doe\"\n}: LoginFormProps) {\n const registerMode = mode === \"register\";\n\n function handleSubmit(event: FormEvent) {\n event.preventDefault();\n const form = new FormData(event.currentTarget);\n void onSubmit({\n name: String(form.get(\"name\") ?? \"\"),\n email: String(form.get(\"email\") ?? \"\"),\n password: String(form.get(\"password\") ?? \"\"),\n passwordConfirm: String(form.get(\"passwordConfirm\") ?? \"\")\n });\n }\n\n return (\n \n {errorMessage ? (\n \n \n {errorMessage}\n \n ) : null}\n\n {successMessage ? (\n \n \n {successMessage}\n \n ) : null}\n\n
\n \n {registerMode ? (\n \n {texts.nameLabel}\n \n \n ) : null}\n\n \n {texts.emailLabel}\n \n \n\n \n {texts.passwordLabel}\n \n \n\n {!registerMode && forgotPasswordLink ? {forgotPasswordLink} : null}\n\n {registerMode ? (\n \n {texts.passwordConfirmLabel}\n \n \n ) : null}\n\n \n \n
\n\n {registerMode || !onOAuthSignIn || (!providers?.google && !providers?.slack) ? null : (\n \n {providers.google ? (\n \n \n \n }\n _hover={{ bg: \"gray.300\" }}\n _active={{ bg: \"gray.300\" }}\n isLoading={oauthLoadingProvider === \"google\"}\n onClick={() => void onOAuthSignIn(\"google\")}\n >\n {texts.googleLabel}\n \n ) : null}\n {providers.slack ? (\n void onOAuthSignIn(\"slack\")}\n >\n {texts.slackLabel}\n \n ) : null}\n \n )}\n\n \n\n {footer ?? null}\n
\n );\n}\n","import type { FormEvent, ReactNode } from \"react\";\nimport {\n Alert,\n AlertDescription,\n AlertIcon,\n Button,\n FormControl,\n FormLabel,\n Input,\n Spinner,\n Stack,\n Text\n} from \"./chakra-compat\";\nimport type { PasswordResetMode, PasswordResetTokenState } from \"./types\";\n\ntype PasswordResetRequestTexts = {\n emailLabel: string;\n submitLabel: string;\n requestSentMessage: string;\n};\n\ntype PasswordResetRequestFormProps = {\n texts: PasswordResetRequestTexts;\n helperText: ReactNode;\n loading?: boolean;\n requestSent?: boolean;\n onSubmit: (values: { email: string }) => void | Promise;\n emailPlaceholder?: string;\n};\n\ntype PasswordResetConfirmTexts = {\n loadingLabel: string;\n passwordLabel: string;\n passwordConfirmLabel: string;\n invalidLinkLabel: string;\n resetSubmitLabel: string;\n createSubmitLabel: string;\n resetSuccessLabel: string;\n createSuccessLabel: string;\n};\n\ntype PasswordResetConfirmFormProps = {\n texts: PasswordResetConfirmTexts;\n tokenState: PasswordResetTokenState;\n loading?: boolean;\n completedMode?: PasswordResetMode | null;\n onSubmit: (values: { password: string; passwordConfirm: string }) => void | Promise;\n};\n\nexport function PasswordResetRequestForm({\n texts,\n helperText,\n loading = false,\n requestSent = false,\n onSubmit,\n emailPlaceholder = \"you@example.com\"\n}: PasswordResetRequestFormProps) {\n function handleSubmit(event: FormEvent) {\n event.preventDefault();\n const form = new FormData(event.currentTarget);\n void onSubmit({\n email: String(form.get(\"email\") ?? \"\")\n });\n }\n\n return (\n \n {requestSent ? (\n \n \n {texts.requestSentMessage}\n \n ) : null}\n\n
\n \n \n {texts.emailLabel}\n \n \n\n \n {helperText}\n \n\n \n \n
\n
\n );\n}\n\nexport function PasswordResetConfirmForm({\n texts,\n tokenState,\n loading = false,\n completedMode = null,\n onSubmit\n}: PasswordResetConfirmFormProps) {\n function handleSubmit(event: FormEvent) {\n event.preventDefault();\n const form = new FormData(event.currentTarget);\n void onSubmit({\n password: String(form.get(\"password\") ?? \"\"),\n passwordConfirm: String(form.get(\"passwordConfirm\") ?? \"\")\n });\n }\n\n if (tokenState.status === \"loading\") {\n return (\n \n \n {texts.loadingLabel}\n \n );\n }\n\n if (tokenState.status === \"invalid\") {\n return (\n \n \n {tokenState.error || texts.invalidLinkLabel}\n \n );\n }\n\n if (completedMode !== null) {\n return (\n \n \n {completedMode === \"create\" ? texts.createSuccessLabel : texts.resetSuccessLabel}\n \n );\n }\n\n return (\n \n \n {tokenState.email}\n \n\n
\n \n \n {texts.passwordLabel}\n \n \n\n \n {texts.passwordConfirmLabel}\n \n \n\n \n \n
\n
\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","jsx","jsxs"]} \ No newline at end of file diff --git a/package.json b/package.json index baf6c46..d855462 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@packages/auth", - "version": "0.0.0", + "version": "0.0.1", "private": true, "type": "module", "files": [ @@ -23,13 +23,16 @@ "peerDependencies": { "@auth/express": "^0.12.1", "@auth/prisma-adapter": "^2.9.1", - "@chakra-ui/react": "^2.10.7", + "@chakra-ui/react": "^3.33.0", "@prisma/client": "^6.5.0", "express": "^4.21.2", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-icons": "^5.6.0", - "react-router-dom": "^6.30.0", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "react-icons": "^5.5.0", + "react-router": "^7.13.2", "zod": "^3.24.2" + }, + "dependencies": { + "@emotion/react": "^11.14.0" } } diff --git a/react/AuthGuard.tsx b/react/AuthGuard.tsx index 9f56742..8172a14 100644 --- a/react/AuthGuard.tsx +++ b/react/AuthGuard.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import { Center, Spinner } from "@chakra-ui/react"; -import { Navigate } from "react-router-dom"; +import { Center, Spinner } from "./chakra-compat"; +import { Navigate } from "react-router"; type AuthGuardProps = { children: React.ReactNode; diff --git a/react/LoginForm.tsx b/react/LoginForm.tsx index e7cb063..1cdab5e 100644 --- a/react/LoginForm.tsx +++ b/react/LoginForm.tsx @@ -1,5 +1,5 @@ import type { FormEvent, ReactNode } from "react"; -import { Alert, AlertDescription, AlertIcon, Button, Center, FormControl, FormLabel, HStack, Icon, Input, Stack } from "@chakra-ui/react"; +import { Alert, AlertDescription, AlertIcon, Button, Center, FormControl, FormLabel, HStack, Icon, Input, Stack } from "./chakra-compat"; import { FcGoogle } from "react-icons/fc"; import type { AuthProviderAvailability, AuthProviderKey, AuthSubmitValues, LoginMode } from "./types"; diff --git a/react/PasswordResetForms.tsx b/react/PasswordResetForms.tsx index bea03bc..f61edc1 100644 --- a/react/PasswordResetForms.tsx +++ b/react/PasswordResetForms.tsx @@ -10,7 +10,7 @@ import { Spinner, Stack, Text -} from "@chakra-ui/react"; +} from "./chakra-compat"; import type { PasswordResetMode, PasswordResetTokenState } from "./types"; type PasswordResetRequestTexts = { diff --git a/react/chakra-compat.tsx b/react/chakra-compat.tsx new file mode 100644 index 0000000..5d3efe7 --- /dev/null +++ b/react/chakra-compat.tsx @@ -0,0 +1,96 @@ +import { + Alert as ChakraAlert, + Box as ChakraBox, + Button as ChakraButton, + Center as ChakraCenter, + HStack as ChakraHStack, + Icon as ChakraIcon, + Input as ChakraInput, + Spinner as ChakraSpinner, + Stack as ChakraStack, + Text as ChakraText +} from "@chakra-ui/react"; +import type { ReactNode } from "react"; + +type AnyProps = Record; + +function normalizeSpacingProps(props: AnyProps) { + const next = { ...props }; + if (next.spacing !== undefined && next.gap === undefined) { + next.gap = next.spacing; + } + delete next.spacing; + return next; +} + +function normalizeInteractiveProps(props: AnyProps) { + const next = normalizeSpacingProps(props); + if (next.isDisabled !== undefined && next.disabled === undefined) { + next.disabled = next.isDisabled; + } + if (next.isLoading !== undefined && next.loading === undefined) { + next.loading = next.isLoading; + } + delete next.isDisabled; + delete next.isLoading; + return next; +} + +export const Center = ChakraCenter as any; +export const Icon = ChakraIcon as any; +export const Input = ChakraInput as any; +export const Spinner = ChakraSpinner as any; + +export function Stack(props: AnyProps) { + return ; +} + +export function HStack(props: AnyProps) { + return ; +} + +export function Text(props: AnyProps) { + const next = { ...props }; + if (next.noOfLines !== undefined && next.lineClamp === undefined) { + next.lineClamp = next.noOfLines; + } + delete next.noOfLines; + return ; +} + +export function Button(props: AnyProps) { + const { leftIcon, rightIcon, children, ...rest } = normalizeInteractiveProps(props); + return ( + + + {leftIcon ?? null} + {children} + {rightIcon ?? null} + + + ); +} + +export function Alert({ children, status = "info", ...props }: AnyProps) { + return ( + + {children} + + ); +} + +export function AlertIcon() { + return ; +} + +export function AlertDescription({ children, ...props }: { children: ReactNode } & AnyProps) { + return {children}; +} + +export function FormControl({ children, ...props }: AnyProps) { + return {children}; +} + +export function FormLabel(props: AnyProps) { + return ; +} diff --git a/tsup.config.ts b/tsup.config.ts index 8b7a559..4088f33 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -20,7 +20,7 @@ export default defineConfig({ "react", "react-dom", "react-icons", - "react-router-dom", + "react-router", "zod" ] });