@civic/auth 0.6.0 → 0.6.1-beta.2

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.
Files changed (127) hide show
  1. package/dist/nextjs/config.d.ts.map +1 -1
  2. package/dist/nextjs/config.js +3 -1
  3. package/dist/nextjs/config.js.map +1 -1
  4. package/dist/nextjs/hooks/useUserCookie.d.ts.map +1 -1
  5. package/dist/nextjs/hooks/useUserCookie.js.map +1 -1
  6. package/dist/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  7. package/dist/nextjs/providers/NextAuthProvider.js +1 -0
  8. package/dist/nextjs/providers/NextAuthProvider.js.map +1 -1
  9. package/dist/shared/components/CivicAuthIframeContainer.js +1 -1
  10. package/dist/shared/components/CivicAuthIframeContainer.js.map +1 -1
  11. package/dist/shared/hooks/useSignIn.d.ts +9 -4
  12. package/dist/shared/hooks/useSignIn.d.ts.map +1 -1
  13. package/dist/shared/hooks/useSignIn.js +75 -42
  14. package/dist/shared/hooks/useSignIn.js.map +1 -1
  15. package/dist/shared/lib/BrowserAuthenticationRefresher.d.ts +7 -1
  16. package/dist/shared/lib/BrowserAuthenticationRefresher.d.ts.map +1 -1
  17. package/dist/shared/lib/BrowserAuthenticationRefresher.js +15 -2
  18. package/dist/shared/lib/BrowserAuthenticationRefresher.js.map +1 -1
  19. package/dist/shared/lib/util.d.ts +1 -1
  20. package/dist/shared/lib/util.d.ts.map +1 -1
  21. package/dist/shared/lib/util.js +6 -1
  22. package/dist/shared/lib/util.js.map +1 -1
  23. package/dist/shared/providers/AuthContext.d.ts +7 -2
  24. package/dist/shared/providers/AuthContext.d.ts.map +1 -1
  25. package/dist/shared/providers/AuthContext.js.map +1 -1
  26. package/dist/shared/providers/UserProvider.d.ts +5 -1
  27. package/dist/shared/providers/UserProvider.d.ts.map +1 -1
  28. package/dist/shared/providers/UserProvider.js.map +1 -1
  29. package/dist/shared/version.d.ts +1 -1
  30. package/dist/shared/version.d.ts.map +1 -1
  31. package/dist/shared/version.js +1 -1
  32. package/dist/shared/version.js.map +1 -1
  33. package/dist/vanillajs/auth/AuthenticationEvents.d.ts.map +1 -1
  34. package/dist/vanillajs/auth/AuthenticationEvents.js +2 -2
  35. package/dist/vanillajs/auth/AuthenticationEvents.js.map +1 -1
  36. package/dist/vanillajs/auth/CivicAuth.d.ts +111 -92
  37. package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
  38. package/dist/vanillajs/auth/CivicAuth.js +474 -321
  39. package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
  40. package/dist/vanillajs/auth/SessionManager.d.ts +40 -9
  41. package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
  42. package/dist/vanillajs/auth/SessionManager.js +96 -61
  43. package/dist/vanillajs/auth/SessionManager.js.map +1 -1
  44. package/dist/vanillajs/auth/TokenRefresher.d.ts +54 -0
  45. package/dist/vanillajs/auth/TokenRefresher.d.ts.map +1 -0
  46. package/dist/vanillajs/auth/TokenRefresher.js +166 -0
  47. package/dist/vanillajs/auth/TokenRefresher.js.map +1 -0
  48. package/dist/vanillajs/auth/config/ConfigProcessor.d.ts +6 -0
  49. package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -0
  50. package/dist/vanillajs/auth/config/ConfigProcessor.js +59 -0
  51. package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -0
  52. package/dist/vanillajs/auth/handlers/IframeAuthHandler.d.ts +40 -0
  53. package/dist/vanillajs/auth/handlers/IframeAuthHandler.d.ts.map +1 -0
  54. package/dist/vanillajs/auth/handlers/IframeAuthHandler.js +388 -0
  55. package/dist/vanillajs/auth/handlers/IframeAuthHandler.js.map +1 -0
  56. package/dist/vanillajs/auth/handlers/MessageHandler.d.ts +170 -0
  57. package/dist/vanillajs/auth/handlers/MessageHandler.d.ts.map +1 -0
  58. package/dist/vanillajs/auth/handlers/MessageHandler.js +367 -0
  59. package/dist/vanillajs/auth/handlers/MessageHandler.js.map +1 -0
  60. package/dist/vanillajs/auth/handlers/OAuthCallbackHandler.d.ts +90 -0
  61. package/dist/vanillajs/auth/handlers/OAuthCallbackHandler.d.ts.map +1 -0
  62. package/dist/vanillajs/auth/handlers/OAuthCallbackHandler.js +301 -0
  63. package/dist/vanillajs/auth/handlers/OAuthCallbackHandler.js.map +1 -0
  64. package/dist/vanillajs/auth/handlers/PopupHandler.d.ts +108 -0
  65. package/dist/vanillajs/auth/handlers/PopupHandler.d.ts.map +1 -0
  66. package/dist/vanillajs/auth/handlers/PopupHandler.js +333 -0
  67. package/dist/vanillajs/auth/handlers/PopupHandler.js.map +1 -0
  68. package/dist/vanillajs/auth/types/AuthTypes.d.ts +128 -0
  69. package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -0
  70. package/dist/vanillajs/auth/types/AuthTypes.js +40 -0
  71. package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -0
  72. package/dist/vanillajs/iframe/IframeManager.d.ts +115 -0
  73. package/dist/vanillajs/iframe/IframeManager.d.ts.map +1 -0
  74. package/dist/vanillajs/iframe/IframeManager.js +614 -0
  75. package/dist/vanillajs/iframe/IframeManager.js.map +1 -0
  76. package/dist/vanillajs/iframe/IframeResizer.d.ts +15 -0
  77. package/dist/vanillajs/iframe/IframeResizer.d.ts.map +1 -0
  78. package/dist/vanillajs/iframe/IframeResizer.js +127 -0
  79. package/dist/vanillajs/iframe/IframeResizer.js.map +1 -0
  80. package/dist/vanillajs/index.d.ts +8 -7
  81. package/dist/vanillajs/index.d.ts.map +1 -1
  82. package/dist/vanillajs/index.js +10 -7
  83. package/dist/vanillajs/index.js.map +1 -1
  84. package/dist/vanillajs/services/ApiService.d.ts.map +1 -1
  85. package/dist/vanillajs/services/ApiService.js +2 -2
  86. package/dist/vanillajs/services/ApiService.js.map +1 -1
  87. package/dist/vanillajs/types/index.d.ts +17 -12
  88. package/dist/vanillajs/types/index.d.ts.map +1 -1
  89. package/dist/vanillajs/types/index.js +15 -10
  90. package/dist/vanillajs/types/index.js.map +1 -1
  91. package/dist/vanillajs/ui/LoadingComponents.d.ts +51 -0
  92. package/dist/vanillajs/ui/LoadingComponents.d.ts.map +1 -0
  93. package/dist/vanillajs/ui/LoadingComponents.js +363 -0
  94. package/dist/vanillajs/ui/LoadingComponents.js.map +1 -0
  95. package/dist/vanillajs/utils/auth-utils.d.ts +2 -1
  96. package/dist/vanillajs/utils/auth-utils.d.ts.map +1 -1
  97. package/dist/vanillajs/utils/auth-utils.js +6 -3
  98. package/dist/vanillajs/utils/auth-utils.js.map +1 -1
  99. package/dist/vanillajs/utils/logger.d.ts +16 -15
  100. package/dist/vanillajs/utils/logger.d.ts.map +1 -1
  101. package/dist/vanillajs/utils/logger.js +35 -19
  102. package/dist/vanillajs/utils/logger.js.map +1 -1
  103. package/package.json +1 -1
  104. package/dist/vanillajs/iframe/domUtils.d.ts +0 -4
  105. package/dist/vanillajs/iframe/domUtils.d.ts.map +0 -1
  106. package/dist/vanillajs/iframe/domUtils.js +0 -25
  107. package/dist/vanillajs/iframe/domUtils.js.map +0 -1
  108. package/dist/vanillajs/storage/BrowserCookieStorageAdapter.d.ts +0 -19
  109. package/dist/vanillajs/storage/BrowserCookieStorageAdapter.d.ts.map +0 -1
  110. package/dist/vanillajs/storage/BrowserCookieStorageAdapter.js +0 -101
  111. package/dist/vanillajs/storage/BrowserCookieStorageAdapter.js.map +0 -1
  112. package/dist/vanillajs/storage/BrowserLocalStorageAdapter.d.ts +0 -9
  113. package/dist/vanillajs/storage/BrowserLocalStorageAdapter.d.ts.map +0 -1
  114. package/dist/vanillajs/storage/BrowserLocalStorageAdapter.js +0 -36
  115. package/dist/vanillajs/storage/BrowserLocalStorageAdapter.js.map +0 -1
  116. package/dist/vanillajs/storage/InMemoryStorageAdapter.d.ts +0 -9
  117. package/dist/vanillajs/storage/InMemoryStorageAdapter.d.ts.map +0 -1
  118. package/dist/vanillajs/storage/InMemoryStorageAdapter.js +0 -16
  119. package/dist/vanillajs/storage/InMemoryStorageAdapter.js.map +0 -1
  120. package/dist/vanillajs/storage/StorageAdapter.d.ts +0 -15
  121. package/dist/vanillajs/storage/StorageAdapter.d.ts.map +0 -1
  122. package/dist/vanillajs/storage/StorageAdapter.js +0 -16
  123. package/dist/vanillajs/storage/StorageAdapter.js.map +0 -1
  124. package/dist/vanillajs/utils/page-handlers.d.ts +0 -29
  125. package/dist/vanillajs/utils/page-handlers.d.ts.map +0 -1
  126. package/dist/vanillajs/utils/page-handlers.js +0 -165
  127. package/dist/vanillajs/utils/page-handlers.js.map +0 -1
