@civic/auth 0.6.0 → 0.6.1-beta.1
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/shared/components/CivicAuthIframeContainer.js +1 -1
- package/dist/shared/components/CivicAuthIframeContainer.js.map +1 -1
- package/dist/shared/lib/BrowserAuthenticationRefresher.d.ts +7 -1
- package/dist/shared/lib/BrowserAuthenticationRefresher.d.ts.map +1 -1
- package/dist/shared/lib/BrowserAuthenticationRefresher.js +15 -2
- package/dist/shared/lib/BrowserAuthenticationRefresher.js.map +1 -1
- package/dist/shared/lib/util.d.ts +1 -1
- package/dist/shared/lib/util.d.ts.map +1 -1
- package/dist/shared/lib/util.js +6 -1
- package/dist/shared/lib/util.js.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.d.ts.map +1 -1
- package/dist/shared/version.js +1 -1
- package/dist/shared/version.js.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.d.ts +63 -5
- package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.js +202 -26
- package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
- package/dist/vanillajs/auth/OAuthCallbackHandler.d.ts +90 -0
- package/dist/vanillajs/auth/OAuthCallbackHandler.d.ts.map +1 -0
- package/dist/vanillajs/auth/OAuthCallbackHandler.js +143 -0
- package/dist/vanillajs/auth/OAuthCallbackHandler.js.map +1 -0
- package/dist/vanillajs/auth/SessionManager.d.ts +40 -9
- package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
- package/dist/vanillajs/auth/SessionManager.js +96 -61
- package/dist/vanillajs/auth/SessionManager.js.map +1 -1
- package/dist/vanillajs/auth/TokenRefresher.d.ts +54 -0
- package/dist/vanillajs/auth/TokenRefresher.d.ts.map +1 -0
- package/dist/vanillajs/auth/TokenRefresher.js +166 -0
- package/dist/vanillajs/auth/TokenRefresher.js.map +1 -0
- package/dist/vanillajs/iframe/IframeManager.d.ts +82 -0
- package/dist/vanillajs/iframe/IframeManager.d.ts.map +1 -0
- package/dist/vanillajs/iframe/IframeManager.js +487 -0
- package/dist/vanillajs/iframe/IframeManager.js.map +1 -0
- package/dist/vanillajs/iframe/IframeResizer.d.ts +15 -0
- package/dist/vanillajs/iframe/IframeResizer.d.ts.map +1 -0
- package/dist/vanillajs/iframe/IframeResizer.js +127 -0
- package/dist/vanillajs/iframe/IframeResizer.js.map +1 -0
- package/dist/vanillajs/index.d.ts +8 -7
- package/dist/vanillajs/index.d.ts.map +1 -1
- package/dist/vanillajs/index.js +10 -7
- package/dist/vanillajs/index.js.map +1 -1
- package/dist/vanillajs/types/index.d.ts +2 -2
- package/dist/vanillajs/types/index.d.ts.map +1 -1
- package/dist/vanillajs/types/index.js.map +1 -1
- package/dist/vanillajs/ui/LoadingComponents.d.ts +51 -0
- package/dist/vanillajs/ui/LoadingComponents.d.ts.map +1 -0
- package/dist/vanillajs/ui/LoadingComponents.js +363 -0
- package/dist/vanillajs/ui/LoadingComponents.js.map +1 -0
- package/package.json +1 -1
- package/dist/vanillajs/iframe/domUtils.d.ts +0 -4
- package/dist/vanillajs/iframe/domUtils.d.ts.map +0 -1
- package/dist/vanillajs/iframe/domUtils.js +0 -25
- package/dist/vanillajs/iframe/domUtils.js.map +0 -1
- package/dist/vanillajs/storage/BrowserCookieStorageAdapter.d.ts +0 -19
- package/dist/vanillajs/storage/BrowserCookieStorageAdapter.d.ts.map +0 -1
- package/dist/vanillajs/storage/BrowserCookieStorageAdapter.js +0 -101
- package/dist/vanillajs/storage/BrowserCookieStorageAdapter.js.map +0 -1
- package/dist/vanillajs/storage/BrowserLocalStorageAdapter.d.ts +0 -9
- package/dist/vanillajs/storage/BrowserLocalStorageAdapter.d.ts.map +0 -1
- package/dist/vanillajs/storage/BrowserLocalStorageAdapter.js +0 -36
- package/dist/vanillajs/storage/BrowserLocalStorageAdapter.js.map +0 -1
- package/dist/vanillajs/storage/InMemoryStorageAdapter.d.ts +0 -9
- package/dist/vanillajs/storage/InMemoryStorageAdapter.d.ts.map +0 -1
- package/dist/vanillajs/storage/InMemoryStorageAdapter.js +0 -16
- package/dist/vanillajs/storage/InMemoryStorageAdapter.js.map +0 -1
- package/dist/vanillajs/storage/StorageAdapter.d.ts +0 -15
- package/dist/vanillajs/storage/StorageAdapter.d.ts.map +0 -1
- package/dist/vanillajs/storage/StorageAdapter.js +0 -16
- package/dist/vanillajs/storage/StorageAdapter.js.map +0 -1
- package/dist/vanillajs/utils/page-handlers.d.ts +0 -29
- package/dist/vanillajs/utils/page-handlers.d.ts.map +0 -1
- package/dist/vanillajs/utils/page-handlers.js +0 -165
- package/dist/vanillajs/utils/page-handlers.js.map +0 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { AuthEvent } from "../types/index.js";
|
|
2
|
+
import { BrowserAuthenticationRefresher, } from "../../shared/lib/BrowserAuthenticationRefresher.js";
|
|
3
|
+
import { getCurrentLogger } from "../utils/logger.js";
|
|
4
|
+
import { retrieveAccessTokenExpiresAt } from "../../shared/lib/util.js";
|
|
5
|
+
/**
|
|
6
|
+
* TokenRefresher handles automatic token refresh for vanilla.js implementation
|
|
7
|
+
* Inspired by the React useRefresh hook and BrowserAuthenticationRefresher
|
|
8
|
+
*/
|
|
9
|
+
export class TokenRefresher {
|
|
10
|
+
refresher;
|
|
11
|
+
storage;
|
|
12
|
+
events;
|
|
13
|
+
authConfig;
|
|
14
|
+
isAuthenticated = false;
|
|
15
|
+
isDestroyed = false;
|
|
16
|
+
logger = getCurrentLogger();
|
|
17
|
+
constructor(storage, events, authConfig) {
|
|
18
|
+
this.storage = storage;
|
|
19
|
+
this.events = events;
|
|
20
|
+
this.authConfig = authConfig;
|
|
21
|
+
this.logger.info("TokenRefresher initialized");
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Initialize the token refresher with auth configuration
|
|
25
|
+
*/
|
|
26
|
+
async initialize(authConfig) {
|
|
27
|
+
if (this.isDestroyed)
|
|
28
|
+
return;
|
|
29
|
+
this.authConfig = authConfig;
|
|
30
|
+
try {
|
|
31
|
+
// Clear any existing refresher
|
|
32
|
+
await this.cleanup();
|
|
33
|
+
const onError = async (error) => {
|
|
34
|
+
this.logger.error("Token refresh error:", error);
|
|
35
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);
|
|
36
|
+
// Clear auto-refresh on error
|
|
37
|
+
this.refresher?.clearAutorefresh();
|
|
38
|
+
// Optionally sign out the user on refresh token errors
|
|
39
|
+
// This mirrors the React implementation behavior
|
|
40
|
+
this.events.emit(AuthEvent.SIGN_OUT_STARTED, null);
|
|
41
|
+
};
|
|
42
|
+
// Create callbacks for refresh events
|
|
43
|
+
const refreshEventCallbacks = {
|
|
44
|
+
onRefreshStarted: () => {
|
|
45
|
+
this.logger.info("Auto token refresh started");
|
|
46
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_STARTED, null);
|
|
47
|
+
},
|
|
48
|
+
onRefreshComplete: () => {
|
|
49
|
+
this.logger.info("Auto token refresh completed");
|
|
50
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_COMPLETE, null);
|
|
51
|
+
},
|
|
52
|
+
onRefreshError: (error) => {
|
|
53
|
+
this.logger.error("Auto token refresh failed:", error);
|
|
54
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
this.refresher = await BrowserAuthenticationRefresher.build(authConfig, this.storage, onError, undefined, // endpointOverrides
|
|
58
|
+
refreshEventCallbacks);
|
|
59
|
+
this.logger.info("TokenRefresher initialized");
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
this.logger.error("Failed to initialize TokenRefresher:", error);
|
|
63
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Set authentication state and manage auto-refresh accordingly
|
|
68
|
+
*/
|
|
69
|
+
setAuthenticationState(isAuthenticated) {
|
|
70
|
+
if (this.isDestroyed)
|
|
71
|
+
return;
|
|
72
|
+
this.isAuthenticated = isAuthenticated;
|
|
73
|
+
if (isAuthenticated && this.refresher) {
|
|
74
|
+
// Fire and forget the async call - we don't want to make setAuthenticationState async
|
|
75
|
+
// as it would break the interface
|
|
76
|
+
this.startAutoRefresh().catch((error) => {
|
|
77
|
+
this.logger.error("Error starting auto refresh:", error);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.stopAutoRefresh();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Manually refresh tokens
|
|
86
|
+
*/
|
|
87
|
+
async refreshTokens() {
|
|
88
|
+
if (this.isDestroyed || !this.refresher) {
|
|
89
|
+
const errorMsg = `TokenRefresher not initialized or destroyed. isDestroyed: ${this.isDestroyed}, hasRefresher: ${!!this.refresher}`;
|
|
90
|
+
this.logger.error(errorMsg);
|
|
91
|
+
throw new Error(errorMsg);
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_STARTED, null);
|
|
95
|
+
this.logger.info("Starting manual token refresh");
|
|
96
|
+
await this.refresher.refreshTokens();
|
|
97
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_COMPLETE, null);
|
|
98
|
+
this.logger.info("Manual token refresh completed");
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
this.logger.error("Manual token refresh failed:", error);
|
|
102
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Start automatic token refresh
|
|
108
|
+
*/
|
|
109
|
+
async startAutoRefresh() {
|
|
110
|
+
if (this.refresher && this.isAuthenticated) {
|
|
111
|
+
this.logger.info("Starting automatic token refresh");
|
|
112
|
+
try {
|
|
113
|
+
// Calculate when the next refresh will happen (same logic as BrowserAuthenticationRefresher)
|
|
114
|
+
const now = Math.floor(Date.now() / 1000);
|
|
115
|
+
const expiresAt = (await retrieveAccessTokenExpiresAt(this.storage)) || now + 60;
|
|
116
|
+
const bufferTime = 30; // 30 seconds buffer
|
|
117
|
+
const refreshTime = Math.max(0, expiresAt - bufferTime - now);
|
|
118
|
+
const nextRefreshDate = new Date((now + refreshTime) * 1000);
|
|
119
|
+
this.logger.info(`Next token refresh scheduled for: ${nextRefreshDate.toISOString()} (in ${refreshTime} seconds)`);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
this.logger.warn("Could not calculate next refresh time:", error);
|
|
123
|
+
}
|
|
124
|
+
this.refresher.setupAutorefresh();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Stop automatic token refresh
|
|
129
|
+
*/
|
|
130
|
+
stopAutoRefresh() {
|
|
131
|
+
if (this.refresher) {
|
|
132
|
+
this.logger.info("Stopping automatic token refresh");
|
|
133
|
+
this.refresher.clearAutorefresh();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Clean up resources
|
|
138
|
+
*/
|
|
139
|
+
async cleanup() {
|
|
140
|
+
this.logger.info("Cleaning up TokenRefresher");
|
|
141
|
+
if (this.refresher) {
|
|
142
|
+
this.refresher.clearAutorefresh();
|
|
143
|
+
this.refresher = undefined;
|
|
144
|
+
}
|
|
145
|
+
this.isAuthenticated = false;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Destroy the token refresher permanently
|
|
149
|
+
*/
|
|
150
|
+
async destroy() {
|
|
151
|
+
this.isDestroyed = true;
|
|
152
|
+
await this.cleanup();
|
|
153
|
+
this.logger.info("TokenRefresher destroyed");
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get current refresh state
|
|
157
|
+
*/
|
|
158
|
+
getState() {
|
|
159
|
+
return {
|
|
160
|
+
isInitialized: !!this.refresher,
|
|
161
|
+
isAuthenticated: this.isAuthenticated,
|
|
162
|
+
isAutoRefreshActive: this.isAuthenticated && !!this.refresher,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=TokenRefresher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenRefresher.js","sourceRoot":"","sources":["../../../src/vanillajs/auth/TokenRefresher.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AuthStorage } from \"../../types.js\";\nimport type { AuthenticationEvents } from \"./AuthenticationEvents.js\";\nimport { AuthEvent } from \"../types/index.js\";\nimport {\n BrowserAuthenticationRefresher,\n type RefreshEventCallbacks,\n} from \"../../shared/lib/BrowserAuthenticationRefresher.js\";\nimport type { AuthConfig } from \"../../server/config.js\";\nimport { getCurrentLogger } from \"../utils/logger.js\";\nimport { retrieveAccessTokenExpiresAt } from \"../../shared/lib/util.js\";\n\n/**\n * TokenRefresher handles automatic token refresh for vanilla.js implementation\n * Inspired by the React useRefresh hook and BrowserAuthenticationRefresher\n */\nexport class TokenRefresher {\n private refresher?: BrowserAuthenticationRefresher;\n private storage: AuthStorage;\n private events: AuthenticationEvents;\n private authConfig?: AuthConfig;\n private isAuthenticated: boolean = false;\n private isDestroyed: boolean = false;\n private logger = getCurrentLogger();\n\n constructor(\n storage: AuthStorage,\n events: AuthenticationEvents,\n authConfig?: AuthConfig,\n ) {\n this.storage = storage;\n this.events = events;\n this.authConfig = authConfig;\n\n this.logger.info(\"TokenRefresher initialized\");\n }\n\n /**\n * Initialize the token refresher with auth configuration\n */\n async initialize(authConfig: AuthConfig): Promise<void> {\n if (this.isDestroyed) return;\n\n this.authConfig = authConfig;\n\n try {\n // Clear any existing refresher\n await this.cleanup();\n\n const onError = async (error: Error) => {\n this.logger.error(\"Token refresh error:\", error);\n this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);\n\n // Clear auto-refresh on error\n this.refresher?.clearAutorefresh();\n\n // Optionally sign out the user on refresh token errors\n // This mirrors the React implementation behavior\n this.events.emit(AuthEvent.SIGN_OUT_STARTED, null);\n };\n\n // Create callbacks for refresh events\n const refreshEventCallbacks: RefreshEventCallbacks = {\n onRefreshStarted: () => {\n this.logger.info(\"Auto token refresh started\");\n this.events.emit(AuthEvent.TOKEN_REFRESH_STARTED, null);\n },\n onRefreshComplete: () => {\n this.logger.info(\"Auto token refresh completed\");\n this.events.emit(AuthEvent.TOKEN_REFRESH_COMPLETE, null);\n },\n onRefreshError: (error: Error) => {\n this.logger.error(\"Auto token refresh failed:\", error);\n this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);\n },\n };\n\n this.refresher = await BrowserAuthenticationRefresher.build(\n authConfig,\n this.storage,\n onError,\n undefined, // endpointOverrides\n refreshEventCallbacks,\n );\n\n this.logger.info(\"TokenRefresher initialized\");\n } catch (error) {\n this.logger.error(\"Failed to initialize TokenRefresher:\", error);\n this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);\n }\n }\n\n /**\n * Set authentication state and manage auto-refresh accordingly\n */\n setAuthenticationState(isAuthenticated: boolean): void {\n if (this.isDestroyed) return;\n\n this.isAuthenticated = isAuthenticated;\n\n if (isAuthenticated && this.refresher) {\n // Fire and forget the async call - we don't want to make setAuthenticationState async\n // as it would break the interface\n this.startAutoRefresh().catch((error) => {\n this.logger.error(\"Error starting auto refresh:\", error);\n });\n } else {\n this.stopAutoRefresh();\n }\n }\n\n /**\n * Manually refresh tokens\n */\n async refreshTokens(): Promise<void> {\n if (this.isDestroyed || !this.refresher) {\n const errorMsg = `TokenRefresher not initialized or destroyed. isDestroyed: ${this.isDestroyed}, hasRefresher: ${!!this.refresher}`;\n this.logger.error(errorMsg);\n throw new Error(errorMsg);\n }\n\n try {\n this.events.emit(AuthEvent.TOKEN_REFRESH_STARTED, null);\n\n this.logger.info(\"Starting manual token refresh\");\n\n await this.refresher.refreshTokens();\n\n this.events.emit(AuthEvent.TOKEN_REFRESH_COMPLETE, null);\n this.logger.info(\"Manual token refresh completed\");\n } catch (error) {\n this.logger.error(\"Manual token refresh failed:\", error);\n this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);\n throw error;\n }\n }\n\n /**\n * Start automatic token refresh\n */\n private async startAutoRefresh(): Promise<void> {\n if (this.refresher && this.isAuthenticated) {\n this.logger.info(\"Starting automatic token refresh\");\n\n try {\n // Calculate when the next refresh will happen (same logic as BrowserAuthenticationRefresher)\n const now = Math.floor(Date.now() / 1000);\n const expiresAt =\n (await retrieveAccessTokenExpiresAt(this.storage)) || now + 60;\n const bufferTime = 30; // 30 seconds buffer\n const refreshTime = Math.max(0, expiresAt - bufferTime - now);\n\n const nextRefreshDate = new Date((now + refreshTime) * 1000);\n this.logger.info(\n `Next token refresh scheduled for: ${nextRefreshDate.toISOString()} (in ${refreshTime} seconds)`,\n );\n } catch (error) {\n this.logger.warn(\"Could not calculate next refresh time:\", error);\n }\n\n this.refresher.setupAutorefresh();\n }\n }\n\n /**\n * Stop automatic token refresh\n */\n private stopAutoRefresh(): void {\n if (this.refresher) {\n this.logger.info(\"Stopping automatic token refresh\");\n this.refresher.clearAutorefresh();\n }\n }\n\n /**\n * Clean up resources\n */\n async cleanup(): Promise<void> {\n this.logger.info(\"Cleaning up TokenRefresher\");\n\n if (this.refresher) {\n this.refresher.clearAutorefresh();\n this.refresher = undefined;\n }\n\n this.isAuthenticated = false;\n }\n\n /**\n * Destroy the token refresher permanently\n */\n async destroy(): Promise<void> {\n this.isDestroyed = true;\n await this.cleanup();\n this.logger.info(\"TokenRefresher destroyed\");\n }\n\n /**\n * Get current refresh state\n */\n getState(): {\n isInitialized: boolean;\n isAuthenticated: boolean;\n isAutoRefreshActive: boolean;\n } {\n return {\n isInitialized: !!this.refresher,\n isAuthenticated: this.isAuthenticated,\n isAutoRefreshActive: this.isAuthenticated && !!this.refresher,\n };\n }\n}\n"]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export interface IframeConfig {
|
|
2
|
+
container: HTMLElement;
|
|
3
|
+
displayMode: "embedded" | "modal";
|
|
4
|
+
width?: string;
|
|
5
|
+
height?: string;
|
|
6
|
+
iframeId?: string;
|
|
7
|
+
onClose?: () => void;
|
|
8
|
+
}
|
|
9
|
+
export declare class IframeManager {
|
|
10
|
+
private static readonly MODAL_Z_INDEX;
|
|
11
|
+
private static readonly MODAL_WIDTH;
|
|
12
|
+
private static readonly MODAL_BACKDROP_COLOR;
|
|
13
|
+
private static readonly MODAL_BACKDROP_BLUR;
|
|
14
|
+
private static readonly BORDER_RADIUS;
|
|
15
|
+
private static readonly TRANSITION_DURATION;
|
|
16
|
+
private static readonly MODAL_MIN_HEIGHT;
|
|
17
|
+
private static readonly EMBEDDED_MIN_HEIGHT;
|
|
18
|
+
private static readonly IFRAME_READY_DELAY;
|
|
19
|
+
private iframe;
|
|
20
|
+
private container;
|
|
21
|
+
private resizer;
|
|
22
|
+
private displayMode;
|
|
23
|
+
private keydownHandler?;
|
|
24
|
+
private clickHandler?;
|
|
25
|
+
private iframeId;
|
|
26
|
+
private onClose?;
|
|
27
|
+
private shimmerLoader;
|
|
28
|
+
private closeButton;
|
|
29
|
+
private isIframeLoaded;
|
|
30
|
+
private iframeReadyMessageListener?;
|
|
31
|
+
private logger;
|
|
32
|
+
constructor(config: IframeConfig);
|
|
33
|
+
private initializeContainer;
|
|
34
|
+
/**
|
|
35
|
+
* Applies modal backdrop styles to create a full-screen overlay
|
|
36
|
+
* Uses !important to override any existing styles
|
|
37
|
+
*/
|
|
38
|
+
private applyModalStyles;
|
|
39
|
+
private setupKeyboardHandlers;
|
|
40
|
+
createIframe(url: string): HTMLIFrameElement;
|
|
41
|
+
/**
|
|
42
|
+
* Applies base styles to the iframe element
|
|
43
|
+
*/
|
|
44
|
+
private applyIframeStyles;
|
|
45
|
+
/**
|
|
46
|
+
* Sets iframe attributes to prevent scrollbars
|
|
47
|
+
*/
|
|
48
|
+
private setIframeAttributes;
|
|
49
|
+
/**
|
|
50
|
+
* Adds CSS styles to hide scrollbars across different browsers
|
|
51
|
+
*/
|
|
52
|
+
private addScrollbarHidingStyles;
|
|
53
|
+
/**
|
|
54
|
+
* Sets up the message listener for iframe ready events
|
|
55
|
+
*/
|
|
56
|
+
private setupIframeMessageListener;
|
|
57
|
+
/**
|
|
58
|
+
* Sets up the iframe onload handler with CSS injection
|
|
59
|
+
*/
|
|
60
|
+
private setupIframeOnloadHandler;
|
|
61
|
+
/**
|
|
62
|
+
* Sets up the iframe for modal display mode
|
|
63
|
+
*/
|
|
64
|
+
private setupModalIframe;
|
|
65
|
+
/**
|
|
66
|
+
* Sets up the iframe for embedded display mode
|
|
67
|
+
*/
|
|
68
|
+
private setupEmbeddedIframe;
|
|
69
|
+
private showShimmerLoader;
|
|
70
|
+
private hideShimmerLoader;
|
|
71
|
+
private markIframeAsLoaded;
|
|
72
|
+
private updateWrapperForLoadedContent;
|
|
73
|
+
hide(): void;
|
|
74
|
+
private cleanupIframeOnly;
|
|
75
|
+
cleanup(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Resets all modal-specific styles by removing CSS properties that were set with !important
|
|
78
|
+
*/
|
|
79
|
+
private resetModalStyles;
|
|
80
|
+
resize(): void;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=IframeManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IframeManager.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/iframe/IframeManager.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,UAAU,GAAG,OAAO,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,qBAAa,aAAa;IAExB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAU;IAC/C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAW;IAC9C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAA2B;IACvE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAe;IAC1D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAU;IAC/C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAW;IACtD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAW;IACtD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IAEjD,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAC,CAAiC;IACxD,OAAO,CAAC,YAAY,CAAC,CAA8B;IACnD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAC,CAAa;IAC7B,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,0BAA0B,CAAC,CAAgC;IACnE,OAAO,CAAC,MAAM,CAAkC;gBAEpC,MAAM,EAAE,YAAY;IAUhC,OAAO,CAAC,mBAAmB;IAgB3B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA4BxB,OAAO,CAAC,qBAAqB;IAWtB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB;IAoCnD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+BzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAehC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA0BlC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA+ChC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAwDxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,6BAA6B;IA2B9B,IAAI,IAAI,IAAI;IAgBnB,OAAO,CAAC,iBAAiB;IAiClB,OAAO,IAAI,IAAI;IAkDtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA2BjB,MAAM,IAAI,IAAI;CAKtB"}
|