@eztrak/shared 0.16.1 → 0.16.3

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.
@@ -28,7 +28,7 @@ import {
28
28
  TooltipText,
29
29
  dropdownStyles,
30
30
  resolveActions
31
- } from "../chunk-DFGYKOJF.mjs";
31
+ } from "../chunk-S7ZLXOPF.mjs";
32
32
  import "../chunk-EIX5CUQF.mjs";
33
33
  export {
34
34
  ActionMenuItem,
package/dist/index.js CHANGED
@@ -2005,15 +2005,49 @@ function ToolTip({
2005
2005
 
2006
2006
  // src/components/sidebar/Sidebar.tsx
2007
2007
  var import_jsx_runtime13 = require("react/jsx-runtime");
2008
+ function getItemTooltip(item) {
2009
+ return item.tooltip || item.name;
2010
+ }
2011
+ function getTooltipPlacement(item, collapsed) {
2012
+ return item.tooltipPlacement || (collapsed ? "right" : "top");
2013
+ }
2014
+ function isItemActive(pathname, link) {
2015
+ if (!link || link === "#") return false;
2016
+ return pathname === link || pathname.startsWith(`${link}/`);
2017
+ }
2018
+ function SidebarItemLabel({
2019
+ name,
2020
+ collapsed,
2021
+ className
2022
+ }) {
2023
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2024
+ "span",
2025
+ {
2026
+ className: cn(
2027
+ className,
2028
+ collapsed && "block w-full text-center text-[10px] font-medium leading-tight line-clamp-2 wrap-break-word"
2029
+ ),
2030
+ children: name
2031
+ }
2032
+ );
2033
+ }
2034
+ function SidebarItemIcon({
2035
+ icon,
2036
+ className
2037
+ }) {
2038
+ if (!icon) return null;
2039
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: cn("inline-flex shrink-0", className), "aria-hidden": "true", children: icon });
2040
+ }
2008
2041
  function Sidebar({
2009
2042
  className,
2010
- sideCollapseWidth = "w-20",
2043
+ sideCollapseWidth = "w-24",
2011
2044
  sidebarWidth = "w-48",
2012
2045
  header,
2013
2046
  children,
2014
2047
  footer,
2015
2048
  items = [],
2016
2049
  logoUrl = "",
2050
+ logoRouteUrl = "",
2017
2051
  logoAltText = "Logo",
2018
2052
  collapseButtonText = "\u2B05\uFE0F Collapse",
2019
2053
  expandButtonText = "\u27A1\uFE0F",
@@ -2026,29 +2060,68 @@ function Sidebar({
2026
2060
  }) {
2027
2061
  const location = (0, import_react_router_dom6.useLocation)();
2028
2062
  const [collapsed, setCollapsed] = (0, import_react10.useState)(isCollapsed);
2029
- const [, setActiveLink] = (0, import_react10.useState)(location.pathname);
2030
- const [subItemsCollapsed, setSubItemsCollapsed] = (0, import_react10.useState)({});
2063
+ const [openGroups, setOpenGroups] = (0, import_react10.useState)({});
2064
+ const onCollapseChangeRef = (0, import_react10.useRef)(onCollapseChange);
2065
+ onCollapseChangeRef.current = onCollapseChange;
2031
2066
  (0, import_react10.useEffect)(() => {
2032
- if (onCollapseChange) {
2033
- onCollapseChange(collapsed);
2034
- }
2035
- }, [collapsed, onCollapseChange]);
2067
+ setCollapsed(isCollapsed);
2068
+ }, [isCollapsed]);
2036
2069
  (0, import_react10.useEffect)(() => {
2037
- setActiveLink(location.pathname);
2038
- }, [location]);
2070
+ onCollapseChangeRef.current?.(collapsed);
2071
+ }, [collapsed]);
2039
2072
  const toggleGroup = (group) => {
2040
- setSubItemsCollapsed((prevState) => ({
2073
+ setOpenGroups((prevState) => ({
2041
2074
  ...prevState,
2042
2075
  [group]: !prevState[group]
2043
2076
  }));
2044
2077
  };
2045
- const isActive = (link) => {
2046
- return location.pathname.startsWith(link);
2078
+ const itemLayoutClass = (active, itemClassName) => cn(
2079
+ "flex cursor-pointer",
2080
+ classNames?.navItem,
2081
+ 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",
2082
+ active && "active",
2083
+ itemClassName
2084
+ );
2085
+ const renderLink = (item, key) => {
2086
+ const active = isItemActive(location.pathname, item.link);
2087
+ 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)(
2088
+ ToolTip,
2089
+ {
2090
+ text: getItemTooltip(item),
2091
+ placement: getTooltipPlacement(item, collapsed),
2092
+ delayShow: 150,
2093
+ className: "block max-w-full min-w-0",
2094
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2095
+ import_react_router_dom6.Link,
2096
+ {
2097
+ to: item.link || "#",
2098
+ className: itemLayoutClass(active, item.itemClassName),
2099
+ "aria-current": active ? "page" : void 0,
2100
+ children: [
2101
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SidebarItemIcon, { icon: item.icon, className: classNames?.navItemText }),
2102
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2103
+ SidebarItemLabel,
2104
+ {
2105
+ name: item.name,
2106
+ collapsed,
2107
+ className: classNames?.navItemText
2108
+ }
2109
+ )
2110
+ ]
2111
+ }
2112
+ )
2113
+ }
2114
+ ) }, key);
2047
2115
  };
