jett.admin.npmpackage 1.0.91 → 1.0.93

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.css CHANGED
@@ -49,6 +49,8 @@
49
49
  --text-xs--line-height: calc(1 / 0.75);
50
50
  --text-sm: 0.875rem;
51
51
  --text-sm--line-height: calc(1.25 / 0.875);
52
+ --text-base: 1rem;
53
+ --text-base--line-height: calc(1.5 / 1);
52
54
  --text-lg: 1.125rem;
53
55
  --text-lg--line-height: calc(1.75 / 1.125);
54
56
  --font-weight-medium: 500;
@@ -412,6 +414,9 @@
412
414
  .max-h-\[100vh\] {
413
415
  max-height: 100vh;
414
416
  }
417
+ .max-h-\[1000px\] {
418
+ max-height: 1000px;
419
+ }
415
420
  .min-h-10 {
416
421
  min-height: calc(var(--spacing) * 10);
417
422
  }
@@ -642,6 +647,9 @@
642
647
  .bg-\[\#ef4444\] {
643
648
  background-color: #ef4444;
644
649
  }
650
+ .bg-\[\#f4f4f5\] {
651
+ background-color: #f4f4f5;
652
+ }
645
653
  .bg-\[\#fafafa\] {
646
654
  background-color: #fafafa;
647
655
  }
@@ -753,6 +761,10 @@
753
761
  .text-right {
754
762
  text-align: right;
755
763
  }
