@riligar/auth-react 1.2.0 → 1.4.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
- }
296
+ const createStore = ((createState) => createState ? createStoreImpl(createState) : createStoreImpl);
262
297
 
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);
587
-
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,110 @@ 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(); // para ter o Provider em JSX
678
+ const isIterable = (obj) => Symbol.iterator in obj;
679
+ const hasIterableEntries = (value) => (
680
+ // HACK: avoid checking entries type
681
+ "entries" in value
682
+ );
683
+ const compareEntries = (valueA, valueB) => {
684
+ const mapA = valueA instanceof Map ? valueA : new Map(valueA.entries());
685
+ const mapB = valueB instanceof Map ? valueB : new Map(valueB.entries());
686
+ if (mapA.size !== mapB.size) {
687
+ return false;
688
+ }
689
+ for (const [key, value] of mapA) {
690
+ if (!mapB.has(key) || !Object.is(value, mapB.get(key))) {
691
+ return false;
692
+ }
693
+ }
694
+ return true;
695
+ };
696
+ const compareIterables = (valueA, valueB) => {
697
+ const iteratorA = valueA[Symbol.iterator]();
698
+ const iteratorB = valueB[Symbol.iterator]();
699
+ let nextA = iteratorA.next();
700
+ let nextB = iteratorB.next();
701
+ while (!nextA.done && !nextB.done) {
702
+ if (!Object.is(nextA.value, nextB.value)) {
703
+ return false;
704
+ }
705
+ nextA = iteratorA.next();
706
+ nextB = iteratorB.next();
707
+ }
708
+ return !!nextA.done && !!nextB.done;
709
+ };
710
+ function shallow(valueA, valueB) {
711
+ if (Object.is(valueA, valueB)) {
712
+ return true;
713
+ }
714
+ if (typeof valueA !== "object" || valueA === null || typeof valueB !== "object" || valueB === null) {
715
+ return false;
716
+ }
717
+ if (Object.getPrototypeOf(valueA) !== Object.getPrototypeOf(valueB)) {
718
+ return false;
719
+ }
720
+ if (isIterable(valueA) && isIterable(valueB)) {
721
+ if (hasIterableEntries(valueA) && hasIterableEntries(valueB)) {
722
+ return compareEntries(valueA, valueB);
723
+ }
724
+ return compareIterables(valueA, valueB);
725
+ }
726
+ return compareEntries(
727
+ { entries: () => Object.entries(valueA) },
728
+ { entries: () => Object.entries(valueB) }
729
+ );
730
+ }
731
+
732
+ function useShallow(selector) {
733
+ const prev = React$1.useRef(void 0);
734
+ return (state) => {
735
+ const next = selector(state);
736
+ return shallow(prev.current, next) ? prev.current : prev.current = next;
737
+ };
738
+ }
739
+
740
+ const AuthContext = /*#__PURE__*/React$1.createContext(); // só para ter o Provider em JSX
759
741
 
