@hexclave/next 1.0.13 → 1.0.15

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 (189) hide show
  1. package/dist/clickmap/clickmap-core.d.ts +15 -0
  2. package/dist/clickmap/clickmap-core.d.ts.map +1 -0
  3. package/dist/clickmap/clickmap-core.js +1527 -0
  4. package/dist/clickmap/clickmap-core.js.map +1 -0
  5. package/dist/clickmap/clickmap-styles.d.ts +5 -0
  6. package/dist/clickmap/clickmap-styles.d.ts.map +1 -0
  7. package/dist/clickmap/clickmap-styles.js +1095 -0
  8. package/dist/clickmap/clickmap-styles.js.map +1 -0
  9. package/dist/clickmap/index.d.ts +16 -0
  10. package/dist/clickmap/index.d.ts.map +1 -0
  11. package/dist/clickmap/index.js +74 -0
  12. package/dist/clickmap/index.js.map +1 -0
  13. package/dist/components/api-key-dialogs.js +2 -2
  14. package/dist/components/credential-sign-in.js +1 -1
  15. package/dist/components/credential-sign-up.js +1 -1
  16. package/dist/components/magic-link-sign-in.js +1 -1
  17. package/dist/components/message-cards/known-error-message-card.d.ts +1 -1
  18. package/dist/components/team-switcher.js +1 -1
  19. package/dist/components-page/account-settings/active-sessions/active-sessions-page.js +1 -1
  20. package/dist/components-page/account-settings/email-and-auth/emails-section.js +1 -1
  21. package/dist/components-page/account-settings/email-and-auth/mfa-section.js +1 -1
  22. package/dist/components-page/account-settings/email-and-auth/password-section.js +1 -1
  23. package/dist/components-page/account-settings/teams/team-creation-page.js +1 -1
  24. package/dist/components-page/account-settings/teams/team-member-invitation-section.js +1 -1
  25. package/dist/components-page/auth-page.js +1 -1
  26. package/dist/components-page/cli-auth-confirm.js +1 -1
  27. package/dist/components-page/cli-auth-confirm.test.js +1 -1
  28. package/dist/components-page/forgot-password.d.ts.map +1 -1
  29. package/dist/components-page/forgot-password.js +2 -3
  30. package/dist/components-page/forgot-password.js.map +1 -1
  31. package/dist/components-page/hexclave-handler-client.d.ts +1 -1
  32. package/dist/components-page/mfa.js +4 -19
  33. package/dist/components-page/mfa.js.map +1 -1
  34. package/dist/components-page/oauth-callback.js +1 -1
  35. package/dist/components-page/onboarding.js +1 -1
  36. package/dist/components-page/password-reset.d.ts.map +1 -1
  37. package/dist/components-page/password-reset.js +5 -7
  38. package/dist/components-page/password-reset.js.map +1 -1
  39. package/dist/components-page/team-creation.js +1 -1
  40. package/dist/dev-tool/dev-tool-core.d.ts.map +1 -1
  41. package/dist/dev-tool/dev-tool-core.js +258 -262
  42. package/dist/dev-tool/dev-tool-core.js.map +1 -1
  43. package/dist/dev-tool/dev-tool-styles.d.ts +1 -1
  44. package/dist/dev-tool/dev-tool-styles.d.ts.map +1 -1
  45. package/dist/dev-tool/dev-tool-styles.js +13 -143
  46. package/dist/dev-tool/dev-tool-styles.js.map +1 -1
  47. package/dist/dev-tool/index.d.ts.map +1 -1
  48. package/dist/dev-tool/index.js +5 -12
  49. package/dist/dev-tool/index.js.map +1 -1
  50. package/dist/esm/clickmap/clickmap-core.d.ts +15 -0
  51. package/dist/esm/clickmap/clickmap-core.d.ts.map +1 -0
  52. package/dist/esm/clickmap/clickmap-core.js +1525 -0
  53. package/dist/esm/clickmap/clickmap-core.js.map +1 -0
  54. package/dist/esm/clickmap/clickmap-styles.d.ts +5 -0
  55. package/dist/esm/clickmap/clickmap-styles.d.ts.map +1 -0
  56. package/dist/esm/clickmap/clickmap-styles.js +1093 -0
  57. package/dist/esm/clickmap/clickmap-styles.js.map +1 -0
  58. package/dist/esm/clickmap/index.d.ts +16 -0
  59. package/dist/esm/clickmap/index.d.ts.map +1 -0
  60. package/dist/esm/clickmap/index.js +72 -0
  61. package/dist/esm/clickmap/index.js.map +1 -0
  62. package/dist/esm/components/api-key-dialogs.js +2 -2
  63. package/dist/esm/components/credential-sign-in.js +1 -1
  64. package/dist/esm/components/credential-sign-up.js +1 -1
  65. package/dist/esm/components/magic-link-sign-in.js +1 -1
  66. package/dist/esm/components/team-switcher.js +1 -1
  67. package/dist/esm/components-page/account-settings/active-sessions/active-sessions-page.js +1 -1
  68. package/dist/esm/components-page/account-settings/email-and-auth/emails-section.js +1 -1
  69. package/dist/esm/components-page/account-settings/email-and-auth/mfa-section.js +1 -1
  70. package/dist/esm/components-page/account-settings/email-and-auth/password-section.js +1 -1
  71. package/dist/esm/components-page/account-settings/teams/team-creation-page.js +1 -1
  72. package/dist/esm/components-page/account-settings/teams/team-member-invitation-section.js +1 -1
  73. package/dist/esm/components-page/auth-page.js +1 -1
  74. package/dist/esm/components-page/cli-auth-confirm.js +1 -1
  75. package/dist/esm/components-page/cli-auth-confirm.test.js +1 -1
  76. package/dist/esm/components-page/forgot-password.d.ts.map +1 -1
  77. package/dist/esm/components-page/forgot-password.js +2 -3
  78. package/dist/esm/components-page/forgot-password.js.map +1 -1
  79. package/dist/esm/components-page/hexclave-handler-client.d.ts +1 -1
  80. package/dist/esm/components-page/mfa.js +4 -19
  81. package/dist/esm/components-page/mfa.js.map +1 -1
  82. package/dist/esm/components-page/oauth-callback.js +1 -1
  83. package/dist/esm/components-page/onboarding.js +1 -1
  84. package/dist/esm/components-page/password-reset.d.ts.map +1 -1
  85. package/dist/esm/components-page/password-reset.js +5 -7
  86. package/dist/esm/components-page/password-reset.js.map +1 -1
  87. package/dist/esm/components-page/team-creation.js +1 -1
  88. package/dist/esm/dev-tool/dev-tool-core.d.ts.map +1 -1
  89. package/dist/esm/dev-tool/dev-tool-core.js +35 -39
  90. package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
  91. package/dist/esm/dev-tool/dev-tool-styles.d.ts +1 -1
  92. package/dist/esm/dev-tool/dev-tool-styles.d.ts.map +1 -1
  93. package/dist/esm/dev-tool/dev-tool-styles.js +13 -143
  94. package/dist/esm/dev-tool/dev-tool-styles.js.map +1 -1
  95. package/dist/esm/dev-tool/index.d.ts.map +1 -1
  96. package/dist/esm/dev-tool/index.js +2 -9
  97. package/dist/esm/dev-tool/index.js.map +1 -1
  98. package/dist/esm/generated/global-css.d.ts +1 -1
  99. package/dist/esm/generated/global-css.js +1 -1
  100. package/dist/esm/generated/global-css.js.map +1 -1
  101. package/dist/esm/generated/quetzal-translations.d.ts +2 -2
  102. package/dist/esm/in-page-ui/base-styles.d.ts +5 -0
  103. package/dist/esm/in-page-ui/base-styles.d.ts.map +1 -0
  104. package/dist/esm/in-page-ui/base-styles.js +166 -0
  105. package/dist/esm/in-page-ui/base-styles.js.map +1 -0
  106. package/dist/esm/in-page-ui/dom.d.ts +15 -0
  107. package/dist/esm/in-page-ui/dom.d.ts.map +1 -0
  108. package/dist/esm/in-page-ui/dom.js +44 -0
  109. package/dist/esm/in-page-ui/dom.js.map +1 -0
  110. package/dist/esm/lib/auth.js +1 -1
  111. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +5 -1
  112. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  113. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js +20 -0
  114. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  115. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  116. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +4 -2
  117. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  118. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
  119. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.d.ts +13 -0
  120. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.d.ts.map +1 -1
  121. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.js +146 -14
  122. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.js.map +1 -1
  123. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.test.js +221 -0
  124. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.test.js.map +1 -1
  125. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  126. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js +1 -1
  127. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.js +1 -1
  128. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.d.ts +5 -0
  129. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.d.ts.map +1 -1
  130. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.js.map +1 -1
  131. package/dist/esm/providers/theme-provider.js +1 -1
  132. package/dist/generated/global-css.d.ts +1 -1
  133. package/dist/generated/global-css.js +1 -1
  134. package/dist/generated/global-css.js.map +1 -1
  135. package/dist/generated/quetzal-translations.d.ts +2 -2
  136. package/dist/in-page-ui/base-styles.d.ts +5 -0
  137. package/dist/in-page-ui/base-styles.d.ts.map +1 -0
  138. package/dist/in-page-ui/base-styles.js +168 -0
  139. package/dist/in-page-ui/base-styles.js.map +1 -0
  140. package/dist/in-page-ui/dom.d.ts +15 -0
  141. package/dist/in-page-ui/dom.d.ts.map +1 -0
  142. package/dist/in-page-ui/dom.js +51 -0
  143. package/dist/in-page-ui/dom.js.map +1 -0
  144. package/dist/index.d.ts +1 -1
  145. package/dist/integrations/convex/component/convex.config.d.ts +1 -1
  146. package/dist/lib/auth.js +1 -1
  147. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +5 -1
  148. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  149. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js +20 -0
  150. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  151. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  152. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +4 -2
  153. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  154. package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
  155. package/dist/lib/hexclave-app/apps/implementations/event-tracker.d.ts +13 -0
  156. package/dist/lib/hexclave-app/apps/implementations/event-tracker.d.ts.map +1 -1
  157. package/dist/lib/hexclave-app/apps/implementations/event-tracker.js +146 -14
  158. package/dist/lib/hexclave-app/apps/implementations/event-tracker.js.map +1 -1
  159. package/dist/lib/hexclave-app/apps/implementations/event-tracker.test.js +221 -0
  160. package/dist/lib/hexclave-app/apps/implementations/event-tracker.test.js.map +1 -1
  161. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  162. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js +1 -1
  163. package/dist/lib/hexclave-app/apps/implementations/session-replay.js +1 -1
  164. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts +5 -0
  165. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts.map +1 -1
  166. package/dist/lib/hexclave-app/apps/interfaces/admin-app.js.map +1 -1
  167. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +1 -1
  168. package/dist/lib/hexclave-app/common.d.ts +1 -1
  169. package/dist/providers/hexclave-provider-client.d.ts +1 -1
  170. package/dist/providers/theme-provider.js +1 -1
  171. package/dist/{storage-CKzvsBxG.d.ts → storage-ksajV_p6.d.ts} +1 -1
  172. package/dist/{storage-CKzvsBxG.d.ts.map → storage-ksajV_p6.d.ts.map} +1 -1
  173. package/package.json +4 -4
  174. package/src/clickmap/clickmap-core.ts +1997 -0
  175. package/src/clickmap/clickmap-styles.ts +1102 -0
  176. package/src/clickmap/index.ts +95 -0
  177. package/src/components-page/forgot-password.tsx +1 -2
  178. package/src/components-page/mfa.tsx +12 -21
  179. package/src/components-page/password-reset.tsx +4 -6
  180. package/src/dev-tool/dev-tool-core.ts +38 -65
  181. package/src/dev-tool/dev-tool-styles.ts +13 -142
  182. package/src/dev-tool/index.ts +1 -14
  183. package/src/in-page-ui/base-styles.ts +171 -0
  184. package/src/in-page-ui/dom.ts +80 -0
  185. package/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts +23 -1
  186. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +7 -0
  187. package/src/lib/hexclave-app/apps/implementations/event-tracker.test.ts +287 -0
  188. package/src/lib/hexclave-app/apps/implementations/event-tracker.ts +226 -16
  189. package/src/lib/hexclave-app/apps/interfaces/admin-app.ts +3 -0
