@pixygon/auth 1.0.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.
@@ -0,0 +1,1646 @@
1
+ import {
2
+ useAuth
3
+ } from "../chunk-E34M2RJD.mjs";
4
+
5
+ // src/components/PixygonAuth.tsx
6
+ import { useState as useState5, useCallback as useCallback5, useEffect as useEffect2 } from "react";
7
+
8
+ // src/components/LoginForm.tsx
9
+ import { useState, useCallback } from "react";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ function LoginForm({
12
+ onSuccess,
13
+ onError,
14
+ onNavigateRegister,
15
+ onNavigateForgotPassword,
16
+ showBranding = true,
17
+ className = ""
18
+ }) {
19
+ const { login, isLoading, error } = useAuth();
20
+ const [userName, setUserName] = useState("");
21
+ const [password, setPassword] = useState("");
22
+ const [localError, setLocalError] = useState(null);
23
+ const handleSubmit = useCallback(
24
+ async (e) => {
25
+ e.preventDefault();
26
+ setLocalError(null);
27
+ if (!userName.trim()) {
28
+ setLocalError("Please enter your username or email");
29
+ return;
30
+ }
31
+ if (!password) {
32
+ setLocalError("Please enter your password");
33
+ return;
34
+ }
35
+ try {
36
+ const response = await login({ userName: userName.trim(), password });
37
+ onSuccess?.(response.user);
38
+ } catch (err) {
39
+ const authError = err;
40
+ onError?.(authError);
41
+ }
42
+ },
43
+ [userName, password, login, onSuccess, onError]
44
+ );
45
+ const displayError = localError || error?.message;
46
+ return /* @__PURE__ */ jsxs("div", { className: `pixygon-auth-container ${className}`, children: [
47
+ /* @__PURE__ */ jsx("style", { children: `
48
+ .pixygon-auth-container {
49
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
50
+ background: #0f0f0f;
51
+ color: #ffffff;
52
+ padding: 2rem;
53
+ border-radius: 1rem;
54
+ max-width: 400px;
55
+ width: 100%;
56
+ margin: 0 auto;
57
+ }
58
+
59
+ .pixygon-auth-header {
60
+ text-align: center;
61
+ margin-bottom: 2rem;
62
+ }
63
+
64
+ .pixygon-auth-logo {
65
+ width: 64px;
66
+ height: 64px;
67
+ margin: 0 auto 1rem;
68
+ display: block;
69
+ }
70
+
71
+ .pixygon-auth-title {
72
+ font-size: 1.5rem;
73
+ font-weight: 600;
74
+ margin: 0 0 0.5rem;
75
+ }
76
+
77
+ .pixygon-auth-subtitle {
78
+ font-size: 0.875rem;
79
+ color: #a3a3a3;
80
+ margin: 0;
81
+ }
82
+
83
+ .pixygon-auth-form {
84
+ display: flex;
85
+ flex-direction: column;
86
+ gap: 1rem;
87
+ }
88
+
89
+ .pixygon-auth-input-group {
90
+ display: flex;
91
+ flex-direction: column;
92
+ gap: 0.375rem;
93
+ }
94
+
95
+ .pixygon-auth-label {
96
+ font-size: 0.875rem;
97
+ font-weight: 500;
98
+ color: #a3a3a3;
99
+ }
100
+
101
+ .pixygon-auth-input {
102
+ background: #262626;
103
+ border: 1px solid #404040;
104
+ border-radius: 0.5rem;
105
+ padding: 0.75rem 1rem;
106
+ font-size: 1rem;
107
+ color: #ffffff;
108
+ outline: none;
109
+ transition: border-color 0.2s, box-shadow 0.2s;
110
+ }
111
+
112
+ .pixygon-auth-input:focus {
113
+ border-color: #6366f1;
114
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
115
+ }
116
+
117
+ .pixygon-auth-input.error {
118
+ border-color: #ef4444;
119
+ }
120
+
121
+ .pixygon-auth-button {
122
+ background: #6366f1;
123
+ color: white;
124
+ border: none;
125
+ border-radius: 0.5rem;
126
+ padding: 0.875rem 1.5rem;
127
+ font-size: 1rem;
128
+ font-weight: 600;
129
+ cursor: pointer;
130
+ transition: background 0.2s;
131
+ display: flex;
132
+ align-items: center;
133
+ justify-content: center;
134
+ gap: 0.5rem;
135
+ margin-top: 0.5rem;
136
+ }
137
+
138
+ .pixygon-auth-button:hover:not(:disabled) {
139
+ background: #4f46e5;
140
+ }
141
+
142
+ .pixygon-auth-button:disabled {
143
+ opacity: 0.6;
144
+ cursor: not-allowed;
145
+ }
146
+
147
+ .pixygon-auth-error {
148
+ background: rgba(239, 68, 68, 0.1);
149
+ border: 1px solid #ef4444;
150
+ border-radius: 0.5rem;
151
+ padding: 0.75rem 1rem;
152
+ color: #fca5a5;
153
+ font-size: 0.875rem;
154
+ }
155
+
156
+ .pixygon-auth-link {
157
+ color: #6366f1;
158
+ text-decoration: none;
159
+ font-size: 0.875rem;
160
+ cursor: pointer;
161
+ background: none;
162
+ border: none;
163
+ padding: 0;
164
+ font-family: inherit;
165
+ }
166
+
167
+ .pixygon-auth-link:hover {
168
+ color: #818cf8;
169
+ text-decoration: underline;
170
+ }
171
+
172
+ .pixygon-auth-footer {
173
+ text-align: center;
174
+ margin-top: 1.5rem;
175
+ font-size: 0.875rem;
176
+ color: #a3a3a3;
177
+ }
178
+
179
+ .pixygon-auth-branding {
180
+ display: flex;
181
+ align-items: center;
182
+ justify-content: center;
183
+ gap: 0.5rem;
184
+ margin-top: 1.5rem;
185
+ font-size: 0.75rem;
186
+ color: #737373;
187
+ }
188
+
189
+ .pixygon-auth-spinner {
190
+ width: 20px;
191
+ height: 20px;
192
+ border: 2px solid transparent;
193
+ border-top-color: currentColor;
194
+ border-radius: 50%;
195
+ animation: pixygon-spin 0.8s linear infinite;
196
+ }
197
+
198
+ @keyframes pixygon-spin {
199
+ to { transform: rotate(360deg); }
200
+ }
201
+
202
+ .pixygon-auth-forgot-password {
203
+ text-align: right;
204
+ margin-top: -0.5rem;
205
+ }
206
+ ` }),
207
+ /* @__PURE__ */ jsxs("div", { className: "pixygon-auth-header", children: [
208
+ /* @__PURE__ */ jsxs(
209
+ "svg",
210
+ {
211
+ className: "pixygon-auth-logo",
212
+ viewBox: "0 0 100 100",
213
+ fill: "none",
214
+ xmlns: "http://www.w3.org/2000/svg",
215
+ children: [
216
+ /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r: "45", fill: "#6366f1" }),
217
+ /* @__PURE__ */ jsx(
218
+ "path",
219
+ {
220
+ d: "M30 45L45 30L70 55L55 70L30 45Z",
221
+ fill: "white",
222
+ fillOpacity: "0.9"
223
+ }
224
+ ),
225
+ /* @__PURE__ */ jsx(
226
+ "path",
227
+ {
228
+ d: "M35 55L50 70L45 75L30 60L35 55Z",
229
+ fill: "white",
230
+ fillOpacity: "0.7"
231
+ }
232
+ )
233
+ ]
234
+ }
235
+ ),
236
+ /* @__PURE__ */ jsx("h1", { className: "pixygon-auth-title", children: "Welcome back" }),
237
+ /* @__PURE__ */ jsx("p", { className: "pixygon-auth-subtitle", children: "Sign in to your Pixygon Account" })
238
+ ] }),
239
+ /* @__PURE__ */ jsxs("form", { className: "pixygon-auth-form", onSubmit: handleSubmit, children: [
240
+ displayError && /* @__PURE__ */ jsx("div", { className: "pixygon-auth-error", children: displayError }),
241
+ /* @__PURE__ */ jsxs("div", { className: "pixygon-auth-input-group", children: [
242
+ /* @__PURE__ */ jsx("label", { className: "pixygon-auth-label", htmlFor: "pixygon-login-username", children: "Username or Email" }),
243
+ /* @__PURE__ */ jsx(
244
+ "input",
245
+ {
246
+ id: "pixygon-login-username",
247
+ className: `pixygon-auth-input ${displayError ? "error" : ""}`,
248
+ type: "text",
249
+ value: userName,
250
+ onChange: (e) => setUserName(e.target.value),
251
+ placeholder: "Enter your username or email",
252
+ autoComplete: "username",
253
+ disabled: isLoading
254
+ }
255
+ )
256
+ ] }),
257
+ /* @__PURE__ */ jsxs("div", { className: "pixygon-auth-input-group", children: [
258
+ /* @__PURE__ */ jsx("label", { className: "pixygon-auth-label", htmlFor: "pixygon-login-password", children: "Password" }),
259
+ /* @__PURE__ */ jsx(
260
+ "input",
261
+ {
262
+ id: "pixygon-login-password",
263
+ className: `pixygon-auth-input ${displayError ? "error" : ""}`,
264
+ type: "password",
265
+ value: password,
266
+ onChange: (e) => setPassword(e.target.value),
267
+ placeholder: "Enter your password",
268
+ autoComplete: "current-password",
269
+ disabled: isLoading
270
+ }
271
+ )
272
+ ] }),
273
+ onNavigateForgotPassword && /* @__PURE__ */ jsx("div", { className: "pixygon-auth-forgot-password", children: /* @__PURE__ */ jsx(
274
+ "button",
275
+ {
276
+ type: "button",
277
+ className: "pixygon-auth-link",
278
+ onClick: onNavigateForgotPassword,
279
+ children: "Forgot password?"
280
+ }
281
+ ) }),
282
+ /* @__PURE__ */ jsx(
283
+ "button",
284
+ {
285
+ type: "submit",
286
+ className: "pixygon-auth-button",
287
+ disabled: isLoading,
288
+ children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
289
+ /* @__PURE__ */ jsx("div", { className: "pixygon-auth-spinner" }),
290
+ "Signing in..."
291
+ ] }) : "Sign in"
292
+ }
293
+ )
294
+ ] }),
295
+ onNavigateRegister && /* @__PURE__ */ jsxs("div", { className: "pixygon-auth-footer", children: [
296
+ "Don't have an account?",
297
+ " ",
298
+ /* @__PURE__ */ jsx(
299
+ "button",
300
+ {
301
+ type: "button",
302
+ className: "pixygon-auth-link",
303
+ onClick: onNavigateRegister,
304
+ children: "Create one"
305
+ }
306
+ )
307
+ ] }),
308
+ showBranding && /* @__PURE__ */ jsx("div", { className: "pixygon-auth-branding", children: "Secured by Pixygon Account" })
309
+ ] });
310
+ }
311
+
312
+ // src/components/RegisterForm.tsx
313
+ import { useState as useState2, useCallback as useCallback2 } from "react";
314
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
315
+ function RegisterForm({
316
+ onSuccess,
317
+ onError,
318
+ onNavigateLogin,
319
+ showBranding = true,
320
+ className = ""
321
+ }) {
322
+ const { register, isLoading, error } = useAuth();
323
+ const [userName, setUserName] = useState2("");
324
+ const [email, setEmail] = useState2("");
325
+ const [password, setPassword] = useState2("");
326
+ const [confirmPassword, setConfirmPassword] = useState2("");
327
+ const [localError, setLocalError] = useState2(null);
328
+ const validateForm = useCallback2(() => {
329
+ if (!userName.trim()) {
330
+ setLocalError("Please enter a username");
331
+ return false;
332
+ }
333
+ if (userName.length < 3) {
334
+ setLocalError("Username must be at least 3 characters");
335
+ return false;
336
+ }
337
+ if (!/^[a-zA-Z0-9_-]+$/.test(userName)) {
338
+ setLocalError("Username can only contain letters, numbers, underscores, and hyphens");
339
+ return false;
340
+ }
341
+ if (!email.trim()) {
342
+ setLocalError("Please enter your email");
343
+ return false;
344
+ }
345
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
346
+ setLocalError("Please enter a valid email address");
347
+ return false;
348
+ }
349
+ if (!password) {
350
+ setLocalError("Please enter a password");
351
+ return false;
352
+ }
353
+ if (password.length < 6) {
354
+ setLocalError("Password must be at least 6 characters");
355
+ return false;
356
+ }
357
+ if (password !== confirmPassword) {
358
+ setLocalError("Passwords do not match");
359
+ return false;
360
+ }
361
+ return true;
362
+ }, [userName, email, password, confirmPassword]);
363
+ const handleSubmit = useCallback2(
364
+ async (e) => {
365
+ e.preventDefault();
366
+ setLocalError(null);
367
+ if (!validateForm()) return;
368
+ try {
369
+ const response = await register({
370
+ userName: userName.trim(),
371
+ email: email.trim().toLowerCase(),
372
+ password,
373
+ confirmPassword
374
+ });
375
+ onSuccess?.(response.user);
376
+ } catch (err) {
377
+ const authError = err;
378
+ onError?.(authError);
379
+ }
380
+ },
381
+ [userName, email, password, confirmPassword, register, validateForm, onSuccess, onError]
382
+ );
383
+ const displayError = localError || error?.message;
384
+ const getPasswordStrength = (pwd) => {
385
+ if (!pwd) return { level: 0, label: "" };
386
+ let strength = 0;
387
+ if (pwd.length >= 6) strength++;
388
+ if (pwd.length >= 10) strength++;
389
+ if (/[A-Z]/.test(pwd)) strength++;
390
+ if (/[0-9]/.test(pwd)) strength++;
391
+ if (/[^A-Za-z0-9]/.test(pwd)) strength++;
392
+ if (strength <= 2) return { level: 1, label: "Weak" };
393
+ if (strength <= 3) return { level: 2, label: "Fair" };
394
+ if (strength <= 4) return { level: 3, label: "Good" };
395
+ return { level: 4, label: "Strong" };
396
+ };
397
+ const passwordStrength = getPasswordStrength(password);
398
+ return /* @__PURE__ */ jsxs2("div", { className: `pixygon-auth-container ${className}`, children: [
399
+ /* @__PURE__ */ jsx2("style", { children: `
400
+ .pixygon-auth-container {
401
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
402
+ background: #0f0f0f;
403
+ color: #ffffff;
404
+ padding: 2rem;
405
+ border-radius: 1rem;
406
+ max-width: 400px;
407
+ width: 100%;
408
+ margin: 0 auto;
409
+ }
410
+
411
+ .pixygon-auth-header {
412
+ text-align: center;
413
+ margin-bottom: 2rem;
414
+ }
415
+
416
+ .pixygon-auth-logo {
417
+ width: 64px;
418
+ height: 64px;
419
+ margin: 0 auto 1rem;
420
+ display: block;
421
+ }
422
+
423
+ .pixygon-auth-title {
424
+ font-size: 1.5rem;
425
+ font-weight: 600;
426
+ margin: 0 0 0.5rem;
427
+ }
428
+
429
+ .pixygon-auth-subtitle {
430
+ font-size: 0.875rem;
431
+ color: #a3a3a3;
432
+ margin: 0;
433
+ }
434
+
435
+ .pixygon-auth-form {
436
+ display: flex;
437
+ flex-direction: column;
438
+ gap: 1rem;
439
+ }
440
+
441
+ .pixygon-auth-input-group {
442
+ display: flex;
443
+ flex-direction: column;
444
+ gap: 0.375rem;
445
+ }
446
+
447
+ .pixygon-auth-label {
448
+ font-size: 0.875rem;
449
+ font-weight: 500;
450
+ color: #a3a3a3;
451
+ }
452
+
453
+ .pixygon-auth-input {
454
+ background: #262626;
455
+ border: 1px solid #404040;
456
+ border-radius: 0.5rem;
457
+ padding: 0.75rem 1rem;
458
+ font-size: 1rem;
459
+ color: #ffffff;
460
+ outline: none;
461
+ transition: border-color 0.2s, box-shadow 0.2s;
462
+ }
463
+
464
+ .pixygon-auth-input:focus {
465
+ border-color: #6366f1;
466
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
467
+ }
468
+
469
+ .pixygon-auth-input.error {
470
+ border-color: #ef4444;
471
+ }
472
+
473
+ .pixygon-auth-button {
474
+ background: #6366f1;
475
+ color: white;
476
+ border: none;
477
+ border-radius: 0.5rem;
478
+ padding: 0.875rem 1.5rem;
479
+ font-size: 1rem;
480
+ font-weight: 600;
481
+ cursor: pointer;
482
+ transition: background 0.2s;
483
+ display: flex;
484
+ align-items: center;
485
+ justify-content: center;
486
+ gap: 0.5rem;
487
+ margin-top: 0.5rem;
488
+ }
489
+
490
+ .pixygon-auth-button:hover:not(:disabled) {
491
+ background: #4f46e5;
492
+ }
493
+
494
+ .pixygon-auth-button:disabled {
495
+ opacity: 0.6;
496
+ cursor: not-allowed;
497
+ }
498
+
499
+ .pixygon-auth-error {
500
+ background: rgba(239, 68, 68, 0.1);
501
+ border: 1px solid #ef4444;
502
+ border-radius: 0.5rem;
503
+ padding: 0.75rem 1rem;
504
+ color: #fca5a5;
505
+ font-size: 0.875rem;
506
+ }
507
+
508
+ .pixygon-auth-link {
509
+ color: #6366f1;
510
+ text-decoration: none;
511
+ font-size: 0.875rem;
512
+ cursor: pointer;
513
+ background: none;
514
+ border: none;
515
+ padding: 0;
516
+ font-family: inherit;
517
+ }
518
+
519
+ .pixygon-auth-link:hover {
520
+ color: #818cf8;
521
+ text-decoration: underline;
522
+ }
523
+
524
+ .pixygon-auth-footer {
525
+ text-align: center;
526
+ margin-top: 1.5rem;
527
+ font-size: 0.875rem;
528
+ color: #a3a3a3;
529
+ }
530
+
531
+ .pixygon-auth-branding {
532
+ display: flex;
533
+ align-items: center;
534
+ justify-content: center;
535
+ gap: 0.5rem;
536
+ margin-top: 1.5rem;
537
+ font-size: 0.75rem;
538
+ color: #737373;
539
+ }
540
+
541
+ .pixygon-auth-spinner {
542
+ width: 20px;
543
+ height: 20px;
544
+ border: 2px solid transparent;
545
+ border-top-color: currentColor;
546
+ border-radius: 50%;
547
+ animation: pixygon-spin 0.8s linear infinite;
548
+ }
549
+
550
+ @keyframes pixygon-spin {
551
+ to { transform: rotate(360deg); }
552
+ }
553
+
554
+ .pixygon-auth-password-strength {
555
+ display: flex;
556
+ gap: 0.25rem;
557
+ margin-top: 0.5rem;
558
+ }
559
+
560
+ .pixygon-auth-password-strength-bar {
561
+ flex: 1;
562
+ height: 4px;
563
+ border-radius: 2px;
564
+ background: #404040;
565
+ transition: background 0.3s;
566
+ }
567
+
568
+ .pixygon-auth-password-strength-bar.active {
569
+ background: #6366f1;
570
+ }
571
+
572
+ .pixygon-auth-password-strength-bar.weak {
573
+ background: #ef4444;
574
+ }
575
+
576
+ .pixygon-auth-password-strength-bar.fair {
577
+ background: #f59e0b;
578
+ }
579
+
580
+ .pixygon-auth-password-strength-bar.good {
581
+ background: #22c55e;
582
+ }
583
+
584
+ .pixygon-auth-password-strength-bar.strong {
585
+ background: #10b981;
586
+ }
587
+
588
+ .pixygon-auth-password-label {
589
+ font-size: 0.75rem;
590
+ color: #737373;
591
+ margin-top: 0.25rem;
592
+ }
593
+ ` }),
594
+ /* @__PURE__ */ jsxs2("div", { className: "pixygon-auth-header", children: [
595
+ /* @__PURE__ */ jsxs2(
596
+ "svg",
597
+ {
598
+ className: "pixygon-auth-logo",
599
+ viewBox: "0 0 100 100",
600
+ fill: "none",
601
+ xmlns: "http://www.w3.org/2000/svg",
602
+ children: [
603
+ /* @__PURE__ */ jsx2("circle", { cx: "50", cy: "50", r: "45", fill: "#6366f1" }),
604
+ /* @__PURE__ */ jsx2(
605
+ "path",
606
+ {
607
+ d: "M30 45L45 30L70 55L55 70L30 45Z",
608
+ fill: "white",
609
+ fillOpacity: "0.9"
610
+ }
611
+ ),
612
+ /* @__PURE__ */ jsx2(
613
+ "path",
614
+ {
615
+ d: "M35 55L50 70L45 75L30 60L35 55Z",
616
+ fill: "white",
617
+ fillOpacity: "0.7"
618
+ }
619
+ )
620
+ ]
621
+ }
622
+ ),
623
+ /* @__PURE__ */ jsx2("h1", { className: "pixygon-auth-title", children: "Create Account" }),
624
+ /* @__PURE__ */ jsx2("p", { className: "pixygon-auth-subtitle", children: "Join Pixygon to access all apps" })
625
+ ] }),
626
+ /* @__PURE__ */ jsxs2("form", { className: "pixygon-auth-form", onSubmit: handleSubmit, children: [
627
+ displayError && /* @__PURE__ */ jsx2("div", { className: "pixygon-auth-error", children: displayError }),
628
+ /* @__PURE__ */ jsxs2("div", { className: "pixygon-auth-input-group", children: [
629
+ /* @__PURE__ */ jsx2("label", { className: "pixygon-auth-label", htmlFor: "pixygon-register-username", children: "Username" }),
630
+ /* @__PURE__ */ jsx2(
631
+ "input",
632
+ {
633
+ id: "pixygon-register-username",
634
+ className: `pixygon-auth-input ${displayError ? "error" : ""}`,
635
+ type: "text",
636
+ value: userName,
637
+ onChange: (e) => setUserName(e.target.value),
638
+ placeholder: "Choose a username",
639
+ autoComplete: "username",
640
+ disabled: isLoading
641
+ }
642
+ )
643
+ ] }),
644
+ /* @__PURE__ */ jsxs2("div", { className: "pixygon-auth-input-group", children: [
645
+ /* @__PURE__ */ jsx2("label", { className: "pixygon-auth-label", htmlFor: "pixygon-register-email", children: "Email" }),
646
+ /* @__PURE__ */ jsx2(
647
+ "input",
648
+ {
649
+ id: "pixygon-register-email",
650
+ className: `pixygon-auth-input ${displayError ? "error" : ""}`,
651
+ type: "email",
652
+ value: email,
653
+ onChange: (e) => setEmail(e.target.value),
654
+ placeholder: "Enter your email",
655
+ autoComplete: "email",
656
+ disabled: isLoading
657
+ }
658
+ )
659
+ ] }),
660
+ /* @__PURE__ */ jsxs2("div", { className: "pixygon-auth-input-group", children: [
661
+ /* @__PURE__ */ jsx2("label", { className: "pixygon-auth-label", htmlFor: "pixygon-register-password", children: "Password" }),
662
+ /* @__PURE__ */ jsx2(
663
+ "input",
664
+ {
665
+ id: "pixygon-register-password",
666
+ className: `pixygon-auth-input ${displayError ? "error" : ""}`,
667
+ type: "password",
668
+ value: password,
669
+ onChange: (e) => setPassword(e.target.value),
670
+ placeholder: "Create a password",
671
+ autoComplete: "new-password",
672
+ disabled: isLoading
673
+ }
674
+ ),
675
+ password && /* @__PURE__ */ jsxs2(Fragment2, { children: [
676
+ /* @__PURE__ */ jsx2("div", { className: "pixygon-auth-password-strength", children: [1, 2, 3, 4].map((level) => /* @__PURE__ */ jsx2(
677
+ "div",
678
+ {
679
+ className: `pixygon-auth-password-strength-bar ${level <= passwordStrength.level ? passwordStrength.level === 1 ? "weak" : passwordStrength.level === 2 ? "fair" : passwordStrength.level === 3 ? "good" : "strong" : ""}`
680
+ },
681
+ level
682
+ )) }),
683
+ /* @__PURE__ */ jsxs2("div", { className: "pixygon-auth-password-label", children: [
684
+ "Password strength: ",
685
+ passwordStrength.label
686
+ ] })
687
+ ] })
688
+ ] }),
689
+ /* @__PURE__ */ jsxs2("div", { className: "pixygon-auth-input-group", children: [
690
+ /* @__PURE__ */ jsx2("label", { className: "pixygon-auth-label", htmlFor: "pixygon-register-confirm", children: "Confirm Password" }),
691
+ /* @__PURE__ */ jsx2(
692
+ "input",
693
+ {
694
+ id: "pixygon-register-confirm",
695
+ className: `pixygon-auth-input ${displayError ? "error" : ""}`,
696
+ type: "password",
697
+ value: confirmPassword,
698
+ onChange: (e) => setConfirmPassword(e.target.value),
699
+ placeholder: "Confirm your password",
700
+ autoComplete: "new-password",
701
+ disabled: isLoading
702
+ }
703
+ )
704
+ ] }),
705
+ /* @__PURE__ */ jsx2(
706
+ "button",
707
+ {
708
+ type: "submit",
709
+ className: "pixygon-auth-button",
710
+ disabled: isLoading,
711
+ children: isLoading ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
712
+ /* @__PURE__ */ jsx2("div", { className: "pixygon-auth-spinner" }),
713
+ "Creating account..."
714
+ ] }) : "Create Account"
715
+ }
716
+ )
717
+ ] }),
718
+ onNavigateLogin && /* @__PURE__ */ jsxs2("div", { className: "pixygon-auth-footer", children: [
719
+ "Already have an account?",
720
+ " ",
721
+ /* @__PURE__ */ jsx2(
722
+ "button",
723
+ {
724
+ type: "button",
725
+ className: "pixygon-auth-link",
726
+ onClick: onNavigateLogin,
727
+ children: "Sign in"
728
+ }
729
+ )
730
+ ] }),
731
+ showBranding && /* @__PURE__ */ jsx2("div", { className: "pixygon-auth-branding", children: "Secured by Pixygon Account" })
732
+ ] });
733
+ }
734
+
735
+ // src/components/VerifyForm.tsx
736
+ import { useState as useState3, useCallback as useCallback3, useRef, useEffect } from "react";
737
+ import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
738
+ function VerifyForm({
739
+ userName,
740
+ onSuccess,
741
+ onError,
742
+ onNavigateLogin,
743
+ showBranding = true,
744
+ className = ""
745
+ }) {
746
+ const { verify, resendVerification, isLoading, error } = useAuth();
747
+ const [code, setCode] = useState3(["", "", "", "", "", ""]);
748
+ const [localError, setLocalError] = useState3(null);
749
+ const [resendSuccess, setResendSuccess] = useState3(false);
750
+ const [resendCooldown, setResendCooldown] = useState3(0);
751
+ const inputRefs = useRef([]);
752
+ useEffect(() => {
753
+ inputRefs.current[0]?.focus();
754
+ }, []);
755
+ useEffect(() => {
756
+ if (resendCooldown > 0) {
757
+ const timer = setTimeout(() => setResendCooldown(resendCooldown - 1), 1e3);
758
+ return () => clearTimeout(timer);
759
+ }
760
+ }, [resendCooldown]);
761
+ const handleChange = useCallback3(
762
+ (index, value) => {
763
+ if (!/^\d*$/.test(value)) return;
764
+ const newCode = [...code];
765
+ newCode[index] = value.slice(-1);
766
+ setCode(newCode);
767
+ if (value && index < 5) {
768
+ inputRefs.current[index + 1]?.focus();
769
+ }
770
+ if (newCode.every((digit) => digit) && value) {
771
+ handleSubmitCode(newCode.join(""));
772
+ }
773
+ },
774
+ [code]
775
+ );
776
+ const handleKeyDown = useCallback3(
777
+ (index, e) => {
778
+ if (e.key === "Backspace" && !code[index] && index > 0) {
779
+ inputRefs.current[index - 1]?.focus();
780
+ }
781
+ },
782
+ [code]
783
+ );
784
+ const handlePaste = useCallback3(
785
+ (e) => {
786
+ e.preventDefault();
787
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6);
788
+ if (pasted.length === 6) {
789
+ const newCode = pasted.split("");
790
+ setCode(newCode);
791
+ inputRefs.current[5]?.focus();
792
+ handleSubmitCode(pasted);
793
+ }
794
+ },
795
+ []
796
+ );
797
+ const handleSubmitCode = useCallback3(
798
+ async (verificationCode) => {
799
+ setLocalError(null);
800
+ setResendSuccess(false);
801
+ try {
802
+ const response = await verify({ userName, verificationCode });
803
+ onSuccess?.(response.user);
804
+ } catch (err) {
805
+ const authError = err;
806
+ onError?.(authError);
807
+ setCode(["", "", "", "", "", ""]);
808
+ inputRefs.current[0]?.focus();
809
+ }
810
+ },
811
+ [userName, verify, onSuccess, onError]
812
+ );
813
+ const handleSubmit = useCallback3(
814
+ (e) => {
815
+ e.preventDefault();
816
+ const verificationCode = code.join("");
817
+ if (verificationCode.length !== 6) {
818
+ setLocalError("Please enter the complete 6-digit code");
819
+ return;
820
+ }
821
+ handleSubmitCode(verificationCode);
822
+ },
823
+ [code, handleSubmitCode]
824
+ );
825
+ const handleResend = useCallback3(async () => {
826
+ if (resendCooldown > 0) return;
827
+ setLocalError(null);
828
+ setResendSuccess(false);
829
+ try {
830
+ await resendVerification({ userName });
831
+ setResendSuccess(true);
832
+ setResendCooldown(60);
833
+ } catch (err) {
834
+ const authError = err;
835
+ setLocalError(authError.message);
836
+ }
837
+ }, [userName, resendVerification, resendCooldown]);
838
+ const displayError = localError || error?.message;
839
+ return /* @__PURE__ */ jsxs3("div", { className: `pixygon-auth-container ${className}`, children: [
840
+ /* @__PURE__ */ jsx3("style", { children: `
841
+ .pixygon-auth-container {
842
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
843
+ background: #0f0f0f;
844
+ color: #ffffff;
845
+ padding: 2rem;
846
+ border-radius: 1rem;
847
+ max-width: 400px;
848
+ width: 100%;
849
+ margin: 0 auto;
850
+ }
851
+
852
+ .pixygon-auth-header {
853
+ text-align: center;
854
+ margin-bottom: 2rem;
855
+ }
856
+
857
+ .pixygon-auth-logo {
858
+ width: 64px;
859
+ height: 64px;
860
+ margin: 0 auto 1rem;
861
+ display: block;
862
+ }
863
+
864
+ .pixygon-auth-title {
865
+ font-size: 1.5rem;
866
+ font-weight: 600;
867
+ margin: 0 0 0.5rem;
868
+ }
869
+
870
+ .pixygon-auth-subtitle {
871
+ font-size: 0.875rem;
872
+ color: #a3a3a3;
873
+ margin: 0;
874
+ }
875
+
876
+ .pixygon-auth-form {
877
+ display: flex;
878
+ flex-direction: column;
879
+ gap: 1.5rem;
880
+ }
881
+
882
+ .pixygon-auth-code-container {
883
+ display: flex;
884
+ gap: 0.5rem;
885
+ justify-content: center;
886
+ }
887
+
888
+ .pixygon-auth-code-input {
889
+ width: 3rem;
890
+ height: 3.5rem;
891
+ text-align: center;
892
+ font-size: 1.5rem;
893
+ font-weight: 600;
894
+ background: #262626;
895
+ border: 1px solid #404040;
896
+ border-radius: 0.5rem;
897
+ color: #ffffff;
898
+ outline: none;
899
+ transition: border-color 0.2s, box-shadow 0.2s;
900
+ }
901
+
902
+ .pixygon-auth-code-input:focus {
903
+ border-color: #6366f1;
904
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
905
+ }
906
+
907
+ .pixygon-auth-code-input.error {
908
+ border-color: #ef4444;
909
+ }
910
+
911
+ .pixygon-auth-button {
912
+ background: #6366f1;
913
+ color: white;
914
+ border: none;
915
+ border-radius: 0.5rem;
916
+ padding: 0.875rem 1.5rem;
917
+ font-size: 1rem;
918
+ font-weight: 600;
919
+ cursor: pointer;
920
+ transition: background 0.2s;
921
+ display: flex;
922
+ align-items: center;
923
+ justify-content: center;
924
+ gap: 0.5rem;
925
+ }
926
+
927
+ .pixygon-auth-button:hover:not(:disabled) {
928
+ background: #4f46e5;
929
+ }
930
+
931
+ .pixygon-auth-button:disabled {
932
+ opacity: 0.6;
933
+ cursor: not-allowed;
934
+ }
935
+
936
+ .pixygon-auth-error {
937
+ background: rgba(239, 68, 68, 0.1);
938
+ border: 1px solid #ef4444;
939
+ border-radius: 0.5rem;
940
+ padding: 0.75rem 1rem;
941
+ color: #fca5a5;
942
+ font-size: 0.875rem;
943
+ }
944
+
945
+ .pixygon-auth-success {
946
+ background: rgba(34, 197, 94, 0.1);
947
+ border: 1px solid #22c55e;
948
+ border-radius: 0.5rem;
949
+ padding: 0.75rem 1rem;
950
+ color: #86efac;
951
+ font-size: 0.875rem;
952
+ }
953
+
954
+ .pixygon-auth-link {
955
+ color: #6366f1;
956
+ text-decoration: none;
957
+ font-size: 0.875rem;
958
+ cursor: pointer;
959
+ background: none;
960
+ border: none;
961
+ padding: 0;
962
+ font-family: inherit;
963
+ }
964
+
965
+ .pixygon-auth-link:hover {
966
+ color: #818cf8;
967
+ text-decoration: underline;
968
+ }
969
+
970
+ .pixygon-auth-link:disabled {
971
+ color: #737373;
972
+ cursor: not-allowed;
973
+ }
974
+
975
+ .pixygon-auth-footer {
976
+ text-align: center;
977
+ margin-top: 1.5rem;
978
+ font-size: 0.875rem;
979
+ color: #a3a3a3;
980
+ }
981
+
982
+ .pixygon-auth-branding {
983
+ display: flex;
984
+ align-items: center;
985
+ justify-content: center;
986
+ gap: 0.5rem;
987
+ margin-top: 1.5rem;
988
+ font-size: 0.75rem;
989
+ color: #737373;
990
+ }
991
+
992
+ .pixygon-auth-spinner {
993
+ width: 20px;
994
+ height: 20px;
995
+ border: 2px solid transparent;
996
+ border-top-color: currentColor;
997
+ border-radius: 50%;
998
+ animation: pixygon-spin 0.8s linear infinite;
999
+ }
1000
+
1001
+ @keyframes pixygon-spin {
1002
+ to { transform: rotate(360deg); }
1003
+ }
1004
+
1005
+ .pixygon-auth-resend {
1006
+ text-align: center;
1007
+ font-size: 0.875rem;
1008
+ color: #a3a3a3;
1009
+ }
1010
+ ` }),
1011
+ /* @__PURE__ */ jsxs3("div", { className: "pixygon-auth-header", children: [
1012
+ /* @__PURE__ */ jsxs3(
1013
+ "svg",
1014
+ {
1015
+ className: "pixygon-auth-logo",
1016
+ viewBox: "0 0 100 100",
1017
+ fill: "none",
1018
+ xmlns: "http://www.w3.org/2000/svg",
1019
+ children: [
1020
+ /* @__PURE__ */ jsx3("circle", { cx: "50", cy: "50", r: "45", fill: "#6366f1" }),
1021
+ /* @__PURE__ */ jsx3(
1022
+ "path",
1023
+ {
1024
+ d: "M30 45L45 30L70 55L55 70L30 45Z",
1025
+ fill: "white",
1026
+ fillOpacity: "0.9"
1027
+ }
1028
+ ),
1029
+ /* @__PURE__ */ jsx3(
1030
+ "path",
1031
+ {
1032
+ d: "M35 55L50 70L45 75L30 60L35 55Z",
1033
+ fill: "white",
1034
+ fillOpacity: "0.7"
1035
+ }
1036
+ )
1037
+ ]
1038
+ }
1039
+ ),
1040
+ /* @__PURE__ */ jsx3("h1", { className: "pixygon-auth-title", children: "Verify Email" }),
1041
+ /* @__PURE__ */ jsx3("p", { className: "pixygon-auth-subtitle", children: "Enter the 6-digit code sent to your email" })
1042
+ ] }),
1043
+ /* @__PURE__ */ jsxs3("form", { className: "pixygon-auth-form", onSubmit: handleSubmit, children: [
1044
+ displayError && /* @__PURE__ */ jsx3("div", { className: "pixygon-auth-error", children: displayError }),
1045
+ resendSuccess && /* @__PURE__ */ jsx3("div", { className: "pixygon-auth-success", children: "Verification code sent! Check your email." }),
1046
+ /* @__PURE__ */ jsx3("div", { className: "pixygon-auth-code-container", children: code.map((digit, index) => /* @__PURE__ */ jsx3(
1047
+ "input",
1048
+ {
1049
+ ref: (el) => inputRefs.current[index] = el,
1050
+ className: `pixygon-auth-code-input ${displayError ? "error" : ""}`,
1051
+ type: "text",
1052
+ inputMode: "numeric",
1053
+ maxLength: 1,
1054
+ value: digit,
1055
+ onChange: (e) => handleChange(index, e.target.value),
1056
+ onKeyDown: (e) => handleKeyDown(index, e),
1057
+ onPaste: handlePaste,
1058
+ disabled: isLoading,
1059
+ "aria-label": `Digit ${index + 1}`
1060
+ },
1061
+ index
1062
+ )) }),
1063
+ /* @__PURE__ */ jsx3(
1064
+ "button",
1065
+ {
1066
+ type: "submit",
1067
+ className: "pixygon-auth-button",
1068
+ disabled: isLoading || code.some((d) => !d),
1069
+ children: isLoading ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
1070
+ /* @__PURE__ */ jsx3("div", { className: "pixygon-auth-spinner" }),
1071
+ "Verifying..."
1072
+ ] }) : "Verify Email"
1073
+ }
1074
+ ),
1075
+ /* @__PURE__ */ jsxs3("div", { className: "pixygon-auth-resend", children: [
1076
+ "Didn't receive the code?",
1077
+ " ",
1078
+ /* @__PURE__ */ jsx3(
1079
+ "button",
1080
+ {
1081
+ type: "button",
1082
+ className: "pixygon-auth-link",
1083
+ onClick: handleResend,
1084
+ disabled: resendCooldown > 0,
1085
+ children: resendCooldown > 0 ? `Resend in ${resendCooldown}s` : "Resend code"
1086
+ }
1087
+ )
1088
+ ] })
1089
+ ] }),
1090
+ onNavigateLogin && /* @__PURE__ */ jsxs3("div", { className: "pixygon-auth-footer", children: [
1091
+ "Wrong account?",
1092
+ " ",
1093
+ /* @__PURE__ */ jsx3(
1094
+ "button",
1095
+ {
1096
+ type: "button",
1097
+ className: "pixygon-auth-link",
1098
+ onClick: onNavigateLogin,
1099
+ children: "Sign in with a different account"
1100
+ }
1101
+ )
1102
+ ] }),
1103
+ showBranding && /* @__PURE__ */ jsx3("div", { className: "pixygon-auth-branding", children: "Secured by Pixygon Account" })
1104
+ ] });
1105
+ }
1106
+
1107
+ // src/components/ForgotPasswordForm.tsx
1108
+ import { useState as useState4, useCallback as useCallback4 } from "react";
1109
+ import { Fragment as Fragment4, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1110
+ function ForgotPasswordForm({
1111
+ onSuccess,
1112
+ onError,
1113
+ onNavigateLogin,
1114
+ showBranding = true,
1115
+ className = ""
1116
+ }) {
1117
+ const { forgotPassword, isLoading, error } = useAuth();
1118
+ const [email, setEmail] = useState4("");
1119
+ const [localError, setLocalError] = useState4(null);
1120
+ const [submitted, setSubmitted] = useState4(false);
1121
+ const handleSubmit = useCallback4(
1122
+ async (e) => {
1123
+ e.preventDefault();
1124
+ setLocalError(null);
1125
+ if (!email.trim()) {
1126
+ setLocalError("Please enter your email address");
1127
+ return;
1128
+ }
1129
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
1130
+ setLocalError("Please enter a valid email address");
1131
+ return;
1132
+ }
1133
+ try {
1134
+ await forgotPassword({ email: email.trim().toLowerCase() });
1135
+ setSubmitted(true);
1136
+ onSuccess?.();
1137
+ } catch (err) {
1138
+ const authError = err;
1139
+ onError?.(authError);
1140
+ }
1141
+ },
1142
+ [email, forgotPassword, onSuccess, onError]
1143
+ );
1144
+ const displayError = localError || error?.message;
1145
+ if (submitted) {
1146
+ return /* @__PURE__ */ jsxs4("div", { className: `pixygon-auth-container ${className}`, children: [
1147
+ /* @__PURE__ */ jsx4("style", { children: `
1148
+ .pixygon-auth-container {
1149
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1150
+ background: #0f0f0f;
1151
+ color: #ffffff;
1152
+ padding: 2rem;
1153
+ border-radius: 1rem;
1154
+ max-width: 400px;
1155
+ width: 100%;
1156
+ margin: 0 auto;
1157
+ }
1158
+
1159
+ .pixygon-auth-header {
1160
+ text-align: center;
1161
+ margin-bottom: 2rem;
1162
+ }
1163
+
1164
+ .pixygon-auth-success-icon {
1165
+ width: 64px;
1166
+ height: 64px;
1167
+ margin: 0 auto 1rem;
1168
+ display: block;
1169
+ }
1170
+
1171
+ .pixygon-auth-title {
1172
+ font-size: 1.5rem;
1173
+ font-weight: 600;
1174
+ margin: 0 0 0.5rem;
1175
+ }
1176
+
1177
+ .pixygon-auth-subtitle {
1178
+ font-size: 0.875rem;
1179
+ color: #a3a3a3;
1180
+ margin: 0;
1181
+ line-height: 1.5;
1182
+ }
1183
+
1184
+ .pixygon-auth-link {
1185
+ color: #6366f1;
1186
+ text-decoration: none;
1187
+ font-size: 0.875rem;
1188
+ cursor: pointer;
1189
+ background: none;
1190
+ border: none;
1191
+ padding: 0;
1192
+ font-family: inherit;
1193
+ }
1194
+
1195
+ .pixygon-auth-link:hover {
1196
+ color: #818cf8;
1197
+ text-decoration: underline;
1198
+ }
1199
+
1200
+ .pixygon-auth-footer {
1201
+ text-align: center;
1202
+ margin-top: 1.5rem;
1203
+ font-size: 0.875rem;
1204
+ color: #a3a3a3;
1205
+ }
1206
+
1207
+ .pixygon-auth-branding {
1208
+ display: flex;
1209
+ align-items: center;
1210
+ justify-content: center;
1211
+ gap: 0.5rem;
1212
+ margin-top: 1.5rem;
1213
+ font-size: 0.75rem;
1214
+ color: #737373;
1215
+ }
1216
+ ` }),
1217
+ /* @__PURE__ */ jsxs4("div", { className: "pixygon-auth-header", children: [
1218
+ /* @__PURE__ */ jsxs4(
1219
+ "svg",
1220
+ {
1221
+ className: "pixygon-auth-success-icon",
1222
+ viewBox: "0 0 100 100",
1223
+ fill: "none",
1224
+ xmlns: "http://www.w3.org/2000/svg",
1225
+ children: [
1226
+ /* @__PURE__ */ jsx4("circle", { cx: "50", cy: "50", r: "45", fill: "#22c55e" }),
1227
+ /* @__PURE__ */ jsx4(
1228
+ "path",
1229
+ {
1230
+ d: "M30 50L45 65L70 35",
1231
+ stroke: "white",
1232
+ strokeWidth: "6",
1233
+ strokeLinecap: "round",
1234
+ strokeLinejoin: "round"
1235
+ }
1236
+ )
1237
+ ]
1238
+ }
1239
+ ),
1240
+ /* @__PURE__ */ jsx4("h1", { className: "pixygon-auth-title", children: "Check Your Email" }),
1241
+ /* @__PURE__ */ jsxs4("p", { className: "pixygon-auth-subtitle", children: [
1242
+ "We've sent password reset instructions to",
1243
+ " ",
1244
+ /* @__PURE__ */ jsx4("strong", { children: email }),
1245
+ ". Please check your inbox."
1246
+ ] })
1247
+ ] }),
1248
+ onNavigateLogin && /* @__PURE__ */ jsx4("div", { className: "pixygon-auth-footer", children: /* @__PURE__ */ jsx4(
1249
+ "button",
1250
+ {
1251
+ type: "button",
1252
+ className: "pixygon-auth-link",
1253
+ onClick: onNavigateLogin,
1254
+ children: "Back to sign in"
1255
+ }
1256
+ ) }),
1257
+ showBranding && /* @__PURE__ */ jsx4("div", { className: "pixygon-auth-branding", children: "Secured by Pixygon Account" })
1258
+ ] });
1259
+ }
1260
+ return /* @__PURE__ */ jsxs4("div", { className: `pixygon-auth-container ${className}`, children: [
1261
+ /* @__PURE__ */ jsx4("style", { children: `
1262
+ .pixygon-auth-container {
1263
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1264
+ background: #0f0f0f;
1265
+ color: #ffffff;
1266
+ padding: 2rem;
1267
+ border-radius: 1rem;
1268
+ max-width: 400px;
1269
+ width: 100%;
1270
+ margin: 0 auto;
1271
+ }
1272
+
1273
+ .pixygon-auth-header {
1274
+ text-align: center;
1275
+ margin-bottom: 2rem;
1276
+ }
1277
+
1278
+ .pixygon-auth-logo {
1279
+ width: 64px;
1280
+ height: 64px;
1281
+ margin: 0 auto 1rem;
1282
+ display: block;
1283
+ }
1284
+
1285
+ .pixygon-auth-title {
1286
+ font-size: 1.5rem;
1287
+ font-weight: 600;
1288
+ margin: 0 0 0.5rem;
1289
+ }
1290
+
1291
+ .pixygon-auth-subtitle {
1292
+ font-size: 0.875rem;
1293
+ color: #a3a3a3;
1294
+ margin: 0;
1295
+ }
1296
+
1297
+ .pixygon-auth-form {
1298
+ display: flex;
1299
+ flex-direction: column;
1300
+ gap: 1rem;
1301
+ }
1302
+
1303
+ .pixygon-auth-input-group {
1304
+ display: flex;
1305
+ flex-direction: column;
1306
+ gap: 0.375rem;
1307
+ }
1308
+
1309
+ .pixygon-auth-label {
1310
+ font-size: 0.875rem;
1311
+ font-weight: 500;
1312
+ color: #a3a3a3;
1313
+ }
1314
+
1315
+ .pixygon-auth-input {
1316
+ background: #262626;
1317
+ border: 1px solid #404040;
1318
+ border-radius: 0.5rem;
1319
+ padding: 0.75rem 1rem;
1320
+ font-size: 1rem;
1321
+ color: #ffffff;
1322
+ outline: none;
1323
+ transition: border-color 0.2s, box-shadow 0.2s;
1324
+ }
1325
+
1326
+ .pixygon-auth-input:focus {
1327
+ border-color: #6366f1;
1328
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
1329
+ }
1330
+
1331
+ .pixygon-auth-input.error {
1332
+ border-color: #ef4444;
1333
+ }
1334
+
1335
+ .pixygon-auth-button {
1336
+ background: #6366f1;
1337
+ color: white;
1338
+ border: none;
1339
+ border-radius: 0.5rem;
1340
+ padding: 0.875rem 1.5rem;
1341
+ font-size: 1rem;
1342
+ font-weight: 600;
1343
+ cursor: pointer;
1344
+ transition: background 0.2s;
1345
+ display: flex;
1346
+ align-items: center;
1347
+ justify-content: center;
1348
+ gap: 0.5rem;
1349
+ margin-top: 0.5rem;
1350
+ }
1351
+
1352
+ .pixygon-auth-button:hover:not(:disabled) {
1353
+ background: #4f46e5;
1354
+ }
1355
+
1356
+ .pixygon-auth-button:disabled {
1357
+ opacity: 0.6;
1358
+ cursor: not-allowed;
1359
+ }
1360
+
1361
+ .pixygon-auth-error {
1362
+ background: rgba(239, 68, 68, 0.1);
1363
+ border: 1px solid #ef4444;
1364
+ border-radius: 0.5rem;
1365
+ padding: 0.75rem 1rem;
1366
+ color: #fca5a5;
1367
+ font-size: 0.875rem;
1368
+ }
1369
+
1370
+ .pixygon-auth-link {
1371
+ color: #6366f1;
1372
+ text-decoration: none;
1373
+ font-size: 0.875rem;
1374
+ cursor: pointer;
1375
+ background: none;
1376
+ border: none;
1377
+ padding: 0;
1378
+ font-family: inherit;
1379
+ }
1380
+
1381
+ .pixygon-auth-link:hover {
1382
+ color: #818cf8;
1383
+ text-decoration: underline;
1384
+ }
1385
+
1386
+ .pixygon-auth-footer {
1387
+ text-align: center;
1388
+ margin-top: 1.5rem;
1389
+ font-size: 0.875rem;
1390
+ color: #a3a3a3;
1391
+ }
1392
+
1393
+ .pixygon-auth-branding {
1394
+ display: flex;
1395
+ align-items: center;
1396
+ justify-content: center;
1397
+ gap: 0.5rem;
1398
+ margin-top: 1.5rem;
1399
+ font-size: 0.75rem;
1400
+ color: #737373;
1401
+ }
1402
+
1403
+ .pixygon-auth-spinner {
1404
+ width: 20px;
1405
+ height: 20px;
1406
+ border: 2px solid transparent;
1407
+ border-top-color: currentColor;
1408
+ border-radius: 50%;
1409
+ animation: pixygon-spin 0.8s linear infinite;
1410
+ }
1411
+
1412
+ @keyframes pixygon-spin {
1413
+ to { transform: rotate(360deg); }
1414
+ }
1415
+ ` }),
1416
+ /* @__PURE__ */ jsxs4("div", { className: "pixygon-auth-header", children: [
1417
+ /* @__PURE__ */ jsxs4(
1418
+ "svg",
1419
+ {
1420
+ className: "pixygon-auth-logo",
1421
+ viewBox: "0 0 100 100",
1422
+ fill: "none",
1423
+ xmlns: "http://www.w3.org/2000/svg",
1424
+ children: [
1425
+ /* @__PURE__ */ jsx4("circle", { cx: "50", cy: "50", r: "45", fill: "#6366f1" }),
1426
+ /* @__PURE__ */ jsx4(
1427
+ "path",
1428
+ {
1429
+ d: "M30 45L45 30L70 55L55 70L30 45Z",
1430
+ fill: "white",
1431
+ fillOpacity: "0.9"
1432
+ }
1433
+ ),
1434
+ /* @__PURE__ */ jsx4(
1435
+ "path",
1436
+ {
1437
+ d: "M35 55L50 70L45 75L30 60L35 55Z",
1438
+ fill: "white",
1439
+ fillOpacity: "0.7"
1440
+ }
1441
+ )
1442
+ ]
1443
+ }
1444
+ ),
1445
+ /* @__PURE__ */ jsx4("h1", { className: "pixygon-auth-title", children: "Reset Password" }),
1446
+ /* @__PURE__ */ jsx4("p", { className: "pixygon-auth-subtitle", children: "Enter your email to receive reset instructions" })
1447
+ ] }),
1448
+ /* @__PURE__ */ jsxs4("form", { className: "pixygon-auth-form", onSubmit: handleSubmit, children: [
1449
+ displayError && /* @__PURE__ */ jsx4("div", { className: "pixygon-auth-error", children: displayError }),
1450
+ /* @__PURE__ */ jsxs4("div", { className: "pixygon-auth-input-group", children: [
1451
+ /* @__PURE__ */ jsx4("label", { className: "pixygon-auth-label", htmlFor: "pixygon-forgot-email", children: "Email" }),
1452
+ /* @__PURE__ */ jsx4(
1453
+ "input",
1454
+ {
1455
+ id: "pixygon-forgot-email",
1456
+ className: `pixygon-auth-input ${displayError ? "error" : ""}`,
1457
+ type: "email",
1458
+ value: email,
1459
+ onChange: (e) => setEmail(e.target.value),
1460
+ placeholder: "Enter your email",
1461
+ autoComplete: "email",
1462
+ disabled: isLoading
1463
+ }
1464
+ )
1465
+ ] }),
1466
+ /* @__PURE__ */ jsx4(
1467
+ "button",
1468
+ {
1469
+ type: "submit",
1470
+ className: "pixygon-auth-button",
1471
+ disabled: isLoading,
1472
+ children: isLoading ? /* @__PURE__ */ jsxs4(Fragment4, { children: [
1473
+ /* @__PURE__ */ jsx4("div", { className: "pixygon-auth-spinner" }),
1474
+ "Sending..."
1475
+ ] }) : "Send Reset Link"
1476
+ }
1477
+ )
1478
+ ] }),
1479
+ onNavigateLogin && /* @__PURE__ */ jsxs4("div", { className: "pixygon-auth-footer", children: [
1480
+ "Remember your password?",
1481
+ " ",
1482
+ /* @__PURE__ */ jsx4(
1483
+ "button",
1484
+ {
1485
+ type: "button",
1486
+ className: "pixygon-auth-link",
1487
+ onClick: onNavigateLogin,
1488
+ children: "Sign in"
1489
+ }
1490
+ )
1491
+ ] }),
1492
+ showBranding && /* @__PURE__ */ jsx4("div", { className: "pixygon-auth-branding", children: "Secured by Pixygon Account" })
1493
+ ] });
1494
+ }
1495
+
1496
+ // src/components/PixygonAuth.tsx
1497
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1498
+ function PixygonAuth({
1499
+ mode: initialMode,
1500
+ onSuccess,
1501
+ onError,
1502
+ onModeChange,
1503
+ userName: initialUserName,
1504
+ showBranding = true,
1505
+ theme = "dark",
1506
+ className = ""
1507
+ }) {
1508
+ const [mode, setMode] = useState5(initialMode);
1509
+ const [userName, setUserName] = useState5(initialUserName || "");
1510
+ useEffect2(() => {
1511
+ setMode(initialMode);
1512
+ }, [initialMode]);
1513
+ const handleModeChange = useCallback5(
1514
+ (newMode) => {
1515
+ setMode(newMode);
1516
+ onModeChange?.(newMode);
1517
+ },
1518
+ [onModeChange]
1519
+ );
1520
+ const handleLoginSuccess = useCallback5(
1521
+ (user) => {
1522
+ if (!user.isVerified) {
1523
+ setUserName(user.userName);
1524
+ handleModeChange("verify");
1525
+ } else {
1526
+ onSuccess?.(user);
1527
+ }
1528
+ },
1529
+ [handleModeChange, onSuccess]
1530
+ );
1531
+ const handleRegisterSuccess = useCallback5(
1532
+ (user) => {
1533
+ setUserName(user.userName);
1534
+ handleModeChange("verify");
1535
+ },
1536
+ [handleModeChange]
1537
+ );
1538
+ const handleVerifySuccess = useCallback5(
1539
+ (user) => {
1540
+ onSuccess?.(user);
1541
+ },
1542
+ [onSuccess]
1543
+ );
1544
+ const handleForgotPasswordSuccess = useCallback5(() => {
1545
+ }, []);
1546
+ const handleError = useCallback5(
1547
+ (error) => {
1548
+ onError?.(error);
1549
+ },
1550
+ [onError]
1551
+ );
1552
+ const containerClassName = `pixygon-auth-wrapper ${theme === "light" ? "light" : ""} ${className}`;
1553
+ return /* @__PURE__ */ jsxs5("div", { className: containerClassName, children: [
1554
+ /* @__PURE__ */ jsx5("style", { children: `
1555
+ .pixygon-auth-wrapper {
1556
+ width: 100%;
1557
+ }
1558
+
1559
+ .pixygon-auth-wrapper.light .pixygon-auth-container {
1560
+ background: #ffffff;
1561
+ color: #0f0f0f;
1562
+ }
1563
+
1564
+ .pixygon-auth-wrapper.light .pixygon-auth-input {
1565
+ background: #f5f5f5;
1566
+ border-color: #e5e5e5;
1567
+ color: #0f0f0f;
1568
+ }
1569
+
1570
+ .pixygon-auth-wrapper.light .pixygon-auth-input:focus {
1571
+ border-color: #6366f1;
1572
+ }
1573
+
1574
+ .pixygon-auth-wrapper.light .pixygon-auth-label {
1575
+ color: #525252;
1576
+ }
1577
+
1578
+ .pixygon-auth-wrapper.light .pixygon-auth-subtitle {
1579
+ color: #525252;
1580
+ }
1581
+
1582
+ .pixygon-auth-wrapper.light .pixygon-auth-footer {
1583
+ color: #525252;
1584
+ }
1585
+
1586
+ .pixygon-auth-wrapper.light .pixygon-auth-branding {
1587
+ color: #a3a3a3;
1588
+ }
1589
+ ` }),
1590
+ mode === "login" && /* @__PURE__ */ jsx5(
1591
+ LoginForm,
1592
+ {
1593
+ onSuccess: handleLoginSuccess,
1594
+ onError: handleError,
1595
+ onNavigateRegister: () => handleModeChange("register"),
1596
+ onNavigateForgotPassword: () => handleModeChange("forgot-password"),
1597
+ showBranding
1598
+ }
1599
+ ),
1600
+ mode === "register" && /* @__PURE__ */ jsx5(
1601
+ RegisterForm,
1602
+ {
1603
+ onSuccess: handleRegisterSuccess,
1604
+ onError: handleError,
1605
+ onNavigateLogin: () => handleModeChange("login"),
1606
+ showBranding
1607
+ }
1608
+ ),
1609
+ mode === "verify" && /* @__PURE__ */ jsx5(
1610
+ VerifyForm,
1611
+ {
1612
+ userName,
1613
+ onSuccess: handleVerifySuccess,
1614
+ onError: handleError,
1615
+ onNavigateLogin: () => handleModeChange("login"),
1616
+ showBranding
1617
+ }
1618
+ ),
1619
+ mode === "forgot-password" && /* @__PURE__ */ jsx5(
1620
+ ForgotPasswordForm,
1621
+ {
1622
+ onSuccess: handleForgotPasswordSuccess,
1623
+ onError: handleError,
1624
+ onNavigateLogin: () => handleModeChange("login"),
1625
+ showBranding
1626
+ }
1627
+ ),
1628
+ mode === "recover-password" && // Recovery form would go here - handled via email link typically
1629
+ /* @__PURE__ */ jsx5(
1630
+ ForgotPasswordForm,
1631
+ {
1632
+ onSuccess: handleForgotPasswordSuccess,
1633
+ onError: handleError,
1634
+ onNavigateLogin: () => handleModeChange("login"),
1635
+ showBranding
1636
+ }
1637
+ )
1638
+ ] });
1639
+ }
1640
+ export {
1641
+ ForgotPasswordForm,
1642
+ LoginForm,
1643
+ PixygonAuth,
1644
+ RegisterForm,
1645
+ VerifyForm
1646
+ };