@s8lab/sso-client 1.0.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 +193 -0
- package/dist/components/CaptchaWidget.d.ts +20 -0
- package/dist/components/ForgotPasswordForm.d.ts +2 -0
- package/dist/components/LoginForm.d.ts +2 -0
- package/dist/components/LogoutButton.d.ts +2 -0
- package/dist/components/ProfileComponent.d.ts +2 -0
- package/dist/components/SignupForm.d.ts +2 -0
- package/dist/components/ui/avatar.d.ts +6 -0
- package/dist/components/ui/button.d.ts +11 -0
- package/dist/components/ui/card.d.ts +8 -0
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/input.d.ts +5 -0
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/context/AuthContext.d.ts +4 -0
- package/dist/index.cjs +100 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +9917 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/captchaV3.d.ts +12 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/types/index.d.ts +148 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# @s8lab/sso-client
|
|
2
|
+
|
|
3
|
+
React authentication component library — **Login**, **Signup**, **Forgot Password**, **Logout**, and **Profile** — with Google reCAPTCHA v2 and shadcn-style UI built on Radix UI + Tailwind CSS.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @s8lab/sso-client
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> **Peer dependencies** — make sure your project has `react` and `react-dom` ≥ 18.
|
|
14
|
+
|
|
15
|
+
### Tailwind setup (required)
|
|
16
|
+
|
|
17
|
+
Add this library to your Tailwind `content` so its classes are picked up:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
// tailwind.config.js
|
|
21
|
+
export default {
|
|
22
|
+
content: [
|
|
23
|
+
"./src/**/*.{ts,tsx}",
|
|
24
|
+
"./node_modules/@s8lab/sso-client/dist/**/*.js",
|
|
25
|
+
],
|
|
26
|
+
// ...
|
|
27
|
+
};
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then import the bundled CSS once at your app root:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import "@s8lab/sso-client/styles.css";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Quick start
|
|
39
|
+
|
|
40
|
+
### 1 — Wrap your app with `<AuthProvider>`
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { AuthProvider } from "@s8lab/sso-client";
|
|
44
|
+
|
|
45
|
+
function App() {
|
|
46
|
+
return (
|
|
47
|
+
<AuthProvider
|
|
48
|
+
apiUrl="https://api.yourapp.com"
|
|
49
|
+
recaptchaSiteKey="6LeXXXXXXXXXXXXXXXXX"
|
|
50
|
+
>
|
|
51
|
+
<Router />
|
|
52
|
+
</AuthProvider>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### `AuthProvider` props
|
|
58
|
+
|
|
59
|
+
| Prop | Type | Default | Description |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `apiUrl` | `string` | **required** | Base URL of your SSO server |
|
|
62
|
+
| `recaptchaSiteKey` | `string` | **required** | Google reCAPTCHA v2 site key |
|
|
63
|
+
| `storageKeyPrefix` | `string` | `"sso"` | localStorage key prefix for tokens |
|
|
64
|
+
| `fetcher` | `(url, init) => Promise<T>` | built-in fetch | Override for custom headers/interceptors |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### 2 — Use the components
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import {
|
|
72
|
+
LoginForm,
|
|
73
|
+
SignupForm,
|
|
74
|
+
ForgotPasswordForm,
|
|
75
|
+
LogoutButton,
|
|
76
|
+
ProfileComponent,
|
|
77
|
+
} from "@s8lab/sso-client";
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### `<LoginForm>`
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<LoginForm
|
|
84
|
+
className="mx-auto"
|
|
85
|
+
title="Welcome back"
|
|
86
|
+
description="Sign in to your account"
|
|
87
|
+
signupUrl="/signup"
|
|
88
|
+
forgotPasswordUrl="/forgot-password"
|
|
89
|
+
onSuccess={(user) => router.push("/dashboard")}
|
|
90
|
+
onError={(err) => toast.error(err.message)}
|
|
91
|
+
/>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
#### `<SignupForm>`
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
<SignupForm
|
|
98
|
+
className="mx-auto"
|
|
99
|
+
loginUrl="/login"
|
|
100
|
+
onSuccess={(user) => router.push("/dashboard")}
|
|
101
|
+
/>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### `<ForgotPasswordForm>`
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
<ForgotPasswordForm
|
|
108
|
+
loginUrl="/login"
|
|
109
|
+
onSuccess={() => toast.success("Reset link sent!")}
|
|
110
|
+
/>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### `<LogoutButton>`
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
// Default button
|
|
117
|
+
<LogoutButton onSuccess={() => router.push("/login")} />
|
|
118
|
+
|
|
119
|
+
// Custom render
|
|
120
|
+
<LogoutButton onSuccess={() => router.push("/login")}>
|
|
121
|
+
{({ isLoading }) => (
|
|
122
|
+
<button disabled={isLoading}>
|
|
123
|
+
{isLoading ? "Logging out…" : "Log out"}
|
|
124
|
+
</button>
|
|
125
|
+
)}
|
|
126
|
+
</LogoutButton>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### `<ProfileComponent>`
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
<ProfileComponent
|
|
133
|
+
showLogout
|
|
134
|
+
onLogoutSuccess={() => router.push("/login")}
|
|
135
|
+
onEditProfile={(user) => router.push("/settings")}
|
|
136
|
+
/>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### 3 — `useAuth` hook
|
|
142
|
+
|
|
143
|
+
Access auth state and actions anywhere inside `<AuthProvider>`:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
import { useAuth } from "@s8lab/sso-client";
|
|
147
|
+
|
|
148
|
+
function Dashboard() {
|
|
149
|
+
const { user, isAuthenticated, isLoading, logout } = useAuth();
|
|
150
|
+
|
|
151
|
+
if (isLoading) return <Spinner />;
|
|
152
|
+
if (!isAuthenticated) return <Redirect to="/login" />;
|
|
153
|
+
|
|
154
|
+
return <h1>Hello, {user.firstName}!</h1>;
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## API server contract
|
|
161
|
+
|
|
162
|
+
The `AuthProvider` expects the following endpoints on your `apiUrl`:
|
|
163
|
+
|
|
164
|
+
| Method | Path | Request body | Response |
|
|
165
|
+
|---|---|---|---|
|
|
166
|
+
| `POST` | `/auth/login` | `{ email, password, recaptchaToken }` | `{ user, tokens }` |
|
|
167
|
+
| `POST` | `/auth/signup` | `{ firstName, lastName, email, password, whatsappNumber?, recaptchaToken }` | `{ user, tokens }` |
|
|
168
|
+
| `POST` | `/auth/logout` | *(none)* | `204` |
|
|
169
|
+
| `POST` | `/auth/forgot-password` | `{ email, recaptchaToken }` | `200` |
|
|
170
|
+
| `GET` | `/auth/me` | *(Authorization header)* | `User` |
|
|
171
|
+
|
|
172
|
+
`tokens` shape: `{ accessToken: string; refreshToken?: string }`
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Customising styles
|
|
177
|
+
|
|
178
|
+
Every component accepts a `className` prop that is merged onto the outer `Card` via `tailwind-merge`, so you can freely override any Tailwind class:
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
<LoginForm className="border-2 border-indigo-500 shadow-xl rounded-2xl" />
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
CSS variables for the design tokens (colors, radius, etc.) follow the standard shadcn/ui convention and can be overridden globally in your CSS.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Publishing to npm
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
npm run build
|
|
192
|
+
npm publish --access public
|
|
193
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CaptchaConfig } from '../types';
|
|
2
|
+
export interface CaptchaHandle {
|
|
3
|
+
reset: () => void;
|
|
4
|
+
}
|
|
5
|
+
interface CaptchaWidgetProps {
|
|
6
|
+
config: CaptchaConfig;
|
|
7
|
+
onVerify: (token: string) => void;
|
|
8
|
+
onExpire: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Renders the appropriate captcha widget based on config:
|
|
12
|
+
* - recaptcha v2 → Google checkbox widget
|
|
13
|
+
* - hcaptcha → hCaptcha checkbox widget
|
|
14
|
+
* - recaptcha v3 → nothing (invisible; execute via executeRecaptchaV3 util)
|
|
15
|
+
* - disabled → nothing
|
|
16
|
+
*
|
|
17
|
+
* Expose .reset() via ref to reset the widget after submission.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CaptchaWidget: import('react').ForwardRefExoticComponent<CaptchaWidgetProps & import('react').RefAttributes<CaptchaHandle>>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
3
|
+
declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
4
|
+
declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
|
|
5
|
+
declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
6
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { VariantProps } from 'class-variance-authority';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
declare const buttonVariants: (props?: ({
|
|
4
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
5
|
+
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
6
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
11
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
3
|
+
declare const CardHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
4
|
+
declare const CardTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLParagraphElement>>;
|
|
5
|
+
declare const CardDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
|
|
6
|
+
declare const CardContent: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
7
|
+
declare const CardFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
3
|
+
declare const Checkbox: React.ForwardRefExoticComponent<Omit<CheckboxPrimitive.CheckboxProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
4
|
+
export { Checkbox };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { VariantProps } from 'class-variance-authority';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
4
|
+
declare const Label: React.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & React.RefAttributes<HTMLLabelElement>, "ref"> & VariantProps<(props?: import('class-variance-authority/types').ClassProp | undefined) => string> & React.RefAttributes<HTMLLabelElement>>;
|
|
5
|
+
export { Label };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
3
|
+
declare const Separator: React.ForwardRefExoticComponent<Omit<SeparatorPrimitive.SeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
4
|
+
export { Separator };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { AuthConfigContextValue, AuthContextValue, AuthProviderProps } from '../types';
|
|
2
|
+
export declare function AuthProvider({ children, apiUrl, projectId, storageKeyPrefix, fetcher, }: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare function useAuth(): AuthContextValue;
|
|
4
|
+
export declare function useAuthConfig(): AuthConfigContextValue;
|