@@ -0,0 +1,95 @@
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
+
6
+ import {
7
+ CLICKMAP_OVERLAY_RESUME_STORAGE_KEY,
8
+ CLICKMAP_OVERLAY_TOKEN_UPDATED_EVENT,
9
+ } from "@hexclave/shared/dist/utils/analytics-clickmap-overlay";
10
+ import { captureError } from "@hexclave/shared/dist/utils/errors";
11
+ import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
12
+ import { canMountIntoDom } from "../in-page-ui/dom";
13
+ import type { StackClientApp } from "../lib/hexclave-app";
14
+ import type { openClickmapOverlay as OpenClickmapOverlayFn } from "./clickmap-core";
15
+
16
+ // While the overlay is open it drops a sentinel into sessionStorage on unload
17
+ // (see clickmap-core); consuming it here reopens the clickmap on the next page
18
+ // so the user picks up where they left off.
19
+ function consumeResumeSentinel(): boolean {
20
+ try {
21
+ if (sessionStorage.getItem(CLICKMAP_OVERLAY_RESUME_STORAGE_KEY) !== '1') return false;
22
+ sessionStorage.removeItem(CLICKMAP_OVERLAY_RESUME_STORAGE_KEY);
23
+ return true;
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ let activeApp: StackClientApp<true> | null = null;
30
+ let activeOverlayCleanup: (() => void) | null = null;
31
+ let openGeneration = 0;
32
+ let tokenListenerAttached = false;
33
+
34
+ let openClickmapOverlayPromise: Promise<typeof OpenClickmapOverlayFn> | null = null;
35
+ function loadOpenClickmapOverlay(): Promise<typeof OpenClickmapOverlayFn> {
36
+ if (!openClickmapOverlayPromise) {
37
+ openClickmapOverlayPromise = import("./clickmap-core").then(m => m.openClickmapOverlay).catch((err) => {
38
+ openClickmapOverlayPromise = null;
39
+ throw err;
40
+ });
41
+ }
42
+ return openClickmapOverlayPromise;
43
+ }
44
+
45
+ function tryOpenOverlay() {
46
+ // Already open: the panel listens for the token event itself and refetches.
47
+ if (activeOverlayCleanup || !activeApp || !canMountIntoDom()) return;
48
+
49
+ const generation = ++openGeneration;
50
+ const app = activeApp;
51
+
52
+ runAsynchronously(async () => {
53
+ const openClickmapOverlay = await loadOpenClickmapOverlay();
54
+ if (generation !== openGeneration) return;
55
+ if (activeOverlayCleanup || activeApp !== app || !canMountIntoDom()) return;
56
+ activeOverlayCleanup = openClickmapOverlay(app, () => {
57
+ activeOverlayCleanup = null;
58
+ });
59
+ }, {
60
+ noErrorLogging: true,
61
+ onError: (error) => {
62
+ captureError("clickmap-mount", error);
63
+ },
64
+ });
65
+ }
66
+
67
+ /**
68
+ * Mounts the clickmap overlay listener on the page.
69
+ *
70
+ * The clickmap is fully independent from the dev tool. It has no ambient UI:
71
+ * nothing renders until a dashboard-minted token is handed over (the
72
+ * CLICKMAP_OVERLAY_TOKEN_UPDATED event fired by the dashboard's console
73
+ * snippet) or a navigation-resume sentinel is present — only then is the
74
+ * actual overlay code lazily loaded and shown.
75
+ */
76
+ export function mountClickmapOverlay(app: StackClientApp<true>): () => void {
77
+ activeApp = app;
78
+
79
+ if (typeof window !== 'undefined' && !tokenListenerAttached) {
80
+ tokenListenerAttached = true;
81
+ window.addEventListener(CLICKMAP_OVERLAY_TOKEN_UPDATED_EVENT, tryOpenOverlay);
82
+ }
83
+
84
+ if (canMountIntoDom() && consumeResumeSentinel()) {
85
+ tryOpenOverlay();
86
+ }
87
+
88
+ return () => {
89
+ if (activeApp !== app) return;
90
+ activeApp = null;
91
+ openGeneration++;
92
+ activeOverlayCleanup?.();
93
+ };
94
+ }
95
+
@@ -54,8 +54,7 @@ export function ForgotPasswordForm({ onSent }: { onSent?: () => void }) {
54
54
  id="email"
55
55
  type="email"
56
56
  autoComplete="email"
57
- {...register('email')}
58
- onChange={() => clearErrors('email')}
57
+ {...register('email', { onChange: () => clearErrors('email') })}
59
58
  />
60
59
  <FormWarningText text={errors.email?.message?.toString()} />
61
60
 
@@ -196,27 +196,18 @@ export function MFA(props: {
196
196
  const headerText = t("Multi-Factor Authentication");
197
197
  const instructionText = t("Enter the six-digit code from your authenticator app");
198
198
 
199
- if (props.fullPage) {
200
- return (
201
- <MaybeFullPage fullPage={true}>
202
- <div
203
- className="stack-scope flex flex-col items-stretch"
204
- style={{ maxWidth: "380px", flexBasis: "380px", padding: "1rem" }}
205
- >
206
- <div className="text-center mb-6">
207
- <Typography type="h2">{headerText}</Typography>
208
- <Typography className="mt-2">{instructionText}</Typography>
209
- </div>
210
- <MfaForm onSuccess={props.onSuccess} onCancel={props.onCancel} />
211
- </div>
212
- </MaybeFullPage>
213
- );
214
- }
215
-
216
199
  return (
217
- <div className="flex flex-col items-stretch stack-scope">
218
- <Typography className="mb-4 text-center">{instructionText}</Typography>
219
- <MfaForm onSuccess={props.onSuccess} onCancel={props.onCancel} />
220
- </div>
200
+ <MaybeFullPage fullPage={!!props.fullPage}>
201
+ <div className={cn(
202
+ "stack-scope max-w-[380px] flex-basis-[380px]",
203
+ props.fullPage ? "p-4" : "p-0"
204
+ )}>
205
+ <div className="text-center mb-6">
206
+ <Typography type="h2">{headerText}</Typography>
207
+ <Typography className="mt-2 text-sm text-muted-foreground">{instructionText}</Typography>
208
+ </div>
209
+ <MfaForm onSuccess={props.onSuccess} onCancel={props.onCancel} />
210
+ </div>
211
+ </MaybeFullPage>
221
212
  );
222
213
  }
@@ -100,11 +100,10 @@ export default function PasswordResetForm(props: {
100
100
  <PasswordInput
101
101
  id="password"
102
102
  autoComplete="new-password"
103
- {...register('password')}
104
- onChange={() => {
103
+ {...register('password', { onChange: () => {
105
104
  clearErrors('password');
106
105
  clearErrors('passwordRepeat');
107
- }}
106
+ } })}
108
107
  />
109
108
  <FormWarningText text={errors.password?.message?.toString()} />
110
109
 
@@ -112,11 +111,10 @@ export default function PasswordResetForm(props: {
112
111
  <PasswordInput
113
112
  id="repeat-password"
114
113
  autoComplete="new-password"
115
- {...register('passwordRepeat')}
116
- onChange={() => {
114
+ {...register('passwordRepeat', { onChange: () => {
117
115
  clearErrors('password');
118
116
  clearErrors('passwordRepeat');
119
- }}
117
+ } })}
120
118
  />
121
119
  <FormWarningText text={errors.passwordRepeat?.message?.toString()} />
122
120
 
@@ -4,10 +4,12 @@
4
4
  //===========================================
5
5
 
6
6
  import type { RequestLogEntry } from "@hexclave/shared/dist/interface/client-interface";
7
+ import { DEV_TOOL_ROOT_ID } from "@hexclave/shared/dist/utils/dev-tool";
7
8
  import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
8
9
  import { isLocalhost } from "@hexclave/shared/dist/utils/urls";
9
10
  import type { StackClientApp } from "../lib/hexclave-app";
10
11
  import { envVars } from "../generated/env";
12
+ import { getGlobalUiInstance, h, hasAppendChild, setGlobalUiInstance, setHtml, type UiGlobalInstance } from "../in-page-ui/dom";
11
13
  import { getBaseUrl } from "../lib/hexclave-app/apps/implementations/common";
12
14
  import type { HandlerUrlOptions, HandlerUrls, HandlerUrlTarget } from "../lib/hexclave-app/common";
13
15
  import { hexclaveAppInternalsSymbol } from "../lib/hexclave-app/common";
@@ -55,7 +57,7 @@ type DevToolState = {
55
57
  // Hexclave rebrand: UI-only local prefs — straight rename (one-time reset is harmless)
56
58
  const STORAGE_KEY = '__hexclave-dev-tool-state';
57
59
  const TRIGGER_POS_KEY = 'hexclave-devtool-trigger-position';
58
- const ROOT_ID = '__hexclave-dev-tool-root';
60
+ const ROOT_ID = DEV_TOOL_ROOT_ID;
59
61
  const GLOBAL_INSTANCE_KEY = '__hexclave-dev-tool-instance';
60
62
  const MAX_LOG_ENTRIES = 500;
61
63
  const CONSOLE_LOG_BATCH_SIZE = 100;
@@ -71,6 +73,10 @@ const TABS: { id: TabId; label: string; icon: string }[] = [
71
73
  { id: 'support', label: 'Support', icon: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>' },
72
74
  ];
73
75
 
76
+ // Clickmaps is intentionally NOT a dev tool tab or feature. It's a fully
77
+ // independent module (see src/clickmap) with its own mount, root element, and
78
+ // styles, so the dev tool can be changed or removed without affecting it.
79
+
74
80
  const DEFAULT_STATE: DevToolState = {
75
81
  isOpen: false,
76
82
  activeTab: 'overview',
@@ -142,29 +148,6 @@ type LogStore = {
142
148
  subscribe(fn: () => void): () => void;
143
149
  };
144
150
 
145
- type DevToolGlobalInstance = {
146
- cleanup: () => void;
147
- };
148
-
149
- function isDevToolGlobalInstance(value: unknown): value is DevToolGlobalInstance {
150
- return typeof value === 'object' && value !== null && typeof Reflect.get(value, 'cleanup') === 'function';
151
- }
152
-
153
- function getGlobalDevToolInstance(): DevToolGlobalInstance | null {
154
- if (typeof window === 'undefined') return null;
155
- const value: unknown = Reflect.get(window, GLOBAL_INSTANCE_KEY);
156
- return isDevToolGlobalInstance(value) ? value : null;
157
- }
158
-
159
- function setGlobalDevToolInstance(instance: DevToolGlobalInstance | null) {
160
- if (typeof window === 'undefined') return;
161
- if (instance === null) {
162
- Reflect.deleteProperty(window, GLOBAL_INSTANCE_KEY);
163
- } else {
164
- Reflect.set(window, GLOBAL_INSTANCE_KEY, instance);
165
- }
166
- }
167
-
168
151
  function getGlobalLogStore(): LogStore {
169
152
  const g = globalThis as any;
170
153
  if (!g.__STACK_DEV_TOOL_LOG_STORE__) {
@@ -272,41 +255,6 @@ function generateRandomEmail(): string {
272
255
  // DOM helpers
273
256
  // ---------------------------------------------------------------------------
274
257
 
275
- function h<K extends keyof HTMLElementTagNameMap>(
276
- tag: K,
277
- attrs?: Record<string, any> | null,
278
- ...children: (string | Node | null | undefined)[]
279
- ): HTMLElementTagNameMap[K] {
280
- const el = document.createElement(tag);
281
- if (attrs) {
282
- for (const [k, v] of Object.entries(attrs)) {
283
- if (v == null) continue;
284
- if (k === 'className') {
285
- el.className = v;
286
- } else if (k === 'style' && typeof v === 'object') {
287
- Object.assign(el.style, v);
288
- } else if (k.startsWith('on') && typeof v === 'function') {
289
- el.addEventListener(k.slice(2).toLowerCase(), v);
290
- } else {
291
- el.setAttribute(k, String(v));
292
- }
293
- }
294
- }
295
- for (const child of children) {
296
- if (child == null) continue;
297
- el.appendChild(typeof child === 'string' ? document.createTextNode(child) : child);
298
- }
299
- return el;
300
- }
301
-
302
- function setHtml(el: HTMLElement, html: string) {
303
- el.innerHTML = html;
304
- }
305
-
306
- function hasAppendChild(value: unknown): value is { appendChild(node: Node): void } {
307
- return typeof value === 'object' && value !== null && typeof Reflect.get(value, 'appendChild') === 'function';
308
- }
309
-
310
258
  function parseMarkdownImage(line: string): { alt: string, src: string } | null {
311
259
  const match = line.trim().match(/^!\[([^\]]*)\]\((.+)\)$/);
312
260
  if (!match) return null;
@@ -666,8 +614,13 @@ function createIframeTab(src: string, title: string, loadingMsg = 'Loading\u2026
666
614
  // Overview tab
667
615
  // ---------------------------------------------------------------------------
668
616
 
617
+ function hasPersistentTokenStoreForDevTool(app: StackClientApp<boolean>): boolean {
618
+ return app[hexclaveAppInternalsSymbol].getConstructorOptions().tokenStore !== null;
619
+ }
620
+
669
621
  function createOverviewTab(app: StackClientApp<true>): TabResult {
670
622
  const container = h('div', { className: 'sdt-ov' });
623
+ const hasPersistentTokenStore = hasPersistentTokenStoreForDevTool(app);
671
624
 
672
625
  // ── Identity card ──────────────────────────────────────────────────────────
673
626
  const heroCard = h('div', { className: 'sdt-ov-card sdt-ov-card-hero' });
@@ -721,6 +674,12 @@ function createOverviewTab(app: StackClientApp<true>): TabResult {
721
674
 
722
675
  function rebuildActions() {
723
676
  actions.innerHTML = '';
677
+ if (!hasPersistentTokenStore) {
678
+ userName.textContent = 'Current user unavailable';
679
+ userEmail.textContent = 'This app was initialized without a token store';
680
+ actions.appendChild(h('button', { className: 'sdt-ov-btn sdt-ov-btn-wide', disabled: 'true' }, 'Session actions unavailable'));
681
+ return;
682
+ }
724
683
  if (currentUser) {
725
684
  const signOutBtn = h('button', { className: 'sdt-ov-btn sdt-ov-btn-danger' }, 'Sign Out');
726
685
  signOutBtn.disabled = loading;
@@ -895,10 +854,13 @@ function createOverviewTab(app: StackClientApp<true>): TabResult {
895
854
 
896
855
  function buildChecklist() {
897
856
  checksCard.innerHTML = '';
857
+ const currentUserCheck = hasPersistentTokenStore
858
+ ? { ok: !!currentUser, label: 'Sign in a test user', hint: 'Use \u201cQuick Sign In\u201d above \u2192' }
859
+ : { ok: true, label: 'Current-user tools unavailable', hint: null };
898
860
  const checks = [
899
861
  { ok: !!projectId && projectId !== 'default', label: 'Project configured', hint: null },
900
862
  { ok: hasActiveAuthMethod === true, label: 'Auth method active', hint: hasActiveAuthMethod === null ? 'Still checking project config' : null },
901
- { ok: !!currentUser, label: 'Sign in a test user', hint: 'Use \u201cQuick Sign In\u201d above \u2192' },
863
+ currentUserCheck,
902
864
  ];
903
865
  const passCount = checks.filter((c) => c.ok).length;
904
866
  const allGood = passCount === checks.length;
@@ -940,6 +902,17 @@ function createOverviewTab(app: StackClientApp<true>): TabResult {
940
902
  }
941
903
 
942
904
  async function refreshUser() {
905
+ if (!hasPersistentTokenStore) {
906
+ avatar.className = 'sdt-ov-avatar';
907
+ avatar.textContent = '?';
908
+ userName.textContent = 'Current user unavailable';
909
+ userEmail.textContent = 'This app was initialized without a token store';
910
+ authIndicator.style.display = 'none';
911
+ currentUser = null;
912
+ rebuildActions();
913
+ buildChecklist();
914
+ return;
915
+ }
943
916
  try {
944
917
  currentUser = await app.getUser();
945
918
 
@@ -2354,7 +2327,7 @@ export function createDevTool(app: StackClientApp<true>): () => void {
2354
2327
  const body = Reflect.get(document, 'body');
2355
2328
  if (!hasAppendChild(body)) return () => {};
2356
2329
 
2357
- getGlobalDevToolInstance()?.cleanup();
2330
+ getGlobalUiInstance(GLOBAL_INSTANCE_KEY)?.cleanup();
2358
2331
  let existingRoot = document.getElementById(ROOT_ID);
2359
2332
  while (existingRoot !== null) {
2360
2333
  existingRoot.remove();
@@ -2436,12 +2409,12 @@ export function createDevTool(app: StackClientApp<true>): () => void {
2436
2409
  });
2437
2410
 
2438
2411
  let didCleanup = false;
2439
- const instance: DevToolGlobalInstance = {
2412
+ const instance: UiGlobalInstance = {
2440
2413
  cleanup: () => {
2441
2414
  if (didCleanup) return;
2442
2415
  didCleanup = true;
2443
- if (getGlobalDevToolInstance() === instance) {
2444
- setGlobalDevToolInstance(null);
2416
+ if (getGlobalUiInstance(GLOBAL_INSTANCE_KEY) === instance) {
2417
+ setGlobalUiInstance(GLOBAL_INSTANCE_KEY, null);
2445
2418
  }
2446
2419
  trigger.cleanup();
2447
2420
  removeRequestListener();
@@ -2451,7 +2424,7 @@ export function createDevTool(app: StackClientApp<true>): () => void {
2451
2424
  }
2452
2425
  },
2453
2426
  };
2454
- setGlobalDevToolInstance(instance);
2427
+ setGlobalUiInstance(GLOBAL_INSTANCE_KEY, instance);
2455
2428
 
2456
2429
  return () => {
2457
2430
  instance.cleanup();
@@ -5,53 +5,11 @@
5
5
  // Theme-aware CSS for the dev tool indicator
6
6
  // Respects Stack theme (data-stack-theme attribute) and system prefers-color-scheme
7
7
  // Uses .hexclave-devtool scope to avoid conflicts with host app styles
8
+ // Design tokens + base reset come from the shared in-page-ui module.
8
9
 
9
- export const devToolCSS = `
10
- .hexclave-devtool {
11
- --sdt-bg: #0a0a0b;
12
- --sdt-bg-elevated: #141416;
13
- --sdt-bg-hover: #1c1c1f;
14
- --sdt-bg-active: #232326;
15
- --sdt-bg-subtle: #111113;
16
- --sdt-border: #2a2a2e;
17
- --sdt-border-subtle: #1e1e22;
18
- --sdt-text: #ececef;
19
- --sdt-text-secondary: #8b8b93;
20
- --sdt-text-tertiary: #5c5c66;
21
- --sdt-accent: #6366f1;
22
- --sdt-accent-hover: #818cf8;
23
- --sdt-accent-muted: rgba(99, 102, 241, 0.15);
24
- --sdt-success: #22c55e;
25
- --sdt-success-muted: rgba(34, 197, 94, 0.15);
26
- --sdt-warning: #eab308;
27
- --sdt-warning-muted: rgba(234, 179, 8, 0.15);
28
- --sdt-error: #ef4444;
29
- --sdt-error-muted: rgba(239, 68, 68, 0.15);
30
- --sdt-info: #3b82f6;
31
- --sdt-info-muted: rgba(59, 130, 246, 0.15);
32
- --sdt-overlay-bg: rgba(17, 17, 19, 0.92);
33
- --sdt-radius: 8px;
34
- --sdt-radius-sm: 4px;
35
- --sdt-radius-lg: 12px;
36
- --sdt-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
37
- --sdt-font-mono: 'SF Mono', SFMono-Regular, ui-monospace, 'DejaVu Sans Mono', Menlo, Consolas, monospace;
38
- --sdt-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.05);
39
- --sdt-trigger-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.08);
40
-
41
- all: initial;
42
- font-family: var(--sdt-font);
43
- color: var(--sdt-text);
44
- font-size: 13px;
45
- line-height: 1.5;
46
- -webkit-font-smoothing: antialiased;
47
- -moz-osx-font-smoothing: grayscale;
48
- box-sizing: border-box;
49
- }
50
-
51
- .hexclave-devtool *, .hexclave-devtool *::before, .hexclave-devtool *::after {
52
- box-sizing: border-box;
53
- }
10
+ import { getInPageUiBaseCSS } from "../in-page-ui/base-styles";
54
11
 
12
+ export const devToolCSS = getInPageUiBaseCSS('.hexclave-devtool') + `
55
13
  /* Trigger pill */
56
14
  .hexclave-devtool .sdt-trigger {
57
15
  position: fixed;
@@ -103,7 +61,7 @@ export const devToolCSS = `
103
61
  position: fixed;
104
62
  bottom: 60px;
105
63
  right: 16px;
106
- z-index: 99998;
64
+ z-index: 2147483647;
107
65
  width: 800px;
108
66
  max-width: calc(100vw - 32px);
109
67
  height: 520px;
@@ -193,6 +151,7 @@ export const devToolCSS = `
193
151
  flex-shrink: 0;
194
152
  gap: 2px;
195
153
  overflow-x: auto;
154
+ overflow-y: hidden;
196
155
  }
197
156
 
198
157
  .hexclave-devtool .sdt-panel-fullscreen .sdt-tabbar {
@@ -263,9 +222,15 @@ export const devToolCSS = `
263
222
  }
264
223
 
265
224
  .hexclave-devtool .sdt-tabbar-actions {
225
+ position: sticky;
226
+ right: 0;
227
+ z-index: 2;
266
228
  display: flex;
267
229
  align-items: center;
230
+ align-self: stretch;
268
231
  gap: 4px;
232
+ padding-left: 6px;
233
+ background: inherit;
269
234
  flex-shrink: 0;
270
235
  }
271
236
 
@@ -370,19 +335,6 @@ export const devToolCSS = `
370
335
  }
371
336
  }
372
337
 
373
- .hexclave-devtool .sdt-tab-pane::-webkit-scrollbar {
374
- width: 6px;
375
- }
376
-
377
- .hexclave-devtool .sdt-tab-pane::-webkit-scrollbar-track {
378
- background: transparent;
379
- }
380
-
381
- .hexclave-devtool .sdt-tab-pane::-webkit-scrollbar-thumb {
382
- background: var(--sdt-border);
383
- border-radius: 3px;
384
- }
385
-
386
338
  /* ===== Overview tab — single column ===== */
387
339
 
388
340
  .hexclave-devtool .sdt-ov {
@@ -1935,35 +1887,8 @@ export const devToolCSS = `
1935
1887
  opacity: 1;
1936
1888
  }
1937
1889
 
1938
- /* --- Light theme: system preference fallback --- */
1939
- @media (prefers-color-scheme: light) {
1940
- .hexclave-devtool {
1941
- --sdt-bg: #ffffff;
1942
- --sdt-bg-elevated: #f8f8fa;
1943
- --sdt-bg-hover: #f0f0f3;
1944
- --sdt-bg-active: #e8e8ec;
1945
- --sdt-bg-subtle: #fafafa;
1946
- --sdt-border: #e0e0e5;
1947
- --sdt-border-subtle: #eaeaef;
1948
- --sdt-text: #111113;
1949
- --sdt-text-secondary: #6b6b73;
1950
- --sdt-text-tertiary: #9b9ba3;
1951
- --sdt-accent: #6366f1;
1952
- --sdt-accent-hover: #4f46e5;
1953
- --sdt-accent-muted: rgba(99, 102, 241, 0.1);
1954
- --sdt-success: #16a34a;
1955
- --sdt-success-muted: rgba(22, 163, 74, 0.1);
1956
- --sdt-warning: #ca8a04;
1957
- --sdt-warning-muted: rgba(202, 138, 4, 0.1);
1958
- --sdt-error: #dc2626;
1959
- --sdt-error-muted: rgba(220, 38, 38, 0.1);
1960
- --sdt-info: #2563eb;
1961
- --sdt-info-muted: rgba(37, 99, 235, 0.1);
1962
- --sdt-overlay-bg: rgba(255, 255, 255, 0.92);
1963
- --sdt-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.06);
1964
- --sdt-trigger-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.06);
1965
- }
1966
- }
1890
+ /* Light theme + data-stack-theme overrides come from the shared in-page-ui
1891
+ base styles (in-page-ui/base-styles.ts). */
1967
1892
 
1968
1893
  /* Export dialog — positioned inside the dev tool panel */
1969
1894
  .hexclave-devtool .sdt-share-overlay {
@@ -2701,58 +2626,4 @@ export const devToolCSS = `
2701
2626
  }
2702
2627
  }
2703
2628
 
2704
- /* --- Stack theme explicit overrides (take priority over system preference) --- */
2705
- html:has(head > [data-stack-theme="light"]) .hexclave-devtool {
2706
- --sdt-bg: #ffffff;
2707
- --sdt-bg-elevated: #f8f8fa;
2708
- --sdt-bg-hover: #f0f0f3;
2709
- --sdt-bg-active: #e8e8ec;
2710
- --sdt-bg-subtle: #fafafa;
2711
- --sdt-border: #e0e0e5;
2712
- --sdt-border-subtle: #eaeaef;
2713
- --sdt-text: #111113;
2714
- --sdt-text-secondary: #6b6b73;
2715
- --sdt-text-tertiary: #9b9ba3;
2716
- --sdt-accent: #6366f1;
2717
- --sdt-accent-hover: #4f46e5;
2718
- --sdt-accent-muted: rgba(99, 102, 241, 0.1);
2719
- --sdt-success: #16a34a;
2720
- --sdt-success-muted: rgba(22, 163, 74, 0.1);
2721
- --sdt-warning: #ca8a04;
2722
- --sdt-warning-muted: rgba(202, 138, 4, 0.1);
2723
- --sdt-error: #dc2626;
2724
- --sdt-error-muted: rgba(220, 38, 38, 0.1);
2725
- --sdt-info: #2563eb;
2726
- --sdt-info-muted: rgba(37, 99, 235, 0.1);
2727
- --sdt-overlay-bg: rgba(255, 255, 255, 0.92);
2728
- --sdt-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.06);
2729
- --sdt-trigger-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.06);
2730
- }
2731
-
2732
- html:has(head > [data-stack-theme="dark"]) .hexclave-devtool {
2733
- --sdt-bg: #0a0a0b;
2734
- --sdt-bg-elevated: #141416;
2735
- --sdt-bg-hover: #1c1c1f;
2736
- --sdt-bg-active: #232326;
2737
- --sdt-bg-subtle: #111113;
2738
- --sdt-border: #2a2a2e;
2739
- --sdt-border-subtle: #1e1e22;
2740
- --sdt-text: #ececef;
2741
- --sdt-text-secondary: #8b8b93;
2742
- --sdt-text-tertiary: #5c5c66;
2743
- --sdt-accent: #6366f1;
2744
- --sdt-accent-hover: #818cf8;
2745
- --sdt-accent-muted: rgba(99, 102, 241, 0.15);
2746
- --sdt-success: #22c55e;
2747
- --sdt-success-muted: rgba(34, 197, 94, 0.15);
2748
- --sdt-warning: #eab308;
2749
- --sdt-warning-muted: rgba(234, 179, 8, 0.15);
2750
- --sdt-error: #ef4444;
2751
- --sdt-error-muted: rgba(239, 68, 68, 0.15);
2752
- --sdt-info: #3b82f6;
2753
- --sdt-info-muted: rgba(59, 130, 246, 0.15);
2754
- --sdt-overlay-bg: rgba(17, 17, 19, 0.92);
2755
- --sdt-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.05);
2756
- --sdt-trigger-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.08);
2757
- }
2758
2629
  `;
@@ -7,25 +7,12 @@ import type { StackClientApp } from "../lib/hexclave-app";
7
7
  import { captureError } from "@hexclave/shared/dist/utils/errors";
8
8
  import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
9
9
  import { isLocalhost } from "@hexclave/shared/dist/utils/urls";
10
+ import { canMountIntoDom } from "../in-page-ui/dom";
10
11
  import type { createDevTool as CreateDevToolFn } from "./dev-tool-core";
11
12
 
12
13
  // Hexclave rebrand: UI-only local pref — straight rename (one-time reset is harmless)
13
14
  const OVERRIDE_KEY = '__hexclave-dev-tool-override';
14
15
 
15
- function hasAppendChild(value: unknown): value is { appendChild(node: Node): void } {
16
- return typeof value === 'object' && value !== null && typeof Reflect.get(value, 'appendChild') === 'function';
17
- }
18
-
19
- function canMountIntoDom(): boolean {
20
- if (typeof window === 'undefined' || typeof document === 'undefined') {
21
- return false;
22
- }
23
- if (typeof document.createElement !== 'function') {
24
- return false;
25
- }
26
- return hasAppendChild(Reflect.get(document, 'body'));
27
- }
28
-
29
16
  function getOverride(): boolean | null {
30
17
  try {
31
18
  const val = localStorage.getItem(OVERRIDE_KEY);