@thetechfossil/auth2 1.2.15 → 1.2.17

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.
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import axios from 'axios';
3
3
  import { UpfilesClient, ImageManager } from '@thetechfossil/upfiles';
4
- import React3, { createContext, forwardRef, useContext, useState, useCallback, useEffect, useMemo, useRef } from 'react';
4
+ import React, { createContext, forwardRef, useContext, useState, useCallback, useEffect, useMemo, useRef } from 'react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
 
7
7
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -62,6 +62,11 @@ var HttpClient = class {
62
62
  return Promise.reject(refreshError);
63
63
  }
64
64
  }
65
+ if (error.response && error.response.data && error.response.data.message) {
66
+ const customError = new Error(error.response.data.message);
67
+ customError.response = error.response;
68
+ return Promise.reject(customError);
69
+ }
65
70
  return Promise.reject(error);
66
71
  }
67
72
  );
@@ -641,7 +646,7 @@ var useAuth = (config) => {
641
646
  uploadAndUpdateAvatar
642
647
  };
643
648
  };
644
- var ThemeContext = createContext({ theme: "light", mounted: false });
649
+ var ThemeContext = React.createContext({ theme: "light", mounted: false });
645
650
  function AuthThemeProvider({ children }) {
646
651
  const [theme, setTheme] = useState("light");
647
652
  const [mounted, setMounted] = useState(false);
@@ -708,11 +713,17 @@ var AuthProvider = ({ children, config }) => {
708
713
  const authenticated = authService.isAuthenticated();
709
714
  if (authenticated) {
710
715
  try {
711
- const currentUser = authService.getCurrentUser();
712
- setUser(currentUser);
716
+ const freshUser = await authService.getProfile();
717
+ setUser(freshUser);
713
718
  } catch (error) {
714
- console.error("Failed to get current user:", error);
715
- setUser(null);
719
+ console.error("Failed to fetch fresh user profile, falling back to token:", error);
720
+ try {
721
+ const currentUser = authService.getCurrentUser();
722
+ setUser(currentUser);
723
+ } catch (fallbackError) {
724
+ console.error("Failed to get current user from token:", fallbackError);
725
+ setUser(null);
726
+ }
716
727
  }
717
728
  } else {
718
729
  setUser(null);
@@ -1028,7 +1039,7 @@ try {
1028
1039
  } catch (error) {
1029
1040
  console.warn("react-phone-number-input not available, using fallback");
1030
1041
  }
1031
- var CustomPhoneInput = React3.forwardRef((props, ref) => /* @__PURE__ */ jsx(
1042
+ var CustomPhoneInput = React.forwardRef((props, ref) => /* @__PURE__ */ jsx(
1032
1043
  "input",
1033
1044
  {
1034
1045
  ...props,
@@ -3507,7 +3518,19 @@ var UserButton = ({ showName = false, appearance }) => {
3507
3518
  e.currentTarget.style.backgroundColor = "transparent";
3508
3519
  },
3509
3520
  children: [
3510
- /* @__PURE__ */ jsx("div", { style: {
3521
+ user.avatar ? /* @__PURE__ */ jsx(
3522
+ "img",
3523
+ {
3524
+ src: user.avatar,
3525
+ alt: user.name,
3526
+ style: {
3527
+ width: "36px",
3528
+ height: "36px",
3529
+ borderRadius: "50%",
3530
+ objectFit: "cover"
3531
+ }
3532
+ }
3533
+ ) : /* @__PURE__ */ jsx("div", { style: {
3511
3534
  width: "36px",
3512
3535
  height: "36px",
3513
3536
  borderRadius: "50%",
@@ -3544,7 +3567,19 @@ var UserButton = ({ showName = false, appearance }) => {
3544
3567
  alignItems: "center",
3545
3568
  gap: "12px"
3546
3569
  }, children: [
3547
- /* @__PURE__ */ jsx("div", { style: {
3570
+ user.avatar ? /* @__PURE__ */ jsx(
3571
+ "img",
3572
+ {
3573
+ src: user.avatar,
3574
+ alt: user.name,
3575
+ style: {
3576
+ width: "48px",
3577
+ height: "48px",
3578
+ borderRadius: "50%",
3579
+ objectFit: "cover"
3580
+ }
3581
+ }
3582
+ ) : /* @__PURE__ */ jsx("div", { style: {
3548
3583
  width: "48px",
3549
3584
  height: "48px",
3550
3585
  borderRadius: "50%",
@@ -4424,6 +4459,68 @@ var ChangePassword = ({ onSuccess, appearance }) => {
4424
4459
  )
4425
4460
  ] }) });
4426
4461
  };
4462
+
4463
+ // src/react/components/utils/injectModalStyles.ts
4464
+ var injectModalStyles = () => {
4465
+ if (document.getElementById("ttf-auth-modal-styles")) {
4466
+ return;
4467
+ }
4468
+ const styleElement = document.createElement("style");
4469
+ styleElement.id = "ttf-auth-modal-styles";
4470
+ styleElement.textContent = `
4471
+ /* ImageManager Modal Styles - Critical for proper modal display */
4472
+ /* Radix UI Dialog styles - Force visibility */
4473
+ [data-radix-portal] {
4474
+ z-index: 99999 !important;
4475
+ position: fixed !important;
4476
+ inset: 0 !important;
4477
+ pointer-events: none !important;
4478
+ }
4479
+
4480
+ [data-radix-portal] > * {
4481
+ pointer-events: auto !important;
4482
+ }
4483
+
4484
+ /* Dialog Overlay */
4485
+ [data-state="open"][data-radix-dialog-overlay],
4486
+ [role="dialog"] + [data-radix-dialog-overlay] {
4487
+ position: fixed !important;
4488
+ inset: 0 !important;
4489
+ z-index: 99998 !important;
4490
+ background-color: rgba(0, 0, 0, 0.6) !important;
4491
+ pointer-events: auto !important;
4492
+ }
4493
+
4494
+ /* Dialog Content - Center the modal properly */
4495
+ [data-state="open"][data-radix-dialog-content],
4496
+ [role="dialog"][data-radix-dialog-content] {
4497
+ position: fixed !important;
4498
+ left: 50% !important;
4499
+ top: 50% !important;
4500
+ transform: translate(-50%, -50%) !important;
4501
+ z-index: 99999 !important;
4502
+ background: white !important;
4503
+ border-radius: 16px !important;
4504
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25) !important;
4505
+ pointer-events: auto !important;
4506
+ width: 95vw !important;
4507
+ max-width: 1280px !important;
4508
+ height: 90vh !important;
4509
+ max-height: 90vh !important;
4510
+ min-width: 800px !important;
4511
+ min-height: 600px !important;
4512
+ overflow: hidden !important;
4513
+ }
4514
+
4515
+ /* Dark mode support */
4516
+ .dark [data-state="open"][data-radix-dialog-content],
4517
+ .dark [role="dialog"][data-radix-dialog-content] {
4518
+ background: #0f172a !important;
4519
+ border: 1px solid #334155 !important;
4520
+ }
4521
+ `;
4522
+ document.head.appendChild(styleElement);
4523
+ };
4427
4524
  var AvatarUploader = ({
4428
4525
  onUploadComplete,
4429
4526
  onError,
@@ -4434,32 +4531,30 @@ var AvatarUploader = ({
4434
4531
  upfilesConfig,
4435
4532
  buttonText = "Upload Avatar"
4436
4533
  }) => {
4437
- const { uploadAndUpdateAvatar } = useAuth2();
4534
+ const { user, updateProfile } = useAuth2();
4438
4535
  const [open, setOpen] = useState(false);
4439
4536
  const [uploading, setUploading] = useState(false);
4537
+ useEffect(() => {
4538
+ injectModalStyles();
4539
+ }, []);
4540
+ const effectiveFolderPath = useMemo(() => {
4541
+ if (user?.id) {
4542
+ return `users/${user.id}/`;
4543
+ }
4544
+ return upfilesConfig.folderPath || "/";
4545
+ }, [user?.id, upfilesConfig.folderPath]);
4440
4546
  const handleSelect = async (image) => {
4441
4547
  setUploading(true);
4442
4548
  try {
4443
- const proxyUrl = `${upfilesConfig.baseUrl}/api/download?fileKey=${encodeURIComponent(image.key)}`;
4444
- const response = await fetch(proxyUrl, {
4445
- headers: upfilesConfig.apiKey ? {
4446
- [upfilesConfig.apiKeyHeader || "authorization"]: upfilesConfig.apiKey.startsWith("upk_") ? `Bearer ${upfilesConfig.apiKey}` : upfilesConfig.apiKey
4447
- } : {}
4448
- });
4449
- if (!response.ok) {
4450
- throw new Error("Failed to fetch image");
4451
- }
4452
- const blob = await response.blob();
4453
- const file = new File([blob], image.originalName, { type: image.contentType });
4454
- const result = await uploadAndUpdateAvatar(file);
4455
- if (result.success && result.user?.avatar) {
4456
- onUploadComplete?.(result.user.avatar);
4549
+ const response = await updateProfile({ avatar: image.url });
4550
+ if (response.success && response.user?.avatar) {
4551
+ onUploadComplete?.(response.user.avatar);
4457
4552
  setOpen(false);
4458
4553
  } else {
4459
- throw new Error(result.message || "Failed to update avatar");
4554
+ throw new Error(response.message || "Failed to update avatar");
4460
4555
  }
4461
4556
  } catch (error) {
4462
- const err = error instanceof Error ? error : new Error("Upload failed");
4557
+ const err = error instanceof Error ? error : new Error("Failed to update avatar");
4463
4558
  onError?.(err);
4464
4559
  } finally {
4465
4560
  setUploading(false);
@@ -4489,7 +4584,7 @@ var AvatarUploader = ({
4489
4584
  presignPath: upfilesConfig.presignPath
4490
4585
  },
4491
4586
  projectId: upfilesConfig.projectId,
4492
- folderPath: upfilesConfig.folderPath || "avatars/",
4587
+ folderPath: effectiveFolderPath,
4493
4588
  title: "Select Avatar",
4494
4589
  description: "Upload a new avatar or select from existing images.",
4495
4590
  mode: "full",
@@ -4806,12 +4901,27 @@ var AvatarManager = ({
4806
4901
  gridClassName,
4807
4902
  maxFileSize = 5 * 1024 * 1024,
4808
4903
  // 5MB default
4904
+ maxFiles = 10,
4809
4905
  mode = "full",
4810
4906
  showDelete = false,
4907
+ autoRecordToDb = true,
4908
+ fetchThumbnails = true,
4909
+ projectId,
4910
+ deleteUrl,
4911
+ onDelete,
4811
4912
  upfilesConfig
4812
4913
  }) => {
4813
- const { updateProfile } = useAuth2();
4914
+ const { user, updateProfile } = useAuth2();
4814
4915
  const [updating, setUpdating] = useState(false);
4916
+ useEffect(() => {
4917
+ injectModalStyles();
4918
+ }, []);
4919
+ const effectiveFolderPath = useMemo(() => {
4920
+ if (user?.id) {
4921
+ return `users/${user.id}/`;
4922
+ }
4923
+ return upfilesConfig.folderPath || "/";
4924
+ }, [user?.id, upfilesConfig.folderPath]);
4815
4925
  const handleSelect = async (image) => {
4816
4926
  setUpdating(true);
4817
4927
  try {
@@ -4839,18 +4949,25 @@ var AvatarManager = ({
4839
4949
  apiKey: upfilesConfig.apiKey,
4840
4950
  apiKeyHeader: upfilesConfig.apiKeyHeader || "authorization",
4841
4951
  presignUrl: upfilesConfig.presignUrl,
4842
- presignPath: upfilesConfig.presignPath
4952
+ presignPath: upfilesConfig.presignPath,
4953
+ headers: upfilesConfig.headers,
4954
+ withCredentials: upfilesConfig.withCredentials
4843
4955
  },
4844
- folderPath: upfilesConfig.folderPath || "avatars/",
4956
+ projectId,
4957
+ folderPath: effectiveFolderPath,
4845
4958
  title,
4846
4959
  description,
4847
4960
  className,
4848
4961
  gridClassName,
4849
4962
  onSelect: handleSelect,
4963
+ onDelete,
4964
+ deleteUrl,
4965
+ autoRecordToDb,
4966
+ fetchThumbnails,
4850
4967
  maxFileSize,
4968
+ maxFiles,
4851
4969
  mode,
4852
- showDelete,
4853
- fetchThumbnails: true
4970
+ showDelete
4854
4971
  }
4855
4972
  );
4856
4973
  };