@eztrak/shared 0.16.0 → 0.16.2

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.
@@ -1102,6 +1102,9 @@ var import_react_dom = require("react-dom");
1102
1102
  var import_fa = require("react-icons/fa");
1103
1103
  var import_io5 = require("react-icons/io5");
1104
1104
 
1105
+ // src/components/Loader/Loader.css
1106
+ var import_loader = require("@eztrak/shared/components/loader.css");
1107
+
1105
1108
  // src/components/Loader/Loader.tsx
1106
1109
  var import_jsx_runtime6 = require("react/jsx-runtime");
1107
1110
  var Loader = ({ className, color = "#F54C00", size = "50px", speed = "1s" }) => {
@@ -1574,15 +1577,49 @@ function ToolTip({
1574
1577
 
1575
1578
  // src/components/sidebar/Sidebar.tsx
1576
1579
  var import_jsx_runtime13 = require("react/jsx-runtime");
1580
+ function getItemTooltip(item) {
1581
+ return item.tooltip || item.name;
1582
+ }
1583
+ function getTooltipPlacement(item, collapsed) {
1584
+ return item.tooltipPlacement || (collapsed ? "right" : "top");
1585
+ }
1586
+ function isItemActive(pathname, link) {
1587
+ if (!link || link === "#") return false;
1588
+ return pathname === link || pathname.startsWith(`${link}/`);
1589
+ }
1590
+ function SidebarItemLabel({
1591
+ name,
1592
+ collapsed,
1593
+ className
1594
+ }) {
1595
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1596
+ "span",
1597
+ {
1598
+ className: cn(
1599
+ className,
1600
+ collapsed && "block w-full text-center text-[10px] font-medium leading-tight line-clamp-2 wrap-break-word"
1601
+ ),
1602
+ children: name
1603
+ }
1604
+ );
1605
+ }
1606
+ function SidebarItemIcon({
1607
+ icon,
1608
+ className
1609
+ }) {
1610
+ if (!icon) return null;
1611
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: cn("inline-flex shrink-0", className), "aria-hidden": "true", children: icon });
1612
+ }
1577
1613
  function Sidebar({
1578
1614
  className,
1579
- sideCollapseWidth = "w-20",
1615
+ sideCollapseWidth = "w-24",
1580
1616
  sidebarWidth = "w-48",
1581
1617
  header,
1582
1618
  children,
1583
1619
  footer,
1584
1620
  items = [],
1585
1621
  logoUrl = "",
1622
+ logoRouteUrl = "",
1586
1623
  logoAltText = "Logo",
1587
1624
  collapseButtonText = "\u2B05\uFE0F Collapse",
1588
1625
  expandButtonText = "\u27A1\uFE0F",
@@ -1595,29 +1632,68 @@ function Sidebar({
1595
1632
  }) {
1596
1633
  const location = (0, import_react_router_dom6.useLocation)();
1597
1634
  const [collapsed, setCollapsed] = (0, import_react8.useState)(isCollapsed);
1598
- const [, setActiveLink] = (0, import_react8.useState)(location.pathname);
1599
- const [subItemsCollapsed, setSubItemsCollapsed] = (0, import_react8.useState)({});
1635
+ const [openGroups, setOpenGroups] = (0, import_react8.useState)({});
1636
+ const onCollapseChangeRef = (0, import_react8.useRef)(onCollapseChange);
1637
+ onCollapseChangeRef.current = onCollapseChange;
1600
1638
  (0, import_react8.useEffect)(() => {
1601
- if (onCollapseChange) {
1602
- onCollapseChange(collapsed);
1603
- }
1604
- }, [collapsed, onCollapseChange]);
1639
+ setCollapsed(isCollapsed);
1640
+ }, [isCollapsed]);
1605
1641
  (0, import_react8.useEffect)(() => {
1606
- setActiveLink(location.pathname);
1607
- }, [location]);
1642
+ onCollapseChangeRef.current?.(collapsed);
1643
+ }, [collapsed]);
1608
1644
  const toggleGroup = (group) => {
1609
- setSubItemsCollapsed((prevState) => ({
1645
+ setOpenGroups((prevState) => ({
1610
1646
  ...prevState,
1611
1647
  [group]: !prevState[group]
1612
1648
  }));
1613
1649
  };
1614
- const isActive = (link) => {
1615
- return location.pathname.startsWith(link);
1650
+ const itemLayoutClass = (active, itemClassName) => cn(
1651
+ "flex cursor-pointer",
1652
+ classNames?.navItem,
1653
+ collapsed && "w-full flex-col items-center justify-center gap-0.5 px-1 py-2 my-1 !mx-0 max-w-full min-w-0 box-border text-center min-h-11",
1654
+ active && "active",
1655
+ itemClassName
1656
+ );
1657
+ const renderLink = (item, key) => {
1658
+ const active = isItemActive(location.pathname, item.link);
1659
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "max-w-full min-w-0", "data-sidebar-item": item.name, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1660
+ ToolTip,
1661
+ {
1662
+ text: getItemTooltip(item),
1663
+ placement: getTooltipPlacement(item, collapsed),
1664
+ delayShow: 150,
1665
+ className: "block max-w-full min-w-0",
1666
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1667
+ import_react_router_dom6.Link,
1668
+ {
1669
+ to: item.link || "#",
1670
+ className: itemLayoutClass(active, item.itemClassName),
1671
+ "aria-current": active ? "page" : void 0,
1672
+ children: [
1673
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SidebarItemIcon, { icon: item.icon, className: classNames?.navItemText }),
1674
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1675
+ SidebarItemLabel,
1676
+ {
1677
+ name: item.name,
1678
+ collapsed,
1679
+ className: classNames?.navItemText
1680
+ }
1681
+ )
1682
+ ]
1683
+ }
1684
+ )
1685
+ }
1686
+ ) }, key);
1616
1687
  };
