@luminaryworks/auth-react 0.5.0 → 0.7.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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- (function(){if(typeof document==="undefined")return;var id="lw-auth-react-headless-login";if(document.getElementById(id))return;var s=document.createElement("style");s.id=id;s.textContent="/* src/HeadlessLoginPanel.module.scss */\n.HeadlessLoginPanel_module_panel {\n --lw-auth-theme: #1677ff;\n --lw-auth-theme-deep: color-mix(in srgb, var(--lw-auth-theme) 72%, #000);\n width: min(100%, 400px);\n padding: 28px 28px 22px;\n border-radius: 16px;\n background: rgba(255, 255, 255, 0.96);\n color: #14212b;\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n font-family:\n \"Segoe UI\",\n \"PingFang SC\",\n \"Noto Sans SC\",\n sans-serif;\n}\n.HeadlessLoginPanel_module_brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n.HeadlessLoginPanel_module_logo {\n border-radius: 12px;\n display: block;\n}\n.HeadlessLoginPanel_module_product {\n margin: 0;\n font-size: 13px;\n font-weight: 650;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--lw-auth-theme);\n}\n.HeadlessLoginPanel_module_title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n.HeadlessLoginPanel_module_subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: #4b5c68;\n}\n.HeadlessLoginPanel_module_form {\n display: grid;\n gap: 10px;\n}\n.HeadlessLoginPanel_module_channelTabs {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px;\n margin-bottom: 2px;\n}\n.HeadlessLoginPanel_module_channelTab {\n border: 1px solid #c9d5de;\n border-radius: 10px;\n padding: 8px 10px;\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n color: #4b5c68;\n background: #f7fafc;\n}\n.HeadlessLoginPanel_module_channelTab:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_channelTabActive {\n color: var(--lw-auth-theme-deep);\n border-color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 10%, #fff);\n}\n.HeadlessLoginPanel_module_codeRow {\n display: grid;\n grid-template-columns: 1fr auto;\n gap: 8px;\n align-items: stretch;\n}\n.HeadlessLoginPanel_module_codeInput {\n min-width: 0;\n}\n.HeadlessLoginPanel_module_secondaryBtn {\n border: 1px solid #b7c9d4;\n border-radius: 10px;\n padding: 0 12px;\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n color: #14212b;\n background: #fff;\n white-space: nowrap;\n}\n.HeadlessLoginPanel_module_secondaryBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n.HeadlessLoginPanel_module_input {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid #c9d5de;\n border-radius: 10px;\n padding: 10px 12px;\n font-size: 14px;\n outline: none;\n background: #f7fafc;\n}\n.HeadlessLoginPanel_module_input:focus {\n border-color: var(--lw-auth-theme);\n}\n.HeadlessLoginPanel_module_input:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n.HeadlessLoginPanel_module_passwordInput {\n padding-right: 42px;\n}\n.HeadlessLoginPanel_module_passwordToggle {\n position: absolute;\n right: 4px;\n top: 50%;\n transform: translateY(-50%);\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 4px;\n padding: 0;\n color: #5a6b76;\n background: transparent;\n cursor: pointer;\n}\n.HeadlessLoginPanel_module_passwordToggle:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n}\n.HeadlessLoginPanel_module_passwordToggle:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n}\n.HeadlessLoginPanel_module_passwordToggle:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_primaryBtn {\n border: none;\n border-radius: 10px;\n padding: 11px 14px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #fff;\n background:\n linear-gradient(\n 135deg,\n var(--lw-auth-theme) 0%,\n var(--lw-auth-theme-deep) 100%);\n}\n.HeadlessLoginPanel_module_primaryBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_socialBtn {\n flex: 1 1 calc(50% - 5px);\n min-width: min(140px, 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: 1px solid #b7c9d4;\n border-radius: 10px;\n padding: 11px 10px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #14212b;\n background: #fff;\n}\n.HeadlessLoginPanel_module_socialBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_socialLogo {\n flex-shrink: 0;\n display: block;\n}\n.HeadlessLoginPanel_module_logoFallback {\n width: 18px;\n height: 18px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--lw-auth-theme) 14%, #fff);\n color: var(--lw-auth-theme-deep);\n font-size: 11px;\n font-weight: 700;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.HeadlessLoginPanel_module_cancelBtn {\n margin-top: 10px;\n width: 100%;\n border: none;\n background: transparent;\n color: #5a6b76;\n font-size: 13px;\n cursor: pointer;\n padding: 8px;\n}\n.HeadlessLoginPanel_module_cancelBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: #90a0ab;\n}\n.HeadlessLoginPanel_module_dividerLine {\n flex: 1;\n height: 1px;\n background: #d5e0e7;\n}\n.HeadlessLoginPanel_module_dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n.HeadlessLoginPanel_module_hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: #6b7c87;\n line-height: 1.45;\n}\n.HeadlessLoginPanel_module_domainsHint {\n margin: -2px 0 0;\n font-size: 12px;\n line-height: 1.45;\n color: #4b5c68;\n word-break: break-word;\n}\n.HeadlessLoginPanel_module_switchMode {\n margin: 12px 0 0;\n text-align: center;\n}\n.HeadlessLoginPanel_module_switchModeBtn {\n border: none;\n background: transparent;\n color: var(--lw-auth-theme);\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n padding: 4px 8px;\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n.HeadlessLoginPanel_module_switchModeBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_error {\n margin: 12px 0 0;\n font-size: 13px;\n color: #b42318;\n line-height: 1.4;\n}\n.HeadlessLoginPanel_module_footer {\n margin-top: 18px;\n padding-top: 12px;\n border-top: 1px solid #e4ebf0;\n font-size: 12px;\n color: #6b7c87;\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n/*# sourceMappingURL=index.css.map */";document.head.appendChild(s);})();
1
+ (function(){if(typeof document==="undefined")return;var id="lw-auth-react-headless-login";if(document.getElementById(id))return;var s=document.createElement("style");s.id=id;s.textContent="/* src/HeadlessLoginPanel.module.scss */\n.HeadlessLoginPanel_module_panel {\n --lw-auth-theme: #1677ff;\n --lw-auth-theme-deep: color-mix(in srgb, var(--lw-auth-theme) 72%, #000);\n box-sizing: border-box;\n width: min(100%, 400px);\n max-width: 400px;\n padding: 28px 28px 22px;\n border-radius: 16px;\n background: rgba(255, 255, 255, 0.96);\n color: #14212b;\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n font-family:\n \"Segoe UI\",\n \"PingFang SC\",\n \"Noto Sans SC\",\n sans-serif;\n}\n.HeadlessLoginPanel_module_brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n.HeadlessLoginPanel_module_logo {\n border-radius: 12px;\n display: block;\n}\n.HeadlessLoginPanel_module_product {\n margin: 0;\n font-size: 13px;\n font-weight: 650;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--lw-auth-theme);\n}\n.HeadlessLoginPanel_module_title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n.HeadlessLoginPanel_module_subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: #4b5c68;\n}\n.HeadlessLoginPanel_module_form {\n display: grid;\n gap: 10px;\n}\n.HeadlessLoginPanel_module_channelTabs {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px;\n margin-bottom: 2px;\n}\n.HeadlessLoginPanel_module_channelTab {\n border: 1px solid #c9d5de;\n border-radius: 10px;\n padding: 8px 10px;\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n color: #4b5c68;\n background: #f7fafc;\n}\n.HeadlessLoginPanel_module_channelTab:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_channelTabActive {\n color: var(--lw-auth-theme-deep);\n border-color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 10%, #fff);\n}\n.HeadlessLoginPanel_module_codeRow {\n display: grid;\n grid-template-columns: 1fr auto;\n gap: 8px;\n align-items: stretch;\n}\n.HeadlessLoginPanel_module_codeInput {\n min-width: 0;\n}\n.HeadlessLoginPanel_module_secondaryBtn {\n border: 1px solid #b7c9d4;\n border-radius: 10px;\n padding: 0 12px;\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n color: #14212b;\n background: #fff;\n white-space: nowrap;\n}\n.HeadlessLoginPanel_module_secondaryBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_socialStack {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 10px;\n font-size: 12px;\n}\n.HeadlessLoginPanel_module_input {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid #c9d5de;\n border-radius: 10px;\n padding: 10px 12px;\n font-size: 14px;\n outline: none;\n background: #f7fafc;\n}\n.HeadlessLoginPanel_module_input:focus {\n border-color: var(--lw-auth-theme);\n}\n.HeadlessLoginPanel_module_input:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n.HeadlessLoginPanel_module_passwordInput {\n padding-right: 42px;\n}\n.HeadlessLoginPanel_module_passwordToggle {\n position: absolute;\n right: 4px;\n top: 50%;\n transform: translateY(-50%);\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 4px;\n padding: 0;\n color: #5a6b76;\n background: transparent;\n cursor: pointer;\n}\n.HeadlessLoginPanel_module_passwordToggle:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n}\n.HeadlessLoginPanel_module_passwordToggle:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n}\n.HeadlessLoginPanel_module_passwordToggle:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_primaryBtn {\n border: none;\n border-radius: 10px;\n padding: 11px 14px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #fff;\n background:\n linear-gradient(\n 135deg,\n var(--lw-auth-theme) 0%,\n var(--lw-auth-theme-deep) 100%);\n}\n.HeadlessLoginPanel_module_primaryBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_socialBtn {\n width: 100%;\n min-width: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: 1px solid #b7c9d4;\n border-radius: 10px;\n padding: 11px 10px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #14212b;\n background: #fff;\n}\n.HeadlessLoginPanel_module_socialBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_socialLogo {\n flex-shrink: 0;\n display: block;\n}\n.HeadlessLoginPanel_module_logoFallback {\n width: 18px;\n height: 18px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--lw-auth-theme) 14%, #fff);\n color: var(--lw-auth-theme-deep);\n font-size: 11px;\n font-weight: 700;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.HeadlessLoginPanel_module_cancelBtn {\n margin-top: 10px;\n width: 100%;\n border: none;\n background: transparent;\n color: #5a6b76;\n font-size: 13px;\n cursor: pointer;\n padding: 8px;\n}\n.HeadlessLoginPanel_module_cancelBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: #90a0ab;\n}\n.HeadlessLoginPanel_module_dividerLine {\n flex: 1;\n height: 1px;\n background: #d5e0e7;\n}\n.HeadlessLoginPanel_module_dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n.HeadlessLoginPanel_module_hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: #6b7c87;\n line-height: 1.45;\n}\n.HeadlessLoginPanel_module_domainsHint {\n margin: -2px 0 0;\n font-size: 12px;\n line-height: 1.45;\n color: #4b5c68;\n word-break: break-word;\n}\n.HeadlessLoginPanel_module_switchMode {\n margin: 12px 0 0;\n text-align: center;\n}\n.HeadlessLoginPanel_module_switchModeBtn {\n border: none;\n background: transparent;\n color: var(--lw-auth-theme);\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n padding: 4px 8px;\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n.HeadlessLoginPanel_module_switchModeBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n.HeadlessLoginPanel_module_error {\n margin: 12px 0 0;\n font-size: 13px;\n color: #b42318;\n line-height: 1.4;\n}\n.HeadlessLoginPanel_module_consent {\n margin: 12px 0 0;\n font-size: 13px;\n line-height: 1.45;\n color: #14212b;\n}\n.HeadlessLoginPanel_module_consentInvalid {\n margin: 12px -8px 0;\n padding: 8px;\n border: 1px solid #b42318;\n border-radius: 10px;\n background: rgba(180, 35, 24, 0.06);\n}\n.HeadlessLoginPanel_module_consentError {\n margin: 8px 0 0;\n font-size: 13px;\n font-weight: 650;\n line-height: 1.4;\n color: #b42318;\n}\n.HeadlessLoginPanel_module_consentLinks {\n margin: 0;\n}\n.HeadlessLoginPanel_module_consentLinks a {\n color: var(--lw-auth-theme);\n}\n.HeadlessLoginPanel_module_footer {\n margin-top: 18px;\n padding-top: 12px;\n border-top: 1px solid #e4ebf0;\n font-size: 12px;\n color: #6b7c87;\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n@media (max-width: 420px) {\n .HeadlessLoginPanel_module_panel {\n padding: 22px 16px 18px;\n }\n}\n\n/* src/LoginLanguageSwitcher.module.scss */\n.LoginLanguageSwitcher_module_switch {\n position: relative;\n display: inline-flex;\n}\n.LoginLanguageSwitcher_module_trigger {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 32px;\n padding: 0 10px 0 8px;\n border: 1px solid rgba(15, 23, 42, 0.12);\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.86);\n color: #243044;\n font: inherit;\n font-size: 13px;\n line-height: 1;\n cursor: pointer;\n backdrop-filter: blur(8px);\n}\n.LoginLanguageSwitcher_module_trigger:hover,\n.LoginLanguageSwitcher_module_trigger[aria-expanded=true] {\n border-color: var(--lw-login-accent, #1677ff);\n color: #0f172a;\n}\n.LoginLanguageSwitcher_module_icon {\n width: 14px;\n height: 14px;\n display: block;\n}\n.LoginLanguageSwitcher_module_caret {\n width: 10px;\n height: 10px;\n opacity: 0.65;\n}\n.LoginLanguageSwitcher_module_menu {\n position: absolute;\n top: calc(100% + 6px);\n right: 0;\n z-index: 20;\n min-width: 168px;\n margin: 0;\n padding: 6px;\n list-style: none;\n border-radius: 12px;\n background: #fff;\n box-shadow: 0 12px 40px rgba(15, 23, 42, 0.16);\n}\n.LoginLanguageSwitcher_module_item {\n display: block;\n width: 100%;\n border: 0;\n border-radius: 8px;\n padding: 8px 10px;\n background: transparent;\n color: #1f2937;\n font: inherit;\n font-size: 14px;\n text-align: left;\n cursor: pointer;\n}\n.LoginLanguageSwitcher_module_item:hover {\n background: #f3f6fb;\n}\n.LoginLanguageSwitcher_module_itemActive {\n background: color-mix(in srgb, var(--lw-login-accent, #1677ff) 14%, #fff);\n color: var(--lw-login-accent, #1677ff);\n font-weight: 650;\n}\n.LoginLanguageSwitcher_module_onDark {\n border-color: rgba(255, 255, 255, 0.22);\n background: rgba(15, 23, 42, 0.28);\n color: rgba(255, 255, 255, 0.92);\n}\n.LoginLanguageSwitcher_module_onDark:hover,\n.LoginLanguageSwitcher_module_onDark[aria-expanded=true] {\n border-color: rgba(255, 255, 255, 0.55);\n color: #fff;\n}\n\n/* src/LoginCanvas.module.scss */\n.LoginCanvas_module_canvas {\n --lw-login-accent: #1677ff;\n position: relative;\n min-height: 100dvh;\n display: grid;\n place-items: center;\n padding: 56px 20px 24px;\n overflow: hidden;\n background:\n radial-gradient(\n 900px 480px at 8% -8%,\n color-mix(in srgb, var(--lw-login-accent) 28%, transparent),\n transparent 58%),\n radial-gradient(\n 720px 420px at 100% 12%,\n color-mix(in srgb, var(--lw-login-accent) 16%, transparent),\n transparent 52%),\n linear-gradient(\n 165deg,\n var(--lw-login-bg-a, #f4f7fb) 0%,\n var(--lw-login-bg-b, #e7eef6) 100%);\n color: var(--lw-login-ink, #122033);\n}\n.LoginCanvas_module_canvas[data-tone=console] {\n --lw-login-accent: #7eb6ff;\n --lw-login-bg-a: #0e1726;\n --lw-login-bg-b: #1a2740;\n --lw-login-ink: #e8eef8;\n --lw-login-grid: rgba(255, 255, 255, 0.05);\n}\n.LoginCanvas_module_canvas[data-tone=vista] {\n --lw-login-accent: #1677ff;\n --lw-login-bg-a: #f4f7fb;\n --lw-login-bg-b: #dde7f0;\n --lw-login-grid: rgba(11, 18, 32, 0.045);\n}\n.LoginCanvas_module_canvas[data-tone=data] {\n --lw-login-accent: #7c3aed;\n --lw-login-bg-a: #0a0f1e;\n --lw-login-bg-b: #0a0f1e;\n --lw-login-ink: #e8eefc;\n --lw-login-grid: rgba(255, 255, 255, 0.045);\n}\n.LoginCanvas_module_canvas[data-tone=edu] {\n --lw-login-accent: #7ec8ff;\n --lw-login-bg-a: #0a348c;\n --lw-login-bg-b: #1d7aef;\n --lw-login-ink: #f4f8ff;\n --lw-login-grid: rgba(255, 255, 255, 0.07);\n}\n.LoginCanvas_module_grid {\n position: absolute;\n inset: 0;\n pointer-events: none;\n background-image:\n linear-gradient(var(--lw-login-grid, rgba(15, 23, 42, 0.04)) 1px, transparent 1px),\n linear-gradient(\n 90deg,\n var(--lw-login-grid, rgba(15, 23, 42, 0.04)) 1px,\n transparent 1px);\n background-size: 48px 48px;\n mask-image:\n radial-gradient(\n ellipse at center,\n #000 18%,\n transparent 74%);\n}\n.LoginCanvas_module_lang {\n position: fixed;\n top: 14px;\n right: 16px;\n z-index: 5;\n}\n.LoginCanvas_module_decor {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 0;\n}\n.LoginCanvas_module_slot {\n position: relative;\n z-index: 1;\n width: min(440px, 100%);\n}\n.LoginCanvas_module_slotFill {\n width: min(1120px, 100%);\n}\n@media (max-width: 720px) {\n .LoginCanvas_module_canvas {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-start;\n overflow-x: hidden;\n overflow-y: auto;\n padding: 72px 16px 28px;\n }\n .LoginCanvas_module_lang {\n top: 12px;\n right: 12px;\n }\n}\n@media (max-width: 420px) {\n .LoginCanvas_module_canvas {\n padding: 64px 12px 20px;\n }\n}\n/*# sourceMappingURL=index.css.map */";document.head.appendChild(s);})();
2
2
  'use strict';
