@xouteiro/auth_npm 1.0.11 → 1.0.12
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 +1 -1
- package/src/components/LoginRegisterFlow.jsx +107 -30
package/package.json
CHANGED
|
@@ -2,19 +2,75 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import { signInWithEmail } from '../login';
|
|
3
3
|
import { registerWithEmail } from '../register';
|
|
4
4
|
|
|
5
|
+
// SVG Eye Icon
|
|
6
|
+
const EyeIcon = ({ open }) => (
|
|
7
|
+
<svg
|
|
8
|
+
width="22"
|
|
9
|
+
height="22"
|
|
10
|
+
viewBox="0 0 22 22"
|
|
11
|
+
fill="none"
|
|
12
|
+
style={{ verticalAlign: 'middle' }}
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
>
|
|
15
|
+
{open ? (
|
|
16
|
+
<>
|
|
17
|
+
<path
|
|
18
|
+
d="M1 11C3.5 5.5 11 2 21 11C18.5 16.5 11 20 1 11Z"
|
|
19
|
+
stroke="#0070f3"
|
|
20
|
+
strokeWidth="2"
|
|
21
|
+
fill="none"
|
|
22
|
+
/>
|
|
23
|
+
<circle
|
|
24
|
+
cx="11"
|
|
25
|
+
cy="11"
|
|
26
|
+
r="3"
|
|
27
|
+
stroke="#0070f3"
|
|
28
|
+
strokeWidth="2"
|
|
29
|
+
fill="none"
|
|
30
|
+
/>
|
|
31
|
+
</>
|
|
32
|
+
) : (
|
|
33
|
+
<>
|
|
34
|
+
<path
|
|
35
|
+
d="M1 11C3.5 5.5 11 2 21 11C18.5 16.5 11 20 1 11Z"
|
|
36
|
+
stroke="#0070f3"
|
|
37
|
+
strokeWidth="2"
|
|
38
|
+
fill="none"
|
|
39
|
+
/>
|
|
40
|
+
<circle
|
|
41
|
+
cx="11"
|
|
42
|
+
cy="11"
|
|
43
|
+
r="3"
|
|
44
|
+
stroke="#0070f3"
|
|
45
|
+
strokeWidth="2"
|
|
46
|
+
fill="none"
|
|
47
|
+
/>
|
|
48
|
+
<line
|
|
49
|
+
x1="4"
|
|
50
|
+
y1="18"
|
|
51
|
+
x2="18"
|
|
52
|
+
y2="4"
|
|
53
|
+
stroke="#d32f2f"
|
|
54
|
+
strokeWidth="2"
|
|
55
|
+
/>
|
|
56
|
+
</>
|
|
57
|
+
)}
|
|
58
|
+
</svg>
|
|
59
|
+
);
|
|
60
|
+
|
|
5
61
|
const boxStyle = {
|
|
6
|
-
maxWidth:
|
|
7
|
-
margin: '
|
|
8
|
-
padding:
|
|
9
|
-
borderRadius:
|
|
10
|
-
boxShadow: '0
|
|
62
|
+
maxWidth: 400,
|
|
63
|
+
margin: '48px auto',
|
|
64
|
+
padding: 36,
|
|
65
|
+
borderRadius: 18,
|
|
66
|
+
boxShadow: '0 4px 24px rgba(0,0,0,0.10)',
|
|
11
67
|
background: '#fff',
|
|
12
|
-
fontFamily: 'sans-serif',
|
|
68
|
+
fontFamily: 'Inter, sans-serif',
|
|
13
69
|
};
|
|
14
70
|
|
|
15
71
|
const tabStyle = (active) => ({
|
|
16
72
|
flex: 1,
|
|
17
|
-
padding:
|
|
73
|
+
padding: 14,
|
|
18
74
|
border: 'none',
|
|
19
75
|
borderBottom: active ? '3px solid #0070f3' : '3px solid #eee',
|
|
20
76
|
background: 'none',
|
|
@@ -22,41 +78,52 @@ const tabStyle = (active) => ({
|
|
|
22
78
|
color: active ? '#0070f3' : '#444',
|
|
23
79
|
cursor: 'pointer',
|
|
24
80
|
outline: 'none',
|
|
81
|
+
fontSize: 18,
|
|
82
|
+
transition: 'border-bottom 0.2s',
|
|
25
83
|
});
|
|
26
84
|
|
|
27
85
|
const inputStyle = {
|
|
28
86
|
width: '100%',
|
|
29
|
-
padding:
|
|
30
|
-
margin: '
|
|
31
|
-
borderRadius:
|
|
32
|
-
border: '
|
|
33
|
-
fontSize:
|
|
87
|
+
padding: '12px 44px 12px 12px',
|
|
88
|
+
margin: '12px 0',
|
|
89
|
+
borderRadius: 8,
|
|
90
|
+
border: '1.5px solid #cfd8dc',
|
|
91
|
+
fontSize: 17,
|
|
92
|
+
background: '#f8fafc',
|
|
93
|
+
boxSizing: 'border-box',
|
|
94
|
+
outline: 'none',
|
|
95
|
+
transition: 'border 0.2s',
|
|
34
96
|
};
|
|
35
97
|
|
|
36
98
|
const buttonStyle = {
|
|
37
99
|
width: '100%',
|
|
38
|
-
padding:
|
|
39
|
-
borderRadius:
|
|
100
|
+
padding: 14,
|
|
101
|
+
borderRadius: 8,
|
|
40
102
|
border: 'none',
|
|
41
|
-
background: '#0070f3',
|
|
103
|
+
background: 'linear-gradient(90deg, #0070f3 60%, #0059c1 100%)',
|
|
42
104
|
color: '#fff',
|
|
43
|
-
fontWeight:
|
|
44
|
-
fontSize:
|
|
45
|
-
marginTop:
|
|
105
|
+
fontWeight: 700,
|
|
106
|
+
fontSize: 18,
|
|
107
|
+
marginTop: 16,
|
|
46
108
|
cursor: 'pointer',
|
|
109
|
+
letterSpacing: 1,
|
|
110
|
+
boxShadow: '0 2px 8px rgba(0,112,243,0.08)',
|
|
111
|
+
transition: 'background 0.2s',
|
|
47
112
|
};
|
|
48
113
|
|
|
49
114
|
const toggleButtonStyle = {
|
|
50
115
|
position: 'absolute',
|
|
51
|
-
right:
|
|
116
|
+
right: 12,
|
|
52
117
|
top: '50%',
|
|
53
118
|
transform: 'translateY(-50%)',
|
|
54
119
|
background: 'none',
|
|
55
120
|
border: 'none',
|
|
56
121
|
color: '#0070f3',
|
|
57
122
|
cursor: 'pointer',
|
|
58
|
-
fontSize:
|
|
123
|
+
fontSize: 18,
|
|
59
124
|
padding: 0,
|
|
125
|
+
display: 'flex',
|
|
126
|
+
alignItems: 'center',
|
|
60
127
|
};
|
|
61
128
|
|
|
62
129
|
const inputWrapperStyle = {
|
|
@@ -65,13 +132,15 @@ const inputWrapperStyle = {
|
|
|
65
132
|
};
|
|
66
133
|
|
|
67
134
|
const messageStyle = (success) => ({
|
|
68
|
-
margin: '
|
|
135
|
+
margin: '16px 0 0 0',
|
|
69
136
|
color: success ? '#0a0' : '#d32f2f',
|
|
70
137
|
background: success ? '#eafbe7' : '#fdeaea',
|
|
71
|
-
padding:
|
|
72
|
-
borderRadius:
|
|
138
|
+
padding: 10,
|
|
139
|
+
borderRadius: 8,
|
|
73
140
|
textAlign: 'center',
|
|
74
|
-
fontSize:
|
|
141
|
+
fontSize: 16,
|
|
142
|
+
fontWeight: 500,
|
|
143
|
+
letterSpacing: 0.2,
|
|
75
144
|
});
|
|
76
145
|
|
|
77
146
|
export default function LoginRegisterFlow({ onLoginSuccess, onRegisterSuccess }) {
|
|
@@ -133,12 +202,12 @@ export default function LoginRegisterFlow({ onLoginSuccess, onRegisterSuccess })
|
|
|
133
202
|
|
|
134
203
|
return (
|
|
135
204
|
<div style={boxStyle}>
|
|
136
|
-
<div style={{ display: 'flex', marginBottom:
|
|
205
|
+
<div style={{ display: 'flex', marginBottom: 28 }}>
|
|
137
206
|
<button style={tabStyle(mode === 'login')} onClick={() => { setMode('login'); setMessage(null); }}>Login</button>
|
|
138
207
|
<button style={tabStyle(mode === 'register')} onClick={() => { setMode('register'); setMessage(null); }}>Register</button>
|
|
139
208
|
</div>
|
|
140
209
|
{mode === 'login' ? (
|
|
141
|
-
<form onSubmit={handleLogin}>
|
|
210
|
+
<form onSubmit={handleLogin} autoComplete="off">
|
|
142
211
|
<input
|
|
143
212
|
style={inputStyle}
|
|
144
213
|
type="text"
|
|
@@ -146,6 +215,7 @@ export default function LoginRegisterFlow({ onLoginSuccess, onRegisterSuccess })
|
|
|
146
215
|
value={identifier}
|
|
147
216
|
onChange={e => setIdentifier(e.target.value)}
|
|
148
217
|
required
|
|
218
|
+
autoComplete="username"
|
|
149
219
|
/>
|
|
150
220
|
<div style={inputWrapperStyle}>
|
|
151
221
|
<input
|
|
@@ -155,20 +225,22 @@ export default function LoginRegisterFlow({ onLoginSuccess, onRegisterSuccess })
|
|
|
155
225
|
value={password}
|
|
156
226
|
onChange={e => setPassword(e.target.value)}
|
|
157
227
|
required
|
|
228
|
+
autoComplete="current-password"
|
|
158
229
|
/>
|
|
159
230
|
<button
|
|
160
231
|
type="button"
|
|
161
232
|
style={toggleButtonStyle}
|
|
162
233
|
tabIndex={-1}
|
|
234
|
+
aria-label={showPassword ? "Hide password" : "Show password"}
|
|
163
235
|
onClick={() => setShowPassword(v => !v)}
|
|
164
236
|
>
|
|
165
|
-
{showPassword
|
|
237
|
+
<EyeIcon open={showPassword} />
|
|
166
238
|
</button>
|
|
167
239
|
</div>
|
|
168
240
|
<button style={buttonStyle} type="submit">Login</button>
|
|
169
241
|
</form>
|
|
170
242
|
) : (
|
|
171
|
-
<form onSubmit={handleRegister}>
|
|
243
|
+
<form onSubmit={handleRegister} autoComplete="off">
|
|
172
244
|
<input
|
|
173
245
|
style={inputStyle}
|
|
174
246
|
type="text"
|
|
@@ -176,6 +248,7 @@ export default function LoginRegisterFlow({ onLoginSuccess, onRegisterSuccess })
|
|
|
176
248
|
value={identifier}
|
|
177
249
|
onChange={e => setIdentifier(e.target.value)}
|
|
178
250
|
required
|
|
251
|
+
autoComplete="username"
|
|
179
252
|
/>
|
|
180
253
|
<div style={inputWrapperStyle}>
|
|
181
254
|
<input
|
|
@@ -185,14 +258,16 @@ export default function LoginRegisterFlow({ onLoginSuccess, onRegisterSuccess })
|
|
|
185
258
|
value={password}
|
|
186
259
|
onChange={e => setPassword(e.target.value)}
|
|
187
260
|
required
|
|
261
|
+
autoComplete="new-password"
|
|
188
262
|
/>
|
|
189
263
|
<button
|
|
190
264
|
type="button"
|
|
191
265
|
style={toggleButtonStyle}
|
|
192
266
|
tabIndex={-1}
|
|
267
|
+
aria-label={showPassword ? "Hide password" : "Show password"}
|
|
193
268
|
onClick={() => setShowPassword(v => !v)}
|
|
194
269
|
>
|
|
195
|
-
{showPassword
|
|
270
|
+
<EyeIcon open={showPassword} />
|
|
196
271
|
</button>
|
|
197
272
|
</div>
|
|
198
273
|
<div style={inputWrapperStyle}>
|
|
@@ -203,14 +278,16 @@ export default function LoginRegisterFlow({ onLoginSuccess, onRegisterSuccess })
|
|
|
203
278
|
value={confirmPassword}
|
|
204
279
|
onChange={e => setConfirmPassword(e.target.value)}
|
|
205
280
|
required
|
|
281
|
+
autoComplete="new-password"
|
|
206
282
|
/>
|
|
207
283
|
<button
|
|
208
284
|
type="button"
|
|
209
285
|
style={toggleButtonStyle}
|
|
210
286
|
tabIndex={-1}
|
|
287
|
+
aria-label={showConfirmPassword ? "Hide confirm password" : "Show confirm password"}
|
|
211
288
|
onClick={() => setShowConfirmPassword(v => !v)}
|
|
212
289
|
>
|
|
213
|
-
{showConfirmPassword
|
|
290
|
+
<EyeIcon open={showConfirmPassword} />
|
|
214
291
|
</button>
|
|
215
292
|
</div>
|
|
216
293
|
<button style={buttonStyle} type="submit">Register</button>
|