@riligar/auth-react 1.9.3 → 1.10.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
@@ -8,6 +8,7 @@ var reactRouterDom = require('react-router-dom');
8
8
  var core = require('@mantine/core');
9
9
  var form = require('@mantine/form');
10
10
  var iconsReact = require('@tabler/icons-react');
11
+ var notifications = require('@mantine/notifications');
11
12
 
12
13
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
13
14
  // Config - pode ser sobrescrita pelo AuthProvider
@@ -284,6 +285,34 @@ const getApplicationInfo = async () => {
284
285
  }
285
286
  };
286
287
 
288
+ /*--- Profile Management ---------------------------*/
289
+ const updateProfile = async data => {
290
+ return await api('/auth/update-user', {
291
+ method: 'POST',
292
+ body: JSON.stringify(data)
293
+ });
294
+ };
295
+ const changePassword = async (currentPassword, newPassword, revokeOtherSessions = false) => {
296
+ return await api('/auth/change-password', {
297
+ method: 'POST',
298
+ body: JSON.stringify({
299
+ currentPassword,
300
+ newPassword,
301
+ revokeOtherSessions
302
+ })
303
+ });
304
+ };
305
+ const changeEmail = async (newEmail, callbackURL) => {
306
+ const callback = callbackURL || (typeof window !== 'undefined' ? `${window.location.origin}/auth/verify-email` : '/auth/verify-email');
307
+ return await api('/auth/change-email', {
308
+ method: 'POST',
309
+ body: JSON.stringify({
310
+ newEmail,
311
+ callbackURL: callback
312
+ })
313
+ });
314
+ };
315
+
287
316
  /* Social login redirect (ex.: Google) -----------*/
