@thetechfossil/auth2 1.2.7 → 1.2.9

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.
@@ -177,6 +177,15 @@ interface UserProfileProps {
177
177
  showAvatar?: boolean;
178
178
  showEmailChange?: boolean;
179
179
  showPasswordChange?: boolean;
180
+ upfilesConfig?: {
181
+ baseUrl: string;
182
+ apiKey?: string;
183
+ apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
184
+ presignUrl?: string;
185
+ presignPath?: string;
186
+ folderPath?: string;
187
+ projectId?: string;
188
+ };
180
189
  }
181
190
  declare const UserProfile: React.FC<UserProfileProps>;
182
191
 
@@ -206,7 +215,9 @@ interface AvatarUploaderProps {
206
215
  presignUrl?: string;
207
216
  presignPath?: string;
208
217
  folderPath?: string;
218
+ projectId?: string;
209
219
  };
220
+ buttonText?: string;
210
221
  }
211
222
  declare const AvatarUploader: React.FC<AvatarUploaderProps>;
212
223
 
@@ -5,15 +5,19 @@ var React2 = require('react');
5
5
  var axios = require('axios');
6
6
  var upfiles = require('@thetechfossil/upfiles');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
- var PhoneInputWithCountry = require('react-phone-number-input');
9
- require('react-phone-number-input/style.css');
10
8
 
11
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
10
 
13
11
  var React2__default = /*#__PURE__*/_interopDefault(React2);
14
12
  var axios__default = /*#__PURE__*/_interopDefault(axios);
15
- var PhoneInputWithCountry__default = /*#__PURE__*/_interopDefault(PhoneInputWithCountry);
16
13
 
