@authon/react 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 +137 -0
- package/dist/index.cjs +310 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +60 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +275 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# @authon/react
|
|
2
|
+
|
|
3
|
+
React SDK for [Authon](https://authon.dev) — Provider, hooks, and pre-built components.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @authon/react
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @authon/react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requires `react >= 18.0.0`.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import {
|
|
19
|
+
AuthonProvider,
|
|
20
|
+
SignedIn,
|
|
21
|
+
SignedOut,
|
|
22
|
+
UserButton,
|
|
23
|
+
useUser,
|
|
24
|
+
useAuthon,
|
|
25
|
+
} from '@authon/react';
|
|
26
|
+
|
|
27
|
+
function App() {
|
|
28
|
+
return (
|
|
29
|
+
<AuthonProvider publishableKey="pk_live_...">
|
|
30
|
+
<Header />
|
|
31
|
+
<Main />
|
|
32
|
+
</AuthonProvider>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function Header() {
|
|
37
|
+
return (
|
|
38
|
+
<nav>
|
|
39
|
+
<SignedIn>
|
|
40
|
+
<UserButton />
|
|
41
|
+
</SignedIn>
|
|
42
|
+
<SignedOut>
|
|
43
|
+
<SignInButton />
|
|
44
|
+
</SignedOut>
|
|
45
|
+
</nav>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function SignInButton() {
|
|
50
|
+
const { openSignIn } = useAuthon();
|
|
51
|
+
return <button onClick={() => openSignIn()}>Sign In</button>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function Main() {
|
|
55
|
+
const { user, isLoading } = useUser();
|
|
56
|
+
if (isLoading) return <p>Loading...</p>;
|
|
57
|
+
if (!user) return <p>Please sign in.</p>;
|
|
58
|
+
return <h1>Welcome, {user.displayName}</h1>;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## API Reference
|
|
63
|
+
|
|
64
|
+
### `<AuthonProvider>`
|
|
65
|
+
|
|
66
|
+
Wraps your app and provides auth context.
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<AuthonProvider
|
|
70
|
+
publishableKey="pk_live_..."
|
|
71
|
+
config={{
|
|
72
|
+
apiUrl: 'https://api.authon.dev',
|
|
73
|
+
theme: 'auto',
|
|
74
|
+
locale: 'en',
|
|
75
|
+
appearance: { primaryColorStart: '#7c3aed' },
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
</AuthonProvider>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Hooks
|
|
83
|
+
|
|
84
|
+
#### `useAuthon()`
|
|
85
|
+
|
|
86
|
+
Returns the full auth context:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const {
|
|
90
|
+
isSignedIn, // boolean
|
|
91
|
+
isLoading, // boolean
|
|
92
|
+
user, // AuthonUser | null
|
|
93
|
+
signOut, // () => Promise<void>
|
|
94
|
+
openSignIn, // () => Promise<void>
|
|
95
|
+
openSignUp, // () => Promise<void>
|
|
96
|
+
getToken, // () => string | null
|
|
97
|
+
client, // Authon instance
|
|
98
|
+
} = useAuthon();
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### `useUser()`
|
|
102
|
+
|
|
103
|
+
Shorthand for user data:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
const { user, isLoading } = useUser();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Components
|
|
110
|
+
|
|
111
|
+
| Component | Props | Description |
|
|
112
|
+
|-----------|-------|-------------|
|
|
113
|
+
| `<SignedIn>` | `children` | Renders children only when signed in |
|
|
114
|
+
| `<SignedOut>` | `children` | Renders children only when signed out |
|
|
115
|
+
| `<UserButton>` | none | Avatar dropdown with sign-out action |
|
|
116
|
+
| `<SignIn>` | `mode?` | Opens sign-in modal or renders embedded form |
|
|
117
|
+
| `<SignUp>` | `mode?` | Opens sign-up modal or renders embedded form |
|
|
118
|
+
| `<Protect>` | `fallback?`, `condition?` | Guards content, optionally with a custom condition |
|
|
119
|
+
|
|
120
|
+
### `<Protect>` Example
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<Protect
|
|
124
|
+
fallback={<p>You need admin access.</p>}
|
|
125
|
+
condition={(user) => user.publicMetadata?.role === 'admin'}
|
|
126
|
+
>
|
|
127
|
+
<AdminPanel />
|
|
128
|
+
</Protect>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Documentation
|
|
132
|
+
|
|
133
|
+
[authon.dev/docs](https://authon.dev/docs)
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
[MIT](../../LICENSE)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AuthonProvider: () => AuthonProvider,
|
|
24
|
+
Protect: () => Protect,
|
|
25
|
+
SignIn: () => SignIn,
|
|
26
|
+
SignUp: () => SignUp,
|
|
27
|
+
SignedIn: () => SignedIn,
|
|
28
|
+
SignedOut: () => SignedOut,
|
|
29
|
+
UserButton: () => UserButton,
|
|
30
|
+
useAuthon: () => useAuthon,
|
|
31
|
+
useUser: () => useUser
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(index_exports);
|
|
34
|
+
|
|
35
|
+
// src/AuthonProvider.tsx
|
|
36
|
+
var import_react = require("react");
|
|
37
|
+
var import_js = require("@authon/js");
|
|
38
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
39
|
+
var AuthonContext = (0, import_react.createContext)(null);
|
|
40
|
+
function AuthonProvider({ publishableKey, children, config }) {
|
|
41
|
+
const [user, setUser] = (0, import_react.useState)(null);
|
|
42
|
+
const [isLoading, setIsLoading] = (0, import_react.useState)(true);
|
|
43
|
+
const clientRef = (0, import_react.useRef)(null);
|
|
44
|
+
(0, import_react.useEffect)(() => {
|
|
45
|
+
const client = new import_js.Authon(publishableKey, config);
|
|
46
|
+
clientRef.current = client;
|
|
47
|
+
client.on("signedIn", (u) => {
|
|
48
|
+
setUser(u);
|
|
49
|
+
setIsLoading(false);
|
|
50
|
+
});
|
|
51
|
+
client.on("signedOut", () => {
|
|
52
|
+
setUser(null);
|
|
53
|
+
});
|
|
54
|
+
client.on("error", () => {
|
|
55
|
+
setIsLoading(false);
|
|
56
|
+
});
|
|
57
|
+
setIsLoading(false);
|
|
58
|
+
return () => {
|
|
59
|
+
client.destroy();
|
|
60
|
+
clientRef.current = null;
|
|
61
|
+
};
|
|
62
|
+
}, [publishableKey]);
|
|
63
|
+
const signOut = (0, import_react.useCallback)(async () => {
|
|
64
|
+
await clientRef.current?.signOut();
|
|
65
|
+
setUser(null);
|
|
66
|
+
}, []);
|
|
67
|
+
const openSignIn = (0, import_react.useCallback)(async () => {
|
|
68
|
+
await clientRef.current?.openSignIn();
|
|
69
|
+
}, []);
|
|
70
|
+
const openSignUp = (0, import_react.useCallback)(async () => {
|
|
71
|
+
await clientRef.current?.openSignUp();
|
|
72
|
+
}, []);
|
|
73
|
+
const getToken = (0, import_react.useCallback)(() => {
|
|
74
|
+
return clientRef.current?.getToken() ?? null;
|
|
75
|
+
}, []);
|
|
76
|
+
const value = (0, import_react.useMemo)(
|
|
77
|
+
() => ({
|
|
78
|
+
isSignedIn: !!user,
|
|
79
|
+
isLoading,
|
|
80
|
+
user,
|
|
81
|
+
signOut,
|
|
82
|
+
openSignIn,
|
|
83
|
+
openSignUp,
|
|
84
|
+
getToken,
|
|
85
|
+
client: clientRef.current
|
|
86
|
+
}),
|
|
87
|
+
[user, isLoading, signOut, openSignIn, openSignUp, getToken]
|
|
88
|
+
);
|
|
89
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthonContext.Provider, { value, children });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/useAuthon.ts
|
|
93
|
+
var import_react2 = require("react");
|
|
94
|
+
function useAuthon() {
|
|
95
|
+
const ctx = (0, import_react2.useContext)(AuthonContext);
|
|
96
|
+
if (!ctx) {
|
|
97
|
+
throw new Error("useAuthon must be used within an <AuthonProvider>");
|
|
98
|
+
}
|
|
99
|
+
return ctx;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/useUser.ts
|
|
103
|
+
function useUser() {
|
|
104
|
+
const { user, isLoading } = useAuthon();
|
|
105
|
+
return { user, isLoading };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/SignIn.tsx
|
|
109
|
+
var import_react3 = require("react");
|
|
110
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
111
|
+
function SignIn({ mode = "popup" }) {
|
|
112
|
+
const { client } = useAuthon();
|
|
113
|
+
const containerRef = (0, import_react3.useRef)(null);
|
|
114
|
+
(0, import_react3.useEffect)(() => {
|
|
115
|
+
if (mode === "popup") {
|
|
116
|
+
client?.openSignIn();
|
|
117
|
+
}
|
|
118
|
+
}, [client, mode]);
|
|
119
|
+
if (mode === "embedded") {
|
|
120
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: containerRef, id: "authon-signin-container" });
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/SignUp.tsx
|
|
126
|
+
var import_react4 = require("react");
|
|
127
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
128
|
+
function SignUp({ mode = "popup" }) {
|
|
129
|
+
const { client } = useAuthon();
|
|
130
|
+
(0, import_react4.useEffect)(() => {
|
|
131
|
+
if (mode === "popup") {
|
|
132
|
+
client?.openSignUp();
|
|
133
|
+
}
|
|
134
|
+
}, [client, mode]);
|
|
135
|
+
if (mode === "embedded") {
|
|
136
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: "authon-signup-container" });
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/UserButton.tsx
|
|
142
|
+
var import_react5 = require("react");
|
|
143
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
144
|
+
function UserButton() {
|
|
145
|
+
const { user, signOut, openSignIn, isSignedIn } = useAuthon();
|
|
146
|
+
const [open, setOpen] = (0, import_react5.useState)(false);
|
|
147
|
+
const dropdownRef = (0, import_react5.useRef)(null);
|
|
148
|
+
const handleClickOutside = (0, import_react5.useCallback)((e) => {
|
|
149
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
150
|
+
setOpen(false);
|
|
151
|
+
}
|
|
152
|
+
}, []);
|
|
153
|
+
(0, import_react5.useEffect)(() => {
|
|
154
|
+
if (open) {
|
|
155
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
156
|
+
}
|
|
157
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
158
|
+
}, [open, handleClickOutside]);
|
|
159
|
+
if (!isSignedIn) {
|
|
160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
161
|
+
"button",
|
|
162
|
+
{
|
|
163
|
+
onClick: () => openSignIn(),
|
|
164
|
+
style: {
|
|
165
|
+
padding: "8px 16px",
|
|
166
|
+
borderRadius: "8px",
|
|
167
|
+
border: "none",
|
|
168
|
+
background: "linear-gradient(135deg, #7c3aed, #4f46e5)",
|
|
169
|
+
color: "#fff",
|
|
170
|
+
cursor: "pointer",
|
|
171
|
+
fontSize: "14px",
|
|
172
|
+
fontWeight: 600
|
|
173
|
+
},
|
|
174
|
+
children: "Sign In"
|
|
175
|
+
}
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
const initials = user?.displayName ? user.displayName.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : (user?.email?.[0] ?? "?").toUpperCase();
|
|
179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { ref: dropdownRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
181
|
+
"button",
|
|
182
|
+
{
|
|
183
|
+
onClick: () => setOpen((v) => !v),
|
|
184
|
+
style: {
|
|
185
|
+
width: "36px",
|
|
186
|
+
height: "36px",
|
|
187
|
+
borderRadius: "50%",
|
|
188
|
+
border: "2px solid #7c3aed",
|
|
189
|
+
background: user?.avatarUrl ? "transparent" : "linear-gradient(135deg, #7c3aed, #4f46e5)",
|
|
190
|
+
cursor: "pointer",
|
|
191
|
+
padding: 0,
|
|
192
|
+
overflow: "hidden",
|
|
193
|
+
display: "flex",
|
|
194
|
+
alignItems: "center",
|
|
195
|
+
justifyContent: "center",
|
|
196
|
+
color: "#fff",
|
|
197
|
+
fontSize: "13px",
|
|
198
|
+
fontWeight: 700
|
|
199
|
+
},
|
|
200
|
+
children: user?.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
201
|
+
"img",
|
|
202
|
+
{
|
|
203
|
+
src: user.avatarUrl,
|
|
204
|
+
alt: user.displayName ?? "avatar",
|
|
205
|
+
style: { width: "100%", height: "100%", objectFit: "cover" }
|
|
206
|
+
}
|
|
207
|
+
) : initials
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
211
|
+
"div",
|
|
212
|
+
{
|
|
213
|
+
style: {
|
|
214
|
+
position: "absolute",
|
|
215
|
+
right: 0,
|
|
216
|
+
top: "44px",
|
|
217
|
+
minWidth: "200px",
|
|
218
|
+
background: "#fff",
|
|
219
|
+
border: "1px solid #e5e7eb",
|
|
220
|
+
borderRadius: "12px",
|
|
221
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
|
|
222
|
+
zIndex: 9999,
|
|
223
|
+
overflow: "hidden"
|
|
224
|
+
},
|
|
225
|
+
children: [
|
|
226
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
227
|
+
"div",
|
|
228
|
+
{
|
|
229
|
+
style: {
|
|
230
|
+
padding: "12px 16px",
|
|
231
|
+
borderBottom: "1px solid #f3f4f6"
|
|
232
|
+
},
|
|
233
|
+
children: [
|
|
234
|
+
user?.displayName && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: "14px", fontWeight: 600, color: "#111827" }, children: user.displayName }),
|
|
235
|
+
user?.email && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: "12px", color: "#6b7280", marginTop: "2px" }, children: user.email })
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
),
|
|
239
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
240
|
+
"button",
|
|
241
|
+
{
|
|
242
|
+
onClick: async () => {
|
|
243
|
+
setOpen(false);
|
|
244
|
+
await signOut();
|
|
245
|
+
},
|
|
246
|
+
style: {
|
|
247
|
+
display: "block",
|
|
248
|
+
width: "100%",
|
|
249
|
+
padding: "10px 16px",
|
|
250
|
+
textAlign: "left",
|
|
251
|
+
background: "none",
|
|
252
|
+
border: "none",
|
|
253
|
+
cursor: "pointer",
|
|
254
|
+
fontSize: "14px",
|
|
255
|
+
color: "#ef4444",
|
|
256
|
+
fontWeight: 500
|
|
257
|
+
},
|
|
258
|
+
onMouseEnter: (e) => {
|
|
259
|
+
e.currentTarget.style.background = "#fef2f2";
|
|
260
|
+
},
|
|
261
|
+
onMouseLeave: (e) => {
|
|
262
|
+
e.currentTarget.style.background = "none";
|
|
263
|
+
},
|
|
264
|
+
children: "Sign out"
|
|
265
|
+
}
|
|
266
|
+
)
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
] });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/SignedIn.tsx
|
|
274
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
275
|
+
function SignedIn({ children }) {
|
|
276
|
+
const { isSignedIn, isLoading } = useAuthon();
|
|
277
|
+
if (isLoading || !isSignedIn) return null;
|
|
278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/SignedOut.tsx
|
|
282
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
283
|
+
function SignedOut({ children }) {
|
|
284
|
+
const { isSignedIn, isLoading } = useAuthon();
|
|
285
|
+
if (isLoading || isSignedIn) return null;
|
|
286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children });
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/Protect.tsx
|
|
290
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
291
|
+
function Protect({ children, fallback = null, condition }) {
|
|
292
|
+
const { isSignedIn, isLoading, user } = useAuthon();
|
|
293
|
+
if (isLoading) return null;
|
|
294
|
+
if (!isSignedIn || !user) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: fallback });
|
|
295
|
+
if (condition && !condition(user)) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: fallback });
|
|
296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children });
|
|
297
|
+
}
|
|
298
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
299
|
+
0 && (module.exports = {
|
|
300
|
+
AuthonProvider,
|
|
301
|
+
Protect,
|
|
302
|
+
SignIn,
|
|
303
|
+
SignUp,
|
|
304
|
+
SignedIn,
|
|
305
|
+
SignedOut,
|
|
306
|
+
UserButton,
|
|
307
|
+
useAuthon,
|
|
308
|
+
useUser
|
|
309
|
+
});
|
|
310
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AuthonProvider.tsx","../src/useAuthon.ts","../src/useUser.ts","../src/SignIn.tsx","../src/SignUp.tsx","../src/UserButton.tsx","../src/SignedIn.tsx","../src/SignedOut.tsx","../src/Protect.tsx"],"sourcesContent":["export { AuthonProvider } from './AuthonProvider';\nexport type { AuthonContextValue } from './AuthonProvider';\nexport { useAuthon } from './useAuthon';\nexport { useUser } from './useUser';\nexport { SignIn } from './SignIn';\nexport { SignUp } from './SignUp';\nexport { UserButton } from './UserButton';\nexport { SignedIn } from './SignedIn';\nexport { SignedOut } from './SignedOut';\nexport { Protect } from './Protect';\n","import { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type { AuthonUser } from '@authon/shared';\n\nexport interface AuthonContextValue {\n isSignedIn: boolean;\n isLoading: boolean;\n user: AuthonUser | null;\n signOut: () => Promise<void>;\n openSignIn: () => Promise<void>;\n openSignUp: () => Promise<void>;\n getToken: () => string | null;\n client: Authon | null;\n}\n\nexport const AuthonContext = createContext<AuthonContextValue | null>(null);\n\ninterface AuthonProviderProps {\n publishableKey: string;\n children: ReactNode;\n config?: Omit<AuthonConfig, 'mode'>;\n}\n\nexport function AuthonProvider({ publishableKey, children, config }: AuthonProviderProps) {\n const [user, setUser] = useState<AuthonUser | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const clientRef = useRef<Authon | null>(null);\n\n useEffect(() => {\n const client = new Authon(publishableKey, config);\n clientRef.current = client;\n\n client.on('signedIn', (u) => {\n setUser(u as AuthonUser);\n setIsLoading(false);\n });\n\n client.on('signedOut', () => {\n setUser(null);\n });\n\n client.on('error', () => {\n setIsLoading(false);\n });\n\n setIsLoading(false);\n\n return () => {\n client.destroy();\n clientRef.current = null;\n };\n }, [publishableKey]);\n\n const signOut = useCallback(async () => {\n await clientRef.current?.signOut();\n setUser(null);\n }, []);\n\n const openSignIn = useCallback(async () => {\n await clientRef.current?.openSignIn();\n }, []);\n\n const openSignUp = useCallback(async () => {\n await clientRef.current?.openSignUp();\n }, []);\n\n const getToken = useCallback(() => {\n return clientRef.current?.getToken() ?? null;\n }, []);\n\n const value = useMemo<AuthonContextValue>(\n () => ({\n isSignedIn: !!user,\n isLoading,\n user,\n signOut,\n openSignIn,\n openSignUp,\n getToken,\n client: clientRef.current,\n }),\n [user, isLoading, signOut, openSignIn, openSignUp, getToken],\n );\n\n return <AuthonContext.Provider value={value}>{children}</AuthonContext.Provider>;\n}\n","import { useContext } from 'react';\nimport { AuthonContext } from './AuthonProvider';\nimport type { AuthonContextValue } from './AuthonProvider';\n\nexport function useAuthon(): AuthonContextValue {\n const ctx = useContext(AuthonContext);\n if (!ctx) {\n throw new Error('useAuthon must be used within an <AuthonProvider>');\n }\n return ctx;\n}\n","import type { AuthonUser } from '@authon/shared';\nimport { useAuthon } from './useAuthon';\n\nexport function useUser(): { user: AuthonUser | null; isLoading: boolean } {\n const { user, isLoading } = useAuthon();\n return { user, isLoading };\n}\n","import { useEffect, useRef } from 'react';\nimport { useAuthon } from './useAuthon';\n\ninterface SignInProps {\n mode?: 'popup' | 'embedded';\n redirectUrl?: string;\n}\n\nexport function SignIn({ mode = 'popup' }: SignInProps) {\n const { client } = useAuthon();\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (mode === 'popup') {\n client?.openSignIn();\n }\n }, [client, mode]);\n\n if (mode === 'embedded') {\n return <div ref={containerRef} id=\"authon-signin-container\" />;\n }\n\n return null;\n}\n","import { useEffect } from 'react';\nimport { useAuthon } from './useAuthon';\n\ninterface SignUpProps {\n mode?: 'popup' | 'embedded';\n}\n\nexport function SignUp({ mode = 'popup' }: SignUpProps) {\n const { client } = useAuthon();\n\n useEffect(() => {\n if (mode === 'popup') {\n client?.openSignUp();\n }\n }, [client, mode]);\n\n if (mode === 'embedded') {\n return <div id=\"authon-signup-container\" />;\n }\n\n return null;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useAuthon } from './useAuthon';\n\nexport function UserButton() {\n const { user, signOut, openSignIn, isSignedIn } = useAuthon();\n const [open, setOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const handleClickOutside = useCallback((e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n }, []);\n\n useEffect(() => {\n if (open) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [open, handleClickOutside]);\n\n if (!isSignedIn) {\n return (\n <button\n onClick={() => openSignIn()}\n style={{\n padding: '8px 16px',\n borderRadius: '8px',\n border: 'none',\n background: 'linear-gradient(135deg, #7c3aed, #4f46e5)',\n color: '#fff',\n cursor: 'pointer',\n fontSize: '14px',\n fontWeight: 600,\n }}\n >\n Sign In\n </button>\n );\n }\n\n const initials = user?.displayName\n ? user.displayName\n .split(' ')\n .map((n) => n[0])\n .join('')\n .toUpperCase()\n .slice(0, 2)\n : (user?.email?.[0] ?? '?').toUpperCase();\n\n return (\n <div ref={dropdownRef} style={{ position: 'relative', display: 'inline-block' }}>\n <button\n onClick={() => setOpen((v) => !v)}\n style={{\n width: '36px',\n height: '36px',\n borderRadius: '50%',\n border: '2px solid #7c3aed',\n background: user?.avatarUrl ? 'transparent' : 'linear-gradient(135deg, #7c3aed, #4f46e5)',\n cursor: 'pointer',\n padding: 0,\n overflow: 'hidden',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#fff',\n fontSize: '13px',\n fontWeight: 700,\n }}\n >\n {user?.avatarUrl ? (\n <img\n src={user.avatarUrl}\n alt={user.displayName ?? 'avatar'}\n style={{ width: '100%', height: '100%', objectFit: 'cover' }}\n />\n ) : (\n initials\n )}\n </button>\n\n {open && (\n <div\n style={{\n position: 'absolute',\n right: 0,\n top: '44px',\n minWidth: '200px',\n background: '#fff',\n border: '1px solid #e5e7eb',\n borderRadius: '12px',\n boxShadow: '0 8px 24px rgba(0,0,0,0.12)',\n zIndex: 9999,\n overflow: 'hidden',\n }}\n >\n <div\n style={{\n padding: '12px 16px',\n borderBottom: '1px solid #f3f4f6',\n }}\n >\n {user?.displayName && (\n <div style={{ fontSize: '14px', fontWeight: 600, color: '#111827' }}>\n {user.displayName}\n </div>\n )}\n {user?.email && (\n <div style={{ fontSize: '12px', color: '#6b7280', marginTop: '2px' }}>\n {user.email}\n </div>\n )}\n </div>\n\n <button\n onClick={async () => {\n setOpen(false);\n await signOut();\n }}\n style={{\n display: 'block',\n width: '100%',\n padding: '10px 16px',\n textAlign: 'left',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n fontSize: '14px',\n color: '#ef4444',\n fontWeight: 500,\n }}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLButtonElement).style.background = '#fef2f2';\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLButtonElement).style.background = 'none';\n }}\n >\n Sign out\n </button>\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport { useAuthon } from './useAuthon';\n\ninterface SignedInProps {\n children: ReactNode;\n}\n\nexport function SignedIn({ children }: SignedInProps) {\n const { isSignedIn, isLoading } = useAuthon();\n if (isLoading || !isSignedIn) return null;\n return <>{children}</>;\n}\n","import type { ReactNode } from 'react';\nimport { useAuthon } from './useAuthon';\n\ninterface SignedOutProps {\n children: ReactNode;\n}\n\nexport function SignedOut({ children }: SignedOutProps) {\n const { isSignedIn, isLoading } = useAuthon();\n if (isLoading || isSignedIn) return null;\n return <>{children}</>;\n}\n","import type { ReactNode } from 'react';\nimport type { AuthonUser } from '@authon/shared';\nimport { useAuthon } from './useAuthon';\n\ninterface ProtectProps {\n children: ReactNode;\n fallback?: ReactNode;\n condition?: (user: AuthonUser) => boolean;\n}\n\nexport function Protect({ children, fallback = null, condition }: ProtectProps) {\n const { isSignedIn, isLoading, user } = useAuthon();\n\n if (isLoading) return null;\n if (!isSignedIn || !user) return <>{fallback}</>;\n if (condition && !condition(user)) return <>{fallback}</>;\n\n return <>{children}</>;\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { Authon, AuthonConfig } from '@authon/js';
|
|
4
|
+
import { AuthonUser } from '@authon/shared';
|
|
5
|
+
|
|
6
|
+
interface AuthonContextValue {
|
|
7
|
+
isSignedIn: boolean;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
user: AuthonUser | null;
|
|
10
|
+
signOut: () => Promise<void>;
|
|
11
|
+
openSignIn: () => Promise<void>;
|
|
12
|
+
openSignUp: () => Promise<void>;
|
|
13
|
+
getToken: () => string | null;
|
|
14
|
+
client: Authon | null;
|
|
15
|
+
}
|
|
16
|
+
interface AuthonProviderProps {
|
|
17
|
+
publishableKey: string;
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
config?: Omit<AuthonConfig, 'mode'>;
|
|
20
|
+
}
|
|
21
|
+
declare function AuthonProvider({ publishableKey, children, config }: AuthonProviderProps): react_jsx_runtime.JSX.Element;
|
|
22
|
+
|
|
23
|
+
declare function useAuthon(): AuthonContextValue;
|
|
24
|
+
|
|
25
|
+
declare function useUser(): {
|
|
26
|
+
user: AuthonUser | null;
|
|
27
|
+
isLoading: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
interface SignInProps {
|
|
31
|
+
mode?: 'popup' | 'embedded';
|
|
32
|
+
redirectUrl?: string;
|
|
33
|
+
}
|
|
34
|
+
declare function SignIn({ mode }: SignInProps): react_jsx_runtime.JSX.Element | null;
|
|
35
|
+
|
|
36
|
+
interface SignUpProps {
|
|
37
|
+
mode?: 'popup' | 'embedded';
|
|
38
|
+
}
|
|
39
|
+
declare function SignUp({ mode }: SignUpProps): react_jsx_runtime.JSX.Element | null;
|
|
40
|
+
|
|
41
|
+
declare function UserButton(): react_jsx_runtime.JSX.Element;
|
|
42
|
+
|
|
43
|
+
interface SignedInProps {
|
|
44
|
+
children: ReactNode;
|
|
45
|
+
}
|
|
46
|
+
declare function SignedIn({ children }: SignedInProps): react_jsx_runtime.JSX.Element | null;
|
|
47
|
+
|
|
48
|
+
interface SignedOutProps {
|
|
49
|
+
children: ReactNode;
|
|
50
|
+
}
|
|
51
|
+
declare function SignedOut({ children }: SignedOutProps): react_jsx_runtime.JSX.Element | null;
|
|
52
|
+
|
|
53
|
+
interface ProtectProps {
|
|
54
|
+
children: ReactNode;
|
|
55
|
+
fallback?: ReactNode;
|
|
56
|
+
condition?: (user: AuthonUser) => boolean;
|
|
57
|
+
}
|
|
58
|
+
declare function Protect({ children, fallback, condition }: ProtectProps): react_jsx_runtime.JSX.Element | null;
|
|
59
|
+
|
|
60
|
+
export { type AuthonContextValue, AuthonProvider, Protect, SignIn, SignUp, SignedIn, SignedOut, UserButton, useAuthon, useUser };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { Authon, AuthonConfig } from '@authon/js';
|
|
4
|
+
import { AuthonUser } from '@authon/shared';
|
|
5
|
+
|
|
6
|
+
interface AuthonContextValue {
|
|
7
|
+
isSignedIn: boolean;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
user: AuthonUser | null;
|
|
10
|
+
signOut: () => Promise<void>;
|
|
11
|
+
openSignIn: () => Promise<void>;
|
|
12
|
+
openSignUp: () => Promise<void>;
|
|
13
|
+
getToken: () => string | null;
|
|
14
|
+
client: Authon | null;
|
|
15
|
+
}
|
|
16
|
+
interface AuthonProviderProps {
|
|
17
|
+
publishableKey: string;
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
config?: Omit<AuthonConfig, 'mode'>;
|
|
20
|
+
}
|
|
21
|
+
declare function AuthonProvider({ publishableKey, children, config }: AuthonProviderProps): react_jsx_runtime.JSX.Element;
|
|
22
|
+
|
|
23
|
+
declare function useAuthon(): AuthonContextValue;
|
|
24
|
+
|
|
25
|
+
declare function useUser(): {
|
|
26
|
+
user: AuthonUser | null;
|
|
27
|
+
isLoading: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
interface SignInProps {
|
|
31
|
+
mode?: 'popup' | 'embedded';
|
|
32
|
+
redirectUrl?: string;
|
|
33
|
+
}
|
|
34
|
+
declare function SignIn({ mode }: SignInProps): react_jsx_runtime.JSX.Element | null;
|
|
35
|
+
|
|
36
|
+
interface SignUpProps {
|
|
37
|
+
mode?: 'popup' | 'embedded';
|
|
38
|
+
}
|
|
39
|
+
declare function SignUp({ mode }: SignUpProps): react_jsx_runtime.JSX.Element | null;
|
|
40
|
+
|
|
41
|
+
declare function UserButton(): react_jsx_runtime.JSX.Element;
|
|
42
|
+
|
|
43
|
+
interface SignedInProps {
|
|
44
|
+
children: ReactNode;
|
|
45
|
+
}
|
|
46
|
+
declare function SignedIn({ children }: SignedInProps): react_jsx_runtime.JSX.Element | null;
|
|
47
|
+
|
|
48
|
+
interface SignedOutProps {
|
|
49
|
+
children: ReactNode;
|
|
50
|
+
}
|
|
51
|
+
declare function SignedOut({ children }: SignedOutProps): react_jsx_runtime.JSX.Element | null;
|
|
52
|
+
|
|
53
|
+
interface ProtectProps {
|
|
54
|
+
children: ReactNode;
|
|
55
|
+
fallback?: ReactNode;
|
|
56
|
+
condition?: (user: AuthonUser) => boolean;
|
|
57
|
+
}
|
|
58
|
+
declare function Protect({ children, fallback, condition }: ProtectProps): react_jsx_runtime.JSX.Element | null;
|
|
59
|
+
|
|
60
|
+
export { type AuthonContextValue, AuthonProvider, Protect, SignIn, SignUp, SignedIn, SignedOut, UserButton, useAuthon, useUser };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
// src/AuthonProvider.tsx
|
|
2
|
+
import { createContext, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { Authon } from "@authon/js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
var AuthonContext = createContext(null);
|
|
6
|
+
function AuthonProvider({ publishableKey, children, config }) {
|
|
7
|
+
const [user, setUser] = useState(null);
|
|
8
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
9
|
+
const clientRef = useRef(null);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const client = new Authon(publishableKey, config);
|
|
12
|
+
clientRef.current = client;
|
|
13
|
+
client.on("signedIn", (u) => {
|
|
14
|
+
setUser(u);
|
|
15
|
+
setIsLoading(false);
|
|
16
|
+
});
|
|
17
|
+
client.on("signedOut", () => {
|
|
18
|
+
setUser(null);
|
|
19
|
+
});
|
|
20
|
+
client.on("error", () => {
|
|
21
|
+
setIsLoading(false);
|
|
22
|
+
});
|
|
23
|
+
setIsLoading(false);
|
|
24
|
+
return () => {
|
|
25
|
+
client.destroy();
|
|
26
|
+
clientRef.current = null;
|
|
27
|
+
};
|
|
28
|
+
}, [publishableKey]);
|
|
29
|
+
const signOut = useCallback(async () => {
|
|
30
|
+
await clientRef.current?.signOut();
|
|
31
|
+
setUser(null);
|
|
32
|
+
}, []);
|
|
33
|
+
const openSignIn = useCallback(async () => {
|
|
34
|
+
await clientRef.current?.openSignIn();
|
|
35
|
+
}, []);
|
|
36
|
+
const openSignUp = useCallback(async () => {
|
|
37
|
+
await clientRef.current?.openSignUp();
|
|
38
|
+
}, []);
|
|
39
|
+
const getToken = useCallback(() => {
|
|
40
|
+
return clientRef.current?.getToken() ?? null;
|
|
41
|
+
}, []);
|
|
42
|
+
const value = useMemo(
|
|
43
|
+
() => ({
|
|
44
|
+
isSignedIn: !!user,
|
|
45
|
+
isLoading,
|
|
46
|
+
user,
|
|
47
|
+
signOut,
|
|
48
|
+
openSignIn,
|
|
49
|
+
openSignUp,
|
|
50
|
+
getToken,
|
|
51
|
+
client: clientRef.current
|
|
52
|
+
}),
|
|
53
|
+
[user, isLoading, signOut, openSignIn, openSignUp, getToken]
|
|
54
|
+
);
|
|
55
|
+
return /* @__PURE__ */ jsx(AuthonContext.Provider, { value, children });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/useAuthon.ts
|
|
59
|
+
import { useContext } from "react";
|
|
60
|
+
function useAuthon() {
|
|
61
|
+
const ctx = useContext(AuthonContext);
|
|
62
|
+
if (!ctx) {
|
|
63
|
+
throw new Error("useAuthon must be used within an <AuthonProvider>");
|
|
64
|
+
}
|
|
65
|
+
return ctx;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/useUser.ts
|
|
69
|
+
function useUser() {
|
|
70
|
+
const { user, isLoading } = useAuthon();
|
|
71
|
+
return { user, isLoading };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/SignIn.tsx
|
|
75
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
76
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
77
|
+
function SignIn({ mode = "popup" }) {
|
|
78
|
+
const { client } = useAuthon();
|
|
79
|
+
const containerRef = useRef2(null);
|
|
80
|
+
useEffect2(() => {
|
|
81
|
+
if (mode === "popup") {
|
|
82
|
+
client?.openSignIn();
|
|
83
|
+
}
|
|
84
|
+
}, [client, mode]);
|
|
85
|
+
if (mode === "embedded") {
|
|
86
|
+
return /* @__PURE__ */ jsx2("div", { ref: containerRef, id: "authon-signin-container" });
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/SignUp.tsx
|
|
92
|
+
import { useEffect as useEffect3 } from "react";
|
|
93
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
94
|
+
function SignUp({ mode = "popup" }) {
|
|
95
|
+
const { client } = useAuthon();
|
|
96
|
+
useEffect3(() => {
|
|
97
|
+
if (mode === "popup") {
|
|
98
|
+
client?.openSignUp();
|
|
99
|
+
}
|
|
100
|
+
}, [client, mode]);
|
|
101
|
+
if (mode === "embedded") {
|
|
102
|
+
return /* @__PURE__ */ jsx3("div", { id: "authon-signup-container" });
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/UserButton.tsx
|
|
108
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef3, useState as useState2 } from "react";
|
|
109
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
110
|
+
function UserButton() {
|
|
111
|
+
const { user, signOut, openSignIn, isSignedIn } = useAuthon();
|
|
112
|
+
const [open, setOpen] = useState2(false);
|
|
113
|
+
const dropdownRef = useRef3(null);
|
|
114
|
+
const handleClickOutside = useCallback2((e) => {
|
|
115
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
116
|
+
setOpen(false);
|
|
117
|
+
}
|
|
118
|
+
}, []);
|
|
119
|
+
useEffect4(() => {
|
|
120
|
+
if (open) {
|
|
121
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
122
|
+
}
|
|
123
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
124
|
+
}, [open, handleClickOutside]);
|
|
125
|
+
if (!isSignedIn) {
|
|
126
|
+
return /* @__PURE__ */ jsx4(
|
|
127
|
+
"button",
|
|
128
|
+
{
|
|
129
|
+
onClick: () => openSignIn(),
|
|
130
|
+
style: {
|
|
131
|
+
padding: "8px 16px",
|
|
132
|
+
borderRadius: "8px",
|
|
133
|
+
border: "none",
|
|
134
|
+
background: "linear-gradient(135deg, #7c3aed, #4f46e5)",
|
|
135
|
+
color: "#fff",
|
|
136
|
+
cursor: "pointer",
|
|
137
|
+
fontSize: "14px",
|
|
138
|
+
fontWeight: 600
|
|
139
|
+
},
|
|
140
|
+
children: "Sign In"
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
const initials = user?.displayName ? user.displayName.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : (user?.email?.[0] ?? "?").toUpperCase();
|
|
145
|
+
return /* @__PURE__ */ jsxs("div", { ref: dropdownRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
146
|
+
/* @__PURE__ */ jsx4(
|
|
147
|
+
"button",
|
|
148
|
+
{
|
|
149
|
+
onClick: () => setOpen((v) => !v),
|
|
150
|
+
style: {
|
|
151
|
+
width: "36px",
|
|
152
|
+
height: "36px",
|
|
153
|
+
borderRadius: "50%",
|
|
154
|
+
border: "2px solid #7c3aed",
|
|
155
|
+
background: user?.avatarUrl ? "transparent" : "linear-gradient(135deg, #7c3aed, #4f46e5)",
|
|
156
|
+
cursor: "pointer",
|
|
157
|
+
padding: 0,
|
|
158
|
+
overflow: "hidden",
|
|
159
|
+
display: "flex",
|
|
160
|
+
alignItems: "center",
|
|
161
|
+
justifyContent: "center",
|
|
162
|
+
color: "#fff",
|
|
163
|
+
fontSize: "13px",
|
|
164
|
+
fontWeight: 700
|
|
165
|
+
},
|
|
166
|
+
children: user?.avatarUrl ? /* @__PURE__ */ jsx4(
|
|
167
|
+
"img",
|
|
168
|
+
{
|
|
169
|
+
src: user.avatarUrl,
|
|
170
|
+
alt: user.displayName ?? "avatar",
|
|
171
|
+
style: { width: "100%", height: "100%", objectFit: "cover" }
|
|
172
|
+
}
|
|
173
|
+
) : initials
|
|
174
|
+
}
|
|
175
|
+
),
|
|
176
|
+
open && /* @__PURE__ */ jsxs(
|
|
177
|
+
"div",
|
|
178
|
+
{
|
|
179
|
+
style: {
|
|
180
|
+
position: "absolute",
|
|
181
|
+
right: 0,
|
|
182
|
+
top: "44px",
|
|
183
|
+
minWidth: "200px",
|
|
184
|
+
background: "#fff",
|
|
185
|
+
border: "1px solid #e5e7eb",
|
|
186
|
+
borderRadius: "12px",
|
|
187
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
|
|
188
|
+
zIndex: 9999,
|
|
189
|
+
overflow: "hidden"
|
|
190
|
+
},
|
|
191
|
+
children: [
|
|
192
|
+
/* @__PURE__ */ jsxs(
|
|
193
|
+
"div",
|
|
194
|
+
{
|
|
195
|
+
style: {
|
|
196
|
+
padding: "12px 16px",
|
|
197
|
+
borderBottom: "1px solid #f3f4f6"
|
|
198
|
+
},
|
|
199
|
+
children: [
|
|
200
|
+
user?.displayName && /* @__PURE__ */ jsx4("div", { style: { fontSize: "14px", fontWeight: 600, color: "#111827" }, children: user.displayName }),
|
|
201
|
+
user?.email && /* @__PURE__ */ jsx4("div", { style: { fontSize: "12px", color: "#6b7280", marginTop: "2px" }, children: user.email })
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
),
|
|
205
|
+
/* @__PURE__ */ jsx4(
|
|
206
|
+
"button",
|
|
207
|
+
{
|
|
208
|
+
onClick: async () => {
|
|
209
|
+
setOpen(false);
|
|
210
|
+
await signOut();
|
|
211
|
+
},
|
|
212
|
+
style: {
|
|
213
|
+
display: "block",
|
|
214
|
+
width: "100%",
|
|
215
|
+
padding: "10px 16px",
|
|
216
|
+
textAlign: "left",
|
|
217
|
+
background: "none",
|
|
218
|
+
border: "none",
|
|
219
|
+
cursor: "pointer",
|
|
220
|
+
fontSize: "14px",
|
|
221
|
+
color: "#ef4444",
|
|
222
|
+
fontWeight: 500
|
|
223
|
+
},
|
|
224
|
+
onMouseEnter: (e) => {
|
|
225
|
+
e.currentTarget.style.background = "#fef2f2";
|
|
226
|
+
},
|
|
227
|
+
onMouseLeave: (e) => {
|
|
228
|
+
e.currentTarget.style.background = "none";
|
|
229
|
+
},
|
|
230
|
+
children: "Sign out"
|
|
231
|
+
}
|
|
232
|
+
)
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
)
|
|
236
|
+
] });
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/SignedIn.tsx
|
|
240
|
+
import { Fragment, jsx as jsx5 } from "react/jsx-runtime";
|
|
241
|
+
function SignedIn({ children }) {
|
|
242
|
+
const { isSignedIn, isLoading } = useAuthon();
|
|
243
|
+
if (isLoading || !isSignedIn) return null;
|
|
244
|
+
return /* @__PURE__ */ jsx5(Fragment, { children });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/SignedOut.tsx
|
|
248
|
+
import { Fragment as Fragment2, jsx as jsx6 } from "react/jsx-runtime";
|
|
249
|
+
function SignedOut({ children }) {
|
|
250
|
+
const { isSignedIn, isLoading } = useAuthon();
|
|
251
|
+
if (isLoading || isSignedIn) return null;
|
|
252
|
+
return /* @__PURE__ */ jsx6(Fragment2, { children });
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/Protect.tsx
|
|
256
|
+
import { Fragment as Fragment3, jsx as jsx7 } from "react/jsx-runtime";
|
|
257
|
+
function Protect({ children, fallback = null, condition }) {
|
|
258
|
+
const { isSignedIn, isLoading, user } = useAuthon();
|
|
259
|
+
if (isLoading) return null;
|
|
260
|
+
if (!isSignedIn || !user) return /* @__PURE__ */ jsx7(Fragment3, { children: fallback });
|
|
261
|
+
if (condition && !condition(user)) return /* @__PURE__ */ jsx7(Fragment3, { children: fallback });
|
|
262
|
+
return /* @__PURE__ */ jsx7(Fragment3, { children });
|
|
263
|
+
}
|
|
264
|
+
export {
|
|
265
|
+
AuthonProvider,
|
|
266
|
+
Protect,
|
|
267
|
+
SignIn,
|
|
268
|
+
SignUp,
|
|
269
|
+
SignedIn,
|
|
270
|
+
SignedOut,
|
|
271
|
+
UserButton,
|
|
272
|
+
useAuthon,
|
|
273
|
+
useUser
|
|
274
|
+
};
|
|
275
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/AuthonProvider.tsx","../src/useAuthon.ts","../src/useUser.ts","../src/SignIn.tsx","../src/SignUp.tsx","../src/UserButton.tsx","../src/SignedIn.tsx","../src/SignedOut.tsx","../src/Protect.tsx"],"sourcesContent":["import { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type { AuthonUser } from '@authon/shared';\n\nexport interface AuthonContextValue {\n isSignedIn: boolean;\n isLoading: boolean;\n user: AuthonUser | null;\n signOut: () => Promise<void>;\n openSignIn: () => Promise<void>;\n openSignUp: () => Promise<void>;\n getToken: () => string | null;\n client: Authon | null;\n}\n\nexport const AuthonContext = createContext<AuthonContextValue | null>(null);\n\ninterface AuthonProviderProps {\n publishableKey: string;\n children: ReactNode;\n config?: Omit<AuthonConfig, 'mode'>;\n}\n\nexport function AuthonProvider({ publishableKey, children, config }: AuthonProviderProps) {\n const [user, setUser] = useState<AuthonUser | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const clientRef = useRef<Authon | null>(null);\n\n useEffect(() => {\n const client = new Authon(publishableKey, config);\n clientRef.current = client;\n\n client.on('signedIn', (u) => {\n setUser(u as AuthonUser);\n setIsLoading(false);\n });\n\n client.on('signedOut', () => {\n setUser(null);\n });\n\n client.on('error', () => {\n setIsLoading(false);\n });\n\n setIsLoading(false);\n\n return () => {\n client.destroy();\n clientRef.current = null;\n };\n }, [publishableKey]);\n\n const signOut = useCallback(async () => {\n await clientRef.current?.signOut();\n setUser(null);\n }, []);\n\n const openSignIn = useCallback(async () => {\n await clientRef.current?.openSignIn();\n }, []);\n\n const openSignUp = useCallback(async () => {\n await clientRef.current?.openSignUp();\n }, []);\n\n const getToken = useCallback(() => {\n return clientRef.current?.getToken() ?? null;\n }, []);\n\n const value = useMemo<AuthonContextValue>(\n () => ({\n isSignedIn: !!user,\n isLoading,\n user,\n signOut,\n openSignIn,\n openSignUp,\n getToken,\n client: clientRef.current,\n }),\n [user, isLoading, signOut, openSignIn, openSignUp, getToken],\n );\n\n return <AuthonContext.Provider value={value}>{children}</AuthonContext.Provider>;\n}\n","import { useContext } from 'react';\nimport { AuthonContext } from './AuthonProvider';\nimport type { AuthonContextValue } from './AuthonProvider';\n\nexport function useAuthon(): AuthonContextValue {\n const ctx = useContext(AuthonContext);\n if (!ctx) {\n throw new Error('useAuthon must be used within an <AuthonProvider>');\n }\n return ctx;\n}\n","import type { AuthonUser } from '@authon/shared';\nimport { useAuthon } from './useAuthon';\n\nexport function useUser(): { user: AuthonUser | null; isLoading: boolean } {\n const { user, isLoading } = useAuthon();\n return { user, isLoading };\n}\n","import { useEffect, useRef } from 'react';\nimport { useAuthon } from './useAuthon';\n\ninterface SignInProps {\n mode?: 'popup' | 'embedded';\n redirectUrl?: string;\n}\n\nexport function SignIn({ mode = 'popup' }: SignInProps) {\n const { client } = useAuthon();\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (mode === 'popup') {\n client?.openSignIn();\n }\n }, [client, mode]);\n\n if (mode === 'embedded') {\n return <div ref={containerRef} id=\"authon-signin-container\" />;\n }\n\n return null;\n}\n","import { useEffect } from 'react';\nimport { useAuthon } from './useAuthon';\n\ninterface SignUpProps {\n mode?: 'popup' | 'embedded';\n}\n\nexport function SignUp({ mode = 'popup' }: SignUpProps) {\n const { client } = useAuthon();\n\n useEffect(() => {\n if (mode === 'popup') {\n client?.openSignUp();\n }\n }, [client, mode]);\n\n if (mode === 'embedded') {\n return <div id=\"authon-signup-container\" />;\n }\n\n return null;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useAuthon } from './useAuthon';\n\nexport function UserButton() {\n const { user, signOut, openSignIn, isSignedIn } = useAuthon();\n const [open, setOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const handleClickOutside = useCallback((e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n }, []);\n\n useEffect(() => {\n if (open) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [open, handleClickOutside]);\n\n if (!isSignedIn) {\n return (\n <button\n onClick={() => openSignIn()}\n style={{\n padding: '8px 16px',\n borderRadius: '8px',\n border: 'none',\n background: 'linear-gradient(135deg, #7c3aed, #4f46e5)',\n color: '#fff',\n cursor: 'pointer',\n fontSize: '14px',\n fontWeight: 600,\n }}\n >\n Sign In\n </button>\n );\n }\n\n const initials = user?.displayName\n ? user.displayName\n .split(' ')\n .map((n) => n[0])\n .join('')\n .toUpperCase()\n .slice(0, 2)\n : (user?.email?.[0] ?? '?').toUpperCase();\n\n return (\n <div ref={dropdownRef} style={{ position: 'relative', display: 'inline-block' }}>\n <button\n onClick={() => setOpen((v) => !v)}\n style={{\n width: '36px',\n height: '36px',\n borderRadius: '50%',\n border: '2px solid #7c3aed',\n background: user?.avatarUrl ? 'transparent' : 'linear-gradient(135deg, #7c3aed, #4f46e5)',\n cursor: 'pointer',\n padding: 0,\n overflow: 'hidden',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#fff',\n fontSize: '13px',\n fontWeight: 700,\n }}\n >\n {user?.avatarUrl ? (\n <img\n src={user.avatarUrl}\n alt={user.displayName ?? 'avatar'}\n style={{ width: '100%', height: '100%', objectFit: 'cover' }}\n />\n ) : (\n initials\n )}\n </button>\n\n {open && (\n <div\n style={{\n position: 'absolute',\n right: 0,\n top: '44px',\n minWidth: '200px',\n background: '#fff',\n border: '1px solid #e5e7eb',\n borderRadius: '12px',\n boxShadow: '0 8px 24px rgba(0,0,0,0.12)',\n zIndex: 9999,\n overflow: 'hidden',\n }}\n >\n <div\n style={{\n padding: '12px 16px',\n borderBottom: '1px solid #f3f4f6',\n }}\n >\n {user?.displayName && (\n <div style={{ fontSize: '14px', fontWeight: 600, color: '#111827' }}>\n {user.displayName}\n </div>\n )}\n {user?.email && (\n <div style={{ fontSize: '12px', color: '#6b7280', marginTop: '2px' }}>\n {user.email}\n </div>\n )}\n </div>\n\n <button\n onClick={async () => {\n setOpen(false);\n await signOut();\n }}\n style={{\n display: 'block',\n width: '100%',\n padding: '10px 16px',\n textAlign: 'left',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n fontSize: '14px',\n color: '#ef4444',\n fontWeight: 500,\n }}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLButtonElement).style.background = '#fef2f2';\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLButtonElement).style.background = 'none';\n }}\n >\n Sign out\n </button>\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport { useAuthon } from './useAuthon';\n\ninterface SignedInProps {\n children: ReactNode;\n}\n\nexport function SignedIn({ children }: SignedInProps) {\n const { isSignedIn, isLoading } = useAuthon();\n if (isLoading || !isSignedIn) return null;\n return <>{children}</>;\n}\n","import type { ReactNode } from 'react';\nimport { useAuthon } from './useAuthon';\n\ninterface SignedOutProps {\n children: ReactNode;\n}\n\nexport function SignedOut({ children }: SignedOutProps) {\n const { isSignedIn, isLoading } = useAuthon();\n if (isLoading || isSignedIn) return null;\n return <>{children}</>;\n}\n","import type { ReactNode } from 'react';\nimport type { AuthonUser } from '@authon/shared';\nimport { useAuthon } from './useAuthon';\n\ninterface ProtectProps {\n children: ReactNode;\n fallback?: ReactNode;\n condition?: (user: AuthonUser) => boolean;\n}\n\nexport function Protect({ children, fallback = null, condition }: ProtectProps) {\n const { isSignedIn, isLoading, user } = useAuthon();\n\n if (isLoading) return null;\n if (!isSignedIn || !user) return <>{fallback}</>;\n if (condition && !condition(user)) return <>{fallback}</>;\n\n return <>{children}</>;\n}\n"],"mappings":"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","names":["useEffect","useRef","jsx","useRef","useEffect","useEffect","jsx","useEffect","useCallback","useEffect","useRef","useState","jsx","useState","useRef","useCallback","useEffect","jsx","Fragment","jsx","Fragment","jsx"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@authon/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Authon React SDK — Provider, hooks, and components for React apps",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": ["dist"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"dev": "tsup --watch"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/mikusnuz/authon-sdk.git",
|
|
25
|
+
"directory": "packages/react"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/mikusnuz/authon-sdk/tree/main/packages/react",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"keywords": ["authon", "auth", "authentication", "react", "hooks", "sdk"],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@authon/js": "workspace:*",
|
|
34
|
+
"@authon/shared": "workspace:*"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
38
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/react": "^19.0.0",
|
|
42
|
+
"react": "^19.0.0",
|
|
43
|
+
"tsup": "^8.0.0",
|
|
44
|
+
"typescript": "^5.9.3"
|
|
45
|
+
}
|
|
46
|
+
}
|