anima-ds-nucleus 1.0.17 → 1.0.19

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.
@@ -1,15 +1,30 @@
1
1
  import { useState } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
+ import { Button } from '../../Atoms/Button/Button';
4
+ import { Typography } from '../../Atoms/Typography/Typography';
3
5
  import { Input } from '../../Inputs/Input/Input';
4
6
  import { Checkbox } from '../../Inputs/Checkbox/Checkbox';
5
- import { Button } from '../../Atoms/Button/Button';
7
+ import { PasswordInput } from '../../Inputs/PasswordInput/PasswordInput';
6
8
 
7
9
  export const LoginForm = ({
10
+ variant,
8
11
  onSubmit,
12
+ loading = false,
13
+ onForgotPassword,
14
+ onGoogleLogin,
15
+ onMicrosoftLogin,
16
+ showSocialLogin = true,
17
+ showDivider = true,
18
+ showPasswordRequirementsOnError = true,
19
+ labels,
20
+ generalError,
21
+ generalErrorTitle,
22
+ generalErrorSubtitle,
9
23
  className = '',
10
24
  ...props
11
25
  }) => {
12
26
  const { t } = useTranslation();
27
+ const isHexaLogin = variant === 'hexa-login';
13
28
  const [formData, setFormData] = useState({
14
29
  email: '',
15
30
  password: '',
@@ -45,52 +60,326 @@ export const LoginForm = ({
45
60
  }
46
61
  };
47
62
 
63
+ const resolvedLabels = {
64
+ emailLabel: labels?.emailLabel ?? t('form.email') ?? 'Email',
65
+ passwordLabel: labels?.passwordLabel ?? t('form.password') ?? 'Contraseña',
66
+ rememberMeLabel: labels?.rememberMeLabel ?? t('form.rememberMe') ?? 'Recordarme',
67
+ forgotPasswordLabel: labels?.forgotPasswordLabel ?? t('form.forgotPassword') ?? 'Olvidé mi contraseña',
68
+ continueWithLabel: labels?.continueWithLabel ?? 'Continuar con',
69
+ googleLabel: labels?.googleLabel ?? 'Google',
70
+ microsoftLabel: labels?.microsoftLabel ?? 'Microsoft',
71
+ };
72
+
73
+ const loginButtonText = loading ? (t('form.loggingIn') ?? 'Ingresando...') : (t('form.login') ?? 'Ingresar');
74
+
48
75
  return (
49
- <form
50
- onSubmit={handleSubmit}
51
- className={`max-w-md mx-auto bg-white p-6 rounded-lg shadow-md ${className}`}
52
- {...props}
53
- >
54
- <h2 className="text-2xl font-bold mb-6 text-center">{t('form.login')}</h2>
55
-
56
- <div className="space-y-4">
57
- <Input
58
- label={t('form.email')}
59
- type="email"
60
- placeholder={t('placeholder.email')}
61
- value={formData.email}
62
- onChange={(e) => handleChange('email', e.target.value)}
63
- error={errors.email}
64
- required
65
- />
66
-
67
- <Input
68
- label={t('form.password')}
69
- type="password"
70
- placeholder={t('placeholder.password')}
71
- value={formData.password}
72
- onChange={(e) => handleChange('password', e.target.value)}
73
- error={errors.password}
74
- required
75
- />
76
-
77
- <Checkbox
78
- label={t('form.rememberMe')}
79
- checked={formData.rememberMe}
80
- onChange={(e) => handleChange('rememberMe', e.target.checked)}
81
- />
82
-
83
- <Button type="submit" variant="primary" className="w-full">
84
- {t('form.login')}
85
- </Button>
86
-
87
- <div className="text-center">
88
- <a href="#" className="text-sm text-blue-600 hover:underline">
89
- {t('form.forgotPassword')}
76
+ isHexaLogin ? (
77
+ <div
78
+ style={{
79
+ width: '427px',
80
+ minHeight: '409px',
81
+ borderRadius: '14px',
82
+ border: '1px solid #0000001A',
83
+ padding: '24px',
84
+ background: '#FFFFFF',
85
+ boxShadow: '0px 4px 6px -4px #0000001A, 0px 10px 15px -3px #0000001A',
86
+ }}
87
+ >
88
+ <form onSubmit={handleSubmit} className={className} {...props}>
89
+ {/* 1) Email */}
90
+ <div className="w-full">
91
+ <label
92
+ className="block mb-2 font-medium text-sm"
93
+ style={{ color: '#2D5C63' }}
94
+ >
95
+ {resolvedLabels.emailLabel}
96
+ </label>
97
+ <input
98
+ type="email"
99
+ value={formData.email}
100
+ onChange={(e) => handleChange('email', e.target.value)}
101
+ placeholder="Ingresa tu correo electronico"
102
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm text-gray-900"
103
+ style={{ borderColor: errors.email ? '#ef4444' : '#2D5C63' }}
104
+ />
105
+ </div>
106
+
107
+ {/* 2) Password */}
108
+ <div className="w-full mt-4">
109
+ <PasswordInput
110
+ variant="hexa-login"
111
+ label={resolvedLabels.passwordLabel}
112
+ labelClassName="block mb-2 font-medium text-sm"
113
+ labelStyle={{ color: '#2D5C63' }}
114
+ placeholder={t('placeholder.password')}
115
+ value={formData.password}
116
+ onChange={(e) => handleChange('password', e.target.value)}
117
+ inputClassName="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm text-gray-900"
118
+ style={{
119
+ paddingRight: '2.75rem',
120
+ borderColor: errors.password ? '#ef4444' : '#2D5C63',
121
+ }}
122
+ />
123
+ </div>
124
+
125
+ {/* 3) Password requirements box (solo si hay error de password) */}
126
+ {showPasswordRequirementsOnError && !!errors.password && (
127
+ <div
128
+ className="rounded-lg p-4 border mt-4"
129
+ style={{
130
+ background: '#f5f3ff',
131
+ borderColor: '#a78bfa',
132
+ color: '#0c4a6e',
133
+ fontFamily: 'IBM Plex Mono',
134
+ }}
135
+ >
136
+ <ul className="list-disc list-inside text-sm space-y-1" style={{ color: '#0c4a6e' }}>
137
+ <li>Al menos 8 caracteres</li>
138
+ <li>Al menos una letra mayúscula</li>
139
+ <li>Al menos un número</li>
140
+ <li>Al menos un caracter especial</li>
141
+ </ul>
142
+ </div>
143
+ )}
144
+
145
+ {/* 4) Row remember/forgot */}
146
+ <div className="flex items-center justify-between mt-4">
147
+ <label className="flex items-center">
148
+ <input
149
+ type="checkbox"
150
+ checked={formData.rememberMe}
151
+ onChange={(e) => handleChange('rememberMe', e.target.checked)}
152
+ className="w-4 h-4 border-gray-300 rounded focus:outline-none focus:ring-0"
153
+ style={{
154
+ accentColor: '#2D5C63',
155
+ borderColor: formData.rememberMe ? '#2D5C63' : '#d1d5db',
156
+ }}
157
+ />
158
+ <span className="ml-2 text-sm font-medium" style={{ color: '#2D5C63' }}>
159
+ {resolvedLabels.rememberMeLabel}
160
+ </span>
161
+ </label>
162
+
163
+ <a
164
+ href="#"
165
+ className="text-body-md hover:underline font-medium"
166
+ style={{ color: '#2D5C63' }}
167
+ onClick={(e) => {
168
+ e.preventDefault();
169
+ if (onForgotPassword) onForgotPassword();
170
+ }}
171
+ >
172
+ {resolvedLabels.forgotPasswordLabel}
90
173
  </a>
91
174
  </div>
175
+
176
+ {/* 5) Error general box rojo (si existe) */}
177
+ {(generalError || errors.general) && (
178
+ <div
179
+ className="mt-4"
180
+ style={{
181
+ width: '377px',
182
+ height: '68px',
183
+ paddingTop: '12px',
184
+ paddingRight: '16px',
185
+ paddingBottom: '12px',
186
+ paddingLeft: '16px',
187
+ gap: '4px',
188
+ borderRadius: '8px',
189
+ borderWidth: '1px',
190
+ border: '1px solid #B30808',
191
+ backgroundColor: '#F8DBDB',
192
+ display: 'flex',
193
+ flexDirection: 'column',
194
+ }}
195
+ >
196
+ <Typography
197
+ variant="body2"
198
+ style={{
199
+ fontFamily: "'IBM Plex Mono', monospace",
200
+ fontWeight: 400,
201
+ fontStyle: 'normal',
202
+ fontSize: '14px',
203
+ lineHeight: '21px',
204
+ letterSpacing: '0.02em',
205
+ color: '#B30808',
206
+ margin: 0,
207
+ }}
208
+ >
209
+ {generalErrorTitle ??
210
+ (typeof generalError === 'string' ? generalError : null) ??
211
+ (errors.general && typeof errors.general === 'string' ? errors.general : null) ??
212
+ (t('errors.invalidCredentials') ?? 'Correo o contraseña incorrectos.')}
213
+ </Typography>
214
+ <Typography
215
+ variant="body2"
216
+ style={{
217
+ fontFamily: "'IBM Plex Mono', monospace",
218
+ fontWeight: 400,
219
+ fontStyle: 'normal',
220
+ fontSize: '14px',
221
+ lineHeight: '21px',
222
+ letterSpacing: '0.02em',
223
+ color: '#B30808',
224
+ margin: 0,
225
+ }}
226
+ >
227
+ {generalErrorSubtitle ??
228
+ (t('errors.tryAgain') ?? 'Intentá nuevamente.')}
229
+ </Typography>
230
+ </div>
231
+ )}
232
+
233
+ {/* 6) Botón login */}
234
+ <div className="mt-4">
235
+ <Button
236
+ type="submit"
237
+ tipo="Primary"
238
+ color="Teal"
239
+ tamaño="Default"
240
+ className="w-full"
241
+ disabled={loading}
242
+ >
243
+ <span
244
+ style={{
245
+ fontFamily: "'IBM Plex Sans', sans-serif",
246
+ fontWeight: 400,
247
+ fontStyle: 'normal',
248
+ fontSize: '16px',
249
+ lineHeight: '24px',
250
+ letterSpacing: '0%',
251
+ }}
252
+ >
253
+ {loginButtonText}
254
+ </span>
255
+ </Button>
256
+ </div>
257
+
258
+ {/* 7) Divider */}
259
+ {showDivider && (
260
+ <div className="flex items-center gap-3 my-6">
261
+ <div className="flex-1" style={{ borderTop: '1px solid #2D5C63' }} />
262
+ <Typography
263
+ variant="body2"
264
+ className="text-body-md font-medium"
265
+ style={{ color: '#2D5C63', whiteSpace: 'nowrap' }}
266
+ >
267
+ {resolvedLabels.continueWithLabel}
268
+ </Typography>
269
+ <div className="flex-1" style={{ borderTop: '1px solid #2D5C63' }} />
270
+ </div>
271
+ )}
272
+
273
+ {/* 8) Social buttons */}
274
+ {showSocialLogin && (
275
+ <div
276
+ style={{
277
+ width: '377px',
278
+ height: '36px',
279
+ gap: '20px',
280
+ marginLeft: 'auto',
281
+ marginRight: 'auto',
282
+ display: 'flex',
283
+ }}
284
+ >
285
+ <button
286
+ type="button"
287
+ onClick={onGoogleLogin}
288
+ className="flex-1 flex items-center justify-center bg-white hover:bg-gray-50 transition-colors"
289
+ style={{
290
+ width: '178.5px',
291
+ height: '36px',
292
+ padding: '8px 43px',
293
+ gap: '16px',
294
+ borderRadius: '8px',
295
+ border: '1px solid #38656D',
296
+ }}
297
+ >
298
+ <svg width="18" height="18" viewBox="0 0 48 48" aria-hidden="true">
299
+ <path fill="#FFC107" d="M43.611 20.083H42V20H24v8h11.303C33.651 32.659 29.227 36 24 36c-6.627 0-12-5.373-12-12s5.373-12 12-12c3.059 0 5.842 1.154 7.961 3.039l5.657-5.657C34.047 6.053 29.272 4 24 4 12.955 4 4 12.955 4 24s8.955 20 20 20 20-8.955 20-20c0-1.341-.138-2.65-.389-3.917z" />
300
+ <path fill="#FF3D00" d="M6.306 14.691l6.571 4.819C14.655 16.108 19.002 12 24 12c3.059 0 5.842 1.154 7.961 3.039l5.657-5.657C34.047 6.053 29.272 4 24 4 16.318 4 9.656 8.337 6.306 14.691z" />
301
+ <path fill="#4CAF50" d="M24 44c5.166 0 9.86-1.977 13.409-5.197l-6.19-5.238C29.211 35.091 26.715 36 24 36c-5.205 0-9.616-3.318-11.281-7.946l-6.522 5.025C9.505 39.556 16.227 44 24 44z" />
302
+ <path fill="#1976D2" d="M43.611 20.083H42V20H24v8h11.303c-.793 2.116-2.318 3.91-4.284 5.238l.003-.002 6.19 5.238C36.971 39.205 44 34 44 24c0-1.341-.138-2.65-.389-3.917z" />
303
+ </svg>
304
+ <Typography variant="body2" className="text-gray-900 font-medium">
305
+ {resolvedLabels.googleLabel}
306
+ </Typography>
307
+ </button>
308
+
309
+ <button
310
+ type="button"
311
+ onClick={onMicrosoftLogin}
312
+ className="flex-1 flex items-center justify-center bg-white hover:bg-gray-50 transition-colors"
313
+ style={{
314
+ width: '178.5px',
315
+ height: '36px',
316
+ padding: '8px 43px',
317
+ gap: '16px',
318
+ borderRadius: '8px',
319
+ border: '1px solid #38656D',
320
+ }}
321
+ >
322
+ <svg width="18" height="18" viewBox="0 0 48 48" aria-hidden="true">
323
+ <path fill="#F25022" d="M6 6h17v17H6z" />
324
+ <path fill="#7FBA00" d="M25 6h17v17H25z" />
325
+ <path fill="#00A4EF" d="M6 25h17v17H6z" />
326
+ <path fill="#FFB900" d="M25 25h17v17H25z" />
327
+ </svg>
328
+ <Typography variant="body2" className="text-gray-900 font-medium">
329
+ {resolvedLabels.microsoftLabel}
330
+ </Typography>
331
+ </button>
332
+ </div>
333
+ )}
334
+ </form>
92
335
  </div>
93
- </form>
336
+ ) : (
337
+ <form
338
+ onSubmit={handleSubmit}
339
+ className={`max-w-md mx-auto bg-white p-6 rounded-lg shadow-md ${className}`}
340
+ {...props}
341
+ >
342
+ <h2 className="text-2xl font-bold mb-6 text-center">{t('form.login')}</h2>
343
+
344
+ <div className="space-y-4">
345
+ <Input
346
+ label={t('form.email')}
347
+ type="email"
348
+ placeholder={t('placeholder.email')}
349
+ value={formData.email}
350
+ onChange={(e) => handleChange('email', e.target.value)}
351
+ error={errors.email}
352
+ required
353
+ />
354
+
355
+ <Input
356
+ label={t('form.password')}
357
+ type="password"
358
+ placeholder={t('placeholder.password')}
359
+ value={formData.password}
360
+ onChange={(e) => handleChange('password', e.target.value)}
361
+ error={errors.password}
362
+ required
363
+ />
364
+
365
+ <Checkbox
366
+ label={t('form.rememberMe')}
367
+ checked={formData.rememberMe}
368
+ onChange={(e) => handleChange('rememberMe', e.target.checked)}
369
+ />
370
+
371
+ <Button type="submit" variant="primary" className="w-full">
372
+ {t('form.login')}
373
+ </Button>
374
+
375
+ <div className="text-center">
376
+ <a href="#" className="text-sm text-blue-600 hover:underline">
377
+ {t('form.forgotPassword')}
378
+ </a>
379
+ </div>
380
+ </div>
381
+ </form>
382
+ )
94
383
  );
95
384
  };
96
385
 
@@ -7,13 +7,59 @@ export default {
7
7
  tags: ['autodocs'],
8
8
  decorators: [
9
9
  (Story) => (
10
- <I18nProvider>
11
- <Story />
10
+ <I18nProvider language="es-AR">
11
+ <div style={{ padding: '2rem', maxWidth: '500px', margin: '0 auto' }}>
12
+ <Story />
13
+ </div>
12
14
  </I18nProvider>
13
15
  ),
14
16
  ],
17
+ argTypes: {
18
+ variant: {
19
+ control: 'select',
20
+ options: ['hexa-login', undefined],
21
+ description: 'Variante del formulario de login',
22
+ },
23
+ loading: {
24
+ control: 'boolean',
25
+ description: 'Estado de carga del formulario',
26
+ },
27
+ showSocialLogin: {
28
+ control: 'boolean',
29
+ description: 'Mostrar botones de login social',
30
+ },
31
+ showDivider: {
32
+ control: 'boolean',
33
+ description: 'Mostrar divisor antes de los botones sociales',
34
+ },
35
+ generalError: {
36
+ control: 'text',
37
+ description: 'Mensaje de error general',
38
+ },
39
+ },
40
+ };
41
+
42
+ // Variante Hexa Login (principal)
43
+ export const HexaLogin = {
44
+ args: {
45
+ variant: 'hexa-login',
46
+ onSubmit: (data) => {
47
+ console.log('Login data:', data);
48
+ alert('Login submitted!');
49
+ },
50
+ onForgotPassword: () => {
51
+ alert('Forgot password clicked');
52
+ },
53
+ onGoogleLogin: () => {
54
+ alert('Google login clicked');
55
+ },
56
+ onMicrosoftLogin: () => {
57
+ alert('Microsoft login clicked');
58
+ },
59
+ },
15
60
  };
16
61
 
62
+ // Variante por defecto
17
63
  export const Default = {
18
64
  args: {
19
65
  onSubmit: (data) => {
@@ -23,33 +69,165 @@ export const Default = {
23
69
  },
24
70
  };
25
71
 
72
+ // Con estado de carga
73
+ export const Loading = {
74
+ args: {
75
+ variant: 'hexa-login',
76
+ loading: true,
77
+ onSubmit: (data) => {
78
+ console.log('Login data:', data);
79
+ },
80
+ onGoogleLogin: () => {
81
+ alert('Google login clicked');
82
+ },
83
+ onMicrosoftLogin: () => {
84
+ alert('Microsoft login clicked');
85
+ },
86
+ },
87
+ };
88
+
89
+ // Con error general (string)
90
+ export const WithError = {
91
+ args: {
92
+ variant: 'hexa-login',
93
+ generalError: 'Credenciales incorrectas',
94
+ onSubmit: (data) => {
95
+ console.log('Login data:', data);
96
+ },
97
+ onGoogleLogin: () => {
98
+ alert('Google login clicked');
99
+ },
100
+ onMicrosoftLogin: () => {
101
+ alert('Microsoft login clicked');
102
+ },
103
+ },
104
+ };
105
+
106
+ // Con error general (boolean - muestra textos i18n)
107
+ export const WithErrorBoolean = {
108
+ args: {
109
+ variant: 'hexa-login',
110
+ generalError: true,
111
+ onSubmit: (data) => {
112
+ console.log('Login data:', data);
113
+ },
114
+ onGoogleLogin: () => {
115
+ alert('Google login clicked');
116
+ },
117
+ onMicrosoftLogin: () => {
118
+ alert('Microsoft login clicked');
119
+ },
120
+ },
121
+ };
122
+
123
+ // Con error general personalizado
124
+ export const WithCustomError = {
125
+ args: {
126
+ variant: 'hexa-login',
127
+ generalError: true,
128
+ generalErrorTitle: 'Error de autenticación',
129
+ generalErrorSubtitle: 'Verifica tus credenciales e intenta nuevamente.',
130
+ onSubmit: (data) => {
131
+ console.log('Login data:', data);
132
+ },
133
+ onGoogleLogin: () => {
134
+ alert('Google login clicked');
135
+ },
136
+ onMicrosoftLogin: () => {
137
+ alert('Microsoft login clicked');
138
+ },
139
+ },
140
+ };
141
+
142
+ // Sin login social
143
+ export const WithoutSocialLogin = {
144
+ args: {
145
+ variant: 'hexa-login',
146
+ showSocialLogin: false,
147
+ showDivider: false,
148
+ onSubmit: (data) => {
149
+ console.log('Login data:', data);
150
+ alert('Login submitted!');
151
+ },
152
+ onForgotPassword: () => {
153
+ alert('Forgot password clicked');
154
+ },
155
+ },
156
+ };
157
+
158
+ // Con labels personalizados
159
+ export const CustomLabels = {
160
+ args: {
161
+ variant: 'hexa-login',
162
+ labels: {
163
+ emailLabel: 'Correo electrónico',
164
+ passwordLabel: 'Contraseña',
165
+ rememberMeLabel: 'Recordar sesión',
166
+ forgotPasswordLabel: '¿Olvidaste tu contraseña?',
167
+ continueWithLabel: 'O continúa con',
168
+ googleLabel: 'Google',
169
+ microsoftLabel: 'Microsoft',
170
+ },
171
+ onSubmit: (data) => {
172
+ console.log('Login data:', data);
173
+ alert('Login submitted!');
174
+ },
175
+ onGoogleLogin: () => {
176
+ alert('Google login clicked');
177
+ },
178
+ onMicrosoftLogin: () => {
179
+ alert('Microsoft login clicked');
180
+ },
181
+ },
182
+ };
183
+
184
+ // Versión en español
26
185
  export const Spanish = {
27
186
  decorators: [
28
187
  (Story) => (
29
188
  <I18nProvider language="es-AR">
30
- <Story />
189
+ <div style={{ padding: '2rem', maxWidth: '500px', margin: '0 auto' }}>
190
+ <Story />
191
+ </div>
31
192
  </I18nProvider>
32
193
  ),
33
194
  ],
34
195
  args: {
196
+ variant: 'hexa-login',
35
197
  onSubmit: (data) => {
36
198
  console.log('Login data:', data);
37
199
  },
200
+ onGoogleLogin: () => {
201
+ alert('Google login clicked');
202
+ },
203
+ onMicrosoftLogin: () => {
204
+ alert('Microsoft login clicked');
205
+ },
38
206
  },
39
207
  };
40
208
 
209
+ // Versión en portugués
41
210
  export const Portuguese = {
42
211
  decorators: [
43
212
  (Story) => (
44
213
  <I18nProvider language="pt-BR">
45
- <Story />
214
+ <div style={{ padding: '2rem', maxWidth: '500px', margin: '0 auto' }}>
215
+ <Story />
216
+ </div>
46
217
  </I18nProvider>
47
218
  ),
48
219
  ],
49
220
  args: {
221
+ variant: 'hexa-login',
50
222
  onSubmit: (data) => {
51
223
  console.log('Login data:', data);
52
224
  },
225
+ onGoogleLogin: () => {
226
+ alert('Google login clicked');
227
+ },
228
+ onMicrosoftLogin: () => {
229
+ alert('Microsoft login clicked');
230
+ },
53
231
  },
54
232
  };
55
233
 
@@ -95,6 +95,12 @@ const resources = {
95
95
  'alert.error': 'Error',
96
96
  'alert.warning': 'Advertencia',
97
97
  'alert.info': 'Información',
98
+
99
+ // Errors
100
+ 'errors.invalidCredentials': 'Correo o contraseña incorrectos.',
101
+ 'errors.tryAgain': 'Intentá nuevamente.',
102
+ 'form.tryAgain': 'Por favor, intentá nuevamente.',
103
+ 'form.loggingIn': 'Ingresando...',
98
104
  },
99
105
  },
100
106
  'pt-BR': {
@@ -190,6 +196,12 @@ const resources = {
190
196
  'alert.error': 'Erro',
191
197
  'alert.warning': 'Aviso',
192
198
  'alert.info': 'Informação',
199
+
200
+ // Errors
201
+ 'errors.invalidCredentials': 'E-mail ou senha incorretos.',
202
+ 'errors.tryAgain': 'Tente novamente.',
203
+ 'form.tryAgain': 'Por favor, tente novamente.',
204
+ 'form.loggingIn': 'Entrando...',
193
205
  },
194
206
  },
195
207
  };
package/src/index.js CHANGED
@@ -71,6 +71,7 @@ export { TagList } from './components/DataDisplay/TagList/TagList';
71
71
  // Views
72
72
  export { LoginForm } from './components/Views/LoginForm/LoginForm';
73
73
  export { ChangePasswordForm } from './components/Views/ChangePasswordForm/ChangePasswordForm';
74
+ export { ForgotPassword } from './components/Views/ForgotPassword/ForgotPassword';
74
75
  export { Chat } from './components/Views/Chat/Chat';
75
76
 
76
77
  // Providers