@civic/auth 0.2.2-beta.3 → 0.2.2-beta.4

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 (60) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/dist/cjs/reactjs/components/ButtonContentOrLoader.d.ts +7 -0
  3. package/dist/cjs/reactjs/components/ButtonContentOrLoader.d.ts.map +1 -0
  4. package/dist/cjs/reactjs/components/ButtonContentOrLoader.js +34 -0
  5. package/dist/cjs/reactjs/components/ButtonContentOrLoader.js.map +1 -0
  6. package/dist/cjs/reactjs/components/LoadingSpinner.d.ts +7 -0
  7. package/dist/cjs/reactjs/components/LoadingSpinner.d.ts.map +1 -0
  8. package/dist/cjs/reactjs/components/LoadingSpinner.js +33 -0
  9. package/dist/cjs/reactjs/components/LoadingSpinner.js.map +1 -0
  10. package/dist/cjs/reactjs/components/SignInButton.d.ts.map +1 -1
  11. package/dist/cjs/reactjs/components/SignInButton.js +4 -3
  12. package/dist/cjs/reactjs/components/SignInButton.js.map +1 -1
  13. package/dist/cjs/reactjs/components/SignOutButton.d.ts.map +1 -1
  14. package/dist/cjs/reactjs/components/SignOutButton.js +4 -3
  15. package/dist/cjs/reactjs/components/SignOutButton.js.map +1 -1
  16. package/dist/cjs/reactjs/components/UserButton.d.ts.map +1 -1
  17. package/dist/cjs/reactjs/components/UserButton.js +29 -30
  18. package/dist/cjs/reactjs/components/UserButton.js.map +1 -1
  19. package/dist/cjs/shared/components/CivicAuthIframeContainer.d.ts.map +1 -1
  20. package/dist/cjs/shared/components/CivicAuthIframeContainer.js +5 -1
  21. package/dist/cjs/shared/components/CivicAuthIframeContainer.js.map +1 -1
  22. package/dist/cjs/shared/hooks/useSignIn.d.ts.map +1 -1
  23. package/dist/cjs/shared/hooks/useSignIn.js +18 -4
  24. package/dist/cjs/shared/hooks/useSignIn.js.map +1 -1
  25. package/dist/cjs/shared/providers/IframeProvider.d.ts +2 -0
  26. package/dist/cjs/shared/providers/IframeProvider.d.ts.map +1 -1
  27. package/dist/cjs/shared/providers/IframeProvider.js +5 -0
  28. package/dist/cjs/shared/providers/IframeProvider.js.map +1 -1
  29. package/dist/cjs/shared/version.d.ts +1 -1
  30. package/dist/cjs/shared/version.js +1 -1
  31. package/dist/cjs/shared/version.js.map +1 -1
  32. package/dist/esm/reactjs/components/ButtonContentOrLoader.d.ts +7 -0
  33. package/dist/esm/reactjs/components/ButtonContentOrLoader.d.ts.map +1 -0
  34. package/dist/esm/reactjs/components/ButtonContentOrLoader.js +27 -0
  35. package/dist/esm/reactjs/components/ButtonContentOrLoader.js.map +1 -0
  36. package/dist/esm/reactjs/components/SignInButton.d.ts.map +1 -1
  37. package/dist/esm/reactjs/components/SignInButton.js +4 -3
  38. package/dist/esm/reactjs/components/SignInButton.js.map +1 -1
  39. package/dist/esm/reactjs/components/SignOutButton.d.ts.map +1 -1
  40. package/dist/esm/reactjs/components/SignOutButton.js +4 -3
  41. package/dist/esm/reactjs/components/SignOutButton.js.map +1 -1
  42. package/dist/esm/reactjs/components/UserButton.d.ts.map +1 -1
  43. package/dist/esm/reactjs/components/UserButton.js +29 -30
  44. package/dist/esm/reactjs/components/UserButton.js.map +1 -1
  45. package/dist/esm/shared/components/CivicAuthIframeContainer.d.ts.map +1 -1
  46. package/dist/esm/shared/components/CivicAuthIframeContainer.js +5 -1
  47. package/dist/esm/shared/components/CivicAuthIframeContainer.js.map +1 -1
  48. package/dist/esm/shared/hooks/useSignIn.d.ts.map +1 -1
  49. package/dist/esm/shared/hooks/useSignIn.js +18 -4
  50. package/dist/esm/shared/hooks/useSignIn.js.map +1 -1
  51. package/dist/esm/shared/providers/IframeProvider.d.ts +2 -0
  52. package/dist/esm/shared/providers/IframeProvider.d.ts.map +1 -1
  53. package/dist/esm/shared/providers/IframeProvider.js +5 -0
  54. package/dist/esm/shared/providers/IframeProvider.js.map +1 -1
  55. package/dist/esm/shared/version.d.ts +1 -1
  56. package/dist/esm/shared/version.js +1 -1
  57. package/dist/esm/shared/version.js.map +1 -1
  58. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  59. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  60. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
- # 0.2.2 isSigningOut flag
1
+ # 0.2.2 isSigningOut, isSigningIn flags and UserButton updates
2
2
  - expose isSigningIn and isSigningOut flag from useUser
3
- - show loading icon in UserButton during sign in and sign out
3
+ - show loading icon in UserButton, SignInButton and SignOutButton during sign in and sign out
4
4
 
5
5
  # 0.2.1 Server getTokens
