anima-ds-nucleus 1.0.21 → 1.0.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anima-ds-nucleus",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "Anima Design System - A comprehensive React component library",
5
5
  "author": "Nucleus Labs <ipvasallo@nucleus.com.ar>",
6
6
  "license": "UNLICENSED",
@@ -30,7 +30,7 @@ export const PasswordInput = ({
30
30
  `.trim().replace(/\s+/g, ' ');
31
31
 
32
32
  return (
33
- <div className={`w-full ${className}`}>
33
+ <div className={`anima-passwordfield w-full ${className}`}>
34
34
  {label && (
35
35
  <label
36
36
  className={labelClassName || 'block text-sm font-medium text-gray-700 mb-1'}
@@ -48,7 +48,7 @@ export const PasswordInput = ({
48
48
  disabled={disabled}
49
49
  value={value}
50
50
  onChange={onChange}
51
- className={resolvedInputClasses}
51
+ className={`${resolvedInputClasses} ${isHexaLogin ? 'anima-passwordfield__input' : ''}`}
52
52
  {...props}
53
53
  />
54
54
 
@@ -56,13 +56,7 @@ export const PasswordInput = ({
56
56
  type="button"
57
57
  tabIndex={-1}
58
58
  onClick={() => setShowPassword((prev) => !prev)}
59
- className="absolute"
60
- style={{
61
- top: '50%',
62
- transform: 'translateY(-50%)',
63
- right: '0.75rem',
64
- color: '#6b7280',
65
- }}
59
+ className="anima-passwordfield__toggle"
66
60
  aria-label={showPassword ? 'Ocultar contraseña' : 'Mostrar contraseña'}
67
61
  >
68
62
  <Icon
@@ -11,10 +11,12 @@ export const ForgotPassword = ({
11
11
  error: externalError,
12
12
  className = '',
13
13
  variant = 'default',
14
+ layout = 'embedded',
14
15
  ...props
15
16
  }) => {
16
17
  const { t } = useTranslation();
17
18
  const isHexaLogin = variant === 'hexa-login';
19
+ const isPageLayout = layout === 'page';
18
20
 
19
21
  // Estados internos (si no se pasan como props)
20
22
  const [email, setEmail] = useState('');
@@ -124,11 +126,11 @@ export const ForgotPassword = ({
124
126
 
125
127
  return (
126
128
  <div
127
- className={`min-h-screen flex flex-col ${className}`}
128
- style={{ backgroundColor: '#f5f5f5' }}
129
+ className={`${isPageLayout ? 'min-h-screen flex flex-col' : ''} ${className}`}
130
+ style={isPageLayout ? { backgroundColor: '#f5f5f5' } : undefined}
129
131
  {...props}
130
132
  >
131
- <div className="flex-1 flex items-center justify-center p-4">
133
+ <div className={isPageLayout ? 'flex-1 flex items-center justify-center p-4' : 'p-4'}>
132
134
  <div className="w-full max-w-md">
133
135
  {/* Título y subtítulo */}
134
136
  <div className="mb-8 text-center">
@@ -16,6 +16,9 @@ export const LoginForm = ({
16
16
  showSocialLogin = true,
17
17
  showDivider = true,
18
18
  showPasswordRequirementsOnError = true,
19
+ passwordRequirementsItems,
20
+ passwordRequirementsTitle,
21
+ passwordRequirementsPrefix,
19
22
  labels,
20
23
  generalError,
21
24
  generalErrorTitle,
@@ -74,18 +77,9 @@ export const LoginForm = ({
74
77
 
75
78
  return (
76
79
  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}>
80
+ <div className={`anima-loginform__container ${className}`} {...props}>
81
+ <div className="anima-loginform__card">
82
+ <form onSubmit={handleSubmit}>
89
83
  {/* 1) Email */}
90
84
  <div className="w-full">
91
85
  <label
@@ -114,9 +108,8 @@ export const LoginForm = ({
114
108
  placeholder={t('placeholder.password')}
115
109
  value={formData.password}
116
110
  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"
111
+ 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 anima-passwordfield__input"
118
112
  style={{
119
- paddingRight: '2.75rem',
120
113
  borderColor: errors.password ? '#ef4444' : '#2D5C63',
121
114
  }}
122
115
  />
@@ -125,20 +118,36 @@ export const LoginForm = ({
125
118
  {/* 3) Password requirements box (solo si hay error de password) */}
126
119
  {showPasswordRequirementsOnError && !!errors.password && (
127
120
  <div
128
- className="rounded-lg p-4 border mt-4"
121
+ className="anima-loginform__requirementsBox rounded-lg p-4 border mt-4"
129
122
  style={{
130
123
  background: '#f5f3ff',
131
124
  borderColor: '#a78bfa',
132
125
  color: '#0c4a6e',
133
- fontFamily: 'IBM Plex Mono',
126
+ fontFamily: "'IBM Plex Mono', monospace",
134
127
  }}
135
128
  >
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>
129
+ <Typography
130
+ variant="body2"
131
+ className="text-sm"
132
+ style={{
133
+ color: '#0c4a6e',
134
+ fontFamily: "'IBM Plex Mono', monospace",
135
+ whiteSpace: 'pre-line',
136
+ }}
137
+ >
138
+ {passwordRequirementsTitle || (() => {
139
+ const prefix = passwordRequirementsPrefix || t('form.passwordRequirementsPrefix') || 'Recuerda que la contraseña debe tener:';
140
+ const defaultItems = passwordRequirementsItems || [
141
+ t('form.passwordRequirementMinChars') || 'Un mínimo de 6 caracteres',
142
+ t('form.passwordRequirementOther') || 'Una mayúscula, un número, un carácter especial',
143
+ ];
144
+
145
+ if (passwordRequirementsItems && passwordRequirementsItems.length > 0) {
146
+ return `${prefix}\n${passwordRequirementsItems[0]}\n\n${passwordRequirementsItems.slice(1).join(', ')}`;
147
+ }
148
+ return `${prefix}\n${defaultItems[0]}\n\n${defaultItems[1]}`;
149
+ })()}
150
+ </Typography>
142
151
  </div>
143
152
  )}
144
153
 
@@ -176,10 +185,8 @@ export const LoginForm = ({
176
185
  {/* 5) Error general box rojo (si existe) */}
177
186
  {(generalError || errors.general) && (
178
187
  <div
179
- className="mt-4"
188
+ className="anima-loginform__errorBox mt-4"
180
189
  style={{
181
- width: '377px',
182
- height: '68px',
183
190
  paddingTop: '12px',
184
191
  paddingRight: '16px',
185
192
  paddingBottom: '12px',
@@ -272,28 +279,11 @@ export const LoginForm = ({
272
279
 
273
280
  {/* 8) Social buttons */}
274
281
  {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
- >
282
+ <div className="anima-loginform__socialRow">
285
283
  <button
286
284
  type="button"
287
285
  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
- }}
286
+ className="anima-loginform__socialButton anima-loginform__socialButton--google"
297
287
  >
298
288
  <svg width="18" height="18" viewBox="0 0 48 48" aria-hidden="true">
299
289
  <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" />
@@ -309,15 +299,7 @@ export const LoginForm = ({
309
299
  <button
310
300
  type="button"
311
301
  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
- }}
302
+ className="anima-loginform__socialButton anima-loginform__socialButton--microsoft"
321
303
  >
322
304
  <svg width="18" height="18" viewBox="0 0 48 48" aria-hidden="true">
323
305
  <path fill="#F25022" d="M6 6h17v17H6z" />
@@ -332,6 +314,7 @@ export const LoginForm = ({
332
314
  </div>
333
315
  )}
334
316
  </form>
317
+ </div>
335
318
  </div>
336
319
  ) : (
337
320
  <form
@@ -36,6 +36,14 @@ export default {
36
36
  control: 'text',
37
37
  description: 'Mensaje de error general',
38
38
  },
39
+ passwordRequirementsItems: {
40
+ control: 'object',
41
+ description: 'Array de strings con los requisitos de contraseña',
42
+ },
43
+ passwordRequirementsTitle: {
44
+ control: 'text',
45
+ description: 'Título opcional para la caja de requisitos de contraseña',
46
+ },
39
47
  },
40
48
  };
41
49
 
@@ -231,3 +239,31 @@ export const Portuguese = {
231
239
  },
232
240
  };
233
241
 
242
+ // Con requisitos de contraseña personalizados
243
+ export const CustomPasswordRequirements = {
244
+ args: {
245
+ variant: 'hexa-login',
246
+ passwordRequirementsTitle: 'Requisitos de contraseña',
247
+ passwordRequirementsItems: [
248
+ 'Mínimo 12 caracteres',
249
+ 'Debe contener mayúsculas y minúsculas',
250
+ 'Debe incluir números',
251
+ 'Debe incluir símbolos especiales',
252
+ 'No puede ser una contraseña común',
253
+ ],
254
+ onSubmit: (data) => {
255
+ console.log('Login data:', data);
256
+ alert('Login submitted!');
257
+ },
258
+ onForgotPassword: () => {
259
+ alert('Forgot password clicked');
260
+ },
261
+ onGoogleLogin: () => {
262
+ alert('Google login clicked');
263
+ },
264
+ onMicrosoftLogin: () => {
265
+ alert('Microsoft login clicked');
266
+ },
267
+ },
268
+ };
269
+
@@ -0,0 +1,389 @@
1
+ import { useTranslation } from 'react-i18next';
2
+ import { PasswordInput } from '../../Inputs/PasswordInput/PasswordInput';
3
+ import { Button } from '../../Atoms/Button/Button';
4
+ import { Typography } from '../../Atoms/Typography/Typography';
5
+
6
+ export const NewPassword = ({
7
+ variant = 'default',
8
+ layout = 'embedded',
9
+ // Título y subtítulo
10
+ title,
11
+ subtitle,
12
+ // Password field
13
+ passwordLabel,
14
+ passwordPlaceholder,
15
+ passwordValue,
16
+ onPasswordChange,
17
+ passwordError,
18
+ // Confirm field
19
+ confirmPasswordLabel,
20
+ confirmPasswordPlaceholder,
21
+ confirmPasswordValue,
22
+ onConfirmPasswordChange,
23
+ confirmPasswordError,
24
+ // Requirements box
25
+ requirementsTitle,
26
+ requirementsItems = [],
27
+ requirementsPrefix,
28
+ showRequirements = true,
29
+ // General error
30
+ generalError,
31
+ // Actions
32
+ cancelLabel,
33
+ submitLabel,
34
+ onCancel,
35
+ onSubmit,
36
+ disabled = false,
37
+ submitting = false,
38
+ // Success
39
+ success = false,
40
+ successTitle,
41
+ successMessage,
42
+ successExtra,
43
+ className = '',
44
+ ...props
45
+ }) => {
46
+ const { t } = useTranslation();
47
+ const isHexaLogin = variant === 'hexa-login';
48
+ const isPageLayout = layout === 'page';
49
+
50
+ const handleSubmit = (e) => {
51
+ e.preventDefault();
52
+ if (onSubmit && !disabled && !submitting) {
53
+ onSubmit({
54
+ password: passwordValue,
55
+ confirmPassword: confirmPasswordValue,
56
+ });
57
+ }
58
+ };
59
+
60
+ // Si está en modo success, mostrar solo el mensaje de éxito
61
+ if (success) {
62
+ return (
63
+ <div
64
+ className={`${isPageLayout ? 'min-h-screen flex flex-col' : ''} ${className}`}
65
+ style={isPageLayout ? { backgroundColor: '#f5f5f5' } : undefined}
66
+ {...props}
67
+ >
68
+ <div className={isPageLayout ? 'flex-1 flex items-center justify-center p-4' : 'p-4'}>
69
+ <div className="w-full max-w-md">
70
+ {/* Título y subtítulo */}
71
+ {(title || subtitle) && (
72
+ <div className="mb-8 text-center">
73
+ {title && (
74
+ <Typography
75
+ variant="h3"
76
+ className="mb-2 font-semibold"
77
+ style={
78
+ isHexaLogin
79
+ ? {
80
+ color: '#2D5C63',
81
+ fontFamily: 'inherit',
82
+ fontWeight: 400,
83
+ fontStyle: 'normal',
84
+ fontSize: '32px',
85
+ lineHeight: '48px',
86
+ letterSpacing: '0px',
87
+ textAlign: 'center',
88
+ }
89
+ : undefined
90
+ }
91
+ >
92
+ {title}
93
+ </Typography>
94
+ )}
95
+ {subtitle && (
96
+ <Typography
97
+ variant="body2"
98
+ className="text-gray-600"
99
+ style={
100
+ isHexaLogin
101
+ ? {
102
+ fontFamily: 'inherit',
103
+ fontWeight: 400,
104
+ fontStyle: 'normal',
105
+ fontSize: '16px',
106
+ lineHeight: '24px',
107
+ letterSpacing: '0px',
108
+ textAlign: 'center',
109
+ }
110
+ : undefined
111
+ }
112
+ >
113
+ {subtitle}
114
+ </Typography>
115
+ )}
116
+ </div>
117
+ )}
118
+
119
+ {/* Card blanca */}
120
+ <div className="bg-white border border-gray-200 rounded-lg p-6 shadow-md">
121
+ {/* Success box */}
122
+ <div
123
+ className="rounded-lg p-4 border"
124
+ style={{
125
+ backgroundColor: '#d1fae5',
126
+ borderColor: '#10b981',
127
+ }}
128
+ >
129
+ {successTitle && (
130
+ <Typography
131
+ variant="body2"
132
+ className="font-medium"
133
+ style={{ color: '#065f46' }}
134
+ >
135
+ {successTitle}
136
+ </Typography>
137
+ )}
138
+ {successMessage && (
139
+ <Typography
140
+ variant="body2"
141
+ className={successTitle ? 'mt-2' : ''}
142
+ style={{ color: '#047857', fontSize: '14px' }}
143
+ >
144
+ {successMessage}
145
+ </Typography>
146
+ )}
147
+ {successExtra && <div className="mt-4">{successExtra}</div>}
148
+ </div>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ </div>
153
+ );
154
+ }
155
+
156
+ return (
157
+ <div
158
+ className={`${isPageLayout ? 'min-h-screen flex flex-col' : ''} ${className}`}
159
+ style={isPageLayout ? { backgroundColor: '#f5f5f5' } : undefined}
160
+ {...props}
161
+ >
162
+ <div className={isPageLayout ? 'flex-1 flex items-center justify-center p-4' : 'p-4'}>
163
+ <div className="w-full max-w-md">
164
+ {/* Título y subtítulo */}
165
+ {(title || subtitle) && (
166
+ <div className="mb-8 text-center">
167
+ {title && (
168
+ <Typography
169
+ variant="h3"
170
+ className="mb-2 font-semibold"
171
+ style={
172
+ isHexaLogin
173
+ ? {
174
+ color: '#2D5C63',
175
+ fontFamily: 'inherit',
176
+ fontWeight: 400,
177
+ fontStyle: 'normal',
178
+ fontSize: '32px',
179
+ lineHeight: '48px',
180
+ letterSpacing: '0px',
181
+ textAlign: 'center',
182
+ }
183
+ : undefined
184
+ }
185
+ >
186
+ {title}
187
+ </Typography>
188
+ )}
189
+ {subtitle && (
190
+ <Typography
191
+ variant="body2"
192
+ className="text-gray-600"
193
+ style={
194
+ isHexaLogin
195
+ ? {
196
+ fontFamily: 'inherit',
197
+ fontWeight: 400,
198
+ fontStyle: 'normal',
199
+ fontSize: '16px',
200
+ lineHeight: '24px',
201
+ letterSpacing: '0px',
202
+ textAlign: 'center',
203
+ }
204
+ : undefined
205
+ }
206
+ >
207
+ {subtitle}
208
+ </Typography>
209
+ )}
210
+ </div>
211
+ )}
212
+
213
+ {/* Card blanca */}
214
+ <div className="bg-white border border-gray-200 rounded-lg p-6 shadow-md">
215
+ <form onSubmit={handleSubmit} className="space-y-4">
216
+ {/* Password field */}
217
+ <div>
218
+ <PasswordInput
219
+ variant={isHexaLogin ? 'hexa-login' : undefined}
220
+ label={passwordLabel}
221
+ labelClassName={isHexaLogin ? 'block mb-2 font-medium text-sm' : undefined}
222
+ labelStyle={isHexaLogin ? { color: '#2D5C63' } : undefined}
223
+ placeholder={passwordPlaceholder}
224
+ value={passwordValue || ''}
225
+ onChange={onPasswordChange}
226
+ error={passwordError}
227
+ inputClassName={
228
+ isHexaLogin
229
+ ? '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 anima-passwordfield__input'
230
+ : undefined
231
+ }
232
+ style={
233
+ isHexaLogin
234
+ ? {
235
+ borderColor: passwordError ? '#ef4444' : '#2D5C63',
236
+ borderWidth: '1px',
237
+ borderStyle: 'solid',
238
+ }
239
+ : undefined
240
+ }
241
+ />
242
+ </div>
243
+
244
+ {/* Confirm password field */}
245
+ <div>
246
+ <PasswordInput
247
+ variant={isHexaLogin ? 'hexa-login' : undefined}
248
+ label={confirmPasswordLabel}
249
+ labelClassName={isHexaLogin ? 'block mb-2 font-medium text-sm' : undefined}
250
+ labelStyle={isHexaLogin ? { color: '#2D5C63' } : undefined}
251
+ placeholder={confirmPasswordPlaceholder}
252
+ value={confirmPasswordValue || ''}
253
+ onChange={onConfirmPasswordChange}
254
+ error={confirmPasswordError}
255
+ inputClassName={
256
+ isHexaLogin
257
+ ? '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 anima-passwordfield__input'
258
+ : undefined
259
+ }
260
+ style={
261
+ isHexaLogin
262
+ ? {
263
+ borderColor: confirmPasswordError ? '#ef4444' : '#2D5C63',
264
+ borderWidth: '1px',
265
+ borderStyle: 'solid',
266
+ }
267
+ : undefined
268
+ }
269
+ />
270
+ </div>
271
+
272
+ {/* Requirements box */}
273
+ {showRequirements && requirementsItems.length > 0 && (
274
+ <div
275
+ className="rounded-lg p-4 border"
276
+ style={{
277
+ background: '#f5f3ff',
278
+ borderColor: '#a78bfa',
279
+ color: '#0c4a6e',
280
+ fontFamily: "'IBM Plex Mono', monospace",
281
+ }}
282
+ >
283
+ <Typography
284
+ variant="body2"
285
+ className="text-sm"
286
+ style={{
287
+ color: '#0c4a6e',
288
+ fontFamily: "'IBM Plex Mono', monospace",
289
+ whiteSpace: 'pre-line',
290
+ }}
291
+ >
292
+ {requirementsTitle || (() => {
293
+ const prefix = requirementsPrefix || t('form.passwordRequirementsPrefix') || 'Recuerda que la contraseña debe tener:';
294
+ const defaultItems = requirementsItems.length > 0 ? requirementsItems : [
295
+ t('form.passwordRequirementMinChars') || 'Un mínimo de 6 caracteres',
296
+ t('form.passwordRequirementOther') || 'Una mayúscula, un número, un carácter especial',
297
+ ];
298
+
299
+ return `${prefix}\n${defaultItems[0]}\n\n${defaultItems.slice(1).join(', ')}`;
300
+ })()}
301
+ </Typography>
302
+ </div>
303
+ )}
304
+
305
+ {/* General error */}
306
+ {generalError && (
307
+ <div
308
+ className="rounded-lg p-4 border"
309
+ style={{
310
+ backgroundColor: '#fecaca',
311
+ borderColor: '#ef4444',
312
+ }}
313
+ >
314
+ <Typography
315
+ variant="body2"
316
+ className="font-bold"
317
+ style={{ color: '#b91c1c' }}
318
+ >
319
+ {generalError}
320
+ </Typography>
321
+ </div>
322
+ )}
323
+
324
+ {/* Botonera 2 columnas */}
325
+ <div className="flex gap-4 pt-4">
326
+ {onCancel && (
327
+ <Button
328
+ type="button"
329
+ tipo="Secondary"
330
+ color="Teal"
331
+ tamaño="Default"
332
+ className="flex-1"
333
+ onClick={onCancel}
334
+ disabled={disabled || submitting}
335
+ >
336
+ <span
337
+ style={
338
+ isHexaLogin
339
+ ? {
340
+ fontFamily: "'IBM Plex Sans', sans-serif",
341
+ fontWeight: 400,
342
+ fontStyle: 'normal',
343
+ fontSize: '16px',
344
+ lineHeight: '24px',
345
+ letterSpacing: '0%',
346
+ }
347
+ : undefined
348
+ }
349
+ >
350
+ {cancelLabel || 'Cancelar'}
351
+ </span>
352
+ </Button>
353
+ )}
354
+ <Button
355
+ type="submit"
356
+ tipo="Primary"
357
+ color="Teal"
358
+ tamaño="Default"
359
+ className={onCancel ? 'flex-1' : 'w-full'}
360
+ disabled={disabled || submitting}
361
+ >
362
+ <span
363
+ style={
364
+ isHexaLogin
365
+ ? {
366
+ fontFamily: "'IBM Plex Sans', sans-serif",
367
+ fontWeight: 400,
368
+ fontStyle: 'normal',
369
+ fontSize: '16px',
370
+ lineHeight: '24px',
371
+ letterSpacing: '0%',
372
+ }
373
+ : undefined
374
+ }
375
+ >
376
+ {submitting ? 'Guardando...' : submitLabel || 'Guardar'}
377
+ </span>
378
+ </Button>
379
+ </div>
380
+ </form>
381
+ </div>
382
+ </div>
383
+ </div>
384
+ </div>
385
+ );
386
+ };
387
+
388
+ export default NewPassword;
389
+