3
3
 
4
4
  var oidcClientTs = require('oidc-client-ts');
@@ -250,6 +250,20 @@ function isLogtoRegisterUsername(value) {
250
250
  function experienceUrl(apiBase, path) {
251
251
  return `${apiBase.replace(/\/$/, "")}/api/experience${path}`;
252
252
  }
253
+ var ExperienceApiError = class extends Error {
254
+ status;
255
+ code;
256
+ constructor(status, code, message) {
257
+ super(message);
258
+ this.name = "ExperienceApiError";
259
+ this.status = status;
260
+ this.code = code;
261
+ }
262
+ };
263
+ var MFA_REQUIRED_CODE = "session.mfa.require_mfa_verification";
264
+ function isMfaVerificationRequired(error) {
265
+ return error instanceof ExperienceApiError && error.code === MFA_REQUIRED_CODE;
266
+ }
253
267
  async function experienceFetch(apiBase, path, init) {
254
268
  const res = await fetch(experienceUrl(apiBase, path), {
255
269
  credentials: "include",
@@ -270,8 +284,10 @@ async function experienceFetch(apiBase, path, init) {
270
284
  }
271
285
  }
272
286
  if (!res.ok) {
273
- const msg = data && typeof data === "object" && data !== null && "message" in data ? String(data.message) : `Experience API ${res.status}`;
274
- throw new Error(msg);
287
+ const body = data && typeof data === "object" && data !== null ? data : null;
288
+ const code = typeof body?.code === "string" ? body.code : "";
289
+ const msg = typeof body?.message === "string" ? body.message : `Experience API ${res.status}`;
290
+ throw new ExperienceApiError(res.status, code, msg);
275
291
  }
276
292
  return data;
277
293
  }
@@ -365,21 +381,44 @@ var LogtoExperienceAdapter = class {
365
381
  method: "POST",
366
382
  body: JSON.stringify({ verificationId })
367
383
  });
368
- const submitted = await experienceFetch(
369
- apiBase,
370
- "/submit",
371
- {
372
- method: "POST",
373
- body: JSON.stringify({})
384
+ try {
385
+ const submitted = await experienceFetch(
386
+ apiBase,
387
+ "/submit",
388
+ {
389
+ method: "POST",
390
+ body: JSON.stringify({})
391
+ }
392
+ );
393
+ return { redirectTo: submitted?.redirectTo, raw: submitted };
394
+ } catch (error) {
395
+ if (isMfaVerificationRequired(error)) {
396
+ return { mfaRequired: true };
374
397
  }
375
- );
376
- return { redirectTo: submitted?.redirectTo, raw: submitted };
398
+ throw error;
399
+ }
377
400
  } catch (error) {
378
401
  lastError = error instanceof Error ? error : new Error(String(error));
379
402
  }
380
403
  }