6
6
  - expose server/getTokens function
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ export declare const ButtonContentOrLoader: ({ isSigningOut, isSigningIn, children, }: {
3
+ isSigningOut: boolean;
4
+ isSigningIn: boolean;
5
+ children: React.ReactNode;
6
+ }) => React.JSX.Element;
7
+ //# sourceMappingURL=ButtonContentOrLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonContentOrLoader.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/components/ButtonContentOrLoader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,eAAO,MAAM,qBAAqB,6CAI/B;IACD,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,sBAoCA,CAAC"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ "use client";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ButtonContentOrLoader = void 0;
8
+ const react_1 = __importDefault(require("react"));
9
+ const LoadingIcon_js_1 = require("../../shared/components/LoadingIcon.js");
10
+ const ButtonContentOrLoader = ({ isSigningOut, isSigningIn, children, }) => {
11
+ return (react_1.default.createElement("div", { style: {
12
+ position: "relative",
13
+ display: "flex",
14
+ alignItems: "center",
15
+ justifyContent: "center",
16
+ } },
17
+ react_1.default.createElement("span", { style: {
18
+ visibility: isSigningOut || isSigningIn ? "hidden" : "visible",
19
+ whiteSpace: "nowrap",
20
+ } }, children),
21
+ (isSigningOut || isSigningIn) && (react_1.default.createElement("span", { style: {
22
+ position: "absolute",
23
+ display: "flex",
24
+ justifyContent: "center",
25
+ alignItems: "center",
26
+ top: 0,
27
+ left: 0,
28
+ right: 0,
29
+ bottom: 0,
30
+ } },
31
+ react_1.default.createElement(LoadingIcon_js_1.LoadingIcon, { width: "1.5em", height: "1.5em" })))));
32
+ };
33
+ exports.ButtonContentOrLoader = ButtonContentOrLoader;
34
+ //# sourceMappingURL=ButtonContentOrLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonContentOrLoader.js","sourceRoot":"","sources":["../../../../src/reactjs/components/ButtonContentOrLoader.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;AACb,kDAA0B;AAC1B,uEAAiE;AAE1D,MAAM,qBAAqB,GAAG,CAAC,EACpC,YAAY,EACZ,WAAW,EACX,QAAQ,GAKT,EAAE,EAAE;IACH,OAAO,CACL,uCACE,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;SACzB;QAED,wCACE,KAAK,EAAE;gBACL,UAAU,EAAE,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBAC9D,UAAU,EAAE,QAAQ;aACrB,IAEA,QAAQ,CACJ;QACN,CAAC,YAAY,IAAI,WAAW,CAAC,IAAI,CAChC,wCACE,KAAK,EAAE;gBACL,QAAQ,EAAE,UAAU;gBACpB,OAAO,EAAE,MAAM;gBACf,cAAc,EAAE,QAAQ;gBACxB,UAAU,EAAE,QAAQ;gBACpB,GAAG,EAAE,CAAC;gBACN,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,CAAC;gBACR,MAAM,EAAE,CAAC;aACV;YAED,8BAAC,4BAAW,IAAC,KAAK,EAAC,OAAO,EAAC,MAAM,EAAC,OAAO,GAAG,CACvC,CACR,CACG,CACP,CAAC;AACJ,CAAC,CAAC;AA5CW,QAAA,qBAAqB,yBA4ChC","sourcesContent":["\"use client\";\nimport React from \"react\";\nimport { LoadingIcon } from \"@/shared/components/LoadingIcon.js\";\n\nexport const ButtonContentOrLoader = ({\n isSigningOut,\n isSigningIn,\n children,\n}: {\n isSigningOut: boolean;\n isSigningIn: boolean;\n children: React.ReactNode;\n}) => {\n return (\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <span\n style={{\n visibility: isSigningOut || isSigningIn ? \"hidden\" : \"visible\",\n whiteSpace: \"nowrap\",\n }}\n >\n {children}\n </span>\n {(isSigningOut || isSigningIn) && (\n <span\n style={{\n position: \"absolute\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n }}\n >\n <LoadingIcon width=\"1.5em\" height=\"1.5em\" />\n </span>\n )}\n </div>\n );\n};\n"]}
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ export declare const ButtonContentOrSpinner: ({ isSigningOut, isSigningIn, children, }: {
3
+ isSigningOut: any;
4
+ isSigningIn: any;
5
+ children: any;
6
+ }) => React.JSX.Element;
7
+ //# sourceMappingURL=LoadingSpinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingSpinner.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/components/LoadingSpinner.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,eAAO,MAAM,sBAAsB;;;;uBAuClC,CAAC"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ "use client";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ButtonContentOrSpinner = void 0;
8
+ const react_1 = __importDefault(require("react"));
9
+ const LoadingIcon_js_1 = require("../../shared/components/LoadingIcon.js");
10
+ const ButtonContentOrSpinner = ({ isSigningOut, isSigningIn, children, }) => {
11
+ return (react_1.default.createElement("div", { style: {
12
+ position: "relative",
13
+ display: "flex",
14
+ alignItems: "center",
15
+ } },
16
+ react_1.default.createElement("span", { style: {
17
+ visibility: isSigningOut || isSigningIn ? "hidden" : "visible",
18
+ whiteSpace: "nowrap",
19
+ } }, children),
20
+ (isSigningOut || isSigningIn) && (react_1.default.createElement("span", { style: {
21
+ position: "absolute",
22
+ display: "flex",
23
+ justifyContent: "center",
24
+ alignItems: "center",
25
+ top: 0,
26
+ left: 0,
27
+ right: 0,
28
+ bottom: 0,
29
+ } },
30
+ react_1.default.createElement(LoadingIcon_js_1.LoadingIcon, { width: "1.5em", height: "1.5em" })))));
31
+ };
32
+ exports.ButtonContentOrSpinner = ButtonContentOrSpinner;
33
+ //# sourceMappingURL=LoadingSpinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingSpinner.js","sourceRoot":"","sources":["../../../../src/reactjs/components/LoadingSpinner.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;AACb,kDAA0B;AAC1B,uEAAiE;AAE1D,MAAM,sBAAsB,GAAG,CAAC,EACrC,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,EAAE,EAAE;IACH,OAAO,CACL,uCACE,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;SACrB;QAED,wCACE,KAAK,EAAE;gBACL,UAAU,EAAE,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBAC9D,UAAU,EAAE,QAAQ;aACrB,IAEA,QAAQ,CACJ;QACN,CAAC,YAAY,IAAI,WAAW,CAAC,IAAI,CAChC,wCACE,KAAK,EAAE;gBACL,QAAQ,EAAE,UAAU;gBACpB,OAAO,EAAE,MAAM;gBACf,cAAc,EAAE,QAAQ;gBACxB,UAAU,EAAE,QAAQ;gBACpB,GAAG,EAAE,CAAC;gBACN,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,CAAC;gBACR,MAAM,EAAE,CAAC;aACV;YAED,8BAAC,4BAAW,IAAC,KAAK,EAAC,OAAO,EAAC,MAAM,EAAC,OAAO,GAAG,CACvC,CACR,CACG,CACP,CAAC;AACJ,CAAC,CAAC;AAvCW,QAAA,sBAAsB,0BAuCjC","sourcesContent":["\"use client\";\nimport React from \"react\";\nimport { LoadingIcon } from \"@/shared/components/LoadingIcon.js\";\n\nexport const ButtonContentOrSpinner = ({\n isSigningOut,\n isSigningIn,\n children,\n}) => {\n return (\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n visibility: isSigningOut || isSigningIn ? \"hidden\" : \"visible\",\n whiteSpace: \"nowrap\",\n }}\n >\n {children}\n </span>\n {(isSigningOut || isSigningIn) && (\n <span\n style={{\n position: \"absolute\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n }}\n >\n <LoadingIcon width=\"1.5em\" height=\"1.5em\" />\n </span>\n )}\n </div>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"SignInButton.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/components/SignInButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,QAAA,MAAM,YAAY,gCAGf;IACD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,sBAmBA,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"SignInButton.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/components/SignInButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,QAAA,MAAM,YAAY,gCAGf;IACD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,sBAwBA,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -7,16 +7,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.SignInButton = void 0;
8
8
  const react_1 = __importDefault(require("react"));
9
9
  const useUser_js_1 = require("../../reactjs/hooks/useUser.js");
10
- const LoadingIcon_js_1 = require("../../shared/components/LoadingIcon.js");
10
+ const ButtonContentOrLoader_js_1 = require("./ButtonContentOrLoader.js");
11
11
  const SignInButton = ({ displayMode, className, }) => {
12
- const { signIn, isSigningIn } = (0, useUser_js_1.useUser)();
12
+ const { signIn, isSigningIn, isSigningOut } = (0, useUser_js_1.useUser)();
13
13
  return (react_1.default.createElement("button", { "data-testid": "sign-in-button", style: {
14
14
  borderRadius: "9999px",
15
15
  border: "1px solid #6b7280",
16
16
  padding: "0.75rem 1rem",
17
17
  transition: "background-color 0.2s",
18
18
  minWidth: "9em", // this stops the button from going too small when in loading mode
19
- }, className: className, onClick: () => signIn(displayMode) }, isSigningIn ? react_1.default.createElement(LoadingIcon_js_1.LoadingIcon, { width: "1.5em", height: "1.5em" }) : "Sign In"));
19
+ }, className: className, onClick: () => signIn(displayMode) },
20
+ react_1.default.createElement(ButtonContentOrLoader_js_1.ButtonContentOrLoader, { isSigningOut: isSigningOut, isSigningIn: isSigningIn }, "Sign In")));
20
21
  };
21
22
  exports.SignInButton = SignInButton;
22
23
  //# sourceMappingURL=SignInButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SignInButton.js","sourceRoot":"","sources":["../../../../src/reactjs/components/SignInButton.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;AACb,kDAA0B;AAE1B,2DAAqD;AACrD,uEAAiE;AAEjE,MAAM,YAAY,GAAG,CAAC,EACpB,WAAW,EACX,SAAS,GAIV,EAAE,EAAE;IACH,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAA,oBAAO,GAAE,CAAC;IAE1C,OAAO,CACL,yDACc,gBAAgB,EAC5B,KAAK,EAAE;YACL,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,cAAc;YACvB,UAAU,EAAE,uBAAuB;YACnC,QAAQ,EAAE,KAAK,EAAE,kEAAkE;SACpF,EACD,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,IAEjC,WAAW,CAAC,CAAC,CAAC,8BAAC,4BAAW,IAAC,KAAK,EAAC,OAAO,EAAC,MAAM,EAAC,OAAO,GAAG,CAAC,CAAC,CAAC,SAAS,CAChE,CACV,CAAC;AACJ,CAAC,CAAC;AAEO,oCAAY","sourcesContent":["\"use client\";\nimport React from \"react\";\nimport type { DisplayMode } from \"@/types.js\";\nimport { useUser } from \"@/reactjs/hooks/useUser.js\";\nimport { LoadingIcon } from \"@/shared/components/LoadingIcon.js\";\n\nconst SignInButton = ({\n displayMode,\n className,\n}: {\n displayMode?: DisplayMode;\n className?: string;\n}) => {\n const { signIn, isSigningIn } = useUser();\n\n return (\n <button\n data-testid=\"sign-in-button\"\n style={{\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n transition: \"background-color 0.2s\",\n minWidth: \"9em\", // this stops the button from going too small when in loading mode\n }}\n className={className}\n onClick={() => signIn(displayMode)}\n >\n {isSigningIn ? <LoadingIcon width=\"1.5em\" height=\"1.5em\" /> : \"Sign In\"}\n </button>\n );\n};\n\nexport { SignInButton };\n"]}