1617
1688
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1618
1689
  "div",
1619
1690
  {
1620
- className: `flex flex-col h-screen overflow-hidden ${collapsed ? `${sideCollapseWidth} justify-center items-center collapsed` : `${sidebarWidth}`} transition-all duration-100 ${className ?? ""}`,
1691
+ className: cn(
1692
+ "flex flex-col h-screen overflow-hidden",
1693
+ collapsed ? `${sideCollapseWidth} items-stretch collapsed` : sidebarWidth,
1694
+ "transition-[width] duration-200 ease-in-out motion-reduce:transition-none",
1695
+ className
1696
+ ),
1621
1697
  ...rest,
1622
1698
  children: [
1623
1699
  logoUrl && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
@@ -1627,134 +1703,205 @@ function Sidebar({
1627
1703
  "flex items-center justify-center h-16 border-b border-gray-300",
1628
1704
  classNames.logoSection
1629
1705
  ),
1630
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src: logoUrl, alt: logoAltText, className: "h-10" })
1706
+ children: logoRouteUrl ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1707
+ import_react_router_dom6.Link,
1708
+ {
1709
+ to: logoRouteUrl,
1710
+ className: "sidebar-logo-link inline-flex items-center justify-center",
1711
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src: logoUrl, alt: logoAltText, className: "h-10" })
1712
+ }
1713
+ ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src: logoUrl, alt: logoAltText, className: "h-10" })
1631
1714
  }
1632
1715
  ),