2048
2116
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2049
2117
  "div",
2050
2118
  {
2051
- className: `flex flex-col h-screen overflow-hidden ${collapsed ? `${sideCollapseWidth} justify-center items-center collapsed` : `${sidebarWidth}`} transition-all duration-100 ${className ?? ""}`,
2119
+ className: cn(
2120
+ "flex flex-col h-screen overflow-hidden",
2121
+ collapsed ? `${sideCollapseWidth} items-stretch collapsed` : sidebarWidth,
2122
+ "transition-[width] duration-200 ease-in-out motion-reduce:transition-none",
2123
+ className
2124
+ ),
2052
2125
  ...rest,
2053
2126
  children: [
2054
2127
  logoUrl && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
@@ -2058,134 +2131,206 @@ function Sidebar({
2058
2131
  "flex items-center justify-center h-16 border-b border-gray-300",
2059
2132
  classNames.logoSection
2060
2133
  ),
2061
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src: logoUrl, alt: logoAltText, className: "h-10" })
2134
+ children: logoRouteUrl ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2135
+ import_react_router_dom6.Link,
2136
+ {
2137
+ to: logoRouteUrl,
2138
+ className: "sidebar-logo-link inline-flex items-center justify-center",
2139
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src: logoUrl, alt: logoAltText, className: "h-10" })
2140
+ }
2141
+ ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src: logoUrl, alt: logoAltText, className: "h-10" })
2062
2142
  }
2063
2143
  ),
