@luminaryworks/auth-react 0.4.3 → 0.4.5
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.css +19 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +36 -2
- package/dist/index.js +138 -10
- package/dist/index.js.map +1 -1
- package/dist/style.css +19 -0
- package/dist/style.css.map +1 -1
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -201,6 +201,25 @@
|
|
|
201
201
|
color: #6b7c87;
|
|
202
202
|
line-height: 1.45;
|
|
203
203
|
}
|
|
204
|
+
.HeadlessLoginPanel_module_switchMode {
|
|
205
|
+
margin: 12px 0 0;
|
|
206
|
+
text-align: center;
|
|
207
|
+
}
|
|
208
|
+
.HeadlessLoginPanel_module_switchModeBtn {
|
|
209
|
+
border: none;
|
|
210
|
+
background: transparent;
|
|
211
|
+
color: var(--lw-auth-theme);
|
|
212
|
+
font-size: 13px;
|
|
213
|
+
font-weight: 650;
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
padding: 4px 8px;
|
|
216
|
+
text-decoration: underline;
|
|
217
|
+
text-underline-offset: 3px;
|
|
218
|
+
}
|
|
219
|
+
.HeadlessLoginPanel_module_switchModeBtn:disabled {
|
|
220
|
+
opacity: 0.65;
|
|
221
|
+
cursor: not-allowed;
|
|
222
|
+
}
|
|
204
223
|
.HeadlessLoginPanel_module_error {
|
|
205
224
|
margin: 12px 0 0;
|
|
206
225
|
font-size: 13px;
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/HeadlessLoginPanel.module.scss"],"sourcesContent":["$ink: #14212b;\n$muted: #4b5c68;\n$hint: #6b7c87;\n$brand: #3d6f8f;\n$brand-deep: #15485c;\n$brand-mid: #1f6f8b;\n$border: #c9d5de;\n$border-soft: #b7c9d4;\n$line: #d5e0e7;\n$divider: #90a0ab;\n$surface: #f7fafc;\n$fallback-bg: #e8eef2;\n$danger: #b42318;\n$footer-line: #e4ebf0;\n$radius-lg: 16px;\n$radius-md: 10px;\n$radius-sm: 4px;\n\n.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: $radius-lg;\n background: rgba(255, 255, 255, 0.96);\n color: $ink;\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n font-family: \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif;\n}\n\n.brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.logo {\n border-radius: 12px;\n display: block;\n}\n\n.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\n.title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: $muted;\n}\n\n.form {\n display: grid;\n gap: 10px;\n}\n\n.socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.input {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid $border;\n border-radius: $radius-md;\n padding: 10px 12px;\n font-size: 14px;\n outline: none;\n background: $surface;\n\n &:focus {\n border-color: var(--lw-auth-theme);\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.passwordInput {\n padding-right: 42px;\n}\n\n.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: $radius-sm;\n padding: 0;\n color: #5a6b76;\n background: transparent;\n cursor: pointer;\n\n &:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n }\n\n &:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.primaryBtn {\n border: none;\n border-radius: $radius-md;\n padding: 11px 14px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #fff;\n background: linear-gradient(135deg, var(--lw-auth-theme) 0%, var(--lw-auth-theme-deep) 100%);\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.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 $border-soft;\n border-radius: $radius-md;\n padding: 11px 10px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: $ink;\n background: #fff;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialLogo {\n flex-shrink: 0;\n display: block;\n}\n\n.logoFallback {\n width: 18px;\n height: 18px;\n border-radius: $radius-sm;\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\n.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 &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: $divider;\n}\n\n.dividerLine {\n flex: 1;\n height: 1px;\n background: $line;\n}\n\n.dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: $hint;\n line-height: 1.45;\n}\n\n.error {\n margin: 12px 0 0;\n font-size: 13px;\n color: $danger;\n line-height: 1.4;\n}\n\n.footer {\n margin-top: 18px;\n padding-top: 12px;\n border-top: 1px solid $footer-line;\n font-size: 12px;\n color: $hint;\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n"],"mappings":"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
|
|
1
|
+
{"version":3,"sources":["../src/HeadlessLoginPanel.module.scss"],"sourcesContent":["$ink: #14212b;\n$muted: #4b5c68;\n$hint: #6b7c87;\n$brand: #3d6f8f;\n$brand-deep: #15485c;\n$brand-mid: #1f6f8b;\n$border: #c9d5de;\n$border-soft: #b7c9d4;\n$line: #d5e0e7;\n$divider: #90a0ab;\n$surface: #f7fafc;\n$fallback-bg: #e8eef2;\n$danger: #b42318;\n$footer-line: #e4ebf0;\n$radius-lg: 16px;\n$radius-md: 10px;\n$radius-sm: 4px;\n\n.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: $radius-lg;\n background: rgba(255, 255, 255, 0.96);\n color: $ink;\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n font-family: \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif;\n}\n\n.brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.logo {\n border-radius: 12px;\n display: block;\n}\n\n.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\n.title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: $muted;\n}\n\n.form {\n display: grid;\n gap: 10px;\n}\n\n.socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.input {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid $border;\n border-radius: $radius-md;\n padding: 10px 12px;\n font-size: 14px;\n outline: none;\n background: $surface;\n\n &:focus {\n border-color: var(--lw-auth-theme);\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.passwordInput {\n padding-right: 42px;\n}\n\n.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: $radius-sm;\n padding: 0;\n color: #5a6b76;\n background: transparent;\n cursor: pointer;\n\n &:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n }\n\n &:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.primaryBtn {\n border: none;\n border-radius: $radius-md;\n padding: 11px 14px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #fff;\n background: linear-gradient(135deg, var(--lw-auth-theme) 0%, var(--lw-auth-theme-deep) 100%);\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.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 $border-soft;\n border-radius: $radius-md;\n padding: 11px 10px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: $ink;\n background: #fff;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialLogo {\n flex-shrink: 0;\n display: block;\n}\n\n.logoFallback {\n width: 18px;\n height: 18px;\n border-radius: $radius-sm;\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\n.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 &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: $divider;\n}\n\n.dividerLine {\n flex: 1;\n height: 1px;\n background: $line;\n}\n\n.dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: $hint;\n line-height: 1.45;\n}\n\n.switchMode {\n margin: 12px 0 0;\n text-align: center;\n}\n\n.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 &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.error {\n margin: 12px 0 0;\n font-size: 13px;\n color: $danger;\n line-height: 1.4;\n}\n\n.footer {\n margin-top: 18px;\n padding-top: 12px;\n border-top: 1px solid $footer-line;\n font-size: 12px;\n color: $hint;\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n"],"mappings":"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","names":["panel","brand","logo","product","title","subtitle","form","socialStack","input","passwordField","passwordInput","passwordToggle","primaryBtn","socialBtn","socialLogo","logoFallback","cancelBtn","divider","dividerLine","dividerText","hint","switchMode","switchModeBtn","error","footer"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -98,6 +98,8 @@ declare function getCurrentUser(config: LuminaryIdpConfig): Promise<LuminaryAuth
|
|
|
98
98
|
*/
|
|
99
99
|
declare const LOGIN_EXPERIENCE_CAPABILITIES: {
|
|
100
100
|
readonly passwordSignIn: "password-sign-in";
|
|
101
|
+
/** Username + password self-register via Experience (Logto NewPasswordIdentity). */
|
|
102
|
+
readonly passwordSignUp: "password-sign-up";
|
|
101
103
|
readonly socialConnectors: "social-connectors";
|
|
102
104
|
readonly socialDirectSignIn: "social-direct-sign-in";
|
|
103
105
|
};
|
|
@@ -123,6 +125,9 @@ interface ExperiencePasswordSignInResult {
|
|
|
123
125
|
redirectTo?: string;
|
|
124
126
|
raw?: unknown;
|
|
125
127
|
}
|
|
128
|
+
/** Same OIDC bootstrap fields as sign-in; username must match Logto username rules. */
|
|
129
|
+
type ExperiencePasswordSignUpInput = ExperiencePasswordSignInInput;
|
|
130
|
+
type ExperiencePasswordSignUpResult = ExperiencePasswordSignInResult;
|
|
126
131
|
interface ExperienceSocialConnector {
|
|
127
132
|
id: string;
|
|
128
133
|
target: string;
|
|
@@ -148,6 +153,11 @@ interface LoginExperienceAdapter {
|
|
|
148
153
|
readonly provider: string;
|
|
149
154
|
readonly capabilities: readonly LoginExperienceCapability[];
|
|
150
155
|
experiencePasswordSignIn?(input: ExperiencePasswordSignInInput): Promise<ExperiencePasswordSignInResult>;
|
|
156
|
+
/**
|
|
157
|
+
* Self-register with username + password (Logto Register + NewPasswordIdentity).
|
|
158
|
+
* Email/phone sign-up needs verification codes — not covered by this method.
|
|
159
|
+
*/
|
|
160
|
+
experiencePasswordSignUp?(input: ExperiencePasswordSignUpInput): Promise<ExperiencePasswordSignUpResult>;
|
|
151
161
|
fetchSocialConnectors?(input: FetchSocialConnectorsInput): Promise<ExperienceSocialConnector[]>;
|
|
152
162
|
createSocialSignInRequest?(target: string): SocialSignInRequest;
|
|
153
163
|
}
|
|
@@ -176,6 +186,7 @@ declare function resolveLoginExperienceProviderFromEnv(env?: Record<string, stri
|
|
|
176
186
|
* work on HTTP localhost.
|
|
177
187
|
*/
|
|
178
188
|
|
|
189
|
+
declare function isLogtoRegisterUsername(value: string): boolean;
|
|
179
190
|
/**
|
|
180
191
|
* Force authorize onto the Experience/SPA origin so Set-Cookie lands on the
|
|
181
192
|
* same host as subsequent `/api/experience` calls (dev proxy strips Domain).
|
|
@@ -188,6 +199,11 @@ declare class LogtoExperienceAdapter implements LoginExperienceAdapter {
|
|
|
188
199
|
readonly provider = "logto";
|
|
189
200
|
readonly capabilities: readonly LoginExperienceCapability[];
|
|
190
201
|
experiencePasswordSignIn(input: ExperiencePasswordSignInInput): Promise<ExperiencePasswordSignInResult>;
|
|
202
|
+
/**
|
|
203
|
+
* Register with username + password via NewPasswordIdentity.
|
|
204
|
+
* Email/phone self-register requires verification codes — use social or invite instead.
|
|
205
|
+
*/
|
|
206
|
+
experiencePasswordSignUp(input: ExperiencePasswordSignUpInput): Promise<ExperiencePasswordSignUpResult>;
|
|
191
207
|
fetchSocialConnectors(input: FetchSocialConnectorsInput): Promise<ExperienceSocialConnector[]>;
|
|
192
208
|
createSocialSignInRequest(target: string): SocialSignInRequest;
|
|
193
209
|
}
|
|
@@ -300,18 +316,30 @@ interface HeadlessLoginLabels {
|
|
|
300
316
|
title?: string;
|
|
301
317
|
subtitle?: string;
|
|
302
318
|
identifierPlaceholder?: string;
|
|
319
|
+
/** Placeholder when panel is in register mode (username). */
|
|
320
|
+
registerIdentifierPlaceholder?: string;
|
|
303
321
|
passwordPlaceholder?: string;
|
|
322
|
+
confirmPasswordPlaceholder?: string;
|
|
304
323
|
submitPassword?: string;
|
|
324
|
+
submitRegister?: string;
|
|
305
325
|
/** Hosted OIDC button shown when the adapter has no password capability. */
|
|
306
326
|
submitSso?: string;
|
|
307
327
|
submitGoogle?: string;
|
|
308
328
|
submitGithub?: string;
|
|
309
329
|
socialDivider?: string;
|
|
310
330
|
hint?: string;
|
|
331
|
+
registerHint?: string;
|
|
311
332
|
cancel?: string;
|
|
312
333
|
experienceUnavailable?: string;
|
|
313
334
|
showPassword?: string;
|
|
314
335
|
hidePassword?: string;
|
|
336
|
+
/** Switch link when on sign-in: "Create an account" */
|
|
337
|
+
registerLink?: string;
|
|
338
|
+
/** Switch link when on register: "Already have an account? Sign in" */
|
|
339
|
+
loginLink?: string;
|
|
340
|
+
passwordMismatch?: string;
|
|
341
|
+
registerTitle?: string;
|
|
342
|
+
registerSubtitle?: string;
|
|
315
343
|
}
|
|
316
344
|
interface HeadlessLoginPanelProps {
|
|
317
345
|
config: Partial<LuminaryIdpConfig>;
|
|
@@ -332,6 +360,12 @@ interface HeadlessLoginPanelProps {
|
|
|
332
360
|
* Equivalent to `socialProviders={[]}` when false.
|
|
333
361
|
*/
|
|
334
362
|
showSocialConnectors?: boolean;
|
|
363
|
+
/**
|
|
364
|
+
* Show self-register switch + register form (username + password via Experience).
|
|
365
|
+
* Default `true` for end-user product logins. Set `false` for admin / ops consoles.
|
|
366
|
+
* Hosted OIDC adapters without passwordSignUp hide register automatically.
|
|
367
|
+
*/
|
|
368
|
+
showRegister?: boolean;
|
|
335
369
|
/**
|
|
336
370
|
* Social providers (when `showSocialConnectors` is not `false`):
|
|
337
371
|
* - omit / `"auto"` — load enabled connectors from IdP (google, github, x, …)
|
|
@@ -359,7 +393,7 @@ interface HeadlessLoginPanelProps {
|
|
|
359
393
|
}
|
|
360
394
|
/** Shared default accent for product login panels (shared/brand --lw-primary). */
|
|
361
395
|
declare const DEFAULT_LOGIN_THEME_COLOR = "#1677ff";
|
|
362
|
-
declare function HeadlessLoginPanel({ config, experienceAdapter: experienceAdapterProp, productName, logoSrc, labels: labelsProp, returnUrl, mode, showSocialConnectors, socialProviders, showCancel, onCancel, onOidcSession, onExperienceRedirect, footer, className, style, themeColor, }: HeadlessLoginPanelProps): react.JSX.Element;
|
|
396
|
+
declare function HeadlessLoginPanel({ config, experienceAdapter: experienceAdapterProp, productName, logoSrc, labels: labelsProp, returnUrl, mode, showSocialConnectors, showRegister, socialProviders, showCancel, onCancel, onOidcSession, onExperienceRedirect, footer, className, style, themeColor, }: HeadlessLoginPanelProps): react.JSX.Element;
|
|
363
397
|
|
|
364
398
|
interface ReauthOverlayProps {
|
|
365
399
|
config: Partial<LuminaryIdpConfig>;
|
|
@@ -422,4 +456,4 @@ declare function createPostLoginPathHelpers(options: PostLoginPathOptions): {
|
|
|
422
456
|
isUnsafeReturnPath: (path: string) => boolean;
|
|
423
457
|
};
|
|
424
458
|
|
|
425
|
-
export { type AuthGateConfig, type AuthGatePhase, AuthGateProvider, type AuthGateProviderProps, type AuthGateSnapshot, DEFAULT_LOGIN_THEME_COLOR, type ExperienceIdentifierType, type ExperiencePasswordSignInInput, type ExperiencePasswordSignInResult, type ExperienceSocialConnector, type FetchSocialConnectorsInput, type HeadlessLoginLabels, HeadlessLoginPanel, type HeadlessLoginPanelProps, HostedOidcExperienceAdapter, LOGIN_EXPERIENCE_CAPABILITIES, type LoginExperienceAdapter, type LoginExperienceCapability, type LoginExperienceProvider, LogtoExperienceAdapter, LuminaryAuthProvider, type LuminaryAuthProviderProps, type LuminaryAuthSession, type LuminaryIdpConfig, type PostLoginPathOptions, ReauthOverlay, type ReauthOverlayProps, type SignInOptions, type SocialProviderTarget, type SocialSignInRequest, type UnauthorizedDisposition, authGate, clearStoredSession, createLoginExperienceAdapter, createLogtoDirectSignInRequest, createPostLoginPathHelpers, createUserManager, experiencePasswordSignIn, fetchSocialConnectors, getCurrentUser, getStoredAccessToken, handleSignInCallback, handleSignInPopupCallback, isIdpConfigured, isOidcPopupWindow, prepareSignInRequestUrl, readIdpConfigFromEnv, resetUserManager, resolveExperienceApiBase, resolveIssuer, resolveLoginExperienceAdapter, resolveLoginExperienceProviderFromEnv, sameOriginAuthorizeUrl, signInPopup, signInRedirect, signOutRedirect, useAuthGate, useAuthGateOptional, useLuminaryAuth, withAuthGateRetry };
|
|
459
|
+
export { type AuthGateConfig, type AuthGatePhase, AuthGateProvider, type AuthGateProviderProps, type AuthGateSnapshot, DEFAULT_LOGIN_THEME_COLOR, type ExperienceIdentifierType, type ExperiencePasswordSignInInput, type ExperiencePasswordSignInResult, type ExperiencePasswordSignUpInput, type ExperiencePasswordSignUpResult, type ExperienceSocialConnector, type FetchSocialConnectorsInput, type HeadlessLoginLabels, HeadlessLoginPanel, type HeadlessLoginPanelProps, HostedOidcExperienceAdapter, LOGIN_EXPERIENCE_CAPABILITIES, type LoginExperienceAdapter, type LoginExperienceCapability, type LoginExperienceProvider, LogtoExperienceAdapter, LuminaryAuthProvider, type LuminaryAuthProviderProps, type LuminaryAuthSession, type LuminaryIdpConfig, type PostLoginPathOptions, ReauthOverlay, type ReauthOverlayProps, type SignInOptions, type SocialProviderTarget, type SocialSignInRequest, type UnauthorizedDisposition, authGate, clearStoredSession, createLoginExperienceAdapter, createLogtoDirectSignInRequest, createPostLoginPathHelpers, createUserManager, experiencePasswordSignIn, fetchSocialConnectors, getCurrentUser, getStoredAccessToken, handleSignInCallback, handleSignInPopupCallback, isIdpConfigured, isLogtoRegisterUsername, isOidcPopupWindow, prepareSignInRequestUrl, readIdpConfigFromEnv, resetUserManager, resolveExperienceApiBase, resolveIssuer, resolveLoginExperienceAdapter, resolveLoginExperienceProviderFromEnv, sameOriginAuthorizeUrl, signInPopup, signInRedirect, signOutRedirect, useAuthGate, useAuthGateOptional, useLuminaryAuth, withAuthGateRetry };
|
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_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_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 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_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_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);})();
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var oidcClientTs = require('oidc-client-ts');
|
|
@@ -53,6 +53,8 @@ var HostedOidcExperienceAdapter = class {
|
|
|
53
53
|
// src/login-experience-adapter.ts
|
|
54
54
|
var LOGIN_EXPERIENCE_CAPABILITIES = {
|
|
55
55
|
passwordSignIn: "password-sign-in",
|
|
56
|
+
/** Username + password self-register via Experience (Logto NewPasswordIdentity). */
|
|
57
|
+
passwordSignUp: "password-sign-up",
|
|
56
58
|
socialConnectors: "social-connectors",
|
|
57
59
|
socialDirectSignIn: "social-direct-sign-in"
|
|
58
60
|
};
|
|
@@ -85,6 +87,10 @@ function resolveLoginExperienceProviderFromEnv(env = {}) {
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
// src/logto-experience-adapter.ts
|
|
90
|
+
var LOGTO_USERNAME_RE = /^[A-Za-z_]\w*$/;
|
|
91
|
+
function isLogtoRegisterUsername(value) {
|
|
92
|
+
return LOGTO_USERNAME_RE.test(value.trim());
|
|
93
|
+
}
|
|
88
94
|
function experienceUrl(apiBase, path) {
|
|
89
95
|
return `${apiBase.replace(/\/$/, "")}/api/experience${path}`;
|
|
90
96
|
}
|
|
@@ -166,6 +172,7 @@ var LogtoExperienceAdapter = class {
|
|
|
166
172
|
provider = "logto";
|
|
167
173
|
capabilities = [
|
|
168
174
|
LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn,
|
|
175
|
+
LOGIN_EXPERIENCE_CAPABILITIES.passwordSignUp,
|
|
169
176
|
LOGIN_EXPERIENCE_CAPABILITIES.socialConnectors,
|
|
170
177
|
LOGIN_EXPERIENCE_CAPABILITIES.socialDirectSignIn
|
|
171
178
|
];
|
|
@@ -215,6 +222,51 @@ var LogtoExperienceAdapter = class {
|
|
|
215
222
|
}
|
|
216
223
|
throw lastError ?? new Error("Experience password sign-in failed");
|
|
217
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Register with username + password via NewPasswordIdentity.
|
|
227
|
+
* Email/phone self-register requires verification codes — use social or invite instead.
|
|
228
|
+
*/
|
|
229
|
+
async experiencePasswordSignUp(input) {
|
|
230
|
+
const { apiBase, identifier, password } = input;
|
|
231
|
+
const username = identifier.trim();
|
|
232
|
+
if (!isLogtoRegisterUsername(username)) {
|
|
233
|
+
throw new Error(
|
|
234
|
+
"Register with a username (letters, digits, underscore; start with a letter or _). Use social login for email-based accounts."
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
if (!password || password.length < 8) {
|
|
238
|
+
throw new Error("Password must be at least 8 characters");
|
|
239
|
+
}
|
|
240
|
+
await bootstrapOidcInteraction(input);
|
|
241
|
+
await experienceFetch(apiBase, "", {
|
|
242
|
+
method: "PUT",
|
|
243
|
+
body: JSON.stringify({ interactionEvent: "Register" })
|
|
244
|
+
});
|
|
245
|
+
const verified = await experienceFetch(
|
|
246
|
+
apiBase,
|
|
247
|
+
"/verification/new-password-identity",
|
|
248
|
+
{
|
|
249
|
+
method: "POST",
|
|
250
|
+
body: JSON.stringify({
|
|
251
|
+
identifier: { type: "username", value: username },
|
|
252
|
+
password
|
|
253
|
+
})
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
const verificationId = verified?.verificationId;
|
|
257
|
+
if (!verificationId) {
|
|
258
|
+
throw new Error("Experience API did not return verificationId");
|
|
259
|
+
}
|
|
260
|
+
await experienceFetch(apiBase, "/identification", {
|
|
261
|
+
method: "POST",
|
|
262
|
+
body: JSON.stringify({ verificationId })
|
|
263
|
+
});
|
|
264
|
+
const submitted = await experienceFetch(apiBase, "/submit", {
|
|
265
|
+
method: "POST",
|
|
266
|
+
body: JSON.stringify({})
|
|
267
|
+
});
|
|
268
|
+
return { redirectTo: submitted?.redirectTo, raw: submitted };
|
|
269
|
+
}
|
|
218
270
|
async fetchSocialConnectors(input) {
|
|
219
271
|
const url = new URL(`${input.apiBase.replace(/\/$/, "")}/api/.well-known/sign-in-exp`);
|
|
220
272
|
if (input.appId?.trim()) url.searchParams.set("appId", input.appId.trim());
|
|
@@ -640,6 +692,8 @@ var HeadlessLoginPanel_module_default = {
|
|
|
640
692
|
dividerLine: "HeadlessLoginPanel_module_dividerLine",
|
|
641
693
|
dividerText: "HeadlessLoginPanel_module_dividerText",
|
|
642
694
|
hint: "HeadlessLoginPanel_module_hint",
|
|
695
|
+
switchMode: "HeadlessLoginPanel_module_switchMode",
|
|
696
|
+
switchModeBtn: "HeadlessLoginPanel_module_switchModeBtn",
|
|
643
697
|
error: "HeadlessLoginPanel_module_error",
|
|
644
698
|
footer: "HeadlessLoginPanel_module_footer"
|
|
645
699
|
};
|
|
@@ -648,17 +702,26 @@ var defaults = {
|
|
|
648
702
|
title: "Sign in",
|
|
649
703
|
subtitle: "Use your LuminaryWorks unified account",
|
|
650
704
|
identifierPlaceholder: "Email or username",
|
|
705
|
+
registerIdentifierPlaceholder: "Username",
|
|
651
706
|
passwordPlaceholder: "Password",
|
|
707
|
+
confirmPasswordPlaceholder: "Confirm password",
|
|
652
708
|
submitPassword: "Sign in with password",
|
|
709
|
+
submitRegister: "Create account",
|
|
653
710
|
submitSso: "Continue with unified account",
|
|
654
711
|
submitGoogle: "Google",
|
|
655
712
|
submitGithub: "GitHub",
|
|
656
713
|
socialDivider: "or",
|
|
657
714
|
hint: "Social providers open directly. Password uses your LuminaryWorks account.",
|
|
715
|
+
registerHint: "Create a username (start with a letter or _). Prefer email? Use a social provider below.",
|
|
658
716
|
cancel: "Cancel",
|
|
659
717
|
experienceUnavailable: "Password sign-in is unavailable; use a social provider instead.",
|
|
660
718
|
showPassword: "Show password",
|
|
661
|
-
hidePassword: "Hide password"
|
|
719
|
+
hidePassword: "Hide password",
|
|
720
|
+
registerLink: "Create an account",
|
|
721
|
+
loginLink: "Already have an account? Sign in",
|
|
722
|
+
passwordMismatch: "Passwords do not match",
|
|
723
|
+
registerTitle: "Create account",
|
|
724
|
+
registerSubtitle: "Create your LuminaryWorks unified account"
|
|
662
725
|
};
|
|
663
726
|
function resolveSieBase(config) {
|
|
664
727
|
const explicit = config.experienceApiBase?.trim();
|
|
@@ -688,6 +751,7 @@ function HeadlessLoginPanel({
|
|
|
688
751
|
returnUrl,
|
|
689
752
|
mode = "popup",
|
|
690
753
|
showSocialConnectors = true,
|
|
754
|
+
showRegister = true,
|
|
691
755
|
socialProviders = "auto",
|
|
692
756
|
showCancel,
|
|
693
757
|
onCancel,
|
|
@@ -704,8 +768,10 @@ function HeadlessLoginPanel({
|
|
|
704
768
|
);
|
|
705
769
|
const labels = { ...defaults, ...labelsProp };
|
|
706
770
|
const configured = isIdpConfigured(config);
|
|
771
|
+
const [panelMode, setPanelMode] = react.useState("sign-in");
|
|
707
772
|
const [identifier, setIdentifier] = react.useState("");
|
|
708
773
|
const [password, setPassword] = react.useState("");
|
|
774
|
+
const [confirmPassword, setConfirmPassword] = react.useState("");
|
|
709
775
|
const [passwordVisible, setPasswordVisible] = react.useState(false);
|
|
710
776
|
const panelStyle = {
|
|
711
777
|
...style,
|
|
@@ -716,6 +782,8 @@ function HeadlessLoginPanel({
|
|
|
716
782
|
const [connectors, setConnectors] = react.useState([]);
|
|
717
783
|
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";
|
|
718
784
|
const passwordEnabled = experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn) && typeof experienceAdapter.experiencePasswordSignIn === "function";
|
|
785
|
+
const registerEnabled = showRegister !== false && experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.passwordSignUp) && typeof experienceAdapter.experiencePasswordSignUp === "function";
|
|
786
|
+
const isRegister = panelMode === "register" && registerEnabled;
|
|
719
787
|
react.useEffect(() => {
|
|
720
788
|
const resetBusy = () => setLoading(null);
|
|
721
789
|
window.addEventListener("pageshow", resetBusy);
|
|
@@ -812,6 +880,30 @@ function HeadlessLoginPanel({
|
|
|
812
880
|
if (!apiBase) {
|
|
813
881
|
throw new Error(labels.experienceUnavailable);
|
|
814
882
|
}
|
|
883
|
+
if (isRegister) {
|
|
884
|
+
if (!registerEnabled || !experienceAdapter.experiencePasswordSignUp) {
|
|
885
|
+
throw new Error(labels.experienceUnavailable);
|
|
886
|
+
}
|
|
887
|
+
if (password !== confirmPassword) {
|
|
888
|
+
throw new Error(labels.passwordMismatch);
|
|
889
|
+
}
|
|
890
|
+
const result2 = await experienceAdapter.experiencePasswordSignUp({
|
|
891
|
+
apiBase,
|
|
892
|
+
identifier: identifier.trim(),
|
|
893
|
+
password,
|
|
894
|
+
issuer: config.issuer,
|
|
895
|
+
clientId: config.clientId,
|
|
896
|
+
redirectUri: config.redirectUri,
|
|
897
|
+
audience: config.audience,
|
|
898
|
+
scopes: config.scopes,
|
|
899
|
+
returnUrl
|
|
900
|
+
});
|
|
901
|
+
if (result2.redirectTo) {
|
|
902
|
+
followExperienceRedirect(result2.redirectTo);
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
throw new Error("Experience API did not return redirectTo");
|
|
906
|
+
}
|
|
815
907
|
if (!passwordEnabled || !experienceAdapter.capabilities.includes(
|
|
816
908
|
LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn
|
|
817
909
|
) || !experienceAdapter.experiencePasswordSignIn) {
|
|
@@ -838,18 +930,29 @@ function HeadlessLoginPanel({
|
|
|
838
930
|
setLoading(null);
|
|
839
931
|
}
|
|
840
932
|
};
|
|
933
|
+
const switchPanelMode = (next) => {
|
|
934
|
+
setPanelMode(next);
|
|
935
|
+
setError("");
|
|
936
|
+
setConfirmPassword("");
|
|
937
|
+
};
|
|
841
938
|
const busy = loading !== null;
|
|
842
939
|
const showSocial = socialEnabled && connectors.length > 0;
|
|
843
|
-
const showHint = Boolean(labelsProp?.hint) || showSocial;
|
|
940
|
+
const showHint = Boolean(labelsProp?.hint) || showSocial || isRegister;
|
|
941
|
+
const formReady = Boolean(identifier.trim()) && Boolean(password) && (!isRegister || Boolean(confirmPassword));
|
|
942
|
+
const titleText = isRegister ? labels.registerTitle : labels.title;
|
|
943
|
+
const subtitleText = isRegister ? labels.registerSubtitle : labels.subtitle;
|
|
944
|
+
const identifierPlaceholder = isRegister ? labels.registerIdentifierPlaceholder : labels.identifierPlaceholder;
|
|
945
|
+
const submitLabel = isRegister ? labels.submitRegister : labels.submitPassword;
|
|
946
|
+
const hintText = isRegister ? labels.registerHint : labels.hint;
|
|
844
947
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(HeadlessLoginPanel_module_default.panel, className), style: panelStyle, children: [
|
|
845
948
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: HeadlessLoginPanel_module_default.brand, children: [
|
|
846
949
|
logoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSrc, alt: "", width: 48, height: 48, className: HeadlessLoginPanel_module_default.logo }) : null,
|
|
847
950
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
848
951
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.product, children: productName }),
|
|
849
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: HeadlessLoginPanel_module_default.title, children:
|
|
952
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: HeadlessLoginPanel_module_default.title, children: titleText })
|
|
850
953
|
] })
|
|
851
954
|
] }),
|
|
852
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.subtitle, children:
|
|
955
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.subtitle, children: subtitleText }),
|
|
853
956
|
configured ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
854
957
|
passwordEnabled ? /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: (e) => void runPassword(e), className: HeadlessLoginPanel_module_default.form, children: [
|
|
855
958
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -857,8 +960,8 @@ function HeadlessLoginPanel({
|
|
|
857
960
|
{
|
|
858
961
|
type: "text",
|
|
859
962
|
name: "identifier",
|
|
860
|
-
autoComplete: "username",
|
|
861
|
-
placeholder:
|
|
963
|
+
autoComplete: isRegister ? "username" : "username",
|
|
964
|
+
placeholder: identifierPlaceholder,
|
|
862
965
|
value: identifier,
|
|
863
966
|
onChange: (e) => setIdentifier(e.target.value),
|
|
864
967
|
className: HeadlessLoginPanel_module_default.input,
|
|
@@ -871,7 +974,7 @@ function HeadlessLoginPanel({
|
|
|
871
974
|
{
|
|
872
975
|
type: passwordVisible ? "text" : "password",
|
|
873
976
|
name: "password",
|
|
874
|
-
autoComplete: "current-password",
|
|
977
|
+
autoComplete: isRegister ? "new-password" : "current-password",
|
|
875
978
|
placeholder: labels.passwordPlaceholder,
|
|
876
979
|
value: password,
|
|
877
980
|
onChange: (e) => setPassword(e.target.value),
|
|
@@ -892,7 +995,20 @@ function HeadlessLoginPanel({
|
|
|
892
995
|
}
|
|
893
996
|
)
|
|
894
997
|
] }),
|
|
895
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
998
|
+
isRegister ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: HeadlessLoginPanel_module_default.passwordField, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
999
|
+
"input",
|
|
1000
|
+
{
|
|
1001
|
+
type: passwordVisible ? "text" : "password",
|
|
1002
|
+
name: "confirmPassword",
|
|
1003
|
+
autoComplete: "new-password",
|
|
1004
|
+
placeholder: labels.confirmPasswordPlaceholder,
|
|
1005
|
+
value: confirmPassword,
|
|
1006
|
+
onChange: (e) => setConfirmPassword(e.target.value),
|
|
1007
|
+
className: cx(HeadlessLoginPanel_module_default.input, HeadlessLoginPanel_module_default.passwordInput),
|
|
1008
|
+
disabled: busy
|
|
1009
|
+
}
|
|
1010
|
+
) }) : null,
|
|
1011
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: HeadlessLoginPanel_module_default.primaryBtn, disabled: busy || !formReady, children: loading === "password" ? "\u2026" : submitLabel })
|
|
896
1012
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: HeadlessLoginPanel_module_default.form, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
897
1013
|
"button",
|
|
898
1014
|
{
|
|
@@ -903,7 +1019,17 @@ function HeadlessLoginPanel({
|
|
|
903
1019
|
children: loading === "sso" ? "\u2026" : labels.submitSso
|
|
904
1020
|
}
|
|
905
1021
|
) }),
|
|
906
|
-
showHint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.hint, children:
|
|
1022
|
+
showHint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.hint, children: hintText }) : null,
|
|
1023
|
+
registerEnabled && passwordEnabled ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: HeadlessLoginPanel_module_default.switchMode, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1024
|
+
"button",
|
|
1025
|
+
{
|
|
1026
|
+
type: "button",
|
|
1027
|
+
className: HeadlessLoginPanel_module_default.switchModeBtn,
|
|
1028
|
+
disabled: busy,
|
|
1029
|
+
onClick: () => switchPanelMode(isRegister ? "sign-in" : "register"),
|
|
1030
|
+
children: isRegister ? labels.loginLink : labels.registerLink
|
|
1031
|
+
}
|
|
1032
|
+
) }) : null,
|
|
907
1033
|
showSocial ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: HeadlessLoginPanel_module_default.divider, "aria-hidden": true, children: [
|
|
908
1034
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: HeadlessLoginPanel_module_default.dividerLine }),
|
|
909
1035
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: HeadlessLoginPanel_module_default.dividerText, children: labels.socialDivider }),
|
|
@@ -997,6 +1123,7 @@ function ReauthOverlay({
|
|
|
997
1123
|
},
|
|
998
1124
|
returnUrl: resolvedReturnUrl,
|
|
999
1125
|
mode: "popup",
|
|
1126
|
+
showRegister: false,
|
|
1000
1127
|
showCancel: dismissible,
|
|
1001
1128
|
onCancel: handleCancel,
|
|
1002
1129
|
onOidcSession: handleSession
|
|
@@ -1147,6 +1274,7 @@ exports.getStoredAccessToken = getStoredAccessToken;
|
|
|
1147
1274
|
exports.handleSignInCallback = handleSignInCallback;
|
|
1148
1275
|
exports.handleSignInPopupCallback = handleSignInPopupCallback;
|
|
1149
1276
|
exports.isIdpConfigured = isIdpConfigured;
|
|
1277
|
+
exports.isLogtoRegisterUsername = isLogtoRegisterUsername;
|
|
1150
1278
|
exports.isOidcPopupWindow = isOidcPopupWindow;
|
|
1151
1279
|
exports.prepareSignInRequestUrl = prepareSignInRequestUrl;
|
|
1152
1280
|
exports.readIdpConfigFromEnv = readIdpConfigFromEnv;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/hosted-oidc-experience-adapter.ts","../src/login-experience-adapter.ts","../src/logto-experience-adapter.ts","../src/oidc-client.ts","../src/experience-client.ts","../src/auth-gate.ts","../src/LuminaryAuthProvider.tsx","../src/HeadlessLoginPanel.module.scss","../src/HeadlessLoginPanel.tsx","../src/ReauthOverlay.tsx","../src/AuthGateProvider.tsx","../src/post-login-path.ts"],"names":["WebStorageStateStore","UserManager","OidcClient","createContext","useMemo","useState","useCallback","useEffect","jsx","useContext","panel","brand","logo","product","title","subtitle","form","socialStack","input","passwordField","passwordInput","passwordToggle","primaryBtn","socialBtn","socialLogo","logoFallback","cancelBtn","divider","dividerLine","dividerText","hint","error","footer","jsxs","Fragment","useSyncExternalStore","storageKey"],"mappings":"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","file":"index.js","sourcesContent":["export interface LuminaryIdpConfig {\n /**\n * OIDC issuer. Prefer Auth Gateway (`http://localhost:3010/oidc`) so products\n * stay IdP-agnostic; direct Logto issuer is OK for local MVP.\n */\n issuer: string;\n clientId: string;\n redirectUri: string;\n /**\n * Popup OIDC callback. Defaults to `redirectUri` (same `/auth/callback`).\n * Must be registered on the IdP application.\n */\n popupRedirectUri?: string;\n postLogoutRedirectUri?: string;\n scopes?: string;\n /** API resource indicator (access token `aud`) */\n audience?: string;\n /** localStorage key for access token */\n tokenStorageKey?: string;\n /**\n * Logto Experience API base (no trailing slash), e.g. Auth Gateway\n * `http://localhost:3010` or direct Logto `http://localhost:3001`.\n * When set, Headless password sign-in is attempted before OIDC popup fallback.\n */\n experienceApiBase?: string;\n /**\n * IAM catalog id: `logto` (default Headless), `oidc` / `zitadel` (Hosted Redirect).\n * Ignored when `HeadlessLoginPanel` receives an explicit `experienceAdapter`.\n */\n iamProvider?: string;\n}\n\nexport interface LuminaryAuthSession {\n accessToken: string;\n idToken?: string;\n expiresAt?: number;\n profile?: Record<string, unknown>;\n}\n\nexport function isIdpConfigured(config: Partial<LuminaryIdpConfig>): config is LuminaryIdpConfig {\n return Boolean(config.issuer && config.clientId && config.redirectUri);\n}\n\n/** Resolve issuer from Auth Gateway base URL or direct IDP_ISSUER. */\nexport function resolveIssuer(env: Record<string, string | undefined>): string | undefined {\n // Prefer explicit IdP issuer so JWT `iss` validation matches Logto.\n // Auth Gateway is a CORS/proxy front — set via VITE_AUTH_EXPERIENCE_URL / VITE_AUTH_GATEWAY_URL.\n const explicit = env.VITE_IDP_ISSUER ?? env.PUBLIC_IDP_ISSUER ?? env.IDP_ISSUER;\n if (explicit) return explicit;\n const gateway = env.VITE_AUTH_GATEWAY_URL ?? env.PUBLIC_AUTH_GATEWAY_URL ?? env.AUTH_GATEWAY_URL;\n if (gateway) return `${gateway.replace(/\\/$/, \"\")}/oidc`;\n return undefined;\n}\n\n/** Derive Experience API host from Gateway URL or by stripping `/oidc` from issuer. */\nexport function resolveExperienceApiBase(env: Record<string, string | undefined>): string | undefined {\n const explicit =\n env.VITE_AUTH_EXPERIENCE_URL ??\n env.PUBLIC_AUTH_EXPERIENCE_URL ??\n env.AUTH_EXPERIENCE_URL;\n if (explicit) return explicit.replace(/\\/$/, \"\");\n\n const gateway = env.VITE_AUTH_GATEWAY_URL ?? env.PUBLIC_AUTH_GATEWAY_URL ?? env.AUTH_GATEWAY_URL;\n if (gateway) return gateway.replace(/\\/$/, \"\");\n\n const issuer = resolveIssuer(env);\n if (!issuer) return undefined;\n return issuer.replace(/\\/$/, \"\").replace(/\\/oidc$/i, \"\");\n}\n\nexport function readIdpConfigFromEnv(env: Record<string, string | undefined>): Partial<LuminaryIdpConfig> {\n const redirectUri = env.VITE_IDP_REDIRECT_URI ?? env.PUBLIC_IDP_REDIRECT_URI ?? \"\";\n return {\n issuer: resolveIssuer(env),\n clientId: env.VITE_IDP_CLIENT_ID ?? env.PUBLIC_IDP_CLIENT_ID,\n redirectUri,\n popupRedirectUri: env.VITE_IDP_POPUP_REDIRECT_URI ?? env.PUBLIC_IDP_POPUP_REDIRECT_URI ?? redirectUri,\n postLogoutRedirectUri: env.VITE_IDP_POST_LOGOUT_URI ?? env.PUBLIC_IDP_POST_LOGOUT_URI,\n scopes: env.VITE_IDP_SCOPES ?? env.PUBLIC_IDP_SCOPES ?? \"openid profile email offline_access\",\n audience: env.VITE_IDP_AUDIENCE ?? env.PUBLIC_IDP_AUDIENCE,\n tokenStorageKey: env.VITE_IDP_TOKEN_KEY ?? \"luminary_access_token\",\n experienceApiBase: resolveExperienceApiBase(env),\n iamProvider:\n env.VITE_IAM_PROVIDER ?? env.PUBLIC_IAM_PROVIDER ?? env.IAM_PROVIDER ?? env.IDP_MODE,\n };\n}\n","import type { LoginExperienceAdapter, LoginExperienceCapability } from \"./login-experience-adapter\";\n\n/**\n * Standard OIDC Hosted Redirect adapter.\n *\n * Used for enterprise OIDC and reserved IAM plugins (ZITADEL) that have no\n * shipped Headless Experience API. Password and social stay on the IdP hosted UI.\n */\nexport class HostedOidcExperienceAdapter implements LoginExperienceAdapter {\n readonly capabilities: readonly LoginExperienceCapability[] = [];\n\n constructor(readonly provider = \"hosted\") {}\n}\n","import { HostedOidcExperienceAdapter } from \"./hosted-oidc-experience-adapter\";\nimport { LogtoExperienceAdapter } from \"./logto-experience-adapter\";\n\n/**\n * Capabilities exposed by a headless login-experience provider.\n *\n * Consumers can use these flags to avoid assuming that every provider supports\n * Logto's password, connector-discovery, or direct social-login flows.\n */\nexport const LOGIN_EXPERIENCE_CAPABILITIES = {\n passwordSignIn: \"password-sign-in\",\n socialConnectors: \"social-connectors\",\n socialDirectSignIn: \"social-direct-sign-in\",\n} as const;\n\nexport type LoginExperienceCapability =\n (typeof LOGIN_EXPERIENCE_CAPABILITIES)[keyof typeof LOGIN_EXPERIENCE_CAPABILITIES];\n\nexport type ExperienceIdentifierType = \"email\" | \"username\" | \"phone\";\n\nexport interface ExperiencePasswordSignInInput {\n /** Experience API origin (no trailing slash). Prefer SPA origin when proxied. */\n apiBase: string;\n identifier: string;\n password: string;\n identifierType?: ExperienceIdentifierType;\n /** Required to bootstrap the OIDC interaction cookie before Experience calls. */\n issuer?: string;\n clientId?: string;\n redirectUri?: string;\n audience?: string;\n scopes?: string;\n /** Carried in OIDC state for post-login return (UserManager PKCE). */\n returnUrl?: string;\n}\n\nexport interface ExperiencePasswordSignInResult {\n /** Continue URL from Experience submit (complete OIDC interaction). */\n redirectTo?: string;\n raw?: unknown;\n}\n\nexport interface ExperienceSocialConnector {\n id: string;\n target: string;\n name: string;\n logo?: string;\n}\n\nexport interface FetchSocialConnectorsInput {\n /** Same origin as Experience / IdP (e.g. SPA proxy or http://localhost:3001). */\n apiBase: string;\n appId?: string;\n}\n\nexport interface SocialSignInRequest {\n /** Provider-specific authorize parameters, passed through by the OIDC client. */\n extraQueryParams?: Record<string, string>;\n}\n\n/**\n * Provider boundary for non-standard login-experience APIs.\n *\n * Standard OIDC redirect/popup and PKCE handling intentionally remain in the\n * OIDC client. Only provider-specific Experience operations belong here.\n */\nexport interface LoginExperienceAdapter {\n readonly provider: string;\n readonly capabilities: readonly LoginExperienceCapability[];\n experiencePasswordSignIn?(\n input: ExperiencePasswordSignInInput,\n ): Promise<ExperiencePasswordSignInResult>;\n fetchSocialConnectors?(\n input: FetchSocialConnectorsInput,\n ): Promise<ExperienceSocialConnector[]>;\n createSocialSignInRequest?(target: string): SocialSignInRequest;\n}\n\nexport type LoginExperienceProvider = \"logto\" | \"hosted\" | \"oidc\" | \"zitadel\" | (string & {});\n\nconst HOSTED_LOGIN_PROVIDERS = new Set([\"hosted\", \"oidc\", \"external_oidc\", \"zitadel\"]);\n\nfunction normalizeLoginExperienceProvider(provider: string): \"logto\" | \"hosted\" {\n const key = provider.trim().toLowerCase();\n if (!key || key === \"logto\") return \"logto\";\n if (HOSTED_LOGIN_PROVIDERS.has(key)) return \"hosted\";\n throw new Error(\n `Unknown login experience provider \"${provider}\". Shipped: logto (default). Hosted OIDC: oidc / hosted / zitadel.`,\n );\n}\n\n/**\n * Factory for built-in login adapters.\n *\n * - `logto`: Experience API Headless (password + social connectors)\n * - `hosted` / `oidc` / `zitadel`: standard OIDC Hosted Redirect (no empty vendor SDK)\n *\n * Products may still pass a custom `LoginExperienceAdapter`. Do not add stub\n * adapters for unintegrated Headless APIs.\n */\nexport function createLoginExperienceAdapter(\n provider: LoginExperienceProvider = \"logto\",\n): LoginExperienceAdapter {\n const kind = normalizeLoginExperienceProvider(provider);\n if (kind === \"logto\") return new LogtoExperienceAdapter();\n return new HostedOidcExperienceAdapter(provider.trim().toLowerCase() || \"hosted\");\n}\n\nconst adapterCache = new Map<string, LoginExperienceAdapter>();\n\n/**\n * Resolve an explicit product adapter, or the catalog adapter for `iamProvider`.\n * Defaults to Logto for backward compatibility.\n */\nexport function resolveLoginExperienceAdapter(\n adapter?: LoginExperienceAdapter | null,\n iamProvider?: string | null,\n): LoginExperienceAdapter {\n if (adapter) return adapter;\n const key = iamProvider?.trim() || \"logto\";\n const cached = adapterCache.get(key);\n if (cached) return cached;\n const created = createLoginExperienceAdapter(key);\n adapterCache.set(key, created);\n return created;\n}\n\n/** `VITE_IAM_PROVIDER` / `IAM_PROVIDER` / older `IDP_MODE`. */\nexport function resolveLoginExperienceProviderFromEnv(\n env: Record<string, string | undefined> = {},\n): LoginExperienceProvider {\n return env.VITE_IAM_PROVIDER ?? env.PUBLIC_IAM_PROVIDER ?? env.IAM_PROVIDER ?? env.IDP_MODE ?? \"logto\";\n}\n","/**\n * Logto Experience API (Headless) adapter.\n * Prefer same-origin Experience base (SPA proxies /api/experience) so cookies\n * work on HTTP localhost.\n */\n\nimport { prepareSignInRequestUrl } from \"./oidc-client\";\nimport {\n LOGIN_EXPERIENCE_CAPABILITIES,\n type ExperienceIdentifierType,\n type ExperiencePasswordSignInInput,\n type ExperiencePasswordSignInResult,\n type ExperienceSocialConnector,\n type FetchSocialConnectorsInput,\n type LoginExperienceAdapter,\n type LoginExperienceCapability,\n type SocialSignInRequest,\n} from \"./login-experience-adapter\";\nimport type { LuminaryIdpConfig } from \"./types\";\n\nfunction experienceUrl(apiBase: string, path: string): string {\n return `${apiBase.replace(/\\/$/, \"\")}/api/experience${path}`;\n}\n\nasync function experienceFetch<T>(apiBase: string, path: string, init: RequestInit): Promise<T> {\n const res = await fetch(experienceUrl(apiBase, path), {\n credentials: \"include\",\n ...init,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...(init.headers ?? {}),\n },\n });\n const text = await res.text();\n let data: unknown = null;\n if (text) {\n try {\n data = JSON.parse(text) as unknown;\n } catch {\n data = text;\n }\n }\n if (!res.ok) {\n const msg =\n data && typeof data === \"object\" && data !== null && \"message\" in data\n ? String((data as { message: unknown }).message)\n : `Experience API ${res.status}`;\n throw new Error(msg);\n }\n return data as T;\n}\n\nfunction guessIdentifierType(identifier: string): ExperienceIdentifierType {\n if (identifier.includes(\"@\")) return \"email\";\n if (/^\\+?\\d{6,}$/.test(identifier.trim())) return \"phone\";\n return \"username\";\n}\n\n/**\n * Force authorize onto the Experience/SPA origin so Set-Cookie lands on the\n * same host as subsequent `/api/experience` calls (dev proxy strips Domain).\n */\nexport function sameOriginAuthorizeUrl(authorizeUrl: string, apiBase: string): string {\n const u = new URL(authorizeUrl);\n const base = new URL(apiBase);\n if (u.origin === base.origin) return authorizeUrl;\n return `${base.origin}${u.pathname}${u.search}${u.hash}`;\n}\n\n/**\n * Logto creates its interaction cookie after an authorize request. The\n * standard OIDC client creates and persists the PKCE request; this adapter only\n * applies Logto's same-origin interaction bootstrap.\n */\nasync function bootstrapOidcInteraction(input: ExperiencePasswordSignInInput): Promise<void> {\n if (!input.issuer || !input.clientId || !input.redirectUri) return;\n if (typeof document === \"undefined\") return;\n\n const config: LuminaryIdpConfig = {\n issuer: input.issuer,\n clientId: input.clientId,\n redirectUri: input.redirectUri,\n audience: input.audience,\n scopes: input.scopes,\n experienceApiBase: input.apiBase,\n };\n\n const signinUrl = await prepareSignInRequestUrl(config, {\n returnUrl: input.returnUrl,\n });\n const authorizeUrl = sameOriginAuthorizeUrl(signinUrl, input.apiBase);\n\n await new Promise<void>((resolve) => {\n const iframe = document.createElement(\"iframe\");\n iframe.setAttribute(\"aria-hidden\", \"true\");\n iframe.tabIndex = -1;\n iframe.style.cssText = \"position:absolute;width:0;height:0;border:0;visibility:hidden\";\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n iframe.remove();\n resolve();\n };\n iframe.addEventListener(\"load\", () => {\n window.setTimeout(finish, 400);\n });\n iframe.src = authorizeUrl;\n document.body.appendChild(iframe);\n window.setTimeout(finish, 2500);\n });\n}\n\n/** Build Logto's provider-specific direct sign-in authorize parameter. */\nexport function createLogtoDirectSignInRequest(directSignIn: string): SocialSignInRequest {\n return { extraQueryParams: { direct_sign_in: directSignIn } };\n}\n\n/** Built-in adapter for Logto's non-standard Experience API. */\nexport class LogtoExperienceAdapter implements LoginExperienceAdapter {\n readonly provider = \"logto\";\n readonly capabilities: readonly LoginExperienceCapability[] = [\n LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn,\n LOGIN_EXPERIENCE_CAPABILITIES.socialConnectors,\n LOGIN_EXPERIENCE_CAPABILITIES.socialDirectSignIn,\n ];\n\n async experiencePasswordSignIn(\n input: ExperiencePasswordSignInInput,\n ): Promise<ExperiencePasswordSignInResult> {\n const { apiBase, identifier, password } = input;\n await bootstrapOidcInteraction(input);\n\n const primary = input.identifierType ?? guessIdentifierType(identifier);\n const alternates: ExperienceIdentifierType[] =\n primary === \"phone\"\n ? [primary]\n : primary === \"email\"\n ? [\"email\", \"username\"]\n : [\"username\", \"email\"];\n\n let lastError: Error | undefined;\n for (const identifierType of alternates) {\n try {\n await experienceFetch(apiBase, \"\", {\n method: \"PUT\",\n body: JSON.stringify({ interactionEvent: \"SignIn\" }),\n });\n\n const verified = await experienceFetch<{ verificationId?: string }>(\n apiBase,\n \"/verification/password\",\n {\n method: \"POST\",\n body: JSON.stringify({\n identifier: { type: identifierType, value: identifier },\n password,\n }),\n },\n );\n\n const verificationId = verified?.verificationId;\n if (!verificationId) {\n throw new Error(\"Experience API did not return verificationId\");\n }\n\n await experienceFetch(apiBase, \"/identification\", {\n method: \"POST\",\n body: JSON.stringify({ verificationId }),\n });\n\n const submitted = await experienceFetch<{ redirectTo?: string }>(\n apiBase,\n \"/submit\",\n {\n method: \"POST\",\n body: JSON.stringify({}),\n },\n );\n\n return { redirectTo: submitted?.redirectTo, raw: submitted };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n }\n throw lastError ?? new Error(\"Experience password sign-in failed\");\n }\n\n async fetchSocialConnectors(\n input: FetchSocialConnectorsInput,\n ): Promise<ExperienceSocialConnector[]> {\n const url = new URL(`${input.apiBase.replace(/\\/$/, \"\")}/api/.well-known/sign-in-exp`);\n if (input.appId?.trim()) url.searchParams.set(\"appId\", input.appId.trim());\n const res = await fetch(url.toString(), {\n // Public metadata — omit cookies so browsers do not require credentialed CORS.\n credentials: \"omit\",\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) {\n throw new Error(`sign-in-exp ${res.status}`);\n }\n const data = (await res.json()) as {\n socialConnectors?: Array<{\n id?: string;\n target?: string;\n name?: string | Record<string, string>;\n logo?: string;\n }>;\n };\n return (data.socialConnectors ?? [])\n .filter(\n (\n connector,\n ): connector is {\n id: string;\n target: string;\n name?: string | Record<string, string>;\n logo?: string;\n } => Boolean(connector?.id && connector?.target),\n )\n .map((connector) => ({\n id: connector.id,\n target: connector.target,\n name: localizeName(connector.name) || titleCase(connector.target),\n logo: connector.logo,\n }));\n }\n\n createSocialSignInRequest(target: string): SocialSignInRequest {\n return createLogtoDirectSignInRequest(`social:${target}`);\n }\n}\n\nfunction localizeName(name: string | Record<string, string> | undefined): string {\n if (!name) return \"\";\n if (typeof name === \"string\") return name;\n return name[\"zh-CN\"] || name.en || Object.values(name)[0] || \"\";\n}\n\nfunction titleCase(target: string): string {\n if (!target) return \"\";\n return target.charAt(0).toUpperCase() + target.slice(1);\n}\n","import {\n OidcClient,\n UserManager,\n WebStorageStateStore,\n type User,\n} from \"oidc-client-ts\";\nimport { createLogtoDirectSignInRequest } from \"./logto-experience-adapter\";\nimport type { LuminaryAuthSession, LuminaryIdpConfig } from \"./types\";\n\nlet manager: UserManager | null = null;\n\nfunction storageKey(config: LuminaryIdpConfig): string {\n return config.tokenStorageKey ?? \"luminary_access_token\";\n}\n\nfunction popupRedirectUri(config: LuminaryIdpConfig): string {\n return config.popupRedirectUri ?? config.redirectUri;\n}\n\nfunction sharedStateStore() {\n // localStorage so popup/redirect/Experience callback windows can resolve PKCE state.\n return new WebStorageStateStore({ store: window.localStorage });\n}\n\nfunction clientSettings(config: LuminaryIdpConfig) {\n const resource = config.audience?.trim() || undefined;\n return {\n authority: config.issuer.replace(/\\/$/, \"\"),\n metadataUrl: resolveOidcMetadataUrl(config),\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n post_logout_redirect_uri: config.postLogoutRedirectUri ?? config.redirectUri,\n response_type: \"code\" as const,\n scope: config.scopes ?? \"openid profile email offline_access\",\n stateStore: sharedStateStore(),\n extraQueryParams: resource ? { resource } : undefined,\n extraTokenParams: resource ? { resource } : undefined,\n };\n}\n\nfunction userManagerSettings(config: LuminaryIdpConfig) {\n const resource = config.audience?.trim() || undefined;\n return {\n ...clientSettings(config),\n popup_redirect_uri: popupRedirectUri(config),\n automaticSilentRenew: true,\n loadUserInfo: !resource,\n userStore: sharedStateStore(),\n };\n}\n\nexport function createUserManager(config: LuminaryIdpConfig): UserManager {\n if (manager) return manager;\n manager = new UserManager(userManagerSettings(config));\n return manager;\n}\n\n/**\n * When Experience/Gateway base differs from the IdP issuer origin, fetch OIDC discovery\n * via the gateway (CORS) while keeping `authority` = Logto issuer (JWT `iss`).\n */\nfunction resolveOidcMetadataUrl(config: LuminaryIdpConfig): string | undefined {\n const proxyBase = config.experienceApiBase?.replace(/\\/$/, \"\");\n if (!proxyBase) return undefined;\n try {\n if (new URL(proxyBase).origin === new URL(config.issuer).origin) return undefined;\n } catch {\n return undefined;\n }\n return `${proxyBase}/oidc/.well-known/openid-configuration`;\n}\n\nexport function resetUserManager(): void {\n manager = null;\n}\n\nexport interface SignInOptions {\n returnUrl?: string;\n /** Provider-specific authorize parameters supplied by an experience adapter. */\n extraQueryParams?: Record<string, string>;\n /**\n * Logto direct sign-in, e.g. `social:google` / `social:github` / `sso:<connectorId>`.\n * Skips the hosted password page and opens the provider immediately.\n * @deprecated Prefer a LoginExperienceAdapter, which supplies extraQueryParams.\n */\n directSignIn?: string;\n}\n\nfunction signInArgs(config: LuminaryIdpConfig, options?: SignInOptions | string) {\n const normalized: SignInOptions =\n typeof options === \"string\" ? { returnUrl: options } : (options ?? {});\n const resource = config.audience?.trim();\n const extraQueryParams: Record<string, string> = { ...normalized.extraQueryParams };\n if (resource) extraQueryParams.resource = resource;\n if (normalized.directSignIn) {\n Object.assign(\n extraQueryParams,\n createLogtoDirectSignInRequest(normalized.directSignIn).extraQueryParams,\n );\n }\n return {\n state: normalized.returnUrl ? { returnUrl: normalized.returnUrl } : undefined,\n extraQueryParams: Object.keys(extraQueryParams).length ? extraQueryParams : undefined,\n };\n}\n\nexport async function signInRedirect(\n config: LuminaryIdpConfig,\n returnUrlOrOptions?: string | SignInOptions,\n): Promise<void> {\n resetUserManager();\n const um = createUserManager(config);\n await um.signinRedirect(signInArgs(config, returnUrlOrOptions));\n}\n\n/**\n * Persist PKCE state (same store as {@link createUserManager}) and return the\n * authorize URL — used by Experience headless bootstrap before navigating to\n * `redirectTo` from `/api/experience/submit`.\n */\nexport async function prepareSignInRequestUrl(\n config: LuminaryIdpConfig,\n returnUrlOrOptions?: string | SignInOptions,\n): Promise<string> {\n resetUserManager();\n // Warm the singleton so callback uses identical settings/stores.\n createUserManager(config);\n const client = new OidcClient(clientSettings(config));\n const args = signInArgs(config, returnUrlOrOptions);\n const request = await client.createSigninRequest({\n state: args.state,\n extraQueryParams: {\n ...(args.extraQueryParams ?? {}),\n prompt: \"login\",\n },\n });\n return request.url;\n}\n\n/**\n * OIDC login in a popup window (not an iframe). Opener keeps SPA state;\n * callback page in the popup must call {@link handleSignInPopupCallback}.\n */\nexport async function signInPopup(\n config: LuminaryIdpConfig,\n returnUrlOrOptions?: string | SignInOptions,\n): Promise<{ session: LuminaryAuthSession; returnUrl?: string }> {\n resetUserManager();\n const um = createUserManager(config);\n const user = await um.signinPopup(signInArgs(config, returnUrlOrOptions));\n const session = toSession(user);\n if (!session.accessToken) {\n throw new Error(\"IdP did not return access_token (check audience / API resource)\");\n }\n assertJwtAccessToken(session.accessToken);\n localStorage.setItem(storageKey(config), session.accessToken);\n const stateReturnUrl =\n typeof user.state === \"object\" && user.state && \"returnUrl\" in user.state\n ? String((user.state as { returnUrl?: string }).returnUrl ?? \"\")\n : undefined;\n return { session, returnUrl: stateReturnUrl || undefined };\n}\n\nexport async function handleSignInCallback(config: LuminaryIdpConfig): Promise<{\n session: LuminaryAuthSession;\n returnUrl?: string;\n}> {\n const um = createUserManager(config);\n const user = await um.signinRedirectCallback();\n const session = toSession(user);\n assertJwtAccessToken(session.accessToken);\n localStorage.setItem(storageKey(config), session.accessToken);\n const returnUrl =\n typeof user.state === \"object\" && user.state && \"returnUrl\" in user.state\n ? String((user.state as { returnUrl?: string }).returnUrl ?? \"\")\n : undefined;\n return { session, returnUrl: returnUrl || undefined };\n}\n\n/**\n * Complete popup OIDC in the popup window. Notifies the opener and closes.\n * Do not run product SSO exchange here — the opener handles that after signInPopup resolves.\n */\nexport async function handleSignInPopupCallback(config: LuminaryIdpConfig): Promise<void> {\n const um = createUserManager(config);\n await um.signinPopupCallback();\n}\n\n/** True when this window is likely an OIDC popup callback. */\nexport function isOidcPopupWindow(): boolean {\n try {\n return Boolean(window.opener && window.opener !== window);\n } catch {\n return false;\n }\n}\n\nexport async function signOutRedirect(config: LuminaryIdpConfig): Promise<void> {\n localStorage.removeItem(storageKey(config));\n const um = createUserManager(config);\n await um.signoutRedirect();\n}\n\nexport function getStoredAccessToken(config: LuminaryIdpConfig): string | null {\n return localStorage.getItem(storageKey(config));\n}\n\nexport function clearStoredSession(config: LuminaryIdpConfig): void {\n localStorage.removeItem(storageKey(config));\n}\n\nfunction toSession(user: User): LuminaryAuthSession {\n return {\n accessToken: user.access_token,\n idToken: user.id_token,\n expiresAt: user.expires_at ? user.expires_at * 1000 : undefined,\n profile: user.profile as Record<string, unknown>,\n };\n}\n\nfunction assertJwtAccessToken(accessToken: string): void {\n if (accessToken.split(\".\").length !== 3) {\n throw new Error(\n \"Received non-JWT access_token. Pass resource (audience) on authorize/token and register the API resource at the IdP.\",\n );\n }\n}\n\nexport async function getCurrentUser(config: LuminaryIdpConfig): Promise<LuminaryAuthSession | null> {\n const um = createUserManager(config);\n const user = await um.getUser();\n if (!user || user.expired) return null;\n return toSession(user);\n}\n","/**\n * @deprecated Import the adapter APIs from the package root instead.\n *\n * This module remains as a compatibility facade for existing consumers.\n */\nimport {\n LOGIN_EXPERIENCE_CAPABILITIES,\n resolveLoginExperienceAdapter,\n} from \"./login-experience-adapter\";\n\nexport type {\n ExperienceIdentifierType,\n ExperiencePasswordSignInInput,\n ExperiencePasswordSignInResult,\n ExperienceSocialConnector,\n FetchSocialConnectorsInput,\n} from \"./login-experience-adapter\";\nexport { sameOriginAuthorizeUrl } from \"./logto-experience-adapter\";\n\nimport type {\n ExperiencePasswordSignInInput,\n ExperiencePasswordSignInResult,\n ExperienceSocialConnector,\n FetchSocialConnectorsInput,\n} from \"./login-experience-adapter\";\n\n/** @deprecated Use a LoginExperienceAdapter instance. */\nexport function experiencePasswordSignIn(\n input: ExperiencePasswordSignInInput,\n): Promise<ExperiencePasswordSignInResult> {\n const adapter = resolveLoginExperienceAdapter();\n if (\n !adapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn) ||\n !adapter.experiencePasswordSignIn\n ) {\n return Promise.reject(new Error(\"Login experience does not support password sign-in\"));\n }\n return adapter.experiencePasswordSignIn(input);\n}\n\n/** @deprecated Use a LoginExperienceAdapter instance. */\nexport function fetchSocialConnectors(\n input: FetchSocialConnectorsInput,\n): Promise<ExperienceSocialConnector[]> {\n const adapter = resolveLoginExperienceAdapter();\n if (\n !adapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.socialConnectors) ||\n !adapter.fetchSocialConnectors\n ) {\n return Promise.reject(new Error(\"Login experience does not support social connectors\"));\n }\n return adapter.fetchSocialConnectors(input);\n}\n","/**\n * AuthGate — single-flight 401 recovery with optional token refresh + reauth UI.\n * Products wire tryRefresh / onReauthRequired; API clients call handleUnauthorized + waitIfBlocked.\n */\n\nexport type AuthGatePhase = \"idle\" | \"refreshing\" | \"reauth\";\n\nexport type UnauthorizedDisposition = \"retry\" | \"fail\";\n\nexport interface AuthGateSnapshot {\n phase: AuthGatePhase;\n /** True while refresh or interactive reauth is in flight. */\n blocked: boolean;\n lastError?: string;\n}\n\nexport interface AuthGateConfig {\n /**\n * Attempt silent product-token (or OIDC) refresh before showing reauth UI.\n * Return true if a new session was established.\n */\n tryRefresh?: () => Promise<boolean>;\n /** Called once when interactive reauth is required (open modal / popup). */\n onReauthRequired?: () => void;\n /** Called when reauth succeeds or is cancelled (phase back to idle). */\n onSettled?: (ok: boolean) => void;\n}\n\ntype Waiter = {\n resolve: (disposition: UnauthorizedDisposition) => void;\n};\n\nclass AuthGateCoordinator {\n private phase: AuthGatePhase = \"idle\";\n private lastError?: string;\n /** Cached for useSyncExternalStore — must keep referential equality when unchanged. */\n private snapshot: AuthGateSnapshot = { phase: \"idle\", blocked: false };\n private config: AuthGateConfig = {};\n private flight: Promise<UnauthorizedDisposition> | null = null;\n private reauthWaiters: Waiter[] = [];\n private listeners = new Set<() => void>();\n\n configure(config: AuthGateConfig): void {\n this.config = { ...this.config, ...config };\n }\n\n getSnapshot = (): AuthGateSnapshot => this.snapshot;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n private emit(): void {\n for (const listener of this.listeners) listener();\n }\n\n private setPhase(phase: AuthGatePhase, lastError?: string): void {\n if (this.phase === phase && this.lastError === lastError) return;\n this.phase = phase;\n this.lastError = lastError;\n this.snapshot = {\n phase,\n blocked: phase !== \"idle\",\n lastError,\n };\n this.emit();\n }\n\n /** Await while a recovery is in flight (pause outbound API traffic). */\n async waitIfBlocked(): Promise<void> {\n if (!this.flight) return;\n await this.flight;\n }\n\n /**\n * Single-flight 401 handler.\n * Concurrent callers share one recovery; all receive the same disposition.\n */\n handleUnauthorized(errorMessage?: string): Promise<UnauthorizedDisposition> {\n if (this.flight) return this.flight;\n this.flight = this.runRecovery(errorMessage).finally(() => {\n this.flight = null;\n });\n return this.flight;\n }\n\n /** Open reauth UI without a preceding 401 (cold start / deep link). */\n requestReauth(errorMessage?: string): Promise<UnauthorizedDisposition> {\n return this.handleUnauthorized(errorMessage);\n }\n\n /** Product calls after popup / Headless login restored the session. */\n completeReauth(): void {\n if (this.phase !== \"reauth\") return;\n const waiters = this.reauthWaiters.splice(0, this.reauthWaiters.length);\n this.setPhase(\"idle\");\n this.config.onSettled?.(true);\n for (const w of waiters) w.resolve(\"retry\");\n }\n\n /** User dismissed reauth; fail queued recovery waiters. */\n cancelReauth(errorMessage?: string): void {\n if (this.phase !== \"reauth\") return;\n const waiters = this.reauthWaiters.splice(0, this.reauthWaiters.length);\n this.setPhase(\"idle\", errorMessage);\n this.config.onSettled?.(false);\n for (const w of waiters) w.resolve(\"fail\");\n }\n\n private async runRecovery(errorMessage?: string): Promise<UnauthorizedDisposition> {\n this.lastError = errorMessage;\n\n if (this.config.tryRefresh) {\n this.setPhase(\"refreshing\", errorMessage);\n try {\n const ok = await this.config.tryRefresh();\n if (ok) {\n this.setPhase(\"idle\");\n this.config.onSettled?.(true);\n return \"retry\";\n }\n } catch (e) {\n this.lastError = e instanceof Error ? e.message : String(e);\n }\n }\n\n this.setPhase(\"reauth\", this.lastError);\n this.config.onReauthRequired?.();\n\n return new Promise<UnauthorizedDisposition>((resolve) => {\n this.reauthWaiters.push({ resolve });\n });\n }\n}\n\n/** Process-wide gate (one per SPA bundle). */\nexport const authGate = new AuthGateCoordinator();\n\n/**\n * Run an async request; on 401, recover via AuthGate and retry once.\n * `isUnauthorized` defaults to checking `status === 401` or `statusCode === 401`.\n */\nexport async function withAuthGateRetry<T>(\n execute: () => Promise<T>,\n options?: {\n isUnauthorized?: (error: unknown) => boolean;\n /** Skip gate (e.g. refresh / sso / login endpoints). */\n bypass?: boolean;\n },\n): Promise<T> {\n if (options?.bypass) return execute();\n\n await authGate.waitIfBlocked();\n\n try {\n return await execute();\n } catch (error) {\n if (!(options?.isUnauthorized ?? defaultIsUnauthorized)(error)) throw error;\n const disposition = await authGate.handleUnauthorized(messageOf(error));\n if (disposition !== \"retry\") throw error;\n return execute();\n }\n}\n\nfunction defaultIsUnauthorized(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const e = error as { status?: number; statusCode?: number; response?: { status?: number } };\n return e.status === 401 || e.statusCode === 401 || e.response?.status === 401;\n}\n\nfunction messageOf(error: unknown): string | undefined {\n if (error instanceof Error) return error.message;\n if (error && typeof error === \"object\" && \"message\" in error) {\n const m = (error as { message?: unknown }).message;\n return typeof m === \"string\" ? m : undefined;\n }\n return undefined;\n}\n","import { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport {\n clearStoredSession,\n getCurrentUser,\n getStoredAccessToken,\n handleSignInCallback,\n signInPopup,\n signInRedirect,\n signOutRedirect,\n} from \"./oidc-client\";\nimport { isIdpConfigured, readIdpConfigFromEnv, type LuminaryAuthSession, type LuminaryIdpConfig } from \"./types\";\n\ninterface LuminaryAuthContextValue {\n configured: boolean;\n session: LuminaryAuthSession | null;\n accessToken: string | null;\n loading: boolean;\n login: (returnUrl?: string) => Promise<void>;\n /** Popup OIDC — keeps the opener SPA mounted. */\n loginPopup: (returnUrl?: string) => Promise<LuminaryAuthSession>;\n logout: () => Promise<void>;\n completeCallback: () => Promise<{ returnUrl?: string }>;\n refreshSession: () => Promise<void>;\n}\n\nconst LuminaryAuthContext = createContext<LuminaryAuthContextValue | null>(null);\n\nexport interface LuminaryAuthProviderProps {\n config?: Partial<LuminaryIdpConfig>;\n children: React.ReactNode;\n}\n\nexport function LuminaryAuthProvider({ config: configProp, children }: LuminaryAuthProviderProps) {\n const config = useMemo(() => configProp ?? {}, [configProp]);\n const configured = isIdpConfigured(config);\n const [session, setSession] = useState<LuminaryAuthSession | null>(null);\n const [loading, setLoading] = useState(configured);\n\n const refreshSession = useCallback(async () => {\n if (!configured) {\n setSession(null);\n setLoading(false);\n return;\n }\n setLoading(true);\n try {\n const current = await getCurrentUser(config);\n setSession(current);\n } catch {\n setSession(null);\n } finally {\n setLoading(false);\n }\n }, [config, configured]);\n\n useEffect(() => {\n void refreshSession();\n }, [refreshSession]);\n\n const login = useCallback(\n async (returnUrl?: string) => {\n if (!configured) throw new Error(\"IdP not configured\");\n await signInRedirect(config, returnUrl);\n },\n [config, configured],\n );\n\n const loginPopup = useCallback(\n async (returnUrl?: string) => {\n if (!configured) throw new Error(\"IdP not configured\");\n const { session: next } = await signInPopup(config, returnUrl);\n setSession(next);\n return next;\n },\n [config, configured],\n );\n\n const logout = useCallback(async () => {\n if (!configured) {\n clearStoredSession(config as LuminaryIdpConfig);\n setSession(null);\n return;\n }\n setSession(null);\n await signOutRedirect(config);\n }, [config, configured]);\n\n const completeCallback = useCallback(async () => {\n if (!configured) throw new Error(\"IdP not configured\");\n const { session: next, returnUrl } = await handleSignInCallback(config);\n setSession(next);\n return { returnUrl };\n }, [config, configured]);\n\n const value = useMemo<LuminaryAuthContextValue>(\n () => ({\n configured,\n session,\n accessToken: session?.accessToken ?? (configured ? getStoredAccessToken(config) : null),\n loading,\n login,\n loginPopup,\n logout,\n completeCallback,\n refreshSession,\n }),\n [configured, session, loading, login, loginPopup, logout, completeCallback, refreshSession, config],\n );\n\n return <LuminaryAuthContext.Provider value={value}>{children}</LuminaryAuthContext.Provider>;\n}\n\nexport function useLuminaryAuth(): LuminaryAuthContextValue {\n const ctx = useContext(LuminaryAuthContext);\n if (!ctx) throw new Error(\"useLuminaryAuth must be used within LuminaryAuthProvider\");\n return ctx;\n}\n\nexport { isIdpConfigured, readIdpConfigFromEnv };\nexport type { LuminaryAuthSession, LuminaryIdpConfig };\n",".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: \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif;\n}\n\n.brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.logo {\n border-radius: 12px;\n display: block;\n}\n\n.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\n.title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: #4b5c68;\n}\n\n.form {\n display: grid;\n gap: 10px;\n}\n\n.socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.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.input:focus {\n border-color: var(--lw-auth-theme);\n}\n.input:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.passwordInput {\n padding-right: 42px;\n}\n\n.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.passwordToggle:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n}\n.passwordToggle:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n}\n.passwordToggle:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.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: linear-gradient(135deg, var(--lw-auth-theme) 0%, var(--lw-auth-theme-deep) 100%);\n}\n.primaryBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.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.socialBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.socialLogo {\n flex-shrink: 0;\n display: block;\n}\n\n.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\n.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.cancelBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: #90a0ab;\n}\n\n.dividerLine {\n flex: 1;\n height: 1px;\n background: #d5e0e7;\n}\n\n.dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: #6b7c87;\n line-height: 1.45;\n}\n\n.error {\n margin: 12px 0 0;\n font-size: 13px;\n color: #b42318;\n line-height: 1.4;\n}\n\n.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=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkhlYWRsZXNzTG9naW5QYW5lbC5tb2R1bGUuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFrQkE7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBLGVBVFU7RUFVVjtFQUNBLE9BekJJO0VBMEJKO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0EsT0E3RE07OztBQWdFUjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0EsZUFsRVU7RUFtRVY7RUFDQTtFQUNBO0VBQ0EsWUEzRVE7O0FBNkVSO0VBQ0U7O0FBR0Y7RUFDRTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0EsZUF2R1U7RUF3R1Y7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOztBQUdGO0VBQ0U7RUFDQTs7QUFHRjtFQUNFO0VBQ0E7OztBQUlKO0VBQ0U7RUFDQSxlQWhJVTtFQWlJVjtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0EsZUF0SlU7RUF1SlY7RUFDQTtFQUNBO0VBQ0E7RUFDQSxPQTFLSTtFQTJLSjs7QUFFQTtFQUNFO0VBQ0E7OztBQUlKO0VBQ0U7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0EsZUEzS1U7RUE0S1Y7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTs7O0FBSUo7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBLE9BbE5ROzs7QUFxTlY7RUFDRTtFQUNBO0VBQ0EsWUF6Tks7OztBQTROUDtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0EsT0EzT0s7RUE0T0w7OztBQUdGO0VBQ0U7RUFDQTtFQUNBLE9BeE9PO0VBeU9QOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0EsT0EzUEs7RUE0UEw7RUFDQTtFQUNBIiwic291cmNlc0NvbnRlbnQiOlsiJGluazogIzE0MjEyYjtcbiRtdXRlZDogIzRiNWM2ODtcbiRoaW50OiAjNmI3Yzg3O1xuJGJyYW5kOiAjM2Q2ZjhmO1xuJGJyYW5kLWRlZXA6ICMxNTQ4NWM7XG4kYnJhbmQtbWlkOiAjMWY2ZjhiO1xuJGJvcmRlcjogI2M5ZDVkZTtcbiRib3JkZXItc29mdDogI2I3YzlkNDtcbiRsaW5lOiAjZDVlMGU3O1xuJGRpdmlkZXI6ICM5MGEwYWI7XG4kc3VyZmFjZTogI2Y3ZmFmYztcbiRmYWxsYmFjay1iZzogI2U4ZWVmMjtcbiRkYW5nZXI6ICNiNDIzMTg7XG4kZm9vdGVyLWxpbmU6ICNlNGViZjA7XG4kcmFkaXVzLWxnOiAxNnB4O1xuJHJhZGl1cy1tZDogMTBweDtcbiRyYWRpdXMtc206IDRweDtcblxuLnBhbmVsIHtcbiAgLS1sdy1hdXRoLXRoZW1lOiAjMTY3N2ZmO1xuICAtLWx3LWF1dGgtdGhlbWUtZGVlcDogY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLWx3LWF1dGgtdGhlbWUpIDcyJSwgIzAwMCk7XG4gIHdpZHRoOiBtaW4oMTAwJSwgNDAwcHgpO1xuICBwYWRkaW5nOiAyOHB4IDI4cHggMjJweDtcbiAgYm9yZGVyLXJhZGl1czogJHJhZGl1cy1sZztcbiAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjk2KTtcbiAgY29sb3I6ICRpbms7XG4gIGJveC1zaGFkb3c6IDAgMjRweCA2NHB4IHJnYmEoMTUsIDIzLCA0MiwgMC4yOCk7XG4gIGZvbnQtZmFtaWx5OiBcIlNlZ29lIFVJXCIsIFwiUGluZ0ZhbmcgU0NcIiwgXCJOb3RvIFNhbnMgU0NcIiwgc2Fucy1zZXJpZjtcbn1cblxuLmJyYW5kIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZ2FwOiAxNHB4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBtYXJnaW4tYm90dG9tOiAxMnB4O1xufVxuXG4ubG9nbyB7XG4gIGJvcmRlci1yYWRpdXM6IDEycHg7XG4gIGRpc3BsYXk6IGJsb2NrO1xufVxuXG4ucHJvZHVjdCB7XG4gIG1hcmdpbjogMDtcbiAgZm9udC1zaXplOiAxM3B4O1xuICBmb250LXdlaWdodDogNjUwO1xuICBsZXR0ZXItc3BhY2luZzogMC4wNGVtO1xuICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xuICBjb2xvcjogdmFyKC0tbHctYXV0aC10aGVtZSk7XG59XG5cbi50aXRsZSB7XG4gIG1hcmdpbjogMnB4IDAgMDtcbiAgZm9udC1zaXplOiAyMnB4O1xuICBmb250LXdlaWdodDogNzAwO1xuICBsaW5lLWhlaWdodDogMS4yNTtcbn1cblxuLnN1YnRpdGxlIHtcbiAgbWFyZ2luOiAwIDAgMThweDtcbiAgZm9udC1zaXplOiAxNHB4O1xuICBsaW5lLWhlaWdodDogMS41O1xuICBjb2xvcjogJG11dGVkO1xufVxuXG4uZm9ybSB7XG4gIGRpc3BsYXk6IGdyaWQ7XG4gIGdhcDogMTBweDtcbn1cblxuLnNvY2lhbFN0YWNrIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC13cmFwOiB3cmFwO1xuICBnYXA6IDEwcHg7XG4gIGZvbnQtc2l6ZTogMTJweDtcbn1cblxuLmlucHV0IHtcbiAgd2lkdGg6IDEwMCU7XG4gIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG4gIGJvcmRlcjogMXB4IHNvbGlkICRib3JkZXI7XG4gIGJvcmRlci1yYWRpdXM6ICRyYWRpdXMtbWQ7XG4gIHBhZGRpbmc6IDEwcHggMTJweDtcbiAgZm9udC1zaXplOiAxNHB4O1xuICBvdXRsaW5lOiBub25lO1xuICBiYWNrZ3JvdW5kOiAkc3VyZmFjZTtcblxuICAmOmZvY3VzIHtcbiAgICBib3JkZXItY29sb3I6IHZhcigtLWx3LWF1dGgtdGhlbWUpO1xuICB9XG5cbiAgJjpkaXNhYmxlZCB7XG4gICAgb3BhY2l0eTogMC42NTtcbiAgICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xuICB9XG59XG5cbi5wYXNzd29yZEZpZWxkIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xufVxuXG4ucGFzc3dvcmRJbnB1dCB7XG4gIHBhZGRpbmctcmlnaHQ6IDQycHg7XG59XG5cbi5wYXNzd29yZFRvZ2dsZSB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgcmlnaHQ6IDRweDtcbiAgdG9wOiA1MCU7XG4gIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtNTAlKTtcbiAgei1pbmRleDogMTtcbiAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICB3aWR0aDogMzZweDtcbiAgaGVpZ2h0OiAzNnB4O1xuICBib3JkZXI6IG5vbmU7XG4gIGJvcmRlci1yYWRpdXM6ICRyYWRpdXMtc207XG4gIHBhZGRpbmc6IDA7XG4gIGNvbG9yOiAjNWE2Yjc2O1xuICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcbiAgY3Vyc29yOiBwb2ludGVyO1xuXG4gICY6aG92ZXI6bm90KDpkaXNhYmxlZCkge1xuICAgIGNvbG9yOiB2YXIoLS1sdy1hdXRoLXRoZW1lKTtcbiAgICBiYWNrZ3JvdW5kOiBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tbHctYXV0aC10aGVtZSkgMTIlLCB0cmFuc3BhcmVudCk7XG4gIH1cblxuICAmOmZvY3VzLXZpc2libGUge1xuICAgIG91dGxpbmU6IDJweCBzb2xpZCB2YXIoLS1sdy1hdXRoLXRoZW1lKTtcbiAgICBvdXRsaW5lLW9mZnNldDogMXB4O1xuICB9XG5cbiAgJjpkaXNhYmxlZCB7XG4gICAgb3BhY2l0eTogMC42NTtcbiAgICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xuICB9XG59XG5cbi5wcmltYXJ5QnRuIHtcbiAgYm9yZGVyOiBub25lO1xuICBib3JkZXItcmFkaXVzOiAkcmFkaXVzLW1kO1xuICBwYWRkaW5nOiAxMXB4IDE0cHg7XG4gIGZvbnQtc2l6ZTogMTRweDtcbiAgZm9udC13ZWlnaHQ6IDY1MDtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBjb2xvcjogI2ZmZjtcbiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgdmFyKC0tbHctYXV0aC10aGVtZSkgMCUsIHZhcigtLWx3LWF1dGgtdGhlbWUtZGVlcCkgMTAwJSk7XG5cbiAgJjpkaXNhYmxlZCB7XG4gICAgb3BhY2l0eTogMC42NTtcbiAgICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xuICB9XG59XG5cbi5zb2NpYWxCdG4ge1xuICBmbGV4OiAxIDEgY2FsYyg1MCUgLSA1cHgpO1xuICBtaW4td2lkdGg6IG1pbigxNDBweCwgMTAwJSk7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBnYXA6IDhweDtcbiAgYm9yZGVyOiAxcHggc29saWQgJGJvcmRlci1zb2Z0O1xuICBib3JkZXItcmFkaXVzOiAkcmFkaXVzLW1kO1xuICBwYWRkaW5nOiAxMXB4IDEwcHg7XG4gIGZvbnQtc2l6ZTogMTRweDtcbiAgZm9udC13ZWlnaHQ6IDY1MDtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBjb2xvcjogJGluaztcbiAgYmFja2dyb3VuZDogI2ZmZjtcblxuICAmOmRpc2FibGVkIHtcbiAgICBvcGFjaXR5OiAwLjY1O1xuICAgIGN1cnNvcjogbm90LWFsbG93ZWQ7XG4gIH1cbn1cblxuLnNvY2lhbExvZ28ge1xuICBmbGV4LXNocmluazogMDtcbiAgZGlzcGxheTogYmxvY2s7XG59XG5cbi5sb2dvRmFsbGJhY2sge1xuICB3aWR0aDogMThweDtcbiAgaGVpZ2h0OiAxOHB4O1xuICBib3JkZXItcmFkaXVzOiAkcmFkaXVzLXNtO1xuICBiYWNrZ3JvdW5kOiBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tbHctYXV0aC10aGVtZSkgMTQlLCAjZmZmKTtcbiAgY29sb3I6IHZhcigtLWx3LWF1dGgtdGhlbWUtZGVlcCk7XG4gIGZvbnQtc2l6ZTogMTFweDtcbiAgZm9udC13ZWlnaHQ6IDcwMDtcbiAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBmbGV4LXNocmluazogMDtcbn1cblxuLmNhbmNlbEJ0biB7XG4gIG1hcmdpbi10b3A6IDEwcHg7XG4gIHdpZHRoOiAxMDAlO1xuICBib3JkZXI6IG5vbmU7XG4gIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICBjb2xvcjogIzVhNmI3NjtcbiAgZm9udC1zaXplOiAxM3B4O1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIHBhZGRpbmc6IDhweDtcblxuICAmOmRpc2FibGVkIHtcbiAgICBvcGFjaXR5OiAwLjY1O1xuICAgIGN1cnNvcjogbm90LWFsbG93ZWQ7XG4gIH1cbn1cblxuLmRpdmlkZXIge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDEwcHg7XG4gIG1hcmdpbjogMTRweCAwO1xuICBjb2xvcjogJGRpdmlkZXI7XG59XG5cbi5kaXZpZGVyTGluZSB7XG4gIGZsZXg6IDE7XG4gIGhlaWdodDogMXB4O1xuICBiYWNrZ3JvdW5kOiAkbGluZTtcbn1cblxuLmRpdmlkZXJUZXh0IHtcbiAgZm9udC1zaXplOiAxMnB4O1xuICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xuICBsZXR0ZXItc3BhY2luZzogMC4wOGVtO1xufVxuXG4uaGludCB7XG4gIG1hcmdpbjogMTBweCAwIDA7XG4gIGZvbnQtc2l6ZTogMTJweDtcbiAgY29sb3I6ICRoaW50O1xuICBsaW5lLWhlaWdodDogMS40NTtcbn1cblxuLmVycm9yIHtcbiAgbWFyZ2luOiAxMnB4IDAgMDtcbiAgZm9udC1zaXplOiAxM3B4O1xuICBjb2xvcjogJGRhbmdlcjtcbiAgbGluZS1oZWlnaHQ6IDEuNDtcbn1cblxuLmZvb3RlciB7XG4gIG1hcmdpbi10b3A6IDE4cHg7XG4gIHBhZGRpbmctdG9wOiAxMnB4O1xuICBib3JkZXItdG9wOiAxcHggc29saWQgJGZvb3Rlci1saW5lO1xuICBmb250LXNpemU6IDEycHg7XG4gIGNvbG9yOiAkaGludDtcbiAgZGlzcGxheTogZmxleDtcbiAgZ2FwOiA4cHg7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xufVxuIl19 */","import { useEffect, useState, type CSSProperties, type FormEvent, type ReactNode } from \"react\";\nimport {\n LOGIN_EXPERIENCE_CAPABILITIES,\n resolveLoginExperienceAdapter,\n type ExperienceSocialConnector,\n type LoginExperienceAdapter,\n type SocialSignInRequest,\n} from \"./login-experience-adapter\";\nimport { signInPopup, signInRedirect } from \"./oidc-client\";\nimport { isIdpConfigured, type LuminaryAuthSession, type LuminaryIdpConfig } from \"./types\";\nimport styles from \"./HeadlessLoginPanel.module.scss\";\n\n/** @deprecated Prefer dynamic connectors from IdP; kept for prop typing. */\nexport type SocialProviderTarget = string;\n\nexport interface HeadlessLoginLabels {\n title?: string;\n subtitle?: string;\n identifierPlaceholder?: string;\n passwordPlaceholder?: string;\n submitPassword?: string;\n /** Hosted OIDC button shown when the adapter has no password capability. */\n submitSso?: string;\n submitGoogle?: string;\n submitGithub?: string;\n socialDivider?: string;\n hint?: string;\n cancel?: string;\n experienceUnavailable?: string;\n showPassword?: string;\n hidePassword?: string;\n}\n\nexport interface HeadlessLoginPanelProps {\n config: Partial<LuminaryIdpConfig>;\n /** Login-experience provider. Defaults to the catalog adapter for `config.iamProvider`. */\n experienceAdapter?: LoginExperienceAdapter;\n /** Product display name shown as brand signal */\n productName: string;\n logoSrc?: string;\n labels?: HeadlessLoginLabels;\n returnUrl?: string;\n /** Prefer popup (default) for reauth; use redirect for full-page login. */\n mode?: \"popup\" | \"redirect\";\n /**\n * Show Experience social connectors (Google / GitHub / …).\n * Default `true`. Set `false` for admin / internal consoles that only allow\n * password (or enterprise SSO via IdP) — hides divider + social buttons and\n * skips fetching connectors.\n * Equivalent to `socialProviders={[]}` when false.\n */\n showSocialConnectors?: boolean;\n /**\n * Social providers (when `showSocialConnectors` is not `false`):\n * - omit / `\"auto\"` — load enabled connectors from IdP (google, github, x, …)\n * - `string[]` — only these targets (still prefers IdP logos/names when available)\n * - `[]` — hide social buttons\n */\n socialProviders?: \"auto\" | SocialProviderTarget[];\n showCancel?: boolean;\n onCancel?: () => void;\n /**\n * Called after OIDC session is obtained (popup) or before redirect navigation.\n * Products typically exchange OIDC access token → product JWT here.\n */\n onOidcSession?: (session: LuminaryAuthSession, returnUrl?: string) => Promise<void> | void;\n /** When Experience returns redirectTo, open it (default: same-tab assign). */\n onExperienceRedirect?: (redirectTo: string) => void;\n footer?: ReactNode;\n className?: string;\n style?: CSSProperties;\n /**\n * Brand accent for primary CTA / focus / product label.\n * Defaults to ecosystem primary `#1677ff`.\n */\n themeColor?: string;\n}\n\n/** Shared default accent for product login panels (shared/brand --lw-primary). */\nexport const DEFAULT_LOGIN_THEME_COLOR = \"#1677ff\";\n\nconst defaults: Required<HeadlessLoginLabels> = {\n title: \"Sign in\",\n subtitle: \"Use your LuminaryWorks unified account\",\n identifierPlaceholder: \"Email or username\",\n passwordPlaceholder: \"Password\",\n submitPassword: \"Sign in with password\",\n submitSso: \"Continue with unified account\",\n submitGoogle: \"Google\",\n submitGithub: \"GitHub\",\n socialDivider: \"or\",\n hint: \"Social providers open directly. Password uses your LuminaryWorks account.\",\n cancel: \"Cancel\",\n experienceUnavailable: \"Password sign-in is unavailable; use a social provider instead.\",\n showPassword: \"Show password\",\n hidePassword: \"Hide password\",\n};\n\nfunction resolveSieBase(config: Partial<LuminaryIdpConfig>): string | undefined {\n // Prefer same-origin Experience base (SPA proxies /api/.well-known) to avoid\n // cross-port CORS on local Logto. Fall back to issuer origin only when needed.\n const explicit = config.experienceApiBase?.trim();\n if (explicit) return explicit.replace(/\\/$/, \"\");\n if (config.issuer) {\n try {\n return new URL(config.issuer).origin;\n } catch {\n /* fall through */\n }\n }\n return undefined;\n}\n\nfunction labelFor(connector: ExperienceSocialConnector, labels: Required<HeadlessLoginLabels>): string {\n if (connector.target === \"google\" && labels.submitGoogle) return labels.submitGoogle;\n if (connector.target === \"github\" && labels.submitGithub) return labels.submitGithub;\n return connector.name;\n}\n\nfunction cx(...parts: Array<string | undefined | false>): string {\n return parts.filter(Boolean).join(\" \");\n}\n\nexport function HeadlessLoginPanel({\n config,\n experienceAdapter: experienceAdapterProp,\n productName,\n logoSrc,\n labels: labelsProp,\n returnUrl,\n mode = \"popup\",\n showSocialConnectors = true,\n socialProviders = \"auto\",\n showCancel,\n onCancel,\n onOidcSession,\n onExperienceRedirect,\n footer,\n className,\n style,\n themeColor = DEFAULT_LOGIN_THEME_COLOR,\n}: HeadlessLoginPanelProps) {\n const experienceAdapter = resolveLoginExperienceAdapter(\n experienceAdapterProp,\n config.iamProvider,\n );\n const labels = { ...defaults, ...labelsProp };\n const configured = isIdpConfigured(config);\n const [identifier, setIdentifier] = useState(\"\");\n const [password, setPassword] = useState(\"\");\n const [passwordVisible, setPasswordVisible] = useState(false);\n const panelStyle: CSSProperties = {\n ...style,\n [\"--lw-auth-theme\" as string]: themeColor || DEFAULT_LOGIN_THEME_COLOR,\n };\n const [loading, setLoading] = useState<\"password\" | string | null>(null);\n const [error, setError] = useState(\"\");\n const [connectors, setConnectors] = useState<ExperienceSocialConnector[]>([]);\n const socialEnabled =\n showSocialConnectors !== false &&\n !(Array.isArray(socialProviders) && socialProviders.length === 0) &&\n experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.socialConnectors) &&\n experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.socialDirectSignIn) &&\n typeof experienceAdapter.fetchSocialConnectors === \"function\" &&\n typeof experienceAdapter.createSocialSignInRequest === \"function\";\n const passwordEnabled =\n experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn) &&\n typeof experienceAdapter.experiencePasswordSignIn === \"function\";\n\n // Browser back from IdP restores bfcache with loading still set → \"…\".\n useEffect(() => {\n const resetBusy = () => setLoading(null);\n window.addEventListener(\"pageshow\", resetBusy);\n window.addEventListener(\"popstate\", resetBusy);\n return () => {\n window.removeEventListener(\"pageshow\", resetBusy);\n window.removeEventListener(\"popstate\", resetBusy);\n };\n }, []);\n\n useEffect(() => {\n const fetchConnectors = experienceAdapter.fetchSocialConnectors;\n if (!socialEnabled || !fetchConnectors) {\n setConnectors([]);\n return;\n }\n let cancelled = false;\n const sieBase = resolveSieBase(config);\n const allowlist =\n socialProviders === \"auto\" || socialProviders === undefined\n ? null\n : new Set(socialProviders.map((t) => t.toLowerCase()));\n\n const apply = (list: ExperienceSocialConnector[]) => {\n const filtered = allowlist\n ? list.filter((c) => allowlist.has(c.target.toLowerCase()))\n : list;\n if (!cancelled) setConnectors(filtered);\n };\n\n if (!sieBase) {\n // No Experience base — do not invent Google/GitHub buttons. Fake fallbacks\n // start OIDC `direct_sign_in` and dump users on Logto `/sign-in`.\n if (!cancelled) setConnectors([]);\n return;\n }\n\n void fetchConnectors.call(experienceAdapter, { apiBase: sieBase, appId: config.clientId })\n .then((list) => {\n apply(list);\n })\n .catch(() => {\n if (!cancelled) setConnectors([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [\n config.clientId,\n config.experienceApiBase,\n config.issuer,\n experienceAdapter,\n socialEnabled,\n socialProviders,\n ]);\n\n const runOidc = async (experienceRequest?: SocialSignInRequest) => {\n if (!configured) throw new Error(\"IdP not configured\");\n if (mode === \"redirect\") {\n await signInRedirect(config, { returnUrl, ...experienceRequest });\n return;\n }\n const { session, returnUrl: next } = await signInPopup(config, {\n returnUrl,\n ...experienceRequest,\n });\n await onOidcSession?.(session, next);\n };\n\n const runSocial = async (target: string) => {\n setError(\"\");\n setLoading(target);\n try {\n if (\n !socialEnabled ||\n !experienceAdapter.capabilities.includes(\n LOGIN_EXPERIENCE_CAPABILITIES.socialDirectSignIn,\n ) ||\n !experienceAdapter.createSocialSignInRequest\n ) {\n throw new Error(\"Login experience does not support direct social sign-in\");\n }\n await runOidc(experienceAdapter.createSocialSignInRequest(target));\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setLoading(null);\n }\n };\n\n const runHostedOidc = async () => {\n setError(\"\");\n setLoading(\"sso\");\n try {\n await runOidc();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setLoading(null);\n }\n };\n\n const followExperienceRedirect = (redirectTo: string) => {\n if (onExperienceRedirect) {\n onExperienceRedirect(redirectTo);\n return;\n }\n window.location.assign(redirectTo);\n };\n\n const runPassword = async (event: FormEvent) => {\n event.preventDefault();\n if (!configured) return;\n setError(\"\");\n setLoading(\"password\");\n try {\n const apiBase = config.experienceApiBase?.trim();\n if (!apiBase) {\n throw new Error(labels.experienceUnavailable);\n }\n if (\n !passwordEnabled ||\n !experienceAdapter.capabilities.includes(\n LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn,\n ) ||\n !experienceAdapter.experiencePasswordSignIn\n ) {\n throw new Error(labels.experienceUnavailable);\n }\n const result = await experienceAdapter.experiencePasswordSignIn({\n apiBase,\n identifier: identifier.trim(),\n password,\n issuer: config.issuer,\n clientId: config.clientId,\n redirectUri: config.redirectUri,\n audience: config.audience,\n scopes: config.scopes,\n returnUrl,\n });\n if (result.redirectTo) {\n // Completes the PKCE interaction from bootstrap — do NOT start a new\n // authorize (that re-opens Logto hosted /sign-in).\n followExperienceRedirect(result.redirectTo);\n return;\n }\n throw new Error(\"Experience API did not return redirectTo\");\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setLoading(null);\n }\n };\n\n const busy = loading !== null;\n const showSocial = socialEnabled && connectors.length > 0;\n const showHint = Boolean(labelsProp?.hint) || showSocial;\n\n return (\n <div className={cx(styles.panel, className)} style={panelStyle}>\n <header className={styles.brand}>\n {logoSrc ? <img src={logoSrc} alt=\"\" width={48} height={48} className={styles.logo} /> : null}\n <div>\n <p className={styles.product}>{productName}</p>\n <h2 className={styles.title}>{labels.title}</h2>\n </div>\n </header>\n <p className={styles.subtitle}>{labels.subtitle}</p>\n\n {configured ? (\n <>\n {passwordEnabled ? (\n <form onSubmit={(e) => void runPassword(e)} className={styles.form}>\n <input\n type=\"text\"\n name=\"identifier\"\n autoComplete=\"username\"\n placeholder={labels.identifierPlaceholder}\n value={identifier}\n onChange={(e) => setIdentifier(e.target.value)}\n className={styles.input}\n disabled={busy}\n />\n <div className={styles.passwordField}>\n <input\n type={passwordVisible ? \"text\" : \"password\"}\n name=\"password\"\n autoComplete=\"current-password\"\n placeholder={labels.passwordPlaceholder}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n className={cx(styles.input, styles.passwordInput)}\n disabled={busy}\n />\n <button\n type=\"button\"\n className={styles.passwordToggle}\n disabled={busy}\n aria-label={passwordVisible ? labels.hidePassword : labels.showPassword}\n aria-pressed={passwordVisible}\n onClick={() => setPasswordVisible((v) => !v)}\n >\n <PasswordVisibilityIcon visible={passwordVisible} />\n </button>\n </div>\n <button type=\"submit\" className={styles.primaryBtn} disabled={busy || !identifier || !password}>\n {loading === \"password\" ? \"…\" : labels.submitPassword}\n </button>\n </form>\n ) : (\n <div className={styles.form}>\n <button\n type=\"button\"\n className={styles.primaryBtn}\n disabled={busy}\n onClick={() => void runHostedOidc()}\n >\n {loading === \"sso\" ? \"…\" : labels.submitSso}\n </button>\n </div>\n )}\n {showHint ? <p className={styles.hint}>{labels.hint}</p> : null}\n\n {showSocial ? (\n <div className={styles.divider} aria-hidden>\n <span className={styles.dividerLine} />\n <span className={styles.dividerText}>{labels.socialDivider}</span>\n <span className={styles.dividerLine} />\n </div>\n ) : null}\n {showSocial ? (\n <div className={styles.socialStack}>\n {connectors.map((connector) => (\n <button\n key={connector.id}\n type=\"button\"\n className={styles.socialBtn}\n disabled={busy}\n onClick={() => void runSocial(connector.target)}\n >\n <SocialLogo connector={connector} />\n {loading === connector.target ? \"…\" : labelFor(connector, labels)}\n </button>\n ))}\n </div>\n ) : null}\n\n </>\n ) : (\n <p className={styles.error}>IdP is not configured (issuer / clientId / redirectUri).</p>\n )}\n\n {error ? <p className={styles.error}>{error}</p> : null}\n\n {showCancel ? (\n <button type=\"button\" className={styles.cancelBtn} disabled={busy} onClick={onCancel}>\n {labels.cancel}\n </button>\n ) : null}\n\n {footer ? <footer className={styles.footer}>{footer}</footer> : null}\n </div>\n );\n}\n\nfunction SocialLogo({ connector }: { connector: ExperienceSocialConnector }) {\n if (connector.logo) {\n return <img src={connector.logo} alt=\"\" width={18} height={18} className={styles.socialLogo} />;\n }\n return (\n <span className={styles.logoFallback} aria-hidden>\n {connector.name.slice(0, 1).toUpperCase()}\n </span>\n );\n}\n\nfunction PasswordVisibilityIcon({ visible }: { visible: boolean }) {\n // Filled icons (antd Eye / EyeInvisible style) — no dependency.\n if (visible) {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 1024 1024\" fill=\"currentColor\" aria-hidden>\n <path d=\"M942.2 486.2C847.4 286.5 704.1 186 512 186c-57.9 0-111.5 9.8-160.3 27.7l72.3 72.3C457 273.3 483.5 266 512 266c161.3 0 279.4 81.8 362.7 254-26.3 54.4-57.5 100.2-93.3 136.1l59.6 59.6C891.4 655.7 932.5 578.5 942.2 537.7a60.3 60.3 0 000-51.5zM336.6 278.6l-59.9-59.9C230.6 255.4 182.8 296.4 141.9 348.1 95.4 412.1 64.6 486.5 51.8 512a60.3 60.3 0 000 51.5C115.3 719.5 224.6 814.8 365.4 860.1l72.5-72.5C353.6 761.6 286.3 698.3 241.3 612.5 220.6 573.1 205 528.6 194.5 486.2c24.5-50.4 55.1-92.1 90.8-124.9l51.3-51.3zM606.6 556.6A112 112 0 01467.4 417.4L606.6 556.6zM508 624c-26.5 0-50.9-9.2-70.2-24.6l-59.9 59.9A175.3 175.3 0 00508 688c97.2 0 176-78.8 176-176 0-26.5-9.2-50.9-24.6-70.2l-59.9 59.9c15.4 19.3 24.6 43.7 24.6 70.2 0 61.9-50.1 112-112 112zM880 112L112 880l48 48 768-768z\" />\n </svg>\n );\n }\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 1024 1024\" fill=\"currentColor\" aria-hidden>\n <path d=\"M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3a60.3 60.3 0 000-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766z\" />\n <path d=\"M508 336c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z\" />\n </svg>\n );\n}\n","import { useSyncExternalStore, type CSSProperties, type ReactNode } from \"react\";\nimport { authGate } from \"./auth-gate\";\nimport { HeadlessLoginPanel, type HeadlessLoginLabels } from \"./HeadlessLoginPanel\";\nimport type { LuminaryAuthSession, LuminaryIdpConfig } from \"./types\";\n\nexport interface ReauthOverlayProps {\n config: Partial<LuminaryIdpConfig>;\n productName: string;\n logoSrc?: string;\n labels?: HeadlessLoginLabels;\n returnUrl?: string;\n /** Brand accent forwarded to HeadlessLoginPanel (default `#1677ff`). */\n themeColor?: string;\n /** Exchange OIDC token / persist product session, then AuthGate completes. */\n onOidcSession: (session: LuminaryAuthSession, returnUrl?: string) => Promise<void> | void;\n /** Optional custom body instead of HeadlessLoginPanel */\n children?: ReactNode;\n /** Allow dismiss → cancelReauth (default true for mid-session; false for hard gate). */\n dismissible?: boolean;\n onDismiss?: () => void;\n}\n\n/**\n * Full-viewport soft gate shown while AuthGate phase is `reauth` (or `refreshing` spinner).\n * Does not iframe the IdP — uses Headless panel + OIDC popup.\n */\nexport function ReauthOverlay({\n config,\n productName,\n logoSrc,\n labels,\n returnUrl,\n themeColor,\n onOidcSession,\n children,\n dismissible = true,\n onDismiss,\n}: ReauthOverlayProps) {\n const snapshot = useSyncExternalStore(authGate.subscribe, authGate.getSnapshot, authGate.getSnapshot);\n\n if (snapshot.phase === \"idle\") return null;\n\n const resolvedReturnUrl =\n returnUrl ??\n (() => {\n if (typeof window === \"undefined\") return undefined;\n const hash = window.location.hash.replace(/^#/, \"\");\n if (!hash || hash.startsWith(\"/login\") || hash.startsWith(\"/auth/\")) return undefined;\n return hash.startsWith(\"/\") ? hash : `/${hash}`;\n })();\n\n const handleSession = async (session: LuminaryAuthSession, next?: string) => {\n await onOidcSession(session, next);\n authGate.completeReauth();\n };\n\n const handleCancel = () => {\n onDismiss?.();\n authGate.cancelReauth(\"cancelled\");\n };\n\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={productName}\n style={backdropStyle}\n onClick={dismissible ? handleCancel : undefined}\n >\n <div style={centerStyle} onClick={(e) => e.stopPropagation()}>\n {snapshot.phase === \"refreshing\" ? (\n <div style={spinnerCardStyle}>\n <div style={spinnerStyle} />\n <p style={{ margin: 0, color: \"#e8eef2\" }}>Refreshing session…</p>\n </div>\n ) : children ? (\n children\n ) : (\n <HeadlessLoginPanel\n config={config}\n productName={productName}\n logoSrc={logoSrc}\n themeColor={themeColor}\n labels={{\n title: labels?.title ?? \"Session expired\",\n subtitle: labels?.subtitle ?? \"Sign in again to keep working — this page will not reload.\",\n ...labels,\n }}\n returnUrl={resolvedReturnUrl}\n mode=\"popup\"\n showCancel={dismissible}\n onCancel={handleCancel}\n onOidcSession={handleSession}\n />\n )}\n </div>\n </div>\n );\n}\n\nconst backdropStyle: CSSProperties = {\n position: \"fixed\",\n inset: 0,\n zIndex: 10000,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 24,\n background:\n \"radial-gradient(1200px 600px at 20% 10%, rgba(56, 120, 150, 0.35), transparent 55%), rgba(10, 18, 24, 0.72)\",\n backdropFilter: \"blur(6px)\",\n};\n\nconst centerStyle: CSSProperties = {\n width: \"min(100%, 420px)\",\n};\n\nconst spinnerCardStyle: CSSProperties = {\n display: \"grid\",\n justifyItems: \"center\",\n gap: 14,\n padding: 28,\n borderRadius: 16,\n background: \"rgba(20, 32, 40, 0.88)\",\n};\n\nconst spinnerStyle: CSSProperties = {\n width: 36,\n height: 36,\n borderRadius: \"50%\",\n border: \"3px solid rgba(255,255,255,0.2)\",\n borderTopColor: \"#7ec8e3\",\n animation: \"luminary-auth-spin 0.8s linear infinite\",\n};\n\n// Inject keyframes once\nif (typeof document !== \"undefined\" && !document.getElementById(\"luminary-auth-spin-style\")) {\n const style = document.createElement(\"style\");\n style.id = \"luminary-auth-spin-style\";\n style.textContent = `@keyframes luminary-auth-spin { to { transform: rotate(360deg); } }`;\n document.head.appendChild(style);\n}\n","import { createContext, useContext, useEffect, useMemo, type ReactNode } from \"react\";\nimport { useSyncExternalStore } from \"react\";\nimport { authGate, type AuthGateConfig, type AuthGateSnapshot } from \"./auth-gate\";\nimport { ReauthOverlay, type ReauthOverlayProps } from \"./ReauthOverlay\";\nimport type { LuminaryAuthSession, LuminaryIdpConfig } from \"./types\";\n\ninterface AuthGateContextValue {\n snapshot: AuthGateSnapshot;\n requestReauth: (message?: string) => Promise<\"retry\" | \"fail\">;\n completeReauth: () => void;\n cancelReauth: (message?: string) => void;\n}\n\nconst AuthGateContext = createContext<AuthGateContextValue | null>(null);\n\nexport interface AuthGateProviderProps extends AuthGateConfig {\n children: ReactNode;\n /** When set, mounts {@link ReauthOverlay} automatically. */\n overlay?: Omit<ReauthOverlayProps, \"onOidcSession\"> & {\n onOidcSession: (session: LuminaryAuthSession, returnUrl?: string) => Promise<void> | void;\n config: Partial<LuminaryIdpConfig>;\n };\n}\n\nexport function AuthGateProvider({\n children,\n tryRefresh,\n onReauthRequired,\n onSettled,\n overlay,\n}: AuthGateProviderProps) {\n useEffect(() => {\n authGate.configure({ tryRefresh, onReauthRequired, onSettled });\n }, [tryRefresh, onReauthRequired, onSettled]);\n\n const snapshot = useSyncExternalStore(authGate.subscribe, authGate.getSnapshot, authGate.getSnapshot);\n\n const value = useMemo<AuthGateContextValue>(\n () => ({\n snapshot,\n requestReauth: (message?: string) => authGate.requestReauth(message),\n completeReauth: () => authGate.completeReauth(),\n cancelReauth: (message?: string) => authGate.cancelReauth(message),\n }),\n [snapshot],\n );\n\n return (\n <AuthGateContext.Provider value={value}>\n {children}\n {overlay ? <ReauthOverlay {...overlay} /> : null}\n </AuthGateContext.Provider>\n );\n}\n\nexport function useAuthGate(): AuthGateContextValue {\n const ctx = useContext(AuthGateContext);\n if (!ctx) throw new Error(\"useAuthGate must be used within AuthGateProvider\");\n return ctx;\n}\n\n/** Optional hook — returns null outside provider (for shared API helpers). */\nexport function useAuthGateOptional(): AuthGateContextValue | null {\n return useContext(AuthGateContext);\n}\n","export interface PostLoginPathOptions {\n /** sessionStorage key (product-scoped), e.g. `dv:postLoginPath` */\n storageKey: string;\n /** Default destination when nothing remembered */\n defaultPath?: string;\n /** Extra paths that must not be used as return targets */\n unsafePrefixes?: string[];\n}\n\nconst DEFAULT_UNSAFE = [\"/login\", \"/auth\", \"/exception\"];\n\nfunction normalizeAppPath(path: string, fallback: string): string {\n const raw = path.replace(/^#/, \"\").trim();\n if (!raw) return fallback.startsWith(\"/\") ? fallback : `/${fallback}`;\n return raw.startsWith(\"/\") ? raw : `/${raw}`;\n}\n\nfunction isUnsafeReturnPath(path: string, unsafePrefixes: string[], fallback: string): boolean {\n const p = normalizeAppPath(path, fallback);\n if (p === \"/\") return true;\n return unsafePrefixes.some((prefix) => p === prefix || p.startsWith(`${prefix}/`) || p.startsWith(prefix));\n}\n\n/**\n * sessionStorage helpers for OIDC redirect return paths.\n * Product-specific ACL checks (e.g. 403 fallback) stay in the product.\n */\nexport function createPostLoginPathHelpers(options: PostLoginPathOptions) {\n const storageKey = options.storageKey;\n const defaultPath = options.defaultPath?.startsWith(\"/\")\n ? options.defaultPath\n : `/${options.defaultPath || \"home\"}`;\n const unsafePrefixes = [...DEFAULT_UNSAFE, ...(options.unsafePrefixes || [])];\n\n function rememberPostLoginPath(path: string): void {\n const normalized = normalizeAppPath(path, defaultPath);\n if (isUnsafeReturnPath(normalized, unsafePrefixes, defaultPath)) return;\n try {\n sessionStorage.setItem(storageKey, normalized);\n } catch {\n /* ignore */\n }\n }\n\n function peekPostLoginPath(): string | undefined {\n try {\n const v = sessionStorage.getItem(storageKey);\n if (!v || isUnsafeReturnPath(v, unsafePrefixes, defaultPath)) return undefined;\n return normalizeAppPath(v, defaultPath);\n } catch {\n return undefined;\n }\n }\n\n function consumePostLoginPath(fallback = defaultPath): string {\n const remembered = peekPostLoginPath();\n try {\n sessionStorage.removeItem(storageKey);\n } catch {\n /* ignore */\n }\n return remembered ?? normalizeAppPath(fallback, defaultPath);\n }\n\n return {\n rememberPostLoginPath,\n peekPostLoginPath,\n consumePostLoginPath,\n normalizeAppPath: (path: string) => normalizeAppPath(path, defaultPath),\n isUnsafeReturnPath: (path: string) => isUnsafeReturnPath(path, unsafePrefixes, defaultPath),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/hosted-oidc-experience-adapter.ts","../src/login-experience-adapter.ts","../src/logto-experience-adapter.ts","../src/oidc-client.ts","../src/experience-client.ts","../src/auth-gate.ts","../src/LuminaryAuthProvider.tsx","../src/HeadlessLoginPanel.module.scss","../src/HeadlessLoginPanel.tsx","../src/ReauthOverlay.tsx","../src/AuthGateProvider.tsx","../src/post-login-path.ts"],"names":["WebStorageStateStore","UserManager","OidcClient","createContext","useMemo","useState","useCallback","useEffect","jsx","useContext","panel","brand","logo","product","title","subtitle","form","socialStack","input","passwordField","passwordInput","passwordToggle","primaryBtn","socialBtn","socialLogo","logoFallback","cancelBtn","divider","dividerLine","dividerText","hint","switchMode","switchModeBtn","error","footer","result","jsxs","Fragment","useSyncExternalStore","storageKey"],"mappings":";;;;;;;AAuCO,SAAS,gBAAgB,MAAA,EAAiE;AAC/F,EAAA,OAAO,QAAQ,MAAA,CAAO,MAAA,IAAU,MAAA,CAAO,QAAA,IAAY,OAAO,WAAW,CAAA;AACvE;AAGO,SAAS,cAAc,GAAA,EAA6D;AAGzF,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,eAAA,IAAmB,GAAA,CAAI,qBAAqB,GAAA,CAAI,UAAA;AACrE,EAAA,IAAI,UAAU,OAAO,QAAA;AACrB,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,qBAAA,IAAyB,GAAA,CAAI,2BAA2B,GAAA,CAAI,gBAAA;AAChF,EAAA,IAAI,SAAS,OAAO,CAAA,EAAG,QAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,KAAA,CAAA;AACjD,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,yBAAyB,GAAA,EAA6D;AACpG,EAAA,MAAM,QAAA,GACJ,GAAA,CAAI,wBAAA,IACJ,GAAA,CAAI,8BACJ,GAAA,CAAI,mBAAA;AACN,EAAA,IAAI,QAAA,EAAU,OAAO,QAAA,CAAS,OAAA,CAAQ,OAAO,EAAE,CAAA;AAE/C,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,qBAAA,IAAyB,GAAA,CAAI,2BAA2B,GAAA,CAAI,gBAAA;AAChF,EAAA,IAAI,OAAA,EAAS,OAAO,OAAA,CAAQ,OAAA,CAAQ,OAAO,EAAE,CAAA;AAE7C,EAAA,MAAM,MAAA,GAAS,cAAc,GAAG,CAAA;AAChC,EAAA,IAAI,CAAC,QAAQ,OAAO,MAAA;AACpB,EAAA,OAAO,OAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,CAAE,OAAA,CAAQ,YAAY,EAAE,CAAA;AACzD;AAEO,SAAS,qBAAqB,GAAA,EAAqE;AACxG,EAAA,MAAM,WAAA,GAAc,GAAA,CAAI,qBAAA,IAAyB,GAAA,CAAI,uBAAA,IAA2B,EAAA;AAChF,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,cAAc,GAAG,CAAA;AAAA,IACzB,QAAA,EAAU,GAAA,CAAI,kBAAA,IAAsB,GAAA,CAAI,oBAAA;AAAA,IACxC,WAAA;AAAA,IACA,gBAAA,EAAkB,GAAA,CAAI,2BAAA,IAA+B,GAAA,CAAI,6BAAA,IAAiC,WAAA;AAAA,IAC1F,qBAAA,EAAuB,GAAA,CAAI,wBAAA,IAA4B,GAAA,CAAI,0BAAA;AAAA,IAC3D,MAAA,EAAQ,GAAA,CAAI,eAAA,IAAmB,GAAA,CAAI,iBAAA,IAAqB,qCAAA;AAAA,IACxD,QAAA,EAAU,GAAA,CAAI,iBAAA,IAAqB,GAAA,CAAI,mBAAA;AAAA,IACvC,eAAA,EAAiB,IAAI,kBAAA,IAAsB,uBAAA;AAAA,IAC3C,iBAAA,EAAmB,yBAAyB,GAAG,CAAA;AAAA,IAC/C,aACE,GAAA,CAAI,iBAAA,IAAqB,IAAI,mBAAA,IAAuB,GAAA,CAAI,gBAAgB,GAAA,CAAI;AAAA,GAChF;AACF;;;AC7EO,IAAM,8BAAN,MAAoE;AAAA,EAGzE,WAAA,CAAqB,WAAW,QAAA,EAAU;AAArB,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAAsB;AAAA,EAAtB,QAAA;AAAA,EAFZ,eAAqD,EAAC;AAGjE;;;ACHO,IAAM,6BAAA,GAAgC;AAAA,EAC3C,cAAA,EAAgB,kBAAA;AAAA;AAAA,EAEhB,cAAA,EAAgB,kBAAA;AAAA,EAChB,gBAAA,EAAkB,mBAAA;AAAA,EAClB,kBAAA,EAAoB;AACtB;AA+EA,IAAM,sBAAA,uBAA6B,GAAA,CAAI,CAAC,UAAU,MAAA,EAAQ,eAAA,EAAiB,SAAS,CAAC,CAAA;AAErF,SAAS,iCAAiC,QAAA,EAAsC;AAC9E,EAAA,MAAM,GAAA,GAAM,QAAA,CAAS,IAAA,EAAK,CAAE,WAAA,EAAY;AACxC,EAAA,IAAI,CAAC,GAAA,IAAO,GAAA,KAAQ,OAAA,EAAS,OAAO,OAAA;AACpC,EAAA,IAAI,sBAAA,CAAuB,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,QAAA;AAC5C,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,sCAAsC,QAAQ,CAAA,kEAAA;AAAA,GAChD;AACF;AAWO,SAAS,4BAAA,CACd,WAAoC,OAAA,EACZ;AACxB,EAAA,MAAM,IAAA,GAAO,iCAAiC,QAAQ,CAAA;AACtD,EAAA,IAAI,IAAA,KAAS,OAAA,EAAS,OAAO,IAAI,sBAAA,EAAuB;AACxD,EAAA,OAAO,IAAI,2BAAA,CAA4B,QAAA,CAAS,MAAK,CAAE,WAAA,MAAiB,QAAQ,CAAA;AAClF;AAEA,IAAM,YAAA,uBAAmB,GAAA,EAAoC;AAMtD,SAAS,6BAAA,CACd,SACA,WAAA,EACwB;AACxB,EAAA,IAAI,SAAS,OAAO,OAAA;AACpB,EAAA,MAAM,GAAA,GAAM,WAAA,EAAa,IAAA,EAAK,IAAK,OAAA;AACnC,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA;AACnC,EAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,EAAA,MAAM,OAAA,GAAU,6BAA6B,GAAG,CAAA;AAChD,EAAA,YAAA,CAAa,GAAA,CAAI,KAAK,OAAO,CAAA;AAC7B,EAAA,OAAO,OAAA;AACT;AAGO,SAAS,qCAAA,CACd,GAAA,GAA0C,EAAC,EAClB;AACzB,EAAA,OAAO,IAAI,iBAAA,IAAqB,GAAA,CAAI,uBAAuB,GAAA,CAAI,YAAA,IAAgB,IAAI,QAAA,IAAY,OAAA;AACjG;;;AC3HA,IAAM,iBAAA,GAAoB,gBAAA;AAEnB,SAAS,wBAAwB,KAAA,EAAwB;AAC9D,EAAA,OAAO,iBAAA,CAAkB,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,CAAA;AAC5C;AAEA,SAAS,aAAA,CAAc,SAAiB,IAAA,EAAsB;AAC5D,EAAA,OAAO,GAAG,OAAA,CAAQ,OAAA,CAAQ,OAAO,EAAE,CAAC,kBAAkB,IAAI,CAAA,CAAA;AAC5D;AAEA,eAAe,eAAA,CAAmB,OAAA,EAAiB,IAAA,EAAc,IAAA,EAA+B;AAC9F,EAAA,MAAM,MAAM,MAAM,KAAA,CAAM,aAAA,CAAc,OAAA,EAAS,IAAI,CAAA,EAAG;AAAA,IACpD,WAAA,EAAa,SAAA;AAAA,IACb,GAAG,IAAA;AAAA,IACH,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB,kBAAA;AAAA,MAChB,MAAA,EAAQ,kBAAA;AAAA,MACR,GAAI,IAAA,CAAK,OAAA,IAAW;AAAC;AACvB,GACD,CAAA;AACD,EAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,EAAA,IAAI,IAAA,GAAgB,IAAA;AACpB,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,IAAI;AACF,MAAA,IAAA,GAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IACxB,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,GAAO,IAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,IAAA,MAAM,GAAA,GACJ,IAAA,IAAQ,OAAO,IAAA,KAAS,YAAY,IAAA,KAAS,IAAA,IAAQ,SAAA,IAAa,IAAA,GAC9D,OAAQ,IAAA,CAA8B,OAAO,CAAA,GAC7C,CAAA,eAAA,EAAkB,IAAI,MAAM,CAAA,CAAA;AAClC,IAAA,MAAM,IAAI,MAAM,GAAG,CAAA;AAAA,EACrB;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,oBAAoB,UAAA,EAA8C;AACzE,EAAA,IAAI,UAAA,CAAW,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,OAAA;AACrC,EAAA,IAAI,cAAc,IAAA,CAAK,UAAA,CAAW,IAAA,EAAM,GAAG,OAAO,OAAA;AAClD,EAAA,OAAO,UAAA;AACT;AAMO,SAAS,sBAAA,CAAuB,cAAsB,OAAA,EAAyB;AACpF,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,YAAY,CAAA;AAC9B,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,OAAO,CAAA;AAC5B,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,IAAA,CAAK,MAAA,EAAQ,OAAO,YAAA;AACrC,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,EAAG,CAAA,CAAE,QAAQ,CAAA,EAAG,CAAA,CAAE,MAAM,CAAA,EAAG,CAAA,CAAE,IAAI,CAAA,CAAA;AACxD;AAOA,eAAe,yBAAyB,KAAA,EAAqD;AAC3F,EAAA,IAAI,CAAC,MAAM,MAAA,IAAU,CAAC,MAAM,QAAA,IAAY,CAAC,MAAM,WAAA,EAAa;AAC5D,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AAErC,EAAA,MAAM,MAAA,GAA4B;AAAA,IAChC,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,aAAa,KAAA,CAAM,WAAA;AAAA,IACnB,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,mBAAmB,KAAA,CAAM;AAAA,GAC3B;AAEA,EAAA,MAAM,SAAA,GAAY,MAAM,uBAAA,CAAwB,MAAA,EAAQ;AAAA,IACtD,WAAW,KAAA,CAAM;AAAA,GAClB,CAAA;AACD,EAAA,MAAM,YAAA,GAAe,sBAAA,CAAuB,SAAA,EAAW,KAAA,CAAM,OAAO,CAAA;AAEpE,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,MAAA,CAAO,YAAA,CAAa,eAAe,MAAM,CAAA;AACzC,IAAA,MAAA,CAAO,QAAA,GAAW,EAAA;AAClB,IAAA,MAAA,CAAO,MAAM,OAAA,GAAU,+DAAA;AACvB,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,IAAI,OAAA,EAAS;AACb,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,MAAA,CAAO,MAAA,EAAO;AACd,MAAA,OAAA,EAAQ;AAAA,IACV,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,QAAQ,MAAM;AACpC,MAAA,MAAA,CAAO,UAAA,CAAW,QAAQ,GAAG,CAAA;AAAA,IAC/B,CAAC,CAAA;AACD,IAAA,MAAA,CAAO,GAAA,GAAM,YAAA;AACb,IAAA,QAAA,CAAS,IAAA,CAAK,YAAY,MAAM,CAAA;AAChC,IAAA,MAAA,CAAO,UAAA,CAAW,QAAQ,IAAI,CAAA;AAAA,EAChC,CAAC,CAAA;AACH;AAGO,SAAS,+BAA+B,YAAA,EAA2C;AACxF,EAAA,OAAO,EAAE,gBAAA,EAAkB,EAAE,cAAA,EAAgB,cAAa,EAAE;AAC9D;AAGO,IAAM,yBAAN,MAA+D;AAAA,EAC3D,QAAA,GAAW,OAAA;AAAA,EACX,YAAA,GAAqD;AAAA,IAC5D,6BAAA,CAA8B,cAAA;AAAA,IAC9B,6BAAA,CAA8B,cAAA;AAAA,IAC9B,6BAAA,CAA8B,gBAAA;AAAA,IAC9B,6BAAA,CAA8B;AAAA,GAChC;AAAA,EAEA,MAAM,yBACJ,KAAA,EACyC;AACzC,IAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,QAAA,EAAS,GAAI,KAAA;AAC1C,IAAA,MAAM,yBAAyB,KAAK,CAAA;AAEpC,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,cAAA,IAAkB,mBAAA,CAAoB,UAAU,CAAA;AACtE,IAAA,MAAM,UAAA,GACJ,OAAA,KAAY,OAAA,GACR,CAAC,OAAO,CAAA,GACR,OAAA,KAAY,OAAA,GACV,CAAC,OAAA,EAAS,UAAU,CAAA,GACpB,CAAC,YAAY,OAAO,CAAA;AAE5B,IAAA,IAAI,SAAA;AACJ,IAAA,KAAA,MAAW,kBAAkB,UAAA,EAAY;AACvC,MAAA,IAAI;AACF,QAAA,MAAM,eAAA,CAAgB,SAAS,EAAA,EAAI;AAAA,UACjC,MAAA,EAAQ,KAAA;AAAA,UACR,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,gBAAA,EAAkB,UAAU;AAAA,SACpD,CAAA;AAED,QAAA,MAAM,WAAW,MAAM,eAAA;AAAA,UACrB,OAAA;AAAA,UACA,wBAAA;AAAA,UACA;AAAA,YACE,MAAA,EAAQ,MAAA;AAAA,YACR,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,cACnB,UAAA,EAAY,EAAE,IAAA,EAAM,cAAA,EAAgB,OAAO,UAAA,EAAW;AAAA,cACtD;AAAA,aACD;AAAA;AACH,SACF;AAEA,QAAA,MAAM,iBAAiB,QAAA,EAAU,cAAA;AACjC,QAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,UAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,QAChE;AAEA,QAAA,MAAM,eAAA,CAAgB,SAAS,iBAAA,EAAmB;AAAA,UAChD,MAAA,EAAQ,MAAA;AAAA,UACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,gBAAgB;AAAA,SACxC,CAAA;AAED,QAAA,MAAM,YAAY,MAAM,eAAA;AAAA,UACtB,OAAA;AAAA,UACA,SAAA;AAAA,UACA;AAAA,YACE,MAAA,EAAQ,MAAA;AAAA,YACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE;AAAA;AACzB,SACF;AAEA,QAAA,OAAO,EAAE,UAAA,EAAY,SAAA,EAAW,UAAA,EAAY,KAAK,SAAA,EAAU;AAAA,MAC7D,SAAS,KAAA,EAAO;AACd,QAAA,SAAA,GAAY,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,MACtE;AAAA,IACF;AACA,IAAA,MAAM,SAAA,IAAa,IAAI,KAAA,CAAM,oCAAoC,CAAA;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,yBACJ,KAAA,EACyC;AACzC,IAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,QAAA,EAAS,GAAI,KAAA;AAC1C,IAAA,MAAM,QAAA,GAAW,WAAW,IAAA,EAAK;AACjC,IAAA,IAAI,CAAC,uBAAA,CAAwB,QAAQ,CAAA,EAAG;AACtC,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,IAAI,CAAC,QAAA,IAAY,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AACpC,MAAA,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAAA,IAC1D;AAEA,IAAA,MAAM,yBAAyB,KAAK,CAAA;AAEpC,IAAA,MAAM,eAAA,CAAgB,SAAS,EAAA,EAAI;AAAA,MACjC,MAAA,EAAQ,KAAA;AAAA,MACR,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,gBAAA,EAAkB,YAAY;AAAA,KACtD,CAAA;AAED,IAAA,MAAM,WAAW,MAAM,eAAA;AAAA,MACrB,OAAA;AAAA,MACA,qCAAA;AAAA,MACA;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,UACnB,UAAA,EAAY,EAAE,IAAA,EAAM,UAAA,EAAY,OAAO,QAAA,EAAS;AAAA,UAChD;AAAA,SACD;AAAA;AACH,KACF;AAEA,IAAA,MAAM,iBAAiB,QAAA,EAAU,cAAA;AACjC,IAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,MAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,IAChE;AAEA,IAAA,MAAM,eAAA,CAAgB,SAAS,iBAAA,EAAmB;AAAA,MAChD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,gBAAgB;AAAA,KACxC,CAAA;AAED,IAAA,MAAM,SAAA,GAAY,MAAM,eAAA,CAAyC,OAAA,EAAS,SAAA,EAAW;AAAA,MACnF,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE;AAAA,KACxB,CAAA;AAED,IAAA,OAAO,EAAE,UAAA,EAAY,SAAA,EAAW,UAAA,EAAY,KAAK,SAAA,EAAU;AAAA,EAC7D;AAAA,EAEA,MAAM,sBACJ,KAAA,EACsC;AACtC,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,QAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,4BAAA,CAA8B,CAAA;AACrF,IAAA,IAAI,KAAA,CAAM,KAAA,EAAO,IAAA,EAAK,EAAG,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,KAAA,CAAM,KAAA,CAAM,IAAA,EAAM,CAAA;AACzE,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,CAAI,UAAS,EAAG;AAAA;AAAA,MAEtC,WAAA,EAAa,MAAA;AAAA,MACb,OAAA,EAAS,EAAE,MAAA,EAAQ,kBAAA;AAAmB,KACvC,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,YAAA,EAAe,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAAA,IAC7C;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAQ7B,IAAA,OAAA,CAAQ,IAAA,CAAK,gBAAA,IAAoB,EAAC,EAC/B,MAAA;AAAA,MACC,CACE,SAAA,KAMG,OAAA,CAAQ,SAAA,EAAW,EAAA,IAAM,WAAW,MAAM;AAAA,KACjD,CACC,GAAA,CAAI,CAAC,SAAA,MAAe;AAAA,MACnB,IAAI,SAAA,CAAU,EAAA;AAAA,MACd,QAAQ,SAAA,CAAU,MAAA;AAAA,MAClB,MAAM,YAAA,CAAa,SAAA,CAAU,IAAI,CAAA,IAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAAA,MAChE,MAAM,SAAA,CAAU;AAAA,KAClB,CAAE,CAAA;AAAA,EACN;AAAA,EAEA,0BAA0B,MAAA,EAAqC;AAC7D,IAAA,OAAO,8BAAA,CAA+B,CAAA,OAAA,EAAU,MAAM,CAAA,CAAE,CAAA;AAAA,EAC1D;AACF;AAEA,SAAS,aAAa,IAAA,EAA2D;AAC/E,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAClB,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACrC,EAAA,OAAO,IAAA,CAAK,OAAO,CAAA,IAAK,IAAA,CAAK,EAAA,IAAM,OAAO,MAAA,CAAO,IAAI,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AAC/D;AAEA,SAAS,UAAU,MAAA,EAAwB;AACzC,EAAA,IAAI,CAAC,QAAQ,OAAO,EAAA;AACpB,EAAA,OAAO,MAAA,CAAO,OAAO,CAAC,CAAA,CAAE,aAAY,GAAI,MAAA,CAAO,MAAM,CAAC,CAAA;AACxD;;;AC3SA,IAAI,OAAA,GAA8B,IAAA;AAElC,SAAS,WAAW,MAAA,EAAmC;AACrD,EAAA,OAAO,OAAO,eAAA,IAAmB,uBAAA;AACnC;AAEA,SAAS,iBAAiB,MAAA,EAAmC;AAC3D,EAAA,OAAO,MAAA,CAAO,oBAAoB,MAAA,CAAO,WAAA;AAC3C;AAEA,SAAS,gBAAA,GAAmB;AAE1B,EAAA,OAAO,IAAIA,iCAAA,CAAqB,EAAE,KAAA,EAAO,MAAA,CAAO,cAAc,CAAA;AAChE;AAEA,SAAS,eAAe,MAAA,EAA2B;AACjD,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,EAAU,IAAA,EAAK,IAAK,MAAA;AAC5C,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,OAAO,EAAE,CAAA;AAAA,IAC1C,WAAA,EAAa,uBAAuB,MAAM,CAAA;AAAA,IAC1C,WAAW,MAAA,CAAO,QAAA;AAAA,IAClB,cAAc,MAAA,CAAO,WAAA;AAAA,IACrB,wBAAA,EAA0B,MAAA,CAAO,qBAAA,IAAyB,MAAA,CAAO,WAAA;AAAA,IACjE,aAAA,EAAe,MAAA;AAAA,IACf,KAAA,EAAO,OAAO,MAAA,IAAU,qCAAA;AAAA,IACxB,YAAY,gBAAA,EAAiB;AAAA,IAC7B,gBAAA,EAAkB,QAAA,GAAW,EAAE,QAAA,EAAS,GAAI,MAAA;AAAA,IAC5C,gBAAA,EAAkB,QAAA,GAAW,EAAE,QAAA,EAAS,GAAI;AAAA,GAC9C;AACF;AAEA,SAAS,oBAAoB,MAAA,EAA2B;AACtD,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,EAAU,IAAA,EAAK,IAAK,MAAA;AAC5C,EAAA,OAAO;AAAA,IACL,GAAG,eAAe,MAAM,CAAA;AAAA,IACxB,kBAAA,EAAoB,iBAAiB,MAAM,CAAA;AAAA,IAC3C,oBAAA,EAAsB,IAAA;AAAA,IACtB,cAAc,CAAC,QAAA;AAAA,IACf,WAAW,gBAAA;AAAiB,GAC9B;AACF;AAEO,SAAS,kBAAkB,MAAA,EAAwC;AACxE,EAAA,IAAI,SAAS,OAAO,OAAA;AACpB,EAAA,OAAA,GAAU,IAAIC,wBAAA,CAAY,mBAAA,CAAoB,MAAM,CAAC,CAAA;AACrD,EAAA,OAAO,OAAA;AACT;AAMA,SAAS,uBAAuB,MAAA,EAA+C;AAC7E,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,iBAAA,EAAmB,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC7D,EAAA,IAAI,CAAC,WAAW,OAAO,MAAA;AACvB,EAAA,IAAI;AACF,IAAA,IAAI,IAAI,GAAA,CAAI,SAAS,CAAA,CAAE,MAAA,KAAW,IAAI,GAAA,CAAI,MAAA,CAAO,MAAM,CAAA,CAAE,MAAA,EAAQ,OAAO,KAAA,CAAA;AAAA,EAC1E,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,GAAG,SAAS,CAAA,sCAAA,CAAA;AACrB;AAEO,SAAS,gBAAA,GAAyB;AACvC,EAAA,OAAA,GAAU,IAAA;AACZ;AAcA,SAAS,UAAA,CAAW,QAA2B,OAAA,EAAkC;AAC/E,EAAA,MAAM,UAAA,GACJ,OAAO,OAAA,KAAY,QAAA,GAAW,EAAE,SAAA,EAAW,OAAA,EAAQ,GAAK,OAAA,IAAW,EAAC;AACtE,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,EAAU,IAAA,EAAK;AACvC,EAAA,MAAM,gBAAA,GAA2C,EAAE,GAAG,UAAA,CAAW,gBAAA,EAAiB;AAClF,EAAA,IAAI,QAAA,mBAA2B,QAAA,GAAW,QAAA;AAC1C,EAAA,IAAI,WAAW,YAAA,EAAc;AAC3B,IAAA,MAAA,CAAO,MAAA;AAAA,MACL,gBAAA;AAAA,MACA,8BAAA,CAA+B,UAAA,CAAW,YAAY,CAAA,CAAE;AAAA,KAC1D;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,OAAO,UAAA,CAAW,SAAA,GAAY,EAAE,SAAA,EAAW,UAAA,CAAW,WAAU,GAAI,MAAA;AAAA,IACpE,kBAAkB,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAA,CAAE,SAAS,gBAAA,GAAmB;AAAA,GAC9E;AACF;AAEA,eAAsB,cAAA,CACpB,QACA,kBAAA,EACe;AACf,EAAA,gBAAA,EAAiB;AACjB,EAAA,MAAM,EAAA,GAAK,kBAAkB,MAAM,CAAA;AACnC,EAAA,MAAM,EAAA,CAAG,cAAA,CAAe,UAAA,CAAW,MAAA,EAAQ,kBAAkB,CAAC,CAAA;AAChE;AAOA,eAAsB,uBAAA,CACpB,QACA,kBAAA,EACiB;AACjB,EAAA,gBAAA,EAAiB;AAEjB,EAAA,iBAAA,CAAkB,MAAM,CAAA;AACxB,EAAA,MAAM,MAAA,GAAS,IAAIC,uBAAA,CAAW,cAAA,CAAe,MAAM,CAAC,CAAA;AACpD,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,MAAA,EAAQ,kBAAkB,CAAA;AAClD,EAAA,MAAM,OAAA,GAAU,MAAM,MAAA,CAAO,mBAAA,CAAoB;AAAA,IAC/C,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,gBAAA,EAAkB;AAAA,MAChB,GAAI,IAAA,CAAK,gBAAA,IAAoB,EAAC;AAAA,MAC9B,MAAA,EAAQ;AAAA;AACV,GACD,CAAA;AACD,EAAA,OAAO,OAAA,CAAQ,GAAA;AACjB;AAMA,eAAsB,WAAA,CACpB,QACA,kBAAA,EAC+D;AAC/D,EAAA,gBAAA,EAAiB;AACjB,EAAA,MAAM,EAAA,GAAK,kBAAkB,MAAM,CAAA;AACnC,EAAA,MAAM,OAAO,MAAM,EAAA,CAAG,YAAY,UAAA,CAAW,MAAA,EAAQ,kBAAkB,CAAC,CAAA;AACxE,EAAA,MAAM,OAAA,GAAU,UAAU,IAAI,CAAA;AAC9B,EAAA,IAAI,CAAC,QAAQ,WAAA,EAAa;AACxB,IAAA,MAAM,IAAI,MAAM,iEAAiE,CAAA;AAAA,EACnF;AACA,EAAA,oBAAA,CAAqB,QAAQ,WAAW,CAAA;AACxC,EAAA,YAAA,CAAa,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA,EAAG,QAAQ,WAAW,CAAA;AAC5D,EAAA,MAAM,cAAA,GACJ,OAAO,IAAA,CAAK,KAAA,KAAU,YAAY,IAAA,CAAK,KAAA,IAAS,WAAA,IAAe,IAAA,CAAK,QAChE,MAAA,CAAQ,IAAA,CAAK,KAAA,CAAiC,SAAA,IAAa,EAAE,CAAA,GAC7D,MAAA;AACN,EAAA,OAAO,EAAE,OAAA,EAAS,SAAA,EAAW,cAAA,IAAkB,MAAA,EAAU;AAC3D;AAEA,eAAsB,qBAAqB,MAAA,EAGxC;AACD,EAAA,MAAM,EAAA,GAAK,kBAAkB,MAAM,CAAA;AACnC,EAAA,MAAM,IAAA,GAAO,MAAM,EAAA,CAAG,sBAAA,EAAuB;AAC7C,EAAA,MAAM,OAAA,GAAU,UAAU,IAAI,CAAA;AAC9B,EAAA,oBAAA,CAAqB,QAAQ,WAAW,CAAA;AACxC,EAAA,YAAA,CAAa,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA,EAAG,QAAQ,WAAW,CAAA;AAC5D,EAAA,MAAM,SAAA,GACJ,OAAO,IAAA,CAAK,KAAA,KAAU,YAAY,IAAA,CAAK,KAAA,IAAS,WAAA,IAAe,IAAA,CAAK,QAChE,MAAA,CAAQ,IAAA,CAAK,KAAA,CAAiC,SAAA,IAAa,EAAE,CAAA,GAC7D,MAAA;AACN,EAAA,OAAO,EAAE,OAAA,EAAS,SAAA,EAAW,SAAA,IAAa,MAAA,EAAU;AACtD;AAMA,eAAsB,0BAA0B,MAAA,EAA0C;AACxF,EAAA,MAAM,EAAA,GAAK,kBAAkB,MAAM,CAAA;AACnC,EAAA,MAAM,GAAG,mBAAA,EAAoB;AAC/B;AAGO,SAAS,iBAAA,GAA6B;AAC3C,EAAA,IAAI;AACF,IAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,MAAA,IAAU,MAAA,CAAO,WAAW,MAAM,CAAA;AAAA,EAC1D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,eAAsB,gBAAgB,MAAA,EAA0C;AAC9E,EAAA,YAAA,CAAa,UAAA,CAAW,UAAA,CAAW,MAAM,CAAC,CAAA;AAC1C,EAAA,MAAM,EAAA,GAAK,kBAAkB,MAAM,CAAA;AACnC,EAAA,MAAM,GAAG,eAAA,EAAgB;AAC3B;AAEO,SAAS,qBAAqB,MAAA,EAA0C;AAC7E,EAAA,OAAO,YAAA,CAAa,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAC,CAAA;AAChD;AAEO,SAAS,mBAAmB,MAAA,EAAiC;AAClE,EAAA,YAAA,CAAa,UAAA,CAAW,UAAA,CAAW,MAAM,CAAC,CAAA;AAC5C;AAEA,SAAS,UAAU,IAAA,EAAiC;AAClD,EAAA,OAAO;AAAA,IACL,aAAa,IAAA,CAAK,YAAA;AAAA,IAClB,SAAS,IAAA,CAAK,QAAA;AAAA,IACd,SAAA,EAAW,IAAA,CAAK,UAAA,GAAa,IAAA,CAAK,aAAa,GAAA,GAAO,MAAA;AAAA,IACtD,SAAS,IAAA,CAAK;AAAA,GAChB;AACF;AAEA,SAAS,qBAAqB,WAAA,EAA2B;AACvD,EAAA,IAAI,WAAA,CAAY,KAAA,CAAM,GAAG,CAAA,CAAE,WAAW,CAAA,EAAG;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACF;AAEA,eAAsB,eAAe,MAAA,EAAgE;AACnG,EAAA,MAAM,EAAA,GAAK,kBAAkB,MAAM,CAAA;AACnC,EAAA,MAAM,IAAA,GAAO,MAAM,EAAA,CAAG,OAAA,EAAQ;AAC9B,EAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,OAAA,EAAS,OAAO,IAAA;AAClC,EAAA,OAAO,UAAU,IAAI,CAAA;AACvB;;;AC9MO,SAAS,yBACd,KAAA,EACyC;AACzC,EAAA,MAAM,UAAU,6BAAA,EAA8B;AAC9C,EAAA,IACE,CAAC,QAAQ,YAAA,CAAa,QAAA,CAAS,8BAA8B,cAAc,CAAA,IAC3E,CAAC,OAAA,CAAQ,wBAAA,EACT;AACA,IAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,IAAI,KAAA,CAAM,oDAAoD,CAAC,CAAA;AAAA,EACvF;AACA,EAAA,OAAO,OAAA,CAAQ,yBAAyB,KAAK,CAAA;AAC/C;AAGO,SAAS,sBACd,KAAA,EACsC;AACtC,EAAA,MAAM,UAAU,6BAAA,EAA8B;AAC9C,EAAA,IACE,CAAC,QAAQ,YAAA,CAAa,QAAA,CAAS,8BAA8B,gBAAgB,CAAA,IAC7E,CAAC,OAAA,CAAQ,qBAAA,EACT;AACA,IAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,IAAI,KAAA,CAAM,qDAAqD,CAAC,CAAA;AAAA,EACxF;AACA,EAAA,OAAO,OAAA,CAAQ,sBAAsB,KAAK,CAAA;AAC5C;;;ACpBA,IAAM,sBAAN,MAA0B;AAAA,EAChB,KAAA,GAAuB,MAAA;AAAA,EACvB,SAAA;AAAA;AAAA,EAEA,QAAA,GAA6B,EAAE,KAAA,EAAO,MAAA,EAAQ,SAAS,KAAA,EAAM;AAAA,EAC7D,SAAyB,EAAC;AAAA,EAC1B,MAAA,GAAkD,IAAA;AAAA,EAClD,gBAA0B,EAAC;AAAA,EAC3B,SAAA,uBAAgB,GAAA,EAAgB;AAAA,EAExC,UAAU,MAAA,EAA8B;AACtC,IAAA,IAAA,CAAK,SAAS,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,GAAG,MAAA,EAAO;AAAA,EAC5C;AAAA,EAEA,WAAA,GAAc,MAAwB,IAAA,CAAK,QAAA;AAAA,EAE3C,SAAA,GAAY,CAAC,QAAA,KAAuC;AAClD,IAAA,IAAA,CAAK,SAAA,CAAU,IAAI,QAAQ,CAAA;AAC3B,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,SAAA,CAAU,OAAO,QAAQ,CAAA;AAAA,IAChC,CAAA;AAAA,EACF,CAAA;AAAA,EAEQ,IAAA,GAAa;AACnB,IAAA,KAAA,MAAW,QAAA,IAAY,IAAA,CAAK,SAAA,EAAW,QAAA,EAAS;AAAA,EAClD;AAAA,EAEQ,QAAA,CAAS,OAAsB,SAAA,EAA0B;AAC/D,IAAA,IAAI,IAAA,CAAK,KAAA,KAAU,KAAA,IAAS,IAAA,CAAK,cAAc,SAAA,EAAW;AAC1D,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,QAAA,GAAW;AAAA,MACd,KAAA;AAAA,MACA,SAAS,KAAA,KAAU,MAAA;AAAA,MACnB;AAAA,KACF;AACA,IAAA,IAAA,CAAK,IAAA,EAAK;AAAA,EACZ;AAAA;AAAA,EAGA,MAAM,aAAA,GAA+B;AACnC,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAClB,IAAA,MAAM,IAAA,CAAK,MAAA;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,YAAA,EAAyD;AAC1E,IAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,OAAO,IAAA,CAAK,MAAA;AAC7B,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,WAAA,CAAY,YAAY,CAAA,CAAE,QAAQ,MAAM;AACzD,MAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAAA,IAChB,CAAC,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA,EAGA,cAAc,YAAA,EAAyD;AACrE,IAAA,OAAO,IAAA,CAAK,mBAAmB,YAAY,CAAA;AAAA,EAC7C;AAAA;AAAA,EAGA,cAAA,GAAuB;AACrB,IAAA,IAAI,IAAA,CAAK,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAM,UAAU,IAAA,CAAK,aAAA,CAAc,OAAO,CAAA,EAAG,IAAA,CAAK,cAAc,MAAM,CAAA;AACtE,IAAA,IAAA,CAAK,SAAS,MAAM,CAAA;AACpB,IAAA,IAAA,CAAK,MAAA,CAAO,YAAY,IAAI,CAAA;AAC5B,IAAA,KAAA,MAAW,CAAA,IAAK,OAAA,EAAS,CAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,EAC5C;AAAA;AAAA,EAGA,aAAa,YAAA,EAA6B;AACxC,IAAA,IAAI,IAAA,CAAK,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAM,UAAU,IAAA,CAAK,aAAA,CAAc,OAAO,CAAA,EAAG,IAAA,CAAK,cAAc,MAAM,CAAA;AACtE,IAAA,IAAA,CAAK,QAAA,CAAS,QAAQ,YAAY,CAAA;AAClC,IAAA,IAAA,CAAK,MAAA,CAAO,YAAY,KAAK,CAAA;AAC7B,IAAA,KAAA,MAAW,CAAA,IAAK,OAAA,EAAS,CAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,EAC3C;AAAA,EAEA,MAAc,YAAY,YAAA,EAAyD;AACjF,IAAA,IAAA,CAAK,SAAA,GAAY,YAAA;AAEjB,IAAA,IAAI,IAAA,CAAK,OAAO,UAAA,EAAY;AAC1B,MAAA,IAAA,CAAK,QAAA,CAAS,cAAc,YAAY,CAAA;AACxC,MAAA,IAAI;AACF,QAAA,MAAM,EAAA,GAAK,MAAM,IAAA,CAAK,MAAA,CAAO,UAAA,EAAW;AACxC,QAAA,IAAI,EAAA,EAAI;AACN,UAAA,IAAA,CAAK,SAAS,MAAM,CAAA;AACpB,UAAA,IAAA,CAAK,MAAA,CAAO,YAAY,IAAI,CAAA;AAC5B,UAAA,OAAO,OAAA;AAAA,QACT;AAAA,MACF,SAAS,CAAA,EAAG;AACV,QAAA,IAAA,CAAK,YAAY,CAAA,YAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,OAAO,CAAC,CAAA;AAAA,MAC5D;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,QAAA,CAAS,QAAA,EAAU,IAAA,CAAK,SAAS,CAAA;AACtC,IAAA,IAAA,CAAK,OAAO,gBAAA,IAAmB;AAE/B,IAAA,OAAO,IAAI,OAAA,CAAiC,CAAC,OAAA,KAAY;AACvD,MAAA,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,EAAE,OAAA,EAAS,CAAA;AAAA,IACrC,CAAC,CAAA;AAAA,EACH;AACF,CAAA;AAGO,IAAM,QAAA,GAAW,IAAI,mBAAA;AAM5B,eAAsB,iBAAA,CACpB,SACA,OAAA,EAKY;AACZ,EAAA,IAAI,OAAA,EAAS,MAAA,EAAQ,OAAO,OAAA,EAAQ;AAEpC,EAAA,MAAM,SAAS,aAAA,EAAc;AAE7B,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,OAAA,EAAQ;AAAA,EACvB,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,EAAE,OAAA,EAAS,cAAA,IAAkB,qBAAA,EAAuB,KAAK,GAAG,MAAM,KAAA;AACtE,IAAA,MAAM,cAAc,MAAM,QAAA,CAAS,kBAAA,CAAmB,SAAA,CAAU,KAAK,CAAC,CAAA;AACtE,IAAA,IAAI,WAAA,KAAgB,SAAS,MAAM,KAAA;AACnC,IAAA,OAAO,OAAA,EAAQ;AAAA,EACjB;AACF;AAEA,SAAS,sBAAsB,KAAA,EAAyB;AACtD,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,UAAU,OAAO,KAAA;AAChD,EAAA,MAAM,CAAA,GAAI,KAAA;AACV,EAAA,OAAO,CAAA,CAAE,WAAW,GAAA,IAAO,CAAA,CAAE,eAAe,GAAA,IAAO,CAAA,CAAE,UAAU,MAAA,KAAW,GAAA;AAC5E;AAEA,SAAS,UAAU,KAAA,EAAoC;AACrD,EAAA,IAAI,KAAA,YAAiB,KAAA,EAAO,OAAO,KAAA,CAAM,OAAA;AACzC,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,aAAa,KAAA,EAAO;AAC5D,IAAA,MAAM,IAAK,KAAA,CAAgC,OAAA;AAC3C,IAAA,OAAO,OAAO,CAAA,KAAM,QAAA,GAAW,CAAA,GAAI,MAAA;AAAA,EACrC;AACA,EAAA,OAAO,MAAA;AACT;AC3JA,IAAM,mBAAA,GAAsBC,oBAA+C,IAAI,CAAA;AAOxE,SAAS,oBAAA,CAAqB,EAAE,MAAA,EAAQ,UAAA,EAAY,UAAS,EAA8B;AAChG,EAAA,MAAM,MAAA,GAASC,cAAQ,MAAM,UAAA,IAAc,EAAC,EAAG,CAAC,UAAU,CAAC,CAAA;AAC3D,EAAA,MAAM,UAAA,GAAa,gBAAgB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,eAAqC,IAAI,CAAA;AACvE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,eAAS,UAAU,CAAA;AAEjD,EAAA,MAAM,cAAA,GAAiBC,kBAAY,YAAY;AAC7C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,MAAM,CAAA;AAC3C,MAAA,UAAA,CAAW,OAAO,CAAA;AAAA,IACpB,CAAA,CAAA,MAAQ;AACN,MAAA,UAAA,CAAW,IAAI,CAAA;AAAA,IACjB,CAAA,SAAE;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,UAAU,CAAC,CAAA;AAEvB,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,KAAK,cAAA,EAAe;AAAA,EACtB,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAA,MAAM,KAAA,GAAQD,iBAAA;AAAA,IACZ,OAAO,SAAA,KAAuB;AAC5B,MAAA,IAAI,CAAC,UAAA,EAAY,MAAM,IAAI,MAAM,oBAAoB,CAAA;AACrD,MAAA,MAAM,cAAA,CAAe,QAAQ,SAAS,CAAA;AAAA,IACxC,CAAA;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,GACrB;AAEA,EAAA,MAAM,UAAA,GAAaA,iBAAA;AAAA,IACjB,OAAO,SAAA,KAAuB;AAC5B,MAAA,IAAI,CAAC,UAAA,EAAY,MAAM,IAAI,MAAM,oBAAoB,CAAA;AACrD,MAAA,MAAM,EAAE,OAAA,EAAS,IAAA,KAAS,MAAM,WAAA,CAAY,QAAQ,SAAS,CAAA;AAC7D,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,GACrB;AAEA,EAAA,MAAM,MAAA,GAASA,kBAAY,YAAY;AACrC,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,kBAAA,CAAmB,MAA2B,CAAA;AAC9C,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA;AAAA,IACF;AACA,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,MAAM,gBAAgB,MAAM,CAAA;AAAA,EAC9B,CAAA,EAAG,CAAC,MAAA,EAAQ,UAAU,CAAC,CAAA;AAEvB,EAAA,MAAM,gBAAA,GAAmBA,kBAAY,YAAY;AAC/C,IAAA,IAAI,CAAC,UAAA,EAAY,MAAM,IAAI,MAAM,oBAAoB,CAAA;AACrD,IAAA,MAAM,EAAE,OAAA,EAAS,IAAA,EAAM,WAAU,GAAI,MAAM,qBAAqB,MAAM,CAAA;AACtE,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,OAAO,EAAE,SAAA,EAAU;AAAA,EACrB,CAAA,EAAG,CAAC,MAAA,EAAQ,UAAU,CAAC,CAAA;AAEvB,EAAA,MAAM,KAAA,GAAQF,aAAA;AAAA,IACZ,OAAO;AAAA,MACL,UAAA;AAAA,MACA,OAAA;AAAA,MACA,aAAa,OAAA,EAAS,WAAA,KAAgB,UAAA,GAAa,oBAAA,CAAqB,MAAM,CAAA,GAAI,IAAA,CAAA;AAAA,MAClF,OAAA;AAAA,MACA,KAAA;AAAA,MACA,UAAA;AAAA,MACA,MAAA;AAAA,MACA,gBAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA,CAAC,YAAY,OAAA,EAAS,OAAA,EAAS,OAAO,UAAA,EAAY,MAAA,EAAQ,gBAAA,EAAkB,cAAA,EAAgB,MAAM;AAAA,GACpG;AAEA,EAAA,uBAAOI,cAAA,CAAC,mBAAA,CAAoB,QAAA,EAApB,EAA6B,OAAe,QAAA,EAAS,CAAA;AAC/D;AAEO,SAAS,eAAA,GAA4C;AAC1D,EAAA,MAAM,GAAA,GAAMC,iBAAW,mBAAmB,CAAA;AAC1C,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,0DAA0D,CAAA;AACpF,EAAA,OAAO,GAAA;AACT;;;ACpHA,IAAA,iCAAA,GAAA;AAAA,EAAC,KAAA,EAAAC,iCAAAA;AAAA,EAYA,KAAA,EAAAC,iCAAAA;AAAA,EAOA,IAAA,EAAAC,gCAAAA;AAAA,EAKA,OAAA,EAAAC,mCAAAA;AAAA,EASA,KAAA,EAAAC,iCAAAA;AAAA,EAOA,QAAA,EAAAC,oCAAAA;AAAA,EAOA,IAAA,EAAAC,gCAAAA;AAAA,EAKA,WAAA,EAAAC,uCAAAA;AAAA,EAOA,KAAA,EAAAC,iCAAAA;AAAA,EAkBA,aAAA,EAAAC,yCAAAA;AAAA,EAMA,aAAA,EAAAC,yCAAAA;AAAA,EAIA,cAAA,EAAAC,0CAAAA;AAAA,EA+BA,UAAA,EAAAC,sCAAAA;AAAA,EAeA,SAAA,EAAAC,qCAAAA;AAAA,EAqBA,UAAA,EAAAC,sCAAAA;AAAA,EAKA,YAAA,EAAAC,wCAAAA;AAAA,EAcA,SAAA,EAAAC,qCAAAA;AAAA,EAeA,OAAA,EAAAC,mCAAAA;AAAA,EAQA,WAAA,EAAAC,uCAAAA;AAAA,EAMA,WAAA,EAAAC,uCAAAA;AAAA,EAMA,IAAA,EAAAC,gCAAAA;AAAA,EAOA,UAAA,EAAAC,sCAAAA;AAAA,EAKA,aAAA,EAAAC,yCAAAA;AAAA,EAgBA,KAAA,EAAAC,iCAAAA;AAAA,EAOA,MAAA,EAAAC;AAAA,CAAA;AClJM,IAAM,yBAAA,GAA4B;AAEzC,IAAM,QAAA,GAA0C;AAAA,EAC9C,KAAA,EAAO,SAAA;AAAA,EACP,QAAA,EAAU,wCAAA;AAAA,EACV,qBAAA,EAAuB,mBAAA;AAAA,EACvB,6BAAA,EAA+B,UAAA;AAAA,EAC/B,mBAAA,EAAqB,UAAA;AAAA,EACrB,0BAAA,EAA4B,kBAAA;AAAA,EAC5B,cAAA,EAAgB,uBAAA;AAAA,EAChB,cAAA,EAAgB,gBAAA;AAAA,EAChB,SAAA,EAAW,+BAAA;AAAA,EACX,YAAA,EAAc,QAAA;AAAA,EACd,YAAA,EAAc,QAAA;AAAA,EACd,aAAA,EAAe,IAAA;AAAA,EACf,IAAA,EAAM,2EAAA;AAAA,EACN,YAAA,EACE,0FAAA;AAAA,EACF,MAAA,EAAQ,QAAA;AAAA,EACR,qBAAA,EAAuB,iEAAA;AAAA,EACvB,YAAA,EAAc,eAAA;AAAA,EACd,YAAA,EAAc,eAAA;AAAA,EACd,YAAA,EAAc,mBAAA;AAAA,EACd,SAAA,EAAW,kCAAA;AAAA,EACX,gBAAA,EAAkB,wBAAA;AAAA,EAClB,aAAA,EAAe,gBAAA;AAAA,EACf,gBAAA,EAAkB;AACpB,CAAA;AAEA,SAAS,eAAe,MAAA,EAAwD;AAG9E,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,iBAAA,EAAmB,IAAA,EAAK;AAChD,EAAA,IAAI,QAAA,EAAU,OAAO,QAAA,CAAS,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC/C,EAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,IAAA,IAAI;AACF,MAAA,OAAO,IAAI,GAAA,CAAI,MAAA,CAAO,MAAM,CAAA,CAAE,MAAA;AAAA,IAChC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,QAAA,CAAS,WAAsC,MAAA,EAA+C;AACrG,EAAA,IAAI,UAAU,MAAA,KAAW,QAAA,IAAY,MAAA,CAAO,YAAA,SAAqB,MAAA,CAAO,YAAA;AACxE,EAAA,IAAI,UAAU,MAAA,KAAW,QAAA,IAAY,MAAA,CAAO,YAAA,SAAqB,MAAA,CAAO,YAAA;AACxE,EAAA,OAAO,SAAA,CAAU,IAAA;AACnB;AAEA,SAAS,MAAM,KAAA,EAAkD;AAC/D,EAAA,OAAO,KAAA,CAAM,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AACvC;AAEO,SAAS,kBAAA,CAAmB;AAAA,EACjC,MAAA;AAAA,EACA,iBAAA,EAAmB,qBAAA;AAAA,EACnB,WAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA,EAAQ,UAAA;AAAA,EACR,SAAA;AAAA,EACA,IAAA,GAAO,OAAA;AAAA,EACP,oBAAA,GAAuB,IAAA;AAAA,EACvB,YAAA,GAAe,IAAA;AAAA,EACf,eAAA,GAAkB,MAAA;AAAA,EAClB,UAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EACA,oBAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA,GAAa;AACf,CAAA,EAA4B;AAC1B,EAAA,MAAM,iBAAA,GAAoB,6BAAA;AAAA,IACxB,qBAAA;AAAA,IACA,MAAA,CAAO;AAAA,GACT;AACA,EAAA,MAAM,MAAA,GAAS,EAAE,GAAG,QAAA,EAAU,GAAG,UAAA,EAAW;AAC5C,EAAA,MAAM,UAAA,GAAa,gBAAgB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI7B,eAAiC,SAAS,CAAA;AAC5E,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIA,eAAS,EAAE,CAAA;AAC/C,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,eAAS,EAAE,CAAA;AAC3C,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAIA,eAAS,EAAE,CAAA;AACzD,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAIA,eAAS,KAAK,CAAA;AAC5D,EAAA,MAAM,UAAA,GAA4B;AAAA,IAChC,GAAG,KAAA;AAAA,IACH,CAAC,iBAA2B,GAAG,UAAA,IAAc;AAAA,GAC/C;AACA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,eAAqC,IAAI,CAAA;AACvE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAS,EAAE,CAAA;AACrC,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIA,cAAAA,CAAsC,EAAE,CAAA;AAC5E,EAAA,MAAM,aAAA,GACJ,oBAAA,KAAyB,KAAA,IACzB,EAAE,KAAA,CAAM,OAAA,CAAQ,eAAe,CAAA,IAAK,eAAA,CAAgB,MAAA,KAAW,CAAA,CAAA,IAC/D,iBAAA,CAAkB,YAAA,CAAa,QAAA,CAAS,6BAAA,CAA8B,gBAAgB,CAAA,IACtF,iBAAA,CAAkB,YAAA,CAAa,QAAA,CAAS,6BAAA,CAA8B,kBAAkB,CAAA,IACxF,OAAO,iBAAA,CAAkB,qBAAA,KAA0B,UAAA,IACnD,OAAO,kBAAkB,yBAAA,KAA8B,UAAA;AACzD,EAAA,MAAM,eAAA,GACJ,kBAAkB,YAAA,CAAa,QAAA,CAAS,8BAA8B,cAAc,CAAA,IACpF,OAAO,iBAAA,CAAkB,wBAAA,KAA6B,UAAA;AACxD,EAAA,MAAM,eAAA,GACJ,YAAA,KAAiB,KAAA,IACjB,iBAAA,CAAkB,YAAA,CAAa,QAAA,CAAS,6BAAA,CAA8B,cAAc,CAAA,IACpF,OAAO,iBAAA,CAAkB,wBAAA,KAA6B,UAAA;AACxD,EAAA,MAAM,UAAA,GAAa,cAAc,UAAA,IAAc,eAAA;AAG/C,EAAAE,gBAAU,MAAM;AACd,IAAA,MAAM,SAAA,GAAY,MAAM,UAAA,CAAW,IAAI,CAAA;AACvC,IAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,SAAS,CAAA;AAC7C,IAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,SAAS,CAAA;AAC7C,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,YAAY,SAAS,CAAA;AAChD,MAAA,MAAA,CAAO,mBAAA,CAAoB,YAAY,SAAS,CAAA;AAAA,IAClD,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAAA,gBAAU,MAAM;AACd,IAAA,MAAM,kBAAkB,iBAAA,CAAkB,qBAAA;AAC1C,IAAA,IAAI,CAAC,aAAA,IAAiB,CAAC,eAAA,EAAiB;AACtC,MAAA,aAAA,CAAc,EAAE,CAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,MAAM,OAAA,GAAU,eAAe,MAAM,CAAA;AACrC,IAAA,MAAM,SAAA,GACJ,eAAA,KAAoB,MAAA,IAAU,eAAA,KAAoB,SAC9C,IAAA,GACA,IAAI,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA;AAEzD,IAAA,MAAM,KAAA,GAAQ,CAAC,IAAA,KAAsC;AACnD,MAAA,MAAM,QAAA,GAAW,SAAA,GACb,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAM,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,MAAA,CAAO,WAAA,EAAa,CAAC,CAAA,GACxD,IAAA;AACJ,MAAA,IAAI,CAAC,SAAA,EAAW,aAAA,CAAc,QAAQ,CAAA;AAAA,IACxC,CAAA;AAEA,IAAA,IAAI,CAAC,OAAA,EAAS;AAGZ,MAAA,IAAI,CAAC,SAAA,EAAW,aAAA,CAAc,EAAE,CAAA;AAChC,MAAA;AAAA,IACF;AAEA,IAAA,KAAK,eAAA,CAAgB,IAAA,CAAK,iBAAA,EAAmB,EAAE,OAAA,EAAS,OAAA,EAAS,KAAA,EAAO,MAAA,CAAO,QAAA,EAAU,CAAA,CACtF,IAAA,CAAK,CAAC,IAAA,KAAS;AACd,MAAA,KAAA,CAAM,IAAI,CAAA;AAAA,IACZ,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AACX,MAAA,IAAI,CAAC,SAAA,EAAW,aAAA,CAAc,EAAE,CAAA;AAAA,IAClC,CAAC,CAAA;AAEH,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG;AAAA,IACD,MAAA,CAAO,QAAA;AAAA,IACP,MAAA,CAAO,iBAAA;AAAA,IACP,MAAA,CAAO,MAAA;AAAA,IACP,iBAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,OAAA,GAAU,OAAO,iBAAA,KAA4C;AACjE,IAAA,IAAI,CAAC,UAAA,EAAY,MAAM,IAAI,MAAM,oBAAoB,CAAA;AACrD,IAAA,IAAI,SAAS,UAAA,EAAY;AACvB,MAAA,MAAM,eAAe,MAAA,EAAQ,EAAE,SAAA,EAAW,GAAG,mBAAmB,CAAA;AAChE,MAAA;AAAA,IACF;AACA,IAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,MAAK,GAAI,MAAM,YAAY,MAAA,EAAQ;AAAA,MAC7D,SAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,MAAM,aAAA,GAAgB,SAAS,IAAI,CAAA;AAAA,EACrC,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,OAAO,MAAA,KAAmB;AAC1C,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,UAAA,CAAW,MAAM,CAAA;AACjB,IAAA,IAAI;AACF,MAAA,IACE,CAAC,aAAA,IACD,CAAC,iBAAA,CAAkB,YAAA,CAAa,QAAA;AAAA,QAC9B,6BAAA,CAA8B;AAAA,OAChC,IACA,CAAC,iBAAA,CAAkB,yBAAA,EACnB;AACA,QAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,MAC3E;AACA,MAAA,MAAM,OAAA,CAAQ,iBAAA,CAAkB,yBAAA,CAA0B,MAAM,CAAC,CAAA;AAAA,IACnE,SAAS,CAAA,EAAG;AACV,MAAA,QAAA,CAAS,aAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AACnD,MAAA,UAAA,CAAW,IAAI,CAAA;AAAA,IACjB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,gBAAgB,YAAY;AAChC,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,EAAQ;AAAA,IAChB,SAAS,CAAA,EAAG;AACV,MAAA,QAAA,CAAS,aAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AACnD,MAAA,UAAA,CAAW,IAAI,CAAA;AAAA,IACjB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,wBAAA,GAA2B,CAAC,UAAA,KAAuB;AACvD,IAAA,IAAI,oBAAA,EAAsB;AACxB,MAAA,oBAAA,CAAqB,UAAU,CAAA;AAC/B,MAAA;AAAA,IACF;AACA,IAAA,MAAA,CAAO,QAAA,CAAS,OAAO,UAAU,CAAA;AAAA,EACnC,CAAA;AAEA,EAAA,MAAM,WAAA,GAAc,OAAO,KAAA,KAAqB;AAC9C,IAAA,KAAA,CAAM,cAAA,EAAe;AACrB,IAAA,IAAI,CAAC,UAAA,EAAY;AACjB,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,UAAA,CAAW,UAAU,CAAA;AACrB,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,iBAAA,EAAmB,IAAA,EAAK;AAC/C,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,qBAAqB,CAAA;AAAA,MAC9C;AACA,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,IACE,CAAC,eAAA,IACD,CAAC,iBAAA,CAAkB,wBAAA,EACnB;AACA,UAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,qBAAqB,CAAA;AAAA,QAC9C;AACA,QAAA,IAAI,aAAa,eAAA,EAAiB;AAChC,UAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,gBAAgB,CAAA;AAAA,QACzC;AACA,QAAA,MAAM4B,OAAAA,GAAS,MAAM,iBAAA,CAAkB,wBAAA,CAAyB;AAAA,UAC9D,OAAA;AAAA,UACA,UAAA,EAAY,WAAW,IAAA,EAAK;AAAA,UAC5B,QAAA;AAAA,UACA,QAAQ,MAAA,CAAO,MAAA;AAAA,UACf,UAAU,MAAA,CAAO,QAAA;AAAA,UACjB,aAAa,MAAA,CAAO,WAAA;AAAA,UACpB,UAAU,MAAA,CAAO,QAAA;AAAA,UACjB,QAAQ,MAAA,CAAO,MAAA;AAAA,UACf;AAAA,SACD,CAAA;AACD,QAAA,IAAIA,QAAO,UAAA,EAAY;AACrB,UAAA,wBAAA,CAAyBA,QAAO,UAAU,CAAA;AAC1C,UAAA;AAAA,QACF;AACA,QAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,MAC5D;AACA,MAAA,IACE,CAAC,eAAA,IACD,CAAC,iBAAA,CAAkB,YAAA,CAAa,QAAA;AAAA,QAC9B,6BAAA,CAA8B;AAAA,OAChC,IACA,CAAC,iBAAA,CAAkB,wBAAA,EACnB;AACA,QAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,qBAAqB,CAAA;AAAA,MAC9C;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,iBAAA,CAAkB,wBAAA,CAAyB;AAAA,QAC9D,OAAA;AAAA,QACA,UAAA,EAAY,WAAW,IAAA,EAAK;AAAA,QAC5B,QAAA;AAAA,QACA,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf;AAAA,OACD,CAAA;AACD,MAAA,IAAI,OAAO,UAAA,EAAY;AAGrB,QAAA,wBAAA,CAAyB,OAAO,UAAU,CAAA;AAC1C,QAAA;AAAA,MACF;AACA,MAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,IAC5D,SAAS,CAAA,EAAG;AACV,MAAA,QAAA,CAAS,aAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AACnD,MAAA,UAAA,CAAW,IAAI,CAAA;AAAA,IACjB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,eAAA,GAAkB,CAAC,IAAA,KAAiC;AACxD,IAAA,YAAA,CAAa,IAAI,CAAA;AACjB,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,kBAAA,CAAmB,EAAE,CAAA;AAAA,EACvB,CAAA;AAEA,EAAA,MAAM,OAAO,OAAA,KAAY,IAAA;AACzB,EAAA,MAAM,UAAA,GAAa,aAAA,IAAiB,UAAA,CAAW,MAAA,GAAS,CAAA;AACxD,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,UAAA,EAAY,IAAI,KAAK,UAAA,IAAc,UAAA;AAC5D,EAAA,MAAM,SAAA,GACJ,OAAA,CAAQ,UAAA,CAAW,IAAA,EAAM,CAAA,IACzB,OAAA,CAAQ,QAAQ,CAAA,KACf,CAAC,UAAA,IAAc,OAAA,CAAQ,eAAe,CAAA,CAAA;AACzC,EAAA,MAAM,SAAA,GAAY,UAAA,GAAa,MAAA,CAAO,aAAA,GAAgB,MAAA,CAAO,KAAA;AAC7D,EAAA,MAAM,YAAA,GAAe,UAAA,GAAa,MAAA,CAAO,gBAAA,GAAmB,MAAA,CAAO,QAAA;AACnE,EAAA,MAAM,qBAAA,GAAwB,UAAA,GAC1B,MAAA,CAAO,6BAAA,GACP,MAAA,CAAO,qBAAA;AACX,EAAA,MAAM,WAAA,GAAc,UAAA,GAAa,MAAA,CAAO,cAAA,GAAiB,MAAA,CAAO,cAAA;AAChE,EAAA,MAAM,QAAA,GAAW,UAAA,GAAa,MAAA,CAAO,YAAA,GAAe,MAAA,CAAO,IAAA;AAE3D,EAAA,uBACEC,eAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,kCAAO,KAAA,EAAO,SAAS,CAAA,EAAG,KAAA,EAAO,UAAA,EAClD,QAAA,EAAA;AAAA,oBAAAA,eAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAW,iCAAA,CAAO,KAAA,EACvB,QAAA,EAAA;AAAA,MAAA,OAAA,mBAAU5B,cAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,SAAS,GAAA,EAAI,EAAA,EAAG,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,EAAA,EAAI,SAAA,EAAW,iCAAA,CAAO,MAAM,CAAA,GAAK,IAAA;AAAA,sCACxF,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAAA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAW,iCAAA,CAAO,SAAU,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,wBAC3CA,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAW,iCAAA,CAAO,OAAQ,QAAA,EAAA,SAAA,EAAU;AAAA,OAAA,EAC1C;AAAA,KAAA,EACF,CAAA;AAAA,oBACAA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAW,iCAAA,CAAO,UAAW,QAAA,EAAA,YAAA,EAAa,CAAA;AAAA,IAE5C,6BACC4B,eAAA,CAAAC,mBAAA,EAAA,EACG,QAAA,EAAA;AAAA,MAAA,eAAA,mBACCD,eAAA,CAAC,MAAA,EAAA,EAAK,QAAA,EAAU,CAAC,CAAA,KAAM,KAAK,WAAA,CAAY,CAAC,CAAA,EAAG,SAAA,EAAW,iCAAA,CAAO,IAAA,EAC5D,QAAA,EAAA;AAAA,wBAAA5B,cAAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,MAAA;AAAA,YACL,IAAA,EAAK,YAAA;AAAA,YACL,YAAA,EAAc,aAAa,UAAA,GAAa,UAAA;AAAA,YACxC,WAAA,EAAa,qBAAA;AAAA,YACb,KAAA,EAAO,UAAA;AAAA,YACP,UAAU,CAAC,CAAA,KAAM,aAAA,CAAc,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,YAC7C,WAAW,iCAAA,CAAO,KAAA;AAAA,YAClB,QAAA,EAAU;AAAA;AAAA,SACZ;AAAA,wBACA4B,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,iCAAA,CAAO,aAAA,EACrB,QAAA,EAAA;AAAA,0BAAA5B,cAAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAM,kBAAkB,MAAA,GAAS,UAAA;AAAA,cACjC,IAAA,EAAK,UAAA;AAAA,cACL,YAAA,EAAc,aAAa,cAAA,GAAiB,kBAAA;AAAA,cAC5C,aAAa,MAAA,CAAO,mBAAA;AAAA,cACpB,KAAA,EAAO,QAAA;AAAA,cACP,UAAU,CAAC,CAAA,KAAM,WAAA,CAAY,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,cAC3C,SAAA,EAAW,EAAA,CAAG,iCAAA,CAAO,KAAA,EAAO,kCAAO,aAAa,CAAA;AAAA,cAChD,QAAA,EAAU;AAAA;AAAA,WACZ;AAAA,0BACAA,cAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,WAAW,iCAAA,CAAO,cAAA;AAAA,cAClB,QAAA,EAAU,IAAA;AAAA,cACV,YAAA,EAAY,eAAA,GAAkB,MAAA,CAAO,YAAA,GAAe,MAAA,CAAO,YAAA;AAAA,cAC3D,cAAA,EAAc,eAAA;AAAA,cACd,SAAS,MAAM,kBAAA,CAAmB,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,cAE3C,QAAA,kBAAAA,cAAAA,CAAC,sBAAA,EAAA,EAAuB,OAAA,EAAS,eAAA,EAAiB;AAAA;AAAA;AACpD,SAAA,EACF,CAAA;AAAA,QACC,6BACCA,cAAAA,CAAC,SAAI,SAAA,EAAW,iCAAA,CAAO,eACrB,QAAA,kBAAAA,cAAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAM,kBAAkB,MAAA,GAAS,UAAA;AAAA,YACjC,IAAA,EAAK,iBAAA;AAAA,YACL,YAAA,EAAa,cAAA;AAAA,YACb,aAAa,MAAA,CAAO,0BAAA;AAAA,YACpB,KAAA,EAAO,eAAA;AAAA,YACP,UAAU,CAAC,CAAA,KAAM,kBAAA,CAAmB,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,YAClD,SAAA,EAAW,EAAA,CAAG,iCAAA,CAAO,KAAA,EAAO,kCAAO,aAAa,CAAA;AAAA,YAChD,QAAA,EAAU;AAAA;AAAA,WAEd,CAAA,GACE,IAAA;AAAA,wBACJA,cAAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,UAAS,SAAA,EAAW,iCAAA,CAAO,UAAA,EAAY,QAAA,EAAU,QAAQ,CAAC,SAAA,EACpE,QAAA,EAAA,OAAA,KAAY,UAAA,GAAa,WAAM,WAAA,EAClC;AAAA,OAAA,EACF,oBAEAA,cAAAA,CAAC,SAAI,SAAA,EAAW,iCAAA,CAAO,MACrB,QAAA,kBAAAA,cAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,WAAW,iCAAA,CAAO,UAAA;AAAA,UAClB,QAAA,EAAU,IAAA;AAAA,UACV,OAAA,EAAS,MAAM,KAAK,aAAA,EAAc;AAAA,UAEjC,QAAA,EAAA,OAAA,KAAY,KAAA,GAAQ,QAAA,GAAM,MAAA,CAAO;AAAA;AAAA,OACpC,EACF,CAAA;AAAA,MAED,QAAA,mBAAWA,cAAAA,CAAC,GAAA,EAAA,EAAE,WAAW,iCAAA,CAAO,IAAA,EAAO,oBAAS,CAAA,GAAO,IAAA;AAAA,MAEvD,eAAA,IAAmB,kCAClBA,cAAAA,CAAC,OAAE,SAAA,EAAW,iCAAA,CAAO,YACnB,QAAA,kBAAAA,cAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,WAAW,iCAAA,CAAO,aAAA;AAAA,UAClB,QAAA,EAAU,IAAA;AAAA,UACV,OAAA,EAAS,MAAM,eAAA,CAAgB,UAAA,GAAa,YAAY,UAAU,CAAA;AAAA,UAEjE,QAAA,EAAA,UAAA,GAAa,MAAA,CAAO,SAAA,GAAY,MAAA,CAAO;AAAA;AAAA,SAE5C,CAAA,GACE,IAAA;AAAA,MAEH,6BACC4B,eAAA,CAAC,KAAA,EAAA,EAAI,WAAW,iCAAA,CAAO,OAAA,EAAS,eAAW,IAAA,EACzC,QAAA,EAAA;AAAA,wBAAA5B,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,iCAAA,CAAO,WAAA,EAAa,CAAA;AAAA,wBACrCA,cAAAA,CAAC,MAAA,EAAA,EAAK,WAAW,iCAAA,CAAO,WAAA,EAAc,iBAAO,aAAA,EAAc,CAAA;AAAA,wBAC3DA,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,kCAAO,WAAA,EAAa;AAAA,OAAA,EACvC,CAAA,GACE,IAAA;AAAA,MACH,UAAA,mBACCA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,kCAAO,WAAA,EACpB,QAAA,EAAA,UAAA,CAAW,GAAA,CAAI,CAAC,SAAA,qBACf4B,eAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAEC,IAAA,EAAK,QAAA;AAAA,UACL,WAAW,iCAAA,CAAO,SAAA;AAAA,UAClB,QAAA,EAAU,IAAA;AAAA,UACV,OAAA,EAAS,MAAM,KAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAAA,UAE9C,QAAA,EAAA;AAAA,4BAAA5B,cAAAA,CAAC,cAAW,SAAA,EAAsB,CAAA;AAAA,YACjC,YAAY,SAAA,CAAU,MAAA,GAAS,QAAA,GAAM,QAAA,CAAS,WAAW,MAAM;AAAA;AAAA,SAAA;AAAA,QAP3D,SAAA,CAAU;AAAA,OASlB,GACH,CAAA,GACE;AAAA,KAAA,EAEN,oBAEAA,cAAAA,CAAC,OAAE,SAAA,EAAW,iCAAA,CAAO,OAAO,QAAA,EAAA,0DAAA,EAAwD,CAAA;AAAA,IAGrF,KAAA,mBAAQA,cAAAA,CAAC,GAAA,EAAA,EAAE,WAAW,iCAAA,CAAO,KAAA,EAAQ,iBAAM,CAAA,GAAO,IAAA;AAAA,IAElD,UAAA,mBACCA,cAAAA,CAAC,QAAA,EAAA,EAAO,MAAK,QAAA,EAAS,SAAA,EAAW,iCAAA,CAAO,SAAA,EAAW,UAAU,IAAA,EAAM,OAAA,EAAS,QAAA,EACzE,QAAA,EAAA,MAAA,CAAO,QACV,CAAA,GACE,IAAA;AAAA,IAEH,MAAA,mBAASA,cAAAA,CAAC,QAAA,EAAA,EAAO,WAAW,iCAAA,CAAO,MAAA,EAAS,kBAAO,CAAA,GAAY;AAAA,GAAA,EAClE,CAAA;AAEJ;AAEA,SAAS,UAAA,CAAW,EAAE,SAAA,EAAU,EAA6C;AAC3E,EAAA,IAAI,UAAU,IAAA,EAAM;AAClB,IAAA,uBAAOA,cAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,UAAU,IAAA,EAAM,GAAA,EAAI,EAAA,EAAG,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,EAAA,EAAI,SAAA,EAAW,kCAAO,UAAA,EAAY,CAAA;AAAA,EAC/F;AACA,EAAA,uBACEA,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,kCAAO,YAAA,EAAc,aAAA,EAAW,IAAA,EAC9C,QAAA,EAAA,SAAA,CAAU,KAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,aAAY,EAC1C,CAAA;AAEJ;AAEA,SAAS,sBAAA,CAAuB,EAAE,OAAA,EAAQ,EAAyB;AAEjE,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBACEA,cAAAA,CAAC,KAAA,EAAA,EAAI,OAAM,IAAA,EAAK,MAAA,EAAO,MAAK,OAAA,EAAQ,eAAA,EAAgB,IAAA,EAAK,cAAA,EAAe,eAAW,IAAA,EACjF,QAAA,kBAAAA,eAAC,MAAA,EAAA,EAAK,CAAA,EAAE,ywBAAwwB,CAAA,EAClxB,CAAA;AAAA,EAEJ;AACA,EAAA,uBACE4B,eAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,OAAA,EAAQ,eAAA,EAAgB,IAAA,EAAK,cAAA,EAAe,aAAA,EAAW,IAAA,EACjF,QAAA,EAAA;AAAA,oBAAA5B,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,sTAAA,EAAuT,CAAA;AAAA,oBAC/TA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,0KAAA,EAA2K;AAAA,GAAA,EACrL,CAAA;AAEJ;AC5hBO,SAAS,aAAA,CAAc;AAAA,EAC5B,MAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,GAAc,IAAA;AAAA,EACd;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,WAAW8B,0BAAA,CAAqB,QAAA,CAAS,WAAW,QAAA,CAAS,WAAA,EAAa,SAAS,WAAW,CAAA;AAEpG,EAAA,IAAI,QAAA,CAAS,KAAA,KAAU,MAAA,EAAQ,OAAO,IAAA;AAEtC,EAAA,MAAM,iBAAA,GACJ,cACC,MAAM;AACL,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,MAAA;AAC1C,IAAA,MAAM,OAAO,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,OAAA,CAAQ,MAAM,EAAE,CAAA;AAClD,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,UAAA,CAAW,QAAQ,KAAK,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,EAAG,OAAO,MAAA;AAC5E,IAAA,OAAO,KAAK,UAAA,CAAW,GAAG,CAAA,GAAI,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA;AAAA,EAC/C,CAAA,GAAG;AAEL,EAAA,MAAM,aAAA,GAAgB,OAAO,OAAA,EAA8B,IAAA,KAAkB;AAC3E,IAAA,MAAM,aAAA,CAAc,SAAS,IAAI,CAAA;AACjC,IAAA,QAAA,CAAS,cAAA,EAAe;AAAA,EAC1B,CAAA;AAEA,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,SAAA,IAAY;AACZ,IAAA,QAAA,CAAS,aAAa,WAAW,CAAA;AAAA,EACnC,CAAA;AAEA,EAAA,uBACE9B,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAW,MAAA;AAAA,MACX,YAAA,EAAY,WAAA;AAAA,MACZ,KAAA,EAAO,aAAA;AAAA,MACP,OAAA,EAAS,cAAc,YAAA,GAAe,MAAA;AAAA,MAEtC,0BAAAA,cAAAA,CAAC,KAAA,EAAA,EAAI,OAAO,WAAA,EAAa,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,eAAA,EAAgB,EACxD,mBAAS,KAAA,KAAU,YAAA,mBAClB4B,eAAAA,CAAC,KAAA,EAAA,EAAI,OAAO,gBAAA,EACV,QAAA,EAAA;AAAA,wBAAA5B,cAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,YAAA,EAAc,CAAA;AAAA,wBAC1BA,cAAAA,CAAC,GAAA,EAAA,EAAE,KAAA,EAAO,EAAE,QAAQ,CAAA,EAAG,KAAA,EAAO,SAAA,EAAU,EAAG,QAAA,EAAA,0BAAA,EAAmB;AAAA,OAAA,EAChE,CAAA,GACE,QAAA,GACF,QAAA,mBAEAA,cAAAA;AAAA,QAAC,kBAAA;AAAA,QAAA;AAAA,UACC,MAAA;AAAA,UACA,WAAA;AAAA,UACA,OAAA;AAAA,UACA,UAAA;AAAA,UACA,MAAA,EAAQ;AAAA,YACN,KAAA,EAAO,QAAQ,KAAA,IAAS,iBAAA;AAAA,YACxB,QAAA,EAAU,QAAQ,QAAA,IAAY,iEAAA;AAAA,YAC9B,GAAG;AAAA,WACL;AAAA,UACA,SAAA,EAAW,iBAAA;AAAA,UACX,IAAA,EAAK,OAAA;AAAA,UACL,YAAA,EAAc,KAAA;AAAA,UACd,UAAA,EAAY,WAAA;AAAA,UACZ,QAAA,EAAU,YAAA;AAAA,UACV,aAAA,EAAe;AAAA;AAAA,OACjB,EAEJ;AAAA;AAAA,GACF;AAEJ;AAEA,IAAM,aAAA,GAA+B;AAAA,EACnC,QAAA,EAAU,OAAA;AAAA,EACV,KAAA,EAAO,CAAA;AAAA,EACP,MAAA,EAAQ,GAAA;AAAA,EACR,OAAA,EAAS,MAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,cAAA,EAAgB,QAAA;AAAA,EAChB,OAAA,EAAS,EAAA;AAAA,EACT,UAAA,EACE,6GAAA;AAAA,EACF,cAAA,EAAgB;AAClB,CAAA;AAEA,IAAM,WAAA,GAA6B;AAAA,EACjC,KAAA,EAAO;AACT,CAAA;AAEA,IAAM,gBAAA,GAAkC;AAAA,EACtC,OAAA,EAAS,MAAA;AAAA,EACT,YAAA,EAAc,QAAA;AAAA,EACd,GAAA,EAAK,EAAA;AAAA,EACL,OAAA,EAAS,EAAA;AAAA,EACT,YAAA,EAAc,EAAA;AAAA,EACd,UAAA,EAAY;AACd,CAAA;AAEA,IAAM,YAAA,GAA8B;AAAA,EAClC,KAAA,EAAO,EAAA;AAAA,EACP,MAAA,EAAQ,EAAA;AAAA,EACR,YAAA,EAAc,KAAA;AAAA,EACd,MAAA,EAAQ,iCAAA;AAAA,EACR,cAAA,EAAgB,SAAA;AAAA,EAChB,SAAA,EAAW;AACb,CAAA;AAGA,IAAI,OAAO,QAAA,KAAa,WAAA,IAAe,CAAC,QAAA,CAAS,cAAA,CAAe,0BAA0B,CAAA,EAAG;AAC3F,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AAC5C,EAAA,KAAA,CAAM,EAAA,GAAK,0BAAA;AACX,EAAA,KAAA,CAAM,WAAA,GAAc,CAAA,mEAAA,CAAA;AACpB,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,KAAK,CAAA;AACjC;ACjIA,IAAM,eAAA,GAAkBL,oBAA2C,IAAI,CAAA;AAWhE,SAAS,gBAAA,CAAiB;AAAA,EAC/B,QAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAAI,gBAAU,MAAM;AACd,IAAA,QAAA,CAAS,SAAA,CAAU,EAAE,UAAA,EAAY,gBAAA,EAAkB,WAAW,CAAA;AAAA,EAChE,CAAA,EAAG,CAAC,UAAA,EAAY,gBAAA,EAAkB,SAAS,CAAC,CAAA;AAE5C,EAAA,MAAM,WAAW+B,0BAAAA,CAAqB,QAAA,CAAS,WAAW,QAAA,CAAS,WAAA,EAAa,SAAS,WAAW,CAAA;AAEpG,EAAA,MAAM,KAAA,GAAQlC,aAAAA;AAAA,IACZ,OAAO;AAAA,MACL,QAAA;AAAA,MACA,aAAA,EAAe,CAAC,OAAA,KAAqB,QAAA,CAAS,cAAc,OAAO,CAAA;AAAA,MACnE,cAAA,EAAgB,MAAM,QAAA,CAAS,cAAA,EAAe;AAAA,MAC9C,YAAA,EAAc,CAAC,OAAA,KAAqB,QAAA,CAAS,aAAa,OAAO;AAAA,KACnE,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,uBACEgC,eAAAA,CAAC,eAAA,CAAgB,QAAA,EAAhB,EAAyB,KAAA,EACvB,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACA,0BAAU5B,cAAAA,CAAC,aAAA,EAAA,EAAe,GAAG,SAAS,CAAA,GAAK;AAAA,GAAA,EAC9C,CAAA;AAEJ;AAEO,SAAS,WAAA,GAAoC;AAClD,EAAA,MAAM,GAAA,GAAMC,iBAAW,eAAe,CAAA;AACtC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAC5E,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,mBAAA,GAAmD;AACjE,EAAA,OAAOA,iBAAW,eAAe,CAAA;AACnC;;;ACvDA,IAAM,cAAA,GAAiB,CAAC,QAAA,EAAU,OAAA,EAAS,YAAY,CAAA;AAEvD,SAAS,gBAAA,CAAiB,MAAc,QAAA,EAA0B;AAChE,EAAA,MAAM,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,EAAE,EAAE,IAAA,EAAK;AACxC,EAAA,IAAI,CAAC,KAAK,OAAO,QAAA,CAAS,WAAW,GAAG,CAAA,GAAI,QAAA,GAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA;AACnE,EAAA,OAAO,IAAI,UAAA,CAAW,GAAG,CAAA,GAAI,GAAA,GAAM,IAAI,GAAG,CAAA,CAAA;AAC5C;AAEA,SAAS,kBAAA,CAAmB,IAAA,EAAc,cAAA,EAA0B,QAAA,EAA2B;AAC7F,EAAA,MAAM,CAAA,GAAI,gBAAA,CAAiB,IAAA,EAAM,QAAQ,CAAA;AACzC,EAAA,IAAI,CAAA,KAAM,KAAK,OAAO,IAAA;AACtB,EAAA,OAAO,cAAA,CAAe,IAAA,CAAK,CAAC,MAAA,KAAW,MAAM,MAAA,IAAU,CAAA,CAAE,UAAA,CAAW,CAAA,EAAG,MAAM,CAAA,CAAA,CAAG,CAAA,IAAK,CAAA,CAAE,UAAA,CAAW,MAAM,CAAC,CAAA;AAC3G;AAMO,SAAS,2BAA2B,OAAA,EAA+B;AACxE,EAAA,MAAM8B,cAAa,OAAA,CAAQ,UAAA;AAC3B,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,WAAA,EAAa,UAAA,CAAW,GAAG,CAAA,GACnD,OAAA,CAAQ,WAAA,GACR,CAAA,CAAA,EAAI,OAAA,CAAQ,WAAA,IAAe,MAAM,CAAA,CAAA;AACrC,EAAA,MAAM,cAAA,GAAiB,CAAC,GAAG,cAAA,EAAgB,GAAI,OAAA,CAAQ,cAAA,IAAkB,EAAG,CAAA;AAE5E,EAAA,SAAS,sBAAsB,IAAA,EAAoB;AACjD,IAAA,MAAM,UAAA,GAAa,gBAAA,CAAiB,IAAA,EAAM,WAAW,CAAA;AACrD,IAAA,IAAI,kBAAA,CAAmB,UAAA,EAAY,cAAA,EAAgB,WAAW,CAAA,EAAG;AACjE,IAAA,IAAI;AACF,MAAA,cAAA,CAAe,OAAA,CAAQA,aAAY,UAAU,CAAA;AAAA,IAC/C,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,SAAS,iBAAA,GAAwC;AAC/C,IAAA,IAAI;AACF,MAAA,MAAM,CAAA,GAAI,cAAA,CAAe,OAAA,CAAQA,WAAU,CAAA;AAC3C,MAAA,IAAI,CAAC,CAAA,IAAK,kBAAA,CAAmB,GAAG,cAAA,EAAgB,WAAW,GAAG,OAAO,KAAA,CAAA;AACrE,MAAA,OAAO,gBAAA,CAAiB,GAAG,WAAW,CAAA;AAAA,IACxC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,SAAS,oBAAA,CAAqB,WAAW,WAAA,EAAqB;AAC5D,IAAA,MAAM,aAAa,iBAAA,EAAkB;AACrC,IAAA,IAAI;AACF,MAAA,cAAA,CAAe,WAAWA,WAAU,CAAA;AAAA,IACtC,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,OAAO,UAAA,IAAc,gBAAA,CAAiB,QAAA,EAAU,WAAW,CAAA;AAAA,EAC7D;AAEA,EAAA,OAAO;AAAA,IACL,qBAAA;AAAA,IACA,iBAAA;AAAA,IACA,oBAAA;AAAA,IACA,gBAAA,EAAkB,CAAC,IAAA,KAAiB,gBAAA,CAAiB,MAAM,WAAW,CAAA;AAAA,IACtE,oBAAoB,CAAC,IAAA,KAAiB,kBAAA,CAAmB,IAAA,EAAM,gBAAgB,WAAW;AAAA,GAC5F;AACF","file":"index.js","sourcesContent":["export interface LuminaryIdpConfig {\n /**\n * OIDC issuer. Prefer Auth Gateway (`http://localhost:3010/oidc`) so products\n * stay IdP-agnostic; direct Logto issuer is OK for local MVP.\n */\n issuer: string;\n clientId: string;\n redirectUri: string;\n /**\n * Popup OIDC callback. Defaults to `redirectUri` (same `/auth/callback`).\n * Must be registered on the IdP application.\n */\n popupRedirectUri?: string;\n postLogoutRedirectUri?: string;\n scopes?: string;\n /** API resource indicator (access token `aud`) */\n audience?: string;\n /** localStorage key for access token */\n tokenStorageKey?: string;\n /**\n * Logto Experience API base (no trailing slash), e.g. Auth Gateway\n * `http://localhost:3010` or direct Logto `http://localhost:3001`.\n * When set, Headless password sign-in is attempted before OIDC popup fallback.\n */\n experienceApiBase?: string;\n /**\n * IAM catalog id: `logto` (default Headless), `oidc` / `zitadel` (Hosted Redirect).\n * Ignored when `HeadlessLoginPanel` receives an explicit `experienceAdapter`.\n */\n iamProvider?: string;\n}\n\nexport interface LuminaryAuthSession {\n accessToken: string;\n idToken?: string;\n expiresAt?: number;\n profile?: Record<string, unknown>;\n}\n\nexport function isIdpConfigured(config: Partial<LuminaryIdpConfig>): config is LuminaryIdpConfig {\n return Boolean(config.issuer && config.clientId && config.redirectUri);\n}\n\n/** Resolve issuer from Auth Gateway base URL or direct IDP_ISSUER. */\nexport function resolveIssuer(env: Record<string, string | undefined>): string | undefined {\n // Prefer explicit IdP issuer so JWT `iss` validation matches Logto.\n // Auth Gateway is a CORS/proxy front — set via VITE_AUTH_EXPERIENCE_URL / VITE_AUTH_GATEWAY_URL.\n const explicit = env.VITE_IDP_ISSUER ?? env.PUBLIC_IDP_ISSUER ?? env.IDP_ISSUER;\n if (explicit) return explicit;\n const gateway = env.VITE_AUTH_GATEWAY_URL ?? env.PUBLIC_AUTH_GATEWAY_URL ?? env.AUTH_GATEWAY_URL;\n if (gateway) return `${gateway.replace(/\\/$/, \"\")}/oidc`;\n return undefined;\n}\n\n/** Derive Experience API host from Gateway URL or by stripping `/oidc` from issuer. */\nexport function resolveExperienceApiBase(env: Record<string, string | undefined>): string | undefined {\n const explicit =\n env.VITE_AUTH_EXPERIENCE_URL ??\n env.PUBLIC_AUTH_EXPERIENCE_URL ??\n env.AUTH_EXPERIENCE_URL;\n if (explicit) return explicit.replace(/\\/$/, \"\");\n\n const gateway = env.VITE_AUTH_GATEWAY_URL ?? env.PUBLIC_AUTH_GATEWAY_URL ?? env.AUTH_GATEWAY_URL;\n if (gateway) return gateway.replace(/\\/$/, \"\");\n\n const issuer = resolveIssuer(env);\n if (!issuer) return undefined;\n return issuer.replace(/\\/$/, \"\").replace(/\\/oidc$/i, \"\");\n}\n\nexport function readIdpConfigFromEnv(env: Record<string, string | undefined>): Partial<LuminaryIdpConfig> {\n const redirectUri = env.VITE_IDP_REDIRECT_URI ?? env.PUBLIC_IDP_REDIRECT_URI ?? \"\";\n return {\n issuer: resolveIssuer(env),\n clientId: env.VITE_IDP_CLIENT_ID ?? env.PUBLIC_IDP_CLIENT_ID,\n redirectUri,\n popupRedirectUri: env.VITE_IDP_POPUP_REDIRECT_URI ?? env.PUBLIC_IDP_POPUP_REDIRECT_URI ?? redirectUri,\n postLogoutRedirectUri: env.VITE_IDP_POST_LOGOUT_URI ?? env.PUBLIC_IDP_POST_LOGOUT_URI,\n scopes: env.VITE_IDP_SCOPES ?? env.PUBLIC_IDP_SCOPES ?? \"openid profile email offline_access\",\n audience: env.VITE_IDP_AUDIENCE ?? env.PUBLIC_IDP_AUDIENCE,\n tokenStorageKey: env.VITE_IDP_TOKEN_KEY ?? \"luminary_access_token\",\n experienceApiBase: resolveExperienceApiBase(env),\n iamProvider:\n env.VITE_IAM_PROVIDER ?? env.PUBLIC_IAM_PROVIDER ?? env.IAM_PROVIDER ?? env.IDP_MODE,\n };\n}\n","import type { LoginExperienceAdapter, LoginExperienceCapability } from \"./login-experience-adapter\";\n\n/**\n * Standard OIDC Hosted Redirect adapter.\n *\n * Used for enterprise OIDC and reserved IAM plugins (ZITADEL) that have no\n * shipped Headless Experience API. Password and social stay on the IdP hosted UI.\n */\nexport class HostedOidcExperienceAdapter implements LoginExperienceAdapter {\n readonly capabilities: readonly LoginExperienceCapability[] = [];\n\n constructor(readonly provider = \"hosted\") {}\n}\n","import { HostedOidcExperienceAdapter } from \"./hosted-oidc-experience-adapter\";\nimport { LogtoExperienceAdapter } from \"./logto-experience-adapter\";\n\n/**\n * Capabilities exposed by a headless login-experience provider.\n *\n * Consumers can use these flags to avoid assuming that every provider supports\n * Logto's password, connector-discovery, or direct social-login flows.\n */\nexport const LOGIN_EXPERIENCE_CAPABILITIES = {\n passwordSignIn: \"password-sign-in\",\n /** Username + password self-register via Experience (Logto NewPasswordIdentity). */\n passwordSignUp: \"password-sign-up\",\n socialConnectors: \"social-connectors\",\n socialDirectSignIn: \"social-direct-sign-in\",\n} as const;\n\nexport type LoginExperienceCapability =\n (typeof LOGIN_EXPERIENCE_CAPABILITIES)[keyof typeof LOGIN_EXPERIENCE_CAPABILITIES];\n\nexport type ExperienceIdentifierType = \"email\" | \"username\" | \"phone\";\n\nexport interface ExperiencePasswordSignInInput {\n /** Experience API origin (no trailing slash). Prefer SPA origin when proxied. */\n apiBase: string;\n identifier: string;\n password: string;\n identifierType?: ExperienceIdentifierType;\n /** Required to bootstrap the OIDC interaction cookie before Experience calls. */\n issuer?: string;\n clientId?: string;\n redirectUri?: string;\n audience?: string;\n scopes?: string;\n /** Carried in OIDC state for post-login return (UserManager PKCE). */\n returnUrl?: string;\n}\n\nexport interface ExperiencePasswordSignInResult {\n /** Continue URL from Experience submit (complete OIDC interaction). */\n redirectTo?: string;\n raw?: unknown;\n}\n\n/** Same OIDC bootstrap fields as sign-in; username must match Logto username rules. */\nexport type ExperiencePasswordSignUpInput = ExperiencePasswordSignInInput;\n\nexport type ExperiencePasswordSignUpResult = ExperiencePasswordSignInResult;\n\nexport interface ExperienceSocialConnector {\n id: string;\n target: string;\n name: string;\n logo?: string;\n}\n\nexport interface FetchSocialConnectorsInput {\n /** Same origin as Experience / IdP (e.g. SPA proxy or http://localhost:3001). */\n apiBase: string;\n appId?: string;\n}\n\nexport interface SocialSignInRequest {\n /** Provider-specific authorize parameters, passed through by the OIDC client. */\n extraQueryParams?: Record<string, string>;\n}\n\n/**\n * Provider boundary for non-standard login-experience APIs.\n *\n * Standard OIDC redirect/popup and PKCE handling intentionally remain in the\n * OIDC client. Only provider-specific Experience operations belong here.\n */\nexport interface LoginExperienceAdapter {\n readonly provider: string;\n readonly capabilities: readonly LoginExperienceCapability[];\n experiencePasswordSignIn?(\n input: ExperiencePasswordSignInInput,\n ): Promise<ExperiencePasswordSignInResult>;\n /**\n * Self-register with username + password (Logto Register + NewPasswordIdentity).\n * Email/phone sign-up needs verification codes — not covered by this method.\n */\n experiencePasswordSignUp?(\n input: ExperiencePasswordSignUpInput,\n ): Promise<ExperiencePasswordSignUpResult>;\n fetchSocialConnectors?(\n input: FetchSocialConnectorsInput,\n ): Promise<ExperienceSocialConnector[]>;\n createSocialSignInRequest?(target: string): SocialSignInRequest;\n}\n\nexport type LoginExperienceProvider = \"logto\" | \"hosted\" | \"oidc\" | \"zitadel\" | (string & {});\n\nconst HOSTED_LOGIN_PROVIDERS = new Set([\"hosted\", \"oidc\", \"external_oidc\", \"zitadel\"]);\n\nfunction normalizeLoginExperienceProvider(provider: string): \"logto\" | \"hosted\" {\n const key = provider.trim().toLowerCase();\n if (!key || key === \"logto\") return \"logto\";\n if (HOSTED_LOGIN_PROVIDERS.has(key)) return \"hosted\";\n throw new Error(\n `Unknown login experience provider \"${provider}\". Shipped: logto (default). Hosted OIDC: oidc / hosted / zitadel.`,\n );\n}\n\n/**\n * Factory for built-in login adapters.\n *\n * - `logto`: Experience API Headless (password + social connectors)\n * - `hosted` / `oidc` / `zitadel`: standard OIDC Hosted Redirect (no empty vendor SDK)\n *\n * Products may still pass a custom `LoginExperienceAdapter`. Do not add stub\n * adapters for unintegrated Headless APIs.\n */\nexport function createLoginExperienceAdapter(\n provider: LoginExperienceProvider = \"logto\",\n): LoginExperienceAdapter {\n const kind = normalizeLoginExperienceProvider(provider);\n if (kind === \"logto\") return new LogtoExperienceAdapter();\n return new HostedOidcExperienceAdapter(provider.trim().toLowerCase() || \"hosted\");\n}\n\nconst adapterCache = new Map<string, LoginExperienceAdapter>();\n\n/**\n * Resolve an explicit product adapter, or the catalog adapter for `iamProvider`.\n * Defaults to Logto for backward compatibility.\n */\nexport function resolveLoginExperienceAdapter(\n adapter?: LoginExperienceAdapter | null,\n iamProvider?: string | null,\n): LoginExperienceAdapter {\n if (adapter) return adapter;\n const key = iamProvider?.trim() || \"logto\";\n const cached = adapterCache.get(key);\n if (cached) return cached;\n const created = createLoginExperienceAdapter(key);\n adapterCache.set(key, created);\n return created;\n}\n\n/** `VITE_IAM_PROVIDER` / `IAM_PROVIDER` / older `IDP_MODE`. */\nexport function resolveLoginExperienceProviderFromEnv(\n env: Record<string, string | undefined> = {},\n): LoginExperienceProvider {\n return env.VITE_IAM_PROVIDER ?? env.PUBLIC_IAM_PROVIDER ?? env.IAM_PROVIDER ?? env.IDP_MODE ?? \"logto\";\n}\n","/**\n * Logto Experience API (Headless) adapter.\n * Prefer same-origin Experience base (SPA proxies /api/experience) so cookies\n * work on HTTP localhost.\n */\n\nimport { prepareSignInRequestUrl } from \"./oidc-client\";\nimport {\n LOGIN_EXPERIENCE_CAPABILITIES,\n type ExperienceIdentifierType,\n type ExperiencePasswordSignInInput,\n type ExperiencePasswordSignInResult,\n type ExperiencePasswordSignUpInput,\n type ExperiencePasswordSignUpResult,\n type ExperienceSocialConnector,\n type FetchSocialConnectorsInput,\n type LoginExperienceAdapter,\n type LoginExperienceCapability,\n type SocialSignInRequest,\n} from \"./login-experience-adapter\";\nimport type { LuminaryIdpConfig } from \"./types\";\n\n/** Logto username pattern for NewPasswordIdentity (see Experience API docs). */\nconst LOGTO_USERNAME_RE = /^[A-Za-z_]\\w*$/;\n\nexport function isLogtoRegisterUsername(value: string): boolean {\n return LOGTO_USERNAME_RE.test(value.trim());\n}\n\nfunction experienceUrl(apiBase: string, path: string): string {\n return `${apiBase.replace(/\\/$/, \"\")}/api/experience${path}`;\n}\n\nasync function experienceFetch<T>(apiBase: string, path: string, init: RequestInit): Promise<T> {\n const res = await fetch(experienceUrl(apiBase, path), {\n credentials: \"include\",\n ...init,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...(init.headers ?? {}),\n },\n });\n const text = await res.text();\n let data: unknown = null;\n if (text) {\n try {\n data = JSON.parse(text) as unknown;\n } catch {\n data = text;\n }\n }\n if (!res.ok) {\n const msg =\n data && typeof data === \"object\" && data !== null && \"message\" in data\n ? String((data as { message: unknown }).message)\n : `Experience API ${res.status}`;\n throw new Error(msg);\n }\n return data as T;\n}\n\nfunction guessIdentifierType(identifier: string): ExperienceIdentifierType {\n if (identifier.includes(\"@\")) return \"email\";\n if (/^\\+?\\d{6,}$/.test(identifier.trim())) return \"phone\";\n return \"username\";\n}\n\n/**\n * Force authorize onto the Experience/SPA origin so Set-Cookie lands on the\n * same host as subsequent `/api/experience` calls (dev proxy strips Domain).\n */\nexport function sameOriginAuthorizeUrl(authorizeUrl: string, apiBase: string): string {\n const u = new URL(authorizeUrl);\n const base = new URL(apiBase);\n if (u.origin === base.origin) return authorizeUrl;\n return `${base.origin}${u.pathname}${u.search}${u.hash}`;\n}\n\n/**\n * Logto creates its interaction cookie after an authorize request. The\n * standard OIDC client creates and persists the PKCE request; this adapter only\n * applies Logto's same-origin interaction bootstrap.\n */\nasync function bootstrapOidcInteraction(input: ExperiencePasswordSignInInput): Promise<void> {\n if (!input.issuer || !input.clientId || !input.redirectUri) return;\n if (typeof document === \"undefined\") return;\n\n const config: LuminaryIdpConfig = {\n issuer: input.issuer,\n clientId: input.clientId,\n redirectUri: input.redirectUri,\n audience: input.audience,\n scopes: input.scopes,\n experienceApiBase: input.apiBase,\n };\n\n const signinUrl = await prepareSignInRequestUrl(config, {\n returnUrl: input.returnUrl,\n });\n const authorizeUrl = sameOriginAuthorizeUrl(signinUrl, input.apiBase);\n\n await new Promise<void>((resolve) => {\n const iframe = document.createElement(\"iframe\");\n iframe.setAttribute(\"aria-hidden\", \"true\");\n iframe.tabIndex = -1;\n iframe.style.cssText = \"position:absolute;width:0;height:0;border:0;visibility:hidden\";\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n iframe.remove();\n resolve();\n };\n iframe.addEventListener(\"load\", () => {\n window.setTimeout(finish, 400);\n });\n iframe.src = authorizeUrl;\n document.body.appendChild(iframe);\n window.setTimeout(finish, 2500);\n });\n}\n\n/** Build Logto's provider-specific direct sign-in authorize parameter. */\nexport function createLogtoDirectSignInRequest(directSignIn: string): SocialSignInRequest {\n return { extraQueryParams: { direct_sign_in: directSignIn } };\n}\n\n/** Built-in adapter for Logto's non-standard Experience API. */\nexport class LogtoExperienceAdapter implements LoginExperienceAdapter {\n readonly provider = \"logto\";\n readonly capabilities: readonly LoginExperienceCapability[] = [\n LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn,\n LOGIN_EXPERIENCE_CAPABILITIES.passwordSignUp,\n LOGIN_EXPERIENCE_CAPABILITIES.socialConnectors,\n LOGIN_EXPERIENCE_CAPABILITIES.socialDirectSignIn,\n ];\n\n async experiencePasswordSignIn(\n input: ExperiencePasswordSignInInput,\n ): Promise<ExperiencePasswordSignInResult> {\n const { apiBase, identifier, password } = input;\n await bootstrapOidcInteraction(input);\n\n const primary = input.identifierType ?? guessIdentifierType(identifier);\n const alternates: ExperienceIdentifierType[] =\n primary === \"phone\"\n ? [primary]\n : primary === \"email\"\n ? [\"email\", \"username\"]\n : [\"username\", \"email\"];\n\n let lastError: Error | undefined;\n for (const identifierType of alternates) {\n try {\n await experienceFetch(apiBase, \"\", {\n method: \"PUT\",\n body: JSON.stringify({ interactionEvent: \"SignIn\" }),\n });\n\n const verified = await experienceFetch<{ verificationId?: string }>(\n apiBase,\n \"/verification/password\",\n {\n method: \"POST\",\n body: JSON.stringify({\n identifier: { type: identifierType, value: identifier },\n password,\n }),\n },\n );\n\n const verificationId = verified?.verificationId;\n if (!verificationId) {\n throw new Error(\"Experience API did not return verificationId\");\n }\n\n await experienceFetch(apiBase, \"/identification\", {\n method: \"POST\",\n body: JSON.stringify({ verificationId }),\n });\n\n const submitted = await experienceFetch<{ redirectTo?: string }>(\n apiBase,\n \"/submit\",\n {\n method: \"POST\",\n body: JSON.stringify({}),\n },\n );\n\n return { redirectTo: submitted?.redirectTo, raw: submitted };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n }\n throw lastError ?? new Error(\"Experience password sign-in failed\");\n }\n\n /**\n * Register with username + password via NewPasswordIdentity.\n * Email/phone self-register requires verification codes — use social or invite instead.\n */\n async experiencePasswordSignUp(\n input: ExperiencePasswordSignUpInput,\n ): Promise<ExperiencePasswordSignUpResult> {\n const { apiBase, identifier, password } = input;\n const username = identifier.trim();\n if (!isLogtoRegisterUsername(username)) {\n throw new Error(\n \"Register with a username (letters, digits, underscore; start with a letter or _). Use social login for email-based accounts.\",\n );\n }\n if (!password || password.length < 8) {\n throw new Error(\"Password must be at least 8 characters\");\n }\n\n await bootstrapOidcInteraction(input);\n\n await experienceFetch(apiBase, \"\", {\n method: \"PUT\",\n body: JSON.stringify({ interactionEvent: \"Register\" }),\n });\n\n const verified = await experienceFetch<{ verificationId?: string }>(\n apiBase,\n \"/verification/new-password-identity\",\n {\n method: \"POST\",\n body: JSON.stringify({\n identifier: { type: \"username\", value: username },\n password,\n }),\n },\n );\n\n const verificationId = verified?.verificationId;\n if (!verificationId) {\n throw new Error(\"Experience API did not return verificationId\");\n }\n\n await experienceFetch(apiBase, \"/identification\", {\n method: \"POST\",\n body: JSON.stringify({ verificationId }),\n });\n\n const submitted = await experienceFetch<{ redirectTo?: string }>(apiBase, \"/submit\", {\n method: \"POST\",\n body: JSON.stringify({}),\n });\n\n return { redirectTo: submitted?.redirectTo, raw: submitted };\n }\n\n async fetchSocialConnectors(\n input: FetchSocialConnectorsInput,\n ): Promise<ExperienceSocialConnector[]> {\n const url = new URL(`${input.apiBase.replace(/\\/$/, \"\")}/api/.well-known/sign-in-exp`);\n if (input.appId?.trim()) url.searchParams.set(\"appId\", input.appId.trim());\n const res = await fetch(url.toString(), {\n // Public metadata — omit cookies so browsers do not require credentialed CORS.\n credentials: \"omit\",\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) {\n throw new Error(`sign-in-exp ${res.status}`);\n }\n const data = (await res.json()) as {\n socialConnectors?: Array<{\n id?: string;\n target?: string;\n name?: string | Record<string, string>;\n logo?: string;\n }>;\n };\n return (data.socialConnectors ?? [])\n .filter(\n (\n connector,\n ): connector is {\n id: string;\n target: string;\n name?: string | Record<string, string>;\n logo?: string;\n } => Boolean(connector?.id && connector?.target),\n )\n .map((connector) => ({\n id: connector.id,\n target: connector.target,\n name: localizeName(connector.name) || titleCase(connector.target),\n logo: connector.logo,\n }));\n }\n\n createSocialSignInRequest(target: string): SocialSignInRequest {\n return createLogtoDirectSignInRequest(`social:${target}`);\n }\n}\n\nfunction localizeName(name: string | Record<string, string> | undefined): string {\n if (!name) return \"\";\n if (typeof name === \"string\") return name;\n return name[\"zh-CN\"] || name.en || Object.values(name)[0] || \"\";\n}\n\nfunction titleCase(target: string): string {\n if (!target) return \"\";\n return target.charAt(0).toUpperCase() + target.slice(1);\n}\n","import {\n OidcClient,\n UserManager,\n WebStorageStateStore,\n type User,\n} from \"oidc-client-ts\";\nimport { createLogtoDirectSignInRequest } from \"./logto-experience-adapter\";\nimport type { LuminaryAuthSession, LuminaryIdpConfig } from \"./types\";\n\nlet manager: UserManager | null = null;\n\nfunction storageKey(config: LuminaryIdpConfig): string {\n return config.tokenStorageKey ?? \"luminary_access_token\";\n}\n\nfunction popupRedirectUri(config: LuminaryIdpConfig): string {\n return config.popupRedirectUri ?? config.redirectUri;\n}\n\nfunction sharedStateStore() {\n // localStorage so popup/redirect/Experience callback windows can resolve PKCE state.\n return new WebStorageStateStore({ store: window.localStorage });\n}\n\nfunction clientSettings(config: LuminaryIdpConfig) {\n const resource = config.audience?.trim() || undefined;\n return {\n authority: config.issuer.replace(/\\/$/, \"\"),\n metadataUrl: resolveOidcMetadataUrl(config),\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n post_logout_redirect_uri: config.postLogoutRedirectUri ?? config.redirectUri,\n response_type: \"code\" as const,\n scope: config.scopes ?? \"openid profile email offline_access\",\n stateStore: sharedStateStore(),\n extraQueryParams: resource ? { resource } : undefined,\n extraTokenParams: resource ? { resource } : undefined,\n };\n}\n\nfunction userManagerSettings(config: LuminaryIdpConfig) {\n const resource = config.audience?.trim() || undefined;\n return {\n ...clientSettings(config),\n popup_redirect_uri: popupRedirectUri(config),\n automaticSilentRenew: true,\n loadUserInfo: !resource,\n userStore: sharedStateStore(),\n };\n}\n\nexport function createUserManager(config: LuminaryIdpConfig): UserManager {\n if (manager) return manager;\n manager = new UserManager(userManagerSettings(config));\n return manager;\n}\n\n/**\n * When Experience/Gateway base differs from the IdP issuer origin, fetch OIDC discovery\n * via the gateway (CORS) while keeping `authority` = Logto issuer (JWT `iss`).\n */\nfunction resolveOidcMetadataUrl(config: LuminaryIdpConfig): string | undefined {\n const proxyBase = config.experienceApiBase?.replace(/\\/$/, \"\");\n if (!proxyBase) return undefined;\n try {\n if (new URL(proxyBase).origin === new URL(config.issuer).origin) return undefined;\n } catch {\n return undefined;\n }\n return `${proxyBase}/oidc/.well-known/openid-configuration`;\n}\n\nexport function resetUserManager(): void {\n manager = null;\n}\n\nexport interface SignInOptions {\n returnUrl?: string;\n /** Provider-specific authorize parameters supplied by an experience adapter. */\n extraQueryParams?: Record<string, string>;\n /**\n * Logto direct sign-in, e.g. `social:google` / `social:github` / `sso:<connectorId>`.\n * Skips the hosted password page and opens the provider immediately.\n * @deprecated Prefer a LoginExperienceAdapter, which supplies extraQueryParams.\n */\n directSignIn?: string;\n}\n\nfunction signInArgs(config: LuminaryIdpConfig, options?: SignInOptions | string) {\n const normalized: SignInOptions =\n typeof options === \"string\" ? { returnUrl: options } : (options ?? {});\n const resource = config.audience?.trim();\n const extraQueryParams: Record<string, string> = { ...normalized.extraQueryParams };\n if (resource) extraQueryParams.resource = resource;\n if (normalized.directSignIn) {\n Object.assign(\n extraQueryParams,\n createLogtoDirectSignInRequest(normalized.directSignIn).extraQueryParams,\n );\n }\n return {\n state: normalized.returnUrl ? { returnUrl: normalized.returnUrl } : undefined,\n extraQueryParams: Object.keys(extraQueryParams).length ? extraQueryParams : undefined,\n };\n}\n\nexport async function signInRedirect(\n config: LuminaryIdpConfig,\n returnUrlOrOptions?: string | SignInOptions,\n): Promise<void> {\n resetUserManager();\n const um = createUserManager(config);\n await um.signinRedirect(signInArgs(config, returnUrlOrOptions));\n}\n\n/**\n * Persist PKCE state (same store as {@link createUserManager}) and return the\n * authorize URL — used by Experience headless bootstrap before navigating to\n * `redirectTo` from `/api/experience/submit`.\n */\nexport async function prepareSignInRequestUrl(\n config: LuminaryIdpConfig,\n returnUrlOrOptions?: string | SignInOptions,\n): Promise<string> {\n resetUserManager();\n // Warm the singleton so callback uses identical settings/stores.\n createUserManager(config);\n const client = new OidcClient(clientSettings(config));\n const args = signInArgs(config, returnUrlOrOptions);\n const request = await client.createSigninRequest({\n state: args.state,\n extraQueryParams: {\n ...(args.extraQueryParams ?? {}),\n prompt: \"login\",\n },\n });\n return request.url;\n}\n\n/**\n * OIDC login in a popup window (not an iframe). Opener keeps SPA state;\n * callback page in the popup must call {@link handleSignInPopupCallback}.\n */\nexport async function signInPopup(\n config: LuminaryIdpConfig,\n returnUrlOrOptions?: string | SignInOptions,\n): Promise<{ session: LuminaryAuthSession; returnUrl?: string }> {\n resetUserManager();\n const um = createUserManager(config);\n const user = await um.signinPopup(signInArgs(config, returnUrlOrOptions));\n const session = toSession(user);\n if (!session.accessToken) {\n throw new Error(\"IdP did not return access_token (check audience / API resource)\");\n }\n assertJwtAccessToken(session.accessToken);\n localStorage.setItem(storageKey(config), session.accessToken);\n const stateReturnUrl =\n typeof user.state === \"object\" && user.state && \"returnUrl\" in user.state\n ? String((user.state as { returnUrl?: string }).returnUrl ?? \"\")\n : undefined;\n return { session, returnUrl: stateReturnUrl || undefined };\n}\n\nexport async function handleSignInCallback(config: LuminaryIdpConfig): Promise<{\n session: LuminaryAuthSession;\n returnUrl?: string;\n}> {\n const um = createUserManager(config);\n const user = await um.signinRedirectCallback();\n const session = toSession(user);\n assertJwtAccessToken(session.accessToken);\n localStorage.setItem(storageKey(config), session.accessToken);\n const returnUrl =\n typeof user.state === \"object\" && user.state && \"returnUrl\" in user.state\n ? String((user.state as { returnUrl?: string }).returnUrl ?? \"\")\n : undefined;\n return { session, returnUrl: returnUrl || undefined };\n}\n\n/**\n * Complete popup OIDC in the popup window. Notifies the opener and closes.\n * Do not run product SSO exchange here — the opener handles that after signInPopup resolves.\n */\nexport async function handleSignInPopupCallback(config: LuminaryIdpConfig): Promise<void> {\n const um = createUserManager(config);\n await um.signinPopupCallback();\n}\n\n/** True when this window is likely an OIDC popup callback. */\nexport function isOidcPopupWindow(): boolean {\n try {\n return Boolean(window.opener && window.opener !== window);\n } catch {\n return false;\n }\n}\n\nexport async function signOutRedirect(config: LuminaryIdpConfig): Promise<void> {\n localStorage.removeItem(storageKey(config));\n const um = createUserManager(config);\n await um.signoutRedirect();\n}\n\nexport function getStoredAccessToken(config: LuminaryIdpConfig): string | null {\n return localStorage.getItem(storageKey(config));\n}\n\nexport function clearStoredSession(config: LuminaryIdpConfig): void {\n localStorage.removeItem(storageKey(config));\n}\n\nfunction toSession(user: User): LuminaryAuthSession {\n return {\n accessToken: user.access_token,\n idToken: user.id_token,\n expiresAt: user.expires_at ? user.expires_at * 1000 : undefined,\n profile: user.profile as Record<string, unknown>,\n };\n}\n\nfunction assertJwtAccessToken(accessToken: string): void {\n if (accessToken.split(\".\").length !== 3) {\n throw new Error(\n \"Received non-JWT access_token. Pass resource (audience) on authorize/token and register the API resource at the IdP.\",\n );\n }\n}\n\nexport async function getCurrentUser(config: LuminaryIdpConfig): Promise<LuminaryAuthSession | null> {\n const um = createUserManager(config);\n const user = await um.getUser();\n if (!user || user.expired) return null;\n return toSession(user);\n}\n","/**\n * @deprecated Import the adapter APIs from the package root instead.\n *\n * This module remains as a compatibility facade for existing consumers.\n */\nimport {\n LOGIN_EXPERIENCE_CAPABILITIES,\n resolveLoginExperienceAdapter,\n} from \"./login-experience-adapter\";\n\nexport type {\n ExperienceIdentifierType,\n ExperiencePasswordSignInInput,\n ExperiencePasswordSignInResult,\n ExperienceSocialConnector,\n FetchSocialConnectorsInput,\n} from \"./login-experience-adapter\";\nexport { sameOriginAuthorizeUrl } from \"./logto-experience-adapter\";\n\nimport type {\n ExperiencePasswordSignInInput,\n ExperiencePasswordSignInResult,\n ExperienceSocialConnector,\n FetchSocialConnectorsInput,\n} from \"./login-experience-adapter\";\n\n/** @deprecated Use a LoginExperienceAdapter instance. */\nexport function experiencePasswordSignIn(\n input: ExperiencePasswordSignInInput,\n): Promise<ExperiencePasswordSignInResult> {\n const adapter = resolveLoginExperienceAdapter();\n if (\n !adapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn) ||\n !adapter.experiencePasswordSignIn\n ) {\n return Promise.reject(new Error(\"Login experience does not support password sign-in\"));\n }\n return adapter.experiencePasswordSignIn(input);\n}\n\n/** @deprecated Use a LoginExperienceAdapter instance. */\nexport function fetchSocialConnectors(\n input: FetchSocialConnectorsInput,\n): Promise<ExperienceSocialConnector[]> {\n const adapter = resolveLoginExperienceAdapter();\n if (\n !adapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.socialConnectors) ||\n !adapter.fetchSocialConnectors\n ) {\n return Promise.reject(new Error(\"Login experience does not support social connectors\"));\n }\n return adapter.fetchSocialConnectors(input);\n}\n","/**\n * AuthGate — single-flight 401 recovery with optional token refresh + reauth UI.\n * Products wire tryRefresh / onReauthRequired; API clients call handleUnauthorized + waitIfBlocked.\n */\n\nexport type AuthGatePhase = \"idle\" | \"refreshing\" | \"reauth\";\n\nexport type UnauthorizedDisposition = \"retry\" | \"fail\";\n\nexport interface AuthGateSnapshot {\n phase: AuthGatePhase;\n /** True while refresh or interactive reauth is in flight. */\n blocked: boolean;\n lastError?: string;\n}\n\nexport interface AuthGateConfig {\n /**\n * Attempt silent product-token (or OIDC) refresh before showing reauth UI.\n * Return true if a new session was established.\n */\n tryRefresh?: () => Promise<boolean>;\n /** Called once when interactive reauth is required (open modal / popup). */\n onReauthRequired?: () => void;\n /** Called when reauth succeeds or is cancelled (phase back to idle). */\n onSettled?: (ok: boolean) => void;\n}\n\ntype Waiter = {\n resolve: (disposition: UnauthorizedDisposition) => void;\n};\n\nclass AuthGateCoordinator {\n private phase: AuthGatePhase = \"idle\";\n private lastError?: string;\n /** Cached for useSyncExternalStore — must keep referential equality when unchanged. */\n private snapshot: AuthGateSnapshot = { phase: \"idle\", blocked: false };\n private config: AuthGateConfig = {};\n private flight: Promise<UnauthorizedDisposition> | null = null;\n private reauthWaiters: Waiter[] = [];\n private listeners = new Set<() => void>();\n\n configure(config: AuthGateConfig): void {\n this.config = { ...this.config, ...config };\n }\n\n getSnapshot = (): AuthGateSnapshot => this.snapshot;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n private emit(): void {\n for (const listener of this.listeners) listener();\n }\n\n private setPhase(phase: AuthGatePhase, lastError?: string): void {\n if (this.phase === phase && this.lastError === lastError) return;\n this.phase = phase;\n this.lastError = lastError;\n this.snapshot = {\n phase,\n blocked: phase !== \"idle\",\n lastError,\n };\n this.emit();\n }\n\n /** Await while a recovery is in flight (pause outbound API traffic). */\n async waitIfBlocked(): Promise<void> {\n if (!this.flight) return;\n await this.flight;\n }\n\n /**\n * Single-flight 401 handler.\n * Concurrent callers share one recovery; all receive the same disposition.\n */\n handleUnauthorized(errorMessage?: string): Promise<UnauthorizedDisposition> {\n if (this.flight) return this.flight;\n this.flight = this.runRecovery(errorMessage).finally(() => {\n this.flight = null;\n });\n return this.flight;\n }\n\n /** Open reauth UI without a preceding 401 (cold start / deep link). */\n requestReauth(errorMessage?: string): Promise<UnauthorizedDisposition> {\n return this.handleUnauthorized(errorMessage);\n }\n\n /** Product calls after popup / Headless login restored the session. */\n completeReauth(): void {\n if (this.phase !== \"reauth\") return;\n const waiters = this.reauthWaiters.splice(0, this.reauthWaiters.length);\n this.setPhase(\"idle\");\n this.config.onSettled?.(true);\n for (const w of waiters) w.resolve(\"retry\");\n }\n\n /** User dismissed reauth; fail queued recovery waiters. */\n cancelReauth(errorMessage?: string): void {\n if (this.phase !== \"reauth\") return;\n const waiters = this.reauthWaiters.splice(0, this.reauthWaiters.length);\n this.setPhase(\"idle\", errorMessage);\n this.config.onSettled?.(false);\n for (const w of waiters) w.resolve(\"fail\");\n }\n\n private async runRecovery(errorMessage?: string): Promise<UnauthorizedDisposition> {\n this.lastError = errorMessage;\n\n if (this.config.tryRefresh) {\n this.setPhase(\"refreshing\", errorMessage);\n try {\n const ok = await this.config.tryRefresh();\n if (ok) {\n this.setPhase(\"idle\");\n this.config.onSettled?.(true);\n return \"retry\";\n }\n } catch (e) {\n this.lastError = e instanceof Error ? e.message : String(e);\n }\n }\n\n this.setPhase(\"reauth\", this.lastError);\n this.config.onReauthRequired?.();\n\n return new Promise<UnauthorizedDisposition>((resolve) => {\n this.reauthWaiters.push({ resolve });\n });\n }\n}\n\n/** Process-wide gate (one per SPA bundle). */\nexport const authGate = new AuthGateCoordinator();\n\n/**\n * Run an async request; on 401, recover via AuthGate and retry once.\n * `isUnauthorized` defaults to checking `status === 401` or `statusCode === 401`.\n */\nexport async function withAuthGateRetry<T>(\n execute: () => Promise<T>,\n options?: {\n isUnauthorized?: (error: unknown) => boolean;\n /** Skip gate (e.g. refresh / sso / login endpoints). */\n bypass?: boolean;\n },\n): Promise<T> {\n if (options?.bypass) return execute();\n\n await authGate.waitIfBlocked();\n\n try {\n return await execute();\n } catch (error) {\n if (!(options?.isUnauthorized ?? defaultIsUnauthorized)(error)) throw error;\n const disposition = await authGate.handleUnauthorized(messageOf(error));\n if (disposition !== \"retry\") throw error;\n return execute();\n }\n}\n\nfunction defaultIsUnauthorized(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const e = error as { status?: number; statusCode?: number; response?: { status?: number } };\n return e.status === 401 || e.statusCode === 401 || e.response?.status === 401;\n}\n\nfunction messageOf(error: unknown): string | undefined {\n if (error instanceof Error) return error.message;\n if (error && typeof error === \"object\" && \"message\" in error) {\n const m = (error as { message?: unknown }).message;\n return typeof m === \"string\" ? m : undefined;\n }\n return undefined;\n}\n","import { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport {\n clearStoredSession,\n getCurrentUser,\n getStoredAccessToken,\n handleSignInCallback,\n signInPopup,\n signInRedirect,\n signOutRedirect,\n} from \"./oidc-client\";\nimport { isIdpConfigured, readIdpConfigFromEnv, type LuminaryAuthSession, type LuminaryIdpConfig } from \"./types\";\n\ninterface LuminaryAuthContextValue {\n configured: boolean;\n session: LuminaryAuthSession | null;\n accessToken: string | null;\n loading: boolean;\n login: (returnUrl?: string) => Promise<void>;\n /** Popup OIDC — keeps the opener SPA mounted. */\n loginPopup: (returnUrl?: string) => Promise<LuminaryAuthSession>;\n logout: () => Promise<void>;\n completeCallback: () => Promise<{ returnUrl?: string }>;\n refreshSession: () => Promise<void>;\n}\n\nconst LuminaryAuthContext = createContext<LuminaryAuthContextValue | null>(null);\n\nexport interface LuminaryAuthProviderProps {\n config?: Partial<LuminaryIdpConfig>;\n children: React.ReactNode;\n}\n\nexport function LuminaryAuthProvider({ config: configProp, children }: LuminaryAuthProviderProps) {\n const config = useMemo(() => configProp ?? {}, [configProp]);\n const configured = isIdpConfigured(config);\n const [session, setSession] = useState<LuminaryAuthSession | null>(null);\n const [loading, setLoading] = useState(configured);\n\n const refreshSession = useCallback(async () => {\n if (!configured) {\n setSession(null);\n setLoading(false);\n return;\n }\n setLoading(true);\n try {\n const current = await getCurrentUser(config);\n setSession(current);\n } catch {\n setSession(null);\n } finally {\n setLoading(false);\n }\n }, [config, configured]);\n\n useEffect(() => {\n void refreshSession();\n }, [refreshSession]);\n\n const login = useCallback(\n async (returnUrl?: string) => {\n if (!configured) throw new Error(\"IdP not configured\");\n await signInRedirect(config, returnUrl);\n },\n [config, configured],\n );\n\n const loginPopup = useCallback(\n async (returnUrl?: string) => {\n if (!configured) throw new Error(\"IdP not configured\");\n const { session: next } = await signInPopup(config, returnUrl);\n setSession(next);\n return next;\n },\n [config, configured],\n );\n\n const logout = useCallback(async () => {\n if (!configured) {\n clearStoredSession(config as LuminaryIdpConfig);\n setSession(null);\n return;\n }\n setSession(null);\n await signOutRedirect(config);\n }, [config, configured]);\n\n const completeCallback = useCallback(async () => {\n if (!configured) throw new Error(\"IdP not configured\");\n const { session: next, returnUrl } = await handleSignInCallback(config);\n setSession(next);\n return { returnUrl };\n }, [config, configured]);\n\n const value = useMemo<LuminaryAuthContextValue>(\n () => ({\n configured,\n session,\n accessToken: session?.accessToken ?? (configured ? getStoredAccessToken(config) : null),\n loading,\n login,\n loginPopup,\n logout,\n completeCallback,\n refreshSession,\n }),\n [configured, session, loading, login, loginPopup, logout, completeCallback, refreshSession, config],\n );\n\n return <LuminaryAuthContext.Provider value={value}>{children}</LuminaryAuthContext.Provider>;\n}\n\nexport function useLuminaryAuth(): LuminaryAuthContextValue {\n const ctx = useContext(LuminaryAuthContext);\n if (!ctx) throw new Error(\"useLuminaryAuth must be used within LuminaryAuthProvider\");\n return ctx;\n}\n\nexport { isIdpConfigured, readIdpConfigFromEnv };\nexport type { LuminaryAuthSession, LuminaryIdpConfig };\n",".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: \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif;\n}\n\n.brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.logo {\n border-radius: 12px;\n display: block;\n}\n\n.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\n.title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: #4b5c68;\n}\n\n.form {\n display: grid;\n gap: 10px;\n}\n\n.socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.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.input:focus {\n border-color: var(--lw-auth-theme);\n}\n.input:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.passwordInput {\n padding-right: 42px;\n}\n\n.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.passwordToggle:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n}\n.passwordToggle:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n}\n.passwordToggle:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.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: linear-gradient(135deg, var(--lw-auth-theme) 0%, var(--lw-auth-theme-deep) 100%);\n}\n.primaryBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.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.socialBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.socialLogo {\n flex-shrink: 0;\n display: block;\n}\n\n.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\n.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.cancelBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: #90a0ab;\n}\n\n.dividerLine {\n flex: 1;\n height: 1px;\n background: #d5e0e7;\n}\n\n.dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: #6b7c87;\n line-height: 1.45;\n}\n\n.switchMode {\n margin: 12px 0 0;\n text-align: center;\n}\n\n.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.switchModeBtn:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n}\n\n.error {\n margin: 12px 0 0;\n font-size: 13px;\n color: #b42318;\n line-height: 1.4;\n}\n\n.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=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkhlYWRsZXNzTG9naW5QYW5lbC5tb2R1bGUuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFrQkE7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBLGVBVFU7RUFVVjtFQUNBLE9BekJJO0VBMEJKO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0EsT0E3RE07OztBQWdFUjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0EsZUFsRVU7RUFtRVY7RUFDQTtFQUNBO0VBQ0EsWUEzRVE7O0FBNkVSO0VBQ0U7O0FBR0Y7RUFDRTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0EsZUF2R1U7RUF3R1Y7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOztBQUdGO0VBQ0U7RUFDQTs7QUFHRjtFQUNFO0VBQ0E7OztBQUlKO0VBQ0U7RUFDQSxlQWhJVTtFQWlJVjtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0EsZUF0SlU7RUF1SlY7RUFDQTtFQUNBO0VBQ0E7RUFDQSxPQTFLSTtFQTJLSjs7QUFFQTtFQUNFO0VBQ0E7OztBQUlKO0VBQ0U7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0EsZUEzS1U7RUE0S1Y7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTs7O0FBSUo7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBLE9BbE5ROzs7QUFxTlY7RUFDRTtFQUNBO0VBQ0EsWUF6Tks7OztBQTROUDtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0EsT0EzT0s7RUE0T0w7OztBQUdGO0VBQ0U7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQSxPQTlQTztFQStQUDs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBLE9BalJLO0VBa1JMO0VBQ0E7RUFDQSIsInNvdXJjZXNDb250ZW50IjpbIiRpbms6ICMxNDIxMmI7XG4kbXV0ZWQ6ICM0YjVjNjg7XG4kaGludDogIzZiN2M4NztcbiRicmFuZDogIzNkNmY4ZjtcbiRicmFuZC1kZWVwOiAjMTU0ODVjO1xuJGJyYW5kLW1pZDogIzFmNmY4YjtcbiRib3JkZXI6ICNjOWQ1ZGU7XG4kYm9yZGVyLXNvZnQ6ICNiN2M5ZDQ7XG4kbGluZTogI2Q1ZTBlNztcbiRkaXZpZGVyOiAjOTBhMGFiO1xuJHN1cmZhY2U6ICNmN2ZhZmM7XG4kZmFsbGJhY2stYmc6ICNlOGVlZjI7XG4kZGFuZ2VyOiAjYjQyMzE4O1xuJGZvb3Rlci1saW5lOiAjZTRlYmYwO1xuJHJhZGl1cy1sZzogMTZweDtcbiRyYWRpdXMtbWQ6IDEwcHg7XG4kcmFkaXVzLXNtOiA0cHg7XG5cbi5wYW5lbCB7XG4gIC0tbHctYXV0aC10aGVtZTogIzE2NzdmZjtcbiAgLS1sdy1hdXRoLXRoZW1lLWRlZXA6IGNvbG9yLW1peChpbiBzcmdiLCB2YXIoLS1sdy1hdXRoLXRoZW1lKSA3MiUsICMwMDApO1xuICB3aWR0aDogbWluKDEwMCUsIDQwMHB4KTtcbiAgcGFkZGluZzogMjhweCAyOHB4IDIycHg7XG4gIGJvcmRlci1yYWRpdXM6ICRyYWRpdXMtbGc7XG4gIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC45Nik7XG4gIGNvbG9yOiAkaW5rO1xuICBib3gtc2hhZG93OiAwIDI0cHggNjRweCByZ2JhKDE1LCAyMywgNDIsIDAuMjgpO1xuICBmb250LWZhbWlseTogXCJTZWdvZSBVSVwiLCBcIlBpbmdGYW5nIFNDXCIsIFwiTm90byBTYW5zIFNDXCIsIHNhbnMtc2VyaWY7XG59XG5cbi5icmFuZCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGdhcDogMTRweDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgbWFyZ2luLWJvdHRvbTogMTJweDtcbn1cblxuLmxvZ28ge1xuICBib3JkZXItcmFkaXVzOiAxMnB4O1xuICBkaXNwbGF5OiBibG9jaztcbn1cblxuLnByb2R1Y3Qge1xuICBtYXJnaW46IDA7XG4gIGZvbnQtc2l6ZTogMTNweDtcbiAgZm9udC13ZWlnaHQ6IDY1MDtcbiAgbGV0dGVyLXNwYWNpbmc6IDAuMDRlbTtcbiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTtcbiAgY29sb3I6IHZhcigtLWx3LWF1dGgtdGhlbWUpO1xufVxuXG4udGl0bGUge1xuICBtYXJnaW46IDJweCAwIDA7XG4gIGZvbnQtc2l6ZTogMjJweDtcbiAgZm9udC13ZWlnaHQ6IDcwMDtcbiAgbGluZS1oZWlnaHQ6IDEuMjU7XG59XG5cbi5zdWJ0aXRsZSB7XG4gIG1hcmdpbjogMCAwIDE4cHg7XG4gIGZvbnQtc2l6ZTogMTRweDtcbiAgbGluZS1oZWlnaHQ6IDEuNTtcbiAgY29sb3I6ICRtdXRlZDtcbn1cblxuLmZvcm0ge1xuICBkaXNwbGF5OiBncmlkO1xuICBnYXA6IDEwcHg7XG59XG5cbi5zb2NpYWxTdGFjayB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtd3JhcDogd3JhcDtcbiAgZ2FwOiAxMHB4O1xuICBmb250LXNpemU6IDEycHg7XG59XG5cbi5pbnB1dCB7XG4gIHdpZHRoOiAxMDAlO1xuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICBib3JkZXI6IDFweCBzb2xpZCAkYm9yZGVyO1xuICBib3JkZXItcmFkaXVzOiAkcmFkaXVzLW1kO1xuICBwYWRkaW5nOiAxMHB4IDEycHg7XG4gIGZvbnQtc2l6ZTogMTRweDtcbiAgb3V0bGluZTogbm9uZTtcbiAgYmFja2dyb3VuZDogJHN1cmZhY2U7XG5cbiAgJjpmb2N1cyB7XG4gICAgYm9yZGVyLWNvbG9yOiB2YXIoLS1sdy1hdXRoLXRoZW1lKTtcbiAgfVxuXG4gICY6ZGlzYWJsZWQge1xuICAgIG9wYWNpdHk6IDAuNjU7XG4gICAgY3Vyc29yOiBub3QtYWxsb3dlZDtcbiAgfVxufVxuXG4ucGFzc3dvcmRGaWVsZCB7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbn1cblxuLnBhc3N3b3JkSW5wdXQge1xuICBwYWRkaW5nLXJpZ2h0OiA0MnB4O1xufVxuXG4ucGFzc3dvcmRUb2dnbGUge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHJpZ2h0OiA0cHg7XG4gIHRvcDogNTAlO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XG4gIHotaW5kZXg6IDE7XG4gIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgd2lkdGg6IDM2cHg7XG4gIGhlaWdodDogMzZweDtcbiAgYm9yZGVyOiBub25lO1xuICBib3JkZXItcmFkaXVzOiAkcmFkaXVzLXNtO1xuICBwYWRkaW5nOiAwO1xuICBjb2xvcjogIzVhNmI3NjtcbiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcG9pbnRlcjtcblxuICAmOmhvdmVyOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBjb2xvcjogdmFyKC0tbHctYXV0aC10aGVtZSk7XG4gICAgYmFja2dyb3VuZDogY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLWx3LWF1dGgtdGhlbWUpIDEyJSwgdHJhbnNwYXJlbnQpO1xuICB9XG5cbiAgJjpmb2N1cy12aXNpYmxlIHtcbiAgICBvdXRsaW5lOiAycHggc29saWQgdmFyKC0tbHctYXV0aC10aGVtZSk7XG4gICAgb3V0bGluZS1vZmZzZXQ6IDFweDtcbiAgfVxuXG4gICY6ZGlzYWJsZWQge1xuICAgIG9wYWNpdHk6IDAuNjU7XG4gICAgY3Vyc29yOiBub3QtYWxsb3dlZDtcbiAgfVxufVxuXG4ucHJpbWFyeUJ0biB7XG4gIGJvcmRlcjogbm9uZTtcbiAgYm9yZGVyLXJhZGl1czogJHJhZGl1cy1tZDtcbiAgcGFkZGluZzogMTFweCAxNHB4O1xuICBmb250LXNpemU6IDE0cHg7XG4gIGZvbnQtd2VpZ2h0OiA2NTA7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgY29sb3I6ICNmZmY7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsIHZhcigtLWx3LWF1dGgtdGhlbWUpIDAlLCB2YXIoLS1sdy1hdXRoLXRoZW1lLWRlZXApIDEwMCUpO1xuXG4gICY6ZGlzYWJsZWQge1xuICAgIG9wYWNpdHk6IDAuNjU7XG4gICAgY3Vyc29yOiBub3QtYWxsb3dlZDtcbiAgfVxufVxuXG4uc29jaWFsQnRuIHtcbiAgZmxleDogMSAxIGNhbGMoNTAlIC0gNXB4KTtcbiAgbWluLXdpZHRoOiBtaW4oMTQwcHgsIDEwMCUpO1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgZ2FwOiA4cHg7XG4gIGJvcmRlcjogMXB4IHNvbGlkICRib3JkZXItc29mdDtcbiAgYm9yZGVyLXJhZGl1czogJHJhZGl1cy1tZDtcbiAgcGFkZGluZzogMTFweCAxMHB4O1xuICBmb250LXNpemU6IDE0cHg7XG4gIGZvbnQtd2VpZ2h0OiA2NTA7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgY29sb3I6ICRpbms7XG4gIGJhY2tncm91bmQ6ICNmZmY7XG5cbiAgJjpkaXNhYmxlZCB7XG4gICAgb3BhY2l0eTogMC42NTtcbiAgICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xuICB9XG59XG5cbi5zb2NpYWxMb2dvIHtcbiAgZmxleC1zaHJpbms6IDA7XG4gIGRpc3BsYXk6IGJsb2NrO1xufVxuXG4ubG9nb0ZhbGxiYWNrIHtcbiAgd2lkdGg6IDE4cHg7XG4gIGhlaWdodDogMThweDtcbiAgYm9yZGVyLXJhZGl1czogJHJhZGl1cy1zbTtcbiAgYmFja2dyb3VuZDogY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLWx3LWF1dGgtdGhlbWUpIDE0JSwgI2ZmZik7XG4gIGNvbG9yOiB2YXIoLS1sdy1hdXRoLXRoZW1lLWRlZXApO1xuICBmb250LXNpemU6IDExcHg7XG4gIGZvbnQtd2VpZ2h0OiA3MDA7XG4gIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgZmxleC1zaHJpbms6IDA7XG59XG5cbi5jYW5jZWxCdG4ge1xuICBtYXJnaW4tdG9wOiAxMHB4O1xuICB3aWR0aDogMTAwJTtcbiAgYm9yZGVyOiBub25lO1xuICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcbiAgY29sb3I6ICM1YTZiNzY7XG4gIGZvbnQtc2l6ZTogMTNweDtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBwYWRkaW5nOiA4cHg7XG5cbiAgJjpkaXNhYmxlZCB7XG4gICAgb3BhY2l0eTogMC42NTtcbiAgICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xuICB9XG59XG5cbi5kaXZpZGVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiAxMHB4O1xuICBtYXJnaW46IDE0cHggMDtcbiAgY29sb3I6ICRkaXZpZGVyO1xufVxuXG4uZGl2aWRlckxpbmUge1xuICBmbGV4OiAxO1xuICBoZWlnaHQ6IDFweDtcbiAgYmFja2dyb3VuZDogJGxpbmU7XG59XG5cbi5kaXZpZGVyVGV4dCB7XG4gIGZvbnQtc2l6ZTogMTJweDtcbiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTtcbiAgbGV0dGVyLXNwYWNpbmc6IDAuMDhlbTtcbn1cblxuLmhpbnQge1xuICBtYXJnaW46IDEwcHggMCAwO1xuICBmb250LXNpemU6IDEycHg7XG4gIGNvbG9yOiAkaGludDtcbiAgbGluZS1oZWlnaHQ6IDEuNDU7XG59XG5cbi5zd2l0Y2hNb2RlIHtcbiAgbWFyZ2luOiAxMnB4IDAgMDtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xufVxuXG4uc3dpdGNoTW9kZUJ0biB7XG4gIGJvcmRlcjogbm9uZTtcbiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XG4gIGNvbG9yOiB2YXIoLS1sdy1hdXRoLXRoZW1lKTtcbiAgZm9udC1zaXplOiAxM3B4O1xuICBmb250LXdlaWdodDogNjUwO1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIHBhZGRpbmc6IDRweCA4cHg7XG4gIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lO1xuICB0ZXh0LXVuZGVybGluZS1vZmZzZXQ6IDNweDtcblxuICAmOmRpc2FibGVkIHtcbiAgICBvcGFjaXR5OiAwLjY1O1xuICAgIGN1cnNvcjogbm90LWFsbG93ZWQ7XG4gIH1cbn1cblxuLmVycm9yIHtcbiAgbWFyZ2luOiAxMnB4IDAgMDtcbiAgZm9udC1zaXplOiAxM3B4O1xuICBjb2xvcjogJGRhbmdlcjtcbiAgbGluZS1oZWlnaHQ6IDEuNDtcbn1cblxuLmZvb3RlciB7XG4gIG1hcmdpbi10b3A6IDE4cHg7XG4gIHBhZGRpbmctdG9wOiAxMnB4O1xuICBib3JkZXItdG9wOiAxcHggc29saWQgJGZvb3Rlci1saW5lO1xuICBmb250LXNpemU6IDEycHg7XG4gIGNvbG9yOiAkaGludDtcbiAgZGlzcGxheTogZmxleDtcbiAgZ2FwOiA4cHg7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xufVxuIl19 */","import { useEffect, useState, type CSSProperties, type FormEvent, type ReactNode } from \"react\";\nimport {\n LOGIN_EXPERIENCE_CAPABILITIES,\n resolveLoginExperienceAdapter,\n type ExperienceSocialConnector,\n type LoginExperienceAdapter,\n type SocialSignInRequest,\n} from \"./login-experience-adapter\";\nimport { signInPopup, signInRedirect } from \"./oidc-client\";\nimport { isIdpConfigured, type LuminaryAuthSession, type LuminaryIdpConfig } from \"./types\";\nimport styles from \"./HeadlessLoginPanel.module.scss\";\n\n/** @deprecated Prefer dynamic connectors from IdP; kept for prop typing. */\nexport type SocialProviderTarget = string;\n\nexport interface HeadlessLoginLabels {\n title?: string;\n subtitle?: string;\n identifierPlaceholder?: string;\n /** Placeholder when panel is in register mode (username). */\n registerIdentifierPlaceholder?: string;\n passwordPlaceholder?: string;\n confirmPasswordPlaceholder?: string;\n submitPassword?: string;\n submitRegister?: string;\n /** Hosted OIDC button shown when the adapter has no password capability. */\n submitSso?: string;\n submitGoogle?: string;\n submitGithub?: string;\n socialDivider?: string;\n hint?: string;\n registerHint?: string;\n cancel?: string;\n experienceUnavailable?: string;\n showPassword?: string;\n hidePassword?: string;\n /** Switch link when on sign-in: \"Create an account\" */\n registerLink?: string;\n /** Switch link when on register: \"Already have an account? Sign in\" */\n loginLink?: string;\n passwordMismatch?: string;\n registerTitle?: string;\n registerSubtitle?: string;\n}\n\nexport interface HeadlessLoginPanelProps {\n config: Partial<LuminaryIdpConfig>;\n /** Login-experience provider. Defaults to the catalog adapter for `config.iamProvider`. */\n experienceAdapter?: LoginExperienceAdapter;\n /** Product display name shown as brand signal */\n productName: string;\n logoSrc?: string;\n labels?: HeadlessLoginLabels;\n returnUrl?: string;\n /** Prefer popup (default) for reauth; use redirect for full-page login. */\n mode?: \"popup\" | \"redirect\";\n /**\n * Show Experience social connectors (Google / GitHub / …).\n * Default `true`. Set `false` for admin / internal consoles that only allow\n * password (or enterprise SSO via IdP) — hides divider + social buttons and\n * skips fetching connectors.\n * Equivalent to `socialProviders={[]}` when false.\n */\n showSocialConnectors?: boolean;\n /**\n * Show self-register switch + register form (username + password via Experience).\n * Default `true` for end-user product logins. Set `false` for admin / ops consoles.\n * Hosted OIDC adapters without passwordSignUp hide register automatically.\n */\n showRegister?: boolean;\n /**\n * Social providers (when `showSocialConnectors` is not `false`):\n * - omit / `\"auto\"` — load enabled connectors from IdP (google, github, x, …)\n * - `string[]` — only these targets (still prefers IdP logos/names when available)\n * - `[]` — hide social buttons\n */\n socialProviders?: \"auto\" | SocialProviderTarget[];\n showCancel?: boolean;\n onCancel?: () => void;\n /**\n * Called after OIDC session is obtained (popup) or before redirect navigation.\n * Products typically exchange OIDC access token → product JWT here.\n */\n onOidcSession?: (session: LuminaryAuthSession, returnUrl?: string) => Promise<void> | void;\n /** When Experience returns redirectTo, open it (default: same-tab assign). */\n onExperienceRedirect?: (redirectTo: string) => void;\n footer?: ReactNode;\n className?: string;\n style?: CSSProperties;\n /**\n * Brand accent for primary CTA / focus / product label.\n * Defaults to ecosystem primary `#1677ff`.\n */\n themeColor?: string;\n}\n\n/** Shared default accent for product login panels (shared/brand --lw-primary). */\nexport const DEFAULT_LOGIN_THEME_COLOR = \"#1677ff\";\n\nconst defaults: Required<HeadlessLoginLabels> = {\n title: \"Sign in\",\n subtitle: \"Use your LuminaryWorks unified account\",\n identifierPlaceholder: \"Email or username\",\n registerIdentifierPlaceholder: \"Username\",\n passwordPlaceholder: \"Password\",\n confirmPasswordPlaceholder: \"Confirm password\",\n submitPassword: \"Sign in with password\",\n submitRegister: \"Create account\",\n submitSso: \"Continue with unified account\",\n submitGoogle: \"Google\",\n submitGithub: \"GitHub\",\n socialDivider: \"or\",\n hint: \"Social providers open directly. Password uses your LuminaryWorks account.\",\n registerHint:\n \"Create a username (start with a letter or _). Prefer email? Use a social provider below.\",\n cancel: \"Cancel\",\n experienceUnavailable: \"Password sign-in is unavailable; use a social provider instead.\",\n showPassword: \"Show password\",\n hidePassword: \"Hide password\",\n registerLink: \"Create an account\",\n loginLink: \"Already have an account? Sign in\",\n passwordMismatch: \"Passwords do not match\",\n registerTitle: \"Create account\",\n registerSubtitle: \"Create your LuminaryWorks unified account\",\n};\n\nfunction resolveSieBase(config: Partial<LuminaryIdpConfig>): string | undefined {\n // Prefer same-origin Experience base (SPA proxies /api/.well-known) to avoid\n // cross-port CORS on local Logto. Fall back to issuer origin only when needed.\n const explicit = config.experienceApiBase?.trim();\n if (explicit) return explicit.replace(/\\/$/, \"\");\n if (config.issuer) {\n try {\n return new URL(config.issuer).origin;\n } catch {\n /* fall through */\n }\n }\n return undefined;\n}\n\nfunction labelFor(connector: ExperienceSocialConnector, labels: Required<HeadlessLoginLabels>): string {\n if (connector.target === \"google\" && labels.submitGoogle) return labels.submitGoogle;\n if (connector.target === \"github\" && labels.submitGithub) return labels.submitGithub;\n return connector.name;\n}\n\nfunction cx(...parts: Array<string | undefined | false>): string {\n return parts.filter(Boolean).join(\" \");\n}\n\nexport function HeadlessLoginPanel({\n config,\n experienceAdapter: experienceAdapterProp,\n productName,\n logoSrc,\n labels: labelsProp,\n returnUrl,\n mode = \"popup\",\n showSocialConnectors = true,\n showRegister = true,\n socialProviders = \"auto\",\n showCancel,\n onCancel,\n onOidcSession,\n onExperienceRedirect,\n footer,\n className,\n style,\n themeColor = DEFAULT_LOGIN_THEME_COLOR,\n}: HeadlessLoginPanelProps) {\n const experienceAdapter = resolveLoginExperienceAdapter(\n experienceAdapterProp,\n config.iamProvider,\n );\n const labels = { ...defaults, ...labelsProp };\n const configured = isIdpConfigured(config);\n const [panelMode, setPanelMode] = useState<\"sign-in\" | \"register\">(\"sign-in\");\n const [identifier, setIdentifier] = useState(\"\");\n const [password, setPassword] = useState(\"\");\n const [confirmPassword, setConfirmPassword] = useState(\"\");\n const [passwordVisible, setPasswordVisible] = useState(false);\n const panelStyle: CSSProperties = {\n ...style,\n [\"--lw-auth-theme\" as string]: themeColor || DEFAULT_LOGIN_THEME_COLOR,\n };\n const [loading, setLoading] = useState<\"password\" | string | null>(null);\n const [error, setError] = useState(\"\");\n const [connectors, setConnectors] = useState<ExperienceSocialConnector[]>([]);\n const socialEnabled =\n showSocialConnectors !== false &&\n !(Array.isArray(socialProviders) && socialProviders.length === 0) &&\n experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.socialConnectors) &&\n experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.socialDirectSignIn) &&\n typeof experienceAdapter.fetchSocialConnectors === \"function\" &&\n typeof experienceAdapter.createSocialSignInRequest === \"function\";\n const passwordEnabled =\n experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn) &&\n typeof experienceAdapter.experiencePasswordSignIn === \"function\";\n const registerEnabled =\n showRegister !== false &&\n experienceAdapter.capabilities.includes(LOGIN_EXPERIENCE_CAPABILITIES.passwordSignUp) &&\n typeof experienceAdapter.experiencePasswordSignUp === \"function\";\n const isRegister = panelMode === \"register\" && registerEnabled;\n\n // Browser back from IdP restores bfcache with loading still set → \"…\".\n useEffect(() => {\n const resetBusy = () => setLoading(null);\n window.addEventListener(\"pageshow\", resetBusy);\n window.addEventListener(\"popstate\", resetBusy);\n return () => {\n window.removeEventListener(\"pageshow\", resetBusy);\n window.removeEventListener(\"popstate\", resetBusy);\n };\n }, []);\n\n useEffect(() => {\n const fetchConnectors = experienceAdapter.fetchSocialConnectors;\n if (!socialEnabled || !fetchConnectors) {\n setConnectors([]);\n return;\n }\n let cancelled = false;\n const sieBase = resolveSieBase(config);\n const allowlist =\n socialProviders === \"auto\" || socialProviders === undefined\n ? null\n : new Set(socialProviders.map((t) => t.toLowerCase()));\n\n const apply = (list: ExperienceSocialConnector[]) => {\n const filtered = allowlist\n ? list.filter((c) => allowlist.has(c.target.toLowerCase()))\n : list;\n if (!cancelled) setConnectors(filtered);\n };\n\n if (!sieBase) {\n // No Experience base — do not invent Google/GitHub buttons. Fake fallbacks\n // start OIDC `direct_sign_in` and dump users on Logto `/sign-in`.\n if (!cancelled) setConnectors([]);\n return;\n }\n\n void fetchConnectors.call(experienceAdapter, { apiBase: sieBase, appId: config.clientId })\n .then((list) => {\n apply(list);\n })\n .catch(() => {\n if (!cancelled) setConnectors([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [\n config.clientId,\n config.experienceApiBase,\n config.issuer,\n experienceAdapter,\n socialEnabled,\n socialProviders,\n ]);\n\n const runOidc = async (experienceRequest?: SocialSignInRequest) => {\n if (!configured) throw new Error(\"IdP not configured\");\n if (mode === \"redirect\") {\n await signInRedirect(config, { returnUrl, ...experienceRequest });\n return;\n }\n const { session, returnUrl: next } = await signInPopup(config, {\n returnUrl,\n ...experienceRequest,\n });\n await onOidcSession?.(session, next);\n };\n\n const runSocial = async (target: string) => {\n setError(\"\");\n setLoading(target);\n try {\n if (\n !socialEnabled ||\n !experienceAdapter.capabilities.includes(\n LOGIN_EXPERIENCE_CAPABILITIES.socialDirectSignIn,\n ) ||\n !experienceAdapter.createSocialSignInRequest\n ) {\n throw new Error(\"Login experience does not support direct social sign-in\");\n }\n await runOidc(experienceAdapter.createSocialSignInRequest(target));\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setLoading(null);\n }\n };\n\n const runHostedOidc = async () => {\n setError(\"\");\n setLoading(\"sso\");\n try {\n await runOidc();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setLoading(null);\n }\n };\n\n const followExperienceRedirect = (redirectTo: string) => {\n if (onExperienceRedirect) {\n onExperienceRedirect(redirectTo);\n return;\n }\n window.location.assign(redirectTo);\n };\n\n const runPassword = async (event: FormEvent) => {\n event.preventDefault();\n if (!configured) return;\n setError(\"\");\n setLoading(\"password\");\n try {\n const apiBase = config.experienceApiBase?.trim();\n if (!apiBase) {\n throw new Error(labels.experienceUnavailable);\n }\n if (isRegister) {\n if (\n !registerEnabled ||\n !experienceAdapter.experiencePasswordSignUp\n ) {\n throw new Error(labels.experienceUnavailable);\n }\n if (password !== confirmPassword) {\n throw new Error(labels.passwordMismatch);\n }\n const result = await experienceAdapter.experiencePasswordSignUp({\n apiBase,\n identifier: identifier.trim(),\n password,\n issuer: config.issuer,\n clientId: config.clientId,\n redirectUri: config.redirectUri,\n audience: config.audience,\n scopes: config.scopes,\n returnUrl,\n });\n if (result.redirectTo) {\n followExperienceRedirect(result.redirectTo);\n return;\n }\n throw new Error(\"Experience API did not return redirectTo\");\n }\n if (\n !passwordEnabled ||\n !experienceAdapter.capabilities.includes(\n LOGIN_EXPERIENCE_CAPABILITIES.passwordSignIn,\n ) ||\n !experienceAdapter.experiencePasswordSignIn\n ) {\n throw new Error(labels.experienceUnavailable);\n }\n const result = await experienceAdapter.experiencePasswordSignIn({\n apiBase,\n identifier: identifier.trim(),\n password,\n issuer: config.issuer,\n clientId: config.clientId,\n redirectUri: config.redirectUri,\n audience: config.audience,\n scopes: config.scopes,\n returnUrl,\n });\n if (result.redirectTo) {\n // Completes the PKCE interaction from bootstrap — do NOT start a new\n // authorize (that re-opens Logto hosted /sign-in).\n followExperienceRedirect(result.redirectTo);\n return;\n }\n throw new Error(\"Experience API did not return redirectTo\");\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setLoading(null);\n }\n };\n\n const switchPanelMode = (next: \"sign-in\" | \"register\") => {\n setPanelMode(next);\n setError(\"\");\n setConfirmPassword(\"\");\n };\n\n const busy = loading !== null;\n const showSocial = socialEnabled && connectors.length > 0;\n const showHint = Boolean(labelsProp?.hint) || showSocial || isRegister;\n const formReady =\n Boolean(identifier.trim()) &&\n Boolean(password) &&\n (!isRegister || Boolean(confirmPassword));\n const titleText = isRegister ? labels.registerTitle : labels.title;\n const subtitleText = isRegister ? labels.registerSubtitle : labels.subtitle;\n const identifierPlaceholder = isRegister\n ? labels.registerIdentifierPlaceholder\n : labels.identifierPlaceholder;\n const submitLabel = isRegister ? labels.submitRegister : labels.submitPassword;\n const hintText = isRegister ? labels.registerHint : labels.hint;\n\n return (\n <div className={cx(styles.panel, className)} style={panelStyle}>\n <header className={styles.brand}>\n {logoSrc ? <img src={logoSrc} alt=\"\" width={48} height={48} className={styles.logo} /> : null}\n <div>\n <p className={styles.product}>{productName}</p>\n <h2 className={styles.title}>{titleText}</h2>\n </div>\n </header>\n <p className={styles.subtitle}>{subtitleText}</p>\n\n {configured ? (\n <>\n {passwordEnabled ? (\n <form onSubmit={(e) => void runPassword(e)} className={styles.form}>\n <input\n type=\"text\"\n name=\"identifier\"\n autoComplete={isRegister ? \"username\" : \"username\"}\n placeholder={identifierPlaceholder}\n value={identifier}\n onChange={(e) => setIdentifier(e.target.value)}\n className={styles.input}\n disabled={busy}\n />\n <div className={styles.passwordField}>\n <input\n type={passwordVisible ? \"text\" : \"password\"}\n name=\"password\"\n autoComplete={isRegister ? \"new-password\" : \"current-password\"}\n placeholder={labels.passwordPlaceholder}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n className={cx(styles.input, styles.passwordInput)}\n disabled={busy}\n />\n <button\n type=\"button\"\n className={styles.passwordToggle}\n disabled={busy}\n aria-label={passwordVisible ? labels.hidePassword : labels.showPassword}\n aria-pressed={passwordVisible}\n onClick={() => setPasswordVisible((v) => !v)}\n >\n <PasswordVisibilityIcon visible={passwordVisible} />\n </button>\n </div>\n {isRegister ? (\n <div className={styles.passwordField}>\n <input\n type={passwordVisible ? \"text\" : \"password\"}\n name=\"confirmPassword\"\n autoComplete=\"new-password\"\n placeholder={labels.confirmPasswordPlaceholder}\n value={confirmPassword}\n onChange={(e) => setConfirmPassword(e.target.value)}\n className={cx(styles.input, styles.passwordInput)}\n disabled={busy}\n />\n </div>\n ) : null}\n <button type=\"submit\" className={styles.primaryBtn} disabled={busy || !formReady}>\n {loading === \"password\" ? \"…\" : submitLabel}\n </button>\n </form>\n ) : (\n <div className={styles.form}>\n <button\n type=\"button\"\n className={styles.primaryBtn}\n disabled={busy}\n onClick={() => void runHostedOidc()}\n >\n {loading === \"sso\" ? \"…\" : labels.submitSso}\n </button>\n </div>\n )}\n {showHint ? <p className={styles.hint}>{hintText}</p> : null}\n\n {registerEnabled && passwordEnabled ? (\n <p className={styles.switchMode}>\n <button\n type=\"button\"\n className={styles.switchModeBtn}\n disabled={busy}\n onClick={() => switchPanelMode(isRegister ? \"sign-in\" : \"register\")}\n >\n {isRegister ? labels.loginLink : labels.registerLink}\n </button>\n </p>\n ) : null}\n\n {showSocial ? (\n <div className={styles.divider} aria-hidden>\n <span className={styles.dividerLine} />\n <span className={styles.dividerText}>{labels.socialDivider}</span>\n <span className={styles.dividerLine} />\n </div>\n ) : null}\n {showSocial ? (\n <div className={styles.socialStack}>\n {connectors.map((connector) => (\n <button\n key={connector.id}\n type=\"button\"\n className={styles.socialBtn}\n disabled={busy}\n onClick={() => void runSocial(connector.target)}\n >\n <SocialLogo connector={connector} />\n {loading === connector.target ? \"…\" : labelFor(connector, labels)}\n </button>\n ))}\n </div>\n ) : null}\n\n </>\n ) : (\n <p className={styles.error}>IdP is not configured (issuer / clientId / redirectUri).</p>\n )}\n\n {error ? <p className={styles.error}>{error}</p> : null}\n\n {showCancel ? (\n <button type=\"button\" className={styles.cancelBtn} disabled={busy} onClick={onCancel}>\n {labels.cancel}\n </button>\n ) : null}\n\n {footer ? <footer className={styles.footer}>{footer}</footer> : null}\n </div>\n );\n}\n\nfunction SocialLogo({ connector }: { connector: ExperienceSocialConnector }) {\n if (connector.logo) {\n return <img src={connector.logo} alt=\"\" width={18} height={18} className={styles.socialLogo} />;\n }\n return (\n <span className={styles.logoFallback} aria-hidden>\n {connector.name.slice(0, 1).toUpperCase()}\n </span>\n );\n}\n\nfunction PasswordVisibilityIcon({ visible }: { visible: boolean }) {\n // Filled icons (antd Eye / EyeInvisible style) — no dependency.\n if (visible) {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 1024 1024\" fill=\"currentColor\" aria-hidden>\n <path d=\"M942.2 486.2C847.4 286.5 704.1 186 512 186c-57.9 0-111.5 9.8-160.3 27.7l72.3 72.3C457 273.3 483.5 266 512 266c161.3 0 279.4 81.8 362.7 254-26.3 54.4-57.5 100.2-93.3 136.1l59.6 59.6C891.4 655.7 932.5 578.5 942.2 537.7a60.3 60.3 0 000-51.5zM336.6 278.6l-59.9-59.9C230.6 255.4 182.8 296.4 141.9 348.1 95.4 412.1 64.6 486.5 51.8 512a60.3 60.3 0 000 51.5C115.3 719.5 224.6 814.8 365.4 860.1l72.5-72.5C353.6 761.6 286.3 698.3 241.3 612.5 220.6 573.1 205 528.6 194.5 486.2c24.5-50.4 55.1-92.1 90.8-124.9l51.3-51.3zM606.6 556.6A112 112 0 01467.4 417.4L606.6 556.6zM508 624c-26.5 0-50.9-9.2-70.2-24.6l-59.9 59.9A175.3 175.3 0 00508 688c97.2 0 176-78.8 176-176 0-26.5-9.2-50.9-24.6-70.2l-59.9 59.9c15.4 19.3 24.6 43.7 24.6 70.2 0 61.9-50.1 112-112 112zM880 112L112 880l48 48 768-768z\" />\n </svg>\n );\n }\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 1024 1024\" fill=\"currentColor\" aria-hidden>\n <path d=\"M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3a60.3 60.3 0 000-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766z\" />\n <path d=\"M508 336c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z\" />\n </svg>\n );\n}\n","import { useSyncExternalStore, type CSSProperties, type ReactNode } from \"react\";\nimport { authGate } from \"./auth-gate\";\nimport { HeadlessLoginPanel, type HeadlessLoginLabels } from \"./HeadlessLoginPanel\";\nimport type { LuminaryAuthSession, LuminaryIdpConfig } from \"./types\";\n\nexport interface ReauthOverlayProps {\n config: Partial<LuminaryIdpConfig>;\n productName: string;\n logoSrc?: string;\n labels?: HeadlessLoginLabels;\n returnUrl?: string;\n /** Brand accent forwarded to HeadlessLoginPanel (default `#1677ff`). */\n themeColor?: string;\n /** Exchange OIDC token / persist product session, then AuthGate completes. */\n onOidcSession: (session: LuminaryAuthSession, returnUrl?: string) => Promise<void> | void;\n /** Optional custom body instead of HeadlessLoginPanel */\n children?: ReactNode;\n /** Allow dismiss → cancelReauth (default true for mid-session; false for hard gate). */\n dismissible?: boolean;\n onDismiss?: () => void;\n}\n\n/**\n * Full-viewport soft gate shown while AuthGate phase is `reauth` (or `refreshing` spinner).\n * Does not iframe the IdP — uses Headless panel + OIDC popup.\n */\nexport function ReauthOverlay({\n config,\n productName,\n logoSrc,\n labels,\n returnUrl,\n themeColor,\n onOidcSession,\n children,\n dismissible = true,\n onDismiss,\n}: ReauthOverlayProps) {\n const snapshot = useSyncExternalStore(authGate.subscribe, authGate.getSnapshot, authGate.getSnapshot);\n\n if (snapshot.phase === \"idle\") return null;\n\n const resolvedReturnUrl =\n returnUrl ??\n (() => {\n if (typeof window === \"undefined\") return undefined;\n const hash = window.location.hash.replace(/^#/, \"\");\n if (!hash || hash.startsWith(\"/login\") || hash.startsWith(\"/auth/\")) return undefined;\n return hash.startsWith(\"/\") ? hash : `/${hash}`;\n })();\n\n const handleSession = async (session: LuminaryAuthSession, next?: string) => {\n await onOidcSession(session, next);\n authGate.completeReauth();\n };\n\n const handleCancel = () => {\n onDismiss?.();\n authGate.cancelReauth(\"cancelled\");\n };\n\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={productName}\n style={backdropStyle}\n onClick={dismissible ? handleCancel : undefined}\n >\n <div style={centerStyle} onClick={(e) => e.stopPropagation()}>\n {snapshot.phase === \"refreshing\" ? (\n <div style={spinnerCardStyle}>\n <div style={spinnerStyle} />\n <p style={{ margin: 0, color: \"#e8eef2\" }}>Refreshing session…</p>\n </div>\n ) : children ? (\n children\n ) : (\n <HeadlessLoginPanel\n config={config}\n productName={productName}\n logoSrc={logoSrc}\n themeColor={themeColor}\n labels={{\n title: labels?.title ?? \"Session expired\",\n subtitle: labels?.subtitle ?? \"Sign in again to keep working — this page will not reload.\",\n ...labels,\n }}\n returnUrl={resolvedReturnUrl}\n mode=\"popup\"\n showRegister={false}\n showCancel={dismissible}\n onCancel={handleCancel}\n onOidcSession={handleSession}\n />\n )}\n </div>\n </div>\n );\n}\n\nconst backdropStyle: CSSProperties = {\n position: \"fixed\",\n inset: 0,\n zIndex: 10000,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 24,\n background:\n \"radial-gradient(1200px 600px at 20% 10%, rgba(56, 120, 150, 0.35), transparent 55%), rgba(10, 18, 24, 0.72)\",\n backdropFilter: \"blur(6px)\",\n};\n\nconst centerStyle: CSSProperties = {\n width: \"min(100%, 420px)\",\n};\n\nconst spinnerCardStyle: CSSProperties = {\n display: \"grid\",\n justifyItems: \"center\",\n gap: 14,\n padding: 28,\n borderRadius: 16,\n background: \"rgba(20, 32, 40, 0.88)\",\n};\n\nconst spinnerStyle: CSSProperties = {\n width: 36,\n height: 36,\n borderRadius: \"50%\",\n border: \"3px solid rgba(255,255,255,0.2)\",\n borderTopColor: \"#7ec8e3\",\n animation: \"luminary-auth-spin 0.8s linear infinite\",\n};\n\n// Inject keyframes once\nif (typeof document !== \"undefined\" && !document.getElementById(\"luminary-auth-spin-style\")) {\n const style = document.createElement(\"style\");\n style.id = \"luminary-auth-spin-style\";\n style.textContent = `@keyframes luminary-auth-spin { to { transform: rotate(360deg); } }`;\n document.head.appendChild(style);\n}\n","import { createContext, useContext, useEffect, useMemo, type ReactNode } from \"react\";\nimport { useSyncExternalStore } from \"react\";\nimport { authGate, type AuthGateConfig, type AuthGateSnapshot } from \"./auth-gate\";\nimport { ReauthOverlay, type ReauthOverlayProps } from \"./ReauthOverlay\";\nimport type { LuminaryAuthSession, LuminaryIdpConfig } from \"./types\";\n\ninterface AuthGateContextValue {\n snapshot: AuthGateSnapshot;\n requestReauth: (message?: string) => Promise<\"retry\" | \"fail\">;\n completeReauth: () => void;\n cancelReauth: (message?: string) => void;\n}\n\nconst AuthGateContext = createContext<AuthGateContextValue | null>(null);\n\nexport interface AuthGateProviderProps extends AuthGateConfig {\n children: ReactNode;\n /** When set, mounts {@link ReauthOverlay} automatically. */\n overlay?: Omit<ReauthOverlayProps, \"onOidcSession\"> & {\n onOidcSession: (session: LuminaryAuthSession, returnUrl?: string) => Promise<void> | void;\n config: Partial<LuminaryIdpConfig>;\n };\n}\n\nexport function AuthGateProvider({\n children,\n tryRefresh,\n onReauthRequired,\n onSettled,\n overlay,\n}: AuthGateProviderProps) {\n useEffect(() => {\n authGate.configure({ tryRefresh, onReauthRequired, onSettled });\n }, [tryRefresh, onReauthRequired, onSettled]);\n\n const snapshot = useSyncExternalStore(authGate.subscribe, authGate.getSnapshot, authGate.getSnapshot);\n\n const value = useMemo<AuthGateContextValue>(\n () => ({\n snapshot,\n requestReauth: (message?: string) => authGate.requestReauth(message),\n completeReauth: () => authGate.completeReauth(),\n cancelReauth: (message?: string) => authGate.cancelReauth(message),\n }),\n [snapshot],\n );\n\n return (\n <AuthGateContext.Provider value={value}>\n {children}\n {overlay ? <ReauthOverlay {...overlay} /> : null}\n </AuthGateContext.Provider>\n );\n}\n\nexport function useAuthGate(): AuthGateContextValue {\n const ctx = useContext(AuthGateContext);\n if (!ctx) throw new Error(\"useAuthGate must be used within AuthGateProvider\");\n return ctx;\n}\n\n/** Optional hook — returns null outside provider (for shared API helpers). */\nexport function useAuthGateOptional(): AuthGateContextValue | null {\n return useContext(AuthGateContext);\n}\n","export interface PostLoginPathOptions {\n /** sessionStorage key (product-scoped), e.g. `dv:postLoginPath` */\n storageKey: string;\n /** Default destination when nothing remembered */\n defaultPath?: string;\n /** Extra paths that must not be used as return targets */\n unsafePrefixes?: string[];\n}\n\nconst DEFAULT_UNSAFE = [\"/login\", \"/auth\", \"/exception\"];\n\nfunction normalizeAppPath(path: string, fallback: string): string {\n const raw = path.replace(/^#/, \"\").trim();\n if (!raw) return fallback.startsWith(\"/\") ? fallback : `/${fallback}`;\n return raw.startsWith(\"/\") ? raw : `/${raw}`;\n}\n\nfunction isUnsafeReturnPath(path: string, unsafePrefixes: string[], fallback: string): boolean {\n const p = normalizeAppPath(path, fallback);\n if (p === \"/\") return true;\n return unsafePrefixes.some((prefix) => p === prefix || p.startsWith(`${prefix}/`) || p.startsWith(prefix));\n}\n\n/**\n * sessionStorage helpers for OIDC redirect return paths.\n * Product-specific ACL checks (e.g. 403 fallback) stay in the product.\n */\nexport function createPostLoginPathHelpers(options: PostLoginPathOptions) {\n const storageKey = options.storageKey;\n const defaultPath = options.defaultPath?.startsWith(\"/\")\n ? options.defaultPath\n : `/${options.defaultPath || \"home\"}`;\n const unsafePrefixes = [...DEFAULT_UNSAFE, ...(options.unsafePrefixes || [])];\n\n function rememberPostLoginPath(path: string): void {\n const normalized = normalizeAppPath(path, defaultPath);\n if (isUnsafeReturnPath(normalized, unsafePrefixes, defaultPath)) return;\n try {\n sessionStorage.setItem(storageKey, normalized);\n } catch {\n /* ignore */\n }\n }\n\n function peekPostLoginPath(): string | undefined {\n try {\n const v = sessionStorage.getItem(storageKey);\n if (!v || isUnsafeReturnPath(v, unsafePrefixes, defaultPath)) return undefined;\n return normalizeAppPath(v, defaultPath);\n } catch {\n return undefined;\n }\n }\n\n function consumePostLoginPath(fallback = defaultPath): string {\n const remembered = peekPostLoginPath();\n try {\n sessionStorage.removeItem(storageKey);\n } catch {\n /* ignore */\n }\n return remembered ?? normalizeAppPath(fallback, defaultPath);\n }\n\n return {\n rememberPostLoginPath,\n peekPostLoginPath,\n consumePostLoginPath,\n normalizeAppPath: (path: string) => normalizeAppPath(path, defaultPath),\n isUnsafeReturnPath: (path: string) => isUnsafeReturnPath(path, unsafePrefixes, defaultPath),\n };\n}\n"]}
|
package/dist/style.css
CHANGED
|
@@ -201,6 +201,25 @@
|
|
|
201
201
|
color: #6b7c87;
|
|
202
202
|
line-height: 1.45;
|
|
203
203
|
}
|
|
204
|
+
.HeadlessLoginPanel_module_switchMode {
|
|
205
|
+
margin: 12px 0 0;
|
|
206
|
+
text-align: center;
|
|
207
|
+
}
|
|
208
|
+
.HeadlessLoginPanel_module_switchModeBtn {
|
|
209
|
+
border: none;
|
|
210
|
+
background: transparent;
|
|
211
|
+
color: var(--lw-auth-theme);
|
|
212
|
+
font-size: 13px;
|
|
213
|
+
font-weight: 650;
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
padding: 4px 8px;
|
|
216
|
+
text-decoration: underline;
|
|
217
|
+
text-underline-offset: 3px;
|
|
218
|
+
}
|
|
219
|
+
.HeadlessLoginPanel_module_switchModeBtn:disabled {
|
|
220
|
+
opacity: 0.65;
|
|
221
|
+
cursor: not-allowed;
|
|
222
|
+
}
|
|
204
223
|
.HeadlessLoginPanel_module_error {
|
|
205
224
|
margin: 12px 0 0;
|
|
206
225
|
font-size: 13px;
|
package/dist/style.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/HeadlessLoginPanel.module.scss"],"sourcesContent":["$ink: #14212b;\n$muted: #4b5c68;\n$hint: #6b7c87;\n$brand: #3d6f8f;\n$brand-deep: #15485c;\n$brand-mid: #1f6f8b;\n$border: #c9d5de;\n$border-soft: #b7c9d4;\n$line: #d5e0e7;\n$divider: #90a0ab;\n$surface: #f7fafc;\n$fallback-bg: #e8eef2;\n$danger: #b42318;\n$footer-line: #e4ebf0;\n$radius-lg: 16px;\n$radius-md: 10px;\n$radius-sm: 4px;\n\n.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: $radius-lg;\n background: rgba(255, 255, 255, 0.96);\n color: $ink;\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n font-family: \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif;\n}\n\n.brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.logo {\n border-radius: 12px;\n display: block;\n}\n\n.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\n.title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: $muted;\n}\n\n.form {\n display: grid;\n gap: 10px;\n}\n\n.socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.input {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid $border;\n border-radius: $radius-md;\n padding: 10px 12px;\n font-size: 14px;\n outline: none;\n background: $surface;\n\n &:focus {\n border-color: var(--lw-auth-theme);\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.passwordInput {\n padding-right: 42px;\n}\n\n.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: $radius-sm;\n padding: 0;\n color: #5a6b76;\n background: transparent;\n cursor: pointer;\n\n &:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n }\n\n &:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.primaryBtn {\n border: none;\n border-radius: $radius-md;\n padding: 11px 14px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #fff;\n background: linear-gradient(135deg, var(--lw-auth-theme) 0%, var(--lw-auth-theme-deep) 100%);\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.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 $border-soft;\n border-radius: $radius-md;\n padding: 11px 10px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: $ink;\n background: #fff;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialLogo {\n flex-shrink: 0;\n display: block;\n}\n\n.logoFallback {\n width: 18px;\n height: 18px;\n border-radius: $radius-sm;\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\n.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 &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: $divider;\n}\n\n.dividerLine {\n flex: 1;\n height: 1px;\n background: $line;\n}\n\n.dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: $hint;\n line-height: 1.45;\n}\n\n.error {\n margin: 12px 0 0;\n font-size: 13px;\n color: $danger;\n line-height: 1.4;\n}\n\n.footer {\n margin-top: 18px;\n padding-top: 12px;\n border-top: 1px solid $footer-line;\n font-size: 12px;\n color: $hint;\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n"],"mappings":"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
|
|
1
|
+
{"version":3,"sources":["../src/HeadlessLoginPanel.module.scss"],"sourcesContent":["$ink: #14212b;\n$muted: #4b5c68;\n$hint: #6b7c87;\n$brand: #3d6f8f;\n$brand-deep: #15485c;\n$brand-mid: #1f6f8b;\n$border: #c9d5de;\n$border-soft: #b7c9d4;\n$line: #d5e0e7;\n$divider: #90a0ab;\n$surface: #f7fafc;\n$fallback-bg: #e8eef2;\n$danger: #b42318;\n$footer-line: #e4ebf0;\n$radius-lg: 16px;\n$radius-md: 10px;\n$radius-sm: 4px;\n\n.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: $radius-lg;\n background: rgba(255, 255, 255, 0.96);\n color: $ink;\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n font-family: \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif;\n}\n\n.brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.logo {\n border-radius: 12px;\n display: block;\n}\n\n.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\n.title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: $muted;\n}\n\n.form {\n display: grid;\n gap: 10px;\n}\n\n.socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.input {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid $border;\n border-radius: $radius-md;\n padding: 10px 12px;\n font-size: 14px;\n outline: none;\n background: $surface;\n\n &:focus {\n border-color: var(--lw-auth-theme);\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.passwordInput {\n padding-right: 42px;\n}\n\n.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: $radius-sm;\n padding: 0;\n color: #5a6b76;\n background: transparent;\n cursor: pointer;\n\n &:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n }\n\n &:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.primaryBtn {\n border: none;\n border-radius: $radius-md;\n padding: 11px 14px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #fff;\n background: linear-gradient(135deg, var(--lw-auth-theme) 0%, var(--lw-auth-theme-deep) 100%);\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.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 $border-soft;\n border-radius: $radius-md;\n padding: 11px 10px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: $ink;\n background: #fff;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialLogo {\n flex-shrink: 0;\n display: block;\n}\n\n.logoFallback {\n width: 18px;\n height: 18px;\n border-radius: $radius-sm;\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\n.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 &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: $divider;\n}\n\n.dividerLine {\n flex: 1;\n height: 1px;\n background: $line;\n}\n\n.dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: $hint;\n line-height: 1.45;\n}\n\n.switchMode {\n margin: 12px 0 0;\n text-align: center;\n}\n\n.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 &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.error {\n margin: 12px 0 0;\n font-size: 13px;\n color: $danger;\n line-height: 1.4;\n}\n\n.footer {\n margin-top: 18px;\n padding-top: 12px;\n border-top: 1px solid $footer-line;\n font-size: 12px;\n color: $hint;\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n"],"mappings":"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","names":["panel","brand","logo","product","title","subtitle","form","socialStack","input","passwordField","passwordInput","passwordToggle","primaryBtn","socialBtn","socialLogo","logoFallback","cancelBtn","divider","dividerLine","dividerText","hint","switchMode","switchModeBtn","error","footer"]}
|