@riligar/auth-react 1.15.0 → 1.16.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.esm.js CHANGED
@@ -3,9 +3,9 @@ import { useMemo, useEffect, createContext, useState, useRef } from 'react';
3
3
  import { useShallow } from 'zustand/react/shallow';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { Navigate, Outlet, useNavigate } from 'react-router-dom';
6
- import { Modal, Stack, Text, Image, Title, Paper, TextInput, PasswordInput, Anchor, Button, Divider, Group, Center, Loader, Box, Avatar, Collapse, Card, Tooltip, ThemeIcon } from '@mantine/core';
6
+ import { Modal, Stack, Text, Image, Title, Paper, TextInput, PasswordInput, Anchor, Button, Divider, Group, Center, Loader, Box, Avatar, Collapse, Card, Tooltip, ThemeIcon, Badge } from '@mantine/core';
7
7
  import { useForm } from '@mantine/form';
8
- import { IconMail, IconLock, IconArrowRight, IconBrandGoogle, IconBrandGithub, IconUser, IconSend, IconCheck, IconX, IconRefresh, IconPhoto, IconTrash, IconPencil, IconShield, IconKey, IconUserCircle } from '@tabler/icons-react';
8
+ import { IconMail, IconLock, IconArrowRight, IconBrandGoogle, IconBrandGithub, IconUser, IconSend, IconCheck, IconX, IconRefresh, IconPhoto, IconTrash, IconPencil, IconShield, IconKey, IconDevices, IconDeviceMobile, IconLogout, IconUserCircle } from '@tabler/icons-react';
9
9
  import { notifications } from '@mantine/notifications';
10
10
 
11
11
  // Config - pode ser sobrescrita pelo AuthProvider
