xertica-ui 2.2.0 → 2.2.1

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/ThemeContext-BgclCB35.js +1856 -0
  4. package/dist/ThemeContext-DQUOeziy.cjs +1855 -0
  5. package/dist/VerifyEmailPage-RrUApqBN.js +3214 -0
  6. package/dist/VerifyEmailPage-VoMI7MYH.cjs +3213 -0
  7. package/dist/XerticaProvider-BSyFrmC0.js +49 -0
  8. package/dist/XerticaProvider-CiNKjMx1.cjs +48 -0
  9. package/dist/XerticaXLogo-B2svDGZh.cjs +251 -0
  10. package/dist/XerticaXLogo-CowGv7BC.js +252 -0
  11. package/dist/brand.cjs.js +2 -2
  12. package/dist/brand.es.js +2 -2
  13. package/dist/hooks.cjs.js +1 -1
  14. package/dist/hooks.es.js +1 -1
  15. package/dist/index.cjs.js +5 -5
  16. package/dist/index.es.js +5 -5
  17. package/dist/layout.cjs.js +1 -1
  18. package/dist/layout.es.js +1 -1
  19. package/dist/pages.cjs.js +1 -1
  20. package/dist/pages.es.js +1 -1
  21. package/dist/sidebar-CRMiBtAi.js +801 -0
  22. package/dist/sidebar-CZ2mWaMM.cjs +800 -0
  23. package/dist/xertica-ui.css +1 -1
  24. package/package.json +1 -1
  25. package/templates/CLAUDE.md +165 -180
  26. package/templates/package.json +2 -2
  27. package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +9 -7
  28. package/templates/src/features/auth/ui/LoginContent.tsx +10 -8
  29. package/templates/src/features/auth/ui/ResetPasswordContent.tsx +179 -177
  30. package/templates/src/features/auth/ui/SocialLoginButtons.tsx +9 -4
  31. package/templates/src/features/auth/ui/VerifyEmailContent.tsx +84 -82
  32. package/templates/src/features/template/ui/TemplateContent.tsx +1 -1
  33. package/templates/src/locales/en/components/assistant.json +14 -0
  34. package/templates/src/locales/en/pages/forgotPassword.json +10 -0
  35. package/templates/src/locales/en/pages/templates.json +1 -1
  36. package/templates/src/locales/es/components/assistant.json +14 -0
  37. package/templates/src/locales/es/pages/forgotPassword.json +10 -0
  38. package/templates/src/locales/es/pages/templates.json +1 -1
  39. package/templates/src/locales/pt-BR/components/assistant.json +14 -0
  40. package/templates/src/locales/pt-BR/pages/forgotPassword.json +10 -0
  41. package/templates/src/locales/pt-BR/pages/templates.json +1 -1
  42. package/templates/src/pages/AssistantPage.tsx +464 -463