288
317
  function socialRedirect(provider, redirectTo = typeof window !== 'undefined' ? window.location.href : '/') {
289
318
  if (typeof window === 'undefined') return;
@@ -304,7 +333,10 @@ const useAuthStore = zustand.create((set, get) => ({
304
333
  verifyMagicLink: false,
305
334
  resetPassword: false,
306
335
  verifyEmail: false,
307
- resendVerification: false
336
+ resendVerification: false,
337
+ updateProfile: false,
338
+ changePassword: false,
339
+ changeEmail: false
308
340
  },
309
341
  // Application info (logo, nome, etc)
310
342
  applicationInfo: null,
@@ -671,7 +703,75 @@ const useAuthStore = zustand.create((set, get) => ({
671
703
  /* Atualizar usuário manualmente */
672
704
  setUser: user => set({
673
705
  user
674
- })
706
+ }),
707
+ /* Profile Management */
708
+ updateProfile: async data => {
709
+ const {
710
+ setLoading
711
+ } = get();
712
+ setLoading('updateProfile', true);
713
+ set({
714
+ error: null
715
+ });
716
+ try {
717
+ const result = await updateProfile(data);
718
+ // Atualiza o user no store com os novos dados
719
+ set(state => ({
720
+ user: state.user ? {
721
+ ...state.user,
722
+ ...data
723
+ } : null
724
+ }));
725
+ setLoading('updateProfile', false);
726
+ return result;
727
+ } catch (err) {
728
+ set({
729
+ error: err
730
+ });
731
+ setLoading('updateProfile', false);
732
+ throw err;
733
+ }
734
+ },
735
+ changePassword: async (currentPassword, newPassword, revokeOtherSessions = false) => {
736
+ const {
737
+ setLoading
738
+ } = get();
739
+ setLoading('changePassword', true);
740
+ set({
741
+ error: null
742
+ });
743
+ try {
744
+ const result = await changePassword(currentPassword, newPassword, revokeOtherSessions);
745
+ setLoading('changePassword', false);
746
+ return result;
747
+ } catch (err) {
748
+ set({
749
+ error: err
750
+ });
751
+ setLoading('changePassword', false);
752
+ throw err;
753
+ }
754
+ },
755
+ changeEmail: async (newEmail, callbackURL) => {
756
+ const {
757
+ setLoading
758
+ } = get();
759
+ setLoading('changeEmail', true);
760
+ set({
761
+ error: null
762
+ });
763
+ try {
764
+ const result = await changeEmail(newEmail, callbackURL);
765
+ setLoading('changeEmail', false);
766
+ return result;
767
+ } catch (err) {
768
+ set({
769
+ error: err
770
+ });
771
+ setLoading('changeEmail', false);
772
+ throw err;
773
+ }
774
+ }
675
775
  }));
676
776
 
677
777
  const AuthContext = /*#__PURE__*/react.createContext(); // só para ter o Provider em JSX
@@ -795,6 +895,18 @@ const useSession = () => useAuthStore(shallow.useShallow(s => ({
795
895
  // Loading States Hook
796
896
  const useAuthLoading = () => useAuthStore(s => s.loadingStates);
797
897
 
898
+ // Profile Management Hook
899
+ const useProfile = () => useAuthStore(shallow.useShallow(s => ({
900
+ user: s.user,
901
+ updateProfile: s.updateProfile,
902
+ changePassword: s.changePassword,
903
+ changeEmail: s.changeEmail,
904
+ loadingUpdateProfile: s.loadingStates.updateProfile,
905
+ loadingChangePassword: s.loadingStates.changePassword,
906
+ loadingChangeEmail: s.loadingStates.changeEmail,
907
+ error: s.error
908
+ })));
909
+
798
910
  // Application Logo Hook
799
911
  const useApplicationLogo = () => {
800
912
  const applicationInfo = useAuthStore(s => s.applicationInfo);
@@ -1731,6 +1843,682 @@ function VerifyEmailCard({
1731
1843
  });
1732
1844
  }
1733
1845
 
1846
+ function AccountModal({
1847
+ // Controle do modal
1848
+ opened,
1849
+ onClose,
1850
+ // Callbacks
1851
+ onProfileUpdate,
1852
+ onPasswordChange,
1853
+ onEmailChange,
1854
+ onError,
1855
+ // Features toggle
1856
+ showAvatar = true,
1857
+ showName = true,
1858
+ showEmail = true,
1859
+ showPassword = true,
1860
+ // Customização
1861
+ labels = {},
1862
+ title = 'Account',
1863
+ subtitle = 'Manage your account info.',
1864
+ // Avatar config
1865
+ maxAvatarSize = 500 * 1024,
1866
+ // 500KB
1867
+
1868
+ ...modalProps
1869
+ }) {
1870
+ // Local state - which section is expanded
1871
+ const [editingSection, setEditingSection] = react.useState(null); // 'password' | 'email' | 'name' | 'avatar' | null
1872
+
1873
+ // Hook para profile
1874
+ const {
1875
+ user,
1876
+ updateProfile,
1877
+ changePassword,
1878
+ changeEmail,
1879
+ loadingUpdateProfile,
1880
+ loadingChangePassword,
1881
+ loadingChangeEmail
1882
+ } = useProfile();
1883
+
1884
+ // Password form
1885
+ const passwordForm = form.useForm({
1886
+ initialValues: {
1887
+ currentPassword: '',
1888
+ newPassword: '',
1889
+ confirmPassword: ''
1890
+ },
1891
+ validate: {
1892
+ currentPassword: v => !v ? labels.currentPasswordRequired || 'Senha atual obrigatória' : null,
1893
+ newPassword: v => {
1894
+ if (!v) return labels.newPasswordRequired || 'Nova senha obrigatória';
1895
+ if (v.length < 8) return labels.passwordMinLength || 'Mínimo 8 caracteres';
1896
+ return null;
1897
+ },
1898
+ confirmPassword: (v, values) => v !== values.newPassword ? labels.passwordMismatch || 'Senhas não coincidem' : null
1899
+ }
1900
+ });
1901
+
1902
+ // Email form
1903
+ const emailForm = form.useForm({
1904
+ initialValues: {
1905
+ newEmail: ''
1906
+ },
1907
+ validate: {
1908
+ newEmail: v => {
1909
+ if (!v) return labels.emailRequired || 'Email obrigatório';
1910
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) return labels.emailInvalid || 'Email inválido';
1911
+ return null;
1912
+ }
1913
+ }
1914
+ });
1915
+
1916
+ // Name form
1917
+ const nameForm = form.useForm({
1918
+ initialValues: {
1919
+ name: ''
1920
+ },
1921
+ validate: {
1922
+ name: v => !v ? labels.nameRequired || 'Nome obrigatório' : null
1923
+ }
1924
+ });
1925
+
1926
+ // Avatar state (base64)
1927
+ const [avatarPreview, setAvatarPreview] = react.useState(null);
1928
+ const [avatarFile, setAvatarFile] = react.useState(null);
1929
+
1930
+ // Handle file selection and convert to base64
1931
+ const handleAvatarFileChange = file => {
1932
+ if (!file) {
1933
+ setAvatarPreview(null);
1934
+ setAvatarFile(null);
1935
+ return;
1936
+ }
1937
+
1938
+ // Validate file type
1939
+ if (!file.type.startsWith('image/')) {
1940
+ notifications.notifications.show({
1941
+ title: labels.errorTitle || 'Erro',
1942
+ message: labels.avatarInvalidType || 'Por favor, selecione uma imagem válida',
1943
+ color: 'red'
1944
+ });
1945
+ return;
1946
+ }
1947
+
1948
+ // Validate file size
1949
+ if (file.size > maxAvatarSize) {
1950
+ notifications.notifications.show({
1951
+ title: labels.errorTitle || 'Erro',
1952
+ message: labels.avatarTooLarge || `Imagem muito grande. Máximo ${Math.round(maxAvatarSize / 1024)}KB.`,
1953
+ color: 'red'
1954
+ });
1955
+ return;
1956
+ }
1957
+ setAvatarFile(file);
1958
+
1959
+ // Convert to base64
1960
+ const reader = new FileReader();
1961
+ reader.onloadend = () => {
1962
+ setAvatarPreview(reader.result);
1963
+ };
1964
+ reader.readAsDataURL(file);
1965
+ };
1966
+
1967
+ // Populate forms when user data is available or section opens
1968
+ react.useEffect(() => {
1969
+ if (editingSection === 'name' && user?.name) {
1970
+ nameForm.setValues({
1971
+ name: user.name
1972
+ });
1973
+ }
1974
+ if (editingSection === 'avatar' && user?.image) {
1975
+ setAvatarPreview(user.image);
1976
+ }
1977
+ }, [editingSection, user]);
1978
+ const handleToggleSection = section => {
1979
+ if (editingSection === section) {
1980
+ setEditingSection(null);
1981
+ passwordForm.reset();
1982
+ emailForm.reset();
1983
+ nameForm.reset();
1984
+ setAvatarPreview(null);
1985
+ setAvatarFile(null);
1986
+ } else {
1987
+ setEditingSection(section);
1988
+ }
1989
+ };
1990
+ const handleChangePassword = async values => {
1991
+ try {
1992
+ await changePassword(values.currentPassword, values.newPassword);
1993
+ notifications.notifications.show({
1994
+ title: labels.successTitle || 'Sucesso',
1995
+ message: labels.passwordChanged || 'Senha alterada com sucesso',
1996
+ color: 'green'
1997
+ });
1998
+ passwordForm.reset();
1999
+ setEditingSection(null);
2000
+ onPasswordChange?.();
2001
+ } catch (error) {
2002
+ notifications.notifications.show({
2003
+ title: labels.errorTitle || 'Erro',
2004
+ message: error.message || labels.passwordChangeFailed || 'Falha ao alterar senha',
2005
+ color: 'red'
2006
+ });
2007
+ onError?.(error);
2008
+ }
2009
+ };
2010
+ const handleChangeEmail = async values => {
2011
+ try {
2012
+ await changeEmail(values.newEmail);
2013
+ notifications.notifications.show({
2014
+ title: labels.successTitle || 'Sucesso',
2015
+ message: labels.emailVerificationSent || 'Verifique seu novo email para confirmar a alteração',
2016
+ color: 'green'
2017
+ });
2018
+ emailForm.reset();
2019
+ setEditingSection(null);
2020
+ onEmailChange?.(values.newEmail);
2021
+ } catch (error) {
2022
+ notifications.notifications.show({
2023
+ title: labels.errorTitle || 'Erro',
2024
+ message: error.message || labels.emailChangeFailed || 'Falha ao alterar email',
2025
+ color: 'red'
2026
+ });
2027
+ onError?.(error);
2028
+ }
2029
+ };
2030
+ const handleChangeName = async values => {
2031
+ try {
2032
+ await updateProfile({
2033
+ name: values.name
2034
+ });
2035
+ notifications.notifications.show({
2036
+ title: labels.successTitle || 'Sucesso',
2037
+ message: labels.nameUpdated || 'Nome atualizado com sucesso',
2038
+ color: 'green'
2039
+ });
2040
+ nameForm.reset();
2041
+ setEditingSection(null);
2042
+ onProfileUpdate?.({
2043
+ name: values.name
2044
+ });
2045
+ } catch (error) {
2046
+ notifications.notifications.show({
2047
+ title: labels.errorTitle || 'Erro',
2048
+ message: error.message || labels.nameUpdateFailed || 'Falha ao atualizar nome',
2049
+ color: 'red'
2050
+ });
2051
+ onError?.(error);
2052
+ }
2053
+ };
2054
+ const handleChangeAvatar = async () => {
2055
+ if (!avatarPreview) {
2056
+ notifications.notifications.show({
2057
+ title: labels.errorTitle || 'Erro',
2058
+ message: labels.avatarRequired || 'Selecione uma imagem',
2059
+ color: 'red'
2060
+ });
2061
+ return;
2062
+ }
2063
+ try {
2064
+ await updateProfile({
2065
+ image: avatarPreview
2066
+ });
2067
+ notifications.notifications.show({
2068
+ title: labels.successTitle || 'Sucesso',
2069
+ message: labels.avatarUpdated || 'Foto de perfil atualizada com sucesso',
2070
+ color: 'green'
2071
+ });
2072
+ setAvatarPreview(null);
2073
+ setAvatarFile(null);
2074
+ setEditingSection(null);
2075
+ onProfileUpdate?.({
2076
+ image: avatarPreview
2077
+ });
2078
+ } catch (error) {
2079
+ notifications.notifications.show({
2080
+ title: labels.errorTitle || 'Erro',
2081
+ message: error.message || labels.avatarUpdateFailed || 'Falha ao atualizar foto',
2082
+ color: 'red'
2083
+ });
2084
+ onError?.(error);
2085
+ }
2086
+ };
2087
+ const handleRemoveAvatar = async () => {
2088
+ try {
2089
+ await updateProfile({
2090
+ image: ''
2091
+ });
2092
+ notifications.notifications.show({
2093
+ title: labels.successTitle || 'Sucesso',
2094
+ message: labels.avatarRemoved || 'Foto de perfil removida',
2095
+ color: 'green'
2096
+ });
2097
+ setAvatarPreview(null);
2098
+ setAvatarFile(null);
2099
+ setEditingSection(null);
2100
+ onProfileUpdate?.({
2101
+ image: ''
2102
+ });
2103
+ } catch (error) {
2104
+ notifications.notifications.show({
2105
+ title: labels.errorTitle || 'Erro',
2106
+ message: error.message || labels.avatarRemoveFailed || 'Falha ao remover foto',
2107
+ color: 'red'
2108
+ });
2109
+ onError?.(error);
2110
+ }
2111
+ };
2112
+
2113
+ // Reusable Section Header
2114
+ const SectionHeader = ({
2115
+ icon: Icon,
2116
+ sectionTitle,
2117
+ description
2118
+ }) => /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2119
+ gap: "sm",
2120
+ mb: "lg",
2121
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.ThemeIcon, {
2122
+ size: 36,
2123
+ variant: "light",
2124
+ children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
2125
+ size: 18
2126
+ })
2127
+ }), /*#__PURE__*/jsxRuntime.jsxs(core.Box, {
2128
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.Text, {
2129
+ fw: 600,
2130
+ size: "md",
2131
+ children: sectionTitle
2132
+ }), description && /*#__PURE__*/jsxRuntime.jsx(core.Text, {
2133
+ size: "xs",
2134
+ c: "dimmed",
2135
+ children: description
2136
+ })]
2137
+ })]
2138
+ });
2139
+
2140
+ // Reusable Row component
2141
+ const SettingRow = ({
2142
+ label,
2143
+ children,
2144
+ action,
2145
+ actionLabel,
2146
+ onClick,
2147
+ expanded
2148
+ }) => /*#__PURE__*/jsxRuntime.jsx(core.Card, {
2149
+ p: "xs",
2150
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2151
+ justify: "space-between",
2152
+ wrap: "nowrap",
2153
+ children: [/*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2154
+ gap: "xl",
2155
+ wrap: "nowrap",
2156
+ flex: 1,
2157
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.Text, {
2158
+ size: "sm",
2159
+ c: "dimmed",
2160
+ w: 100,
2161
+ style: {
2162
+ flexShrink: 0
2163
+ },
2164
+ children: label
2165
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Box, {
2166
+ flex: 1,
2167
+ children: children
2168
+ })]
2169
+ }), action && /*#__PURE__*/jsxRuntime.jsx(core.Tooltip, {
2170
+ label: actionLabel || action,
2171
+ position: "left",
2172
+ children: /*#__PURE__*/jsxRuntime.jsx(core.Anchor, {
2173
+ size: "sm",
2174
+ fw: 500,
2175
+ onClick: onClick,
2176
+ c: expanded ? 'red' : 'blue',
2177
+ children: expanded ? labels.cancel || 'Cancel' : action
2178
+ })
2179
+ })]
2180
+ })
2181
+ });
2182
+ return /*#__PURE__*/jsxRuntime.jsxs(core.Modal, {
2183
+ opened: opened,
2184
+ onClose: onClose,
2185
+ size: 550,
2186
+ withCloseButton: true,
2187
+ radius: "lg",
2188
+ overlayProps: {
2189
+ backgroundOpacity: 0.55,
2190
+ blur: 3
2191
+ },
2192
+ title: /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2193
+ gap: "md",
2194
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.ThemeIcon, {
2195
+ size: 44,
2196
+ variant: "light",
2197
+ children: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconUserCircle, {
2198
+ size: 24
2199
+ })
2200
+ }), /*#__PURE__*/jsxRuntime.jsxs(core.Box, {
2201
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.Title, {
2202
+ order: 4,
2203
+ children: title
2204
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Text, {
2205
+ size: "sm",
2206
+ c: "dimmed",
2207
+ children: subtitle
2208
+ })]
2209
+ })]
2210
+ }),
2211
+ ...modalProps,
2212
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.Divider, {
2213
+ mb: "md"
2214
+ }), (showAvatar || showName || showEmail) && /*#__PURE__*/jsxRuntime.jsxs(core.Box, {
2215
+ mb: "xl",
2216
+ children: [/*#__PURE__*/jsxRuntime.jsx(SectionHeader, {
2217
+ icon: iconsReact.IconUser,
2218
+ sectionTitle: labels.profileSection || 'Profile',
2219
+ description: labels.profileDescription || 'Your personal information'
2220
+ }), /*#__PURE__*/jsxRuntime.jsxs(core.Stack, {
2221
+ gap: "sm",
2222
+ children: [showAvatar && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
2223
+ children: [/*#__PURE__*/jsxRuntime.jsx(SettingRow, {
2224
+ label: labels.avatar || 'Avatar',
2225
+ action: labels.update || 'Update',
2226
+ actionLabel: labels.updateAvatar || 'Update your profile picture',
2227
+ onClick: () => handleToggleSection('avatar'),
2228
+ expanded: editingSection === 'avatar',
2229
+ children: /*#__PURE__*/jsxRuntime.jsx(core.Group, {
2230
+ gap: "md",
2231
+ children: /*#__PURE__*/jsxRuntime.jsx(core.Avatar, {
2232
+ src: user?.image,
2233
+ name: user?.name || user?.email,
2234
+ size: 48,
2235
+ radius: "xl",
2236
+ color: "initials"
2237
+ })
2238
+ })
2239
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Collapse, {
2240
+ in: editingSection === 'avatar',
2241
+ children: /*#__PURE__*/jsxRuntime.jsx(core.Card, {
2242
+ p: "md",
2243
+ withBorder: true,
2244
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Stack, {
2245
+ gap: "md",
2246
+ align: "center",
2247
+ children: [/*#__PURE__*/jsxRuntime.jsx("input", {
2248
+ type: "file",
2249
+ id: "avatar-upload",
2250
+ accept: "image/*",
2251
+ style: {
2252
+ display: 'none'
2253
+ },
2254
+ onChange: e => handleAvatarFileChange(e.target.files?.[0])
2255
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Tooltip, {
2256
+ label: labels.clickToChange || 'Clique para alterar',
2257
+ position: "bottom",
2258
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Box, {
2259
+ onClick: () => document.getElementById('avatar-upload')?.click(),
2260
+ style: {
2261
+ position: 'relative',
2262
+ cursor: 'pointer',
2263
+ borderRadius: '50%'
2264
+ },
2265
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.Avatar, {
2266
+ src: avatarPreview || user?.image,
2267
+ name: user?.name || user?.email,
2268
+ size: 100,
2269
+ radius: 100,
2270
+ color: "initials"
2271
+ }), /*#__PURE__*/jsxRuntime.jsx(core.ThemeIcon, {
2272
+ size: 32,
2273
+ radius: "xl",
2274
+ color: "blue",
2275
+ style: {
2276
+ position: 'absolute',
2277
+ bottom: 0,
2278
+ right: 0,
2279
+ border: '2px solid var(--mantine-color-body)'
2280
+ },
2281
+ children: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconPhoto, {
2282
+ size: 16
2283
+ })
2284
+ })]
2285
+ })
2286
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Text, {
2287
+ size: "xs",
2288
+ c: "dimmed",
2289
+ ta: "center",
2290
+ children: labels.avatarHint || `Máximo ${Math.round(maxAvatarSize / 1024)}KB • JPG, PNG, GIF, WebP`
2291
+ }), /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2292
+ justify: "center",
2293
+ gap: "sm",
2294
+ children: [user?.image && /*#__PURE__*/jsxRuntime.jsx(core.Tooltip, {
2295
+ label: labels.removePhoto || 'Remover foto',
2296
+ children: /*#__PURE__*/jsxRuntime.jsx(core.Button, {
2297
+ variant: "light",
2298
+ color: "red",
2299
+ size: "xs",
2300
+ onClick: handleRemoveAvatar,
2301
+ loading: loadingUpdateProfile,
2302
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconTrash, {
2303
+ size: 14
2304
+ }),
2305
+ children: labels.remove || 'Remover'
2306
+ })
2307
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Button, {
2308
+ variant: "default",
2309
+ size: "xs",
2310
+ onClick: () => handleToggleSection('avatar'),
2311
+ children: labels.cancel || 'Cancelar'
2312
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Button, {
2313
+ size: "xs",
2314
+ loading: loadingUpdateProfile,
2315
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconCheck, {
2316
+ size: 14
2317
+ }),
2318
+ onClick: handleChangeAvatar,
2319
+ disabled: !avatarPreview || avatarPreview === user?.image,
2320
+ children: labels.save || 'Salvar'
2321
+ })]
2322
+ })]
2323
+ })
2324
+ })
2325
+ })]
2326
+ }), showName && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
2327
+ children: [/*#__PURE__*/jsxRuntime.jsx(SettingRow, {
2328
+ label: labels.name || 'Nome',
2329
+ action: labels.change || 'Change',
2330
+ actionLabel: labels.changeName || 'Change your display name',
2331
+ onClick: () => handleToggleSection('name'),
2332
+ expanded: editingSection === 'name',
2333
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2334
+ gap: "xs",
2335
+ children: [/*#__PURE__*/jsxRuntime.jsx(iconsReact.IconPencil, {
2336
+ size: 16,
2337
+ color: "var(--mantine-color-dimmed)"
2338
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Text, {
2339
+ size: "sm",
2340
+ children: user?.name || labels.notDefined || 'Não definido'
2341
+ })]
2342
+ })
2343
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Collapse, {
2344
+ in: editingSection === 'name',
2345
+ children: /*#__PURE__*/jsxRuntime.jsx(core.Card, {
2346
+ p: "md",
2347
+ withBorder: true,
2348
+ children: /*#__PURE__*/jsxRuntime.jsx("form", {
2349
+ onSubmit: nameForm.onSubmit(handleChangeName),
2350
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Stack, {
2351
+ gap: "sm",
2352
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.TextInput, {
2353
+ label: labels.name || 'Nome',
2354
+ placeholder: labels.namePlaceholder || 'Digite seu nome',
2355
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconUser, {
2356
+ size: 16
2357
+ }),
2358
+ ...nameForm.getInputProps('name')
2359
+ }), /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2360
+ justify: "flex-end",
2361
+ gap: "sm",
2362
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.Button, {
2363
+ variant: "default",
2364
+ size: "xs",
2365
+ onClick: () => handleToggleSection('name'),
2366
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconX, {
2367
+ size: 14
2368
+ }),
2369
+ children: labels.cancel || 'Cancelar'
2370
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Button, {
2371
+ type: "submit",
2372
+ size: "xs",
2373
+ loading: loadingUpdateProfile,
2374
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconCheck, {
2375
+ size: 14
2376
+ }),
2377
+ children: labels.save || 'Salvar'
2378
+ })]
2379
+ })]
2380
+ })
2381
+ })
2382
+ })
2383
+ })]
2384
+ }), showEmail && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
2385
+ children: [/*#__PURE__*/jsxRuntime.jsx(SettingRow, {
2386
+ label: labels.email || 'Email',
2387
+ action: labels.change || 'Change',
2388
+ actionLabel: labels.changeEmail || 'Change your email',
2389
+ onClick: () => handleToggleSection('email'),
2390
+ expanded: editingSection === 'email',
2391
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2392
+ gap: "xs",
2393
+ children: [/*#__PURE__*/jsxRuntime.jsx(iconsReact.IconMail, {
2394
+ size: 16,
2395
+ color: "var(--mantine-color-dimmed)"
2396
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Text, {
2397
+ size: "sm",
2398
+ children: user?.email || 'email@exemplo.com'
2399
+ })]
2400
+ })
2401
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Collapse, {
2402
+ in: editingSection === 'email',
2403
+ children: /*#__PURE__*/jsxRuntime.jsx(core.Card, {
2404
+ p: "md",
2405
+ withBorder: true,
2406
+ children: /*#__PURE__*/jsxRuntime.jsx("form", {
2407
+ onSubmit: emailForm.onSubmit(handleChangeEmail),
2408
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Stack, {
2409
+ gap: "sm",
2410
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.TextInput, {
2411
+ label: labels.newEmail || 'Novo Email',
2412
+ placeholder: labels.newEmailPlaceholder || 'Digite o novo email',
2413
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconMail, {
2414
+ size: 16
2415
+ }),
2416
+ ...emailForm.getInputProps('newEmail')
2417
+ }), /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2418
+ justify: "flex-end",
2419
+ gap: "sm",
2420
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.Button, {
2421
+ variant: "default",
2422
+ size: "xs",
2423
+ onClick: () => handleToggleSection('email'),
2424
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconX, {
2425
+ size: 14
2426
+ }),
2427
+ children: labels.cancel || 'Cancelar'
2428
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Button, {
2429
+ type: "submit",
2430
+ size: "xs",
2431
+ loading: loadingChangeEmail,
2432
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconCheck, {
2433
+ size: 14
2434
+ }),
2435
+ children: labels.save || 'Salvar'
2436
+ })]
2437
+ })]
2438
+ })
2439
+ })
2440
+ })
2441
+ })]
2442
+ })]
2443
+ })]
2444
+ }), showPassword && /*#__PURE__*/jsxRuntime.jsxs(core.Box, {
2445
+ mb: "md",
2446
+ children: [/*#__PURE__*/jsxRuntime.jsx(SectionHeader, {
2447
+ icon: iconsReact.IconShield,
2448
+ sectionTitle: labels.securitySection || 'Security',
2449
+ description: labels.securityDescription || 'Protect your account'
2450
+ }), /*#__PURE__*/jsxRuntime.jsxs(core.Stack, {
2451
+ gap: "sm",
2452
+ children: [/*#__PURE__*/jsxRuntime.jsx(SettingRow, {
2453
+ label: labels.password || 'Password',
2454
+ action: labels.change || 'Change',
2455
+ actionLabel: labels.changePassword || 'Change your password',
2456
+ onClick: () => handleToggleSection('password'),
2457
+ expanded: editingSection === 'password',
2458
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2459
+ gap: "xs",
2460
+ children: [/*#__PURE__*/jsxRuntime.jsx(iconsReact.IconKey, {
2461
+ size: 16,
2462
+ color: "var(--mantine-color-dimmed)"
2463
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Text, {
2464
+ size: "sm",
2465
+ c: "dimmed",
2466
+ children: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
2467
+ })]
2468
+ })
2469
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Collapse, {
2470
+ in: editingSection === 'password',
2471
+ children: /*#__PURE__*/jsxRuntime.jsx(core.Card, {
2472
+ p: "md",
2473
+ withBorder: true,
2474
+ children: /*#__PURE__*/jsxRuntime.jsx("form", {
2475
+ onSubmit: passwordForm.onSubmit(handleChangePassword),
2476
+ children: /*#__PURE__*/jsxRuntime.jsxs(core.Stack, {
2477
+ gap: "sm",
2478
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.PasswordInput, {
2479
+ label: labels.currentPassword || 'Senha Atual',
2480
+ placeholder: labels.currentPasswordPlaceholder || 'Digite sua senha atual',
2481
+ ...passwordForm.getInputProps('currentPassword')
2482
+ }), /*#__PURE__*/jsxRuntime.jsx(core.PasswordInput, {
2483
+ label: labels.newPassword || 'Nova Senha',
2484
+ placeholder: labels.newPasswordPlaceholder || 'Digite a nova senha',
2485
+ description: labels.passwordDescription || 'Mínimo 8 caracteres',
2486
+ ...passwordForm.getInputProps('newPassword')
2487
+ }), /*#__PURE__*/jsxRuntime.jsx(core.PasswordInput, {
2488
+ label: labels.confirmPassword || 'Confirmar Nova Senha',
2489
+ placeholder: labels.confirmPasswordPlaceholder || 'Confirme a nova senha',
2490
+ ...passwordForm.getInputProps('confirmPassword')
2491
+ }), /*#__PURE__*/jsxRuntime.jsxs(core.Group, {
2492
+ justify: "flex-end",
2493
+ gap: "xs",
2494
+ children: [/*#__PURE__*/jsxRuntime.jsx(core.Button, {
2495
+ variant: "default",
2496
+ size: "xs",
2497
+ onClick: () => handleToggleSection('password'),
2498
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconX, {
2499
+ size: 14
2500
+ }),
2501
+ children: labels.cancel || 'Cancelar'
2502
+ }), /*#__PURE__*/jsxRuntime.jsx(core.Button, {
2503
+ type: "submit",
2504
+ size: "xs",
2505
+ loading: loadingChangePassword,
2506
+ leftSection: /*#__PURE__*/jsxRuntime.jsx(iconsReact.IconCheck, {
2507
+ size: 14
2508
+ }),
2509
+ children: labels.save || 'Salvar'
2510
+ })]
2511
+ })]
2512
+ })
2513
+ })
2514
+ })
2515
+ })]
2516
+ })]
2517
+ })]
2518
+ });
2519
+ }
2520
+
2521
+ exports.AccountModal = AccountModal;
1734
2522
  exports.AuthCard = AuthCard;
