@axzydev/axzy_ui_system 1.4.3 → 1.4.4

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.d.cts CHANGED
@@ -3100,8 +3100,19 @@ interface ITSidebarProps {
3100
3100
  navigationItems: ITNavigationItem[];
3101
3101
  /** Whether the sidebar is collapsed to icon-only mode. */
3102
3102
  isCollapsed?: boolean;
3103
- /** Callback when the user toggles collapse via the toggle button. */
3103
+ /**
3104
+ * Callback that flips `isCollapsed`. `ITLayout` calls it from the top bar's
3105
+ * menu button when `expandOnHover` is `false`; the sidebar itself calls it
3106
+ * when a collapsed parent item is clicked, so its submenu can be shown.
3107
+ */
3104
3108
  onToggleCollapse?: () => void;
3109
+ /**
3110
+ * How the collapsed rail opens. `true`: it expands over the content while
3111
+ * the pointer is on it (no button). `false`: it stays an icon-only rail —
3112
+ * the item name shows in a tooltip on hover — and it only opens through
3113
+ * `onToggleCollapse` (the top bar's menu button in `ITLayout`). @default true
3114
+ */
3115
+ expandOnHover?: boolean;
3105
3116
  /** Force sidebar visible on mobile breakpoints. */
3106
3117
  visibleOnMobile?: boolean;
3107
3118
  /** Callback when a top-level navigation item is clicked. Receives the item. */
@@ -3161,7 +3172,7 @@ interface ITSidebarProps {
3161
3172
  * />
3162
3173
  * ```
3163
3174
  */
3164
- declare function ITSidebar({ navigationItems, isCollapsed, className, visibleOnMobile, onItemClick, onSubItemClick, subitemConnector, header, notification, brand, }: ITSidebarProps): react_jsx_runtime.JSX.Element;
3175
+ declare function ITSidebar({ navigationItems, isCollapsed, className, visibleOnMobile, onItemClick, onSubItemClick, subitemConnector, header, notification, brand, onToggleCollapse, expandOnHover, }: ITSidebarProps): react_jsx_runtime.JSX.Element;
3165
3176
 
3166
3177
  /** Skeleton shape variant: "text" (line) | "circular" (avatar/icon) | "rectangular" (card/image). */
3167
3178
  type SkeletonVariant = "text" | "circular" | "rectangular";
@@ -3782,6 +3793,12 @@ interface ITTopBarProps {
3782
3793
  showMobileMenuButton?: boolean;
3783
3794
  /** Callback fired when the mobile menu toggle button is clicked. */
3784
3795
  onToggleMobileMenu?: () => void;
3796
+ /**
3797
+ * Keeps the menu toggle button visible from the `lg` breakpoint up as well
3798
+ * (it is mobile-only by default). `ITLayout` turns it on when the sidebar
3799
+ * collapses by button instead of hover (`sidebar.expandOnHover === false`). @default false
3800
+ */
3801
+ showDesktopMenuButton?: boolean;
3785
3802
  /**
3786
3803
  * Hides the logo and `logoText` from the `lg` breakpoint up and left-aligns
3787
3804
  * `centerContent`. Use it when the brand already lives somewhere else (e.g.
package/dist/index.d.ts CHANGED
@@ -3100,8 +3100,19 @@ interface ITSidebarProps {
3100
3100
  navigationItems: ITNavigationItem[];
3101
3101
  /** Whether the sidebar is collapsed to icon-only mode. */
3102
3102
  isCollapsed?: boolean;
3103
- /** Callback when the user toggles collapse via the toggle button. */
3103
+ /**
3104
+ * Callback that flips `isCollapsed`. `ITLayout` calls it from the top bar's
3105
+ * menu button when `expandOnHover` is `false`; the sidebar itself calls it
3106
+ * when a collapsed parent item is clicked, so its submenu can be shown.
3107
+ */
3104
3108
  onToggleCollapse?: () => void;
3109
+ /**
3110
+ * How the collapsed rail opens. `true`: it expands over the content while
3111
+ * the pointer is on it (no button). `false`: it stays an icon-only rail —
3112
+ * the item name shows in a tooltip on hover — and it only opens through
3113
+ * `onToggleCollapse` (the top bar's menu button in `ITLayout`). @default true
3114
+ */
3115
+ expandOnHover?: boolean;
3105
3116
  /** Force sidebar visible on mobile breakpoints. */
3106
3117
  visibleOnMobile?: boolean;
3107
3118
  /** Callback when a top-level navigation item is clicked. Receives the item. */
@@ -3161,7 +3172,7 @@ interface ITSidebarProps {
3161
3172
  * />
3162
3173
  * ```
3163
3174
  */
3164
- declare function ITSidebar({ navigationItems, isCollapsed, className, visibleOnMobile, onItemClick, onSubItemClick, subitemConnector, header, notification, brand, }: ITSidebarProps): react_jsx_runtime.JSX.Element;
3175
+ declare function ITSidebar({ navigationItems, isCollapsed, className, visibleOnMobile, onItemClick, onSubItemClick, subitemConnector, header, notification, brand, onToggleCollapse, expandOnHover, }: ITSidebarProps): react_jsx_runtime.JSX.Element;
3165
3176
 
3166
3177
  /** Skeleton shape variant: "text" (line) | "circular" (avatar/icon) | "rectangular" (card/image). */
3167
3178
  type SkeletonVariant = "text" | "circular" | "rectangular";
@@ -3782,6 +3793,12 @@ interface ITTopBarProps {
3782
3793
  showMobileMenuButton?: boolean;
3783
3794
  /** Callback fired when the mobile menu toggle button is clicked. */
3784
3795
  onToggleMobileMenu?: () => void;
3796
+ /**
3797
+ * Keeps the menu toggle button visible from the `lg` breakpoint up as well
3798
+ * (it is mobile-only by default). `ITLayout` turns it on when the sidebar
3799
+ * collapses by button instead of hover (`sidebar.expandOnHover === false`). @default false
3800
+ */
3801
+ showDesktopMenuButton?: boolean;
3785
3802
  /**
3786
3803
  * Hides the logo and `logoText` from the `lg` breakpoint up and left-aligns
3787
3804
  * `centerContent`. Use it when the brand already lives somewhere else (e.g.
package/dist/index.js CHANGED
@@ -7606,7 +7606,9 @@ function ITSidebar({
7606
7606
  subitemConnector = "dot",
7607
7607
  header,
7608
7608
  notification,
7609
- brand
7609
+ brand,
7610
+ onToggleCollapse,
7611
+ expandOnHover = true
7610
7612
  }) {
7611
7613
  const flat = useITFlatAppearance();
7612
7614
  const [expandedItems, setExpandedItems] = useState27(/* @__PURE__ */ new Set());
@@ -7662,6 +7664,9 @@ function ITSidebar({
7662
7664
  });
7663
7665
  }
7664
7666
  }, [navigationItems]);