1633
- header && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex items-center justify-between p-4 border-b border-gray-300", children: header }),
1634
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("nav", { className: cn("flex-grow", classNames.navSection), children: items.map((item, index) => {
1635
- if (item.subItems) {
1636
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1637
- "div",
1638
- {
1639
- className: `my-2 ${item?.subItems && "has-sub-items"}`,
1640
- children: [
1641
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1642
- "div",
1643
- {
1644
- onClick: () => toggleGroup(item.name),
1645
- "data-sidebar-item": item.name,
1646
- "data-tooltip-id": item.name,
1647
- className: `flex cursor-pointer dropdown-title-wrapper ${classNames?.navItem ?? ""}`,
1648
- children: [
1649
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1650
- ToolTip,
1651
- {
1652
- text: item.tooltip || item.name,
1653
- placement: item.tooltipPlacement || "top",
1654
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center space-x-2", children: [
1655
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames?.navItemText, children: item.icon }),
1656
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames?.navItemText, children: item.name })
1657
- ] })
1658
- }
1659
- ),
1660
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1661
- "span",
1662
- {
1663
- className: `transform transition-transform ${subItemsCollapsed[item.name] ? "rotate-180" : "rotate-0"}`,
1664
- children: itemDropdownIcon
1665
- }
1666
- )
1667
- ]
1668
- }
1669
- ),
1670
- subItemsCollapsed[item.name] && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("collapse-btn-wrapper", classNames.subItem), children: item.subItems.map((subItem, subIndex) => {
1671
- if (subItem.component) {
1672
- const SubItemComponent = subItem.component;
1673
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SubItemComponent, {}, `${index}-${subIndex}`);
1674
- }
1675
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1676
- "div",
1677
- {
1678
- className: "w-full",
1679
- "data-sidebar-item": subItem.name,
1680
- "data-tooltip-id": subItem.name,
1681
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1682
- ToolTip,
1683
- {
1684
- text: item.tooltip || item.name,
1685
- placement: item.tooltipPlacement || "top",
1686
- className: "block w-full",
1687
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1688
- import_react_router_dom6.Link,
1689
- {
1690
- to: subItem.link || "#",
1691
- className: `flex ${classNames?.navItem ?? ""} ${isActive(subItem?.link ?? "") ? "active" : ""} ${item?.itemClassName}`,
1692
- onClick: () => subItem.link && setActiveLink(subItem.link || ""),
1693
- title: subItem.tooltip || subItem.name,
1694
- children: [
1695
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1696
- "span",
1697
- {
1698
- className: classNames.navItemText ?? "text-orange-600",
1699
- children: subItem.icon
1700
- }
1716
+ header && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex items-center justify-between p-4 border-b border-gray-300 shrink-0", children: header }),
1717
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1718
+ "nav",
1719
+ {
1720
+ "aria-label": "Sidebar",
1721
+ className: cn(
1722
+ "grow min-h-0 min-w-0 w-full",
1723
+ classNames.navSection
1724
+ ),
1725
+ children: items.map((item, index) => {
1726
+ if (item.subItems) {
1727
+ const groupOpen = Boolean(openGroups[item.name]);
1728
+ const groupId = `sidebar-group-${index}`;
1729
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1730
+ "div",
1731
+ {
1732
+ className: cn(
1733
+ "has-sub-items max-w-full min-w-0 flex flex-col",
1734
+ collapsed ? "my-1" : "my-2"
1735
+ ),
1736
+ children: [
1737
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1738
+ ToolTip,
1739
+ {
1740
+ text: getItemTooltip(item),
1741
+ placement: getTooltipPlacement(item, collapsed),
1742
+ delayShow: 150,
1743
+ className: "flex flex-col w-full max-w-full min-w-0",
1744
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1745
+ "button",
1746
+ {
1747
+ type: "button",
1748
+ onClick: () => toggleGroup(item.name),
1749
+ "data-sidebar-item": item.name,
1750
+ "aria-expanded": groupOpen,
1751
+ "aria-controls": groupId,
1752
+ className: cn(
1753
+ itemLayoutClass(false, item.itemClassName),
1754
+ !collapsed && "dropdown-title-wrapper",
1755
+ "relative appearance-none border-0 bg-transparent [font:inherit]"
1756
+ ),
1757
+ children: [
1758
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1759
+ "span",
1760
+ {
1761
+ className: cn(
1762
+ "flex items-center min-w-0",
1763
+ collapsed ? "flex-col gap-0.5 w-full" : "space-x-2 flex-1"
1764
+ ),
1765
+ children: [
1766
+ collapsed ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "flex w-full items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
1767
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "inline-flex w-3 shrink-0", "aria-hidden": "true" }),
1768
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1769
+ SidebarItemIcon,
1770
+ {
1771
+ icon: item.icon,
1772
+ className: classNames?.navItemText
1773
+ }
1774
+ ),
1775
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1776
+ "span",
1777
+ {
1778
+ className: cn(
1779
+ "sidebar-group-caret inline-flex w-3 shrink-0 items-center justify-center text-current [&>svg]:h-3 [&>svg]:w-3 transition-transform duration-200 motion-reduce:transition-none",
1780
+ groupOpen ? "rotate-180" : "rotate-0"
1781
+ ),
1782
+ "aria-hidden": "true",
1783
+ children: itemDropdownIcon
1784
+ }
1785
+ )
1786
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "flex items-center space-x-2 min-w-0 flex-1", children: [
1787
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1788
+ SidebarItemIcon,
1789
+ {
1790
+ icon: item.icon,
1791
+ className: classNames?.navItemText
1792
+ }
1793
+ ),
1794
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1795
+ SidebarItemLabel,
1796
+ {
1797
+ name: item.name,
1798
+ collapsed: false,
1799
+ className: classNames?.navItemText
1800
+ }
1801
+ )
1802
+ ] }),
1803
+ collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1804
+ SidebarItemLabel,
1805
+ {
1806
+ name: item.name,
1807
+ collapsed: true,
1808
+ className: classNames?.navItemText
1809
+ }
1810
+ )
1811
+ ]
1812
+ }
1813
+ ),
1814
+ !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1815
+ "span",
1816
+ {
1817
+ className: cn(
1818
+ "transform transition-transform duration-200 motion-reduce:transition-none",
1819
+ groupOpen ? "rotate-180" : "rotate-0"
1820
+ ),
1821
+ "aria-hidden": "true",
1822
+ children: itemDropdownIcon
1823
+ }
1824
+ )
1825
+ ]
1826
+ }
1827
+ )
1828
+ }
1829
+ ),
1830
+ groupOpen && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1831
+ "div",
1832
+ {
1833
+ id: groupId,
1834
+ role: "group",
1835
+ "aria-label": item.name,
1836
+ className: cn(
1837
+ collapsed ? "sidebar-sub-panel flex flex-col items-center max-w-full min-w-0 box-border" : "collapse-btn-wrapper",
1838
+ classNames.subItem
1839
+ ),
1840
+ children: item.subItems.map((subItem, subIndex) => {
1841
+ if (subItem.component) {
1842
+ const SubItemComponent = subItem.component;
1843
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1844
+ "div",
1845
+ {
1846
+ className: cn(
1847
+ "min-w-0 max-w-full",
1848
+ collapsed && "flex flex-col items-center text-center"
1701
1849
  ),
1702
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames.navItemText, children: subItem.name })
1703
- ]
1704
- }
1705
- )
1706
- }
1707
- )
1708
- },
1709
- `${index}-${subIndex}`
1710
- );
1711
- }) })
1712
- ]
1713
- },
1714
- index
1715
- );
1850
+ "data-sidebar-item": subItem.name,
1851
+ children: [
1852
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SubItemComponent, {}),
1853
+ collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1854
+ SidebarItemLabel,
1855
+ {
1856
+ name: subItem.name,
1857
+ collapsed: true,
1858
+ className: classNames?.navItemText
1859
+ }
1860
+ )
1861
+ ]
1862
+ },
1863
+ `${index}-${subIndex}`
1864
+ );
1865
+ }
1866
+ return renderLink(subItem, `${index}-${subIndex}`);
1867
+ })
1868
+ }
1869
+ )
1870
+ ]
1871
+ },
1872
+ index
1873
+ );
1874
+ }
1875
+ if (item.component) {
1876
+ const ItemComponent = item.component;
1877
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ItemComponent, {}, index);
1878
+ }
1879
+ return renderLink(item, String(index));
1880
+ })
1716
1881
  }