1735
2523
  exports.AuthProvider = AuthProvider;
1736
2524
  exports.ForgotPasswordForm = ForgotPasswordForm;
@@ -1741,6 +2529,8 @@ exports.ResetPasswordForm = ResetPasswordForm;
1741
2529
  exports.SignInForm = SignInForm;
1742
2530
  exports.SignUpForm = SignUpForm;
1743
2531
  exports.VerifyEmailCard = VerifyEmailCard;
2532
+ exports.changeEmail = changeEmail;
2533
+ exports.changePassword = changePassword;
1744
2534
  exports.configure = configure;
1745
2535
  exports.decodeJWT = decodeJWT;
1746
2536
  exports.forgotPassword = forgotPassword;
@@ -1756,6 +2546,7 @@ exports.signIn = signIn;
1756
2546
  exports.signOut = signOut;
1757
2547
  exports.signUp = signUp;
1758
2548
  exports.socialRedirect = socialRedirect;
2549
+ exports.updateProfile = updateProfile;
1759
2550
  exports.useAuth = useAuth;
1760
2551
  exports.useAuthLoading = useAuthLoading;
1761
2552
  exports.useAuthStore = useAuthStore;
@@ -1763,6 +2554,7 @@ exports.useCheckToken = useCheckToken;
1763
2554
  exports.useEmailVerification = useEmailVerification;
1764
2555
  exports.useMagicLink = useMagicLink;
1765
2556
  exports.usePasswordReset = usePasswordReset;
2557
+ exports.useProfile = useProfile;
1766
2558
  exports.useSession = useSession;
1767
2559
  exports.useSignIn = useSignIn;
1768
2560
  exports.useSignOut = useSignOut;