@civic/auth 0.9.6-beta.1 → 0.9.6-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 (219) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/nextjs/actions.d.ts +12 -0
  3. package/dist/nextjs/actions.d.ts.map +1 -0
  4. package/dist/nextjs/actions.js +26 -0
  5. package/dist/nextjs/actions.js.map +1 -0
  6. package/dist/nextjs/config.d.ts +2 -0
  7. package/dist/nextjs/config.d.ts.map +1 -1
  8. package/dist/nextjs/config.js +3 -2
  9. package/dist/nextjs/config.js.map +1 -1
  10. package/dist/nextjs/cookies.d.ts.map +1 -1
  11. package/dist/nextjs/cookies.js +45 -3
  12. package/dist/nextjs/cookies.js.map +1 -1
  13. package/dist/nextjs/hooks/useInitialAuthConfig.d.ts +31 -0
  14. package/dist/nextjs/hooks/useInitialAuthConfig.d.ts.map +1 -0
  15. package/dist/nextjs/hooks/useInitialAuthConfig.js +109 -0
  16. package/dist/nextjs/hooks/useInitialAuthConfig.js.map +1 -0
  17. package/dist/nextjs/index.d.ts +1 -0
  18. package/dist/nextjs/index.d.ts.map +1 -1
  19. package/dist/nextjs/index.js +13 -3
  20. package/dist/nextjs/index.js.map +1 -1
  21. package/dist/nextjs/providers/NextAuthProvider.d.ts +6 -7
  22. package/dist/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  23. package/dist/nextjs/providers/NextAuthProvider.js +19 -138
  24. package/dist/nextjs/providers/NextAuthProvider.js.map +1 -1
  25. package/dist/nextjs/providers/NextAuthProviderClient.d.ts +11 -0
  26. package/dist/nextjs/providers/NextAuthProviderClient.d.ts.map +1 -0
  27. package/dist/nextjs/providers/NextAuthProviderClient.js +62 -0
  28. package/dist/nextjs/providers/NextAuthProviderClient.js.map +1 -0
  29. package/dist/nextjs/providers/ServerUserContext.d.ts +2 -0
  30. package/dist/nextjs/providers/ServerUserContext.d.ts.map +1 -0
  31. package/dist/nextjs/providers/ServerUserContext.js +5 -0
  32. package/dist/nextjs/providers/ServerUserContext.js.map +1 -0
  33. package/dist/nextjs/routeHandler.d.ts.map +1 -1
  34. package/dist/nextjs/routeHandler.js +241 -352
  35. package/dist/nextjs/routeHandler.js.map +1 -1
  36. package/dist/react-router-7/components/UserButton.js +1 -1
  37. package/dist/react-router-7/components/UserButton.js.map +1 -1
  38. package/dist/react-router-7/routeHandler.d.ts.map +1 -1
  39. package/dist/react-router-7/routeHandler.js +1 -0
  40. package/dist/react-router-7/routeHandler.js.map +1 -1
  41. package/dist/react-router-7/useUser.d.ts.map +1 -1
  42. package/dist/react-router-7/useUser.js +13 -2
  43. package/dist/react-router-7/useUser.js.map +1 -1
  44. package/dist/reactjs/components/ButtonContentOrLoader.d.ts.map +1 -1
  45. package/dist/reactjs/components/ButtonContentOrLoader.js +2 -4
  46. package/dist/reactjs/components/ButtonContentOrLoader.js.map +1 -1
  47. package/dist/reactjs/components/CivicAuthIframeContainer.d.ts +2 -0
  48. package/dist/reactjs/components/CivicAuthIframeContainer.d.ts.map +1 -0
  49. package/dist/reactjs/components/CivicAuthIframeContainer.js +26 -0
  50. package/dist/reactjs/components/CivicAuthIframeContainer.js.map +1 -0
  51. package/dist/reactjs/components/SignInButton.d.ts.map +1 -1
  52. package/dist/reactjs/components/SignInButton.js +11 -1
  53. package/dist/reactjs/components/SignInButton.js.map +1 -1
  54. package/dist/reactjs/components/UserButton.d.ts +9 -2
  55. package/dist/reactjs/components/UserButton.d.ts.map +1 -1
  56. package/dist/reactjs/components/UserButton.js +41 -9
  57. package/dist/reactjs/components/UserButton.js.map +1 -1
  58. package/dist/reactjs/components/index.d.ts +1 -0
  59. package/dist/reactjs/components/index.d.ts.map +1 -1
  60. package/dist/reactjs/components/index.js +1 -0
  61. package/dist/reactjs/components/index.js.map +1 -1
  62. package/dist/reactjs/core/GlobalAuthManager.d.ts +26 -0
  63. package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -1
  64. package/dist/reactjs/core/GlobalAuthManager.js +76 -5
  65. package/dist/reactjs/core/GlobalAuthManager.js.map +1 -1
  66. package/dist/reactjs/hooks/useUser.d.ts +19 -2
  67. package/dist/reactjs/hooks/useUser.d.ts.map +1 -1
  68. package/dist/reactjs/hooks/useUser.js +95 -7
  69. package/dist/reactjs/hooks/useUser.js.map +1 -1
  70. package/dist/reactjs/index.d.ts +1 -2
  71. package/dist/reactjs/index.d.ts.map +1 -1
  72. package/dist/reactjs/index.js +1 -2
  73. package/dist/reactjs/index.js.map +1 -1
  74. package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
  75. package/dist/server/ServerAuthenticationResolver.js +18 -0
  76. package/dist/server/ServerAuthenticationResolver.js.map +1 -1
  77. package/dist/server/index.d.ts +1 -1
  78. package/dist/server/index.d.ts.map +1 -1
  79. package/dist/server/index.js.map +1 -1
  80. package/dist/server/session.d.ts +51 -0
  81. package/dist/server/session.d.ts.map +1 -1
  82. package/dist/server/session.js +276 -15
  83. package/dist/server/session.js.map +1 -1
  84. package/dist/shared/components/SVGLoading.js +1 -1
  85. package/dist/shared/components/SVGLoading.js.map +1 -1
  86. package/dist/shared/components/UserButtonPresentation.d.ts.map +1 -0
  87. package/dist/shared/components/UserButtonPresentation.js.map +1 -0
  88. package/dist/shared/hooks/index.d.ts +1 -2
  89. package/dist/shared/hooks/index.d.ts.map +1 -1
  90. package/dist/shared/hooks/index.js +1 -2
  91. package/dist/shared/hooks/index.js.map +1 -1
  92. package/dist/shared/hooks/useBfcacheHandler.d.ts +23 -0
  93. package/dist/shared/hooks/useBfcacheHandler.d.ts.map +1 -0
  94. package/dist/shared/hooks/useBfcacheHandler.js +65 -0
  95. package/dist/shared/hooks/useBfcacheHandler.js.map +1 -0
  96. package/dist/shared/index.d.ts +1 -0
  97. package/dist/shared/index.d.ts.map +1 -1
  98. package/dist/shared/index.js +1 -0
  99. package/dist/shared/index.js.map +1 -1
  100. package/dist/shared/lib/util.d.ts +32 -0
  101. package/dist/shared/lib/util.d.ts.map +1 -1
  102. package/dist/shared/lib/util.js +79 -0
  103. package/dist/shared/lib/util.js.map +1 -1
  104. package/dist/shared/providers/AuthStatusContext.d.ts.map +1 -1
  105. package/dist/shared/providers/AuthStatusContext.js +2 -1
  106. package/dist/shared/providers/AuthStatusContext.js.map +1 -1
  107. package/dist/shared/providers/CivicAuthConfigContext.d.ts +2 -1
  108. package/dist/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
  109. package/dist/shared/providers/CivicAuthConfigContext.js +5 -2
  110. package/dist/shared/providers/CivicAuthConfigContext.js.map +1 -1
  111. package/dist/shared/providers/types.d.ts +1 -0
  112. package/dist/shared/providers/types.d.ts.map +1 -1
  113. package/dist/shared/providers/types.js.map +1 -1
  114. package/dist/shared/utils/locationChange.d.ts +34 -0
  115. package/dist/shared/utils/locationChange.d.ts.map +1 -0
  116. package/dist/shared/utils/locationChange.js +28 -0
  117. package/dist/shared/utils/locationChange.js.map +1 -0
  118. package/dist/shared/version.d.ts +1 -1
  119. package/dist/shared/version.js +1 -1
  120. package/dist/shared/version.js.map +1 -1
  121. package/dist/vanillajs/auth/AuthenticationEvents.d.ts +10 -1
  122. package/dist/vanillajs/auth/AuthenticationEvents.d.ts.map +1 -1
  123. package/dist/vanillajs/auth/AuthenticationEvents.js +29 -0
  124. package/dist/vanillajs/auth/AuthenticationEvents.js.map +1 -1
  125. package/dist/vanillajs/auth/BackendAuthenticationRefresher.d.ts.map +1 -1
  126. package/dist/vanillajs/auth/BackendAuthenticationRefresher.js +2 -2
  127. package/dist/vanillajs/auth/BackendAuthenticationRefresher.js.map +1 -1
  128. package/dist/vanillajs/auth/CivicAuth.d.ts +32 -0
  129. package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
  130. package/dist/vanillajs/auth/CivicAuth.js +255 -55
  131. package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
  132. package/dist/vanillajs/auth/SessionManager.d.ts +3 -2
  133. package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
  134. package/dist/vanillajs/auth/SessionManager.js +33 -7
  135. package/dist/vanillajs/auth/SessionManager.js.map +1 -1
  136. package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -1
  137. package/dist/vanillajs/auth/config/ConfigProcessor.js +2 -14
  138. package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
  139. package/dist/vanillajs/auth/handlers/IframeAuthHandler.d.ts.map +1 -1
  140. package/dist/vanillajs/auth/handlers/IframeAuthHandler.js +64 -11
  141. package/dist/vanillajs/auth/handlers/IframeAuthHandler.js.map +1 -1
  142. package/dist/vanillajs/auth/handlers/MessageHandler.d.ts.map +1 -1
  143. package/dist/vanillajs/auth/handlers/MessageHandler.js +4 -1
  144. package/dist/vanillajs/auth/handlers/MessageHandler.js.map +1 -1
  145. package/dist/vanillajs/auth/handlers/PopupHandler.d.ts.map +1 -1
  146. package/dist/vanillajs/auth/handlers/PopupHandler.js +3 -1
  147. package/dist/vanillajs/auth/handlers/PopupHandler.js.map +1 -1
  148. package/dist/vanillajs/auth/types/AuthTypes.d.ts +11 -1
  149. package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -1
  150. package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -1
  151. package/dist/vanillajs/iframe/IframeManager.d.ts +22 -1
  152. package/dist/vanillajs/iframe/IframeManager.d.ts.map +1 -1
  153. package/dist/vanillajs/iframe/IframeManager.js +184 -22
  154. package/dist/vanillajs/iframe/IframeManager.js.map +1 -1
  155. package/dist/vanillajs/types/index.d.ts +1 -1
  156. package/dist/vanillajs/types/index.d.ts.map +1 -1
  157. package/dist/vanillajs/types/index.js +1 -1
  158. package/dist/vanillajs/types/index.js.map +1 -1
  159. package/dist/vanillajs/ui/LoadingComponents.d.ts +4 -0
  160. package/dist/vanillajs/ui/LoadingComponents.d.ts.map +1 -1
  161. package/dist/vanillajs/ui/LoadingComponents.js +51 -1
  162. package/dist/vanillajs/ui/LoadingComponents.js.map +1 -1
  163. package/package.json +5 -5
  164. package/dist/nextjs/hooks/index.d.ts +0 -2
  165. package/dist/nextjs/hooks/index.d.ts.map +0 -1
  166. package/dist/nextjs/hooks/index.js +0 -2
  167. package/dist/nextjs/hooks/index.js.map +0 -1
  168. package/dist/nextjs/hooks/usePrevious.d.ts +0 -2
  169. package/dist/nextjs/hooks/usePrevious.d.ts.map +0 -1
  170. package/dist/nextjs/hooks/usePrevious.js +0 -9
  171. package/dist/nextjs/hooks/usePrevious.js.map +0 -1
  172. package/dist/nextjs/hooks/useUserCookie.d.ts +0 -9
  173. package/dist/nextjs/hooks/useUserCookie.d.ts.map +0 -1
  174. package/dist/nextjs/hooks/useUserCookie.js +0 -109
  175. package/dist/nextjs/hooks/useUserCookie.js.map +0 -1
  176. package/dist/react-router-7/components/UserButtonPresentation.d.ts.map +0 -1
  177. package/dist/react-router-7/components/UserButtonPresentation.js.map +0 -1
  178. package/dist/shared/components/BlockDisplay.d.ts +0 -6
  179. package/dist/shared/components/BlockDisplay.d.ts.map +0 -1
  180. package/dist/shared/components/BlockDisplay.js +0 -30
  181. package/dist/shared/components/BlockDisplay.js.map +0 -1
  182. package/dist/shared/components/CivicAuthIframe.d.ts +0 -10
  183. package/dist/shared/components/CivicAuthIframe.d.ts.map +0 -1
  184. package/dist/shared/components/CivicAuthIframe.js +0 -49
  185. package/dist/shared/components/CivicAuthIframe.js.map +0 -1
  186. package/dist/shared/components/CivicAuthIframeContainer.d.ts +0 -15
  187. package/dist/shared/components/CivicAuthIframeContainer.d.ts.map +0 -1
  188. package/dist/shared/components/CivicAuthIframeContainer.js +0 -177
  189. package/dist/shared/components/CivicAuthIframeContainer.js.map +0 -1
  190. package/dist/shared/components/CivicAuthLogoutIframeContainer.d.ts +0 -6
  191. package/dist/shared/components/CivicAuthLogoutIframeContainer.d.ts.map +0 -1
  192. package/dist/shared/components/CivicAuthLogoutIframeContainer.js +0 -51
  193. package/dist/shared/components/CivicAuthLogoutIframeContainer.js.map +0 -1
  194. package/dist/shared/components/IFrameAndLoading.d.ts +0 -7
  195. package/dist/shared/components/IFrameAndLoading.d.ts.map +0 -1
  196. package/dist/shared/components/IFrameAndLoading.js +0 -66
  197. package/dist/shared/components/IFrameAndLoading.js.map +0 -1
  198. package/dist/shared/hooks/useAuth.d.ts +0 -3
  199. package/dist/shared/hooks/useAuth.d.ts.map +0 -1
  200. package/dist/shared/hooks/useAuth.js +0 -12
  201. package/dist/shared/hooks/useAuth.js.map +0 -1
  202. package/dist/shared/hooks/useIframe.d.ts +0 -3
  203. package/dist/shared/hooks/useIframe.d.ts.map +0 -1
  204. package/dist/shared/hooks/useIframe.js +0 -13
  205. package/dist/shared/hooks/useIframe.js.map +0 -1
  206. package/dist/shared/hooks/useIsInIframe.d.ts +0 -7
  207. package/dist/shared/hooks/useIsInIframe.d.ts.map +0 -1
  208. package/dist/shared/hooks/useIsInIframe.js +0 -23
  209. package/dist/shared/hooks/useIsInIframe.js.map +0 -1
  210. package/dist/shared/hooks/useSignIn.d.ts +0 -20
  211. package/dist/shared/hooks/useSignIn.d.ts.map +0 -1
  212. package/dist/shared/hooks/useSignIn.js +0 -358
  213. package/dist/shared/hooks/useSignIn.js.map +0 -1
  214. package/dist/shared/providers/IframeProvider.d.ts +0 -28
  215. package/dist/shared/providers/IframeProvider.d.ts.map +0 -1
  216. package/dist/shared/providers/IframeProvider.js +0 -64
  217. package/dist/shared/providers/IframeProvider.js.map +0 -1
  218. /package/dist/{react-router-7 → shared}/components/UserButtonPresentation.d.ts +0 -0
  219. /package/dist/{react-router-7 → shared}/components/UserButtonPresentation.js +0 -0