1
+ {"version":3,"file":"SignInButton.js","sourceRoot":"","sources":["../../../../src/reactjs/components/SignInButton.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;AACb,kDAA0B;AAE1B,2DAAqD;AACrD,yEAAmE;AAEnE,MAAM,YAAY,GAAG,CAAC,EACpB,WAAW,EACX,SAAS,GAIV,EAAE,EAAE;IACH,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,IAAA,oBAAO,GAAE,CAAC;IAExD,OAAO,CACL,yDACc,gBAAgB,EAC5B,KAAK,EAAE;YACL,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,cAAc;YACvB,UAAU,EAAE,uBAAuB;YACnC,QAAQ,EAAE,KAAK,EAAE,kEAAkE;SACpF,EACD,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;QAElC,8BAAC,gDAAqB,IACpB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,WAAW,cAGF,CACjB,CACV,CAAC;AACJ,CAAC,CAAC;AAEO,oCAAY","sourcesContent":["\"use client\";\nimport React from \"react\";\nimport type { DisplayMode } from \"@/types.js\";\nimport { useUser } from \"@/reactjs/hooks/useUser.js\";\nimport { ButtonContentOrLoader } from \"./ButtonContentOrLoader.js\";\n\nconst SignInButton = ({\n displayMode,\n className,\n}: {\n displayMode?: DisplayMode;\n className?: string;\n}) => {\n const { signIn, isSigningIn, isSigningOut } = useUser();\n\n return (\n <button\n data-testid=\"sign-in-button\"\n style={{\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n transition: \"background-color 0.2s\",\n minWidth: \"9em\", // this stops the button from going too small when in loading mode\n }}\n className={className}\n onClick={() => signIn(displayMode)}\n >\n <ButtonContentOrLoader\n isSigningOut={isSigningOut}\n isSigningIn={isSigningIn}\n >\n Sign In\n </ButtonContentOrLoader>\n </button>\n );\n};\n\nexport { SignInButton };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"SignOutButton.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/components/SignOutButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,QAAA,MAAM,aAAa,kBAAmB;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sBAiB3D,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"SignOutButton.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/components/SignOutButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,QAAA,MAAM,aAAa,kBAAmB;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sBAsB3D,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -7,15 +7,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.SignOutButton = void 0;
8
8
  const react_1 = __importDefault(require("react"));
9
9
  const useUser_js_1 = require("../../reactjs/hooks/useUser.js");
10
- const LoadingIcon_js_1 = require("../../shared/components/LoadingIcon.js");
10
+ const ButtonContentOrLoader_js_1 = require("./ButtonContentOrLoader.js");
11
11
  const SignOutButton = ({ className }) => {
12
- const { signOut, isSigningOut } = (0, useUser_js_1.useUser)();
12
+ const { signOut, isSigningOut, isSigningIn } = (0, useUser_js_1.useUser)();
13
13
  return (react_1.default.createElement("button", { style: {
14
14
  borderRadius: "9999px",
15
15
  border: "1px solid #6b7280",
16
16
  padding: "0.75rem 1rem",
17
17
  transition: "background-color 0.2s",
18
- }, className: className, onClick: () => signOut() }, isSigningOut ? react_1.default.createElement(LoadingIcon_js_1.LoadingIcon, { width: "1.5em", height: "1.5em" }) : "Sign Out"));
18
+ }, className: className, onClick: () => signOut() },
19
+ react_1.default.createElement(ButtonContentOrLoader_js_1.ButtonContentOrLoader, { isSigningOut: isSigningOut, isSigningIn: isSigningIn }, "Sign Out")));
19
20
  };
20
21
  exports.SignOutButton = SignOutButton;
21
22
  //# sourceMappingURL=SignOutButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SignOutButton.js","sourceRoot":"","sources":["../../../../src/reactjs/components/SignOutButton.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;AACb,kDAA0B;AAC1B,2DAAqD;AACrD,uEAAiE;AAEjE,MAAM,aAAa,GAAG,CAAC,EAAE,SAAS,EAA0B,EAAE,EAAE;IAC9D,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,IAAA,oBAAO,GAAE,CAAC;IAE5C,OAAO,CACL,0CACE,KAAK,EAAE;YACL,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,cAAc;YACvB,UAAU,EAAE,uBAAuB;SACpC,EACD,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,IAEvB,YAAY,CAAC,CAAC,CAAC,8BAAC,4BAAW,IAAC,KAAK,EAAC,OAAO,EAAC,MAAM,EAAC,OAAO,GAAG,CAAC,CAAC,CAAC,UAAU,CAClE,CACV,CAAC;AACJ,CAAC,CAAC;AAEO,sCAAa","sourcesContent":["\"use client\";\nimport React from \"react\";\nimport { useUser } from \"@/reactjs/hooks/useUser.js\";\nimport { LoadingIcon } from \"@/shared/components/LoadingIcon.js\";\n\nconst SignOutButton = ({ className }: { className?: string }) => {\n const { signOut, isSigningOut } = useUser();\n\n return (\n <button\n style={{\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n transition: \"background-color 0.2s\",\n }}\n className={className}\n onClick={() => signOut()}\n >\n {isSigningOut ? <LoadingIcon width=\"1.5em\" height=\"1.5em\" /> : \"Sign Out\"}\n </button>\n );\n};\n\nexport { SignOutButton };\n"]}
1
+ {"version":3,"file":"SignOutButton.js","sourceRoot":"","sources":["../../../../src/reactjs/components/SignOutButton.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;AACb,kDAA0B;AAC1B,2DAAqD;AACrD,yEAAmE;AAEnE,MAAM,aAAa,GAAG,CAAC,EAAE,SAAS,EAA0B,EAAE,EAAE;IAC9D,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,IAAA,oBAAO,GAAE,CAAC;IAEzD,OAAO,CACL,0CACE,KAAK,EAAE;YACL,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,cAAc;YACvB,UAAU,EAAE,uBAAuB;SACpC,EACD,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE;QAExB,8BAAC,gDAAqB,IACpB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,WAAW,eAGF,CACjB,CACV,CAAC;AACJ,CAAC,CAAC;AAEO,sCAAa","sourcesContent":["\"use client\";\nimport React from \"react\";\nimport { useUser } from \"@/reactjs/hooks/useUser.js\";\nimport { ButtonContentOrLoader } from \"./ButtonContentOrLoader.js\";\n\nconst SignOutButton = ({ className }: { className?: string }) => {\n const { signOut, isSigningOut, isSigningIn } = useUser();\n\n return (\n <button\n style={{\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n transition: \"background-color 0.2s\",\n }}\n className={className}\n onClick={() => signOut()}\n >\n <ButtonContentOrLoader\n isSigningOut={isSigningOut}\n isSigningIn={isSigningIn}\n >\n Sign Out\n </ButtonContentOrLoader>\n </button>\n );\n};\n\nexport { SignOutButton };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"UserButton.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/components/UserButton.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAoCxE,QAAA,MAAM,UAAU,kBAAmB;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sBAyNxD,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"UserButton.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/components/UserButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAqCxE,QAAA,MAAM,UAAU,kBAAmB;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sBAsNxD,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -36,8 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.UserButton = void 0;
38
38
  const index_js_1 = require("../../reactjs/hooks/index.js");
39
- const LoadingIcon_js_1 = require("../../shared/components/LoadingIcon.js");
40
39
  const react_1 = __importStar(require("react"));
40
+ const ButtonContentOrLoader_js_1 = require("./ButtonContentOrLoader.js");
41
41
  const ChevronDown = () => (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-chevron-down" },
42
42
  react_1.default.createElement("path", { d: "m6 9 6 6 6-6" })));
43
43
  const ChevronUp = () => (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-chevron-up" },
@@ -63,12 +63,12 @@ const UserButton = ({ className }) => {
63
63
  }
64
64
  }, []);
65
65
  const handleSignOut = (0, react_1.useCallback)(async () => {
66
- await signOut();
67
66
  setIsOpen(false);
67
+ await signOut();
68
68
  }, [signOut]);
69
69
  const handleSignIn = (0, react_1.useCallback)(async () => {
70
- await signIn();
71
70
  setIsOpen(false);
71
+ await signIn();
72
72
  }, [signIn]);
73
73
  const handleEscape = (0, react_1.useCallback)((event) => {
74
74
  if (event.key === "Escape") {
@@ -101,32 +101,30 @@ const UserButton = ({ className }) => {
101
101
  background: "none",
102
102
  transition: "background-color 0.2s",
103
103
  }, className: className, onMouseEnter: (e) => (e.currentTarget.style.backgroundColor = "#f3f4f6"), onMouseLeave: (e) => (e.currentTarget.style.backgroundColor = "transparent"), onClick: () => {
104
- setIsOpen((isOpen) => !isOpen);
105
- } }, isSigningOut ? (react_1.default.createElement("span", { style: {
106
- display: "flex",
107
- justifyContent: "center",
108
- alignItems: "center",
109
- height: "100%",
110
- width: "100%",
104
+ !isSigningOut && setIsOpen((isOpen) => !isOpen);
111
105
  } },
112
- react_1.default.createElement(LoadingIcon_js_1.LoadingIcon, { width: "1.5em", height: "1.5em" }))) : (react_1.default.createElement(react_1.default.Fragment, null,
113
- user?.picture ? (react_1.default.createElement("span", { style: {
114
- position: "relative",
115
- display: "flex",
116
- height: "1.5rem",
117
- width: "1.5rem",
118
- flexShrink: 0,
119
- gap: "0.5rem",
120
- overflow: "hidden",
121
- borderRadius: "9999px",
122
- } },
123
- react_1.default.createElement("img", { style: {
124
- height: "100%",
125
- width: "100%",
126
- objectFit: "cover",
127
- }, src: user.picture, alt: user?.name || user?.email }))) : (react_1.default.createElement("span", { style: { display: "block" } })),
128
- react_1.default.createElement("span", null, user?.name || user?.email),
129
- react_1.default.createElement("span", { style: { display: "block", pointerEvents: "none" } }, isOpen ? react_1.default.createElement(ChevronUp, null) : react_1.default.createElement(ChevronDown, null))))),
106
+ react_1.default.createElement(react_1.default.Fragment, null,
107
+ user?.picture ? (react_1.default.createElement("span", { style: {
108
+ position: "relative",
109
+ display: "flex",
110
+ height: "1.5rem",
111
+ width: "1.5rem",
112
+ flexShrink: 0,
113
+ gap: "0.5rem",
114
+ overflow: "hidden",
115
+ borderRadius: "9999px",
116
+ } },
117
+ react_1.default.createElement("img", { style: {
118
+ height: "100%",
119
+ width: "100%",
120
+ objectFit: "cover",
121
+ }, src: user.picture, alt: user?.name || user?.email }))) : (react_1.default.createElement("span", { style: { display: "block" } })),
122
+ react_1.default.createElement(ButtonContentOrLoader_js_1.ButtonContentOrLoader, { isSigningOut: isSigningOut, isSigningIn: isSigningIn }, user?.name || user?.email),
123
+ react_1.default.createElement("span", { style: {
124
+ display: "block",
125
+ pointerEvents: "none",
126
+ visibility: isSigningOut || isSigningIn ? "hidden" : "visible",
127
+ } }, isOpen ? react_1.default.createElement(ChevronUp, null) : react_1.default.createElement(ChevronDown, null)))),
130
128
  react_1.default.createElement("div", { ref: dropdownRef, style: isOpen
131
129
  ? {
132
130
  position: "absolute",
@@ -152,7 +150,7 @@ const UserButton = ({ className }) => {
152
150
  border: "none",
153
151
  textAlign: "center",
154
152
  cursor: "pointer",
155
- }, onClick: handleSignOut, onMouseEnter: (e) => (e.currentTarget.style.backgroundColor = "#f3f4f6"), onMouseLeave: (e) => (e.currentTarget.style.backgroundColor = "transparent") }, "Logout"))))));
153
+ }, onClick: () => !(isSigningOut || isSigningIn) && handleSignOut(), onMouseEnter: (e) => (e.currentTarget.style.backgroundColor = "#f3f4f6"), onMouseLeave: (e) => (e.currentTarget.style.backgroundColor = "transparent") }, "Logout"))))));
156
154
  }
