(function () { "use strict"; const style = document.createElement("style"); style.setAttribute("data-paperq-auth-styles", ""); style.textContent = `.auth-dialog { --paperq-auth-text: #000000; --paperq-auth-muted: #8a8c93; --paperq-auth-panel: #ffffff; --paperq-auth-line: rgba(206, 206, 214, 0.5); --paperq-auth-primary: #cdfa85; --paperq-auth-secondary: #f1f2f4; --paperq-auth-danger: #f75555; --paperq-auth-shadow: 0 0 13.9px 1px rgba(21, 21, 20, 0.2); --paperq-auth-input-shadow: 0 0 6.5px 1px rgba(21, 21, 20, 0.08); --paperq-auth-radius-window: 20px; --paperq-auth-radius-input: 12px; --paperq-auth-radius-button: 8px; --paperq-auth-font: "Golos Text", Inter, Arial, sans-serif; width: 300px; max-width: calc(100vw - 24px); border: 0; padding: 0; background: transparent; color: var(--paperq-auth-text); font-family: var(--paperq-auth-font); overflow: visible; } .auth-dialog, .auth-dialog *, .auth-dialog *::before, .auth-dialog *::after { box-sizing: border-box; } .auth-dialog button, .auth-dialog input { appearance: none; min-width: 0; margin: 0; font: inherit; letter-spacing: 0; } .auth-dialog button { cursor: pointer; } .auth-dialog::backdrop { background: rgba(0, 0, 0, 0.42); } .auth-dialog__panel { position: relative; display: flex; width: 100%; flex-direction: column; align-items: stretch; gap: 10px; border: 0; border-radius: var(--paperq-auth-radius-window); background: var(--paperq-auth-panel); box-shadow: var(--paperq-auth-shadow); padding: 24px 16px 16px; } .auth-dialog--forced .auth-dialog__close, .auth-dialog--forced [data-auth-later] { display: none; } .auth-step { display: flex; width: 100%; flex-direction: column; align-items: stretch; gap: 10px; } .auth-step[hidden] { display: none; } .auth-dialog h2 { width: 100%; margin: 0; padding: 0 22px; color: var(--paperq-auth-text); font-size: 24px; font-weight: 600; line-height: 1; text-align: center; } .auth-dialog p { width: 100%; margin: 0; color: var(--paperq-auth-text); font-size: 12px; font-weight: 500; line-height: 1.3; text-align: center; } .auth-dialog label { display: flex; width: 100%; flex-direction: column; gap: 0; margin: 0; color: transparent; font-size: 0; line-height: 0; } .auth-step input { display: flex; width: 100%; height: 45px; align-items: center; border: 1px solid var(--paperq-auth-line); border-radius: var(--paperq-auth-radius-input); background: var(--paperq-auth-panel); box-shadow: var(--paperq-auth-input-shadow); color: var(--paperq-auth-text); font-size: 12px; font-weight: 400; line-height: 1.5; outline: 0; padding: 8px 8px 8px 16px; } .auth-step input::placeholder { color: var(--paperq-auth-muted); opacity: 1; } .auth-step input:focus { border-color: rgba(206, 206, 214, 0.9); box-shadow: var(--paperq-auth-input-shadow), 0 0 0 2px rgba(205, 250, 133, 0.22); } .auth-step input[aria-invalid="true"], .auth-step input.is-error { border-color: var(--paperq-auth-danger); box-shadow: 0 0 6.5px 1px rgba(247, 85, 85, 0.12); } .auth-dialog strong { font-weight: 500; } .otp-demo { display: none; } .form-error { min-height: 13px; margin: -4px 0 0; color: var(--paperq-auth-danger); font-size: 10px; font-weight: 400; line-height: 1.3; text-align: left; } .auth-dialog__actions { display: flex; width: 100%; align-items: center; gap: 8px; margin-top: 0; } .auth-dialog .primary-button, .auth-dialog .secondary-button { display: inline-flex; height: 40px; flex: 1 1 0; align-items: center; justify-content: center; border: 0; border-radius: var(--paperq-auth-radius-button); color: var(--paperq-auth-text); font-size: 12px; font-weight: 500; line-height: 1; padding: 10px 12px; text-align: center; text-decoration: none; white-space: nowrap; transition: background 140ms ease, color 140ms ease, opacity 140ms ease, transform 140ms ease; } .auth-dialog .primary-button { background: var(--paperq-auth-primary); } .auth-dialog .secondary-button { background: var(--paperq-auth-secondary); } .auth-dialog .primary-button:hover, .auth-dialog .secondary-button:hover { transform: translateY(-1px); } .auth-dialog .primary-button:active, .auth-dialog .secondary-button:active { transform: translateY(0); } .auth-dialog .icon-button.auth-dialog__close { position: absolute; top: 10px; right: 10px; display: inline-flex; width: 24px; height: 24px; align-items: center; justify-content: center; border: 0; border-radius: 999px; background: transparent; box-shadow: none; color: #a9abb2; padding: 0; } .auth-dialog .icon-button.auth-dialog__close span { display: block; font-size: 24px; font-weight: 300; line-height: 1; transform: translateY(-1px); } .auth-dialog .icon-button.auth-dialog__close:hover { background: rgba(0, 0, 0, 0.04); color: var(--paperq-auth-muted); } .auth-dialog [disabled] { cursor: default; opacity: 0.7; transform: none; } @media (max-width: 360px) { .auth-dialog { width: calc(100vw - 24px); } }`; document.head.appendChild(style); class AuthPopup { constructor(options = {}) { this.currentEmail = options.initialEmail || ""; this.onOtpRequested = options.onOtpRequested || noop; this.onAuthenticated = options.onAuthenticated || noop; this.onClose = options.onClose || noop; this.forced = false; this.step = "email"; this.pendingEmail = ""; this.inFlight = false; this.els = { dialog: document.querySelector("[data-auth-dialog]"), form: document.querySelector("[data-auth-form]"), close: document.querySelector("[data-auth-close]"), later: document.querySelector("[data-auth-later]"), title: document.querySelector("[data-auth-title]"), copy: document.querySelector("[data-auth-copy]"), emailStep: document.querySelector('[data-auth-step="email"]'), otpStep: document.querySelector('[data-auth-step="otp"]'), emailInput: document.querySelector("[data-email-input]"), otpInput: document.querySelector("[data-otp-input]"), otpEmail: document.querySelector("[data-otp-email]"), emailError: document.querySelector("[data-email-error]"), otpError: document.querySelector("[data-otp-error]"), changeEmail: document.querySelector("[data-change-email]"), }; this.bindEvents(); } bindEvents() { this.els.form.addEventListener("submit", (event) => { event.preventDefault(); this.submitCurrentStep(); }); this.els.close.addEventListener("click", () => this.close()); this.els.later.addEventListener("click", () => this.close()); this.els.changeEmail.addEventListener("click", () => this.showEmailStep()); this.els.dialog.addEventListener("cancel", (event) => { if (this.forced) { event.preventDefault(); } }); this.els.otpInput.addEventListener("input", () => { this.els.otpInput.value = this.els.otpInput.value.replace(/\D/g, "").slice(0, 6); this.els.otpError.textContent = ""; }); this.els.emailInput.addEventListener("input", () => { this.els.emailError.textContent = ""; }); } open(options = {}) { this.forced = Boolean(options.required); this.pendingEmail = ""; this.currentEmail = options.email || this.currentEmail || ""; this.showEmailStep(); this.els.dialog.classList.toggle("auth-dialog--forced", this.forced); this.els.close.hidden = this.forced; this.els.later.hidden = this.forced; this.els.title.textContent = options.title || (this.forced ? "Войдите в Paper Q" : "Войти в Paper Q"); this.els.copy.textContent = options.copy || (this.forced ? "После трех вопросов нужен email. Мы отправим одноразовый код, он будет действителен 5 минут." : "Укажите email. Если аккаунта еще нет, он будет создан после подтверждения одноразового кода."); if (typeof this.els.dialog.showModal === "function" && !this.els.dialog.open) { this.els.dialog.showModal(); } } close() { if (this.forced) return false; this.forceClose(); return true; } forceClose() { this.forced = false; this.els.dialog.classList.remove("auth-dialog--forced"); this.els.close.hidden = false; this.els.later.hidden = false; if (this.els.dialog.open) { this.els.dialog.close(); } this.onClose(); } setEmail(email) { this.currentEmail = String(email || "").trim(); } showEmailStep() { this.step = "email"; this.els.emailStep.hidden = false; this.els.otpStep.hidden = true; this.els.emailInput.value = this.pendingEmail || this.currentEmail || ""; this.els.emailError.textContent = ""; this.els.otpError.textContent = ""; window.setTimeout(() => this.els.emailInput.focus(), 30); } showOtpStep(email) { this.step = "otp"; this.pendingEmail = email; this.els.emailStep.hidden = true; this.els.otpStep.hidden = false; this.els.otpEmail.textContent = email; this.els.otpInput.value = ""; this.els.otpError.textContent = ""; window.setTimeout(() => this.els.otpInput.focus(), 30); } async submitCurrentStep() { if (this.inFlight) return; this.inFlight = true; this.setDisabled(true); try { if (this.step === "email") { await this.submitEmailStep(); } else { await this.submitOtpStep(); } } finally { this.inFlight = false; this.setDisabled(false); } } async submitEmailStep() { const email = this.els.emailInput.value.trim(); if (!isValidEmail(email)) { this.els.emailError.textContent = "Введите корректный email."; return; } try { await this.onOtpRequested({ email }); this.showOtpStep(email); } catch (error) { this.els.emailError.textContent = getErrorMessage(error); } } async submitOtpStep() { const code = this.els.otpInput.value.trim(); if (!/^\d{6}$/.test(code)) { this.els.otpError.textContent = "Введите 6 цифр из письма."; return; } const email = this.pendingEmail || this.els.emailInput.value.trim(); try { await this.onAuthenticated({ email, code }); this.currentEmail = email; this.forceClose(); } catch (error) { this.els.otpError.textContent = getErrorMessage(error); } } setDisabled(disabled) { this.els.form.querySelectorAll("button, input").forEach((element) => { if (element === this.els.close || element === this.els.later) return; element.disabled = disabled; }); } } function isValidEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } function getErrorMessage(error) { if (error && error.message) return error.message; return "Не удалось выполнить запрос. Попробуйте еще раз."; } function noop() {} window.PaperQAuthPopup = { version: "paperq-auth-popup-v2", create(options) { return new AuthPopup(options); }, }; })();