@@ -1,177 +1,179 @@
1
- import React, { useState } from 'react';
2
- import { Button, Input, Label } from 'xertica-ui/ui';
3
- import { XerticaLogo } from 'xertica-ui/brand';
4
- import { ArrowLeft, CheckCircle2, AlertCircle } from 'lucide-react';
5
- import { useNavigate } from 'react-router-dom';
6
- import { AuthPageShell } from './AuthPageShell';
7
-
8
- export function ResetPasswordContent() {
9
- const navigate = useNavigate();
10
- const [password, setPassword] = useState('');
11
- const [confirmPassword, setConfirmPassword] = useState('');
12
- const [isLoading, setIsLoading] = useState(false);
13
- const [error, setError] = useState('');
14
- const [passwordStrength, setPasswordStrength] = useState<'weak' | 'medium' | 'strong' | null>(
15
- null
16
- );
17
-
18
- const checkPasswordStrength = (pwd: string) => {
19
- if (pwd.length === 0) {
20
- setPasswordStrength(null);
21
- return;
22
- }
23
- if (pwd.length < 6) setPasswordStrength('weak');
24
- else if (pwd.length < 10) setPasswordStrength('medium');
25
- else setPasswordStrength('strong');
26
- };
27
-
28
- const handlePasswordChange = (value: string) => {
29
- setPassword(value);
30
- checkPasswordStrength(value);
31
- setError('');
32
- };
33
-
34
- const handleSubmit = async (e: React.FormEvent) => {
35
- e.preventDefault();
36
- setError('');
37
- if (password.length < 6) {
38
- setError('A senha deve ter no mínimo 6 caracteres');
39
- return;
40
- }
41
- if (password !== confirmPassword) {
42
- setError('As senhas não coincidem');
43
- return;
44
- }
45
- setIsLoading(true);
46
- await new Promise(resolve => setTimeout(resolve, 1500));
47
- navigate('/login', { state: { resetSuccess: true } });
48
- setIsLoading(false);
49
- };
50
-
51
- const getStrengthColor = () => {
52
- switch (passwordStrength) {
53
- case 'weak':
54
- return 'text-destructive';
55
- case 'medium':
56
- return 'text-[var(--chart-3)]';
57
- case 'strong':
58
- return 'text-[var(--chart-2)]';
59
- default:
60
- return 'text-muted-foreground';
61
- }
62
- };
63
-
64
- const getStrengthText = () => {
65
- switch (passwordStrength) {
66
- case 'weak':
67
- return 'Senha fraca';
68
- case 'medium':
69
- return 'Senha média';
70
- case 'strong':
71
- return 'Senha forte';
72
- default:
73
- return '';
74
- }
75
- };
76
-
77
- return (
78
- <AuthPageShell
79
- imageSrc="https://images.unsplash.com/photo-1555949963-aa79dcee981c?w=1200&h=800&fit=crop&auto=format"
80
- imageAlt="Segurança e proteção"
81
- >
82
- <button
83
- onClick={() => navigate('/login')}
84
- className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors"
85
- >
86
- <ArrowLeft className="w-4 h-4" />
87
- <span className="text-small">Voltar para login</span>
88
- </button>
89
-
90
- <div className="text-center">
91
- <div className="flex items-center justify-center mb-4">
92
- <XerticaLogo className="h-12 w-auto text-primary dark:text-foreground" variant="theme" />
93
- </div>
94
- <h2 className="text-sm text-muted-foreground">Redefinir senha</h2>
95
- <p className="mt-2 text-muted-foreground">Crie uma nova senha segura para sua conta</p>
96
- </div>
97
-
98
- <form className="space-y-6" onSubmit={handleSubmit}>
99
- <div className="space-y-2">
100
- <Label htmlFor="password">Nova senha</Label>
101
- <Input
102
- id="password"
103
- name="password"
104
- type="password"
105
- required
106
- className="w-full"
107
- placeholder="••••••••"
108
- value={password}
109
- onChange={e => handlePasswordChange(e.target.value)}
110
- />
111
- {passwordStrength && (
112
- <div className="flex items-center gap-2">
113
- <div className="flex-1 h-1 bg-muted rounded-full overflow-hidden">
114
- <div
115
- className={`h-full transition-all duration-300 ${
116
- passwordStrength === 'weak'
117
- ? 'w-1/3 bg-destructive'
118
- : passwordStrength === 'medium'
119
- ? 'w-2/3 bg-[var(--chart-3)]'
120
- : 'w-full bg-[var(--chart-2)]'
121
- }`}
122
- />
123
- </div>
124
- <span className={`text-small ${getStrengthColor()}`}>{getStrengthText()}</span>
125
- </div>
126
- )}
127
- </div>
128
-
129
- <div className="space-y-2">
130
- <Label htmlFor="confirmPassword">Confirmar senha</Label>
131
- <Input
132
- id="confirmPassword"
133
- name="confirmPassword"
134
- type="password"
135
- required
136
- className="w-full"
137
- placeholder="••••••••"
138
- value={confirmPassword}
139
- onChange={e => {
140
- setConfirmPassword(e.target.value);
141
- setError('');
142
- }}
143
- />
144
- </div>
145
-
146
- <div className="bg-accent rounded-[var(--radius)] p-4 space-y-2">
147
- <p className="text-sm">Requisitos da senha:</p>
148
- <div className="space-y-1">
149
- <div className="flex items-center gap-2">
150
- <CheckCircle2
151
- className={`w-4 h-4 ${password.length >= 6 ? 'text-[var(--chart-2)]' : 'text-muted-foreground'}`}
152
- />
153
- <span className="text-sm text-muted-foreground">Mínimo de 6 caracteres</span>
154
- </div>
155
- <div className="flex items-center gap-2">
156
- <CheckCircle2
157
- className={`w-4 h-4 ${password === confirmPassword && password.length > 0 ? 'text-[var(--chart-2)]' : 'text-muted-foreground'}`}
158
- />
159
- <span className="text-sm text-muted-foreground">Senhas coincidem</span>
160
- </div>
161
- </div>
162
- </div>
163
-
164
- {error && (
165
- <div className="flex items-center gap-2 text-destructive bg-destructive/10 rounded-[var(--radius)] p-3">
166
- <AlertCircle className="w-4 h-4 flex-shrink-0" />
167
- <span className="text-sm">{error}</span>
168
- </div>
169
- )}
170
-
171
- <Button type="submit" className="w-full" disabled={isLoading}>
172
- {isLoading ? 'Redefinindo...' : 'Redefinir senha'}
173
- </Button>
174
- </form>
175
- </AuthPageShell>
176
- );
177
- }
1
+ import React, { useState } from 'react';
2
+ import { Button, Input, Label } from 'xertica-ui/ui';
3
+ import { XerticaLogo } from 'xertica-ui/brand';
4
+ import { ArrowLeft, CheckCircle2, AlertCircle } from 'lucide-react';
5
+ import { useNavigate } from 'react-router-dom';
6
+ import { AuthPageShell } from './AuthPageShell';
7
+ import { useTranslation } from 'react-i18next';
8
+
9
+ export function ResetPasswordContent() {
10
+ const navigate = useNavigate();
11
+ const { t } = useTranslation();
12
+ const [password, setPassword] = useState('');
13
+ const [confirmPassword, setConfirmPassword] = useState('');
14
+ const [isLoading, setIsLoading] = useState(false);
15
+ const [error, setError] = useState('');
16
+ const [passwordStrength, setPasswordStrength] = useState<'weak' | 'medium' | 'strong' | null>(
17
+ null
18
+ );
19
+
20
+ const checkPasswordStrength = (pwd: string) => {
21
+ if (pwd.length === 0) {
22
+ setPasswordStrength(null);
23
+ return;
24
+ }
25
+ if (pwd.length < 6) setPasswordStrength('weak');
26
+ else if (pwd.length < 10) setPasswordStrength('medium');
27
+ else setPasswordStrength('strong');
28
+ };
29
+
30
+ const handlePasswordChange = (value: string) => {
31
+ setPassword(value);
32
+ checkPasswordStrength(value);
33
+ setError('');
34
+ };
35
+
36
+ const handleSubmit = async (e: React.FormEvent) => {
37
+ e.preventDefault();
38
+ setError('');
39
+ if (password.length < 6) {
40
+ setError(t('resetPassword.errorMinLength'));
41
+ return;
42
+ }
43
+ if (password !== confirmPassword) {
44
+ setError(t('resetPassword.errorMismatch'));
45
+ return;
46
+ }
47
+ setIsLoading(true);
48
+ await new Promise(resolve => setTimeout(resolve, 1500));
49
+ navigate('/login', { state: { resetSuccess: true } });
50
+ setIsLoading(false);
51
+ };
52
+
53
+ const getStrengthColor = () => {
54
+ switch (passwordStrength) {
55
+ case 'weak':
56
+ return 'text-destructive';
57
+ case 'medium':
58
+ return 'text-[var(--chart-3)]';
59
+ case 'strong':
60
+ return 'text-[var(--chart-2)]';
61
+ default:
62
+ return 'text-muted-foreground';
63
+ }
64
+ };
65
+
66
+ const getStrengthText = () => {
67
+ switch (passwordStrength) {
68
+ case 'weak':
69
+ return t('resetPassword.strengthWeak');
70
+ case 'medium':
71
+ return t('resetPassword.strengthMedium');
72
+ case 'strong':
73
+ return t('resetPassword.strengthStrong');
74
+ default:
75
+ return '';
76
+ }
77
+ };
78
+
79
+ return (
80
+ <AuthPageShell
81
+ imageSrc="https://images.unsplash.com/photo-1555949963-aa79dcee981c?w=1200&h=800&fit=crop&auto=format"
82
+ imageAlt={t('resetPassword.heroImageAlt')}
83
+ >
84
+ <button
85
+ onClick={() => navigate('/login')}
86
+ className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors"
87
+ >
88
+ <ArrowLeft className="w-4 h-4" />
89
+ <span className="text-small">{t('resetPassword.backToLogin')}</span>
90
+ </button>
91
+
92
+ <div className="text-center">
93
+ <div className="flex items-center justify-center mb-4">
94
+ <XerticaLogo className="h-12 w-auto text-primary dark:text-foreground" variant="theme" />
95
+ </div>
96
+ <h2 className="text-sm text-muted-foreground">{t('resetPassword.heading')}</h2>
97
+ <p className="mt-2 text-muted-foreground">{t('resetPassword.subheading')}</p>
98
+ </div>
99
+
100
+ <form className="space-y-6" onSubmit={handleSubmit}>
101
+ <div className="space-y-2">
102
+ <Label htmlFor="password">{t('resetPassword.newPasswordLabel')}</Label>
103
+ <Input
104
+ id="password"
105
+ name="password"
106
+ type="password"
107
+ required
108
+ className="w-full"
109
+ placeholder="••••••••"
110
+ value={password}
111
+ onChange={e => handlePasswordChange(e.target.value)}
112
+ />
113
+ {passwordStrength && (
114
+ <div className="flex items-center gap-2">
115
+ <div className="flex-1 h-1 bg-muted rounded-full overflow-hidden">
116
+ <div
117
+ className={`h-full transition-all duration-300 ${
118
+ passwordStrength === 'weak'
119
+ ? 'w-1/3 bg-destructive'
120
+ : passwordStrength === 'medium'
121
+ ? 'w-2/3 bg-[var(--chart-3)]'
122
+ : 'w-full bg-[var(--chart-2)]'
123
+ }`}
124
+ />
125
+ </div>
126
+ <span className={`text-small ${getStrengthColor()}`}>{getStrengthText()}</span>
127
+ </div>
128
+ )}
129
+ </div>
130
+
131
+ <div className="space-y-2">
132
+ <Label htmlFor="confirmPassword">{t('resetPassword.confirmPasswordLabel')}</Label>
133
+ <Input
134
+ id="confirmPassword"
135
+ name="confirmPassword"
136
+ type="password"
137
+ required
138
+ className="w-full"
139
+ placeholder="••••••••"
140
+ value={confirmPassword}
141
+ onChange={e => {
142
+ setConfirmPassword(e.target.value);
143
+ setError('');
144
+ }}
145
+ />
146
+ </div>
147
+
148
+ <div className="bg-accent rounded-[var(--radius)] p-4 space-y-2">
149
+ <p className="text-sm">{t('resetPassword.requirements')}</p>
150
+ <div className="space-y-1">
151
+ <div className="flex items-center gap-2">
152
+ <CheckCircle2
153
+ className={`w-4 h-4 ${password.length >= 6 ? 'text-[var(--chart-2)]' : 'text-muted-foreground'}`}
154
+ />
155
+ <span className="text-sm text-muted-foreground">{t('resetPassword.requirementMinChars')}</span>
156
+ </div>
157
+ <div className="flex items-center gap-2">
158
+ <CheckCircle2
159
+ className={`w-4 h-4 ${password === confirmPassword && password.length > 0 ? 'text-[var(--chart-2)]' : 'text-muted-foreground'}`}
160
+ />
161
+ <span className="text-sm text-muted-foreground">{t('resetPassword.requirementMatch')}</span>
162
+ </div>
163
+ </div>
164
+ </div>
165
+
166
+ {error && (
167
+ <div className="flex items-center gap-2 text-destructive bg-destructive/10 rounded-[var(--radius)] p-3">
168
+ <AlertCircle className="w-4 h-4 flex-shrink-0" />
169
+ <span className="text-sm">{error}</span>
170
+ </div>
171
+ )}
172
+
173
+ <Button type="submit" className="w-full" disabled={isLoading}>
174
+ {isLoading ? t('resetPassword.submitting') : t('resetPassword.submit')}
175
+ </Button>
176
+ </form>
177
+ </AuthPageShell>
178
+ );
179
+ }
@@ -1,12 +1,15 @@
1
1
  import React from 'react';