157
155
  return (react_1.default.createElement("button", { ref: buttonRef, "data-testid": "sign-in-button", style: {
158
156
  cursor: "pointer",
@@ -162,7 +160,8 @@ const UserButton = ({ className }) => {
162
160
  background: "none",
163
161
  transition: "background-color 0.2s",
164
162
  minWidth: "9em", // this stops the button from going too small when in loading mode
165
- }, className: className, onMouseEnter: (e) => (e.currentTarget.style.backgroundColor = "#f3f4f6"), onMouseLeave: (e) => (e.currentTarget.style.backgroundColor = "transparent"), onClick: handleSignIn }, isSigningOut || isSigningIn ? (react_1.default.createElement(LoadingIcon_js_1.LoadingIcon, { width: "1.5em", height: "1.5em" })) : ("Sign in")));
163
+ }, className: className, onMouseEnter: (e) => (e.currentTarget.style.backgroundColor = "#f3f4f6"), onMouseLeave: (e) => (e.currentTarget.style.backgroundColor = "transparent"), onClick: () => !(isSigningOut || isSigningIn) && handleSignIn() },
164
+ react_1.default.createElement(ButtonContentOrLoader_js_1.ButtonContentOrLoader, { isSigningOut: isSigningOut, isSigningIn: isSigningIn }, "Sign in")));
166
165
  };
167
166
  exports.UserButton = UserButton;
168
167
  //# sourceMappingURL=UserButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserButton.js","sourceRoot":"","sources":["../../../../src/reactjs/components/UserButton.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACb,uDAAmD;AACnD,uEAAiE;AACjE,+CAAwE;AAExE,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,CACxB,uCACE,KAAK,EAAC,4BAA4B,EAClC,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,SAAS,EAAC,4BAA4B;IAEtC,wCAAM,CAAC,EAAC,cAAc,GAAG,CACrB,CACP,CAAC;AAEF,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,CACtB,uCACE,KAAK,EAAC,4BAA4B,EAClC,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,SAAS,EAAC,0BAA0B;IAEpC,wCAAM,CAAC,EAAC,gBAAgB,GAAG,CACvB,CACP,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,EAAE,SAAS,EAA0B,EAAE,EAAE;IAC3D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,IAAA,gBAAQ,EAAgB,IAAI,CAAC,CAAC;IACpE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,IAAA,kBAAO,GAAE,CAAC;IACvE,MAAM,SAAS,GAAG,IAAA,cAAM,EAAoB,IAAI,CAAC,CAAC;IAClD,MAAM,WAAW,GAAG,IAAA,cAAM,EAAiB,IAAI,CAAC,CAAC;IAEjD,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,kBAAkB,GAAG,IAAA,mBAAW,EAAC,CAAC,KAAiB,EAAE,EAAE;QAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB,CAAC;QAE3C,IACE,SAAS,CAAC,OAAO;YACjB,WAAW,CAAC,OAAO;YACnB,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;YACnC,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EACrC,CAAC;YACD,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,aAAa,GAAG,IAAA,mBAAW,EAAC,KAAK,IAAI,EAAE;QAC3C,MAAM,OAAO,EAAE,CAAC;QAEhB,SAAS,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,MAAM,YAAY,GAAG,IAAA,mBAAW,EAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,MAAM,EAAE,CAAC;QAEf,SAAS,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,YAAY,GAAG,IAAA,mBAAW,EAAC,CAAC,KAAoB,EAAE,EAAE;QACxD,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC3B,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;YAErD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;YAExD,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACtD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,kBAAkB,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAE/C,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CACL,uCACE,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,EAC9C,EAAE,EAAC,0BAA0B;YAE7B,0CACE,GAAG,EAAE,SAAS,EACd,KAAK,EAAE;oBACL,MAAM,EAAE,SAAS;oBACjB,OAAO,EAAE,MAAM;oBACf,QAAQ,EAAE,OAAO;oBACjB,UAAU,EAAE,QAAQ;oBACpB,cAAc,EAAE,eAAe;oBAC/B,GAAG,EAAE,QAAQ;oBACb,YAAY,EAAE,QAAQ;oBACtB,MAAM,EAAE,mBAAmB;oBAC3B,OAAO,EAAE,cAAc;oBACvB,KAAK,EAAE,SAAS;oBAChB,UAAU,EAAE,MAAM;oBAClB,UAAU,EAAE,uBAAuB;iBACpC,EACD,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAClB,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC,EAErD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAClB,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,GAAG,aAAa,CAAC,EAEzD,OAAO,EAAE,GAAG,EAAE;oBACZ,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;gBACjC,CAAC,IAEA,YAAY,CAAC,CAAC,CAAC,CACd,wCACE,KAAK,EAAE;oBACL,OAAO,EAAE,MAAM;oBACf,cAAc,EAAE,QAAQ;oBACxB,UAAU,EAAE,QAAQ;oBACpB,MAAM,EAAE,MAAM;oBACd,KAAK,EAAE,MAAM;iBACd;gBAED,8BAAC,4BAAW,IAAC,KAAK,EAAC,OAAO,EAAC,MAAM,EAAC,OAAO,GAAG,CACvC,CACR,CAAC,CAAC,CAAC,CACF;gBACG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CACf,wCACE,KAAK,EAAE;wBACL,QAAQ,EAAE,UAAU;wBACpB,OAAO,EAAE,MAAM;wBACf,MAAM,EAAE,QAAQ;wBAChB,KAAK,EAAE,QAAQ;wBACf,UAAU,EAAE,CAAC;wBACb,GAAG,EAAE,QAAQ;wBACb,QAAQ,EAAE,QAAQ;wBAClB,YAAY,EAAE,QAAQ;qBACvB;oBAED,uCACE,KAAK,EAAE;4BACL,MAAM,EAAE,MAAM;4BACd,KAAK,EAAE,MAAM;4BACb,SAAS,EAAE,OAAO;yBACnB,EACD,GAAG,EAAE,IAAI,CAAC,OAAO,EACjB,GAAG,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,KAAK,GAC9B,CACG,CACR,CAAC,CAAC,CAAC,CACF,wCAAM,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,GAAI,CACtC;gBAED,4CAAO,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,KAAK,CAAQ;gBAExC,wCAAM,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,IACrD,MAAM,CAAC,CAAC,CAAC,8BAAC,SAAS,OAAG,CAAC,CAAC,CAAC,8BAAC,WAAW,OAAG,CACpC,CACN,CACJ,CACM;YACT,uCACE,GAAG,EAAE,WAAW,EAChB,KAAK,EACH,MAAM;oBACJ,CAAC,CAAC;wBACE,QAAQ,EAAE,UAAU;wBACpB,IAAI,EAAE,CAAC;wBACP,KAAK,EAAE,WAAW,IAAI,MAAM;wBAC5B,SAAS,EAAE,QAAQ;wBACnB,YAAY,EAAE,QAAQ;wBACtB,eAAe,EAAE,OAAO;wBACxB,OAAO,EAAE,UAAU;wBACnB,KAAK,EAAE,SAAS;wBAChB,SAAS,EACP,yEAAyE;wBAC3E,MAAM,EAAE,IAAI;qBACb;oBACH,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;gBAGzB,sCAAI,KAAK,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;oBACzD;wBACE,0CACE,KAAK,EAAE;gCACL,OAAO,EAAE,OAAO;gCAChB,KAAK,EAAE,MAAM;gCACb,OAAO,EAAE,aAAa;gCACtB,UAAU,EAAE,uBAAuB;gCACnC,UAAU,EAAE,MAAM;gCAClB,MAAM,EAAE,MAAM;gCACd,SAAS,EAAE,QAAQ;gCACnB,MAAM,EAAE,SAAS;6BAClB,EACD,OAAO,EAAE,aAAa,EACtB,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAClB,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC,EAErD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAClB,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,GAAG,aAAa,CAAC,aAIlD,CACN,CACF,CACD,CACF,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,0CACE,GAAG,EAAE,SAAS,iBACF,gBAAgB,EAC5B,KAAK,EAAE;YACL,MAAM,EAAE,SAAS;YACjB,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,cAAc;YACvB,UAAU,EAAE,MAAM;YAClB,UAAU,EAAE,uBAAuB;YACnC,QAAQ,EAAE,KAAK,EAAE,kEAAkE;SACpF,EACD,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC,EACxE,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAClB,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,GAAG,aAAa,CAAC,EAEzD,OAAO,EAAE,YAAY,IAEpB,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,CAC7B,8BAAC,4BAAW,IAAC,KAAK,EAAC,OAAO,EAAC,MAAM,EAAC,OAAO,GAAG,CAC7C,CAAC,CAAC,CAAC,CACF,SAAS,CACV,CACM,CACV,CAAC;AACJ,CAAC,CAAC;AAEO,gCAAU","sourcesContent":["\"use client\";\nimport { useUser } from \"@/reactjs/hooks/index.js\";\nimport { LoadingIcon } from \"@/shared/components/LoadingIcon.js\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\n\nconst ChevronDown = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-chevron-down\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n\nconst ChevronUp = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-chevron-up\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n);\n\nconst UserButton = ({ className }: { className?: string }) => {\n const [isOpen, setIsOpen] = useState(false);\n const [buttonWidth, setButtonWidth] = useState<number | null>(null);\n const { user, signIn, signOut, isSigningOut, isSigningIn } = useUser();\n const buttonRef = useRef<HTMLButtonElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (buttonRef.current) {\n setButtonWidth(buttonRef.current.offsetWidth);\n }\n }, [isOpen]);\n\n const handleClickOutside = useCallback((event: MouseEvent) => {\n const target = event.target as HTMLElement;\n\n if (\n buttonRef.current &&\n dropdownRef.current &&\n !buttonRef.current.contains(target) &&\n !dropdownRef.current.contains(target)\n ) {\n setIsOpen(false);\n }\n }, []);\n\n const handleSignOut = useCallback(async () => {\n await signOut();\n\n setIsOpen(false);\n }, [signOut]);\n\n const handleSignIn = useCallback(async () => {\n await signIn();\n\n setIsOpen(false);\n }, [signIn]);\n\n const handleEscape = useCallback((event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n }, []);\n\n useEffect(() => {\n if (isOpen) {\n window.addEventListener(\"click\", handleClickOutside);\n\n window.addEventListener(\"keydown\", handleEscape);\n }\n\n return () => {\n window.removeEventListener(\"click\", handleClickOutside);\n\n window.removeEventListener(\"keydown\", handleEscape);\n };\n }, [handleClickOutside, handleEscape, isOpen]);\n\n if (user) {\n return (\n <div\n style={{ position: \"relative\", width: \"auto\" }}\n id=\"civic-dropdown-container\"\n >\n <button\n ref={buttonRef}\n style={{\n cursor: \"pointer\",\n display: \"flex\",\n minWidth: \"10rem\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"0.5rem\",\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n color: \"#6b7280\",\n background: \"none\",\n transition: \"background-color 0.2s\",\n }}\n className={className}\n onMouseEnter={(e) =>\n (e.currentTarget.style.backgroundColor = \"#f3f4f6\")\n }\n onMouseLeave={(e) =>\n (e.currentTarget.style.backgroundColor = \"transparent\")\n }\n onClick={() => {\n setIsOpen((isOpen) => !isOpen);\n }}\n >\n {isSigningOut ? (\n <span\n style={{\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n height: \"100%\",\n width: \"100%\",\n }}\n >\n <LoadingIcon width=\"1.5em\" height=\"1.5em\" />\n </span>\n ) : (\n <>\n {user?.picture ? (\n <span\n style={{\n position: \"relative\",\n display: \"flex\",\n height: \"1.5rem\",\n width: \"1.5rem\",\n flexShrink: 0,\n gap: \"0.5rem\",\n overflow: \"hidden\",\n borderRadius: \"9999px\",\n }}\n >\n <img\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\",\n }}\n src={user.picture}\n alt={user?.name || user?.email}\n />\n </span>\n ) : (\n <span style={{ display: \"block\" }} />\n )}\n\n <span>{user?.name || user?.email}</span>\n\n <span style={{ display: \"block\", pointerEvents: \"none\" }}>\n {isOpen ? <ChevronUp /> : <ChevronDown />}\n </span>\n </>\n )}\n </button>\n <div\n ref={dropdownRef}\n style={\n isOpen\n ? {\n position: \"absolute\",\n left: 0,\n width: buttonWidth || \"auto\",\n marginTop: \"0.5rem\",\n borderRadius: \"0.5rem\",\n backgroundColor: \"white\",\n padding: \"0.5rem 0\",\n color: \"#6b7280\",\n boxShadow:\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)\",\n zIndex: 1000,\n }\n : { display: \"none\" }\n }\n >\n <ul style={{ listStyleType: \"none\", margin: 0, padding: 0 }}>\n <li>\n <button\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"0.5rem 1rem\",\n transition: \"background-color 0.2s\",\n background: \"none\",\n border: \"none\",\n textAlign: \"center\",\n cursor: \"pointer\",\n }}\n onClick={handleSignOut}\n onMouseEnter={(e) =>\n (e.currentTarget.style.backgroundColor = \"#f3f4f6\")\n }\n onMouseLeave={(e) =>\n (e.currentTarget.style.backgroundColor = \"transparent\")\n }\n >\n Logout\n </button>\n </li>\n </ul>\n </div>\n </div>\n );\n }\n\n return (\n <button\n ref={buttonRef}\n data-testid=\"sign-in-button\"\n style={{\n cursor: \"pointer\",\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n background: \"none\",\n transition: \"background-color 0.2s\",\n minWidth: \"9em\", // this stops the button from going too small when in loading mode\n }}\n className={className}\n onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = \"#f3f4f6\")}\n onMouseLeave={(e) =>\n (e.currentTarget.style.backgroundColor = \"transparent\")\n }\n onClick={handleSignIn}\n >\n {isSigningOut || isSigningIn ? (\n <LoadingIcon width=\"1.5em\" height=\"1.5em\" />\n ) : (\n \"Sign in\"\n )}\n </button>\n );\n};\n\nexport { UserButton };\n"]}