14
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
15
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
16
+ }) : x)(function(x) {
17
+ if (typeof require !== "undefined")
18
+ return require.apply(this, arguments);
19
+ throw new Error('Dynamic require of "' + x + '" is not supported');
20
+ });
17
21
  var HttpClient = class {
18
22
  constructor(baseUrl, defaultHeaders = {}) {
19
23
  this.csrfToken = null;
@@ -695,6 +699,14 @@ function useThemeColors() {
695
699
  const { theme } = useAuthTheme();
696
700
  return theme === "dark" ? darkTheme : lightTheme;
697
701
  }
702
+ var PhoneInputWithCountry = null;
703
+ try {
704
+ const module = __require("react-phone-number-input");
705
+ PhoneInputWithCountry = module.default || module;
706
+ __require("react-phone-number-input/style.css");
707
+ } catch (error) {
708
+ console.warn("react-phone-number-input not available, using fallback");
709
+ }
698
710
  var CustomPhoneInput = React2__default.default.forwardRef((props, ref) => /* @__PURE__ */ jsxRuntime.jsx(
699
711
  "input",
700
712
  {
@@ -887,6 +899,30 @@ var PhoneInput = ({
887
899
  const handleChange = React2.useMemo(() => (val) => {
888
900
  onChange(val || "");
889
901
  }, [onChange]);
902
+ if (!PhoneInputWithCountry) {
903
+ return /* @__PURE__ */ jsxRuntime.jsx(
904
+ "input",
905
+ {
906
+ id,
907
+ type: "tel",
908
+ value,
909
+ onChange: (e) => onChange(e.target.value),
910
+ disabled,
911
+ required,
912
+ placeholder,
913
+ style: {
914
+ width: "100%",
915
+ padding: "12px 16px",
916
+ border: `1px solid ${colors.borderSecondary}`,
917
+ borderRadius: "8px",
918
+ fontSize: "16px",
919
+ backgroundColor: colors.bgSecondary,
920
+ color: colors.textPrimary,
921
+ ...style
922
+ }
923
+ }
924
+ );
925
+ }
890
926
  return /* @__PURE__ */ jsxRuntime.jsxs(
891
927
  "div",
892
928
  {
@@ -897,7 +933,7 @@ var PhoneInput = ({
897
933
  children: [
898
934
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: styleContent }),
899
935
  /* @__PURE__ */ jsxRuntime.jsx(
900
- PhoneInputWithCountry__default.default,
936
+ PhoneInputWithCountry,
901
937
  {
902
938
  id,
903
939
  international: true,
@@ -4113,15 +4149,85 @@ var ChangePassword = ({ onSuccess, appearance }) => {
4113
4149
  )
4114
4150
  ] }) });
4115
4151
  };
4152
+ var AvatarUploader = ({
4153
+ onUploadComplete,
4154
+ onError,
4155
+ className,
4156
+ buttonClassName,
4157
+ maxFileSize = 5 * 1024 * 1024,
4158
+ // 5MB default
4159
+ upfilesConfig,
4160
+ buttonText = "Upload Avatar"
4161
+ }) => {
4162
+ const { uploadAndUpdateAvatar } = useAuth2();
4163
+ const [open, setOpen] = React2.useState(false);
4164
+ const [uploading, setUploading] = React2.useState(false);
4165
+ const handleSelect = async (image) => {
4166
+ setUploading(true);
4167
+ try {
4168
+ const response = await fetch(image.url);
4169
+ const blob = await response.blob();
4170
+ const file = new File([blob], image.originalName, { type: image.contentType });
4171
+ const result = await uploadAndUpdateAvatar(file);
4172
+ if (result.success && result.user?.avatar) {
4173
+ onUploadComplete?.(result.user.avatar);
4174
+ setOpen(false);
4175
+ } else {
4176
+ throw new Error(result.message || "Failed to update avatar");
4177
+ }
4178
+ } catch (error) {
4179
+ const err = error instanceof Error ? error : new Error("Upload failed");
4180
+ onError?.(err);
4181
+ } finally {
4182
+ setUploading(false);
4183
+ }
4184
+ };
4185
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
4186
+ /* @__PURE__ */ jsxRuntime.jsx(
4187
+ "button",
4188
+ {
4189
+ type: "button",
4190
+ onClick: () => setOpen(true),
4191
+ disabled: uploading,
4192
+ className: buttonClassName || "px-4 py-2 text-sm rounded border bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50",
4193
+ children: uploading ? "Uploading..." : buttonText
4194
+ }
4195
+ ),
4196
+ /* @__PURE__ */ jsxRuntime.jsx(
4197
+ upfiles.ImageManager,
4198
+ {
4199
+ open,
4200
+ onOpenChange: setOpen,
4201
+ clientOptions: {
4202
+ baseUrl: upfilesConfig.baseUrl,
4203
+ apiKey: upfilesConfig.apiKey,
4204
+ apiKeyHeader: upfilesConfig.apiKeyHeader || "authorization",
4205
+ presignUrl: upfilesConfig.presignUrl,
4206
+ presignPath: upfilesConfig.presignPath
4207
+ },
4208
+ projectId: upfilesConfig.projectId,
4209
+ folderPath: upfilesConfig.folderPath || "avatars/",
4210
+ title: "Select Avatar",
4211
+ description: "Upload a new avatar or select from existing images.",
4212
+ mode: "full",
4213
+ maxFileSize,
4214
+ maxFiles: 1,
4215
+ autoRecordToDb: true,
4216
+ fetchThumbnails: true,
4217
+ onSelect: handleSelect
4218
+ }
4219
+ )
4220
+ ] });
4221
+ };
4116
4222
  var UserProfile = ({
4117
4223
  showAvatar = true,
4118
4224
  showEmailChange = true,
4119
- showPasswordChange = true
4225
+ showPasswordChange = true,
4226
+ upfilesConfig
4120
4227
  }) => {
4121
4228
  const { user, updateProfile, requestEmailChange } = useAuth2();
4122
4229
  const colors = useThemeColors();
4123
4230
  const [name, setName] = React2.useState(user?.name || "");
4124
- const [avatar, setAvatar] = React2.useState(user?.avatar || "");
4125
4231
  const [phoneNumber, setPhoneNumber] = React2.useState(user?.phoneNumber || "");
4126
4232
  const [newEmail, setNewEmail] = React2.useState("");
4127
4233
  const [isLoading, setIsLoading] = React2.useState(false);
@@ -4137,9 +4243,6 @@ var UserProfile = ({
4137
4243
  if (name !== user?.name) {
4138
4244
  updates.name = name;
4139
4245
  }
4140
- if (showAvatar && avatar !== user?.avatar) {
4141
- updates.avatar = avatar;
4142
- }
4143
4246
  if (phoneNumber !== user?.phoneNumber) {
4144
4247
  updates.phoneNumber = phoneNumber;
4145
4248
  }
@@ -4160,6 +4263,12 @@ var UserProfile = ({
4160
4263
  setIsLoading(false);
4161
4264
  }
4162
4265
  };
4266
+ const handleAvatarUploadComplete = (avatarUrl) => {
4267
+ setSuccess("Avatar updated successfully!");
4268
+ };
4269
+ const handleAvatarUploadError = (error2) => {
4270
+ setError(error2.message || "Failed to upload avatar");
4271
+ };
4163
4272
  const handleRequestEmailChange = async (e) => {
4164
4273
  e.preventDefault();
4165
4274
  setIsLoading(true);
@@ -4262,34 +4371,36 @@ var UserProfile = ({
4262
4371
  }
4263
4372
  )
4264
4373
  ] }),
4265
- showAvatar && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "20px" }, children: [
4266
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "avatar", style: {
4374
+ showAvatar && upfilesConfig && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "20px" }, children: [
4375
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: {
4267
4376
  display: "block",
4268
4377
  marginBottom: "8px",
4269
4378
  fontWeight: 500,
4270
4379
  color: colors.textSecondary,
4271
4380
  fontSize: "14px"
4272
- }, children: "Avatar URL" }),
4273
- /* @__PURE__ */ jsxRuntime.jsx(
4274
- "input",
4381
+ }, children: "Avatar" }),
4382
+ user?.avatar && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginBottom: "12px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
4383
+ "img",
4275
4384
  {
4276
- id: "avatar",
4277
- type: "url",
4278
- value: avatar,
4279
- onChange: (e) => setAvatar(e.target.value),
4280
- disabled: isLoading,
4385
+ src: user.avatar,
4386
+ alt: "Current avatar",
4281
4387
  style: {
4282
- width: "100%",
4283
- padding: "12px 16px",
4284
- border: `1px solid ${colors.borderSecondary}`,
4285
- borderRadius: "8px",
4286
- fontSize: "16px",
4287
- boxSizing: "border-box",
4288
- backgroundColor: colors.bgSecondary,
4289
- color: colors.textPrimary,
4290
- transition: "all 0.2s ease"
4291
- },
4292
- placeholder: "https://example.com/avatar.jpg"
4388
+ width: "80px",
4389
+ height: "80px",
4390
+ borderRadius: "50%",
4391
+ objectFit: "cover",
4392
+ border: `2px solid ${colors.borderSecondary}`
4393
+ }
4394
+ }
4395
+ ) }),
4396
+ /* @__PURE__ */ jsxRuntime.jsx(
4397
+ AvatarUploader,
4398
+ {
4399
+ upfilesConfig,
4400
+ onUploadComplete: handleAvatarUploadComplete,
4401
+ onError: handleAvatarUploadError,
4402
+ maxFileSize: 5 * 1024 * 1024,
4403
+ accept: ["image/*"]
4293
4404
  }
4294
4405
  )