2064
- header && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex items-center justify-between p-4 border-b border-gray-300", children: header }),
2065
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("nav", { className: cn("flex-grow", classNames.navSection), children: items.map((item, index) => {
2066
- if (item.subItems) {
2067
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2068
- "div",
2069
- {
2070
- className: `my-2 ${item?.subItems && "has-sub-items"}`,
2071
- children: [
2072
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2073
- "div",
2074
- {
2075
- onClick: () => toggleGroup(item.name),
2076
- "data-sidebar-item": item.name,
2077
- "data-tooltip-id": item.name,
2078
- className: `flex cursor-pointer dropdown-title-wrapper ${classNames?.navItem ?? ""}`,
2079
- children: [
2080
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2081
- ToolTip,
2082
- {
2083
- text: item.tooltip || item.name,
2084
- placement: item.tooltipPlacement || "top",
2085
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center space-x-2", children: [
2086
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames?.navItemText, children: item.icon }),
2087
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames?.navItemText, children: item.name })
2088
- ] })
2089
- }
2090
- ),
2091
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2092
- "span",
2093
- {
2094
- className: `transform transition-transform ${subItemsCollapsed[item.name] ? "rotate-180" : "rotate-0"}`,
2095
- children: itemDropdownIcon
2096
- }
2097
- )
2098
- ]
2099
- }
2100
- ),
2101
- subItemsCollapsed[item.name] && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("collapse-btn-wrapper", classNames.subItem), children: item.subItems.map((subItem, subIndex) => {
2102
- if (subItem.component) {
2103
- const SubItemComponent = subItem.component;
2104
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SubItemComponent, {}, `${index}-${subIndex}`);
2105
- }
2106
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2107
- "div",
2108
- {
2109
- className: "w-full",
2110
- "data-sidebar-item": subItem.name,
2111
- "data-tooltip-id": subItem.name,
2112
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2113
- ToolTip,
2114
- {
2115
- text: item.tooltip || item.name,
2116
- placement: item.tooltipPlacement || "top",
2117
- className: "block w-full",
2118
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2119
- import_react_router_dom6.Link,
2120
- {
2121
- to: subItem.link || "#",
2122
- className: `flex ${classNames?.navItem ?? ""} ${isActive(subItem?.link ?? "") ? "active" : ""} ${item?.itemClassName}`,
2123
- onClick: () => subItem.link && setActiveLink(subItem.link || ""),
2124
- title: subItem.tooltip || subItem.name,
2125
- children: [
2126
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2127
- "span",
2128
- {
2129
- className: classNames.navItemText ?? "text-orange-600",
2130
- children: subItem.icon
2131
- }
2144
+ 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 }),
2145
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2146
+ "nav",
2147
+ {
2148
+ "aria-label": "Sidebar",
2149
+ className: cn(
2150
+ "grow min-h-0 min-w-0 w-full",
2151
+ classNames.navSection
2152
+ ),
2153
+ children: items.map((item, index) => {
2154
+ if (item.subItems) {
2155
+ const groupOpen = Boolean(openGroups[item.name]);
2156
+ const groupId = `sidebar-group-${index}`;
2157
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2158
+ "div",
2159
+ {
2160
+ "data-sidebar-item": item.name,
2161
+ className: cn(
2162
+ "has-sub-items max-w-full min-w-0 flex flex-col",
2163
+ collapsed ? "my-1" : "my-2"
2164
+ ),
2165
+ children: [
2166
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2167
+ ToolTip,
2168
+ {
2169
+ text: getItemTooltip(item),
2170
+ placement: getTooltipPlacement(item, collapsed),
2171
+ delayShow: 150,
2172
+ className: "flex flex-col w-full max-w-full min-w-0",
2173
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2174
+ "button",
2175
+ {
2176
+ type: "button",
2177
+ onClick: () => toggleGroup(item.name),
2178
+ "data-sidebar-item": item.name,
2179
+ "aria-expanded": groupOpen,
2180
+ "aria-controls": groupId,
2181
+ className: cn(
2182
+ itemLayoutClass(false, item.itemClassName),
2183
+ !collapsed && "dropdown-title-wrapper",
2184
+ "relative appearance-none border-0 bg-transparent [font:inherit]"
2185
+ ),
2186
+ children: [
2187
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2188
+ "span",
2189
+ {
2190
+ className: cn(
2191
+ "flex items-center min-w-0",
2192
+ collapsed ? "flex-col gap-0.5 w-full" : "space-x-2 flex-1"
2193
+ ),
2194
+ children: [
2195
+ 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: [
2196
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "inline-flex w-3 shrink-0", "aria-hidden": "true" }),
2197
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2198
+ SidebarItemIcon,
2199
+ {
2200
+ icon: item.icon,
2201
+ className: classNames?.navItemText
2202
+ }
2203
+ ),
2204
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2205
+ "span",
2206
+ {
2207
+ className: cn(
2208
+ "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",
2209
+ groupOpen ? "rotate-180" : "rotate-0"
2210
+ ),
2211
+ "aria-hidden": "true",
2212
+ children: itemDropdownIcon
2213
+ }
2214
+ )
2215
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "flex items-center space-x-2 min-w-0 flex-1", children: [
2216
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2217
+ SidebarItemIcon,
2218
+ {
2219
+ icon: item.icon,
2220
+ className: classNames?.navItemText
2221
+ }
2222
+ ),
2223
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2224
+ SidebarItemLabel,
2225
+ {
2226
+ name: item.name,
2227
+ collapsed: false,
2228
+ className: classNames?.navItemText
2229
+ }
2230
+ )
2231
+ ] }),
2232
+ collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2233
+ SidebarItemLabel,
2234
+ {
2235
+ name: item.name,
2236
+ collapsed: true,
2237
+ className: classNames?.navItemText
2238
+ }
2239
+ )
2240
+ ]
2241
+ }
2242
+ ),
2243
+ !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2244
+ "span",
2245
+ {
2246
+ className: cn(
2247
+ "transform transition-transform duration-200 motion-reduce:transition-none",
2248
+ groupOpen ? "rotate-180" : "rotate-0"
2249
+ ),
2250
+ "aria-hidden": "true",
2251
+ children: itemDropdownIcon
2252
+ }
2253
+ )
2254
+ ]
2255
+ }
2256
+ )
2257
+ }
2258
+ ),
2259
+ groupOpen && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2260
+ "div",
2261
+ {
2262
+ id: groupId,
2263
+ role: "group",
2264
+ "aria-label": item.name,
2265
+ className: cn(
2266
+ collapsed ? "sidebar-sub-panel flex flex-col items-center max-w-full min-w-0 box-border" : "collapse-btn-wrapper",
2267
+ classNames.subItem
2268
+ ),
2269
+ children: item.subItems.map((subItem, subIndex) => {
2270
+ if (subItem.component) {
2271
+ const SubItemComponent = subItem.component;
2272
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2273
+ "div",
2274
+ {
2275
+ className: cn(
2276
+ "min-w-0 max-w-full",
2277
+ collapsed && "flex flex-col items-center text-center"
2132
2278
  ),
2133
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames.navItemText, children: subItem.name })
2134
- ]
2135
- }
2136
- )
2137
- }
2138
- )
2139
- },
2140
- `${index}-${subIndex}`
2141
- );
2142
- }) })
2143
- ]
2144
- },
2145
- index
2146
- );
2279
+ "data-sidebar-item": subItem.name,
2280
+ children: [
2281
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SubItemComponent, {}),
2282
+ collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2283
+ SidebarItemLabel,
2284
+ {
2285
+ name: subItem.name,
2286
+ collapsed: true,
2287
+ className: classNames?.navItemText
2288
+ }
2289
+ )
2290
+ ]
2291
+ },
2292
+ `${index}-${subIndex}`
2293
+ );
2294
+ }
2295
+ return renderLink(subItem, `${index}-${subIndex}`);
2296
+ })
2297
+ }
2298
+ )
2299
+ ]
2300
+ },
2301
+ index
2302
+ );
2303
+ }
2304
+ if (item.component) {
2305
+ const ItemComponent = item.component;
2306
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ItemComponent, {}, index);
2307
+ }
2308
+ return renderLink(item, String(index));
2309
+ })
2147
2310
  }