1
+ {"version":3,"file":"UserButton.js","sourceRoot":"","sources":["../../../../src/reactjs/components/UserButton.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport { useUser } from \"@/reactjs/hooks/index.js\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { ButtonContentOrLoader } from \"./ButtonContentOrLoader.js\";\n\nconst ChevronDown = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-chevron-down\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n\nconst ChevronUp = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-chevron-up\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n);\n\nconst UserButton = ({ className }: { className?: string }) => {\n const [isOpen, setIsOpen] = useState(false);\n const [buttonWidth, setButtonWidth] = useState<number | null>(null);\n const { user, signIn, signOut, isSigningOut, isSigningIn } = useUser();\n const buttonRef = useRef<HTMLButtonElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (buttonRef.current) {\n setButtonWidth(buttonRef.current.offsetWidth);\n }\n }, [isOpen]);\n\n const handleClickOutside = useCallback((event: MouseEvent) => {\n const target = event.target as HTMLElement;\n\n if (\n buttonRef.current &&\n dropdownRef.current &&\n !buttonRef.current.contains(target) &&\n !dropdownRef.current.contains(target)\n ) {\n setIsOpen(false);\n }\n }, []);\n\n const handleSignOut = useCallback(async () => {\n setIsOpen(false);\n await signOut();\n }, [signOut]);\n\n const handleSignIn = useCallback(async () => {\n setIsOpen(false);\n await signIn();\n }, [signIn]);\n\n const handleEscape = useCallback((event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n }, []);\n\n useEffect(() => {\n if (isOpen) {\n window.addEventListener(\"click\", handleClickOutside);\n\n window.addEventListener(\"keydown\", handleEscape);\n }\n\n return () => {\n window.removeEventListener(\"click\", handleClickOutside);\n\n window.removeEventListener(\"keydown\", handleEscape);\n };\n }, [handleClickOutside, handleEscape, isOpen]);\n\n if (user) {\n return (\n <div\n style={{ position: \"relative\", width: \"auto\" }}\n id=\"civic-dropdown-container\"\n >\n <button\n ref={buttonRef}\n style={{\n cursor: \"pointer\",\n display: \"flex\",\n minWidth: \"10rem\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"0.5rem\",\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n color: \"#6b7280\",\n background: \"none\",\n transition: \"background-color 0.2s\",\n }}\n className={className}\n onMouseEnter={(e) =>\n (e.currentTarget.style.backgroundColor = \"#f3f4f6\")\n }\n onMouseLeave={(e) =>\n (e.currentTarget.style.backgroundColor = \"transparent\")\n }\n onClick={() => {\n !isSigningOut && setIsOpen((isOpen) => !isOpen);\n }}\n >\n <>\n {user?.picture ? (\n <span\n style={{\n position: \"relative\",\n display: \"flex\",\n height: \"1.5rem\",\n width: \"1.5rem\",\n flexShrink: 0,\n gap: \"0.5rem\",\n overflow: \"hidden\",\n borderRadius: \"9999px\",\n }}\n >\n <img\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\",\n }}\n src={user.picture}\n alt={user?.name || user?.email}\n />\n </span>\n ) : (\n <span style={{ display: \"block\" }} />\n )}\n\n <ButtonContentOrLoader\n isSigningOut={isSigningOut}\n isSigningIn={isSigningIn}\n >\n {user?.name || user?.email}\n </ButtonContentOrLoader>\n <span\n style={{\n display: \"block\",\n pointerEvents: \"none\",\n visibility: isSigningOut || isSigningIn ? \"hidden\" : \"visible\",\n }}\n >\n {isOpen ? <ChevronUp /> : <ChevronDown />}\n </span>\n </>\n </button>\n <div\n ref={dropdownRef}\n style={\n isOpen\n ? {\n position: \"absolute\",\n left: 0,\n width: buttonWidth || \"auto\",\n marginTop: \"0.5rem\",\n borderRadius: \"0.5rem\",\n backgroundColor: \"white\",\n padding: \"0.5rem 0\",\n color: \"#6b7280\",\n boxShadow:\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)\",\n zIndex: 1000,\n }\n : { display: \"none\" }\n }\n >\n <ul style={{ listStyleType: \"none\", margin: 0, padding: 0 }}>\n <li>\n <button\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"0.5rem 1rem\",\n transition: \"background-color 0.2s\",\n background: \"none\",\n border: \"none\",\n textAlign: \"center\",\n cursor: \"pointer\",\n }}\n onClick={() =>\n !(isSigningOut || isSigningIn) && handleSignOut()\n }\n onMouseEnter={(e) =>\n (e.currentTarget.style.backgroundColor = \"#f3f4f6\")\n }\n onMouseLeave={(e) =>\n (e.currentTarget.style.backgroundColor = \"transparent\")\n }\n >\n Logout\n </button>\n </li>\n </ul>\n </div>\n </div>\n );\n }\n\n return (\n <button\n ref={buttonRef}\n data-testid=\"sign-in-button\"\n style={{\n cursor: \"pointer\",\n borderRadius: \"9999px\",\n border: \"1px solid #6b7280\",\n padding: \"0.75rem 1rem\",\n background: \"none\",\n transition: \"background-color 0.2s\",\n minWidth: \"9em\", // this stops the button from going too small when in loading mode\n }}\n className={className}\n onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = \"#f3f4f6\")}\n onMouseLeave={(e) =>\n (e.currentTarget.style.backgroundColor = \"transparent\")\n }\n onClick={() => !(isSigningOut || isSigningIn) && handleSignIn()}\n >\n <ButtonContentOrLoader\n isSigningOut={isSigningOut}\n isSigningIn={isSigningIn}\n >\n Sign in\n </ButtonContentOrLoader>\n </button>\n );\n};\n\nexport { UserButton };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CivicAuthIframeContainer.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframeContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAUxE,KAAK,6BAA6B,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAWF,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,OAAO,GACR,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,qBAsDA;AAED,QAAA,MAAM,wBAAwB,kCAG3B,6BAA6B,sBAiH/B,CAAC;AAEF,YAAY,EAAE,6BAA6B,EAAE,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
1
+ {"version":3,"file":"CivicAuthIframeContainer.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframeContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAUxE,KAAK,6BAA6B,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAWF,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,OAAO,GACR,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,qBA0DA;AAED,QAAA,MAAM,wBAAwB,kCAG3B,6BAA6B,sBAiH/B,CAAC;AAEF,YAAY,EAAE,6BAA6B,EAAE,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
@@ -49,6 +49,7 @@ function NoChrome({ children, }) {
49
49
  return react_1.default.createElement("div", { style: { position: "relative" } }, children);
50
50
  }
51
51
  function IframeChrome({ children, onClose, }) {
52
+ const { setIframeAborted } = (0, index_js_1.useIframe)();
52
53
  return (react_1.default.createElement("div", { style: {
53
54
  position: "fixed", // Change to fixed to stay in viewport
54
55
  left: 0,
@@ -83,7 +84,10 @@ function IframeChrome({ children, onClose, }) {
83
84
  backgroundColor: "transparent",
84
85
  padding: "0.25rem",
85
86
  color: "#9ca3af",
86
- }, onClick: onClose },
87
+ }, onClick: () => {
88
+ setIframeAborted(true);
89
+ onClose?.();
90
+ } },
87
91
  react_1.default.createElement(CloseIcon_js_1.CloseIcon, null)),
88
92
  children)));
89
93
  }