381
404
  throw lastError ?? new Error("Experience password sign-in failed");
382
405
  }
406
+ /** Verify the user's existing authenticator code, then submit the interaction. */
407
+ async experienceVerifyTotp(input) {
408
+ const code = input.code.trim();
409
+ if (!code) {
410
+ throw new Error("Authenticator code is required");
411
+ }
412
+ await experienceFetch(input.apiBase, "/verification/totp/verify", {
413
+ method: "POST",
414
+ body: JSON.stringify({ code })
415
+ });
416
+ const submitted = await experienceFetch(input.apiBase, "/submit", {
417
+ method: "POST",
418
+ body: JSON.stringify({})
419
+ });
420
+ return { redirectTo: submitted?.redirectTo, raw: submitted };
421
+ }
383
422
  /**
384
423
  * Register with username + password via NewPasswordIdentity.
385
424
  * Email/phone self-register requires verification codes — use social or invite instead.
@@ -920,6 +959,392 @@ function useLuminaryAuth() {
920
959
  return ctx;
921
960
  }
922
961
 
962
+ // src/login-labels.ts
963
+ var DEFAULT_LOGIN_LOCALES = [
964
+ { code: "zh-CN", label: "\u7B80\u4F53\u4E2D\u6587", short: "\u7B80" },
965
+ { code: "zh-TW", label: "\u7E41\u9AD4\u4E2D\u6587", short: "\u7E41" },
966
+ { code: "ja", label: "\u65E5\u672C\u8A9E", short: "JA" },
967
+ { code: "ko", label: "\uD55C\uAD6D\uC5B4", short: "KO" },
968
+ { code: "en", label: "English", short: "EN" },
969
+ { code: "pt", label: "Portugu\xEAs", short: "PT" },
970
+ { code: "nl", label: "Nederlands", short: "NL" },
971
+ { code: "it", label: "Italiano", short: "IT" },
972
+ { code: "es", label: "Espa\xF1ol", short: "ES" },
973
+ { code: "fr", label: "Fran\xE7ais", short: "FR" }
974
+ ];
975
+ var ZH_CN = {
976
+ title: "\u767B\u5F55",
977
+ subtitle: "\u4F7F\u7528 LuminaryWorks \u7EDF\u4E00\u8D26\u53F7",
978
+ identifierPlaceholder: "\u90AE\u7BB1\u6216\u7528\u6237\u540D",
979
+ registerIdentifierPlaceholder: "\u7528\u6237\u540D",
980
+ passwordPlaceholder: "\u5BC6\u7801",
981
+ confirmPasswordPlaceholder: "\u786E\u8BA4\u5BC6\u7801",
982
+ submitPassword: "\u5BC6\u7801\u767B\u5F55",
983
+ submitRegister: "\u521B\u5EFA\u8D26\u53F7",
984
+ submitSso: "\u4F7F\u7528\u7EDF\u4E00\u8D26\u53F7\u7EE7\u7EED",
985
+ submitGoogle: "Google",
986
+ submitGithub: "GitHub",
987
+ socialDivider: "\u6216",
988
+ hint: "\u793E\u4EA4\u8D26\u53F7\u4F1A\u76F4\u63A5\u6253\u5F00\u5BF9\u5E94\u670D\u52A1\u3002\u5BC6\u7801\u767B\u5F55\u4F7F\u7528\u4F60\u7684 LuminaryWorks \u8D26\u53F7\u3002",
989
+ registerHint: "\u90AE\u7BB1\u6CE8\u518C\u9700\u8981\u9A8C\u8BC1\u7801\u3002\u4E5F\u53EF\u4EE5\u7528\u7528\u6237\u540D\u6CE8\u518C\uFF0C\u6216\u6539\u7528\u793E\u4EA4\u8D26\u53F7\u4E00\u952E\u767B\u5F55\u3002",
990
+ cancel: "\u53D6\u6D88",
991
+ experienceUnavailable: "\u5BC6\u7801\u767B\u5F55\u6682\u4E0D\u53EF\u7528\uFF0C\u8BF7\u6539\u7528\u793E\u4EA4\u8D26\u53F7\u3002",
992
+ showPassword: "\u663E\u793A\u5BC6\u7801",
993
+ hidePassword: "\u9690\u85CF\u5BC6\u7801",
994
+ registerLink: "\u521B\u5EFA\u8D26\u53F7",
995
+ loginLink: "\u5DF2\u6709\u8D26\u53F7\uFF1F\u53BB\u767B\u5F55",
996
+ passwordMismatch: "\u4E24\u6B21\u5BC6\u7801\u4E0D\u4E00\u81F4",
997
+ registerTitle: "\u521B\u5EFA\u8D26\u53F7",
998
+ registerSubtitle: "\u521B\u5EFA LuminaryWorks \u7EDF\u4E00\u8D26\u53F7",
999
+ registerWithEmail: "\u90AE\u7BB1",
1000
+ registerWithUsername: "\u7528\u6237\u540D",
1001
+ emailPlaceholder: "\u90AE\u7BB1",
1002
+ verificationCodePlaceholder: "\u9A8C\u8BC1\u7801",
1003
+ sendCode: "\u53D1\u9001\u9A8C\u8BC1\u7801",
1004
+ resendCode: "\u91CD\u65B0\u53D1\u9001",
1005
+ allowedDomainsPrefix: "\u5141\u8BB8\u7684\u90AE\u7BB1\u57DF\u540D",
1006
+ allowedDomainsOpen: "\u5927\u591A\u6570\u90AE\u7BB1\u90FD\u53EF\u4EE5\u6CE8\u518C\u3002",
1007
+ allowedDomainsBlocklist: "\u5927\u591A\u6570\u90AE\u7BB1\u53EF\u7528\u3002\u4E34\u65F6\u90AE\u7BB1\u4F1A\u88AB\u62D2\u7EDD\u3002",
1008
+ waitingExternalBrowser: "\u8BF7\u5728\u6D4F\u89C8\u5668\u4E2D\u5B8C\u6210\u767B\u5F55\uFF0C\u7136\u540E\u56DE\u5230\u672C\u5E94\u7528\u3002",
1009
+ consentRequired: "\u8BF7\u5148\u540C\u610F\u7528\u6237\u534F\u8BAE\u540E\u518D\u7EE7\u7EED\u3002",
1010
+ mfaTitle: "\u8EAB\u4EFD\u9A8C\u8BC1\u7801",
1011
+ mfaSubtitle: "\u8F93\u5165\u9A8C\u8BC1\u5668\u5E94\u7528\u4E2D\u7684 6 \u4F4D\u6570\u5B57\u3002",
1012
+ mfaCodePlaceholder: "6 \u4F4D\u9A8C\u8BC1\u7801",
1013
+ mfaSubmit: "\u9A8C\u8BC1\u5E76\u7EE7\u7EED",
1014
+ mfaBack: "\u8FD4\u56DE"
1015
+ };
1016
+ var ZH_TW = {
1017
+ title: "\u767B\u5165",
1018
+ subtitle: "\u4F7F\u7528 LuminaryWorks \u7D71\u4E00\u5E33\u865F",
1019
+ identifierPlaceholder: "\u96FB\u5B50\u90F5\u4EF6\u6216\u4F7F\u7528\u8005\u540D\u7A31",
1020
+ registerIdentifierPlaceholder: "\u4F7F\u7528\u8005\u540D\u7A31",
1021
+ passwordPlaceholder: "\u5BC6\u78BC",
1022
+ confirmPasswordPlaceholder: "\u78BA\u8A8D\u5BC6\u78BC",
1023
+ submitPassword: "\u5BC6\u78BC\u767B\u5165",
1024
+ submitRegister: "\u5EFA\u7ACB\u5E33\u865F",
1025
+ submitSso: "\u4F7F\u7528\u7D71\u4E00\u5E33\u865F\u7E7C\u7E8C",
1026
+ submitGoogle: "Google",
1027
+ submitGithub: "GitHub",
1028
+ socialDivider: "\u6216",
1029
+ hint: "\u793E\u4EA4\u5E33\u865F\u6703\u76F4\u63A5\u958B\u555F\u5C0D\u61C9\u670D\u52D9\u3002\u5BC6\u78BC\u767B\u5165\u4F7F\u7528\u4F60\u7684 LuminaryWorks \u5E33\u865F\u3002",
1030
+ registerHint: "\u96FB\u5B50\u90F5\u4EF6\u8A3B\u518A\u9700\u8981\u9A57\u8B49\u78BC\u3002\u4E5F\u53EF\u4EE5\u7528\u4F7F\u7528\u8005\u540D\u7A31\u8A3B\u518A\uFF0C\u6216\u6539\u7528\u793E\u4EA4\u5E33\u865F\u3002",
1031
+ cancel: "\u53D6\u6D88",
1032
+ experienceUnavailable: "\u5BC6\u78BC\u767B\u5165\u66AB\u4E0D\u53EF\u7528\uFF0C\u8ACB\u6539\u7528\u793E\u4EA4\u5E33\u865F\u3002",
1033
+ showPassword: "\u986F\u793A\u5BC6\u78BC",
1034
+ hidePassword: "\u96B1\u85CF\u5BC6\u78BC",
1035
+ registerLink: "\u5EFA\u7ACB\u5E33\u865F",
1036
+ loginLink: "\u5DF2\u6709\u5E33\u865F\uFF1F\u53BB\u767B\u5165",
1037
+ passwordMismatch: "\u5169\u6B21\u5BC6\u78BC\u4E0D\u4E00\u81F4",
1038
+ registerTitle: "\u5EFA\u7ACB\u5E33\u865F",
1039
+ registerSubtitle: "\u5EFA\u7ACB LuminaryWorks \u7D71\u4E00\u5E33\u865F",
1040
+ registerWithEmail: "\u96FB\u5B50\u90F5\u4EF6",
1041
+ registerWithUsername: "\u4F7F\u7528\u8005\u540D\u7A31",
1042
+ emailPlaceholder: "\u96FB\u5B50\u90F5\u4EF6",
1043
+ verificationCodePlaceholder: "\u9A57\u8B49\u78BC",
1044
+ sendCode: "\u767C\u9001\u9A57\u8B49\u78BC",
1045
+ resendCode: "\u91CD\u65B0\u767C\u9001",
1046
+ allowedDomainsPrefix: "\u5141\u8A31\u7684\u96FB\u5B50\u90F5\u4EF6\u7DB2\u57DF",
1047
+ allowedDomainsOpen: "\u5927\u591A\u6578\u96FB\u5B50\u90F5\u4EF6\u90FD\u53EF\u4EE5\u8A3B\u518A\u3002",
1048
+ allowedDomainsBlocklist: "\u5927\u591A\u6578\u96FB\u5B50\u90F5\u4EF6\u53EF\u7528\u3002\u81E8\u6642\u4FE1\u7BB1\u6703\u88AB\u62D2\u7D55\u3002",
1049
+ waitingExternalBrowser: "\u8ACB\u5728\u700F\u89BD\u5668\u4E2D\u5B8C\u6210\u767B\u5165\uFF0C\u7136\u5F8C\u56DE\u5230\u672C\u61C9\u7528\u3002",
1050
+ consentRequired: "\u8ACB\u5148\u540C\u610F\u4F7F\u7528\u689D\u6B3E\u5F8C\u518D\u7E7C\u7E8C\u3002",
1051
+ mfaTitle: "\u8EAB\u5206\u9A57\u8B49\u78BC",
1052
+ mfaSubtitle: "\u8F38\u5165\u9A57\u8B49\u5668\u61C9\u7528\u7A0B\u5F0F\u4E2D\u7684 6 \u4F4D\u6578\u5B57\u3002",
1053
+ mfaCodePlaceholder: "6 \u4F4D\u9A57\u8B49\u78BC",
1054
+ mfaSubmit: "\u9A57\u8B49\u4E26\u7E7C\u7E8C",
1055
+ mfaBack: "\u8FD4\u56DE"
1056
+ };
1057
+ var ES = {
1058
+ title: "Iniciar sesi\xF3n",
1059
+ subtitle: "Usa tu cuenta unificada de LuminaryWorks",
1060
+ identifierPlaceholder: "Correo o usuario",
1061
+ registerIdentifierPlaceholder: "Usuario",
1062
+ passwordPlaceholder: "Contrase\xF1a",
1063
+ confirmPasswordPlaceholder: "Confirmar contrase\xF1a",
1064
+ submitPassword: "Entrar con contrase\xF1a",
1065
+ submitRegister: "Crear cuenta",
1066
+ submitSso: "Continuar con la cuenta unificada",
1067
+ submitGoogle: "Google",
1068
+ submitGithub: "GitHub",
1069
+ socialDivider: "o",
1070
+ hint: "Las redes abren el proveedor directamente. La contrase\xF1a usa tu cuenta LuminaryWorks.",
1071
+ registerHint: "El registro por correo pide un c\xF3digo. Tambi\xE9n puedes usar un nombre de usuario o una red social.",
1072
+ cancel: "Cancelar",
1073
+ experienceUnavailable: "El inicio con contrase\xF1a no est\xE1 disponible. Usa una red social.",
1074
+ showPassword: "Mostrar contrase\xF1a",
1075
+ hidePassword: "Ocultar contrase\xF1a",
1076
+ registerLink: "Crear una cuenta",
1077
+ loginLink: "\xBFYa tienes cuenta? Inicia sesi\xF3n",
1078
+ passwordMismatch: "Las contrase\xF1as no coinciden",
1079
+ registerTitle: "Crear cuenta",
1080
+ registerSubtitle: "Crea tu cuenta unificada de LuminaryWorks",
1081
+ registerWithEmail: "Correo",
1082
+ registerWithUsername: "Usuario",
1083
+ emailPlaceholder: "Correo",
1084
+ verificationCodePlaceholder: "C\xF3digo",
1085
+ sendCode: "Enviar c\xF3digo",
1086
+ resendCode: "Reenviar",
1087
+ allowedDomainsPrefix: "Dominios de correo permitidos",
1088
+ allowedDomainsOpen: "El registro por correo est\xE1 abierto para la mayor\xEDa de proveedores.",
1089
+ allowedDomainsBlocklist: "Se aceptan la mayor\xEDa de correos. Se bloquean direcciones temporales.",
1090
+ waitingExternalBrowser: "Termina el inicio de sesi\xF3n en el navegador y vuelve a esta app.",
1091
+ consentRequired: "Acepta los t\xE9rminos antes de continuar."
1092
+ };
1093
+ var JA = {
1094
+ title: "\u30ED\u30B0\u30A4\u30F3",
1095
+ subtitle: "LuminaryWorks \u7D71\u5408\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u4F7F\u7528",
1096
+ identifierPlaceholder: "\u30E1\u30FC\u30EB\u307E\u305F\u306F\u30E6\u30FC\u30B6\u30FC\u540D",
1097
+ registerIdentifierPlaceholder: "\u30E6\u30FC\u30B6\u30FC\u540D",
1098
+ passwordPlaceholder: "\u30D1\u30B9\u30EF\u30FC\u30C9",
1099
+ confirmPasswordPlaceholder: "\u30D1\u30B9\u30EF\u30FC\u30C9\u78BA\u8A8D",
1100
+ submitPassword: "\u30D1\u30B9\u30EF\u30FC\u30C9\u3067\u30ED\u30B0\u30A4\u30F3",
1101
+ submitRegister: "\u30A2\u30AB\u30A6\u30F3\u30C8\u4F5C\u6210",
1102
+ submitSso: "\u7D71\u5408\u30A2\u30AB\u30A6\u30F3\u30C8\u3067\u7D9A\u3051\u308B",
1103
+ submitGoogle: "Google",
1104
+ submitGithub: "GitHub",
1105
+ socialDivider: "\u307E\u305F\u306F",
1106
+ hint: "\u30BD\u30FC\u30B7\u30E3\u30EB\u306F\u5404\u30B5\u30FC\u30D3\u30B9\u3092\u76F4\u63A5\u958B\u304D\u307E\u3059\u3002\u30D1\u30B9\u30EF\u30FC\u30C9\u306F LuminaryWorks \u30A2\u30AB\u30A6\u30F3\u30C8\u3067\u3059\u3002",
1107
+ registerHint: "\u30E1\u30FC\u30EB\u767B\u9332\u306B\u306F\u78BA\u8A8D\u30B3\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059\u3002\u30E6\u30FC\u30B6\u30FC\u540D\u307E\u305F\u306F\u30BD\u30FC\u30B7\u30E3\u30EB\u3082\u4F7F\u3048\u307E\u3059\u3002",
1108
+ cancel: "\u30AD\u30E3\u30F3\u30BB\u30EB",
1109
+ experienceUnavailable: "\u30D1\u30B9\u30EF\u30FC\u30C9\u30ED\u30B0\u30A4\u30F3\u306F\u4F7F\u3048\u307E\u305B\u3093\u3002\u30BD\u30FC\u30B7\u30E3\u30EB\u3092\u304A\u4F7F\u3044\u304F\u3060\u3055\u3044\u3002",
1110
+ showPassword: "\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u8868\u793A",
1111
+ hidePassword: "\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u96A0\u3059",
1112
+ registerLink: "\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u4F5C\u6210",
1113
+ loginLink: "\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u304A\u6301\u3061\u3067\u3059\u304B\uFF1F\u30ED\u30B0\u30A4\u30F3",
1114
+ passwordMismatch: "\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093",
1115
+ registerTitle: "\u30A2\u30AB\u30A6\u30F3\u30C8\u4F5C\u6210",
1116
+ registerSubtitle: "LuminaryWorks \u7D71\u5408\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u4F5C\u6210",
1117
+ registerWithEmail: "\u30E1\u30FC\u30EB",
1118
+ registerWithUsername: "\u30E6\u30FC\u30B6\u30FC\u540D",
1119
+ emailPlaceholder: "\u30E1\u30FC\u30EB",
1120
+ verificationCodePlaceholder: "\u78BA\u8A8D\u30B3\u30FC\u30C9",
1121
+ sendCode: "\u30B3\u30FC\u30C9\u3092\u9001\u4FE1",
1122
+ resendCode: "\u518D\u9001\u4FE1",
1123
+ allowedDomainsPrefix: "\u5229\u7528\u3067\u304D\u308B\u30E1\u30FC\u30EB\u30C9\u30E1\u30A4\u30F3",
1124
+ allowedDomainsOpen: "\u307B\u3068\u3093\u3069\u306E\u30E1\u30FC\u30EB\u3067\u767B\u9332\u3067\u304D\u307E\u3059\u3002",
1125
+ allowedDomainsBlocklist: "\u307B\u3068\u3093\u3069\u306E\u30E1\u30FC\u30EB\u306F\u4F7F\u3048\u307E\u3059\u3002\u4F7F\u3044\u6368\u3066\u30A2\u30C9\u30EC\u30B9\u306F\u62D2\u5426\u3055\u308C\u307E\u3059\u3002",
1126
+ waitingExternalBrowser: "\u30D6\u30E9\u30A6\u30B6\u3067\u30ED\u30B0\u30A4\u30F3\u3092\u7D42\u3048\u305F\u3089\u3001\u3053\u306E\u30A2\u30D7\u30EA\u306B\u623B\u3063\u3066\u304F\u3060\u3055\u3044\u3002",
1127
+ consentRequired: "\u7D9A\u3051\u308B\u524D\u306B\u5229\u7528\u898F\u7D04\u3078\u540C\u610F\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
1128
+ };
1129
+ var KO = {
1130
+ title: "\uB85C\uADF8\uC778",
1131
+ subtitle: "LuminaryWorks \uD1B5\uD569 \uACC4\uC815 \uC0AC\uC6A9",
1132
+ identifierPlaceholder: "\uC774\uBA54\uC77C \uB610\uB294 \uC0AC\uC6A9\uC790 \uC774\uB984",
1133
+ registerIdentifierPlaceholder: "\uC0AC\uC6A9\uC790 \uC774\uB984",
1134
+ passwordPlaceholder: "\uBE44\uBC00\uBC88\uD638",
1135
+ confirmPasswordPlaceholder: "\uBE44\uBC00\uBC88\uD638 \uD655\uC778",
1136
+ submitPassword: "\uBE44\uBC00\uBC88\uD638\uB85C \uB85C\uADF8\uC778",
1137
+ submitRegister: "\uACC4\uC815 \uB9CC\uB4E4\uAE30",
1138
+ submitSso: "\uD1B5\uD569 \uACC4\uC815\uC73C\uB85C \uACC4\uC18D",
1139
+ submitGoogle: "Google",
1140
+ submitGithub: "GitHub",
1141
+ socialDivider: "\uB610\uB294",
1142
+ hint: "\uC18C\uC15C \uB85C\uADF8\uC778\uC740 \uD574\uB2F9 \uC11C\uBE44\uC2A4\uB97C \uBC14\uB85C \uC5FD\uB2C8\uB2E4. \uBE44\uBC00\uBC88\uD638\uB294 LuminaryWorks \uACC4\uC815\uC785\uB2C8\uB2E4.",
1143
+ registerHint: "\uC774\uBA54\uC77C \uAC00\uC785\uC5D0\uB294 \uC778\uC99D \uCF54\uB4DC\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uC790 \uC774\uB984\uC774\uB098 \uC18C\uC15C\uB3C4 \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
1144
+ cancel: "\uCDE8\uC18C",
1145
+ experienceUnavailable: "\uBE44\uBC00\uBC88\uD638 \uB85C\uADF8\uC778\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC18C\uC15C \uB85C\uADF8\uC778\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.",
1146
+ showPassword: "\uBE44\uBC00\uBC88\uD638 \uD45C\uC2DC",
1147
+ hidePassword: "\uBE44\uBC00\uBC88\uD638 \uC228\uAE30\uAE30",
1148
+ registerLink: "\uACC4\uC815 \uB9CC\uB4E4\uAE30",
1149
+ loginLink: "\uACC4\uC815\uC774 \uC788\uB098\uC694? \uB85C\uADF8\uC778",
1150
+ passwordMismatch: "\uBE44\uBC00\uBC88\uD638\uAC00 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
1151
+ registerTitle: "\uACC4\uC815 \uB9CC\uB4E4\uAE30",
1152
+ registerSubtitle: "LuminaryWorks \uD1B5\uD569 \uACC4\uC815 \uB9CC\uB4E4\uAE30",
1153
+ registerWithEmail: "\uC774\uBA54\uC77C",
1154
+ registerWithUsername: "\uC0AC\uC6A9\uC790 \uC774\uB984",
1155
+ emailPlaceholder: "\uC774\uBA54\uC77C",
1156
+ verificationCodePlaceholder: "\uC778\uC99D \uCF54\uB4DC",
1157
+ sendCode: "\uCF54\uB4DC \uBCF4\uB0B4\uAE30",
1158
+ resendCode: "\uB2E4\uC2DC \uBCF4\uB0B4\uAE30",
1159
+ allowedDomainsPrefix: "\uD5C8\uC6A9\uB41C \uC774\uBA54\uC77C \uB3C4\uBA54\uC778",
1160
+ allowedDomainsOpen: "\uB300\uBD80\uBD84\uC758 \uC774\uBA54\uC77C\uB85C \uAC00\uC785\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
1161
+ allowedDomainsBlocklist: "\uB300\uBD80\uBD84\uC758 \uC774\uBA54\uC77C\uC744 \uD5C8\uC6A9\uD569\uB2C8\uB2E4. \uC784\uC2DC \uC8FC\uC18C\uB294 \uAC70\uBD80\uB429\uB2C8\uB2E4.",
1162
+ waitingExternalBrowser: "\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB85C\uADF8\uC778\uC744 \uB9C8\uCE5C \uB4A4 \uC774 \uC571\uC73C\uB85C \uB3CC\uC544\uC624\uC138\uC694.",
1163
+ consentRequired: "\uACC4\uC18D\uD558\uB824\uBA74 \uC57D\uAD00\uC5D0 \uB3D9\uC758\uD558\uC138\uC694."
1164
+ };
1165
+ var PT = {
1166
+ title: "Entrar",
1167
+ subtitle: "Use a conta unificada LuminaryWorks",
1168
+ identifierPlaceholder: "E-mail ou usu\xE1rio",
1169
+ registerIdentifierPlaceholder: "Usu\xE1rio",
1170
+ passwordPlaceholder: "Senha",
1171
+ confirmPasswordPlaceholder: "Confirmar senha",
1172
+ submitPassword: "Entrar com senha",
1173
+ submitRegister: "Criar conta",
1174
+ submitSso: "Continuar com a conta unificada",
1175
+ submitGoogle: "Google",
1176
+ submitGithub: "GitHub",
1177
+ socialDivider: "ou",
1178
+ hint: "Redes sociais abrem o provedor direto. A senha usa sua conta LuminaryWorks.",
1179
+ registerHint: "O cadastro por e-mail pede um c\xF3digo. Tamb\xE9m d\xE1 para usar usu\xE1rio ou rede social.",
1180
+ cancel: "Cancelar",
1181
+ experienceUnavailable: "Entrada por senha indispon\xEDvel. Use uma rede social.",
1182
+ showPassword: "Mostrar senha",
1183
+ hidePassword: "Ocultar senha",
1184
+ registerLink: "Criar uma conta",
1185
+ loginLink: "J\xE1 tem conta? Entrar",
1186
+ passwordMismatch: "As senhas n\xE3o coincidem",
1187
+ registerTitle: "Criar conta",
1188
+ registerSubtitle: "Crie sua conta unificada LuminaryWorks",
1189
+ registerWithEmail: "E-mail",
1190
+ registerWithUsername: "Usu\xE1rio",
1191
+ emailPlaceholder: "E-mail",
1192
+ verificationCodePlaceholder: "C\xF3digo",
1193
+ sendCode: "Enviar c\xF3digo",
1194
+ resendCode: "Reenviar",
1195
+ allowedDomainsPrefix: "Dom\xEDnios de e-mail permitidos",
1196
+ allowedDomainsOpen: "O cadastro por e-mail est\xE1 aberto para a maioria dos provedores.",
1197
+ allowedDomainsBlocklist: "A maioria dos e-mails \xE9 aceita. Endere\xE7os tempor\xE1rios s\xE3o bloqueados.",
1198
+ waitingExternalBrowser: "Conclua o login no navegador e volte a este app.",
1199
+ consentRequired: "Aceite os termos antes de continuar."
1200
+ };
1201
+ var NL = {
1202
+ title: "Inloggen",
1203
+ subtitle: "Gebruik je LuminaryWorks-account",
1204
+ identifierPlaceholder: "E-mail of gebruikersnaam",
1205
+ registerIdentifierPlaceholder: "Gebruikersnaam",
1206
+ passwordPlaceholder: "Wachtwoord",
1207
+ confirmPasswordPlaceholder: "Bevestig wachtwoord",
1208
+ submitPassword: "Inloggen met wachtwoord",
1209
+ submitRegister: "Account maken",
1210
+ submitSso: "Doorgaan met unified account",
1211
+ submitGoogle: "Google",
1212
+ submitGithub: "GitHub",
1213
+ socialDivider: "of",
1214
+ hint: "Sociale logins openen de provider direct. Het wachtwoord is je LuminaryWorks-account.",
1215
+ registerHint: "Registreren via e-mail vraagt een code. Een gebruikersnaam of sociale login kan ook.",
1216
+ cancel: "Annuleren",
1217
+ experienceUnavailable: "Inloggen met wachtwoord is niet beschikbaar. Gebruik een sociale login.",
1218
+ showPassword: "Wachtwoord tonen",
1219
+ hidePassword: "Wachtwoord verbergen",
1220
+ registerLink: "Account maken",
1221
+ loginLink: "Al een account? Inloggen",
1222
+ passwordMismatch: "Wachtwoorden komen niet overeen",
1223
+ registerTitle: "Account maken",
1224
+ registerSubtitle: "Maak je LuminaryWorks-account",
1225
+ registerWithEmail: "E-mail",
1226
+ registerWithUsername: "Gebruikersnaam",
1227
+ emailPlaceholder: "E-mail",
1228
+ verificationCodePlaceholder: "Code",
1229
+ sendCode: "Code versturen",
1230
+ resendCode: "Opnieuw",
1231
+ allowedDomainsPrefix: "Toegestane e-maildomeinen",
1232
+ allowedDomainsOpen: "Registreren kan met de meeste e-mailproviders.",
1233
+ allowedDomainsBlocklist: "De meeste adressen zijn toegestaan. Tijdelijke adressen worden geweigerd.",
1234
+ waitingExternalBrowser: "Rond het inloggen af in de browser en kom terug naar deze app.",
1235
+ consentRequired: "Ga eerst akkoord met de voorwaarden."
1236
+ };
1237
+ var IT = {
1238
+ title: "Accedi",
1239
+ subtitle: "Usa l'account unificato LuminaryWorks",
1240
+ identifierPlaceholder: "Email o nome utente",
1241
+ registerIdentifierPlaceholder: "Nome utente",
1242
+ passwordPlaceholder: "Password",
1243
+ confirmPasswordPlaceholder: "Conferma password",
1244
+ submitPassword: "Accedi con password",
1245
+ submitRegister: "Crea account",
1246
+ submitSso: "Continua con l'account unificato",
1247
+ submitGoogle: "Google",
1248
+ submitGithub: "GitHub",
1249
+ socialDivider: "oppure",
1250
+ hint: "I social aprono il provider. La password usa il tuo account LuminaryWorks.",
1251
+ registerHint: "La registrazione email chiede un codice. Puoi anche usare un nome utente o un social.",
1252
+ cancel: "Annulla",
1253
+ experienceUnavailable: "Accesso con password non disponibile. Usa un social.",
1254
+ showPassword: "Mostra password",
1255
+ hidePassword: "Nascondi password",
1256
+ registerLink: "Crea un account",
1257
+ loginLink: "Hai gi\xE0 un account? Accedi",
1258
+ passwordMismatch: "Le password non coincidono",
1259
+ registerTitle: "Crea account",
1260
+ registerSubtitle: "Crea il tuo account unificato LuminaryWorks",
1261
+ registerWithEmail: "Email",
1262
+ registerWithUsername: "Nome utente",
1263
+ emailPlaceholder: "Email",
1264
+ verificationCodePlaceholder: "Codice",
1265
+ sendCode: "Invia codice",
1266
+ resendCode: "Invia di nuovo",
1267
+ allowedDomainsPrefix: "Domini email consentiti",
1268
+ allowedDomainsOpen: "La registrazione email \xE8 aperta per la maggior parte dei provider.",
1269
+ allowedDomainsBlocklist: "La maggior parte delle email \xE8 accettata. Gli indirizzi temporanei sono bloccati.",
1270
+ waitingExternalBrowser: "Completa l'accesso nel browser e torna a questa app.",
1271
+ consentRequired: "Accetta i termini prima di continuare."
1272
+ };
1273
+ var FR = {
1274
+ title: "Connexion",
1275
+ subtitle: "Utilisez votre compte unifi\xE9 LuminaryWorks",
1276
+ identifierPlaceholder: "E-mail ou nom d'utilisateur",
1277
+ registerIdentifierPlaceholder: "Nom d'utilisateur",
1278
+ passwordPlaceholder: "Mot de passe",
1279
+ confirmPasswordPlaceholder: "Confirmer le mot de passe",
1280
+ submitPassword: "Se connecter avec mot de passe",
1281
+ submitRegister: "Cr\xE9er un compte",
1282
+ submitSso: "Continuer avec le compte unifi\xE9",
1283
+ submitGoogle: "Google",
1284
+ submitGithub: "GitHub",
1285
+ socialDivider: "ou",
1286
+ hint: "Les r\xE9seaux ouvrent le fournisseur. Le mot de passe utilise votre compte LuminaryWorks.",
1287
+ registerHint: "L'inscription par e-mail demande un code. Un nom d'utilisateur ou un r\xE9seau social convient aussi.",
1288
+ cancel: "Annuler",
1289
+ experienceUnavailable: "Connexion par mot de passe indisponible. Utilisez un r\xE9seau social.",
1290
+ showPassword: "Afficher le mot de passe",
1291
+ hidePassword: "Masquer le mot de passe",
1292
+ registerLink: "Cr\xE9er un compte",
1293
+ loginLink: "D\xE9j\xE0 un compte ? Se connecter",
1294
+ passwordMismatch: "Les mots de passe ne correspondent pas",
1295
+ registerTitle: "Cr\xE9er un compte",
1296
+ registerSubtitle: "Cr\xE9ez votre compte unifi\xE9 LuminaryWorks",
1297
+ registerWithEmail: "E-mail",
1298
+ registerWithUsername: "Nom d'utilisateur",
1299
+ emailPlaceholder: "E-mail",
1300
+ verificationCodePlaceholder: "Code",
1301
+ sendCode: "Envoyer le code",
1302
+ resendCode: "Renvoyer",
1303
+ allowedDomainsPrefix: "Domaines e-mail autoris\xE9s",
1304
+ allowedDomainsOpen: "L'inscription par e-mail est ouverte pour la plupart des fournisseurs.",
1305
+ allowedDomainsBlocklist: "La plupart des e-mails sont accept\xE9s. Les adresses jetables sont refus\xE9es.",
1306
+ waitingExternalBrowser: "Terminez la connexion dans le navigateur, puis revenez \xE0 cette application.",
1307
+ consentRequired: "Acceptez les conditions avant de continuer.",
1308
+ mfaTitle: "Code d'authentification",
1309
+ mfaSubtitle: "Saisissez le code \xE0 6 chiffres de votre application.",
1310
+ mfaCodePlaceholder: "123456",
1311
+ mfaSubmit: "V\xE9rifier et continuer",
1312
+ mfaBack: "Retour"
1313
+ };
1314
+ var BY_LOCALE = {
1315
+ en: void 0,
1316
+ "zh-CN": ZH_CN,
1317
+ "zh-TW": ZH_TW,
1318
+ ja: JA,
1319
+ ko: KO,
1320
+ pt: PT,
1321
+ nl: NL,
1322
+ it: IT,
1323
+ es: ES,
1324
+ fr: FR
1325
+ };
1326
+ function normalizeLoginLocale(locale) {
1327
+ const raw = (locale ?? "en").trim().toLowerCase();
1328
+ if (raw === "zh" || raw === "zh-cn" || raw === "zh-hans" || raw.startsWith("zh-cn")) {
1329
+ return "zh-CN";
1330
+ }
1331
+ if (raw === "zh-tw" || raw === "zh-hant" || raw.startsWith("zh-tw") || raw.startsWith("zh-hk")) {
1332
+ return "zh-TW";
1333
+ }
1334
+ if (raw === "ja" || raw.startsWith("ja-")) return "ja";
1335
+ if (raw === "ko" || raw.startsWith("ko-")) return "ko";
1336
+ if (raw === "pt" || raw.startsWith("pt-")) return "pt";
1337
+ if (raw === "nl" || raw.startsWith("nl-")) return "nl";
1338
+ if (raw === "it" || raw.startsWith("it-")) return "it";
1339
+ if (raw === "es" || raw.startsWith("es-")) return "es";
1340
+ if (raw === "fr" || raw.startsWith("fr-")) return "fr";
1341
+ if (raw === "en" || raw.startsWith("en-")) return "en";
1342
+ return "en";
1343
+ }
1344
+ function loginLabels(locale) {
1345
+ return BY_LOCALE[normalizeLoginLocale(locale)] ?? {};
1346
+ }
1347
+
923
1348
  // src/HeadlessLoginPanel.module.scss
924
1349
  var HeadlessLoginPanel_module_default = {
925
1350
  panel: "HeadlessLoginPanel_module_panel",
@@ -953,9 +1378,14 @@ var HeadlessLoginPanel_module_default = {
953
1378
  switchMode: "HeadlessLoginPanel_module_switchMode",
954
1379
  switchModeBtn: "HeadlessLoginPanel_module_switchModeBtn",
955
1380
  error: "HeadlessLoginPanel_module_error",
1381
+ consent: "HeadlessLoginPanel_module_consent",
1382
+ consentInvalid: "HeadlessLoginPanel_module_consentInvalid",
1383
+ consentError: "HeadlessLoginPanel_module_consentError",
1384
+ consentLinks: "HeadlessLoginPanel_module_consentLinks",
956
1385
  footer: "HeadlessLoginPanel_module_footer"
957
1386
  };
958
1387
  var DEFAULT_LOGIN_THEME_COLOR = "#1677ff";
1388
+ var LOGIN_CARD_MAX_WIDTH = 400;
959
1389
  var defaults = {
960
1390
  title: "Sign in",
961
1391
  subtitle: "Use your LuminaryWorks unified account",
@@ -989,7 +1419,13 @@ var defaults = {
989
1419
  allowedDomainsPrefix: "Allowed email domains",
990
1420
  allowedDomainsOpen: "Email registration is open for most providers.",
991
1421
  allowedDomainsBlocklist: "Most email providers are accepted. Temporary / disposable addresses are blocked.",
992
- waitingExternalBrowser: "Finish signing in with your browser, then return to this app."
1422
+ waitingExternalBrowser: "Finish signing in with your browser, then return to this app.",
1423
+ consentRequired: "Please agree to the terms before continuing.",
1424
+ mfaTitle: "Authenticator code",
1425
+ mfaSubtitle: "Enter the 6-digit code from your authenticator app.",
1426
+ mfaCodePlaceholder: "123456",
1427
+ mfaSubmit: "Verify and continue",
1428
+ mfaBack: "Back"
993
1429
  };
994
1430
  function resolveSieBase(config) {
995
1431
  const explicit = config.experienceApiBase?.trim();
@@ -1016,6 +1452,7 @@ function HeadlessLoginPanel({
1016
1452
  productName,
1017
1453
  logoSrc,
1018
1454
  labels: labelsProp,
1455
+ locale,
1019
1456
  returnUrl,
1020
1457
  mode = "popup",
1021
1458
  openExternalUrl,
@@ -1029,6 +1466,12 @@ function HeadlessLoginPanel({
1029
1466
  onCancel,
1030
1467
  onOidcSession,
1031
1468
  onExperienceRedirect,
1469
+ consent,
1470
+ consentDocuments,
1471
+ consentOk = true,
1472
+ onConsentBlocked,
1473
+ initialIdentifier,
1474
+ onIdentifierChange,
1032
1475
  footer,
1033
1476
  className,
1034
1477
  style,
@@ -1073,22 +1516,34 @@ function HeadlessLoginPanel({
1073
1516
  experienceAdapter.emailPolicy = emailPolicy;
1074
1517
  }
1075
1518
  }, [emailPolicy, experienceAdapter]);
1076
- const labels = { ...defaults, ...labelsProp };
1519
+ const labels = { ...defaults, ...loginLabels(locale), ...labelsProp };
1077
1520
  const configured = isIdpConfigured(config);
1078
1521
  const [panelMode, setPanelMode] = react.useState("sign-in");
1079
1522
  const [registerChannel, setRegisterChannel] = react.useState("email");
1080
- const [identifier, setIdentifier] = react.useState("");
1523
+ const [identifier, setIdentifier] = react.useState(initialIdentifier ?? "");
1524
+ const hydratedIdentifier = react.useRef(false);
1525
+ react.useEffect(() => {
1526
+ if (hydratedIdentifier.current) return;
1527
+ if (!initialIdentifier) return;
1528
+ hydratedIdentifier.current = true;
1529
+ setIdentifier(initialIdentifier);
1530
+ }, [initialIdentifier]);
1081
1531
  const [password, setPassword] = react.useState("");
1082
1532
  const [confirmPassword, setConfirmPassword] = react.useState("");
1083
1533
  const [verificationCode, setVerificationCode] = react.useState("");
1084
1534
  const [emailVerificationId, setEmailVerificationId] = react.useState(null);
1085
1535
  const [passwordVisible, setPasswordVisible] = react.useState(false);
1086
1536
  const panelStyle = {
1537
+ width: `min(100%, ${LOGIN_CARD_MAX_WIDTH}px)`,
1538
+ maxWidth: LOGIN_CARD_MAX_WIDTH,
1087
1539
  ...style,
1088
1540
  ["--lw-auth-theme"]: themeColor || DEFAULT_LOGIN_THEME_COLOR
1089
1541
  };
1090
1542
  const [loading, setLoading] = react.useState(null);
1091
1543
  const [error, setError] = react.useState("");
1544
+ const [consentBlocked, setConsentBlocked] = react.useState(false);
1545
+ const [mfaPending, setMfaPending] = react.useState(false);
1546
+ const [mfaCode, setMfaCode] = react.useState("");
1092
1547
  const [awaitingExternal, setAwaitingExternal] = react.useState(false);
1093
1548
  const [connectors, setConnectors] = react.useState([]);
1094
1549
  const socialEnabled = showSocialConnectors !== false && !(Array.isArray(socialProviders) && socialProviders.length === 0) && experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.socialConnectors) && experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.socialDirectSignIn) && typeof experienceAdapter.fetchSocialConnectors === "function" && typeof experienceAdapter.createSocialSignInRequest === "function";
@@ -1143,6 +1598,15 @@ function HeadlessLoginPanel({
1143
1598
  socialEnabled,
1144
1599
  socialProviders
1145
1600
  ]);
1601
+ react.useEffect(() => {
1602
+ if (consentOk) setConsentBlocked(false);
1603
+ }, [consentOk]);
1604
+ const ensureConsent = () => {
1605
+ if (consentOk) return true;
1606
+ setConsentBlocked(true);
1607
+ onConsentBlocked?.();
1608
+ return false;
1609
+ };
1146
1610
  const runOidc = async (experienceRequest) => {
1147
1611
  if (!configured) throw new Error("IdP not configured");
1148
1612
  if (mode === "external") {
@@ -1169,6 +1633,7 @@ function HeadlessLoginPanel({
1169
1633
  await onOidcSession?.(session, next);
1170
1634
  };
1171
1635
  const runSocial = async (target) => {
1636
+ if (!ensureConsent()) return;
1172
1637
  setError("");
1173
1638
  setLoading(target);
1174
1639
  try {
@@ -1185,6 +1650,7 @@ function HeadlessLoginPanel({
1185
1650
  }
1186
1651
  };
1187
1652
  const runHostedOidc = async () => {
1653
+ if (!ensureConsent()) return;
1188
1654
  setError("");
1189
1655
  setLoading("sso");
1190
1656
  try {
@@ -1205,6 +1671,7 @@ function HeadlessLoginPanel({
1205
1671
  const runPassword = async (event) => {
1206
1672
  event.preventDefault();
1207
1673
  if (!configured) return;
1674
+ if (!ensureConsent()) return;
1208
1675
  setError("");
1209
1676
  setLoading("password");
1210
1677
  try {
@@ -1281,6 +1748,36 @@ function HeadlessLoginPanel({
1281
1748
  scopes: config.scopes,
1282
1749
  returnUrl
1283
1750
  });
1751
+ if (result.mfaRequired) {
1752
+ setMfaPending(true);
1753
+ setMfaCode("");
1754
+ setLoading(null);
1755
+ return;
1756
+ }
1757
+ if (result.redirectTo) {
1758
+ followExperienceRedirect(result.redirectTo);
1759
+ return;
1760
+ }
1761
+ throw new Error("Experience API did not return redirectTo");
1762
+ } catch (e) {
1763
+ setError(e instanceof Error ? e.message : String(e));
1764
+ setLoading(null);
1765
+ }
1766
+ };
1767
+ const runMfa = async (event) => {
1768
+ event.preventDefault();
1769
+ if (!configured || !ensureConsent()) return;
1770
+ setError("");
1771
+ setLoading("mfa");
1772
+ try {
1773
+ const apiBase = config.experienceApiBase?.trim();
1774
+ if (!apiBase || !experienceAdapter.experienceVerifyTotp) {
1775
+ throw new Error(labels.experienceUnavailable);
1776
+ }
1777
+ const result = await experienceAdapter.experienceVerifyTotp({
1778
+ apiBase,
1779
+ code: mfaCode
1780
+ });
1284
1781
  if (result.redirectTo) {
1285
1782
  followExperienceRedirect(result.redirectTo);
1286
1783
  return;
@@ -1293,6 +1790,7 @@ function HeadlessLoginPanel({
1293
1790
  };
1294
1791
  const runSendCode = async () => {
1295
1792
  if (!configured || !useEmailRegister) return;
1793
+ if (!ensureConsent()) return;
1296
1794
  setError("");
1297
1795
  setLoading("send-code");
1298
1796
  try {
@@ -1334,8 +1832,8 @@ function HeadlessLoginPanel({
1334
1832
  const showSocial = socialEnabled && connectors.length > 0;
1335
1833
  const showHint = Boolean(labelsProp?.hint) || showSocial || isRegister;
1336
1834
  const formReady = Boolean(identifier.trim()) && Boolean(password) && (!isRegister || Boolean(confirmPassword)) && (!useEmailRegister || Boolean(verificationCode.trim()) && Boolean(emailVerificationId));
1337
- const titleText = isRegister ? labels.registerTitle : labels.title;
1338
- const subtitleText = isRegister ? labels.registerSubtitle : labels.subtitle;
1835
+ const titleText = mfaPending ? labels.mfaTitle : isRegister ? labels.registerTitle : labels.title;
1836
+ const subtitleText = mfaPending ? labels.mfaSubtitle : isRegister ? labels.registerSubtitle : labels.subtitle;
1339
1837
  const identifierPlaceholder = isRegister ? useEmailRegister ? labels.emailPlaceholder : labels.registerIdentifierPlaceholder : labels.identifierPlaceholder;
1340
1838
  const submitLabel = isRegister ? labels.submitRegister : labels.submitPassword;
1341
1839
  const hintText = isRegister ? labels.registerHint : labels.hint;
@@ -1354,7 +1852,44 @@ function HeadlessLoginPanel({
1354
1852
  ] }),
1355
1853
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.subtitle, children: subtitleText }),
1356
1854
  configured ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1357
- passwordEnabled ? /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: (e) => void runPassword(e), className: HeadlessLoginPanel_module_default.form, children: [
1855
+ passwordEnabled && mfaPending ? /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: (e) => void runMfa(e), className: HeadlessLoginPanel_module_default.form, children: [
1856
+ /* @__PURE__ */ jsxRuntime.jsx(
1857
+ "input",
1858
+ {
1859
+ inputMode: "numeric",
1860
+ autoComplete: "one-time-code",
1861
+ name: "totp",
1862
+ placeholder: labels.mfaCodePlaceholder,
1863
+ value: mfaCode,
1864
+ onChange: (e) => setMfaCode(e.target.value),
1865
+ className: HeadlessLoginPanel_module_default.input,
1866
+ disabled: busy
1867
+ }
1868
+ ),
1869
+ /* @__PURE__ */ jsxRuntime.jsx(
1870
+ "button",
1871
+ {
1872
+ type: "submit",
1873
+ className: HeadlessLoginPanel_module_default.primaryBtn,
1874
+ disabled: busy || mfaCode.trim().length < 6,
1875
+ children: loading === "mfa" ? "\u2026" : labels.mfaSubmit
1876
+ }
1877
+ ),
1878
+ /* @__PURE__ */ jsxRuntime.jsx(
1879
+ "button",
1880
+ {
1881
+ type: "button",
1882
+ className: HeadlessLoginPanel_module_default.cancelBtn,
1883
+ disabled: busy,
1884
+ onClick: () => {
1885
+ setMfaPending(false);
1886
+ setMfaCode("");
1887
+ setError("");
1888
+ },
1889
+ children: labels.mfaBack
1890
+ }
1891
+ )
1892
+ ] }) : passwordEnabled ? /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: (e) => void runPassword(e), className: HeadlessLoginPanel_module_default.form, children: [
1358
1893
  isRegister && emailRegisterEnabled && usernameRegisterEnabled ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: HeadlessLoginPanel_module_default.channelTabs, role: "tablist", "aria-label": "Register method", children: [
1359
1894
  /* @__PURE__ */ jsxRuntime.jsx(
1360
1895
  "button",
@@ -1406,7 +1941,9 @@ function HeadlessLoginPanel({
1406
1941
  placeholder: identifierPlaceholder,
1407
1942
  value: identifier,
1408
1943
  onChange: (e) => {
1409
- setIdentifier(e.target.value);
1944
+ const next = e.target.value;
1945
+ setIdentifier(next);
1946
+ onIdentifierChange?.(next);
1410
1947
  if (useEmailRegister) {
1411
1948
  setEmailVerificationId(null);
1412
1949
  }
@@ -1493,6 +2030,13 @@ function HeadlessLoginPanel({
1493
2030
  children: loading === "sso" ? "\u2026" : labels.submitSso
1494
2031
  }
1495
2032
  ) }),
2033
+ consent || consentDocuments && consentDocuments.length > 0 || consentBlocked ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(HeadlessLoginPanel_module_default.consent, consentBlocked && HeadlessLoginPanel_module_default.consentInvalid), children: [
2034
+ consent ? consent : consentDocuments && consentDocuments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.consentLinks, children: consentDocuments.map((doc, index) => /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2035
+ index > 0 ? " \xB7 " : null,
2036
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: doc.href, target: "_blank", rel: "noopener noreferrer", children: doc.label })
2037
+ ] }, doc.id)) }) : null,
2038
+ consentBlocked ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.consentError, children: labels.consentRequired }) : null
2039
+ ] }) : null,
1496
2040
  showHint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.hint, children: hintText }) : null,
