@riligar/auth-react 1.2.0 → 1.3.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/dist/index.js CHANGED
@@ -1,16 +1,47 @@
1
1
  'use strict';
2
2
 
3
- var require$$0 = require('react');
3
+ var React$1 = require('react');
4
4
  var reactRouterDom = require('react-router-dom');
5
+ var core = require('@mantine/core');
6
+ var form = require('@mantine/form');
7
+ var iconsReact = require('@tabler/icons-react');
5
8
 
6
- // Ajuste se o back-end estiver em outro domínio/porta
7
- const API_BASE = typeof window !== 'undefined' && window?.location ? undefined?.VITE_API_BASE ?? "http://localhost:3000" : "http://localhost:3000";
9
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
10
+ // Config - pode ser sobrescrita pelo AuthProvider
11
+ // Tenta detectar ambiente Vite, mas falha graciosamente se não existir
12
+ const getEnvVar = key => {
13
+ try {
14
+ if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)) }) !== 'undefined' && undefined && undefined[key]) {
15
+ return undefined[key];
16
+ }
17
+ } catch (e) {
18
+ // ignore
19
+ }
20
+ return null;
21
+ };
22
+ let API_BASE = (typeof window !== 'undefined' && window?.location ? getEnvVar('VITE_API_BASE') : null) || 'http://localhost:3000';
23
+ let API_KEY = null;
24
+
25
+ // Permite configurar a API base e key externamente (chamado pelo AuthProvider)
26
+ function configure({
27
+ apiUrl,
28
+ apiKey
29
+ }) {
30
+ if (apiUrl) API_BASE = apiUrl.replace(/\/$/, ''); // Remove trailing slash
31
+ if (apiKey) API_KEY = apiKey;
32
+ }
8
33
 
9
34
  // helper fetch pré-configurado