2
2
  import { Button } from 'xertica-ui/ui';
3
3
  import { Lock } from 'lucide-react';
4
+ import { useTranslation } from 'react-i18next';
4
5
 
5
6
  interface SocialLoginButtonsProps {
6
7
  onSocialLogin: (provider: string) => void;
7
8
  }
8
9
 
9
10
  export function SocialLoginButtons({ onSocialLogin }: SocialLoginButtonsProps) {
11
+ const { t } = useTranslation();
12
+
10
13
  return (
11
14
  <>
12
15
  <div className="relative">
@@ -14,7 +17,7 @@ export function SocialLoginButtons({ onSocialLogin }: SocialLoginButtonsProps) {
14
17
  <div className="w-full border-t border-border" />
15
18
  </div>
16
19
  <div className="relative flex justify-center text-sm">
17
- <span className="bg-muted px-2 text-muted-foreground">ou continuar com</span>
20
+ <span className="bg-muted px-2 text-muted-foreground">{t('login.orContinueWith')}</span>
18
21
  </div>
19
22
  </div>
20
23
 
@@ -44,7 +47,7 @@ export function SocialLoginButtons({ onSocialLogin }: SocialLoginButtonsProps) {
44
47
  />
45
48
  <path fill="none" d="M0 0h48v48H0z" />
46
49
  </svg>
47
- <span>Entrar com Google</span>
50
+ <span>{t('login.signInWithGoogle')}</span>
48
51
  </Button>
49
52
 
50
53
  <Button
@@ -54,7 +57,7 @@ export function SocialLoginButtons({ onSocialLogin }: SocialLoginButtonsProps) {
54
57
  onClick={() => onSocialLogin('MT Login')}
55
58
  >
56
59
  <Lock className="w-5 h-5 mr-2 text-[var(--chart-4)]" />
57
- <span>Entrar com MT Login</span>
60
+ <span>{t('login.signInWithMTLogin')}</span>
58
61
  </Button>
59
62
 
60
63
  <Button
@@ -64,7 +67,9 @@ export function SocialLoginButtons({ onSocialLogin }: SocialLoginButtonsProps) {
64
67
  onClick={() => onSocialLogin('gov.br')}
65
68
  >
66
69
  <span>
67
- Entrar com <strong className="font-semibold">gov.br</strong>
70
+ {t('login.signInWithGovBr').split('gov.br')[0]}
71
+ <strong className="font-semibold">gov.br</strong>
72
+ {t('login.signInWithGovBr').split('gov.br')[1] || ''}
68
73
  </span>
69
74
  </Button>
70
75
  </div>
@@ -1,82 +1,84 @@
1
- import React, { useState } from 'react';
2
- import { Button } from 'xertica-ui/ui';
3
- import { XerticaLogo } from 'xertica-ui/brand';
4
- import { ArrowLeft, Mail, CheckCircle2 } from 'lucide-react';
5
- import { useNavigate, useLocation } from 'react-router-dom';
6
- import { AuthPageShell } from './AuthPageShell';
7
- import { SocialLoginButtons } from './SocialLoginButtons';
8
-
9
- export function VerifyEmailContent() {
10
- const navigate = useNavigate();
11
- const location = useLocation();
12
- const email = location.state?.email || 'seu@email.com';
13
- const [isResending, setIsResending] = useState(false);
14
- const [resendSuccess, setResendSuccess] = useState(false);
15
-
16
- const handleResend = async () => {
17
- setIsResending(true);
18
- setResendSuccess(false);
19
- await new Promise(resolve => setTimeout(resolve, 1500));
20
- setIsResending(false);
21
- setResendSuccess(true);
22
- setTimeout(() => setResendSuccess(false), 3000);
23
- };
24
-
25
- return (
26
- <AuthPageShell
27
- imageSrc="https://images.unsplash.com/photo-1563986768609-322da13575f3?w=1200&h=800&fit=crop&auto=format"
28
- imageAlt="Email e comunicação"
29
- >
30
- <div className="text-center">
31
- <div className="flex items-center justify-center mb-4">
32
- <XerticaLogo className="h-12 w-auto text-primary dark:text-foreground" variant="theme" />
33
- </div>
34
- <div className="flex items-center justify-center mb-4">
35
- <div className="p-4 bg-primary/10 rounded-[var(--radius)]">
36
- <Mail className="w-12 h-12 text-primary" />
37
- </div>
38
- </div>
39
- <h2 className="text-sm text-muted-foreground">Verifique seu email</h2>
40
- <p className="mt-2 text-muted-foreground">
41
- Enviamos instruções para redefinir sua senha para:
42
- </p>
43
- <p className="mt-1 text-primary">{email}</p>
44
- </div>
45
-
46
- <div className="bg-accent rounded-[var(--radius)] p-4 space-y-3">
47
- <p className="text-muted-foreground">
48
- Siga as instruções no email para redefinir sua senha. O link expira em 24 horas.
49
- </p>
50
- <div className="flex items-start gap-2 text-muted-foreground">
51
- <CheckCircle2 className="w-4 h-4 mt-0.5 flex-shrink-0 text-[var(--chart-2)]" />
52
- <span className="text-sm">Verifique a caixa de spam se não encontrar o email</span>
53
- </div>
54
- </div>
55
-
56
- {resendSuccess && (
57
- <div className="bg-[var(--chart-2)]/10 border border-[var(--chart-2)]/20 rounded-[var(--radius)] p-3 flex items-center gap-2">
58
- <CheckCircle2 className="w-5 h-5 text-[var(--chart-2)] flex-shrink-0" />
59
- <span className="text-sm text-[var(--chart-2)]">Email reenviado com sucesso!</span>
60
- </div>
61
- )}
62
-
63
- <div className="space-y-3">
64
- <p className="text-center text-muted-foreground">Não recebeu o email?</p>
65
- <Button variant="outline" className="w-full" onClick={handleResend} disabled={isResending}>
66
- {isResending ? 'Reenviando...' : 'Reenviar email'}
67
- </Button>
68
- <Button
69
- type="button"
70
- onClick={() => navigate('/login')}
71
- variant="outline"
72
- className="w-full text-muted-foreground hover:text-foreground"
73
- >
74
- <ArrowLeft className="w-4 h-4 mr-2" />
75
- Voltar para login
76
- </Button>
77
- </div>
78
-
79
- <SocialLoginButtons onSocialLogin={provider => console.log(`Login com ${provider}`)} />
80
- </AuthPageShell>
81
- );
82
- }
1
+ import React, { useState } from 'react';
2
+ import { Button } from 'xertica-ui/ui';
3
+ import { XerticaLogo } from 'xertica-ui/brand';
4
+ import { ArrowLeft, Mail, CheckCircle2 } from 'lucide-react';
5
+ import { useNavigate, useLocation } from 'react-router-dom';
6
+ import { AuthPageShell } from './AuthPageShell';
7
+ import { SocialLoginButtons } from './SocialLoginButtons';
8
+ import { useTranslation } from 'react-i18next';
9
+
10
+ export function VerifyEmailContent() {
11
+ const navigate = useNavigate();
12
+ const location = useLocation();
13
+ const { t } = useTranslation();
14
+ const email = location.state?.email || 'seu@email.com';
15
+ const [isResending, setIsResending] = useState(false);
16
+ const [resendSuccess, setResendSuccess] = useState(false);
17
+
18
+ const handleResend = async () => {
19
+ setIsResending(true);
20
+ setResendSuccess(false);
21
+ await new Promise(resolve => setTimeout(resolve, 1500));
22
+ setIsResending(false);
23
+ setResendSuccess(true);
24
+ setTimeout(() => setResendSuccess(false), 3000);
25
+ };
26
+
27
+ return (
28
+ <AuthPageShell
29
+ imageSrc="https://images.unsplash.com/photo-1563986768609-322da13575f3?w=1200&h=800&fit=crop&auto=format"
30
+ imageAlt={t('verifyEmail.heroImageAlt')}
31
+ >
32
+ <div className="text-center">
33
+ <div className="flex items-center justify-center mb-4">
34
+ <XerticaLogo className="h-12 w-auto text-primary dark:text-foreground" variant="theme" />
35
+ </div>
36
+ <div className="flex items-center justify-center mb-4">
37
+ <div className="p-4 bg-primary/10 rounded-[var(--radius)]">
38
+ <Mail className="w-12 h-12 text-primary" />
39
+ </div>
40
+ </div>
41
+ <h2 className="text-sm text-muted-foreground">{t('verifyEmail.heading')}</h2>
42
+ <p className="mt-2 text-muted-foreground">
43
+ {t('verifyEmail.instructionsSent')}
44
+ </p>
45
+ <p className="mt-1 text-primary">{email}</p>
46
+ </div>
47
+
48
+ <div className="bg-accent rounded-[var(--radius)] p-4 space-y-3">
49
+ <p className="text-muted-foreground">
50
+ {t('verifyEmail.instructions')}
51
+ </p>
52
+ <div className="flex items-start gap-2 text-muted-foreground">
53
+ <CheckCircle2 className="w-4 h-4 mt-0.5 flex-shrink-0 text-[var(--chart-2)]" />
54
+ <span className="text-sm">{t('verifyEmail.checkSpam')}</span>
55
+ </div>
56
+ </div>
57
+
58
+ {resendSuccess && (
59
+ <div className="bg-[var(--chart-2)]/10 border border-[var(--chart-2)]/20 rounded-[var(--radius)] p-3 flex items-center gap-2">
60
+ <CheckCircle2 className="w-5 h-5 text-[var(--chart-2)] flex-shrink-0" />
61
+ <span className="text-sm text-[var(--chart-2)]">{t('verifyEmail.resentSuccess')}</span>
62
+ </div>
63
+ )}
64
+
65
+ <div className="space-y-3">
66
+ <p className="text-center text-muted-foreground">{t('verifyEmail.notReceived')}</p>
67
+ <Button variant="outline" className="w-full" onClick={handleResend} disabled={isResending}>
68
+ {isResending ? t('verifyEmail.resending') : t('verifyEmail.resend')}
69
+ </Button>
70
+ <Button
71
+ type="button"
72
+ onClick={() => navigate('/login')}
73
+ variant="outline"
74
+ className="w-full text-muted-foreground hover:text-foreground"
75
+ >
76
+ <ArrowLeft className="w-4 h-4 mr-2" />
77
+ {t('verifyEmail.backToLogin')}
78
+ </Button>
79
+ </div>
80
+
81
+ <SocialLoginButtons onSocialLogin={provider => console.log(`Login com ${provider}`)} />
82
+ </AuthPageShell>
83
+ );
84
+ }
@@ -1114,7 +1114,7 @@ export function TemplateContent() {
1114
1114
 
1115
1115
  <Separator className="my-8" />
1116
1116
 
1117
- {/* ── v2.2.0 Components ──────────────────────────────────── */}
1117
+ {/* ── v2.2.1 Components ──────────────────────────────────── */}
1118
1118
  <Separator className="my-8" />
1119
1119
 
1120
1120
  <section>
@@ -101,5 +101,19 @@
101
101
  "incorrectInfo": "Incorrect information",
102
102
  "incompleteAnswer": "Incomplete answer",
103
103
  "other": "Other..."
104
+ },
105
+ "page": {
106
+ "today": "Today",
107
+ "yesterday": "Yesterday",
108
+ "thisWeek": "This week",
109
+ "searchConversations": "Search conversations...",
110
+ "rename": "Rename",
111
+ "delete": "Delete",
112
+ "cancel": "Cancel",
113
+ "save": "Save",
114
+ "deleteConversationTitle": "Delete conversation",
115
+ "deleteConversationDesc": "Are you sure you want to delete \"{{name}}\"? This action cannot be undone.",
116
+ "renameConversationTitle": "Rename conversation",
117
+ "conversationNameLabel": "Conversation name"
104
118
  }
105
119
  }
@@ -0,0 +1,10 @@
1
+ {
2
+ "heading": "Recover password",
3
+ "subheading": "Enter your email and we will send instructions to reset your password",
4
+ "emailLabel": "Email",
5
+ "emailPlaceholder": "your@email.com",
6
+ "submit": "Send instructions",
7
+ "submitting": "Sending...",
8
+ "backToLogin": "Back to login",
9
+ "heroImageAlt": "Security and technology"
10
+ }
@@ -10,7 +10,7 @@
10
10
  "badges": "Badges",
11
11
  "dialogs": "Dialogs",
12
12
  "sidebarVariations": "Sidebar Variations",
13
- "enhancedComponents": "v2.2.0 — Enhanced Components"
13
+ "enhancedComponents": "v2.2.1 — Enhanced Components"
14
14
  },
15
15
  "alerts": {
16
16
  "infoTitle": "Information",