@@ -0,0 +1,614 @@
1
+ import { CivicIframeResizer } from "./IframeResizer.js";
2
+ import { createIframeShimmerLoader, createCloseButton, } from "../ui/LoadingComponents.js";
3
+ import { createLogger } from "../utils/logger.js";
4
+ /**
5
+ * IframeManager - Manages iframe visual presentation and DOM lifecycle
6
+ * Handles styling, positioning, UI components, and iframe element creation/cleanup
7
+ */
8
+ export class IframeManager {
9
+ // Constants for styling and configuration
10
+ static MODAL_Z_INDEX = "1050";
11
+ static MODAL_WIDTH = "20rem"; // 320px
12
+ static MODAL_BACKDROP_COLOR = "rgba(17, 24, 39, 0.5)";
13
+ static MODAL_BACKDROP_BLUR = "blur(4px)";
14
+ static BORDER_RADIUS = "24px";
15
+ static TRANSITION_DURATION = "250ms";
16
+ static MODAL_MIN_HEIGHT = "26px";
17
+ static EMBEDDED_MIN_HEIGHT = "225px";
18
+ static IFRAME_READY_DELAY = 100; // ms
19
+ iframe = null;
20
+ container;
21
+ resizer = null;
22
+ displayMode;
23
+ keydownHandler;
24
+ clickHandler;
25
+ iframeId;
26
+ onClose;
27
+ shimmerLoader = null;
28
+ closeButton = null;
29
+ isIframeLoaded = false;
30
+ iframeReadyMessageListener;
31
+ logger;
32
+ // Store references to wrapper elements for styling control
33
+ contentWrapper = null;
34
+ iframeWrapper = null;
35
+ constructor(config) {
36
+ this.container = config.container;
37
+ this.displayMode = config.displayMode;
38
+ this.iframeId = config.iframeId || "civic-auth-iframe";
39
+ this.onClose = config.onClose;
40
+ this.logger = createLogger("iframe");
41
+ this.initializeContainer(config);
42
+ this.setupKeyboardHandlers();
43
+ }
44
+ initializeContainer(config) {
45
+ if (this.displayMode === "modal") {
46
+ this.applyModalStyles();
47
+ return;
48
+ }
49
+ // Embedded mode
50
+ this.container.style.position = "relative";
51
+ this.container.style.width = config.width || "auto";
52
+ this.container.style.height = config.height || "auto";
53
+ this.container.style.backgroundColor = "white";
54
+ this.container.style.borderRadius = IframeManager.BORDER_RADIUS;
55
+ this.container.style.overflow = "hidden";
56
+ this.container.style.transition = "all 0.5s ease-in-out";
57
+ }
58
+ /**
59
+ * Applies modal backdrop styles to create a full-screen overlay
60
+ * Uses !important to override any existing styles
61
+ */
62
+ applyModalStyles() {
63
+ const modalStyles = {
64
+ position: "fixed",
65
+ left: "0",
66
+ top: "0",
67
+ width: "100vw",
68
+ height: "100vh",
69
+ "z-index": IframeManager.MODAL_Z_INDEX,
70
+ display: "flex",
71
+ "align-items": "center",
72
+ "justify-content": "center",
73
+ "background-color": IframeManager.MODAL_BACKDROP_COLOR,
74
+ "backdrop-filter": IframeManager.MODAL_BACKDROP_BLUR,
75
+ opacity: "1",
76
+ transition: `opacity ${IframeManager.TRANSITION_DURATION} ease`,
77
+ // Reset any conflicting styles that might prevent modal from working
78
+ margin: "0",
79
+ padding: "0",
80
+ border: "none",
81
+ "border-radius": "0",
82
+ "min-height": "100vh",
83
+ };
84
+ Object.entries(modalStyles).forEach(([property, value]) => {
85
+ this.container.style.setProperty(property, value, "important");
86
+ });
87
+ }
88
+ setupKeyboardHandlers() {
89
+ if (this.displayMode === "modal") {
90
+ this.keydownHandler = (event) => {
91
+ if (event.key === "Escape") {
92
+ this.onClose?.();
93
+ }
94
+ };
95
+ window.addEventListener("keydown", this.keydownHandler);
96
+ }
97
+ }
98
+ createIframe(url) {
99
+ // Clean up any existing iframe content, but preserve container styles for modal mode
100
+ this.cleanupIframeOnly();
101
+ // Create new iframe
102
+ this.iframe = document.createElement("iframe");
103
+ this.iframe.id = this.iframeId;
104
+ this.iframe.src = url;
105
+ this.iframe.setAttribute("data-testid", "civic-auth-iframe-with-resizer");
106
+ // Apply iframe styles
107
+ this.applyIframeStyles();
108
+ // Add attributes that prevent scrollbars
109
+ this.setIframeAttributes();
110
+ // Add CSS to prevent scrollbars
111
+ this.addScrollbarHidingStyles();
112
+ // Set up message listener for iframe ready events (more reliable than onload)
113
+ this.setupIframeMessageListener();
114
+ // Set up iframe onload handler
115
+ this.setupIframeOnloadHandler();
116
+ if (this.displayMode === "modal") {
117
+ this.setupModalIframe();
118
+ }
119
+ else {
120
+ this.setupEmbeddedIframe();
121
+ }
122
+ // Initialize resizer - this will handle all the message-based resizing
123
+ this.resizer = new CivicIframeResizer(this.iframe, this.container);
124
+ return this.iframe;
125
+ }
126
+ /**
127
+ * Applies base styles to the iframe element
128
+ */
129
+ applyIframeStyles() {
130
+ if (!this.iframe)
131
+ return;
132
+ const baseStyles = {
133
+ border: "none",
134
+ display: "block",
135
+ pointerEvents: "auto",
136
+ width: "100%",
137
+ minWidth: "100%",
138
+ overflow: "hidden",
139
+ overflowX: "hidden",
140
+ overflowY: "hidden",
141
+ opacity: "0",
142
+ transition: `opacity ${IframeManager.TRANSITION_DURATION} ease, height ${IframeManager.TRANSITION_DURATION} ease`,
143
+ };
144
+ Object.entries(baseStyles).forEach(([property, value]) => {
145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required to handle dynamic CSS property assignment since CSSStyleDeclaration type doesn't fully capture all possible properties
146
+ this.iframe.style[property] = value;
147
+ });
148
+ // Set initial height based on display mode
149
+ if (this.displayMode === "modal") {
150
+ this.iframe.style.height = IframeManager.MODAL_MIN_HEIGHT;
151
+ this.iframe.style.minHeight = IframeManager.MODAL_MIN_HEIGHT;
152
+ }
153
+ else {
154
+ this.iframe.style.height = "auto";
155
+ this.iframe.style.minHeight = IframeManager.EMBEDDED_MIN_HEIGHT; // Embedded mode minimum
156
+ }
157
+ }
158
+ /**
159
+ * Sets iframe attributes to prevent scrollbars
160
+ */
161
+ setIframeAttributes() {
162
+ if (!this.iframe)
163
+ return;
164
+ this.iframe.setAttribute("scrolling", "no");
165
+ this.iframe.setAttribute("frameborder", "0");
166
+ this.iframe.setAttribute("seamless", "seamless");
167
+ // Add additional CSS to prevent scrollbars
168
+ this.iframe.style.cssText +=
169
+ "; -ms-overflow-style: none; scrollbar-width: none;";
170
+ }
171
+ /**
172
+ * Adds CSS styles to hide scrollbars across different browsers
173
+ */
174
+ addScrollbarHidingStyles() {
175
+ const iframeStyle = document.createElement("style");
176
+ iframeStyle.textContent = `
177
+ iframe[id="${this.iframeId}"] {
178
+ -webkit-overflow-scrolling: touch !important;
179
+ }
180
+ iframe[id="${this.iframeId}"]::webkit-scrollbar {
181
+ display: none !important;
182
+ width: 0 !important;
183
+ height: 0 !important;
184
+ }
185
+ `;
186
+ document.head.appendChild(iframeStyle);
187
+ }
188
+ /**
189
+ * Sets up the message listener for iframe ready events
190
+ */
191
+ setupIframeMessageListener() {
192
+ this.iframeReadyMessageListener = (event) => {
193
+ try {
194
+ // Only handle messages from our iframe
195
+ if (!this.iframe?.contentWindow ||
196
+ event.source !== this.iframe.contentWindow) {
197
+ return;
198
+ }
199
+ const message = event.data;
200
+ // Handle ready message from iframe resizer
201
+ if (message.type === "civic-iframe-ready") {
202
+ this.logger.debug("Iframe content is ready - hiding shimmer loader");
203
+ this.markIframeAsLoaded();
204
+ }
205
+ }
206
+ catch (error) {
207
+ this.logger.debug("Error processing iframe ready message:", error);
208
+ }
209
+ };
210
+ window.addEventListener("message", this.iframeReadyMessageListener);
211
+ }
212
+ /**
213
+ * Sets up the iframe onload handler with CSS injection
214
+ */
215
+ setupIframeOnloadHandler() {
216
+ if (!this.iframe)
217
+ return;
218
+ this.iframe.onload = () => {
219
+ // Use a small delay to allow ready message to arrive first
220
+ setTimeout(() => {
221
+ if (!this.isIframeLoaded) {
222
+ this.logger.debug("Iframe onload fired - hiding shimmer loader (fallback)");
223
+ this.markIframeAsLoaded();
224
+ }
225
+ }, IframeManager.IFRAME_READY_DELAY);
226
+ try {
227
+ const iframeDoc = this.iframe?.contentDocument || this.iframe?.contentWindow?.document;
228
+ if (iframeDoc && iframeDoc.head) {
229
+ const style = iframeDoc.createElement("style");
230
+ style.textContent = `
231
+ html, body {
232
+ overflow: hidden !important;
233
+ overflow-x: hidden !important;
234
+ overflow-y: hidden !important;
235
+ -ms-overflow-style: none !important;
236
+ scrollbar-width: none !important;
237
+ margin: 0 !important;
238
+ padding: 0 !important;
239
+ }
240
+ body::-webkit-scrollbar {
241
+ display: none !important;
242
+ }
243
+ * {
244
+ box-sizing: border-box !important;
245
+ }
246
+ `;
247
+ iframeDoc.head.appendChild(style);
248
+ }
249
+ }
250
+ catch (error) {
251
+ this.logger.debug("Could not inject CSS into iframe (likely cross-origin):", error);
252
+ }
253
+ };
254
+ }
255
+ /**
256
+ * Sets up the iframe for modal display mode
257
+ */
258
+ setupModalIframe() {
259
+ if (!this.iframe)
260
+ return;
261
+ // Ensure modal is visible (in case it was hidden by cleanup)
262
+ this.container.style.setProperty("display", "flex", "important");
263
+ // Create content wrapper for modal
264
+ this.contentWrapper = document.createElement("div");
265
+ this.contentWrapper.style.position = "relative";
266
+ this.contentWrapper.style.overflow = "hidden";
267
+ this.contentWrapper.style.width = IframeManager.MODAL_WIDTH; // 320px like React version
268
+ // Apply initial visual styling
269
+ this.applyModalVisualStyling();
270
+ // Stop propagation on content wrapper to prevent backdrop clicks
271
+ this.contentWrapper.addEventListener("click", (e) => {
272
+ e.stopPropagation();
273
+ });
274
+ // Create inner iframe wrapper to match React structure
275
+ this.iframeWrapper = document.createElement("div");
276
+ this.iframeWrapper.style.position = "relative";
277
+ this.iframeWrapper.style.overflow = "hidden";
278
+ this.iframeWrapper.style.overflowX = "hidden";
279
+ this.iframeWrapper.style.overflowY = "hidden";
280
+ this.iframeWrapper.style.transition = `all ${IframeManager.TRANSITION_DURATION} ease`;
281
+ this.iframeWrapper.style.width = "100%";
282
+ this.iframeWrapper.style.height = "auto";
283
+ this.iframeWrapper.style.minHeight = IframeManager.MODAL_MIN_HEIGHT; // Start small for modal mode
284
+ // Apply initial wrapper styling
285
+ this.applyIframeWrapperStyling();
286
+ // Add shimmer loader for modal mode
287
+ this.showShimmerLoader(this.iframeWrapper, "white");
288
+ // Add close button for modal mode (initially hidden)
289
+ if (this.onClose) {
290
+ this.closeButton = createCloseButton(this.onClose);
291
+ this.contentWrapper.appendChild(this.closeButton);
292
+ }
293
+ // Add iframe to wrapper, then wrapper to content, then content to container
294
+ this.iframeWrapper.appendChild(this.iframe);
295
+ this.contentWrapper.appendChild(this.iframeWrapper);
296
+ this.container.appendChild(this.contentWrapper);
297
+ // Add click-to-close functionality after content is added
298
+ this.clickHandler = (e) => {
299
+ if (e.target === this.container) {
300
+ // Only close if clicking the backdrop, not the iframe content
301
+ this.onClose?.();
302
+ }
303
+ };
304
+ this.container.addEventListener("click", this.clickHandler);
305
+ }
306
+ /**
307
+ * Sets up the iframe for embedded display mode
308
+ */
309
+ setupEmbeddedIframe() {
310
+ if (!this.iframe)
311
+ return;
312
+ // Embedded mode - create wrapper with border radius and overflow hidden
313
+ this.iframeWrapper = document.createElement("div");
314
+ this.iframeWrapper.style.position = "relative";
315
+ this.iframeWrapper.style.overflow = "hidden";
316
+ this.iframeWrapper.style.overflowX = "hidden";
317
+ this.iframeWrapper.style.overflowY = "hidden";
318
+ this.iframeWrapper.style.transition = "all 0.5s ease-in-out";
319
+ this.iframeWrapper.style.width = "100%";
320
+ this.iframeWrapper.style.height = "auto";
321
+ this.iframeWrapper.style.minHeight = IframeManager.EMBEDDED_MIN_HEIGHT; // Embedded mode minimum
322
+ // Apply initial wrapper styling
323
+ this.applyIframeWrapperStyling();
324
+ // Add shimmer loader for embedded mode with max width
325
+ this.showShimmerLoader(this.iframeWrapper, "white", IframeManager.MODAL_WIDTH);
326
+ // Add iframe to wrapper, then wrapper to container
327
+ this.iframeWrapper.appendChild(this.iframe);
328
+ this.container.appendChild(this.iframeWrapper);
329
+ }
330
+ showShimmerLoader(parentElement, backgroundColor = "white", maxWidth) {
331
+ if (!this.isIframeLoaded && !this.shimmerLoader) {
332
+ this.shimmerLoader = createIframeShimmerLoader(backgroundColor, maxWidth);
333
+ parentElement.appendChild(this.shimmerLoader);
334
+ }
335
+ }
336
+ hideShimmerLoader() {
337
+ if (this.shimmerLoader && this.shimmerLoader.parentNode) {
338
+ // Add fade-out transition before removing
339
+ this.shimmerLoader.style.opacity = "0";
340
+ this.shimmerLoader.style.transition = `opacity ${IframeManager.TRANSITION_DURATION} ease`;
341
+ // Remove after transition completes
342
+ setTimeout(() => {
343
+ if (this.shimmerLoader && this.shimmerLoader.parentNode) {
344
+ this.shimmerLoader.parentNode.removeChild(this.shimmerLoader);
345
+ this.shimmerLoader = null;
346
+ }
347
+ }, parseInt(IframeManager.TRANSITION_DURATION));
348
+ }
349
+ }
350
+ markIframeAsLoaded() {
351
+ if (!this.isIframeLoaded) {
352
+ this.isIframeLoaded = true;
353
+ this.hideShimmerLoader();
354
+ this.updateWrapperForLoadedContent();
355
+ }
356
+ }
357
+ updateWrapperForLoadedContent() {
358
+ // Fade in the iframe
359
+ if (this.iframe) {
360
+ this.iframe.style.opacity = "1";
361
+ }
362
+ // Show close button for modal mode when content is loaded
363
+ if (this.displayMode === "modal" && this.closeButton) {
364
+ this.closeButton.style.opacity = "1";
365
+ }
366
+ // Find the iframe wrapper and update its styles for loaded content
367
+ const iframeWrapper = this.iframe?.parentElement;
368
+ if (iframeWrapper) {
369
+ // Remove minimum height constraints to allow natural sizing
370
+ if (this.displayMode === "modal") {
371
+ iframeWrapper.style.minHeight = "auto";
372
+ }
373
+ else {
374
+ // For embedded mode, keep some minimum but allow natural growth
375
+ iframeWrapper.style.minHeight = "auto";
376
+ }
377
+ // Add border radius transition for loaded state (matching React implementation)
378
+ iframeWrapper.style.borderRadius = IframeManager.BORDER_RADIUS;
379
+ }
380
+ }
381
+ hide() {
382
+ if (this.displayMode === "modal") {
383
+ // Add fade-out transition for modal backdrop
384
+ this.container.style.opacity = "0";
385
+ this.container.style.transition = `opacity ${IframeManager.TRANSITION_DURATION} ease`;
386
+ // Hide after transition completes
387
+ setTimeout(() => {
388
+ this.container.style.display = "none";
389
+ }, parseInt(IframeManager.TRANSITION_DURATION));
390
+ }
391
+ else {
392
+ // For embedded mode, just hide immediately
393
+ this.container.style.display = "none";
394
+ }
395
+ }
396
+ cleanupIframeOnly() {
397
+ if (this.resizer) {
398
+ this.resizer.cleanup();
399
+ this.resizer = null;
400
+ }
401
+ // Clean up shimmer loader
402
+ this.hideShimmerLoader();
403
+ // Clean up close button
404
+ if (this.closeButton && this.closeButton.parentNode) {
405
+ this.closeButton.parentNode.removeChild(this.closeButton);
406
+ this.closeButton = null;
407
+ }
408
+ // Clean up message listener
409
+ if (this.iframeReadyMessageListener) {
410
+ window.removeEventListener("message", this.iframeReadyMessageListener);
411
+ this.iframeReadyMessageListener = undefined;
412
+ }
413
+ if (this.iframe && this.iframe.parentNode) {
414
+ this.iframe.parentNode.removeChild(this.iframe);
415
+ this.iframe = null;
416
+ }
417
+ // Reset loading state
418
+ this.isIframeLoaded = false;
419
+ // Clear wrapper references
420
+ this.contentWrapper = null;
421
+ this.iframeWrapper = null;
422
+ // Clear container content but DON'T reset styles for modal mode
423
+ this.container.innerHTML = "";
424
+ }
425
+ cleanup() {
426
+ if (this.resizer) {
427
+ this.resizer.cleanup();
428
+ this.resizer = null;
429
+ }
430
+ // Clean up shimmer loader
431
+ this.hideShimmerLoader();
432
+ // Clean up close button
433
+ if (this.closeButton && this.closeButton.parentNode) {
434
+ this.closeButton.parentNode.removeChild(this.closeButton);
435
+ this.closeButton = null;
436
+ }
437
+ // Clean up message listener
438
+ if (this.iframeReadyMessageListener) {
439
+ window.removeEventListener("message", this.iframeReadyMessageListener);
440
+ this.iframeReadyMessageListener = undefined;
441
+ }
442
+ if (this.iframe && this.iframe.parentNode) {
443
+ this.iframe.parentNode.removeChild(this.iframe);
444
+ this.iframe = null;
445
+ }
446
+ // Reset loading state
447
+ this.isIframeLoaded = false;
448
+ // Remove keyboard event listener
449
+ if (this.keydownHandler) {
450
+ window.removeEventListener("keydown", this.keydownHandler);
451
+ this.keydownHandler = undefined;
452
+ }
453
+ // Remove click event listener
454
+ if (this.clickHandler) {
455
+ this.container.removeEventListener("click", this.clickHandler);
456
+ this.clickHandler = undefined;
457
+ }
458
+ // Clear wrapper references
459
+ this.contentWrapper = null;
460
+ this.iframeWrapper = null;
461
+ // Clear container content and reset styles
462
+ this.container.innerHTML = "";
463
+ if (this.displayMode === "modal") {
464
+ // Reset all modal-specific styles to ensure clean state
465
+ this.resetModalStyles();
466
+ }
467
+ }
468
+ /**
469
+ * Resets all modal-specific styles by removing CSS properties that were set with !important
470
+ */
471
+ resetModalStyles() {
472
+ const modalStyleProperties = [
473
+ "position",
474
+ "left",
475
+ "top",
476
+ "width",
477
+ "height",
478
+ "z-index",
479
+ "display",
480
+ "align-items",
481
+ "justify-content",
482
+ "background-color",
483
+ "backdrop-filter",
484
+ "opacity",
485
+ "transition",
486
+ "margin",
487
+ "padding",
488
+ "border",
489
+ "border-radius",
490
+ "min-height",
491
+ ];
492
+ modalStyleProperties.forEach((property) => {
493
+ this.container.style.removeProperty(property);
494
+ });
495
+ }
496
+ resize() {
497
+ if (this.resizer) {
498
+ this.resizer.resize();
499
+ }
500
+ }
501
+ /**
502
+ * Force show the shimmer loader and hide iframe content
503
+ * Used when we want to mask non-login content
504
+ */
505
+ forceShowLoader() {
506
+ // Reset loading state to show shimmer
507
+ this.isIframeLoaded = false;
508
+ // Hide iframe content
509
+ if (this.iframe) {
510
+ this.iframe.style.opacity = "0";
511
+ }
512
+ // Hide close button
513
+ if (this.displayMode === "modal" && this.closeButton) {
514
+ this.closeButton.style.opacity = "0";
515
+ }
516
+ // Hide visual decorations (borders, shadows) when masking content
517
+ if (this.displayMode === "modal") {
518
+ this.removeModalVisualStyling();
519
+ }
520
+ this.removeIframeWrapperStyling();
521
+ // Show shimmer loader
522
+ if (this.iframeWrapper && !this.shimmerLoader) {
523
+ this.showShimmerLoader(this.iframeWrapper, "white", this.displayMode === "embedded" ? IframeManager.MODAL_WIDTH : undefined);
524
+ }
525
+ }
526
+ /**
527
+ * Force hide the shimmer loader and show iframe content
528
+ * Used when we want to show the login app
529
+ */
530
+ forceHideLoader() {
531
+ // Restore visual decorations when showing content
532
+ if (this.displayMode === "modal") {
533
+ this.applyModalVisualStyling();
534
+ }
535
+ this.applyIframeWrapperStyling();
536
+ this.markIframeAsLoaded();
537
+ }
538
+ /**
539
+ * Applies visual styling (borders, shadows) to modal content wrapper
540
+ */
541
+ applyModalVisualStyling() {
542
+ if (!this.contentWrapper)
543
+ return;
544
+ this.contentWrapper.style.borderRadius = IframeManager.BORDER_RADIUS;
545
+ this.contentWrapper.style.boxShadow =
546
+ "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)";
547
+ }
548
+ /**
549
+ * Removes visual styling (borders, shadows) from modal content wrapper
550
+ */
551
+ removeModalVisualStyling() {
552
+ if (!this.contentWrapper)
553
+ return;
554
+ this.contentWrapper.style.borderRadius = "0";
555
+ this.contentWrapper.style.boxShadow = "none";
556
+ }
557
+ /**
558
+ * Applies visual styling (borders) to iframe wrapper
559
+ */
560
+ applyIframeWrapperStyling() {
561
+ if (!this.iframeWrapper)
562
+ return;
563
+ this.iframeWrapper.style.borderRadius = IframeManager.BORDER_RADIUS;
564
+ }
565
+ /**
566
+ * Removes visual styling (borders) from iframe wrapper
567
+ */
568
+ removeIframeWrapperStyling() {
569
+ if (!this.iframeWrapper)
570
+ return;
571
+ this.iframeWrapper.style.borderRadius = "0";
572
+ }
573
+ showSubtlePopupFallbackIndicator() {
574
+ if (!this.iframeWrapper && !this.contentWrapper) {
575
+ this.logger.warn("Cannot show popup fallback indicator, no iframe wrapper or content wrapper found.");
576
+ return;
577
+ }
578
+ const targetElement = this.iframeWrapper || this.contentWrapper;
579
+ if (targetElement) {
580
+ this.logger.debug("Showing popup fallback overlay.");
581
+ // Create overlay element
582
+ const overlay = document.createElement("div");
583
+ overlay.id = "civic-popup-fallback-overlay";
584
+ overlay.style.cssText = `
585
+ position: absolute;
586
+ top: 0;
587
+ left: 0;
588
+ right: 0;
589
+ bottom: 0;
590
+ background: transparent;
591
+ display: flex;
592
+ flex-direction: column;
593
+ align-items: center;
594
+ justify-content: center;
595
+ z-index: 1000;
596
+ border-radius: ${IframeManager.BORDER_RADIUS};
597
+ backdrop-filter: blur(.4px);
598
+ opacity: 1;
599
+ `;
600
+ // Add overlay to target element
601
+ targetElement.style.position = "relative";
602
+ targetElement.appendChild(overlay);
603
+ // Remove overlay quickly
604
+ setTimeout(() => {
605
+ if (overlay.parentNode) {
606
+ overlay.parentNode.removeChild(overlay);
607
+ }
608
+ this.logger.debug("Popup fallback overlay removed.");
609
+ }, 500); // Remove after 500ms
610
+ this.logger.debug("Popup fallback overlay displayed.");
611
+ }
612
+ }
613
+ }
614
+ //# sourceMappingURL=IframeManager.js.map