1497
2041
  registerEnabled && passwordEnabled ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.switchMode, children: /* @__PURE__ */ jsxRuntime.jsx(
1498
2042
  "button",
@@ -1678,6 +2222,159 @@ function useAuthGateOptional() {
1678
2222
  return react.useContext(AuthGateContext);
1679
2223
  }
1680
2224
 
2225
+ // src/login-legal.ts
2226
+ var DEFAULT_PLATFORM_TERMS_URL = "https://luminaryworks.dev/legal/terms";
2227
+ var DEFAULT_PLATFORM_PRIVACY_URL = "https://luminaryworks.dev/legal/privacy";
2228
+ function pickEnv(env, name) {
2229
+ const keys = [`VITE_${name}`, `PUBLIC_${name}`, `NEXT_PUBLIC_${name}`, name];
2230
+ for (const key of keys) {
2231
+ const value = env[key]?.trim();
2232
+ if (value) return value;
2233
+ }
2234
+ return void 0;
2235
+ }
2236
+ function readLoginLegalConfigFromEnv(env, defaults2) {
2237
+ return {
2238
+ platformTermsUrl: pickEnv(env, "LEGAL_PLATFORM_TERMS_URL") || defaults2?.platformTermsUrl || DEFAULT_PLATFORM_TERMS_URL,
2239
+ platformPrivacyUrl: pickEnv(env, "LEGAL_PLATFORM_PRIVACY_URL") || defaults2?.platformPrivacyUrl || DEFAULT_PLATFORM_PRIVACY_URL,
2240
+ productTermsUrl: pickEnv(env, "LEGAL_PRODUCT_TERMS_URL") || defaults2?.productTermsUrl || "/legal/terms",
2241
+ productPrivacyUrl: pickEnv(env, "LEGAL_PRODUCT_PRIVACY_URL") || defaults2?.productPrivacyUrl || "/legal/privacy"
2242
+ };
2243
+ }
2244
+ function buildLoginLegalDocuments(urls, labels) {
2245
+ const docs = [
2246
+ {
2247
+ id: "product-terms",
2248
+ href: urls.productTermsUrl,
2249
+ label: labels.productTerms
2250
+ },
2251
+ {
2252
+ id: "privacy",
2253
+ href: urls.productPrivacyUrl || urls.platformPrivacyUrl,
2254
+ label: labels.privacy
2255
+ }
2256
+ ];
2257
+ return docs.filter((row) => row.href.length > 0 && row.label.length > 0);
2258
+ }
2259
+
2260
+ // src/LoginLanguageSwitcher.module.scss
2261
+ var LoginLanguageSwitcher_module_default = {
2262
+ switch: "LoginLanguageSwitcher_module_switch",
2263
+ trigger: "LoginLanguageSwitcher_module_trigger",
2264
+ icon: "LoginLanguageSwitcher_module_icon",
2265
+ caret: "LoginLanguageSwitcher_module_caret",
2266
+ menu: "LoginLanguageSwitcher_module_menu",
2267
+ item: "LoginLanguageSwitcher_module_item",
2268
+ itemActive: "LoginLanguageSwitcher_module_itemActive",
2269
+ onDark: "LoginLanguageSwitcher_module_onDark"
2270
+ };
2271
+ function GlobeIcon() {
2272
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: LoginLanguageSwitcher_module_default.icon, viewBox: "0 0 24 24", "aria-hidden": "true", children: [
2273
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
2274
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "12", cy: "12", rx: "4", ry: "9", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
2275
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 12h18M5 8h14M5 16h14", fill: "none", stroke: "currentColor", strokeWidth: "1.6" })
2276
+ ] });
2277
+ }
2278
+ function LoginLanguageSwitcher({
2279
+ locale,
2280
+ onChange,
2281
+ locales = DEFAULT_LOGIN_LOCALES,
2282
+ label = "Language",
2283
+ variant = "default"
2284
+ }) {
2285
+ const [open, setOpen] = react.useState(false);
2286
+ const rootRef = react.useRef(null);
2287
+ const menuId = react.useId();
2288
+ const current = locales.find((item) => item.code === locale) ?? locales.find((item) => normalizeLoginLocale(item.code) === normalizeLoginLocale(locale)) ?? locales[0];
2289
+ react.useEffect(() => {
2290
+ if (!open) return;
2291
+ const onPointer = (event) => {
2292
+ if (!rootRef.current?.contains(event.target)) setOpen(false);
2293
+ };
2294
+ const onKey = (event) => {
2295
+ if (event.key === "Escape") setOpen(false);
2296
+ };
2297
+ document.addEventListener("mousedown", onPointer);
2298
+ document.addEventListener("keydown", onKey);
2299
+ return () => {
2300
+ document.removeEventListener("mousedown", onPointer);
2301
+ document.removeEventListener("keydown", onKey);
2302
+ };
2303
+ }, [open]);
2304
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: LoginLanguageSwitcher_module_default.switch, ref: rootRef, children: [
2305
+ /* @__PURE__ */ jsxRuntime.jsxs(
2306
+ "button",
2307
+ {
2308
+ type: "button",
2309
+ className: variant === "onDark" ? `${LoginLanguageSwitcher_module_default.trigger} ${LoginLanguageSwitcher_module_default.onDark}` : LoginLanguageSwitcher_module_default.trigger,
2310
+ "aria-label": label,
2311
+ "aria-haspopup": "listbox",
2312
+ "aria-expanded": open,
2313
+ "aria-controls": menuId,
2314
+ onClick: () => setOpen((value) => !value),
2315
+ children: [
2316
+ /* @__PURE__ */ jsxRuntime.jsx(GlobeIcon, {}),
2317
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: current?.short ?? "EN" }),
2318
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: LoginLanguageSwitcher_module_default.caret, viewBox: "0 0 12 12", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2.5 4.5 6 8l3.5-3.5", fill: "none", stroke: "currentColor", strokeWidth: "1.4" }) })
2319
+ ]
2320
+ }
2321
+ ),
2322
+ open ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: LoginLanguageSwitcher_module_default.menu, id: menuId, role: "listbox", "aria-label": label, children: locales.map((item) => {
2323
+ const active = item.code === current?.code;
2324
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { role: "presentation", children: /* @__PURE__ */ jsxRuntime.jsx(
2325
+ "button",
2326
+ {
2327
+ type: "button",
2328
+ role: "option",
2329
+ "aria-selected": active,
2330
+ className: active ? `${LoginLanguageSwitcher_module_default.item} ${LoginLanguageSwitcher_module_default.itemActive}` : LoginLanguageSwitcher_module_default.item,
2331
+ onClick: () => {
2332
+ onChange(item.code);
2333
+ setOpen(false);
2334
+ },
2335
+ children: item.label
2336
+ }
2337
+ ) }, item.code);
2338
+ }) }) : null
2339
+ ] });
2340
+ }
2341
+
2342
+ // src/LoginCanvas.module.scss
2343
+ var LoginCanvas_module_default = {
2344
+ canvas: "LoginCanvas_module_canvas",
2345
+ grid: "LoginCanvas_module_grid",
2346
+ lang: "LoginCanvas_module_lang",
2347
+ decor: "LoginCanvas_module_decor",
2348
+ slot: "LoginCanvas_module_slot",
2349
+ slotFill: "LoginCanvas_module_slotFill"
2350
+ };
2351
+ function LoginCanvas({
2352
+ tone,
2353
+ locale,
2354
+ onLocaleChange,
2355
+ locales,
2356
+ languageLabel,
2357
+ fill = false,
2358
+ decor,
2359
+ children
2360
+ }) {
2361
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: LoginCanvas_module_default.canvas, "data-tone": tone, children: [
2362
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: LoginCanvas_module_default.grid, "aria-hidden": "true" }),
2363
+ decor ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: LoginCanvas_module_default.decor, children: decor }) : null,
2364
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: LoginCanvas_module_default.lang, children: /* @__PURE__ */ jsxRuntime.jsx(
2365
+ LoginLanguageSwitcher,
2366
+ {
2367
+ locale,
2368
+ onChange: onLocaleChange,
2369
+ locales,
2370
+ label: languageLabel,
2371
+ variant: tone === "console" || tone === "data" || tone === "edu" ? "onDark" : "default"
2372
+ }
2373
+ ) }),
2374
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: fill ? `${LoginCanvas_module_default.slot} ${LoginCanvas_module_default.slotFill}` : LoginCanvas_module_default.slot, children })
2375
+ ] });
2376
+ }
2377
+
1681
2378
  // src/post-login-path.ts
