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