@insforge/react 1.0.4 → 1.0.5-dev.1

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.js CHANGED
@@ -15,9 +15,8 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
15
15
  import * as React2 from 'react';
16
16
  import { createContext, forwardRef, useContext, useState, useMemo, useEffect, useRef, useCallback, isValidElement, cloneElement } from 'react';
17
17
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
18
- import { createClient } from '@insforge/sdk';
19
18
  import { InsforgeContext } from '@insforge/shared/react';
20
- import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck, LogOut } from 'lucide-react';
19
+ import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck, X, User, LogOut } from 'lucide-react';
21
20
  import { z } from 'zod';
22
21
 
23
22
  var __create = Object.create;
@@ -225,7 +224,7 @@ var require_react_is_development = __commonJS({
225
224
  var ContextProvider = REACT_PROVIDER_TYPE;
226
225
  var Element = REACT_ELEMENT_TYPE;
227
226
  var ForwardRef = REACT_FORWARD_REF_TYPE;
228
- var Fragment9 = REACT_FRAGMENT_TYPE;
227
+ var Fragment10 = REACT_FRAGMENT_TYPE;
229
228
  var Lazy = REACT_LAZY_TYPE;
230
229
  var Memo = REACT_MEMO_TYPE;
231
230
  var Portal = REACT_PORTAL_TYPE;
@@ -284,7 +283,7 @@ var require_react_is_development = __commonJS({
284
283
  exports$1.ContextProvider = ContextProvider;
285
284
  exports$1.Element = Element;
286
285
  exports$1.ForwardRef = ForwardRef;
287
- exports$1.Fragment = Fragment9;
286
+ exports$1.Fragment = Fragment10;
288
287
  exports$1.Lazy = Lazy;
289
288
  exports$1.Memo = Memo;
290
289
  exports$1.Portal = Portal;
@@ -467,6 +466,8 @@ function useSearchParams() {
467
466
  const adapter = useNavigationAdapter();
468
467
  return adapter.useSearchParams();
469
468
  }
469
+
470
+ // src/core/InsforgeManager.ts
470
471
  var InsforgeManager = class _InsforgeManager {
471
472
  // Static private instance
472
473
  static instance = null;
@@ -482,7 +483,7 @@ var InsforgeManager = class _InsforgeManager {
482
483
  // Private constructor (prevents external instantiation)
483
484
  constructor(config) {
484
485
  this.config = config;
485
- this.sdk = createClient({ baseUrl: config.baseUrl });
486
+ this.sdk = config.client;
486
487
  this.user = void 0;
487
488
  this.isLoaded = false;
488
489
  }
@@ -490,6 +491,9 @@ var InsforgeManager = class _InsforgeManager {
490
491
  static getInstance(config) {
491
492
  if (typeof window !== "undefined" && _InsforgeManager.instance) {
492
493
  _InsforgeManager.instance.updateConfig(config);
494
+ if (config.client && _InsforgeManager.instance.sdk !== config.client) {
495
+ _InsforgeManager.instance.sdk = config.client;
496
+ }
493
497
  return _InsforgeManager.instance;
494
498
  }
495
499
  _InsforgeManager.instance = new _InsforgeManager(config);
@@ -567,12 +571,10 @@ var InsforgeManager = class _InsforgeManager {
567
571
  }
568
572
  const userResult = await this.sdk.auth.getCurrentUser();
569
573
  if (userResult.data) {
570
- const profile = userResult.data.user.profile;
571
574
  const userData = {
572
575
  id: userResult.data.user.id,
573
576
  email: userResult.data.user.email,
574
- name: profile?.name || "",
575
- avatarUrl: profile?.avatar_url || ""
577
+ profile: userResult.data.user.profile
576
578
  };
577
579
  this.user = userData;
578
580
  if (this.config.onAuthChange) {
@@ -608,12 +610,10 @@ var InsforgeManager = class _InsforgeManager {
608
610
  async handleAuthSuccess(authToken, fallbackUser) {
609
611
  const userResult = await this.sdk.auth.getCurrentUser();
610
612
  if (userResult.data) {
611
- const profile = userResult.data.user.profile;
612
613
  const userData = {
613
614
  id: userResult.data.user.id,
614
615
  email: userResult.data.user.email,
615
- name: profile?.name || "",
616
- avatarUrl: profile?.avatar_url || ""
616
+ profile: userResult.data.user.profile
617
617
  };
618
618
  this.user = userData;
619
619
  this.notifyListeners();
@@ -633,8 +633,7 @@ var InsforgeManager = class _InsforgeManager {
633
633
  const userData = {
634
634
  id: fallbackUser.id || "",
635
635
  email: fallbackUser.email || "",
636
- name: fallbackUser.name || "",
637
- avatarUrl: ""
636
+ profile: fallbackUser.profile || null
638
637
  };
639
638
  this.user = userData;
640
639
  this.notifyListeners();
@@ -655,7 +654,7 @@ var InsforgeManager = class _InsforgeManager {
655
654
  sdkResult.data.user ? {
656
655
  id: sdkResult.data.user.id,
657
656
  email: sdkResult.data.user.email,
658
- name: sdkResult.data.user.profile?.name || ""
657
+ profile: sdkResult.data.user.profile || void 0
659
658
  } : void 0
660
659
  );
661
660
  return sdkResult.data;
@@ -676,7 +675,7 @@ var InsforgeManager = class _InsforgeManager {
676
675
  sdkResult.data.user ? {
677
676
  id: sdkResult.data.user.id,
678
677
  email: sdkResult.data.user.email,
679
- name: sdkResult.data.user.profile?.name || ""
678
+ profile: sdkResult.data.user.profile || void 0
680
679
  } : void 0
681
680
  );
682
681
  }
@@ -714,27 +713,21 @@ var InsforgeManager = class _InsforgeManager {
714
713
  if (!this.user) {
715
714
  return { error: "No user signed in" };
716
715
  }
717
- const profileUpdate = {
718
- name: data.name,
719
- avatar_url: data.avatarUrl
720
- };
721
- const result = await this.sdk.auth.setProfile(profileUpdate);
716
+ if (!data) {
717
+ return { error: "No profile data provided" };
718
+ }
719
+ const result = await this.sdk.auth.setProfile(data);
722
720
  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();
721
+ const updatedUser = {
722
+ id: this.user.id,
723
+ email: this.user.email,
724
+ profile: data
725
+ };
726
+ this.user = updatedUser;
727
+ if (this.config.onAuthChange) {
728
+ this.config.onAuthChange(updatedUser);
737
729
  }
730
+ this.notifyListeners();
738
731
  return null;
739
732
  }
740
733
  const error = result.error;
@@ -830,12 +823,10 @@ var InsforgeManager = class _InsforgeManager {
830
823
  return;
831
824
  }
832
825
  if (initialState.userId) {
833
- const normalizeValue = (val) => val && val !== "null" ? val : "";
834
826
  this.user = {
835
827
  id: initialState.userId,
836
- email: normalizeValue(initialState.user?.email),
837
- name: normalizeValue(initialState.user?.name),
838
- avatarUrl: normalizeValue(initialState.user?.avatarUrl)
828
+ email: initialState.user?.email || "",
829
+ profile: initialState.user?.profile || null
839
830
  };
840
831
  } else {
841
832
  this.user = null;
@@ -2179,7 +2170,7 @@ function StyleProvider({ children, nonce }) {
2179
2170
  }
2180
2171
  function InsforgeProviderCore({
2181
2172
  children,
2182
- baseUrl,
2173
+ client,
2183
2174
  afterSignInUrl = "/",
2184
2175
  onAuthChange,
2185
2176
  onSignIn,
@@ -2189,14 +2180,14 @@ function InsforgeProviderCore({
2189
2180
  }) {
2190
2181
  const manager = useMemo(
2191
2182
  () => InsforgeManager.getInstance({
2192
- baseUrl,
2183
+ client,
2193
2184
  afterSignInUrl,
2194
2185
  onAuthChange,
2195
2186
  onSignIn,
2196
2187
  onSignOut,
2197
2188
  onRefresh
2198
2189
  }),
2199
- [baseUrl, afterSignInUrl, onAuthChange, onSignIn, onSignOut, onRefresh]
2190
+ [client, afterSignInUrl, onAuthChange, onSignIn, onSignOut, onRefresh]
2200
2191
  );
2201
2192
  if (initialState) {
2202
2193
  const currentState = manager.getState();
@@ -2248,7 +2239,7 @@ function InsforgeProviderCore({
2248
2239
  loginWithOAuth: (provider, redirectTo) => manager.loginWithOAuth(provider, redirectTo),
2249
2240
  getPublicAuthConfig: () => manager.getPublicAuthConfig(),
2250
2241
  // Config
2251
- baseUrl: manager.getConfig().baseUrl,
2242
+ baseUrl: manager.getConfig().client.getHttpClient().baseUrl,
2252
2243
  afterSignInUrl: manager.getConfig().afterSignInUrl || "/"
2253
2244
  }),
2254
2245
  [state, manager]
@@ -5257,9 +5248,384 @@ var UserButtonMenuItemIcon = styled.div`
5257
5248
  height: 100%;
5258
5249
  }
5259
5250
  `;
5260
- function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
5251
+ var ProfileModalOverlay = styled.div`
5252
+ position: fixed;
5253
+ inset: 0;
5254
+ background-color: rgba(0, 0, 0, 0.5);
5255
+ display: flex;
5256
+ align-items: center;
5257
+ justify-content: center;
5258
+ z-index: 100;
5259
+ padding: ${theme.spacing[4]};
5260
+ `;
5261
+ var ProfileModalContainer = styled.div`
5262
+ background-color: ${theme.colors.bgWhite};
5263
+ border-radius: ${theme.radius.xl};
5264
+ box-shadow: ${theme.shadow.lg};
5265
+ width: 100%;
5266
+ max-width: 400px;
5267
+ max-height: 90vh;
5268
+ overflow: hidden;
5269
+ display: flex;
5270
+ flex-direction: column;
5271
+ font-family: ${theme.fontFamily.base};
5272
+ `;
5273
+ var ProfileModalHeader = styled.div`
5274
+ display: flex;
5275
+ align-items: center;
5276
+ justify-content: space-between;
5277
+ padding: ${theme.spacing[4]} ${theme.spacing[6]};
5278
+ border-bottom: 1px solid ${theme.colors.border};
5279
+ `;
5280
+ var ProfileModalTitle = styled.h2`
5281
+ font-size: ${theme.fontSize.lg};
5282
+ font-weight: ${theme.fontWeight.semibold};
5283
+ color: ${theme.colors.text};
5284
+ margin: 0;
5285
+ `;
5286
+ var ProfileModalCloseButton = styled.button`
5287
+ display: flex;
5288
+ align-items: center;
5289
+ justify-content: center;
5290
+ width: 2rem;
5291
+ height: 2rem;
5292
+ border-radius: ${theme.radius.md};
5293
+ background: none;
5294
+ border: none;
5295
+ cursor: pointer;
5296
+ color: ${theme.colors.textSecondary};
5297
+ transition: all ${theme.transition.fast};
5298
+
5299
+ &:hover {
5300
+ background-color: ${theme.colors.bgLight};
5301
+ color: ${theme.colors.text};
5302
+ }
5303
+
5304
+ svg {
5305
+ width: 1.25rem;
5306
+ height: 1.25rem;
5307
+ }
5308
+ `;
5309
+ var ProfileModalBody = styled.div`
5310
+ padding: ${theme.spacing[6]};
5311
+ overflow-y: auto;
5312
+ flex: 1;
5313
+ `;
5314
+ var ProfileAvatarSection = styled.div`
5315
+ display: flex;
5316
+ flex-direction: column;
5317
+ align-items: center;
5318
+ margin-bottom: ${theme.spacing[6]};
5319
+ `;
5320
+ var ProfileAvatar = styled.div`
5321
+ width: 5rem;
5322
+ height: 5rem;
5323
+ border-radius: ${theme.radius.full};
5324
+ background-color: ${theme.colors.primary};
5325
+ color: ${theme.colors.bgWhite};
5326
+ display: flex;
5327
+ align-items: center;
5328
+ justify-content: center;
5329
+ font-weight: ${theme.fontWeight.semibold};
5330
+ font-size: ${theme.fontSize["2xl"]};
5331
+ overflow: hidden;
5332
+ `;
5333
+ var ProfileAvatarImage = styled.img`
5334
+ width: 100%;
5335
+ height: 100%;
5336
+ object-fit: cover;
5337
+ `;
5338
+ var ProfileFieldsContainer = styled.div`
5339
+ display: flex;
5340
+ flex-direction: column;
5341
+ gap: ${theme.spacing[4]};
5342
+ `;
5343
+ var ProfileField = styled.div`
5344
+ display: flex;
5345
+ flex-direction: column;
5346
+ gap: ${theme.spacing[1]};
5347
+ `;
5348
+ var ProfileFieldLabel = styled.label`
5349
+ font-size: ${theme.fontSize.sm};
5350
+ font-weight: ${theme.fontWeight.medium};
5351
+ color: ${theme.colors.textSecondary};
5352
+ text-transform: capitalize;
5353
+ `;
5354
+ var ProfileFieldValue = styled.div`
5355
+ font-size: ${theme.fontSize.base};
5356
+ color: ${theme.colors.text};
5357
+ padding: ${theme.spacing[2]} 0;
5358
+ word-break: break-word;
5359
+ `;
5360
+ var ProfileFieldInput = styled.input`
5361
+ width: 100%;
5362
+ height: ${theme.sizes.input.height};
5363
+ padding: 0 ${theme.spacing[3]};
5364
+ border: 1px solid ${theme.colors.border};
5365
+ border-radius: ${theme.radius.md};
5366
+ font-size: ${theme.fontSize.base};
5367
+ font-family: ${theme.fontFamily.base};
5368
+ color: ${theme.colors.text};
5369
+ background-color: ${theme.colors.bgWhite};
5370
+ transition: border-color ${theme.transition.fast};
5371
+
5372
+ &:focus {
5373
+ outline: none;
5374
+ border-color: ${theme.colors.borderFocus};
5375
+ }
5376
+
5377
+ &:disabled {
5378
+ background-color: ${theme.colors.bgLight};
5379
+ color: ${theme.colors.textSecondary};
5380
+ cursor: not-allowed;
5381
+ }
5382
+ `;
5383
+ var ProfileModalFooter = styled.div`
5384
+ display: flex;
5385
+ align-items: center;
5386
+ justify-content: flex-end;
5387
+ gap: ${theme.spacing[3]};
5388
+ padding: ${theme.spacing[4]} ${theme.spacing[6]};
5389
+ border-top: 1px solid ${theme.colors.border};
5390
+ `;
5391
+ var ProfileButton = styled.button`
5392
+ display: flex;
5393
+ align-items: center;
5394
+ justify-content: center;
5395
+ gap: ${theme.spacing[2]};
5396
+ height: ${theme.sizes.button.height};
5397
+ padding: 0 ${theme.spacing[4]};
5398
+ border-radius: ${theme.radius.md};
5399
+ font-size: ${theme.fontSize.sm};
5400
+ font-weight: ${theme.fontWeight.medium};
5401
+ font-family: ${theme.fontFamily.base};
5402
+ cursor: pointer;
5403
+ transition: all ${theme.transition.fast};
5404
+
5405
+ ${(props) => props.$primary ? `
5406
+ background-color: ${theme.colors.primary};
5407
+ color: ${theme.colors.bgWhite};
5408
+ border: none;
5409
+
5410
+ &:hover:not(:disabled) {
5411
+ background-color: ${theme.colors.primaryHover};
5412
+ }
5413
+
5414
+ &:disabled {
5415
+ opacity: 0.5;
5416
+ cursor: not-allowed;
5417
+ }
5418
+ ` : `
5419
+ background-color: ${theme.colors.bgWhite};
5420
+ color: ${theme.colors.text};
5421
+ border: 1px solid ${theme.colors.border};
5422
+
5423
+ &:hover:not(:disabled) {
5424
+ background-color: ${theme.colors.bgLight};
5425
+ }
5426
+
5427
+ &:disabled {
5428
+ opacity: 0.5;
5429
+ cursor: not-allowed;
5430
+ }
5431
+ `}
5432
+ `;
5433
+ var ProfileSpinner = styled.div`
5434
+ width: 1rem;
5435
+ height: 1rem;
5436
+ border: 2px solid transparent;
5437
+ border-top-color: currentColor;
5438
+ border-radius: ${theme.radius.full};
5439
+ animation: spin 0.6s linear infinite;
5440
+
5441
+ @keyframes spin {
5442
+ to {
5443
+ transform: rotate(360deg);
5444
+ }
5445
+ }
5446
+ `;
5447
+ var READ_ONLY_FIELDS = ["id", "email", "avatar_url", "created_at", "updated_at"];
5448
+ var HIDDEN_FIELDS = ["id"];
5449
+ function formatFieldLabel(key) {
5450
+ return key.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
5451
+ }
5452
+ function UserProfileModal({ onClose, onError }) {
5453
+ const { user, updateUser, isLoaded } = useInsforge();
5454
+ const [isEditing, setIsEditing] = useState(false);
5455
+ const [isSaving, setIsSaving] = useState(false);
5456
+ const [imageError, setImageError] = useState(false);
5457
+ const [formData, setFormData] = useState({});
5458
+ useEffect(() => {
5459
+ if (user) {
5460
+ const initialData = {
5461
+ name: user.profile?.name || ""
5462
+ };
5463
+ if (user.profile) {
5464
+ Object.entries(user.profile).forEach(([key, value]) => {
5465
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
5466
+ initialData[key] = value;
5467
+ }
5468
+ });
5469
+ }
5470
+ setFormData(initialData);
5471
+ }
5472
+ }, [user]);
5473
+ useEffect(() => {
5474
+ setImageError(false);
5475
+ const avatarUrl = user?.profile?.avatar_url;
5476
+ if (!avatarUrl) {
5477
+ return;
5478
+ }
5479
+ const checkImageUrl = async () => {
5480
+ try {
5481
+ const response = await fetch(avatarUrl, {
5482
+ method: "HEAD",
5483
+ cache: "no-cache"
5484
+ });
5485
+ if (!response.ok) {
5486
+ setImageError(true);
5487
+ }
5488
+ } catch {
5489
+ setImageError(true);
5490
+ }
5491
+ };
5492
+ void checkImageUrl();
5493
+ }, [user?.profile?.avatar_url]);
5494
+ const handleFieldChange = useCallback((key, value) => {
5495
+ setFormData((prev2) => ({
5496
+ ...prev2,
5497
+ [key]: value
5498
+ }));
5499
+ }, []);
5500
+ const handleSave = useCallback(async () => {
5501
+ if (!user) return;
5502
+ setIsSaving(true);
5503
+ try {
5504
+ const { name, ...dynamicFields } = formData;
5505
+ const updateData = {
5506
+ profile: {
5507
+ name
5508
+ }
5509
+ };
5510
+ if (Object.keys(dynamicFields).length > 0) {
5511
+ updateData.profile = dynamicFields;
5512
+ }
5513
+ const result = await updateUser(updateData);
5514
+ if (result?.error) {
5515
+ onError?.(result.error);
5516
+ } else {
5517
+ setIsEditing(false);
5518
+ }
5519
+ } catch (error) {
5520
+ onError?.(error instanceof Error ? error.message : "Failed to update profile");
5521
+ } finally {
5522
+ setIsSaving(false);
5523
+ }
5524
+ }, [user, formData, updateUser, onError]);
5525
+ const handleCancel = useCallback(() => {
5526
+ if (user) {
5527
+ const resetData = {
5528
+ name: user.profile?.name || ""
5529
+ };
5530
+ if (user.profile) {
5531
+ Object.entries(user.profile).forEach(([key, value]) => {
5532
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
5533
+ resetData[key] = value;
5534
+ }
5535
+ });
5536
+ }
5537
+ setFormData(resetData);
5538
+ }
5539
+ setIsEditing(false);
5540
+ }, [user]);
5541
+ const handleOverlayClick = useCallback(
5542
+ (e) => {
5543
+ if (e.target === e.currentTarget) {
5544
+ onClose();
5545
+ }
5546
+ },
5547
+ [onClose]
5548
+ );
5549
+ useEffect(() => {
5550
+ const handleEscape = (e) => {
5551
+ if (e.key === "Escape") {
5552
+ if (isEditing) {
5553
+ handleCancel();
5554
+ } else {
5555
+ onClose();
5556
+ }
5557
+ }
5558
+ };
5559
+ document.addEventListener("keydown", handleEscape);
5560
+ return () => document.removeEventListener("keydown", handleEscape);
5561
+ }, [isEditing, handleCancel, onClose]);
5562
+ if (!isLoaded || !user) {
5563
+ return null;
5564
+ }
5565
+ const initials = user.profile?.name ? user.profile.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
5566
+ const fields = [];
5567
+ fields.push({ key: "email", value: user.email, readOnly: true });
5568
+ fields.push({
5569
+ key: "name",
5570
+ value: isEditing ? formData.name || "" : user.profile?.name || "",
5571
+ readOnly: false
5572
+ });
5573
+ if (user.profile) {
5574
+ Object.entries(user.profile).forEach(([key, value]) => {
5575
+ if (!HIDDEN_FIELDS.includes(key) && typeof value === "string") {
5576
+ fields.push({
5577
+ key,
5578
+ value: isEditing ? formData[key] ?? value : value,
5579
+ readOnly: READ_ONLY_FIELDS.includes(key)
5580
+ });
5581
+ }
5582
+ });
5583
+ }
5584
+ return /* @__PURE__ */ jsx(ProfileModalOverlay, { onClick: handleOverlayClick, children: /* @__PURE__ */ jsxs(ProfileModalContainer, { onClick: (e) => e.stopPropagation(), children: [
5585
+ /* @__PURE__ */ jsxs(ProfileModalHeader, { children: [
5586
+ /* @__PURE__ */ jsx(ProfileModalTitle, { children: "Profile" }),
5587
+ /* @__PURE__ */ jsx(ProfileModalCloseButton, { onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(X, {}) })
5588
+ ] }),
5589
+ /* @__PURE__ */ jsxs(ProfileModalBody, { children: [
5590
+ /* @__PURE__ */ jsx(ProfileAvatarSection, { children: /* @__PURE__ */ jsx(ProfileAvatar, { children: user.profile?.avatar_url && !imageError ? /* @__PURE__ */ jsx(
5591
+ ProfileAvatarImage,
5592
+ {
5593
+ src: user.profile.avatar_url,
5594
+ alt: user.profile?.name || user.email,
5595
+ onError: () => setImageError(true)
5596
+ }
5597
+ ) : initials }) }),
5598
+ /* @__PURE__ */ jsx(ProfileFieldsContainer, { children: fields.map(({ key, value, readOnly }) => /* @__PURE__ */ jsxs(ProfileField, { children: [
5599
+ /* @__PURE__ */ jsx(ProfileFieldLabel, { children: formatFieldLabel(key) }),
5600
+ isEditing && !readOnly ? /* @__PURE__ */ jsx(
5601
+ ProfileFieldInput,
5602
+ {
5603
+ type: "text",
5604
+ value: formData[key] ?? value,
5605
+ onChange: (e) => handleFieldChange(key, e.target.value),
5606
+ disabled: isSaving
5607
+ }
5608
+ ) : /* @__PURE__ */ jsx(ProfileFieldValue, { children: value || "-" })
5609
+ ] }, key)) })
5610
+ ] }),
5611
+ /* @__PURE__ */ jsx(ProfileModalFooter, { children: isEditing ? /* @__PURE__ */ jsxs(Fragment, { children: [
5612
+ /* @__PURE__ */ jsx(ProfileButton, { onClick: handleCancel, disabled: isSaving, children: "Cancel" }),
5613
+ /* @__PURE__ */ jsxs(ProfileButton, { $primary: true, onClick: () => void handleSave(), disabled: isSaving, children: [
5614
+ isSaving && /* @__PURE__ */ jsx(ProfileSpinner, {}),
5615
+ isSaving ? "Saving..." : "Save"
5616
+ ] })
5617
+ ] }) : /* @__PURE__ */ jsx(ProfileButton, { $primary: true, onClick: () => setIsEditing(true), children: "Edit Profile" }) })
5618
+ ] }) });
5619
+ }
5620
+ function UserButton({
5621
+ afterSignOutUrl = "/",
5622
+ mode = "simple",
5623
+ showProfile = true,
5624
+ onProfileError
5625
+ }) {
5261
5626
  const { user } = useInsforge();
5262
5627
  const [isOpen, setIsOpen] = useState(false);
5628
+ const [showProfileModal, setShowProfileModal] = useState(false);
5263
5629
  const [imageError, setImageError] = useState(false);
5264
5630
  const [openUpward, setOpenUpward] = useState(false);
5265
5631
  const [horizontalOffset, setHorizontalOffset] = useState(0);
@@ -5267,7 +5633,7 @@ function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
5267
5633
  const menuRef = useRef(null);
5268
5634
  useEffect(() => {
5269
5635
  setImageError(false);
5270
- const avatarUrl = user?.avatarUrl;
5636
+ const avatarUrl = user?.profile?.avatar_url;
5271
5637
  if (!avatarUrl) {
5272
5638
  return;
5273
5639
  }
@@ -5288,7 +5654,7 @@ function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
5288
5654
  }
5289
5655
  };
5290
5656
  void checkImageUrl();
5291
- }, [user?.avatarUrl]);
5657
+ }, [user?.profile?.avatar_url]);
5292
5658
  useEffect(() => {
5293
5659
  if (isOpen && dropdownRef.current) {
5294
5660
  const buttonRect = dropdownRef.current.getBoundingClientRect();
@@ -5332,7 +5698,7 @@ function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
5332
5698
  if (!user) {
5333
5699
  return null;
5334
5700
  }
5335
- const initials = user.name ? user.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
5701
+ const initials = user.profile?.name ? user.profile.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
5336
5702
  return /* @__PURE__ */ jsxs(UserButtonContainer, { ref: dropdownRef, children: [
5337
5703
  /* @__PURE__ */ jsxs(
5338
5704
  UserButtonButton,
@@ -5342,25 +5708,41 @@ function UserButton({ afterSignOutUrl = "/", mode = "simple" }) {
5342
5708
  "aria-expanded": isOpen,
5343
5709
  "aria-haspopup": "true",
5344
5710
  children: [
5345
- /* @__PURE__ */ jsx(UserButtonAvatar, { children: user.avatarUrl && !imageError ? /* @__PURE__ */ jsx(
5711
+ /* @__PURE__ */ jsx(UserButtonAvatar, { children: user.profile?.avatar_url && !imageError ? /* @__PURE__ */ jsx(
5346
5712
  UserButtonAvatarImage,
5347
5713
  {
5348
- src: user.avatarUrl,
5714
+ src: user.profile.avatar_url,
5349
5715
  alt: user.email,
5350
5716
  onError: () => setImageError(true)
5351
5717
  }
5352
5718
  ) : /* @__PURE__ */ jsx(UserButtonAvatarInitials, { children: initials }) }),
5353
5719
  mode === "detailed" && /* @__PURE__ */ jsxs(UserButtonInfo, { children: [
5354
- user.name && /* @__PURE__ */ jsx(UserButtonName, { children: user.name }),
5720
+ user.profile?.name && /* @__PURE__ */ jsx(UserButtonName, { children: user.profile.name }),
5355
5721
  /* @__PURE__ */ jsx(UserButtonEmail, { children: user.email })
5356
5722
  ] })
5357
5723
  ]
5358
5724
  }
5359
5725
  ),
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
- ] }) }) })
5726
+ isOpen && /* @__PURE__ */ jsxs(UserButtonMenu, { ref: menuRef, $openUpward: openUpward, $horizontalOffset: horizontalOffset, children: [
5727
+ showProfile && /* @__PURE__ */ jsxs(
5728
+ UserButtonMenuItem,
5729
+ {
5730
+ onClick: () => {
5731
+ setShowProfileModal(true);
5732
+ setIsOpen(false);
5733
+ },
5734
+ children: [
5735
+ /* @__PURE__ */ jsx(UserButtonMenuItemIcon, { children: /* @__PURE__ */ jsx(User, {}) }),
5736
+ "Profile"
5737
+ ]
5738
+ }
5739
+ ),
5740
+ /* @__PURE__ */ jsx(SignOutButton, { afterSignOutUrl, children: /* @__PURE__ */ jsxs(UserButtonMenuItem, { $signout: true, onClick: () => setIsOpen(false), children: [
5741
+ /* @__PURE__ */ jsx(UserButtonMenuItemIcon, { children: /* @__PURE__ */ jsx(LogOut, {}) }),
5742
+ "Sign out"
5743
+ ] }) })
5744
+ ] }),
5745
+ showProfileModal && /* @__PURE__ */ jsx(UserProfileModal, { onClose: () => setShowProfileModal(false), onError: onProfileError })
5364
5746
  ] });
5365
5747
  }
5366
5748
  function Protect({
@@ -5491,6 +5873,6 @@ react-is/cjs/react-is.development.js:
5491
5873
  *)
5492
5874
  */
5493
5875
 
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 };
5876
+ 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
5877
  //# sourceMappingURL=index.js.map
5496
5878
  //# sourceMappingURL=index.js.map