760
742
  function AuthProvider({
761
- children
743
+ children,
744
+ apiUrl,
745
+ // URL base da API (OBRIGATÓRIA)
746
+ apiKey,
747
+ // API Key para header X-API-Key (OBRIGATÓRIA)
748
+ onError // Callback de erro global
762
749
  }) {
750
+ // Validação de props obrigatórias
751
+ if (!apiKey) {
752
+ throw new Error('[@riligar/auth-react] apiKey é obrigatória no AuthProvider. ' + 'Obtenha sua API Key no dashboard em https://dashboard.myauth.click');
753
+ }
754
+ if (!apiUrl) {
755
+ throw new Error('[@riligar/auth-react] apiUrl é obrigatória no AuthProvider. ' + 'Use a URL do seu servidor de autenticação.');
756
+ }
763
757
  const init = useAuthStore(s => s.init);
764
758
  const startRefresh = useAuthStore(s => s.startRefresh);
765
759
  const checkTokenValidity = useAuthStore(s => s.checkTokenValidity);
766
- require$$0.useEffect(() => {
760
+
761
+ // Configura SDK com apiUrl e apiKey
762
+ React$1.useEffect(() => {
763
+ configure({
764
+ apiUrl,
765
+ apiKey
766
+ });
767
+ }, [apiUrl, apiKey]);
768
+ React$1.useEffect(() => {
767
769
  init();
768
770
  startRefresh();
769
771
  }, [init, startRefresh]);
770
772
 
771
773
  // Sincronização entre abas - escuta logout e mudanças no token
772
- require$$0.useEffect(() => {
774
+ React$1.useEffect(() => {
773
775
  if (typeof window === 'undefined') return;
774
776
  const handleStorageChange = event => {
775
777
  if (event.key === 'auth:logout') {
@@ -785,7 +787,7 @@ function AuthProvider({
785
787
  }, [checkTokenValidity]);
786
788
 
787
789
  // Verifica validade do token periodicamente
788
- require$$0.useEffect(() => {
790
+ React$1.useEffect(() => {
789
791
  if (typeof window === 'undefined') return;
790
792
  const interval = setInterval(() => {
791
793
  checkTokenValidity();
@@ -793,23 +795,66 @@ function AuthProvider({
793
795
 
794
796
  return () => clearInterval(interval);
795
797
  }, [checkTokenValidity]);
798
+
799
+ // Contexto com onError callback
800
+ const contextValue = React$1.useMemo(() => ({
801
+ onError
802
+ }), [onError]);
796
803
  return /*#__PURE__*/React.createElement(AuthContext.Provider, {
797
- value: null /* valor irrelevante */
804
+ value: contextValue
798
805
  }, children);
799
806
  }
800
807
 
801
808
  /* Hooks "facade" que a app vai usar */
802
- const useAuth = () => useAuthStore(s => ({
809
+ const useAuth = () => useAuthStore(useShallow(s => ({
803
810
  user: s.user,
804
811
  loading: s.loading,
805
812
  error: s.error,
806
813
  isAuthenticated: s.user !== null
807
- }));
814
+ })));
815
+
816
+ // Auth Actions
808
817
  const useSignIn = () => useAuthStore(s => s.signIn);
809
818
  const useSignUp = () => useAuthStore(s => s.signUp);
810
819
  const useSignOut = () => useAuthStore(s => s.signOut);
811
820
  const useCheckToken = () => useAuthStore(s => s.checkTokenValidity);
812
821
 
822
+ // Magic Link Hook
823
+ const useMagicLink = () => useAuthStore(useShallow(s => ({
824
+ sendMagicLink: s.sendMagicLink,
825
+ verifyMagicLink: s.verifyMagicLink,
826
+ loading: s.loadingStates.magicLink,
827
+ verifying: s.loadingStates.verifyMagicLink,
828
+ error: s.error
829
+ })));
830
+
831
+ // Password Reset Hook
832
+ const usePasswordReset = () => useAuthStore(useShallow(s => ({
833
+ forgotPassword: s.forgotPassword,
834
+ resetPassword: s.resetPassword,
835
+ loading: s.loadingStates.resetPassword,
836
+ error: s.error
837
+ })));
838
+
839
+ // Email Verification Hook
840
+ const useEmailVerification = () => useAuthStore(useShallow(s => ({
841
+ verifyEmail: s.verifyEmail,
842
+ resendVerification: s.resendVerification,
843
+ loading: s.loadingStates.verifyEmail,
844
+ resending: s.loadingStates.resendVerification,
845
+ error: s.error
846
+ })));
847
+
848
+ // Session Hook
849
+ const useSession = () => useAuthStore(useShallow(s => ({
850
+ getSession: s.getSession,
851
+ user: s.user,
852
+ setUser: s.setUser
853
+ })));
854
+
855
+ // Loading States Hook
856
+ const useAuthLoading = () => useAuthStore(s => s.loadingStates);
857
+
813
858
  function ProtectedRoute({
814
859
  fallback = /*#__PURE__*/React.createElement("p", null, "\u231B Carregando..."),
815
860
  redirectTo = "/login"
@@ -826,19 +871,822 @@ function ProtectedRoute({
826
871
  return /*#__PURE__*/React.createElement(reactRouterDom.Outlet, null);
827
872
  }
828
873
 
874
+ function _extends() {
875
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
876
+ for (var e = 1; e < arguments.length; e++) {
877
+ var t = arguments[e];
878
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
879
+ }
880
+ return n;
881
+ }, _extends.apply(null, arguments);
882
+ }
883
+
884
+ /**
885
+ * Container wrapper para componentes de autenticação
886
+ * Usa Mantine Paper com estilo consistente
887
+ */
888
+ function AuthCard({
889
+ children,
890
+ title,
891
+ subtitle,
892
+ logo,
893
+ logoHeight = 32,
894
+ width = 350,
895
+ ...props
896
+ }) {
897
+ return /*#__PURE__*/React.createElement(core.Paper, _extends({
898
+ withBorder: true,
899
+ shadow: "md",
900
+ p: 24,
901
+ w: width,
902
+ radius: "md"
903
+ }, props), /*#__PURE__*/React.createElement(core.Stack, {
904
+ gap: "sm"
905
+ }, (logo || title || subtitle) && /*#__PURE__*/React.createElement(core.Stack, {
906
+ gap: "xs"
907
+ }, logo && /*#__PURE__*/React.createElement(core.Image, {
908
+ src: logo,
909
+ alt: "Auth",
910
+ h: logoHeight,
911
+ fit: "contain"
912
+ }), title && /*#__PURE__*/React.createElement(core.Title, {
913
+ order: 3
914
+ }, title), subtitle && /*#__PURE__*/React.createElement(core.Text, {
915
+ size: "sm",
916
+ c: "dimmed"
917
+ }, subtitle)), children));
918
+ }
919
+
920
+ var img = "data:image/webp;base64,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";
921
+
922
+ /**
923
+ * Formulário de Sign In completo com Mantine
924
+ * Suporta email/password, magic link, social login
925
+ */
926
+ function SignInForm({
927
+ // Configuração
928
+ logo = img,
929
+ title = 'Entrar',
930
+ subtitle = 'Acesse sua conta para continuar',
931
+ // Features
932
+ showMagicLink = true,
933
+ showForgotPassword = true,
934
+ showSocialLogin = false,
935
+ showSignUpLink = true,
936
+ // Links
937
+ signUpUrl = '/auth/signup',
938
+ // Callbacks
939
+ onSuccess,
940
+ onError,
941
+ onMagicLinkSent,
942
+ onForgotPasswordSent,
943
+ onSocialLogin,
944
+ // Custom labels
945
+ labels = {},
946
+ ...cardProps
947
+ }) {
948
+ const signIn = useAuthStore(s => s.signIn);
949
+ const sendMagicLink = useAuthStore(s => s.sendMagicLink);
950
+ const forgotPassword = useAuthStore(s => s.forgotPassword);
951
+ const loadingSignIn = useAuthStore(s => s.loadingStates.signIn);
952
+ const loadingMagicLink = useAuthStore(s => s.loadingStates.magicLink);
953
+ const loadingResetPassword = useAuthStore(s => s.loadingStates.resetPassword);
954
+ const form$1 = form.useForm({
955
+ initialValues: {
956
+ email: '',
957
+ password: ''
958
+ },
959
+ validate: {
960
+ email: value => /^\S+@\S+$/.test(value) ? null : labels.invalidEmail || 'Email inválido',
961
+ password: value => value.length < 6 ? labels.passwordTooShort || 'A senha deve ter pelo menos 6 caracteres' : null
962
+ }
963
+ });
964
+ const handleSubmit = async values => {
965
+ try {
966
+ const result = await signIn(values.email, values.password);
967
+ onSuccess?.(result);
968
+ } catch (error) {
969
+ onError?.(error);
970
+ }
971
+ };
972
+ const handleMagicLink = async () => {
973
+ if (!form$1.values.email) {
974
+ form$1.setFieldError('email', labels.emailRequired || 'Email obrigatório');
975
+ return;
976
+ }
977
+ try {
978
+ await sendMagicLink(form$1.values.email);
979
+ onMagicLinkSent?.(form$1.values.email);
980
+ } catch (error) {
981
+ onError?.(error);
982
+ }
983
+ };
984
+ const handleForgotPassword = async () => {
985
+ if (!form$1.values.email) {
986
+ form$1.setFieldError('email', labels.emailRequired || 'Email obrigatório');
987
+ return;
988
+ }
989
+ try {
990
+ await forgotPassword(form$1.values.email);
991
+ onForgotPasswordSent?.(form$1.values.email);
992
+ } catch (error) {
993
+ onError?.(error);
994
+ }
995
+ };
996
+ const isLoading = loadingSignIn || loadingMagicLink || loadingResetPassword;
997
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
998
+ logo: logo,
999
+ title: title,
1000
+ subtitle: subtitle
1001
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1002
+ onSubmit: form$1.onSubmit(handleSubmit)
1003
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1004
+ gap: "sm"
1005
+ }, /*#__PURE__*/React.createElement(core.TextInput, _extends({
1006
+ label: labels.email || 'Email',
1007
+ placeholder: labels.emailPlaceholder || 'seu@email.com',
1008
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1009
+ size: 16
1010
+ })
1011
+ }, form$1.getInputProps('email'), {
1012
+ disabled: isLoading
1013
+ })), /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1014
+ label: labels.password || 'Senha',
1015
+ placeholder: labels.passwordPlaceholder || 'Sua senha',
1016
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1017
+ size: 16
1018
+ })
1019
+ }, form$1.getInputProps('password'), {
1020
+ disabled: isLoading
1021
+ })), showForgotPassword && /*#__PURE__*/React.createElement(core.Anchor, {
1022
+ size: "sm",
1023
+ ta: "right",
1024
+ onClick: handleForgotPassword,
1025
+ style: {
1026
+ cursor: 'pointer'
1027
+ },
1028
+ c: loadingResetPassword ? 'dimmed' : 'blue'
1029
+ }, loadingResetPassword ? labels.sendingReset || 'Enviando...' : labels.forgotPassword || 'Esqueceu a senha?'), /*#__PURE__*/React.createElement(core.Button, {
1030
+ type: "submit",
1031
+ fullWidth: true,
1032
+ loading: loadingSignIn,
1033
+ rightSection: /*#__PURE__*/React.createElement(iconsReact.IconArrowRight, {
1034
+ size: 16
1035
+ })
1036
+ }, labels.signInButton || 'Entrar'))), showMagicLink && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(core.Divider, {
1037
+ label: labels.orContinueWith || 'Ou continue com'
1038
+ }), /*#__PURE__*/React.createElement(core.Button, {
1039
+ variant: "light",
1040
+ fullWidth: true,
1041
+ loading: loadingMagicLink,
1042
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1043
+ size: 16
1044
+ }),
1045
+ onClick: handleMagicLink,
1046
+ disabled: isLoading || !form$1.values.email
1047
+ }, labels.magicLinkButton || 'Enviar Link Mágico')), showSocialLogin && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(core.Divider, null), /*#__PURE__*/React.createElement(core.Group, {
1048
+ grow: true
1049
+ }, /*#__PURE__*/React.createElement(core.Button, {
1050
+ variant: "light",
1051
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconBrandGoogle, {
1052
+ size: 16
1053
+ }),
1054
+ onClick: () => onSocialLogin?.('google'),
1055
+ disabled: isLoading
1056
+ }, "Google"), /*#__PURE__*/React.createElement(core.Button, {
1057
+ variant: "light",
1058
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconBrandGithub, {
1059
+ size: 16
1060
+ }),
1061
+ onClick: () => onSocialLogin?.('github'),
1062
+ disabled: isLoading
1063
+ }, "GitHub"))), showSignUpLink && /*#__PURE__*/React.createElement(core.Center, null, /*#__PURE__*/React.createElement(core.Text, {
1064
+ size: "sm",
1065
+ c: "dimmed"
1066
+ }, labels.noAccount || 'Não tem uma conta?', " ", /*#__PURE__*/React.createElement(core.Anchor, {
1067
+ href: signUpUrl
1068
+ }, labels.createAccount || 'Criar conta'))));
1069
+ }
1070
+
1071
+ /**
1072
+ * Formulário de Sign Up com Mantine
1073
+ */
1074
+ function SignUpForm({
1075
+ // Configuração
1076
+ logo = img,
1077
+ title = 'Criar Conta',
1078
+ subtitle = 'Preencha os dados para se cadastrar',
1079
+ // Features
1080
+ requireName = true,
1081
+ showSignInLink = true,
1082
+ showSocialLogin = false,
1083
+ // Links
1084
+ signInUrl = '/auth/signin',
1085
+ // Callbacks
1086
+ onSuccess,
1087
+ onError,
1088
+ onSocialLogin,
1089
+ // Custom labels
1090
+ labels = {},
1091
+ ...cardProps
1092
+ }) {
1093
+ const signUp = useAuthStore(s => s.signUp);
1094
+ const loading = useAuthStore(s => s.loadingStates.signUp);
1095
+ const form$1 = form.useForm({
1096
+ initialValues: {
1097
+ name: '',
1098
+ email: '',
1099
+ password: '',
1100
+ confirmPassword: ''
1101
+ },
1102
+ validate: {
1103
+ name: value => requireName && !value ? labels.nameRequired || 'Nome obrigatório' : null,
1104
+ email: value => /^\S+@\S+$/.test(value) ? null : labels.invalidEmail || 'Email inválido',
1105
+ password: value => value.length < 6 ? labels.passwordTooShort || 'A senha deve ter pelo menos 6 caracteres' : null,
1106
+ confirmPassword: (value, values) => value !== values.password ? labels.passwordMismatch || 'As senhas não coincidem' : null
1107
+ }
1108
+ });
1109
+ const handleSubmit = async values => {
1110
+ try {
1111
+ const result = await signUp(values.email, values.password, values.name);
1112
+ onSuccess?.(result);
1113
+ } catch (error) {
1114
+ onError?.(error);
1115
+ }
1116
+ };
1117
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1118
+ logo: logo,
1119
+ title: title,
1120
+ subtitle: subtitle
1121
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1122
+ onSubmit: form$1.onSubmit(handleSubmit)
1123
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1124
+ gap: "sm"
1125
+ }, requireName && /*#__PURE__*/React.createElement(core.TextInput, _extends({
1126
+ label: labels.name || 'Nome',
1127
+ placeholder: labels.namePlaceholder || 'Seu nome',
1128
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconUser, {
1129
+ size: 16
1130
+ })
1131
+ }, form$1.getInputProps('name'), {
1132
+ disabled: loading
1133
+ })), /*#__PURE__*/React.createElement(core.TextInput, _extends({
1134
+ label: labels.email || 'Email',
1135
+ placeholder: labels.emailPlaceholder || 'seu@email.com',
1136
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1137
+ size: 16
1138
+ })
1139
+ }, form$1.getInputProps('email'), {
1140
+ disabled: loading
1141
+ })), /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1142
+ label: labels.password || 'Senha',
1143
+ placeholder: labels.passwordPlaceholder || 'Crie uma senha',
1144
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1145
+ size: 16
1146
+ })
1147
+ }, form$1.getInputProps('password'), {
1148
+ disabled: loading
1149
+ })), /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1150
+ label: labels.confirmPassword || 'Confirmar Senha',
1151
+ placeholder: labels.confirmPasswordPlaceholder || 'Repita a senha',
1152
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1153
+ size: 16
1154
+ })
1155
+ }, form$1.getInputProps('confirmPassword'), {
1156
+ disabled: loading
1157
+ })), /*#__PURE__*/React.createElement(core.Button, {
1158
+ type: "submit",
1159
+ fullWidth: true,
1160
+ loading: loading,
1161
+ rightSection: /*#__PURE__*/React.createElement(iconsReact.IconArrowRight, {
1162
+ size: 16
1163
+ })
1164
+ }, labels.signUpButton || 'Criar Conta'))), showSocialLogin && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(core.Divider, {
1165
+ label: labels.orContinueWith || 'Ou continue com'
1166
+ }), /*#__PURE__*/React.createElement(core.Group, {
1167
+ grow: true
1168
+ }, /*#__PURE__*/React.createElement(core.Button, {
1169
+ variant: "light",
1170
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconBrandGoogle, {
1171
+ size: 16
1172
+ }),
1173
+ onClick: () => onSocialLogin?.('google'),
1174
+ disabled: loading
1175
+ }, "Google"), /*#__PURE__*/React.createElement(core.Button, {
1176
+ variant: "light",
1177
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconBrandGithub, {
1178
+ size: 16
1179
+ }),
1180
+ onClick: () => onSocialLogin?.('github'),
1181
+ disabled: loading
1182
+ }, "GitHub"))), showSignInLink && /*#__PURE__*/React.createElement(core.Center, null, /*#__PURE__*/React.createElement(core.Text, {
1183
+ size: "sm",
1184
+ c: "dimmed"
1185
+ }, labels.hasAccount || 'Já tem uma conta?', " ", /*#__PURE__*/React.createElement(core.Anchor, {
1186
+ href: signInUrl
1187
+ }, labels.signIn || 'Entrar'))));
1188
+ }
1189
+
1190
+ /**
1191
+ * Formulário para envio de Magic Link
1192
+ */
1193
+ function MagicLinkForm({
1194
+ // Configuração
1195
+ logo = img,
1196
+ title = 'Login sem Senha',
1197
+ subtitle = 'Receba um link de acesso no seu email',
1198
+ // Features
1199
+ showSignInLink = true,
1200
+ // Links
1201
+ signInUrl = '/auth/signin',
1202
+ // Callbacks
1203
+ onSent,
1204
+ onError,
1205
+ // Custom labels
1206
+ labels = {},
1207
+ ...cardProps
1208
+ }) {
1209
+ const sendMagicLink = useAuthStore(s => s.sendMagicLink);
1210
+ const loading = useAuthStore(s => s.loadingStates.magicLink);
1211
+ const form$1 = form.useForm({
1212
+ initialValues: {
1213
+ email: ''
1214
+ },
1215
+ validate: {
1216
+ email: value => /^\S+@\S+$/.test(value) ? null : labels.invalidEmail || 'Email inválido'
1217
+ }
1218
+ });
1219
+ const handleSubmit = async values => {
1220
+ try {
1221
+ await sendMagicLink(values.email);
1222
+ onSent?.(values.email);
1223
+ } catch (error) {
1224
+ onError?.(error);
1225
+ }
1226
+ };
1227
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1228
+ logo: logo,
1229
+ title: title,
1230
+ subtitle: subtitle
1231
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1232
+ onSubmit: form$1.onSubmit(handleSubmit)
1233
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1234
+ gap: "sm"
1235
+ }, /*#__PURE__*/React.createElement(core.TextInput, _extends({
1236
+ label: labels.email || 'Email',
1237
+ placeholder: labels.emailPlaceholder || 'seu@email.com',
1238
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1239
+ size: 16
1240
+ })
1241
+ }, form$1.getInputProps('email'), {
1242
+ disabled: loading
1243
+ })), /*#__PURE__*/React.createElement(core.Button, {
1244
+ type: "submit",
1245
+ fullWidth: true,
1246
+ loading: loading,
1247
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconSend, {
1248
+ size: 16
1249
+ })
1250
+ }, labels.sendButton || 'Enviar Link Mágico'))), showSignInLink && /*#__PURE__*/React.createElement(core.Center, null, /*#__PURE__*/React.createElement(core.Text, {
1251
+ size: "sm",
1252
+ c: "dimmed"
1253
+ }, labels.backTo || 'Voltar para', " ", /*#__PURE__*/React.createElement(core.Anchor, {
1254
+ href: signInUrl
1255
+ }, labels.signIn || 'login com senha'))));
1256
+ }
1257
+
1258
+ /**
1259
+ * Componente de verificação de Magic Link
1260
+ * Extrai token da URL e verifica automaticamente
1261
+ */
1262
+ function MagicLinkVerify({
1263
+ // Configuração
1264
+ logo = img,
1265
+ // Token pode ser passado diretamente ou extraído da URL
1266
+ token: propToken,
1267
+ // Callbacks
1268
+ onSuccess,
1269
+ onError,
1270
+ // Redirect após sucesso/erro
1271
+ redirectTo,
1272
+ redirectDelay = 2000,
1273
+ // Custom labels
1274
+ labels = {},
1275
+ ...cardProps
1276
+ }) {
1277
+ const [status, setStatus] = React$1.useState('verifying'); // verifying, success, error
1278
+ const [errorMessage, setErrorMessage] = React$1.useState('');
1279
+ const verifyMagicLink = useAuthStore(s => s.verifyMagicLink);
1280
+ React$1.useEffect(() => {
1281
+ const verify = async () => {
1282
+ // Pega token da prop ou da URL
1283
+ let token = propToken;
1284
+ if (!token && typeof window !== 'undefined') {
1285
+ const urlParams = new URLSearchParams(window.location.search);
1286
+ token = urlParams.get('token');
1287
+ }
1288
+ if (!token) {
1289
+ setStatus('error');
1290
+ setErrorMessage(labels.noToken || 'Token não encontrado na URL');
1291
+ onError?.(new Error('No token'));
1292
+ return;
1293
+ }
1294
+ try {
1295
+ const result = await verifyMagicLink(token);
1296
+ setStatus('success');
1297
+ onSuccess?.(result);
1298
+ if (redirectTo) {
1299
+ setTimeout(() => {
1300
+ window.location.href = redirectTo;
1301
+ }, redirectDelay);
1302
+ }
1303
+ } catch (error) {
1304
+ setStatus('error');
1305
+ setErrorMessage(error.message || labels.verificationFailed || 'Verificação falhou');
1306
+ onError?.(error);
1307
+ }
1308
+ };
1309
+ verify();
1310
+ }, [propToken, verifyMagicLink, onSuccess, onError, redirectTo, redirectDelay, labels]);
1311
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1312
+ logo: logo
1313
+ }, cardProps), status === 'verifying' && /*#__PURE__*/React.createElement(core.Stack, {
1314
+ align: "center",
1315
+ gap: "sm"
1316
+ }, /*#__PURE__*/React.createElement(core.Loader, {
1317
+ size: "lg"
1318
+ }), /*#__PURE__*/React.createElement(core.Title, {
1319
+ order: 4
1320
+ }, labels.verifying || 'Verificando Link Mágico'), /*#__PURE__*/React.createElement(core.Text, {
1321
+ size: "sm",
1322
+ c: "dimmed",
1323
+ ta: "center"
1324
+ }, labels.pleaseWait || 'Aguarde enquanto autenticamos você...')), status === 'success' && /*#__PURE__*/React.createElement(core.Stack, {
1325
+ align: "center",
1326
+ gap: "sm"
1327
+ }, /*#__PURE__*/React.createElement(iconsReact.IconCheck, {
1328
+ size: 48,
1329
+ color: "var(--mantine-color-green-6)"
1330
+ }), /*#__PURE__*/React.createElement(core.Title, {
1331
+ order: 4
1332
+ }, labels.success || 'Autenticado com Sucesso!'), /*#__PURE__*/React.createElement(core.Text, {
1333
+ size: "sm",
1334
+ c: "dimmed",
1335
+ ta: "center"
1336
+ }, redirectTo ? labels.redirecting || 'Redirecionando...' : labels.authenticated || 'Você está autenticado.')), status === 'error' && /*#__PURE__*/React.createElement(core.Stack, {
1337
+ align: "center",
1338
+ gap: "sm"
1339
+ }, /*#__PURE__*/React.createElement(iconsReact.IconX, {
1340
+ size: 48,
1341
+ color: "var(--mantine-color-red-6)"
1342
+ }), /*#__PURE__*/React.createElement(core.Title, {
1343
+ order: 4
1344
+ }, labels.failed || 'Falha na Autenticação'), /*#__PURE__*/React.createElement(core.Text, {
1345
+ size: "sm",
1346
+ c: "dimmed",
1347
+ ta: "center"
1348
+ }, errorMessage || labels.invalidLink || 'O link é inválido ou expirou.')));
1349
+ }
1350
+
1351
+ /**
1352
+ * Formulário para solicitar reset de senha
1353
+ */
1354
+ function ForgotPasswordForm({
1355
+ // Configuração
1356
+ logo = img,
1357
+ title = 'Recuperar Senha',
1358
+ subtitle = 'Enviaremos um link para redefinir sua senha',
1359
+ // Features
1360
+ showSignInLink = true,
1361
+ // Links
1362
+ signInUrl = '/auth/signin',
1363
+ // Callbacks
1364
+ onSent,
1365
+ onError,
1366
+ // Custom labels
1367
+ labels = {},
1368
+ ...cardProps
1369
+ }) {
1370
+ const forgotPassword = useAuthStore(s => s.forgotPassword);
1371
+ const loading = useAuthStore(s => s.loadingStates.resetPassword);
1372
+ const form$1 = form.useForm({
1373
+ initialValues: {
1374
+ email: ''
1375
+ },
1376
+ validate: {
1377
+ email: value => /^\S+@\S+$/.test(value) ? null : labels.invalidEmail || 'Email inválido'
1378
+ }
1379
+ });
1380
+ const handleSubmit = async values => {
1381
+ try {
1382
+ await forgotPassword(values.email);
1383
+ onSent?.(values.email);
1384
+ } catch (error) {
1385
+ onError?.(error);
1386
+ }
1387
+ };
1388
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1389
+ logo: logo,
1390
+ title: title,
1391
+ subtitle: subtitle
1392
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1393
+ onSubmit: form$1.onSubmit(handleSubmit)
1394
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1395
+ gap: "sm"
1396
+ }, /*#__PURE__*/React.createElement(core.TextInput, _extends({
1397
+ label: labels.email || 'Email',
1398
+ placeholder: labels.emailPlaceholder || 'seu@email.com',
1399
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconMail, {
1400
+ size: 16
1401
+ })
1402
+ }, form$1.getInputProps('email'), {
1403
+ disabled: loading
1404
+ })), /*#__PURE__*/React.createElement(core.Button, {
1405
+ type: "submit",
1406
+ fullWidth: true,
1407
+ loading: loading,
1408
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconSend, {
1409
+ size: 16
1410
+ })
1411
+ }, labels.sendButton || 'Enviar Link de Recuperação'))), showSignInLink && /*#__PURE__*/React.createElement(core.Center, null, /*#__PURE__*/React.createElement(core.Text, {
1412
+ size: "sm",
1413
+ c: "dimmed"
1414
+ }, labels.rememberedPassword || 'Lembrou a senha?', " ", /*#__PURE__*/React.createElement(core.Anchor, {
1415
+ href: signInUrl
1416
+ }, labels.signIn || 'Entrar'))));
1417
+ }
1418
+
1419
+ /**
1420
+ * Formulário para redefinir senha com token
1421
+ */
1422
+ function ResetPasswordForm({
1423
+ // Configuração
1424
+ logo = img,
1425
+ title = 'Nova Senha',
1426
+ subtitle = 'Crie uma nova senha para sua conta',
1427
+ // Token pode ser passado diretamente ou extraído da URL
1428
+ token: propToken,
1429
+ // Callbacks
1430
+ onSuccess,
1431
+ onError,
1432
+ // Redirect após sucesso
1433
+ signInUrl = '/auth/signin',
1434
+ // Custom labels
1435
+ labels = {},
1436
+ ...cardProps
1437
+ }) {
1438
+ const [token, setToken] = React$1.useState(propToken || '');
1439
+ const [success, setSuccess] = React$1.useState(false);
1440
+ const resetPassword = useAuthStore(s => s.resetPassword);
1441
+ const loading = useAuthStore(s => s.loadingStates.resetPassword);
1442
+
1443
+ // Extrai token da URL se não foi passado como prop
1444
+ React$1.useEffect(() => {
1445
+ if (!propToken && typeof window !== 'undefined') {
1446
+ const urlParams = new URLSearchParams(window.location.search);
1447
+ const urlToken = urlParams.get('token');
1448
+ if (urlToken) setToken(urlToken);
1449
+ }
1450
+ }, [propToken]);
1451
+ const form$1 = form.useForm({
1452
+ initialValues: {
1453
+ password: '',
1454
+ confirmPassword: ''
1455
+ },
1456
+ validate: {
1457
+ password: value => value.length < 6 ? labels.passwordTooShort || 'A senha deve ter pelo menos 6 caracteres' : null,
1458
+ confirmPassword: (value, values) => value !== values.password ? labels.passwordMismatch || 'As senhas não coincidem' : null
1459
+ }
1460
+ });
1461
+ const handleSubmit = async values => {
1462
+ if (!token) {
1463
+ onError?.(new Error('Token não encontrado'));
1464
+ return;
1465
+ }
1466
+ try {
1467
+ await resetPassword(token, values.password);
1468
+ setSuccess(true);
1469
+ onSuccess?.();
1470
+ } catch (error) {
1471
+ onError?.(error);
1472
+ }
1473
+ };
1474
+ if (success) {
1475
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1476
+ logo: logo
1477
+ }, cardProps), /*#__PURE__*/React.createElement(core.Stack, {
1478
+ align: "center",
1479
+ gap: "sm"
1480
+ }, /*#__PURE__*/React.createElement(iconsReact.IconCheck, {
1481
+ size: 48,
1482
+ color: "var(--mantine-color-green-6)"
1483
+ }), /*#__PURE__*/React.createElement(core.Title, {
1484
+ order: 4
1485
+ }, labels.successTitle || 'Senha Redefinida!'), /*#__PURE__*/React.createElement(core.Text, {
1486
+ size: "sm",
1487
+ c: "dimmed",
1488
+ ta: "center"
1489
+ }, labels.successMessage || 'Sua senha foi alterada com sucesso.'), /*#__PURE__*/React.createElement(core.Button, {
1490
+ component: "a",
1491
+ href: signInUrl,
1492
+ fullWidth: true
1493
+ }, labels.goToSignIn || 'Ir para Login')));
1494
+ }
1495
+ if (!token) {
1496
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1497
+ logo: logo
1498
+ }, cardProps), /*#__PURE__*/React.createElement(core.Stack, {
1499
+ align: "center",
1500
+ gap: "sm"
1501
+ }, /*#__PURE__*/React.createElement(core.Text, {
1502
+ c: "red"
1503
+ }, labels.noToken || 'Token não encontrado na URL'), /*#__PURE__*/React.createElement(core.Button, {
1504
+ component: "a",
1505
+ href: signInUrl,
1506
+ variant: "light",
1507
+ fullWidth: true
1508
+ }, labels.goToSignIn || 'Voltar para Login')));
1509
+ }
1510
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1511
+ logo: logo,
1512
+ title: title,
1513
+ subtitle: subtitle
1514
+ }, cardProps), /*#__PURE__*/React.createElement("form", {
1515
+ onSubmit: form$1.onSubmit(handleSubmit)
1516
+ }, /*#__PURE__*/React.createElement(core.Stack, {
1517
+ gap: "sm"
1518
+ }, /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1519
+ label: labels.newPassword || 'Nova Senha',
1520
+ placeholder: labels.newPasswordPlaceholder || 'Crie uma nova senha',
1521
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1522
+ size: 16
1523
+ })
1524
+ }, form$1.getInputProps('password'), {
1525
+ disabled: loading
1526
+ })), /*#__PURE__*/React.createElement(core.PasswordInput, _extends({
1527
+ label: labels.confirmPassword || 'Confirmar Senha',
1528
+ placeholder: labels.confirmPasswordPlaceholder || 'Repita a nova senha',
1529
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconLock, {
1530
+ size: 16
1531
+ })
1532
+ }, form$1.getInputProps('confirmPassword'), {
1533
+ disabled: loading
1534
+ })), /*#__PURE__*/React.createElement(core.Button, {
1535
+ type: "submit",
1536
+ fullWidth: true,
1537
+ loading: loading
1538
+ }, labels.resetButton || 'Redefinir Senha'))));
1539
+ }
1540
+
1541
+ /**
1542
+ * Card de verificação de email
1543
+ * Verifica token automaticamente e permite reenvio
1544
+ */
1545
+ function VerifyEmailCard({
1546
+ // Configuração
1547
+ logo = img,
1548
+ // Token pode ser passado diretamente ou extraído da URL
1549
+ token: propToken,
1550
+ // Email para reenvio (opcional)
1551
+ email,
1552
+ // Callbacks
1553
+ onSuccess,
1554
+ onError,
1555
+ onResent,
1556
+ // Redirect após sucesso
1557
+ redirectTo,
1558
+ redirectDelay = 2000,
1559
+ // Custom labels
1560
+ labels = {},
1561
+ ...cardProps
1562
+ }) {
1563
+ const [status, setStatus] = React$1.useState('verifying'); // verifying, success, error
1564
+ const [errorMessage, setErrorMessage] = React$1.useState('');
1565
+ const verifyEmail = useAuthStore(s => s.verifyEmail);
1566
+ const resendVerification = useAuthStore(s => s.resendVerification);
1567
+ const loadingResend = useAuthStore(s => s.loadingStates.resendVerification);
1568
+ React$1.useEffect(() => {
1569
+ const verify = async () => {
1570
+ // Pega token da prop ou da URL
1571
+ let token = propToken;
1572
+ if (!token && typeof window !== 'undefined') {
1573
+ const urlParams = new URLSearchParams(window.location.search);
1574
+ token = urlParams.get('token');
1575
+ }
1576
+ if (!token) {
1577
+ setStatus('error');
1578
+ setErrorMessage(labels.noToken || 'Token não encontrado na URL');
1579
+ onError?.(new Error('No token'));
1580
+ return;
1581
+ }
1582
+ try {
1583
+ const result = await verifyEmail(token);
1584
+ setStatus('success');
1585
+ onSuccess?.(result);
1586
+ if (redirectTo) {
1587
+ setTimeout(() => {
1588
+ window.location.href = redirectTo;
1589
+ }, redirectDelay);
1590
+ }
1591
+ } catch (error) {
1592
+ setStatus('error');
1593
+ setErrorMessage(error.message || labels.verificationFailed || 'Verificação falhou');
1594
+ onError?.(error);
1595
+ }
1596
+ };
1597
+ verify();
1598
+ }, [propToken, verifyEmail, onSuccess, onError, redirectTo, redirectDelay, labels]);
1599
+ const handleResend = async () => {
1600
+ if (!email) return;
1601
+ try {
1602
+ await resendVerification(email);
1603
+ onResent?.(email);
1604
+ } catch (error) {
1605
+ onError?.(error);
1606
+ }
1607
+ };
1608
+ return /*#__PURE__*/React.createElement(AuthCard, _extends({
1609
+ logo: logo
1610
+ }, cardProps), status === 'verifying' && /*#__PURE__*/React.createElement(core.Stack, {
1611
+ align: "center",
1612
+ gap: "sm"
1613
+ }, /*#__PURE__*/React.createElement(core.Loader, {
1614
+ size: "lg"
1615
+ }), /*#__PURE__*/React.createElement(core.Title, {
1616
+ order: 4
1617
+ }, labels.verifying || 'Verificando Email'), /*#__PURE__*/React.createElement(core.Text, {
1618
+ size: "sm",
1619
+ c: "dimmed",
1620
+ ta: "center"
1621
+ }, labels.pleaseWait || 'Aguarde enquanto verificamos seu email...')), status === 'success' && /*#__PURE__*/React.createElement(core.Stack, {
1622
+ align: "center",
1623
+ gap: "sm"
1624
+ }, /*#__PURE__*/React.createElement(iconsReact.IconCheck, {
1625
+ size: 48,
1626
+ color: "var(--mantine-color-green-6)"
1627
+ }), /*#__PURE__*/React.createElement(core.Title, {
1628
+ order: 4
1629
+ }, labels.success || 'Email Verificado!'), /*#__PURE__*/React.createElement(core.Text, {
1630
+ size: "sm",
1631
+ c: "dimmed",
1632
+ ta: "center"
1633
+ }, redirectTo ? labels.redirecting || 'Redirecionando...' : labels.verified || 'Seu email foi verificado com sucesso.')), status === 'error' && /*#__PURE__*/React.createElement(core.Stack, {
1634
+ align: "center",
1635
+ gap: "sm"
1636
+ }, /*#__PURE__*/React.createElement(iconsReact.IconX, {
1637
+ size: 48,
1638
+ color: "var(--mantine-color-red-6)"
1639
+ }), /*#__PURE__*/React.createElement(core.Title, {
1640
+ order: 4
1641
+ }, labels.failed || 'Verificação Falhou'), /*#__PURE__*/React.createElement(core.Text, {
1642
+ size: "sm",
1643
+ c: "dimmed",
1644
+ ta: "center"
1645
+ }, errorMessage || labels.invalidToken || 'O link é inválido ou expirou.'), email && /*#__PURE__*/React.createElement(core.Button, {
1646
+ variant: "light",
1647
+ leftSection: /*#__PURE__*/React.createElement(iconsReact.IconRefresh, {
1648
+ size: 16
1649
+ }),
1650
+ onClick: handleResend,
1651
+ loading: loadingResend,
1652
+ fullWidth: true
1653
+ }, labels.resend || 'Reenviar Email de Verificação')));
1654
+ }
1655
+
1656
+ exports.AuthCard = AuthCard;
829
1657
  exports.AuthProvider = AuthProvider;