2148
- if (item.component) {
2149
- const ItemComponent = item.component;
2150
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ItemComponent, {}, index);
2311
+ ),
2312
+ children != null && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2313
+ "div",
2314
+ {
2315
+ className: cn(
2316
+ "sidebar-chrome w-full shrink-0",
2317
+ collapsed && "flex flex-col items-center"
2318
+ ),
2319
+ children
2151
2320
  }
2152
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2153
- "div",
2154
- {
2155
- className: "w-full",
2156
- "data-sidebar-item": item.name,
2157
- "data-tooltip-id": item.name,
2158
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2159
- ToolTip,
2160
- {
2161
- text: item.tooltip || item.name,
2162
- placement: item.tooltipPlacement || "top",
2163
- className: "block w-full",
2164
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2165
- import_react_router_dom6.Link,
2166
- {
2167
- to: item.link || "#",
2168
- className: `flex ${classNames?.navItem ?? ""} ${isActive(item.link || "") ? "active" : ""} ${item?.itemClassName}`,
2169
- onClick: () => setActiveLink(item.link || ""),
2170
- title: item.tooltip || item.name,
2171
- children: [
2172
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames.navItemText ?? "text-orange-600", children: item.icon }),
2173
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: classNames.navItemText, children: item.name })
2174
- ]
2175
- }
2176
- )
2177
- }
2178
- )
2179
- },
2180
- index
2181
- );
2182
- }) }),
2183
- children,
2321
+ ),
2184
2322
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2185
2323
  "button",
2186
2324
  {
2325
+ type: "button",
2187
2326
  onClick: () => setCollapsed(!collapsed),
2188
- className: cn("", classNames.collapseButton) ?? "p-4 border-t border-gray-300",
2327
+ "aria-expanded": !collapsed,
2328
+ "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
2329
+ className: cn(
2330
+ "shrink-0 border-t border-gray-300",
2331
+ classNames.collapseButton,
2332
+ collapsed && "flex items-center justify-center"
2333
+ ),
2189
2334
  children: collapsed ? expandButtonText : collapseButtonText
2190
2335
  }
2191
2336
  ),