@authon/js 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +72 -26
- package/dist/index.mjs +72 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -100,6 +100,7 @@ var ModalRenderer = class {
|
|
|
100
100
|
onProviderClick;
|
|
101
101
|
onEmailSubmit;
|
|
102
102
|
onClose;
|
|
103
|
+
escHandler = null;
|
|
103
104
|
constructor(options) {
|
|
104
105
|
this.mode = options.mode;
|
|
105
106
|
this.theme = options.theme || "auto";
|
|
@@ -118,10 +119,18 @@ var ModalRenderer = class {
|
|
|
118
119
|
this.branding = { ...DEFAULT_BRANDING, ...branding };
|
|
119
120
|
}
|
|
120
121
|
open(view = "signIn") {
|
|
121
|
-
this.
|
|
122
|
-
|
|
122
|
+
if (this.shadowRoot && this.hostElement) {
|
|
123
|
+
this.shadowRoot.innerHTML = this.buildHTML(view);
|
|
124
|
+
this.attachEvents(view);
|
|
125
|
+
} else {
|
|
126
|
+
this.render(view);
|
|
127
|
+
}
|
|
123
128
|
}
|
|
124
129
|
close() {
|
|
130
|
+
if (this.escHandler) {
|
|
131
|
+
document.removeEventListener("keydown", this.escHandler);
|
|
132
|
+
this.escHandler = null;
|
|
133
|
+
}
|
|
125
134
|
if (this.hostElement) {
|
|
126
135
|
this.hostElement.remove();
|
|
127
136
|
this.hostElement = null;
|
|
@@ -143,6 +152,21 @@ var ModalRenderer = class {
|
|
|
143
152
|
errorEl.appendChild(errDiv);
|
|
144
153
|
}
|
|
145
154
|
}
|
|
155
|
+
showBanner(message, type = "error") {
|
|
156
|
+
if (!this.shadowRoot) return;
|
|
157
|
+
this.clearBanner();
|
|
158
|
+
const container = this.shadowRoot.querySelector(".modal-container");
|
|
159
|
+
if (!container) return;
|
|
160
|
+
const banner = document.createElement("div");
|
|
161
|
+
banner.id = "authon-banner";
|
|
162
|
+
banner.className = type === "warning" ? "banner-warning" : "error-msg";
|
|
163
|
+
banner.textContent = message;
|
|
164
|
+
container.insertBefore(banner, container.firstChild);
|
|
165
|
+
}
|
|
166
|
+
clearBanner() {
|
|
167
|
+
if (!this.shadowRoot) return;
|
|
168
|
+
this.shadowRoot.getElementById("authon-banner")?.remove();
|
|
169
|
+
}
|
|
146
170
|
clearError() {
|
|
147
171
|
if (!this.shadowRoot) return;
|
|
148
172
|
this.shadowRoot.getElementById("authon-error-msg")?.remove();
|
|
@@ -198,8 +222,8 @@ var ModalRenderer = class {
|
|
|
198
222
|
}).join("");
|
|
199
223
|
const divider = b.showDivider !== false && b.showEmailPassword !== false ? `<div class="divider"><span>or</span></div>` : "";
|
|
200
224
|
const emailForm = b.showEmailPassword !== false ? `<form class="email-form" id="email-form">
|
|
201
|
-
<input type="email" placeholder="Email address" name="email" required class="input" />
|
|
202
|
-
<input type="password" placeholder="Password" name="password" required class="input" />
|
|
225
|
+
<input type="email" placeholder="Email address" name="email" required class="input" autocomplete="email" />
|
|
226
|
+
<input type="password" placeholder="Password" name="password" required class="input" autocomplete="${isSignUp ? "new-password" : "current-password"}" />
|
|
203
227
|
<button type="submit" class="submit-btn">${isSignUp ? "Sign up" : "Sign in"}</button>
|
|
204
228
|
</form>` : "";
|
|
205
229
|
const footer = b.termsUrl || b.privacyUrl ? `<div class="footer">
|
|
@@ -320,6 +344,13 @@ var ModalRenderer = class {
|
|
|
320
344
|
font-size: 13px; color: #ef4444; text-align: center;
|
|
321
345
|
animation: fadeIn 0.15s ease;
|
|
322
346
|
}
|
|
347
|
+
.banner-warning {
|
|
348
|
+
margin-bottom: 16px; padding: 10px 14px;
|
|
349
|
+
background: rgba(245,158,11,0.1); border: 1px solid rgba(245,158,11,0.3);
|
|
350
|
+
border-radius: calc(var(--authon-radius) * 0.33);
|
|
351
|
+
font-size: 13px; color: #f59e0b; text-align: center;
|
|
352
|
+
animation: fadeIn 0.15s ease;
|
|
353
|
+
}
|
|
323
354
|
.switch-view { text-align: center; margin-top: 16px; font-size: 13px; color: var(--authon-muted); }
|
|
324
355
|
.switch-view a { color: var(--authon-primary-start); text-decoration: none; font-weight: 500; }
|
|
325
356
|
.switch-view a:hover { text-decoration: underline; }
|
|
@@ -401,14 +432,15 @@ var ModalRenderer = class {
|
|
|
401
432
|
if (backdrop) {
|
|
402
433
|
backdrop.addEventListener("click", () => this.onClose());
|
|
403
434
|
}
|
|
435
|
+
if (this.escHandler) {
|
|
436
|
+
document.removeEventListener("keydown", this.escHandler);
|
|
437
|
+
this.escHandler = null;
|
|
438
|
+
}
|
|
404
439
|
if (this.mode === "popup") {
|
|
405
|
-
|
|
406
|
-
if (e.key === "Escape")
|
|
407
|
-
this.onClose();
|
|
408
|
-
document.removeEventListener("keydown", handler);
|
|
409
|
-
}
|
|
440
|
+
this.escHandler = (e) => {
|
|
441
|
+
if (e.key === "Escape") this.onClose();
|
|
410
442
|
};
|
|
411
|
-
document.addEventListener("keydown",
|
|
443
|
+
document.addEventListener("keydown", this.escHandler);
|
|
412
444
|
}
|
|
413
445
|
}
|
|
414
446
|
};
|
|
@@ -632,39 +664,51 @@ var Authon = class {
|
|
|
632
664
|
"authon-oauth",
|
|
633
665
|
`width=${width},height=${height},left=${left},top=${top},toolbar=no,menubar=no`
|
|
634
666
|
);
|
|
667
|
+
if (!popup || popup.closed) {
|
|
668
|
+
this.modal?.hideLoading();
|
|
669
|
+
this.modal?.showBanner(
|
|
670
|
+
"Pop-up blocked. Please allow pop-ups for this site and try again.",
|
|
671
|
+
"warning"
|
|
672
|
+
);
|
|
673
|
+
this.emit("error", new Error("Popup was blocked by the browser"));
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
635
676
|
let callbackReceived = false;
|
|
636
677
|
let cleaned = false;
|
|
637
678
|
const cleanup = () => {
|
|
638
679
|
if (cleaned) return;
|
|
639
680
|
cleaned = true;
|
|
640
681
|
window.removeEventListener("message", handler);
|
|
641
|
-
|
|
682
|
+
if (pollTimer) clearInterval(pollTimer);
|
|
642
683
|
if (maxTimer) clearTimeout(maxTimer);
|
|
643
684
|
};
|
|
644
|
-
const
|
|
685
|
+
const pollTimer = setInterval(() => {
|
|
645
686
|
if (callbackReceived || cleaned) return;
|
|
646
|
-
|
|
647
|
-
if (
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
687
|
+
try {
|
|
688
|
+
if (popup.closed) {
|
|
689
|
+
setTimeout(() => {
|
|
690
|
+
if (callbackReceived || cleaned) return;
|
|
691
|
+
cleanup();
|
|
692
|
+
this.modal?.hideLoading();
|
|
693
|
+
}, 500);
|
|
694
|
+
clearInterval(pollTimer);
|
|
695
|
+
}
|
|
696
|
+
} catch {
|
|
697
|
+
}
|
|
698
|
+
}, 500);
|
|
653
699
|
const maxTimer = setTimeout(() => {
|
|
654
700
|
if (callbackReceived || cleaned) return;
|
|
655
701
|
cleanup();
|
|
656
702
|
this.modal?.hideLoading();
|
|
657
703
|
}, 18e4);
|
|
658
|
-
if (!popup) {
|
|
659
|
-
cleanup();
|
|
660
|
-
this.modal?.hideLoading();
|
|
661
|
-
this.emit("error", new Error("Popup was blocked by the browser"));
|
|
662
|
-
return;
|
|
663
|
-
}
|
|
664
704
|
const handler = async (e) => {
|
|
665
705
|
if (e.data?.type !== "authon-oauth-callback") return;
|
|
666
706
|
callbackReceived = true;
|
|
667
707
|
cleanup();
|
|
708
|
+
try {
|
|
709
|
+
if (!popup.closed) popup.close();
|
|
710
|
+
} catch {
|
|
711
|
+
}
|
|
668
712
|
try {
|
|
669
713
|
const tokens = await this.apiPost("/v1/auth/oauth/callback", {
|
|
670
714
|
code: e.data.code,
|
|
@@ -676,7 +720,9 @@ var Authon = class {
|
|
|
676
720
|
this.emit("signedIn", tokens.user);
|
|
677
721
|
} catch (err) {
|
|
678
722
|
this.modal?.hideLoading();
|
|
679
|
-
|
|
723
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
724
|
+
this.modal?.showError(msg.includes("500") ? "Authentication failed. Please try again." : msg);
|
|
725
|
+
this.emit("error", err instanceof Error ? err : new Error(msg));
|
|
680
726
|
}
|
|
681
727
|
};
|
|
682
728
|
window.addEventListener("message", handler);
|
package/dist/index.mjs
CHANGED
|
@@ -73,6 +73,7 @@ var ModalRenderer = class {
|
|
|
73
73
|
onProviderClick;
|
|
74
74
|
onEmailSubmit;
|
|
75
75
|
onClose;
|
|
76
|
+
escHandler = null;
|
|
76
77
|
constructor(options) {
|
|
77
78
|
this.mode = options.mode;
|
|
78
79
|
this.theme = options.theme || "auto";
|
|
@@ -91,10 +92,18 @@ var ModalRenderer = class {
|
|
|
91
92
|
this.branding = { ...DEFAULT_BRANDING, ...branding };
|
|
92
93
|
}
|
|
93
94
|
open(view = "signIn") {
|
|
94
|
-
this.
|
|
95
|
-
|
|
95
|
+
if (this.shadowRoot && this.hostElement) {
|
|
96
|
+
this.shadowRoot.innerHTML = this.buildHTML(view);
|
|
97
|
+
this.attachEvents(view);
|
|
98
|
+
} else {
|
|
99
|
+
this.render(view);
|
|
100
|
+
}
|
|
96
101
|
}
|
|
97
102
|
close() {
|
|
103
|
+
if (this.escHandler) {
|
|
104
|
+
document.removeEventListener("keydown", this.escHandler);
|
|
105
|
+
this.escHandler = null;
|
|
106
|
+
}
|
|
98
107
|
if (this.hostElement) {
|
|
99
108
|
this.hostElement.remove();
|
|
100
109
|
this.hostElement = null;
|
|
@@ -116,6 +125,21 @@ var ModalRenderer = class {
|
|
|
116
125
|
errorEl.appendChild(errDiv);
|
|
117
126
|
}
|
|
118
127
|
}
|
|
128
|
+
showBanner(message, type = "error") {
|
|
129
|
+
if (!this.shadowRoot) return;
|
|
130
|
+
this.clearBanner();
|
|
131
|
+
const container = this.shadowRoot.querySelector(".modal-container");
|
|
132
|
+
if (!container) return;
|
|
133
|
+
const banner = document.createElement("div");
|
|
134
|
+
banner.id = "authon-banner";
|
|
135
|
+
banner.className = type === "warning" ? "banner-warning" : "error-msg";
|
|
136
|
+
banner.textContent = message;
|
|
137
|
+
container.insertBefore(banner, container.firstChild);
|
|
138
|
+
}
|
|
139
|
+
clearBanner() {
|
|
140
|
+
if (!this.shadowRoot) return;
|
|
141
|
+
this.shadowRoot.getElementById("authon-banner")?.remove();
|
|
142
|
+
}
|
|
119
143
|
clearError() {
|
|
120
144
|
if (!this.shadowRoot) return;
|
|
121
145
|
this.shadowRoot.getElementById("authon-error-msg")?.remove();
|
|
@@ -171,8 +195,8 @@ var ModalRenderer = class {
|
|
|
171
195
|
}).join("");
|
|
172
196
|
const divider = b.showDivider !== false && b.showEmailPassword !== false ? `<div class="divider"><span>or</span></div>` : "";
|
|
173
197
|
const emailForm = b.showEmailPassword !== false ? `<form class="email-form" id="email-form">
|
|
174
|
-
<input type="email" placeholder="Email address" name="email" required class="input" />
|
|
175
|
-
<input type="password" placeholder="Password" name="password" required class="input" />
|
|
198
|
+
<input type="email" placeholder="Email address" name="email" required class="input" autocomplete="email" />
|
|
199
|
+
<input type="password" placeholder="Password" name="password" required class="input" autocomplete="${isSignUp ? "new-password" : "current-password"}" />
|
|
176
200
|
<button type="submit" class="submit-btn">${isSignUp ? "Sign up" : "Sign in"}</button>
|
|
177
201
|
</form>` : "";
|
|
178
202
|
const footer = b.termsUrl || b.privacyUrl ? `<div class="footer">
|
|
@@ -293,6 +317,13 @@ var ModalRenderer = class {
|
|
|
293
317
|
font-size: 13px; color: #ef4444; text-align: center;
|
|
294
318
|
animation: fadeIn 0.15s ease;
|
|
295
319
|
}
|
|
320
|
+
.banner-warning {
|
|
321
|
+
margin-bottom: 16px; padding: 10px 14px;
|
|
322
|
+
background: rgba(245,158,11,0.1); border: 1px solid rgba(245,158,11,0.3);
|
|
323
|
+
border-radius: calc(var(--authon-radius) * 0.33);
|
|
324
|
+
font-size: 13px; color: #f59e0b; text-align: center;
|
|
325
|
+
animation: fadeIn 0.15s ease;
|
|
326
|
+
}
|
|
296
327
|
.switch-view { text-align: center; margin-top: 16px; font-size: 13px; color: var(--authon-muted); }
|
|
297
328
|
.switch-view a { color: var(--authon-primary-start); text-decoration: none; font-weight: 500; }
|
|
298
329
|
.switch-view a:hover { text-decoration: underline; }
|
|
@@ -374,14 +405,15 @@ var ModalRenderer = class {
|
|
|
374
405
|
if (backdrop) {
|
|
375
406
|
backdrop.addEventListener("click", () => this.onClose());
|
|
376
407
|
}
|
|
408
|
+
if (this.escHandler) {
|
|
409
|
+
document.removeEventListener("keydown", this.escHandler);
|
|
410
|
+
this.escHandler = null;
|
|
411
|
+
}
|
|
377
412
|
if (this.mode === "popup") {
|
|
378
|
-
|
|
379
|
-
if (e.key === "Escape")
|
|
380
|
-
this.onClose();
|
|
381
|
-
document.removeEventListener("keydown", handler);
|
|
382
|
-
}
|
|
413
|
+
this.escHandler = (e) => {
|
|
414
|
+
if (e.key === "Escape") this.onClose();
|
|
383
415
|
};
|
|
384
|
-
document.addEventListener("keydown",
|
|
416
|
+
document.addEventListener("keydown", this.escHandler);
|
|
385
417
|
}
|
|
386
418
|
}
|
|
387
419
|
};
|
|
@@ -605,39 +637,51 @@ var Authon = class {
|
|
|
605
637
|
"authon-oauth",
|
|
606
638
|
`width=${width},height=${height},left=${left},top=${top},toolbar=no,menubar=no`
|
|
607
639
|
);
|
|
640
|
+
if (!popup || popup.closed) {
|
|
641
|
+
this.modal?.hideLoading();
|
|
642
|
+
this.modal?.showBanner(
|
|
643
|
+
"Pop-up blocked. Please allow pop-ups for this site and try again.",
|
|
644
|
+
"warning"
|
|
645
|
+
);
|
|
646
|
+
this.emit("error", new Error("Popup was blocked by the browser"));
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
608
649
|
let callbackReceived = false;
|
|
609
650
|
let cleaned = false;
|
|
610
651
|
const cleanup = () => {
|
|
611
652
|
if (cleaned) return;
|
|
612
653
|
cleaned = true;
|
|
613
654
|
window.removeEventListener("message", handler);
|
|
614
|
-
|
|
655
|
+
if (pollTimer) clearInterval(pollTimer);
|
|
615
656
|
if (maxTimer) clearTimeout(maxTimer);
|
|
616
657
|
};
|
|
617
|
-
const
|
|
658
|
+
const pollTimer = setInterval(() => {
|
|
618
659
|
if (callbackReceived || cleaned) return;
|
|
619
|
-
|
|
620
|
-
if (
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
660
|
+
try {
|
|
661
|
+
if (popup.closed) {
|
|
662
|
+
setTimeout(() => {
|
|
663
|
+
if (callbackReceived || cleaned) return;
|
|
664
|
+
cleanup();
|
|
665
|
+
this.modal?.hideLoading();
|
|
666
|
+
}, 500);
|
|
667
|
+
clearInterval(pollTimer);
|
|
668
|
+
}
|
|
669
|
+
} catch {
|
|
670
|
+
}
|
|
671
|
+
}, 500);
|
|
626
672
|
const maxTimer = setTimeout(() => {
|
|
627
673
|
if (callbackReceived || cleaned) return;
|
|
628
674
|
cleanup();
|
|
629
675
|
this.modal?.hideLoading();
|
|
630
676
|
}, 18e4);
|
|
631
|
-
if (!popup) {
|
|
632
|
-
cleanup();
|
|
633
|
-
this.modal?.hideLoading();
|
|
634
|
-
this.emit("error", new Error("Popup was blocked by the browser"));
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
677
|
const handler = async (e) => {
|
|
638
678
|
if (e.data?.type !== "authon-oauth-callback") return;
|
|
639
679
|
callbackReceived = true;
|
|
640
680
|
cleanup();
|
|
681
|
+
try {
|
|
682
|
+
if (!popup.closed) popup.close();
|
|
683
|
+
} catch {
|
|
684
|
+
}
|
|
641
685
|
try {
|
|
642
686
|
const tokens = await this.apiPost("/v1/auth/oauth/callback", {
|
|
643
687
|
code: e.data.code,
|
|
@@ -649,7 +693,9 @@ var Authon = class {
|
|
|
649
693
|
this.emit("signedIn", tokens.user);
|
|
650
694
|
} catch (err) {
|
|
651
695
|
this.modal?.hideLoading();
|
|
652
|
-
|
|
696
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
697
|
+
this.modal?.showError(msg.includes("500") ? "Authentication failed. Please try again." : msg);
|
|
698
|
+
this.emit("error", err instanceof Error ? err : new Error(msg));
|
|
653
699
|
}
|
|
654
700
|
};
|
|
655
701
|
window.addEventListener("message", handler);
|