@stackframe/stack 2.8.58 → 2.8.59

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 (233) hide show
  1. package/dist/components/api-key-dialogs.js.map +1 -1
  2. package/dist/components/api-key-table.js.map +1 -1
  3. package/dist/components/credential-sign-in.js.map +1 -1
  4. package/dist/components/credential-sign-up.js.map +1 -1
  5. package/dist/components/elements/form-warning.js.map +1 -1
  6. package/dist/components/elements/maybe-full-page.js.map +1 -1
  7. package/dist/components/elements/separator-with-text.js.map +1 -1
  8. package/dist/components/elements/sidebar-layout.js.map +1 -1
  9. package/dist/components/elements/ssr-layout-effect.js.map +1 -1
  10. package/dist/components/elements/user-avatar.js.map +1 -1
  11. package/dist/components/link.js.map +1 -1
  12. package/dist/components/magic-link-sign-in.js.map +1 -1
  13. package/dist/components/message-cards/known-error-message-card.js.map +1 -1
  14. package/dist/components/message-cards/message-card.js.map +1 -1
  15. package/dist/components/message-cards/predefined-message-card.js.map +1 -1
  16. package/dist/components/oauth-button-group.js.map +1 -1
  17. package/dist/components/oauth-button.js.map +1 -1
  18. package/dist/components/passkey-button.js.map +1 -1
  19. package/dist/components/profile-image-editor.js.map +1 -1
  20. package/dist/components/selected-team-switcher.js.map +1 -1
  21. package/dist/components/team-icon.js.map +1 -1
  22. package/dist/components/team-switcher.js.map +1 -1
  23. package/dist/components/use-in-iframe.js.map +1 -1
  24. package/dist/components/user-button.js.map +1 -1
  25. package/dist/components-page/account-settings/active-sessions/active-sessions-page.js.map +1 -1
  26. package/dist/components-page/account-settings/api-keys/api-keys-page.js.map +1 -1
  27. package/dist/components-page/account-settings/editable-text.js.map +1 -1
  28. package/dist/components-page/account-settings/email-and-auth/email-and-auth-page.js.map +1 -1
  29. package/dist/components-page/account-settings/email-and-auth/emails-section.js.map +1 -1
  30. package/dist/components-page/account-settings/email-and-auth/mfa-section.js.map +1 -1
  31. package/dist/components-page/account-settings/email-and-auth/otp-section.js.map +1 -1
  32. package/dist/components-page/account-settings/email-and-auth/passkey-section.js.map +1 -1
  33. package/dist/components-page/account-settings/email-and-auth/password-section.js.map +1 -1
  34. package/dist/components-page/account-settings/notifications/notifications-page.js.map +1 -1
  35. package/dist/components-page/account-settings/page-layout.js.map +1 -1
  36. package/dist/components-page/account-settings/payments/payments-page.js +79 -0
  37. package/dist/components-page/account-settings/payments/payments-page.js.map +1 -0
  38. package/dist/components-page/account-settings/payments/payments-panel.js +374 -0
  39. package/dist/components-page/account-settings/payments/payments-panel.js.map +1 -0
  40. package/dist/components-page/account-settings/profile-page/profile-page.js.map +1 -1
  41. package/dist/components-page/account-settings/section.js.map +1 -1
  42. package/dist/components-page/account-settings/settings/delete-account-section.js.map +1 -1
  43. package/dist/components-page/account-settings/settings/settings-page.js.map +1 -1
  44. package/dist/components-page/account-settings/settings/sign-out-section.js.map +1 -1
  45. package/dist/components-page/account-settings/teams/leave-team-section.js.map +1 -1
  46. package/dist/components-page/account-settings/teams/team-api-keys-section.js.map +1 -1
  47. package/dist/components-page/account-settings/teams/team-creation-page.js.map +1 -1
  48. package/dist/components-page/account-settings/teams/team-display-name-section.js.map +1 -1
  49. package/dist/components-page/account-settings/teams/team-member-invitation-section.js.map +1 -1
  50. package/dist/components-page/account-settings/teams/team-member-list-section.js.map +1 -1
  51. package/dist/components-page/account-settings/teams/team-page.js.map +1 -1
  52. package/dist/components-page/account-settings/teams/team-profile-image-section.js.map +1 -1
  53. package/dist/components-page/account-settings/teams/team-profile-user-section.js.map +1 -1
  54. package/dist/components-page/account-settings.js +22 -2
  55. package/dist/components-page/account-settings.js.map +1 -1
  56. package/dist/components-page/auth-page.js.map +1 -1
  57. package/dist/components-page/cli-auth-confirm.js.map +1 -1
  58. package/dist/components-page/email-verification.js.map +1 -1
  59. package/dist/components-page/error-page.js.map +1 -1
  60. package/dist/components-page/forgot-password.js.map +1 -1
  61. package/dist/components-page/magic-link-callback.js.map +1 -1
  62. package/dist/components-page/mfa.js.map +1 -1
  63. package/dist/components-page/oauth-callback.js.map +1 -1
  64. package/dist/components-page/onboarding.js.map +1 -1
  65. package/dist/components-page/password-reset.js.map +1 -1
  66. package/dist/components-page/section.js.map +1 -1
  67. package/dist/components-page/sign-in.js.map +1 -1
  68. package/dist/components-page/sign-out.js.map +1 -1
  69. package/dist/components-page/sign-up.js.map +1 -1
  70. package/dist/components-page/stack-handler-client.js.map +1 -1
  71. package/dist/components-page/stack-handler.js.map +1 -1
  72. package/dist/components-page/team-creation.js.map +1 -1
  73. package/dist/components-page/team-invitation.js.map +1 -1
  74. package/dist/esm/components/api-key-dialogs.js.map +1 -1
  75. package/dist/esm/components/api-key-table.js.map +1 -1
  76. package/dist/esm/components/credential-sign-in.js.map +1 -1
  77. package/dist/esm/components/credential-sign-up.js.map +1 -1
  78. package/dist/esm/components/elements/form-warning.js.map +1 -1
  79. package/dist/esm/components/elements/maybe-full-page.js.map +1 -1
  80. package/dist/esm/components/elements/separator-with-text.js.map +1 -1
  81. package/dist/esm/components/elements/sidebar-layout.js.map +1 -1
  82. package/dist/esm/components/elements/ssr-layout-effect.js.map +1 -1
  83. package/dist/esm/components/elements/user-avatar.js.map +1 -1
  84. package/dist/esm/components/link.js.map +1 -1
  85. package/dist/esm/components/magic-link-sign-in.js.map +1 -1
  86. package/dist/esm/components/message-cards/known-error-message-card.js.map +1 -1
  87. package/dist/esm/components/message-cards/message-card.js.map +1 -1
  88. package/dist/esm/components/message-cards/predefined-message-card.js.map +1 -1
  89. package/dist/esm/components/oauth-button-group.js.map +1 -1
  90. package/dist/esm/components/oauth-button.js.map +1 -1
  91. package/dist/esm/components/passkey-button.js.map +1 -1
  92. package/dist/esm/components/profile-image-editor.js.map +1 -1
  93. package/dist/esm/components/selected-team-switcher.js.map +1 -1
  94. package/dist/esm/components/team-icon.js.map +1 -1
  95. package/dist/esm/components/team-switcher.js.map +1 -1
  96. package/dist/esm/components/use-in-iframe.js.map +1 -1
  97. package/dist/esm/components/user-button.js.map +1 -1
  98. package/dist/esm/components-page/account-settings/active-sessions/active-sessions-page.js.map +1 -1
  99. package/dist/esm/components-page/account-settings/api-keys/api-keys-page.js.map +1 -1
  100. package/dist/esm/components-page/account-settings/editable-text.js.map +1 -1
  101. package/dist/esm/components-page/account-settings/email-and-auth/email-and-auth-page.js.map +1 -1
  102. package/dist/esm/components-page/account-settings/email-and-auth/emails-section.js.map +1 -1
  103. package/dist/esm/components-page/account-settings/email-and-auth/mfa-section.js.map +1 -1
  104. package/dist/esm/components-page/account-settings/email-and-auth/otp-section.js.map +1 -1
  105. package/dist/esm/components-page/account-settings/email-and-auth/passkey-section.js.map +1 -1
  106. package/dist/esm/components-page/account-settings/email-and-auth/password-section.js.map +1 -1
  107. package/dist/esm/components-page/account-settings/notifications/notifications-page.js.map +1 -1
  108. package/dist/esm/components-page/account-settings/page-layout.js.map +1 -1
  109. package/dist/esm/components-page/account-settings/payments/payments-page.js +55 -0
  110. package/dist/esm/components-page/account-settings/payments/payments-page.js.map +1 -0
  111. package/dist/esm/components-page/account-settings/payments/payments-panel.js +350 -0
  112. package/dist/esm/components-page/account-settings/payments/payments-panel.js.map +1 -0
  113. package/dist/esm/components-page/account-settings/profile-page/profile-page.js.map +1 -1
  114. package/dist/esm/components-page/account-settings/section.js.map +1 -1
  115. package/dist/esm/components-page/account-settings/settings/delete-account-section.js.map +1 -1
  116. package/dist/esm/components-page/account-settings/settings/settings-page.js.map +1 -1
  117. package/dist/esm/components-page/account-settings/settings/sign-out-section.js.map +1 -1
  118. package/dist/esm/components-page/account-settings/teams/leave-team-section.js.map +1 -1
  119. package/dist/esm/components-page/account-settings/teams/team-api-keys-section.js.map +1 -1
  120. package/dist/esm/components-page/account-settings/teams/team-creation-page.js.map +1 -1
  121. package/dist/esm/components-page/account-settings/teams/team-display-name-section.js.map +1 -1
  122. package/dist/esm/components-page/account-settings/teams/team-member-invitation-section.js.map +1 -1
  123. package/dist/esm/components-page/account-settings/teams/team-member-list-section.js.map +1 -1
  124. package/dist/esm/components-page/account-settings/teams/team-page.js.map +1 -1
  125. package/dist/esm/components-page/account-settings/teams/team-profile-image-section.js.map +1 -1
  126. package/dist/esm/components-page/account-settings/teams/team-profile-user-section.js.map +1 -1
  127. package/dist/esm/components-page/account-settings.js +23 -3
  128. package/dist/esm/components-page/account-settings.js.map +1 -1
  129. package/dist/esm/components-page/auth-page.js.map +1 -1
  130. package/dist/esm/components-page/cli-auth-confirm.js.map +1 -1
  131. package/dist/esm/components-page/email-verification.js.map +1 -1
  132. package/dist/esm/components-page/error-page.js.map +1 -1
  133. package/dist/esm/components-page/forgot-password.js.map +1 -1
  134. package/dist/esm/components-page/magic-link-callback.js.map +1 -1
  135. package/dist/esm/components-page/mfa.js.map +1 -1
  136. package/dist/esm/components-page/oauth-callback.js.map +1 -1
  137. package/dist/esm/components-page/onboarding.js.map +1 -1
  138. package/dist/esm/components-page/password-reset.js.map +1 -1
  139. package/dist/esm/components-page/section.js.map +1 -1
  140. package/dist/esm/components-page/sign-in.js.map +1 -1
  141. package/dist/esm/components-page/sign-out.js.map +1 -1
  142. package/dist/esm/components-page/sign-up.js.map +1 -1
  143. package/dist/esm/components-page/stack-handler-client.js.map +1 -1
  144. package/dist/esm/components-page/stack-handler.js.map +1 -1
  145. package/dist/esm/components-page/team-creation.js.map +1 -1
  146. package/dist/esm/components-page/team-invitation.js.map +1 -1
  147. package/dist/esm/generated/global-css.js +1 -1
  148. package/dist/esm/generated/global-css.js.map +1 -1
  149. package/dist/esm/generated/quetzal-translations.js.map +1 -1
  150. package/dist/esm/index.js.map +1 -1
  151. package/dist/esm/integrations/convex/component/convex.config.js.map +1 -1
  152. package/dist/esm/integrations/convex.js.map +1 -1
  153. package/dist/esm/lib/auth.js.map +1 -1
  154. package/dist/esm/lib/cookie.js.map +1 -1
  155. package/dist/esm/lib/hooks.js.map +1 -1
  156. package/dist/esm/lib/stack-app/api-keys/index.js.map +1 -1
  157. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  158. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +63 -4
  159. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  160. package/dist/esm/lib/stack-app/apps/implementations/common.js +1 -1
  161. package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
  162. package/dist/esm/lib/stack-app/apps/implementations/index.js.map +1 -1
  163. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  164. package/dist/esm/lib/stack-app/apps/index.js.map +1 -1
  165. package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  166. package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  167. package/dist/esm/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  168. package/dist/esm/lib/stack-app/common.js.map +1 -1
  169. package/dist/esm/lib/stack-app/contact-channels/index.js.map +1 -1
  170. package/dist/esm/lib/stack-app/email-templates/index.js.map +1 -1
  171. package/dist/esm/lib/stack-app/index.js.map +1 -1
  172. package/dist/esm/lib/stack-app/internal-api-keys/index.js.map +1 -1
  173. package/dist/esm/lib/stack-app/permissions/index.js.map +1 -1
  174. package/dist/esm/lib/stack-app/projects/index.js.map +1 -1
  175. package/dist/esm/lib/stack-app/teams/index.js.map +1 -1
  176. package/dist/esm/lib/stack-app/users/index.js.map +1 -1
  177. package/dist/esm/lib/translations.js.map +1 -1
  178. package/dist/esm/providers/stack-provider-client.js.map +1 -1
  179. package/dist/esm/providers/stack-provider.js.map +1 -1
  180. package/dist/esm/providers/theme-provider.js.map +1 -1
  181. package/dist/esm/providers/translation-provider-client.js.map +1 -1
  182. package/dist/esm/providers/translation-provider.js.map +1 -1
  183. package/dist/esm/utils/browser-script.js.map +1 -1
  184. package/dist/esm/utils/constants.js.map +1 -1
  185. package/dist/esm/utils/url.js.map +1 -1
  186. package/dist/generated/global-css.js +1 -1
  187. package/dist/generated/global-css.js.map +1 -1
  188. package/dist/generated/quetzal-translations.js.map +1 -1
  189. package/dist/index.d.mts +37 -1
  190. package/dist/index.d.ts +37 -1
  191. package/dist/index.js.map +1 -1
  192. package/dist/integrations/convex/component/convex.config.js.map +1 -1
  193. package/dist/integrations/convex.js.map +1 -1
  194. package/dist/lib/auth.js.map +1 -1
  195. package/dist/lib/cookie.js.map +1 -1
  196. package/dist/lib/hooks.js.map +1 -1
  197. package/dist/lib/stack-app/api-keys/index.js.map +1 -1
  198. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  199. package/dist/lib/stack-app/apps/implementations/client-app-impl.js +63 -4
  200. package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  201. package/dist/lib/stack-app/apps/implementations/common.js +1 -1
  202. package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
  203. package/dist/lib/stack-app/apps/implementations/index.js.map +1 -1
  204. package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  205. package/dist/lib/stack-app/apps/index.js.map +1 -1
  206. package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  207. package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  208. package/dist/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  209. package/dist/lib/stack-app/common.js.map +1 -1
  210. package/dist/lib/stack-app/connected-accounts/index.js.map +1 -1
  211. package/dist/lib/stack-app/contact-channels/index.js.map +1 -1
  212. package/dist/lib/stack-app/customers/index.js.map +1 -1
  213. package/dist/lib/stack-app/data-vault/index.js.map +1 -1
  214. package/dist/lib/stack-app/email/index.js.map +1 -1
  215. package/dist/lib/stack-app/email-templates/index.js.map +1 -1
  216. package/dist/lib/stack-app/index.js.map +1 -1
  217. package/dist/lib/stack-app/internal-api-keys/index.js.map +1 -1
  218. package/dist/lib/stack-app/notification-categories/index.js.map +1 -1
  219. package/dist/lib/stack-app/permissions/index.js.map +1 -1
  220. package/dist/lib/stack-app/project-configs/index.js.map +1 -1
  221. package/dist/lib/stack-app/projects/index.js.map +1 -1
  222. package/dist/lib/stack-app/teams/index.js.map +1 -1
  223. package/dist/lib/stack-app/users/index.js.map +1 -1
  224. package/dist/lib/translations.js.map +1 -1
  225. package/dist/providers/stack-provider-client.js.map +1 -1
  226. package/dist/providers/stack-provider.js.map +1 -1
  227. package/dist/providers/theme-provider.js.map +1 -1
  228. package/dist/providers/translation-provider-client.js.map +1 -1
  229. package/dist/providers/translation-provider.js.map +1 -1
  230. package/dist/utils/browser-script.js.map +1 -1
  231. package/dist/utils/constants.js.map +1 -1
  232. package/dist/utils/url.js.map +1 -1
  233. package/package.json +19 -17
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/api-key-dialogs.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { yupObject, yupString } from '@stackframe/stack-shared/dist/schema-fields';\nimport { captureError } from '@stackframe/stack-shared/dist/utils/errors';\nimport { runAsynchronously } from '@stackframe/stack-shared/dist/utils/promises';\nimport { ActionDialog, Button, CopyField, Input, Label, Typography } from '@stackframe/stack-ui';\nimport { useState } from \"react\";\nimport { useForm } from 'react-hook-form';\nimport * as yup from \"yup\";\nimport { useUser } from '..';\nimport { FormWarningText } from '../components/elements/form-warning';\nimport { ApiKey, ApiKeyCreationOptions, ApiKeyType } from \"../lib/stack-app/api-keys\";\nimport { useTranslation } from \"../lib/translations\";\n\n// Constants for expiration options\nexport const neverInMs = 1000 * 60 * 60 * 24 * 365 * 200;\nexport const expiresInOptions = {\n [1000 * 60 * 60 * 24 * 1]: \"1 day\",\n [1000 * 60 * 60 * 24 * 7]: \"7 days\",\n [1000 * 60 * 60 * 24 * 30]: \"30 days\",\n [1000 * 60 * 60 * 24 * 90]: \"90 days\",\n [1000 * 60 * 60 * 24 * 365]: \"1 year\",\n [neverInMs]: \"Never\",\n} as const;\n\n/**\n * Dialog for creating a new API key\n */\nexport function CreateApiKeyDialog<Type extends ApiKeyType = ApiKeyType>(props: {\n open: boolean,\n onOpenChange: (open: boolean) => void,\n onKeyCreated?: (key: ApiKey<Type, true>) => void,\n createApiKey: (data: ApiKeyCreationOptions<Type>) => Promise<ApiKey<Type, true>>,\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const user = useUser({ or: props.mockMode ? 'return-null' : 'redirect' });\n const [loading, setLoading] = useState(false);\n\n const apiKeySchema = yupObject({\n description: yupString().defined().nonEmpty(t('Description is required')),\n expiresIn: yupString().defined(),\n });\n\n const { register, handleSubmit, formState: { errors }, reset } = useForm({\n resolver: yupResolver(apiKeySchema),\n defaultValues: {\n description: '',\n expiresIn: Object.keys(expiresInOptions)[2], // Default to 30 days\n }\n });\n\n const onSubmit = async (data: yup.InferType<typeof apiKeySchema>) => {\n setLoading(true);\n try {\n const expiresAt = new Date(Date.now() + parseInt(data.expiresIn));\n const apiKey = await props.createApiKey({\n description: data.description,\n expiresAt,\n });\n\n if (props.onKeyCreated) {\n props.onKeyCreated(apiKey);\n }\n\n reset();\n props.onOpenChange(false);\n } catch (error) {\n captureError(\"Failed to create API key\", { error });\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <ActionDialog\n open={props.open}\n onOpenChange={props.onOpenChange}\n title={t('Create API Key')}\n description={t('API keys grant programmatic access to your account.')}\n >\n <form\n onSubmit={(e) => {\n e.preventDefault();\n runAsynchronously(handleSubmit(onSubmit));\n }}\n className=\"space-y-4\"\n >\n <div className=\"space-y-2\">\n <Label htmlFor=\"description\">{t('Description')}</Label>\n <Input\n id=\"description\"\n placeholder={t('e.g. Development, Production, CI/CD')}\n {...register('description')}\n />\n {errors.description && <FormWarningText text={errors.description.message} />}\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"expiresIn\">{t('Expires In')}</Label>\n <select\n id=\"expiresIn\"\n className=\"w-full p-2 border border-input rounded-md bg-background\"\n {...register('expiresIn')}\n >\n {Object.entries(expiresInOptions).map(([value, label]) => (\n <option key={value} value={value}>{t(label)}</option>\n ))}\n </select>\n {errors.expiresIn && <FormWarningText text={errors.expiresIn.message} />}\n </div>\n\n <div className=\"flex justify-end gap-2 pt-4\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n onClick={() => {\n reset();\n props.onOpenChange(false);\n }}\n >\n {t('Cancel')}\n </Button>\n <Button type=\"submit\" loading={loading}>\n {t('Create')}\n </Button>\n </div>\n </form>\n </ActionDialog>\n );\n}\n\n/**\n * Dialog for showing the newly created API key\n */\nexport function ShowApiKeyDialog<Type extends ApiKeyType = ApiKeyType>(props: {\n apiKey: ApiKey<Type, true> | null,\n onClose?: () => void,\n}) {\n const { t } = useTranslation();\n\n return (\n <ActionDialog\n open={!!props.apiKey}\n title={t(\"API Key\")}\n okButton={{ label: t(\"Close\") }}\n onClose={props.onClose}\n preventClose\n confirmText={t(\"I understand that I will not be able to view this key again.\")}\n >\n <div className=\"flex flex-col gap-4\">\n <Typography>\n {t(\"Here is your API key.\")}{\" \"}\n <span className=\"font-bold\">\n {t(\"Copy it to a safe place. You will not be able to view it again.\")}\n </span>\n </Typography>\n <CopyField\n type=\"input\"\n monospace\n value={props.apiKey?.value ?? ''}\n label={t(\"Secret API Key\")}\n />\n </div>\n </ActionDialog>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/api-key-dialogs.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { yupObject, yupString } from '@stackframe/stack-shared/dist/schema-fields';\nimport { captureError } from '@stackframe/stack-shared/dist/utils/errors';\nimport { runAsynchronously } from '@stackframe/stack-shared/dist/utils/promises';\nimport { ActionDialog, Button, CopyField, Input, Label, Typography } from '@stackframe/stack-ui';\nimport { useState } from \"react\";\nimport { useForm } from 'react-hook-form';\nimport * as yup from \"yup\";\nimport { useUser } from '..';\nimport { FormWarningText } from '../components/elements/form-warning';\nimport { ApiKey, ApiKeyCreationOptions, ApiKeyType } from \"../lib/stack-app/api-keys\";\nimport { useTranslation } from \"../lib/translations\";\n\n// Constants for expiration options\nexport const neverInMs = 1000 * 60 * 60 * 24 * 365 * 200;\nexport const expiresInOptions = {\n [1000 * 60 * 60 * 24 * 1]: \"1 day\",\n [1000 * 60 * 60 * 24 * 7]: \"7 days\",\n [1000 * 60 * 60 * 24 * 30]: \"30 days\",\n [1000 * 60 * 60 * 24 * 90]: \"90 days\",\n [1000 * 60 * 60 * 24 * 365]: \"1 year\",\n [neverInMs]: \"Never\",\n} as const;\n\n/**\n * Dialog for creating a new API key\n */\nexport function CreateApiKeyDialog<Type extends ApiKeyType = ApiKeyType>(props: {\n open: boolean,\n onOpenChange: (open: boolean) => void,\n onKeyCreated?: (key: ApiKey<Type, true>) => void,\n createApiKey: (data: ApiKeyCreationOptions<Type>) => Promise<ApiKey<Type, true>>,\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const user = useUser({ or: props.mockMode ? 'return-null' : 'redirect' });\n const [loading, setLoading] = useState(false);\n\n const apiKeySchema = yupObject({\n description: yupString().defined().nonEmpty(t('Description is required')),\n expiresIn: yupString().defined(),\n });\n\n const { register, handleSubmit, formState: { errors }, reset } = useForm({\n resolver: yupResolver(apiKeySchema),\n defaultValues: {\n description: '',\n expiresIn: Object.keys(expiresInOptions)[2], // Default to 30 days\n }\n });\n\n const onSubmit = async (data: yup.InferType<typeof apiKeySchema>) => {\n setLoading(true);\n try {\n const expiresAt = new Date(Date.now() + parseInt(data.expiresIn));\n const apiKey = await props.createApiKey({\n description: data.description,\n expiresAt,\n });\n\n if (props.onKeyCreated) {\n props.onKeyCreated(apiKey);\n }\n\n reset();\n props.onOpenChange(false);\n } catch (error) {\n captureError(\"Failed to create API key\", { error });\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <ActionDialog\n open={props.open}\n onOpenChange={props.onOpenChange}\n title={t('Create API Key')}\n description={t('API keys grant programmatic access to your account.')}\n >\n <form\n onSubmit={(e) => {\n e.preventDefault();\n runAsynchronously(handleSubmit(onSubmit));\n }}\n className=\"space-y-4\"\n >\n <div className=\"space-y-2\">\n <Label htmlFor=\"description\">{t('Description')}</Label>\n <Input\n id=\"description\"\n placeholder={t('e.g. Development, Production, CI/CD')}\n {...register('description')}\n />\n {errors.description && <FormWarningText text={errors.description.message} />}\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"expiresIn\">{t('Expires In')}</Label>\n <select\n id=\"expiresIn\"\n className=\"w-full p-2 border border-input rounded-md bg-background\"\n {...register('expiresIn')}\n >\n {Object.entries(expiresInOptions).map(([value, label]) => (\n <option key={value} value={value}>{t(label)}</option>\n ))}\n </select>\n {errors.expiresIn && <FormWarningText text={errors.expiresIn.message} />}\n </div>\n\n <div className=\"flex justify-end gap-2 pt-4\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n onClick={() => {\n reset();\n props.onOpenChange(false);\n }}\n >\n {t('Cancel')}\n </Button>\n <Button type=\"submit\" loading={loading}>\n {t('Create')}\n </Button>\n </div>\n </form>\n </ActionDialog>\n );\n}\n\n/**\n * Dialog for showing the newly created API key\n */\nexport function ShowApiKeyDialog<Type extends ApiKeyType = ApiKeyType>(props: {\n apiKey: ApiKey<Type, true> | null,\n onClose?: () => void,\n}) {\n const { t } = useTranslation();\n\n return (\n <ActionDialog\n open={!!props.apiKey}\n title={t(\"API Key\")}\n okButton={{ label: t(\"Close\") }}\n onClose={props.onClose}\n preventClose\n confirmText={t(\"I understand that I will not be able to view this key again.\")}\n >\n <div className=\"flex flex-col gap-4\">\n <Typography>\n {t(\"Here is your API key.\")}{\" \"}\n <span className=\"font-bold\">\n {t(\"Copy it to a safe place. You will not be able to view it again.\")}\n </span>\n </Typography>\n <CopyField\n type=\"input\"\n monospace\n value={props.apiKey?.value ?? ''}\n label={t(\"Secret API Key\")}\n />\n </div>\n </ActionDialog>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/api-key-table.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { ActionCell, ActionDialog, BadgeCell, DataTable, DataTableColumnHeader, DataTableFacetedFilter, DateCell, SearchToolbarItem, TextCell, standardFilterFn } from \"@stackframe/stack-ui\";\nimport { ColumnDef, Row, Table } from \"@tanstack/react-table\";\nimport { useMemo, useState } from \"react\";\nimport { ApiKey } from \"../lib/stack-app/api-keys\";\n\ntype ExtendedApiKey = ApiKey & {\n status: 'valid' | 'expired' | 'revoked',\n};\n\nfunction toolbarRender<TData>(table: Table<TData>) {\n return (\n <>\n <SearchToolbarItem table={table} placeholder=\"Search table\" />\n <DataTableFacetedFilter\n column={table.getColumn(\"status\")}\n title=\"Status\"\n options={['valid', 'expired', 'revoked'].map((provider) => ({\n value: provider,\n label: provider,\n }))}\n />\n </>\n );\n}\n\nfunction RevokeDialog(props: {\n apiKey: ExtendedApiKey,\n open: boolean,\n onOpenChange: (open: boolean) => void,\n}) {\n return <ActionDialog\n open={props.open}\n onOpenChange={props.onOpenChange}\n title=\"Revoke API Key\"\n danger\n cancelButton\n okButton={{ label: \"Revoke Key\", onClick: async () => { await props.apiKey.revoke(); } }}\n confirmText=\"I understand this will unlink all the apps using this API key\"\n >\n {`Are you sure you want to revoke API key *****${props.apiKey.value.lastFour}?`}\n </ActionDialog>;\n}\n\nfunction Actions({ row }: { row: Row<ExtendedApiKey> }) {\n const [isRevokeModalOpen, setIsRevokeModalOpen] = useState(false);\n return (\n <>\n <RevokeDialog apiKey={row.original} open={isRevokeModalOpen} onOpenChange={setIsRevokeModalOpen} />\n <ActionCell\n invisible={row.original.status !== 'valid'}\n items={[{\n item: \"Revoke\",\n danger: true,\n onClick: () => setIsRevokeModalOpen(true),\n }]}\n />\n </>\n );\n}\n\nconst columns: ColumnDef<ExtendedApiKey>[] = [\n {\n accessorKey: \"description\",\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Description\" />,\n cell: ({ row }) => <TextCell size={100}>{row.original.description}</TextCell>,\n },\n {\n accessorKey: \"status\",\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Status\" />,\n cell: ({ row }) => <BadgeCell badges={[row.original.status]} />,\n filterFn: standardFilterFn,\n },\n {\n id: \"value\",\n accessorFn: (row) => row.value.lastFour,\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Client Key\" />,\n cell: ({ row }) => <TextCell>*******{row.original.value.lastFour}</TextCell>,\n enableSorting: false,\n },\n {\n accessorKey: \"expiresAt\",\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Expires At\" />,\n cell: ({ row }) => {\n if (row.original.status === 'revoked') return <TextCell>-</TextCell>;\n return row.original.expiresAt ? <DateCell date={row.original.expiresAt} ignoreAfterYears={50} /> : <TextCell>Never</TextCell>;\n },\n },\n {\n accessorKey: \"createdAt\",\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Created At\" />,\n cell: ({ row }) => <DateCell date={row.original.createdAt} ignoreAfterYears={50} />\n },\n {\n id: \"actions\",\n cell: ({ row }) => <Actions row={row} />,\n },\n];\n\nexport function ApiKeyTable(props: { apiKeys: ApiKey[] }) {\n const extendedApiKeys = useMemo(() => {\n const keys = props.apiKeys.map((apiKey) => ({\n ...apiKey,\n status: ({ 'valid': 'valid', 'manually-revoked': 'revoked', 'expired': 'expired' } as const)[apiKey.whyInvalid() || 'valid'],\n } satisfies ExtendedApiKey));\n // first sort based on status, then by createdAt\n return keys.sort((a, b) => {\n if (a.status === b.status) {\n return a.createdAt < b.createdAt ? 1 : -1;\n }\n return a.status === 'valid' ? -1 : 1;\n });\n }, [props.apiKeys]);\n\n return <DataTable\n data={extendedApiKeys}\n columns={columns}\n toolbarRender={toolbarRender}\n defaultColumnFilters={[]}\n defaultSorting={[]}\n />;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/api-key-table.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { ActionCell, ActionDialog, BadgeCell, DataTable, DataTableColumnHeader, DataTableFacetedFilter, DateCell, SearchToolbarItem, TextCell, standardFilterFn } from \"@stackframe/stack-ui\";\nimport { ColumnDef, Row, Table } from \"@tanstack/react-table\";\nimport { useMemo, useState } from \"react\";\nimport { ApiKey } from \"../lib/stack-app/api-keys\";\n\ntype ExtendedApiKey = ApiKey & {\n status: 'valid' | 'expired' | 'revoked',\n};\n\nfunction toolbarRender<TData>(table: Table<TData>) {\n return (\n <>\n <SearchToolbarItem table={table} placeholder=\"Search table\" />\n <DataTableFacetedFilter\n column={table.getColumn(\"status\")}\n title=\"Status\"\n options={['valid', 'expired', 'revoked'].map((provider) => ({\n value: provider,\n label: provider,\n }))}\n />\n </>\n );\n}\n\nfunction RevokeDialog(props: {\n apiKey: ExtendedApiKey,\n open: boolean,\n onOpenChange: (open: boolean) => void,\n}) {\n return <ActionDialog\n open={props.open}\n onOpenChange={props.onOpenChange}\n title=\"Revoke API Key\"\n danger\n cancelButton\n okButton={{ label: \"Revoke Key\", onClick: async () => { await props.apiKey.revoke(); } }}\n confirmText=\"I understand this will unlink all the apps using this API key\"\n >\n {`Are you sure you want to revoke API key *****${props.apiKey.value.lastFour}?`}\n </ActionDialog>;\n}\n\nfunction Actions({ row }: { row: Row<ExtendedApiKey> }) {\n const [isRevokeModalOpen, setIsRevokeModalOpen] = useState(false);\n return (\n <>\n <RevokeDialog apiKey={row.original} open={isRevokeModalOpen} onOpenChange={setIsRevokeModalOpen} />\n <ActionCell\n invisible={row.original.status !== 'valid'}\n items={[{\n item: \"Revoke\",\n danger: true,\n onClick: () => setIsRevokeModalOpen(true),\n }]}\n />\n </>\n );\n}\n\nconst columns: ColumnDef<ExtendedApiKey>[] = [\n {\n accessorKey: \"description\",\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Description\" />,\n cell: ({ row }) => <TextCell size={100}>{row.original.description}</TextCell>,\n },\n {\n accessorKey: \"status\",\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Status\" />,\n cell: ({ row }) => <BadgeCell badges={[row.original.status]} />,\n filterFn: standardFilterFn,\n },\n {\n id: \"value\",\n accessorFn: (row) => row.value.lastFour,\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Client Key\" />,\n cell: ({ row }) => <TextCell>*******{row.original.value.lastFour}</TextCell>,\n enableSorting: false,\n },\n {\n accessorKey: \"expiresAt\",\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Expires At\" />,\n cell: ({ row }) => {\n if (row.original.status === 'revoked') return <TextCell>-</TextCell>;\n return row.original.expiresAt ? <DateCell date={row.original.expiresAt} ignoreAfterYears={50} /> : <TextCell>Never</TextCell>;\n },\n },\n {\n accessorKey: \"createdAt\",\n header: ({ column }) => <DataTableColumnHeader column={column} columnTitle=\"Created At\" />,\n cell: ({ row }) => <DateCell date={row.original.createdAt} ignoreAfterYears={50} />\n },\n {\n id: \"actions\",\n cell: ({ row }) => <Actions row={row} />,\n },\n];\n\nexport function ApiKeyTable(props: { apiKeys: ApiKey[] }) {\n const extendedApiKeys = useMemo(() => {\n const keys = props.apiKeys.map((apiKey) => ({\n ...apiKey,\n status: ({ 'valid': 'valid', 'manually-revoked': 'revoked', 'expired': 'expired' } as const)[apiKey.whyInvalid() || 'valid'],\n } satisfies ExtendedApiKey));\n // first sort based on status, then by createdAt\n return keys.sort((a, b) => {\n if (a.status === b.status) {\n return a.createdAt < b.createdAt ? 1 : -1;\n }\n return a.status === 'valid' ? -1 : 1;\n });\n }, [props.apiKeys]);\n\n return <DataTable\n data={extendedApiKeys}\n columns={columns}\n toolbarRender={toolbarRender}\n defaultColumnFilters={[]}\n defaultSorting={[]}\n />;\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/credential-sign-in.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { passwordSchema, strictEmailSchema, yupObject } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, Label, PasswordInput } from \"@stackframe/stack-ui\";\nimport { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp } from \"..\";\nimport { useTranslation } from \"../lib/translations\";\nimport { FormWarningText } from \"./elements/form-warning\";\nimport { StyledLink } from \"./link\";\n\nexport function CredentialSignIn() {\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 password: passwordSchema.defined().nonEmpty(t('Please enter your password'))\n });\n\n const { register, handleSubmit, setError, formState: { errors } } = useForm({\n resolver: yupResolver(schema)\n });\n const app = useStackApp();\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n\n try {\n const { email, password } = data;\n const result = await app.signInWithCredential({\n email,\n password,\n });\n if (result.status === 'error') {\n setError('email', { type: 'manual', message: result.error.message });\n }\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('Email')}</Label>\n <Input\n id=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n {...register('email')}\n />\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Label htmlFor=\"password\" className=\"mt-4 mb-1\">{t('Password')}</Label>\n <PasswordInput\n id=\"password\"\n autoComplete=\"current-password\"\n {...register('password')}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n\n <StyledLink href={app.urls.forgotPassword} className=\"mt-1 text-sm\">\n {t('Forgot password?')}\n </StyledLink>\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n {t('Sign In')}\n </Button>\n </form>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,iBAA4B;AAC5B,2BAA6D;AAC7D,sBAA2C;AAC3C,sBAAoD;AACpD,mBAAyB;AACzB,6BAAwB;AAExB,eAA4B;AAC5B,0BAA+B;AAC/B,0BAAgC;AAChC,kBAA2B;AAkCvB;AAhCG,SAAS,mBAAmB;AACjC,QAAM,EAAE,EAAE,QAAI,oCAAe;AAE7B,QAAM,aAAS,gCAAU;AAAA,IACvB,WAAO,wCAAkB,EAAE,4BAA4B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,yBAAyB,CAAC;AAAA,IACzG,UAAU,oCAAe,QAAQ,EAAE,SAAS,EAAE,4BAA4B,CAAC;AAAA,EAC7E,CAAC;AAED,QAAM,EAAE,UAAU,cAAc,UAAU,WAAW,EAAE,OAAO,EAAE,QAAI,gCAAQ;AAAA,IAC1E,cAAU,wBAAY,MAAM;AAAA,EAC9B,CAAC;AACD,QAAM,UAAM,sBAAY;AACxB,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,KAAK;AAE5C,QAAM,WAAW,OAAO,SAAuC;AAC7D,eAAW,IAAI;AAEf,QAAI;AACF,YAAM,EAAE,OAAO,SAAS,IAAI;AAC5B,YAAM,SAAS,MAAM,IAAI,qBAAqB;AAAA,QAC5C;AAAA,QACA;AAAA,MACF,CAAC;AACD,UAAI,OAAO,WAAW,SAAS;AAC7B,iBAAS,SAAS,EAAE,MAAM,UAAU,SAAS,OAAO,MAAM,QAAQ,CAAC;AAAA,MACrE;AAAA,IACF,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,UAAU,WAAK,4CAA2B,aAAa,QAAQ,EAAE,CAAC,CAAC;AAAA,MACnE,YAAU;AAAA,MAEV;AAAA,oDAAC,yBAAM,SAAQ,SAAQ,WAAU,QAAQ,YAAE,OAAO,GAAE;AAAA,QACpD;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,MAAK;AAAA,YACL,cAAa;AAAA,YACZ,GAAG,SAAS,OAAO;AAAA;AAAA,QACtB;AAAA,QACA,4CAAC,uCAAgB,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AAAA,QAE1D,4CAAC,yBAAM,SAAQ,YAAW,WAAU,aAAa,YAAE,UAAU,GAAE;AAAA,QAC/D;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,cAAa;AAAA,YACZ,GAAG,SAAS,UAAU;AAAA;AAAA,QACzB;AAAA,QACA,4CAAC,uCAAgB,MAAM,OAAO,UAAU,SAAS,SAAS,GAAG;AAAA,QAE7D,4CAAC,0BAAW,MAAM,IAAI,KAAK,gBAAgB,WAAU,gBAClD,YAAE,kBAAkB,GACvB;AAAA,QAEA,4CAAC,0BAAO,MAAK,UAAS,WAAU,QAAO,SACpC,YAAE,SAAS,GACd;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/credential-sign-in.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { passwordSchema, strictEmailSchema, yupObject } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, Label, PasswordInput } from \"@stackframe/stack-ui\";\nimport { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp } from \"..\";\nimport { useTranslation } from \"../lib/translations\";\nimport { FormWarningText } from \"./elements/form-warning\";\nimport { StyledLink } from \"./link\";\n\nexport function CredentialSignIn() {\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 password: passwordSchema.defined().nonEmpty(t('Please enter your password'))\n });\n\n const { register, handleSubmit, setError, formState: { errors } } = useForm({\n resolver: yupResolver(schema)\n });\n const app = useStackApp();\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n\n try {\n const { email, password } = data;\n const result = await app.signInWithCredential({\n email,\n password,\n });\n if (result.status === 'error') {\n setError('email', { type: 'manual', message: result.error.message });\n }\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('Email')}</Label>\n <Input\n id=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n {...register('email')}\n />\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Label htmlFor=\"password\" className=\"mt-4 mb-1\">{t('Password')}</Label>\n <PasswordInput\n id=\"password\"\n autoComplete=\"current-password\"\n {...register('password')}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n\n <StyledLink href={app.urls.forgotPassword} className=\"mt-1 text-sm\">\n {t('Forgot password?')}\n </StyledLink>\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n {t('Sign In')}\n </Button>\n </form>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,iBAA4B;AAC5B,2BAA6D;AAC7D,sBAA2C;AAC3C,sBAAoD;AACpD,mBAAyB;AACzB,6BAAwB;AAExB,eAA4B;AAC5B,0BAA+B;AAC/B,0BAAgC;AAChC,kBAA2B;AAkCvB;AAhCG,SAAS,mBAAmB;AACjC,QAAM,EAAE,EAAE,QAAI,oCAAe;AAE7B,QAAM,aAAS,gCAAU;AAAA,IACvB,WAAO,wCAAkB,EAAE,4BAA4B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,yBAAyB,CAAC;AAAA,IACzG,UAAU,oCAAe,QAAQ,EAAE,SAAS,EAAE,4BAA4B,CAAC;AAAA,EAC7E,CAAC;AAED,QAAM,EAAE,UAAU,cAAc,UAAU,WAAW,EAAE,OAAO,EAAE,QAAI,gCAAQ;AAAA,IAC1E,cAAU,wBAAY,MAAM;AAAA,EAC9B,CAAC;AACD,QAAM,UAAM,sBAAY;AACxB,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,KAAK;AAE5C,QAAM,WAAW,OAAO,SAAuC;AAC7D,eAAW,IAAI;AAEf,QAAI;AACF,YAAM,EAAE,OAAO,SAAS,IAAI;AAC5B,YAAM,SAAS,MAAM,IAAI,qBAAqB;AAAA,QAC5C;AAAA,QACA;AAAA,MACF,CAAC;AACD,UAAI,OAAO,WAAW,SAAS;AAC7B,iBAAS,SAAS,EAAE,MAAM,UAAU,SAAS,OAAO,MAAM,QAAQ,CAAC;AAAA,MACrE;AAAA,IACF,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,UAAU,WAAK,4CAA2B,aAAa,QAAQ,EAAE,CAAC,CAAC;AAAA,MACnE,YAAU;AAAA,MAEV;AAAA,oDAAC,yBAAM,SAAQ,SAAQ,WAAU,QAAQ,YAAE,OAAO,GAAE;AAAA,QACpD;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,MAAK;AAAA,YACL,cAAa;AAAA,YACZ,GAAG,SAAS,OAAO;AAAA;AAAA,QACtB;AAAA,QACA,4CAAC,uCAAgB,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AAAA,QAE1D,4CAAC,yBAAM,SAAQ,YAAW,WAAU,aAAa,YAAE,UAAU,GAAE;AAAA,QAC/D;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,cAAa;AAAA,YACZ,GAAG,SAAS,UAAU;AAAA;AAAA,QACzB;AAAA,QACA,4CAAC,uCAAgB,MAAM,OAAO,UAAU,SAAS,SAAS,GAAG;AAAA,QAE7D,4CAAC,0BAAW,MAAM,IAAI,KAAK,gBAAgB,WAAU,gBAClD,YAAE,kBAAkB,GACvB;AAAA,QAEA,4CAAC,0BAAO,MAAK,UAAS,WAAU,QAAO,SACpC,YAAE,SAAS,GACd;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/credential-sign-up.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { getPasswordError } from \"@stackframe/stack-shared/dist/helpers/password\";\nimport { passwordSchema, strictEmailSchema, yupObject } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { runAsynchronously, runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, Label, PasswordInput } from \"@stackframe/stack-ui\";\nimport React, { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp } from \"..\";\nimport { useTranslation } from \"../lib/translations\";\nimport { FormWarningText } from \"./elements/form-warning\";\n\nexport function CredentialSignUp(props: { noPasswordRepeat?: boolean }) {\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 password: passwordSchema.defined().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 ...(!props.noPasswordRepeat && {\n passwordRepeat: passwordSchema.nullable().oneOf([yup.ref('password'), \"\", null], t('Passwords do not match')).nonEmpty(t('Please repeat your password'))\n })\n });\n\n const { register, handleSubmit, setError, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const app = 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, password } = data;\n const result = await app.signUpWithCredential({ email, password });\n if (result.status === 'error') {\n setError('email', { type: 'manual', message: result.error.message });\n }\n } finally {\n setLoading(false);\n }\n };\n\n const registerPassword = register('password');\n const registerPasswordRepeat = register('passwordRepeat');\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('Email')}</Label>\n <Input id=\"email\" type=\"email\" autoComplete=\"email\" {...register('email')}/>\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Label htmlFor=\"password\" className=\"mt-4 mb-1\">{t('Password')}</Label>\n <PasswordInput\n id=\"password\"\n autoComplete=\"new-password\"\n {...registerPassword}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n runAsynchronously(registerPassword.onChange(e));\n }}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n {\n !props.noPasswordRepeat && (\n <>\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">{t('Repeat Password')}</Label>\n <PasswordInput\n id=\"repeat-password\"\n {...registerPasswordRepeat}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n runAsynchronously(registerPasswordRepeat.onChange(e));\n }}\n />\n <FormWarningText text={errors.passwordRepeat?.message?.toString()} />\n </>\n )\n }\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n {t('Sign Up')}\n </Button>\n </form>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/credential-sign-up.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { getPasswordError } from \"@stackframe/stack-shared/dist/helpers/password\";\nimport { passwordSchema, strictEmailSchema, yupObject } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { runAsynchronously, runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, Label, PasswordInput } from \"@stackframe/stack-ui\";\nimport React, { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp } from \"..\";\nimport { useTranslation } from \"../lib/translations\";\nimport { FormWarningText } from \"./elements/form-warning\";\n\nexport function CredentialSignUp(props: { noPasswordRepeat?: boolean }) {\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 password: passwordSchema.defined().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 ...(!props.noPasswordRepeat && {\n passwordRepeat: passwordSchema.nullable().oneOf([yup.ref('password'), \"\", null], t('Passwords do not match')).nonEmpty(t('Please repeat your password'))\n })\n });\n\n const { register, handleSubmit, setError, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const app = 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, password } = data;\n const result = await app.signUpWithCredential({ email, password });\n if (result.status === 'error') {\n setError('email', { type: 'manual', message: result.error.message });\n }\n } finally {\n setLoading(false);\n }\n };\n\n const registerPassword = register('password');\n const registerPasswordRepeat = register('passwordRepeat');\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('Email')}</Label>\n <Input id=\"email\" type=\"email\" autoComplete=\"email\" {...register('email')}/>\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Label htmlFor=\"password\" className=\"mt-4 mb-1\">{t('Password')}</Label>\n <PasswordInput\n id=\"password\"\n autoComplete=\"new-password\"\n {...registerPassword}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n runAsynchronously(registerPassword.onChange(e));\n }}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n {\n !props.noPasswordRepeat && (\n <>\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">{t('Repeat Password')}</Label>\n <PasswordInput\n id=\"repeat-password\"\n {...registerPasswordRepeat}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n runAsynchronously(registerPasswordRepeat.onChange(e));\n }}\n />\n <FormWarningText text={errors.passwordRepeat?.message?.toString()} />\n </>\n )\n }\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n {t('Sign Up')}\n </Button>\n </form>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,iBAA4B;AAC5B,sBAAiC;AACjC,2BAA6D;AAC7D,sBAA8D;AAC9D,sBAAoD;AACpD,mBAAgC;AAChC,6BAAwB;AACxB,UAAqB;AACrB,eAA4B;AAC5B,0BAA+B;AAC/B,0BAAgC;AAmD1B;AAjDC,SAAS,iBAAiB,OAAuC;AACtE,QAAM,EAAE,EAAE,QAAI,oCAAe;AAE7B,QAAM,aAAS,gCAAU;AAAA,IACvB,WAAO,wCAAkB,EAAE,4BAA4B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,yBAAyB,CAAC;AAAA,IACzG,UAAU,oCAAe,QAAQ,EAAE,SAAS,EAAE,4BAA4B,CAAC,EAAE,KAAK;AAAA,MAChF,MAAM;AAAA,MACN,MAAM,CAAC,OAAO,QAAQ;AACpB,cAAM,YAAQ,kCAAiB,KAAK;AACpC,YAAI,OAAO;AACT,iBAAO,IAAI,YAAY,EAAE,SAAS,MAAM,QAAQ,CAAC;AAAA,QACnD,OAAO;AACL,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAAA,IACD,GAAI,CAAC,MAAM,oBAAoB;AAAA,MAC7B,gBAAgB,oCAAe,SAAS,EAAE,MAAM,CAAK,QAAI,UAAU,GAAG,IAAI,IAAI,GAAG,EAAE,wBAAwB,CAAC,EAAE,SAAS,EAAE,6BAA6B,CAAC;AAAA,IACzJ;AAAA,EACF,CAAC;AAED,QAAM,EAAE,UAAU,cAAc,UAAU,WAAW,EAAE,OAAO,GAAG,YAAY,QAAI,gCAAQ;AAAA,IACvF,cAAU,wBAAY,MAAM;AAAA,EAC9B,CAAC;AACD,QAAM,UAAM,sBAAY;AACxB,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,KAAK;AAE5C,QAAM,WAAW,OAAO,SAAuC;AAC7D,eAAW,IAAI;AACf,QAAI;AACF,YAAM,EAAE,OAAO,SAAS,IAAI;AAC5B,YAAM,SAAS,MAAM,IAAI,qBAAqB,EAAE,OAAO,SAAS,CAAC;AACjE,UAAI,OAAO,WAAW,SAAS;AAC7B,iBAAS,SAAS,EAAE,MAAM,UAAU,SAAS,OAAO,MAAM,QAAQ,CAAC;AAAA,MACrE;AAAA,IACF,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,mBAAmB,SAAS,UAAU;AAC5C,QAAM,yBAAyB,SAAS,gBAAgB;AAExD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,UAAU,WAAK,4CAA2B,aAAa,QAAQ,EAAE,CAAC,CAAC;AAAA,MACnE,YAAU;AAAA,MAEV;AAAA,oDAAC,yBAAM,SAAQ,SAAQ,WAAU,QAAQ,YAAE,OAAO,GAAE;AAAA,QACpD,4CAAC,yBAAM,IAAG,SAAQ,MAAK,SAAQ,cAAa,SAAS,GAAG,SAAS,OAAO,GAAE;AAAA,QAC1E,4CAAC,uCAAgB,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AAAA,QAE1D,4CAAC,yBAAM,SAAQ,YAAW,WAAU,aAAa,YAAE,UAAU,GAAE;AAAA,QAC/D;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,cAAa;AAAA,YACZ,GAAG;AAAA,YACJ,UAAU,CAAC,MAA2C;AACpD,0BAAY,UAAU;AACtB,0BAAY,gBAAgB;AAC5B,qDAAkB,iBAAiB,SAAS,CAAC,CAAC;AAAA,YAChD;AAAA;AAAA,QACF;AAAA,QACA,4CAAC,uCAAgB,MAAM,OAAO,UAAU,SAAS,SAAS,GAAG;AAAA,QAE3D,CAAC,MAAM,oBACL,4EACE;AAAA,sDAAC,yBAAM,SAAQ,mBAAkB,WAAU,aAAa,YAAE,iBAAiB,GAAE;AAAA,UAC7E;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACF,GAAG;AAAA,cACJ,UAAU,CAAC,MAA2C;AACtD,4BAAY,UAAU;AACtB,4BAAY,gBAAgB;AAC5B,uDAAkB,uBAAuB,SAAS,CAAC,CAAC;AAAA,cACpD;AAAA;AAAA,UACF;AAAA,UACA,4CAAC,uCAAgB,MAAM,OAAO,gBAAgB,SAAS,SAAS,GAAG;AAAA,WACrE;AAAA,QAIJ,4CAAC,0BAAO,MAAK,UAAS,WAAU,QAAO,SACpC,YAAE,SAAS,GACd;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/elements/form-warning.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nexport function FormWarningText({ text }: { text?: string }) {\n if (!text) {\n return null;\n }\n return (\n <div className=\"text-red-500 text-sm mt-1\">\n {text}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAYI;AALG,SAAS,gBAAgB,EAAE,KAAK,GAAsB;AAC3D,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,SACE,4CAAC,SAAI,WAAU,6BACZ,gBACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/elements/form-warning.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nexport function FormWarningText({ text }: { text?: string }) {\n if (!text) {\n return null;\n }\n return (\n <div className=\"text-red-500 text-sm mt-1\">\n {text}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAYI;AALG,SAAS,gBAAgB,EAAE,KAAK,GAAsB;AAC3D,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,SACE,4CAAC,SAAI,WAAU,6BACZ,gBACH;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/elements/maybe-full-page.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport React, { useId } from \"react\";\nimport { SsrScript } from \"./ssr-layout-effect\";\n\nexport function MaybeFullPage({\n children,\n fullPage,\n}: {\n children: React.ReactNode,\n fullPage: boolean,\n size?: number,\n containerClassName?: string,\n}) {\n const uniqueId = useId();\n const id = `stack-full-page-container-${uniqueId}`;\n\n const scriptString = `(([id]) => {\n const el = document.getElementById(id);\n if (!el) {\n // component is not full page\n return;\n }\n const offset = el.getBoundingClientRect().top + document.documentElement.scrollTop;\n el.style.minHeight = \\`calc(100vh - \\${offset}px)\\`;\n })(${JSON.stringify([id])})`;\n\n if (fullPage) {\n return (\n <>\n <div\n suppressHydrationWarning\n id={id}\n style={{\n minHeight: '100vh',\n alignSelf: 'stretch',\n flexGrow: 1,\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n className=\"stack-scope\"\n >\n {children}\n </div>\n <SsrScript script={scriptString} />\n </>\n );\n } else {\n return <>\n {children}\n </>;\n }\n\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,mBAA6B;AAC7B,+BAA0B;AA0BpB;AAxBC,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AACF,GAKG;AACD,QAAM,eAAW,oBAAM;AACvB,QAAM,KAAK,6BAA6B,QAAQ;AAEhD,QAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAQhB,KAAK,UAAU,CAAC,EAAE,CAAC,CAAC;AAEzB,MAAI,UAAU;AACZ,WACE,4EACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,0BAAwB;AAAA,UACxB;AAAA,UACA,OAAO;AAAA,YACL,WAAW;AAAA,YACX,WAAW;AAAA,YACX,UAAU;AAAA,YACV,SAAS;AAAA,YACT,gBAAgB;AAAA,YAChB,YAAY;AAAA,UACd;AAAA,UACA,WAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MACA,4CAAC,sCAAU,QAAQ,cAAc;AAAA,OACnC;AAAA,EAEJ,OAAO;AACL,WAAO,2EACJ,UACH;AAAA,EACF;AAEF;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/elements/maybe-full-page.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport React, { useId } from \"react\";\nimport { SsrScript } from \"./ssr-layout-effect\";\n\nexport function MaybeFullPage({\n children,\n fullPage,\n}: {\n children: React.ReactNode,\n fullPage: boolean,\n size?: number,\n containerClassName?: string,\n}) {\n const uniqueId = useId();\n const id = `stack-full-page-container-${uniqueId}`;\n\n const scriptString = `(([id]) => {\n const el = document.getElementById(id);\n if (!el) {\n // component is not full page\n return;\n }\n const offset = el.getBoundingClientRect().top + document.documentElement.scrollTop;\n el.style.minHeight = \\`calc(100vh - \\${offset}px)\\`;\n })(${JSON.stringify([id])})`;\n\n if (fullPage) {\n return (\n <>\n <div\n suppressHydrationWarning\n id={id}\n style={{\n minHeight: '100vh',\n alignSelf: 'stretch',\n flexGrow: 1,\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n className=\"stack-scope\"\n >\n {children}\n </div>\n <SsrScript script={scriptString} />\n </>\n );\n } else {\n return <>\n {children}\n </>;\n }\n\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,mBAA6B;AAC7B,+BAA0B;AA0BpB;AAxBC,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AACF,GAKG;AACD,QAAM,eAAW,oBAAM;AACvB,QAAM,KAAK,6BAA6B,QAAQ;AAEhD,QAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAQhB,KAAK,UAAU,CAAC,EAAE,CAAC,CAAC;AAEzB,MAAI,UAAU;AACZ,WACE,4EACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,0BAAwB;AAAA,UACxB;AAAA,UACA,OAAO;AAAA,YACL,WAAW;AAAA,YACX,WAAW;AAAA,YACX,UAAU;AAAA,YACV,SAAS;AAAA,YACT,gBAAgB;AAAA,YAChB,YAAY;AAAA,UACd;AAAA,UACA,WAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MACA,4CAAC,sCAAU,QAAQ,cAAc;AAAA,OACnC;AAAA,EAEJ,OAAO;AACL,WAAO,2EACJ,UACH;AAAA,EACF;AAEF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/elements/separator-with-text.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { Separator } from \"@stackframe/stack-ui\";\n\nexport function SeparatorWithText({ text }: { text: string }) {\n return (\n <div className=\"flex items-center justify-center my-6 stack-scope\">\n <div className=\"flex-1\">\n <Separator />\n </div>\n <div className=\"mx-2 text-sm text-zinc-500\">{text}</div>\n <div className=\"flex-1\">\n <Separator />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAA0B;AAItB;AAFG,SAAS,kBAAkB,EAAE,KAAK,GAAqB;AAC5D,SACE,6CAAC,SAAI,WAAU,qDACb;AAAA,gDAAC,SAAI,WAAU,UACb,sDAAC,6BAAU,GACb;AAAA,IACA,4CAAC,SAAI,WAAU,8BAA8B,gBAAK;AAAA,IAClD,4CAAC,SAAI,WAAU,UACb,sDAAC,6BAAU,GACb;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/elements/separator-with-text.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { Separator } from \"@stackframe/stack-ui\";\n\nexport function SeparatorWithText({ text }: { text: string }) {\n return (\n <div className=\"flex items-center justify-center my-6 stack-scope\">\n <div className=\"flex-1\">\n <Separator />\n </div>\n <div className=\"mx-2 text-sm text-zinc-500\">{text}</div>\n <div className=\"flex-1\">\n <Separator />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAA0B;AAItB;AAFG,SAAS,kBAAkB,EAAE,KAAK,GAAqB;AAC5D,SACE,6CAAC,SAAI,WAAU,qDACb;AAAA,gDAAC,SAAI,WAAU,UACb,sDAAC,6BAAU,GACb;AAAA,IACA,4CAAC,SAAI,WAAU,8BAA8B,gBAAK;AAAA,IAClD,4CAAC,SAAI,WAAU,UACb,sDAAC,6BAAU,GACb;AAAA,KACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/elements/sidebar-layout.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { useHash } from '@stackframe/stack-shared/dist/hooks/use-hash';\nimport { Button, Typography, cn } from '@stackframe/stack-ui';\nimport { XIcon } from 'lucide-react';\nimport React, { ReactNode } from 'react';\nimport { useStackApp } from '../..';\n\nexport type SidebarItem = {\n title: React.ReactNode,\n type: 'item' | 'divider',\n description?: React.ReactNode,\n id?: string,\n icon?: React.ReactNode,\n content?: React.ReactNode,\n contentTitle?: React.ReactNode,\n}\n\nexport function SidebarLayout(props: { items: SidebarItem[], title?: ReactNode, className?: string }) {\n const hash = useHash();\n const selectedIndex = props.items.findIndex(item => item.id && (item.id === hash));\n return (\n <>\n <div className={cn(\"hidden sm:flex stack-scope h-full\", props.className)}>\n <DesktopLayout items={props.items} title={props.title} selectedIndex={selectedIndex} />\n </div>\n <div className={cn(\"sm:hidden stack-scope h-full\", props.className)}>\n <MobileLayout items={props.items} title={props.title} selectedIndex={selectedIndex} />\n </div>\n </>\n );\n}\n\nfunction Items(props: { items: SidebarItem[], selectedIndex: number }) {\n const app = useStackApp();\n const navigate = app.useNavigate();\n\n\n const activeItemIndex = props.selectedIndex === -1 ? 0 : props.selectedIndex;\n\n return props.items.map((item, index) => (\n item.type === 'item' ?\n <Button\n key={index}\n variant='ghost'\n size='sm'\n className={cn(\n activeItemIndex === index && \"sm:bg-muted\",\n \"justify-start text-md text-zinc-800 dark:text-zinc-300 px-2 text-left\",\n )}\n onClick={() => {\n if (item.id) {\n navigate('#' + item.id);\n }\n }}\n >\n {item.icon}\n {item.title}\n </Button> :\n <Typography key={index}>\n {item.title}\n </Typography>\n ));\n\n}\n\nfunction DesktopLayout(props: { items: SidebarItem[], title?: ReactNode, selectedIndex: number }) {\n const selectedItem = props.items[props.selectedIndex === -1 ? 0 : props.selectedIndex];\n\n return (\n <div className=\"stack-scope flex w-full h-full max-w-full relative\">\n <div className=\"flex max-w-[200px] min-w-[200px] border-r flex-col items-stretch gap-2 p-2 overflow-y-auto\">\n {props.title && <div className='mb-2 ml-2'>\n <Typography type='h2' className=\"text-lg font-semibold text-zinc-800 dark:text-zinc-300\">{props.title}</Typography>\n </div>}\n\n <Items items={props.items} selectedIndex={props.selectedIndex} />\n </div>\n <div className=\"flex-1 w-0 flex justify-center gap-4 py-2 px-4\">\n <div className='flex flex-col max-w-[800px] w-[800px]'>\n <div className='mt-4 mb-6'>\n <Typography type='h4' className='font-semibold'>{selectedItem.title}</Typography>\n {selectedItem.description && <Typography variant='secondary' type='label'>{selectedItem.description}</Typography>}\n </div>\n <div className='flex-1'>\n {selectedItem.content}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction MobileLayout(props: { items: SidebarItem[], title?: ReactNode, selectedIndex: number }) {\n const selectedItem = props.items[props.selectedIndex];\n const app = useStackApp();\n const navigate = app.useNavigate();\n\n if (props.selectedIndex === -1) {\n return (\n <div className=\"flex flex-col gap-2 p-2\">\n {props.title && <div className='mb-2 ml-2'>\n <Typography type='h2' className=\"text-lg font-semibold text-zinc-800 dark:text-zinc-300\">{props.title}</Typography>\n </div>}\n\n <Items items={props.items} selectedIndex={props.selectedIndex} />\n </div>\n );\n } else {\n return (\n <div className=\"flex-1 flex flex-col gap-4 py-2 px-4\">\n <div className='flex flex-col'>\n <div className='flex justify-between'>\n <Typography type='h4' className='font-semibold'>{selectedItem.title}</Typography>\n <Button\n variant='ghost'\n size='icon'\n onClick={() => { navigate('#'); }}\n >\n <XIcon className='h-5 w-5' />\n </Button>\n </div>\n {selectedItem.description && <Typography variant='secondary' type='label'>{selectedItem.description}</Typography>}\n </div>\n <div className='flex-1'>\n {selectedItem.content}\n </div>\n </div>\n );\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/elements/sidebar-layout.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { useHash } from '@stackframe/stack-shared/dist/hooks/use-hash';\nimport { Button, Typography, cn } from '@stackframe/stack-ui';\nimport { XIcon } from 'lucide-react';\nimport React, { ReactNode } from 'react';\nimport { useStackApp } from '../..';\n\nexport type SidebarItem = {\n title: React.ReactNode,\n type: 'item' | 'divider',\n description?: React.ReactNode,\n id?: string,\n icon?: React.ReactNode,\n content?: React.ReactNode,\n contentTitle?: React.ReactNode,\n}\n\nexport function SidebarLayout(props: { items: SidebarItem[], title?: ReactNode, className?: string }) {\n const hash = useHash();\n const selectedIndex = props.items.findIndex(item => item.id && (item.id === hash));\n return (\n <>\n <div className={cn(\"hidden sm:flex stack-scope h-full\", props.className)}>\n <DesktopLayout items={props.items} title={props.title} selectedIndex={selectedIndex} />\n </div>\n <div className={cn(\"sm:hidden stack-scope h-full\", props.className)}>\n <MobileLayout items={props.items} title={props.title} selectedIndex={selectedIndex} />\n </div>\n </>\n );\n}\n\nfunction Items(props: { items: SidebarItem[], selectedIndex: number }) {\n const app = useStackApp();\n const navigate = app.useNavigate();\n\n\n const activeItemIndex = props.selectedIndex === -1 ? 0 : props.selectedIndex;\n\n return props.items.map((item, index) => (\n item.type === 'item' ?\n <Button\n key={index}\n variant='ghost'\n size='sm'\n className={cn(\n activeItemIndex === index && \"sm:bg-muted\",\n \"justify-start text-md text-zinc-800 dark:text-zinc-300 px-2 text-left\",\n )}\n onClick={() => {\n if (item.id) {\n navigate('#' + item.id);\n }\n }}\n >\n {item.icon}\n {item.title}\n </Button> :\n <Typography key={index}>\n {item.title}\n </Typography>\n ));\n\n}\n\nfunction DesktopLayout(props: { items: SidebarItem[], title?: ReactNode, selectedIndex: number }) {\n const selectedItem = props.items[props.selectedIndex === -1 ? 0 : props.selectedIndex];\n\n return (\n <div className=\"stack-scope flex w-full h-full max-w-full relative\">\n <div className=\"flex max-w-[200px] min-w-[200px] border-r flex-col items-stretch gap-2 p-2 overflow-y-auto\">\n {props.title && <div className='mb-2 ml-2'>\n <Typography type='h2' className=\"text-lg font-semibold text-zinc-800 dark:text-zinc-300\">{props.title}</Typography>\n </div>}\n\n <Items items={props.items} selectedIndex={props.selectedIndex} />\n </div>\n <div className=\"flex-1 w-0 flex justify-center gap-4 py-2 px-4\">\n <div className='flex flex-col max-w-[800px] w-[800px]'>\n <div className='mt-4 mb-6'>\n <Typography type='h4' className='font-semibold'>{selectedItem.title}</Typography>\n {selectedItem.description && <Typography variant='secondary' type='label'>{selectedItem.description}</Typography>}\n </div>\n <div className='flex-1'>\n {selectedItem.content}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction MobileLayout(props: { items: SidebarItem[], title?: ReactNode, selectedIndex: number }) {\n const selectedItem = props.items[props.selectedIndex];\n const app = useStackApp();\n const navigate = app.useNavigate();\n\n if (props.selectedIndex === -1) {\n return (\n <div className=\"flex flex-col gap-2 p-2\">\n {props.title && <div className='mb-2 ml-2'>\n <Typography type='h2' className=\"text-lg font-semibold text-zinc-800 dark:text-zinc-300\">{props.title}</Typography>\n </div>}\n\n <Items items={props.items} selectedIndex={props.selectedIndex} />\n </div>\n );\n } else {\n return (\n <div className=\"flex-1 flex flex-col gap-4 py-2 px-4\">\n <div className='flex flex-col'>\n <div className='flex justify-between'>\n <Typography type='h4' className='font-semibold'>{selectedItem.title}</Typography>\n <Button\n variant='ghost'\n size='icon'\n onClick={() => { navigate('#'); }}\n >\n <XIcon className='h-5 w-5' />\n </Button>\n </div>\n {selectedItem.description && <Typography variant='secondary' type='label'>{selectedItem.description}</Typography>}\n </div>\n <div className='flex-1'>\n {selectedItem.content}\n </div>\n </div>\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAAwB;AACxB,sBAAuC;AACvC,0BAAsB;AAEtB,eAA4B;AAgBxB;AAJG,SAAS,cAAc,OAAwE;AACpG,QAAM,WAAO,yBAAQ;AACrB,QAAM,gBAAgB,MAAM,MAAM,UAAU,UAAQ,KAAK,MAAO,KAAK,OAAO,IAAK;AACjF,SACE,4EACE;AAAA,gDAAC,SAAI,eAAW,oBAAG,qCAAqC,MAAM,SAAS,GACrE,sDAAC,iBAAc,OAAO,MAAM,OAAO,OAAO,MAAM,OAAO,eAA8B,GACvF;AAAA,IACA,4CAAC,SAAI,eAAW,oBAAG,gCAAgC,MAAM,SAAS,GAChE,sDAAC,gBAAa,OAAO,MAAM,OAAO,OAAO,MAAM,OAAO,eAA8B,GACtF;AAAA,KACF;AAEJ;AAEA,SAAS,MAAM,OAAwD;AACrE,QAAM,UAAM,sBAAY;AACxB,QAAM,WAAW,IAAI,YAAY;AAGjC,QAAM,kBAAkB,MAAM,kBAAkB,KAAK,IAAI,MAAM;AAE/D,SAAO,MAAM,MAAM,IAAI,CAAC,MAAM,UAC5B,KAAK,SAAS,SACZ;AAAA,IAAC;AAAA;AAAA,MAEC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,eAAW;AAAA,QACT,oBAAoB,SAAS;AAAA,QAC7B;AAAA,MACF;AAAA,MACA,SAAS,MAAM;AACb,YAAI,KAAK,IAAI;AACX,mBAAS,MAAM,KAAK,EAAE;AAAA,QACxB;AAAA,MACF;AAAA,MAEC;AAAA,aAAK;AAAA,QACL,KAAK;AAAA;AAAA;AAAA,IAdD;AAAA,EAeP,IACA,4CAAC,8BACE,eAAK,SADS,KAEjB,CACH;AAEH;AAEA,SAAS,cAAc,OAA2E;AAChG,QAAM,eAAe,MAAM,MAAM,MAAM,kBAAkB,KAAK,IAAI,MAAM,aAAa;AAErF,SACE,6CAAC,SAAI,WAAU,sDACb;AAAA,iDAAC,SAAI,WAAU,8FACZ;AAAA,YAAM,SAAS,4CAAC,SAAI,WAAU,aAC7B,sDAAC,8BAAW,MAAK,MAAK,WAAU,0DAA0D,gBAAM,OAAM,GACxG;AAAA,MAEA,4CAAC,SAAM,OAAO,MAAM,OAAO,eAAe,MAAM,eAAe;AAAA,OACjE;AAAA,IACA,4CAAC,SAAI,WAAU,kDACb,uDAAC,SAAI,WAAU,yCACb;AAAA,mDAAC,SAAI,WAAU,aACb;AAAA,oDAAC,8BAAW,MAAK,MAAK,WAAU,iBAAiB,uBAAa,OAAM;AAAA,QACnE,aAAa,eAAe,4CAAC,8BAAW,SAAQ,aAAY,MAAK,SAAS,uBAAa,aAAY;AAAA,SACtG;AAAA,MACA,4CAAC,SAAI,WAAU,UACZ,uBAAa,SAChB;AAAA,OACF,GACF;AAAA,KACF;AAEJ;AAEA,SAAS,aAAa,OAA2E;AAC/F,QAAM,eAAe,MAAM,MAAM,MAAM,aAAa;AACpD,QAAM,UAAM,sBAAY;AACxB,QAAM,WAAW,IAAI,YAAY;AAEjC,MAAI,MAAM,kBAAkB,IAAI;AAC9B,WACE,6CAAC,SAAI,WAAU,2BACZ;AAAA,YAAM,SAAS,4CAAC,SAAI,WAAU,aAC7B,sDAAC,8BAAW,MAAK,MAAK,WAAU,0DAA0D,gBAAM,OAAM,GACxG;AAAA,MAEA,4CAAC,SAAM,OAAO,MAAM,OAAO,eAAe,MAAM,eAAe;AAAA,OACjE;AAAA,EAEJ,OAAO;AACL,WACE,6CAAC,SAAI,WAAU,wCACb;AAAA,mDAAC,SAAI,WAAU,iBACb;AAAA,qDAAC,SAAI,WAAU,wBACb;AAAA,sDAAC,8BAAW,MAAK,MAAK,WAAU,iBAAiB,uBAAa,OAAM;AAAA,UACpE;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AAAE,yBAAS,GAAG;AAAA,cAAG;AAAA,cAEhC,sDAAC,6BAAM,WAAU,WAAU;AAAA;AAAA,UAC7B;AAAA,WACF;AAAA,QACC,aAAa,eAAe,4CAAC,8BAAW,SAAQ,aAAY,MAAK,SAAS,uBAAa,aAAY;AAAA,SACtG;AAAA,MACA,4CAAC,SAAI,WAAU,UACZ,uBAAa,SAChB;AAAA,OACF;AAAA,EAEJ;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/elements/ssr-layout-effect.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { useLayoutEffect } from \"react\";\n\nexport function SsrScript(props: { script: string, nonce?: string }) {\n useLayoutEffect(() => {\n // TODO fix workaround: React has a bug where it doesn't run the script on the first CSR render if SSR has been skipped due to suspense\n // As a workaround, we run the script in the <script> tag again after the first render\n // Note that we do an indirect eval as described here: https://esbuild.github.io/content-types/#direct-eval\n (0, eval)(props.script);\n }, []);\n\n return (\n <script\n suppressHydrationWarning // the transpiler is setup differently for client/server targets, so if `script` was generated with Function.toString they will differ\n nonce={props.nonce}\n dangerouslySetInnerHTML={{ __html: props.script }}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,mBAAgC;AAW5B;AATG,SAAS,UAAU,OAA2C;AACnE,oCAAgB,MAAM;AAIpB,KAAC,GAAG,MAAM,MAAM,MAAM;AAAA,EACxB,GAAG,CAAC,CAAC;AAEL,SACE;AAAA,IAAC;AAAA;AAAA,MACC,0BAAwB;AAAA,MACxB,OAAO,MAAM;AAAA,MACb,yBAAyB,EAAE,QAAQ,MAAM,OAAO;AAAA;AAAA,EAClD;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/elements/ssr-layout-effect.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { useLayoutEffect } from \"react\";\n\nexport function SsrScript(props: { script: string, nonce?: string }) {\n useLayoutEffect(() => {\n // TODO fix workaround: React has a bug where it doesn't run the script on the first CSR render if SSR has been skipped due to suspense\n // As a workaround, we run the script in the <script> tag again after the first render\n // Note that we do an indirect eval as described here: https://esbuild.github.io/content-types/#direct-eval\n (0, eval)(props.script);\n }, []);\n\n return (\n <script\n suppressHydrationWarning // the transpiler is setup differently for client/server targets, so if `script` was generated with Function.toString they will differ\n nonce={props.nonce}\n dangerouslySetInnerHTML={{ __html: props.script }}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,mBAAgC;AAW5B;AATG,SAAS,UAAU,OAA2C;AACnE,oCAAgB,MAAM;AAIpB,KAAC,GAAG,MAAM,MAAM,MAAM;AAAA,EACxB,GAAG,CAAC,CAAC;AAEL,SACE;AAAA,IAAC;AAAA;AAAA,MACC,0BAAwB;AAAA,MACxB,OAAO,MAAM;AAAA,MACb,yBAAyB,EAAE,QAAQ,MAAM,OAAO;AAAA;AAAA,EAClD;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/elements/user-avatar.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { Avatar, AvatarFallback, AvatarImage } from \"@stackframe/stack-ui\";\nimport { UserRound } from \"lucide-react\";\n\nconst defaultSize = 34;\n\nexport function UserAvatar(props: {\n size?: number,\n user?: {\n profileImageUrl?: string | null,\n displayName?: string | null,\n primaryEmail?: string | null,\n } | null,\n border?: boolean,\n}) {\n const user = props.user;\n return (\n <Avatar style={{ height: props.size || defaultSize, width: props.size || defaultSize }} className={props.border ? 'border' : ''}>\n <AvatarImage src={user?.profileImageUrl || ''} />\n <AvatarFallback>\n {user ?\n <div className='font-medium' style={{ fontSize: (props.size || defaultSize) * 0.4 }}>\n {(user.displayName || user.primaryEmail)?.slice(0, 2).toUpperCase()}\n </div> :\n <UserRound className=\"text-zinc-500\" size={(props.size || defaultSize) * 0.6} />}\n </AvatarFallback>\n </Avatar>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,sBAAoD;AACpD,0BAA0B;AAetB;AAbJ,IAAM,cAAc;AAEb,SAAS,WAAW,OAQxB;AACD,QAAM,OAAO,MAAM;AACnB,SACE,6CAAC,0BAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,aAAa,OAAO,MAAM,QAAQ,YAAY,GAAG,WAAW,MAAM,SAAS,WAAW,IAC3H;AAAA,gDAAC,+BAAY,KAAK,MAAM,mBAAmB,IAAI;AAAA,IAC/C,4CAAC,kCACE,iBACC,4CAAC,SAAI,WAAU,eAAc,OAAO,EAAE,WAAW,MAAM,QAAQ,eAAe,IAAI,GAC9E,gBAAK,eAAe,KAAK,eAAe,MAAM,GAAG,CAAC,EAAE,YAAY,GACpE,IACA,4CAAC,iCAAU,WAAU,iBAAgB,OAAO,MAAM,QAAQ,eAAe,KAAK,GAClF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/elements/user-avatar.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { Avatar, AvatarFallback, AvatarImage } from \"@stackframe/stack-ui\";\nimport { UserRound } from \"lucide-react\";\n\nconst defaultSize = 34;\n\nexport function UserAvatar(props: {\n size?: number,\n user?: {\n profileImageUrl?: string | null,\n displayName?: string | null,\n primaryEmail?: string | null,\n } | null,\n border?: boolean,\n}) {\n const user = props.user;\n return (\n <Avatar style={{ height: props.size || defaultSize, width: props.size || defaultSize }} className={props.border ? 'border' : ''}>\n <AvatarImage src={user?.profileImageUrl || ''} />\n <AvatarFallback>\n {user ?\n <div className='font-medium' style={{ fontSize: (props.size || defaultSize) * 0.4 }}>\n {(user.displayName || user.primaryEmail)?.slice(0, 2).toUpperCase()}\n </div> :\n <UserRound className=\"text-zinc-500\" size={(props.size || defaultSize) * 0.6} />}\n </AvatarFallback>\n </Avatar>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,sBAAoD;AACpD,0BAA0B;AAetB;AAbJ,IAAM,cAAc;AAEb,SAAS,WAAW,OAQxB;AACD,QAAM,OAAO,MAAM;AACnB,SACE,6CAAC,0BAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,aAAa,OAAO,MAAM,QAAQ,YAAY,GAAG,WAAW,MAAM,SAAS,WAAW,IAC3H;AAAA,gDAAC,+BAAY,KAAK,MAAM,mBAAmB,IAAI;AAAA,IAC/C,4CAAC,kCACE,iBACC,4CAAC,SAAI,WAAU,eAAc,OAAO,EAAE,WAAW,MAAM,QAAQ,eAAe,IAAI,GAC9E,gBAAK,eAAe,KAAK,eAAe,MAAM,GAAG,CAAC,EAAE,YAAY,GACpE,IACA,4CAAC,iCAAU,WAAU,iBAAgB,OAAO,MAAM,QAAQ,eAAe,KAAK,GAClF;AAAA,KACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/link.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { cn } from \"@stackframe/stack-ui\";\nimport NextLink from 'next/link'; // THIS_LINE_PLATFORM next\n\ntype LinkProps = {\n href: string,\n children: React.ReactNode,\n className?: string,\n target?: string,\n onClick?: React.MouseEventHandler<HTMLAnchorElement>,\n prefetch?: boolean,\n};\n\nfunction Link(props: LinkProps) {\n return <NextLink\n href={props.href}\n target={props.target}\n className={props.className}\n prefetch={props.prefetch}\n onClick={props.onClick}\n >\n {props.children}\n </NextLink>;\n}\n\nfunction StyledLink(props: LinkProps) {\n return (\n <Link {...props} className={cn(\"underline font-medium\", props.className)}>\n {props.children}\n </Link>\n );\n}\n\nexport { Link, StyledLink };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAAmB;AACnB,kBAAqB;AAYZ;AADT,SAAS,KAAK,OAAkB;AAC9B,SAAO;AAAA,IAAC,YAAAA;AAAA,IAAA;AAAA,MACN,MAAM,MAAM;AAAA,MACZ,QAAQ,MAAM;AAAA,MACd,WAAW,MAAM;AAAA,MACjB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM;AAAA,MAEd,gBAAM;AAAA;AAAA,EACT;AACF;AAEA,SAAS,WAAW,OAAkB;AACpC,SACE,4CAAC,QAAM,GAAG,OAAO,eAAW,oBAAG,yBAAyB,MAAM,SAAS,GACpE,gBAAM,UACT;AAEJ;","names":["NextLink"]}
1
+ {"version":3,"sources":["../../src/components/link.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { cn } from \"@stackframe/stack-ui\";\nimport NextLink from 'next/link'; // THIS_LINE_PLATFORM next\n\ntype LinkProps = {\n href: string,\n children: React.ReactNode,\n className?: string,\n target?: string,\n onClick?: React.MouseEventHandler<HTMLAnchorElement>,\n prefetch?: boolean,\n};\n\nfunction Link(props: LinkProps) {\n return <NextLink\n href={props.href}\n target={props.target}\n className={props.className}\n prefetch={props.prefetch}\n onClick={props.onClick}\n >\n {props.children}\n </NextLink>;\n}\n\nfunction StyledLink(props: LinkProps) {\n return (\n <Link {...props} className={cn(\"underline font-medium\", props.className)}>\n {props.children}\n </Link>\n );\n}\n\nexport { Link, StyledLink };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAAmB;AACnB,kBAAqB;AAYZ;AADT,SAAS,KAAK,OAAkB;AAC9B,SAAO;AAAA,IAAC,YAAAA;AAAA,IAAA;AAAA,MACN,MAAM,MAAM;AAAA,MACZ,QAAQ,MAAM;AAAA,MACd,WAAW,MAAM;AAAA,MACjB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM;AAAA,MAEd,gBAAM;AAAA;AAAA,EACT;AACF;AAEA,SAAS,WAAW,OAAkB;AACpC,SACE,4CAAC,QAAM,GAAG,OAAO,eAAW,oBAAG,yBAAyB,MAAM,SAAS,GACpE,gBAAM,UACT;AAEJ;","names":["NextLink"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/magic-link-sign-in.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { KnownErrors } from \"@stackframe/stack-shared\";\nimport { strictEmailSchema, yupObject } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, InputOTP, InputOTPGroup, InputOTPSlot, Label, Typography } from \"@stackframe/stack-ui\";\nimport { useEffect, useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp } from \"..\";\nimport { useTranslation } from \"../lib/translations\";\nimport { FormWarningText } from \"./elements/form-warning\";\n\nfunction OTP(props: {\n onBack: () => void,\n nonce: string,\n}) {\n const { t } = useTranslation();\n const [otp, setOtp] = useState<string>('');\n const [submitting, setSubmitting] = useState<boolean>(false);\n const stackApp = useStackApp();\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (otp.length === 6 && !submitting) {\n setSubmitting(true);\n // eslint-disable-next-line no-restricted-syntax\n stackApp.signInWithMagicLink(otp + props.nonce)\n .then(result => {\n if (result.status === 'error') {\n if (KnownErrors.VerificationCodeError.isInstance(result.error)) {\n setError(t(\"Invalid code\"));\n } else if (KnownErrors.InvalidTotpCode.isInstance(result.error)) {\n setError(t(\"Invalid TOTP code\"));\n } else {\n throw result.error;\n }\n }\n })\n .catch(e => console.error(e))\n .finally(() => {\n setSubmitting(false);\n setOtp('');\n });\n }\n if (otp.length !== 0 && otp.length !== 6) {\n setError(null);\n }\n }, [otp, submitting]);\n\n return (\n <div className=\"flex flex-col items-stretch stack-scope\">\n <form className='w-full flex flex-col items-center mb-2'>\n <Typography className='mb-2' >{t('Enter the code from your email')}</Typography>\n <InputOTP\n maxLength={6}\n type=\"text\"\n inputMode=\"text\"\n pattern={\"^[a-zA-Z0-9]+$\"}\n value={otp}\n onChange={value => setOtp(value.toUpperCase())}\n disabled={submitting}\n >\n <InputOTPGroup>\n {[0, 1, 2, 3, 4, 5].map((index) => (\n <InputOTPSlot key={index} index={index} size='lg' />\n ))}\n </InputOTPGroup>\n </InputOTP>\n {error && <FormWarningText text={error} />}\n </form>\n <Button variant='link' onClick={props.onBack} className='underline'>{t('Cancel')}</Button>\n </div>\n );\n}\n\nexport function MagicLinkSignIn() {\n const { t } = useTranslation();\n const app = useStackApp();\n const [loading, setLoading] = useState(false);\n const [nonce, setNonce] = useState<string | null>(null);\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, setError, formState: { errors } } = useForm({\n resolver: yupResolver(schema)\n });\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { email } = data;\n const result = await app.sendMagicLinkEmail(email);\n if (result.status === 'error') {\n setError('email', { type: 'manual', message: result.error.message });\n return;\n } else {\n setNonce(result.data.nonce);\n }\n } catch (e) {\n if (KnownErrors.SignUpNotEnabled.isInstance(e)) {\n setError('email', { type: 'manual', message: t('New account registration is not allowed') });\n } else {\n throw e;\n }\n } finally {\n setLoading(false);\n }\n };\n\n if (nonce) {\n return <OTP nonce={nonce} onBack={() => setNonce(null)} />;\n } else {\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('Email')}</Label>\n <Input\n id=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n {...register('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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/magic-link-sign-in.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { KnownErrors } from \"@stackframe/stack-shared\";\nimport { strictEmailSchema, yupObject } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, InputOTP, InputOTPGroup, InputOTPSlot, Label, Typography } from \"@stackframe/stack-ui\";\nimport { useEffect, useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp } from \"..\";\nimport { useTranslation } from \"../lib/translations\";\nimport { FormWarningText } from \"./elements/form-warning\";\n\nfunction OTP(props: {\n onBack: () => void,\n nonce: string,\n}) {\n const { t } = useTranslation();\n const [otp, setOtp] = useState<string>('');\n const [submitting, setSubmitting] = useState<boolean>(false);\n const stackApp = useStackApp();\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (otp.length === 6 && !submitting) {\n setSubmitting(true);\n // eslint-disable-next-line no-restricted-syntax\n stackApp.signInWithMagicLink(otp + props.nonce)\n .then(result => {\n if (result.status === 'error') {\n if (KnownErrors.VerificationCodeError.isInstance(result.error)) {\n setError(t(\"Invalid code\"));\n } else if (KnownErrors.InvalidTotpCode.isInstance(result.error)) {\n setError(t(\"Invalid TOTP code\"));\n } else {\n throw result.error;\n }\n }\n })\n .catch(e => console.error(e))\n .finally(() => {\n setSubmitting(false);\n setOtp('');\n });\n }\n if (otp.length !== 0 && otp.length !== 6) {\n setError(null);\n }\n }, [otp, submitting]);\n\n return (\n <div className=\"flex flex-col items-stretch stack-scope\">\n <form className='w-full flex flex-col items-center mb-2'>\n <Typography className='mb-2' >{t('Enter the code from your email')}</Typography>\n <InputOTP\n maxLength={6}\n type=\"text\"\n inputMode=\"text\"\n pattern={\"^[a-zA-Z0-9]+$\"}\n value={otp}\n onChange={value => setOtp(value.toUpperCase())}\n disabled={submitting}\n >\n <InputOTPGroup>\n {[0, 1, 2, 3, 4, 5].map((index) => (\n <InputOTPSlot key={index} index={index} size='lg' />\n ))}\n </InputOTPGroup>\n </InputOTP>\n {error && <FormWarningText text={error} />}\n </form>\n <Button variant='link' onClick={props.onBack} className='underline'>{t('Cancel')}</Button>\n </div>\n );\n}\n\nexport function MagicLinkSignIn() {\n const { t } = useTranslation();\n const app = useStackApp();\n const [loading, setLoading] = useState(false);\n const [nonce, setNonce] = useState<string | null>(null);\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, setError, formState: { errors } } = useForm({\n resolver: yupResolver(schema)\n });\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { email } = data;\n const result = await app.sendMagicLinkEmail(email);\n if (result.status === 'error') {\n setError('email', { type: 'manual', message: result.error.message });\n return;\n } else {\n setNonce(result.data.nonce);\n }\n } catch (e) {\n if (KnownErrors.SignUpNotEnabled.isInstance(e)) {\n setError('email', { type: 'manual', message: t('New account registration is not allowed') });\n } else {\n throw e;\n }\n } finally {\n setLoading(false);\n }\n };\n\n if (nonce) {\n return <OTP nonce={nonce} onBack={() => setNonce(null)} />;\n } else {\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('Email')}</Label>\n <Input\n id=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n {...register('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"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/message-cards/known-error-message-card.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { KnownError } from \"@stackframe/stack-shared\";\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp } from \"../..\";\nimport { MessageCard } from \"./message-card\";\n\nexport function KnownErrorMessageCard({\n error,\n fullPage=false,\n}: {\n error: KnownError,\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n\n return (\n <MessageCard\n title={\"An error occurred\"}\n fullPage={fullPage}\n primaryButtonText={\"Go Home\"}\n primaryAction={() => stackApp.redirectToHome()}\n >\n {<Typography>Error Code: {error.errorCode}</Typography>}\n {<Typography>Error Message: {error.message}</Typography>}\n </MessageCard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,sBAA2B;AAC3B,eAA4B;AAC5B,0BAA4B;AAkBrB;AAhBA,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,WAAS;AACX,GAGG;AACD,QAAM,eAAW,sBAAY;AAE7B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP;AAAA,MACA,mBAAmB;AAAA,MACnB,eAAe,MAAM,SAAS,eAAe;AAAA,MAE5C;AAAA,qDAAC,8BAAW;AAAA;AAAA,UAAa,MAAM;AAAA,WAAU;AAAA,QACzC,6CAAC,8BAAW;AAAA;AAAA,UAAgB,MAAM;AAAA,WAAQ;AAAA;AAAA;AAAA,EAC7C;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/message-cards/known-error-message-card.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { KnownError } from \"@stackframe/stack-shared\";\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp } from \"../..\";\nimport { MessageCard } from \"./message-card\";\n\nexport function KnownErrorMessageCard({\n error,\n fullPage=false,\n}: {\n error: KnownError,\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n\n return (\n <MessageCard\n title={\"An error occurred\"}\n fullPage={fullPage}\n primaryButtonText={\"Go Home\"}\n primaryAction={() => stackApp.redirectToHome()}\n >\n {<Typography>Error Code: {error.errorCode}</Typography>}\n {<Typography>Error Message: {error.message}</Typography>}\n </MessageCard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,sBAA2B;AAC3B,eAA4B;AAC5B,0BAA4B;AAkBrB;AAhBA,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,WAAS;AACX,GAGG;AACD,QAAM,eAAW,sBAAY;AAE7B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP;AAAA,MACA,mBAAmB;AAAA,MACnB,eAAe,MAAM,SAAS,eAAe;AAAA,MAE5C;AAAA,qDAAC,8BAAW;AAAA;AAAA,UAAa,MAAM;AAAA,WAAU;AAAA,QACzC,6CAAC,8BAAW;AAAA;AAAA,UAAgB,MAAM;AAAA,WAAQ;AAAA;AAAA;AAAA,EAC7C;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/message-cards/message-card.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport React from \"react\";\nimport { MaybeFullPage } from \"../elements/maybe-full-page\";\nimport { Button, Typography } from \"@stackframe/stack-ui\";\n\nexport function MessageCard(\n { fullPage=false, ...props }:\n {\n children?: React.ReactNode,\n title: string,\n fullPage?: boolean,\n primaryButtonText?: string,\n primaryAction?: () => Promise<void> | void,\n secondaryButtonText?: string,\n secondaryAction?: () => Promise<void> | void,\n }\n) {\n return (\n <MaybeFullPage fullPage={fullPage}>\n <div className=\"text-center stack-scope flex flex-col gap-4\" style={{ maxWidth: '380px', flexBasis: '380px', padding: fullPage ? '1rem' : 0 }}>\n <Typography type='h3'>{props.title}</Typography>\n {props.children}\n {(props.primaryButtonText || props.secondaryButtonText) && (\n <div className=\"flex justify-center gap-4 my-5\">\n {props.secondaryButtonText && (\n <Button variant=\"secondary\" onClick={props.secondaryAction}>\n {props.secondaryButtonText}\n </Button>\n )}\n {props.primaryButtonText && (\n <Button onClick={props.primaryAction}>\n {props.primaryButtonText}\n </Button>\n )}\n </div>\n )}\n </div>\n </MaybeFullPage>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,6BAA8B;AAC9B,sBAAmC;AAiB3B;AAfD,SAAS,YACd,EAAE,WAAS,OAAO,GAAG,MAAM,GAU3B;AACA,SACE,4CAAC,wCAAc,UACb,uDAAC,SAAI,WAAU,+CAA8C,OAAO,EAAE,UAAU,SAAS,WAAW,SAAS,SAAS,WAAW,SAAS,EAAE,GAC1I;AAAA,gDAAC,8BAAW,MAAK,MAAM,gBAAM,OAAM;AAAA,IAClC,MAAM;AAAA,KACL,MAAM,qBAAqB,MAAM,wBACjC,6CAAC,SAAI,WAAU,kCACZ;AAAA,YAAM,uBACL,4CAAC,0BAAO,SAAQ,aAAY,SAAS,MAAM,iBACxC,gBAAM,qBACT;AAAA,MAED,MAAM,qBACL,4CAAC,0BAAO,SAAS,MAAM,eACpB,gBAAM,mBACT;AAAA,OAEJ;AAAA,KAEJ,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/message-cards/message-card.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport React from \"react\";\nimport { MaybeFullPage } from \"../elements/maybe-full-page\";\nimport { Button, Typography } from \"@stackframe/stack-ui\";\n\nexport function MessageCard(\n { fullPage=false, ...props }:\n {\n children?: React.ReactNode,\n title: string,\n fullPage?: boolean,\n primaryButtonText?: string,\n primaryAction?: () => Promise<void> | void,\n secondaryButtonText?: string,\n secondaryAction?: () => Promise<void> | void,\n }\n) {\n return (\n <MaybeFullPage fullPage={fullPage}>\n <div className=\"text-center stack-scope flex flex-col gap-4\" style={{ maxWidth: '380px', flexBasis: '380px', padding: fullPage ? '1rem' : 0 }}>\n <Typography type='h3'>{props.title}</Typography>\n {props.children}\n {(props.primaryButtonText || props.secondaryButtonText) && (\n <div className=\"flex justify-center gap-4 my-5\">\n {props.secondaryButtonText && (\n <Button variant=\"secondary\" onClick={props.secondaryAction}>\n {props.secondaryButtonText}\n </Button>\n )}\n {props.primaryButtonText && (\n <Button onClick={props.primaryAction}>\n {props.primaryButtonText}\n </Button>\n )}\n </div>\n )}\n </div>\n </MaybeFullPage>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,6BAA8B;AAC9B,sBAAmC;AAiB3B;AAfD,SAAS,YACd,EAAE,WAAS,OAAO,GAAG,MAAM,GAU3B;AACA,SACE,4CAAC,wCAAc,UACb,uDAAC,SAAI,WAAU,+CAA8C,OAAO,EAAE,UAAU,SAAS,WAAW,SAAS,SAAS,WAAW,SAAS,EAAE,GAC1I;AAAA,gDAAC,8BAAW,MAAK,MAAM,gBAAM,OAAM;AAAA,IAClC,MAAM;AAAA,KACL,MAAM,qBAAqB,MAAM,wBACjC,6CAAC,SAAI,WAAU,kCACZ;AAAA,YAAM,uBACL,4CAAC,0BAAO,SAAQ,aAAY,SAAS,MAAM,iBACxC,gBAAM,qBACT;AAAA,MAED,MAAM,qBACL,4CAAC,0BAAO,SAAS,MAAM,eACpB,gBAAM,mBACT;AAAA,OAEJ;AAAA,KAEJ,GACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/message-cards/predefined-message-card.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp } from \"../..\";\nimport { useTranslation } from \"../../lib/translations\";\nimport { MessageCard } from \"./message-card\";\n\nexport function PredefinedMessageCard({\n type,\n fullPage=false,\n}: {\n type: 'signedIn' | 'signedOut' | 'emailSent' | 'passwordReset' | 'unknownError' | 'signUpDisabled',\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n const { t } = useTranslation();\n\n let title: string;\n let message: string | null = null;\n let primaryButton: string | null = null;\n let secondaryButton: string | null = null;\n let primaryAction: (() => Promise<void> | void) | null = null;\n let secondaryAction: (() => Promise<void> | void) | null = null;\n\n switch (type) {\n case 'signedIn': {\n title = t(\"You are already signed in\");\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignOut();\n primaryButton = t(\"Go home\");\n secondaryButton = t(\"Sign out\");\n break;\n }\n case 'signedOut': {\n title = t(\"You are not currently signed in.\");\n primaryAction = () => stackApp.redirectToSignIn();\n primaryButton = t(\"Sign in\");\n break;\n }\n case 'signUpDisabled': {\n title = t(\"Sign up for new users is not enabled at the moment.\");\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignIn();\n primaryButton = t(\"Go home\");\n secondaryButton = t(\"Sign in\");\n break;\n }\n case 'emailSent': {\n title = t(\"Email sent!\");\n message = t(\"If the user with this e-mail address exists, an e-mail was sent to your inbox. Make sure to check your spam folder.\");\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = t(\"Go home\");\n break;\n }\n case 'passwordReset': {\n title = t(\"Password reset successfully!\");\n message = t(\"Your password has been reset. You can now sign in with your new password.\");\n primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true });\n primaryButton = t(\"Sign in\");\n break;\n }\n case 'unknownError': {\n title = t(\"An unknown error occurred\");\n message = t(\"Please try again and if the problem persists, contact support.\");\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = t(\"Go home\");\n break;\n }\n }\n\n return (\n <MessageCard\n title={title}\n fullPage={fullPage}\n primaryButtonText={primaryButton}\n primaryAction={primaryAction}\n secondaryButtonText={secondaryButton || undefined}\n secondaryAction={secondaryAction || undefined}\n >\n {message && <Typography>{message}</Typography>}\n </MessageCard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAA2B;AAC3B,eAA4B;AAC5B,0BAA+B;AAC/B,0BAA4B;AA0EV;AAxEX,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,WAAS;AACX,GAGG;AACD,QAAM,eAAW,sBAAY;AAC7B,QAAM,EAAE,EAAE,QAAI,oCAAe;AAE7B,MAAI;AACJ,MAAI,UAAyB;AAC7B,MAAI,gBAA+B;AACnC,MAAI,kBAAiC;AACrC,MAAI,gBAAqD;AACzD,MAAI,kBAAuD;AAE3D,UAAQ,MAAM;AAAA,IACZ,KAAK,YAAY;AACf,cAAQ,EAAE,2BAA2B;AACrC,sBAAgB,MAAM,SAAS,eAAe;AAC9C,wBAAkB,MAAM,SAAS,kBAAkB;AACnD,sBAAgB,EAAE,SAAS;AAC3B,wBAAkB,EAAE,UAAU;AAC9B;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,cAAQ,EAAE,kCAAkC;AAC5C,sBAAgB,MAAM,SAAS,iBAAiB;AAChD,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,kBAAkB;AACrB,cAAQ,EAAE,qDAAqD;AAC/D,sBAAgB,MAAM,SAAS,eAAe;AAC9C,wBAAkB,MAAM,SAAS,iBAAiB;AAClD,sBAAgB,EAAE,SAAS;AAC3B,wBAAkB,EAAE,SAAS;AAC7B;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,cAAQ,EAAE,aAAa;AACvB,gBAAU,EAAE,qHAAqH;AACjI,sBAAgB,MAAM,SAAS,eAAe;AAC9C,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,iBAAiB;AACpB,cAAQ,EAAE,8BAA8B;AACxC,gBAAU,EAAE,2EAA2E;AACvF,sBAAgB,MAAM,SAAS,iBAAiB,EAAE,gBAAgB,KAAK,CAAC;AACxE,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,gBAAgB;AACnB,cAAQ,EAAE,2BAA2B;AACrC,gBAAU,EAAE,gEAAgE;AAC5E,sBAAgB,MAAM,SAAS,eAAe;AAC9C,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB;AAAA,MACA,qBAAqB,mBAAmB;AAAA,MACxC,iBAAiB,mBAAmB;AAAA,MAEnC,qBAAW,4CAAC,8BAAY,mBAAQ;AAAA;AAAA,EACnC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/message-cards/predefined-message-card.tsx"],"sourcesContent":["\"use client\";\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp } from \"../..\";\nimport { useTranslation } from \"../../lib/translations\";\nimport { MessageCard } from \"./message-card\";\n\nexport function PredefinedMessageCard({\n type,\n fullPage=false,\n}: {\n type: 'signedIn' | 'signedOut' | 'emailSent' | 'passwordReset' | 'unknownError' | 'signUpDisabled',\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n const { t } = useTranslation();\n\n let title: string;\n let message: string | null = null;\n let primaryButton: string | null = null;\n let secondaryButton: string | null = null;\n let primaryAction: (() => Promise<void> | void) | null = null;\n let secondaryAction: (() => Promise<void> | void) | null = null;\n\n switch (type) {\n case 'signedIn': {\n title = t(\"You are already signed in\");\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignOut();\n primaryButton = t(\"Go home\");\n secondaryButton = t(\"Sign out\");\n break;\n }\n case 'signedOut': {\n title = t(\"You are not currently signed in.\");\n primaryAction = () => stackApp.redirectToSignIn();\n primaryButton = t(\"Sign in\");\n break;\n }\n case 'signUpDisabled': {\n title = t(\"Sign up for new users is not enabled at the moment.\");\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignIn();\n primaryButton = t(\"Go home\");\n secondaryButton = t(\"Sign in\");\n break;\n }\n case 'emailSent': {\n title = t(\"Email sent!\");\n message = t(\"If the user with this e-mail address exists, an e-mail was sent to your inbox. Make sure to check your spam folder.\");\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = t(\"Go home\");\n break;\n }\n case 'passwordReset': {\n title = t(\"Password reset successfully!\");\n message = t(\"Your password has been reset. You can now sign in with your new password.\");\n primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true });\n primaryButton = t(\"Sign in\");\n break;\n }\n case 'unknownError': {\n title = t(\"An unknown error occurred\");\n message = t(\"Please try again and if the problem persists, contact support.\");\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = t(\"Go home\");\n break;\n }\n }\n\n return (\n <MessageCard\n title={title}\n fullPage={fullPage}\n primaryButtonText={primaryButton}\n primaryAction={primaryAction}\n secondaryButtonText={secondaryButton || undefined}\n secondaryAction={secondaryAction || undefined}\n >\n {message && <Typography>{message}</Typography>}\n </MessageCard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAA2B;AAC3B,eAA4B;AAC5B,0BAA+B;AAC/B,0BAA4B;AA0EV;AAxEX,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,WAAS;AACX,GAGG;AACD,QAAM,eAAW,sBAAY;AAC7B,QAAM,EAAE,EAAE,QAAI,oCAAe;AAE7B,MAAI;AACJ,MAAI,UAAyB;AAC7B,MAAI,gBAA+B;AACnC,MAAI,kBAAiC;AACrC,MAAI,gBAAqD;AACzD,MAAI,kBAAuD;AAE3D,UAAQ,MAAM;AAAA,IACZ,KAAK,YAAY;AACf,cAAQ,EAAE,2BAA2B;AACrC,sBAAgB,MAAM,SAAS,eAAe;AAC9C,wBAAkB,MAAM,SAAS,kBAAkB;AACnD,sBAAgB,EAAE,SAAS;AAC3B,wBAAkB,EAAE,UAAU;AAC9B;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,cAAQ,EAAE,kCAAkC;AAC5C,sBAAgB,MAAM,SAAS,iBAAiB;AAChD,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,kBAAkB;AACrB,cAAQ,EAAE,qDAAqD;AAC/D,sBAAgB,MAAM,SAAS,eAAe;AAC9C,wBAAkB,MAAM,SAAS,iBAAiB;AAClD,sBAAgB,EAAE,SAAS;AAC3B,wBAAkB,EAAE,SAAS;AAC7B;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,cAAQ,EAAE,aAAa;AACvB,gBAAU,EAAE,qHAAqH;AACjI,sBAAgB,MAAM,SAAS,eAAe;AAC9C,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,iBAAiB;AACpB,cAAQ,EAAE,8BAA8B;AACxC,gBAAU,EAAE,2EAA2E;AACvF,sBAAgB,MAAM,SAAS,iBAAiB,EAAE,gBAAgB,KAAK,CAAC;AACxE,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,gBAAgB;AACnB,cAAQ,EAAE,2BAA2B;AACrC,gBAAU,EAAE,gEAAgE;AAC5E,sBAAgB,MAAM,SAAS,eAAe;AAC9C,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB;AAAA,MACA,qBAAqB,mBAAmB;AAAA,MACxC,iBAAiB,mBAAmB;AAAA,MAEnC,qBAAW,4CAAC,8BAAY,mBAAQ;AAAA;AAAA,EACnC;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/oauth-button-group.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { useStackApp } from \"../lib/hooks\";\nimport { OAuthButton } from \"./oauth-button\";\n\nexport function OAuthButtonGroup({\n type,\n mockProject,\n}: {\n type: 'sign-in' | 'sign-up',\n mockProject?: {\n config: {\n oauthProviders: {\n id: string,\n }[],\n },\n },\n}) {\n const stackApp = useStackApp();\n const project = mockProject || stackApp.useProject();\n return (\n <div className='gap-4 flex flex-col items-stretch stack-scope'>\n {project.config.oauthProviders.map(p => (\n <OAuthButton key={p.id} provider={p.id} type={type}\n isMock={!!mockProject}\n />\n ))}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,mBAA4B;AAC5B,0BAA4B;AAoBpB;AAlBD,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AACF,GASG;AACD,QAAM,eAAW,0BAAY;AAC7B,QAAM,UAAU,eAAe,SAAS,WAAW;AACnD,SACE,4CAAC,SAAI,WAAU,iDACZ,kBAAQ,OAAO,eAAe,IAAI,OACjC;AAAA,IAAC;AAAA;AAAA,MAAuB,UAAU,EAAE;AAAA,MAAI;AAAA,MACtC,QAAQ,CAAC,CAAC;AAAA;AAAA,IADM,EAAE;AAAA,EAEpB,CACD,GACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/oauth-button-group.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { useStackApp } from \"../lib/hooks\";\nimport { OAuthButton } from \"./oauth-button\";\n\nexport function OAuthButtonGroup({\n type,\n mockProject,\n}: {\n type: 'sign-in' | 'sign-up',\n mockProject?: {\n config: {\n oauthProviders: {\n id: string,\n }[],\n },\n },\n}) {\n const stackApp = useStackApp();\n const project = mockProject || stackApp.useProject();\n return (\n <div className='gap-4 flex flex-col items-stretch stack-scope'>\n {project.config.oauthProviders.map(p => (\n <OAuthButton key={p.id} provider={p.id} type={type}\n isMock={!!mockProject}\n />\n ))}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,mBAA4B;AAC5B,0BAA4B;AAoBpB;AAlBD,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AACF,GASG;AACD,QAAM,eAAW,0BAAY;AAC7B,QAAM,UAAU,eAAe,SAAS,WAAW;AACnD,SACE,4CAAC,SAAI,WAAU,iDACZ,kBAAQ,OAAO,eAAe,IAAI,OACjC;AAAA,IAAC;AAAA;AAAA,MAAuB,UAAU,EAAE;AAAA,MAAI;AAAA,MACtC,QAAQ,CAAC,CAAC;AAAA;AAAA,IADM,EAAE;AAAA,EAEpB,CACD,GACH;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/oauth-button.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { BrandIcons, Button, SimpleTooltip } from '@stackframe/stack-ui';\nimport Color from 'color';\nimport { useEffect, useId, useState } from 'react';\nimport { useStackApp } from '..';\nimport { useTranslation } from '../lib/translations';\nimport { useInIframe } from './use-in-iframe';\n\nconst iconSize = 22;\n\nconst changeColor = (c: Color, value: number) => {\n if (c.isLight()) {\n value = -value;\n }\n return c.hsl(c.hue(), c.saturationl(), c.lightness() + value).toString();\n};\n\nexport function OAuthButton({\n provider,\n type,\n isMock = false,\n}: {\n provider: string,\n type: 'sign-in' | 'sign-up',\n isMock?: boolean,\n}) {\n const { t } = useTranslation();\n const stackApp = useStackApp();\n const styleId = useId().replaceAll(':', '-');\n const isIframe = useInIframe();\n\n const [lastUsed, setLastUsed] = useState<string | null>(null);\n useEffect(() => {\n setLastUsed(localStorage.getItem('_STACK_AUTH.lastUsed'));\n }, []);\n\n let style : {\n backgroundColor?: string,\n textColor?: string,\n name: string,\n icon: JSX.Element | null,\n border?: string,\n };\n switch (provider) {\n case 'google': {\n style = {\n backgroundColor: '#fff',\n textColor: '#000',\n name: 'Google',\n border: '1px solid #ddd',\n icon: <BrandIcons.Google iconSize={iconSize} />,\n };\n break;\n }\n case 'github': {\n style = {\n backgroundColor: '#111',\n textColor: '#fff',\n border: '1px solid #333',\n name: 'GitHub',\n icon: <BrandIcons.GitHub iconSize={iconSize} />,\n };\n break;\n }\n case 'facebook': {\n style = {\n backgroundColor: '#1877F2',\n textColor: '#fff',\n name: 'Facebook',\n icon: <BrandIcons.Facebook iconSize={iconSize} />,\n };\n break;\n }\n case 'microsoft': {\n style = {\n backgroundColor: '#2f2f2f',\n textColor: '#fff',\n name: 'Microsoft',\n icon: <BrandIcons.Microsoft iconSize={iconSize} />,\n };\n break;\n }\n case 'spotify': {\n style = {\n backgroundColor: '#1DB954',\n textColor: '#fff',\n name: 'Spotify',\n icon: <BrandIcons.Spotify iconSize={iconSize} />,\n };\n break;\n }\n case 'discord': {\n style = {\n backgroundColor: '#5865F2',\n textColor: '#fff',\n name: 'Discord',\n icon: <BrandIcons.Discord iconSize={iconSize} />,\n };\n break;\n }\n case 'gitlab': {\n style = {\n backgroundColor: \"#111\",\n textColor: \"#fff\",\n border: \"1px solid #333\",\n name: \"Gitlab\",\n icon: <BrandIcons.Gitlab iconSize={iconSize} />,\n };\n break;\n }\n case 'apple': {\n style = {\n backgroundColor: \"#000\",\n textColor: \"#fff\",\n border: \"1px solid #333\",\n name: \"Apple\",\n icon: <BrandIcons.Apple iconSize={iconSize} />,\n };\n break;\n }\n case \"bitbucket\": {\n style = {\n backgroundColor: \"#fff\",\n textColor: \"#000\",\n border: \"1px solid #ddd\",\n name: \"Bitbucket\",\n icon: <BrandIcons.Bitbucket iconSize={iconSize} />,\n };\n break;\n }\n case 'linkedin': {\n style = {\n backgroundColor: \"#0073b1\",\n textColor: \"#fff\",\n name: \"LinkedIn\",\n icon: <BrandIcons.LinkedIn iconSize={iconSize} />,\n };\n break;\n }\n case 'x': {\n style = {\n backgroundColor: \"#000\",\n textColor: \"#fff\",\n name: \"X\",\n icon: <BrandIcons.X iconSize={iconSize} />,\n };\n break;\n }\n case 'twitch': {\n style = {\n backgroundColor: \"#6441a5\",\n textColor: \"#fff\",\n name: \"Twitch\",\n icon: <BrandIcons.Twitch iconSize={iconSize} />,\n };\n break;\n }\n default: {\n style = {\n name: provider,\n icon: null,\n };\n }\n }\n\n const styleSheet = `\n .stack-oauth-button-${styleId} {\n background-color: ${style.backgroundColor} !important;\n color: ${style.textColor} !important;\n border: ${style.border} !important;\n }\n .stack-oauth-button-${styleId}:hover {\n background-color: ${changeColor(Color(style.backgroundColor), 10)} !important;\n }\n `;\n\n return (\n <>\n <style>{styleSheet}</style>\n <SimpleTooltip\n disabled={!isIframe}\n tooltip={isIframe ? \"This auth provider is not supported in an iframe for security reasons.\" : undefined}\n className='stack-scope w-full inline-flex'\n >\n <Button\n onClick={async () => {\n localStorage.setItem('_STACK_AUTH.lastUsed', provider);\n await stackApp.signInWithOAuth(provider);\n }}\n className={`stack-oauth-button-${styleId} stack-scope relative w-full`}\n disabled={isIframe}\n >\n {!isMock && lastUsed === provider && (\n <span className=\"absolute -top-2 -right-2 bg-blue-500 text-white text-xs px-2 py-1 rounded-md\">\n last\n </span>\n )}\n <div className='flex items-center w-full gap-4'>\n {style.icon}\n <span className='flex-1'>\n {type === 'sign-up' ?\n t('Sign up with {provider}', { provider: style.name }) :\n t('Sign in with {provider}', { provider: style.name })\n }\n </span>\n </div>\n </Button>\n </SimpleTooltip>\n </>\n );\n}\n"],"mappings":"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","names":["Color"]}
1
+ {"version":3,"sources":["../../src/components/oauth-button.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { BrandIcons, Button, SimpleTooltip } from '@stackframe/stack-ui';\nimport Color, { ColorInstance } from 'color';\nimport { useEffect, useId, useState } from 'react';\nimport { useStackApp } from '..';\nimport { useTranslation } from '../lib/translations';\nimport { useInIframe } from './use-in-iframe';\n\nconst iconSize = 22;\n\nconst changeColor = (c: ColorInstance, value: number) => {\n if (c.isLight()) {\n value = -value;\n }\n return c.hsl(c.hue(), c.saturationl(), c.lightness() + value).toString();\n};\n\nexport function OAuthButton({\n provider,\n type,\n isMock = false,\n}: {\n provider: string,\n type: 'sign-in' | 'sign-up',\n isMock?: boolean,\n}) {\n const { t } = useTranslation();\n const stackApp = useStackApp();\n const styleId = useId().replaceAll(':', '-');\n const isIframe = useInIframe();\n\n const [lastUsed, setLastUsed] = useState<string | null>(null);\n useEffect(() => {\n setLastUsed(localStorage.getItem('_STACK_AUTH.lastUsed'));\n }, []);\n\n let style : {\n backgroundColor?: string,\n textColor?: string,\n name: string,\n icon: JSX.Element | null,\n border?: string,\n };\n switch (provider) {\n case 'google': {\n style = {\n backgroundColor: '#fff',\n textColor: '#000',\n name: 'Google',\n border: '1px solid #ddd',\n icon: <BrandIcons.Google iconSize={iconSize} />,\n };\n break;\n }\n case 'github': {\n style = {\n backgroundColor: '#111',\n textColor: '#fff',\n border: '1px solid #333',\n name: 'GitHub',\n icon: <BrandIcons.GitHub iconSize={iconSize} />,\n };\n break;\n }\n case 'facebook': {\n style = {\n backgroundColor: '#1877F2',\n textColor: '#fff',\n name: 'Facebook',\n icon: <BrandIcons.Facebook iconSize={iconSize} />,\n };\n break;\n }\n case 'microsoft': {\n style = {\n backgroundColor: '#2f2f2f',\n textColor: '#fff',\n name: 'Microsoft',\n icon: <BrandIcons.Microsoft iconSize={iconSize} />,\n };\n break;\n }\n case 'spotify': {\n style = {\n backgroundColor: '#1DB954',\n textColor: '#fff',\n name: 'Spotify',\n icon: <BrandIcons.Spotify iconSize={iconSize} />,\n };\n break;\n }\n case 'discord': {\n style = {\n backgroundColor: '#5865F2',\n textColor: '#fff',\n name: 'Discord',\n icon: <BrandIcons.Discord iconSize={iconSize} />,\n };\n break;\n }\n case 'gitlab': {\n style = {\n backgroundColor: \"#111\",\n textColor: \"#fff\",\n border: \"1px solid #333\",\n name: \"Gitlab\",\n icon: <BrandIcons.Gitlab iconSize={iconSize} />,\n };\n break;\n }\n case 'apple': {\n style = {\n backgroundColor: \"#000\",\n textColor: \"#fff\",\n border: \"1px solid #333\",\n name: \"Apple\",\n icon: <BrandIcons.Apple iconSize={iconSize} />,\n };\n break;\n }\n case \"bitbucket\": {\n style = {\n backgroundColor: \"#fff\",\n textColor: \"#000\",\n border: \"1px solid #ddd\",\n name: \"Bitbucket\",\n icon: <BrandIcons.Bitbucket iconSize={iconSize} />,\n };\n break;\n }\n case 'linkedin': {\n style = {\n backgroundColor: \"#0073b1\",\n textColor: \"#fff\",\n name: \"LinkedIn\",\n icon: <BrandIcons.LinkedIn iconSize={iconSize} />,\n };\n break;\n }\n case 'x': {\n style = {\n backgroundColor: \"#000\",\n textColor: \"#fff\",\n name: \"X\",\n icon: <BrandIcons.X iconSize={iconSize} />,\n };\n break;\n }\n case 'twitch': {\n style = {\n backgroundColor: \"#6441a5\",\n textColor: \"#fff\",\n name: \"Twitch\",\n icon: <BrandIcons.Twitch iconSize={iconSize} />,\n };\n break;\n }\n default: {\n style = {\n name: provider,\n icon: null,\n };\n }\n }\n\n const styleSheet = `\n .stack-oauth-button-${styleId} {\n background-color: ${style.backgroundColor} !important;\n color: ${style.textColor} !important;\n border: ${style.border} !important;\n }\n .stack-oauth-button-${styleId}:hover {\n background-color: ${changeColor(Color(style.backgroundColor), 10)} !important;\n }\n `;\n\n return (\n <>\n <style>{styleSheet}</style>\n <SimpleTooltip\n disabled={!isIframe}\n tooltip={isIframe ? \"This auth provider is not supported in an iframe for security reasons.\" : undefined}\n className='stack-scope w-full inline-flex'\n >\n <Button\n onClick={async () => {\n localStorage.setItem('_STACK_AUTH.lastUsed', provider);\n await stackApp.signInWithOAuth(provider);\n }}\n className={`stack-oauth-button-${styleId} stack-scope relative w-full`}\n disabled={isIframe}\n >\n {!isMock && lastUsed === provider && (\n <span className=\"absolute -top-2 -right-2 bg-blue-500 text-white text-xs px-2 py-1 rounded-md\">\n last\n </span>\n )}\n <div className='flex items-center w-full gap-4'>\n {style.icon}\n <span className='flex-1'>\n {type === 'sign-up' ?\n t('Sign up with {provider}', { provider: style.name }) :\n t('Sign in with {provider}', { provider: style.name })\n }\n </span>\n </div>\n </Button>\n </SimpleTooltip>\n </>\n );\n}\n"],"mappings":"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","names":["Color"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/passkey-button.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\n\nimport { Button } from '@stackframe/stack-ui';\nimport { KeyRound } from 'lucide-react';\nimport { useId } from 'react';\nimport { useStackApp } from '..';\nimport { useTranslation } from '../lib/translations';\n\n\nexport function PasskeyButton({\n type,\n}: {\n type: 'sign-in' | 'sign-up',\n}) {\n const { t } = useTranslation();\n const stackApp = useStackApp();\n const styleId = useId().replaceAll(':', '-');\n\n\n return (\n <>\n <Button\n onClick={async () => { await stackApp.signInWithPasskey(); }}\n className={`stack-oauth-button-${styleId} stack-scope`}\n >\n <div className='flex items-center w-full gap-4'>\n <KeyRound />\n <span className='flex-1'>\n {type === 'sign-up' ?\n t('Sign up with Passkey') :\n t('Sign in with Passkey')\n }\n </span>\n </div>\n </Button>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAAuB;AACvB,0BAAyB;AACzB,mBAAsB;AACtB,eAA4B;AAC5B,0BAA+B;AAc3B;AAXG,SAAS,cAAc;AAAA,EAC5B;AACF,GAEG;AACD,QAAM,EAAE,EAAE,QAAI,oCAAe;AAC7B,QAAM,eAAW,sBAAY;AAC7B,QAAM,cAAU,oBAAM,EAAE,WAAW,KAAK,GAAG;AAG3C,SACE,2EACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,YAAY;AAAE,cAAM,SAAS,kBAAkB;AAAA,MAAG;AAAA,MAC3D,WAAW,sBAAsB,OAAO;AAAA,MAExC,uDAAC,SAAI,WAAU,kCACb;AAAA,oDAAC,gCAAS;AAAA,QACV,4CAAC,UAAK,WAAU,UACb,mBAAS,YACR,EAAE,sBAAsB,IACxB,EAAE,sBAAsB,GAE5B;AAAA,SACF;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/passkey-button.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { Button } from '@stackframe/stack-ui';\nimport { KeyRound } from 'lucide-react';\nimport { useId } from 'react';\nimport { useStackApp } from '..';\nimport { useTranslation } from '../lib/translations';\n\n\nexport function PasskeyButton({\n type,\n}: {\n type: 'sign-in' | 'sign-up',\n}) {\n const { t } = useTranslation();\n const stackApp = useStackApp();\n const styleId = useId().replaceAll(':', '-');\n\n\n return (\n <>\n <Button\n onClick={async () => { await stackApp.signInWithPasskey(); }}\n className={`stack-oauth-button-${styleId} stack-scope`}\n >\n <div className='flex items-center w-full gap-4'>\n <KeyRound />\n <span className='flex-1'>\n {type === 'sign-up' ?\n t('Sign up with Passkey') :\n t('Sign in with Passkey')\n }\n </span>\n </div>\n </Button>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAAuB;AACvB,0BAAyB;AACzB,mBAAsB;AACtB,eAA4B;AAC5B,0BAA+B;AAc3B;AAXG,SAAS,cAAc;AAAA,EAC5B;AACF,GAEG;AACD,QAAM,EAAE,EAAE,QAAI,oCAAe;AAC7B,QAAM,eAAW,sBAAY;AAC7B,QAAM,cAAU,oBAAM,EAAE,WAAW,KAAK,GAAG;AAG3C,SACE,2EACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,YAAY;AAAE,cAAM,SAAS,kBAAkB;AAAA,MAAG;AAAA,MAC3D,WAAW,sBAAsB,OAAO;AAAA,MAExC,uDAAC,SAAI,WAAU,kCACb;AAAA,oDAAC,gCAAS;AAAA,QACV,4CAAC,UAAK,WAAU,UACb,mBAAS,YACR,EAAE,sBAAsB,IACxB,EAAE,sBAAsB,GAE5B;AAAA,SACF;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/profile-image-editor.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { fileToBase64 } from '@stackframe/stack-shared/dist/utils/base64';\nimport { runAsynchronouslyWithAlert } from '@stackframe/stack-shared/dist/utils/promises';\nimport { Button, Slider, Typography } from '@stackframe/stack-ui';\nimport imageCompression from 'browser-image-compression';\nimport { Upload } from 'lucide-react';\nimport { ComponentProps, useCallback, useState } from 'react';\nimport Cropper, { Area } from 'react-easy-crop';\nimport { useTranslation } from '../lib/translations';\nimport { UserAvatar } from './elements/user-avatar';\n\nexport async function checkImageUrl(url: string){\n try {\n const res = await fetch(url, { method: 'HEAD' });\n const buff = await res.blob();\n return buff.type.startsWith('image/');\n } catch (e) {\n return false;\n }\n}\n\nconst createImage = (url: string): Promise<HTMLImageElement> =>\n new Promise((resolve, reject) => {\n const image = new Image();\n image.addEventListener('load', () => resolve(image));\n image.addEventListener('error', (error) => reject(error));\n image.setAttribute('crossOrigin', 'anonymous');\n image.src = url;\n });\n\nexport async function getCroppedImg(imageSrc: string, pixelCrop: Area): Promise<string | null> {\n const image = await createImage(imageSrc);\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n return null;\n }\n\n const safeCrop = {\n x: Math.max(0, pixelCrop.x),\n y: Math.max(0, pixelCrop.y),\n width: Math.max(1, pixelCrop.width),\n height: Math.max(1, pixelCrop.height),\n };\n\n canvas.width = safeCrop.width;\n canvas.height = safeCrop.height;\n\n ctx.drawImage(\n image,\n safeCrop.x,\n safeCrop.y,\n safeCrop.width,\n safeCrop.height,\n 0,\n 0,\n safeCrop.width,\n safeCrop.height\n );\n\n return canvas.toDataURL('image/jpeg');\n}\n\nexport function ProfileImageEditor(props: {\n user: NonNullable<ComponentProps<typeof UserAvatar>['user']>,\n onProfileImageUrlChange: (profileImageUrl: string | null) => void | Promise<void>,\n}) {\n const { t } = useTranslation();\n const [rawUrl, setRawUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);\n\n function reset() {\n setRawUrl(null);\n setError(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n }\n\n const onCropChange = useCallback((crop: { x: number, y: number }) => {\n setCrop(crop);\n }, []);\n\n const onCropComplete = useCallback((croppedArea: Area, croppedAreaPixels: Area) => {\n setCroppedAreaPixels(croppedAreaPixels);\n }, []);\n\n const onZoomChange = useCallback((zoom: number) => {\n setZoom(zoom);\n }, []);\n\n\n function upload() {\n const input = document.createElement('input');\n input.type = 'file';\n input.onchange = (e) => {\n const file = (e.target as HTMLInputElement).files?.[0];\n if (!file) return;\n runAsynchronouslyWithAlert(async () => {\n const rawUrl = await fileToBase64(file);\n if (await checkImageUrl(rawUrl)) {\n setRawUrl(rawUrl);\n setError(null);\n } else {\n setError(t('Invalid image'));\n }\n input.remove();\n });\n };\n input.click();\n }\n\n if (!rawUrl) {\n return <div className='flex flex-col'>\n <div className='cursor-pointer relative' onClick={upload}>\n <UserAvatar\n size={60}\n user={props.user}\n border\n />\n <div className='absolute top-0 left-0 h-[60px] w-[60px] bg-gray-500/20 backdrop-blur-sm items-center justify-center rounded-full flex opacity-0 hover:opacity-100 transition-opacity'>\n <div className='bg-background p-2 rounded-full'>\n <Upload className='h-5 w-5' />\n </div>\n </div>\n </div>\n {error && <Typography variant='destructive' type='label'>{error}</Typography>}\n </div>;\n }\n\n return (\n <div className='flex flex-col items-center gap-4'>\n <div className='relative w-64 h-64'>\n <Cropper\n image={rawUrl || props.user.profileImageUrl || \"\"}\n crop={crop}\n zoom={zoom}\n aspect={1}\n cropShape=\"round\"\n showGrid={false}\n onCropChange={onCropChange}\n onCropComplete={onCropComplete}\n onZoomChange={onZoomChange}\n />\n </div>\n <Slider\n min={1}\n max={3}\n step={0.1}\n value={[zoom]}\n onValueChange={(v) => onZoomChange(v[0])}\n />\n\n <div className='flex flex-row gap-2'>\n <Button\n onClick={async () => {\n if (rawUrl && croppedAreaPixels) {\n const croppedImageUrl = await getCroppedImg(rawUrl, croppedAreaPixels);\n if (croppedImageUrl) {\n const compressedFile = await imageCompression(\n await imageCompression.getFilefromDataUrl(croppedImageUrl, 'profile-image'),\n {\n maxSizeMB: 0.1,\n fileType: \"image/jpeg\",\n }\n );\n const compressedUrl = await imageCompression.getDataUrlFromFile(compressedFile);\n await props.onProfileImageUrlChange(compressedUrl);\n reset();\n } else {\n setError(t('Could not crop image.'));\n }\n }\n }}\n >\n {t('Save')}\n </Button>\n <Button\n variant=\"secondary\"\n onClick={reset}\n >\n {t('Cancel')}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["crop","croppedAreaPixels","zoom","rawUrl","Cropper","imageCompression"]}
1
+ {"version":3,"sources":["../../src/components/profile-image-editor.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { fileToBase64 } from '@stackframe/stack-shared/dist/utils/base64';\nimport { runAsynchronouslyWithAlert } from '@stackframe/stack-shared/dist/utils/promises';\nimport { Button, Slider, Typography } from '@stackframe/stack-ui';\nimport imageCompression from 'browser-image-compression';\nimport { Upload } from 'lucide-react';\nimport { ComponentProps, useCallback, useState } from 'react';\nimport Cropper, { Area } from 'react-easy-crop';\nimport { useTranslation } from '../lib/translations';\nimport { UserAvatar } from './elements/user-avatar';\n\nexport async function checkImageUrl(url: string){\n try {\n const res = await fetch(url, { method: 'HEAD' });\n const buff = await res.blob();\n return buff.type.startsWith('image/');\n } catch (e) {\n return false;\n }\n}\n\nconst createImage = (url: string): Promise<HTMLImageElement> =>\n new Promise((resolve, reject) => {\n const image = new Image();\n image.addEventListener('load', () => resolve(image));\n image.addEventListener('error', (error) => reject(error));\n image.setAttribute('crossOrigin', 'anonymous');\n image.src = url;\n });\n\nexport async function getCroppedImg(imageSrc: string, pixelCrop: Area): Promise<string | null> {\n const image = await createImage(imageSrc);\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n return null;\n }\n\n const safeCrop = {\n x: Math.max(0, pixelCrop.x),\n y: Math.max(0, pixelCrop.y),\n width: Math.max(1, pixelCrop.width),\n height: Math.max(1, pixelCrop.height),\n };\n\n canvas.width = safeCrop.width;\n canvas.height = safeCrop.height;\n\n ctx.drawImage(\n image,\n safeCrop.x,\n safeCrop.y,\n safeCrop.width,\n safeCrop.height,\n 0,\n 0,\n safeCrop.width,\n safeCrop.height\n );\n\n return canvas.toDataURL('image/jpeg');\n}\n\nexport function ProfileImageEditor(props: {\n user: NonNullable<ComponentProps<typeof UserAvatar>['user']>,\n onProfileImageUrlChange: (profileImageUrl: string | null) => void | Promise<void>,\n}) {\n const { t } = useTranslation();\n const [rawUrl, setRawUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [crop, setCrop] = useState({ x: 0, y: 0 });\n const [zoom, setZoom] = useState(1);\n const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);\n\n function reset() {\n setRawUrl(null);\n setError(null);\n setCrop({ x: 0, y: 0 });\n setZoom(1);\n setCroppedAreaPixels(null);\n }\n\n const onCropChange = useCallback((crop: { x: number, y: number }) => {\n setCrop(crop);\n }, []);\n\n const onCropComplete = useCallback((croppedArea: Area, croppedAreaPixels: Area) => {\n setCroppedAreaPixels(croppedAreaPixels);\n }, []);\n\n const onZoomChange = useCallback((zoom: number) => {\n setZoom(zoom);\n }, []);\n\n\n function upload() {\n const input = document.createElement('input');\n input.type = 'file';\n input.onchange = (e) => {\n const file = (e.target as HTMLInputElement).files?.[0];\n if (!file) return;\n runAsynchronouslyWithAlert(async () => {\n const rawUrl = await fileToBase64(file);\n if (await checkImageUrl(rawUrl)) {\n setRawUrl(rawUrl);\n setError(null);\n } else {\n setError(t('Invalid image'));\n }\n input.remove();\n });\n };\n input.click();\n }\n\n if (!rawUrl) {\n return <div className='flex flex-col'>\n <div className='cursor-pointer relative' onClick={upload}>\n <UserAvatar\n size={60}\n user={props.user}\n border\n />\n <div className='absolute top-0 left-0 h-[60px] w-[60px] bg-gray-500/20 backdrop-blur-sm items-center justify-center rounded-full flex opacity-0 hover:opacity-100 transition-opacity'>\n <div className='bg-background p-2 rounded-full'>\n <Upload className='h-5 w-5' />\n </div>\n </div>\n </div>\n {error && <Typography variant='destructive' type='label'>{error}</Typography>}\n </div>;\n }\n\n return (\n <div className='flex flex-col items-center gap-4'>\n <div className='relative w-64 h-64'>\n <Cropper\n image={rawUrl || props.user.profileImageUrl || \"\"}\n crop={crop}\n zoom={zoom}\n aspect={1}\n cropShape=\"round\"\n showGrid={false}\n onCropChange={onCropChange}\n onCropComplete={onCropComplete}\n onZoomChange={onZoomChange}\n />\n </div>\n <Slider\n min={1}\n max={3}\n step={0.1}\n value={[zoom]}\n onValueChange={(v) => onZoomChange(v[0])}\n />\n\n <div className='flex flex-row gap-2'>\n <Button\n onClick={async () => {\n if (rawUrl && croppedAreaPixels) {\n const croppedImageUrl = await getCroppedImg(rawUrl, croppedAreaPixels);\n if (croppedImageUrl) {\n const compressedFile = await imageCompression(\n await imageCompression.getFilefromDataUrl(croppedImageUrl, 'profile-image'),\n {\n maxSizeMB: 0.1,\n fileType: \"image/jpeg\",\n }\n );\n const compressedUrl = await imageCompression.getDataUrlFromFile(compressedFile);\n await props.onProfileImageUrlChange(compressedUrl);\n reset();\n } else {\n setError(t('Could not crop image.'));\n }\n }\n }}\n >\n {t('Save')}\n </Button>\n <Button\n variant=\"secondary\"\n onClick={reset}\n >\n {t('Cancel')}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["crop","croppedAreaPixels","zoom","rawUrl","Cropper","imageCompression"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/selected-team-switcher.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport {\n Skeleton,\n} from \"@stackframe/stack-ui\";\nimport { Suspense, useEffect } from \"react\";\nimport { Team, useStackApp, useUser } from \"..\";\nimport { TeamSwitcher } from \"./team-switcher\";\n\ntype MockTeam = {\n id: string,\n displayName: string,\n profileImageUrl?: string | null,\n};\n\ntype SelectedTeamSwitcherProps<AllowNull extends boolean = false> = {\n urlMap?: (team: AllowNull extends true ? Team | null : Team) => string,\n selectedTeam?: Team,\n noUpdateSelectedTeam?: boolean,\n allowNull?: AllowNull,\n nullLabel?: string,\n onChange?: (team: AllowNull extends true ? Team | null : Team) => void,\n triggerClassName?: string,\n // Mock data props\n mockUser?: {\n selectedTeam?: MockTeam,\n },\n mockTeams?: MockTeam[],\n mockProject?: {\n config: {\n clientTeamCreationEnabled: boolean,\n },\n },\n};\n\nexport function SelectedTeamSwitcher<AllowNull extends boolean = false>(props: SelectedTeamSwitcherProps<AllowNull>) {\n return <Suspense fallback={<Fallback />}>\n <Inner {...props} />\n </Suspense>;\n}\n\nfunction Fallback() {\n return <Skeleton className=\"h-9 w-full max-w-64 stack-scope\" />;\n}\n\nfunction Inner<AllowNull extends boolean>(props: SelectedTeamSwitcherProps<AllowNull>) {\n const appFromHook = useStackApp();\n const userFromHook = useUser();\n\n // Use mock data if provided, otherwise use real data\n const app = props.mockUser ? {\n useProject: () => props.mockProject || { config: { clientTeamCreationEnabled: false } },\n useNavigate: () => () => {}, // Mock navigate function\n urls: { accountSettings: '/account-settings' },\n } : appFromHook;\n\n const user = props.mockUser ? {\n selectedTeam: props.mockUser.selectedTeam,\n useTeams: () => props.mockTeams || [],\n setSelectedTeam: async () => {}, // Mock function\n } : userFromHook;\n\n const navigate = app.useNavigate();\n\n useEffect(() => {\n if (!props.noUpdateSelectedTeam && props.selectedTeam && !props.mockUser) {\n runAsynchronouslyWithAlert(user?.setSelectedTeam(props.selectedTeam));\n }\n }, [props.noUpdateSelectedTeam, props.selectedTeam, props.mockUser]);\n\n return (\n <TeamSwitcher\n team={props.selectedTeam}\n allowNull={props.allowNull}\n nullLabel={props.nullLabel}\n triggerClassName={props.triggerClassName}\n onChange={async (team) => {\n if (props.onChange) {\n props.onChange(team as Team);\n }\n // Skip actual navigation/updates in mock mode\n if (props.mockUser) return;\n if (!props.noUpdateSelectedTeam) {\n await user?.setSelectedTeam(team as Team);\n }\n if (props.urlMap) {\n navigate(props.urlMap(team as Team));\n }\n }}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,sBAA2C;AAC3C,sBAEO;AACP,mBAAoC;AACpC,eAA2C;AAC3C,2BAA6B;AA6BA;AADtB,SAAS,qBAAwD,OAA6C;AACnH,SAAO,4CAAC,yBAAS,UAAU,4CAAC,YAAS,GACnC,sDAAC,SAAO,GAAG,OAAO,GACpB;AACF;AAEA,SAAS,WAAW;AAClB,SAAO,4CAAC,4BAAS,WAAU,mCAAkC;AAC/D;AAEA,SAAS,MAAiC,OAA6C;AACrF,QAAM,kBAAc,sBAAY;AAChC,QAAM,mBAAe,kBAAQ;AAG7B,QAAM,MAAM,MAAM,WAAW;AAAA,IAC3B,YAAY,MAAM,MAAM,eAAe,EAAE,QAAQ,EAAE,2BAA2B,MAAM,EAAE;AAAA,IACtF,aAAa,MAAM,MAAM;AAAA,IAAC;AAAA;AAAA,IAC1B,MAAM,EAAE,iBAAiB,oBAAoB;AAAA,EAC/C,IAAI;AAEJ,QAAM,OAAO,MAAM,WAAW;AAAA,IAC5B,cAAc,MAAM,SAAS;AAAA,IAC7B,UAAU,MAAM,MAAM,aAAa,CAAC;AAAA,IACpC,iBAAiB,YAAY;AAAA,IAAC;AAAA;AAAA,EAChC,IAAI;AAEJ,QAAM,WAAW,IAAI,YAAY;AAEjC,8BAAU,MAAM;AACd,QAAI,CAAC,MAAM,wBAAwB,MAAM,gBAAgB,CAAC,MAAM,UAAU;AACxE,sDAA2B,MAAM,gBAAgB,MAAM,YAAY,CAAC;AAAA,IACtE;AAAA,EACF,GAAG,CAAC,MAAM,sBAAsB,MAAM,cAAc,MAAM,QAAQ,CAAC;AAEnE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,MAAM;AAAA,MACZ,WAAW,MAAM;AAAA,MACjB,WAAW,MAAM;AAAA,MACjB,kBAAkB,MAAM;AAAA,MACxB,UAAU,OAAO,SAAS;AACxB,YAAI,MAAM,UAAU;AAClB,gBAAM,SAAS,IAAY;AAAA,QAC7B;AAEA,YAAI,MAAM,SAAU;AACpB,YAAI,CAAC,MAAM,sBAAsB;AAC/B,gBAAM,MAAM,gBAAgB,IAAY;AAAA,QAC1C;AACA,YAAI,MAAM,QAAQ;AAChB,mBAAS,MAAM,OAAO,IAAY,CAAC;AAAA,QACrC;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/selected-team-switcher.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport {\n Skeleton,\n} from \"@stackframe/stack-ui\";\nimport { Suspense, useEffect } from \"react\";\nimport { Team, useStackApp, useUser } from \"..\";\nimport { TeamSwitcher } from \"./team-switcher\";\n\ntype MockTeam = {\n id: string,\n displayName: string,\n profileImageUrl?: string | null,\n};\n\ntype SelectedTeamSwitcherProps<AllowNull extends boolean = false> = {\n urlMap?: (team: AllowNull extends true ? Team | null : Team) => string,\n selectedTeam?: Team,\n noUpdateSelectedTeam?: boolean,\n allowNull?: AllowNull,\n nullLabel?: string,\n onChange?: (team: AllowNull extends true ? Team | null : Team) => void,\n triggerClassName?: string,\n // Mock data props\n mockUser?: {\n selectedTeam?: MockTeam,\n },\n mockTeams?: MockTeam[],\n mockProject?: {\n config: {\n clientTeamCreationEnabled: boolean,\n },\n },\n};\n\nexport function SelectedTeamSwitcher<AllowNull extends boolean = false>(props: SelectedTeamSwitcherProps<AllowNull>) {\n return <Suspense fallback={<Fallback />}>\n <Inner {...props} />\n </Suspense>;\n}\n\nfunction Fallback() {\n return <Skeleton className=\"h-9 w-full max-w-64 stack-scope\" />;\n}\n\nfunction Inner<AllowNull extends boolean>(props: SelectedTeamSwitcherProps<AllowNull>) {\n const appFromHook = useStackApp();\n const userFromHook = useUser();\n\n // Use mock data if provided, otherwise use real data\n const app = props.mockUser ? {\n useProject: () => props.mockProject || { config: { clientTeamCreationEnabled: false } },\n useNavigate: () => () => {}, // Mock navigate function\n urls: { accountSettings: '/account-settings' },\n } : appFromHook;\n\n const user = props.mockUser ? {\n selectedTeam: props.mockUser.selectedTeam,\n useTeams: () => props.mockTeams || [],\n setSelectedTeam: async () => {}, // Mock function\n } : userFromHook;\n\n const navigate = app.useNavigate();\n\n useEffect(() => {\n if (!props.noUpdateSelectedTeam && props.selectedTeam && !props.mockUser) {\n runAsynchronouslyWithAlert(user?.setSelectedTeam(props.selectedTeam));\n }\n }, [props.noUpdateSelectedTeam, props.selectedTeam, props.mockUser]);\n\n return (\n <TeamSwitcher\n team={props.selectedTeam}\n allowNull={props.allowNull}\n nullLabel={props.nullLabel}\n triggerClassName={props.triggerClassName}\n onChange={async (team) => {\n if (props.onChange) {\n props.onChange(team as Team);\n }\n // Skip actual navigation/updates in mock mode\n if (props.mockUser) return;\n if (!props.noUpdateSelectedTeam) {\n await user?.setSelectedTeam(team as Team);\n }\n if (props.urlMap) {\n navigate(props.urlMap(team as Team));\n }\n }}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,sBAA2C;AAC3C,sBAEO;AACP,mBAAoC;AACpC,eAA2C;AAC3C,2BAA6B;AA6BA;AADtB,SAAS,qBAAwD,OAA6C;AACnH,SAAO,4CAAC,yBAAS,UAAU,4CAAC,YAAS,GACnC,sDAAC,SAAO,GAAG,OAAO,GACpB;AACF;AAEA,SAAS,WAAW;AAClB,SAAO,4CAAC,4BAAS,WAAU,mCAAkC;AAC/D;AAEA,SAAS,MAAiC,OAA6C;AACrF,QAAM,kBAAc,sBAAY;AAChC,QAAM,mBAAe,kBAAQ;AAG7B,QAAM,MAAM,MAAM,WAAW;AAAA,IAC3B,YAAY,MAAM,MAAM,eAAe,EAAE,QAAQ,EAAE,2BAA2B,MAAM,EAAE;AAAA,IACtF,aAAa,MAAM,MAAM;AAAA,IAAC;AAAA;AAAA,IAC1B,MAAM,EAAE,iBAAiB,oBAAoB;AAAA,EAC/C,IAAI;AAEJ,QAAM,OAAO,MAAM,WAAW;AAAA,IAC5B,cAAc,MAAM,SAAS;AAAA,IAC7B,UAAU,MAAM,MAAM,aAAa,CAAC;AAAA,IACpC,iBAAiB,YAAY;AAAA,IAAC;AAAA;AAAA,EAChC,IAAI;AAEJ,QAAM,WAAW,IAAI,YAAY;AAEjC,8BAAU,MAAM;AACd,QAAI,CAAC,MAAM,wBAAwB,MAAM,gBAAgB,CAAC,MAAM,UAAU;AACxE,sDAA2B,MAAM,gBAAgB,MAAM,YAAY,CAAC;AAAA,IACtE;AAAA,EACF,GAAG,CAAC,MAAM,sBAAsB,MAAM,cAAc,MAAM,QAAQ,CAAC;AAEnE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,MAAM;AAAA,MACZ,WAAW,MAAM;AAAA,MACjB,WAAW,MAAM;AAAA,MACjB,kBAAkB,MAAM;AAAA,MACxB,UAAU,OAAO,SAAS;AACxB,YAAI,MAAM,UAAU;AAClB,gBAAM,SAAS,IAAY;AAAA,QAC7B;AAEA,YAAI,MAAM,SAAU;AACpB,YAAI,CAAC,MAAM,sBAAsB;AAC/B,gBAAM,MAAM,gBAAgB,IAAY;AAAA,QAC1C;AACA,YAAI,MAAM,QAAQ;AAChB,mBAAS,MAAM,OAAO,IAAY,CAAC;AAAA,QACrC;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/team-icon.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY\n//===========================================\nimport { Avatar, AvatarImage, Typography } from \"@stackframe/stack-ui\";\nimport { User2 } from \"lucide-react\";\nimport { Team } from \"..\";\n\nexport function TeamIcon(props: { team: Team | 'personal' }) {\n if (props.team === 'personal') {\n return (\n <div className=\"flex items-center justify-center min-w-6 min-h-6 max-w-6 max-h-6 rounded bg-zinc-200\">\n <User2 className=\"w-4 h-4\" />\n </div>\n );\n }\n if (props.team.profileImageUrl) {\n return (\n <Avatar className=\"min-w-6 min-h-6 max-w-6 max-h-6 rounded\">\n <AvatarImage src={props.team.profileImageUrl} alt={props.team.displayName} />\n </Avatar>\n );\n } else {\n return (\n <div className=\"flex items-center justify-center min-w-6 min-h-6 max-w-6 max-h-6 rounded bg-zinc-200\">\n <Typography className=\"text-zinc-800 dark:text-zinc-800\">{props.team.displayName.slice(0, 1).toUpperCase()}</Typography>\n </div>\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,sBAAgD;AAChD,0BAAsB;AAOd;AAJD,SAAS,SAAS,OAAoC;AAC3D,MAAI,MAAM,SAAS,YAAY;AAC7B,WACE,4CAAC,SAAI,WAAU,wFACb,sDAAC,6BAAM,WAAU,WAAU,GAC7B;AAAA,EAEJ;AACA,MAAI,MAAM,KAAK,iBAAiB;AAC9B,WACE,4CAAC,0BAAO,WAAU,2CAChB,sDAAC,+BAAY,KAAK,MAAM,KAAK,iBAAiB,KAAK,MAAM,KAAK,aAAa,GAC7E;AAAA,EAEJ,OAAO;AACL,WACE,4CAAC,SAAI,WAAU,wFACb,sDAAC,8BAAW,WAAU,oCAAoC,gBAAM,KAAK,YAAY,MAAM,GAAG,CAAC,EAAE,YAAY,GAAE,GAC7G;AAAA,EAEJ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/components/team-icon.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { Avatar, AvatarImage, Typography } from \"@stackframe/stack-ui\";\nimport { User2 } from \"lucide-react\";\nimport { Team } from \"..\";\n\nexport function TeamIcon(props: { team: Team | 'personal' }) {\n if (props.team === 'personal') {\n return (\n <div className=\"flex items-center justify-center min-w-6 min-h-6 max-w-6 max-h-6 rounded bg-zinc-200\">\n <User2 className=\"w-4 h-4\" />\n </div>\n );\n }\n if (props.team.profileImageUrl) {\n return (\n <Avatar className=\"min-w-6 min-h-6 max-w-6 max-h-6 rounded\">\n <AvatarImage src={props.team.profileImageUrl} alt={props.team.displayName} />\n </Avatar>\n );\n } else {\n return (\n <div className=\"flex items-center justify-center min-w-6 min-h-6 max-w-6 max-h-6 rounded bg-zinc-200\">\n <Typography className=\"text-zinc-800 dark:text-zinc-800\">{props.team.displayName.slice(0, 1).toUpperCase()}</Typography>\n </div>\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,sBAAgD;AAChD,0BAAsB;AAOd;AAJD,SAAS,SAAS,OAAoC;AAC3D,MAAI,MAAM,SAAS,YAAY;AAC7B,WACE,4CAAC,SAAI,WAAU,wFACb,sDAAC,6BAAM,WAAU,WAAU,GAC7B;AAAA,EAEJ;AACA,MAAI,MAAM,KAAK,iBAAiB;AAC9B,WACE,4CAAC,0BAAO,WAAU,2CAChB,sDAAC,+BAAY,KAAK,MAAM,KAAK,iBAAiB,KAAK,MAAM,KAAK,aAAa,GAC7E;AAAA,EAEJ,OAAO;AACL,WACE,4CAAC,SAAI,WAAU,wFACb,sDAAC,8BAAW,WAAU,oCAAoC,gBAAM,KAAK,YAAY,MAAM,GAAG,CAAC,EAAE,YAAY,GAAE,GAC7G;AAAA,EAEJ;AACF;","names":[]}