@hexclave/next 1.0.125 → 1.0.127

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 (161) hide show
  1. package/dist/{admin-app-impl-Bxad6t8m.d.ts → admin-app-impl-CjCeXtJd.d.ts} +29 -13
  2. package/dist/admin-app-impl-CjCeXtJd.d.ts.map +1 -0
  3. package/dist/clickmap/clickmap-core.d.ts +1 -1
  4. package/dist/clickmap/index.d.ts +1 -1
  5. package/dist/{client-app-B0cTytS5.d.ts → client-app-jAjrgwSh.d.ts} +34 -6
  6. package/dist/client-app-jAjrgwSh.d.ts.map +1 -0
  7. package/dist/{common-B2gkWlXX.d.ts → common-BjAI7WW6.d.ts} +15 -3
  8. package/dist/common-BjAI7WW6.d.ts.map +1 -0
  9. package/dist/{common-BK_sydxF.d.ts → common-DWfeER0s.d.ts} +2 -2
  10. package/dist/{common-BK_sydxF.d.ts.map → common-DWfeER0s.d.ts.map} +1 -1
  11. package/dist/components/message-cards/predefined-message-card.js +4 -2
  12. package/dist/components/message-cards/predefined-message-card.js.map +1 -1
  13. package/dist/components/selected-team-switcher.d.ts +1 -1
  14. package/dist/components/team-icon.d.ts +1 -1
  15. package/dist/components/team-switcher.d.ts +1 -1
  16. package/dist/components/user-button.js +9 -9
  17. package/dist/components/user-button.js.map +1 -1
  18. package/dist/components/user-button.test.d.ts +1 -0
  19. package/dist/components/user-button.test.js +71 -0
  20. package/dist/components/user-button.test.js.map +1 -0
  21. package/dist/components-page/account-settings/payments/payments-page.d.ts +1 -1
  22. package/dist/components-page/account-settings/payments/payments-panel.d.ts +1 -1
  23. package/dist/components-page/account-settings/settings/sign-out-section.d.ts +1 -1
  24. package/dist/components-page/account-settings/settings/sign-out-section.d.ts.map +1 -1
  25. package/dist/components-page/account-settings/settings/sign-out-section.js +4 -1
  26. package/dist/components-page/account-settings/settings/sign-out-section.js.map +1 -1
  27. package/dist/components-page/account-settings/teams/leave-team-section.d.ts +1 -1
  28. package/dist/components-page/account-settings/teams/team-api-keys-section.d.ts +1 -1
  29. package/dist/components-page/account-settings/teams/team-display-name-section.d.ts +1 -1
  30. package/dist/components-page/account-settings/teams/team-member-invitation-section.d.ts +1 -1
  31. package/dist/components-page/account-settings/teams/team-member-list-section.d.ts +1 -1
  32. package/dist/components-page/account-settings/teams/team-page.d.ts +1 -1
  33. package/dist/components-page/account-settings/teams/team-profile-image-section.d.ts +1 -1
  34. package/dist/components-page/account-settings/teams/team-profile-user-section.d.ts +1 -1
  35. package/dist/components-page/hexclave-handler-client.d.ts +1 -1
  36. package/dist/components-page/hexclave-handler.d.ts +1 -1
  37. package/dist/components-page/onboarding.js +15 -13
  38. package/dist/components-page/onboarding.js.map +1 -1
  39. package/dist/components-page/onboarding.test.js +2 -1
  40. package/dist/components-page/onboarding.test.js.map +1 -1
  41. package/dist/dev-tool/dev-tool-core.d.ts +1 -1
  42. package/dist/dev-tool/index.d.ts +1 -1
  43. package/dist/esm/components/message-cards/predefined-message-card.js +4 -2
  44. package/dist/esm/components/message-cards/predefined-message-card.js.map +1 -1
  45. package/dist/esm/components/user-button.js +9 -9
  46. package/dist/esm/components/user-button.js.map +1 -1
  47. package/dist/esm/components/user-button.test.d.ts +1 -0
  48. package/dist/esm/components/user-button.test.js +70 -0
  49. package/dist/esm/components/user-button.test.js.map +1 -0
  50. package/dist/esm/components-page/account-settings/settings/sign-out-section.d.ts +1 -1
  51. package/dist/esm/components-page/account-settings/settings/sign-out-section.d.ts.map +1 -1
  52. package/dist/esm/components-page/account-settings/settings/sign-out-section.js +4 -1
  53. package/dist/esm/components-page/account-settings/settings/sign-out-section.js.map +1 -1
  54. package/dist/esm/components-page/onboarding.js +15 -13
  55. package/dist/esm/components-page/onboarding.js.map +1 -1
  56. package/dist/esm/components-page/onboarding.test.js +2 -1
  57. package/dist/esm/components-page/onboarding.test.js.map +1 -1
  58. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +4 -4
  59. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  60. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +18 -2
  61. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  62. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.d.ts +1 -0
  63. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.js +382 -0
  64. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.js.map +1 -0
  65. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.d.ts +1 -0
  66. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.js +66 -0
  67. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.js.map +1 -0
  68. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +66 -14
  69. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  70. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
  71. package/dist/esm/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.d.ts +31 -0
  72. package/dist/esm/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.d.ts.map +1 -0
  73. package/dist/esm/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.js +115 -0
  74. package/dist/esm/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.js.map +1 -0
  75. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts +16 -1
  76. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts.map +1 -1
  77. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
  78. package/dist/esm/lib/hexclave-app/common.d.ts +14 -2
  79. package/dist/esm/lib/hexclave-app/common.d.ts.map +1 -1
  80. package/dist/esm/lib/hexclave-app/common.js +17 -1
  81. package/dist/esm/lib/hexclave-app/common.js.map +1 -1
  82. package/dist/esm/lib/hexclave-app/index.d.ts +2 -2
  83. package/dist/esm/lib/hexclave-app/index.js +2 -2
  84. package/dist/esm/lib/hexclave-app/users/index.d.ts +14 -1
  85. package/dist/esm/lib/hexclave-app/users/index.d.ts.map +1 -1
  86. package/dist/esm/lib/hexclave-app/users/index.js.map +1 -1
  87. package/dist/{hexclave-provider-w8nX8KDv.d.ts → hexclave-provider-Br8j6WHN.d.ts} +2 -2
  88. package/dist/{hexclave-provider-w8nX8KDv.d.ts.map → hexclave-provider-Br8j6WHN.d.ts.map} +1 -1
  89. package/dist/{hooks-nqzRtl9S.d.ts → hooks-DyC8t1Sh.d.ts} +3 -3
  90. package/dist/{hooks-nqzRtl9S.d.ts.map → hooks-DyC8t1Sh.d.ts.map} +1 -1
  91. package/dist/{index-DbiyXho6.d.ts → index-CQ4kC6Cu.d.ts} +2 -2
  92. package/dist/{index-DbiyXho6.d.ts.map → index-CQ4kC6Cu.d.ts.map} +1 -1
  93. package/dist/{index-BDzsJvkD.d.ts → index-CWaynElx.d.ts} +3 -3
  94. package/dist/{index-BDzsJvkD.d.ts.map → index-CWaynElx.d.ts.map} +1 -1
  95. package/dist/{index-BSr2pd22.d.ts → index-FsS-NA9c.d.ts} +2 -2
  96. package/dist/{index-BSr2pd22.d.ts.map → index-FsS-NA9c.d.ts.map} +1 -1
  97. package/dist/index.d.ts +7 -7
  98. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
  99. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
  100. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.d.ts +1 -0
  101. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.js +381 -0
  102. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.js.map +1 -0
  103. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.d.ts +1 -0
  104. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.js +65 -0
  105. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.js.map +1 -0
  106. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +65 -13
  107. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  108. package/dist/lib/hexclave-app/apps/implementations/common.d.ts +1 -1
  109. package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
  110. package/dist/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.d.ts +31 -0
  111. package/dist/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.d.ts.map +1 -0
  112. package/dist/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.js +117 -0
  113. package/dist/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.js.map +1 -0
  114. package/dist/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
  115. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.d.ts +1 -1
  116. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  117. package/dist/lib/hexclave-app/apps/index.d.ts +1 -1
  118. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts +1 -1
  119. package/dist/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -1
  120. package/dist/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
  121. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +1 -1
  122. package/dist/lib/hexclave-app/common.d.ts +2 -2
  123. package/dist/lib/hexclave-app/common.js +19 -0
  124. package/dist/lib/hexclave-app/common.js.map +1 -1
  125. package/dist/lib/hexclave-app/customers/index.d.ts +1 -1
  126. package/dist/lib/hexclave-app/data-vault/index.d.ts +1 -1
  127. package/dist/lib/hexclave-app/index.d.ts +4 -4
  128. package/dist/lib/hexclave-app/index.js +18 -0
  129. package/dist/lib/hexclave-app/projects/index.d.ts +1 -1
  130. package/dist/lib/hexclave-app/teams/index.d.ts +1 -1
  131. package/dist/lib/hexclave-app/url-targets.d.ts +1 -1
  132. package/dist/lib/hexclave-app/users/index.d.ts +1 -1
  133. package/dist/lib/hexclave-app/users/index.js.map +1 -1
  134. package/dist/lib/hooks.d.ts +1 -1
  135. package/dist/providers/hexclave-context.d.ts +1 -1
  136. package/dist/providers/hexclave-provider-client.d.ts +1 -1
  137. package/dist/providers/hexclave-provider.d.ts +1 -1
  138. package/dist/pushed-config-error-overlay/index.d.ts +1 -1
  139. package/dist/{redirect-page-urls-ofcg3AYr.d.ts → redirect-page-urls-CnGvn0UJ.d.ts} +2 -2
  140. package/dist/{redirect-page-urls-ofcg3AYr.d.ts.map → redirect-page-urls-CnGvn0UJ.d.ts.map} +1 -1
  141. package/dist/tanstack-start-server-context.d.ts.map +1 -1
  142. package/dist/{url-targets-CWO0mjTr.d.ts → url-targets-DbhzuQtY.d.ts} +2 -2
  143. package/dist/{url-targets-CWO0mjTr.d.ts.map → url-targets-DbhzuQtY.d.ts.map} +1 -1
  144. package/package.json +4 -4
  145. package/src/components/message-cards/predefined-message-card.tsx +4 -2
  146. package/src/components/user-button.test.tsx +87 -0
  147. package/src/components/user-button.tsx +9 -9
  148. package/src/components-page/account-settings/settings/sign-out-section.tsx +9 -1
  149. package/src/components-page/onboarding.test.tsx +1 -0
  150. package/src/components-page/onboarding.tsx +16 -13
  151. package/src/lib/hexclave-app/apps/implementations/client-app-impl.external-token-store.test.ts +425 -0
  152. package/src/lib/hexclave-app/apps/implementations/client-app-impl.init-analytics.test.ts +79 -0
  153. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +124 -13
  154. package/src/lib/hexclave-app/apps/implementations/external-token-store-session-adapter.ts +190 -0
  155. package/src/lib/hexclave-app/apps/interfaces/client-app.ts +17 -0
  156. package/src/lib/hexclave-app/common.ts +33 -0
  157. package/src/lib/hexclave-app/index.ts +4 -0
  158. package/src/lib/hexclave-app/users/index.ts +13 -1
  159. package/dist/admin-app-impl-Bxad6t8m.d.ts.map +0 -1
  160. package/dist/client-app-B0cTytS5.d.ts.map +0 -1
  161. package/dist/common-B2gkWlXX.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- import { _ as ResolvedHandlerUrls, i as DefaultHandlerUrlTarget, u as HandlerUrlOptions } from "./common-B2gkWlXX.js";