10
35
  async function api(route, opts = {}) {
36
+ // Garante que a rota comece com /
37
+ const cleanRoute = route.startsWith('/') ? route : `/${route}`;
38
+
39
+ // Constrói URL completa (API_BASE já teve trailing slash removido no configure)
40
+ const url = `${API_BASE}${cleanRoute}`;
11
41
  const token = getStoredToken();
12
42
  const headers = {
13
- "Content-Type": "application/json",
43
+ 'Content-Type': 'application/json',
44
+ Accept: 'application/json',
14
45
  ...opts.headers
15
46
  };
16
47
 
@@ -18,7 +49,12 @@ async function api(route, opts = {}) {
18
49
  if (token) {
19
50
  headers.Authorization = `Bearer ${token}`;
20
51
  }
21
- const res = await fetch(`${API_BASE}${route}`, {
52
+
53
+ // Adiciona API Key se configurada
54
+ if (API_KEY) {
55
+ headers['X-API-Key'] = API_KEY;
56
+ }
57
+ const res = await fetch(url, {
22
58
  headers,
23
59
  ...opts
24
60
  });
@@ -45,14 +81,38 @@ function setStoredToken(token) {
45
81
  window.localStorage.removeItem('auth:token');
46
82
  }
47
83
  }
84
+ // Helper para processar resposta de autenticação e salvar token
85
+ function handleAuthResponse(result) {
86
+ // Tenta encontrar o token em vários lugares possíveis
87
+ const token = result.token || result.session?.token || result.session?.sessionToken;
88
+ console.log('[AuthSDK] Handling Auth Response:', {
89
+ hasToken: !!result.token,
90
+ hasSessionToken: !!result.session?.token,
91
+ hasSessionSessionToken: !!result.session?.sessionToken,
92
+ extractedToken: token
93
+ });
94
+ if (token) {
95
+ console.log('[AuthSDK] Saving token to storage');
96
+ setStoredToken(token);
97
+ } else {
98
+ console.warn('[AuthSDK] No token found in response', result);
99
+ }
100
+ return result;
101
+ }
48
102
 
49
103
  // Decodifica JWT (apenas payload, sem verificação de assinatura)
50
104
  function decodeJWT(token) {
51
105
  try {
52
106
  const parts = token.split('.');
53
107
  if (parts.length !== 3) return null;
54
- const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
55
- return payload;
108
+
109
+ // Safe base64 decode
110
+ const base64Url = parts[1];
111
+ const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
112
+
113
+ // Verifica ambiente para decodificar
114
+ const jsonPayload = typeof window !== 'undefined' ? window.atob(base64) : Buffer.from(base64, 'base64').toString();
115
+ return JSON.parse(jsonPayload);
56
116
  } catch {
57
117
  return null;
58
118
  }
@@ -61,14 +121,33 @@ function decodeJWT(token) {
61
121
  // Verifica se o token está expirado
62
122
  function isTokenExpired(token) {
63
123
  const payload = decodeJWT(token);
64
- if (!payload || !payload.exp) return true;
65
- return Date.now() >= payload.exp * 1000;
124
+
125
+ // Se não for um JWT válido (payload null), assumimos que é um token opaco (session token)
126
+ // Nesse caso, deixamos o servidor validar via 401
127
+ if (!payload) return false;
128
+ if (!payload.exp) return false;
129
+ const now = Date.now();
130
+ const exp = payload.exp * 1000;
131
+ const isExpired = now >= exp;
132
+ if (isExpired) {
133
+ console.log('[AuthSDK] Token expired:', {
134
+ now,
135
+ exp,
136
+ diff: exp - now
137
+ });
138
+ }
139
+ return isExpired;
66
140
  }
67
141
 
68
142
  // Verifica se o usuário está autenticado
69
143
  function isAuthenticated() {
70
144
  const token = getStoredToken();
71
- return token && !isTokenExpired(token);
145
+ const valid = token && !isTokenExpired(token);
146
+ console.log('[AuthSDK] isAuthenticated check:', {
147
+ hasToken: !!token,
148
+ valid
149
+ });
150
+ return valid;
72
151
  }
73
152
 
74
153
  // Obtém dados do usuário do token
@@ -84,37 +163,32 @@ function getCurrentUser() {
84
163
  } : null;
85
164
  }
86
165
 
87
- /*--- métodos de autenticação-------------------*/
88
- const signUp = async (email, password) => {
89
- const result = await api("/auth/sign-up", {
90
- method: "POST",
166
+ /*--- métodos de autenticação -------------------*/
167
+ const signUp = async (email, password, name = '') => {
168
+ const result = await api('/auth/sign-up/email', {
169
+ method: 'POST',
91
170
  body: JSON.stringify({
92
171
  email,
93
- password
172
+ password,
173
+ name
94
174
  })
95
175
  });
96
- if (result.token) {
97
- setStoredToken(result.token);
98
- }
99
- return result;
176
+ return handleAuthResponse(result);
100
177
  };
101
178
  const signIn = async (email, password) => {
102
- const result = await api("/auth/sign-in", {
103
- method: "POST",
179
+ const result = await api('/auth/sign-in/email', {
180
+ method: 'POST',
104
181
  body: JSON.stringify({
105
182
  email,
106
183
  password
107
184
  })
108
185
  });
109
- if (result.token) {
110
- setStoredToken(result.token);
111
- }
112
- return result;
186
+ return handleAuthResponse(result);
113
187
  };
114
188
  const signOut = async () => {
115
189
  try {
116
- await api("/auth/sign-out", {
117
- method: "POST"
190
+ await api('/auth/sign-out', {
191
+ method: 'POST'
118
192
  });
119
193
  } catch {
120
194
  // Ignora erros de logout no servidor
@@ -124,23 +198,77 @@ const signOut = async () => {
124
198
  };
125
199
  const refreshToken = async () => {
126
200
  try {
127
- const result = await api("/auth/refresh", {
128
- method: "POST"
201
+ const result = await api('/auth/refresh', {
202
+ method: 'POST'
129
203
  });
130
- if (result.token) {
131
- setStoredToken(result.token);
132
- return result;
133
- }
204
+ return handleAuthResponse(result);
134
205
  } catch (error) {
135
206
  setStoredToken(null);
136
207
  throw error;
137
208
  }
138
209
  };
139
210
 
140
- /* Social login redirect (ex.: Google) ---------*/
211
+ /*--- Magic Link ---------------------------------*/
212
+ const sendMagicLink = async (email, callbackURL) => {
213
+ const callback = callbackURL || (typeof window !== 'undefined' ? `${window.location.origin}/auth/magic-link/verify` : '/auth/magic-link/verify');
214
+ return await api('/auth/sign-in/magic-link', {
215
+ method: 'POST',
216
+ body: JSON.stringify({
217
+ email,
218
+ callbackURL: callback
219
+ })
220
+ });
221
+ };
222
+ const verifyMagicLink = async token => {
223
+ const result = await api(`/auth/magic-link/verify?token=${encodeURIComponent(token)}`);
224
+ return handleAuthResponse(result);
225
+ };
226
+
227
+ /*--- Password Reset -----------------------------*/
228
+ const forgotPassword = async (email, redirectTo) => {
229
+ const redirect = redirectTo || (typeof window !== 'undefined' ? `${window.location.origin}/auth/reset-password` : '/auth/reset-password');
230
+ return await api('/auth/forget-password', {
231
+ method: 'POST',
232
+ body: JSON.stringify({
233
+ email,
234
+ redirectTo: redirect
235
+ })
236
+ });
237
+ };
238
+ const resetPassword = async (token, newPassword) => {
239
+ return await api('/auth/reset-password', {
240
+ method: 'POST',
241
+ body: JSON.stringify({
242
+ token,
243
+ newPassword
244
+ })
245
+ });
246
+ };
247
+
248
+ /*--- Email Verification -------------------------*/
249
+ const verifyEmail = async token => {
250
+ const result = await api(`/auth/verify-email?token=${encodeURIComponent(token)}`);
251
+ return handleAuthResponse(result);
252
+ };
253
+ const resendVerification = async (email, callbackURL) => {
254
+ const callback = callbackURL || (typeof window !== 'undefined' ? `${window.location.origin}/auth/verify-email` : '/auth/verify-email');
255
+ return await api('/auth/send-verification-email', {
256
+ method: 'POST',
257
+ body: JSON.stringify({
258
+ email,
259
+ callbackURL: callback
260
+ })
261
+ });
262
+ };
263
+
264
+ /*--- Session ------------------------------------*/
265
+ const getSession = async () => {
266
+ return await api('/auth/session');
267
+ };
268
+
269
+ /* Social login redirect (ex.: Google) -----------*/
141
270
  function socialRedirect(provider, redirectTo = typeof window !== 'undefined' ? window.location.href : '/') {
142
271
  if (typeof window === 'undefined') return;
143
- // Melhor pegar a URL de redirect dada pelo back-end, mas isso já funciona:
144
272
  window.location = `${API_BASE}/auth/sign-in/${provider}?redirect=${encodeURIComponent(redirectTo)}`;
145
273
  }
146
274
 
@@ -161,479 +289,84 @@ const createStoreImpl = (createState) => {
161
289
  listeners.add(listener);
162
290
  return () => listeners.delete(listener);
163
291
  };
164
- const destroy = () => {
165
- if ((undefined ? undefined.MODE : void 0) !== "production") {
166
- console.warn(
167
- "[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."
168
- );
169
- }
170
- listeners.clear();
171
- };
172
- const api = { setState, getState, getInitialState, subscribe, destroy };
292
+ const api = { setState, getState, getInitialState, subscribe };
173
293
  const initialState = state = createState(setState, getState, api);
174
294
  return api;
175
295
  };
176
- const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
177
-
178
- function getDefaultExportFromCjs (x) {
179
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
180
- }
181
-
182
- var withSelector = {exports: {}};
183
-
184
- var withSelector_production = {};
185
-
186
- var shim = {exports: {}};
187
-
188
- var useSyncExternalStoreShim_production = {};
189
-
190
- /**
191
- * @license React
192
- * use-sync-external-store-shim.production.js
193
- *
194
- * Copyright (c) Meta Platforms, Inc. and affiliates.
195
- *
196
- * This source code is licensed under the MIT license found in the
197
- * LICENSE file in the root directory of this source tree.
198
- */
199
-
200
- var hasRequiredUseSyncExternalStoreShim_production;
201
-
202
- function requireUseSyncExternalStoreShim_production () {
203
- if (hasRequiredUseSyncExternalStoreShim_production) return useSyncExternalStoreShim_production;
204
- hasRequiredUseSyncExternalStoreShim_production = 1;
205
- var React = require$$0;
206
- function is(x, y) {
207
- return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
208
- }
209
- var objectIs = "function" === typeof Object.is ? Object.is : is,
210
- useState = React.useState,
211
- useEffect = React.useEffect,
212
- useLayoutEffect = React.useLayoutEffect,
213
- useDebugValue = React.useDebugValue;
214
- function useSyncExternalStore$2(subscribe, getSnapshot) {
215
- var value = getSnapshot(),
216
- _useState = useState({ inst: { value: value, getSnapshot: getSnapshot } }),
217
- inst = _useState[0].inst,
218
- forceUpdate = _useState[1];
219
- useLayoutEffect(
220
- function () {
221
- inst.value = value;
222
- inst.getSnapshot = getSnapshot;
223
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
224
- },
225
- [subscribe, value, getSnapshot]
226
- );
227
- useEffect(
228
- function () {
229
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
230
- return subscribe(function () {
231
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
232
- });
233
- },
234
- [subscribe]
235
- );
236
- useDebugValue(value);
237
- return value;
238
- }
239
- function checkIfSnapshotChanged(inst) {
240
- var latestGetSnapshot = inst.getSnapshot;
241
- inst = inst.value;
242
- try {
243
- var nextValue = latestGetSnapshot();
244
- return !objectIs(inst, nextValue);
245
- } catch (error) {
246
- return true;
247
- }
248
- }
249
- function useSyncExternalStore$1(subscribe, getSnapshot) {
250
- return getSnapshot();
251
- }
252
- var shim =
253
- "undefined" === typeof window ||
254
- "undefined" === typeof window.document ||
255
- "undefined" === typeof window.document.createElement
256
- ? useSyncExternalStore$1
257
- : useSyncExternalStore$2;
258
- useSyncExternalStoreShim_production.useSyncExternalStore =
259
- void 0 !== React.useSyncExternalStore ? React.useSyncExternalStore : shim;
260
- return useSyncExternalStoreShim_production;
261
- }
262
-
263
- var useSyncExternalStoreShim_development = {};
264
-
265
- /**
266
- * @license React
267
- * use-sync-external-store-shim.development.js
268
- *
269
- * Copyright (c) Meta Platforms, Inc. and affiliates.
270
- *
271
- * This source code is licensed under the MIT license found in the
272
- * LICENSE file in the root directory of this source tree.
273
- */
274
-
275
- var hasRequiredUseSyncExternalStoreShim_development;
276
-
277
- function requireUseSyncExternalStoreShim_development () {
278
- if (hasRequiredUseSyncExternalStoreShim_development) return useSyncExternalStoreShim_development;
279
- hasRequiredUseSyncExternalStoreShim_development = 1;
280
- "production" !== process.env.NODE_ENV &&
281
- (function () {
282
- function is(x, y) {
283
- return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
284
- }
285
- function useSyncExternalStore$2(subscribe, getSnapshot) {
286
- didWarnOld18Alpha ||
287
- void 0 === React.startTransition ||
288
- ((didWarnOld18Alpha = true),
289
- console.error(
290
- "You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."
291
- ));
292
- var value = getSnapshot();
293
- if (!didWarnUncachedGetSnapshot) {
294
- var cachedValue = getSnapshot();
295
- objectIs(value, cachedValue) ||
296
- (console.error(
297
- "The result of getSnapshot should be cached to avoid an infinite loop"
298
- ),
299
- (didWarnUncachedGetSnapshot = true));
300
- }
301
- cachedValue = useState({
302
- inst: { value: value, getSnapshot: getSnapshot }
303
- });
304
- var inst = cachedValue[0].inst,
305
- forceUpdate = cachedValue[1];
306
- useLayoutEffect(
307
- function () {
308
- inst.value = value;
309
- inst.getSnapshot = getSnapshot;
310
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
311
- },
312
- [subscribe, value, getSnapshot]
313
- );
314
- useEffect(
315
- function () {
316
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
317
- return subscribe(function () {
318
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
319
- });
320
- },
321
- [subscribe]
322
- );
323
- useDebugValue(value);
324
- return value;
325
- }
326
- function checkIfSnapshotChanged(inst) {
327
- var latestGetSnapshot = inst.getSnapshot;
328
- inst = inst.value;
329
- try {
330
- var nextValue = latestGetSnapshot();
331
- return !objectIs(inst, nextValue);
332
- } catch (error) {
333
- return true;
334
- }
335
- }
336
- function useSyncExternalStore$1(subscribe, getSnapshot) {
337
- return getSnapshot();
338
- }
339
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
340
- "function" ===
341
- typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&
342
- __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
343
- var React = require$$0,
344
- objectIs = "function" === typeof Object.is ? Object.is : is,
345
- useState = React.useState,
346
- useEffect = React.useEffect,
347
- useLayoutEffect = React.useLayoutEffect,
348
- useDebugValue = React.useDebugValue,
349
- didWarnOld18Alpha = false,
350
- didWarnUncachedGetSnapshot = false,
351
- shim =
352
- "undefined" === typeof window ||
353
- "undefined" === typeof window.document ||
354
- "undefined" === typeof window.document.createElement
355
- ? useSyncExternalStore$1
356
- : useSyncExternalStore$2;
357
- useSyncExternalStoreShim_development.useSyncExternalStore =
358
- void 0 !== React.useSyncExternalStore ? React.useSyncExternalStore : shim;
359
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
360
- "function" ===
361
- typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
362
- __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
363
- })();
364
- return useSyncExternalStoreShim_development;
365
- }
366
-
367
- var hasRequiredShim;
368
-
369
- function requireShim () {
370
- if (hasRequiredShim) return shim.exports;
371
- hasRequiredShim = 1;
372
-
373
- if (process.env.NODE_ENV === 'production') {
374
- shim.exports = requireUseSyncExternalStoreShim_production();
375
- } else {
376
- shim.exports = requireUseSyncExternalStoreShim_development();
377
- }
378
- return shim.exports;
379
- }
380
-
381
- /**
382
- * @license React
383
- * use-sync-external-store-shim/with-selector.production.js
384
- *
385
- * Copyright (c) Meta Platforms, Inc. and affiliates.
386
- *
387
- * This source code is licensed under the MIT license found in the
388
- * LICENSE file in the root directory of this source tree.
389
- */
390
-
391
- var hasRequiredWithSelector_production;
392
-
393
- function requireWithSelector_production () {
394
- if (hasRequiredWithSelector_production) return withSelector_production;
395
- hasRequiredWithSelector_production = 1;
396
- var React = require$$0,
397
- shim = requireShim();
398
- function is(x, y) {
399
- return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
400
- }
401
- var objectIs = "function" === typeof Object.is ? Object.is : is,
402
- useSyncExternalStore = shim.useSyncExternalStore,
403
- useRef = React.useRef,
404
- useEffect = React.useEffect,
405
- useMemo = React.useMemo,
406
- useDebugValue = React.useDebugValue;
407
- withSelector_production.useSyncExternalStoreWithSelector = function (
408
- subscribe,
409
- getSnapshot,
410
- getServerSnapshot,
411
- selector,
412
- isEqual
413
- ) {
414
- var instRef = useRef(null);
415
- if (null === instRef.current) {
416
- var inst = { hasValue: false, value: null };
417
- instRef.current = inst;
418
- } else inst = instRef.current;
419
- instRef = useMemo(
420
- function () {
421
- function memoizedSelector(nextSnapshot) {
422
- if (!hasMemo) {
423
- hasMemo = true;
424
- memoizedSnapshot = nextSnapshot;
425
- nextSnapshot = selector(nextSnapshot);
426
- if (void 0 !== isEqual && inst.hasValue) {
427
- var currentSelection = inst.value;
428
- if (isEqual(currentSelection, nextSnapshot))
429
- return (memoizedSelection = currentSelection);
430
- }
431
- return (memoizedSelection = nextSnapshot);
432
- }
433
- currentSelection = memoizedSelection;
434
- if (objectIs(memoizedSnapshot, nextSnapshot)) return currentSelection;
435
- var nextSelection = selector(nextSnapshot);
436
- if (void 0 !== isEqual && isEqual(currentSelection, nextSelection))
437
- return (memoizedSnapshot = nextSnapshot), currentSelection;
438
- memoizedSnapshot = nextSnapshot;
439
- return (memoizedSelection = nextSelection);
440
- }
441
- var hasMemo = false,
442
- memoizedSnapshot,
443
- memoizedSelection,
444
- maybeGetServerSnapshot =
445
- void 0 === getServerSnapshot ? null : getServerSnapshot;
446
- return [
447
- function () {
448
- return memoizedSelector(getSnapshot());
449
- },
450
- null === maybeGetServerSnapshot
451
- ? void 0
452
- : function () {
453
- return memoizedSelector(maybeGetServerSnapshot());
454
- }
455
- ];
456
- },
457
- [getSnapshot, getServerSnapshot, selector, isEqual]
458
- );
459
- var value = useSyncExternalStore(subscribe, instRef[0], instRef[1]);
460
- useEffect(
461
- function () {
462
- inst.hasValue = true;
463
- inst.value = value;
464
- },
465
- [value]
466
- );
467
- useDebugValue(value);
468
- return value;
469
- };
470
- return withSelector_production;
471
- }
472
-
473
- var withSelector_development = {};
474
-
475
- /**
476
- * @license React
477
- * use-sync-external-store-shim/with-selector.development.js
478
- *
479
- * Copyright (c) Meta Platforms, Inc. and affiliates.
480
- *
481
- * This source code is licensed under the MIT license found in the
482
- * LICENSE file in the root directory of this source tree.
483
- */
484
-
485
- var hasRequiredWithSelector_development;
486
-
487
- function requireWithSelector_development () {
488
- if (hasRequiredWithSelector_development) return withSelector_development;
489
- hasRequiredWithSelector_development = 1;
490
- "production" !== process.env.NODE_ENV &&
491
- (function () {
492
- function is(x, y) {
493
- return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
494
- }
495
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
496
- "function" ===
497
- typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&
498
- __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
499
- var React = require$$0,
500
- shim = requireShim(),
501
- objectIs = "function" === typeof Object.is ? Object.is : is,
502
- useSyncExternalStore = shim.useSyncExternalStore,
503
- useRef = React.useRef,
504
- useEffect = React.useEffect,
505
- useMemo = React.useMemo,
506
- useDebugValue = React.useDebugValue;
507
- withSelector_development.useSyncExternalStoreWithSelector = function (
508
- subscribe,
509
- getSnapshot,
510
- getServerSnapshot,
511
- selector,
512
- isEqual
513
- ) {
514
- var instRef = useRef(null);
515
- if (null === instRef.current) {
516
- var inst = { hasValue: false, value: null };
517
- instRef.current = inst;
518
- } else inst = instRef.current;
519
- instRef = useMemo(
520
- function () {
521
- function memoizedSelector(nextSnapshot) {
522
- if (!hasMemo) {
523
- hasMemo = true;
524
- memoizedSnapshot = nextSnapshot;
525
- nextSnapshot = selector(nextSnapshot);
526
- if (void 0 !== isEqual && inst.hasValue) {
527
- var currentSelection = inst.value;
528
- if (isEqual(currentSelection, nextSnapshot))
529
- return (memoizedSelection = currentSelection);
530
- }
531
- return (memoizedSelection = nextSnapshot);
532
- }
533
- currentSelection = memoizedSelection;
534
- if (objectIs(memoizedSnapshot, nextSnapshot))
535
- return currentSelection;
536
- var nextSelection = selector(nextSnapshot);
537
- if (void 0 !== isEqual && isEqual(currentSelection, nextSelection))
538
- return (memoizedSnapshot = nextSnapshot), currentSelection;
539
- memoizedSnapshot = nextSnapshot;
540
- return (memoizedSelection = nextSelection);
541
- }
542
- var hasMemo = false,
543
- memoizedSnapshot,
544
- memoizedSelection,
545
- maybeGetServerSnapshot =
546
- void 0 === getServerSnapshot ? null : getServerSnapshot;
547
- return [
548
- function () {
549
- return memoizedSelector(getSnapshot());
550
- },
551
- null === maybeGetServerSnapshot
552
- ? void 0
553
- : function () {
554
- return memoizedSelector(maybeGetServerSnapshot());
555
- }
556
- ];
557
- },
558
- [getSnapshot, getServerSnapshot, selector, isEqual]
559
- );
560
- var value = useSyncExternalStore(subscribe, instRef[0], instRef[1]);
561
- useEffect(
562
- function () {
563
- inst.hasValue = true;
564
- inst.value = value;
565
- },
566
- [value]
567
- );
568
- useDebugValue(value);
569
- return value;
570
- };
571
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
572
- "function" ===
573
- typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
574
- __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
575
- })();
576
- return withSelector_development;
577
- }
578
-
579
- if (process.env.NODE_ENV === 'production') {
580
- withSelector.exports = requireWithSelector_production();
581
- } else {
582
- withSelector.exports = requireWithSelector_development();
583
- }
584
-
585
- var withSelectorExports = withSelector.exports;
586
- var useSyncExternalStoreExports = /*@__PURE__*/getDefaultExportFromCjs(withSelectorExports);
296
+ const createStore = ((createState) => createState ? createStoreImpl(createState) : createStoreImpl);
587
297
 
588
- const { useDebugValue } = require$$0;
589
- const { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports;
590
- let didWarnAboutEqualityFn = false;
591
298
  const identity = (arg) => arg;
592
- function useStore(api, selector = identity, equalityFn) {
593
- if ((undefined ? undefined.MODE : void 0) !== "production" && equalityFn && !didWarnAboutEqualityFn) {
594
- console.warn(
595
- "[DEPRECATED] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`. They can be imported from 'zustand/traditional'. https://github.com/pmndrs/zustand/discussions/1937"
596
- );
597
- didWarnAboutEqualityFn = true;
598
- }
599
- const slice = useSyncExternalStoreWithSelector(
299
+ function useStore(api, selector = identity) {
300
+ const slice = React$1.useSyncExternalStore(
600
301
  api.subscribe,
601
- api.getState,
602
- api.getServerState || api.getInitialState,
603
- selector,
604
- equalityFn
302
+ React$1.useCallback(() => selector(api.getState()), [api, selector]),
303
+ React$1.useCallback(() => selector(api.getInitialState()), [api, selector])
605
304
  );
606
- useDebugValue(slice);
305
+ React$1.useDebugValue(slice);
607
306
  return slice;
608
307
  }
609
308
  const createImpl = (createState) => {
610
- if ((undefined ? undefined.MODE : void 0) !== "production" && typeof createState !== "function") {
611
- console.warn(
612
- "[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`."
613
- );
614
- }
615
- const api = typeof createState === "function" ? createStore(createState) : createState;
616
- const useBoundStore = (selector, equalityFn) => useStore(api, selector, equalityFn);
309
+ const api = createStore(createState);
310
+ const useBoundStore = (selector) => useStore(api, selector);
617
311
  Object.assign(useBoundStore, api);
618
312
  return useBoundStore;
619
313
  };
620
- const create = (createState) => createState ? createImpl(createState) : createImpl;
314
+ const create = ((createState) => createState ? createImpl(createState) : createImpl);
621
315
 
622
316
  // Estado: { user, loading, error }
623
317
  const useAuthStore = create((set, get) => ({
624
318
  user: null,
625
319
  loading: true,
626
320
  error: null,
321
+ // Loading states granulares
322
+ loadingStates: {
323
+ signIn: false,
324
+ signUp: false,
325
+ signOut: false,
326
+ magicLink: false,
327
+ verifyMagicLink: false,
328
+ resetPassword: false,
329
+ verifyEmail: false,
330
+ resendVerification: false
331
+ },
332
+ // Helper para atualizar loading states
333
+ setLoading: (key, value) => set(state => ({
334
+ loadingStates: {
335
+ ...state.loadingStates,
336
+ [key]: value
337
+ }
338
+ })),
627
339
  /* Init ao montar o Provider */
628
340
  init: async () => {
629
341
  try {
630
- // Verifica se há um token válido e obtém dados do usuário
342
+ // Verifica se há um token válido
631
343
  if (isAuthenticated()) {
632
- const user = getCurrentUser();
633
- set({
634
- user,
635
- loading: false
636
- });
344
+ // Tenta extrair usuário do token (JWT)
345
+ let user = getCurrentUser();
346
+
347
+ // Se o token for opaco (não-JWT), getCurrentUser retorna null.
348
+ // Precisamos buscar a sessão no servidor.
349
+ if (!user) {
350
+ try {
351
+ const session = await getSession();
352
+ if (session?.user) {
353
+ user = session.user;
354
+ }
355
+ } catch (sessionError) {
356
+ console.warn('[AuthStore] Failed to fetch session:', sessionError);
357
+ }
358
+ }
359
+ if (user) {
360
+ set({
361
+ user,
362
+ loading: false
363
+ });
364
+ } else {
365
+ set({
366
+ user: null,
367
+ loading: false
368
+ });
369
+ }
637
370
  } else {
638
371
  set({
639
372
  user: null,
@@ -648,57 +381,237 @@ const useAuthStore = create((set, get) => ({
648
381
  });
649
382
  }
650
383
  },
651
- /* Ações */
652
- signUp: async (email, password) => {
384
+ /* Ações de Autenticação */
385
+ signUp: async (email, password, name) => {
386
+ const {
387
+ setLoading
388
+ } = get();
389
+ setLoading('signUp', true);
653
390
  set({
654
- loading: true,
655
391
  error: null
656
392
  });
657
393
  try {
658
- const result = await signUp(email, password);
394
+ const result = await signUp(email, password, name);
659
395
  const user = getCurrentUser();
660
396
  set({
661
397
  user,
662
398
  loading: false
663
399
  });
400
+ setLoading('signUp', false);
664
401
  return result;
665
402
  } catch (err) {
666
403
  set({
667
- error: err,
668
- loading: false
404
+ error: err
669
405
  });
406
+ setLoading('signUp', false);
670
407
  throw err;
671
408
  }
672
409
  },
673
410
  signIn: async (email, password) => {
411
+ const {
412
+ setLoading
413
+ } = get();
414
+ setLoading('signIn', true);
674
415
  set({
675
- loading: true,
676
416
  error: null
677
417
  });
678
418
  try {
679
419
  const result = await signIn(email, password);
680
- const user = getCurrentUser();
420
+
421
+ // Tenta obter usuário do token (se JWT)
422
+ let user = getCurrentUser();
423
+
424
+ // Se não encontrou no token (sessão opaca), busca do servidor
425
+ if (!user) {
426
+ const session = await getSession();
427
+ if (session?.user) user = session.user;
428
+ }
681
429
  set({
682
430
  user,
683
431
  loading: false
684
432
  });
433
+ setLoading('signIn', false);
685
434
  return result;
686
435
  } catch (err) {
687
436
  set({
688
- error: err,
689
- loading: false
437
+ error: err
690
438
  });
439
+ setLoading('signIn', false);
691
440
  throw err;
692
441
  }
693
442
  },
694
443
  signOut: async () => {
695
- await signOut();
444
+ const {
445
+ setLoading
446
+ } = get();
447
+ setLoading('signOut', true);
448
+ try {
449
+ await signOut();
450
+ set({
451
+ user: null
452
+ });
453
+ // Sincronizar logout entre abas
454
+ if (typeof window !== 'undefined') {
455
+ window.localStorage.setItem('auth:logout', Date.now());
456
+ }
457
+ } finally {
458
+ setLoading('signOut', false);
459
+ }
460
+ },
461
+ /* Magic Link */
462
+ sendMagicLink: async (email, callbackURL) => {
463
+ const {
464
+ setLoading
465
+ } = get();
466
+ setLoading('magicLink', true);
696
467
  set({
697
- user: null
468
+ error: null
698
469
  });
699
- // Sincronizar logout entre abas
700
- if (typeof window !== 'undefined') {
701
- window.localStorage.setItem("auth:logout", Date.now());
470
+ try {
471
+ const result = await sendMagicLink(email, callbackURL);
472
+ setLoading('magicLink', false);
473
+ return result;
474
+ } catch (err) {
475
+ set({
476
+ error: err
477
+ });
478
+ setLoading('magicLink', false);
479
+ throw err;
480
+ }
481
+ },
482
+ verifyMagicLink: async token => {
483
+ const {
484
+ setLoading
485
+ } = get();
486
+ setLoading('verifyMagicLink', true);
487
+ set({
488
+ error: null
489
+ });
490
+ try {
491
+ const result = await verifyMagicLink(token);
492
+ let user = result.user;
493
+
494
+ // Se não veio no resultado, tenta pegar do token ou do servidor
495
+ if (!user) {
496
+ user = getCurrentUser();
497
+ if (!user) {
498
+ const session = await getSession();
499
+ if (session?.user) user = session.user;
500
+ }
501
+ }
502
+ if (user) {
503
+ set({
504
+ user,
505
+ loading: false
506
+ });
507
+ }
508
+ setLoading('verifyMagicLink', false);
509
+ return result;
510
+ } catch (err) {
511
+ set({
512
+ error: err
513
+ });
514
+ setLoading('verifyMagicLink', false);
515
+ throw err;
516
+ }
517
+ },
518
+ /* Password Reset */
519
+ forgotPassword: async (email, redirectTo) => {
520
+ const {
521
+ setLoading
522
+ } = get();
523
+ setLoading('resetPassword', true);
524
+ set({
525
+ error: null
526
+ });
527
+ try {
528
+ const result = await forgotPassword(email, redirectTo);
529
+ setLoading('resetPassword', false);
530
+ return result;
531
+ } catch (err) {
532
+ set({
533
+ error: err
534
+ });
535
+ setLoading('resetPassword', false);
536
+ throw err;
537
+ }
538
+ },
539
+ resetPassword: async (token, newPassword) => {
540
+ const {
541
+ setLoading
542
+ } = get();
543
+ setLoading('resetPassword', true);
544
+ set({
545
+ error: null
546
+ });
547
+ try {
548
+ const result = await resetPassword(token, newPassword);
549
+ setLoading('resetPassword', false);
550
+ return result;
551
+ } catch (err) {
552
+ set({
553
+ error: err
554
+ });
555
+ setLoading('resetPassword', false);
556
+ throw err;
557
+ }
558
+ },
559
+ /* Email Verification */
560
+ verifyEmail: async token => {
561
+ const {
562
+ setLoading
563
+ } = get();
564
+ setLoading('verifyEmail', true);
565
+ set({
566
+ error: null
567
+ });
568
+ try {
569
+ const result = await verifyEmail(token);
570
+ if (result.user) {
571
+ set({
572
+ user: result.user,
573
+ loading: false
574
+ });
575
+ }
576
+ setLoading('verifyEmail', false);
577
+ return result;
578
+ } catch (err) {
579
+ set({
580
+ error: err
581
+ });
582
+ setLoading('verifyEmail', false);
583
+ throw err;
584
+ }
585
+ },
586
+ resendVerification: async (email, callbackURL) => {
587
+ const {
588
+ setLoading
589
+ } = get();
590
+ setLoading('resendVerification', true);
591
+ set({
592
+ error: null
593
+ });
594
+ try {
595
+ const result = await resendVerification(email, callbackURL);
596
+ setLoading('resendVerification', false);
597
+ return result;
598
+ } catch (err) {
599
+ set({
600
+ error: err
601
+ });
602
+ setLoading('resendVerification', false);
603
+ throw err;
604
+ }
605
+ },
606
+ /* Session */
607
+ getSession: async () => {
608
+ try {
609
+ return await getSession();
610
+ } catch (err) {
611
+ set({
612
+ error: err
613
+ });
614
+ throw err;
702
615
  }
703
616
  },
704
617
  /* Refresh do token em background */
@@ -711,7 +624,10 @@ const useAuthStore = create((set, get) => ({
711
624
  const token = window.localStorage.getItem('auth:token');
712
625
  if (token) {
713
626
  // Decodifica o token para verificar tempo de expiração
714
- const payload = JSON.parse(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
627
+ const base64Url = token.split('.')[1];
628
+ const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
629
+ const jsonPayload = window.atob(base64);
630
+ const payload = JSON.parse(jsonPayload);
715
631
  const now = Date.now() / 1000;
716
632
  const timeUntilExpiry = payload.exp - now;
717
633
 
@@ -752,24 +668,48 @@ const useAuthStore = create((set, get) => ({
752
668
  return false;
753
669
  }
754
670
  return true;
755
- }
671
+ },
672
+ /* Atualizar usuário manualmente */
673
+ setUser: user => set({
674
+ user
675
+ })
756
676
  }));
757
677
 
758
- const AuthContext = /*#__PURE__*/require$$0.createContext(); // só para ter o Provider em JSX
678
+ const AuthContext = /*#__PURE__*/React$1.createContext(); // só para ter o Provider em JSX
759
679
 
760
680
  function AuthProvider({
761
- children
681
+ children,
682
+ apiUrl,
683
+ // URL base da API (OBRIGATÓRIA)
684
+ apiKey,
685
+ // API Key para header X-API-Key (OBRIGATÓRIA)
686
+ onError // Callback de erro global
762
687
  }) {
688
+ // Validação de props obrigatórias
689
+ if (!apiKey) {
690
+ throw new Error('[@riligar/auth-react] apiKey é obrigatória no AuthProvider. ' + 'Obtenha sua API Key no dashboard em https://dashboard.myauth.click');
691
+ }
692
+ if (!apiUrl) {
693
+ throw new Error('[@riligar/auth-react] apiUrl é obrigatória no AuthProvider. ' + 'Use a URL do seu servidor de autenticação.');
694
+ }
763
695
  const init = useAuthStore(s => s.init);
764
696
  const startRefresh = useAuthStore(s => s.startRefresh);
765
697
  const checkTokenValidity = useAuthStore(s => s.checkTokenValidity);
766
- require$$0.useEffect(() => {
698
+
699
+ // Configura SDK com apiUrl e apiKey
700
+ React$1.useEffect(() => {
701
+ configure({
702
+ apiUrl,
703
+ apiKey
704
+ });
705
+ }, [apiUrl, apiKey]);
706
+ React$1.useEffect(() => {
767
707
  init();
768
708
  startRefresh();
769
709
  }, [init, startRefresh]);
770
710
 
771
711
  // Sincronização entre abas - escuta logout e mudanças no token
772
- require$$0.useEffect(() => {
712
+ React$1.useEffect(() => {
773
713
  if (typeof window === 'undefined') return;
774
714
  const handleStorageChange = event => {
775
715
  if (event.key === 'auth:logout') {
@@ -785,7 +725,7 @@ function AuthProvider({
785
725
  }, [checkTokenValidity]);
786
726
 
787
727
  // Verifica validade do token periodicamente
788
- require$$0.useEffect(() => {
728
+ React$1.useEffect(() => {
789
729
  if (typeof window === 'undefined') return;
790
730
  const interval = setInterval(() => {
791
731
  checkTokenValidity();
@@ -793,8 +733,13 @@ function AuthProvider({
793
733
 
794
734
  return () => clearInterval(interval);
795
735
  }, [checkTokenValidity]);
736
+
737
+ // Contexto com onError callback
738
+ const contextValue = React$1.useMemo(() => ({
739
+ onError
740
+ }), [onError]);
796
741
  return /*#__PURE__*/React.createElement(AuthContext.Provider, {
797
- value: null /* valor irrelevante */
742
+ value: contextValue
798
743
  }, children);
799
744
  }
800
745
 
@@ -805,11 +750,74 @@ const useAuth = () => useAuthStore(s => ({
805
750
  error: s.error,
806
751
  isAuthenticated: s.user !== null
807
752
  }));
753
+
754
+ // Auth Actions
808
755
  const useSignIn = () => useAuthStore(s => s.signIn);
809
756
  const useSignUp = () => useAuthStore(s => s.signUp);
810
757
  const useSignOut = () => useAuthStore(s => s.signOut);
811
758
  const useCheckToken = () => useAuthStore(s => s.checkTokenValidity);
812
759
 
760
+ // Magic Link Hook
761
+ const useMagicLink = () => {
762
+ const sendMagicLink = useAuthStore(s => s.sendMagicLink);
763
+ const verifyMagicLink = useAuthStore(s => s.verifyMagicLink);
764
+ const loading = useAuthStore(s => s.loadingStates.magicLink);
765
+ const verifying = useAuthStore(s => s.loadingStates.verifyMagicLink);
766
+ const error = useAuthStore(s => s.error);
767
+ return {
768
+ sendMagicLink,
769
+ verifyMagicLink,
770
+ loading,
771
+ verifying,
772
+ error
773
+ };
774
+ };
775
+
776
+ // Password Reset Hook
777
+ const usePasswordReset = () => {
778
+ const forgotPassword = useAuthStore(s => s.forgotPassword);
779
+ const resetPassword = useAuthStore(s => s.resetPassword);
780
+ const loading = useAuthStore(s => s.loadingStates.resetPassword);
781
+ const error = useAuthStore(s => s.error);
782
+ return {
783
+ forgotPassword,
784
+ resetPassword,
785
+ loading,
786
+ error
787
+ };
788
+ };
789
+
790
+ // Email Verification Hook
791
+ const useEmailVerification = () => {
792
+ const verifyEmail = useAuthStore(s => s.verifyEmail);
793
+ const resendVerification = useAuthStore(s => s.resendVerification);
794
+ const loading = useAuthStore(s => s.loadingStates.verifyEmail);
795
+ const resending = useAuthStore(s => s.loadingStates.resendVerification);
796
+ const error = useAuthStore(s => s.error);
797
+ return {
798
+ verifyEmail,
799
+ resendVerification,
800
+ loading,
801
+ resending,
802
+ error
803
+ };
804
+ };
805
+
806
+ // Session Hook
807
+ const useSession = () => {
808
+ const getSession = useAuthStore(s => s.getSession);
809
+ const user = useAuthStore(s => s.user);
810
+ const setUser = useAuthStore(s => s.setUser);
811
+ return {
812
+ getSession,
813
+ user,
814
+ setUser
815
+ };
816
+ };
817
+
818
+ // Loading States Hook
819
+ const useAuthLoading = () => useAuthStore(s => s.loadingStates);
820
+
813
821
  function ProtectedRoute({
814
822
  fallback = /*#__PURE__*/React.createElement("p", null, "\u231B Carregando..."),
815
823
  redirectTo = "/login"
@@ -826,19 +834,822 @@ function ProtectedRoute({
826
834
  return /*#__PURE__*/React.createElement(reactRouterDom.Outlet, null);
827
835
  }
828
836
 
837
+ function _extends() {
838
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
839
+ for (var e = 1; e < arguments.length; e++) {
840
+ var t = arguments[e];
841
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
842
+ }
843
+ return n;
844
+ }, _extends.apply(null, arguments);
845
+ }
846
+
847
+ /**
848
+ * Container wrapper para componentes de autenticação
849
+ * Usa Mantine Paper com estilo consistente
850
+ */
851
+ function AuthCard({
852
+ children,
853
+ title,
854
+ subtitle,
855
+ logo,
856
+ logoHeight = 32,
857
+ width = 350,
858
+ ...props
859
+ }) {
860
+ return /*#__PURE__*/React.createElement(core.Paper, _extends({
861
+ withBorder: true,
862
+ shadow: "md",
863
+ p: 24,
864
+ w: width,
865
+ radius: "md"
866
+ }, props), /*#__PURE__*/React.createElement(core.Stack, {
867
+ gap: "sm"
868
+ }, (logo || title || subtitle) && /*#__PURE__*/React.createElement(core.Stack, {
869
+ gap: "xs"
870
+ }, logo && /*#__PURE__*/React.createElement(core.Image, {
871
+ src: logo,
872
+ alt: "Auth",
873
+ h: logoHeight,
874
+ fit: "contain"
875
+ }), title && /*#__PURE__*/React.createElement(core.Title, {
876
+ order: 3
877
+ }, title), subtitle && /*#__PURE__*/React.createElement(core.Text, {
878
+ size: "sm",
879
+ c: "dimmed"
880
+ }, subtitle)), children));
881
+ }
882
+
883
+ var img = "data:image/webp;base64,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";
884
+
885
+ /**
886
+ * Formulário de Sign In completo com Mantine
887
+ * Suporta email/password, magic link, social login
888
+ */
889
+ function SignInForm({
890
+ // Configuração
891
+ logo = img,
892
+ title = 'Entrar',
893
+ subtitle = 'Acesse sua conta para continuar',
894
+ // Features
895
+ showMagicLink = true,
896
+ showForgotPassword = true,
897
+ showSocialLogin = false,
898
+ showSignUpLink = true,
899
+ // Links
900
+ signUpUrl = '/auth/signup',
901
+ // Callbacks
902
+ onSuccess,
903
+ onError,
904
+ onMagicLinkSent,
905
+ onForgotPasswordSent,
906
+ onSocialLogin,
907
+ // Custom labels
908
+ labels = {},
909
+ ...cardProps
910
+ }) {
911
+ const signIn = useAuthStore(s => s.signIn);
912
+ const sendMagicLink = useAuthStore(s => s.sendMagicLink);
913
+ const forgotPassword = useAuthStore(s => s.forgotPassword);
914
+ const loadingSignIn = useAuthStore(s => s.loadingStates.signIn);
915
+ const loadingMagicLink = useAuthStore(s => s.loadingStates.magicLink);
916
+ const loadingResetPassword = useAuthStore(s => s.loadingStates.resetPassword);
917
+ const form$1 = form.useForm({
918
+ initialValues: {
919
+ email: '',
920
+ password: ''
921
+ },
922
+ validate: {
923
+ email: value => /^\S+@\S+$/.test(value) ? null : labels.invalidEmail || 'Email inválido',
924
+ password: value => value.length < 6 ? labels.passwordTooShort || 'A senha deve ter pelo menos 6 caracteres' : null
925
+ }
926
+ });
927
+ const handleSubmit = async values => {
928
+ try {
929
+ const result = await signIn(values.email, values.password);
930
+ onSuccess?.(result);
931
+ } catch (error) {
932
+ onError?.(error);
933
+ }
934
+ };
935
+ const handleMagicLink = async () => {
936
+ if (!form$1.values.email) {
937
+ form$1.setFieldError('email', labels.emailRequired || 'Email obrigatório');
938
+ return;
939
+ }
940
+ try {
941
+ await sendMagicLink(form$1.values.email);
942
+ onMagicLinkSent?.(form$1.values.email);
943
+ } catch (error) {
944
+ onError?.(error);
945
+ }
946
+ };
947
+ const handleForgotPassword = async () => {
948
+ if (!form$1.values.email) {
949
+ form$1.setFieldError('email', labels.emailRequired || 'Email obrigatório');
950
+ return;
951
+ }
952
+ try {
953
+ await forgotPassword(form$1.values.email);
954
+ onForgotPasswordSent?.(form$1.values.email);
955
+ } catch (error) {
956
+ onError?.(error);
957
+ }
958
+ };
959
+ const isLoading = loadingSignIn || loadingMagicLink || loadingResetPassword;
960
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
961
+ logo: logo,
962
+ title: title,
963
+ subtitle: subtitle
964
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
965
+ onSubmit: form$1.onSubmit(handleSubmit)
966
+ }, /*#__PURE__*/React.createElement(core.Stack, {
967
+ gap: "sm"
968
+ }, /*#__PURE__*/React.createElement(core.TextInput, _extends({
969
+ label: labels.email || 'Email',
970
+ placeholder: labels.emailPlaceholder || 'seu@email.com',
971
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
972
+ size: 16
973
+ })
974
+ }, form$1.getInputProps('email'), {
975
+ disabled: isLoading
976
+ })), /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
977
+ label: labels.password || 'Senha',
978
+ placeholder: labels.passwordPlaceholder || 'Sua senha',
979
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
980
+ size: 16
981
+ })
982
+ }, form$1.getInputProps('password'), {
983
+ disabled: isLoading
984
+ })), showForgotPassword && /*#__PURE__*/React.createElement(core.Anchor, {
985
+ size: "sm",
986
+ ta: "right",
987
+ onClick: handleForgotPassword,
988
+ style: {
989
+ cursor: 'pointer'
990
+ },
991
+ c: loadingResetPassword ? 'dimmed' : 'blue'
992
+ }, loadingResetPassword ? labels.sendingReset || 'Enviando...' : labels.forgotPassword || 'Esqueceu a senha?'), /*#__PURE__*/React.createElement(core.Button, {
993
+ type: "submit",
994
+ fullWidth: true,
995
+ loading: loadingSignIn,
996
+ rightSection: /*#__PURE__*/React.createElement(iconsReact.IconArrowRight, {
997
+ size: 16
998
+ })
999
+ }, labels.signInButton || 'Entrar'))), showMagicLink && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(core.Divider, {
1000
+ label: labels.orContinueWith || 'Ou continue com'
1001
+ }), /*#__PURE__*/React.createElement(core.Button, {
1002
+ variant: "light",
1003
+ fullWidth: true,
1004
+ loading: loadingMagicLink,
1005
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1006
+ size: 16
1007
+ }),
1008
+ onClick: handleMagicLink,
1009
+ disabled: isLoading || !form$1.values.email
1010
+ }, labels.magicLinkButton || 'Enviar Link Mágico')), showSocialLogin && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(core.Divider, null), /*#__PURE__*/React.createElement(core.Group, {
1011
+ grow: true
1012
+ }, /*#__PURE__*/React.createElement(core.Button, {
1013
+ variant: "light",
1014
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconBrandGoogle, {
1015
+ size: 16
1016
+ }),
1017
+ onClick: () => onSocialLogin?.('google'),
1018
+ disabled: isLoading
1019
+ }, "Google"), /*#__PURE__*/React.createElement(core.Button, {
1020
+ variant: "light",
1021
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconBrandGithub, {
1022
+ size: 16
1023
+ }),
1024
+ onClick: () => onSocialLogin?.('github'),
1025
+ disabled: isLoading
1026
+ }, "GitHub"))), showSignUpLink && /*#__PURE__*/React.createElement(core.Center, null, /*#__PURE__*/React.createElement(core.Text, {
1027
+ size: "sm",
1028
+ c: "dimmed"
1029
+ }, labels.noAccount || 'Não tem uma conta?', " ", /*#__PURE__*/React.createElement(core.Anchor, {
1030
+ href: signUpUrl
1031
+ }, labels.createAccount || 'Criar conta'))));
1032
+ }
1033
+
1034
+ /**
1035
+ * Formulário de Sign Up com Mantine
1036
+ */
1037
+ function SignUpForm({
1038
+ // Configuração
1039
+ logo = img,
1040
+ title = 'Criar Conta',
1041
+ subtitle = 'Preencha os dados para se cadastrar',
1042
+ // Features
1043
+ requireName = true,
1044
+ showSignInLink = true,
1045
+ showSocialLogin = false,
1046
+ // Links
1047
+ signInUrl = '/auth/signin',
1048
+ // Callbacks
1049
+ onSuccess,
1050
+ onError,
1051
+ onSocialLogin,
1052
+ // Custom labels
1053
+ labels = {},
1054
+ ...cardProps
1055
+ }) {
1056
+ const signUp = useAuthStore(s => s.signUp);
1057
+ const loading = useAuthStore(s => s.loadingStates.signUp);
1058
+ const form$1 = form.useForm({
1059
+ initialValues: {
1060
+ name: '',
1061
+ email: '',
1062
+ password: '',
1063
+ confirmPassword: ''
1064
+ },
1065
+ validate: {
1066
+ name: value => requireName && !value ? labels.nameRequired || 'Nome obrigatório' : null,
1067
+ email: value => /^\S+@\S+$/.test(value) ? null : labels.invalidEmail || 'Email inválido',
1068
+ password: value => value.length < 6 ? labels.passwordTooShort || 'A senha deve ter pelo menos 6 caracteres' : null,
1069
+ confirmPassword: (value, values) => value !== values.password ? labels.passwordMismatch || 'As senhas não coincidem' : null
1070
+ }
1071
+ });
1072
+ const handleSubmit = async values => {
1073
+ try {
1074
+ const result = await signUp(values.email, values.password, values.name);
1075
+ onSuccess?.(result);
1076
+ } catch (error) {
1077
+ onError?.(error);
1078
+ }
1079
+ };
1080
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1081
+ logo: logo,
1082
+ title: title,
1083
+ subtitle: subtitle
1084
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1085
+ onSubmit: form$1.onSubmit(handleSubmit)
1086
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1087
+ gap: "sm"
1088
+ }, requireName && /*#__PURE__*/React.createElement(core.TextInput, _extends({
1089
+ label: labels.name || 'Nome',
1090
+ placeholder: labels.namePlaceholder || 'Seu nome',
1091
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconUser, {
1092
+ size: 16
1093
+ })
1094
+ }, form$1.getInputProps('name'), {
1095
+ disabled: loading
1096
+ })), /*#__PURE__*/React.createElement(core.TextInput, _extends({
1097
+ label: labels.email || 'Email',
1098
+ placeholder: labels.emailPlaceholder || 'seu@email.com',
1099
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1100
+ size: 16
1101
+ })
1102
+ }, form$1.getInputProps('email'), {
1103
+ disabled: loading
1104
+ })), /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1105
+ label: labels.password || 'Senha',
1106
+ placeholder: labels.passwordPlaceholder || 'Crie uma senha',
1107
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1108
+ size: 16
1109
+ })
1110
+ }, form$1.getInputProps('password'), {
1111
+ disabled: loading
1112
+ })), /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1113
+ label: labels.confirmPassword || 'Confirmar Senha',
1114
+ placeholder: labels.confirmPasswordPlaceholder || 'Repita a senha',
1115
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1116
+ size: 16
1117
+ })
1118
+ }, form$1.getInputProps('confirmPassword'), {
1119
+ disabled: loading
1120
+ })), /*#__PURE__*/React.createElement(core.Button, {
1121
+ type: "submit",
1122
+ fullWidth: true,
1123
+ loading: loading,
1124
+ rightSection: /*#__PURE__*/React.createElement(iconsReact.IconArrowRight, {
1125
+ size: 16
1126
+ })
1127
+ }, labels.signUpButton || 'Criar Conta'))), showSocialLogin && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(core.Divider, {
1128
+ label: labels.orContinueWith || 'Ou continue com'
1129
+ }), /*#__PURE__*/React.createElement(core.Group, {
1130
+ grow: true
1131
+ }, /*#__PURE__*/React.createElement(core.Button, {
1132
+ variant: "light",
1133
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconBrandGoogle, {
1134
+ size: 16
1135
+ }),
1136
+ onClick: () => onSocialLogin?.('google'),
1137
+ disabled: loading
1138
+ }, "Google"), /*#__PURE__*/React.createElement(core.Button, {
1139
+ variant: "light",
1140
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconBrandGithub, {
1141
+ size: 16
1142
+ }),
1143
+ onClick: () => onSocialLogin?.('github'),
1144
+ disabled: loading
1145
+ }, "GitHub"))), showSignInLink && /*#__PURE__*/React.createElement(core.Center, null, /*#__PURE__*/React.createElement(core.Text, {
1146
+ size: "sm",
1147
+ c: "dimmed"
1148
+ }, labels.hasAccount || 'Já tem uma conta?', " ", /*#__PURE__*/React.createElement(core.Anchor, {
1149
+ href: signInUrl
1150
+ }, labels.signIn || 'Entrar'))));
1151
+ }
1152
+
1153
+ /**
1154
+ * Formulário para envio de Magic Link
1155
+ */
1156
+ function MagicLinkForm({
1157
+ // Configuração
1158
+ logo = img,
1159
+ title = 'Login sem Senha',
1160
+ subtitle = 'Receba um link de acesso no seu email',
1161
+ // Features
1162
+ showSignInLink = true,
1163
+ // Links
1164
+ signInUrl = '/auth/signin',
1165
+ // Callbacks
1166
+ onSent,
1167
+ onError,
1168
+ // Custom labels
1169
+ labels = {},
1170
+ ...cardProps
1171
+ }) {
1172
+ const sendMagicLink = useAuthStore(s => s.sendMagicLink);
1173
+ const loading = useAuthStore(s => s.loadingStates.magicLink);
1174
+ const form$1 = form.useForm({
1175
+ initialValues: {
1176
+ email: ''
1177
+ },
1178
+ validate: {
1179
+ email: value => /^\S+@\S+$/.test(value) ? null : labels.invalidEmail || 'Email inválido'
1180
+ }
1181
+ });
1182
+ const handleSubmit = async values => {
1183
+ try {
1184
+ await sendMagicLink(values.email);
1185
+ onSent?.(values.email);
1186
+ } catch (error) {
1187
+ onError?.(error);
1188
+ }
1189
+ };
1190
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1191
+ logo: logo,
1192
+ title: title,
1193
+ subtitle: subtitle
1194
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1195
+ onSubmit: form$1.onSubmit(handleSubmit)
1196
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1197
+ gap: "sm"
1198
+ }, /*#__PURE__*/React.createElement(core.TextInput, _extends({
1199
+ label: labels.email || 'Email',
1200
+ placeholder: labels.emailPlaceholder || 'seu@email.com',
1201
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1202
+ size: 16
1203
+ })
1204
+ }, form$1.getInputProps('email'), {
1205
+ disabled: loading
1206
+ })), /*#__PURE__*/React.createElement(core.Button, {
1207
+ type: "submit",
1208
+ fullWidth: true,
1209
+ loading: loading,
1210
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconSend, {
1211
+ size: 16
1212
+ })
1213
+ }, labels.sendButton || 'Enviar Link Mágico'))), showSignInLink && /*#__PURE__*/React.createElement(core.Center, null, /*#__PURE__*/React.createElement(core.Text, {
1214
+ size: "sm",
1215
+ c: "dimmed"
1216
+ }, labels.backTo || 'Voltar para', " ", /*#__PURE__*/React.createElement(core.Anchor, {
1217
+ href: signInUrl
1218
+ }, labels.signIn || 'login com senha'))));
1219
+ }
1220
+
1221
+ /**
1222
+ * Componente de verificação de Magic Link
1223
+ * Extrai token da URL e verifica automaticamente
1224
+ */
1225
+ function MagicLinkVerify({
1226
+ // Configuração
1227
+ logo = img,
1228
+ // Token pode ser passado diretamente ou extraído da URL
1229
+ token: propToken,
1230
+ // Callbacks
1231
+ onSuccess,
1232
+ onError,
1233
+ // Redirect após sucesso/erro
1234
+ redirectTo,
1235
+ redirectDelay = 2000,
1236
+ // Custom labels
1237
+ labels = {},
1238
+ ...cardProps
1239
+ }) {
1240
+ const [status, setStatus] = React$1.useState('verifying'); // verifying, success, error
1241
+ const [errorMessage, setErrorMessage] = React$1.useState('');
1242
+ const verifyMagicLink = useAuthStore(s => s.verifyMagicLink);
1243
+ React$1.useEffect(() => {
1244
+ const verify = async () => {
1245
+ // Pega token da prop ou da URL
1246
+ let token = propToken;
1247
+ if (!token && typeof window !== 'undefined') {
1248
+ const urlParams = new URLSearchParams(window.location.search);
1249
+ token = urlParams.get('token');
1250
+ }
1251
+ if (!token) {
1252
+ setStatus('error');
1253
+ setErrorMessage(labels.noToken || 'Token não encontrado na URL');
1254
+ onError?.(new Error('No token'));
1255
+ return;
1256
+ }
1257
+ try {
1258
+ const result = await verifyMagicLink(token);
1259
+ setStatus('success');
1260
+ onSuccess?.(result);
1261
+ if (redirectTo) {
1262
+ setTimeout(() => {
1263
+ window.location.href = redirectTo;
1264
+ }, redirectDelay);
1265
+ }
1266
+ } catch (error) {
1267
+ setStatus('error');
1268
+ setErrorMessage(error.message || labels.verificationFailed || 'Verificação falhou');
1269
+ onError?.(error);
1270
+ }
1271
+ };
1272
+ verify();
1273
+ }, [propToken, verifyMagicLink, onSuccess, onError, redirectTo, redirectDelay, labels]);
1274
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1275
+ logo: logo
1276
+ }, cardProps), status === 'verifying' && /*#__PURE__*/React.createElement(core.Stack, {
1277
+ align: "center",
1278
+ gap: "sm"
1279
+ }, /*#__PURE__*/React.createElement(core.Loader, {
1280
+ size: "lg"
1281
+ }), /*#__PURE__*/React.createElement(core.Title, {
1282
+ order: 4
1283
+ }, labels.verifying || 'Verificando Link Mágico'), /*#__PURE__*/React.createElement(core.Text, {
1284
+ size: "sm",
1285
+ c: "dimmed",
1286
+ ta: "center"
1287
+ }, labels.pleaseWait || 'Aguarde enquanto autenticamos você...')), status === 'success' && /*#__PURE__*/React.createElement(core.Stack, {
1288
+ align: "center",
1289
+ gap: "sm"
1290
+ }, /*#__PURE__*/React.createElement(iconsReact.IconCheck, {
1291
+ size: 48,
1292
+ color: "var(--mantine-color-green-6)"
1293
+ }), /*#__PURE__*/React.createElement(core.Title, {
1294
+ order: 4
1295
+ }, labels.success || 'Autenticado com Sucesso!'), /*#__PURE__*/React.createElement(core.Text, {
1296
+ size: "sm",
1297
+ c: "dimmed",
1298
+ ta: "center"
1299
+ }, redirectTo ? labels.redirecting || 'Redirecionando...' : labels.authenticated || 'Você está autenticado.')), status === 'error' && /*#__PURE__*/React.createElement(core.Stack, {
1300
+ align: "center",
1301
+ gap: "sm"
1302
+ }, /*#__PURE__*/React.createElement(iconsReact.IconX, {
1303
+ size: 48,
1304
+ color: "var(--mantine-color-red-6)"
1305
+ }), /*#__PURE__*/React.createElement(core.Title, {
1306
+ order: 4
1307
+ }, labels.failed || 'Falha na Autenticação'), /*#__PURE__*/React.createElement(core.Text, {
1308
+ size: "sm",
1309
+ c: "dimmed",
1310
+ ta: "center"
1311
+ }, errorMessage || labels.invalidLink || 'O link é inválido ou expirou.')));
1312
+ }
1313
+
1314
+ /**
1315
+ * Formulário para solicitar reset de senha
1316
+ */
1317
+ function ForgotPasswordForm({
1318
+ // Configuração
1319
+ logo = img,
1320
+ title = 'Recuperar Senha',
1321
+ subtitle = 'Enviaremos um link para redefinir sua senha',
1322
+ // Features
1323
+ showSignInLink = true,
1324
+ // Links
1325
+ signInUrl = '/auth/signin',
1326
+ // Callbacks
1327
+ onSent,
1328
+ onError,
1329
+ // Custom labels
1330
+ labels = {},
1331
+ ...cardProps
1332
+ }) {
1333
+ const forgotPassword = useAuthStore(s => s.forgotPassword);
1334
+ const loading = useAuthStore(s => s.loadingStates.resetPassword);
1335
+ const form$1 = form.useForm({
1336
+ initialValues: {
1337
+ email: ''
1338
+ },
1339
+ validate: {
1340
+ email: value => /^\S+@\S+$/.test(value) ? null : labels.invalidEmail || 'Email inválido'
1341
+ }
1342
+ });
1343
+ const handleSubmit = async values => {
1344
+ try {
1345
+ await forgotPassword(values.email);
1346
+ onSent?.(values.email);
1347
+ } catch (error) {
1348
+ onError?.(error);
1349
+ }
1350
+ };
1351
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1352
+ logo: logo,
1353
+ title: title,
1354
+ subtitle: subtitle
1355
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1356
+ onSubmit: form$1.onSubmit(handleSubmit)
1357
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1358
+ gap: "sm"
1359
+ }, /*#__PURE__*/React.createElement(core.TextInput, _extends({
1360
+ label: labels.email || 'Email',
1361
+ placeholder: labels.emailPlaceholder || 'seu@email.com',
1362
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1363
+ size: 16
1364
+ })
1365
+ }, form$1.getInputProps('email'), {
1366
+ disabled: loading
1367
+ })), /*#__PURE__*/React.createElement(core.Button, {
1368
+ type: "submit",
1369
+ fullWidth: true,
1370
+ loading: loading,
1371
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconSend, {
1372
+ size: 16
1373
+ })
1374
+ }, labels.sendButton || 'Enviar Link de Recuperação'))), showSignInLink && /*#__PURE__*/React.createElement(core.Center, null, /*#__PURE__*/React.createElement(core.Text, {
1375
+ size: "sm",
1376
+ c: "dimmed"
1377
+ }, labels.rememberedPassword || 'Lembrou a senha?', " ", /*#__PURE__*/React.createElement(core.Anchor, {
1378
+ href: signInUrl
1379
+ }, labels.signIn || 'Entrar'))));
1380
+ }
1381
+
1382
+ /**
1383
+ * Formulário para redefinir senha com token
1384
+ */
1385
+ function ResetPasswordForm({
1386
+ // Configuração
1387
+ logo = img,
1388
+ title = 'Nova Senha',
1389
+ subtitle = 'Crie uma nova senha para sua conta',
1390
+ // Token pode ser passado diretamente ou extraído da URL
1391
+ token: propToken,
1392
+ // Callbacks
1393
+ onSuccess,
1394
+ onError,
1395
+ // Redirect após sucesso
1396
+ signInUrl = '/auth/signin',
1397
+ // Custom labels
1398
+ labels = {},
1399
+ ...cardProps
1400
+ }) {
1401
+ const [token, setToken] = React$1.useState(propToken || '');
1402
+ const [success, setSuccess] = React$1.useState(false);
1403
+ const resetPassword = useAuthStore(s => s.resetPassword);
1404
+ const loading = useAuthStore(s => s.loadingStates.resetPassword);
1405
+
1406
+ // Extrai token da URL se não foi passado como prop
1407
+ React$1.useEffect(() => {
1408
+ if (!propToken && typeof window !== 'undefined') {
1409
+ const urlParams = new URLSearchParams(window.location.search);
1410
+ const urlToken = urlParams.get('token');
1411
+ if (urlToken) setToken(urlToken);
1412
+ }
1413
+ }, [propToken]);
1414
+ const form$1 = form.useForm({
1415
+ initialValues: {
1416
+ password: '',
1417
+ confirmPassword: ''
1418
+ },
1419
+ validate: {
1420
+ password: value => value.length < 6 ? labels.passwordTooShort || 'A senha deve ter pelo menos 6 caracteres' : null,
1421
+ confirmPassword: (value, values) => value !== values.password ? labels.passwordMismatch || 'As senhas não coincidem' : null
1422
+ }
1423
+ });
1424
+ const handleSubmit = async values => {
1425
+ if (!token) {
1426
+ onError?.(new Error('Token não encontrado'));
1427
+ return;
1428
+ }
1429
+ try {
1430
+ await resetPassword(token, values.password);
1431
+ setSuccess(true);
1432
+ onSuccess?.();
1433
+ } catch (error) {
1434
+ onError?.(error);
1435
+ }
1436
+ };
1437
+ if (success) {
1438
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1439
+ logo: logo
1440
+ }, cardProps), /*#__PURE__*/React.createElement(core.Stack, {
1441
+ align: "center",
1442
+ gap: "sm"
1443
+ }, /*#__PURE__*/React.createElement(iconsReact.IconCheck, {
1444
+ size: 48,
1445
+ color: "var(--mantine-color-green-6)"
1446
+ }), /*#__PURE__*/React.createElement(core.Title, {
1447
+ order: 4
1448
+ }, labels.successTitle || 'Senha Redefinida!'), /*#__PURE__*/React.createElement(core.Text, {
1449
+ size: "sm",
1450
+ c: "dimmed",
1451
+ ta: "center"
1452
+ }, labels.successMessage || 'Sua senha foi alterada com sucesso.'), /*#__PURE__*/React.createElement(core.Button, {
1453
+ component: "a",
1454
+ href: signInUrl,
1455
+ fullWidth: true
1456
+ }, labels.goToSignIn || 'Ir para Login')));
1457
+ }
1458
+ if (!token) {
1459
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1460
+ logo: logo
1461
+ }, cardProps), /*#__PURE__*/React.createElement(core.Stack, {
1462
+ align: "center",
1463
+ gap: "sm"
1464
+ }, /*#__PURE__*/React.createElement(core.Text, {
1465
+ c: "red"
1466
+ }, labels.noToken || 'Token não encontrado na URL'), /*#__PURE__*/React.createElement(core.Button, {
1467
+ component: "a",
1468
+ href: signInUrl,
1469
+ variant: "light",
1470
+ fullWidth: true
1471
+ }, labels.goToSignIn || 'Voltar para Login')));
1472
+ }
1473
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1474
+ logo: logo,
1475
+ title: title,
1476
+ subtitle: subtitle
1477
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1478
+ onSubmit: form$1.onSubmit(handleSubmit)
1479
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1480
+ gap: "sm"
1481
+ }, /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1482
+ label: labels.newPassword || 'Nova Senha',
1483
+ placeholder: labels.newPasswordPlaceholder || 'Crie uma nova senha',
1484
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1485
+ size: 16
1486
+ })
1487
+ }, form$1.getInputProps('password'), {
1488
+ disabled: loading
1489
+ })), /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1490
+ label: labels.confirmPassword || 'Confirmar Senha',
1491
+ placeholder: labels.confirmPasswordPlaceholder || 'Repita a nova senha',
1492
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1493
+ size: 16
1494
+ })
1495
+ }, form$1.getInputProps('confirmPassword'), {
1496
+ disabled: loading
1497
+ })), /*#__PURE__*/React.createElement(core.Button, {
1498
+ type: "submit",
1499
+ fullWidth: true,
1500
+ loading: loading
1501
+ }, labels.resetButton || 'Redefinir Senha'))));
1502
+ }
1503
+
1504
+ /**
1505
+ * Card de verificação de email
1506
+ * Verifica token automaticamente e permite reenvio
1507
+ */
1508
+ function VerifyEmailCard({
1509
+ // Configuração
1510
+ logo = img,
1511
+ // Token pode ser passado diretamente ou extraído da URL
1512
+ token: propToken,
1513
+ // Email para reenvio (opcional)
1514
+ email,
1515
+ // Callbacks
1516
+ onSuccess,
1517
+ onError,
1518
+ onResent,
1519
+ // Redirect após sucesso
1520
+ redirectTo,
1521
+ redirectDelay = 2000,
1522
+ // Custom labels
1523
+ labels = {},
1524
+ ...cardProps
1525
+ }) {
1526
+ const [status, setStatus] = React$1.useState('verifying'); // verifying, success, error
1527
+ const [errorMessage, setErrorMessage] = React$1.useState('');
1528
+ const verifyEmail = useAuthStore(s => s.verifyEmail);
1529
+ const resendVerification = useAuthStore(s => s.resendVerification);
1530
+ const loadingResend = useAuthStore(s => s.loadingStates.resendVerification);
1531
+ React$1.useEffect(() => {
1532
+ const verify = async () => {
1533
+ // Pega token da prop ou da URL
1534
+ let token = propToken;
1535
+ if (!token && typeof window !== 'undefined') {
1536
+ const urlParams = new URLSearchParams(window.location.search);
1537
+ token = urlParams.get('token');
1538
+ }
1539
+ if (!token) {
1540
+ setStatus('error');
1541
+ setErrorMessage(labels.noToken || 'Token não encontrado na URL');
1542
+ onError?.(new Error('No token'));
1543
+ return;
1544
+ }
1545
+ try {
1546
+ const result = await verifyEmail(token);
1547
+ setStatus('success');
1548
+ onSuccess?.(result);
1549
+ if (redirectTo) {
1550
+ setTimeout(() => {
1551
+ window.location.href = redirectTo;
1552
+ }, redirectDelay);
1553
+ }
1554
+ } catch (error) {
1555
+ setStatus('error');
1556
+ setErrorMessage(error.message || labels.verificationFailed || 'Verificação falhou');
1557
+ onError?.(error);
1558
+ }
1559
+ };
1560
+ verify();
1561
+ }, [propToken, verifyEmail, onSuccess, onError, redirectTo, redirectDelay, labels]);
1562
+ const handleResend = async () => {
1563
+ if (!email) return;
1564
+ try {
1565
+ await resendVerification(email);
1566
+ onResent?.(email);
1567
+ } catch (error) {
1568
+ onError?.(error);
1569
+ }
1570
+ };
1571
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1572
+ logo: logo
1573
+ }, cardProps), status === 'verifying' && /*#__PURE__*/React.createElement(core.Stack, {
1574
+ align: "center",
1575
+ gap: "sm"
1576
+ }, /*#__PURE__*/React.createElement(core.Loader, {
1577
+ size: "lg"
1578
+ }), /*#__PURE__*/React.createElement(core.Title, {
1579
+ order: 4
1580
+ }, labels.verifying || 'Verificando Email'), /*#__PURE__*/React.createElement(core.Text, {
1581
+ size: "sm",
1582
+ c: "dimmed",
1583
+ ta: "center"
1584
+ }, labels.pleaseWait || 'Aguarde enquanto verificamos seu email...')), status === 'success' && /*#__PURE__*/React.createElement(core.Stack, {
1585
+ align: "center",
1586
+ gap: "sm"
1587
+ }, /*#__PURE__*/React.createElement(iconsReact.IconCheck, {
1588
+ size: 48,
1589
+ color: "var(--mantine-color-green-6)"
1590
+ }), /*#__PURE__*/React.createElement(core.Title, {
1591
+ order: 4
1592
+ }, labels.success || 'Email Verificado!'), /*#__PURE__*/React.createElement(core.Text, {
1593
+ size: "sm",
1594
+ c: "dimmed",
1595
+ ta: "center"
1596
+ }, redirectTo ? labels.redirecting || 'Redirecionando...' : labels.verified || 'Seu email foi verificado com sucesso.')), status === 'error' && /*#__PURE__*/React.createElement(core.Stack, {
1597
+ align: "center",
1598
+ gap: "sm"
1599
+ }, /*#__PURE__*/React.createElement(iconsReact.IconX, {
1600
+ size: 48,
1601
+ color: "var(--mantine-color-red-6)"
1602
+ }), /*#__PURE__*/React.createElement(core.Title, {
1603
+ order: 4
1604
+ }, labels.failed || 'Verificação Falhou'), /*#__PURE__*/React.createElement(core.Text, {
1605
+ size: "sm",
1606
+ c: "dimmed",
1607
+ ta: "center"
1608
+ }, errorMessage || labels.invalidToken || 'O link é inválido ou expirou.'), email && /*#__PURE__*/React.createElement(core.Button, {
1609
+ variant: "light",
1610
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconRefresh, {
1611
+ size: 16
1612
+ }),
1613
+ onClick: handleResend,
1614
+ loading: loadingResend,
1615
+ fullWidth: true
1616
+ }, labels.resend || 'Reenviar Email de Verificação')));
1617
+ }
1618
+
1619
+ exports.AuthCard = AuthCard;
829
1620
  exports.AuthProvider = AuthProvider;