1717
- if (item.component) {
1718
- const ItemComponent = item.component;
1719
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ItemComponent, {}, index);
1882
+ ),
1883
+ children != null && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1884
+ "div",
1885
+ {
1886
+ className: cn(
1887
+ "sidebar-chrome w-full shrink-0",
1888
+ collapsed && "flex flex-col items-center"
1889
+ ),
1890
+ children
1720
1891
  }
1721
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1722
- "div",
1723
- {
1724
- className: "w-full",
1725
- "data-sidebar-item": item.name,
1726
- "data-tooltip-id": item.name,
1727
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1728
- ToolTip,
1729
- {
1730
- text: item.tooltip || item.name,
1731
- placement: item.tooltipPlacement || "top",
1732
- className: "block w-full",
1733
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1734
- import_react_router_dom6.Link,
1735
- {
1736
- to: item.link || "#",
1737
- className: `flex ${classNames?.navItem ?? ""} ${isActive(item.link || "") ? "active" : ""} ${item?.itemClassName}`,
1738
- onClick: () => setActiveLink(item.link || ""),
1739
- title: item.tooltip || item.name,
1740
- children: [
1741
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames.navItemText ?? "text-orange-600", children: item.icon }),
1742
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames.navItemText, children: item.name })
1743
- ]
1744
- }
1745
- )
1746
- }
1747
- )
1748
- },
1749
- index
1750
- );
1751
- }) }),
1752
- children,
1892
+ ),
1753
1893
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1754
1894
  "button",
1755
1895
  {
1896
+ type: "button",
1756
1897
  onClick: () => setCollapsed(!collapsed),
1757
- className: cn("", classNames.collapseButton) ?? "p-4 border-t border-gray-300",
1898
+ "aria-expanded": !collapsed,
1899
+ "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
1900
+ className: cn(
1901
+ "shrink-0 border-t border-gray-300",
1902
+ classNames.collapseButton,
1903
+ collapsed && "flex items-center justify-center"
1904
+ ),
1758
1905
  children: collapsed ? expandButtonText : collapseButtonText
1759
1906
  }
1760
1907
  ),