@hexclave/next 1.0.14 → 1.0.16

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 (220) 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.d.ts +1 -1
  14. package/dist/components/api-key-dialogs.js +5 -5
  15. package/dist/components/credential-sign-in.js +3 -3
  16. package/dist/components/credential-sign-up.js +5 -5
  17. package/dist/components/elements/sidebar-layout.js +1 -1
  18. package/dist/components/elements/user-avatar.js +1 -1
  19. package/dist/components/magic-link-sign-in.js +5 -5
  20. package/dist/components/message-cards/known-error-message-card.d.ts +1 -1
  21. package/dist/components/message-cards/predefined-message-card.js +1 -1
  22. package/dist/components/passkey-button.js +1 -1
  23. package/dist/components/profile-image-editor.js +1 -1
  24. package/dist/components/team-icon.js +1 -1
  25. package/dist/components/team-switcher.js +2 -2
  26. package/dist/components/user-button.js +1 -1
  27. package/dist/components-page/account-settings/active-sessions/active-sessions-page.js +1 -1
  28. package/dist/components-page/account-settings/editable-text.js +1 -1
  29. package/dist/components-page/account-settings/email-and-auth/emails-section.js +3 -3
  30. package/dist/components-page/account-settings/email-and-auth/mfa-section.js +1 -1
  31. package/dist/components-page/account-settings/email-and-auth/password-section.js +3 -3
  32. package/dist/components-page/account-settings/teams/team-api-keys-section.js +1 -1
  33. package/dist/components-page/account-settings/teams/team-creation-page.js +3 -3
  34. package/dist/components-page/account-settings/teams/team-member-invitation-section.js +4 -4
  35. package/dist/components-page/account-settings.js +3 -3
  36. package/dist/components-page/auth-page.js +2 -2
  37. package/dist/components-page/cli-auth-confirm.js +2 -2
  38. package/dist/components-page/cli-auth-confirm.test.js +1 -1
  39. package/dist/components-page/email-verification.js +1 -1
  40. package/dist/components-page/forgot-password.d.ts.map +1 -1
  41. package/dist/components-page/forgot-password.js +6 -7
  42. package/dist/components-page/forgot-password.js.map +1 -1
  43. package/dist/components-page/hexclave-handler-client.d.ts +1 -1
  44. package/dist/components-page/hexclave-handler-client.js +2 -2
  45. package/dist/components-page/magic-link-callback.js +1 -1
  46. package/dist/components-page/mfa.js +7 -22
  47. package/dist/components-page/mfa.js.map +1 -1
  48. package/dist/components-page/oauth-callback.js +2 -2
  49. package/dist/components-page/onboarding.js +4 -4
  50. package/dist/components-page/password-reset.d.ts.map +1 -1
  51. package/dist/components-page/password-reset.js +12 -14
  52. package/dist/components-page/password-reset.js.map +1 -1
  53. package/dist/components-page/team-creation.js +5 -5
  54. package/dist/dev-tool/dev-tool-core.d.ts.map +1 -1
  55. package/dist/dev-tool/dev-tool-core.js +258 -262
  56. package/dist/dev-tool/dev-tool-core.js.map +1 -1
  57. package/dist/dev-tool/dev-tool-styles.d.ts +1 -1
  58. package/dist/dev-tool/dev-tool-styles.d.ts.map +1 -1
  59. package/dist/dev-tool/dev-tool-styles.js +13 -143
  60. package/dist/dev-tool/dev-tool-styles.js.map +1 -1
  61. package/dist/dev-tool/index.d.ts.map +1 -1
  62. package/dist/dev-tool/index.js +4 -11
  63. package/dist/dev-tool/index.js.map +1 -1
  64. package/dist/esm/clickmap/clickmap-core.d.ts +15 -0
  65. package/dist/esm/clickmap/clickmap-core.d.ts.map +1 -0
  66. package/dist/esm/clickmap/clickmap-core.js +1525 -0
  67. package/dist/esm/clickmap/clickmap-core.js.map +1 -0
  68. package/dist/esm/clickmap/clickmap-styles.d.ts +5 -0
  69. package/dist/esm/clickmap/clickmap-styles.d.ts.map +1 -0
  70. package/dist/esm/clickmap/clickmap-styles.js +1093 -0
  71. package/dist/esm/clickmap/clickmap-styles.js.map +1 -0
  72. package/dist/esm/clickmap/index.d.ts +16 -0
  73. package/dist/esm/clickmap/index.d.ts.map +1 -0
  74. package/dist/esm/clickmap/index.js +72 -0
  75. package/dist/esm/clickmap/index.js.map +1 -0
  76. package/dist/esm/components/api-key-dialogs.d.ts +1 -1
  77. package/dist/esm/components/api-key-dialogs.js +5 -5
  78. package/dist/esm/components/credential-sign-in.js +3 -3
  79. package/dist/esm/components/credential-sign-up.js +5 -5
  80. package/dist/esm/components/elements/sidebar-layout.js +1 -1
  81. package/dist/esm/components/elements/user-avatar.js +1 -1
  82. package/dist/esm/components/magic-link-sign-in.js +5 -5
  83. package/dist/esm/components/message-cards/predefined-message-card.js +1 -1
  84. package/dist/esm/components/passkey-button.js +1 -1
  85. package/dist/esm/components/profile-image-editor.js +1 -1
  86. package/dist/esm/components/team-icon.js +1 -1
  87. package/dist/esm/components/team-switcher.js +2 -2
  88. package/dist/esm/components/user-button.js +1 -1
  89. package/dist/esm/components-page/account-settings/active-sessions/active-sessions-page.js +1 -1
  90. package/dist/esm/components-page/account-settings/editable-text.js +1 -1
  91. package/dist/esm/components-page/account-settings/email-and-auth/emails-section.js +3 -3
  92. package/dist/esm/components-page/account-settings/email-and-auth/mfa-section.js +1 -1
  93. package/dist/esm/components-page/account-settings/email-and-auth/password-section.js +3 -3
  94. package/dist/esm/components-page/account-settings/teams/team-api-keys-section.js +1 -1
  95. package/dist/esm/components-page/account-settings/teams/team-creation-page.js +3 -3
  96. package/dist/esm/components-page/account-settings/teams/team-member-invitation-section.js +4 -4
  97. package/dist/esm/components-page/account-settings.d.ts +1 -1
  98. package/dist/esm/components-page/account-settings.js +3 -3
  99. package/dist/esm/components-page/auth-page.js +2 -2
  100. package/dist/esm/components-page/cli-auth-confirm.js +2 -2
  101. package/dist/esm/components-page/cli-auth-confirm.test.js +1 -1
  102. package/dist/esm/components-page/email-verification.js +1 -1
  103. package/dist/esm/components-page/forgot-password.d.ts.map +1 -1
  104. package/dist/esm/components-page/forgot-password.js +6 -7
  105. package/dist/esm/components-page/forgot-password.js.map +1 -1
  106. package/dist/esm/components-page/hexclave-handler-client.d.ts +1 -1
  107. package/dist/esm/components-page/hexclave-handler-client.js +2 -2
  108. package/dist/esm/components-page/magic-link-callback.js +1 -1
  109. package/dist/esm/components-page/mfa.js +7 -22
  110. package/dist/esm/components-page/mfa.js.map +1 -1
  111. package/dist/esm/components-page/oauth-callback.js +2 -2
  112. package/dist/esm/components-page/onboarding.js +4 -4
  113. package/dist/esm/components-page/password-reset.d.ts.map +1 -1
  114. package/dist/esm/components-page/password-reset.js +11 -13
  115. package/dist/esm/components-page/password-reset.js.map +1 -1
  116. package/dist/esm/components-page/team-creation.js +5 -5
  117. package/dist/esm/dev-tool/dev-tool-core.d.ts.map +1 -1
  118. package/dist/esm/dev-tool/dev-tool-core.js +35 -39
  119. package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
  120. package/dist/esm/dev-tool/dev-tool-styles.d.ts +1 -1
  121. package/dist/esm/dev-tool/dev-tool-styles.d.ts.map +1 -1
  122. package/dist/esm/dev-tool/dev-tool-styles.js +13 -143
  123. package/dist/esm/dev-tool/dev-tool-styles.js.map +1 -1
  124. package/dist/esm/dev-tool/index.d.ts.map +1 -1
  125. package/dist/esm/dev-tool/index.js +1 -8
  126. package/dist/esm/dev-tool/index.js.map +1 -1
  127. package/dist/esm/generated/global-css.d.ts +1 -1
  128. package/dist/esm/generated/global-css.js +1 -1
  129. package/dist/esm/generated/global-css.js.map +1 -1
  130. package/dist/esm/generated/quetzal-translations.d.ts +2 -2
  131. package/dist/esm/in-page-ui/base-styles.d.ts +5 -0
  132. package/dist/esm/in-page-ui/base-styles.d.ts.map +1 -0
  133. package/dist/esm/in-page-ui/base-styles.js +166 -0
  134. package/dist/esm/in-page-ui/base-styles.js.map +1 -0
  135. package/dist/esm/in-page-ui/dom.d.ts +15 -0
  136. package/dist/esm/in-page-ui/dom.d.ts.map +1 -0
  137. package/dist/esm/in-page-ui/dom.js +44 -0
  138. package/dist/esm/in-page-ui/dom.js.map +1 -0
  139. package/dist/esm/lib/auth.js +2 -2
  140. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +6 -2
  141. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  142. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js +21 -1
  143. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  144. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
  145. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  146. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +4 -2
  147. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  148. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
  149. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.d.ts +13 -0
  150. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.d.ts.map +1 -1
  151. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.js +146 -14
  152. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.js.map +1 -1
  153. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.test.js +221 -0
  154. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.test.js.map +1 -1
  155. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +2 -2
  156. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js +1 -1
  157. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.d.ts +5 -0
  158. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.d.ts.map +1 -1
  159. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.js.map +1 -1
  160. package/dist/esm/lib/hexclave-app/users/index.d.ts +1 -1
  161. package/dist/esm/providers/theme-provider.js +1 -1
  162. package/dist/esm/providers/translation-provider.js +1 -1
  163. package/dist/generated/global-css.d.ts +1 -1
  164. package/dist/generated/global-css.js +1 -1
  165. package/dist/generated/global-css.js.map +1 -1
  166. package/dist/generated/quetzal-translations.d.ts +2 -2
  167. package/dist/in-page-ui/base-styles.d.ts +5 -0
  168. package/dist/in-page-ui/base-styles.d.ts.map +1 -0
  169. package/dist/in-page-ui/base-styles.js +168 -0
  170. package/dist/in-page-ui/base-styles.js.map +1 -0
  171. package/dist/in-page-ui/dom.d.ts +15 -0
  172. package/dist/in-page-ui/dom.d.ts.map +1 -0
  173. package/dist/in-page-ui/dom.js +51 -0
  174. package/dist/in-page-ui/dom.js.map +1 -0
  175. package/dist/index.d.ts +1 -1
  176. package/dist/integrations/convex/component/convex.config.d.ts +1 -1
  177. package/dist/lib/auth.js +2 -2
  178. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +5 -1
  179. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  180. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js +21 -1
  181. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  182. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  183. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +4 -2
  184. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  185. package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
  186. package/dist/lib/hexclave-app/apps/implementations/event-tracker.d.ts +13 -0
  187. package/dist/lib/hexclave-app/apps/implementations/event-tracker.d.ts.map +1 -1
  188. package/dist/lib/hexclave-app/apps/implementations/event-tracker.js +146 -14
  189. package/dist/lib/hexclave-app/apps/implementations/event-tracker.js.map +1 -1
  190. package/dist/lib/hexclave-app/apps/implementations/event-tracker.test.js +221 -0
  191. package/dist/lib/hexclave-app/apps/implementations/event-tracker.test.js.map +1 -1
  192. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  193. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js +1 -1
  194. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts +5 -0
  195. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts.map +1 -1
  196. package/dist/lib/hexclave-app/apps/interfaces/admin-app.js.map +1 -1
  197. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +1 -1
  198. package/dist/lib/hexclave-app/common.d.ts +1 -1
  199. package/dist/providers/hexclave-provider-client.d.ts +1 -1
  200. package/dist/providers/theme-provider.js +1 -1
  201. package/dist/providers/translation-provider.js +1 -1
  202. package/dist/{storage-CKzvsBxG.d.ts → storage-ksajV_p6.d.ts} +1 -1
  203. package/dist/{storage-CKzvsBxG.d.ts.map → storage-ksajV_p6.d.ts.map} +1 -1
  204. package/package.json +4 -4
  205. package/src/clickmap/clickmap-core.ts +1997 -0
  206. package/src/clickmap/clickmap-styles.ts +1102 -0
  207. package/src/clickmap/index.ts +95 -0
  208. package/src/components-page/forgot-password.tsx +1 -2
  209. package/src/components-page/mfa.tsx +12 -21
  210. package/src/components-page/password-reset.tsx +4 -6
  211. package/src/dev-tool/dev-tool-core.ts +38 -65
  212. package/src/dev-tool/dev-tool-styles.ts +13 -142
  213. package/src/dev-tool/index.ts +1 -14
  214. package/src/in-page-ui/base-styles.ts +171 -0
  215. package/src/in-page-ui/dom.ts +80 -0
  216. package/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts +23 -1
  217. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +7 -0
  218. package/src/lib/hexclave-app/apps/implementations/event-tracker.test.ts +287 -0
  219. package/src/lib/hexclave-app/apps/implementations/event-tracker.ts +226 -16
  220. package/src/lib/hexclave-app/apps/interfaces/admin-app.ts +3 -0
