@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.
@@ -163,13 +163,29 @@ declare function VerifyEmail({ token, onSuccess, onError, ...uiProps }: VerifyEm
163
163
  interface UserButtonProps {
164
164
  afterSignOutUrl?: string;
165
165
  mode?: 'detailed' | 'simple';
166
+ /** Whether to show the Profile menu item (default: true) */
167
+ showProfile?: boolean;
168
+ /** Callback when profile update fails */
169
+ onProfileError?: (error: string) => void;
166
170
  }
167
171
  /**
168
172
  * User profile button with dropdown menu and sign-out functionality.
169
173
  *
170
174
  * Styles are powered by Emotion CSS-in-JS to prevent FOUC in SSR environments.
171
175
  */
172
- declare function UserButton({ afterSignOutUrl, mode }: UserButtonProps): react_jsx_runtime.JSX.Element | null;
176
+ declare function UserButton({ afterSignOutUrl, mode, showProfile, onProfileError, }: UserButtonProps): react_jsx_runtime.JSX.Element | null;
177
+
178
+ interface UserProfileModalProps {
179
+ /** Called when the modal is closed */
180
+ onClose: () => void;
181
+ /** Called when an error occurs */
182
+ onError?: (error: string) => void;
183
+ }
184
+ /**
185
+ * User profile modal component.
186
+ * Displays user profile information with edit capability for allowed fields.
187
+ */
188
+ declare function UserProfileModal({ onClose, onError }: UserProfileModalProps): react_jsx_runtime.JSX.Element | null;
173
189
 
174
190
  interface ProtectProps {
175
191
  children: ReactNode;
@@ -341,4 +357,4 @@ interface SignOutButtonProps {
341
357
  */
342
358
  declare function SignOutButton({ children, className, afterSignOutUrl }: SignOutButtonProps): react_jsx_runtime.JSX.Element;
343
359
 
344
- export { type ConditionalProps$1 as ConditionalProps, ForgotPassword, type ForgotPasswordProps, Protect, type ProtectProps, ResetPassword, type ResetPasswordProps, SignIn, SignInButton, type SignInButtonProps, type SignInProps, SignOutButton, type SignOutButtonProps, SignUp, SignUpButton, type SignUpButtonProps, type SignUpProps, SignedIn, SignedOut, UserButton, type UserButtonProps, VerifyEmail, type VerifyEmailProps };
360
+ export { type ConditionalProps$1 as ConditionalProps, ForgotPassword, type ForgotPasswordProps, Protect, type ProtectProps, ResetPassword, type ResetPasswordProps, SignIn, SignInButton, type SignInButtonProps, type SignInProps, SignOutButton, type SignOutButtonProps, SignUp, SignUpButton, type SignUpButtonProps, type SignUpProps, SignedIn, SignedOut, UserButton, type UserButtonProps, UserProfileModal, type UserProfileModalProps, VerifyEmail, type VerifyEmailProps };
@@ -163,13 +163,29 @@ declare function VerifyEmail({ token, onSuccess, onError, ...uiProps }: VerifyEm
163
163
  interface UserButtonProps {
164
164
  afterSignOutUrl?: string;
165
165
  mode?: 'detailed' | 'simple';
166
+ /** Whether to show the Profile menu item (default: true) */
167
+ showProfile?: boolean;
168
+ /** Callback when profile update fails */
169
+ onProfileError?: (error: string) => void;
166
170
  }
167
171
  /**
168
172
  * User profile button with dropdown menu and sign-out functionality.
169
173
  *
170
174
  * Styles are powered by Emotion CSS-in-JS to prevent FOUC in SSR environments.
171
175
  */
172
- declare function UserButton({ afterSignOutUrl, mode }: UserButtonProps): react_jsx_runtime.JSX.Element | null;
176
+ declare function UserButton({ afterSignOutUrl, mode, showProfile, onProfileError, }: UserButtonProps): react_jsx_runtime.JSX.Element | null;
177
+
178
+ interface UserProfileModalProps {
179
+ /** Called when the modal is closed */
180
+ onClose: () => void;
181
+ /** Called when an error occurs */
182
+ onError?: (error: string) => void;
183
+ }
184
+ /**
185
+ * User profile modal component.
186
+ * Displays user profile information with edit capability for allowed fields.
187
+ */
188
+ declare function UserProfileModal({ onClose, onError }: UserProfileModalProps): react_jsx_runtime.JSX.Element | null;
173
189
 
174
190
  interface ProtectProps {
175
191
  children: ReactNode;
@@ -341,4 +357,4 @@ interface SignOutButtonProps {
341
357
  */
342
358
  declare function SignOutButton({ children, className, afterSignOutUrl }: SignOutButtonProps): react_jsx_runtime.JSX.Element;
343
359
 
344
- export { type ConditionalProps$1 as ConditionalProps, ForgotPassword, type ForgotPasswordProps, Protect, type ProtectProps, ResetPassword, type ResetPasswordProps, SignIn, SignInButton, type SignInButtonProps, type SignInProps, SignOutButton, type SignOutButtonProps, SignUp, SignUpButton, type SignUpButtonProps, type SignUpProps, SignedIn, SignedOut, UserButton, type UserButtonProps, VerifyEmail, type VerifyEmailProps };
360
+ export { type ConditionalProps$1 as ConditionalProps, ForgotPassword, type ForgotPasswordProps, Protect, type ProtectProps, ResetPassword, type ResetPasswordProps, SignIn, SignInButton, type SignInButtonProps, type SignInProps, SignOutButton, type SignOutButtonProps, SignUp, SignUpButton, type SignUpButtonProps, type SignUpProps, SignedIn, SignedOut, UserButton, type UserButtonProps, UserProfileModal, type UserProfileModalProps, VerifyEmail, type VerifyEmailProps };
@@ -3,7 +3,7 @@ import { createContext, forwardRef, useContext, useState, useMemo, useRef, useEf
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
  import '@insforge/sdk';
5
5
  import { InsforgeContext } from '@insforge/shared/react';
6
- import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck, LogOut } from 'lucide-react';
6
+ import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck, X, User, LogOut } from 'lucide-react';
7
7
  import { z } from 'zod';
8
8
 
9
9
  var __create = Object.create;
@@ -211,7 +211,7 @@ var require_react_is_development = __commonJS({
211
211
  var ContextProvider = REACT_PROVIDER_TYPE;
212
212
  var Element = REACT_ELEMENT_TYPE;
213
213
  var ForwardRef = REACT_FORWARD_REF_TYPE;
214
- var Fragment9 = REACT_FRAGMENT_TYPE;
214
+ var Fragment10 = REACT_FRAGMENT_TYPE;
215
215
  var Lazy = REACT_LAZY_TYPE;
216
216
  var Memo = REACT_MEMO_TYPE;
217
217
  var Portal = REACT_PORTAL_TYPE;
@@ -270,7 +270,7 @@ var require_react_is_development = __commonJS({
270
270
  exports$1.ContextProvider = ContextProvider;
271
271
  exports$1.Element = Element;
272
272
  exports$1.ForwardRef = ForwardRef;
273
- exports$1.Fragment = Fragment9;
273
+ exports$1.Fragment = Fragment10;
274
274
  exports$1.Lazy = Lazy;
275
275
  exports$1.Memo = Memo;
276
276
  exports$1.Portal = Portal;
@@ -2127,6 +2127,8 @@ var theme = {
2127
2127
  sm: "0.875rem",
2128
2128
  // 14px
2129
2129
  base: "1rem",
2130
+ // 16px
2131
+ lg: "1.125rem",
2130
2132
  // 20px
2131
2133
  "2xl": "1.5rem"
2132
2134
  // 24px
@@ -2158,6 +2160,10 @@ var theme = {
2158
2160
  base: "200ms cubic-bezier(0.4, 0, 0.2, 1)"
2159
2161
  },
2160
2162
  sizes: {
2163
+ input: {
2164
+ height: "2.5rem"
2165
+ // 40px
2166
+ },
2161
2167
  button: {
2162
2168
  height: "2.5rem",
2163
2169
  // 40px for submit
@@ -4673,9 +4679,382 @@ var UserButtonMenuItemIcon = styled.div`
4673
4679
  height: 100%;
4674
4680
  }
4675
4681
  `;
4676
- function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
4682
+ var ProfileModalOverlay = styled.div`
4683
+ position: fixed;
4684
+ inset: 0;
4685
+ background-color: rgba(0, 0, 0, 0.5);
4686
+ display: flex;
4687
+ align-items: center;
4688
+ justify-content: center;
4689
+ z-index: 100;
4690
+ padding: ${theme.spacing[4]};
4691
+ `;
4692
+ var ProfileModalContainer = styled.div`
4693
+ background-color: ${theme.colors.bgWhite};
4694
+ border-radius: ${theme.radius.xl};
4695
+ box-shadow: ${theme.shadow.lg};
4696
+ width: 100%;
4697
+ max-width: 400px;
4698
+ max-height: 90vh;
4699
+ overflow: hidden;
4700
+ display: flex;
4701
+ flex-direction: column;
4702
+ font-family: ${theme.fontFamily.base};
4703
+ `;
4704
+ var ProfileModalHeader = styled.div`
4705
+ display: flex;
4706
+ align-items: center;
4707
+ justify-content: space-between;
4708
+ padding: ${theme.spacing[4]} ${theme.spacing[6]};
4709
+ border-bottom: 1px solid ${theme.colors.border};
4710
+ `;
4711
+ var ProfileModalTitle = styled.h2`
4712
+ font-size: ${theme.fontSize.lg};
4713
+ font-weight: ${theme.fontWeight.semibold};
4714
+ color: ${theme.colors.text};
4715
+ margin: 0;
4716
+ `;
4717
+ var ProfileModalCloseButton = styled.button`
4718
+ display: flex;
4719
+ align-items: center;
4720
+ justify-content: center;
4721
+ width: 2rem;
4722
+ height: 2rem;
4723
+ border-radius: ${theme.radius.md};
4724
+ background: none;
4725
+ border: none;
4726
+ cursor: pointer;
4727
+ color: ${theme.colors.textSecondary};
4728
+ transition: all ${theme.transition.fast};
4729
+
4730
+ &:hover {
4731
+ background-color: ${theme.colors.bgLight};
4732
+ color: ${theme.colors.text};
4733
+ }
4734
+
4735
+ svg {
4736
+ width: 1.25rem;
4737
+ height: 1.25rem;
4738
+ }
4739
+ `;
4740
+ var ProfileModalBody = styled.div`
4741
+ padding: ${theme.spacing[6]};
4742
+ overflow-y: auto;
4743
+ flex: 1;
4744
+ `;
4745
+ var ProfileAvatarSection = styled.div`
4746
+ display: flex;
4747
+ flex-direction: column;
4748
+ align-items: center;
4749
+ margin-bottom: ${theme.spacing[6]};
4750
+ `;
4751
+ var ProfileAvatar = styled.div`
4752
+ width: 5rem;
4753
+ height: 5rem;
4754
+ border-radius: ${theme.radius.full};
4755
+ background-color: ${theme.colors.primary};
4756
+ color: ${theme.colors.bgWhite};
4757
+ display: flex;
4758
+ align-items: center;
4759
+ justify-content: center;
4760
+ font-weight: ${theme.fontWeight.semibold};
4761
+ font-size: ${theme.fontSize["2xl"]};
4762
+ overflow: hidden;
4763
+ `;
4764
+ var ProfileAvatarImage = styled.img`
4765
+ width: 100%;
4766
+ height: 100%;
4767
+ object-fit: cover;
4768
+ `;
4769
+ var ProfileFieldsContainer = styled.div`
4770
+ display: flex;
4771
+ flex-direction: column;
4772
+ gap: ${theme.spacing[4]};
4773
+ `;
4774
+ var ProfileField = styled.div`
4775
+ display: flex;
4776
+ flex-direction: column;
4777
+ gap: ${theme.spacing[1]};
4778
+ `;
4779
+ var ProfileFieldLabel = styled.label`
4780
+ font-size: ${theme.fontSize.sm};
4781
+ font-weight: ${theme.fontWeight.medium};
4782
+ color: ${theme.colors.textSecondary};
4783
+ text-transform: capitalize;
4784
+ `;
4785
+ var ProfileFieldValue = styled.div`
4786
+ font-size: ${theme.fontSize.base};
4787
+ color: ${theme.colors.text};
4788
+ padding: ${theme.spacing[2]} 0;
4789
+ word-break: break-word;
4790
+ `;
4791
+ var ProfileFieldInput = styled.input`
4792
+ width: 100%;
4793
+ height: ${theme.sizes.input.height};
4794
+ padding: 0 ${theme.spacing[3]};
4795
+ border: 1px solid ${theme.colors.border};
4796
+ border-radius: ${theme.radius.md};
4797
+ font-size: ${theme.fontSize.base};
4798
+ font-family: ${theme.fontFamily.base};
4799
+ color: ${theme.colors.text};
4800
+ background-color: ${theme.colors.bgWhite};
4801
+ transition: border-color ${theme.transition.fast};
4802
+
4803
+ &:focus {
4804
+ outline: none;
4805
+ border-color: ${theme.colors.borderFocus};
4806
+ }
4807
+
4808
+ &:disabled {
4809
+ background-color: ${theme.colors.bgLight};
4810
+ color: ${theme.colors.textSecondary};
4811
+ cursor: not-allowed;
4812
+ }
4813
+ `;
4814
+ var ProfileModalFooter = styled.div`
4815
+ display: flex;
4816
+ align-items: center;
4817
+ justify-content: flex-end;
4818
+ gap: ${theme.spacing[3]};
4819
+ padding: ${theme.spacing[4]} ${theme.spacing[6]};
4820
+ border-top: 1px solid ${theme.colors.border};
4821
+ `;
4822
+ var ProfileButton = styled.button`
4823
+ display: flex;
4824
+ align-items: center;
4825
+ justify-content: center;
4826
+ gap: ${theme.spacing[2]};
4827
+ height: ${theme.sizes.button.height};
4828
+ padding: 0 ${theme.spacing[4]};
4829
+ border-radius: ${theme.radius.md};
4830
+ font-size: ${theme.fontSize.sm};
4831
+ font-weight: ${theme.fontWeight.medium};
4832
+ font-family: ${theme.fontFamily.base};
4833
+ cursor: pointer;
4834
+ transition: all ${theme.transition.fast};
4835
+
4836
+ ${(props) => props.$primary ? `
4837
+ background-color: ${theme.colors.primary};
4838
+ color: ${theme.colors.bgWhite};
4839
+ border: none;
4840
+
4841
+ &:hover:not(:disabled) {
4842
+ background-color: ${theme.colors.primaryHover};
4843
+ }
4844
+
4845
+ &:disabled {
4846
+ opacity: 0.5;
4847
+ cursor: not-allowed;
4848
+ }
4849
+ ` : `
4850
+ background-color: ${theme.colors.bgWhite};
4851
+ color: ${theme.colors.text};
4852
+ border: 1px solid ${theme.colors.border};
4853
+
4854
+ &:hover:not(:disabled) {
4855
+ background-color: ${theme.colors.bgLight};
4856
+ }
4857
+
4858
+ &:disabled {
4859
+ opacity: 0.5;
4860
+ cursor: not-allowed;
4861
+ }
4862
+ `}
4863
+ `;
4864
+ var ProfileSpinner = styled.div`
4865
+ width: 1rem;
4866
+ height: 1rem;
4867
+ border: 2px solid transparent;
4868
+ border-top-color: currentColor;
4869
+ border-radius: ${theme.radius.full};
4870
+ animation: spin 0.6s linear infinite;
4871
+
4872
+ @keyframes spin {
4873
+ to {
4874
+ transform: rotate(360deg);
4875
+ }
4876
+ }
4877
+ `;
4878
+ var READ_ONLY_FIELDS = ["id", "email", "avatar_url", "created_at", "updated_at"];
4879
+ var HIDDEN_FIELDS = ["id"];
4880
+ function formatFieldLabel(key) {
4881
+ return key.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
4882
+ }
4883
+ function UserProfileModal({ onClose, onError }) {
4884
+ const { user, updateUser, isLoaded } = useInsforge();
4885
+ const [isEditing, setIsEditing] = useState(false);
4886
+ const [isSaving, setIsSaving] = useState(false);
4887
+ const [imageError, setImageError] = useState(false);
4888
+ const [formData, setFormData] = useState({});
4889
+ useEffect(() => {
4890
+ if (user) {
4891
+ const initialData = {
4892
+ name: user.name || ""
4893
+ };
4894
+ if (user.profile) {
4895
+ Object.entries(user.profile).forEach(([key, value]) => {
4896
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
4897
+ initialData[key] = value;
4898
+ }
4899
+ });
4900
+ }
4901
+ setFormData(initialData);
4902
+ }
4903
+ }, [user]);
4904
+ useEffect(() => {
4905
+ setImageError(false);
4906
+ const avatarUrl = user?.avatarUrl;
4907
+ if (!avatarUrl) {
4908
+ return;
4909
+ }
4910
+ const checkImageUrl = async () => {
4911
+ try {
4912
+ const response = await fetch(avatarUrl, {
4913
+ method: "HEAD",
4914
+ cache: "no-cache"
4915
+ });
4916
+ if (!response.ok) {
4917
+ setImageError(true);
4918
+ }
4919
+ } catch {
4920
+ setImageError(true);
4921
+ }
4922
+ };
4923
+ void checkImageUrl();
4924
+ }, [user?.avatarUrl]);
4925
+ const handleFieldChange = useCallback((key, value) => {
4926
+ setFormData((prev2) => ({
4927
+ ...prev2,
4928
+ [key]: value
4929
+ }));
4930
+ }, []);
4931
+ const handleSave = useCallback(async () => {
4932
+ if (!user) return;
4933
+ setIsSaving(true);
4934
+ try {
4935
+ const { name, ...dynamicFields } = formData;
4936
+ const updateData = {
4937
+ name
4938
+ };
4939
+ if (Object.keys(dynamicFields).length > 0) {
4940
+ updateData.profile = dynamicFields;
4941
+ }
4942
+ const result = await updateUser(updateData);
4943
+ if (result?.error) {
4944
+ onError?.(result.error);
4945
+ } else {
4946
+ setIsEditing(false);
4947
+ }
4948
+ } catch (error) {
4949
+ onError?.(error instanceof Error ? error.message : "Failed to update profile");
4950
+ } finally {
4951
+ setIsSaving(false);
4952
+ }
4953
+ }, [user, formData, updateUser, onError]);
4954
+ const handleCancel = useCallback(() => {
4955
+ if (user) {
4956
+ const resetData = {
4957
+ name: user.name || ""
4958
+ };
4959
+ if (user.profile) {
4960
+ Object.entries(user.profile).forEach(([key, value]) => {
4961
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
4962
+ resetData[key] = value;
4963
+ }
4964
+ });
4965
+ }
4966
+ setFormData(resetData);
4967
+ }
4968
+ setIsEditing(false);
4969
+ }, [user]);
4970
+ const handleOverlayClick = useCallback(
4971
+ (e) => {
4972
+ if (e.target === e.currentTarget) {
4973
+ onClose();
4974
+ }
4975
+ },
4976
+ [onClose]
4977
+ );
4978
+ useEffect(() => {
4979
+ const handleEscape = (e) => {
4980
+ if (e.key === "Escape") {
4981
+ if (isEditing) {
4982
+ handleCancel();
4983
+ } else {
4984
+ onClose();
4985
+ }
4986
+ }
4987
+ };
4988
+ document.addEventListener("keydown", handleEscape);
4989
+ return () => document.removeEventListener("keydown", handleEscape);
4990
+ }, [isEditing, handleCancel, onClose]);
4991
+ if (!isLoaded || !user) {
4992
+ return null;
4993
+ }
4994
+ const initials = user.name ? user.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
4995
+ const fields = [];
4996
+ fields.push({ key: "email", value: user.email, readOnly: true });
4997
+ fields.push({
4998
+ key: "name",
4999
+ value: isEditing ? formData.name || "" : user.name || "",
5000
+ readOnly: false
5001
+ });
5002
+ if (user.profile) {
5003
+ Object.entries(user.profile).forEach(([key, value]) => {
5004
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
5005
+ fields.push({
5006
+ key,
5007
+ value: isEditing ? formData[key] ?? value : value,
5008
+ readOnly: READ_ONLY_FIELDS.includes(key)
5009
+ });
5010
+ }
5011
+ });
5012
+ }
5013
+ return /* @__PURE__ */ jsx(ProfileModalOverlay, { onClick: handleOverlayClick, children: /* @__PURE__ */ jsxs(ProfileModalContainer, { onClick: (e) => e.stopPropagation(), children: [
5014
+ /* @__PURE__ */ jsxs(ProfileModalHeader, { children: [
5015
+ /* @__PURE__ */ jsx(ProfileModalTitle, { children: "Profile" }),
5016
+ /* @__PURE__ */ jsx(ProfileModalCloseButton, { onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(X, {}) })
5017
+ ] }),
5018
+ /* @__PURE__ */ jsxs(ProfileModalBody, { children: [
5019
+ /* @__PURE__ */ jsx(ProfileAvatarSection, { children: /* @__PURE__ */ jsx(ProfileAvatar, { children: user.avatarUrl && !imageError ? /* @__PURE__ */ jsx(
5020
+ ProfileAvatarImage,
5021
+ {
5022
+ src: user.avatarUrl,
5023
+ alt: user.name || user.email,
5024
+ onError: () => setImageError(true)
5025
+ }
5026
+ ) : initials }) }),
5027
+ /* @__PURE__ */ jsx(ProfileFieldsContainer, { children: fields.map(({ key, value, readOnly }) => /* @__PURE__ */ jsxs(ProfileField, { children: [
5028
+ /* @__PURE__ */ jsx(ProfileFieldLabel, { children: formatFieldLabel(key) }),
5029
+ isEditing && !readOnly ? /* @__PURE__ */ jsx(
5030
+ ProfileFieldInput,
5031
+ {
5032
+ type: "text",
5033
+ value: formData[key] ?? value,
5034
+ onChange: (e) => handleFieldChange(key, e.target.value),
5035
+ disabled: isSaving
5036
+ }
5037
+ ) : /* @__PURE__ */ jsx(ProfileFieldValue, { children: value || "-" })
5038
+ ] }, key)) })
5039
+ ] }),
5040
+ /* @__PURE__ */ jsx(ProfileModalFooter, { children: isEditing ? /* @__PURE__ */ jsxs(Fragment, { children: [
5041
+ /* @__PURE__ */ jsx(ProfileButton, { onClick: handleCancel, disabled: isSaving, children: "Cancel" }),
5042
+ /* @__PURE__ */ jsxs(ProfileButton, { $primary: true, onClick: handleSave, disabled: isSaving, children: [
5043
+ isSaving && /* @__PURE__ */ jsx(ProfileSpinner, {}),
5044
+ isSaving ? "Saving..." : "Save"
5045
+ ] })
5046
+ ] }) : /* @__PURE__ */ jsx(ProfileButton, { $primary: true, onClick: () => setIsEditing(true), children: "Edit Profile" }) })
5047
+ ] }) });
5048
+ }
5049
+ function UserButton({
5050
+ afterSignOutUrl = "/",
5051
+ mode = "simple",
5052
+ showProfile = true,
5053
+ onProfileError
5054
+ }) {
4677
5055
  const { user } = useInsforge();
4678
5056
  const [isOpen, setIsOpen] = useState(false);
5057
+ const [showProfileModal, setShowProfileModal] = useState(false);
4679
5058
  const [imageError, setImageError] = useState(false);
4680
5059
  const [openUpward, setOpenUpward] = useState(false);
4681
5060
  const [horizontalOffset, setHorizontalOffset] = useState(0);
@@ -4773,10 +5152,32 @@ function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
4773
5152
  ]
4774
5153
  }
4775
5154
  ),
4776
- 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: [
4777
- /* @__PURE__ */ jsx(UserButtonMenuItemIcon, { children: /* @__PURE__ */ jsx(LogOut, {}) }),
4778
- "Sign out"
4779
- ] }) }) })
5155
+ isOpen && /* @__PURE__ */ jsxs(UserButtonMenu, { ref: menuRef, $openUpward: openUpward, $horizontalOffset: horizontalOffset, children: [
5156
+ showProfile && /* @__PURE__ */ jsxs(
5157
+ UserButtonMenuItem,
5158
+ {
5159
+ onClick: () => {
5160
+ setShowProfileModal(true);
5161
+ setIsOpen(false);
5162
+ },
5163
+ children: [
5164
+ /* @__PURE__ */ jsx(UserButtonMenuItemIcon, { children: /* @__PURE__ */ jsx(User, {}) }),
5165
+ "Profile"
5166
+ ]
5167
+ }
5168
+ ),
5169
+ /* @__PURE__ */ jsx(SignOutButton, { afterSignOutUrl, children: /* @__PURE__ */ jsxs(UserButtonMenuItem, { $signout: true, onClick: () => setIsOpen(false), children: [
5170
+ /* @__PURE__ */ jsx(UserButtonMenuItemIcon, { children: /* @__PURE__ */ jsx(LogOut, {}) }),
5171
+ "Sign out"
5172
+ ] }) })
5173
+ ] }),
5174
+ showProfileModal && /* @__PURE__ */ jsx(
5175
+ UserProfileModal,
5176
+ {
5177
+ onClose: () => setShowProfileModal(false),
5178
+ onError: onProfileError
5179
+ }
5180
+ )
4780
5181
  ] });
4781
5182
  }
4782
5183
  function Protect({
@@ -4895,6 +5296,6 @@ react-is/cjs/react-is.development.js:
4895
5296
  *)
4896
5297
  */
4897
5298
 
4898
- export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthVerificationCodeInput, ForgotPassword, ForgotPasswordForm, Protect, ResetPassword, ResetPasswordForm, SignIn, SignInButton, SignInForm, SignOutButton, SignUp, SignUpButton, SignUpForm, SignedIn, SignedOut, UserButton, VerifyEmail, VerifyEmailStatus };
5299
+ export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthVerificationCodeInput, ForgotPassword, ForgotPasswordForm, Protect, ResetPassword, ResetPasswordForm, SignIn, SignInButton, SignInForm, SignOutButton, SignUp, SignUpButton, SignUpForm, SignedIn, SignedOut, UserButton, UserProfileModal, VerifyEmail, VerifyEmailStatus };
4899
5300
  //# sourceMappingURL=components.js.map
4900
5301
  //# sourceMappingURL=components.js.map