7667
+ const isSidebarCollapsed = visibleOnMobile ? false : isCollapsed && !(expandOnHover && isHovering);
7668
+ const sidebarWidth = isSidebarCollapsed ? flat ? "w-[72px]" : "w-[88px]" : flat ? "w-[248px]" : "w-[280px]";
7669
+ const fixedRail = isSidebarCollapsed && !expandOnHover;
7665
7670
  const toggleExpanded = (itemId) => {
7666
7671
  const newExpanded = new Set(expandedItems);
7667
7672
  if (newExpanded.has(itemId)) newExpanded.delete(itemId);
@@ -7670,14 +7675,17 @@ function ITSidebar({
7670
7675
  };
7671
7676
  const handleItemClick = (item) => {
7672
7677
  if (item.subitems && item.subitems.length > 0) {
7673
- toggleExpanded(item.id);
7678
+ if (isSidebarCollapsed && !expandOnHover) {
7679
+ setExpandedItems((prev) => new Set(prev).add(item.id));
7680
+ onToggleCollapse?.();
7681
+ } else {
7682
+ toggleExpanded(item.id);
7683
+ }
7674
7684
  } else {
7675
7685
  if (item.action) item.action();
7676
7686
  if (onItemClick) onItemClick(item);
7677
7687
  }
7678
7688
  };
7679
- const isSidebarCollapsed = visibleOnMobile ? false : !isHovering && isCollapsed;
7680
- const sidebarWidth = isSidebarCollapsed ? "w-[88px]" : flat ? "w-[248px]" : "w-[280px]";
7681
7689
  const renderSubItem = (subitem) => /* @__PURE__ */ jsx56("li", { className: "relative", children: /* @__PURE__ */ jsxs43(
7682
7690
  "button",
7683
7691
  {
@@ -7690,7 +7698,7 @@ function ITSidebar({
7690
7698
  style: {
7691
7699
  color: subitem.isActive ? "var(--it-sidebar-active-color, var(--color-secondary-900))" : "var(--it-sidebar-label-color, var(--color-secondary-600))",
7692
7700
  backgroundColor: subitem.isActive ? "var(--it-sidebar-active-bg, var(--color-secondary-50))" : "transparent",
7693
- fontSize: "0.78rem",
7701
+ fontSize: flat ? "0.84rem" : "0.78rem",
7694
7702
  fontWeight: subitem.isActive ? 600 : 500,
7695
7703
  letterSpacing: "0.01em",
7696
7704
  marginLeft: subitemConnector === "|" ? "-1px" : "0"
@@ -7708,7 +7716,7 @@ function ITSidebar({
7708
7716
  }
7709
7717
  },
7710
7718
  children: [
7711
- subitem.isActive && subitemConnector === "|" && /* @__PURE__ */ jsx56(
7719
+ subitem.isActive && subitemConnector === "|" && !flat && /* @__PURE__ */ jsx56(
7712
7720
  "div",
7713
7721
  {
7714
7722
  className: "absolute left-0 top-1/3 bottom-1/3 w-[2.5px] rounded-r-full transition-all",
@@ -7872,10 +7880,11 @@ function ITSidebar({
7872
7880
  ),
7873
7881
  header && !isSidebarCollapsed && /* @__PURE__ */ jsx56("div", { className: "px-4 pt-4 pb-1 flex-shrink-0", children: header }),
7874
7882
  notification && /* @__PURE__ */ jsx56("div", { className: "px-4 pt-3 flex-shrink-0", children: renderNotification() }),
7875
- /* @__PURE__ */ jsx56("nav", { "aria-label": "Componentes de la librer\xEDa", className: "flex-1 py-4 overflow-y-auto overflow-x-hidden custom-scrollbar px-4", children: /* @__PURE__ */ jsx56("ul", { className: "space-y-1", children: navigationItems.map((item) => {
7883
+ /* @__PURE__ */ jsx56("nav", { "aria-label": "Componentes de la librer\xEDa", className: `flex-1 py-4 custom-scrollbar ${fixedRail ? "overflow-visible" : "overflow-y-auto overflow-x-hidden"} ${flat && isSidebarCollapsed ? "px-3" : "px-4"}`, children: /* @__PURE__ */ jsx56("ul", { className: "space-y-1", children: navigationItems.map((item) => {
7876
7884
  const hasSubmenu = !!item.subitems && item.subitems.length > 0;
7877
7885
  const submenuId = `it-sidebar-submenu-${item.id}`;
7878
7886
  const { className: badgeClassName, ...badgeRest } = item.badgeProps ?? {};
7887
+ const active = !!item.isActive && !(flat && hasSubmenu && !isSidebarCollapsed);
7879
7888
  return /* @__PURE__ */ jsxs43("li", { className: "relative group/navitem", children: [
7880
7889
  /* @__PURE__ */ jsxs43(
7881
7890
  "div",
@@ -7888,18 +7897,18 @@ function ITSidebar({
7888
7897
  className: `flex items-center cursor-pointer
7889
7898
  transition-all duration-300 ease-[cubic-bezier(0.2,0,0,1)]
7890
7899
  rounded-xl relative overflow-visible
7891
- ${isSidebarCollapsed ? "justify-center p-2 mb-1" : "justify-between px-3 py-2 mb-0.5"}
7900
+ ${isSidebarCollapsed ? flat ? "justify-center h-10 mb-1" : "justify-center p-2 mb-1" : "justify-between px-3 py-2 mb-0.5"}
7892
7901
  `,
7893
7902
  style: {
7894
- backgroundColor: item.isActive ? "var(--it-sidebar-active-bg, var(--color-secondary-50))" : "transparent",
7895
- boxShadow: item.isActive && !flat ? "var(--shadow-xs)" : "none",
7896
- border: item.isActive && !flat ? "1px solid var(--it-sidebar-border, var(--color-secondary-200))" : "1px solid transparent"
7903
+ backgroundColor: active ? "var(--it-sidebar-active-bg, var(--color-secondary-50))" : "transparent",
7904
+ boxShadow: active && !flat ? "var(--shadow-xs)" : "none",
7905
+ border: active && !flat ? "1px solid var(--it-sidebar-border, var(--color-secondary-200))" : "1px solid transparent"
7897
7906
  },
7898
7907
  onMouseEnter: (e) => {
7899
- if (!item.isActive) e.currentTarget.style.backgroundColor = "var(--it-sidebar-hover-bg, var(--color-secondary-100))";
7908
+ if (!active) e.currentTarget.style.backgroundColor = "var(--it-sidebar-hover-bg, var(--color-secondary-100))";
7900
7909
  },
7901
7910
  onMouseLeave: (e) => {
7902
- if (!item.isActive) e.currentTarget.style.backgroundColor = "transparent";
7911
+ if (!active) e.currentTarget.style.backgroundColor = "transparent";
7903
7912
  },
7904
7913
  onClick: () => handleItemClick(item),
7905
7914
  onKeyDown: (e) => {
@@ -7909,7 +7918,7 @@ function ITSidebar({
7909
7918
  }
7910
7919
  },
7911
7920
  children: [
7912
- item.isActive && !isSidebarCollapsed && !flat && /* @__PURE__ */ jsx56(
7921
+ active && !isSidebarCollapsed && !flat && /* @__PURE__ */ jsx56(
7913
7922
  "div",
7914
7923
  {
7915
7924
  className: "absolute left-0 top-1/4 bottom-1/4 w-[3px] rounded-r-full transition-all",
@@ -7922,10 +7931,10 @@ function ITSidebar({
7922
7931
  {
7923
7932
  className: `transition-all duration-300 flex-shrink-0 flex items-center justify-center`,
7924
7933
  style: {
7925
- color: item.isActive ? "var(--it-sidebar-active-icon, var(--color-primary-500))" : "var(--it-sidebar-icon-color, #9ca3af)",
7926
- opacity: item.isActive ? 1 : 0.8,
7927
- fontSize: flat ? "1rem" : item.isActive ? "1.12rem" : "1.05rem",
7928
- filter: item.isActive && !flat ? "drop-shadow(0 0 8px rgba(255,255,255,0.2))" : "none"
7934
+ color: active ? "var(--it-sidebar-active-icon, var(--color-primary-500))" : "var(--it-sidebar-icon-color, #9ca3af)",
7935
+ opacity: active ? 1 : 0.8,
7936
+ fontSize: flat ? "1rem" : active ? "1.12rem" : "1.05rem",
7937
+ filter: active && !flat ? "drop-shadow(0 0 8px rgba(255,255,255,0.2))" : "none"
7929
7938
  },
7930
7939
  children: item.icon
7931
7940
  }
@@ -7936,9 +7945,9 @@ function ITSidebar({
7936
7945
  as: "span",
7937
7946
  className: `transition-all duration-300 truncate tracking-wide`,
7938
7947
  style: {
7939
- color: item.isActive ? "var(--it-sidebar-active-color, #ffffff)" : "var(--it-sidebar-label-color, var(--color-secondary-300))",
7948
+ color: active ? "var(--it-sidebar-active-color, #ffffff)" : "var(--it-sidebar-label-color, var(--color-secondary-300))",
7940
7949
  fontSize: flat ? "0.875rem" : "0.8rem",
7941
- fontWeight: item.isActive ? "600" : "500"
7950
+ fontWeight: active ? "600" : "500"
7942
7951
  },
7943
7952
  children: item.label
7944
7953
  }
@@ -7948,7 +7957,7 @@ function ITSidebar({
7948
7957
  "div",
7949
7958
  {
7950
7959
  className: `flex-shrink-0 transition-transform duration-300 ease-[cubic-bezier(0.2,0,0,1)] ${expandedItems.has(item.id) ? "rotate-180" : ""}`,
7951
- style: { color: item.isActive ? "var(--it-sidebar-active-color, var(--color-secondary-900))" : "var(--it-sidebar-icon-color, var(--color-secondary-500))", opacity: 0.7 },
7960
+ style: { color: active ? "var(--it-sidebar-active-color, var(--color-secondary-900))" : "var(--it-sidebar-icon-color, var(--color-secondary-500))", opacity: 0.7 },
7952
7961
  children: /* @__PURE__ */ jsx56(FaChevronDown4, { className: "w-3 h-3" })
7953
7962
  }
7954
7963
  ),
@@ -7969,7 +7978,21 @@ function ITSidebar({
7969
7978
  ]
7970
7979
  }
7971
7980
  ),
7972
- isSidebarCollapsed && /* @__PURE__ */ jsxs43(
7981
+ isSidebarCollapsed && flat && /* @__PURE__ */ jsx56(
7982
+ "div",
7983
+ {
7984
+ role: "tooltip",
7985
+ className: "absolute left-full top-1/2 -translate-y-1/2 ml-3 px-2.5 py-1.5 rounded-lg whitespace-nowrap opacity-0 invisible group-hover/navitem:opacity-100 group-hover/navitem:visible transition-opacity duration-150 pointer-events-none z-[70]",
7986
+ style: {
7987
+ backgroundColor: "var(--it-sidebar-tooltip-bg, var(--color-secondary-900))",
7988
+ color: "var(--it-sidebar-tooltip-color, #ffffff)",
7989
+ fontSize: "0.78rem",
7990
+ fontWeight: 500
7991
+ },
7992
+ children: item.label
7993
+ }
7994
+ ),
7995
+ isSidebarCollapsed && !flat && /* @__PURE__ */ jsxs43(
7973
7996
  "div",
7974
7997
  {
7975
7998
  className: "absolute left-full top-0 ml-4 rounded-2xl opacity-0 invisible group-hover/navitem:opacity-100 group-hover/navitem:visible transition-all duration-300 pointer-events-none z-[70] min-w-[220px] overflow-hidden -translate-x-2 group-hover/navitem:translate-x-0 shadow-[0_10px_40px_-10px_rgba(0,0,0,0.15)]",
@@ -8011,7 +8034,7 @@ function ITSidebar({
8011
8034
  !isSidebarCollapsed && item.subitems && item.subitems.length > 0 && /* @__PURE__ */ jsx56("div", { id: submenuId, role: "group", "aria-label": item.label, className: `overflow-hidden transition-all duration-400 ease-[cubic-bezier(0.2,0,0,1)] ${expandedItems.has(item.id) ? "max-h-[1000px] opacity-100 mt-1" : "max-h-0 opacity-0"}`, children: /* @__PURE__ */ jsx56(
8012
8035
  "ul",
8013
8036
  {
8014
- className: "ml-4 flex flex-col gap-0 py-0.5",
8037
+ className: `${flat && subitemConnector === "|" ? "ml-[21px] pl-2" : "ml-4"} flex flex-col gap-0 py-0.5`,
8015
8038
  style: {
8016
8039
  borderLeft: subitemConnector === "|" ? "1px solid var(--it-sidebar-border, var(--color-secondary-200))" : "none"
8017
8040
  },
@@ -10025,7 +10048,8 @@ function ITTopBar({
10025
10048
  onToggleMobileMenu,
10026
10049
  navItems,
10027
10050
  onNavItemClick,
10028
- hideBrandOnDesktop = false
10051
+ hideBrandOnDesktop = false,
10052
+ showDesktopMenuButton = false
10029
10053
  }) {
10030
10054
  const flat = useITFlatAppearance();
10031
10055
  const initials = (userMenu?.userName ?? "").trim().split(/\s+/).slice(0, 2).map((word) => word.charAt(0).toUpperCase()).join("");
@@ -10046,7 +10070,9 @@ function ITTopBar({
10046
10070
  showMobileMenuButton && /* @__PURE__ */ jsx68(
10047
10071
  "button",
10048
10072
  {
10049
- className: "lg:hidden p-2.5 rounded-xl transition-colors duration-200",
10073
+ type: "button",
10074
+ "aria-label": "Men\xFA",
10075
+ className: `${showDesktopMenuButton ? "" : "lg:hidden"} p-2.5 -ml-2.5 rounded-xl transition-colors duration-200`,
10050
10076
  style: {
10051
10077
  color: "var(--it-topbar-icon, #64748b)"
10052
10078
  },
@@ -10224,7 +10250,12 @@ function ITLayout({
10224
10250
  const handleToggleCollapse = isControlled ? sidebar.onToggleCollapse ?? (() => {
10225
10251
  }) : () => setInternalCollapsed((v) => !v);
10226
10252
  const layoutTokens = theme.layout;
10227
- const reservedWidth = desktopCollapsed ? "w-[88px]" : flat ? "w-[248px]" : "w-[280px]";
10253
+ const reservedWidth = desktopCollapsed ? flat ? "w-[72px]" : "w-[88px]" : flat ? "w-[248px]" : "w-[280px]";
10254
+ const toggleByButton = sidebar.expandOnHover === false;
10255
+ const handleMenuButton = () => {
10256
+ if (toggleByButton && window.matchMedia("(min-width: 1024px)").matches) handleToggleCollapse();
10257
+ else setMobileSidebarOpen((v) => !v);
10258
+ };
10228
10259
  const brand = sidebarFullHeight ? sidebar.brand ?? { logo: topBar.logo, text: topBar.logoText } : sidebar.brand;
10229
10260
  const topBarNode = /* @__PURE__ */ jsx69(
10230
10261
  ITTopBar,
@@ -10232,7 +10263,8 @@ function ITLayout({
10232
10263
  ...topBar,
10233
10264
  hideBrandOnDesktop: sidebarFullHeight || topBar.hideBrandOnDesktop,
10234
10265
  showMobileMenuButton: true,
10235
- onToggleMobileMenu: () => setMobileSidebarOpen((v) => !v)
10266
+ showDesktopMenuButton: toggleByButton || topBar.showDesktopMenuButton,
10267
+ onToggleMobileMenu: handleMenuButton
10236
10268
  }
10237
10269
  );
10238
10270
  const desktopSidebar = (