764
+ .text-base {
765
+ font-size: var(--text-base);
766
+ line-height: var(--tw-leading, var(--text-base--line-height));
767
+ }
756
768
  .text-lg {
757
769
  font-size: var(--text-lg);
758
770
  line-height: var(--tw-leading, var(--text-lg--line-height));
package/dist/index.js CHANGED
@@ -709,6 +709,8 @@ var AppSideBar = ({
709
709
  const [authData, setAuthData] = (0, import_react12.useState)(null);
710
710
  const [selectedCountry, setSelectedCountry] = (0, import_react12.useState)("dubai");
711
711
  const [isMobileMenuOpen, setIsMobileMenuOpen] = (0, import_react12.useState)(false);
712
+ const [openMenus, setOpenMenus] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
713
+ const [activeMenuPath, setActiveMenuPath] = (0, import_react12.useState)(null);
712
714
  const [currAppearance, setCurrAppearance] = (0, import_react12.useState)("light");
713
715
  (0, import_react12.useEffect)(() => {
714
716
  setCurrAppearance("light");
@@ -720,28 +722,69 @@ var AppSideBar = ({
720
722
  { label: "Singapore", value: "singapore" },
721
723
  { label: "Qatar", value: "qatar" }
722
724
  ];
723
- const handleIconRotate = (e, index, additionalKey, parentIndex) => {
724
- let dropDownIcon = e.currentTarget.children[2];
725
- if (!dropDownIcon) return;
726
- if (dropDownIcon.classList.contains("rotate-180")) {
727
- dropDownIcon.classList.remove("rotate-180");
725
+ const toggleMenu = (menuKey) => {
726
+ setOpenMenus((prev) => {
727
+ const newSet = new Set(prev);
728
+ if (newSet.has(menuKey)) {
729
+ newSet.delete(menuKey);
730
+ } else {
731
+ newSet.add(menuKey);
732
+ }
733
+ return newSet;
734
+ });
735
+ };
736
+ const isMenuOpen = (menuKey) => {
737
+ return openMenus.has(menuKey);
738
+ };
739
+ const handleMenuClick = (item, index, e) => {
740
+ if (item.isDropDown) {
741
+ e.preventDefault();
742
+ const menuKey = `menu-${index}`;
743
+ toggleMenu(menuKey);
744
+ setActiveMenuPath(`menu-${index}`);
728
745
  } else {
729
- dropDownIcon.classList.add("transition-all");
730
- dropDownIcon.classList.add("rotate-180");
746
+ setActiveMenuPath(`menu-${index}`);
747
+ if (item.onClick) {
748
+ item.onClick(e);
749
+ }
750
+ closeMobileMenu();
731
751
  }
732
- const optionsContainer = document.getElementById(
733
- `dropDownOptions-${index}${additionalKey ? `-${additionalKey}` : ""}${parentIndex ? `-${parentIndex}` : ""}`
734
- );
735
- if (!optionsContainer) return;
736
- optionsContainer.classList.add("transition-all");
737
- if (optionsContainer.classList.contains("max-h-0")) {
738
- optionsContainer.classList.remove("max-h-0");
739
- optionsContainer.classList.add("min-h-[50px]");
752
+ };
753
+ const handleSubMenuClick = (option, optionsIndex, parentIndex, e) => {
754
+ const parentMenuKey = `menu-${parentIndex}`;
755
+ setOpenMenus((prev) => {
756
+ const newSet = new Set(prev);
757
+ newSet.add(parentMenuKey);
758
+ return newSet;
759
+ });
760
+ if (option.isDropDown) {
761
+ e.preventDefault();
762
+ const menuKey = `menu-${parentIndex}-option-${optionsIndex}`;
763
+ toggleMenu(menuKey);
764
+ setActiveMenuPath(`menu-${parentIndex}-option-${optionsIndex}`);
740
765
  } else {
741
- optionsContainer.classList.remove("min-h-[50px]");
742
- optionsContainer.classList.add("max-h-0");
766
+ setActiveMenuPath(`menu-${parentIndex}-option-${optionsIndex}`);
767
+ if (option.onClick) {
768
+ option.onClick();
769
+ }
770
+ closeMobileMenu();
743
771
  }
744
772
  };
773
+ const handleSubSubMenuClick = (subOption, parentIndex, optionsIndex, e) => {
774
+ const parentMenuKey = `menu-${parentIndex}`;
775
+ const subMenuKey = `menu-${parentIndex}-option-${optionsIndex}`;
776
+ setOpenMenus((prev) => {
777
+ const newSet = new Set(prev);
778
+ newSet.add(parentMenuKey);
779
+ newSet.add(subMenuKey);
780
+ return newSet;
781
+ });
782
+ setActiveMenuPath(`menu-${parentIndex}-option-${optionsIndex}-sub-${subOption.label}`);
783
+ if (subOption.onClick) {
784
+ subOption.onClick();
785
+ }
786
+ closeMobileMenu();
787
+ };
745
788
  (0, import_react12.useEffect)(() => {
746
789
  const storedAuthData = localStorage.getItem("authData");
747
790
  if (storedAuthData) {
@@ -749,9 +792,172 @@ var AppSideBar = ({
749
792
  setAuthData(parseData);
750
793
  }
751
794
  }, [localStorage.getItem("authData")]);
795
+ const extractUrlFromOnClick = (onClick) => {
796
+ if (!onClick || typeof onClick !== "function") return null;
797
+ const funcString = onClick.toString();
798
+ let match = funcString.match(/window\.location\.href\s*=\s*`([^`]+)`/);
799
+ if (!match) {
800
+ match = funcString.match(/window\.location\.href\s*=\s*["']([^"']+)["']/);
801
+ }
802
+ if (match && match[1]) {
803
+ try {
804
+ if (match[1].startsWith("http://") || match[1].startsWith("https://")) {
805
+ const url = new URL(match[1]);
806
+ return {
807
+ pathname: url.pathname,
808
+ search: url.search,
809
+ fullPath: url.pathname + url.search
810
+ };
811
+ }
812
+ if (match[1].startsWith("/")) {
813
+ const url = new URL(match[1], window.location.origin);
814
+ return {
815
+ pathname: url.pathname,
816
+ search: url.search,
817
+ fullPath: url.pathname + url.search
818
+ };
819
+ }
820
+ return null;
821
+ } catch {
822
+ const pathMatch = match[1].match(/^([^?]+)(\?.*)?$/);
823
+ if (pathMatch) {
824
+ return {
825
+ pathname: pathMatch[1],
826
+ search: pathMatch[2] || "",
827
+ fullPath: match[1]
828
+ };
829
+ }
830
+ return null;
831
+ }
832
+ }
833
+ return null;
834
+ };
835
+ const currentUrlMatches = (menuUrlData, currentPath, currentSearch) => {
836
+ if (!menuUrlData || !currentPath) return false;
837
+ const normalizedMenuPath = menuUrlData.pathname.replace(/\/$/, "") || "/";
838
+ const normalizedCurrentPath = currentPath.replace(/\/$/, "") || "/";
839
+ if (normalizedMenuPath === "/orgselector" && normalizedCurrentPath === "/orgselector") {
840
+ const menuPathParam = new URLSearchParams(menuUrlData.search).get("path");
841
+ const currentPathParam = new URLSearchParams(currentSearch).get("path");
842
+ if (menuPathParam && currentPathParam) {
843
+ return menuPathParam === currentPathParam;
844
+ }
845
+ if (menuPathParam && !currentPathParam) {
846
+ return false;
847
+ }
848
+ if (!menuPathParam && currentPathParam) {
849
+ return false;
850
+ }
851
+ }
852
+ if (normalizedMenuPath === "/users/users" && normalizedCurrentPath === "/users/users") {
853
+ const menuParams = new URLSearchParams(menuUrlData.search);
854
+ const currentParams = new URLSearchParams(currentSearch);
855
+ const menuRole = menuParams.get("role");
856
+ const currentRole = currentParams.get("role");
857
+ if (menuRole && currentRole) {
858
+ return menuRole === currentRole;
859
+ }
860
+ if (menuRole && !currentRole || !menuRole && currentRole) {
861
+ return false;
862
+ }
863
+ return true;
864
+ }
865
+ if (normalizedMenuPath === normalizedCurrentPath) {
866
+ if (menuUrlData.search) {
867
+ const menuParams = new URLSearchParams(menuUrlData.search);
868
+ const currentParams = new URLSearchParams(currentSearch);
869
+ for (const [key, value] of menuParams.entries()) {
870
+ if (key === "auth") {
871
+ continue;
872
+ }
873
+ if (currentParams.get(key) !== value) {
874
+ return false;
875
+ }
876
+ }
877
+ return true;
878
+ }
879
+ return true;
880
+ }
881
+ if (normalizedCurrentPath.startsWith(normalizedMenuPath + "/")) {
882
+ return true;
883
+ }
884
+ return false;
885
+ };
752
886
  const navItemsLocal = navItems ?? navItemsConstant;
753
887
  const additionalItemsLocal = additionalItems ?? additionalItemsConstant;
754
888
  const sideBarLogoLocal = sideBarLogo ?? logo_white_default;
889
+ const detectAndSetActiveMenu = (0, import_react12.useCallback)(() => {
890
+ const currentPath = window.location.pathname;
891
+ const currentSearch = window.location.search;
892
+ const newOpenMenus = /* @__PURE__ */ new Set();
893
+ let foundActivePath = null;
894
+ navItemsLocal.forEach((item, index) => {
895
+ if (!item.isDropDown && item.onClick && typeof item.onClick === "function") {
896
+ const itemUrlData = extractUrlFromOnClick(item.onClick);
897
+ if (itemUrlData && currentUrlMatches(itemUrlData, currentPath, currentSearch)) {
898
+ foundActivePath = `menu-${index}`;
899
+ }
900
+ }
901
+ if (item.options && item.options.length > 0) {
902
+ item.options.forEach((option, optionsIndex) => {
903
+ if (option.onClick && typeof option.onClick === "function") {
904
+ const optionUrlData = extractUrlFromOnClick(option.onClick);
905
+ if (optionUrlData && currentUrlMatches(optionUrlData, currentPath, currentSearch)) {
906
+ const menuKey = `menu-${index}`;
907
+ newOpenMenus.add(menuKey);
908
+ foundActivePath = `menu-${index}-option-${optionsIndex}`;
909
+ if (option.options && option.options.length > 0) {
910
+ option.options.forEach((subOption, subIndex) => {
911
+ const subOptionUrlData = extractUrlFromOnClick(subOption.onClick);
912
+ if (subOptionUrlData && currentUrlMatches(subOptionUrlData, currentPath, currentSearch)) {
913
+ const subMenuKey = `menu-${index}-option-${optionsIndex}`;
914
+ newOpenMenus.add(subMenuKey);
915
+ foundActivePath = `menu-${index}-option-${optionsIndex}-sub-${subOption.label}`;
916
+ }
917
+ });
918
+ }
919
+ }
920
+ }
921
+ });
922
+ }
923
+ });
924
+ if (foundActivePath) {
925
+ setOpenMenus(newOpenMenus);
926
+ setActiveMenuPath(foundActivePath);
927
+ }
928
+ }, [navItemsLocal]);
929
+ const [currentUrl, setCurrentUrl] = (0, import_react12.useState)(
930
+ () => window.location.pathname + window.location.search
931
+ );
932
+ (0, import_react12.useEffect)(() => {
933
+ detectAndSetActiveMenu();
934
+ setCurrentUrl(window.location.pathname + window.location.search);
935
+ }, [detectAndSetActiveMenu]);
936
+ (0, import_react12.useEffect)(() => {
937
+ let lastUrl = window.location.pathname + window.location.search;
938
+ const handleLocationChange = () => {
939
+ const newUrl = window.location.pathname + window.location.search;
940
+ if (newUrl !== lastUrl) {
941
+ lastUrl = newUrl;
942
+ setCurrentUrl(newUrl);
943
+ detectAndSetActiveMenu();
944
+ }
945
+ };
946
+ window.addEventListener("popstate", handleLocationChange);
947
+ const checkInterval = setInterval(() => {
948
+ const newUrl = window.location.pathname + window.location.search;
949
+ if (newUrl !== lastUrl) {
950
+ handleLocationChange();
951
+ }
952
+ }, 250);
953
+ return () => {
954
+ window.removeEventListener("popstate", handleLocationChange);
955
+ clearInterval(checkInterval);
956
+ };
957
+ }, [detectAndSetActiveMenu]);
958
+ (0, import_react12.useEffect)(() => {
959
+ detectAndSetActiveMenu();
960
+ }, [currentUrl, detectAndSetActiveMenu]);
755
961
  const toggleMobileMenu = () => {
756
962
  setIsMobileMenuOpen(!isMobileMenuOpen);
757
963
  };
@@ -798,69 +1004,55 @@ var AppSideBar = ({
798
1004
  ))),
799
1005
  /* @__PURE__ */ import_react12.default.createElement("div", { className: "mb-4" }),
800
1006
  /* @__PURE__ */ import_react12.default.createElement("div", { className: "overflow-y-auto scrollbar-hide" }, /* @__PURE__ */ import_react12.default.createElement("div", null, navItemsLocal == null ? void 0 : navItemsLocal.map((item, index) => {
1007
+ const menuKey = `menu-${index}`;
1008
+ const isOpen = isMenuOpen(menuKey);
1009
+ const isActive = activeMenuPath === menuKey;
801
1010
  return /* @__PURE__ */ import_react12.default.createElement("div", { key: index, className: "" }, /* @__PURE__ */ import_react12.default.createElement(
802
1011
  "div",
803
1012
  {
804
- className: "flex items-center gap-3 p-2.5 hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-700 dark:text-[#f4f4f5cc] cursor-pointer rounded-lg ml-2 mr-2 transition-colors duration-200",
805
- onClick: (e) => {
806
- item.onClick && item.onClick(e);
807
- handleIconRotate(e, index);
808
- if (!item.isDropDown) {
809
- closeMobileMenu();
810
- }
811
- }
1013
+ className: `flex items-center gap-3 p-2.5 hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-700 dark:text-[#f4f4f5cc] cursor-pointer rounded-lg ml-2 mr-2 transition-colors duration-200 ${isActive ? "bg-[#f4f4f5] dark:bg-[#27272a]" : ""}`,
1014
+ onClick: (e) => handleMenuClick(item, index, e)
812
1015
  },
813
1016
  /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-primary" }, /* @__PURE__ */ import_react12.default.createElement(item.Icon, { width: 20, height: 20 })),
814
- /* @__PURE__ */ import_react12.default.createElement("span", { className: "font-medium text-[16px] text-[#000] dark:text-[#f4f4f5cc]" }, item.label),
815
- item.isDropDown && /* @__PURE__ */ import_react12.default.createElement("div", { className: `ml-auto transition-all delay-75` }, /* @__PURE__ */ import_react12.default.createElement(import_lucide_react6.ChevronDown, { width: 20, height: 20, className: "text-gray-500 dark:text-gray-400" }))
1017
+ /* @__PURE__ */ import_react12.default.createElement("span", { className: "font-medium text-base text-[#000] dark:text-[#f4f4f5cc]" }, item.label),
1018
+ item.isDropDown && /* @__PURE__ */ import_react12.default.createElement("div", { className: `ml-auto transition-all delay-75 ${isOpen ? "rotate-180" : ""}` }, /* @__PURE__ */ import_react12.default.createElement(import_lucide_react6.ChevronDown, { width: 20, height: 20, className: "text-gray-500 dark:text-gray-400" }))
816
1019
  ), item.options && item.options.length > 0 && /* @__PURE__ */ import_react12.default.createElement(
817
1020
  "div",
818
1021
  {
819
- className: "ml-[20px] max-h-0 overflow-hidden flex flex-col",
820
- id: `dropDownOptions-${index}`
1022
+ className: `ml-[20px] overflow-hidden flex flex-col transition-all duration-200 ${isOpen ? "max-h-[1000px] min-h-[50px]" : "max-h-0"}`
821
1023
  },
822
1024
  item.options.map((options, optionsIndex) => {
823
- return /* @__PURE__ */ import_react12.default.createElement("div", { className: "" }, /* @__PURE__ */ import_react12.default.createElement(
1025
+ const subMenuKey = `menu-${index}-option-${optionsIndex}`;
1026
+ const isSubMenuOpen = isMenuOpen(subMenuKey);
1027
+ const isSubActive = activeMenuPath === subMenuKey || (activeMenuPath == null ? void 0 : activeMenuPath.startsWith(`${subMenuKey}-`));
1028
+ return /* @__PURE__ */ import_react12.default.createElement("div", { key: optionsIndex, className: "" }, /* @__PURE__ */ import_react12.default.createElement(
824
1029
  "div",
825
1030
  {
826
- className: "flex items-center gap-3 py-2 px-3 ml-4 mr-2 hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-600 dark:text-[#a1a1aa] cursor-pointer rounded-md transition-colors duration-200",
827
- onClick: (e) => {
828
- options.onClick && options.onClick();
829
- options.isDropDown && handleIconRotate(
830
- e,
831
- optionsIndex,
832
- "subOption",
833
- index
834
- );
835
- if (!options.isDropDown) {
836
- closeMobileMenu();
837
- }
838
- }
1031
+ className: `flex items-center gap-3 py-2 px-3 ml-4 mr-2 hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-600 dark:text-[#a1a1aa] cursor-pointer rounded-md transition-colors duration-200 ${isSubActive ? "bg-[#f4f4f5] dark:bg-[#27272a]" : ""}`,
1032
+ onClick: (e) => handleSubMenuClick(options, optionsIndex, index, e)
839
1033
  },
840
1034
  /* @__PURE__ */ import_react12.default.createElement("div", null),
841
- /* @__PURE__ */ import_react12.default.createElement("span", { className: "font-medium text-[#3f3f46cc] text-sm dark:text-[#a1a1aa]" }, options.label),
1035
+ /* @__PURE__ */ import_react12.default.createElement("span", { className: "font-medium text-base text-[#3f3f46cc] dark:text-[#a1a1aa]" }, options.label),
842
1036
  options.isDropDown && /* @__PURE__ */ import_react12.default.createElement(
843
1037
  "div",
844
1038
  {
845
- className: `ml-auto transition-all delay-75`
1039
+ className: `ml-auto transition-all delay-75 ${isSubMenuOpen ? "rotate-180" : ""}`
846
1040
  },
847
1041
  /* @__PURE__ */ import_react12.default.createElement(import_lucide_react6.ChevronDown, { width: 18, height: 18, className: "text-gray-400 dark:text-gray-500" })
848
1042
  )
849
- ), options.options && options.options.length > 1 && /* @__PURE__ */ import_react12.default.createElement(
1043
+ ), options.options && options.options.length > 0 && /* @__PURE__ */ import_react12.default.createElement(
850
1044
  "div",
851
1045
  {
852
- className: "ml-[20px] max-h-0 overflow-hidden flex flex-col",
853
- id: `dropDownOptions-${optionsIndex}-subOption-${index}`
1046
+ className: `ml-[20px] overflow-hidden flex flex-col transition-all duration-200 ${isSubMenuOpen ? "max-h-[1000px] min-h-[50px]" : "max-h-0"}`
854
1047
  },
855
- options.options.map((subOption) => {
1048
+ options.options.map((subOption, subIndex) => {
1049
+ const isSubSubActive = activeMenuPath === `menu-${index}-option-${optionsIndex}-sub-${subOption.label}`;
856
1050
  return /* @__PURE__ */ import_react12.default.createElement(
857
1051
  "div",
858
1052
  {
859
- className: "py-1.5 px-3 rounded-md hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-500 dark:text-[#71717a] font-medium text-sm cursor-pointer ml-8 mr-2 transition-colors duration-200",
860
- onClick: (e) => {
861
- subOption.onClick && subOption.onClick();
862
- closeMobileMenu();
863
- }
1053
+ key: subIndex,
1054
+ className: `py-1.5 px-3 rounded-md hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-500 dark:text-[#71717a] font-medium text-base cursor-pointer ml-8 mr-2 transition-colors duration-200 ${isSubSubActive ? "bg-[#f4f4f5] dark:bg-[#27272a]" : ""}`,
1055
+ onClick: (e) => handleSubSubMenuClick(subOption, index, optionsIndex, e)
864
1056
  },
865
1057
  subOption.label
866
1058
  );
package/dist/index.mjs CHANGED
@@ -398,7 +398,7 @@ import {
398
398
  Menu,
399
399
  X
400
400
  } from "lucide-react";
401
- import React12, { useEffect, useState as useState3 } from "react";
401
+ import React12, { useEffect, useState as useState3, useCallback } from "react";
402
402
 
403
403
  // ConstantUI.js
404
404
  import {
@@ -680,6 +680,8 @@ var AppSideBar = ({
680
680
  const [authData, setAuthData] = useState3(null);
681
681
  const [selectedCountry, setSelectedCountry] = useState3("dubai");
682
682
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState3(false);
683
+ const [openMenus, setOpenMenus] = useState3(/* @__PURE__ */ new Set());
684
+ const [activeMenuPath, setActiveMenuPath] = useState3(null);
683
685
  const [currAppearance, setCurrAppearance] = useState3("light");
684
686
  useEffect(() => {
685
687
  setCurrAppearance("light");
@@ -691,28 +693,69 @@ var AppSideBar = ({
691
693
  { label: "Singapore", value: "singapore" },
692
694
  { label: "Qatar", value: "qatar" }
693
695
  ];
694
- const handleIconRotate = (e, index, additionalKey, parentIndex) => {
695
- let dropDownIcon = e.currentTarget.children[2];
696
- if (!dropDownIcon) return;
697
- if (dropDownIcon.classList.contains("rotate-180")) {
698
- dropDownIcon.classList.remove("rotate-180");
696
+ const toggleMenu = (menuKey) => {
697
+ setOpenMenus((prev) => {
698
+ const newSet = new Set(prev);
699
+ if (newSet.has(menuKey)) {
700
+ newSet.delete(menuKey);
701
+ } else {
702
+ newSet.add(menuKey);
703
+ }
704
+ return newSet;
705
+ });
706
+ };
707
+ const isMenuOpen = (menuKey) => {
708
+ return openMenus.has(menuKey);
709
+ };
710
+ const handleMenuClick = (item, index, e) => {
711
+ if (item.isDropDown) {
712
+ e.preventDefault();
713
+ const menuKey = `menu-${index}`;
714
+ toggleMenu(menuKey);
715
+ setActiveMenuPath(`menu-${index}`);
699
716
  } else {
700
- dropDownIcon.classList.add("transition-all");
701
- dropDownIcon.classList.add("rotate-180");
717
+ setActiveMenuPath(`menu-${index}`);
718
+ if (item.onClick) {
719
+ item.onClick(e);
720
+ }
721
+ closeMobileMenu();
702
722
  }
703
- const optionsContainer = document.getElementById(
704
- `dropDownOptions-${index}${additionalKey ? `-${additionalKey}` : ""}${parentIndex ? `-${parentIndex}` : ""}`
705
- );
706
- if (!optionsContainer) return;
707
- optionsContainer.classList.add("transition-all");
708
- if (optionsContainer.classList.contains("max-h-0")) {
709
- optionsContainer.classList.remove("max-h-0");
710
- optionsContainer.classList.add("min-h-[50px]");
723
+ };
724
+ const handleSubMenuClick = (option, optionsIndex, parentIndex, e) => {
725
+ const parentMenuKey = `menu-${parentIndex}`;
726
+ setOpenMenus((prev) => {
727
+ const newSet = new Set(prev);
728
+ newSet.add(parentMenuKey);
729
+ return newSet;
730
+ });
731
+ if (option.isDropDown) {
732
+ e.preventDefault();
733
+ const menuKey = `menu-${parentIndex}-option-${optionsIndex}`;
734
+ toggleMenu(menuKey);
735
+ setActiveMenuPath(`menu-${parentIndex}-option-${optionsIndex}`);
711
736
  } else {
712
- optionsContainer.classList.remove("min-h-[50px]");
713
- optionsContainer.classList.add("max-h-0");
737
+ setActiveMenuPath(`menu-${parentIndex}-option-${optionsIndex}`);
738
+ if (option.onClick) {
739
+ option.onClick();
740
+ }
741
+ closeMobileMenu();
714
742
  }
715
743
  };
744
+ const handleSubSubMenuClick = (subOption, parentIndex, optionsIndex, e) => {
745
+ const parentMenuKey = `menu-${parentIndex}`;
746
+ const subMenuKey = `menu-${parentIndex}-option-${optionsIndex}`;
747
+ setOpenMenus((prev) => {
748
+ const newSet = new Set(prev);
749
+ newSet.add(parentMenuKey);
750
+ newSet.add(subMenuKey);
751
+ return newSet;
752
+ });
753
+ setActiveMenuPath(`menu-${parentIndex}-option-${optionsIndex}-sub-${subOption.label}`);
754
+ if (subOption.onClick) {
755
+ subOption.onClick();
756
+ }
757
+ closeMobileMenu();
758
+ };
716
759
  useEffect(() => {
717
760
  const storedAuthData = localStorage.getItem("authData");
718
761
  if (storedAuthData) {
@@ -720,9 +763,172 @@ var AppSideBar = ({
720
763
  setAuthData(parseData);
721
764
  }
722
765
  }, [localStorage.getItem("authData")]);
766
+ const extractUrlFromOnClick = (onClick) => {
767
+ if (!onClick || typeof onClick !== "function") return null;
768
+ const funcString = onClick.toString();
769
+ let match = funcString.match(/window\.location\.href\s*=\s*`([^`]+)`/);
770
+ if (!match) {
771
+ match = funcString.match(/window\.location\.href\s*=\s*["']([^"']+)["']/);
772
+ }
773
+ if (match && match[1]) {
774
+ try {
775
+ if (match[1].startsWith("http://") || match[1].startsWith("https://")) {
776
+ const url = new URL(match[1]);
777
+ return {
778
+ pathname: url.pathname,
779
+ search: url.search,
780
+ fullPath: url.pathname + url.search
781
+ };
782
+ }
783
+ if (match[1].startsWith("/")) {
784
+ const url = new URL(match[1], window.location.origin);
785
+ return {
786
+ pathname: url.pathname,
787
+ search: url.search,
788
+ fullPath: url.pathname + url.search
789
+ };
790
+ }
791
+ return null;
792
+ } catch {
793
+ const pathMatch = match[1].match(/^([^?]+)(\?.*)?$/);
794
+ if (pathMatch) {
795
+ return {
796
+ pathname: pathMatch[1],
797
+ search: pathMatch[2] || "",
798
+ fullPath: match[1]
799
+ };
800
+ }
801
+ return null;
802
+ }
803
+ }
804
+ return null;
805
+ };
806
+ const currentUrlMatches = (menuUrlData, currentPath, currentSearch) => {
807
+ if (!menuUrlData || !currentPath) return false;
808
+ const normalizedMenuPath = menuUrlData.pathname.replace(/\/$/, "") || "/";
809
+ const normalizedCurrentPath = currentPath.replace(/\/$/, "") || "/";
810
+ if (normalizedMenuPath === "/orgselector" && normalizedCurrentPath === "/orgselector") {
811
+ const menuPathParam = new URLSearchParams(menuUrlData.search).get("path");
812
+ const currentPathParam = new URLSearchParams(currentSearch).get("path");
813
+ if (menuPathParam && currentPathParam) {
814
+ return menuPathParam === currentPathParam;
815
+ }
816
+ if (menuPathParam && !currentPathParam) {
817
+ return false;
818
+ }
819
+ if (!menuPathParam && currentPathParam) {
820
+ return false;
821
+ }
822
+ }
823
+ if (normalizedMenuPath === "/users/users" && normalizedCurrentPath === "/users/users") {
824
+ const menuParams = new URLSearchParams(menuUrlData.search);
825
+ const currentParams = new URLSearchParams(currentSearch);
826
+ const menuRole = menuParams.get("role");
827
+ const currentRole = currentParams.get("role");
828
+ if (menuRole && currentRole) {
829
+ return menuRole === currentRole;
830
+ }
831
+ if (menuRole && !currentRole || !menuRole && currentRole) {
832
+ return false;
833
+ }
834
+ return true;
835
+ }
836
+ if (normalizedMenuPath === normalizedCurrentPath) {
837
+ if (menuUrlData.search) {
838
+ const menuParams = new URLSearchParams(menuUrlData.search);
839
+ const currentParams = new URLSearchParams(currentSearch);
840
+ for (const [key, value] of menuParams.entries()) {
841
+ if (key === "auth") {
842
+ continue;
843
+ }
844
+ if (currentParams.get(key) !== value) {
845
+ return false;
846
+ }
847
+ }
848
+ return true;
849
+ }
850
+ return true;
851
+ }
852
+ if (normalizedCurrentPath.startsWith(normalizedMenuPath + "/")) {
853
+ return true;
854
+ }
855
+ return false;
856
+ };
723
857
  const navItemsLocal = navItems ?? navItemsConstant;
724
858
  const additionalItemsLocal = additionalItems ?? additionalItemsConstant;
725
859
  const sideBarLogoLocal = sideBarLogo ?? logo_white_default;
860
+ const detectAndSetActiveMenu = useCallback(() => {
861
+ const currentPath = window.location.pathname;
862
+ const currentSearch = window.location.search;
863
+ const newOpenMenus = /* @__PURE__ */ new Set();
864
+ let foundActivePath = null;
865
+ navItemsLocal.forEach((item, index) => {
866
+ if (!item.isDropDown && item.onClick && typeof item.onClick === "function") {
867
+ const itemUrlData = extractUrlFromOnClick(item.onClick);
868
+ if (itemUrlData && currentUrlMatches(itemUrlData, currentPath, currentSearch)) {
869
+ foundActivePath = `menu-${index}`;
870
+ }
871
+ }
872
+ if (item.options && item.options.length > 0) {
873
+ item.options.forEach((option, optionsIndex) => {
874
+ if (option.onClick && typeof option.onClick === "function") {
875
+ const optionUrlData = extractUrlFromOnClick(option.onClick);
876
+ if (optionUrlData && currentUrlMatches(optionUrlData, currentPath, currentSearch)) {
877
+ const menuKey = `menu-${index}`;
878
+ newOpenMenus.add(menuKey);
879
+ foundActivePath = `menu-${index}-option-${optionsIndex}`;
880
+ if (option.options && option.options.length > 0) {
881
+ option.options.forEach((subOption, subIndex) => {
882
+ const subOptionUrlData = extractUrlFromOnClick(subOption.onClick);
883
+ if (subOptionUrlData && currentUrlMatches(subOptionUrlData, currentPath, currentSearch)) {
884
+ const subMenuKey = `menu-${index}-option-${optionsIndex}`;
885
+ newOpenMenus.add(subMenuKey);
886
+ foundActivePath = `menu-${index}-option-${optionsIndex}-sub-${subOption.label}`;
887
+ }
888
+ });
889
+ }
890
+ }
891
+ }
892
+ });
893
+ }
894
+ });
895
+ if (foundActivePath) {
896
+ setOpenMenus(newOpenMenus);
897
+ setActiveMenuPath(foundActivePath);
898
+ }
899
+ }, [navItemsLocal]);
900
+ const [currentUrl, setCurrentUrl] = useState3(
901
+ () => window.location.pathname + window.location.search
902
+ );
903
+ useEffect(() => {
904
+ detectAndSetActiveMenu();
905
+ setCurrentUrl(window.location.pathname + window.location.search);
906
+ }, [detectAndSetActiveMenu]);
907
+ useEffect(() => {
908
+ let lastUrl = window.location.pathname + window.location.search;
909
+ const handleLocationChange = () => {
910
+ const newUrl = window.location.pathname + window.location.search;
911
+ if (newUrl !== lastUrl) {
912
+ lastUrl = newUrl;
913
+ setCurrentUrl(newUrl);
914
+ detectAndSetActiveMenu();
915
+ }
916
+ };
917
+ window.addEventListener("popstate", handleLocationChange);
918
+ const checkInterval = setInterval(() => {
919
+ const newUrl = window.location.pathname + window.location.search;
920
+ if (newUrl !== lastUrl) {
921
+ handleLocationChange();
922
+ }
923
+ }, 250);
924
+ return () => {
925
+ window.removeEventListener("popstate", handleLocationChange);
926
+ clearInterval(checkInterval);
927
+ };
928
+ }, [detectAndSetActiveMenu]);
929
+ useEffect(() => {
930
+ detectAndSetActiveMenu();
931
+ }, [currentUrl, detectAndSetActiveMenu]);
726
932
  const toggleMobileMenu = () => {
727
933
  setIsMobileMenuOpen(!isMobileMenuOpen);
728
934
  };
@@ -769,69 +975,55 @@ var AppSideBar = ({
769
975
  ))),
770
976
  /* @__PURE__ */ React12.createElement("div", { className: "mb-4" }),
771
977
  /* @__PURE__ */ React12.createElement("div", { className: "overflow-y-auto scrollbar-hide" }, /* @__PURE__ */ React12.createElement("div", null, navItemsLocal == null ? void 0 : navItemsLocal.map((item, index) => {
978
+ const menuKey = `menu-${index}`;
979
+ const isOpen = isMenuOpen(menuKey);
980
+ const isActive = activeMenuPath === menuKey;
772
981
  return /* @__PURE__ */ React12.createElement("div", { key: index, className: "" }, /* @__PURE__ */ React12.createElement(
773
982
  "div",
774
983
  {
775
- className: "flex items-center gap-3 p-2.5 hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-700 dark:text-[#f4f4f5cc] cursor-pointer rounded-lg ml-2 mr-2 transition-colors duration-200",
776
- onClick: (e) => {
777
- item.onClick && item.onClick(e);
778
- handleIconRotate(e, index);
779
- if (!item.isDropDown) {
780
- closeMobileMenu();
781
- }
782
- }
984
+ className: `flex items-center gap-3 p-2.5 hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-700 dark:text-[#f4f4f5cc] cursor-pointer rounded-lg ml-2 mr-2 transition-colors duration-200 ${isActive ? "bg-[#f4f4f5] dark:bg-[#27272a]" : ""}`,
985
+ onClick: (e) => handleMenuClick(item, index, e)
783
986
  },
784
987
  /* @__PURE__ */ React12.createElement("div", { className: "text-primary" }, /* @__PURE__ */ React12.createElement(item.Icon, { width: 20, height: 20 })),
785
- /* @__PURE__ */ React12.createElement("span", { className: "font-medium text-[16px] text-[#000] dark:text-[#f4f4f5cc]" }, item.label),
786
- item.isDropDown && /* @__PURE__ */ React12.createElement("div", { className: `ml-auto transition-all delay-75` }, /* @__PURE__ */ React12.createElement(ChevronDown3, { width: 20, height: 20, className: "text-gray-500 dark:text-gray-400" }))
988
+ /* @__PURE__ */ React12.createElement("span", { className: "font-medium text-base text-[#000] dark:text-[#f4f4f5cc]" }, item.label),
989
+ item.isDropDown && /* @__PURE__ */ React12.createElement("div", { className: `ml-auto transition-all delay-75 ${isOpen ? "rotate-180" : ""}` }, /* @__PURE__ */ React12.createElement(ChevronDown3, { width: 20, height: 20, className: "text-gray-500 dark:text-gray-400" }))
787
990
  ), item.options && item.options.length > 0 && /* @__PURE__ */ React12.createElement(
788
991
  "div",
789
992
  {
790
- className: "ml-[20px] max-h-0 overflow-hidden flex flex-col",
791
- id: `dropDownOptions-${index}`
993
+ className: `ml-[20px] overflow-hidden flex flex-col transition-all duration-200 ${isOpen ? "max-h-[1000px] min-h-[50px]" : "max-h-0"}`
792
994
  },
793
995
  item.options.map((options, optionsIndex) => {
794
- return /* @__PURE__ */ React12.createElement("div", { className: "" }, /* @__PURE__ */ React12.createElement(
996
+ const subMenuKey = `menu-${index}-option-${optionsIndex}`;
997
+ const isSubMenuOpen = isMenuOpen(subMenuKey);
998
+ const isSubActive = activeMenuPath === subMenuKey || (activeMenuPath == null ? void 0 : activeMenuPath.startsWith(`${subMenuKey}-`));
999
+ return /* @__PURE__ */ React12.createElement("div", { key: optionsIndex, className: "" }, /* @__PURE__ */ React12.createElement(
795
1000
  "div",
796
1001
  {
797
- className: "flex items-center gap-3 py-2 px-3 ml-4 mr-2 hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-600 dark:text-[#a1a1aa] cursor-pointer rounded-md transition-colors duration-200",
798
- onClick: (e) => {
799
- options.onClick && options.onClick();
800
- options.isDropDown && handleIconRotate(
801
- e,
802
- optionsIndex,
803
- "subOption",
804
- index
805
- );
806
- if (!options.isDropDown) {
807
- closeMobileMenu();
808
- }
809
- }
1002
+ className: `flex items-center gap-3 py-2 px-3 ml-4 mr-2 hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-600 dark:text-[#a1a1aa] cursor-pointer rounded-md transition-colors duration-200 ${isSubActive ? "bg-[#f4f4f5] dark:bg-[#27272a]" : ""}`,
1003
+ onClick: (e) => handleSubMenuClick(options, optionsIndex, index, e)
810
1004
  },
811
1005
  /* @__PURE__ */ React12.createElement("div", null),
812
- /* @__PURE__ */ React12.createElement("span", { className: "font-medium text-[#3f3f46cc] text-sm dark:text-[#a1a1aa]" }, options.label),
1006
+ /* @__PURE__ */ React12.createElement("span", { className: "font-medium text-base text-[#3f3f46cc] dark:text-[#a1a1aa]" }, options.label),
813
1007
  options.isDropDown && /* @__PURE__ */ React12.createElement(
814
1008
  "div",
815
1009
  {
816
- className: `ml-auto transition-all delay-75`
1010
+ className: `ml-auto transition-all delay-75 ${isSubMenuOpen ? "rotate-180" : ""}`
817
1011
  },
818
1012
  /* @__PURE__ */ React12.createElement(ChevronDown3, { width: 18, height: 18, className: "text-gray-400 dark:text-gray-500" })
819
1013
  )
820
- ), options.options && options.options.length > 1 && /* @__PURE__ */ React12.createElement(
1014
+ ), options.options && options.options.length > 0 && /* @__PURE__ */ React12.createElement(
821
1015
  "div",
822
1016
  {
823
- className: "ml-[20px] max-h-0 overflow-hidden flex flex-col",
824
- id: `dropDownOptions-${optionsIndex}-subOption-${index}`
1017
+ className: `ml-[20px] overflow-hidden flex flex-col transition-all duration-200 ${isSubMenuOpen ? "max-h-[1000px] min-h-[50px]" : "max-h-0"}`
825
1018
  },
826
- options.options.map((subOption) => {
1019
+ options.options.map((subOption, subIndex) => {
1020
+ const isSubSubActive = activeMenuPath === `menu-${index}-option-${optionsIndex}-sub-${subOption.label}`;
827
1021
  return /* @__PURE__ */ React12.createElement(
828
1022
  "div",
829
1023
  {
830
- className: "py-1.5 px-3 rounded-md hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-500 dark:text-[#71717a] font-medium text-sm cursor-pointer ml-8 mr-2 transition-colors duration-200",
831
- onClick: (e) => {
832
- subOption.onClick && subOption.onClick();
833
- closeMobileMenu();
834
- }
1024
+ key: subIndex,
1025
+ className: `py-1.5 px-3 rounded-md hover:bg-[#f4f4f5] dark:hover:bg-[#27272a] text-gray-500 dark:text-[#71717a] font-medium text-base cursor-pointer ml-8 mr-2 transition-colors duration-200 ${isSubSubActive ? "bg-[#f4f4f5] dark:bg-[#27272a]" : ""}`,
1026
+ onClick: (e) => handleSubSubMenuClick(subOption, index, optionsIndex, e)
835
1027
  },
836
1028
  subOption.label
837
1029
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jett.admin.npmpackage",
3
- "version": "1.0.91",
3
+ "version": "1.0.93",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "exports": {