@retinalabsllc/zairusjs 20.1.15 → 20.1.20

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
@@ -5512,6 +5512,8 @@ var UniversalSettings = ({
5512
5512
  const [isSavingProfile, setIsSavingProfile] = (0, import_react89.useState)(false);
5513
5513
  const orgFileInputRef = (0, import_react89.useRef)(null);
5514
5514
  const userFileInputRef = (0, import_react89.useRef)(null);
5515
+ const [pendingOrgAvatar, setPendingOrgAvatar] = (0, import_react89.useState)(null);
5516
+ const [pendingUserAvatar, setPendingUserAvatar] = (0, import_react89.useState)(null);
5515
5517
  const [isUploadingOrgAvatar, setIsUploadingOrgAvatar] = (0, import_react89.useState)(false);
5516
5518
  const [isUploadingUserAvatar, setIsUploadingUserAvatar] = (0, import_react89.useState)(false);
5517
5519
  (0, import_react89.useEffect)(() => {
@@ -5525,7 +5527,7 @@ var UniversalSettings = ({
5525
5527
  setDescription(initialDescription || "");
5526
5528
  setAvatarUrl(initialAvatarUrl || "");
5527
5529
  }, [initialOrgName, initialOrgSlug, initialOrgAvatarUrl, initialFullName, initialJobTitle, initialDescription, initialAvatarUrl]);
5528
- const handleFileSelect = async (e, type) => {
5530
+ const handleFileSelect = (e, type) => {
5529
5531
  const file = e.target.files?.[0];
5530
5532
  if (!file) return;
5531
5533
  if (file.size > 1024 * 1024) {
@@ -5539,27 +5541,15 @@ var UniversalSettings = ({
5539
5541
  e.target.value = "";
5540
5542
  return;
5541
5543
  }
5542
- if (!onUploadAvatar) {
5543
- import_react_hot_toast15.default.error("Upload service not configured.");
5544
- e.target.value = "";
5545
- return;
5546
- }
5547
- try {
5548
- if (type === "USER") setIsUploadingUserAvatar(true);
5549
- if (type === "ORGANIZATION") setIsUploadingOrgAvatar(true);
5550
- const res = await onUploadAvatar(file, type);
5551
- if (res?.url) {
5552
- if (type === "USER") setAvatarUrl(res.url);
5553
- if (type === "ORGANIZATION") setOrgAvatarUrl(res.url);
5554
- import_react_hot_toast15.default.success("Image uploaded. Remember to save changes.");
5555
- }
5556
- } catch (error) {
5557
- import_react_hot_toast15.default.error("Failed to process image upload.");
5558
- } finally {
5559
- if (type === "USER") setIsUploadingUserAvatar(false);
5560
- if (type === "ORGANIZATION") setIsUploadingOrgAvatar(false);
5561
- e.target.value = "";
5544
+ const previewUrl = URL.createObjectURL(file);
5545
+ if (type === "USER") {
5546
+ setPendingUserAvatar(file);
5547
+ setAvatarUrl(previewUrl);
5548
+ } else if (type === "ORGANIZATION") {
5549
+ setPendingOrgAvatar(file);
5550
+ setOrgAvatarUrl(previewUrl);
5562
5551
  }
5552
+ e.target.value = "";
5563
5553
  };
5564
5554
  (0, import_react89.useEffect)(() => {
5565
5555
  if (activeTab !== "MEMBERS") return;
@@ -5651,13 +5641,32 @@ var UniversalSettings = ({
5651
5641
  if (orgSlug !== initialOrgSlug && slugAvailable === false) return import_react_hot_toast15.default.error("Address handle unavailable.");
5652
5642
  setIsSavingOrg(true);
5653
5643
  try {
5654
- const res = await onSaveOrganization({ name: orgName, slug: orgSlug, avatarUrl: orgAvatarUrl });
5644
+ let finalAvatarUrl = orgAvatarUrl;
5645
+ if (pendingOrgAvatar && onUploadAvatar) {
5646
+ setIsUploadingOrgAvatar(true);
5647
+ try {
5648
+ const res2 = await onUploadAvatar(pendingOrgAvatar, "ORGANIZATION");
5649
+ if (res2?.url) {
5650
+ finalAvatarUrl = res2.url;
5651
+ setOrgAvatarUrl(finalAvatarUrl);
5652
+ }
5653
+ } catch (err) {
5654
+ import_react_hot_toast15.default.error("Failed to securely upload workspace avatar.");
5655
+ setIsSavingOrg(false);
5656
+ setIsUploadingOrgAvatar(false);
5657
+ return;
5658
+ }
5659
+ setPendingOrgAvatar(null);
5660
+ setIsUploadingOrgAvatar(false);
5661
+ }
5662
+ const res = await onSaveOrganization({ name: orgName, slug: orgSlug, avatarUrl: finalAvatarUrl });
5655
5663
  if (res.success) import_react_hot_toast15.default.success("Workspace updated successfully.");
5656
5664
  else import_react_hot_toast15.default.error(res.error || "Failed to update workspace.");
5657
5665
  } catch (error) {
5658
5666
  import_react_hot_toast15.default.error("Service unavailable.");
5659
5667
  } finally {
5660
5668
  setIsSavingOrg(false);
5669
+ setIsUploadingOrgAvatar(false);
5661
5670
  }
5662
5671
  };
5663
5672
  const handleSaveProfile = async (e) => {
@@ -5665,13 +5674,32 @@ var UniversalSettings = ({
5665
5674
  if (isSavingProfile || !onSaveProfile) return;
5666
5675
  setIsSavingProfile(true);
5667
5676
  try {
5668
- const res = await onSaveProfile({ firstName, lastName, jobTitle, description, avatarUrl });
5677
+ let finalAvatarUrl = avatarUrl;
5678
+ if (pendingUserAvatar && onUploadAvatar) {
5679
+ setIsUploadingUserAvatar(true);
5680
+ try {
5681
+ const res2 = await onUploadAvatar(pendingUserAvatar, "USER");
5682
+ if (res2?.url) {
5683
+ finalAvatarUrl = res2.url;
5684
+ setAvatarUrl(finalAvatarUrl);
5685
+ }
5686
+ } catch (err) {
5687
+ import_react_hot_toast15.default.error("Failed to securely upload profile avatar.");
5688
+ setIsSavingProfile(false);
5689
+ setIsUploadingUserAvatar(false);
5690
+ return;
5691
+ }
5692
+ setPendingUserAvatar(null);
5693
+ setIsUploadingUserAvatar(false);
5694
+ }
5695
+ const res = await onSaveProfile({ firstName, lastName, jobTitle, description, avatarUrl: finalAvatarUrl });
5669
5696
  if (res.success) import_react_hot_toast15.default.success("Identity updated successfully.");
5670
5697
  else import_react_hot_toast15.default.error(res.error || "Failed to update identity.");
5671
5698
  } catch (error) {
5672
5699
  import_react_hot_toast15.default.error("Service unavailable.");
5673
5700
  } finally {
5674
5701
  setIsSavingProfile(false);
5702
+ setIsUploadingUserAvatar(false);
5675
5703
  }
5676
5704
  };
5677
5705
  const hasOrgChanges = orgName !== initialOrgName || orgSlug !== initialOrgSlug || orgAvatarUrl !== initialOrgAvatarUrl;
@@ -5719,6 +5747,7 @@ var UniversalSettings = ({
5719
5747
  setOrgName(initialOrgName || "");
5720
5748
  setOrgSlug(initialOrgSlug || "");
5721
5749
  setOrgAvatarUrl(initialOrgAvatarUrl || "");
5750
+ setPendingOrgAvatar(null);
5722
5751
  }, className: "text-xs tracking-widest text-stone-400 hover:text-black transition-colors outline-none" }, "Cancel")))), activeTab === "ACCOUNT" && /* @__PURE__ */ import_react89.default.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react89.default.createElement("div", { className: "flex flex-col gap-8 rounded-2xl p-6 bg-white w-full" }, /* @__PURE__ */ import_react89.default.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react89.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react89.default.createElement("div", { className: "relative group cursor-pointer shrink-0", onClick: () => !isSavingProfile ? userFileInputRef.current?.click() : void 0 }, /* @__PURE__ */ import_react89.default.createElement(MemberAvatar3, { src: avatarUrl, status: "ACTIVE", sizeClass: "w-14 h-14" }), /* @__PURE__ */ import_react89.default.createElement("div", { className: "absolute -bottom-1 -right-1 w-6 h-6 bg-white border border-stone-200 rounded-full flex items-center justify-center text-stone-500 group-hover:text-black transition-colors z-20" }, isUploadingUserAvatar ? /* @__PURE__ */ import_react89.default.createElement(import_react90.HugeiconsIcon, { icon: import_core_free_icons33.Loading03Icon, size: 12, className: "animate-spin" }) : /* @__PURE__ */ import_react89.default.createElement(import_react90.HugeiconsIcon, { icon: import_core_free_icons33.PlusSignIcon, size: 14 })), /* @__PURE__ */ import_react89.default.createElement("input", { type: "file", ref: userFileInputRef, className: "hidden", accept: ".png, .jpg, .jpeg", onChange: (e) => handleFileSelect(e, "USER") })), /* @__PURE__ */ import_react89.default.createElement("div", null, /* @__PURE__ */ import_react89.default.createElement("h2", { className: "text-black text-xl mb-1 tracking-tight" }, "Personal Identity"), /* @__PURE__ */ import_react89.default.createElement("p", { className: "text-xs text-stone-500" }, "Update your system display name and contact email.")))), /* @__PURE__ */ import_react89.default.createElement("form", { className: "flex flex-col gap-6 w-full max-w-5xl", onSubmit: handleSaveProfile, autoComplete: "off" }, /* @__PURE__ */ import_react89.default.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-6" }, /* @__PURE__ */ import_react89.default.createElement(TextInput, { label: "First Name", value: firstName, onChange: (v) => setFirstName(v.replace(/[^a-zA-Z\s-]/g, "").substring(0, 50)), disabled: isSavingProfile, placeholder: "First name", maxLength: 50 }), /* @__PURE__ */ import_react89.default.createElement(TextInput, { label: "Last Name", value: lastName, onChange: (v) => setLastName(v.replace(/[^a-zA-Z\s-]/g, "").substring(0, 50)), disabled: isSavingProfile, placeholder: "Last name", maxLength: 50 })), /* @__PURE__ */ import_react89.default.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-6" }, /* @__PURE__ */ import_react89.default.createElement(TextInput, { label: "Job Title", value: jobTitle, onChange: (v) => setJobTitle(v.substring(0, 50)), disabled: isSavingProfile, placeholder: "e.g. HR Manager, CEO", maxLength: 50 }), /* @__PURE__ */ import_react89.default.createElement("div", { className: "space-y-1.5 w-full" }, /* @__PURE__ */ import_react89.default.createElement("label", { className: "text-xs text-stone-400 tracking-[0.2em] block" }, "Email Address"), /* @__PURE__ */ import_react89.default.createElement("input", { type: "email", value: initialEmail, disabled: true, className: "w-full pb-3 pt-3 text-sm bg-transparent text-stone-400 border-b border-stone-200 outline-none cursor-not-allowed" }))), /* @__PURE__ */ import_react89.default.createElement("div", { className: "space-y-1.5 w-full" }, /* @__PURE__ */ import_react89.default.createElement("label", { className: "text-xs text-stone-400 tracking-[0.2em] block" }, "About Me"), /* @__PURE__ */ import_react89.default.createElement(
5723
5752
  "textarea",
5724
5753
  {
package/dist/index.mjs CHANGED
@@ -5567,6 +5567,8 @@ var UniversalSettings = ({
5567
5567
  const [isSavingProfile, setIsSavingProfile] = useState38(false);
5568
5568
  const orgFileInputRef = useRef14(null);
5569
5569
  const userFileInputRef = useRef14(null);
5570
+ const [pendingOrgAvatar, setPendingOrgAvatar] = useState38(null);
5571
+ const [pendingUserAvatar, setPendingUserAvatar] = useState38(null);
5570
5572
  const [isUploadingOrgAvatar, setIsUploadingOrgAvatar] = useState38(false);
5571
5573
  const [isUploadingUserAvatar, setIsUploadingUserAvatar] = useState38(false);
5572
5574
  useEffect21(() => {
@@ -5580,7 +5582,7 @@ var UniversalSettings = ({
5580
5582
  setDescription(initialDescription || "");
5581
5583
  setAvatarUrl(initialAvatarUrl || "");
5582
5584
  }, [initialOrgName, initialOrgSlug, initialOrgAvatarUrl, initialFullName, initialJobTitle, initialDescription, initialAvatarUrl]);
5583
- const handleFileSelect = async (e, type) => {
5585
+ const handleFileSelect = (e, type) => {
5584
5586
  const file = e.target.files?.[0];
5585
5587
  if (!file) return;
5586
5588
  if (file.size > 1024 * 1024) {
@@ -5594,27 +5596,15 @@ var UniversalSettings = ({
5594
5596
  e.target.value = "";
5595
5597
  return;
5596
5598
  }
5597
- if (!onUploadAvatar) {
5598
- toast14.error("Upload service not configured.");
5599
- e.target.value = "";
5600
- return;
5601
- }
5602
- try {
5603
- if (type === "USER") setIsUploadingUserAvatar(true);
5604
- if (type === "ORGANIZATION") setIsUploadingOrgAvatar(true);
5605
- const res = await onUploadAvatar(file, type);
5606
- if (res?.url) {
5607
- if (type === "USER") setAvatarUrl(res.url);
5608
- if (type === "ORGANIZATION") setOrgAvatarUrl(res.url);
5609
- toast14.success("Image uploaded. Remember to save changes.");
5610
- }
5611
- } catch (error) {
5612
- toast14.error("Failed to process image upload.");
5613
- } finally {
5614
- if (type === "USER") setIsUploadingUserAvatar(false);
5615
- if (type === "ORGANIZATION") setIsUploadingOrgAvatar(false);
5616
- e.target.value = "";
5599
+ const previewUrl = URL.createObjectURL(file);
5600
+ if (type === "USER") {
5601
+ setPendingUserAvatar(file);
5602
+ setAvatarUrl(previewUrl);
5603
+ } else if (type === "ORGANIZATION") {
5604
+ setPendingOrgAvatar(file);
5605
+ setOrgAvatarUrl(previewUrl);
5617
5606
  }
5607
+ e.target.value = "";
5618
5608
  };
5619
5609
  useEffect21(() => {
5620
5610
  if (activeTab !== "MEMBERS") return;
@@ -5706,13 +5696,32 @@ var UniversalSettings = ({
5706
5696
  if (orgSlug !== initialOrgSlug && slugAvailable === false) return toast14.error("Address handle unavailable.");
5707
5697
  setIsSavingOrg(true);
5708
5698
  try {
5709
- const res = await onSaveOrganization({ name: orgName, slug: orgSlug, avatarUrl: orgAvatarUrl });
5699
+ let finalAvatarUrl = orgAvatarUrl;
5700
+ if (pendingOrgAvatar && onUploadAvatar) {
5701
+ setIsUploadingOrgAvatar(true);
5702
+ try {
5703
+ const res2 = await onUploadAvatar(pendingOrgAvatar, "ORGANIZATION");
5704
+ if (res2?.url) {
5705
+ finalAvatarUrl = res2.url;
5706
+ setOrgAvatarUrl(finalAvatarUrl);
5707
+ }
5708
+ } catch (err) {
5709
+ toast14.error("Failed to securely upload workspace avatar.");
5710
+ setIsSavingOrg(false);
5711
+ setIsUploadingOrgAvatar(false);
5712
+ return;
5713
+ }
5714
+ setPendingOrgAvatar(null);
5715
+ setIsUploadingOrgAvatar(false);
5716
+ }
5717
+ const res = await onSaveOrganization({ name: orgName, slug: orgSlug, avatarUrl: finalAvatarUrl });
5710
5718
  if (res.success) toast14.success("Workspace updated successfully.");
5711
5719
  else toast14.error(res.error || "Failed to update workspace.");
5712
5720
  } catch (error) {
5713
5721
  toast14.error("Service unavailable.");
5714
5722
  } finally {
5715
5723
  setIsSavingOrg(false);
5724
+ setIsUploadingOrgAvatar(false);
5716
5725
  }
5717
5726
  };
5718
5727
  const handleSaveProfile = async (e) => {
@@ -5720,13 +5729,32 @@ var UniversalSettings = ({
5720
5729
  if (isSavingProfile || !onSaveProfile) return;
5721
5730
  setIsSavingProfile(true);
5722
5731
  try {
5723
- const res = await onSaveProfile({ firstName, lastName, jobTitle, description, avatarUrl });
5732
+ let finalAvatarUrl = avatarUrl;
5733
+ if (pendingUserAvatar && onUploadAvatar) {
5734
+ setIsUploadingUserAvatar(true);
5735
+ try {
5736
+ const res2 = await onUploadAvatar(pendingUserAvatar, "USER");
5737
+ if (res2?.url) {
5738
+ finalAvatarUrl = res2.url;
5739
+ setAvatarUrl(finalAvatarUrl);
5740
+ }
5741
+ } catch (err) {
5742
+ toast14.error("Failed to securely upload profile avatar.");
5743
+ setIsSavingProfile(false);
5744
+ setIsUploadingUserAvatar(false);
5745
+ return;
5746
+ }
5747
+ setPendingUserAvatar(null);
5748
+ setIsUploadingUserAvatar(false);
5749
+ }
5750
+ const res = await onSaveProfile({ firstName, lastName, jobTitle, description, avatarUrl: finalAvatarUrl });
5724
5751
  if (res.success) toast14.success("Identity updated successfully.");
5725
5752
  else toast14.error(res.error || "Failed to update identity.");
5726
5753
  } catch (error) {
5727
5754
  toast14.error("Service unavailable.");
5728
5755
  } finally {
5729
5756
  setIsSavingProfile(false);
5757
+ setIsUploadingUserAvatar(false);
5730
5758
  }
5731
5759
  };
5732
5760
  const hasOrgChanges = orgName !== initialOrgName || orgSlug !== initialOrgSlug || orgAvatarUrl !== initialOrgAvatarUrl;
@@ -5774,6 +5802,7 @@ var UniversalSettings = ({
5774
5802
  setOrgName(initialOrgName || "");
5775
5803
  setOrgSlug(initialOrgSlug || "");
5776
5804
  setOrgAvatarUrl(initialOrgAvatarUrl || "");
5805
+ setPendingOrgAvatar(null);
5777
5806
  }, className: "text-xs tracking-widest text-stone-400 hover:text-black transition-colors outline-none" }, "Cancel")))), activeTab === "ACCOUNT" && /* @__PURE__ */ React52.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in duration-300" }, /* @__PURE__ */ React52.createElement("div", { className: "flex flex-col gap-8 rounded-2xl p-6 bg-white w-full" }, /* @__PURE__ */ React52.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ React52.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React52.createElement("div", { className: "relative group cursor-pointer shrink-0", onClick: () => !isSavingProfile ? userFileInputRef.current?.click() : void 0 }, /* @__PURE__ */ React52.createElement(MemberAvatar3, { src: avatarUrl, status: "ACTIVE", sizeClass: "w-14 h-14" }), /* @__PURE__ */ React52.createElement("div", { className: "absolute -bottom-1 -right-1 w-6 h-6 bg-white border border-stone-200 rounded-full flex items-center justify-center text-stone-500 group-hover:text-black transition-colors z-20" }, isUploadingUserAvatar ? /* @__PURE__ */ React52.createElement(HugeiconsIcon38, { icon: Loading03Icon25, size: 12, className: "animate-spin" }) : /* @__PURE__ */ React52.createElement(HugeiconsIcon38, { icon: PlusSignIcon3, size: 14 })), /* @__PURE__ */ React52.createElement("input", { type: "file", ref: userFileInputRef, className: "hidden", accept: ".png, .jpg, .jpeg", onChange: (e) => handleFileSelect(e, "USER") })), /* @__PURE__ */ React52.createElement("div", null, /* @__PURE__ */ React52.createElement("h2", { className: "text-black text-xl mb-1 tracking-tight" }, "Personal Identity"), /* @__PURE__ */ React52.createElement("p", { className: "text-xs text-stone-500" }, "Update your system display name and contact email.")))), /* @__PURE__ */ React52.createElement("form", { className: "flex flex-col gap-6 w-full max-w-5xl", onSubmit: handleSaveProfile, autoComplete: "off" }, /* @__PURE__ */ React52.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-6" }, /* @__PURE__ */ React52.createElement(TextInput, { label: "First Name", value: firstName, onChange: (v) => setFirstName(v.replace(/[^a-zA-Z\s-]/g, "").substring(0, 50)), disabled: isSavingProfile, placeholder: "First name", maxLength: 50 }), /* @__PURE__ */ React52.createElement(TextInput, { label: "Last Name", value: lastName, onChange: (v) => setLastName(v.replace(/[^a-zA-Z\s-]/g, "").substring(0, 50)), disabled: isSavingProfile, placeholder: "Last name", maxLength: 50 })), /* @__PURE__ */ React52.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-6" }, /* @__PURE__ */ React52.createElement(TextInput, { label: "Job Title", value: jobTitle, onChange: (v) => setJobTitle(v.substring(0, 50)), disabled: isSavingProfile, placeholder: "e.g. HR Manager, CEO", maxLength: 50 }), /* @__PURE__ */ React52.createElement("div", { className: "space-y-1.5 w-full" }, /* @__PURE__ */ React52.createElement("label", { className: "text-xs text-stone-400 tracking-[0.2em] block" }, "Email Address"), /* @__PURE__ */ React52.createElement("input", { type: "email", value: initialEmail, disabled: true, className: "w-full pb-3 pt-3 text-sm bg-transparent text-stone-400 border-b border-stone-200 outline-none cursor-not-allowed" }))), /* @__PURE__ */ React52.createElement("div", { className: "space-y-1.5 w-full" }, /* @__PURE__ */ React52.createElement("label", { className: "text-xs text-stone-400 tracking-[0.2em] block" }, "About Me"), /* @__PURE__ */ React52.createElement(
5778
5807
  "textarea",
5779
5808
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retinalabsllc/zairusjs",
3
- "version": "20.1.15",
3
+ "version": "20.1.20",
4
4
  "description": "A perceptive, Ai data driven Next.js UI component library.",
5
5
  "author": "Retina Labs Company",
6
6
  "license": "MIT",