1
+ import { d as HandlerUrlOptions, i as DefaultHandlerUrlTarget, v as ResolvedHandlerUrls } from "./common-BjAI7WW6.js";
2
2
 
3
3
  //#region src/lib/hexclave-app/url-targets.d.ts
4
4
  declare const getHostedHandlerUrl: (options: {
@@ -36,4 +36,4 @@ declare const isHostedHandlerUrlForProject: (options: {
36
36
  }) => boolean;
37
37
  //#endregion
38
38
  export { isLocalHandlerUrlTarget as a, isHostedHandlerUrlForProject as i, getHostedHandlerUrl as n, resolveHandlerUrls as o, getPagePrompt as r, resolveUnknownHandlerPathFallbackUrl as s, buildCliAuthConfirmUrl as t };
39
- //# sourceMappingURL=url-targets-CWO0mjTr.d.ts.map
39
+ //# sourceMappingURL=url-targets-DbhzuQtY.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"url-targets-CWO0mjTr.d.ts","names":[],"sources":["../src/lib/hexclave-app/url-targets.ts"],"mappings":";;;cA2Ga,mBAAA,GAAuB,OAAA;EAAW,SAAA;EAAmB,QAAA;AAAA;AAAA,cA0BrD,uBAAA,GAA2B,OAAA;EACtC,SAAA;EACA,WAAA;EACA,aAAA;AAAA;AAAA,cA+DW,kBAAA,GAAsB,OAAA;EAAW,IAAA,EAAM,iBAAA;EAA+B,SAAA;AAAA,MAAsB,mBAmJxG;AAAA,cAEY,sBAAA,GAA0B,OAAA;EACrC,iBAAA,UAvNA;EAyNA,MAAA;EACA,SAAA;AAAA;AAAA,cAOW,oCAAA,GAAwC,OAAA;EACnD,aAAA,EAAe,uBAAuB;EACtC,SAAA;EACA,WAAA;AAAA;AAAA,iBAiBc,aAAA,CAAc,QAAA,UAAkB,cAAA;EAA4B,KAAA;EAAe,UAAA;EAAoB,aAAA;EAA8B,aAAA;AAAA;AAAA,cAuBhI,4BAAA,GAAgC,OAAA;EAAW,GAAA;EAAa,SAAA;AAAA"}
1
+ {"version":3,"file":"url-targets-DbhzuQtY.d.ts","names":[],"sources":["../src/lib/hexclave-app/url-targets.ts"],"mappings":";;;cA2Ga,mBAAA,GAAuB,OAAA;EAAW,SAAA;EAAmB,QAAA;AAAA;AAAA,cA0BrD,uBAAA,GAA2B,OAAA;EACtC,SAAA;EACA,WAAA;EACA,aAAA;AAAA;AAAA,cA+DW,kBAAA,GAAsB,OAAA;EAAW,IAAA,EAAM,iBAAA;EAA+B,SAAA;AAAA,MAAsB,mBAmJxG;AAAA,cAEY,sBAAA,GAA0B,OAAA;EACrC,iBAAA,UAvNA;EAyNA,MAAA;EACA,SAAA;AAAA;AAAA,cAOW,oCAAA,GAAwC,OAAA;EACnD,aAAA,EAAe,uBAAuB;EACtC,SAAA;EACA,WAAA;AAAA;AAAA,iBAiBc,aAAA,CAAc,QAAA,UAAkB,cAAA;EAA4B,KAAA;EAAe,UAAA;EAAoB,aAAA;EAA8B,aAAA;AAAA;AAAA,cAuBhI,4BAAA,GAAgC,OAAA;EAAW,GAAA;EAAa,SAAA;AAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template (FOR package.json FILES, PLEASE EDIT package-template.json)",
3
3
  "name": "@hexclave/next",
4
- "version": "1.0.125",
4
+ "version": "1.0.127",
5
5
  "repository": "https://github.com/hexclave/hexclave",
6
6
  "sideEffects": false,
7
7
  "main": "./dist/index.js",
@@ -74,9 +74,9 @@
74
74
  "tailwindcss-animate": "^1.0.7",
75
75
  "rrweb": "^1.1.3",
76
76
  "yup": "^1.7.1",
77
- "@hexclave/sc": "1.0.125",
78
- "@hexclave/ui": "1.0.125",
79
- "@hexclave/shared": "1.0.125"
77
+ "@hexclave/sc": "1.0.127",
78
+ "@hexclave/shared": "1.0.127",
79
+ "@hexclave/ui": "1.0.127"
80
80
  },
81
81
  "peerDependencies": {
82
82
  "@types/react": ">=18.0.0",
@@ -31,9 +31,11 @@ export function PredefinedMessageCard({
31
31
  case 'signedIn': {
32
32
  title = t("You are already signed in");
33
33
  primaryAction = () => hexclaveApp.redirectToHome();
34
- secondaryAction = () => hexclaveApp.redirectToSignOut();
34
+ if (!hexclaveApp.isExternalAuthApp()) {
35
+ secondaryAction = () => hexclaveApp.redirectToSignOut();
36
+ secondaryButton = t("Sign out");
37
+ }
35
38
  primaryButton = t("Go home");
36
- secondaryButton = t("Sign out");
37
39
  break;
38
40
  }
39
41
  case 'signedOut': {
@@ -0,0 +1,87 @@
1
+
2
+ //===========================================
3
+ // THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template
4
+ //===========================================
5
+ // @vitest-environment jsdom
6
+
7
+ import React, { act } from "react";
8
+ import { createRoot, type Root } from "react-dom/client";
9
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
10
+ import { UserButton } from "./user-button";
11
+
12
+ type MockState = {
13
+ app: { isExternalAuthApp: () => boolean, redirectToAccountSettings: () => Promise<void> } | null,
14
+ user: { displayName: string, primaryEmail: string, signOut: () => Promise<void> } | null,
15
+ };
16
+
17
+ const previousActEnvironment = Reflect.get(globalThis, "IS_REACT_ACT_ENVIRONMENT");
18
+
19
+ const state = vi.hoisted<MockState>(() => ({
20
+ app: null,
21
+ user: null,
22
+ }));
23
+
24
+ vi.mock("..", () => ({
25
+ useStackApp: () => state.app,
26
+ useUser: () => state.user,
27
+ }));
28
+
29
+ vi.mock("../lib/translations", () => ({
30
+ useTranslation: () => ({ t: (value: string) => value }),
31
+ }));
32
+
33
+ vi.mock("./elements/user-avatar", () => ({
34
+ UserAvatar: () => <div data-testid="user-avatar" />,
35
+ }));
36
+
37
+ vi.mock("@hexclave/ui", () => ({
38
+ DropdownMenu: (props: { children: React.ReactNode }) => <div>{props.children}</div>,
39
+ DropdownMenuContent: (props: { children: React.ReactNode }) => <div>{props.children}</div>,
40
+ DropdownMenuItem: (props: { children: React.ReactNode, onClick: () => void }) => <button onClick={props.onClick}>{props.children}</button>,
41
+ DropdownMenuLabel: (props: { children: React.ReactNode }) => <div>{props.children}</div>,
42
+ DropdownMenuSeparator: () => <hr />,
43
+ DropdownMenuTrigger: (props: { children: React.ReactNode }) => <div>{props.children}</div>,
44
+ Skeleton: () => <div />,
45
+ Typography: (props: { children: React.ReactNode }) => <div>{props.children}</div>,
46
+ }));
47
+
48
+ describe("UserButton", () => {
49
+ let root: Root | null = null;
50
+ let container: HTMLDivElement | null = null;
51
+
52
+ beforeEach(() => {
53
+ Reflect.set(globalThis, "IS_REACT_ACT_ENVIRONMENT", true);
54
+ });
55
+
56
+ afterEach(() => {
57
+ act(() => root?.unmount());
58
+ container?.remove();
59
+ root = null;
60
+ container = null;
61
+ state.app = null;
62
+ state.user = null;
63
+ Reflect.set(globalThis, "IS_REACT_ACT_ENVIRONMENT", previousActEnvironment);
64
+ });
65
+
66
+ it("hides external-auth sign out while keeping account settings", async () => {
67
+ state.app = {
68
+ isExternalAuthApp: () => true,
69
+ redirectToAccountSettings: vi.fn(async () => {}),
70
+ };
71
+ state.user = {
72
+ displayName: "External user",
73
+ primaryEmail: "user@example.com",
74
+ signOut: vi.fn(async () => {}),
75
+ };
76
+ container = document.createElement("div");
77
+ document.body.append(container);
78
+ root = createRoot(container);
79
+
80
+ await act(async () => {
81
+ root?.render(<UserButton />);
82
+ });
83
+
84
+ expect(container.textContent).toContain("Account settings");
85
+ expect(container.textContent).not.toContain("Sign out");
86
+ });
87
+ });
@@ -77,7 +77,7 @@ function UserButtonInnerInner(props: UserButtonProps & { user: CurrentUser | nul
77
77
  <DropdownMenuTrigger className="outline-none stack-scope rounded-lg hover:bg-muted/50 transition-colors hover:transition-none p-1.5">
78
78
  <div className="flex gap-2 items-center">
79
79
  <UserAvatar user={user} />
80
- {user && props.showUserInfo &&
80
+ {user != null && props.showUserInfo &&
81
81
  <div className="flex flex-col justify-center text-left min-w-0">
82
82
  <div className="max-w-40 truncate text-sm font-medium">{user.displayName}</div>
83
83
  <div className="max-w-40 truncate text-xs text-muted-foreground">{user.primaryEmail}</div>
@@ -90,14 +90,14 @@ function UserButtonInnerInner(props: UserButtonProps & { user: CurrentUser | nul
90
90
  <div className="flex gap-2 items-center">
91
91
  <UserAvatar user={user} />
92
92
  <div>
93
- {user && <Typography className="max-w-40 truncate">{user.displayName}</Typography>}
94
- {user && <Typography className="max-w-40 truncate" variant="secondary" type='label'>{user.primaryEmail}</Typography>}
95
- {!user && <Typography>{t('Not signed in')}</Typography>}
93
+ {user != null && <Typography className="max-w-40 truncate">{user.displayName}</Typography>}
94
+ {user != null && <Typography className="max-w-40 truncate" variant="secondary" type='label'>{user.primaryEmail}</Typography>}
95
+ {user == null && <Typography>{t('Not signed in')}</Typography>}
96
96
  </div>
97
97
  </div>
98
98
  </DropdownMenuLabel>
99
99
  <DropdownMenuSeparator />
100
- {user && <Item
100
+ {user != null && <Item
101
101
  text={t('Account settings')}
102
102
  onClick={async () => {
103
103
  if (props.mockUser) {
@@ -108,7 +108,7 @@ function UserButtonInnerInner(props: UserButtonProps & { user: CurrentUser | nul
108
108
  }}
109
109
  icon={<CircleUser {...iconProps} />}
110
110
  />}
111
- {!user && <Item
111
+ {user == null && <Item
112
112
  text={t('Sign in')}
113
113
  onClick={async () => {
114
114
  if (props.mockUser) {
@@ -119,7 +119,7 @@ function UserButtonInnerInner(props: UserButtonProps & { user: CurrentUser | nul
119
119
  }}
120
120
  icon={<LogIn {...iconProps} />}
121
121
  />}
122
- {!user && <Item
122
+ {user == null && <Item
123
123
  text={t('Sign up')}
124
124
  onClick={async () => {
125
125
  if (props.mockUser) {
@@ -130,7 +130,7 @@ function UserButtonInnerInner(props: UserButtonProps & { user: CurrentUser | nul
130
130
  }}
131
131
  icon={<UserPlus {...iconProps}/> }
132
132
  />}
133
- {user && props.extraItems && props.extraItems.map((item, index) => (
133
+ {user != null && props.extraItems && props.extraItems.map((item, index) => (
134
134
  <Item key={index} {...item} />
135
135
  ))}
136
136
  {props.colorModeToggle && (
@@ -140,7 +140,7 @@ function UserButtonInnerInner(props: UserButtonProps & { user: CurrentUser | nul
140
140
  icon={<SunMoon {...iconProps} />}
141
141
  />
142
142
  )}
143
- {user && <Item
143
+ {user != null && !app.isExternalAuthApp() && <Item
144
144
  text={t('Sign out')}
145
145
  onClick={async () => {
146
146
  if (props.mockUser) {
@@ -3,13 +3,21 @@
3
3
  // THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template
4
4
  //===========================================
5
5
  import { Button } from "@hexclave/ui";
6
+ import { useStackApp } from "../../..";
6
7
  import { useUser } from "../../../lib/hooks";
7
8
  import { useTranslation } from "../../../lib/translations";
8
9
  import { Section } from "../section";
9
10
 
10
11
  export function SignOutSection(props?: { mockMode?: boolean }) {
11
12
  const { t } = useTranslation();
12
- const user = useUser({ or: props?.mockMode ? "return-null" : "throw" });
13
+ const app = useStackApp();
14
+ // External-auth apps render nothing here, and the provider can clear its session (so Hexclave has no user)
15
+ // before this re-renders, so don't throw for them.
16
+ const user = useUser({ or: props?.mockMode || app.isExternalAuthApp() ? "return-null" : "throw" });
17
+
18
+ if (app.isExternalAuthApp()) {
19
+ return null;
20
+ }
13
21
 
14
22
  const handleSignOut = async () => {
15
23
  if (props?.mockMode) {
@@ -45,6 +45,7 @@ function createAppTestDouble() {
45
45
  const app = {
46
46
  redirectToSignIn: vi.fn(async () => {}),
47
47
  redirectToAfterSignIn: vi.fn(async () => {}),
48
+ isExternalAuthApp: vi.fn(() => false),
48
49
  };
49
50
 
50
51
  // This test double intentionally implements only the StackClientApp surface that Onboarding touches.
@@ -23,6 +23,7 @@ export function Onboarding(props: {
23
23
  const { t } = useTranslation();
24
24
  const hexclaveApp = useStackApp();
25
25
  const user = useUser({ or: "return-null", includeRestricted: true });
26
+ const canSignOut = !hexclaveApp.isExternalAuthApp();
26
27
 
27
28
  // If user is not restricted anymore, redirect to the intended destination
28
29
  // redirectToAfterSignIn automatically checks for after_auth_return_to in the URL
@@ -60,10 +61,10 @@ export function Onboarding(props: {
60
61
  <MessageCard
61
62
  title={t("Your account has been restricted")}
62
63
  fullPage={!!props.fullPage}
63
- secondaryButtonText={t("Sign out")}
64
- secondaryAction={async () => {
64
+ secondaryButtonText={canSignOut ? t("Sign out") : undefined}
65
+ secondaryAction={canSignOut ? async () => {
65
66
  await user.signOut();
66
- }}
67
+ } : undefined}
67
68
  >
68
69
  {/* The public reason is set by the project's administrators (sign-up rules or manually), so it's the most
69
70
  helpful thing we can show; the generic sentence is only a fallback for when they didn't provide one. */}
@@ -77,10 +78,10 @@ export function Onboarding(props: {
77
78
  <MessageCard
78
79
  title={t("Complete your account setup")}
79
80
  fullPage={!!props.fullPage}
80
- secondaryButtonText={t("Sign out")}
81
- secondaryAction={async () => {
81
+ secondaryButtonText={canSignOut ? t("Sign out") : undefined}
82
+ secondaryAction={canSignOut ? async () => {
82
83
  await user.signOut();
83
- }}
84
+ } : undefined}
84
85
  >
85
86
  <p>{t("You have not yet completed your account setup. Please reach out to support if you believe this is an error.")}</p>
86
87
  </MessageCard>
@@ -94,6 +95,7 @@ function AddEmailForm(props: {
94
95
  const { t } = useTranslation();
95
96
  const user = useUser({ or: "throw", includeRestricted: true });
96
97
  const hexclaveApp = useStackApp();
98
+ const canSignOut = !hexclaveApp.isExternalAuthApp();
97
99
  const [loading, setLoading] = useState(false);
98
100
 
99
101
  const emailSchema = yupObject({
@@ -120,10 +122,10 @@ function AddEmailForm(props: {
120
122
  <MessageCard
121
123
  title={t("Add your email address")}
122
124
  fullPage={!!props.fullPage}
123
- secondaryButtonText={t("Sign out")}
124
- secondaryAction={async () => {
125
+ secondaryButtonText={canSignOut ? t("Sign out") : undefined}
126
+ secondaryAction={canSignOut ? async () => {
125
127
  await user.signOut();
126
- }}
128
+ } : undefined}
127
129
  >
128
130
  <Typography className="mb-4">
129
131
  {t("Please add an email address to complete your account setup. We'll send you a verification email.")}
@@ -154,6 +156,8 @@ function VerifyEmailScreen(props: {
154
156
  }) {
155
157
  const { t } = useTranslation();
156
158
  const { user, email } = props;
159
+ const hexclaveApp = useStackApp();
160
+ const canSignOut = !hexclaveApp.isExternalAuthApp();
157
161
  const [changingEmail, setChangingEmail] = useState(false);
158
162
 
159
163
  if (changingEmail) {
@@ -168,10 +172,10 @@ function VerifyEmailScreen(props: {
168
172
  primaryAction={async () => {
169
173
  await user.sendVerificationEmail();
170
174
  }}
171
- secondaryButtonText={t("Sign out")}
172
- secondaryAction={async () => {
175
+ secondaryButtonText={canSignOut ? t("Sign out") : undefined}
176
+ secondaryAction={canSignOut ? async () => {
173
177
  await user.signOut();
174
- }}
178
+ } : undefined}
175
179
  >
176
180
  <Typography>
177
181
  {t("Please verify your email address ")}
@@ -190,4 +194,3 @@ function VerifyEmailScreen(props: {
190
194
  </MessageCard>
191
195
  );
192
196
  }
193
-