@@ -1 +1 @@
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 { TOKEN_EXCHANGE_TRIGGER_TEXT } from \"@/constants.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/index.js\";\nimport { useClientTokenExchangeSession } from \"@/shared/hooks/index.js\";\nimport { useSession } from \"@/shared/hooks/index.js\";\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 <div style={{ position: \"relative\" }}>{children}</div>;\n}\n\nexport function IframeChrome({\n children,\n onClose,\n}: {\n children: React.ReactNode;\n onClose?: () => void;\n}) {\n return (\n <div\n style={{\n position: \"fixed\", // Change to fixed to stay in viewport\n left: 0,\n top: 0,\n zIndex: 50,\n display: \"flex\",\n height: \"100vh\",\n width: \"100vw\",\n minWidth: \"18rem\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(17, 24, 39, 0.5)\", // Semi-transparent dark background\n backdropFilter: \"blur(4px)\", // Optional: adds slight blur to background\n }}\n onClick={onClose}\n >\n <div\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n borderRadius: \"1.5rem\",\n backgroundColor: \"white\",\n padding: \"1.5rem\",\n boxShadow:\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)\",\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n style={{\n position: \"absolute\",\n right: \"1rem\",\n top: \"1rem\",\n display: \"flex\",\n cursor: \"pointer\",\n alignItems: \"center\",\n justifyContent: \"center\",\n border: \"none\",\n backgroundColor: \"transparent\",\n padding: \"0.25rem\",\n color: \"#9ca3af\",\n }}\n onClick={onClose}\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 [isLoading, setIsLoading] = useState(true);\n const { isLoading: isAuthLoading, data: session } = useSession();\n const config = useCivicAuthConfig();\n const [tokenExchangeUrl, setTokenExchangeUrl] = useState<string | null>(null);\n const { doTokenExchange } = useClientTokenExchangeSession();\n const { iframeRef, iframeMode } = useIframe();\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 && iframeRef.current.contentWindow) {\n try {\n const iframeUrl = iframeRef.current.contentWindow.location.href;\n // we know that oauth has finished when the iframe redirects to our redirectUrl\n if (iframeUrl.startsWith(config.redirectUrl)) {\n // we still want to show the spinner during redirect\n setIsLoading(true);\n const iframeBody =\n iframeRef.current.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\n if (closeOnRedirect) onClose?.();\n return true; // Successfully processed the URL\n }\n } catch (e) {\n console.log(\"Waiting for redirect...\", e);\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\n return () => window.removeEventListener(\"keydown\", handleEscape);\n });\n\n const handleIframeLoad = useCallback(() => {\n setIsLoading(false);\n\n const iframeHasUrl = processIframeUrl();\n\n if (iframeHasUrl && intervalId.current) {\n clearInterval(intervalId.current);\n }\n }, [processIframeUrl, setIsLoading, intervalId]);\n\n // if we're already authenticated then we're waiting either for the iframe to be closed\n // or the page to redirect, so we want to show the loading icon\n const showLoadingIcon = session?.authenticated || isLoading || isAuthLoading;\n\n const WrapperComponent = iframeMode === \"embedded\" ? NoChrome : IframeChrome;\n\n return (\n <WrapperComponent onClose={onClose}>\n {showLoadingIcon ? (\n <div\n id=\"civic-auth-loading-icon-wrapper\"\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"white\",\n }}\n >\n <LoadingIcon />\n </div>\n ) : null}\n\n <CivicAuthIframe\n ref={iframeRef}\n id={\"civic-auth-iframe\"}\n onLoad={handleIframeLoad}\n />\n </WrapperComponent>\n );\n};\n\nexport type { CivicAuthIframeContainerProps };\n\nexport { CivicAuthIframeContainer };\n"]}
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 { TOKEN_EXCHANGE_TRIGGER_TEXT } from \"@/constants.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/index.js\";\nimport { useClientTokenExchangeSession } from \"@/shared/hooks/index.js\";\nimport { useSession } from \"@/shared/hooks/index.js\";\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 <div style={{ position: \"relative\" }}>{children}</div>;\n}\n\nexport function IframeChrome({\n children,\n onClose,\n}: {\n children: React.ReactNode;\n onClose?: () => void;\n}) {\n const { setIframeAborted } = useIframe();\n return (\n <div\n style={{\n position: \"fixed\", // Change to fixed to stay in viewport\n left: 0,\n top: 0,\n zIndex: 50,\n display: \"flex\",\n height: \"100vh\",\n width: \"100vw\",\n minWidth: \"18rem\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(17, 24, 39, 0.5)\", // Semi-transparent dark background\n backdropFilter: \"blur(4px)\", // Optional: adds slight blur to background\n }}\n onClick={onClose}\n >\n <div\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n borderRadius: \"1.5rem\",\n backgroundColor: \"white\",\n padding: \"1.5rem\",\n boxShadow:\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)\",\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n style={{\n position: \"absolute\",\n right: \"1rem\",\n top: \"1rem\",\n display: \"flex\",\n cursor: \"pointer\",\n alignItems: \"center\",\n justifyContent: \"center\",\n border: \"none\",\n backgroundColor: \"transparent\",\n padding: \"0.25rem\",\n color: \"#9ca3af\",\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 [isLoading, setIsLoading] = useState(true);\n const { isLoading: isAuthLoading, data: session } = useSession();\n const config = useCivicAuthConfig();\n const [tokenExchangeUrl, setTokenExchangeUrl] = useState<string | null>(null);\n const { doTokenExchange } = useClientTokenExchangeSession();\n const { iframeRef, iframeMode } = useIframe();\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 && iframeRef.current.contentWindow) {\n try {\n const iframeUrl = iframeRef.current.contentWindow.location.href;\n // we know that oauth has finished when the iframe redirects to our redirectUrl\n if (iframeUrl.startsWith(config.redirectUrl)) {\n // we still want to show the spinner during redirect\n setIsLoading(true);\n const iframeBody =\n iframeRef.current.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\n if (closeOnRedirect) onClose?.();\n return true; // Successfully processed the URL\n }\n } catch (e) {\n console.log(\"Waiting for redirect...\", e);\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\n return () => window.removeEventListener(\"keydown\", handleEscape);\n });\n\n const handleIframeLoad = useCallback(() => {\n setIsLoading(false);\n\n const iframeHasUrl = processIframeUrl();\n\n if (iframeHasUrl && intervalId.current) {\n clearInterval(intervalId.current);\n }\n }, [processIframeUrl, setIsLoading, intervalId]);\n\n // if we're already authenticated then we're waiting either for the iframe to be closed\n // or the page to redirect, so we want to show the loading icon\n const showLoadingIcon = session?.authenticated || isLoading || isAuthLoading;\n\n const WrapperComponent = iframeMode === \"embedded\" ? NoChrome : IframeChrome;\n\n return (\n <WrapperComponent onClose={onClose}>\n {showLoadingIcon ? (\n <div\n id=\"civic-auth-loading-icon-wrapper\"\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"white\",\n }}\n >\n <LoadingIcon />\n </div>\n ) : null}\n\n <CivicAuthIframe\n ref={iframeRef}\n id={\"civic-auth-iframe\"}\n onLoad={handleIframeLoad}\n />\n </WrapperComponent>\n );\n};\n\nexport type { CivicAuthIframeContainerProps };\n\nexport { CivicAuthIframeContainer };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"useSignIn.d.ts","sourceRoot":"","sources":["../../../../src/shared/hooks/useSignIn.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKpE,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,QAAA,MAAM,SAAS,4DAKZ,WAAW;kBAoEyB,OAAO,CAAC,IAAI,CAAC;;;;;CA8FnD,CAAC;AACF,OAAO,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"useSignIn.d.ts","sourceRoot":"","sources":["../../../../src/shared/hooks/useSignIn.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKpE,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,QAAA,MAAM,SAAS,4DAKZ,WAAW;kBAuEyB,OAAO,CAAC,IAAI,CAAC;;;;;CA+GnD,CAAC;AACF,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -12,7 +12,7 @@ const storage_js_1 = require("../../browser/storage.js");
12
12
  const util_js_1 = require("../lib/util.js");
13
13
  const useSignIn = ({ pkceConsumer, preSignOut, postSignOut, displayMode, }) => {
14
14
  const civicAuthConfig = (0, useCivicAuthConfig_js_1.useCivicAuthConfig)();
15
- const { iframeRef, logoutIframeRef, setIframeIsVisible, setLogoutIframeIsVisible, } = (0, useIframe_js_1.useIframe)();
15
+ const { iframeRef, logoutIframeRef, setIframeIsVisible, iframeIsVisible, setLogoutIframeIsVisible, iframeAborted, setIframeAborted, } = (0, useIframe_js_1.useIframe)();
16
16
  const { data: session } = (0, useSession_js_1.useSession)();
17
17
  const [isSigningOut, setIsSigningOut] = (0, react_1.useState)(false);
18
18
  const [isSigningIn, setIsSigningIn] = (0, react_1.useState)(false);
@@ -122,6 +122,21 @@ const useSignIn = ({ pkceConsumer, preSignOut, postSignOut, displayMode, }) => {
122
122
  preSignOut,
123
123
  logoutIframeRef,
124
124
  ]);
125
+ (0, react_1.useEffect)(() => {
126
+ if (isSigningIn) {
127
+ if (session?.authenticated ||
128
+ (displayMode === "iframe" && iframeAborted)) {
129
+ setIsSigningIn(false);
130
+ setIframeAborted(false);
131
+ }
132
+ }
133
+ }, [
134
+ displayMode,
135
+ iframeAborted,
136
+ isSigningIn,
137
+ session?.authenticated,
138
+ setIframeAborted,
139
+ ]);
125
140
  // handle logout finished
126
141
  (0, react_1.useEffect)(() => {
127
142
  if (isSigningOut && !session?.authenticated) {
@@ -131,15 +146,14 @@ const useSignIn = ({ pkceConsumer, preSignOut, postSignOut, displayMode, }) => {
131
146
  });
132
147
  return;
133
148
  }
134
- if (isSigningIn && session?.authenticated) {
135
- setIsSigningIn(false);
136
- }
137
149
  }, [
138
150
  session,
139
151
  postSignOut,
140
152
  isSigningOut,
141
153
  setLogoutIframeIsVisible,
142
154
  isSigningIn,
155
+ displayMode,
156
+ iframeIsVisible,
143
157
  ]);