1682
2379
  var DEFAULT_UNSAFE = ["/login", "/auth", "/exception"];
1683
2380
  function normalizeAppPath(path, fallback) {
@@ -1730,15 +2427,23 @@ function createPostLoginPathHelpers(options) {
1730
2427
 
1731
2428
  exports.AuthGateProvider = AuthGateProvider;
1732
2429
  exports.DEFAULT_DISPOSABLE_EMAIL_BLOCKLIST = DEFAULT_DISPOSABLE_EMAIL_BLOCKLIST;
2430
+ exports.DEFAULT_LOGIN_LOCALES = DEFAULT_LOGIN_LOCALES;
1733
2431
  exports.DEFAULT_LOGIN_THEME_COLOR = DEFAULT_LOGIN_THEME_COLOR;
2432
+ exports.DEFAULT_PLATFORM_PRIVACY_URL = DEFAULT_PLATFORM_PRIVACY_URL;
2433
+ exports.DEFAULT_PLATFORM_TERMS_URL = DEFAULT_PLATFORM_TERMS_URL;
1734
2434
  exports.DEFAULT_REGISTER_EMAIL_ALLOWLIST = DEFAULT_REGISTER_EMAIL_ALLOWLIST;
2435
+ exports.ExperienceApiError = ExperienceApiError;
1735
2436
  exports.HeadlessLoginPanel = HeadlessLoginPanel;
1736
2437
  exports.HostedOidcExperienceAdapter = HostedOidcExperienceAdapter;
2438
+ exports.LOGIN_CARD_MAX_WIDTH = LOGIN_CARD_MAX_WIDTH;
1737
2439
  exports.LOGIN_EXPERIENCE_CAPABILITIES = LOGIN_EXPERIENCE_CAPABILITIES;
2440
+ exports.LoginCanvas = LoginCanvas;
2441
+ exports.LoginLanguageSwitcher = LoginLanguageSwitcher;
1738
2442
  exports.LogtoExperienceAdapter = LogtoExperienceAdapter;
1739
2443
  exports.LuminaryAuthProvider = LuminaryAuthProvider;
1740
2444
  exports.ReauthOverlay = ReauthOverlay;
1741
2445
  exports.authGate = authGate;
2446
+ exports.buildLoginLegalDocuments = buildLoginLegalDocuments;
1742
2447
  exports.clearStoredSession = clearStoredSession;
1743
2448
  exports.createLoginExperienceAdapter = createLoginExperienceAdapter;
1744
2449
  exports.createLogtoDirectSignInRequest = createLogtoDirectSignInRequest;
@@ -1756,11 +2461,15 @@ exports.handleSignInCallback = handleSignInCallback;
1756
2461
  exports.handleSignInPopupCallback = handleSignInPopupCallback;
1757
2462
  exports.isIdpConfigured = isIdpConfigured;
1758
2463
  exports.isLogtoRegisterUsername = isLogtoRegisterUsername;
2464
+ exports.isMfaVerificationRequired = isMfaVerificationRequired;
1759
2465
  exports.isOidcPopupWindow = isOidcPopupWindow;
1760
2466
  exports.isValidEmailShape = isValidEmailShape;
2467
+ exports.loginLabels = loginLabels;
2468
+ exports.normalizeLoginLocale = normalizeLoginLocale;
1761
2469
  exports.normalizeRegisterEmailMode = normalizeRegisterEmailMode;
1762
2470
  exports.prepareSignInRequestUrl = prepareSignInRequestUrl;
1763
2471
  exports.readIdpConfigFromEnv = readIdpConfigFromEnv;
2472
+ exports.readLoginLegalConfigFromEnv = readLoginLegalConfigFromEnv;
1764
2473
  exports.readRegisterEmailPolicyFromEnv = readRegisterEmailPolicyFromEnv;
1765
2474
  exports.registerEmailDomainsHint = registerEmailDomainsHint;
1766
2475
  exports.registerEmailRejectionMessage = registerEmailRejectionMessage;