@@ -273,11 +273,11 @@ const getSession = async () => {
273
273
  const listSessions = async () => {
274
274
  return await api('/auth/list-sessions');
275
275
  };
276
- const revokeSession = async token => {
277
- return await api('/auth/revoke-session', {
276
+ const revokeSession = async id => {
277
+ return await api('/auth/revoke-session-by-id', {
278
278
  method: 'POST',
279
279
  body: JSON.stringify({
280
- token
280
+ id
281
281
  })
282
282
  });
283
283
  };
@@ -339,7 +339,7 @@ const useAuthStore = create((set, get) => ({
339
339
  error: null,
340
340
  // Session management
341
341
  sessions: [],
342
- currentSessionToken: null,
342
+ currentSession: null,
343
343
  // Loading states granulares
344
344
  loadingStates: {
345
345
  signIn: false,
@@ -397,9 +397,14 @@ const useAuthStore = create((set, get) => ({
397
397
  // Precisamos buscar a sessão no servidor.
398
398
  if (!user) {
399
399
  try {
400
- const session = await getSession();
401
- if (session?.user) {
402
- user = session.user;
400
+ const sessionData = await getSession();
401
+ if (sessionData?.user) {
402
+ user = sessionData.user;
403
+ }
404
+ if (sessionData?.session) {
405
+ set({
406
+ currentSession: sessionData.session
407
+ });
403
408
  }
404
409
  } catch (sessionError) {
405
410
  console.warn('[AuthStore] Failed to fetch session:', sessionError);
@@ -472,8 +477,13 @@ const useAuthStore = create((set, get) => ({
472
477
 
473
478
  // Se não encontrou no token (sessão opaca), busca do servidor
474
479
  if (!user) {
475
- const session = await getSession();
476
- if (session?.user) user = session.user;
480
+ const sessionData = await getSession();
481
+ if (sessionData?.user) user = sessionData.user;
482
+ if (sessionData?.session) {
483
+ set({
484
+ currentSession: sessionData.session
485
+ });
486
+ }
477
487
  }
478
488
  set({
479
489
  user,
@@ -655,14 +665,14 @@ const useAuthStore = create((set, get) => ({
655
665
  /* Session */
656
666
  getSession: async () => {
657
667
  try {
658
- const session = await getSession();
659
- // Store current session token for comparison
660
- if (session?.session?.token) {
668
+ const sessionData = await getSession();
669
+ // Store current session for comparison (includes id)
670
+ if (sessionData?.session) {
661
671
  set({
662
- currentSessionToken: session.session.token
672
+ currentSession: sessionData.session
663
673
  });
664
674
  }
665
- return session;
675
+ return sessionData;
666
676
  } catch (err) {
667
677
  set({
668
678
  error: err
@@ -914,8 +924,24 @@ function AuthProvider({
914
924
  checkTokenValidity();
915
925
  }
916
926
  };
927
+
928
+ // Escuta evento de sessão revogada (quando o usuário revoga sua própria sessão)
929
+ const handleSessionRevoked = () => {
930
+ // Limpa o usuário do store
931
+ useAuthStore.setState({
932
+ user: null,
933
+ currentSession: null,
934
+ sessions: []
935
+ });
936
+ // Dispara evento de logout para sincronizar entre abas
937
+ localStorage.setItem('auth:logout', Date.now());
938
+ };
917
939
  window.addEventListener('storage', handleStorageChange);
918
- return () => window.removeEventListener('storage', handleStorageChange);
940
+ window.addEventListener('auth:session-revoked', handleSessionRevoked);
941
+ return () => {
942
+ window.removeEventListener('storage', handleStorageChange);
943
+ window.removeEventListener('auth:session-revoked', handleSessionRevoked);
944
+ };
919
945
  }, [checkTokenValidity]);
920
946
 
921
947
  // Verifica validade do token periodicamente
@@ -1003,6 +1029,19 @@ const useUser = () => useAuthStore(useShallow(s => ({
1003
1029
  // Alias deprecado para backwards compatibility
1004
1030
  const useProfile = useUser;
1005
1031
 
1032
+ // Sessions Management Hook
1033
+ const useSessions = () => useAuthStore(useShallow(s => ({
1034
+ currentSession: s.currentSession,
1035
+ sessions: s.sessions,
1036
+ getSession: s.getSession,
1037
+ listSessions: s.listSessions,
1038
+ revokeSession: s.revokeSession,
1039
+ revokeOtherSessions: s.revokeOtherSessions,
1040
+ loadingListSessions: s.loadingStates.listSessions,
1041
+ loadingRevokeSession: s.loadingStates.revokeSession,
1042
+ error: s.error
1043
+ })));
1044
+
1006
1045
  // Application Logo Hook
1007
1046
  const useApplicationLogo = () => {
1008
1047
  const applicationInfo = useAuthStore(s => s.applicationInfo);
@@ -2032,6 +2071,7 @@ function UserProfile({
2032
2071
  showName = true,
2033
2072
  showEmail = true,
2034
2073
  showPassword = true,
2074
+ showSessions = true,
2035
2075
  // Customização
2036
2076
  labels = {},
2037
2077
  title = 'Account',
@@ -2059,6 +2099,111 @@ function UserProfile({
2059
2099
  loadingChangeEmail
2060
2100
  } = useProfile();
2061
2101
 
2102
+ // Hook para sessions
2103
+ const {
2104
+ currentSession,
2105
+ sessions,
2106
+ listSessions,
2107
+ getSession,
2108
+ revokeSession,
2109
+ revokeOtherSessions,
2110
+ loadingListSessions,
2111
+ loadingRevokeSession
2112
+ } = useSessions();
2113
+
2114
+ // Load sessions when opened (modal) or component mounts (card), and when sessions section is opened
2115
+ useEffect(() => {
2116
+ if (showSessions && (variant === 'card' || opened)) {
2117
+ // Fetch current session first to get the session ID, then list all sessions
2118
+ getSession().catch(err => console.warn('Failed to get current session:', err));
2119
+ listSessions().catch(err => console.warn('Failed to load sessions:', err));
2120
+ }
2121
+ }, [opened, showSessions, variant]);
2122
+
2123
+ // Helper to parse user agent string
2124
+ const parseUserAgent = ua => {
2125
+ if (!ua) return {
2126
+ browser: 'Unknown Browser',
2127
+ os: 'Unknown OS'
2128
+ };
2129
+ let browser = 'Unknown Browser';
2130
+ let os = 'Unknown OS';
2131
+
2132
+ // Detect browser
2133
+ if (ua.includes('Chrome') && !ua.includes('Edg')) browser = 'Chrome';else if (ua.includes('Firefox')) browser = 'Firefox';else if (ua.includes('Safari') && !ua.includes('Chrome')) browser = 'Safari';else if (ua.includes('Edg')) browser = 'Edge';else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';
2134
+
2135
+ // Detect OS
2136
+ if (ua.includes('Windows')) os = 'Windows';else if (ua.includes('Mac OS')) os = 'macOS';else if (ua.includes('Linux')) os = 'Linux';else if (ua.includes('Android')) os = 'Android';else if (ua.includes('iPhone') || ua.includes('iPad')) os = 'iOS';
2137
+ return {
2138
+ browser,
2139
+ os
2140
+ };
2141
+ };
2142
+
2143
+ // Session handlers
2144
+ const handleRevokeSession = async sessionId => {
2145
+ // Check if revoking current session
2146
+ const isCurrentSession = sessionId === currentSession?.id || sessions.length === 1;
2147
+
2148
+ // If revoking current session, handle logout immediately after revocation
2149
+ if (isCurrentSession) {
2150
+ try {
2151
+ await revokeSession(sessionId);
2152
+ } catch (error) {
2153
+ // Even if it fails, we're revoking our own session, so just logout
2154
+ // The server already revoked our session
2155
+ }
2156
+ // Clear auth state and redirect
2157
+ localStorage.removeItem('auth:token');
2158
+ window.dispatchEvent(new CustomEvent('auth:session-revoked'));
2159
+ if (variant === 'modal') onClose?.();
2160
+ return;
2161
+ }
2162
+
2163
+ // Revoking another session
2164
+ try {
2165
+ await revokeSession(sessionId);
2166
+ notifications.show({
2167
+ title: labels.successTitle || 'Sucesso',
2168
+ message: labels.sessionRevoked || 'Sessão encerrada com sucesso',
2169
+ color: 'green'
2170
+ });
2171
+ } catch (error) {
2172
+ // Check for 401 error (our SDK uses error.res, axios uses error.response)
2173
+ const status = error.res?.status || error.response?.status;
2174
+ if (status === 401) {
2175
+ // This means our session was revoked, not the target one - do logout
2176
+ localStorage.removeItem('auth:token');
2177
+ window.dispatchEvent(new CustomEvent('auth:session-revoked'));
2178
+ if (variant === 'modal') onClose?.();
2179
+ return;
2180
+ }
2181
+ notifications.show({
2182
+ title: labels.errorTitle || 'Erro',
2183
+ message: error.message || labels.sessionRevokeFailed || 'Falha ao encerrar sessão',
2184
+ color: 'red'
2185
+ });
2186
+ onError?.(error);
2187
+ }
2188
+ };
2189
+ const handleRevokeOtherSessions = async () => {
2190
+ try {
2191
+ await revokeOtherSessions();
2192
+ notifications.show({
2193
+ title: labels.successTitle || 'Sucesso',
2194
+ message: labels.otherSessionsRevoked || 'Todas as outras sessões foram encerradas',
2195
+ color: 'green'
2196
+ });
2197
+ } catch (error) {
2198
+ notifications.show({
2199
+ title: labels.errorTitle || 'Erro',
2200
+ message: error.message || labels.otherSessionsRevokeFailed || 'Falha ao encerrar sessões',
2201
+ color: 'red'
2202
+ });
2203
+ onError?.(error);
2204
+ }
2205
+ };
2206
+
2062
2207
  // Password form
2063
2208
  const passwordForm = useForm({
2064
2209
  initialValues: {
@@ -2590,7 +2735,7 @@ function UserProfile({
2590
2735
  })]
2591
2736
  })]
2592
2737
  })]
2593
- }), showPassword && /*#__PURE__*/jsxs(Box, {
2738
+ }), (showPassword || showSessions) && /*#__PURE__*/jsxs(Box, {
2594
2739
  mb: "md",
2595
2740
  children: [/*#__PURE__*/jsx(SectionHeader, {
2596
2741
  icon: IconShield,
@@ -2598,69 +2743,196 @@ function UserProfile({
2598
2743
  description: labels.securityDescription || 'Protect your account'
2599
2744
  }), /*#__PURE__*/jsxs(Stack, {
2600
2745
  gap: "sm",
2601
- children: [/*#__PURE__*/jsx(SettingRow, {
2602
- label: labels.password || 'Password',
2603
- action: labels.change || 'Change',
2604
- actionLabel: labels.changePassword || 'Change your password',
2605
- onClick: () => handleToggleSection('password'),
2606
- expanded: editingSection === 'password',
2607
- children: /*#__PURE__*/jsxs(Group, {
2608
- gap: "xs",
2609
- children: [/*#__PURE__*/jsx(IconKey, {
2610
- size: 16,
2611
- color: "var(--mantine-color-dimmed)"
2612
- }), /*#__PURE__*/jsx(Text, {
2613
- size: "sm",
2614
- c: "dimmed",
2615
- children: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
2616
- })]
2617
- })
2618
- }), /*#__PURE__*/jsx(Collapse, {
2619
- in: editingSection === 'password',
2620
- children: /*#__PURE__*/jsx(Card, {
2621
- p: "md",
2622
- withBorder: true,
2623
- children: /*#__PURE__*/jsx("form", {
2624
- onSubmit: passwordForm.onSubmit(handleChangePassword),
2625
- children: /*#__PURE__*/jsxs(Stack, {
2626
- gap: "sm",
2627
- children: [/*#__PURE__*/jsx(PasswordInput, {
2628
- label: labels.currentPassword || 'Senha Atual',
2629
- placeholder: labels.currentPasswordPlaceholder || 'Digite sua senha atual',
2630
- ...passwordForm.getInputProps('currentPassword')
2631
- }), /*#__PURE__*/jsx(PasswordInput, {
2632
- label: labels.newPassword || 'Nova Senha',
2633
- placeholder: labels.newPasswordPlaceholder || 'Digite a nova senha',
2634
- description: labels.passwordDescription || 'Mínimo 8 caracteres',
2635
- ...passwordForm.getInputProps('newPassword')
2636
- }), /*#__PURE__*/jsx(PasswordInput, {
2637
- label: labels.confirmPassword || 'Confirmar Nova Senha',
2638
- placeholder: labels.confirmPasswordPlaceholder || 'Confirme a nova senha',
2639
- ...passwordForm.getInputProps('confirmPassword')
2640
- }), /*#__PURE__*/jsxs(Group, {
2641
- justify: "flex-end",
2642
- gap: "xs",
2643
- children: [/*#__PURE__*/jsx(Button, {
2644
- variant: "default",
2645
- size: "xs",
2646
- onClick: () => handleToggleSection('password'),
2647
- leftSection: /*#__PURE__*/jsx(IconX, {
2648
- size: 14
2649
- }),
2650
- children: labels.cancel || 'Cancelar'
2651
- }), /*#__PURE__*/jsx(Button, {
2652
- type: "submit",
2653
- size: "xs",
2654
- loading: loadingChangePassword,
2655
- leftSection: /*#__PURE__*/jsx(IconCheck, {
2656
- size: 14
2657
- }),
2658
- children: labels.save || 'Salvar'
2746
+ children: [showPassword && /*#__PURE__*/jsxs(Fragment, {
2747
+ children: [/*#__PURE__*/jsx(SettingRow, {
2748
+ label: labels.password || 'Password',
2749
+ action: labels.change || 'Change',
2750
+ actionLabel: labels.changePassword || 'Change your password',
2751
+ onClick: () => handleToggleSection('password'),
2752
+ expanded: editingSection === 'password',
2753
+ children: /*#__PURE__*/jsxs(Group, {
2754
+ gap: "xs",
2755
+ children: [/*#__PURE__*/jsx(IconKey, {
2756
+ size: 16,
2757
+ color: "var(--mantine-color-dimmed)"
2758
+ }), /*#__PURE__*/jsx(Text, {
2759
+ size: "sm",
2760
+ c: "dimmed",
2761
+ children: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
2762
+ })]
2763
+ })
2764
+ }), /*#__PURE__*/jsx(Collapse, {
2765
+ in: editingSection === 'password',
2766
+ children: /*#__PURE__*/jsx(Card, {
2767
+ p: "md",
2768
+ withBorder: true,
2769
+ children: /*#__PURE__*/jsx("form", {
2770
+ onSubmit: passwordForm.onSubmit(handleChangePassword),
2771
+ children: /*#__PURE__*/jsxs(Stack, {
2772
+ gap: "sm",
2773
+ children: [/*#__PURE__*/jsx(PasswordInput, {
2774
+ label: labels.currentPassword || 'Senha Atual',
2775
+ placeholder: labels.currentPasswordPlaceholder || 'Digite sua senha atual',
2776
+ ...passwordForm.getInputProps('currentPassword')
2777
+ }), /*#__PURE__*/jsx(PasswordInput, {
2778
+ label: labels.newPassword || 'Nova Senha',
2779
+ placeholder: labels.newPasswordPlaceholder || 'Digite a nova senha',
2780
+ description: labels.passwordDescription || 'Mínimo 8 caracteres',
2781
+ ...passwordForm.getInputProps('newPassword')
2782
+ }), /*#__PURE__*/jsx(PasswordInput, {
2783
+ label: labels.confirmPassword || 'Confirmar Nova Senha',
2784
+ placeholder: labels.confirmPasswordPlaceholder || 'Confirme a nova senha',
2785
+ ...passwordForm.getInputProps('confirmPassword')
2786
+ }), /*#__PURE__*/jsxs(Group, {
2787
+ justify: "flex-end",
2788
+ gap: "xs",
2789
+ children: [/*#__PURE__*/jsx(Button, {
2790
+ variant: "default",
2791
+ size: "xs",
2792
+ onClick: () => handleToggleSection('password'),
2793
+ leftSection: /*#__PURE__*/jsx(IconX, {
2794
+ size: 14
2795
+ }),
2796
+ children: labels.cancel || 'Cancelar'
2797
+ }), /*#__PURE__*/jsx(Button, {
2798
+ type: "submit",
2799
+ size: "xs",
2800
+ loading: loadingChangePassword,
2801
+ leftSection: /*#__PURE__*/jsx(IconCheck, {
2802
+ size: 14
2803
+ }),
2804
+ children: labels.save || 'Salvar'
2805
+ })]
2659
2806
  })]
2660
- })]
2807
+ })
2661
2808
  })
2662
2809
  })
2663
- })
2810
+ })]
2811
+ }), showSessions && /*#__PURE__*/jsxs(Fragment, {
2812
+ children: [/*#__PURE__*/jsx(SettingRow, {
2813
+ label: labels.sessions || 'Sessions',
2814
+ action: editingSection === 'sessions' ? labels.close || 'Close' : labels.manage || 'Manage',
2815
+ actionLabel: labels.manageSessions || 'Manage your active sessions',
2816
+ onClick: () => handleToggleSection('sessions'),
2817
+ expanded: editingSection === 'sessions',
2818
+ children: /*#__PURE__*/jsxs(Group, {
2819
+ gap: "xs",
2820
+ children: [/*#__PURE__*/jsx(IconDevices, {
2821
+ size: 16,
2822
+ color: "var(--mantine-color-dimmed)"
2823
+ }), /*#__PURE__*/jsx(Text, {
2824
+ size: "sm",
2825
+ c: "dimmed",
2826
+ children: sessions.length > 0 ? `${sessions.length} active session${sessions.length > 1 ? 's' : ''}` : loadingListSessions ? 'Loading...' : 'No sessions'
2827
+ })]
2828
+ })
2829
+ }), /*#__PURE__*/jsx(Collapse, {
2830
+ in: editingSection === 'sessions',
2831
+ children: /*#__PURE__*/jsx(Card, {
2832
+ p: "md",
2833
+ withBorder: true,
2834
+ children: /*#__PURE__*/jsx(Stack, {
2835
+ gap: "md",
2836
+ children: loadingListSessions ? /*#__PURE__*/jsx(Text, {
2837
+ size: "sm",
2838
+ c: "dimmed",
2839
+ ta: "center",
2840
+ children: labels.loadingSessions || 'Carregando sessões...'
2841
+ }) : sessions.length === 0 ? /*#__PURE__*/jsx(Text, {
2842
+ size: "sm",
2843
+ c: "dimmed",
2844
+ ta: "center",
2845
+ children: labels.noSessionsFound || 'Nenhuma sessão encontrada'
2846
+ }) : /*#__PURE__*/jsxs(Fragment, {
2847
+ children: [sessions.map(sessionItem => {
2848
+ const isCurrentSession = sessionItem.id === currentSession?.id;
2849
+ const deviceInfo = parseUserAgent(sessionItem.userAgent);
2850
+ const createdDate = new Date(sessionItem.createdAt);
2851
+ return /*#__PURE__*/jsx(Card, {
2852
+ p: "sm",
2853
+ style: {
2854
+ borderColor: isCurrentSession ? 'var(--mantine-color-blue-5)' : undefined,
2855
+ backgroundColor: isCurrentSession ? 'var(--mantine-color-blue-light)' : undefined
2856
+ },
2857
+ children: /*#__PURE__*/jsxs(Group, {
2858
+ justify: "space-between",
2859
+ wrap: "nowrap",
2860
+ children: [/*#__PURE__*/jsxs(Group, {
2861
+ gap: "sm",
2862
+ wrap: "nowrap",
2863
+ style: {
2864
+ flex: 1
2865
+ },
2866
+ children: [/*#__PURE__*/jsx(ThemeIcon, {
2867
+ size: 36,
2868
+ variant: "light",
2869
+ color: isCurrentSession ? 'blue' : 'gray',
2870
+ children: /*#__PURE__*/jsx(IconDeviceMobile, {
2871
+ size: 18
2872
+ })
2873
+ }), /*#__PURE__*/jsxs(Box, {
2874
+ style: {
2875
+ flex: 1
2876
+ },
2877
+ children: [/*#__PURE__*/jsxs(Group, {
2878
+ gap: "xs",
2879
+ children: [/*#__PURE__*/jsx(Text, {
2880
+ size: "sm",
2881
+ fw: 500,
2882
+ children: deviceInfo.browser
2883
+ }), isCurrentSession && /*#__PURE__*/jsx(Badge, {
2884
+ size: "xs",
2885
+ variant: "filled",
2886
+ color: "blue",
2887
+ children: labels.thisDevice || 'Este dispositivo'
2888
+ })]
2889
+ }), /*#__PURE__*/jsxs(Text, {
2890
+ size: "xs",
2891
+ c: "dimmed",
2892
+ children: [deviceInfo.os, " \u2022 ", sessionItem.ipAddress || labels.unknownIP || 'IP desconhecido']
2893
+ }), /*#__PURE__*/jsxs(Text, {
2894
+ size: "xs",
2895
+ c: "dimmed",
2896
+ children: [labels.createdAt || 'Criada em', " ", createdDate.toLocaleDateString('pt-BR'), " ", labels.at || 'às', ' ', createdDate.toLocaleTimeString('pt-BR', {
2897
+ hour: '2-digit',
2898
+ minute: '2-digit'
2899
+ })]
2900
+ })]
2901
+ })]
2902
+ }), /*#__PURE__*/jsx(Tooltip, {
2903
+ label: isCurrentSession ? labels.signOutAndEnd || 'Encerrar e sair' : labels.endSession || 'Encerrar sessão',
2904
+ children: /*#__PURE__*/jsx(Button, {
2905
+ variant: "light",
2906
+ color: "red",
2907
+ size: "xs",
2908
+ onClick: () => handleRevokeSession(sessionItem.id),
2909
+ loading: loadingRevokeSession,
2910
+ leftSection: /*#__PURE__*/jsx(IconLogout, {
2911
+ size: 14
2912
+ }),
2913
+ children: labels.end || 'Encerrar'
2914
+ })
2915
+ })]
2916
+ })
2917
+ }, sessionItem.id);
2918
+ }), sessions.length > 1 && /*#__PURE__*/jsx(Group, {
2919
+ justify: "flex-end",
2920
+ children: /*#__PURE__*/jsx(Button, {
2921
+ variant: "light",
2922
+ color: "red",
2923
+ size: "xs",
2924
+ onClick: handleRevokeOtherSessions,
2925
+ loading: loadingRevokeSession,
2926
+ leftSection: /*#__PURE__*/jsx(IconLogout, {
2927
+ size: 14
2928
+ }),
2929
+ children: labels.endOtherSessions || 'Encerrar todas as outras sessões'
2930
+ })
2931
+ })]
2932
+ })
2933
+ })
2934
+ })
2935
+ })]
2664
2936
  })]
2665
2937
  })]
2666
2938
  })]
@@ -2844,5 +3116,5 @@ function SignOutButton({
2844
3116
  });
2845
3117
  }
2846
3118
 
2847
- export { UserProfile as AccountModal, AuthCard, AuthLoaded, AuthLoading, AuthProvider, ForgotPassword, ForgotPassword as ForgotPasswordForm, MagicLink, MagicLinkCallback, MagicLink as MagicLinkForm, MagicLinkCallback as MagicLinkVerify, Protect, Protect as ProtectedRoute, ResetPassword, ResetPassword as ResetPasswordForm, SignIn, SignInButton, SignIn as SignInForm, SignOutButton, SignUp, SignUpButton, SignUp as SignUpForm, SignedIn, SignedOut, UserProfile, VerifyEmail, VerifyEmail as VerifyEmailCard, changeEmail, changePassword, configure, decodeJWT, forgotPassword, getApplicationInfo, getCurrentUser, getSession, isAuthenticated, listSessions, refreshToken, resendVerification, resetPassword, revokeOtherSessions, revokeSession, sendMagicLink, signIn, signOut, signUp, socialRedirect, updateProfile, useApplicationLogo, useAuth, useAuthLoading, useAuthStore, useCheckToken, useEmailVerification, useMagicLink, usePasswordReset, useUser as useProfile, useSession, useSignIn, useSignOut, useSignUp, useUser, verifyEmail, verifyMagicLink };
3119
+ export { UserProfile as AccountModal, AuthCard, AuthLoaded, AuthLoading, AuthProvider, ForgotPassword, ForgotPassword as ForgotPasswordForm, MagicLink, MagicLinkCallback, MagicLink as MagicLinkForm, MagicLinkCallback as MagicLinkVerify, Protect, Protect as ProtectedRoute, ResetPassword, ResetPassword as ResetPasswordForm, SignIn, SignInButton, SignIn as SignInForm, SignOutButton, SignUp, SignUpButton, SignUp as SignUpForm, SignedIn, SignedOut, UserProfile, VerifyEmail, VerifyEmail as VerifyEmailCard, changeEmail, changePassword, configure, decodeJWT, forgotPassword, getApplicationInfo, getCurrentUser, getSession, isAuthenticated, listSessions, refreshToken, resendVerification, resetPassword, revokeOtherSessions, revokeSession, sendMagicLink, signIn, signOut, signUp, socialRedirect, updateProfile, useApplicationLogo, useAuth, useAuthLoading, useAuthStore, useCheckToken, useEmailVerification, useMagicLink, usePasswordReset, useUser as useProfile, useSession, useSessions, useSignIn, useSignOut, useSignUp, useUser, verifyEmail, verifyMagicLink };
2848
3120
  //# sourceMappingURL=index.esm.js.map