@insforge/react 1.0.4 → 1.0.5-dev.0

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/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { ConditionalProps, ForgotPassword, ForgotPasswordProps, Protect, ProtectProps, ResetPassword, ResetPasswordProps, SignIn, SignInButton, SignInButtonProps, SignInProps, SignOutButton, SignOutButtonProps, SignUp, SignUpButton, SignUpButtonProps, SignUpProps, SignedIn, SignedOut, UserButton, UserButtonProps, VerifyEmail, VerifyEmailProps } from './components.cjs';
1
+ export { ConditionalProps, ForgotPassword, ForgotPasswordProps, Protect, ProtectProps, ResetPassword, ResetPasswordProps, SignIn, SignInButton, SignInButtonProps, SignInProps, SignOutButton, SignOutButtonProps, SignUp, SignUpButton, SignUpButtonProps, SignUpProps, SignedIn, SignedOut, UserButton, UserButtonProps, UserProfileModal, UserProfileModalProps, VerifyEmail, VerifyEmailProps } from './components.cjs';
2
2
  export { ForgotPasswordForm, ForgotPasswordFormProps, ResetPasswordForm, ResetPasswordFormProps, SignInForm, SignInFormProps, SignUpForm, SignUpFormProps, VerifyEmailStatus, VerifyEmailStatusProps } from './forms.cjs';
3
3
  export { AuthBranding, AuthContainer, AuthContainerProps, AuthDivider, AuthDividerProps, AuthEmailVerificationStep, AuthErrorBanner, AuthErrorBannerProps, AuthFormField, AuthFormFieldProps, AuthHeader, AuthHeaderProps, AuthLink, AuthLinkProps, AuthOAuthButton, AuthOAuthButtonProps, AuthOAuthProviders, AuthOAuthProvidersProps, AuthPasswordField, AuthPasswordFieldProps, AuthPasswordStrengthIndicator, AuthPasswordStrengthIndicatorProps, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthSubmitButtonProps, AuthVerificationCodeInput, AuthVerificationCodeInputProps } from './atoms.cjs';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { ConditionalProps, ForgotPassword, ForgotPasswordProps, Protect, ProtectProps, ResetPassword, ResetPasswordProps, SignIn, SignInButton, SignInButtonProps, SignInProps, SignOutButton, SignOutButtonProps, SignUp, SignUpButton, SignUpButtonProps, SignUpProps, SignedIn, SignedOut, UserButton, UserButtonProps, VerifyEmail, VerifyEmailProps } from './components.js';
1
+ export { ConditionalProps, ForgotPassword, ForgotPasswordProps, Protect, ProtectProps, ResetPassword, ResetPasswordProps, SignIn, SignInButton, SignInButtonProps, SignInProps, SignOutButton, SignOutButtonProps, SignUp, SignUpButton, SignUpButtonProps, SignUpProps, SignedIn, SignedOut, UserButton, UserButtonProps, UserProfileModal, UserProfileModalProps, VerifyEmail, VerifyEmailProps } from './components.js';
2
2
  export { ForgotPasswordForm, ForgotPasswordFormProps, ResetPasswordForm, ResetPasswordFormProps, SignInForm, SignInFormProps, SignUpForm, SignUpFormProps, VerifyEmailStatus, VerifyEmailStatusProps } from './forms.js';
3
3
  export { AuthBranding, AuthContainer, AuthContainerProps, AuthDivider, AuthDividerProps, AuthEmailVerificationStep, AuthErrorBanner, AuthErrorBannerProps, AuthFormField, AuthFormFieldProps, AuthHeader, AuthHeaderProps, AuthLink, AuthLinkProps, AuthOAuthButton, AuthOAuthButtonProps, AuthOAuthProviders, AuthOAuthProvidersProps, AuthPasswordField, AuthPasswordFieldProps, AuthPasswordStrengthIndicator, AuthPasswordStrengthIndicatorProps, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthSubmitButtonProps, AuthVerificationCodeInput, AuthVerificationCodeInputProps } from './atoms.js';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import { createContext, forwardRef, useContext, useState, useMemo, useEffect, us
17
17
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
18
18
  import { createClient } from '@insforge/sdk';
19
19
  import { InsforgeContext } from '@insforge/shared/react';
20
- import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck, LogOut } from 'lucide-react';
20
+ import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck, X, User, LogOut } from 'lucide-react';
21
21
  import { z } from 'zod';