1621
+ exports.ForgotPasswordForm = ForgotPasswordForm;
1622
+ exports.MagicLinkForm = MagicLinkForm;
1623
+ exports.MagicLinkVerify = MagicLinkVerify;
830
1624
  exports.ProtectedRoute = ProtectedRoute;
1625
+ exports.ResetPasswordForm = ResetPasswordForm;
1626
+ exports.SignInForm = SignInForm;
1627
+ exports.SignUpForm = SignUpForm;
1628
+ exports.VerifyEmailCard = VerifyEmailCard;
1629
+ exports.configure = configure;
1630
+ exports.forgotPassword = forgotPassword;
831
1631
  exports.getCurrentUser = getCurrentUser;
1632
+ exports.getSession = getSession;
832
1633
  exports.isAuthenticated = isAuthenticated;
833
1634
  exports.refreshToken = refreshToken;
1635
+ exports.resendVerification = resendVerification;
1636
+ exports.resetPassword = resetPassword;
1637
+ exports.sendMagicLink = sendMagicLink;
834
1638
  exports.signIn = signIn;
835
1639
  exports.signOut = signOut;
836
1640
  exports.signUp = signUp;
837
1641
  exports.socialRedirect = socialRedirect;
838
1642
  exports.useAuth = useAuth;
1643
+ exports.useAuthLoading = useAuthLoading;
839
1644
  exports.useAuthStore = useAuthStore;
840
1645
  exports.useCheckToken = useCheckToken;
1646
+ exports.useEmailVerification = useEmailVerification;
1647
+ exports.useMagicLink = useMagicLink;
1648
+ exports.usePasswordReset = usePasswordReset;
1649
+ exports.useSession = useSession;
841
1650
  exports.useSignIn = useSignIn;
842
1651
  exports.useSignOut = useSignOut;
843
1652
  exports.useSignUp = useSignUp;
1653
+ exports.verifyEmail = verifyEmail;
1654
+ exports.verifyMagicLink = verifyMagicLink;
844
1655
  //# sourceMappingURL=index.js.map