1658
+ exports.ForgotPasswordForm = ForgotPasswordForm;
1659
+ exports.MagicLinkForm = MagicLinkForm;
1660
+ exports.MagicLinkVerify = MagicLinkVerify;
830
1661
  exports.ProtectedRoute = ProtectedRoute;
1662
+ exports.ResetPasswordForm = ResetPasswordForm;
1663
+ exports.SignInForm = SignInForm;
1664
+ exports.SignUpForm = SignUpForm;
1665
+ exports.VerifyEmailCard = VerifyEmailCard;
1666
+ exports.configure = configure;
1667
+ exports.forgotPassword = forgotPassword;
831
1668
  exports.getCurrentUser = getCurrentUser;
1669
+ exports.getSession = getSession;
832
1670
  exports.isAuthenticated = isAuthenticated;
833
1671
  exports.refreshToken = refreshToken;
1672
+ exports.resendVerification = resendVerification;
1673
+ exports.resetPassword = resetPassword;
1674
+ exports.sendMagicLink = sendMagicLink;
834
1675
  exports.signIn = signIn;
835
1676
  exports.signOut = signOut;
836
1677
  exports.signUp = signUp;
837
1678
  exports.socialRedirect = socialRedirect;
838
1679
  exports.useAuth = useAuth;
1680
+ exports.useAuthLoading = useAuthLoading;
839
1681
  exports.useAuthStore = useAuthStore;
840
1682
  exports.useCheckToken = useCheckToken;
1683
+ exports.useEmailVerification = useEmailVerification;
1684
+ exports.useMagicLink = useMagicLink;
1685
+ exports.usePasswordReset = usePasswordReset;
1686
+ exports.useSession = useSession;
841
1687
  exports.useSignIn = useSignIn;
842
1688
  exports.useSignOut = useSignOut;
843
1689
  exports.useSignUp = useSignUp;
1690
+ exports.verifyEmail = verifyEmail;
1691
+ exports.verifyMagicLink = verifyMagicLink;
844
1692
  //# sourceMappingURL=index.js.map