22
22
 
23
23
  var __create = Object.create;
@@ -225,7 +225,7 @@ var require_react_is_development = __commonJS({
225
225
  var ContextProvider = REACT_PROVIDER_TYPE;
226
226
  var Element = REACT_ELEMENT_TYPE;
227
227
  var ForwardRef = REACT_FORWARD_REF_TYPE;
228
- var Fragment9 = REACT_FRAGMENT_TYPE;
228
+ var Fragment10 = REACT_FRAGMENT_TYPE;
229
229
  var Lazy = REACT_LAZY_TYPE;
230
230
  var Memo = REACT_MEMO_TYPE;
231
231
  var Portal = REACT_PORTAL_TYPE;
@@ -284,7 +284,7 @@ var require_react_is_development = __commonJS({
284
284
  exports$1.ContextProvider = ContextProvider;
285
285
  exports$1.Element = Element;
286
286
  exports$1.ForwardRef = ForwardRef;
287
- exports$1.Fragment = Fragment9;
287
+ exports$1.Fragment = Fragment10;
288
288
  exports$1.Lazy = Lazy;
289
289
  exports$1.Memo = Memo;
290
290
  exports$1.Portal = Portal;
@@ -568,11 +568,14 @@ var InsforgeManager = class _InsforgeManager {
568
568
  const userResult = await this.sdk.auth.getCurrentUser();
569
569
  if (userResult.data) {
570
570
  const profile = userResult.data.user.profile;
571
+ const { name, avatar_url, ...dynamicFields } = profile || {};
571
572
  const userData = {
572
573
  id: userResult.data.user.id,
573
574
  email: userResult.data.user.email,
574
- name: profile?.name || "",
575
- avatarUrl: profile?.avatar_url || ""
575
+ name: name || "",
576
+ avatarUrl: avatar_url || "",
577
+ // Store additional dynamic fields
578
+ profile: Object.keys(dynamicFields).length > 0 ? dynamicFields : void 0
576
579
  };
577
580
  this.user = userData;
578
581
  if (this.config.onAuthChange) {
@@ -609,11 +612,14 @@ var InsforgeManager = class _InsforgeManager {
609
612
  const userResult = await this.sdk.auth.getCurrentUser();
610
613
  if (userResult.data) {
611
614
  const profile = userResult.data.user.profile;
615
+ const { name, avatar_url, ...dynamicFields } = profile || {};
612
616
  const userData = {
613
617
  id: userResult.data.user.id,
614
618
  email: userResult.data.user.email,
615
- name: profile?.name || "",
616
- avatarUrl: profile?.avatar_url || ""
619
+ name: name || "",
620
+ avatarUrl: avatar_url || "",
621
+ // Store additional dynamic fields
622
+ profile: Object.keys(dynamicFields).length > 0 ? dynamicFields : void 0
617
623
  };
618
624
  this.user = userData;
619
625
  this.notifyListeners();
@@ -714,27 +720,32 @@ var InsforgeManager = class _InsforgeManager {
714
720
  if (!this.user) {
715
721
  return { error: "No user signed in" };
716
722
  }
717
- const profileUpdate = {
718
- name: data.name,
719
- avatar_url: data.avatarUrl
720
- };
723
+ const profileUpdate = {};
724
+ if (data.name !== void 0) {
725
+ profileUpdate.name = data.name;
726
+ }
727
+ if (data.avatarUrl !== void 0) {
728
+ profileUpdate.avatar_url = data.avatarUrl;
729
+ }
730
+ if (data.profile) {
731
+ Object.assign(profileUpdate, data.profile);
732
+ }
721
733
  const result = await this.sdk.auth.setProfile(profileUpdate);
722
734
  if (result.data) {
723
- const userResult = await this.sdk.auth.getCurrentUser();
724
- if (userResult.data) {
725
- const profile = userResult.data.user.profile;
726
- const updatedUser = {
727
- id: userResult.data.user.id,
728
- email: userResult.data.user.email,
729
- name: profile?.name || "",
730
- avatarUrl: profile?.avatar_url || ""
731
- };
732
- this.user = updatedUser;
733
- if (this.config.onAuthChange) {
734
- this.config.onAuthChange(updatedUser);
735
- }
736
- this.notifyListeners();
735
+ const updatedUser = {
736
+ id: this.user.id,
737
+ email: this.user.email,
738
+ // Use sent value if provided, otherwise keep existing
739
+ name: profileUpdate.name !== void 0 ? profileUpdate.name : this.user.name || "",
740
+ avatarUrl: profileUpdate.avatar_url !== void 0 ? profileUpdate.avatar_url : this.user.avatarUrl || "",
741
+ // Merge existing profile with new dynamic fields
742
+ profile: data.profile ? { ...this.user.profile, ...data.profile } : this.user.profile
743
+ };
744
+ this.user = updatedUser;
745
+ if (this.config.onAuthChange) {
746
+ this.config.onAuthChange(updatedUser);
737
747
  }
748
+ this.notifyListeners();
738
749
  return null;
739
750
  }
740
751
  const error = result.error;
@@ -5257,9 +5268,382 @@ var UserButtonMenuItemIcon = styled.div`
5257
5268
  height: 100%;
5258
5269
  }
5259
5270
  `;
5260
- function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
5271
+ var ProfileModalOverlay = styled.div`
5272
+ position: fixed;
5273
+ inset: 0;
5274
+ background-color: rgba(0, 0, 0, 0.5);
5275
+ display: flex;
5276
+ align-items: center;
5277
+ justify-content: center;
5278
+ z-index: 100;
5279
+ padding: ${theme.spacing[4]};
5280
+ `;
5281
+ var ProfileModalContainer = styled.div`
5282
+ background-color: ${theme.colors.bgWhite};
5283
+ border-radius: ${theme.radius.xl};
5284
+ box-shadow: ${theme.shadow.lg};
5285
+ width: 100%;
5286
+ max-width: 400px;
5287
+ max-height: 90vh;
5288
+ overflow: hidden;
5289
+ display: flex;
5290
+ flex-direction: column;
5291
+ font-family: ${theme.fontFamily.base};
5292
+ `;
5293
+ var ProfileModalHeader = styled.div`
5294
+ display: flex;
5295
+ align-items: center;
5296
+ justify-content: space-between;
5297
+ padding: ${theme.spacing[4]} ${theme.spacing[6]};
5298
+ border-bottom: 1px solid ${theme.colors.border};
5299
+ `;
5300
+ var ProfileModalTitle = styled.h2`
5301
+ font-size: ${theme.fontSize.lg};
5302
+ font-weight: ${theme.fontWeight.semibold};
5303
+ color: ${theme.colors.text};
5304
+ margin: 0;
5305
+ `;
5306
+ var ProfileModalCloseButton = styled.button`
5307
+ display: flex;
5308
+ align-items: center;
5309
+ justify-content: center;
5310
+ width: 2rem;
5311
+ height: 2rem;
5312
+ border-radius: ${theme.radius.md};
5313
+ background: none;
5314
+ border: none;
5315
+ cursor: pointer;
5316
+ color: ${theme.colors.textSecondary};
5317
+ transition: all ${theme.transition.fast};
5318
+
5319
+ &:hover {
5320
+ background-color: ${theme.colors.bgLight};
5321
+ color: ${theme.colors.text};
5322
+ }
5323
+
5324
+ svg {
5325
+ width: 1.25rem;
5326
+ height: 1.25rem;
5327
+ }
5328
+ `;
5329
+ var ProfileModalBody = styled.div`
5330
+ padding: ${theme.spacing[6]};
5331
+ overflow-y: auto;
5332
+ flex: 1;
5333
+ `;
5334
+ var ProfileAvatarSection = styled.div`
5335
+ display: flex;
5336
+ flex-direction: column;
5337
+ align-items: center;
5338
+ margin-bottom: ${theme.spacing[6]};
5339
+ `;
5340
+ var ProfileAvatar = styled.div`
5341
+ width: 5rem;
5342
+ height: 5rem;
5343
+ border-radius: ${theme.radius.full};
5344
+ background-color: ${theme.colors.primary};
5345
+ color: ${theme.colors.bgWhite};
5346
+ display: flex;
5347
+ align-items: center;
5348
+ justify-content: center;
5349
+ font-weight: ${theme.fontWeight.semibold};
5350
+ font-size: ${theme.fontSize["2xl"]};
5351
+ overflow: hidden;
5352
+ `;
5353
+ var ProfileAvatarImage = styled.img`
5354
+ width: 100%;
5355
+ height: 100%;
5356
+ object-fit: cover;
5357
+ `;
5358
+ var ProfileFieldsContainer = styled.div`
5359
+ display: flex;
5360
+ flex-direction: column;
5361
+ gap: ${theme.spacing[4]};
5362
+ `;
5363
+ var ProfileField = styled.div`
5364
+ display: flex;
5365
+ flex-direction: column;
5366
+ gap: ${theme.spacing[1]};
5367
+ `;
5368
+ var ProfileFieldLabel = styled.label`
5369
+ font-size: ${theme.fontSize.sm};
5370
+ font-weight: ${theme.fontWeight.medium};
5371
+ color: ${theme.colors.textSecondary};
5372
+ text-transform: capitalize;
5373
+ `;
5374
+ var ProfileFieldValue = styled.div`
5375
+ font-size: ${theme.fontSize.base};
5376
+ color: ${theme.colors.text};
5377
+ padding: ${theme.spacing[2]} 0;
5378
+ word-break: break-word;
5379
+ `;
5380
+ var ProfileFieldInput = styled.input`
5381
+ width: 100%;
5382
+ height: ${theme.sizes.input.height};
5383
+ padding: 0 ${theme.spacing[3]};
5384
+ border: 1px solid ${theme.colors.border};
5385
+ border-radius: ${theme.radius.md};
5386
+ font-size: ${theme.fontSize.base};
5387
+ font-family: ${theme.fontFamily.base};
5388
+ color: ${theme.colors.text};
5389
+ background-color: ${theme.colors.bgWhite};
5390
+ transition: border-color ${theme.transition.fast};
5391
+
5392
+ &:focus {
5393
+ outline: none;
5394
+ border-color: ${theme.colors.borderFocus};
5395
+ }
5396
+
5397
+ &:disabled {
5398
+ background-color: ${theme.colors.bgLight};
5399
+ color: ${theme.colors.textSecondary};
5400
+ cursor: not-allowed;
5401
+ }
5402
+ `;
5403
+ var ProfileModalFooter = styled.div`
5404
+ display: flex;
5405
+ align-items: center;
5406
+ justify-content: flex-end;
5407
+ gap: ${theme.spacing[3]};
5408
+ padding: ${theme.spacing[4]} ${theme.spacing[6]};
5409
+ border-top: 1px solid ${theme.colors.border};
5410
+ `;
5411
+ var ProfileButton = styled.button`
5412
+ display: flex;
5413
+ align-items: center;
5414
+ justify-content: center;
5415
+ gap: ${theme.spacing[2]};
5416
+ height: ${theme.sizes.button.height};
5417
+ padding: 0 ${theme.spacing[4]};
5418
+ border-radius: ${theme.radius.md};
5419
+ font-size: ${theme.fontSize.sm};
5420
+ font-weight: ${theme.fontWeight.medium};
5421
+ font-family: ${theme.fontFamily.base};
5422
+ cursor: pointer;
5423
+ transition: all ${theme.transition.fast};
5424
+
5425
+ ${(props) => props.$primary ? `
5426
+ background-color: ${theme.colors.primary};
5427
+ color: ${theme.colors.bgWhite};
5428
+ border: none;
5429
+
5430
+ &:hover:not(:disabled) {
5431
+ background-color: ${theme.colors.primaryHover};
5432
+ }
5433
+
5434
+ &:disabled {
5435
+ opacity: 0.5;
5436
+ cursor: not-allowed;
5437
+ }
5438
+ ` : `
5439
+ background-color: ${theme.colors.bgWhite};
5440
+ color: ${theme.colors.text};
5441
+ border: 1px solid ${theme.colors.border};
5442
+
5443
+ &:hover:not(:disabled) {
5444
+ background-color: ${theme.colors.bgLight};
5445
+ }
5446
+
5447
+ &:disabled {
5448
+ opacity: 0.5;
5449
+ cursor: not-allowed;
5450
+ }
5451
+ `}
5452
+ `;
5453
+ var ProfileSpinner = styled.div`
5454
+ width: 1rem;
5455
+ height: 1rem;
5456
+ border: 2px solid transparent;
5457
+ border-top-color: currentColor;
5458
+ border-radius: ${theme.radius.full};
5459
+ animation: spin 0.6s linear infinite;
5460
+
5461
+ @keyframes spin {
5462
+ to {
5463
+ transform: rotate(360deg);
5464
+ }
5465
+ }
5466
+ `;
5467
+ var READ_ONLY_FIELDS = ["id", "email", "avatar_url", "created_at", "updated_at"];
5468
+ var HIDDEN_FIELDS = ["id"];
5469
+ function formatFieldLabel(key) {
5470
+ return key.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
5471
+ }
5472
+ function UserProfileModal({ onClose, onError }) {
5473
+ const { user, updateUser, isLoaded } = useInsforge();
5474
+ const [isEditing, setIsEditing] = useState(false);
5475
+ const [isSaving, setIsSaving] = useState(false);
5476
+ const [imageError, setImageError] = useState(false);
5477
+ const [formData, setFormData] = useState({});
5478
+ useEffect(() => {
5479
+ if (user) {
5480
+ const initialData = {
5481
+ name: user.name || ""
5482
+ };
5483
+ if (user.profile) {
5484
+ Object.entries(user.profile).forEach(([key, value]) => {
5485
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
5486
+ initialData[key] = value;
5487
+ }
5488
+ });
5489
+ }
5490
+ setFormData(initialData);
5491
+ }
5492
+ }, [user]);
5493
+ useEffect(() => {
5494
+ setImageError(false);
5495
+ const avatarUrl = user?.avatarUrl;
5496
+ if (!avatarUrl) {
5497
+ return;
5498
+ }
5499
+ const checkImageUrl = async () => {
5500
+ try {
5501
+ const response = await fetch(avatarUrl, {
5502
+ method: "HEAD",
5503
+ cache: "no-cache"
5504
+ });
5505
+ if (!response.ok) {
5506
+ setImageError(true);
5507
+ }
5508
+ } catch {
5509
+ setImageError(true);
5510
+ }
5511
+ };
5512
+ void checkImageUrl();
5513
+ }, [user?.avatarUrl]);
5514
+ const handleFieldChange = useCallback((key, value) => {
5515
+ setFormData((prev2) => ({
5516
+ ...prev2,
5517
+ [key]: value
5518
+ }));
5519
+ }, []);
5520
+ const handleSave = useCallback(async () => {
5521
+ if (!user) return;
5522
+ setIsSaving(true);
5523
+ try {
5524
+ const { name, ...dynamicFields } = formData;
5525
+ const updateData = {
5526
+ name
5527
+ };
5528
+ if (Object.keys(dynamicFields).length > 0) {
5529
+ updateData.profile = dynamicFields;
5530
+ }
5531
+ const result = await updateUser(updateData);
5532
+ if (result?.error) {
5533
+ onError?.(result.error);
5534
+ } else {
5535
+ setIsEditing(false);
5536
+ }
5537
+ } catch (error) {
5538
+ onError?.(error instanceof Error ? error.message : "Failed to update profile");
5539
+ } finally {
5540
+ setIsSaving(false);
5541
+ }
5542
+ }, [user, formData, updateUser, onError]);
5543
+ const handleCancel = useCallback(() => {
5544
+ if (user) {
5545
+ const resetData = {
5546
+ name: user.name || ""
5547
+ };
5548
+ if (user.profile) {
5549
+ Object.entries(user.profile).forEach(([key, value]) => {
5550
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
5551
+ resetData[key] = value;
5552
+ }
5553
+ });
5554
+ }
5555
+ setFormData(resetData);
5556
+ }
5557
+ setIsEditing(false);
5558
+ }, [user]);
5559
+ const handleOverlayClick = useCallback(
5560
+ (e) => {
5561
+ if (e.target === e.currentTarget) {
5562
+ onClose();
5563
+ }
5564
+ },
5565
+ [onClose]
5566
+ );
5567
+ useEffect(() => {
5568
+ const handleEscape = (e) => {
5569
+ if (e.key === "Escape") {
5570
+ if (isEditing) {
5571
+ handleCancel();
5572
+ } else {
5573
+ onClose();
5574
+ }
5575
+ }
5576
+ };
5577
+ document.addEventListener("keydown", handleEscape);
5578
+ return () => document.removeEventListener("keydown", handleEscape);
5579
+ }, [isEditing, handleCancel, onClose]);
5580
+ if (!isLoaded || !user) {
5581
+ return null;
5582
+ }
5583
+ const initials = user.name ? user.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
5584
+ const fields = [];
5585
+ fields.push({ key: "email", value: user.email, readOnly: true });
5586
+ fields.push({
5587
+ key: "name",
5588
+ value: isEditing ? formData.name || "" : user.name || "",
5589
+ readOnly: false
5590
+ });
5591
+ if (user.profile) {
5592
+ Object.entries(user.profile).forEach(([key, value]) => {
5593
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
5594
+ fields.push({
5595
+ key,
5596
+ value: isEditing ? formData[key] ?? value : value,
5597
+ readOnly: READ_ONLY_FIELDS.includes(key)
5598
+ });
5599
+ }
5600
+ });
5601
+ }
5602
+ return /* @__PURE__ */ jsx(ProfileModalOverlay, { onClick: handleOverlayClick, children: /* @__PURE__ */ jsxs(ProfileModalContainer, { onClick: (e) => e.stopPropagation(), children: [
5603
+ /* @__PURE__ */ jsxs(ProfileModalHeader, { children: [
5604
+ /* @__PURE__ */ jsx(ProfileModalTitle, { children: "Profile" }),
5605
+ /* @__PURE__ */ jsx(ProfileModalCloseButton, { onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(X, {}) })
5606
+ ] }),
5607
+ /* @__PURE__ */ jsxs(ProfileModalBody, { children: [
5608
+ /* @__PURE__ */ jsx(ProfileAvatarSection, { children: /* @__PURE__ */ jsx(ProfileAvatar, { children: user.avatarUrl && !imageError ? /* @__PURE__ */ jsx(
5609
+ ProfileAvatarImage,
5610
+ {
5611
+ src: user.avatarUrl,
5612
+ alt: user.name || user.email,
5613
+ onError: () => setImageError(true)
5614
+ }
5615
+ ) : initials }) }),
5616
+ /* @__PURE__ */ jsx(ProfileFieldsContainer, { children: fields.map(({ key, value, readOnly }) => /* @__PURE__ */ jsxs(ProfileField, { children: [
5617
+ /* @__PURE__ */ jsx(ProfileFieldLabel, { children: formatFieldLabel(key) }),
5618
+ isEditing && !readOnly ? /* @__PURE__ */ jsx(
5619
+ ProfileFieldInput,
5620
+ {
5621
+ type: "text",
5622
+ value: formData[key] ?? value,
5623
+ onChange: (e) => handleFieldChange(key, e.target.value),
5624
+ disabled: isSaving
5625
+ }
5626
+ ) : /* @__PURE__ */ jsx(ProfileFieldValue, { children: value || "-" })
5627
+ ] }, key)) })
5628
+ ] }),
5629
+ /* @__PURE__ */ jsx(ProfileModalFooter, { children: isEditing ? /* @__PURE__ */ jsxs(Fragment, { children: [
5630
+ /* @__PURE__ */ jsx(ProfileButton, { onClick: handleCancel, disabled: isSaving, children: "Cancel" }),
5631
+ /* @__PURE__ */ jsxs(ProfileButton, { $primary: true, onClick: handleSave, disabled: isSaving, children: [
5632
+ isSaving && /* @__PURE__ */ jsx(ProfileSpinner, {}),
5633
+ isSaving ? "Saving..." : "Save"
5634
+ ] })
5635
+ ] }) : /* @__PURE__ */ jsx(ProfileButton, { $primary: true, onClick: () => setIsEditing(true), children: "Edit Profile" }) })
5636
+ ] }) });
5637
+ }
5638
+ function UserButton({
5639
+ afterSignOutUrl = "/",
5640
+ mode = "simple",
5641
+ showProfile = true,
5642
+ onProfileError
5643
+ }) {
5261
5644
  const { user } = useInsforge();
5262
5645
  const [isOpen, setIsOpen] = useState(false);
5646
+ const [showProfileModal, setShowProfileModal] = useState(false);
5263
5647
  const [imageError, setImageError] = useState(false);
5264
5648
  const [openUpward, setOpenUpward] = useState(false);
5265
5649
  const [horizontalOffset, setHorizontalOffset] = useState(0);
@@ -5357,10 +5741,32 @@ function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
5357
5741
  ]
5358
5742
  }
5359
5743
  ),
5360
- isOpen && /* @__PURE__ */ jsx(UserButtonMenu, { ref: menuRef, $openUpward: openUpward, $horizontalOffset: horizontalOffset, children: /* @__PURE__ */ jsx(SignOutButton, { afterSignOutUrl, children: /* @__PURE__ */ jsxs(UserButtonMenuItem, { $signout: true, onClick: () => setIsOpen(false), children: [
5361
- /* @__PURE__ */ jsx(UserButtonMenuItemIcon, { children: /* @__PURE__ */ jsx(LogOut, {}) }),
5362
- "Sign out"
5363
- ] }) }) })
5744
+ isOpen && /* @__PURE__ */ jsxs(UserButtonMenu, { ref: menuRef, $openUpward: openUpward, $horizontalOffset: horizontalOffset, children: [
5745
+ showProfile && /* @__PURE__ */ jsxs(
5746
+ UserButtonMenuItem,
5747
+ {
5748
+ onClick: () => {
5749
+ setShowProfileModal(true);
5750
+ setIsOpen(false);
5751
+ },
5752
+ children: [
5753
+ /* @__PURE__ */ jsx(UserButtonMenuItemIcon, { children: /* @__PURE__ */ jsx(User, {}) }),
5754
+ "Profile"
5755
+ ]
5756
+ }
5757
+ ),
5758
+ /* @__PURE__ */ jsx(SignOutButton, { afterSignOutUrl, children: /* @__PURE__ */ jsxs(UserButtonMenuItem, { $signout: true, onClick: () => setIsOpen(false), children: [
5759
+ /* @__PURE__ */ jsx(UserButtonMenuItemIcon, { children: /* @__PURE__ */ jsx(LogOut, {}) }),
5760
+ "Sign out"
5761
+ ] }) })
5762
+ ] }),
5763
+ showProfileModal && /* @__PURE__ */ jsx(
5764
+ UserProfileModal,
5765
+ {
5766
+ onClose: () => setShowProfileModal(false),
5767
+ onError: onProfileError
5768
+ }
5769
+ )
5364
5770
  ] });
5365
5771
  }
5366
5772
  function Protect({
@@ -5491,6 +5897,6 @@ react-is/cjs/react-is.development.js:
5491
5897
  *)
5492
5898
  */
5493
5899
 
5494
- export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthVerificationCodeInput, BrowserNavigationAdapter, ForgotPassword, ForgotPasswordForm, InsforgeProvider, InsforgeProviderCore, NavigationProvider, OAUTH_PROVIDER_CONFIG, Protect, ResetPassword, ResetPasswordForm, SignIn, SignInButton, SignInForm, SignOutButton, SignUp, SignUpButton, SignUpForm, SignedIn, SignedOut, StyleProvider, UserButton, VerifyEmail, VerifyEmailStatus, checkPasswordStrength, createPasswordSchema, emailSchema, getAllProviderConfigs, getProviderConfig, passwordSchema, resolveAuthPath, resolveAuthUrl, theme, useAuth, useInsforge, useNavigationAdapter, usePublicAuthConfig, useSearchParams, useUser, validateEmail, validatePassword };
5900
+ export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthVerificationCodeInput, BrowserNavigationAdapter, ForgotPassword, ForgotPasswordForm, InsforgeProvider, InsforgeProviderCore, NavigationProvider, OAUTH_PROVIDER_CONFIG, Protect, ResetPassword, ResetPasswordForm, SignIn, SignInButton, SignInForm, SignOutButton, SignUp, SignUpButton, SignUpForm, SignedIn, SignedOut, StyleProvider, UserButton, UserProfileModal, VerifyEmail, VerifyEmailStatus, checkPasswordStrength, createPasswordSchema, emailSchema, getAllProviderConfigs, getProviderConfig, passwordSchema, resolveAuthPath, resolveAuthUrl, theme, useAuth, useInsforge, useNavigationAdapter, usePublicAuthConfig, useSearchParams, useUser, validateEmail, validatePassword };
5495
5901
  //# sourceMappingURL=index.js.map
5496
5902
  //# sourceMappingURL=index.js.map