@@ -1 +1 @@
1
- {"version":3,"file":"forgot-password.js","names":[],"sources":["../../../src/components-page/forgot-password.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { strictEmailSchema, yupObject } from \"@hexclave/shared/dist/schema-fields\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { Button, Input, Label, Typography, cn } from \"@hexclave/ui\";\nimport { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp, useUser } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { StyledLink } from \"../components/link\";\nimport { PredefinedMessageCard } from \"../components/message-cards/predefined-message-card\";\nimport { useTranslation } from \"../lib/translations\";\n\nexport function ForgotPasswordForm({ onSent }: { onSent?: () => void }) {\n const { t } = useTranslation();\n\n const schema = yupObject({\n email: strictEmailSchema(t(\"Please enter a valid email\")).defined().nonEmpty(t(\"Please enter your email\"))\n });\n\n const { register, handleSubmit, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const hexclaveApp = useStackApp();\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { email } = data;\n await hexclaveApp.sendForgotPasswordEmail(email);\n onSent?.();\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <form\n className=\"flex flex-col items-stretch stack-scope\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"email\" className=\"mb-1\">{t(\"Your Email\")}</Label>\n <Input\n id=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n {...register('email')}\n onChange={() => clearErrors('email')}\n />\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n {t(\"Send Email\")}\n </Button>\n </form>\n );\n}\n\n\nexport function ForgotPassword(props: { fullPage?: boolean }) {\n const { t } = useTranslation();\n const hexclaveApp = useStackApp();\n const user = useUser();\n const [sent, setSent] = useState(false);\n\n if (user) {\n return <PredefinedMessageCard type='signedIn' fullPage={!!props.fullPage} />;\n }\n\n if (sent) {\n return <PredefinedMessageCard type='emailSent' fullPage={!!props.fullPage} />;\n }\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div className={cn(\n \"stack-scope max-w-[380px] flex-basis-[380px]\",\n props.fullPage ? \"p-4\" : \"p-0\"\n )}>\n <div className=\"text-center\">\n <Typography type='h2'>{t(\"Reset Your Password\")}</Typography>\n <Typography>\n {t(\"Don't need to reset?\")}{\" \"}\n <StyledLink href={hexclaveApp.urls['signIn']}>\n {t(\"Sign in\")}\n </StyledLink>\n </Typography>\n </div>\n <div className=\"mt-6\">\n <ForgotPasswordForm onSent={() => setSent(true)} />\n </div>\n </div>\n </MaybeFullPage>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,SAAgB,mBAAmB,EAAE,UAAmC;CACtE,MAAM,EAAE,MAAM,gBAAgB;CAM9B,MAAM,EAAE,UAAU,cAAc,WAAW,EAAE,UAAU,gBAAgB,QAAQ,EAC7E,UAAU,YALG,UAAU,EACvB,OAAO,kBAAkB,EAAE,6BAA6B,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,0BAA0B,CAAC,EAC3G,CAAC,CAG6B,EAC9B,CAAC;CACF,MAAM,cAAc,aAAa;CACjC,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAE7C,MAAM,WAAW,OAAO,SAAuC;AAC7D,aAAW,KAAK;AAChB,MAAI;GACF,MAAM,EAAE,UAAU;AAClB,SAAM,YAAY,wBAAwB,MAAM;AAClD,aAAU;YACA;AACR,cAAW,MAAM;;;AAIrB,QACE,qBAAC;EACC,WAAU;EACV,WAAU,MAAK,2BAA2B,aAAa,SAAS,CAAC,EAAE,CAAC;EACpE;;GAEA,oBAAC;IAAM,SAAQ;IAAQ,WAAU;cAAQ,EAAE,aAAa;KAAS;GACjE,oBAAC;IACC,IAAG;IACH,MAAK;IACL,cAAa;IACb,GAAI,SAAS,QAAQ;IACrB,gBAAgB,YAAY,QAAQ;KACpC;GACF,oBAAC,mBAAgB,MAAM,OAAO,OAAO,SAAS,UAAU,GAAI;GAE5D,oBAAC;IAAO,MAAK;IAAS,WAAU;IAAgB;cAC7C,EAAE,aAAa;KACT;;GACJ;;AAKX,SAAgB,eAAe,OAA+B;CAC5D,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,cAAc,aAAa;CACjC,MAAM,OAAO,SAAS;CACtB,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;AAEvC,KAAI,KACF,QAAO,oBAAC;EAAsB,MAAK;EAAW,UAAU,CAAC,CAAC,MAAM;GAAY;AAG9E,KAAI,KACF,QAAO,oBAAC;EAAsB,MAAK;EAAY,UAAU,CAAC,CAAC,MAAM;GAAY;AAG/E,QACE,oBAAC;EAAc,UAAU,CAAC,CAAC,MAAM;YAC/B,qBAAC;GAAI,WAAW,GACd,gDACA,MAAM,WAAW,QAAQ,MAC1B;cACC,qBAAC;IAAI,WAAU;eACb,oBAAC;KAAW,MAAK;eAAM,EAAE,sBAAsB;MAAc,EAC7D,qBAAC;KACE,EAAE,uBAAuB;KAAE;KAC5B,oBAAC;MAAW,MAAM,YAAY,KAAK;gBAChC,EAAE,UAAU;OACF;QACF;KACT,EACN,oBAAC;IAAI,WAAU;cACb,oBAAC,sBAAmB,cAAc,QAAQ,KAAK,GAAI;KAC/C;IACF;GACQ"}
1
+ {"version":3,"file":"forgot-password.js","names":[],"sources":["../../../src/components-page/forgot-password.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { strictEmailSchema, yupObject } from \"@hexclave/shared/dist/schema-fields\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { Button, Input, Label, Typography, cn } from \"@hexclave/ui\";\nimport { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp, useUser } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { StyledLink } from \"../components/link\";\nimport { PredefinedMessageCard } from \"../components/message-cards/predefined-message-card\";\nimport { useTranslation } from \"../lib/translations\";\n\nexport function ForgotPasswordForm({ onSent }: { onSent?: () => void }) {\n const { t } = useTranslation();\n\n const schema = yupObject({\n email: strictEmailSchema(t(\"Please enter a valid email\")).defined().nonEmpty(t(\"Please enter your email\"))\n });\n\n const { register, handleSubmit, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const hexclaveApp = useStackApp();\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { email } = data;\n await hexclaveApp.sendForgotPasswordEmail(email);\n onSent?.();\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <form\n className=\"flex flex-col items-stretch stack-scope\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"email\" className=\"mb-1\">{t(\"Your Email\")}</Label>\n <Input\n id=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n {...register('email', { onChange: () => clearErrors('email') })}\n />\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n {t(\"Send Email\")}\n </Button>\n </form>\n );\n}\n\n\nexport function ForgotPassword(props: { fullPage?: boolean }) {\n const { t } = useTranslation();\n const hexclaveApp = useStackApp();\n const user = useUser();\n const [sent, setSent] = useState(false);\n\n if (user) {\n return <PredefinedMessageCard type='signedIn' fullPage={!!props.fullPage} />;\n }\n\n if (sent) {\n return <PredefinedMessageCard type='emailSent' fullPage={!!props.fullPage} />;\n }\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div className={cn(\n \"stack-scope max-w-[380px] flex-basis-[380px]\",\n props.fullPage ? \"p-4\" : \"p-0\"\n )}>\n <div className=\"text-center\">\n <Typography type='h2'>{t(\"Reset Your Password\")}</Typography>\n <Typography>\n {t(\"Don't need to reset?\")}{\" \"}\n <StyledLink href={hexclaveApp.urls['signIn']}>\n {t(\"Sign in\")}\n </StyledLink>\n </Typography>\n </div>\n <div className=\"mt-6\">\n <ForgotPasswordForm onSent={() => setSent(true)} />\n </div>\n </div>\n </MaybeFullPage>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,SAAgB,mBAAmB,EAAE,UAAmC;CACtE,MAAM,EAAE,MAAM,gBAAgB;CAM9B,MAAM,EAAE,UAAU,cAAc,WAAW,EAAE,UAAU,gBAAgB,QAAQ,EAC7E,UAAU,YALG,UAAU,EACvB,OAAO,kBAAkB,EAAE,6BAA6B,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,0BAA0B,CAAC,EAC3G,CAAC,CAG6B,EAC9B,CAAC;CACF,MAAM,cAAc,aAAa;CACjC,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAE7C,MAAM,WAAW,OAAO,SAAuC;AAC7D,aAAW,KAAK;AAChB,MAAI;GACF,MAAM,EAAE,UAAU;AAClB,SAAM,YAAY,wBAAwB,MAAM;AAClD,aAAU;YACA;AACR,cAAW,MAAM;;;AAIrB,QACE,qBAAC;EACC,WAAU;EACV,WAAU,MAAK,2BAA2B,aAAa,SAAS,CAAC,EAAE,CAAC;EACpE;;GAEA,oBAAC;IAAM,SAAQ;IAAQ,WAAU;cAAQ,EAAE,aAAa;KAAS;GACjE,oBAAC;IACC,IAAG;IACH,MAAK;IACL,cAAa;IACb,GAAI,SAAS,SAAS,EAAE,gBAAgB,YAAY,QAAQ,EAAE,CAAC;KAC/D;GACF,oBAAC,mBAAgB,MAAM,OAAO,OAAO,SAAS,UAAU,GAAI;GAE5D,oBAAC;IAAO,MAAK;IAAS,WAAU;IAAgB;cAC7C,EAAE,aAAa;KACT;;GACJ;;AAKX,SAAgB,eAAe,OAA+B;CAC5D,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,cAAc,aAAa;CACjC,MAAM,OAAO,SAAS;CACtB,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;AAEvC,KAAI,KACF,QAAO,oBAAC;EAAsB,MAAK;EAAW,UAAU,CAAC,CAAC,MAAM;GAAY;AAG9E,KAAI,KACF,QAAO,oBAAC;EAAsB,MAAK;EAAY,UAAU,CAAC,CAAC,MAAM;GAAY;AAG/E,QACE,oBAAC;EAAc,UAAU,CAAC,CAAC,MAAM;YAC/B,qBAAC;GAAI,WAAW,GACd,gDACA,MAAM,WAAW,QAAQ,MAC1B;cACC,qBAAC;IAAI,WAAU;eACb,oBAAC;KAAW,MAAK;eAAM,EAAE,sBAAsB;MAAc,EAC7D,qBAAC;KACE,EAAE,uBAAuB;KAAE;KAC5B,oBAAC;MAAW,MAAM,YAAY,KAAK;gBAChC,EAAE,UAAU;OACF;QACF;KACT,EACN,oBAAC;IAAI,WAAU;cACb,oBAAC,sBAAmB,cAAc,QAAQ,KAAK,GAAI;KAC/C;IACF;GACQ"}
@@ -1,6 +1,6 @@
1
1
  import { KnownError } from "@hexclave/shared";
2
- import { SignIn, SignUp } from "..";
3
2
  import { HandlerUrls, StackClientApp } from "../lib/hexclave-app";
3
+ import { SignIn, SignUp } from "..";
4
4
  import { AccountSettings } from "./account-settings";
5
5
  import { CliAuthConfirmation } from "./cli-auth-confirm";
6
6
  import { EmailVerification } from "./email-verification";
@@ -1,16 +1,16 @@
1
1
  "use client";
2
2
 
3
+ import { HexclaveAssertionError, captureError } from "@hexclave/shared/dist/utils/errors";
3
4
  import { Suspense, useMemo, useSyncExternalStore } from "react";
4
5
  import { SignIn, SignUp } from "../index.js";
5
6
  import { jsx } from "react/jsx-runtime";
7
+ import { useStackApp as useStackApp$1 } from "../lib/hooks.js";
6
8
  import { KnownError } from "@hexclave/shared";
7
- import { HexclaveAssertionError, captureError } from "@hexclave/shared/dist/utils/errors";
8
9
  import { use } from "@hexclave/shared/dist/utils/react";
9
10
  import { KnownErrorMessageCard } from "../components/message-cards/known-error-message-card.js";
10
11
  import { MessageCard as MessageCard$1 } from "../components/message-cards/message-card.js";
11
12
  import { PredefinedMessageCard } from "../components/message-cards/predefined-message-card.js";
12
13
  import { CliAuthConfirmation } from "./cli-auth-confirm.js";
13
- import { useStackApp as useStackApp$1 } from "../lib/hooks.js";
14
14
  import { hexclaveAppInternalsSymbol } from "../lib/hexclave-app/index.js";
15
15
  import { filterUndefined } from "@hexclave/shared/dist/utils/objects";
16
16
  import { getRelativePart } from "@hexclave/shared/dist/utils/urls";
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
+ import { throwErr } from "@hexclave/shared/dist/utils/errors";
3
4
  import React from "react";
4
5
  import { useStackApp, useUser } from "../index.js";
5
6
  import { useTranslation } from "../lib/translations.js";
6
7
  import { jsx } from "react/jsx-runtime";
7
8
  import { KnownErrors } from "@hexclave/shared";
8
- import { throwErr } from "@hexclave/shared/dist/utils/errors";
9
9
  import { MessageCard as MessageCard$1 } from "../components/message-cards/message-card.js";
10
10
  import { PredefinedMessageCard } from "../components/message-cards/predefined-message-card.js";
11
11
  import { cacheFunction } from "@hexclave/shared/dist/utils/caches";
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
 
3
3
  import { Button, InputOTP, InputOTPGroup, InputOTPSlot, Spinner, Typography, cn } from "@hexclave/ui";
4
- import { CheckIcon } from "lucide-react";
5
4
  import { useEffect, useMemo, useRef, useState } from "react";
6
5
  import { useStackApp } from "../index.js";
7
- import { MaybeFullPage } from "../components/elements/maybe-full-page.js";
6
+ import { FormWarningText } from "../components/elements/form-warning.js";
8
7
  import { useTranslation } from "../lib/translations.js";
9
8
  import { jsx, jsxs } from "react/jsx-runtime";
10
9
  import { KnownErrors } from "@hexclave/shared";
11
- import { FormWarningText } from "../components/elements/form-warning.js";
10
+ import { CheckIcon } from "lucide-react";
11
+ import { MaybeFullPage } from "../components/elements/maybe-full-page.js";
12
12
 
13
13
  //#region src/components-page/mfa.tsx
14
14
  function MfaForm({ onSuccess, onCancel }) {
@@ -126,22 +126,17 @@ function MFA(props) {
126
126
  const { t } = useTranslation();
127
127
  const headerText = t("Multi-Factor Authentication");
128
128
  const instructionText = t("Enter the six-digit code from your authenticator app");
129
- if (props.fullPage) return /* @__PURE__ */ jsx(MaybeFullPage, {
130
- fullPage: true,
129
+ return /* @__PURE__ */ jsx(MaybeFullPage, {
130
+ fullPage: !!props.fullPage,
131
131
  children: /* @__PURE__ */ jsxs("div", {
132
- className: "stack-scope flex flex-col items-stretch",
133
- style: {
134
- maxWidth: "380px",
135
- flexBasis: "380px",
136
- padding: "1rem"
137
- },
132
+ className: cn("stack-scope max-w-[380px] flex-basis-[380px]", props.fullPage ? "p-4" : "p-0"),
138
133
  children: [/* @__PURE__ */ jsxs("div", {
139
134
  className: "text-center mb-6",
140
135
  children: [/* @__PURE__ */ jsx(Typography, {
141
136
  type: "h2",
142
137
  children: headerText
143
138
  }), /* @__PURE__ */ jsx(Typography, {
144
- className: "mt-2",
139
+ className: "mt-2 text-sm text-muted-foreground",
145
140
  children: instructionText
146
141
  })]
147
142
  }), /* @__PURE__ */ jsx(MfaForm, {
@@ -150,16 +145,6 @@ function MFA(props) {
150
145
  })]
151
146
  })
152
147
  });
153
- return /* @__PURE__ */ jsxs("div", {
154
- className: "flex flex-col items-stretch stack-scope",
155
- children: [/* @__PURE__ */ jsx(Typography, {
156
- className: "mb-4 text-center",
157
- children: instructionText
158
- }), /* @__PURE__ */ jsx(MfaForm, {
159
- onSuccess: props.onSuccess,
160
- onCancel: props.onCancel
161
- })]
162
- });
163
148
  }
164
149
 
165
150
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"mfa.js","names":[],"sources":["../../../src/components-page/mfa.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { KnownErrors } from \"@hexclave/shared\";\nimport {\n Button,\n InputOTP,\n InputOTPGroup,\n InputOTPSlot,\n Spinner,\n Typography,\n cn,\n} from \"@hexclave/ui\";\nimport { CheckIcon } from \"lucide-react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useStackApp } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { useTranslation } from \"../lib/translations\";\n\nfunction MfaForm({ onSuccess, onCancel }: {\n onSuccess?: () => void,\n onCancel?: () => void,\n}) {\n const hexclaveApp = useStackApp();\n const { t } = useTranslation();\n const [otp, setOtp] = useState<string>(\"\");\n const formRef = useRef<HTMLFormElement>(null);\n\n const [submitting, setSubmitting] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const [verified, setVerified] = useState<boolean>(false);\n\n const [attemptCode, setAttemptCode] = useState<string | null>(null);\n\n useEffect(() => {\n if (!attemptCode && typeof window !== \"undefined\") {\n // Hexclave rebrand: prefer the new MFA attempt code key, fall back to the legacy key.\n const code = window.sessionStorage.getItem(\"hexclave_mfa_attempt_code\") ?? window.sessionStorage.getItem(\"stack_mfa_attempt_code\");\n if (code) {\n setAttemptCode(code);\n }\n }\n }, [ attemptCode]);\n\n // Handle OTP verification when code is complete\n useEffect(() => {\n if (otp.length === 6 && !submitting) {\n // Blur any focused inputs\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n if (formRef.current) {\n const inputs = formRef.current.querySelectorAll('input');\n for (const input of inputs) {\n input.blur();\n }\n }\n\n setSubmitting(true);\n setError(null);\n\n if (attemptCode) {\n hexclaveApp\n .signInWithMfa(otp, attemptCode, { noRedirect: true })\n .then(async (result) => {\n if (result.status === \"ok\") {\n setVerified(true);\n\n // Cleanup session storage\n if (typeof window !== \"undefined\") {\n // Hexclave rebrand: remove both the new and legacy MFA attempt code keys.\n window.sessionStorage.removeItem(\"hexclave_mfa_attempt_code\");\n window.sessionStorage.removeItem(\"stack_mfa_attempt_code\");\n }\n\n if (onSuccess) {\n onSuccess();\n } else {\n await hexclaveApp.redirectToAfterSignIn();\n }\n } else {\n throw result.error;\n }\n })\n .catch((e) => {\n if (e instanceof KnownErrors.InvalidTotpCode) {\n setError(t(\"Invalid TOTP code\"));\n } else {\n setError(t(\"Verification failed\"));\n }\n })\n .finally(() => {\n setSubmitting(false);\n if (!verified) {\n setOtp(\"\");\n }\n });\n } else {\n setSubmitting(false);\n setError(t(\"Missing verification information\"));\n }\n }\n\n // Clear error when user is typing\n if (otp.length !== 0 && otp.length !== 6) {\n setError(null);\n }\n }, [otp, submitting, onSuccess, attemptCode, hexclaveApp, t, verified]);\n\n\n const inputStyleClass = useMemo(() => {\n if (verified) {\n return \"opacity-85 transition-all duration-300\";\n }\n\n if (error) {\n return \"ring-red-500 border-red-500\";\n }\n\n return \"focus:ring-primary/50\";\n }, [error, verified]);\n\n return (\n <div className=\"flex flex-col items-stretch stack-scope\">\n <form ref={formRef} className=\"w-full flex flex-col items-center gap-4\">\n <InputOTP\n maxLength={6}\n type=\"text\"\n inputMode=\"numeric\"\n placeholder=\"······\"\n value={otp}\n onChange={(value) => setOtp(value.toUpperCase())}\n disabled={submitting || verified}\n >\n <InputOTPGroup>\n {[0, 1, 2, 3, 4, 5].map((index) => (\n <InputOTPSlot\n key={index}\n index={index}\n size=\"lg\"\n className={cn(\n \"border focus:ring-2 transition-all\",\n inputStyleClass,\n )}\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n\n {/* Verification Status */}\n <div className=\"h-8 flex flex-col gap-4 items-center justify-center w-full\">\n {verified ? (\n <div className=\"flex items-center gap-2 animate-in fade-in duration-300 slide-in-from-bottom-2\">\n <CheckIcon className=\"w-5 h-5 text-green-600 animate-in zoom-in duration-300\" />\n <Typography className=\"text-sm font-medium\">{t(\"Verified! Redirecting...\")}</Typography>\n </div>\n ) : submitting ? (\n <div className=\"flex items-center gap-2\">\n <Spinner className=\"text-primary h-4 w-4\" />\n <Typography className=\"text-sm\">{t(\"Verifying...\")}</Typography>\n </div>\n ) : null}\n\n {/* Error reporting */}\n {error !== null && !submitting && !verified ? <FormWarningText text={error} /> : null}\n </div>\n </form>\n\n {/* Cancel Button */}\n {onCancel && !verified && (\n <Button\n variant=\"link\"\n onClick={onCancel}\n className=\"underline mt-4 self-center\"\n disabled={submitting || verified}\n >\n {t(\"Cancel\")}\n </Button>\n )}\n </div>\n );\n}\n\nexport function MFA(props: {\n fullPage?: boolean,\n onSuccess?: () => void,\n onCancel?: () => void,\n}) {\n const { t } = useTranslation();\n\n const headerText = t(\"Multi-Factor Authentication\");\n const instructionText = t(\"Enter the six-digit code from your authenticator app\");\n\n if (props.fullPage) {\n return (\n <MaybeFullPage fullPage={true}>\n <div\n className=\"stack-scope flex flex-col items-stretch\"\n style={{ maxWidth: \"380px\", flexBasis: \"380px\", padding: \"1rem\" }}\n >\n <div className=\"text-center mb-6\">\n <Typography type=\"h2\">{headerText}</Typography>\n <Typography className=\"mt-2\">{instructionText}</Typography>\n </div>\n <MfaForm onSuccess={props.onSuccess} onCancel={props.onCancel} />\n </div>\n </MaybeFullPage>\n );\n }\n\n return (\n <div className=\"flex flex-col items-stretch stack-scope\">\n <Typography className=\"mb-4 text-center\">{instructionText}</Typography>\n <MfaForm onSuccess={props.onSuccess} onCancel={props.onCancel} />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mfa.js","names":[],"sources":["../../../src/components-page/mfa.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { KnownErrors } from \"@hexclave/shared\";\nimport {\n Button,\n InputOTP,\n InputOTPGroup,\n InputOTPSlot,\n Spinner,\n Typography,\n cn,\n} from \"@hexclave/ui\";\nimport { CheckIcon } from \"lucide-react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useStackApp } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { useTranslation } from \"../lib/translations\";\n\nfunction MfaForm({ onSuccess, onCancel }: {\n onSuccess?: () => void,\n onCancel?: () => void,\n}) {\n const hexclaveApp = useStackApp();\n const { t } = useTranslation();\n const [otp, setOtp] = useState<string>(\"\");\n const formRef = useRef<HTMLFormElement>(null);\n\n const [submitting, setSubmitting] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const [verified, setVerified] = useState<boolean>(false);\n\n const [attemptCode, setAttemptCode] = useState<string | null>(null);\n\n useEffect(() => {\n if (!attemptCode && typeof window !== \"undefined\") {\n // Hexclave rebrand: prefer the new MFA attempt code key, fall back to the legacy key.\n const code = window.sessionStorage.getItem(\"hexclave_mfa_attempt_code\") ?? window.sessionStorage.getItem(\"stack_mfa_attempt_code\");\n if (code) {\n setAttemptCode(code);\n }\n }\n }, [ attemptCode]);\n\n // Handle OTP verification when code is complete\n useEffect(() => {\n if (otp.length === 6 && !submitting) {\n // Blur any focused inputs\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n if (formRef.current) {\n const inputs = formRef.current.querySelectorAll('input');\n for (const input of inputs) {\n input.blur();\n }\n }\n\n setSubmitting(true);\n setError(null);\n\n if (attemptCode) {\n hexclaveApp\n .signInWithMfa(otp, attemptCode, { noRedirect: true })\n .then(async (result) => {\n if (result.status === \"ok\") {\n setVerified(true);\n\n // Cleanup session storage\n if (typeof window !== \"undefined\") {\n // Hexclave rebrand: remove both the new and legacy MFA attempt code keys.\n window.sessionStorage.removeItem(\"hexclave_mfa_attempt_code\");\n window.sessionStorage.removeItem(\"stack_mfa_attempt_code\");\n }\n\n if (onSuccess) {\n onSuccess();\n } else {\n await hexclaveApp.redirectToAfterSignIn();\n }\n } else {\n throw result.error;\n }\n })\n .catch((e) => {\n if (e instanceof KnownErrors.InvalidTotpCode) {\n setError(t(\"Invalid TOTP code\"));\n } else {\n setError(t(\"Verification failed\"));\n }\n })\n .finally(() => {\n setSubmitting(false);\n if (!verified) {\n setOtp(\"\");\n }\n });\n } else {\n setSubmitting(false);\n setError(t(\"Missing verification information\"));\n }\n }\n\n // Clear error when user is typing\n if (otp.length !== 0 && otp.length !== 6) {\n setError(null);\n }\n }, [otp, submitting, onSuccess, attemptCode, hexclaveApp, t, verified]);\n\n\n const inputStyleClass = useMemo(() => {\n if (verified) {\n return \"opacity-85 transition-all duration-300\";\n }\n\n if (error) {\n return \"ring-red-500 border-red-500\";\n }\n\n return \"focus:ring-primary/50\";\n }, [error, verified]);\n\n return (\n <div className=\"flex flex-col items-stretch stack-scope\">\n <form ref={formRef} className=\"w-full flex flex-col items-center gap-4\">\n <InputOTP\n maxLength={6}\n type=\"text\"\n inputMode=\"numeric\"\n placeholder=\"······\"\n value={otp}\n onChange={(value) => setOtp(value.toUpperCase())}\n disabled={submitting || verified}\n >\n <InputOTPGroup>\n {[0, 1, 2, 3, 4, 5].map((index) => (\n <InputOTPSlot\n key={index}\n index={index}\n size=\"lg\"\n className={cn(\n \"border focus:ring-2 transition-all\",\n inputStyleClass,\n )}\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n\n {/* Verification Status */}\n <div className=\"h-8 flex flex-col gap-4 items-center justify-center w-full\">\n {verified ? (\n <div className=\"flex items-center gap-2 animate-in fade-in duration-300 slide-in-from-bottom-2\">\n <CheckIcon className=\"w-5 h-5 text-green-600 animate-in zoom-in duration-300\" />\n <Typography className=\"text-sm font-medium\">{t(\"Verified! Redirecting...\")}</Typography>\n </div>\n ) : submitting ? (\n <div className=\"flex items-center gap-2\">\n <Spinner className=\"text-primary h-4 w-4\" />\n <Typography className=\"text-sm\">{t(\"Verifying...\")}</Typography>\n </div>\n ) : null}\n\n {/* Error reporting */}\n {error !== null && !submitting && !verified ? <FormWarningText text={error} /> : null}\n </div>\n </form>\n\n {/* Cancel Button */}\n {onCancel && !verified && (\n <Button\n variant=\"link\"\n onClick={onCancel}\n className=\"underline mt-4 self-center\"\n disabled={submitting || verified}\n >\n {t(\"Cancel\")}\n </Button>\n )}\n </div>\n );\n}\n\nexport function MFA(props: {\n fullPage?: boolean,\n onSuccess?: () => void,\n onCancel?: () => void,\n}) {\n const { t } = useTranslation();\n\n const headerText = t(\"Multi-Factor Authentication\");\n const instructionText = t(\"Enter the six-digit code from your authenticator app\");\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div className={cn(\n \"stack-scope max-w-[380px] flex-basis-[380px]\",\n props.fullPage ? \"p-4\" : \"p-0\"\n )}>\n <div className=\"text-center mb-6\">\n <Typography type=\"h2\">{headerText}</Typography>\n <Typography className=\"mt-2 text-sm text-muted-foreground\">{instructionText}</Typography>\n </div>\n <MfaForm onSuccess={props.onSuccess} onCancel={props.onCancel} />\n </div>\n </MaybeFullPage>\n );\n}\n"],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  'use client';
2
2
 
3
3
  import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
4
+ import { captureError } from "@hexclave/shared/dist/utils/errors";
4
5
  import { Spinner, cn } from "@hexclave/ui";
5
6
  import { useEffect, useRef, useState } from "react";
6
7
  import { useStackApp } from "../index.js";
7
- import { MaybeFullPage } from "../components/elements/maybe-full-page.js";
8
8
  import { useTranslation } from "../lib/translations.js";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
10
  import { KnownError } from "@hexclave/shared";
11
- import { captureError } from "@hexclave/shared/dist/utils/errors";
11
+ import { MaybeFullPage } from "../components/elements/maybe-full-page.js";
12
12
  import { StyledLink } from "../components/link.js";
13
13
  import { hexclaveAppInternalsSymbol } from "../lib/hexclave-app/index.js";
14
14
 
@@ -1,16 +1,16 @@
1
1
  'use client';
2
2
 
3
3
  import { runAsynchronously, runAsynchronouslyWithAlert } from "@hexclave/shared/dist/utils/promises";
4
+ import { yupResolver } from "@hookform/resolvers/yup";
5
+ import { strictEmailSchema, yupObject } from "@hexclave/shared/dist/schema-fields";
4
6
  import { Button, Input, Typography } from "@hexclave/ui";
5
7
  import { useState } from "react";
8
+ import { useForm } from "react-hook-form";
6
9
  import { useStackApp, useUser } from "../index.js";
10
+ import { FormWarningText } from "../components/elements/form-warning.js";
7
11
  import { useTranslation } from "../lib/translations.js";
8
12
  import { jsx, jsxs } from "react/jsx-runtime";
9
13
  import { MessageCard as MessageCard$1 } from "../components/message-cards/message-card.js";
10
- import { yupResolver } from "@hookform/resolvers/yup";
11
- import { strictEmailSchema, yupObject } from "@hexclave/shared/dist/schema-fields";
12
- import { useForm } from "react-hook-form";
13
- import { FormWarningText } from "../components/elements/form-warning.js";
14
14
 
15
15
  //#region src/components-page/onboarding.tsx
16
16
  function Onboarding(props) {
@@ -1 +1 @@
1
- {"version":3,"file":"password-reset.d.ts","names":[],"sources":["../../../src/components-page/password-reset.tsx"],"mappings":";;;iBAyBwB,iBAAA,CAAkB,KAAA;EACxC,IAAA;EACA,QAAA;AAAA,IACD,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBA4Ge,aAAA,CAAA;EACd,YAAA;EACA;AAAA;EAEA,YAAA,EAAc,MAAA;EACd,QAAA;AAAA,IACD,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"password-reset.d.ts","names":[],"sources":["../../../src/components-page/password-reset.tsx"],"mappings":";;;iBAyBwB,iBAAA,CAAkB,KAAA;EACxC,IAAA;EACA,QAAA;AAAA,IACD,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBA0Ge,aAAA,CAAA;EACd,YAAA;EACA;AAAA;EAEA,YAAA,EAAc,MAAA;EACd,QAAA;AAAA,IACD,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -1,23 +1,23 @@
1
1
  'use client';
2
2
 
3
3
  import { runAsynchronouslyWithAlert } from "@hexclave/shared/dist/utils/promises";
4
+ import { yupResolver } from "@hookform/resolvers/yup";
5
+ import { passwordSchema, yupObject, yupString } from "@hexclave/shared/dist/schema-fields";
4
6
  import { Button, Label, PasswordInput, Typography, cn } from "@hexclave/ui";
5
7
  import { useState } from "react";
8
+ import { useForm } from "react-hook-form";
6
9
  import { useStackApp } from "../index.js";
7
- import { MaybeFullPage } from "../components/elements/maybe-full-page.js";
10
+ import { FormWarningText } from "../components/elements/form-warning.js";
8
11
  import { useTranslation } from "../lib/translations.js";
9
12
  import { jsx, jsxs } from "react/jsx-runtime";
13
+ import { getPasswordError } from "@hexclave/shared/dist/helpers/password";
14
+ import * as yup from "yup";
10
15
  import { KnownErrors } from "@hexclave/shared";
16
+ import { MaybeFullPage } from "../components/elements/maybe-full-page.js";
11
17
  import { use } from "@hexclave/shared/dist/utils/react";
12
18
  import { MessageCard as MessageCard$1 } from "../components/message-cards/message-card.js";
13
19
  import { PredefinedMessageCard } from "../components/message-cards/predefined-message-card.js";
14
- import { yupResolver } from "@hookform/resolvers/yup";
15
- import { passwordSchema, yupObject, yupString } from "@hexclave/shared/dist/schema-fields";
16
- import { useForm } from "react-hook-form";
17
- import { FormWarningText } from "../components/elements/form-warning.js";
18
20
  import { cacheFunction } from "@hexclave/shared/dist/utils/caches";
19
- import { getPasswordError } from "@hexclave/shared/dist/helpers/password";
20
- import * as yup from "yup";
21
21
 
22
22
  //#region src/components-page/password-reset.tsx
23
23
  function PasswordResetForm(props) {
@@ -85,11 +85,10 @@ function PasswordResetForm(props) {
85
85
  /* @__PURE__ */ jsx(PasswordInput, {
86
86
  id: "password",
87
87
  autoComplete: "new-password",
88
- ...register("password"),
89
- onChange: () => {
88
+ ...register("password", { onChange: () => {
90
89
  clearErrors("password");
91
90
  clearErrors("passwordRepeat");
92
- }
91
+ } })
93
92
  }),
94
93
  /* @__PURE__ */ jsx(FormWarningText, { text: errors.password?.message?.toString() }),
95
94
  /* @__PURE__ */ jsx(Label, {
@@ -100,11 +99,10 @@ function PasswordResetForm(props) {
100
99
  /* @__PURE__ */ jsx(PasswordInput, {
101
100
  id: "repeat-password",
102
101
  autoComplete: "new-password",
103
- ...register("passwordRepeat"),
104
- onChange: () => {
102
+ ...register("passwordRepeat", { onChange: () => {
105
103
  clearErrors("password");
106
104
  clearErrors("passwordRepeat");
107
- }
105
+ } })
108
106
  }),
109
107
  /* @__PURE__ */ jsx(FormWarningText, { text: errors.passwordRepeat?.message?.toString() }),
110
108
  /* @__PURE__ */ jsx(Button, {
@@ -1 +1 @@
1
- {"version":3,"file":"password-reset.js","names":["MessageCard"],"sources":["../../../src/components-page/password-reset.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { KnownErrors } from \"@hexclave/shared\";\nimport { getPasswordError } from \"@hexclave/shared/dist/helpers/password\";\nimport { passwordSchema, yupObject, yupString } from \"@hexclave/shared/dist/schema-fields\";\nimport { cacheFunction } from \"@hexclave/shared/dist/utils/caches\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { use } from \"@hexclave/shared/dist/utils/react\";\nimport { Button, Label, PasswordInput, Typography, cn } from \"@hexclave/ui\";\nimport { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { StackClientApp, useStackApp } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { MessageCard } from \"../components/message-cards/message-card\";\nimport { PredefinedMessageCard } from \"../components/message-cards/predefined-message-card\";\nimport { useTranslation } from \"../lib/translations\";\n\nexport default function PasswordResetForm(props: {\n code: string,\n fullPage?: boolean,\n}) {\n const { t } = useTranslation();\n\n const schema = yupObject({\n password: passwordSchema.defined(t(\"Please enter your password\")).nonEmpty(t(\"Please enter your password\")).test({\n name: 'is-valid-password',\n test: (value, ctx) => {\n const error = getPasswordError(value);\n if (error) {\n return ctx.createError({ message: error.message });\n } else {\n return true;\n }\n }\n }),\n passwordRepeat: yupString().nullable().oneOf([yup.ref('password'), null], t(\"Passwords do not match\")).defined().nonEmpty(t(\"Please repeat your password\"))\n });\n\n const { register, handleSubmit, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const hexclaveApp = useStackApp();\n const [finished, setFinished] = useState(false);\n const [resetError, setResetError] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { password } = data;\n const result = await hexclaveApp.resetPassword({ password, code: props.code });\n if (result.status === 'error') {\n setResetError(true);\n return;\n }\n\n setFinished(true);\n } finally {\n setLoading(false);\n }\n };\n\n if (finished) {\n return <PredefinedMessageCard type='passwordReset' fullPage={!!props.fullPage} />;\n }\n\n if (resetError) {\n return (\n <MessageCard title={t(\"Failed to reset password\")} fullPage={!!props.fullPage}>\n {t(\"Failed to reset password. Please request a new password reset link\")}\n </MessageCard>\n );\n }\n\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div className={cn(\n \"flex flex-col items-stretch max-w-[380px] flex-basis-[380px]\",\n props.fullPage ? \"p-4\" : \"p-0\"\n )}>\n <div className=\"text-center mb-6\">\n <Typography type='h2'>{t(\"Reset Your Password\")}</Typography>\n </div>\n\n <form\n className=\"flex flex-col items-stretch\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"password\" className=\"mb-1\">{t(\"New Password\")}</Label>\n <PasswordInput\n id=\"password\"\n autoComplete=\"new-password\"\n {...register('password')}\n onChange={() => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n }}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">{t(\"Repeat New Password\")}</Label>\n <PasswordInput\n id=\"repeat-password\"\n autoComplete=\"new-password\"\n {...register('passwordRepeat')}\n onChange={() => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n }}\n />\n <FormWarningText text={errors.passwordRepeat?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n {t(\"Reset Password\")}\n </Button>\n </form>\n </div>\n </MaybeFullPage>\n );\n}\n\n\nconst cachedVerifyPasswordResetCode = cacheFunction(async (hexclaveApp: StackClientApp<true>, code: string) => {\n return await hexclaveApp.verifyPasswordResetCode(code);\n});\n\nexport function PasswordReset({\n searchParams,\n fullPage = false,\n}: {\n searchParams: Record<string, string>,\n fullPage?: boolean,\n}) {\n const { t } = useTranslation();\n const hexclaveApp = useStackApp();\n\n const invalidJsx = (\n <MessageCard title={t(\"Invalid Password Reset Link\")} fullPage={fullPage}>\n <Typography>{t(\"Please double check if you have the correct password reset link.\")}</Typography>\n </MessageCard>\n );\n\n const expiredJsx = (\n <MessageCard title={t(\"Expired Password Reset Link\")} fullPage={fullPage}>\n <Typography>{t(\"Your password reset link has expired. Please request a new password reset link from the login page.\")}</Typography>\n </MessageCard>\n );\n\n const usedJsx = (\n <MessageCard title={t(\"Used Password Reset Link\")} fullPage={fullPage}>\n <Typography>{t(\"This password reset link has already been used. If you need to reset your password again, please request a new password reset link from the login page.\")}</Typography>\n </MessageCard>\n );\n\n const code = searchParams.code;\n if (!code) {\n return invalidJsx;\n }\n\n const result = use(cachedVerifyPasswordResetCode(hexclaveApp, code));\n\n if (result.status === 'error') {\n if (KnownErrors.VerificationCodeNotFound.isInstance(result.error)) {\n return invalidJsx;\n } else if (KnownErrors.VerificationCodeExpired.isInstance(result.error)) {\n return expiredJsx;\n } else if (KnownErrors.VerificationCodeAlreadyUsed.isInstance(result.error)) {\n return usedJsx;\n } else {\n throw result.error;\n }\n }\n\n return <PasswordResetForm code={code} fullPage={fullPage} />;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"password-reset.js","names":["MessageCard"],"sources":["../../../src/components-page/password-reset.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { KnownErrors } from \"@hexclave/shared\";\nimport { getPasswordError } from \"@hexclave/shared/dist/helpers/password\";\nimport { passwordSchema, yupObject, yupString } from \"@hexclave/shared/dist/schema-fields\";\nimport { cacheFunction } from \"@hexclave/shared/dist/utils/caches\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { use } from \"@hexclave/shared/dist/utils/react\";\nimport { Button, Label, PasswordInput, Typography, cn } from \"@hexclave/ui\";\nimport { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { StackClientApp, useStackApp } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { MessageCard } from \"../components/message-cards/message-card\";\nimport { PredefinedMessageCard } from \"../components/message-cards/predefined-message-card\";\nimport { useTranslation } from \"../lib/translations\";\n\nexport default function PasswordResetForm(props: {\n code: string,\n fullPage?: boolean,\n}) {\n const { t } = useTranslation();\n\n const schema = yupObject({\n password: passwordSchema.defined(t(\"Please enter your password\")).nonEmpty(t(\"Please enter your password\")).test({\n name: 'is-valid-password',\n test: (value, ctx) => {\n const error = getPasswordError(value);\n if (error) {\n return ctx.createError({ message: error.message });\n } else {\n return true;\n }\n }\n }),\n passwordRepeat: yupString().nullable().oneOf([yup.ref('password'), null], t(\"Passwords do not match\")).defined().nonEmpty(t(\"Please repeat your password\"))\n });\n\n const { register, handleSubmit, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const hexclaveApp = useStackApp();\n const [finished, setFinished] = useState(false);\n const [resetError, setResetError] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { password } = data;\n const result = await hexclaveApp.resetPassword({ password, code: props.code });\n if (result.status === 'error') {\n setResetError(true);\n return;\n }\n\n setFinished(true);\n } finally {\n setLoading(false);\n }\n };\n\n if (finished) {\n return <PredefinedMessageCard type='passwordReset' fullPage={!!props.fullPage} />;\n }\n\n if (resetError) {\n return (\n <MessageCard title={t(\"Failed to reset password\")} fullPage={!!props.fullPage}>\n {t(\"Failed to reset password. Please request a new password reset link\")}\n </MessageCard>\n );\n }\n\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div className={cn(\n \"flex flex-col items-stretch max-w-[380px] flex-basis-[380px]\",\n props.fullPage ? \"p-4\" : \"p-0\"\n )}>\n <div className=\"text-center mb-6\">\n <Typography type='h2'>{t(\"Reset Your Password\")}</Typography>\n </div>\n\n <form\n className=\"flex flex-col items-stretch\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"password\" className=\"mb-1\">{t(\"New Password\")}</Label>\n <PasswordInput\n id=\"password\"\n autoComplete=\"new-password\"\n {...register('password', { onChange: () => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n } })}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">{t(\"Repeat New Password\")}</Label>\n <PasswordInput\n id=\"repeat-password\"\n autoComplete=\"new-password\"\n {...register('passwordRepeat', { onChange: () => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n } })}\n />\n <FormWarningText text={errors.passwordRepeat?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n {t(\"Reset Password\")}\n </Button>\n </form>\n </div>\n </MaybeFullPage>\n );\n}\n\n\nconst cachedVerifyPasswordResetCode = cacheFunction(async (hexclaveApp: StackClientApp<true>, code: string) => {\n return await hexclaveApp.verifyPasswordResetCode(code);\n});\n\nexport function PasswordReset({\n searchParams,\n fullPage = false,\n}: {\n searchParams: Record<string, string>,\n fullPage?: boolean,\n}) {\n const { t } = useTranslation();\n const hexclaveApp = useStackApp();\n\n const invalidJsx = (\n <MessageCard title={t(\"Invalid Password Reset Link\")} fullPage={fullPage}>\n <Typography>{t(\"Please double check if you have the correct password reset link.\")}</Typography>\n </MessageCard>\n );\n\n const expiredJsx = (\n <MessageCard title={t(\"Expired Password Reset Link\")} fullPage={fullPage}>\n <Typography>{t(\"Your password reset link has expired. Please request a new password reset link from the login page.\")}</Typography>\n </MessageCard>\n );\n\n const usedJsx = (\n <MessageCard title={t(\"Used Password Reset Link\")} fullPage={fullPage}>\n <Typography>{t(\"This password reset link has already been used. If you need to reset your password again, please request a new password reset link from the login page.\")}</Typography>\n </MessageCard>\n );\n\n const code = searchParams.code;\n if (!code) {\n return invalidJsx;\n }\n\n const result = use(cachedVerifyPasswordResetCode(hexclaveApp, code));\n\n if (result.status === 'error') {\n if (KnownErrors.VerificationCodeNotFound.isInstance(result.error)) {\n return invalidJsx;\n } else if (KnownErrors.VerificationCodeExpired.isInstance(result.error)) {\n return expiredJsx;\n } else if (KnownErrors.VerificationCodeAlreadyUsed.isInstance(result.error)) {\n return usedJsx;\n } else {\n throw result.error;\n }\n }\n\n return <PasswordResetForm code={code} fullPage={fullPage} />;\n}\n"],"mappings":"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"}
@@ -1,16 +1,16 @@
1
1
  'use client';
2
2
 
3
3
  import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
4
+ import { yupResolver } from "@hookform/resolvers/yup";
5
+ import { yupObject, yupString } from "@hexclave/shared/dist/schema-fields";
4
6
  import { Button, Input, Label, Typography } from "@hexclave/ui";
5
7
  import { useState } from "react";
8
+ import { useForm } from "react-hook-form";
6
9
  import { MessageCard, useStackApp, useUser } from "../index.js";
7
- import { MaybeFullPage } from "../components/elements/maybe-full-page.js";
10
+ import { FormWarningText } from "../components/elements/form-warning.js";
8
11
  import { useTranslation } from "../lib/translations.js";
9
12
  import { jsx, jsxs } from "react/jsx-runtime";
10
- import { yupResolver } from "@hookform/resolvers/yup";
11
- import { yupObject, yupString } from "@hexclave/shared/dist/schema-fields";
12
- import { useForm } from "react-hook-form";
13
- import { FormWarningText } from "../components/elements/form-warning.js";
13
+ import { MaybeFullPage } from "../components/elements/maybe-full-page.js";
14
14
 
15
15
  //#region src/components-page/team-creation.tsx
16
16
  function TeamCreation(props) {
@@ -1 +1 @@
1
- {"version":3,"file":"dev-tool-core.d.ts","names":[],"sources":["../../../src/dev-tool/dev-tool-core.ts"],"mappings":";;;iBA6yEgB,aAAA,CAAc,GAAA,EAAK,cAAA"}
1
+ {"version":3,"file":"dev-tool-core.d.ts","names":[],"sources":["../../../src/dev-tool/dev-tool-core.ts"],"mappings":";;;iBAkxEgB,aAAA,CAAc,GAAA,EAAK,cAAA"}
@@ -1,4 +1,6 @@
1
+ import { DEV_TOOL_ROOT_ID } from "@hexclave/shared/dist/utils/dev-tool";
1
2
  import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
3
+ import { getGlobalUiInstance, h, hasAppendChild, setGlobalUiInstance, setHtml } from "../in-page-ui/dom.js";
2
4
  import { hexclaveAppInternalsSymbol } from "../lib/hexclave-app/common.js";
3
5
  import { isLocalhost } from "@hexclave/shared/dist/utils/urls";
4
6
  import { getPagePrompt } from "../lib/hexclave-app/url-targets.js";
@@ -10,7 +12,7 @@ import { clampTriggerPosition, getSnappedTriggerPlacement, resolveTriggerPositio
10
12
  //#region src/dev-tool/dev-tool-core.ts
11
13
  const STORAGE_KEY = "__hexclave-dev-tool-state";
12
14
  const TRIGGER_POS_KEY = "hexclave-devtool-trigger-position";
13
- const ROOT_ID = "__hexclave-dev-tool-root";
15
+ const ROOT_ID = DEV_TOOL_ROOT_ID;
14
16
  const GLOBAL_INSTANCE_KEY = "__hexclave-dev-tool-instance";
15
17
  const MAX_LOG_ENTRIES = 500;
16
18
  const CONSOLE_LOG_BATCH_SIZE = 100;
@@ -100,19 +102,6 @@ function createStateStore() {
100
102
  }
101
103
  };
102
104
  }
103
- function isDevToolGlobalInstance(value) {
104
- return typeof value === "object" && value !== null && typeof Reflect.get(value, "cleanup") === "function";
105
- }
106
- function getGlobalDevToolInstance() {
107
- if (typeof window === "undefined") return null;
108
- const value = Reflect.get(window, GLOBAL_INSTANCE_KEY);
109
- return isDevToolGlobalInstance(value) ? value : null;
110
- }
111
- function setGlobalDevToolInstance(instance) {
112
- if (typeof window === "undefined") return;
113
- if (instance === null) Reflect.deleteProperty(window, GLOBAL_INSTANCE_KEY);
114
- else Reflect.set(window, GLOBAL_INSTANCE_KEY, instance);
115
- }
116
105
  function getGlobalLogStore() {
117
106
  const g = globalThis;
118
107
  if (!g.__STACK_DEV_TOOL_LOG_STORE__) g.__STACK_DEV_TOOL_LOG_STORE__ = {
@@ -192,27 +181,6 @@ function generateRandomEmail() {
192
181
  for (let i = 0; i < 8; i++) id += chars[Math.floor(Math.random() * 36)];
193
182
  return `dev-${id}@test.hexclave.com`;
194
183
  }
195
- function h(tag, attrs, ...children) {
196
- const el = document.createElement(tag);
197
- if (attrs) for (const [k, v] of Object.entries(attrs)) {
198
- if (v == null) continue;
199
- if (k === "className") el.className = v;
200
- else if (k === "style" && typeof v === "object") Object.assign(el.style, v);
201
- else if (k.startsWith("on") && typeof v === "function") el.addEventListener(k.slice(2).toLowerCase(), v);
202
- else el.setAttribute(k, String(v));
203
- }
204
- for (const child of children) {
205
- if (child == null) continue;
206
- el.appendChild(typeof child === "string" ? document.createTextNode(child) : child);
207
- }
208
- return el;
209
- }
210
- function setHtml(el, html) {
211
- el.innerHTML = html;
212
- }
213
- function hasAppendChild(value) {
214
- return typeof value === "object" && value !== null && typeof Reflect.get(value, "appendChild") === "function";
215
- }
216
184
  function appendInlineMarkdown(container, text) {
217
185
  const tokenPattern = /(\[[^\]]+\]\([^)]+\)|`[^`\n]+`|\*\*[^*\n]+\*\*|__[^_\n]+__|\*[^*\n]+\*|_[^_\n]+_)/g;
218
186
  let lastIndex = 0;
@@ -509,8 +477,12 @@ function createIframeTab(src, title, loadingMsg = "Loading…", errorMsg = "Unab
509
477
  container.appendChild(iframe);
510
478
  return container;
511
479
  }
480
+ function hasPersistentTokenStoreForDevTool(app) {
481
+ return app[hexclaveAppInternalsSymbol].getConstructorOptions().tokenStore !== null;
482
+ }
512
483
  function createOverviewTab(app) {
513
484
  const container = h("div", { className: "sdt-ov" });
485
+ const hasPersistentTokenStore = hasPersistentTokenStoreForDevTool(app);
514
486
  const heroCard = h("div", { className: "sdt-ov-card sdt-ov-card-hero" });
515
487
  heroCard.appendChild(h("div", { className: "sdt-ov-label" }, "Identity"));
516
488
  const userRow = h("div", { className: "sdt-ov-user-row" });
@@ -556,6 +528,15 @@ function createOverviewTab(app) {
556
528
  let loading = false;
557
529
  function rebuildActions() {
558
530
  actions.innerHTML = "";
531
+ if (!hasPersistentTokenStore) {
532
+ userName.textContent = "Current user unavailable";
533
+ userEmail.textContent = "This app was initialized without a token store";
534
+ actions.appendChild(h("button", {
535
+ className: "sdt-ov-btn sdt-ov-btn-wide",
536
+ disabled: "true"
537
+ }, "Session actions unavailable"));
538
+ return;
539
+ }
559
540
  if (currentUser) {
560
541
  const signOutBtn = h("button", { className: "sdt-ov-btn sdt-ov-btn-danger" }, "Sign Out");
561
542
  signOutBtn.disabled = loading;
@@ -744,10 +725,14 @@ function createOverviewTab(app) {
744
725
  label: "Auth method active",
745
726
  hint: hasActiveAuthMethod === null ? "Still checking project config" : null
746
727
  },
747
- {
728
+ hasPersistentTokenStore ? {
748
729
  ok: !!currentUser,
749
730
  label: "Sign in a test user",
750
731
  hint: "Use “Quick Sign In” above →"
732
+ } : {
733
+ ok: true,
734
+ label: "Current-user tools unavailable",
735
+ hint: null
751
736
  }
752
737
  ];
753
738
  const passCount = checks.filter((c) => c.ok).length;
@@ -787,6 +772,17 @@ function createOverviewTab(app) {
787
772
  }
788
773
  }
789
774
  async function refreshUser() {
775
+ if (!hasPersistentTokenStore) {
776
+ avatar.className = "sdt-ov-avatar";
777
+ avatar.textContent = "?";
778
+ userName.textContent = "Current user unavailable";
779
+ userEmail.textContent = "This app was initialized without a token store";
780
+ authIndicator.style.display = "none";
781
+ currentUser = null;
782
+ rebuildActions();
783
+ buildChecklist();
784
+ return;
785
+ }
790
786
  try {
791
787
  currentUser = await app.getUser();
792
788
  if (currentUser) {
@@ -2023,7 +2019,7 @@ function createDevTool(app) {
2023
2019
  if (typeof document === "undefined" || typeof document.createElement !== "function") return () => {};
2024
2020
  const body = Reflect.get(document, "body");
2025
2021
  if (!hasAppendChild(body)) return () => {};
2026
- getGlobalDevToolInstance()?.cleanup();
2022
+ getGlobalUiInstance(GLOBAL_INSTANCE_KEY)?.cleanup();
2027
2023
  let existingRoot = document.getElementById(ROOT_ID);
2028
2024
  while (existingRoot !== null) {
2029
2025
  existingRoot.remove();
@@ -2097,13 +2093,13 @@ function createDevTool(app) {
2097
2093
  const instance = { cleanup: () => {
2098
2094
  if (didCleanup) return;
2099
2095
  didCleanup = true;
2100
- if (getGlobalDevToolInstance() === instance) setGlobalDevToolInstance(null);
2096
+ if (getGlobalUiInstance(GLOBAL_INSTANCE_KEY) === instance) setGlobalUiInstance(GLOBAL_INSTANCE_KEY, null);
2101
2097
  trigger.cleanup();
2102
2098
  removeRequestListener();
2103
2099
  panel?.cleanup();
2104
2100
  if (root.parentNode) root.parentNode.removeChild(root);
2105
2101
  } };
2106
- setGlobalDevToolInstance(instance);
2102
+ setGlobalUiInstance(GLOBAL_INSTANCE_KEY, instance);
2107
2103
  return () => {
2108
2104
  instance.cleanup();
2109
2105
  };