@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.
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import axios from 'axios';
3
3
  import { UpfilesClient, ImageManager } from '@thetechfossil/upfiles';
4
4
  export { ConnectProjectDialog, ImageManager, ProjectFilesWidget, UpfilesClient, Uploader } from '@thetechfossil/upfiles';
5
- import React3, { createContext, forwardRef, useContext, useState, useCallback, useEffect, useRef, useMemo } from 'react';
5
+ import React, { createContext, forwardRef, useContext, useState, useCallback, useEffect, useRef, useMemo } from 'react';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
 
8
8
  var __defProp = Object.defineProperty;
@@ -68,6 +68,11 @@ var HttpClient = class {
68
68
  return Promise.reject(refreshError);
69
69
  }
70
70
  }
71
+ if (error.response && error.response.data && error.response.data.message) {
72
+ const customError = new Error(error.response.data.message);
73
+ customError.response = error.response;
74
+ return Promise.reject(customError);
75
+ }
71
76
  return Promise.reject(error);
72
77
  }
73
78
  );
@@ -504,7 +509,7 @@ var AuthService = class {
504
509
  return response;
505
510
  }
506
511
  };
507
- var ThemeContext = createContext({ theme: "light", mounted: false });
512
+ var ThemeContext = React.createContext({ theme: "light", mounted: false });
508
513
  function AuthThemeProvider({ children }) {
509
514
  const [theme, setTheme] = useState("light");
510
515
  const [mounted, setMounted] = useState(false);
@@ -571,11 +576,17 @@ var AuthProvider = ({ children, config }) => {
571
576
  const authenticated = authService.isAuthenticated();
572
577
  if (authenticated) {
573
578
  try {
574
- const currentUser = authService.getCurrentUser();
575
- setUser(currentUser);
579
+ const freshUser = await authService.getProfile();
580
+ setUser(freshUser);
576
581
  } catch (error) {
577
- console.error("Failed to get current user:", error);
578
- setUser(null);
582
+ console.error("Failed to fetch fresh user profile, falling back to token:", error);
583
+ try {
584
+ const currentUser = authService.getCurrentUser();
585
+ setUser(currentUser);
586
+ } catch (fallbackError) {
587
+ console.error("Failed to get current user from token:", fallbackError);
588
+ setUser(null);
589
+ }
579
590
  }
580
591
  } else {
581
592
  setUser(null);
@@ -1034,7 +1045,7 @@ try {
1034
1045
  } catch (error) {
1035
1046
  console.warn("react-phone-number-input not available, using fallback");
1036
1047
  }
1037
- var CustomPhoneInput = React3.forwardRef((props, ref) => /* @__PURE__ */ jsx(
1048
+ var CustomPhoneInput = React.forwardRef((props, ref) => /* @__PURE__ */ jsx(
1038
1049
  "input",
1039
1050
  {
1040
1051
  ...props,
@@ -3513,7 +3524,19 @@ var UserButton = ({ showName = false, appearance }) => {
3513
3524
  e.currentTarget.style.backgroundColor = "transparent";
3514
3525
  },
3515
3526
  children: [
3516
- /* @__PURE__ */ jsx("div", { style: {
3527
+ user.avatar ? /* @__PURE__ */ jsx(
3528
+ "img",
3529
+ {
3530
+ src: user.avatar,
3531
+ alt: user.name,
3532
+ style: {
3533
+ width: "36px",
3534
+ height: "36px",
3535
+ borderRadius: "50%",
3536
+ objectFit: "cover"
3537
+ }
3538
+ }
3539
+ ) : /* @__PURE__ */ jsx("div", { style: {
3517
3540
  width: "36px",
3518
3541
  height: "36px",
3519
3542
  borderRadius: "50%",
@@ -3550,7 +3573,19 @@ var UserButton = ({ showName = false, appearance }) => {
3550
3573
  alignItems: "center",
3551
3574
  gap: "12px"
3552
3575
  }, children: [
3553
- /* @__PURE__ */ jsx("div", { style: {
3576
+ user.avatar ? /* @__PURE__ */ jsx(
3577
+ "img",
3578
+ {
3579
+ src: user.avatar,
3580
+ alt: user.name,
3581
+ style: {
3582
+ width: "48px",
3583
+ height: "48px",
3584
+ borderRadius: "50%",
3585
+ objectFit: "cover"
3586
+ }
3587
+ }
3588
+ ) : /* @__PURE__ */ jsx("div", { style: {
3554
3589
  width: "48px",
3555
3590
  height: "48px",
3556
3591
  borderRadius: "50%",
@@ -4430,6 +4465,68 @@ var ChangePassword = ({ onSuccess, appearance }) => {
4430
4465
  )
4431
4466
  ] }) });
4432
4467
  };
4468
+
4469
+ // src/react/components/utils/injectModalStyles.ts
4470
+ var injectModalStyles = () => {
4471
+ if (document.getElementById("ttf-auth-modal-styles")) {
4472
+ return;
4473
+ }
4474
+ const styleElement = document.createElement("style");
4475
+ styleElement.id = "ttf-auth-modal-styles";
4476
+ styleElement.textContent = `
4477
+ /* ImageManager Modal Styles - Critical for proper modal display */
4478
+ /* Radix UI Dialog styles - Force visibility */
4479
+ [data-radix-portal] {
4480
+ z-index: 99999 !important;
4481
+ position: fixed !important;
4482
+ inset: 0 !important;
4483
+ pointer-events: none !important;
4484
+ }
4485
+
4486
+ [data-radix-portal] > * {
4487
+ pointer-events: auto !important;
4488
+ }
4489
+
4490
+ /* Dialog Overlay */
4491
+ [data-state="open"][data-radix-dialog-overlay],
4492
+ [role="dialog"] + [data-radix-dialog-overlay] {
4493
+ position: fixed !important;
4494
+ inset: 0 !important;
4495
+ z-index: 99998 !important;
4496
+ background-color: rgba(0, 0, 0, 0.6) !important;
4497
+ pointer-events: auto !important;
4498
+ }
4499
+
4500
+ /* Dialog Content - Center the modal properly */
4501
+ [data-state="open"][data-radix-dialog-content],
4502
+ [role="dialog"][data-radix-dialog-content] {
4503
+ position: fixed !important;
4504
+ left: 50% !important;
4505
+ top: 50% !important;
4506
+ transform: translate(-50%, -50%) !important;
4507
+ z-index: 99999 !important;
4508
+ background: white !important;
4509
+ border-radius: 16px !important;
4510
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25) !important;
4511
+ pointer-events: auto !important;
4512
+ width: 95vw !important;
4513
+ max-width: 1280px !important;
4514
+ height: 90vh !important;
4515
+ max-height: 90vh !important;
4516
+ min-width: 800px !important;
4517
+ min-height: 600px !important;
4518
+ overflow: hidden !important;
4519
+ }
4520
+
4521
+ /* Dark mode support */
4522
+ .dark [data-state="open"][data-radix-dialog-content],
4523
+ .dark [role="dialog"][data-radix-dialog-content] {
4524
+ background: #0f172a !important;
4525
+ border: 1px solid #334155 !important;
4526
+ }
4527
+ `;
4528
+ document.head.appendChild(styleElement);
4529
+ };
4433
4530
  var AvatarUploader = ({
4434
4531
  onUploadComplete,
4435
4532
  onError,
@@ -4440,32 +4537,30 @@ var AvatarUploader = ({
4440
4537
  upfilesConfig,
4441
4538
  buttonText = "Upload Avatar"
4442
4539
  }) => {
4443
- const { uploadAndUpdateAvatar } = useAuth();
4540
+ const { user, updateProfile } = useAuth();
4444
4541
  const [open, setOpen] = useState(false);
4445
4542
  const [uploading, setUploading] = useState(false);
4543
+ useEffect(() => {
4544
+ injectModalStyles();
4545
+ }, []);
4546
+ const effectiveFolderPath = useMemo(() => {
4547
+ if (user?.id) {
4548
+ return `users/${user.id}/`;
4549
+ }
4550
+ return upfilesConfig.folderPath || "/";
4551
+ }, [user?.id, upfilesConfig.folderPath]);
4446
4552
  const handleSelect = async (image) => {
4447
4553
  setUploading(true);
4448
4554
  try {
4449
- const proxyUrl = `${upfilesConfig.baseUrl}/api/download?fileKey=${encodeURIComponent(image.key)}`;
4450
- const response = await fetch(proxyUrl, {
4451
- headers: upfilesConfig.apiKey ? {
4452
- [upfilesConfig.apiKeyHeader || "authorization"]: upfilesConfig.apiKey.startsWith("upk_") ? `Bearer ${upfilesConfig.apiKey}` : upfilesConfig.apiKey
4453
- } : {}
4454
- });
4455
- if (!response.ok) {
4456
- throw new Error("Failed to fetch image");
4457
- }
4458
- const blob = await response.blob();
4459
- const file = new File([blob], image.originalName, { type: image.contentType });
4460
- const result = await uploadAndUpdateAvatar(file);
4461
- if (result.success && result.user?.avatar) {
4462
- onUploadComplete?.(result.user.avatar);
4555
+ const response = await updateProfile({ avatar: image.url });
4556
+ if (response.success && response.user?.avatar) {
4557
+ onUploadComplete?.(response.user.avatar);
4463
4558
  setOpen(false);
4464
4559
  } else {
4465
- throw new Error(result.message || "Failed to update avatar");
4560
+ throw new Error(response.message || "Failed to update avatar");
4466
4561
  }
4467
4562
  } catch (error) {
4468
- const err = error instanceof Error ? error : new Error("Upload failed");
4563
+ const err = error instanceof Error ? error : new Error("Failed to update avatar");
4469
4564
  onError?.(err);
4470
4565
  } finally {
4471
4566
  setUploading(false);
@@ -4495,7 +4590,7 @@ var AvatarUploader = ({
4495
4590
  presignPath: upfilesConfig.presignPath
4496
4591
  },
4497
4592
  projectId: upfilesConfig.projectId,
4498
- folderPath: upfilesConfig.folderPath || "avatars/",
4593
+ folderPath: effectiveFolderPath,
4499
4594
  title: "Select Avatar",
4500
4595
  description: "Upload a new avatar or select from existing images.",
4501
4596
  mode: "full",
@@ -4812,12 +4907,27 @@ var AvatarManager = ({
4812
4907
  gridClassName,
4813
4908
  maxFileSize = 5 * 1024 * 1024,
4814
4909
  // 5MB default
4910
+ maxFiles = 10,
4815
4911
  mode = "full",
4816
4912
  showDelete = false,
4913
+ autoRecordToDb = true,
4914
+ fetchThumbnails = true,
4915
+ projectId,
4916
+ deleteUrl,
4917
+ onDelete,
4817
4918
  upfilesConfig
4818
4919
  }) => {
4819
- const { updateProfile } = useAuth();
4920
+ const { user, updateProfile } = useAuth();
4820
4921
  const [updating, setUpdating] = useState(false);
4922
+ useEffect(() => {
4923
+ injectModalStyles();
4924
+ }, []);
4925
+ const effectiveFolderPath = useMemo(() => {
4926
+ if (user?.id) {
4927
+ return `users/${user.id}/`;
4928
+ }
4929
+ return upfilesConfig.folderPath || "/";
4930
+ }, [user?.id, upfilesConfig.folderPath]);
4821
4931
  const handleSelect = async (image) => {
4822
4932
  setUpdating(true);
4823
4933
  try {
@@ -4845,18 +4955,25 @@ var AvatarManager = ({
4845
4955
  apiKey: upfilesConfig.apiKey,
4846
4956
  apiKeyHeader: upfilesConfig.apiKeyHeader || "authorization",
4847
4957
  presignUrl: upfilesConfig.presignUrl,
4848
- presignPath: upfilesConfig.presignPath
4958
+ presignPath: upfilesConfig.presignPath,
4959
+ headers: upfilesConfig.headers,
4960
+ withCredentials: upfilesConfig.withCredentials
4849
4961
  },
4850
- folderPath: upfilesConfig.folderPath || "avatars/",
4962
+ projectId,
4963
+ folderPath: effectiveFolderPath,
4851
4964
  title,
4852
4965
  description,
4853
4966
  className,
4854
4967
  gridClassName,
4855
4968
  onSelect: handleSelect,
4969
+ onDelete,
4970
+ deleteUrl,
4971
+ autoRecordToDb,
4972
+ fetchThumbnails,
4856
4973
  maxFileSize,
4974
+ maxFiles,
4857
4975
  mode,
4858
- showDelete,
4859
- fetchThumbnails: true
4976
+ showDelete
4860
4977
  }
4861
4978
  );
4862
4979
  };