144
158
  return {
145
159
  signIn,
@@ -1 +1 @@
1
- {"version":3,"file":"useSignIn.js","sourceRoot":"","sources":["../../../../src/shared/hooks/useSignIn.ts"],"names":[],"mappings":"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","sourcesContent":["import { BrowserAuthenticationInitiator } from \"@/services/AuthenticationService.js\";\nimport { BrowserPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/useCivicAuthConfig.js\";\nimport type { DisplayMode } from \"@/types.js\";\nimport { useIframe } from \"@/shared/hooks/useIframe.js\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { PopupError, type PKCEConsumer } from \"@/services/types.js\";\nimport { useSession } from \"./useSession.js\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport { clearTokens, clearUser } from \"../lib/util.js\";\n\ntype SignInProps = {\n pkceConsumer?: PKCEConsumer;\n preSignOut?: () => Promise<void>;\n postSignOut?: () => Promise<void>;\n displayMode: DisplayMode;\n};\nconst useSignIn = ({\n pkceConsumer,\n preSignOut,\n postSignOut,\n displayMode,\n}: SignInProps) => {\n const civicAuthConfig = useCivicAuthConfig();\n const {\n iframeRef,\n logoutIframeRef,\n setIframeIsVisible,\n setLogoutIframeIsVisible,\n } = useIframe();\n const { data: session } = useSession();\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [isSigningIn, setIsSigningIn] = useState(false);\n\n const authInitiator = useMemo(() => {\n if (!civicAuthConfig) {\n return null;\n }\n const {\n clientId,\n redirectUrl,\n logoutUrl,\n logoutRedirectUrl,\n nonce,\n oauthServer,\n endpoints,\n scopes,\n } = civicAuthConfig;\n return new BrowserAuthenticationInitiator({\n pkceConsumer: pkceConsumer || new BrowserPublicClientPKCEProducer(), // generate and retrieve the challenge client-side\n clientId,\n redirectUrl,\n logoutUrl,\n logoutRedirectUrl,\n scopes,\n displayMode,\n oauthServer,\n endpointOverrides: endpoints,\n nonce,\n });\n }, [civicAuthConfig, displayMode, pkceConsumer]);\n\n useEffect(() => {\n return () => {\n if (authInitiator) {\n authInitiator.cleanup();\n }\n };\n }, [authInitiator]);\n\n // This effect is used to clear the tokens and user when the user signs out after a redirect\n useEffect(() => {\n const params = new URLSearchParams(window.location.search);\n const state = params.get(\"state\");\n const localStorage = new LocalStorageAdapter();\n localStorage.get(\"logout_state\").then((storedLogoutState) => {\n if (state && state === storedLogoutState) {\n // Clear storage\n clearTokens(localStorage);\n clearUser(localStorage);\n LocalStorageAdapter.emitter.emit(\"signOut\");\n\n // Clean up storage and URL\n sessionStorage.removeItem(\"logout_state\");\n const cleanUrl = window.location.href.split(\"?\")[0];\n window.history.replaceState({}, document.title, cleanUrl);\n }\n });\n }, []);\n\n const signIn = useCallback(async (): Promise<void> => {\n if (!authInitiator) return;\n\n setIsSigningIn(true);\n authInitiator.setDisplayMode(displayMode);\n if (displayMode === \"iframe\") {\n setIframeIsVisible(true);\n }\n const useIframeRef = iframeRef?.current || null;\n await authInitiator.signIn(useIframeRef).catch((error) => {\n setIsSigningIn(false);\n console.log(\"signIn error\", {\n error,\n isPopupError: error instanceof PopupError,\n });\n // if we've tried to open a popup and it has failed, then fallback to redirect mode\n if (error instanceof PopupError) {\n setIframeIsVisible(false); // hide the iframe\n authInitiator.cleanup(); // clear any event listeners from before\n authInitiator.setDisplayMode(\"redirect\"); // switch to redirect mode\n authInitiator.signIn(useIframeRef); // retry the sign in\n }\n });\n }, [authInitiator, displayMode, iframeRef, setIframeIsVisible]);\n\n const signOut = useCallback(async () => {\n const idToken = session?.idToken;\n if (!authInitiator) return;\n\n setIsSigningOut(true);\n if (displayMode === \"iframe\") {\n setIframeIsVisible(false);\n setLogoutIframeIsVisible(true);\n }\n\n try {\n await preSignOut?.();\n\n const useIframeRef = logoutIframeRef?.current || null;\n await authInitiator.signOut(idToken, useIframeRef).catch((error) => {\n setIsSigningOut(false);\n console.log(\"signOut error\", {\n error,\n isPopupError: error instanceof PopupError,\n });\n\n // Same popup fallback as signIn\n if (error instanceof PopupError) {\n setLogoutIframeIsVisible(false);\n authInitiator.cleanup();\n authInitiator.setDisplayMode(\"redirect\");\n authInitiator.signOut(idToken, useIframeRef);\n }\n });\n } catch (error) {\n console.error(\"Signout error:\", error);\n }\n }, [\n session?.idToken,\n authInitiator,\n displayMode,\n setLogoutIframeIsVisible,\n setIframeIsVisible,\n preSignOut,\n logoutIframeRef,\n ]);\n\n // handle logout finished\n useEffect(() => {\n if (isSigningOut && !session?.authenticated) {\n setIsSigningOut(false);\n postSignOut?.().then(() => {\n setLogoutIframeIsVisible(false);\n });\n return;\n }\n if (isSigningIn && session?.authenticated) {\n setIsSigningIn(false);\n }\n }, [\n session,\n postSignOut,\n isSigningOut,\n setLogoutIframeIsVisible,\n isSigningIn,\n ]);\n\n return {\n signIn,\n signOut,\n isSigningOut,\n isSigningIn,\n displayMode,\n };\n};\nexport { useSignIn };\n"]}
1
+ {"version":3,"file":"useSignIn.js","sourceRoot":"","sources":["../../../../src/shared/hooks/useSignIn.ts"],"names":[],"mappings":"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","sourcesContent":["import { BrowserAuthenticationInitiator } from \"@/services/AuthenticationService.js\";\nimport { BrowserPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/useCivicAuthConfig.js\";\nimport type { DisplayMode } from \"@/types.js\";\nimport { useIframe } from \"@/shared/hooks/useIframe.js\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { PopupError, type PKCEConsumer } from \"@/services/types.js\";\nimport { useSession } from \"./useSession.js\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport { clearTokens, clearUser } from \"../lib/util.js\";\n\ntype SignInProps = {\n pkceConsumer?: PKCEConsumer;\n preSignOut?: () => Promise<void>;\n postSignOut?: () => Promise<void>;\n displayMode: DisplayMode;\n};\nconst useSignIn = ({\n pkceConsumer,\n preSignOut,\n postSignOut,\n displayMode,\n}: SignInProps) => {\n const civicAuthConfig = useCivicAuthConfig();\n const {\n iframeRef,\n logoutIframeRef,\n setIframeIsVisible,\n iframeIsVisible,\n setLogoutIframeIsVisible,\n iframeAborted,\n setIframeAborted,\n } = useIframe();\n const { data: session } = useSession();\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [isSigningIn, setIsSigningIn] = useState(false);\n\n const authInitiator = useMemo(() => {\n if (!civicAuthConfig) {\n return null;\n }\n const {\n clientId,\n redirectUrl,\n logoutUrl,\n logoutRedirectUrl,\n nonce,\n oauthServer,\n endpoints,\n scopes,\n } = civicAuthConfig;\n return new BrowserAuthenticationInitiator({\n pkceConsumer: pkceConsumer || new BrowserPublicClientPKCEProducer(), // generate and retrieve the challenge client-side\n clientId,\n redirectUrl,\n logoutUrl,\n logoutRedirectUrl,\n scopes,\n displayMode,\n oauthServer,\n endpointOverrides: endpoints,\n nonce,\n });\n }, [civicAuthConfig, displayMode, pkceConsumer]);\n\n useEffect(() => {\n return () => {\n if (authInitiator) {\n authInitiator.cleanup();\n }\n };\n }, [authInitiator]);\n\n // This effect is used to clear the tokens and user when the user signs out after a redirect\n useEffect(() => {\n const params = new URLSearchParams(window.location.search);\n const state = params.get(\"state\");\n const localStorage = new LocalStorageAdapter();\n localStorage.get(\"logout_state\").then((storedLogoutState) => {\n if (state && state === storedLogoutState) {\n // Clear storage\n clearTokens(localStorage);\n clearUser(localStorage);\n LocalStorageAdapter.emitter.emit(\"signOut\");\n\n // Clean up storage and URL\n sessionStorage.removeItem(\"logout_state\");\n const cleanUrl = window.location.href.split(\"?\")[0];\n window.history.replaceState({}, document.title, cleanUrl);\n }\n });\n }, []);\n\n const signIn = useCallback(async (): Promise<void> => {\n if (!authInitiator) return;\n\n setIsSigningIn(true);\n authInitiator.setDisplayMode(displayMode);\n if (displayMode === \"iframe\") {\n setIframeIsVisible(true);\n }\n const useIframeRef = iframeRef?.current || null;\n await authInitiator.signIn(useIframeRef).catch((error) => {\n setIsSigningIn(false);\n console.log(\"signIn error\", {\n error,\n isPopupError: error instanceof PopupError,\n });\n // if we've tried to open a popup and it has failed, then fallback to redirect mode\n if (error instanceof PopupError) {\n setIframeIsVisible(false); // hide the iframe\n authInitiator.cleanup(); // clear any event listeners from before\n authInitiator.setDisplayMode(\"redirect\"); // switch to redirect mode\n authInitiator.signIn(useIframeRef); // retry the sign in\n }\n });\n }, [authInitiator, displayMode, iframeRef, setIframeIsVisible]);\n\n const signOut = useCallback(async () => {\n const idToken = session?.idToken;\n if (!authInitiator) return;\n\n setIsSigningOut(true);\n if (displayMode === \"iframe\") {\n setIframeIsVisible(false);\n setLogoutIframeIsVisible(true);\n }\n\n try {\n await preSignOut?.();\n\n const useIframeRef = logoutIframeRef?.current || null;\n await authInitiator.signOut(idToken, useIframeRef).catch((error) => {\n setIsSigningOut(false);\n console.log(\"signOut error\", {\n error,\n isPopupError: error instanceof PopupError,\n });\n\n // Same popup fallback as signIn\n if (error instanceof PopupError) {\n setLogoutIframeIsVisible(false);\n authInitiator.cleanup();\n authInitiator.setDisplayMode(\"redirect\");\n authInitiator.signOut(idToken, useIframeRef);\n }\n });\n } catch (error) {\n console.error(\"Signout error:\", error);\n }\n }, [\n session?.idToken,\n authInitiator,\n displayMode,\n setLogoutIframeIsVisible,\n setIframeIsVisible,\n preSignOut,\n logoutIframeRef,\n ]);\n\n useEffect(() => {\n if (isSigningIn) {\n if (\n session?.authenticated ||\n (displayMode === \"iframe\" && iframeAborted)\n ) {\n setIsSigningIn(false);\n setIframeAborted(false);\n }\n }\n }, [\n displayMode,\n iframeAborted,\n isSigningIn,\n session?.authenticated,\n setIframeAborted,\n ]);\n\n // handle logout finished\n useEffect(() => {\n if (isSigningOut && !session?.authenticated) {\n setIsSigningOut(false);\n postSignOut?.().then(() => {\n setLogoutIframeIsVisible(false);\n });\n return;\n }\n }, [\n session,\n postSignOut,\n isSigningOut,\n setLogoutIframeIsVisible,\n isSigningIn,\n displayMode,\n iframeIsVisible,\n ]);\n\n return {\n signIn,\n signOut,\n isSigningOut,\n isSigningIn,\n displayMode,\n };\n};\nexport { useSignIn };\n"]}
@@ -5,6 +5,8 @@ export type IframeProviderOutput = {
5
5
  iframeRef: RefObject<HTMLIFrameElement> | null;
6
6
  logoutIframeRef: RefObject<HTMLIFrameElement> | null;
7
7
  setIframeIsVisible: Dispatch<SetStateAction<boolean>>;
8
+ setIframeAborted: Dispatch<SetStateAction<boolean>>;
9
+ iframeAborted: boolean;
8
10
  setLogoutIframeIsVisible: Dispatch<SetStateAction<boolean>>;
9
11
  iframeIsVisible: boolean;
10
12
  logoutIframeIsVisible: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"IframeProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/IframeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAC5E,OAAO,KAA0C,MAAM,OAAO,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,SAAS,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC;IAC/C,eAAe,EAAE,SAAS,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACrD,kBAAkB,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,wBAAwB,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,eAAe,EAAE,OAAO,CAAC;IACzB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAaF,QAAA,MAAM,aAAa,qCAAqD,CAAC;AAEzE,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF,QAAA,MAAM,cAAc,8BAGjB,iBAAiB,sBAwBnB,CAAC;AAEF,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"IframeProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/IframeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAC5E,OAAO,KAA0C,MAAM,OAAO,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,SAAS,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC;IAC/C,eAAe,EAAE,SAAS,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACrD,kBAAkB,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,gBAAgB,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,aAAa,EAAE,OAAO,CAAC;IACvB,wBAAwB,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,eAAe,EAAE,OAAO,CAAC;IACzB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAeF,QAAA,MAAM,aAAa,qCAAqD,CAAC;AAEzE,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF,QAAA,MAAM,cAAc,8BAGjB,iBAAiB,sBA2BnB,CAAC;AAEF,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC"}