4295
4406
  ] }),
@@ -4401,63 +4512,6 @@ var UserProfile = ({
4401
4512
  ] })
4402
4513
  ] });
4403
4514
  };
4404
- var AvatarUploader = ({
4405
- onUploadComplete,
4406
- onError,
4407
- className,
4408
- buttonClassName,
4409
- dropzoneClassName,
4410
- maxFileSize = 5 * 1024 * 1024,
4411
- // 5MB default
4412
- accept = ["image/*"],
4413
- upfilesConfig
4414
- }) => {
4415
- const { uploadAndUpdateAvatar } = useAuth2();
4416
- const [uploading, setUploading] = React2.useState(false);
4417
- const handleUploadComplete = async (files) => {
4418
- if (files.length === 0)
4419
- return;
4420
- setUploading(true);
4421
- try {
4422
- const file = files[0];
4423
- const response = await uploadAndUpdateAvatar(file.file);
4424
- if (response.success && response.user?.avatar) {
4425
- onUploadComplete?.(response.user.avatar);
4426
- } else {
4427
- throw new Error(response.message || "Failed to update avatar");
4428
- }
4429
- } catch (error) {
4430
- const err = error instanceof Error ? error : new Error("Upload failed");
4431
- onError?.(err);
4432
- } finally {
4433
- setUploading(false);
4434
- }
4435
- };
4436
- const handleError = (error) => {
4437
- onError?.(error);
4438
- };
4439
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx(
4440
- upfiles.Uploader,
4441
- {
4442
- clientOptions: {
4443
- baseUrl: upfilesConfig.baseUrl,
4444
- apiKey: upfilesConfig.apiKey,
4445
- apiKeyHeader: upfilesConfig.apiKeyHeader || "authorization",
4446
- presignUrl: upfilesConfig.presignUrl,
4447
- presignPath: upfilesConfig.presignPath
4448
- },
4449
- multiple: false,
4450
- accept,
4451
- maxFileSize,
4452
- maxFiles: 1,
4453
- onComplete: handleUploadComplete,
4454
- onError: handleError,
4455
- buttonClassName,
4456
- dropzoneClassName,
4457
- children: uploading ? "Uploading..." : "Upload Avatar"
4458
- }
4459
- ) });
4460
- };
4461
4515
  var AvatarManager = ({
4462
4516
  open,
4463
4517
  onOpenChange,