@@ -1,2 +0,0 @@
1
- export { useUserCookie } from "../../nextjs/hooks/useUserCookie.js";
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/nextjs/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC","sourcesContent":["export { useUserCookie } from \"@/nextjs/hooks/useUserCookie.js\";\n"]}
@@ -1,2 +0,0 @@
1
- export declare function usePrevious<T>(value: T): T | undefined;
2
- //# sourceMappingURL=usePrevious.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"usePrevious.d.ts","sourceRoot":"","sources":["../../../src/nextjs/hooks/usePrevious.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,iBAMtC"}
@@ -1,9 +0,0 @@
1
- import { useEffect, useRef } from "react";
2
- export function usePrevious(value) {
3
- const ref = useRef();
4
- useEffect(() => {
5
- ref.current = value;
6
- }, [value]);
7
- return ref.current;
8
- }
9
- //# sourceMappingURL=usePrevious.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"usePrevious.js","sourceRoot":"","sources":["../../../src/nextjs/hooks/usePrevious.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE1C,MAAM,UAAU,WAAW,CAAI,KAAQ;IACrC,MAAM,GAAG,GAAG,MAAM,EAAK,CAAC;IACxB,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACZ,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC","sourcesContent":["import { useEffect, useRef } from \"react\";\n\nexport function usePrevious<T>(value: T) {\n const ref = useRef<T>();\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n"]}
@@ -1,9 +0,0 @@
1
- import type { EmptyObject, User } from "../../types.js";
2
- export declare const useUserCookie: <T extends EmptyObject>() => {
3
- user: User<T> | null;
4
- idToken: string | undefined;
5
- userChanged: boolean;
6
- fetchUser: (abortController?: AbortController) => void;
7
- isLoading: boolean;
8
- };
9
- //# sourceMappingURL=useUserCookie.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useUserCookie.d.ts","sourceRoot":"","sources":["../../../src/nextjs/hooks/useUserCookie.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAwBpD,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,WAAW;;;;kCAwBA,eAAe;;CAiFjE,CAAC"}
@@ -1,109 +0,0 @@
1
- "use client";
2
- import { useCallback, useEffect, useRef, useState } from "react";
3
- import { OAuthTokenTypes, UserStorage } from "../../shared/lib/types.js";
4
- import { objectsAreEqual } from "../../lib/obj.js";
5
- import { BrowserCookieStorage } from "../../shared/index.js";
6
- import { useIsClient } from "usehooks-ts";
7
- const browserCookieStorage = new BrowserCookieStorage();
8
- const getUserAndTokenFromCookie = () => {
9
- const userCookie = browserCookieStorage.getSync(UserStorage.USER);
10
- const idTokenCookie = browserCookieStorage.getSync(OAuthTokenTypes.ID_TOKEN);
11
- return {
12
- [UserStorage.USER]: userCookie ? JSON.parse(userCookie) : undefined,
13
- [OAuthTokenTypes.ID_TOKEN]: idTokenCookie || undefined,
14
- };
15
- };
16
- export const useUserCookie = () => {
17
- // need to make sure this is only run on the client
18
- // because it uses cookies that expect a document object to be present to read from
19
- const isClient = useIsClient();
20
- const response = (isClient && getUserAndTokenFromCookie()) || {};
21
- // initialise user and token from cookies so that we don't
22
- // have to wait for the first fetch to expose these values
23
- const userData = response[UserStorage.USER];
24
- const tokenData = response[OAuthTokenTypes.ID_TOKEN];
25
- // we need both a ref and state for the user and token
26
- // because the ref is used to compare the previous value
27
- // to the new value to see if it has changed
28
- // and the state is used to trigger a re-render
29
- // when the value changes
30
- const userRef = useRef(userData);
31
- const tokenRef = useRef(tokenData);
32
- const [user, setUser] = useState(userData);
33
- const [idToken, setToken] = useState(tokenData);
34
- const [userChanged, setUserChanged] = useState(false);
35
- const userChangedToggle = useRef(false);
36
- const [initialFetchComplete, setInitialFetchComplete] = useState(!!userData);
37
- const fetchUser = useCallback((abortController) => {
38
- if (abortController?.signal.aborted) {
39
- setInitialFetchComplete(true);
40
- return;
41
- }
42
- const response = getUserAndTokenFromCookie() || {};
43
- const userData = response[UserStorage.USER];
44
- const tokenData = response[OAuthTokenTypes.ID_TOKEN];
45
- if (abortController?.signal.aborted) {
46
- setInitialFetchComplete(true);
47
- return;
48
- }
49
- // we use objectsAreEqual here comparing the object references could trigger
50
- // unnecessary re-renders if the object is the same but a new reference is created
51
- if (!objectsAreEqual(userData, userRef.current)) {
52
- userRef.current = userData || null;
53
- setUser(userData || null);
54
- // Toggle userChanged to force effect to fire
55
- userChangedToggle.current = !userChangedToggle.current;
56
- setUserChanged(userChangedToggle.current);
57
- }
58
- if (tokenData !== tokenRef.current) {
59
- tokenRef.current = tokenData;
60
- setToken(tokenData);
61
- }
62
- setInitialFetchComplete(true);
63
- }, []);
64
- /**
65
- * Set up a listener for when the user cookies change which will be triggered
66
- * by server-side during token exchange. We are able to receive these updates as the auth
67
- * calls will be running in the iframe and the cookies will be set in the parent window.
68
- */
69
- useEffect(() => {
70
- let abortController = new AbortController();
71
- const cookieListener = () => {
72
- // pass an abort controller to fetchUser to cancel any in-flight requests
73
- // that might have been triggered before re-render
74
- abortController = new AbortController();
75
- fetchUser(abortController);
76
- };
77
- document.addEventListener("visibilitychange", cookieListener);
78
- window.addEventListener("storage", cookieListener);
79
- window.addEventListener("focus", cookieListener);
80
- // set the user and token ref from cookies again as the component has now mounted
81
- // so cookies might be available that weren't there at initialisation above
82
- const response = getUserAndTokenFromCookie() || {};
83
- const userData = response[UserStorage.USER];
84
- const tokenData = response[OAuthTokenTypes.ID_TOKEN];
85
- userRef.current = userData;
86
- tokenRef.current = tokenData;
87
- setUser(userData);
88
- setToken(tokenData);
89
- fetchUser(abortController);
90
- // poll for changes to the cookies every 2 seconds
91
- // this is required as react doesn't have a built-in hook that will change on cookie changes
92
- const intervalId = setInterval(cookieListener, 2000);
93
- return () => {
94
- abortController.abort();
95
- document.removeEventListener("visibilitychange", cookieListener);
96
- window.removeEventListener("storage", cookieListener);
97
- window.removeEventListener("focus", cookieListener);
98
- clearInterval(intervalId);
99
- };
100
- }, [fetchUser]);
101
- return {
102
- user,
103
- idToken,
104
- userChanged,
105
- fetchUser,
106
- isLoading: !initialFetchComplete,
107
- };
108
- };
109
- //# sourceMappingURL=useUserCookie.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useUserCookie.js","sourceRoot":"","sources":["../../../src/nextjs/hooks/useUserCookie.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { EmptyObject, User } from \"@/types.js\";\nimport { OAuthTokenTypes, UserStorage } from \"@/shared/lib/types.js\";\nimport { objectsAreEqual } from \"@/lib/obj.js\";\nimport { BrowserCookieStorage } from \"@/shared/index.js\";\nimport { useIsClient } from \"usehooks-ts\";\n\ntype UserAndTokenFromCookie = {\n [UserStorage.USER]: User | undefined;\n [OAuthTokenTypes.ID_TOKEN]: string | undefined;\n};\nconst browserCookieStorage = new BrowserCookieStorage();\nconst getUserAndTokenFromCookie = (): UserAndTokenFromCookie => {\n const userCookie = browserCookieStorage.getSync(\n UserStorage.USER,\n ) as unknown as string | null;\n const idTokenCookie = browserCookieStorage.getSync(\n OAuthTokenTypes.ID_TOKEN,\n ) as unknown as string | null;\n return {\n [UserStorage.USER]: userCookie ? JSON.parse(userCookie) : undefined,\n [OAuthTokenTypes.ID_TOKEN]: idTokenCookie || undefined,\n };\n};\n\nexport const useUserCookie = <T extends EmptyObject>() => {\n // need to make sure this is only run on the client\n // because it uses cookies that expect a document object to be present to read from\n const isClient = useIsClient();\n const response =\n (isClient && getUserAndTokenFromCookie()) || ({} as UserAndTokenFromCookie);\n // initialise user and token from cookies so that we don't\n // have to wait for the first fetch to expose these values\n const userData = response[UserStorage.USER] as User<T>;\n const tokenData = response[OAuthTokenTypes.ID_TOKEN];\n\n // we need both a ref and state for the user and token\n // because the ref is used to compare the previous value\n // to the new value to see if it has changed\n // and the state is used to trigger a re-render\n // when the value changes\n const userRef = useRef(userData);\n const tokenRef = useRef(tokenData);\n const [user, setUser] = useState<User<T> | null>(userData);\n const [idToken, setToken] = useState<string | undefined>(tokenData);\n const [userChanged, setUserChanged] = useState<boolean>(false);\n const userChangedToggle = useRef(false);\n const [initialFetchComplete, setInitialFetchComplete] = useState(!!userData);\n\n const fetchUser = useCallback((abortController?: AbortController) => {\n if (abortController?.signal.aborted) {\n setInitialFetchComplete(true);\n return;\n }\n\n const response = getUserAndTokenFromCookie() || {};\n const userData = response[UserStorage.USER] as User<T>;\n const tokenData = response[OAuthTokenTypes.ID_TOKEN];\n\n if (abortController?.signal.aborted) {\n setInitialFetchComplete(true);\n return;\n }\n\n // we use objectsAreEqual here comparing the object references could trigger\n // unnecessary re-renders if the object is the same but a new reference is created\n if (!objectsAreEqual(userData, userRef.current)) {\n userRef.current = userData || null;\n setUser(userData || null);\n // Toggle userChanged to force effect to fire\n userChangedToggle.current = !userChangedToggle.current;\n setUserChanged(userChangedToggle.current);\n }\n if (tokenData !== tokenRef.current) {\n tokenRef.current = tokenData;\n setToken(tokenData);\n }\n setInitialFetchComplete(true);\n }, []);\n\n /**\n * Set up a listener for when the user cookies change which will be triggered\n * by server-side during token exchange. We are able to receive these updates as the auth\n * calls will be running in the iframe and the cookies will be set in the parent window.\n */\n useEffect(() => {\n let abortController = new AbortController();\n const cookieListener = () => {\n // pass an abort controller to fetchUser to cancel any in-flight requests\n // that might have been triggered before re-render\n abortController = new AbortController();\n fetchUser(abortController);\n };\n\n document.addEventListener(\"visibilitychange\", cookieListener);\n window.addEventListener(\"storage\", cookieListener);\n window.addEventListener(\"focus\", cookieListener);\n\n // set the user and token ref from cookies again as the component has now mounted\n // so cookies might be available that weren't there at initialisation above\n const response =\n getUserAndTokenFromCookie() || ({} as UserAndTokenFromCookie);\n const userData = response[UserStorage.USER] as User<T>;\n const tokenData = response[OAuthTokenTypes.ID_TOKEN];\n userRef.current = userData;\n tokenRef.current = tokenData;\n setUser(userData);\n setToken(tokenData);\n fetchUser(abortController);\n\n // poll for changes to the cookies every 2 seconds\n // this is required as react doesn't have a built-in hook that will change on cookie changes\n const intervalId = setInterval(cookieListener, 2000);\n\n return () => {\n abortController.abort();\n document.removeEventListener(\"visibilitychange\", cookieListener);\n window.removeEventListener(\"storage\", cookieListener);\n window.removeEventListener(\"focus\", cookieListener);\n clearInterval(intervalId);\n };\n }, [fetchUser]);\n\n return {\n user,\n idToken,\n userChanged,\n fetchUser,\n isLoading: !initialFetchComplete,\n };\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"UserButtonPresentation.d.ts","sourceRoot":"","sources":["../../../src/react-router-7/components/UserButtonPresentation.tsx"],"names":[],"mappings":"AAEA,UAAU,2BAA2B;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,sBAAsB,CAAC,EACrC,SAAS,EACT,KAAK,EACL,OAAO,EACP,aAAa,EAAE,UAAU,EACzB,QAAQ,GACT,EAAE,2BAA2B,oDA0B7B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"UserButtonPresentation.js","sourceRoot":"","sources":["../../../src/react-router-7/components/UserButtonPresentation.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAUb,MAAM,UAAU,sBAAsB,CAAC,EACrC,SAAS,EACT,KAAK,EACL,OAAO,EACP,aAAa,EAAE,UAAU,EACzB,QAAQ,GACoB;IAC5B,OAAO,CACL,iBACE,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE;YACL,MAAM,EAAE,SAAS;YACjB,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,cAAc;YACvB,KAAK,EAAE,SAAS;YAChB,UAAU,EAAE,uBAAuB;YACnC,QAAQ,EAAE,KAAK;YACf,GAAG,KAAK;SACT,EACD,OAAO,EAAE,OAAO,iBACH,UAAU,EACvB,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;YAClB,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC;QACpD,CAAC,EACD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;YAClB,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC;QAC7C,CAAC,YAEA,QAAQ,GACF,CACV,CAAC;AACJ,CAAC","sourcesContent":["\"use client\";\n\ninterface UserButtonPresentationProps {\n className?: string;\n style?: React.CSSProperties;\n onClick?: () => void;\n \"data-testid\"?: string;\n children: React.ReactNode;\n}\n\nexport function UserButtonPresentation({\n className,\n style,\n onClick,\n \"data-testid\": dataTestId,\n children,\n}: UserButtonPresentationProps) {\n return (\n <button\n className={className}\n style={{\n cursor: \"pointer\",\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n color: \"#6b7280\",\n transition: \"background-color 0.2s\",\n minWidth: \"9em\",\n ...style,\n }}\n onClick={onClick}\n data-testid={dataTestId}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#f3f4f6\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"\";\n }}\n >\n {children}\n </button>\n );\n}\n"]}
@@ -1,6 +0,0 @@
1
- import { type ReactNode } from "react";
2
- declare const BlockDisplay: ({ children }: {
3
- children: ReactNode;
4
- }) => import("@emotion/react/jsx-runtime").JSX.Element | null;
5
- export { BlockDisplay };
6
- //# sourceMappingURL=BlockDisplay.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BlockDisplay.d.ts","sourceRoot":"","sources":["../../../src/shared/components/BlockDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,QAAA,MAAM,YAAY,iBAAkB;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,4DAmC1D,CAAC;AACF,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -1,30 +0,0 @@
1
- import { jsx as _jsx } from "@emotion/react/jsx-runtime";
2
- import {} from "react";
3
- import { useIframe } from "../hooks/useIframe.js";
4
- import { useIsClient } from "usehooks-ts";
5
- const BlockDisplay = ({ children }) => {
6
- const { backgroundColor } = useIframe();
7
- const isClient = useIsClient();
8
- // don't render in server-mode as the appearance changes after load
9
- return !isClient ? null : (_jsx("div", { id: "iframe-block-display-wrapper", style: {
10
- position: "absolute",
11
- left: 0,
12
- top: 0,
13
- zIndex: 200,
14
- display: "flex",
15
- height: "100vh",
16
- width: "100vw",
17
- alignItems: "center",
18
- justifyContent: "center",
19
- backgroundColor,
20
- }, children: _jsx("div", { id: "iframe-block-display", style: {
21
- position: "relative",
22
- inset: 0,
23
- display: "flex",
24
- alignItems: "center",
25
- justifyContent: "center",
26
- backgroundColor,
27
- }, children: children }) }));
28
- };
29
- export { BlockDisplay };
30
- //# sourceMappingURL=BlockDisplay.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BlockDisplay.js","sourceRoot":"","sources":["../../../src/shared/components/BlockDisplay.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,YAAY,GAAG,CAAC,EAAE,QAAQ,EAA2B,EAAE,EAAE;IAC7D,MAAM,EAAE,eAAe,EAAE,GAAG,SAAS,EAAE,CAAC;IACxC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACxB,cACE,EAAE,EAAC,8BAA8B,EACjC,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,CAAC;YACN,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,OAAO;YACf,KAAK,EAAE,OAAO;YACd,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,eAAe;SAChB,YAED,cACE,EAAE,EAAC,sBAAsB,EACzB,KAAK,EAAE;gBACL,QAAQ,EAAE,UAAU;gBACpB,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,QAAQ;gBACpB,cAAc,EAAE,QAAQ;gBACxB,eAAe;aAChB,YAEA,QAAQ,GACL,GACF,CACP,CAAC;AACJ,CAAC,CAAC;AACF,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import { type ReactNode } from \"react\";\nimport { useIframe } from \"../hooks/useIframe.js\";\nimport { useIsClient } from \"usehooks-ts\";\n\nconst BlockDisplay = ({ children }: { children: ReactNode }) => {\n const { backgroundColor } = useIframe();\n const isClient = useIsClient();\n // don't render in server-mode as the appearance changes after load\n return !isClient ? null : (\n <div\n id=\"iframe-block-display-wrapper\"\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n zIndex: 200,\n display: \"flex\",\n height: \"100vh\",\n width: \"100vw\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor,\n }}\n >\n <div\n id=\"iframe-block-display\"\n style={{\n position: \"relative\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor,\n }}\n >\n {children}\n </div>\n </div>\n );\n};\nexport { BlockDisplay };\n"]}
@@ -1,10 +0,0 @@
1
- import React from "react";
2
- type CivicAuthIframeProps = {
3
- onLoad?: () => void;
4
- id: string;
5
- isRedirecting?: boolean;
6
- };
7
- declare const CivicAuthIframe: React.ForwardRefExoticComponent<CivicAuthIframeProps & React.RefAttributes<HTMLIFrameElement>>;
8
- export type { CivicAuthIframeProps };
9
- export { CivicAuthIframe };
10
- //# sourceMappingURL=CivicAuthIframe.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CivicAuthIframe.d.ts","sourceRoot":"","sources":["../../../src/shared/components/CivicAuthIframe.tsx"],"names":[],"mappings":"AACA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAM1C,KAAK,oBAAoB,GAAG;IAC1B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,QAAA,MAAM,eAAe,gGA6EpB,CAAC;AAIF,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -1,49 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
3
- import React, { forwardRef } from "react";
4
- import { IframeResizer } from "@civic/iframe-resizer";
5
- import SVGLoading from "./SVGLoading.js";
6
- import { useIframe } from "../hooks/useIframe.js";
7
- import { useIsClient } from "usehooks-ts";
8
- const CivicAuthIframe = forwardRef(({ onLoad, id, isRedirecting }, ref) => {
9
- const [isLoaded, setIsLoaded] = React.useState(false);
10
- const { iframeMode, backgroundColor } = useIframe();
11
- const iframeRef = ref;
12
- const isClient = useIsClient();
13
- // don't render on the server as the appearance changes when the iframe is loaded from login-app post-messages
14
- return !isClient ? null : (_jsxs("div", { style: {
15
- position: "relative",
16
- borderRadius: isLoaded ? "26px" : 0,
17
- overflow: "hidden",
18
- transition: "all 250ms ease",
19
- backgroundColor: isLoaded ? backgroundColor : "transparent",
20
- minHeight: iframeMode !== "embedded" ? "26px" : "auto",
21
- }, children: [!isLoaded || isRedirecting ? (_jsx("div", { "data-testid": "iframe-shimmer-loader", style: {
22
- width: "100%",
23
- height: "26px",
24
- display: "flex",
25
- alignItems: "center",
26
- justifyContent: "center",
27
- position: "absolute",
28
- top: "50%",
29
- left: "50%",
30
- transform: "translate(-50%, -50%)",
31
- borderRadius: "13px",
32
- overflow: "hidden",
33
- }, children: iframeMode !== "embedded" && (_jsx(SVGLoading, { backgroundColor: backgroundColor })) })) : null, _jsx("div", { style: {
34
- opacity: isLoaded ? 1 : 0,
35
- transition: "opacity 250ms ease",
36
- }, children: !isRedirecting && (_jsx(IframeResizer, { ref: iframeRef, id: id, "data-testid": "civic-auth-iframe-with-resizer", initialHeight: iframeMode !== "embedded" ? "26px" : "max-content", animate: true, animationDuration: 250, checkOrigin: false, style: {
37
- width: "100%",
38
- border: "none",
39
- minWidth: "100%",
40
- backgroundColor: isLoaded ? backgroundColor : "transparent",
41
- pointerEvents: "auto",
42
- }, onLoad: () => {
43
- setIsLoaded(true);
44
- onLoad?.();
45
- }, allow: "camera; screen-wake-lock; publickey-credentials-get *; publickey-credentials-create *;", allowFullScreen: true })) })] }));
46
- });
47
- CivicAuthIframe.displayName = "CivicAuthIframe";
48
- export { CivicAuthIframe };
49
- //# sourceMappingURL=CivicAuthIframe.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CivicAuthIframe.js","sourceRoot":"","sources":["../../../src/shared/components/CivicAuthIframe.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport React, { forwardRef } from \"react\";\nimport { IframeResizer } from \"@civic/iframe-resizer\";\nimport SVGLoading from \"./SVGLoading.js\";\nimport { useIframe } from \"../hooks/useIframe.js\";\nimport { useIsClient } from \"usehooks-ts\";\n\ntype CivicAuthIframeProps = {\n onLoad?: () => void;\n id: string;\n isRedirecting?: boolean; // Optional prop to indicate if the iframe is redirecting\n};\n\nconst CivicAuthIframe = forwardRef<HTMLIFrameElement, CivicAuthIframeProps>(\n ({ onLoad, id, isRedirecting }, ref) => {\n const [isLoaded, setIsLoaded] = React.useState(false);\n const { iframeMode, backgroundColor } = useIframe();\n const iframeRef = ref;\n const isClient = useIsClient();\n\n // don't render on the server as the appearance changes when the iframe is loaded from login-app post-messages\n return !isClient ? null : (\n <div\n style={{\n position: \"relative\",\n borderRadius: isLoaded ? \"26px\" : 0,\n overflow: \"hidden\",\n transition: \"all 250ms ease\",\n backgroundColor: isLoaded ? backgroundColor : \"transparent\",\n minHeight: iframeMode !== \"embedded\" ? \"26px\" : \"auto\",\n }}\n >\n {/* show the shimmer effect while loading or redirecting */}\n {!isLoaded || isRedirecting ? (\n <div\n data-testid=\"iframe-shimmer-loader\"\n style={{\n width: \"100%\",\n height: \"26px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n borderRadius: \"13px\",\n overflow: \"hidden\",\n }}\n >\n {iframeMode !== \"embedded\" && (\n <SVGLoading backgroundColor={backgroundColor} />\n )}\n </div>\n ) : null}\n <div\n style={{\n opacity: isLoaded ? 1 : 0,\n transition: \"opacity 250ms ease\",\n }}\n >\n {/* don't need to show the iframe at all if we are redirecting */}\n {!isRedirecting && (\n <IframeResizer\n ref={iframeRef}\n id={id}\n data-testid={\"civic-auth-iframe-with-resizer\"}\n initialHeight={iframeMode !== \"embedded\" ? \"26px\" : \"max-content\"}\n animate={true}\n animationDuration={250}\n checkOrigin={false}\n style={{\n width: \"100%\",\n border: \"none\",\n minWidth: \"100%\",\n backgroundColor: isLoaded ? backgroundColor : \"transparent\",\n pointerEvents: \"auto\",\n }}\n onLoad={() => {\n setIsLoaded(true);\n onLoad?.();\n }}\n allow=\"camera; screen-wake-lock; publickey-credentials-get *; publickey-credentials-create *;\"\n allowFullScreen\n />\n )}\n </div>\n </div>\n );\n },\n);\n\nCivicAuthIframe.displayName = \"CivicAuthIframe\";\n\nexport type { CivicAuthIframeProps };\n\nexport { CivicAuthIframe };\n"]}
@@ -1,15 +0,0 @@
1
- import React from "react";
2
- type CivicAuthIframeContainerProps = {
3
- onClose?: () => void;
4
- closeOnRedirect?: boolean;
5
- };
6
- export declare function IframeChrome({ children, onClose, isFrameLoaded, isRedirecting, }: {
7
- children: React.ReactNode;
8
- onClose?: () => void;
9
- isFrameLoaded: boolean;
10
- isRedirecting?: boolean;
11
- }): import("@emotion/react/jsx-runtime").JSX.Element;
12
- declare const CivicAuthIframeContainer: ({ onClose, closeOnRedirect, }: CivicAuthIframeContainerProps) => import("@emotion/react/jsx-runtime").JSX.Element;
13
- export type { CivicAuthIframeContainerProps };
14
- export { CivicAuthIframeContainer };
15
- //# sourceMappingURL=CivicAuthIframeContainer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CivicAuthIframeContainer.d.ts","sourceRoot":"","sources":["../../../src/shared/components/CivicAuthIframeContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAcxE,KAAK,6BAA6B,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAeF,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,OAAO,EACP,aAAa,EACb,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,oDA8DA;AAED,QAAA,MAAM,wBAAwB,kCAG3B,6BAA6B,qDA4K/B,CAAC;AAEF,YAAY,EAAE,6BAA6B,EAAE,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
@@ -1,177 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
3
- import React, { useCallback, useEffect, useRef, useState } from "react";
4
- import { LoadingIcon } from "../../shared/components/LoadingIcon.js";
5
- import { CloseIcon } from "../../shared/components/CloseIcon.js";
6
- import { CivicAuthIframe } from "../../shared/components/CivicAuthIframe.js";
7
- import { useIframe } from "../../shared/hooks/index.js";
8
- import { TOKEN_EXCHANGE_SUCCESS_TEXT, TOKEN_EXCHANGE_TRIGGER_TEXT, } from "../../constants.js";
9
- import { useCivicAuthConfig } from "../../shared/hooks/index.js";
10
- import { useClientTokenExchangeSession } from "../../shared/hooks/index.js";
11
- import { getIframeRef } from "../lib/iframeUtils.js";
12
- import { useIsClient } from "usehooks-ts";
13
- function NoChrome({ children, }) {
14
- return (_jsx("div", { "data-testid": "civic-iframe-no-chrome", style: { position: "relative" }, children: children }));
15
- }
16
- export function IframeChrome({ children, onClose, isFrameLoaded, isRedirecting, }) {
17
- const { setIframeAborted } = useIframe();
18
- return (_jsx("div", { style: {
19
- position: "absolute",
20
- left: 0,
21
- top: 0,
22
- zIndex: 50,
23
- display: "flex",
24
- height: "100vh",
25
- width: "100vw",
26
- alignItems: "center",
27
- justifyContent: "center",
28
- backgroundColor: "rgba(17, 24, 39, 0.5)",
29
- backdropFilter: "blur(4px)",
30
- }, onClick: () => {
31
- setIframeAborted(true);
32
- onClose?.();
33
- }, children: _jsxs("div", { "data-testid": "iframe-chrome", style: {
34
- position: "relative",
35
- overflow: "hidden",
36
- paddingLeft: "0",
37
- paddingRight: "0",
38
- paddingBottom: "0",
39
- width: "22rem",
40
- }, onClick: (e) => e.stopPropagation(), children: [isFrameLoaded && !isRedirecting && (_jsx("button", { style: {
41
- position: "absolute",
42
- right: "0.6rem",
43
- top: "0.6rem",
44
- cursor: "pointer",
45
- alignItems: "center",
46
- justifyContent: "center",
47
- border: "none",
48
- backgroundColor: "transparent",
49
- padding: "0.25rem",
50
- color: "#9ca3af",
51
- zIndex: 100,
52
- }, onClick: () => {
53
- setIframeAborted(true);
54
- onClose?.();
55
- }, children: _jsx(CloseIcon, {}) })), children] }) }));
56
- }
57
- const CivicAuthIframeContainer = ({ onClose, closeOnRedirect = true, }) => {
58
- const config = useCivicAuthConfig();
59
- const [tokenExchangeUrl, setTokenExchangeUrl] = useState(null);
60
- const { doTokenExchange } = useClientTokenExchangeSession();
61
- const { iframeRef, iframeMode, backgroundColor, setIframeMounted } = useIframe();
62
- const [isIframeContentLoaded, setIsIframeContentLoaded] = useState(false);
63
- const [isRedirecting, setIsRedirecting] = useState(false);
64
- useEffect(() => {
65
- setIframeMounted(true);
66
- }, [setIframeMounted]);
67
- useEffect(() => {
68
- if (tokenExchangeUrl) {
69
- doTokenExchange?.(tokenExchangeUrl);
70
- }
71
- }, [doTokenExchange, tokenExchangeUrl]);
72
- const processIframeUrl = useCallback(() => {
73
- if (!config)
74
- return;
75
- if (iframeRef && iframeRef.current) {
76
- const ref = getIframeRef(iframeRef.current);
77
- if (ref?.contentWindow) {
78
- try {
79
- const iframeUrl = ref.contentWindow.location.href;
80
- // we know that oauth has finished when the iframe redirects to our redirectUrl
81
- if (iframeUrl.startsWith(config.redirectUrl)) {
82
- const iframeBody = ref.contentWindow.document.body.innerHTML;
83
- // If we're doing a server token exchange, we need to call the server a second time
84
- // using a fetch so that we're on the same domain and cookies can be sent and read
85
- // The server will use the presence of the code_verifier cookie to determine whether to do a token exchange or not.
86
- // On the initial (3rd party) redirect from the auth server, the cookie won't be sent, so the server-side callback route will just render a blank page,
87
- // and we'll do the exchange request from here, which will include the cookies.
88
- if (iframeBody.includes(TOKEN_EXCHANGE_TRIGGER_TEXT)) {
89
- const params = new URL(iframeUrl).searchParams;
90
- const appUrl = globalThis.window?.location?.origin;
91
- fetch(`${config.redirectUrl}?${params.toString()}&appUrl=${appUrl}`);
92
- }
93
- else {
94
- // if we're doing token-exchange in the client, we can just set the authResponseUrl
95
- // to be handled by the auth provider
96
- // iframeRef.current.setAttribute("src", "");
97
- setTokenExchangeUrl(iframeUrl);
98
- }
99
- if (iframeBody.includes(TOKEN_EXCHANGE_SUCCESS_TEXT) &&
100
- config.loginSuccessUrl) {
101
- globalThis.window.location.href = config.loginSuccessUrl;
102
- }
103
- if (closeOnRedirect)
104
- onClose?.();
105
- return true; // Successfully processed the URL
106
- }
107
- }
108
- catch {
109
- // ignore errors while waiting for redirect
110
- }
111
- }
112
- }
113
- return false; // Haven't processed the URL yet
114
- }, [closeOnRedirect, config, iframeRef, onClose]);
115
- const intervalId = useRef();
116
- const handleEscape = useCallback((event) => {
117
- if (event.key === "Escape") {
118
- onClose?.();
119
- }
120
- }, [onClose]);
121
- // handle Escape
122
- useEffect(() => {
123
- window.addEventListener("keydown", handleEscape);
124
- window.addEventListener("locationWillChange", () => {
125
- console.log("locationWillChange event triggered, setting isRedirecting to true");
126
- // If the location will
127
- // Show loading state
128
- setIsRedirecting(true);
129
- });
130
- return () => window.removeEventListener("keydown", handleEscape);
131
- });
132
- const handleIframeLoad = useCallback(() => {
133
- setIsIframeContentLoaded(true);
134
- const iframeHasUrl = processIframeUrl();
135
- if (iframeHasUrl && intervalId.current) {
136
- clearInterval(intervalId.current);
137
- }
138
- }, [processIframeUrl, intervalId]);
139
- const WrapperComponent = iframeMode === "embedded" ? NoChrome : IframeChrome;
140
- const isClient = useIsClient();
141
- // if the iframe is embedded, we need to handle the loading state differently
142
- if (iframeMode === "embedded") {
143
- return (_jsx(WrapperComponent, { onClose: onClose, isFrameLoaded: isIframeContentLoaded, children: _jsxs("div", { style: {
144
- minHeight: isIframeContentLoaded ? "auto" : "225px",
145
- backgroundColor: isClient ? backgroundColor : "#8E949D",
146
- borderRadius: "26px",
147
- position: "relative",
148
- transition: "all 0.5s ease-in-out",
149
- display: "flex",
150
- alignItems: "center",
151
- justifyContent: "center",
152
- overflow: "hidden",
153
- }, children: [!isIframeContentLoaded && (_jsx("div", { style: {
154
- position: "absolute",
155
- top: 0,
156
- left: 0,
157
- right: 0,
158
- bottom: 0,
159
- display: "flex",
160
- alignItems: "center",
161
- justifyContent: "center",
162
- }, children: _jsx(LoadingIcon, {}) })), _jsx("div", { style: {
163
- width: "100%",
164
- minWidth: "100%",
165
- alignItems: "center",
166
- justifyContent: "center",
167
- borderRadius: "26px",
168
- overflow: "hidden",
169
- opacity: isIframeContentLoaded ? 1 : 0,
170
- transition: "opacity 0.5s ease-in-out",
171
- }, children: _jsx(CivicAuthIframe, { ref: iframeRef, id: "civic-auth-iframe", onLoad: handleIframeLoad }) })] }) }));
172
- }
173
- // if the iframe is not embedded, we can just render the iframe directly
174
- return (_jsx(WrapperComponent, { onClose: onClose, isFrameLoaded: isIframeContentLoaded, isRedirecting: isRedirecting, children: _jsx(CivicAuthIframe, { ref: iframeRef, id: "civic-auth-iframe", onLoad: handleIframeLoad, isRedirecting: isRedirecting }) }));
175
- };
176
- export { CivicAuthIframeContainer };
177
- //# sourceMappingURL=CivicAuthIframeContainer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CivicAuthIframeContainer.js","sourceRoot":"","sources":["../../../src/shared/components/CivicAuthIframeContainer.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { LoadingIcon } from \"@/shared/components/LoadingIcon.js\";\nimport { CloseIcon } from \"@/shared/components/CloseIcon.js\";\nimport { CivicAuthIframe } from \"@/shared/components/CivicAuthIframe.js\";\nimport { useIframe } from \"@/shared/hooks/index.js\";\nimport {\n TOKEN_EXCHANGE_SUCCESS_TEXT,\n TOKEN_EXCHANGE_TRIGGER_TEXT,\n} from \"@/constants.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/index.js\";\nimport { useClientTokenExchangeSession } from \"@/shared/hooks/index.js\";\nimport { getIframeRef } from \"../lib/iframeUtils.js\";\nimport { useIsClient } from \"usehooks-ts\";\n\ntype CivicAuthIframeContainerProps = {\n onClose?: () => void;\n closeOnRedirect?: boolean;\n};\n\nfunction NoChrome({\n children,\n}: {\n children: React.ReactNode;\n onClose?: () => void;\n}) {\n return (\n <div data-testid=\"civic-iframe-no-chrome\" style={{ position: \"relative\" }}>\n {children}\n </div>\n );\n}\n\nexport function IframeChrome({\n children,\n onClose,\n isFrameLoaded,\n isRedirecting,\n}: {\n children: React.ReactNode;\n onClose?: () => void;\n isFrameLoaded: boolean;\n isRedirecting?: boolean;\n}) {\n const { setIframeAborted } = useIframe();\n\n return (\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n zIndex: 50,\n display: \"flex\",\n height: \"100vh\",\n width: \"100vw\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(17, 24, 39, 0.5)\",\n backdropFilter: \"blur(4px)\",\n }}\n onClick={() => {\n setIframeAborted(true);\n onClose?.();\n }}\n >\n <div\n data-testid=\"iframe-chrome\"\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n paddingLeft: \"0\",\n paddingRight: \"0\",\n paddingBottom: \"0\",\n width: \"22rem\",\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {isFrameLoaded && !isRedirecting && (\n <button\n style={{\n position: \"absolute\",\n right: \"0.6rem\",\n top: \"0.6rem\",\n cursor: \"pointer\",\n alignItems: \"center\",\n justifyContent: \"center\",\n border: \"none\",\n backgroundColor: \"transparent\",\n padding: \"0.25rem\",\n color: \"#9ca3af\",\n zIndex: 100,\n }}\n onClick={() => {\n setIframeAborted(true);\n onClose?.();\n }}\n >\n <CloseIcon />\n </button>\n )}\n {children}\n </div>\n </div>\n );\n}\n\nconst CivicAuthIframeContainer = ({\n onClose,\n closeOnRedirect = true,\n}: CivicAuthIframeContainerProps) => {\n const config = useCivicAuthConfig();\n const [tokenExchangeUrl, setTokenExchangeUrl] = useState<string | null>(null);\n const { doTokenExchange } = useClientTokenExchangeSession();\n const { iframeRef, iframeMode, backgroundColor, setIframeMounted } =\n useIframe();\n const [isIframeContentLoaded, setIsIframeContentLoaded] = useState(false);\n const [isRedirecting, setIsRedirecting] = useState(false);\n useEffect(() => {\n setIframeMounted(true);\n }, [setIframeMounted]);\n\n useEffect(() => {\n if (tokenExchangeUrl) {\n doTokenExchange?.(tokenExchangeUrl);\n }\n }, [doTokenExchange, tokenExchangeUrl]);\n\n const processIframeUrl = useCallback(() => {\n if (!config) return;\n if (iframeRef && iframeRef.current) {\n const ref = getIframeRef(iframeRef.current)!;\n if (ref?.contentWindow) {\n try {\n const iframeUrl = ref.contentWindow.location.href;\n // we know that oauth has finished when the iframe redirects to our redirectUrl\n if (iframeUrl.startsWith(config.redirectUrl)) {\n const iframeBody = ref.contentWindow.document.body.innerHTML;\n\n // If we're doing a server token exchange, we need to call the server a second time\n // using a fetch so that we're on the same domain and cookies can be sent and read\n // The server will use the presence of the code_verifier cookie to determine whether to do a token exchange or not.\n // On the initial (3rd party) redirect from the auth server, the cookie won't be sent, so the server-side callback route will just render a blank page,\n // and we'll do the exchange request from here, which will include the cookies.\n if (iframeBody.includes(TOKEN_EXCHANGE_TRIGGER_TEXT)) {\n const params = new URL(iframeUrl).searchParams;\n const appUrl = globalThis.window?.location?.origin;\n fetch(\n `${config.redirectUrl}?${params.toString()}&appUrl=${appUrl}`,\n );\n } else {\n // if we're doing token-exchange in the client, we can just set the authResponseUrl\n // to be handled by the auth provider\n // iframeRef.current.setAttribute(\"src\", \"\");\n setTokenExchangeUrl(iframeUrl);\n }\n if (\n iframeBody.includes(TOKEN_EXCHANGE_SUCCESS_TEXT) &&\n config.loginSuccessUrl\n ) {\n globalThis.window.location.href = config.loginSuccessUrl;\n }\n\n if (closeOnRedirect) onClose?.();\n return true; // Successfully processed the URL\n }\n } catch {\n // ignore errors while waiting for redirect\n }\n }\n }\n return false; // Haven't processed the URL yet\n }, [closeOnRedirect, config, iframeRef, onClose]);\n\n const intervalId = useRef<NodeJS.Timeout>();\n\n const handleEscape = useCallback(\n (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose?.();\n }\n },\n [onClose],\n );\n\n // handle Escape\n useEffect(() => {\n window.addEventListener(\"keydown\", handleEscape);\n window.addEventListener(\"locationWillChange\", () => {\n console.log(\n \"locationWillChange event triggered, setting isRedirecting to true\",\n );\n // If the location will\n // Show loading state\n setIsRedirecting(true);\n });\n return () => window.removeEventListener(\"keydown\", handleEscape);\n });\n\n const handleIframeLoad = useCallback(() => {\n setIsIframeContentLoaded(true);\n\n const iframeHasUrl = processIframeUrl();\n if (iframeHasUrl && intervalId.current) {\n clearInterval(intervalId.current);\n }\n }, [processIframeUrl, intervalId]);\n\n const WrapperComponent = iframeMode === \"embedded\" ? NoChrome : IframeChrome;\n const isClient = useIsClient();\n // if the iframe is embedded, we need to handle the loading state differently\n if (iframeMode === \"embedded\") {\n return (\n <WrapperComponent onClose={onClose} isFrameLoaded={isIframeContentLoaded}>\n <div\n style={{\n minHeight: isIframeContentLoaded ? \"auto\" : \"225px\",\n backgroundColor: isClient ? backgroundColor : \"#8E949D\",\n borderRadius: \"26px\",\n position: \"relative\",\n transition: \"all 0.5s ease-in-out\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n }}\n >\n {/* always load the loading spinner in the center of the iframe */}\n {!isIframeContentLoaded && (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <LoadingIcon />\n </div>\n )}\n <div\n style={{\n width: \"100%\",\n minWidth: \"100%\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: \"26px\",\n overflow: \"hidden\",\n opacity: isIframeContentLoaded ? 1 : 0,\n transition: \"opacity 0.5s ease-in-out\",\n }}\n >\n <CivicAuthIframe\n ref={iframeRef}\n id={\"civic-auth-iframe\"}\n onLoad={handleIframeLoad}\n />\n </div>\n </div>\n </WrapperComponent>\n );\n }\n\n // if the iframe is not embedded, we can just render the iframe directly\n return (\n <WrapperComponent\n onClose={onClose}\n isFrameLoaded={isIframeContentLoaded}\n isRedirecting={isRedirecting}\n >\n <CivicAuthIframe\n ref={iframeRef}\n id={\"civic-auth-iframe\"}\n onLoad={handleIframeLoad}\n isRedirecting={isRedirecting} // Pass the isRedirecting state to the iframe\n />\n </WrapperComponent>\n );\n};\n\nexport type { CivicAuthIframeContainerProps };\n\nexport { CivicAuthIframeContainer };\n"]}
@@ -1,6 +0,0 @@
1
- type CivicAuthLogoutIframeContainerProps = {
2
- isLoading?: boolean;
3
- };
4
- declare const CivicAuthLogoutIframeContainer: ({ isLoading, }: CivicAuthLogoutIframeContainerProps) => import("@emotion/react/jsx-runtime").JSX.Element | null;
5
- export { CivicAuthLogoutIframeContainer };
6
- //# sourceMappingURL=CivicAuthLogoutIframeContainer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CivicAuthLogoutIframeContainer.d.ts","sourceRoot":"","sources":["../../../src/shared/components/CivicAuthLogoutIframeContainer.tsx"],"names":[],"mappings":"AAWA,KAAK,mCAAmC,GAAG;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,8BAA8B,mBAEjC,mCAAmC,4DA4DrC,CAAC;AAEF,OAAO,EAAE,8BAA8B,EAAE,CAAC"}
@@ -1,51 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
3
- import { CivicAuthIframe } from "../../shared/components/CivicAuthIframe.js";
4
- import { useIframe } from "../../shared/hooks/index.js";
5
- import { LoadingIcon } from "./LoadingIcon.js";
6
- import { IframeChrome } from "./CivicAuthIframeContainer.js";
7
- import { useIsClient } from "usehooks-ts";
8
- import { useCallback } from "react";
9
- import { getIframeRef } from "../lib/iframeUtils.js";
10
- import { LOGOUT_SUCCESS_TEXT } from "../../constants.js";
11
- const CivicAuthLogoutIframeContainer = ({ isLoading = false, }) => {
12
- const { logoutIframeRef } = useIframe();
13
- const isClient = useIsClient();
14
- const processLogoutIframeUrl = useCallback(() => {
15
- if (logoutIframeRef && logoutIframeRef.current) {
16
- const ref = getIframeRef(logoutIframeRef.current);
17
- if (!ref?.contentWindow) {
18
- return;
19
- }
20
- try {
21
- const iframeBody = ref.contentWindow.document.body.innerHTML;
22
- // If we have LOGOUT_SUCCESS_TEXT in the body, we know the logout succeeded on the server,
23
- // and we should redirect the parent to the post logout success URL indicated in the included link tag.
24
- if (iframeBody.includes(LOGOUT_SUCCESS_TEXT)) {
25
- const link = ref.contentWindow.document.querySelector("a[rel='civic-auth-post-logout-redirect-url']");
26
- if (link) {
27
- const redirectUrl = link.getAttribute("href");
28
- if (redirectUrl && redirectUrl !== "#") {
29
- window.location.href = redirectUrl;
30
- return true;
31
- }
32
- }
33
- }
34
- }
35
- catch {
36
- // ignore errors while waiting for redirect
37
- }
38
- }
39
- return false; // Haven't processed the URL yet
40
- }, [logoutIframeRef]);
41
- // don't render the in server-mode as the appearance changes after load
42
- return !isClient ? null : (_jsxs(IframeChrome, { isFrameLoaded: true, children: [isLoading ? (_jsx("div", { id: "civic-auth-loading-icon-wrapper", style: {
43
- position: "absolute",
44
- inset: 0,
45
- display: "flex",
46
- alignItems: "center",
47
- justifyContent: "center",
48
- }, children: _jsx(LoadingIcon, {}) })) : null, _jsx(CivicAuthIframe, { ref: logoutIframeRef, id: "civic-auth-logout-iframe", onLoad: processLogoutIframeUrl })] }));
49
- };
50
- export { CivicAuthLogoutIframeContainer };
51
- //# sourceMappingURL=CivicAuthLogoutIframeContainer.js.map