@authon/react-native 0.1.22 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +407 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +137 -44
- package/dist/index.d.ts +137 -44
- package/dist/index.js +399 -26
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -23,6 +33,9 @@ __export(index_exports, {
|
|
|
23
33
|
AuthonContext: () => AuthonContext,
|
|
24
34
|
AuthonMobileClient: () => AuthonMobileClient,
|
|
25
35
|
AuthonProvider: () => AuthonProvider,
|
|
36
|
+
ProviderIcon: () => ProviderIcon,
|
|
37
|
+
SocialButton: () => SocialButton,
|
|
38
|
+
SocialButtons: () => SocialButtons,
|
|
26
39
|
useAuthon: () => useAuthon,
|
|
27
40
|
useUser: () => useUser
|
|
28
41
|
});
|
|
@@ -38,7 +51,14 @@ var AuthonMobileClient = class {
|
|
|
38
51
|
apiUrl;
|
|
39
52
|
publishableKey;
|
|
40
53
|
tokens = null;
|
|
54
|
+
user = null;
|
|
41
55
|
storage = null;
|
|
56
|
+
refreshTimer = null;
|
|
57
|
+
listeners = /* @__PURE__ */ new Map();
|
|
58
|
+
// Cached provider/branding data
|
|
59
|
+
_providers = [];
|
|
60
|
+
_branding = null;
|
|
61
|
+
_initialized = false;
|
|
42
62
|
constructor(config) {
|
|
43
63
|
this.publishableKey = config.publishableKey;
|
|
44
64
|
this.apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\/$/, "");
|
|
@@ -46,6 +66,7 @@ var AuthonMobileClient = class {
|
|
|
46
66
|
setStorage(storage) {
|
|
47
67
|
this.storage = storage;
|
|
48
68
|
}
|
|
69
|
+
// ── Initialization ──
|
|
49
70
|
async initialize() {
|
|
50
71
|
if (!this.storage) return null;
|
|
51
72
|
const stored = await this.storage.getItem(STORAGE_KEY);
|
|
@@ -54,6 +75,7 @@ var AuthonMobileClient = class {
|
|
|
54
75
|
const tokens = JSON.parse(stored);
|
|
55
76
|
if (tokens.expiresAt > Date.now()) {
|
|
56
77
|
this.tokens = tokens;
|
|
78
|
+
this.scheduleRefresh(tokens.expiresAt);
|
|
57
79
|
return tokens;
|
|
58
80
|
}
|
|
59
81
|
return await this.refreshToken(tokens.refreshToken);
|
|
@@ -62,17 +84,39 @@ var AuthonMobileClient = class {
|
|
|
62
84
|
return null;
|
|
63
85
|
}
|
|
64
86
|
}
|
|
87
|
+
/** Fetch providers + branding from API (lazy, cached) */
|
|
88
|
+
async ensureInitialized() {
|
|
89
|
+
if (this._initialized) return;
|
|
90
|
+
try {
|
|
91
|
+
const [branding, providersRes] = await Promise.all([
|
|
92
|
+
this.request("GET", "/v1/auth/branding"),
|
|
93
|
+
this.request("GET", "/v1/auth/providers")
|
|
94
|
+
]);
|
|
95
|
+
this._branding = branding;
|
|
96
|
+
this._providers = providersRes.providers;
|
|
97
|
+
this._initialized = true;
|
|
98
|
+
} catch (err) {
|
|
99
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// ── Auth ──
|
|
65
103
|
async signIn(params) {
|
|
66
104
|
const res = await this.request("POST", "/v1/auth/signin", params);
|
|
67
105
|
this.tokens = this.toTokenPair(res);
|
|
106
|
+
this.user = res.user;
|
|
68
107
|
await this.persistTokens();
|
|
69
|
-
|
|
108
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
109
|
+
this.emit("signedIn", res.user);
|
|
110
|
+
return { tokens: this.tokens, user: res.user };
|
|
70
111
|
}
|
|
71
112
|
async signUp(params) {
|
|
72
113
|
const res = await this.request("POST", "/v1/auth/signup", params);
|
|
73
114
|
this.tokens = this.toTokenPair(res);
|
|
115
|
+
this.user = res.user;
|
|
74
116
|
await this.persistTokens();
|
|
75
|
-
|
|
117
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
118
|
+
this.emit("signedIn", res.user);
|
|
119
|
+
return { tokens: this.tokens, user: res.user };
|
|
76
120
|
}
|
|
77
121
|
async signOut() {
|
|
78
122
|
if (this.tokens) {
|
|
@@ -81,19 +125,23 @@ var AuthonMobileClient = class {
|
|
|
81
125
|
} catch {
|
|
82
126
|
}
|
|
83
127
|
}
|
|
84
|
-
this.
|
|
85
|
-
|
|
86
|
-
await this.storage.removeItem(STORAGE_KEY);
|
|
87
|
-
}
|
|
128
|
+
this.clearSession();
|
|
129
|
+
this.emit("signedOut");
|
|
88
130
|
}
|
|
89
131
|
async getUser() {
|
|
90
132
|
if (!this.tokens) return null;
|
|
91
133
|
try {
|
|
92
|
-
|
|
134
|
+
const user = await this.request("GET", "/v1/auth/me");
|
|
135
|
+
this.user = user;
|
|
136
|
+
return user;
|
|
93
137
|
} catch {
|
|
94
138
|
return null;
|
|
95
139
|
}
|
|
96
140
|
}
|
|
141
|
+
getCachedUser() {
|
|
142
|
+
return this.user;
|
|
143
|
+
}
|
|
144
|
+
// ── Token management ──
|
|
97
145
|
async refreshToken(refreshToken) {
|
|
98
146
|
const token = refreshToken || this.tokens?.refreshToken;
|
|
99
147
|
if (!token) return null;
|
|
@@ -107,13 +155,15 @@ var AuthonMobileClient = class {
|
|
|
107
155
|
body: JSON.stringify({ refreshToken: token })
|
|
108
156
|
});
|
|
109
157
|
if (!res.ok) {
|
|
110
|
-
this.
|
|
111
|
-
if (this.storage) await this.storage.removeItem(STORAGE_KEY);
|
|
158
|
+
this.clearSession();
|
|
112
159
|
return null;
|
|
113
160
|
}
|
|
114
161
|
const data = await res.json();
|
|
115
162
|
this.tokens = this.toTokenPair(data);
|
|
163
|
+
this.user = data.user;
|
|
116
164
|
await this.persistTokens();
|
|
165
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
166
|
+
this.emit("tokenRefreshed");
|
|
117
167
|
return this.tokens;
|
|
118
168
|
} catch {
|
|
119
169
|
return null;
|
|
@@ -125,6 +175,98 @@ var AuthonMobileClient = class {
|
|
|
125
175
|
isAuthenticated() {
|
|
126
176
|
return this.tokens !== null && this.tokens.expiresAt > Date.now();
|
|
127
177
|
}
|
|
178
|
+
// ── OAuth ──
|
|
179
|
+
async getProviders() {
|
|
180
|
+
await this.ensureInitialized();
|
|
181
|
+
return this._providers;
|
|
182
|
+
}
|
|
183
|
+
async getBranding() {
|
|
184
|
+
await this.ensureInitialized();
|
|
185
|
+
return this._branding;
|
|
186
|
+
}
|
|
187
|
+
async getOAuthUrl(provider, redirectUri) {
|
|
188
|
+
const params = new URLSearchParams({ redirectUri, flow: "redirect" });
|
|
189
|
+
return await this.request(
|
|
190
|
+
"GET",
|
|
191
|
+
`/v1/auth/oauth/${provider}/url?${params.toString()}`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
async pollOAuth(state) {
|
|
195
|
+
try {
|
|
196
|
+
const res = await fetch(
|
|
197
|
+
`${this.apiUrl}/v1/auth/oauth/poll?state=${encodeURIComponent(state)}`,
|
|
198
|
+
{ headers: { "x-api-key": this.publishableKey } }
|
|
199
|
+
);
|
|
200
|
+
if (!res.ok) return null;
|
|
201
|
+
const data = await res.json();
|
|
202
|
+
if (data.status === "completed" && data.accessToken) {
|
|
203
|
+
return data;
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
206
|
+
} catch {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/** Poll for OAuth completion (3 minute timeout, matching JS SDK) */
|
|
211
|
+
async completeOAuth(state) {
|
|
212
|
+
const maxAttempts = 360;
|
|
213
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
214
|
+
const result = await this.pollOAuth(state);
|
|
215
|
+
if (result) {
|
|
216
|
+
this.tokens = this.toTokenPair(result);
|
|
217
|
+
this.user = result.user;
|
|
218
|
+
await this.persistTokens();
|
|
219
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
220
|
+
this.emit("signedIn", result.user);
|
|
221
|
+
return { tokens: this.tokens, user: result.user };
|
|
222
|
+
}
|
|
223
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
224
|
+
}
|
|
225
|
+
throw new Error("OAuth timeout");
|
|
226
|
+
}
|
|
227
|
+
getApiUrl() {
|
|
228
|
+
return this.apiUrl;
|
|
229
|
+
}
|
|
230
|
+
// ── Event system ──
|
|
231
|
+
on(event, listener) {
|
|
232
|
+
if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
233
|
+
const set = this.listeners.get(event);
|
|
234
|
+
set.add(listener);
|
|
235
|
+
return () => set.delete(listener);
|
|
236
|
+
}
|
|
237
|
+
emit(event, ...args) {
|
|
238
|
+
this.listeners.get(event)?.forEach((fn) => fn(...args));
|
|
239
|
+
}
|
|
240
|
+
// ── Cleanup ──
|
|
241
|
+
destroy() {
|
|
242
|
+
this.clearRefreshTimer();
|
|
243
|
+
this.listeners.clear();
|
|
244
|
+
}
|
|
245
|
+
// ── Private ──
|
|
246
|
+
clearSession() {
|
|
247
|
+
this.tokens = null;
|
|
248
|
+
this.user = null;
|
|
249
|
+
this.clearRefreshTimer();
|
|
250
|
+
if (this.storage) {
|
|
251
|
+
this.storage.removeItem(STORAGE_KEY).catch(() => {
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
clearRefreshTimer() {
|
|
256
|
+
if (this.refreshTimer) {
|
|
257
|
+
clearTimeout(this.refreshTimer);
|
|
258
|
+
this.refreshTimer = null;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/** Schedule auto-refresh 60 seconds before token expiry (like JS SDK) */
|
|
262
|
+
scheduleRefresh(expiresAt) {
|
|
263
|
+
this.clearRefreshTimer();
|
|
264
|
+
const refreshIn = Math.max(expiresAt - Date.now() - 6e4, 3e4);
|
|
265
|
+
this.refreshTimer = setTimeout(() => {
|
|
266
|
+
this.refreshToken().catch(() => {
|
|
267
|
+
});
|
|
268
|
+
}, refreshIn);
|
|
269
|
+
}
|
|
128
270
|
async persistTokens() {
|
|
129
271
|
if (this.storage && this.tokens) {
|
|
130
272
|
await this.storage.setItem(STORAGE_KEY, JSON.stringify(this.tokens));
|
|
@@ -152,7 +294,8 @@ var AuthonMobileClient = class {
|
|
|
152
294
|
});
|
|
153
295
|
if (!res.ok) {
|
|
154
296
|
const error = await res.json().catch(() => ({ message: res.statusText }));
|
|
155
|
-
|
|
297
|
+
const msg = Array.isArray(error.message) ? error.message[0] : error.message || `Request failed with status ${res.status}`;
|
|
298
|
+
throw new Error(msg);
|
|
156
299
|
}
|
|
157
300
|
const text = await res.text();
|
|
158
301
|
return text ? JSON.parse(text) : void 0;
|
|
@@ -172,6 +315,8 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
172
315
|
accessToken: null
|
|
173
316
|
});
|
|
174
317
|
const [user, setUser] = (0, import_react.useState)(null);
|
|
318
|
+
const [providers, setProviders] = (0, import_react.useState)([]);
|
|
319
|
+
const [branding, setBranding] = (0, import_react.useState)(null);
|
|
175
320
|
if (!clientRef.current) {
|
|
176
321
|
clientRef.current = new AuthonMobileClient(config);
|
|
177
322
|
}
|
|
@@ -180,7 +325,13 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
180
325
|
if (storage) {
|
|
181
326
|
client.setStorage(storage);
|
|
182
327
|
}
|
|
183
|
-
|
|
328
|
+
const init = async () => {
|
|
329
|
+
const tokens = await client.initialize();
|
|
330
|
+
await client.ensureInitialized();
|
|
331
|
+
const p = await client.getProviders();
|
|
332
|
+
const b = await client.getBranding();
|
|
333
|
+
setProviders(p);
|
|
334
|
+
setBranding(b);
|
|
184
335
|
if (tokens) {
|
|
185
336
|
const u = await client.getUser();
|
|
186
337
|
setUser(u);
|
|
@@ -194,11 +345,33 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
194
345
|
} else {
|
|
195
346
|
setAuthState((prev) => ({ ...prev, isLoaded: true }));
|
|
196
347
|
}
|
|
197
|
-
}
|
|
348
|
+
};
|
|
349
|
+
init();
|
|
350
|
+
const unsubs = [
|
|
351
|
+
client.on("signedOut", () => {
|
|
352
|
+
setUser(null);
|
|
353
|
+
setAuthState({
|
|
354
|
+
isLoaded: true,
|
|
355
|
+
isSignedIn: false,
|
|
356
|
+
userId: null,
|
|
357
|
+
sessionId: null,
|
|
358
|
+
accessToken: null
|
|
359
|
+
});
|
|
360
|
+
}),
|
|
361
|
+
client.on("tokenRefreshed", () => {
|
|
362
|
+
const token = client.getAccessToken();
|
|
363
|
+
if (token) {
|
|
364
|
+
setAuthState((prev) => ({ ...prev, accessToken: token }));
|
|
365
|
+
}
|
|
366
|
+
})
|
|
367
|
+
];
|
|
368
|
+
return () => {
|
|
369
|
+
unsubs.forEach((fn) => fn());
|
|
370
|
+
client.destroy();
|
|
371
|
+
};
|
|
198
372
|
}, []);
|
|
199
373
|
const signIn = (0, import_react.useCallback)(async (params) => {
|
|
200
|
-
const tokens = await client.signIn(params);
|
|
201
|
-
const u = await client.getUser();
|
|
374
|
+
const { tokens, user: u } = await client.signIn(params);
|
|
202
375
|
setUser(u);
|
|
203
376
|
setAuthState({
|
|
204
377
|
isLoaded: true,
|
|
@@ -209,8 +382,7 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
209
382
|
});
|
|
210
383
|
}, [client]);
|
|
211
384
|
const signUp = (0, import_react.useCallback)(async (params) => {
|
|
212
|
-
const tokens = await client.signUp(params);
|
|
213
|
-
const u = await client.getUser();
|
|
385
|
+
const { tokens, user: u } = await client.signUp(params);
|
|
214
386
|
setUser(u);
|
|
215
387
|
setAuthState({
|
|
216
388
|
isLoaded: true,
|
|
@@ -222,18 +394,37 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
222
394
|
}, [client]);
|
|
223
395
|
const signOut = (0, import_react.useCallback)(async () => {
|
|
224
396
|
await client.signOut();
|
|
225
|
-
setUser(null);
|
|
226
|
-
setAuthState({
|
|
227
|
-
isLoaded: true,
|
|
228
|
-
isSignedIn: false,
|
|
229
|
-
userId: null,
|
|
230
|
-
sessionId: null,
|
|
231
|
-
accessToken: null
|
|
232
|
-
});
|
|
233
397
|
}, [client]);
|
|
234
398
|
const getToken = (0, import_react.useCallback)(() => {
|
|
235
399
|
return client.getAccessToken();
|
|
236
400
|
}, [client]);
|
|
401
|
+
const startOAuth = (0, import_react.useCallback)(
|
|
402
|
+
async (provider, redirectUri) => {
|
|
403
|
+
const uri = redirectUri || `${client.getApiUrl()}/v1/auth/oauth/redirect`;
|
|
404
|
+
return client.getOAuthUrl(provider, uri);
|
|
405
|
+
},
|
|
406
|
+
[client]
|
|
407
|
+
);
|
|
408
|
+
const completeOAuthCb = (0, import_react.useCallback)(
|
|
409
|
+
async (state) => {
|
|
410
|
+
const { tokens, user: u } = await client.completeOAuth(state);
|
|
411
|
+
setUser(u);
|
|
412
|
+
setAuthState({
|
|
413
|
+
isLoaded: true,
|
|
414
|
+
isSignedIn: true,
|
|
415
|
+
userId: u?.id || null,
|
|
416
|
+
sessionId: null,
|
|
417
|
+
accessToken: tokens.accessToken
|
|
418
|
+
});
|
|
419
|
+
},
|
|
420
|
+
[client]
|
|
421
|
+
);
|
|
422
|
+
const on = (0, import_react.useCallback)(
|
|
423
|
+
(event, listener) => {
|
|
424
|
+
return client.on(event, listener);
|
|
425
|
+
},
|
|
426
|
+
[client]
|
|
427
|
+
);
|
|
237
428
|
const value = (0, import_react.useMemo)(
|
|
238
429
|
() => ({
|
|
239
430
|
...authState,
|
|
@@ -241,9 +432,15 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
241
432
|
signIn,
|
|
242
433
|
signUp,
|
|
243
434
|
signOut,
|
|
244
|
-
getToken
|
|
435
|
+
getToken,
|
|
436
|
+
providers,
|
|
437
|
+
branding,
|
|
438
|
+
startOAuth,
|
|
439
|
+
completeOAuth: completeOAuthCb,
|
|
440
|
+
on,
|
|
441
|
+
client
|
|
245
442
|
}),
|
|
246
|
-
[authState, user, signIn, signUp, signOut, getToken]
|
|
443
|
+
[authState, user, signIn, signUp, signOut, getToken, providers, branding, startOAuth, completeOAuthCb, on, client]
|
|
247
444
|
);
|
|
248
445
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthonContext.Provider, { value, children });
|
|
249
446
|
}
|
|
@@ -263,11 +460,195 @@ function useUser() {
|
|
|
263
460
|
const { isLoaded, isSignedIn, user } = useAuthon();
|
|
264
461
|
return { isLoaded, isSignedIn, user };
|
|
265
462
|
}
|
|
463
|
+
|
|
464
|
+
// src/icons.tsx
|
|
465
|
+
var import_react3 = require("react");
|
|
466
|
+
var import_react_native_svg = __toESM(require("react-native-svg"), 1);
|
|
467
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
468
|
+
function GoogleIcon({ size = 20 }) {
|
|
469
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, children: [
|
|
470
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { fill: "#4285F4", d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" }),
|
|
471
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { fill: "#34A853", d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" }),
|
|
472
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { fill: "#FBBC05", d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" }),
|
|
473
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { fill: "#EA4335", d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" })
|
|
474
|
+
] });
|
|
475
|
+
}
|
|
476
|
+
function AppleIcon({ size = 20, color = "#fff" }) {
|
|
477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { d: "M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z" }) });
|
|
478
|
+
}
|
|
479
|
+
function KakaoIcon({ size = 20 }) {
|
|
480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { fill: "#191919", d: "M12 3C6.48 3 2 6.36 2 10.43c0 2.62 1.75 4.93 4.37 6.23l-1.12 4.14c-.1.36.31.65.62.44l4.93-3.26c.39.04.79.06 1.2.06 5.52 0 10-3.36 10-7.61C22 6.36 17.52 3 12 3z" }) });
|
|
481
|
+
}
|
|
482
|
+
function NaverIcon({ size = 20, color = "#fff" }) {
|
|
483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { fill: color, d: "M16.273 12.845 7.376 0H0v24h7.726V11.156L16.624 24H24V0h-7.727v12.845Z" }) });
|
|
484
|
+
}
|
|
485
|
+
function FacebookIcon({ size = 20, color = "#fff" }) {
|
|
486
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { fill: color, d: "M24 12.07C24 5.41 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.04V9.41c0-3.02 1.8-4.7 4.54-4.7 1.31 0 2.68.24 2.68.24v2.97h-1.5c-1.5 0-1.96.93-1.96 1.89v2.26h3.33l-.53 3.49h-2.8V24C19.62 23.1 24 18.1 24 12.07z" }) });
|
|
487
|
+
}
|
|
488
|
+
function GithubIcon({ size = 20, color = "#fff" }) {
|
|
489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { d: "M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z" }) });
|
|
490
|
+
}
|
|
491
|
+
function DiscordIcon({ size = 20, color = "#fff" }) {
|
|
492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { d: "M20.32 4.37a19.8 19.8 0 00-4.89-1.52.07.07 0 00-.08.04c-.21.38-.44.87-.61 1.26a18.27 18.27 0 00-5.49 0 12.64 12.64 0 00-.62-1.26.07.07 0 00-.08-.04 19.74 19.74 0 00-4.89 1.52.07.07 0 00-.03.03C1.11 8.39.34 12.28.73 16.12a.08.08 0 00.03.06 19.9 19.9 0 005.99 3.03.08.08 0 00.08-.03c.46-.63.87-1.3 1.22-2a.08.08 0 00-.04-.11 13.1 13.1 0 01-1.87-.9.08.08 0 01-.01-.13c.13-.09.25-.19.37-.29a.07.07 0 01.08-.01c3.93 1.8 8.18 1.8 12.07 0a.07.07 0 01.08 0c.12.1.25.2.37.3a.08.08 0 01-.01.12c-.6.35-1.22.65-1.87.9a.08.08 0 00-.04.1c.36.7.77 1.37 1.22 2a.08.08 0 00.08.03 19.83 19.83 0 006-3.03.08.08 0 00.03-.05c.47-4.87-.78-9.09-3.3-12.84a.06.06 0 00-.03-.03zM8.02 13.62c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.9 2.28-2.03 2.28zm7.5 0c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.89 2.28-2.03 2.28z" }) });
|
|
493
|
+
}
|
|
494
|
+
function XIcon({ size = 20, color = "#fff" }) {
|
|
495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" }) });
|
|
496
|
+
}
|
|
497
|
+
function LineIcon({ size = 20, color = "#fff" }) {
|
|
498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Path, { d: "M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314" }) });
|
|
499
|
+
}
|
|
500
|
+
function MicrosoftIcon({ size = 20 }) {
|
|
501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native_svg.default, { viewBox: "0 0 24 24", width: size, height: size, children: [
|
|
502
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Rect, { fill: "#F25022", x: 1, y: 1, width: 10, height: 10 }),
|
|
503
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Rect, { fill: "#7FBA00", x: 13, y: 1, width: 10, height: 10 }),
|
|
504
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Rect, { fill: "#00A4EF", x: 1, y: 13, width: 10, height: 10 }),
|
|
505
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_svg.Rect, { fill: "#FFB900", x: 13, y: 13, width: 10, height: 10 })
|
|
506
|
+
] });
|
|
507
|
+
}
|
|
508
|
+
var ICON_MAP = {
|
|
509
|
+
google: GoogleIcon,
|
|
510
|
+
apple: AppleIcon,
|
|
511
|
+
kakao: KakaoIcon,
|
|
512
|
+
naver: NaverIcon,
|
|
513
|
+
facebook: FacebookIcon,
|
|
514
|
+
github: GithubIcon,
|
|
515
|
+
discord: DiscordIcon,
|
|
516
|
+
x: XIcon,
|
|
517
|
+
line: LineIcon,
|
|
518
|
+
microsoft: MicrosoftIcon
|
|
519
|
+
};
|
|
520
|
+
function ProviderIcon({ provider, size = 20, color }) {
|
|
521
|
+
const Icon = ICON_MAP[provider];
|
|
522
|
+
if (!Icon) return null;
|
|
523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { size, color });
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// src/SocialButton.tsx
|
|
527
|
+
var import_react4 = require("react");
|
|
528
|
+
var import_react_native = require("react-native");
|
|
529
|
+
var import_shared = require("@authon/shared");
|
|
530
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
531
|
+
function SocialButton({
|
|
532
|
+
provider,
|
|
533
|
+
onPress,
|
|
534
|
+
loading = false,
|
|
535
|
+
disabled = false,
|
|
536
|
+
label,
|
|
537
|
+
style,
|
|
538
|
+
labelStyle,
|
|
539
|
+
iconSize = 20,
|
|
540
|
+
borderRadius = 10,
|
|
541
|
+
height = 48
|
|
542
|
+
}) {
|
|
543
|
+
const colors = import_shared.PROVIDER_COLORS[provider] || { bg: "#333", text: "#fff" };
|
|
544
|
+
const displayName = import_shared.PROVIDER_DISPLAY_NAMES[provider] || provider;
|
|
545
|
+
const buttonLabel = label ?? `Continue with ${displayName}`;
|
|
546
|
+
const needsBorder = colors.bg.toLowerCase() === "#ffffff";
|
|
547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
548
|
+
import_react_native.TouchableOpacity,
|
|
549
|
+
{
|
|
550
|
+
style: [
|
|
551
|
+
styles.button,
|
|
552
|
+
{
|
|
553
|
+
backgroundColor: colors.bg,
|
|
554
|
+
borderRadius,
|
|
555
|
+
height
|
|
556
|
+
},
|
|
557
|
+
needsBorder && styles.bordered,
|
|
558
|
+
style
|
|
559
|
+
],
|
|
560
|
+
onPress: () => onPress(provider),
|
|
561
|
+
disabled: disabled || loading,
|
|
562
|
+
activeOpacity: 0.8,
|
|
563
|
+
children: loading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native.ActivityIndicator, { color: colors.text, size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
564
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProviderIcon, { provider, size: iconSize, color: colors.text }),
|
|
565
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
566
|
+
import_react_native.Text,
|
|
567
|
+
{
|
|
568
|
+
style: [
|
|
569
|
+
styles.label,
|
|
570
|
+
{ color: colors.text },
|
|
571
|
+
labelStyle
|
|
572
|
+
],
|
|
573
|
+
numberOfLines: 1,
|
|
574
|
+
children: buttonLabel
|
|
575
|
+
}
|
|
576
|
+
)
|
|
577
|
+
] })
|
|
578
|
+
}
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
var styles = import_react_native.StyleSheet.create({
|
|
582
|
+
button: {
|
|
583
|
+
flexDirection: "row",
|
|
584
|
+
alignItems: "center",
|
|
585
|
+
justifyContent: "center",
|
|
586
|
+
gap: 10,
|
|
587
|
+
paddingHorizontal: 16
|
|
588
|
+
},
|
|
589
|
+
bordered: {
|
|
590
|
+
borderWidth: 1,
|
|
591
|
+
borderColor: "#dadce0"
|
|
592
|
+
},
|
|
593
|
+
label: {
|
|
594
|
+
fontSize: 15,
|
|
595
|
+
fontWeight: "600"
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
// src/SocialButtons.tsx
|
|
600
|
+
var import_react5 = require("react");
|
|
601
|
+
var import_react_native2 = require("react-native");
|
|
602
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
603
|
+
function SocialButtons({
|
|
604
|
+
onSuccess,
|
|
605
|
+
onError,
|
|
606
|
+
style,
|
|
607
|
+
gap = 10,
|
|
608
|
+
buttonProps
|
|
609
|
+
}) {
|
|
610
|
+
const { providers, startOAuth, completeOAuth } = useAuthon();
|
|
611
|
+
const [loadingProvider, setLoadingProvider] = (0, import_react5.useState)(null);
|
|
612
|
+
if (providers.length === 0) return null;
|
|
613
|
+
const handlePress = async (provider) => {
|
|
614
|
+
setLoadingProvider(provider);
|
|
615
|
+
try {
|
|
616
|
+
const { url, state } = await startOAuth(provider);
|
|
617
|
+
await import_react_native2.Linking.openURL(url);
|
|
618
|
+
await completeOAuth(state);
|
|
619
|
+
onSuccess?.();
|
|
620
|
+
} catch (e) {
|
|
621
|
+
const error = e instanceof Error ? e : new Error(String(e));
|
|
622
|
+
if (error.message !== "OAuth timeout") {
|
|
623
|
+
onError?.(error);
|
|
624
|
+
}
|
|
625
|
+
} finally {
|
|
626
|
+
setLoadingProvider(null);
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native2.View, { style: [styles2.container, { gap }, style], children: providers.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
630
|
+
SocialButton,
|
|
631
|
+
{
|
|
632
|
+
provider,
|
|
633
|
+
onPress: handlePress,
|
|
634
|
+
loading: loadingProvider === provider,
|
|
635
|
+
disabled: !!loadingProvider,
|
|
636
|
+
...buttonProps
|
|
637
|
+
},
|
|
638
|
+
provider
|
|
639
|
+
)) });
|
|
640
|
+
}
|
|
641
|
+
var styles2 = import_react_native2.StyleSheet.create({
|
|
642
|
+
container: {}
|
|
643
|
+
});
|
|
266
644
|
// Annotate the CommonJS export names for ESM import in node:
|
|
267
645
|
0 && (module.exports = {
|
|
268
646
|
AuthonContext,
|
|
269
647
|
AuthonMobileClient,
|
|
270
648
|
AuthonProvider,
|
|
649
|
+
ProviderIcon,
|
|
650
|
+
SocialButton,
|
|
651
|
+
SocialButtons,
|
|
271
652
|
useAuthon,
|
|
272
653
|
useUser
|
|
273
654
|
});
|