@hexclave/next 1.0.2 → 1.0.5
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.
- package/dist/components/api-key-dialogs.d.ts +1 -1
- package/dist/components/api-key-dialogs.js.map +1 -1
- package/dist/components/api-key-table.d.ts +1 -1
- package/dist/components/api-key-table.js.map +1 -1
- package/dist/components/credential-sign-in.js.map +1 -1
- package/dist/components/credential-sign-up.js.map +1 -1
- package/dist/components/elements/form-warning.js.map +1 -1
- package/dist/components/elements/maybe-full-page.js.map +1 -1
- package/dist/components/elements/separator-with-text.js.map +1 -1
- package/dist/components/elements/sidebar-layout.js.map +1 -1
- package/dist/components/elements/ssr-layout-effect.js.map +1 -1
- package/dist/components/elements/user-avatar.js.map +1 -1
- package/dist/components/link.js.map +1 -1
- package/dist/components/magic-link-sign-in.js +2 -2
- package/dist/components/magic-link-sign-in.js.map +1 -1
- package/dist/components/message-cards/known-error-message-card.js +2 -2
- package/dist/components/message-cards/known-error-message-card.js.map +1 -1
- package/dist/components/message-cards/message-card.js.map +1 -1
- package/dist/components/message-cards/predefined-message-card.js +9 -9
- package/dist/components/message-cards/predefined-message-card.js.map +1 -1
- package/dist/components/oauth-button-group.js +2 -2
- package/dist/components/oauth-button-group.js.map +1 -1
- package/dist/components/oauth-button.js +2 -2
- package/dist/components/oauth-button.js.map +1 -1
- package/dist/components/passkey-button.js +2 -2
- package/dist/components/passkey-button.js.map +1 -1
- package/dist/components/profile-image-editor.js.map +1 -1
- package/dist/components/selected-team-switcher.d.ts +1 -1
- package/dist/components/selected-team-switcher.js.map +1 -1
- package/dist/components/team-icon.d.ts +1 -1
- package/dist/components/team-icon.js.map +1 -1
- package/dist/components/team-switcher.d.ts +1 -1
- package/dist/components/team-switcher.js.map +1 -1
- package/dist/components/use-in-iframe.js.map +1 -1
- package/dist/components/user-button.js.map +1 -1
- package/dist/components-page/account-settings/active-sessions/active-sessions-page.js.map +1 -1
- package/dist/components-page/account-settings/api-keys/api-keys-page.js.map +1 -1
- package/dist/components-page/account-settings/editable-text.js.map +1 -1
- package/dist/components-page/account-settings/email-and-auth/email-and-auth-page.js.map +1 -1
- package/dist/components-page/account-settings/email-and-auth/emails-section.js.map +1 -1
- package/dist/components-page/account-settings/email-and-auth/mfa-section.js.map +1 -1
- package/dist/components-page/account-settings/email-and-auth/otp-section.js.map +1 -1
- package/dist/components-page/account-settings/email-and-auth/passkey-section.js.map +1 -1
- package/dist/components-page/account-settings/email-and-auth/password-section.js.map +1 -1
- package/dist/components-page/account-settings/notifications/notifications-page.js.map +1 -1
- package/dist/components-page/account-settings/page-layout.js.map +1 -1
- package/dist/components-page/account-settings/payments/payments-page.d.ts +1 -1
- package/dist/components-page/account-settings/payments/payments-page.js.map +1 -1
- package/dist/components-page/account-settings/payments/payments-panel.d.ts +1 -1
- package/dist/components-page/account-settings/payments/payments-panel.js +3 -3
- package/dist/components-page/account-settings/payments/payments-panel.js.map +1 -1
- package/dist/components-page/account-settings/profile-page/profile-page.js.map +1 -1
- package/dist/components-page/account-settings/section.js.map +1 -1
- package/dist/components-page/account-settings/settings/delete-account-section.js.map +1 -1
- package/dist/components-page/account-settings/settings/settings-page.js.map +1 -1
- package/dist/components-page/account-settings/settings/sign-out-section.js.map +1 -1
- package/dist/components-page/account-settings/teams/leave-team-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/leave-team-section.js.map +1 -1
- package/dist/components-page/account-settings/teams/team-api-keys-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-api-keys-section.js.map +1 -1
- package/dist/components-page/account-settings/teams/team-creation-page.js.map +1 -1
- package/dist/components-page/account-settings/teams/team-display-name-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-display-name-section.js.map +1 -1
- package/dist/components-page/account-settings/teams/team-member-invitation-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-member-invitation-section.js.map +1 -1
- package/dist/components-page/account-settings/teams/team-member-list-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-member-list-section.js.map +1 -1
- package/dist/components-page/account-settings/teams/team-page.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-page.js.map +1 -1
- package/dist/components-page/account-settings/teams/team-profile-image-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-profile-image-section.js.map +1 -1
- package/dist/components-page/account-settings/teams/team-profile-user-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-profile-user-section.js.map +1 -1
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/auth-page.d.ts.map +1 -1
- package/dist/components-page/auth-page.js +55 -10
- package/dist/components-page/auth-page.js.map +1 -1
- package/dist/components-page/cli-auth-confirm.js +3 -3
- package/dist/components-page/cli-auth-confirm.js.map +1 -1
- package/dist/components-page/cli-auth-confirm.test.js +4 -4
- package/dist/components-page/cli-auth-confirm.test.js.map +1 -1
- package/dist/components-page/email-verification.js +4 -4
- package/dist/components-page/email-verification.js.map +1 -1
- package/dist/components-page/error-page.js +9 -9
- package/dist/components-page/error-page.js.map +1 -1
- package/dist/components-page/forgot-password.js +4 -4
- package/dist/components-page/forgot-password.js.map +1 -1
- package/dist/components-page/{stack-handler-client.d.ts → hexclave-handler-client.d.ts} +4 -4
- package/dist/components-page/hexclave-handler-client.d.ts.map +1 -0
- package/dist/components-page/{stack-handler-client.js → hexclave-handler-client.js} +19 -18
- package/dist/components-page/hexclave-handler-client.js.map +1 -0
- package/dist/components-page/{stack-handler.d.ts → hexclave-handler.d.ts} +5 -5
- package/dist/components-page/hexclave-handler.d.ts.map +1 -0
- package/dist/components-page/{stack-handler.js → hexclave-handler.js} +4 -4
- package/dist/components-page/hexclave-handler.js.map +1 -0
- package/dist/components-page/magic-link-callback.js +7 -7
- package/dist/components-page/magic-link-callback.js.map +1 -1
- package/dist/components-page/mfa.js +4 -4
- package/dist/components-page/mfa.js.map +1 -1
- package/dist/components-page/oauth-callback.js +3 -3
- package/dist/components-page/oauth-callback.js.map +1 -1
- package/dist/components-page/onboarding.js +3 -3
- package/dist/components-page/onboarding.js.map +1 -1
- package/dist/components-page/password-reset.js +8 -8
- package/dist/components-page/password-reset.js.map +1 -1
- package/dist/components-page/sign-in.js.map +1 -1
- package/dist/components-page/sign-out.d.ts +1 -0
- package/dist/components-page/sign-out.d.ts.map +1 -1
- package/dist/components-page/sign-out.js +11 -5
- package/dist/components-page/sign-out.js.map +1 -1
- package/dist/components-page/sign-up.js.map +1 -1
- package/dist/components-page/team-creation.js.map +1 -1
- package/dist/components-page/team-invitation.js +16 -16
- package/dist/components-page/team-invitation.js.map +1 -1
- package/dist/dev-tool/dev-tool-core.d.ts +1 -1
- package/dist/dev-tool/dev-tool-core.js +11 -11
- package/dist/dev-tool/dev-tool-core.js.map +1 -1
- package/dist/dev-tool/dev-tool-styles.d.ts +1 -1
- package/dist/dev-tool/dev-tool-styles.js +371 -371
- package/dist/dev-tool/dev-tool-styles.js.map +1 -1
- package/dist/dev-tool/dev-tool-trigger-position.js.map +1 -1
- package/dist/dev-tool/dev-tool-trigger-position.test.js.map +1 -1
- package/dist/dev-tool/index.d.ts +4 -4
- package/dist/dev-tool/index.js +4 -4
- package/dist/dev-tool/index.js.map +1 -1
- package/dist/esm/components/api-key-dialogs.d.ts +1 -1
- package/dist/esm/components/api-key-dialogs.js.map +1 -1
- package/dist/esm/components/api-key-table.d.ts +1 -1
- package/dist/esm/components/api-key-table.js.map +1 -1
- package/dist/esm/components/credential-sign-in.js.map +1 -1
- package/dist/esm/components/credential-sign-up.js.map +1 -1
- package/dist/esm/components/elements/form-warning.js.map +1 -1
- package/dist/esm/components/elements/maybe-full-page.js.map +1 -1
- package/dist/esm/components/elements/separator-with-text.js.map +1 -1
- package/dist/esm/components/elements/sidebar-layout.js.map +1 -1
- package/dist/esm/components/elements/ssr-layout-effect.js.map +1 -1
- package/dist/esm/components/elements/user-avatar.js.map +1 -1
- package/dist/esm/components/link.js.map +1 -1
- package/dist/esm/components/magic-link-sign-in.js +2 -2
- package/dist/esm/components/magic-link-sign-in.js.map +1 -1
- package/dist/esm/components/message-cards/known-error-message-card.js +2 -2
- package/dist/esm/components/message-cards/known-error-message-card.js.map +1 -1
- package/dist/esm/components/message-cards/message-card.js.map +1 -1
- package/dist/esm/components/message-cards/predefined-message-card.js +9 -9
- package/dist/esm/components/message-cards/predefined-message-card.js.map +1 -1
- package/dist/esm/components/oauth-button-group.js +2 -2
- package/dist/esm/components/oauth-button-group.js.map +1 -1
- package/dist/esm/components/oauth-button.js +2 -2
- package/dist/esm/components/oauth-button.js.map +1 -1
- package/dist/esm/components/passkey-button.js +2 -2
- package/dist/esm/components/passkey-button.js.map +1 -1
- package/dist/esm/components/profile-image-editor.js.map +1 -1
- package/dist/esm/components/selected-team-switcher.js.map +1 -1
- package/dist/esm/components/team-icon.js.map +1 -1
- package/dist/esm/components/team-switcher.js.map +1 -1
- package/dist/esm/components/use-in-iframe.js.map +1 -1
- package/dist/esm/components/user-button.js.map +1 -1
- package/dist/esm/components-page/account-settings/active-sessions/active-sessions-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/api-keys/api-keys-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/editable-text.js.map +1 -1
- package/dist/esm/components-page/account-settings/email-and-auth/email-and-auth-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/email-and-auth/emails-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/email-and-auth/mfa-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/email-and-auth/otp-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/email-and-auth/passkey-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/email-and-auth/password-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/notifications/notifications-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/page-layout.js.map +1 -1
- package/dist/esm/components-page/account-settings/payments/payments-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/payments/payments-panel.d.ts +1 -1
- package/dist/esm/components-page/account-settings/payments/payments-panel.js +3 -3
- package/dist/esm/components-page/account-settings/payments/payments-panel.js.map +1 -1
- package/dist/esm/components-page/account-settings/profile-page/profile-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/section.js.map +1 -1
- package/dist/esm/components-page/account-settings/settings/delete-account-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/settings/settings-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/settings/sign-out-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/leave-team-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/team-api-keys-section.d.ts +1 -1
- package/dist/esm/components-page/account-settings/teams/team-api-keys-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/team-creation-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/team-display-name-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/team-member-invitation-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/team-member-list-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/team-page.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/team-profile-image-section.js.map +1 -1
- package/dist/esm/components-page/account-settings/teams/team-profile-user-section.js.map +1 -1
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/auth-page.d.ts.map +1 -1
- package/dist/esm/components-page/auth-page.js +56 -11
- package/dist/esm/components-page/auth-page.js.map +1 -1
- package/dist/esm/components-page/cli-auth-confirm.js +3 -3
- package/dist/esm/components-page/cli-auth-confirm.js.map +1 -1
- package/dist/esm/components-page/cli-auth-confirm.test.js +4 -4
- package/dist/esm/components-page/cli-auth-confirm.test.js.map +1 -1
- package/dist/esm/components-page/email-verification.js +4 -4
- package/dist/esm/components-page/email-verification.js.map +1 -1
- package/dist/esm/components-page/error-page.js +9 -9
- package/dist/esm/components-page/error-page.js.map +1 -1
- package/dist/esm/components-page/forgot-password.js +4 -4
- package/dist/esm/components-page/forgot-password.js.map +1 -1
- package/dist/esm/components-page/{stack-handler-client.d.ts → hexclave-handler-client.d.ts} +4 -4
- package/dist/esm/components-page/hexclave-handler-client.d.ts.map +1 -0
- package/dist/esm/components-page/{stack-handler-client.js → hexclave-handler-client.js} +17 -16
- package/dist/esm/components-page/hexclave-handler-client.js.map +1 -0
- package/dist/esm/components-page/{stack-handler.d.ts → hexclave-handler.d.ts} +5 -5
- package/dist/esm/components-page/hexclave-handler.d.ts.map +1 -0
- package/dist/esm/components-page/{stack-handler.js → hexclave-handler.js} +4 -4
- package/dist/esm/components-page/hexclave-handler.js.map +1 -0
- package/dist/esm/components-page/magic-link-callback.js +7 -7
- package/dist/esm/components-page/magic-link-callback.js.map +1 -1
- package/dist/esm/components-page/mfa.js +4 -4
- package/dist/esm/components-page/mfa.js.map +1 -1
- package/dist/esm/components-page/oauth-callback.js +3 -3
- package/dist/esm/components-page/oauth-callback.js.map +1 -1
- package/dist/esm/components-page/onboarding.js +3 -3
- package/dist/esm/components-page/onboarding.js.map +1 -1
- package/dist/esm/components-page/password-reset.js +8 -8
- package/dist/esm/components-page/password-reset.js.map +1 -1
- package/dist/esm/components-page/sign-in.js.map +1 -1
- package/dist/esm/components-page/sign-out.d.ts +1 -0
- package/dist/esm/components-page/sign-out.d.ts.map +1 -1
- package/dist/esm/components-page/sign-out.js +11 -5
- package/dist/esm/components-page/sign-out.js.map +1 -1
- package/dist/esm/components-page/sign-up.js.map +1 -1
- package/dist/esm/components-page/team-creation.js.map +1 -1
- package/dist/esm/components-page/team-invitation.js +16 -16
- package/dist/esm/components-page/team-invitation.js.map +1 -1
- package/dist/esm/dev-tool/dev-tool-core.d.ts +1 -1
- package/dist/esm/dev-tool/dev-tool-core.js +10 -10
- package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
- package/dist/esm/dev-tool/dev-tool-styles.d.ts +1 -1
- package/dist/esm/dev-tool/dev-tool-styles.js +371 -371
- package/dist/esm/dev-tool/dev-tool-styles.js.map +1 -1
- package/dist/esm/dev-tool/dev-tool-trigger-position.js.map +1 -1
- package/dist/esm/dev-tool/dev-tool-trigger-position.test.js.map +1 -1
- package/dist/esm/dev-tool/index.d.ts +4 -4
- package/dist/esm/dev-tool/index.js +4 -4
- package/dist/esm/dev-tool/index.js.map +1 -1
- package/dist/esm/generated/global-css.d.ts +1 -1
- package/dist/esm/generated/global-css.js +1 -1
- package/dist/esm/generated/global-css.js.map +1 -1
- package/dist/esm/generated/quetzal-translations.d.ts +2 -2
- package/dist/esm/generated/quetzal-translations.js.map +1 -1
- package/dist/esm/index.d.ts +4 -4
- package/dist/esm/index.js +3 -3
- package/dist/esm/integrations/convex/component/convex.config.js.map +1 -1
- package/dist/esm/integrations/convex.js +1 -1
- package/dist/esm/integrations/convex.js.map +1 -1
- package/dist/esm/lib/auth.js.map +1 -1
- package/dist/esm/lib/auth.test.js.map +1 -1
- package/dist/esm/lib/cookie.js +2 -2
- package/dist/esm/lib/cookie.js.map +1 -1
- package/dist/esm/lib/env.js.map +1 -1
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/api-keys/index.d.ts +2 -2
- package/dist/esm/lib/hexclave-app/api-keys/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/api-keys/index.js +1 -1
- package/dist/esm/lib/hexclave-app/api-keys/index.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/admin-app-impl.d.ts +6 -6
- package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/admin-app-impl.js +7 -7
- package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.cross-domain.test.js +2 -2
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.d.ts +13 -13
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.js +23 -30
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.oauth-prefetch.test.js +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.oauth-prefetch.test.js.map +1 -0
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/apps/implementations/common.d.ts +4 -4
- package/dist/esm/lib/hexclave-app/apps/implementations/common.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/common.js +7 -7
- package/dist/esm/lib/hexclave-app/apps/implementations/common.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/event-tracker.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/event-tracker.js +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/event-tracker.test.js +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.test.js.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/index.d.ts +9 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/index.d.ts.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/index.js +27 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/index.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/redirect-page-urls.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/redirect-page-urls.js +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/server-app-impl.d.ts +4 -4
- package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/server-app-impl.js +6 -6
- package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -0
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/apps/implementations/session-refresh-subscription.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/session-refresh-subscription.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/session-refresh-subscription.js +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/session-refresh-subscription.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/session-refresh-subscription.test.js +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/session-refresh-subscription.test.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/session-replay.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/session-replay.js +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/session-replay.test.js +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.test.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/interfaces/admin-app.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/interfaces/admin-app.js +3 -3
- package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/interfaces/client-app.d.ts +4 -4
- package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/interfaces/client-app.js +3 -3
- package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/interfaces/server-app.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/apps/interfaces/server-app.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/apps/interfaces/server-app.js +3 -3
- package/dist/esm/lib/hexclave-app/apps/interfaces/server-app.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/common.d.ts +7 -7
- package/dist/esm/lib/hexclave-app/common.d.ts.map +1 -0
- package/dist/esm/lib/hexclave-app/common.js +7 -0
- package/dist/esm/lib/hexclave-app/common.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/connected-accounts/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/connected-accounts/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/contact-channels/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/contact-channels/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/contact-channels/index.js +1 -1
- package/dist/esm/lib/hexclave-app/contact-channels/index.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/customers/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/customers/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/data-vault/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/data-vault/index.d.ts.map +1 -0
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/email/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/email/index.d.ts.map +1 -0
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/email-templates/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/email-templates/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/email-templates/index.js +1 -1
- package/dist/esm/lib/hexclave-app/email-templates/index.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/index.d.ts +2 -2
- package/dist/esm/lib/{stack-app → hexclave-app}/index.js +2 -2
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/internal-api-keys/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/internal-api-keys/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/internal-api-keys/index.js +1 -1
- package/dist/esm/lib/hexclave-app/internal-api-keys/index.js.map +1 -0
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/notification-categories/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/notification-categories/index.d.ts.map +1 -0
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/permissions/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/permissions/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/permissions/index.js +1 -1
- package/dist/esm/lib/hexclave-app/permissions/index.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/project-configs/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/project-configs/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/projects/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/projects/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/projects/index.js +1 -1
- package/dist/esm/lib/hexclave-app/projects/index.js.map +1 -0
- package/dist/{lib/stack-app → esm/lib/hexclave-app}/session-replays/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/session-replays/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/teams/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/teams/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/teams/index.js +1 -1
- package/dist/esm/lib/hexclave-app/teams/index.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/url-targets.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/url-targets.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/url-targets.js +2 -2
- package/dist/esm/lib/hexclave-app/url-targets.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/url-targets.test.js +1 -1
- package/dist/esm/lib/hexclave-app/url-targets.test.js.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/users/index.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/users/index.d.ts.map +1 -0
- package/dist/esm/lib/{stack-app → hexclave-app}/users/index.js +1 -1
- package/dist/esm/lib/hexclave-app/users/index.js.map +1 -0
- package/dist/esm/lib/hooks.d.ts +1 -1
- package/dist/esm/lib/hooks.js +9 -9
- package/dist/esm/lib/hooks.js.map +1 -1
- package/dist/esm/lib/translations.js.map +1 -1
- package/dist/esm/providers/hexclave-context.d.ts +11 -0
- package/dist/esm/providers/hexclave-context.d.ts.map +1 -0
- package/dist/esm/providers/hexclave-context.js +12 -0
- package/dist/esm/providers/hexclave-context.js.map +1 -0
- package/dist/esm/providers/{stack-provider-client.d.ts → hexclave-provider-client.d.ts} +5 -5
- package/dist/esm/providers/hexclave-provider-client.d.ts.map +1 -0
- package/dist/esm/providers/hexclave-provider-client.js +30 -0
- package/dist/esm/providers/hexclave-provider-client.js.map +1 -0
- package/dist/esm/providers/{stack-provider.d.ts → hexclave-provider.d.ts} +3 -3
- package/dist/esm/providers/hexclave-provider.d.ts.map +1 -0
- package/dist/esm/providers/{stack-provider.js → hexclave-provider.js} +6 -6
- package/dist/esm/providers/hexclave-provider.js.map +1 -0
- package/dist/esm/providers/theme-provider.js.map +1 -1
- package/dist/esm/providers/translation-provider-client.js.map +1 -1
- package/dist/esm/providers/translation-provider.js.map +1 -1
- package/dist/esm/tanstack-start-server-context.d.ts +1 -1
- package/dist/esm/utils/browser-script.js.map +1 -1
- package/dist/esm/utils/constants.js.map +1 -1
- package/dist/esm/utils/url.js.map +1 -1
- package/dist/generated/global-css.d.ts +1 -1
- package/dist/generated/global-css.js +1 -1
- package/dist/generated/global-css.js.map +1 -1
- package/dist/generated/quetzal-translations.d.ts +2 -2
- package/dist/generated/quetzal-translations.js.map +1 -1
- package/dist/index.d.ts +18 -18
- package/dist/index.js +9 -9
- package/dist/integrations/convex/component/convex.config.d.ts +2 -2
- package/dist/integrations/convex/component/convex.config.d.ts.map +1 -1
- package/dist/integrations/convex/component/convex.config.js.map +1 -1
- package/dist/integrations/convex.js +2 -2
- package/dist/integrations/convex.js.map +1 -1
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/auth.test.js.map +1 -1
- package/dist/lib/cookie.js +2 -2
- package/dist/lib/cookie.js.map +1 -1
- package/dist/lib/env.js.map +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/api-keys/index.d.ts +2 -2
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/api-keys/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/api-keys/index.js +1 -1
- package/dist/lib/hexclave-app/api-keys/index.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/admin-app-impl.d.ts +6 -6
- package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/admin-app-impl.js +5 -5
- package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.cross-domain.test.js +2 -2
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.d.ts +13 -13
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.js +22 -29
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.oauth-prefetch.test.js +1 -1
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.oauth-prefetch.test.js.map +1 -0
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/implementations/common.d.ts +4 -4
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/implementations/common.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/common.js +6 -6
- package/dist/lib/hexclave-app/apps/implementations/common.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/event-tracker.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/implementations/event-tracker.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/event-tracker.js +1 -1
- package/dist/lib/hexclave-app/apps/implementations/event-tracker.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/event-tracker.test.js +1 -1
- package/dist/lib/hexclave-app/apps/implementations/event-tracker.test.js.map +1 -0
- package/dist/lib/hexclave-app/apps/implementations/index.d.ts +9 -0
- package/dist/lib/hexclave-app/apps/implementations/index.d.ts.map +1 -0
- package/dist/lib/hexclave-app/apps/implementations/index.js +31 -0
- package/dist/lib/hexclave-app/apps/implementations/index.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/redirect-page-urls.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/implementations/redirect-page-urls.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/redirect-page-urls.js +1 -1
- package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/server-app-impl.d.ts +4 -4
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/implementations/server-app-impl.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/server-app-impl.js +5 -5
- package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -0
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/implementations/session-refresh-subscription.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/implementations/session-refresh-subscription.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/session-refresh-subscription.js +1 -1
- package/dist/lib/hexclave-app/apps/implementations/session-refresh-subscription.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/session-refresh-subscription.test.js +1 -1
- package/dist/lib/hexclave-app/apps/implementations/session-refresh-subscription.test.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/session-replay.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/implementations/session-replay.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/session-replay.js +1 -1
- package/dist/lib/hexclave-app/apps/implementations/session-replay.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/implementations/session-replay.test.js +1 -1
- package/dist/lib/hexclave-app/apps/implementations/session-replay.test.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/interfaces/admin-app.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/interfaces/admin-app.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/interfaces/admin-app.js +2 -2
- package/dist/lib/hexclave-app/apps/interfaces/admin-app.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/interfaces/client-app.d.ts +4 -4
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/interfaces/client-app.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/interfaces/client-app.js +2 -2
- package/dist/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/apps/interfaces/server-app.d.ts +2 -2
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/apps/interfaces/server-app.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/apps/interfaces/server-app.js +2 -2
- package/dist/lib/hexclave-app/apps/interfaces/server-app.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/common.d.ts +8 -8
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/common.d.ts.map +1 -1
- package/dist/lib/hexclave-app/common.js +9 -0
- package/dist/lib/hexclave-app/common.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/connected-accounts/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/connected-accounts/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/contact-channels/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/contact-channels/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/contact-channels/index.js +1 -1
- package/dist/lib/hexclave-app/contact-channels/index.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/customers/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/customers/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/data-vault/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/data-vault/index.d.ts.map +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/email/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/email/index.d.ts.map +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/email-templates/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/email-templates/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/email-templates/index.js +1 -1
- package/dist/lib/hexclave-app/email-templates/index.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/index.d.ts +2 -2
- package/dist/lib/{stack-app → hexclave-app}/index.js +2 -2
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/internal-api-keys/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/internal-api-keys/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/internal-api-keys/index.js +1 -1
- package/dist/lib/hexclave-app/internal-api-keys/index.js.map +1 -0
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/notification-categories/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/notification-categories/index.d.ts.map +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/permissions/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/permissions/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/permissions/index.js +1 -1
- package/dist/lib/hexclave-app/permissions/index.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/project-configs/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/project-configs/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/projects/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/projects/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/projects/index.js +1 -1
- package/dist/lib/hexclave-app/projects/index.js.map +1 -0
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/session-replays/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/session-replays/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/teams/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/teams/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/teams/index.js +1 -1
- package/dist/lib/hexclave-app/teams/index.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/url-targets.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/url-targets.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/url-targets.js +2 -2
- package/dist/lib/hexclave-app/url-targets.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/url-targets.test.js +1 -1
- package/dist/lib/hexclave-app/url-targets.test.js.map +1 -0
- package/dist/lib/{stack-app → hexclave-app}/users/index.d.ts +1 -1
- package/dist/{esm/lib/stack-app → lib/hexclave-app}/users/index.d.ts.map +1 -1
- package/dist/lib/{stack-app → hexclave-app}/users/index.js +1 -1
- package/dist/lib/hexclave-app/users/index.js.map +1 -0
- package/dist/lib/hooks.d.ts +3 -3
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/hooks.js +9 -9
- package/dist/lib/hooks.js.map +1 -1
- package/dist/lib/translations.js.map +1 -1
- package/dist/providers/hexclave-context.d.ts +11 -0
- package/dist/providers/hexclave-context.d.ts.map +1 -0
- package/dist/providers/hexclave-context.js +15 -0
- package/dist/providers/hexclave-context.js.map +1 -0
- package/dist/providers/{stack-provider-client.d.ts → hexclave-provider-client.d.ts} +5 -5
- package/dist/providers/hexclave-provider-client.d.ts.map +1 -0
- package/dist/providers/{stack-provider-client.js → hexclave-provider-client.js} +9 -9
- package/dist/providers/hexclave-provider-client.js.map +1 -0
- package/dist/providers/{stack-provider.d.ts → hexclave-provider.d.ts} +5 -5
- package/dist/providers/hexclave-provider.d.ts.map +1 -0
- package/dist/providers/{stack-provider.js → hexclave-provider.js} +6 -6
- package/dist/providers/hexclave-provider.js.map +1 -0
- package/dist/providers/theme-provider.js.map +1 -1
- package/dist/providers/translation-provider-client.js.map +1 -1
- package/dist/providers/translation-provider.js.map +1 -1
- package/dist/{storage-kTmOAWHW.d.ts → storage-CKzvsBxG.d.ts} +18 -18
- package/dist/{storage-kTmOAWHW.d.ts.map → storage-CKzvsBxG.d.ts.map} +1 -1
- package/dist/tanstack-start-server-context.d.ts +1 -1
- package/dist/utils/browser-script.js.map +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/url.js.map +1 -1
- package/package.json +6 -5
- package/src/components/api-key-dialogs.tsx +173 -0
- package/src/components/api-key-table.tsx +127 -0
- package/src/components/credential-sign-in.tsx +83 -0
- package/src/components/credential-sign-up.tsx +108 -0
- package/src/components/elements/form-warning.tsx +17 -0
- package/src/components/elements/maybe-full-page.tsx +60 -0
- package/src/components/elements/separator-with-text.tsx +22 -0
- package/src/components/elements/sidebar-layout.tsx +136 -0
- package/src/components/elements/ssr-layout-effect.tsx +24 -0
- package/src/components/elements/user-avatar.tsx +32 -0
- package/src/components/link.tsx +40 -0
- package/src/components/magic-link-sign-in.tsx +143 -0
- package/src/components/message-cards/known-error-message-card.tsx +33 -0
- package/src/components/message-cards/message-card.tsx +46 -0
- package/src/components/message-cards/predefined-message-card.tsx +88 -0
- package/src/components/oauth-button-group.tsx +35 -0
- package/src/components/oauth-button.tsx +222 -0
- package/src/components/passkey-button.tsx +43 -0
- package/src/components/profile-image-editor.tsx +194 -0
- package/src/components/selected-team-switcher.tsx +97 -0
- package/src/components/team-icon.tsx +30 -0
- package/src/components/team-switcher.tsx +191 -0
- package/src/components/use-in-iframe.tsx +18 -0
- package/src/components/user-button.tsx +157 -0
- package/src/components-page/account-settings/active-sessions/active-sessions-page.tsx +238 -0
- package/src/components-page/account-settings/api-keys/api-keys-page.tsx +157 -0
- package/src/components-page/account-settings/editable-text.tsx +53 -0
- package/src/components-page/account-settings/email-and-auth/email-and-auth-page.tsx +24 -0
- package/src/components-page/account-settings/email-and-auth/emails-section.tsx +201 -0
- package/src/components-page/account-settings/email-and-auth/mfa-section.tsx +139 -0
- package/src/components-page/account-settings/email-and-auth/otp-section.tsx +102 -0
- package/src/components-page/account-settings/email-and-auth/passkey-section.tsx +112 -0
- package/src/components-page/account-settings/email-and-auth/password-section.tsx +174 -0
- package/src/components-page/account-settings/notifications/notifications-page.tsx +44 -0
- package/src/components-page/account-settings/page-layout.tsx +11 -0
- package/src/components-page/account-settings/payments/payments-page.tsx +73 -0
- package/src/components-page/account-settings/payments/payments-panel.tsx +543 -0
- package/src/components-page/account-settings/profile-page/profile-page.tsx +61 -0
- package/src/components-page/account-settings/section.tsx +26 -0
- package/src/components-page/account-settings/settings/delete-account-section.tsx +85 -0
- package/src/components-page/account-settings/settings/settings-page.tsx +19 -0
- package/src/components-page/account-settings/settings/sign-out-section.tsx +40 -0
- package/src/components-page/account-settings/teams/leave-team-section.tsx +57 -0
- package/src/components-page/account-settings/teams/team-api-keys-section.tsx +74 -0
- package/src/components-page/account-settings/teams/team-creation-page.tsx +92 -0
- package/src/components-page/account-settings/teams/team-display-name-section.tsx +31 -0
- package/src/components-page/account-settings/teams/team-member-invitation-section.tsx +128 -0
- package/src/components-page/account-settings/teams/team-member-list-section.tsx +59 -0
- package/src/components-page/account-settings/teams/team-page.tsx +28 -0
- package/src/components-page/account-settings/teams/team-profile-image-section.tsx +33 -0
- package/src/components-page/account-settings/teams/team-profile-user-section.tsx +29 -0
- package/src/components-page/account-settings.tsx +343 -0
- package/src/components-page/auth-page.tsx +206 -0
- package/src/components-page/cli-auth-confirm.test.tsx +204 -0
- package/src/components-page/cli-auth-confirm.tsx +278 -0
- package/src/components-page/email-verification.tsx +76 -0
- package/src/components-page/error-page.tsx +105 -0
- package/src/components-page/forgot-password.tsx +105 -0
- package/src/components-page/hexclave-handler-client.tsx +325 -0
- package/src/components-page/hexclave-handler.tsx +48 -0
- package/src/components-page/magic-link-callback.tsx +92 -0
- package/src/components-page/mfa.tsx +222 -0
- package/src/components-page/oauth-callback.tsx +78 -0
- package/src/components-page/onboarding.tsx +176 -0
- package/src/components-page/password-reset.tsx +185 -0
- package/src/components-page/section.tsx +27 -0
- package/src/components-page/sign-in.tsx +34 -0
- package/src/components-page/sign-out.tsx +37 -0
- package/src/components-page/sign-up.tsx +24 -0
- package/src/components-page/team-creation.tsx +78 -0
- package/src/components-page/team-invitation.tsx +150 -0
- package/src/dev-tool/dev-tool-core.ts +2460 -0
- package/src/dev-tool/dev-tool-styles.ts +2758 -0
- package/src/dev-tool/dev-tool-trigger-position.test.ts +113 -0
- package/src/dev-tool/dev-tool-trigger-position.ts +109 -0
- package/src/dev-tool/index.ts +149 -0
- package/src/generated/.gitignore +3 -0
- package/src/generated/quetzal-translations.ts +4312 -0
- package/src/global.css +13 -0
- package/src/global.d.ts +5 -0
- package/src/index.ts +39 -0
- package/src/integrations/convex/component/README.md +74 -0
- package/src/integrations/convex/component/convex.config.ts +9 -0
- package/src/integrations/convex.ts +28 -0
- package/src/lib/auth.test.ts +67 -0
- package/src/lib/auth.ts +175 -0
- package/src/lib/cookie.ts +421 -0
- package/src/lib/env.ts +93 -0
- package/src/lib/hexclave-app/api-keys/index.ts +73 -0
- package/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts +1261 -0
- package/src/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.ts +141 -0
- package/src/lib/hexclave-app/apps/implementations/client-app-impl.oauth-prefetch.test.ts +36 -0
- package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +3912 -0
- package/src/lib/hexclave-app/apps/implementations/common.ts +244 -0
- package/src/lib/hexclave-app/apps/implementations/event-tracker.test.ts +105 -0
- package/src/lib/hexclave-app/apps/implementations/event-tracker.ts +306 -0
- package/src/lib/hexclave-app/apps/implementations/index.ts +35 -0
- package/src/lib/hexclave-app/apps/implementations/redirect-page-urls.ts +342 -0
- package/src/lib/hexclave-app/apps/implementations/server-app-impl.ts +1619 -0
- package/src/lib/hexclave-app/apps/implementations/session-refresh-subscription.test.ts +106 -0
- package/src/lib/hexclave-app/apps/implementations/session-refresh-subscription.ts +52 -0
- package/src/lib/hexclave-app/apps/implementations/session-replay.test.ts +33 -0
- package/src/lib/hexclave-app/apps/implementations/session-replay.ts +356 -0
- package/src/lib/hexclave-app/apps/index.ts +40 -0
- package/src/lib/hexclave-app/apps/interfaces/admin-app.ts +192 -0
- package/src/lib/hexclave-app/apps/interfaces/client-app.ts +180 -0
- package/src/lib/hexclave-app/apps/interfaces/server-app.ts +129 -0
- package/src/lib/hexclave-app/common.ts +216 -0
- package/src/lib/hexclave-app/connected-accounts/index.ts +49 -0
- package/src/lib/hexclave-app/contact-channels/index.ts +80 -0
- package/src/lib/hexclave-app/customers/index.ts +158 -0
- package/src/lib/hexclave-app/data-vault/index.ts +12 -0
- package/src/lib/hexclave-app/email/index.ts +280 -0
- package/src/lib/hexclave-app/email-templates/index.ts +24 -0
- package/src/lib/hexclave-app/index.ts +146 -0
- package/src/lib/hexclave-app/internal-api-keys/index.ts +55 -0
- package/src/lib/hexclave-app/notification-categories/index.ts +12 -0
- package/src/lib/hexclave-app/permissions/index.ts +75 -0
- package/src/lib/hexclave-app/project-configs/index.ts +103 -0
- package/src/lib/hexclave-app/projects/index.ts +236 -0
- package/src/lib/hexclave-app/session-replays/index.ts +72 -0
- package/src/lib/hexclave-app/teams/index.ts +206 -0
- package/src/lib/hexclave-app/url-targets.test.ts +253 -0
- package/src/lib/hexclave-app/url-targets.ts +395 -0
- package/src/lib/hexclave-app/users/index.ts +523 -0
- package/src/lib/hooks.tsx +63 -0
- package/src/lib/translations.tsx +23 -0
- package/src/providers/hexclave-context.tsx +20 -0
- package/src/providers/hexclave-provider-client.tsx +39 -0
- package/src/providers/hexclave-provider.tsx +48 -0
- package/src/providers/theme-provider.tsx +121 -0
- package/src/providers/translation-provider-client.tsx +35 -0
- package/src/providers/translation-provider.tsx +25 -0
- package/src/tanstack-start-server-context.d.ts +13 -0
- package/src/utils/browser-script.tsx +135 -0
- package/src/utils/constants.tsx +58 -0
- package/src/utils/url.ts +24 -0
- package/dist/components-page/stack-handler-client.d.ts.map +0 -1
- package/dist/components-page/stack-handler-client.js.map +0 -1
- package/dist/components-page/stack-handler.d.ts.map +0 -1
- package/dist/components-page/stack-handler.js.map +0 -1
- package/dist/esm/components-page/stack-handler-client.d.ts.map +0 -1
- package/dist/esm/components-page/stack-handler-client.js.map +0 -1
- package/dist/esm/components-page/stack-handler.d.ts.map +0 -1
- package/dist/esm/components-page/stack-handler.js.map +0 -1
- package/dist/esm/lib/stack-app/api-keys/index.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.d.ts.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.cross-domain.test.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.d.ts.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.oauth-prefetch.test.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/event-tracker.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/event-tracker.test.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/index.d.ts +0 -9
- package/dist/esm/lib/stack-app/apps/implementations/index.d.ts.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/index.js +0 -27
- package/dist/esm/lib/stack-app/apps/implementations/index.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/redirect-page-urls.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/session-refresh-subscription.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/session-refresh-subscription.test.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/session-replay.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/implementations/session-replay.test.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +0 -1
- package/dist/esm/lib/stack-app/apps/interfaces/server-app.js.map +0 -1
- package/dist/esm/lib/stack-app/common.js +0 -7
- package/dist/esm/lib/stack-app/common.js.map +0 -1
- package/dist/esm/lib/stack-app/contact-channels/index.js.map +0 -1
- package/dist/esm/lib/stack-app/email-templates/index.js.map +0 -1
- package/dist/esm/lib/stack-app/internal-api-keys/index.js.map +0 -1
- package/dist/esm/lib/stack-app/permissions/index.js.map +0 -1
- package/dist/esm/lib/stack-app/projects/index.js.map +0 -1
- package/dist/esm/lib/stack-app/teams/index.js.map +0 -1
- package/dist/esm/lib/stack-app/url-targets.js.map +0 -1
- package/dist/esm/lib/stack-app/url-targets.test.js.map +0 -1
- package/dist/esm/lib/stack-app/users/index.js.map +0 -1
- package/dist/esm/providers/stack-context.d.ts +0 -11
- package/dist/esm/providers/stack-context.d.ts.map +0 -1
- package/dist/esm/providers/stack-context.js +0 -12
- package/dist/esm/providers/stack-context.js.map +0 -1
- package/dist/esm/providers/stack-provider-client.d.ts.map +0 -1
- package/dist/esm/providers/stack-provider-client.js +0 -30
- package/dist/esm/providers/stack-provider-client.js.map +0 -1
- package/dist/esm/providers/stack-provider.d.ts.map +0 -1
- package/dist/esm/providers/stack-provider.js.map +0 -1
- package/dist/lib/stack-app/api-keys/index.d.ts.map +0 -1
- package/dist/lib/stack-app/api-keys/index.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.cross-domain.test.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.oauth-prefetch.test.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/common.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/common.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/event-tracker.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/event-tracker.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/event-tracker.test.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/index.d.ts +0 -9
- package/dist/lib/stack-app/apps/implementations/index.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/index.js +0 -31
- package/dist/lib/stack-app/apps/implementations/index.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/redirect-page-urls.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/redirect-page-urls.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/session-refresh-subscription.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/session-refresh-subscription.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/session-refresh-subscription.test.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/session-replay.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/implementations/session-replay.js.map +0 -1
- package/dist/lib/stack-app/apps/implementations/session-replay.test.js.map +0 -1
- package/dist/lib/stack-app/apps/interfaces/admin-app.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +0 -1
- package/dist/lib/stack-app/apps/interfaces/client-app.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/interfaces/client-app.js.map +0 -1
- package/dist/lib/stack-app/apps/interfaces/server-app.d.ts.map +0 -1
- package/dist/lib/stack-app/apps/interfaces/server-app.js.map +0 -1
- package/dist/lib/stack-app/common.d.ts.map +0 -1
- package/dist/lib/stack-app/common.js +0 -9
- package/dist/lib/stack-app/common.js.map +0 -1
- package/dist/lib/stack-app/connected-accounts/index.d.ts.map +0 -1
- package/dist/lib/stack-app/contact-channels/index.d.ts.map +0 -1
- package/dist/lib/stack-app/contact-channels/index.js.map +0 -1
- package/dist/lib/stack-app/customers/index.d.ts.map +0 -1
- package/dist/lib/stack-app/data-vault/index.d.ts.map +0 -1
- package/dist/lib/stack-app/email/index.d.ts.map +0 -1
- package/dist/lib/stack-app/email-templates/index.d.ts.map +0 -1
- package/dist/lib/stack-app/email-templates/index.js.map +0 -1
- package/dist/lib/stack-app/internal-api-keys/index.d.ts.map +0 -1
- package/dist/lib/stack-app/internal-api-keys/index.js.map +0 -1
- package/dist/lib/stack-app/notification-categories/index.d.ts.map +0 -1
- package/dist/lib/stack-app/permissions/index.d.ts.map +0 -1
- package/dist/lib/stack-app/permissions/index.js.map +0 -1
- package/dist/lib/stack-app/project-configs/index.d.ts.map +0 -1
- package/dist/lib/stack-app/projects/index.d.ts.map +0 -1
- package/dist/lib/stack-app/projects/index.js.map +0 -1
- package/dist/lib/stack-app/session-replays/index.d.ts.map +0 -1
- package/dist/lib/stack-app/teams/index.d.ts.map +0 -1
- package/dist/lib/stack-app/teams/index.js.map +0 -1
- package/dist/lib/stack-app/url-targets.d.ts.map +0 -1
- package/dist/lib/stack-app/url-targets.js.map +0 -1
- package/dist/lib/stack-app/url-targets.test.js.map +0 -1
- package/dist/lib/stack-app/users/index.d.ts.map +0 -1
- package/dist/lib/stack-app/users/index.js.map +0 -1
- package/dist/providers/stack-context.d.ts +0 -11
- package/dist/providers/stack-context.d.ts.map +0 -1
- package/dist/providers/stack-context.js +0 -15
- package/dist/providers/stack-context.js.map +0 -1
- package/dist/providers/stack-provider-client.d.ts.map +0 -1
- package/dist/providers/stack-provider-client.js.map +0 -1
- package/dist/providers/stack-provider.d.ts.map +0 -1
- package/dist/providers/stack-provider.js.map +0 -1
- /package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.cross-domain.test.d.ts +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.oauth-prefetch.test.d.ts +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/event-tracker.test.d.ts +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/session-refresh-subscription.test.d.ts +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/apps/implementations/session-replay.test.d.ts +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/apps/index.d.ts +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/apps/index.js +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/connected-accounts/index.js +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/customers/index.js +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/data-vault/index.js +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/email/index.js +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/notification-categories/index.js +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/project-configs/index.js +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/session-replays/index.js +0 -0
- /package/dist/esm/lib/{stack-app → hexclave-app}/url-targets.test.d.ts +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.cross-domain.test.d.ts +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/apps/implementations/client-app-impl.oauth-prefetch.test.d.ts +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/apps/implementations/event-tracker.test.d.ts +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/apps/implementations/session-refresh-subscription.test.d.ts +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/apps/implementations/session-replay.test.d.ts +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/apps/index.d.ts +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/apps/index.js +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/connected-accounts/index.js +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/customers/index.js +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/data-vault/index.js +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/email/index.js +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/notification-categories/index.js +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/project-configs/index.js +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/session-replays/index.js +0 -0
- /package/dist/lib/{stack-app → hexclave-app}/url-targets.test.d.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-image-editor.js","names":["UserAvatar","Upload","Typography","Cropper","Slider","Button","imageCompression"],"sources":["../../src/components/profile-image-editor.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"profile-image-editor.js","names":["UserAvatar","Upload","Typography","Cropper","Slider","Button","imageCompression"],"sources":["../../src/components/profile-image-editor.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { fileToBase64 } from '@hexclave/shared/dist/utils/base64';\nimport { runAsynchronouslyWithAlert } from '@hexclave/shared/dist/utils/promises';\nimport { Button, Slider, Typography } from '@hexclave/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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selected-team-switcher.js","names":["Suspense","Skeleton","TeamSwitcher"],"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
|
|
1
|
+
{"version":3,"file":"selected-team-switcher.js","names":["Suspense","Skeleton","TeamSwitcher"],"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 UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport {\n Skeleton,\n} from \"@hexclave/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":";;;;;;;;;;;;AAwCA,SAAgB,qBAAwD,OAA6C;AACnH,QAAO,2CAACA;EAAS,UAAU,2CAAC,aAAW;YACrC,2CAAC,SAAM,GAAI,QAAS;GACX;;AAGb,SAAS,WAAW;AAClB,QAAO,2CAACC,yBAAS,WAAU,oCAAoC;;AAGjE,SAAS,MAAiC,OAA6C;CACrF,MAAM,4CAA2B;CACjC,MAAM,yCAAwB;CAG9B,MAAM,MAAM,MAAM,WAAW;EAC3B,kBAAkB,MAAM,eAAe,EAAE,QAAQ,EAAE,2BAA2B,OAAO,EAAE;EACvF,yBAAyB;EACzB,MAAM,EAAE,iBAAiB,qBAAqB;EAC/C,GAAG;CAEJ,MAAM,OAAO,MAAM,WAAW;EAC5B,cAAc,MAAM,SAAS;EAC7B,gBAAgB,MAAM,aAAa,EAAE;EACrC,iBAAiB,YAAY;EAC9B,GAAG;CAEJ,MAAM,WAAW,IAAI,aAAa;AAElC,4BAAgB;AACd,MAAI,CAAC,MAAM,wBAAwB,MAAM,gBAAgB,CAAC,MAAM,SAC9D,sEAA2B,MAAM,gBAAgB,MAAM,aAAa,CAAC;IAEtE;EAAC,MAAM;EAAsB,MAAM;EAAc,MAAM;EAAS,CAAC;AAEpE,QACE,2CAACC;EACC,MAAM,MAAM;EACZ,WAAW,MAAM;EACjB,WAAW,MAAM;EACjB,kBAAkB,MAAM;EACxB,UAAU,OAAO,SAAS;AACxB,OAAI,MAAM,SACR,OAAM,SAAS,KAAa;AAG9B,OAAI,MAAM,SAAU;AACpB,OAAI,CAAC,MAAM,qBACT,OAAM,MAAM,gBAAgB,KAAa;AAE3C,OAAI,MAAM,OACR,UAAS,MAAM,OAAO,KAAa,CAAC;;GAGxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-icon.js","names":["User2","Avatar","AvatarImage","Typography"],"sources":["../../src/components/team-icon.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"team-icon.js","names":["User2","Avatar","AvatarImage","Typography"],"sources":["../../src/components/team-icon.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { Avatar, AvatarImage, Typography } from \"@hexclave/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":";;;;;;;AAQA,SAAgB,SAAS,OAAoC;AAC3D,KAAI,MAAM,SAAS,WACjB,QACE,2CAAC;EAAI,WAAU;YACb,2CAACA,sBAAM,WAAU,YAAY;GACzB;AAGV,KAAI,MAAM,KAAK,gBACb,QACE,2CAACC;EAAO,WAAU;YAChB,2CAACC;GAAY,KAAK,MAAM,KAAK;GAAiB,KAAK,MAAM,KAAK;IAAe;GACtE;KAGX,QACE,2CAAC;EAAI,WAAU;YACb,2CAACC;GAAW,WAAU;aAAoC,MAAM,KAAK,YAAY,MAAM,GAAG,EAAE,CAAC,aAAa;IAAc;GACpH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-switcher.js","names":["Suspense","Skeleton","Select","HexclaveAssertionError","SelectTrigger","SelectValue","SelectContent","SelectGroup","SelectLabel","Button","Settings","SelectItem","TeamIcon","Typography","SelectSeparator","PlusCircle"],"sources":["../../src/components/team-switcher.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"team-switcher.js","names":["Suspense","Skeleton","Select","HexclaveAssertionError","SelectTrigger","SelectValue","SelectContent","SelectGroup","SelectLabel","Button","Settings","SelectItem","TeamIcon","Typography","SelectSeparator","PlusCircle"],"sources":["../../src/components/team-switcher.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { HexclaveAssertionError } from \"@hexclave/shared/dist/utils/errors\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport {\n Button,\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n Skeleton,\n Typography,\n cn,\n} from \"@hexclave/ui\";\nimport { PlusCircle, Settings } from \"lucide-react\";\nimport { Suspense, useMemo } from \"react\";\nimport { Team, useStackApp, useUser } from \"..\";\nimport { useTranslation } from \"../lib/translations\";\nimport { TeamIcon } from \"./team-icon\";\n\ntype MockTeam = {\n id: string,\n displayName: string,\n profileImageUrl?: string | null,\n};\n\ntype TeamSwitcherProps<AllowNull extends boolean = false> = {\n team?: Team,\n teamId?: string,\n teams?: Team[],\n allowNull?: AllowNull,\n nullLabel?: string,\n triggerClassName?: string,\n onChange?: (team: AllowNull extends true ? Team | null : Team) => Promise<void>,\n // Mock data props\n mockUser?: {\n team?: MockTeam,\n },\n mockTeams?: MockTeam[],\n mockProject?: {\n config: {\n clientTeamCreationEnabled: boolean,\n },\n },\n};\n\nexport function TeamSwitcher<AllowNull extends boolean = false>(props: TeamSwitcherProps<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: TeamSwitcherProps<AllowNull>) {\n const { t } = useTranslation();\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.team,\n useTeams: () => props.mockTeams || [],\n setSelectedTeam: async () => {}, // Mock function\n } : userFromHook;\n\n const navigate = app.useNavigate();\n const project = app.useProject();\n const rawTeams = props.teams ?? user?.useTeams();\n const selectedTeam = props.team || rawTeams?.find(team => team.id === props.teamId);\n const teams = useMemo(() => rawTeams?.sort((a, b) => b.id === selectedTeam?.id ? 1 : -1), [rawTeams, selectedTeam]);\n\n\n return (\n <Select\n value={selectedTeam?.id || (props.allowNull ? 'null-sentinel' : undefined)}\n onValueChange={(value) => {\n runAsynchronouslyWithAlert(async () => {\n let team: MockTeam | null = null;\n if (value !== 'null-sentinel') {\n team = teams?.find(team => team.id === value) || null;\n if (!team) {\n throw new HexclaveAssertionError('Team not found, this should not happen');\n }\n } else {\n team = null;\n }\n\n // Call onChange callback if provided\n if (props.onChange) {\n await props.onChange(team as Team);\n }\n });\n }}\n >\n <SelectTrigger className={cn(\"stack-scope max-w-64\", props.triggerClassName)}>\n <SelectValue placeholder=\"Select team\"/>\n </SelectTrigger>\n <SelectContent className=\"stack-scope\">\n {selectedTeam ? <SelectGroup>\n <SelectLabel>\n <div className=\"flex items-center justify-between\">\n <span>\n {t('Current team')}\n </span>\n <Button\n variant='ghost'\n size='icon'\n className=\"h-6 w-6\"\n onClick={() => {\n if (!props.mockUser) {\n navigate(`${app.urls.accountSettings}#team-${selectedTeam.id}`);\n }\n }}\n >\n <Settings className=\"h-4 w-4\"/>\n </Button>\n </div>\n </SelectLabel>\n <SelectItem value={selectedTeam.id}>\n <div className=\"flex items-center gap-2\">\n <TeamIcon team={selectedTeam as Team} />\n <Typography className=\"max-w-40 truncate\">{selectedTeam.displayName}</Typography>\n </div>\n </SelectItem>\n </SelectGroup> : undefined}\n\n {props.allowNull && <SelectGroup>\n <SelectItem value=\"null-sentinel\">\n <div className=\"flex items-center gap-2\">\n <TeamIcon team='personal' />\n <Typography className=\"max-w-40 truncate\">{props.nullLabel || t('No team')}</Typography>\n </div>\n </SelectItem>\n </SelectGroup>}\n\n {teams?.length ?\n <SelectGroup>\n <SelectLabel>{t('Other teams')}</SelectLabel>\n {teams.filter(team => team.id !== selectedTeam?.id)\n .map(team => (\n <SelectItem value={team.id} key={team.id}>\n <div className=\"flex items-center gap-2\">\n <TeamIcon team={team as Team} />\n <Typography className=\"max-w-64 truncate\">{team.displayName}</Typography>\n </div>\n </SelectItem>\n ))}\n </SelectGroup> : null}\n\n {!teams?.length && !props.allowNull ?\n <SelectGroup>\n <SelectLabel>{t('No teams yet')}</SelectLabel>\n </SelectGroup> : null}\n\n {project.config.clientTeamCreationEnabled && <>\n <SelectSeparator/>\n <div>\n <Button\n onClick={() => {\n if (!props.mockUser) {\n navigate(`${app.urls.accountSettings}#team-creation`);\n }\n }}\n className=\"w-full\"\n variant='ghost'\n >\n <PlusCircle className=\"mr-2 h-4 w-4\"/> {t('Create a team')}\n </Button>\n </div>\n </>}\n </SelectContent>\n </Select>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-in-iframe.js","names":[],"sources":["../../src/components/use-in-iframe.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"use-in-iframe.js","names":[],"sources":["../../src/components/use-in-iframe.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { useEffect, useState } from \"react\";\n\nexport function useInIframe() {\n const [isIframe, setIsIframe] = useState(false);\n useEffect(() => {\n if (window.self !== window.top) {\n setIsIframe(true);\n }\n }, []);\n\n return isIframe;\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,cAAc;CAC5B,MAAM,CAAC,UAAU,mCAAwB,MAAM;AAC/C,4BAAgB;AACd,MAAI,OAAO,SAAS,OAAO,IACzB,aAAY,KAAK;IAElB,EAAE,CAAC;AAEN,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-button.js","names":["DropdownMenuItem","Typography","Suspense","Skeleton","DropdownMenu","DropdownMenuTrigger","UserAvatar","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","CircleUser","LogIn","UserPlus","SunMoon","LogOut"],"sources":["../../src/components/user-button.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"user-button.js","names":["DropdownMenuItem","Typography","Suspense","Skeleton","DropdownMenu","DropdownMenuTrigger","UserAvatar","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","CircleUser","LogIn","UserPlus","SunMoon","LogOut"],"sources":["../../src/components/user-button.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, Skeleton, Typography } from \"@hexclave/ui\";\nimport { CircleUser, LogIn, LogOut, SunMoon, UserPlus } from \"lucide-react\";\nimport React, { Suspense } from \"react\";\nimport { CurrentUser, useStackApp, useUser } from \"..\";\nimport { useTranslation } from \"../lib/translations\";\nimport { UserAvatar } from \"./elements/user-avatar\";\n\nfunction Item(props: { text: string, icon: React.ReactNode, onClick: () => void | Promise<void> }) {\n return (\n <DropdownMenuItem onClick={() => runAsynchronouslyWithAlert(props.onClick)}>\n <div className=\"flex gap-2 items-center\">\n {props.icon}\n <Typography>{props.text}</Typography>\n </div>\n </DropdownMenuItem>\n );\n}\n\ntype UserButtonProps = {\n showUserInfo?: boolean,\n colorModeToggle?: () => void | Promise<void>,\n extraItems?: {\n text: string,\n icon: React.ReactNode,\n onClick: () => void | Promise<void>,\n }[],\n mockUser?: {\n displayName?: string,\n primaryEmail?: string,\n profileImageUrl?: string,\n },\n};\n\nexport function UserButton(props: UserButtonProps) {\n return (\n <Suspense fallback={<Skeleton className=\"h-[34px] w-[34px] rounded-full stack-scope\" />}>\n <UserButtonInner {...props} />\n </Suspense>\n );\n}\n\nfunction UserButtonInner(props: UserButtonProps) {\n const userFromHook = useUser();\n\n // Use mock user if provided, otherwise use real user\n const user = props.mockUser ? {\n displayName: props.mockUser.displayName || 'Mock User',\n primaryEmail: props.mockUser.primaryEmail || 'mock@example.com',\n profileImageUrl: props.mockUser.profileImageUrl,\n signOut: () => {\n console.log('Mock sign out - no action taken in demo mode');\n return Promise.resolve();\n }\n } as CurrentUser : userFromHook;\n\n return <UserButtonInnerInner {...props} user={user} />;\n}\n\n\nfunction UserButtonInnerInner(props: UserButtonProps & { user: CurrentUser | null }) {\n const { t } = useTranslation();\n const user = props.user;\n const app = useStackApp();\n\n const iconProps = { size: 20, className: 'h-4 w-4' };\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger className=\"outline-none stack-scope rounded-lg hover:bg-muted/50 transition-colors hover:transition-none p-1.5\">\n <div className=\"flex gap-2 items-center\">\n <UserAvatar user={user} />\n {user && props.showUserInfo &&\n <div className=\"flex flex-col justify-center text-left min-w-0\">\n <div className=\"max-w-40 truncate text-sm font-medium\">{user.displayName}</div>\n <div className=\"max-w-40 truncate text-xs text-muted-foreground\">{user.primaryEmail}</div>\n </div>\n }\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"stack-scope\">\n <DropdownMenuLabel>\n <div className=\"flex gap-2 items-center\">\n <UserAvatar user={user} />\n <div>\n {user && <Typography className=\"max-w-40 truncate\">{user.displayName}</Typography>}\n {user && <Typography className=\"max-w-40 truncate\" variant=\"secondary\" type='label'>{user.primaryEmail}</Typography>}\n {!user && <Typography>{t('Not signed in')}</Typography>}\n </div>\n </div>\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {user && <Item\n text={t('Account settings')}\n onClick={async () => {\n if (props.mockUser) {\n console.log('Mock account settings - no navigation in demo mode');\n } else {\n await app.redirectToAccountSettings();\n }\n }}\n icon={<CircleUser {...iconProps} />}\n />}\n {!user && <Item\n text={t('Sign in')}\n onClick={async () => {\n if (props.mockUser) {\n console.log('Mock sign in - no navigation in demo mode');\n } else {\n await app.redirectToSignIn();\n }\n }}\n icon={<LogIn {...iconProps} />}\n />}\n {!user && <Item\n text={t('Sign up')}\n onClick={async () => {\n if (props.mockUser) {\n console.log('Mock sign up - no navigation in demo mode');\n } else {\n await app.redirectToSignUp();\n }\n }}\n icon={<UserPlus {...iconProps}/> }\n />}\n {user && props.extraItems && props.extraItems.map((item, index) => (\n <Item key={index} {...item} />\n ))}\n {props.colorModeToggle && (\n <Item\n text={t('Toggle theme')}\n onClick={props.colorModeToggle}\n icon={<SunMoon {...iconProps} />}\n />\n )}\n {user && <Item\n text={t('Sign out')}\n onClick={async () => {\n if (props.mockUser) {\n console.log('Mock sign out - no action taken in demo mode');\n } else {\n await user.signOut();\n }\n }}\n icon={<LogOut {...iconProps} />}\n />}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAS,KAAK,OAAqF;AACjG,QACE,2CAACA;EAAiB,oFAA0C,MAAM,QAAQ;YACxE,4CAAC;GAAI,WAAU;cACZ,MAAM,MACP,2CAACC,qCAAY,MAAM,OAAkB;IACjC;GACW;;AAmBvB,SAAgB,WAAW,OAAwB;AACjD,QACE,2CAACC;EAAS,UAAU,2CAACC,yBAAS,WAAU,+CAA+C;YACrF,2CAAC,mBAAgB,GAAI,QAAS;GACrB;;AAIf,SAAS,gBAAgB,OAAwB;CAC/C,MAAM,yCAAwB;CAG9B,MAAM,OAAO,MAAM,WAAW;EAC5B,aAAa,MAAM,SAAS,eAAe;EAC3C,cAAc,MAAM,SAAS,gBAAgB;EAC7C,iBAAiB,MAAM,SAAS;EAChC,eAAe;AACb,WAAQ,IAAI,+CAA+C;AAC3D,UAAO,QAAQ,SAAS;;EAE3B,GAAkB;AAEnB,QAAO,2CAAC;EAAqB,GAAI;EAAa;GAAQ;;AAIxD,SAAS,qBAAqB,OAAuD;CACnF,MAAM,EAAE,kDAAsB;CAC9B,MAAM,OAAO,MAAM;CACnB,MAAM,oCAAmB;CAEzB,MAAM,YAAY;EAAE,MAAM;EAAI,WAAW;EAAW;AAEpD,QACE,4CAACC,wCACC,2CAACC;EAAoB,WAAU;YAC7B,4CAAC;GAAI,WAAU;cACb,2CAACC,wCAAiB,OAAQ,EACzB,QAAQ,MAAM,gBACb,4CAAC;IAAI,WAAU;eACb,2CAAC;KAAI,WAAU;eAAyC,KAAK;MAAkB,EAC/E,2CAAC;KAAI,WAAU;eAAmD,KAAK;MAAmB;KACtF;IAEJ;GACc,EACtB,4CAACC;EAAoB,WAAU;;GAC7B,2CAACC,4CACC,4CAAC;IAAI,WAAU;eACb,2CAACF,wCAAiB,OAAQ,EAC1B,4CAAC;KACE,QAAQ,2CAACL;MAAW,WAAU;gBAAqB,KAAK;OAAyB;KACjF,QAAQ,2CAACA;MAAW,WAAU;MAAoB,SAAQ;MAAY,MAAK;gBAAS,KAAK;OAA0B;KACnH,CAAC,QAAQ,2CAACA,qCAAY,EAAE,gBAAgB,GAAc;QACnD;KACF,GACY;GACpB,2CAACQ,uCAAwB;GACxB,QAAQ,2CAAC;IACR,MAAM,EAAE,mBAAmB;IAC3B,SAAS,YAAY;AACnB,SAAI,MAAM,SACR,SAAQ,IAAI,qDAAqD;SAEjE,OAAM,IAAI,2BAA2B;;IAGzC,MAAM,2CAACC,2BAAW,GAAI,YAAa;KACnC;GACD,CAAC,QAAQ,2CAAC;IACT,MAAM,EAAE,UAAU;IAClB,SAAS,YAAY;AACnB,SAAI,MAAM,SACR,SAAQ,IAAI,4CAA4C;SAExD,OAAM,IAAI,kBAAkB;;IAGhC,MAAM,2CAACC,sBAAM,GAAI,YAAa;KAC9B;GACD,CAAC,QAAQ,2CAAC;IACT,MAAM,EAAE,UAAU;IAClB,SAAS,YAAY;AACnB,SAAI,MAAM,SACR,SAAQ,IAAI,4CAA4C;SAExD,OAAM,IAAI,kBAAkB;;IAGhC,MAAM,2CAACC,yBAAS,GAAI,YAAY;KAChC;GACD,QAAQ,MAAM,cAAc,MAAM,WAAW,KAAK,MAAM,UACvD,2CAAC,QAAiB,GAAI,QAAX,MAAmB,CAC9B;GACD,MAAM,mBACL,2CAAC;IACC,MAAM,EAAE,eAAe;IACvB,SAAS,MAAM;IACf,MAAM,2CAACC,wBAAQ,GAAI,YAAa;KAChC;GAEH,QAAQ,2CAAC;IACR,MAAM,EAAE,WAAW;IACnB,SAAS,YAAY;AACnB,SAAI,MAAM,SACR,SAAQ,IAAI,+CAA+C;SAE3D,OAAM,KAAK,SAAS;;IAGxB,MAAM,2CAACC,uBAAO,GAAI,YAAa;KAC/B;;GACkB,IACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"active-sessions-page.js","names":["PageLayout","Typography","Button","Skeleton","Table","TableHeader","TableRow","TableHead","TableBody","TableCell","Badge","ActionCell"],"sources":["../../../../src/components-page/account-settings/active-sessions/active-sessions-page.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 { fromNow } from \"@hexclave/shared/dist/utils/dates\";\nimport { captureError } from \"@hexclave/shared/dist/utils/errors\";\nimport { runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { ActionCell, Badge, Button, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from \"@hexclave/ui\";\nimport { useEffect, useState } from \"react\";\nimport { useUser } from \"../../../lib/hooks\";\nimport { ActiveSession } from \"../../../lib/stack-app/users\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { PageLayout } from \"../page-layout\";\n\nexport function ActiveSessionsPage(props?: {\n mockSessions?: Array<{\n id: string,\n isCurrentSession: boolean,\n isImpersonation?: boolean,\n createdAt: string,\n lastUsedAt?: string,\n geoInfo?: {\n ip?: string,\n cityName?: string,\n },\n }>,\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const userFromHook = useUser({ or: (props?.mockSessions || props?.mockMode) ? 'return-null' : 'throw' });\n const [isLoading, setIsLoading] = useState(!props?.mockSessions);\n const [isRevokingAll, setIsRevokingAll] = useState(false);\n const [sessions, setSessions] = useState<ActiveSession[]>([]);\n const [showConfirmRevokeAll, setShowConfirmRevokeAll] = useState(false);\n\n // Use mock data if provided\n const mockSessionsData = props?.mockSessions ? props.mockSessions.map(session => ({\n id: session.id,\n isCurrentSession: session.isCurrentSession,\n isImpersonation: session.isImpersonation || false,\n createdAt: session.createdAt,\n lastUsedAt: session.lastUsedAt,\n geoInfo: session.geoInfo,\n })) : [\n {\n id: 'current-session',\n isCurrentSession: true,\n createdAt: new Date().toISOString(),\n lastUsedAt: new Date().toISOString(),\n geoInfo: { ip: '192.168.1.1', cityName: 'San Francisco' }\n },\n {\n id: 'mobile-session',\n isCurrentSession: false,\n createdAt: new Date(Date.now() - 86400000).toISOString(), // 1 day ago\n lastUsedAt: new Date(Date.now() - 7200000).toISOString(), // 2 hours ago\n geoInfo: { ip: '10.0.0.1', cityName: 'New York' }\n }\n ];\n\n // Fetch sessions when component mounts (only if not using mock data)\n useEffect(() => {\n if (props?.mockSessions) {\n setSessions(mockSessionsData as any);\n setIsLoading(false);\n return;\n }\n\n // If in mock mode but no mock sessions provided, use default mock data\n if (props?.mockMode && !userFromHook) {\n setSessions(mockSessionsData as any);\n setIsLoading(false);\n return;\n }\n\n if (!userFromHook) return;\n\n runAsynchronously(async () => {\n setIsLoading(true);\n const sessionsData = await userFromHook.getActiveSessions();\n const enhancedSessions = sessionsData;\n setSessions(enhancedSessions);\n setIsLoading(false);\n });\n }, [userFromHook, props?.mockSessions]);\n\n const handleRevokeSession = async (sessionId: string) => {\n if (props?.mockSessions) {\n // Mock revoke - just remove from list\n setSessions(prev => prev.filter(session => session.id !== sessionId));\n return;\n }\n\n if (!userFromHook) return;\n\n try {\n await userFromHook.revokeSession(sessionId);\n setSessions(prev => prev.filter(session => session.id !== sessionId));\n } catch (error) {\n captureError(\"session-revoke\", { sessionId ,error });\n throw error;\n }\n };\n\n const handleRevokeAllSessions = async () => {\n setIsRevokingAll(true);\n try {\n if (props?.mockSessions) {\n // Mock revoke all - just keep current session\n setSessions(prevSessions => prevSessions.filter(session => session.isCurrentSession));\n } else if (userFromHook) {\n const deletionPromises = sessions\n .filter(session => !session.isCurrentSession)\n .map(session => userFromHook.revokeSession(session.id));\n await Promise.all(deletionPromises);\n setSessions(prevSessions => prevSessions.filter(session => session.isCurrentSession));\n }\n } catch (error) {\n captureError(\"all-sessions-revoke\", { error, sessionIds: sessions.map(session => session.id) });\n throw error;\n } finally {\n setIsRevokingAll(false);\n setShowConfirmRevokeAll(false);\n }\n };\n\n return (\n <PageLayout>\n <div>\n <div className=\"flex justify-between items-center mb-2\">\n <Typography className='font-medium'>{t(\"Active Sessions\")}</Typography>\n {sessions.filter(s => !s.isCurrentSession).length > 0 && !isLoading && (\n showConfirmRevokeAll ? (\n <div className=\"flex gap-2\">\n <Button\n variant=\"destructive\"\n size=\"sm\"\n loading={isRevokingAll}\n onClick={handleRevokeAllSessions}\n >\n {t(\"Confirm\")}\n </Button>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n disabled={isRevokingAll}\n onClick={() => setShowConfirmRevokeAll(false)}\n >\n {t(\"Cancel\")}\n </Button>\n </div>\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setShowConfirmRevokeAll(true)}\n >\n {t(\"Revoke All Other Sessions\")}\n </Button>\n )\n )}\n </div>\n <Typography variant='secondary' type='footnote' className=\"mb-4\">\n {t(\"These are devices where you're currently logged in. You can revoke access to end a session.\")}\n </Typography>\n\n {isLoading ? (\n <Skeleton className=\"h-[300px] w-full rounded-md\" />\n ) : (\n <div className='border rounded-md'>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[200px]\">{t(\"Session\")}</TableHead>\n <TableHead className=\"w-[150px]\">{t(\"IP Address\")}</TableHead>\n <TableHead className=\"w-[150px]\">{t(\"Location\")}</TableHead>\n <TableHead className=\"w-[150px]\">{t(\"Last used\")}</TableHead>\n <TableHead className=\"w-[80px]\"></TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {sessions.length === 0 ? (\n <TableRow>\n <TableCell colSpan={5} className=\"text-center py-6\">\n <Typography variant=\"secondary\">{t(\"No active sessions found\")}</Typography>\n </TableCell>\n </TableRow>\n ) : (\n sessions.map((session) => (\n <TableRow key={session.id}>\n <TableCell>\n <div className=\"flex flex-col\">\n {/* We currently do not save any usefull information about the user, in the future, the name should probably say what kind of session it is (e.g. cli, browser, maybe what auth method was used) */}\n <Typography>{session.isCurrentSession ? t(\"Current Session\") : t(\"Other Session\")}</Typography>\n {session.isImpersonation && <Badge variant=\"secondary\" className=\"w-fit mt-1\">{t(\"Impersonation\")}</Badge>}\n <Typography variant='secondary' type='footnote'>\n {t(\"Signed in {time}\", { time: new Date(session.createdAt).toLocaleDateString() })}\n </Typography>\n </div>\n </TableCell>\n <TableCell>\n <Typography>{session.geoInfo?.ip || t('-')}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{session.geoInfo?.cityName || t('Unknown')}</Typography>\n </TableCell>\n <TableCell>\n <div className=\"flex flex-col\">\n <Typography>{session.lastUsedAt ? fromNow(new Date(session.lastUsedAt)) : t(\"Never\")}</Typography>\n <Typography variant='secondary' type='footnote' title={session.lastUsedAt ? new Date(session.lastUsedAt).toLocaleString() : \"\"}>\n {session.lastUsedAt ? new Date(session.lastUsedAt).toLocaleDateString() : \"\"}\n </Typography>\n </div>\n </TableCell>\n <TableCell align=\"right\">\n <ActionCell\n items={[\n {\n item: t(\"Revoke\"),\n onClick: () => handleRevokeSession(session.id),\n danger: true,\n disabled: session.isCurrentSession,\n disabledTooltip: session.isCurrentSession ? t(\"You cannot revoke your current session\") : undefined,\n },\n ]}\n />\n </TableCell>\n </TableRow>\n ))\n )}\n </TableBody>\n </Table>\n </div>\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"active-sessions-page.js","names":["PageLayout","Typography","Button","Skeleton","Table","TableHeader","TableRow","TableHead","TableBody","TableCell","Badge","ActionCell"],"sources":["../../../../src/components-page/account-settings/active-sessions/active-sessions-page.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { fromNow } from \"@hexclave/shared/dist/utils/dates\";\nimport { captureError } from \"@hexclave/shared/dist/utils/errors\";\nimport { runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { ActionCell, Badge, Button, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from \"@hexclave/ui\";\nimport { useEffect, useState } from \"react\";\nimport { useUser } from \"../../../lib/hooks\";\nimport { ActiveSession } from \"../../../lib/hexclave-app/users\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { PageLayout } from \"../page-layout\";\n\nexport function ActiveSessionsPage(props?: {\n mockSessions?: Array<{\n id: string,\n isCurrentSession: boolean,\n isImpersonation?: boolean,\n createdAt: string,\n lastUsedAt?: string,\n geoInfo?: {\n ip?: string,\n cityName?: string,\n },\n }>,\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const userFromHook = useUser({ or: (props?.mockSessions || props?.mockMode) ? 'return-null' : 'throw' });\n const [isLoading, setIsLoading] = useState(!props?.mockSessions);\n const [isRevokingAll, setIsRevokingAll] = useState(false);\n const [sessions, setSessions] = useState<ActiveSession[]>([]);\n const [showConfirmRevokeAll, setShowConfirmRevokeAll] = useState(false);\n\n // Use mock data if provided\n const mockSessionsData = props?.mockSessions ? props.mockSessions.map(session => ({\n id: session.id,\n isCurrentSession: session.isCurrentSession,\n isImpersonation: session.isImpersonation || false,\n createdAt: session.createdAt,\n lastUsedAt: session.lastUsedAt,\n geoInfo: session.geoInfo,\n })) : [\n {\n id: 'current-session',\n isCurrentSession: true,\n createdAt: new Date().toISOString(),\n lastUsedAt: new Date().toISOString(),\n geoInfo: { ip: '192.168.1.1', cityName: 'San Francisco' }\n },\n {\n id: 'mobile-session',\n isCurrentSession: false,\n createdAt: new Date(Date.now() - 86400000).toISOString(), // 1 day ago\n lastUsedAt: new Date(Date.now() - 7200000).toISOString(), // 2 hours ago\n geoInfo: { ip: '10.0.0.1', cityName: 'New York' }\n }\n ];\n\n // Fetch sessions when component mounts (only if not using mock data)\n useEffect(() => {\n if (props?.mockSessions) {\n setSessions(mockSessionsData as any);\n setIsLoading(false);\n return;\n }\n\n // If in mock mode but no mock sessions provided, use default mock data\n if (props?.mockMode && !userFromHook) {\n setSessions(mockSessionsData as any);\n setIsLoading(false);\n return;\n }\n\n if (!userFromHook) return;\n\n runAsynchronously(async () => {\n setIsLoading(true);\n const sessionsData = await userFromHook.getActiveSessions();\n const enhancedSessions = sessionsData;\n setSessions(enhancedSessions);\n setIsLoading(false);\n });\n }, [userFromHook, props?.mockSessions]);\n\n const handleRevokeSession = async (sessionId: string) => {\n if (props?.mockSessions) {\n // Mock revoke - just remove from list\n setSessions(prev => prev.filter(session => session.id !== sessionId));\n return;\n }\n\n if (!userFromHook) return;\n\n try {\n await userFromHook.revokeSession(sessionId);\n setSessions(prev => prev.filter(session => session.id !== sessionId));\n } catch (error) {\n captureError(\"session-revoke\", { sessionId ,error });\n throw error;\n }\n };\n\n const handleRevokeAllSessions = async () => {\n setIsRevokingAll(true);\n try {\n if (props?.mockSessions) {\n // Mock revoke all - just keep current session\n setSessions(prevSessions => prevSessions.filter(session => session.isCurrentSession));\n } else if (userFromHook) {\n const deletionPromises = sessions\n .filter(session => !session.isCurrentSession)\n .map(session => userFromHook.revokeSession(session.id));\n await Promise.all(deletionPromises);\n setSessions(prevSessions => prevSessions.filter(session => session.isCurrentSession));\n }\n } catch (error) {\n captureError(\"all-sessions-revoke\", { error, sessionIds: sessions.map(session => session.id) });\n throw error;\n } finally {\n setIsRevokingAll(false);\n setShowConfirmRevokeAll(false);\n }\n };\n\n return (\n <PageLayout>\n <div>\n <div className=\"flex justify-between items-center mb-2\">\n <Typography className='font-medium'>{t(\"Active Sessions\")}</Typography>\n {sessions.filter(s => !s.isCurrentSession).length > 0 && !isLoading && (\n showConfirmRevokeAll ? (\n <div className=\"flex gap-2\">\n <Button\n variant=\"destructive\"\n size=\"sm\"\n loading={isRevokingAll}\n onClick={handleRevokeAllSessions}\n >\n {t(\"Confirm\")}\n </Button>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n disabled={isRevokingAll}\n onClick={() => setShowConfirmRevokeAll(false)}\n >\n {t(\"Cancel\")}\n </Button>\n </div>\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setShowConfirmRevokeAll(true)}\n >\n {t(\"Revoke All Other Sessions\")}\n </Button>\n )\n )}\n </div>\n <Typography variant='secondary' type='footnote' className=\"mb-4\">\n {t(\"These are devices where you're currently logged in. You can revoke access to end a session.\")}\n </Typography>\n\n {isLoading ? (\n <Skeleton className=\"h-[300px] w-full rounded-md\" />\n ) : (\n <div className='border rounded-md'>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[200px]\">{t(\"Session\")}</TableHead>\n <TableHead className=\"w-[150px]\">{t(\"IP Address\")}</TableHead>\n <TableHead className=\"w-[150px]\">{t(\"Location\")}</TableHead>\n <TableHead className=\"w-[150px]\">{t(\"Last used\")}</TableHead>\n <TableHead className=\"w-[80px]\"></TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {sessions.length === 0 ? (\n <TableRow>\n <TableCell colSpan={5} className=\"text-center py-6\">\n <Typography variant=\"secondary\">{t(\"No active sessions found\")}</Typography>\n </TableCell>\n </TableRow>\n ) : (\n sessions.map((session) => (\n <TableRow key={session.id}>\n <TableCell>\n <div className=\"flex flex-col\">\n {/* We currently do not save any usefull information about the user, in the future, the name should probably say what kind of session it is (e.g. cli, browser, maybe what auth method was used) */}\n <Typography>{session.isCurrentSession ? t(\"Current Session\") : t(\"Other Session\")}</Typography>\n {session.isImpersonation && <Badge variant=\"secondary\" className=\"w-fit mt-1\">{t(\"Impersonation\")}</Badge>}\n <Typography variant='secondary' type='footnote'>\n {t(\"Signed in {time}\", { time: new Date(session.createdAt).toLocaleDateString() })}\n </Typography>\n </div>\n </TableCell>\n <TableCell>\n <Typography>{session.geoInfo?.ip || t('-')}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{session.geoInfo?.cityName || t('Unknown')}</Typography>\n </TableCell>\n <TableCell>\n <div className=\"flex flex-col\">\n <Typography>{session.lastUsedAt ? fromNow(new Date(session.lastUsedAt)) : t(\"Never\")}</Typography>\n <Typography variant='secondary' type='footnote' title={session.lastUsedAt ? new Date(session.lastUsedAt).toLocaleString() : \"\"}>\n {session.lastUsedAt ? new Date(session.lastUsedAt).toLocaleDateString() : \"\"}\n </Typography>\n </div>\n </TableCell>\n <TableCell align=\"right\">\n <ActionCell\n items={[\n {\n item: t(\"Revoke\"),\n onClick: () => handleRevokeSession(session.id),\n danger: true,\n disabled: session.isCurrentSession,\n disabledTooltip: session.isCurrentSession ? t(\"You cannot revoke your current session\") : undefined,\n },\n ]}\n />\n </TableCell>\n </TableRow>\n ))\n )}\n </TableBody>\n </Table>\n </div>\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-keys-page.js","names":["CreateApiKeyDialog","ShowApiKeyDialog","PageLayout","Button","ApiKeyTable"],"sources":["../../../../src/components-page/account-settings/api-keys/api-keys-page.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"api-keys-page.js","names":["CreateApiKeyDialog","ShowApiKeyDialog","PageLayout","Button","ApiKeyTable"],"sources":["../../../../src/components-page/account-settings/api-keys/api-keys-page.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { Button } from \"@hexclave/ui\";\nimport { useState } from \"react\";\nimport { CreateApiKeyDialog, ShowApiKeyDialog } from \"../../../components/api-key-dialogs\";\nimport { ApiKeyTable } from \"../../../components/api-key-table\";\nimport { useUser } from \"../../../lib/hooks\";\nimport { ApiKey, ApiKeyCreationOptions } from \"../../../lib/hexclave-app/api-keys\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { PageLayout } from \"../page-layout\";\n\n\nexport function ApiKeysPage(props?: {\n mockApiKeys?: Array<{\n id: string,\n description: string,\n createdAt: string,\n expiresAt?: string,\n manuallyRevokedAt?: string,\n }>,\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n\n // Check if we're in any kind of mock mode first\n const isInMockMode = !!(props?.mockApiKeys || props?.mockMode);\n\n const userFromHook = useUser({ or: isInMockMode ? 'return-null' : 'redirect' });\n\n // In mock mode, we don't need a user - just show mock data\n if (isInMockMode && !userFromHook) {\n // This is expected in mock mode, continue with mock data\n }\n\n // Only return null if we're not in mock mode and don't have a user\n if (!isInMockMode && !userFromHook) {\n return null; // This shouldn't happen due to redirect, but just in case\n }\n\n // Use mock data if provided\n const mockApiKeysData = props?.mockApiKeys ? props.mockApiKeys.map(mockKey => ({\n id: mockKey.id,\n description: mockKey.description,\n createdAt: new Date(mockKey.createdAt),\n expiresAt: mockKey.expiresAt ? new Date(mockKey.expiresAt) : undefined,\n manuallyRevokedAt: mockKey.manuallyRevokedAt ? new Date(mockKey.manuallyRevokedAt) : null,\n value: {\n lastFour: mockKey.id.slice(-4).padStart(4, '0'), // Use last 4 chars of ID or pad with zeros\n },\n type: 'user' as const,\n userId: 'mock-user-id',\n update: async () => {\n console.log('Mock API key update called');\n },\n revoke: async () => {\n console.log('Mock API key revoke called');\n },\n isValid: () => {\n const now = new Date();\n const isExpired = mockKey.expiresAt ? new Date(mockKey.expiresAt) < now : false;\n const isRevoked = !!mockKey.manuallyRevokedAt;\n return !isExpired && !isRevoked;\n },\n whyInvalid: () => {\n const now = new Date();\n if (mockKey.manuallyRevokedAt) return 'manually-revoked';\n if (mockKey.expiresAt && new Date(mockKey.expiresAt) < now) return 'expired';\n return null;\n },\n })) : [\n {\n id: 'key-1',\n description: 'Development Key',\n createdAt: new Date(Date.now() - 172800000), // 2 days ago\n expiresAt: undefined,\n manuallyRevokedAt: null,\n value: {\n lastFour: 'ey-1'.slice(-4).padStart(4, '0'),\n },\n type: 'user' as const,\n userId: 'mock-user-id',\n update: async () => {\n console.log('Mock API key update called');\n },\n revoke: async () => {\n console.log('Mock API key revoke called');\n },\n isValid: () => true,\n whyInvalid: () => null,\n }\n ];\n\n // Determine which API keys to use\n let apiKeys: any[];\n if (isInMockMode) {\n apiKeys = mockApiKeysData;\n } else if (userFromHook) {\n apiKeys = userFromHook.useApiKeys();\n } else {\n apiKeys = [];\n }\n\n const [isNewApiKeyDialogOpen, setIsNewApiKeyDialogOpen] = useState(false);\n const [returnedApiKey, setReturnedApiKey] = useState<ApiKey<\"user\", true> | null>(null);\n\n const CreateDialog = CreateApiKeyDialog<\"user\">;\n const ShowDialog = ShowApiKeyDialog<\"user\">;\n\n const handleCreateApiKey = async (data: ApiKeyCreationOptions<\"user\">) => {\n if (isInMockMode) {\n // Mock API key creation\n const mockApiKey = {\n id: `key-${Date.now()}`,\n description: data.description,\n createdAt: new Date().toISOString(),\n expiresAt: data.expiresAt?.toISOString(),\n value: 'sk_dev_mock_key_' + Math.random().toString(36).substring(2),\n update: async () => {\n console.log('Mock API key update called');\n },\n revoke: async () => {\n console.log('Mock API key revoke called');\n },\n isValid: () => true,\n whyInvalid: () => null,\n type: 'user' as const,\n userId: 'mock-user-id',\n };\n return mockApiKey as any;\n }\n\n if (!userFromHook) throw new Error('User not available');\n return await userFromHook.createApiKey(data);\n };\n\n return (\n <PageLayout>\n <Button onClick={() => setIsNewApiKeyDialogOpen(true)}>\n {t(\"Create API Key\")}\n </Button>\n <ApiKeyTable apiKeys={apiKeys} />\n <CreateDialog\n open={isNewApiKeyDialogOpen}\n onOpenChange={setIsNewApiKeyDialogOpen}\n onKeyCreated={setReturnedApiKey}\n createApiKey={handleCreateApiKey}\n mockMode={isInMockMode}\n />\n <ShowDialog\n apiKey={returnedApiKey}\n onClose={() => setReturnedApiKey(null)}\n />\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAcA,SAAgB,YAAY,OASzB;CACD,MAAM,EAAE,wDAAsB;CAG9B,MAAM,eAAe,CAAC,EAAE,OAAO,eAAe,OAAO;CAErD,MAAM,kDAAuB,EAAE,IAAI,eAAe,gBAAgB,YAAY,CAAC;AAG/E,KAAI,gBAAgB,CAAC,cAAc;AAKnC,KAAI,CAAC,gBAAgB,CAAC,aACpB,QAAO;CAIT,MAAM,kBAAkB,OAAO,cAAc,MAAM,YAAY,KAAI,aAAY;EAC7E,IAAI,QAAQ;EACZ,aAAa,QAAQ;EACrB,WAAW,IAAI,KAAK,QAAQ,UAAU;EACtC,WAAW,QAAQ,YAAY,IAAI,KAAK,QAAQ,UAAU,GAAG;EAC7D,mBAAmB,QAAQ,oBAAoB,IAAI,KAAK,QAAQ,kBAAkB,GAAG;EACrF,OAAO,EACL,UAAU,QAAQ,GAAG,MAAM,GAAG,CAAC,SAAS,GAAG,IAAI,EAChD;EACD,MAAM;EACN,QAAQ;EACR,QAAQ,YAAY;AAClB,WAAQ,IAAI,6BAA6B;;EAE3C,QAAQ,YAAY;AAClB,WAAQ,IAAI,6BAA6B;;EAE3C,eAAe;GACb,MAAM,sBAAM,IAAI,MAAM;GACtB,MAAM,YAAY,QAAQ,YAAY,IAAI,KAAK,QAAQ,UAAU,GAAG,MAAM;GAC1E,MAAM,YAAY,CAAC,CAAC,QAAQ;AAC5B,UAAO,CAAC,aAAa,CAAC;;EAExB,kBAAkB;GAChB,MAAM,sBAAM,IAAI,MAAM;AACtB,OAAI,QAAQ,kBAAmB,QAAO;AACtC,OAAI,QAAQ,aAAa,IAAI,KAAK,QAAQ,UAAU,GAAG,IAAK,QAAO;AACnE,UAAO;;EAEV,EAAE,GAAG,CACJ;EACE,IAAI;EACJ,aAAa;EACb,2BAAW,IAAI,KAAK,KAAK,KAAK,GAAG,OAAU;EAC3C,WAAW;EACX,mBAAmB;EACnB,OAAO,EACL,UAAU,OAAO,MAAM,GAAG,CAAC,SAAS,GAAG,IAAI,EAC5C;EACD,MAAM;EACN,QAAQ;EACR,QAAQ,YAAY;AAClB,WAAQ,IAAI,6BAA6B;;EAE3C,QAAQ,YAAY;AAClB,WAAQ,IAAI,6BAA6B;;EAE3C,eAAe;EACf,kBAAkB;EACnB,CACF;CAGD,IAAI;AACJ,KAAI,aACF,WAAU;UACD,aACT,WAAU,aAAa,YAAY;KAEnC,WAAU,EAAE;CAGd,MAAM,CAAC,uBAAuB,gDAAqC,MAAM;CACzE,MAAM,CAAC,gBAAgB,yCAA2D,KAAK;CAEvF,MAAM,eAAeA;CACrB,MAAM,aAAaC;CAEnB,MAAM,qBAAqB,OAAO,SAAwC;AACxE,MAAI,aAmBF,QAjBmB;GACjB,IAAI,OAAO,KAAK,KAAK;GACrB,aAAa,KAAK;GAClB,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,WAAW,KAAK,WAAW,aAAa;GACxC,OAAO,qBAAqB,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,UAAU,EAAE;GACnE,QAAQ,YAAY;AAClB,YAAQ,IAAI,6BAA6B;;GAE3C,QAAQ,YAAY;AAClB,YAAQ,IAAI,6BAA6B;;GAE3C,eAAe;GACf,kBAAkB;GAClB,MAAM;GACN,QAAQ;GACT;AAIH,MAAI,CAAC,aAAc,OAAM,IAAI,MAAM,qBAAqB;AACxD,SAAO,MAAM,aAAa,aAAa,KAAK;;AAG9C,QACE,4CAACC;EACC,2CAACC;GAAO,eAAe,yBAAyB,KAAK;aAClD,EAAE,iBAAiB;IACb;EACT,2CAACC,oDAAqB,UAAW;EACjC,2CAAC;GACC,MAAM;GACN,cAAc;GACd,cAAc;GACd,cAAc;GACd,UAAU;IACV;EACF,2CAAC;GACC,QAAQ;GACR,eAAe,kBAAkB,KAAK;IACtC;KACS"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable-text.js","names":["Input","Button","Typography","Edit"],"sources":["../../../src/components-page/account-settings/editable-text.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"editable-text.js","names":["Input","Button","Typography","Edit"],"sources":["../../../src/components-page/account-settings/editable-text.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { Button, Input, Typography } from \"@hexclave/ui\";\nimport { Edit } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"../../lib/translations\";\n\n\nexport function EditableText(props: { value: string, onSave?: (value: string) => void | Promise<void> }) {\n const [editing, setEditing] = useState(false);\n const [editingValue, setEditingValue] = useState(props.value);\n const { t } = useTranslation();\n\n return (\n <div className='flex items-center gap-2'>\n {editing ? (\n <>\n <Input\n value={editingValue}\n onChange={(e) => setEditingValue(e.target.value)}\n />\n <Button\n size='sm'\n onClick={async () => {\n await props.onSave?.(editingValue);\n setEditing(false);\n }}\n >\n {t(\"Save\")}\n </Button>\n <Button\n size='sm'\n variant='secondary'\n onClick={() => {\n setEditingValue(props.value);\n setEditing(false);\n }}>\n {t(\"Cancel\")}\n </Button>\n </>\n ) : (\n <>\n <Typography>{props.value}</Typography>\n <Button onClick={() => setEditing(true)} size='icon' variant='ghost'>\n <Edit className=\"w-4 h-4\" />\n </Button>\n </>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAUA,SAAgB,aAAa,OAA4E;CACvG,MAAM,CAAC,SAAS,kCAAuB,MAAM;CAC7C,MAAM,CAAC,cAAc,uCAA4B,MAAM,MAAM;CAC7D,MAAM,EAAE,qDAAsB;AAE9B,QACE,2CAAC;EAAI,WAAU;YACZ,UACC;GACE,2CAACA;IACC,OAAO;IACP,WAAW,MAAM,gBAAgB,EAAE,OAAO,MAAM;KAChD;GACF,2CAACC;IACC,MAAK;IACL,SAAS,YAAY;AACnB,WAAM,MAAM,SAAS,aAAa;AAClC,gBAAW,MAAM;;cAGlB,EAAE,OAAO;KACH;GACT,2CAACA;IACC,MAAK;IACL,SAAQ;IACR,eAAe;AACb,qBAAgB,MAAM,MAAM;AAC5B,gBAAW,MAAM;;cAElB,EAAE,SAAS;KACL;MACR,GAEH,qFACE,2CAACC,qCAAY,MAAM,QAAmB,EACtC,2CAACD;GAAO,eAAe,WAAW,KAAK;GAAE,MAAK;GAAO,SAAQ;aAC3D,2CAACE,qBAAK,WAAU,YAAY;IACrB,IACR;GAED"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-and-auth-page.js","names":["PageLayout","EmailsSection","PasswordSection","PasskeySection","OtpSection","MfaSection"],"sources":["../../../../src/components-page/account-settings/email-and-auth/email-and-auth-page.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"email-and-auth-page.js","names":["PageLayout","EmailsSection","PasswordSection","PasskeySection","OtpSection","MfaSection"],"sources":["../../../../src/components-page/account-settings/email-and-auth/email-and-auth-page.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { PageLayout } from \"../page-layout\";\nimport { EmailsSection } from \"./emails-section\";\nimport { MfaSection } from \"./mfa-section\";\nimport { OtpSection } from \"./otp-section\";\nimport { PasskeySection } from \"./passkey-section\";\nimport { PasswordSection } from \"./password-section\";\n\nexport function EmailsAndAuthPage(props?: {\n mockMode?: boolean,\n}) {\n return (\n <PageLayout>\n <EmailsSection mockMode={props?.mockMode}/>\n <PasswordSection mockMode={props?.mockMode} />\n <PasskeySection mockMode={props?.mockMode} />\n <OtpSection mockMode={props?.mockMode} />\n <MfaSection mockMode={props?.mockMode} />\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,kBAAkB,OAE/B;AACD,QACE,4CAACA;EACC,2CAACC,qCAAc,UAAU,OAAO,WAAW;EAC3C,2CAACC,yCAAgB,UAAU,OAAO,WAAY;EAC9C,2CAACC,uCAAe,UAAU,OAAO,WAAY;EAC7C,2CAACC,+BAAW,UAAU,OAAO,WAAY;EACzC,2CAACC,+BAAW,UAAU,OAAO,WAAY;KAC9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emails-section.js","names":["Typography","Input","Button","FormWarningText","Table","TableBody","TableRow","TableCell","Badge","ActionCell","KnownErrors"],"sources":["../../../../src/components-page/account-settings/email-and-auth/emails-section.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 { yupResolver } from \"@hookform/resolvers/yup\";\nimport { KnownErrors } from \"@hexclave/shared/dist/known-errors\";\nimport { strictEmailSchema, yupObject } from \"@hexclave/shared/dist/schema-fields\";\nimport { runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { ActionCell, Badge, Button, Input, Table, TableBody, TableCell, TableRow, Typography } from \"@hexclave/ui\";\nimport { useEffect, useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { FormWarningText } from \"../../../components/elements/form-warning\";\nimport { useUser } from \"../../../lib/hooks\";\nimport { useTranslation } from \"../../../lib/translations\";\n\nexport function EmailsSection(props?: {\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const user = useUser({ or: props?.mockMode ? 'return-null' : 'redirect' });\n\n // In mock mode, show a placeholder message\n if (props?.mockMode && !user) {\n return (\n <div>\n <div className='flex flex-col md:flex-row justify-between mb-4 gap-4'>\n <Typography className='font-medium'>{t(\"Emails\")}</Typography>\n </div>\n <Typography variant='secondary'>{t(\"Email management is not available in demo mode.\")}</Typography>\n </div>\n );\n }\n\n if (!user) {\n return null; // This shouldn't happen in non-mock mode due to redirect\n }\n\n const contactChannels = user.useContactChannels();\n const [addingEmail, setAddingEmail] = useState(contactChannels.length === 0);\n const [addingEmailLoading, setAddingEmailLoading] = useState(false);\n const [addedEmail, setAddedEmail] = useState<string | null>(null);\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const isLastEmailUsedForAuth = contactChannels.filter(x => x.usedForAuth && x.type === 'email').length === 1;\n\n useEffect(() => {\n if (addedEmail) {\n runAsynchronously(async () => {\n const cc = contactChannels.find(x => x.value === addedEmail);\n if (cc && !cc.isVerified) {\n await cc.sendVerificationEmail();\n }\n setAddedEmail(null);\n });\n }\n }, [contactChannels, addedEmail]);\n\n const emailSchema = yupObject({\n email: strictEmailSchema(t('Please enter a valid email address'))\n .notOneOf(contactChannels.map(x => x.value), t('Email already exists'))\n .defined()\n .nonEmpty(t('Email is required')),\n });\n\n const { register, handleSubmit, formState: { errors }, reset } = useForm({\n resolver: yupResolver(emailSchema)\n });\n\n const onSubmit = async (data: yup.InferType<typeof emailSchema>) => {\n setAddingEmailLoading(true);\n try {\n await user.createContactChannel({ type: 'email', value: data.email, usedForAuth: false });\n setAddedEmail(data.email);\n } finally {\n setAddingEmailLoading(false);\n }\n setAddingEmail(false);\n reset();\n };\n\n return (\n <div>\n <div className='flex flex-col md:flex-row justify-between mb-4 gap-4'>\n <Typography className='font-medium'>{t(\"Emails\")}</Typography>\n {addingEmail ? (\n <form\n onSubmit={(e) => {\n e.preventDefault();\n runAsynchronously(handleSubmit(onSubmit));\n }}\n className='flex flex-col'\n >\n <div className='flex gap-2'>\n <Input\n {...register(\"email\")}\n placeholder={t(\"Enter email\")}\n />\n <Button type=\"submit\" loading={addingEmailLoading}>\n {t(\"Add\")}\n </Button>\n <Button\n variant='secondary'\n onClick={() => {\n setAddingEmail(false);\n reset();\n }}\n >\n {t(\"Cancel\")}\n </Button>\n </div>\n {errors.email && <FormWarningText text={errors.email.message} />}\n </form>\n ) : (\n <div className='flex md:justify-end'>\n <Button variant='secondary' onClick={() => setAddingEmail(true)}>{t(\"Add an email\")}</Button>\n </div>\n )}\n </div>\n\n {contactChannels.length > 0 ? (\n <div className='border rounded-md'>\n <Table>\n <TableBody>\n {/*eslint-disable-next-line @typescript-eslint/no-unnecessary-condition*/}\n {contactChannels.filter(x => x.type === 'email')\n .sort((a, b) => {\n if (a.isPrimary !== b.isPrimary) return a.isPrimary ? -1 : 1;\n if (a.isVerified !== b.isVerified) return a.isVerified ? -1 : 1;\n return 0;\n })\n .map(x => (\n <TableRow key={x.id}>\n <TableCell>\n <div className='flex flex-col md:flex-row gap-2 md:gap-4'>\n {x.value}\n <div className='flex gap-2'>\n {x.isPrimary ? <Badge>{t(\"Primary\")}</Badge> : null}\n {!x.isVerified ? <Badge variant='destructive'>{t(\"Unverified\")}</Badge> : null}\n {x.usedForAuth ? <Badge variant='outline'>{t(\"Used for sign-in\")}</Badge> : null}\n </div>\n </div>\n </TableCell>\n <TableCell className=\"flex justify-end\">\n <ActionCell items={[\n ...(!x.isVerified ? [{\n item: t(\"Send verification email\"),\n onClick: async () => { await x.sendVerificationEmail(); },\n }] : []),\n ...(!x.isPrimary && x.isVerified ? [{\n item: t(\"Set as primary\"),\n onClick: async () => { await x.update({ isPrimary: true }); },\n }] :\n !x.isPrimary ? [{\n item: t(\"Set as primary\"),\n onClick: async () => {},\n disabled: true,\n disabledTooltip: t(\"Please verify your email first\"),\n }] : []),\n ...(!x.usedForAuth && x.isVerified ? [{\n item: t(\"Use for sign-in\"),\n onClick: async () => {\n try {\n await x.update({ usedForAuth: true });\n } catch (e) {\n if (KnownErrors.ContactChannelAlreadyUsedForAuthBySomeoneElse.isInstance(e)) {\n alert(t(\"This email is already used for sign-in by another user.\"));\n }\n }\n }\n }] : []),\n ...(x.usedForAuth && !isLastEmailUsedForAuth ? [{\n item: t(\"Stop using for sign-in\"),\n onClick: async () => { await x.update({ usedForAuth: false }); },\n }] : x.usedForAuth ? [{\n item: t(\"Stop using for sign-in\"),\n onClick: async () => {},\n disabled: true,\n disabledTooltip: t(\"You can not remove your last sign-in email\"),\n }] : []),\n // Determine if this email can be removed\n ...(!isLastEmailUsedForAuth || !x.usedForAuth ? [{\n item: t(\"Remove\"),\n onClick: async () => { await x.delete(); },\n danger: true,\n }] : [{\n item: t(\"Remove\"),\n onClick: async () => {},\n disabled: true,\n disabledTooltip: t(\"You can not remove your last sign-in email\"),\n }]),\n ]}/>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"emails-section.js","names":["Typography","Input","Button","FormWarningText","Table","TableBody","TableRow","TableCell","Badge","ActionCell","KnownErrors"],"sources":["../../../../src/components-page/account-settings/email-and-auth/emails-section.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { KnownErrors } from \"@hexclave/shared/dist/known-errors\";\nimport { strictEmailSchema, yupObject } from \"@hexclave/shared/dist/schema-fields\";\nimport { runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { ActionCell, Badge, Button, Input, Table, TableBody, TableCell, TableRow, Typography } from \"@hexclave/ui\";\nimport { useEffect, useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { FormWarningText } from \"../../../components/elements/form-warning\";\nimport { useUser } from \"../../../lib/hooks\";\nimport { useTranslation } from \"../../../lib/translations\";\n\nexport function EmailsSection(props?: {\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const user = useUser({ or: props?.mockMode ? 'return-null' : 'redirect' });\n\n // In mock mode, show a placeholder message\n if (props?.mockMode && !user) {\n return (\n <div>\n <div className='flex flex-col md:flex-row justify-between mb-4 gap-4'>\n <Typography className='font-medium'>{t(\"Emails\")}</Typography>\n </div>\n <Typography variant='secondary'>{t(\"Email management is not available in demo mode.\")}</Typography>\n </div>\n );\n }\n\n if (!user) {\n return null; // This shouldn't happen in non-mock mode due to redirect\n }\n\n const contactChannels = user.useContactChannels();\n const [addingEmail, setAddingEmail] = useState(contactChannels.length === 0);\n const [addingEmailLoading, setAddingEmailLoading] = useState(false);\n const [addedEmail, setAddedEmail] = useState<string | null>(null);\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const isLastEmailUsedForAuth = contactChannels.filter(x => x.usedForAuth && x.type === 'email').length === 1;\n\n useEffect(() => {\n if (addedEmail) {\n runAsynchronously(async () => {\n const cc = contactChannels.find(x => x.value === addedEmail);\n if (cc && !cc.isVerified) {\n await cc.sendVerificationEmail();\n }\n setAddedEmail(null);\n });\n }\n }, [contactChannels, addedEmail]);\n\n const emailSchema = yupObject({\n email: strictEmailSchema(t('Please enter a valid email address'))\n .notOneOf(contactChannels.map(x => x.value), t('Email already exists'))\n .defined()\n .nonEmpty(t('Email is required')),\n });\n\n const { register, handleSubmit, formState: { errors }, reset } = useForm({\n resolver: yupResolver(emailSchema)\n });\n\n const onSubmit = async (data: yup.InferType<typeof emailSchema>) => {\n setAddingEmailLoading(true);\n try {\n await user.createContactChannel({ type: 'email', value: data.email, usedForAuth: false });\n setAddedEmail(data.email);\n } finally {\n setAddingEmailLoading(false);\n }\n setAddingEmail(false);\n reset();\n };\n\n return (\n <div>\n <div className='flex flex-col md:flex-row justify-between mb-4 gap-4'>\n <Typography className='font-medium'>{t(\"Emails\")}</Typography>\n {addingEmail ? (\n <form\n onSubmit={(e) => {\n e.preventDefault();\n runAsynchronously(handleSubmit(onSubmit));\n }}\n className='flex flex-col'\n >\n <div className='flex gap-2'>\n <Input\n {...register(\"email\")}\n placeholder={t(\"Enter email\")}\n />\n <Button type=\"submit\" loading={addingEmailLoading}>\n {t(\"Add\")}\n </Button>\n <Button\n variant='secondary'\n onClick={() => {\n setAddingEmail(false);\n reset();\n }}\n >\n {t(\"Cancel\")}\n </Button>\n </div>\n {errors.email && <FormWarningText text={errors.email.message} />}\n </form>\n ) : (\n <div className='flex md:justify-end'>\n <Button variant='secondary' onClick={() => setAddingEmail(true)}>{t(\"Add an email\")}</Button>\n </div>\n )}\n </div>\n\n {contactChannels.length > 0 ? (\n <div className='border rounded-md'>\n <Table>\n <TableBody>\n {/*eslint-disable-next-line @typescript-eslint/no-unnecessary-condition*/}\n {contactChannels.filter(x => x.type === 'email')\n .sort((a, b) => {\n if (a.isPrimary !== b.isPrimary) return a.isPrimary ? -1 : 1;\n if (a.isVerified !== b.isVerified) return a.isVerified ? -1 : 1;\n return 0;\n })\n .map(x => (\n <TableRow key={x.id}>\n <TableCell>\n <div className='flex flex-col md:flex-row gap-2 md:gap-4'>\n {x.value}\n <div className='flex gap-2'>\n {x.isPrimary ? <Badge>{t(\"Primary\")}</Badge> : null}\n {!x.isVerified ? <Badge variant='destructive'>{t(\"Unverified\")}</Badge> : null}\n {x.usedForAuth ? <Badge variant='outline'>{t(\"Used for sign-in\")}</Badge> : null}\n </div>\n </div>\n </TableCell>\n <TableCell className=\"flex justify-end\">\n <ActionCell items={[\n ...(!x.isVerified ? [{\n item: t(\"Send verification email\"),\n onClick: async () => { await x.sendVerificationEmail(); },\n }] : []),\n ...(!x.isPrimary && x.isVerified ? [{\n item: t(\"Set as primary\"),\n onClick: async () => { await x.update({ isPrimary: true }); },\n }] :\n !x.isPrimary ? [{\n item: t(\"Set as primary\"),\n onClick: async () => {},\n disabled: true,\n disabledTooltip: t(\"Please verify your email first\"),\n }] : []),\n ...(!x.usedForAuth && x.isVerified ? [{\n item: t(\"Use for sign-in\"),\n onClick: async () => {\n try {\n await x.update({ usedForAuth: true });\n } catch (e) {\n if (KnownErrors.ContactChannelAlreadyUsedForAuthBySomeoneElse.isInstance(e)) {\n alert(t(\"This email is already used for sign-in by another user.\"));\n }\n }\n }\n }] : []),\n ...(x.usedForAuth && !isLastEmailUsedForAuth ? [{\n item: t(\"Stop using for sign-in\"),\n onClick: async () => { await x.update({ usedForAuth: false }); },\n }] : x.usedForAuth ? [{\n item: t(\"Stop using for sign-in\"),\n onClick: async () => {},\n disabled: true,\n disabledTooltip: t(\"You can not remove your last sign-in email\"),\n }] : []),\n // Determine if this email can be removed\n ...(!isLastEmailUsedForAuth || !x.usedForAuth ? [{\n item: t(\"Remove\"),\n onClick: async () => { await x.delete(); },\n danger: true,\n }] : [{\n item: t(\"Remove\"),\n onClick: async () => {},\n disabled: true,\n disabledTooltip: t(\"You can not remove your last sign-in email\"),\n }]),\n ]}/>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mfa-section.js","names":["Section","Typography","Input","Button","QRCode"],"sources":["../../../../src/components-page/account-settings/email-and-auth/mfa-section.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"mfa-section.js","names":["Section","Typography","Input","Button","QRCode"],"sources":["../../../../src/components-page/account-settings/email-and-auth/mfa-section.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { createTOTPKeyURI, verifyTOTP } from \"@oslojs/otp\";\nimport { useAsyncCallback } from '@hexclave/shared/dist/hooks/use-async-callback';\nimport { generateRandomValues } from '@hexclave/shared/dist/utils/crypto';\nimport { throwErr } from \"@hexclave/shared/dist/utils/errors\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { Button, Input, Typography } from \"@hexclave/ui\";\nimport * as QRCode from 'qrcode';\nimport { useEffect, useState } from \"react\";\nimport { CurrentUser, Project } from '../../..';\nimport { useStackApp, useUser } from \"../../../lib/hooks\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { Section } from \"../section\";\n\nexport function MfaSection(props?: {\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const project = useStackApp().useProject();\n const user = useUser({ or: props?.mockMode ? 'return-null' : \"throw\" });\n\n // In mock mode, show a placeholder message\n if (props?.mockMode && !user) {\n return (\n <Section\n title={t(\"Multi-factor authentication\")}\n description={t(\"MFA management is not available in demo mode.\")}\n >\n <Typography variant='secondary'>{t(\"MFA management is not available in demo mode.\")}</Typography>\n </Section>\n );\n }\n\n if (!user) {\n return null; // This shouldn't happen in non-mock mode due to throw\n }\n const [generatedSecret, setGeneratedSecret] = useState<Uint8Array | null>(null);\n const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);\n const [mfaCode, setMfaCode] = useState<string>(\"\");\n const [isMaybeWrong, setIsMaybeWrong] = useState(false);\n const isEnabled = user.isMultiFactorRequired;\n\n const [handleSubmit, isLoading] = useAsyncCallback(async () => {\n await user.update({\n totpMultiFactorSecret: generatedSecret,\n });\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }, [generatedSecret, user]);\n\n useEffect(() => {\n setIsMaybeWrong(false);\n runAsynchronouslyWithAlert(async () => {\n if (generatedSecret && verifyTOTP(generatedSecret, 30, 6, mfaCode)) {\n await handleSubmit();\n }\n setIsMaybeWrong(true);\n });\n }, [mfaCode, generatedSecret, handleSubmit]);\n\n return (\n <Section\n title={t(\"Multi-factor authentication\")}\n description={isEnabled\n ? t(\"Multi-factor authentication is currently enabled.\")\n : t(\"Multi-factor authentication is currently disabled.\")}\n >\n <div className='flex flex-col gap-4'>\n {!isEnabled && generatedSecret && (\n <>\n <Typography>{t(\"Scan this QR code with your authenticator app:\")}</Typography>\n <img width={200} height={200} src={qrCodeUrl ?? throwErr(\"TOTP QR code failed to generate\")} alt={t(\"TOTP multi-factor authentication QR code\")} />\n <Typography>{t(\"Then, enter your six-digit MFA code:\")}</Typography>\n <Input\n value={mfaCode}\n onChange={(e) => {\n setIsMaybeWrong(false);\n setMfaCode(e.target.value);\n }}\n placeholder=\"123456\"\n maxLength={6}\n disabled={isLoading}\n />\n {isMaybeWrong && mfaCode.length === 6 && (\n <Typography variant=\"destructive\">{t(\"Incorrect code. Please try again.\")}</Typography>\n )}\n <div className='flex'>\n <Button\n variant='secondary'\n onClick={() => {\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }}\n >\n {t(\"Cancel\")}\n </Button>\n </div>\n </>\n )}\n <div className='flex gap-2'>\n {isEnabled ? (\n <Button\n variant='secondary'\n onClick={async () => {\n await user.update({\n totpMultiFactorSecret: null,\n });\n }}\n >\n {t(\"Disable MFA\")}\n </Button>\n ) : !generatedSecret && (\n <Button\n variant='secondary'\n onClick={async () => {\n const secret = generateRandomValues(new Uint8Array(20));\n setQrCodeUrl(await generateTotpQrCode(project, user, secret));\n setGeneratedSecret(secret);\n }}\n >\n {t(\"Enable MFA\")}\n </Button>\n )}\n </div>\n </div>\n </Section>\n );\n}\n\n\nasync function generateTotpQrCode(project: Project, user: CurrentUser, secret: Uint8Array) {\n const uri = createTOTPKeyURI(project.displayName, user.primaryEmail ?? user.id, secret, 30, 6);\n return await QRCode.toDataURL(uri) as any;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAgB,WAAW,OAExB;CACD,MAAM,EAAE,wDAAsB;CAC9B,MAAM,kDAAuB,CAAC,YAAY;CAC1C,MAAM,0CAAe,EAAE,IAAI,OAAO,WAAW,gBAAgB,SAAS,CAAC;AAGvE,KAAI,OAAO,YAAY,CAAC,KACtB,QACE,2CAACA;EACC,OAAO,EAAE,8BAA8B;EACvC,aAAa,EAAE,gDAAgD;YAE/D,2CAACC;GAAW,SAAQ;aAAa,EAAE,gDAAgD;IAAc;GACzF;AAId,KAAI,CAAC,KACH,QAAO;CAET,MAAM,CAAC,iBAAiB,0CAAkD,KAAK;CAC/E,MAAM,CAAC,WAAW,oCAAwC,KAAK;CAC/D,MAAM,CAAC,SAAS,kCAA+B,GAAG;CAClD,MAAM,CAAC,cAAc,uCAA4B,MAAM;CACvD,MAAM,YAAY,KAAK;CAEvB,MAAM,CAAC,cAAc,kFAA8B,YAAY;AAC7D,QAAM,KAAK,OAAO,EAChB,uBAAuB,iBACxB,CAAC;AACF,qBAAmB,KAAK;AACxB,eAAa,KAAK;AAClB,aAAW,GAAG;IACb,CAAC,iBAAiB,KAAK,CAAC;AAE3B,4BAAgB;AACd,kBAAgB,MAAM;AACtB,uEAA2B,YAAY;AACrC,OAAI,+CAA8B,iBAAiB,IAAI,GAAG,QAAQ,CAChE,OAAM,cAAc;AAEtB,mBAAgB,KAAK;IACrB;IACD;EAAC;EAAS;EAAiB;EAAa,CAAC;AAE5C,QACE,2CAACD;EACC,OAAO,EAAE,8BAA8B;EACvC,aAAa,YACT,EAAE,oDAAoD,GACtD,EAAE,qDAAqD;YAE3D,4CAAC;GAAI,WAAU;cACZ,CAAC,aAAa,mBACb;IACE,2CAACC,qCAAY,EAAE,iDAAiD,GAAc;IAC9E,2CAAC;KAAI,OAAO;KAAK,QAAQ;KAAK,KAAK,8DAAsB,kCAAkC;KAAE,KAAK,EAAE,2CAA2C;MAAI;IACnJ,2CAACA,qCAAY,EAAE,uCAAuC,GAAc;IACpE,2CAACC;KACC,OAAO;KACP,WAAW,MAAM;AACf,sBAAgB,MAAM;AACtB,iBAAW,EAAE,OAAO,MAAM;;KAE5B,aAAY;KACZ,WAAW;KACX,UAAU;MACV;IACD,gBAAgB,QAAQ,WAAW,KAClC,2CAACD;KAAW,SAAQ;eAAe,EAAE,oCAAoC;MAAc;IAEzF,2CAAC;KAAI,WAAU;eACb,2CAACE;MACC,SAAQ;MACR,eAAe;AACb,0BAAmB,KAAK;AACxB,oBAAa,KAAK;AAClB,kBAAW,GAAG;;gBAGf,EAAE,SAAS;OACL;MACL;OACL,EAEL,2CAAC;IAAI,WAAU;cACZ,YACC,2CAACA;KACC,SAAQ;KACR,SAAS,YAAY;AACnB,YAAM,KAAK,OAAO,EAChB,uBAAuB,MACxB,CAAC;;eAGH,EAAE,cAAc;MACV,GACP,CAAC,mBACH,2CAACA;KACC,SAAQ;KACR,SAAS,YAAY;MACnB,MAAM,sEAA8B,IAAI,WAAW,GAAG,CAAC;AACvD,mBAAa,MAAM,mBAAmB,SAAS,MAAM,OAAO,CAAC;AAC7D,yBAAmB,OAAO;;eAG3B,EAAE,aAAa;MACT;KAEP;IACF;GACE;;AAKd,eAAe,mBAAmB,SAAkB,MAAmB,QAAoB;CACzF,MAAM,wCAAuB,QAAQ,aAAa,KAAK,gBAAgB,KAAK,IAAI,QAAQ,IAAI,EAAE;AAC9F,QAAO,MAAMC,OAAO,UAAU,IAAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otp-section.js","names":["Section","Typography","Button"],"sources":["../../../../src/components-page/account-settings/email-and-auth/otp-section.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"otp-section.js","names":["Section","Typography","Button"],"sources":["../../../../src/components-page/account-settings/email-and-auth/otp-section.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { Button, Typography } from \"@hexclave/ui\";\nimport { useState } from \"react\";\nimport { useStackApp, useUser } from \"../../../lib/hooks\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { Section } from \"../section\";\n\nexport function OtpSection(props?: {\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const user = useUser({ or: props?.mockMode ? 'return-null' : \"throw\" });\n\n // In mock mode, show a placeholder message\n if (props?.mockMode && !user) {\n return (\n <Section\n title={t(\"One-Time Password\")}\n description={t(\"OTP management is not available in demo mode.\")}\n >\n <Typography variant='secondary'>{t(\"OTP management is not available in demo mode.\")}</Typography>\n </Section>\n );\n }\n\n if (!user) {\n return null; // This shouldn't happen in non-mock mode due to throw\n }\n const project = useStackApp().useProject();\n const contactChannels = user.useContactChannels();\n const isLastAuth = user.otpAuthEnabled && !user.hasPassword && user.oauthProviders.length === 0 && !user.passkeyAuthEnabled;\n const [disabling, setDisabling] = useState(false);\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const hasValidEmail = contactChannels.filter(x => x.type === 'email' && x.isVerified && x.usedForAuth).length > 0;\n\n if (!project.config.magicLinkEnabled) {\n return null;\n }\n\n const handleDisableOTP = async () => {\n await user.update({ otpAuthEnabled: false });\n setDisabling(false);\n };\n\n return (\n <Section title={t(\"OTP sign-in\")} description={user.otpAuthEnabled ? t(\"OTP/magic link sign-in is currently enabled.\") : t(\"Enable sign-in via magic link or OTP sent to your sign-in emails.\")}>\n <div className='flex md:justify-end'>\n {hasValidEmail ? (\n user.otpAuthEnabled ? (\n !isLastAuth ? (\n !disabling ? (\n <Button\n variant='secondary'\n onClick={() => setDisabling(true)}\n >\n {t(\"Disable OTP\")}\n </Button>\n ) : (\n <div className='flex flex-col gap-2'>\n <Typography variant='destructive'>\n {t(\"Are you sure you want to disable OTP sign-in? You will not be able to sign in with only emails anymore.\")}\n </Typography>\n <div className='flex gap-2'>\n <Button\n variant='destructive'\n onClick={handleDisableOTP}\n >\n {t(\"Disable\")}\n </Button>\n <Button\n variant='secondary'\n onClick={() => setDisabling(false)}\n >\n {t(\"Cancel\")}\n </Button>\n </div>\n </div>\n )\n ) : (\n <Typography variant='secondary' type='label'>{t(\"OTP sign-in is enabled and cannot be disabled as it is currently the only sign-in method\")}</Typography>\n )\n ) : (\n <Button\n variant='secondary'\n onClick={async () => {\n await user.update({ otpAuthEnabled: true });\n }}\n >\n {t(\"Enable OTP\")}\n </Button>\n )\n ) : (\n <Typography variant='secondary' type='label'>{t(\"To enable OTP sign-in, please add a verified sign-in email.\")}</Typography>\n )}\n </div>\n </Section>\n );\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,WAAW,OAExB;CACD,MAAM,EAAE,wDAAsB;CAC9B,MAAM,0CAAe,EAAE,IAAI,OAAO,WAAW,gBAAgB,SAAS,CAAC;AAGvE,KAAI,OAAO,YAAY,CAAC,KACtB,QACE,2CAACA;EACC,OAAO,EAAE,oBAAoB;EAC7B,aAAa,EAAE,gDAAgD;YAE/D,2CAACC;GAAW,SAAQ;aAAa,EAAE,gDAAgD;IAAc;GACzF;AAId,KAAI,CAAC,KACH,QAAO;CAET,MAAM,kDAAuB,CAAC,YAAY;CAC1C,MAAM,kBAAkB,KAAK,oBAAoB;CACjD,MAAM,aAAa,KAAK,kBAAkB,CAAC,KAAK,eAAe,KAAK,eAAe,WAAW,KAAK,CAAC,KAAK;CACzG,MAAM,CAAC,WAAW,oCAAyB,MAAM;CAGjD,MAAM,gBAAgB,gBAAgB,QAAO,MAAK,EAAE,SAAS,WAAW,EAAE,cAAc,EAAE,YAAY,CAAC,SAAS;AAEhH,KAAI,CAAC,QAAQ,OAAO,iBAClB,QAAO;CAGT,MAAM,mBAAmB,YAAY;AACnC,QAAM,KAAK,OAAO,EAAE,gBAAgB,OAAO,CAAC;AAC5C,eAAa,MAAM;;AAGrB,QACE,2CAACD;EAAQ,OAAO,EAAE,cAAc;EAAE,aAAa,KAAK,iBAAiB,EAAE,+CAA+C,GAAG,EAAE,oEAAoE;YAC7L,2CAAC;GAAI,WAAU;aACZ,gBACC,KAAK,iBACH,CAAC,aACC,CAAC,YACC,2CAACE;IACC,SAAQ;IACR,eAAe,aAAa,KAAK;cAEhC,EAAE,cAAc;KACV,GAET,4CAAC;IAAI,WAAU;eACb,2CAACD;KAAW,SAAQ;eACjB,EAAE,0GAA0G;MAClG,EACb,4CAAC;KAAI,WAAU;gBACb,2CAACC;MACC,SAAQ;MACR,SAAS;gBAER,EAAE,UAAU;OACN,EACT,2CAACA;MACC,SAAQ;MACR,eAAe,aAAa,MAAM;gBAEjC,EAAE,SAAS;OACL;MACL;KACF,GAGR,2CAACD;IAAW,SAAQ;IAAY,MAAK;cAAS,EAAE,2FAA2F;KAAc,GAG3J,2CAACC;IACC,SAAQ;IACR,SAAS,YAAY;AACnB,WAAM,KAAK,OAAO,EAAE,gBAAgB,MAAM,CAAC;;cAG5C,EAAE,aAAa;KACT,GAGX,2CAACD;IAAW,SAAQ;IAAY,MAAK;cAAS,EAAE,8DAA8D;KAAc;IAE1H;GACE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passkey-section.js","names":["Section","Typography","Button"],"sources":["../../../../src/components-page/account-settings/email-and-auth/passkey-section.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY
|
|
1
|
+
{"version":3,"file":"passkey-section.js","names":["Section","Typography","Button"],"sources":["../../../../src/components-page/account-settings/email-and-auth/passkey-section.tsx"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { Button, Typography } from \"@hexclave/ui\";\nimport { useState } from \"react\";\nimport { useStackApp } from \"../../..\";\nimport { useUser } from \"../../../lib/hooks\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { Section } from \"../section\";\n\nexport function PasskeySection(props?: {\n mockMode?: boolean,\n}) {\n const { t } = useTranslation();\n const user = useUser({ or: props?.mockMode ? 'return-null' : \"throw\" });\n\n // In mock mode, show a placeholder message\n if (props?.mockMode && !user) {\n return (\n <Section\n title={t(\"Passkey\")}\n description={t(\"Passkey management is not available in demo mode.\")}\n >\n <Typography variant='secondary'>{t(\"Passkey management is not available in demo mode.\")}</Typography>\n </Section>\n );\n }\n\n if (!user) {\n return null; // This shouldn't happen in non-mock mode due to throw\n }\n const hexclaveApp = useStackApp();\n const project = hexclaveApp.useProject();\n const contactChannels = user.useContactChannels();\n\n\n // passkey is enabled if there is a passkey\n const hasPasskey = user.passkeyAuthEnabled;\n\n const isLastAuth = user.passkeyAuthEnabled && !user.hasPassword && user.oauthProviders.length === 0 && !user.otpAuthEnabled;\n const [showConfirmationModal, setShowConfirmationModal] = useState(false);\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const hasValidEmail = contactChannels.filter(x => x.type === 'email' && x.isVerified && x.usedForAuth).length > 0;\n\n if (!project.config.passkeyEnabled) {\n return null;\n }\n\n const handleDeletePasskey = async () => {\n await user.update({ passkeyAuthEnabled: false });\n setShowConfirmationModal(false);\n };\n\n\n const handleAddNewPasskey = async () => {\n await user.registerPasskey();\n };\n\n return (\n <>\n <Section title={t(\"Passkey\")} description={hasPasskey ? t(\"Passkey registered\") : t(\"Register a passkey\")}>\n <div className='flex md:justify-end gap-2'>\n {!hasValidEmail && (\n <Typography variant='secondary' type='label'>{t(\"To enable Passkey sign-in, please add a verified sign-in email.\")}</Typography>\n )}\n {hasValidEmail && hasPasskey && isLastAuth && (\n <Typography variant='secondary' type='label'>{t(\"Passkey sign-in is enabled and cannot be disabled as it is currently the only sign-in method\")}</Typography>\n )}\n {!hasPasskey && hasValidEmail && (\n <div>\n <Button onClick={handleAddNewPasskey} variant='secondary'>{t(\"Add new passkey\")}</Button>\n </div>\n )}\n {hasValidEmail && hasPasskey && !isLastAuth && !showConfirmationModal && (\n <Button\n variant='secondary'\n onClick={() => setShowConfirmationModal(true)}\n >\n {t(\"Delete Passkey\")}\n </Button>\n )}\n {hasValidEmail && hasPasskey && !isLastAuth && showConfirmationModal && (\n <div className='flex flex-col gap-2'>\n <Typography variant='destructive'>\n {t(\"Are you sure you want to disable Passkey sign-in? You will not be able to sign in with your passkey anymore.\")}\n </Typography>\n <div className='flex gap-2'>\n <Button\n variant='destructive'\n onClick={handleDeletePasskey}\n >\n {t(\"Disable\")}\n </Button>\n <Button\n variant='secondary'\n onClick={() => setShowConfirmationModal(false)}\n >\n {t(\"Cancel\")}\n </Button>\n </div>\n </div>\n )}\n </div>\n </Section>\n\n\n </>\n\n );\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,eAAe,OAE5B;CACD,MAAM,EAAE,wDAAsB;CAC9B,MAAM,0CAAe,EAAE,IAAI,OAAO,WAAW,gBAAgB,SAAS,CAAC;AAGvE,KAAI,OAAO,YAAY,CAAC,KACtB,QACE,2CAACA;EACC,OAAO,EAAE,UAAU;EACnB,aAAa,EAAE,oDAAoD;YAEnE,2CAACC;GAAW,SAAQ;aAAa,EAAE,oDAAoD;IAAc;GAC7F;AAId,KAAI,CAAC,KACH,QAAO;CAGT,MAAM,8CAD2B,CACL,YAAY;CACxC,MAAM,kBAAkB,KAAK,oBAAoB;CAIjD,MAAM,aAAa,KAAK;CAExB,MAAM,aAAa,KAAK,sBAAsB,CAAC,KAAK,eAAe,KAAK,eAAe,WAAW,KAAK,CAAC,KAAK;CAC7G,MAAM,CAAC,uBAAuB,gDAAqC,MAAM;CAGzE,MAAM,gBAAgB,gBAAgB,QAAO,MAAK,EAAE,SAAS,WAAW,EAAE,cAAc,EAAE,YAAY,CAAC,SAAS;AAEhH,KAAI,CAAC,QAAQ,OAAO,eAClB,QAAO;CAGT,MAAM,sBAAsB,YAAY;AACtC,QAAM,KAAK,OAAO,EAAE,oBAAoB,OAAO,CAAC;AAChD,2BAAyB,MAAM;;CAIjC,MAAM,sBAAsB,YAAY;AACtC,QAAM,KAAK,iBAAiB;;AAG9B,QACE,mFACE,2CAACD;EAAQ,OAAO,EAAE,UAAU;EAAE,aAAa,aAAa,EAAE,qBAAqB,GAAG,EAAE,qBAAqB;YACvG,4CAAC;GAAI,WAAU;;IACZ,CAAC,iBACA,2CAACC;KAAW,SAAQ;KAAY,MAAK;eAAS,EAAE,kEAAkE;MAAc;IAEjI,iBAAiB,cAAc,cAC9B,2CAACA;KAAW,SAAQ;KAAY,MAAK;eAAS,EAAE,+FAA+F;MAAc;IAE9J,CAAC,cAAc,iBACd,2CAAC,mBACC,2CAACC;KAAO,SAAS;KAAqB,SAAQ;eAAa,EAAE,kBAAkB;MAAU,GACrF;IAEP,iBAAiB,cAAc,CAAC,cAAc,CAAC,yBAC9C,2CAACA;KACC,SAAQ;KACR,eAAe,yBAAyB,KAAK;eAE5C,EAAE,iBAAiB;MACb;IAEV,iBAAiB,cAAc,CAAC,cAAc,yBAC7C,4CAAC;KAAI,WAAU;gBACb,2CAACD;MAAW,SAAQ;gBACjB,EAAE,+GAA+G;OACvG,EACb,4CAAC;MAAI,WAAU;iBACb,2CAACC;OACC,SAAQ;OACR,SAAS;iBAER,EAAE,UAAU;QACN,EACT,2CAACA;OACC,SAAQ;OACR,eAAe,yBAAyB,MAAM;iBAE7C,EAAE,SAAS;QACL;OACL;MACF;;IAEJ;GACE,GAGT"}
|