@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/components.cjs +409 -7
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.cts +18 -2
- package/dist/components.d.ts +18 -2
- package/dist/components.js +410 -9
- package/dist/components.js.map +1 -1
- package/dist/index.cjs +436 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +437 -31
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/components.d.cts
CHANGED
|
@@ -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 };
|
package/dist/components.d.ts
CHANGED
|
@@ -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 };
|
package/dist/components.js
CHANGED
|
@@ -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
|
|
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 =
|
|
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
|
-
|
|
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__ */
|
|
4777
|
-
|
|
4778
|
-
|
|
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
|