pixelize-design-library 2.3.14 → 2.3.15
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/.cursor/modules/layout-navigation/MODULE.md +44 -0
- package/dist/App.d.ts.map +1 -1
- package/dist/Components/NavigationBar/NavigationBar.d.ts +1 -1
- package/dist/Components/NavigationBar/NavigationBar.d.ts.map +1 -1
- package/dist/Components/NavigationBar/NavigationBar.js +2 -2
- package/dist/Components/NavigationBar/NavigationBarProps.d.ts +7 -0
- package/dist/Components/NavigationBar/NavigationBarProps.d.ts.map +1 -1
- package/dist/Components/SideBar/SideBar.d.ts +1 -1
- package/dist/Components/SideBar/SideBar.d.ts.map +1 -1
- package/dist/Components/SideBar/SideBar.js +130 -12
- package/dist/Components/SideBar/SideBarProps.d.ts +25 -0
- package/dist/Components/SideBar/SideBarProps.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -12,3 +12,47 @@ Accordion, Breadcrumbs, NavigationBar, SideBar, Header, Drawer, FilterSidebar.
|
|
|
12
12
|
|
|
13
13
|
- SideBar/Header have sub-`components/` folders
|
|
14
14
|
- Used by crm-frontend, account-frontend sidebars
|
|
15
|
+
|
|
16
|
+
## SideBar — responsive overlay (< lg / 992px)
|
|
17
|
+
|
|
18
|
+
At/above `lg` the SideBar is unchanged: inline, sticky, with the collapse/mini-rail
|
|
19
|
+
(`toggle`). Below `lg` it becomes a slide-in **overlay** above the content (it leaves
|
|
20
|
+
layout flow, so content stays full-width — not shrunk):
|
|
21
|
+
|
|
22
|
+
- `mobileOpen?: boolean` + `onMobileClose?: () => void` props drive the overlay. Wire
|
|
23
|
+
`mobileOpen` to the NavigationBar hamburger (`sideBarToggole` / `onSideBarToggole`).
|
|
24
|
+
- Overlay is always expanded (collapse/mini-rail is desktop-only and hidden < lg). The
|
|
25
|
+
header's trailing control becomes a Close (X) instead of the collapse chevron.
|
|
26
|
+
- Dismiss: backdrop scrim click, **Esc**, the Close button, or **swipe-left** on the
|
|
27
|
+
panel. Body scroll is locked while open; panel exposes `role="dialog"`/`aria-modal`.
|
|
28
|
+
- NavigationBar hamburger now shows below `lg` (was `< md`); its panel icon is
|
|
29
|
+
state-aware (`PanelLeftClose` open / `PanelRightClose` closed).
|
|
30
|
+
- The overlay panel has **square edges** (no border radius).
|
|
31
|
+
|
|
32
|
+
Breakpoint, scrim/slide, and z-index are Chakra responsive props (no JS flash) when
|
|
33
|
+
`mobileNav` is off; the breakpoint is read once via `useBreakpointValue({ base: true, lg: false })`.
|
|
34
|
+
|
|
35
|
+
## SideBar — Hide/Show (mobile navbar on big screens)
|
|
36
|
+
|
|
37
|
+
A footer **Hide/Show** toggle (next to Collapse) switches the navbar *presentation*
|
|
38
|
+
between the docked desktop sidebar and the mobile-style overlay — at **any** width, so
|
|
39
|
+
desktop users can get the full-screen content experience. It is a layout switch, **not**
|
|
40
|
+
a close: toggling never hides the navigation.
|
|
41
|
+
|
|
42
|
+
- `mobileNav?: boolean` forces overlay presentation regardless of breakpoint:
|
|
43
|
+
`overlay = (below lg) || mobileNav`. `onToggleMobileNav?: () => void` backs the
|
|
44
|
+
footer control (render the control only when provided).
|
|
45
|
+
- Footer control: docked → segmented **Collapse | Hide**; desktop mobile-nav overlay →
|
|
46
|
+
**Show** (return to docked). Pure below-`lg` overlay shows no navbar-mode control.
|
|
47
|
+
- Wire so entering mobile-nav also opens the overlay (sidebar stays visible) and leaving
|
|
48
|
+
docks it — see `App.tsx`. NavigationBar `forceSideBarToggle` shows the hamburger at all
|
|
49
|
+
widths while `mobileNav` is on.
|
|
50
|
+
- Selecting a **leaf** menu item in overlay mode auto-closes the overlay (content returns
|
|
51
|
+
to full-screen); submenu **parents** only expand and do not close it.
|
|
52
|
+
|
|
53
|
+
### Known gaps
|
|
54
|
+
|
|
55
|
+
- `SecondaryBar` keeps its current side-by-side stacking inside the overlay — revisit if
|
|
56
|
+
it feels cramped on very narrow screens.
|
|
57
|
+
- Consumer apps (crm/account/…) must pass `mobileOpen`/`onMobileClose` to adopt overlay
|
|
58
|
+
mode; until then they get the unchanged inline sidebar.
|
package/dist/App.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.tsx"],"names":[],"mappings":"AAQA,OAAO,cAAc,CAAC;AAyDtB,iBAAS,GAAG,
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.tsx"],"names":[],"mappings":"AAQA,OAAO,cAAc,CAAC;AAyDtB,iBAAS,GAAG,4CAkFX;AAED,eAAe,GAAG,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { NavbarProps } from "./NavigationBarProps";
|
|
2
|
-
export default function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavOnClick, handleLogout, logoutText, navigationBarText, sideBarToggole, onSideBarToggole, }: NavbarProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export default function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavOnClick, handleLogout, logoutText, navigationBarText, sideBarToggole, onSideBarToggole, forceSideBarToggle, }: NavbarProps): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=NavigationBar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationBar.d.ts","sourceRoot":"","sources":["../../../src/Components/NavigationBar/NavigationBar.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAa,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAS9D,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC9B,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,gBAAgB,
|
|
1
|
+
{"version":3,"file":"NavigationBar.d.ts","sourceRoot":"","sources":["../../../src/Components/NavigationBar/NavigationBar.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAa,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAS9D,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC9B,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAA0B,GAC1B,EAAE,WAAW,2CAmKb"}
|
|
@@ -5,7 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const react_1 = require("@chakra-ui/react");
|
|
6
6
|
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
7
7
|
const lucide_react_1 = require("lucide-react");
|
|
8
|
-
function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavOnClick, handleLogout, logoutText, navigationBarText, sideBarToggole, onSideBarToggole, }) {
|
|
8
|
+
function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavOnClick, handleLogout, logoutText, navigationBarText, sideBarToggole, onSideBarToggole, forceSideBarToggle = false, }) {
|
|
9
9
|
var _a, _b, _c, _d;
|
|
10
10
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
11
11
|
// Shared rounded pill affordance for the bar's icon controls.
|
|
@@ -35,7 +35,7 @@ function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavO
|
|
|
35
35
|
_focus: { bg: theme.colors.primary[50], color: theme.colors.primary[700] },
|
|
36
36
|
_active: { bg: theme.colors.primary[50], color: theme.colors.primary[700] },
|
|
37
37
|
};
|
|
38
|
-
return ((0, jsx_runtime_1.jsx)(react_1.Box, { bg: theme.colors.backgroundColor.light, px: 4, borderBottom: "1px solid", borderColor: "blackAlpha.100", children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { h: 16, alignItems: "center", justifyContent: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", gap: 1.5, alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { onClick: () => onSideBarToggole === null || onSideBarToggole === void 0 ? void 0 : onSideBarToggole(), display: { base: "flex", lg: "none",
|
|
38
|
+
return ((0, jsx_runtime_1.jsx)(react_1.Box, { bg: theme.colors.backgroundColor.light, px: 4, borderBottom: "1px solid", borderColor: "blackAlpha.100", children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { h: 16, alignItems: "center", justifyContent: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", gap: 1.5, alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { onClick: () => onSideBarToggole === null || onSideBarToggole === void 0 ? void 0 : onSideBarToggole(), display: forceSideBarToggle ? "flex" : { base: "flex", lg: "none" }, "aria-label": sideBarToggole ? "Close navigation menu" : "Open navigation menu", ...iconButtonStyle, children: sideBarToggole ? ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { size: "1.25rem" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { size: "1.25rem" })) }), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) && ((0, jsx_runtime_1.jsx)(react_1.Box, { ...iconButtonStyle, display: "flex", onClick: () => { var _a; return (_a = navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) === null || _a === void 0 ? void 0 : _a.call(navigationBarText); }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleArrowLeft, { size: "1.25rem", color: (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b[500] }) })), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text) && ((0, jsx_runtime_1.jsx)(react_1.Text, { color: (_d = (_c = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _c === void 0 ? void 0 : _c.secondary) === null || _d === void 0 ? void 0 : _d[500], fontSize: "1.25rem", fontWeight: 600, fontFamily: "open-sans, sans-serif", letterSpacing: "-0.013rem", children: navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text }))] }), (0, jsx_runtime_1.jsx)(react_1.Flex, { minW: 0, flexShrink: 1, children: (0, jsx_runtime_1.jsxs)(react_1.Stack, { direction: "row", alignItems: "center", spacing: 4, minW: 0, children: [moreIcon && ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", minW: 0, children: moreIcon })), (0, jsx_runtime_1.jsxs)(react_1.Menu, { children: [(0, jsx_runtime_1.jsx)(react_1.MenuButton, { as: react_1.Button, rounded: "full", variant: "link", cursor: "pointer", minW: 0, flexShrink: 0, children: (0, jsx_runtime_1.jsx)(react_1.Avatar, { size: "sm", name: userName, src: userAvathar }) }), (0, jsx_runtime_1.jsx)(react_1.MenuList, { alignItems: "center", zIndex: 5, p: 0, py: "0.375rem", bg: theme.colors.backgroundColor.light, border: "1px solid", borderColor: "blackAlpha.100", borderRadius: "0.75rem", boxShadow: "lg", color: "gray.700", overflow: "hidden", children: (0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", flexDirection: "column", maxH: "90vh", children: [(0, jsx_runtime_1.jsx)(react_1.Center, { pt: 4, pb: 2, children: (0, jsx_runtime_1.jsx)(react_1.Avatar, { size: "xl", name: userName, src: userAvathar }) }), (0, jsx_runtime_1.jsxs)(react_1.Center, { flexDirection: "column", gap: "0.125rem", pb: 2, px: 4, children: [(0, jsx_runtime_1.jsx)(react_1.Text, { fontWeight: 600, fontSize: "14px", color: "gray.800", isTruncated: true, maxW: "100%", children: userName }), userRole && ((0, jsx_runtime_1.jsx)(react_1.Text, { fontSize: "11px", color: "gray.500", isTruncated: true, maxW: "100%", children: userRole }))] }), (0, jsx_runtime_1.jsx)(react_1.MenuDivider, { borderColor: "blackAlpha.100" }), (0, jsx_runtime_1.jsx)(react_1.Box, { flex: 1, overflowY: "auto", children: navMenu === null || navMenu === void 0 ? void 0 : navMenu.map((menu, idx) => {
|
|
39
39
|
var _a, _b, _c;
|
|
40
40
|
return ((0, jsx_runtime_1.jsxs)(react_1.MenuItem, { onClick: () => handleNavOnClick(menu.url), sx: menuItemStyle, children: [menu.icon && ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", flexShrink: 0, sx: { "& svg": { width: "16px", height: "16px" } }, children: menu === null || menu === void 0 ? void 0 : menu.icon })), (0, jsx_runtime_1.jsx)(react_1.Box, { children: menu.title })] }, `${String((_c = (_b = (_a = menu.id) !== null && _a !== void 0 ? _a : menu.url) !== null && _b !== void 0 ? _b : menu.title) !== null && _c !== void 0 ? _c : idx)}-${idx}`));
|
|
41
41
|
}) }), (0, jsx_runtime_1.jsx)(react_1.MenuDivider, { borderColor: "blackAlpha.100" }), (0, jsx_runtime_1.jsxs)(react_1.MenuItem, { onClick: handleLogout, sx: {
|
|
@@ -14,6 +14,13 @@ export type NavbarProps = {
|
|
|
14
14
|
};
|
|
15
15
|
sideBarToggole?: boolean;
|
|
16
16
|
onSideBarToggole?: () => void;
|
|
17
|
+
/**
|
|
18
|
+
* Force the sidebar hamburger to show at all widths (not just below `lg`).
|
|
19
|
+
* Set this when the sidebar is in "mobile navbar" mode on a big screen, so the
|
|
20
|
+
* hamburger remains available to open the overlay. Defaults to `false`
|
|
21
|
+
* (hamburger shows only below `lg`).
|
|
22
|
+
*/
|
|
23
|
+
forceSideBarToggle?: boolean;
|
|
17
24
|
};
|
|
18
25
|
export type MenuProps = {
|
|
19
26
|
id?: string | number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationBarProps.d.ts","sourceRoot":"","sources":["../../../src/Components/NavigationBar/NavigationBarProps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE;QAClB,IAAI,EAAE,SAAS,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;KAC1B,CAAC;IACF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"NavigationBarProps.d.ts","sourceRoot":"","sources":["../../../src/Components/NavigationBar/NavigationBarProps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE;QAClB,IAAI,EAAE,SAAS,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;KAC1B,CAAC;IACF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { SidebarProps } from "./SideBarProps";
|
|
2
|
-
export default function Sidebar({ menus, activeMenu, handleMenuClick, handleSecondaryNavClick, toggle, changeToggle, logo, companyName, companySubtitle, user, isDisableAddNew, onAddNewClick, selectedSubMenu, selectedSecondaryItem, isLoading, loadingLines, open, otherApps, }: SidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export default function Sidebar({ menus, activeMenu, handleMenuClick, handleSecondaryNavClick, toggle, changeToggle, logo, companyName, companySubtitle, user, isDisableAddNew, onAddNewClick, selectedSubMenu, selectedSecondaryItem, isLoading, loadingLines, open, otherApps, mobileOpen, onMobileClose, mobileNav, onToggleMobileNav, }: SidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=SideBar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SideBar.d.ts","sourceRoot":"","sources":["../../../src/Components/SideBar/SideBar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAe,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"SideBar.d.ts","sourceRoot":"","sources":["../../../src/Components/SideBar/SideBar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAe,MAAM,gBAAgB,CAAC;AAuZ3D,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAC9B,KAAK,EACL,UAAU,EACV,eAAe,EACf,uBAAuB,EACvB,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,eAAe,EACf,IAAI,EACJ,eAAuB,EACvB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,SAAS,EACT,YAAY,EACZ,IAAW,EACX,SAAS,EACT,UAAkB,EAClB,aAAa,EACb,SAAiB,EACjB,iBAAiB,GAClB,EAAE,YAAY,2CA+Qd"}
|
|
@@ -10,23 +10,28 @@ const react_2 = require("@chakra-ui/react");
|
|
|
10
10
|
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
11
11
|
const Sidebar_1 = require("../../Constants/Sidebar");
|
|
12
12
|
const lucide_react_1 = require("lucide-react");
|
|
13
|
+
// Overlay stacking — mirrors theme.zIndices (overlay=1300 scrim, modal=1400 panel).
|
|
14
|
+
const Z_SCRIM = 1300;
|
|
15
|
+
const Z_PANEL = 1400;
|
|
16
|
+
// Width of the slide-in overlay panel (a touch wider than the inline 13rem for touch).
|
|
17
|
+
const OVERLAY_WIDTH = "16rem";
|
|
13
18
|
const MenuItems_1 = __importDefault(require("./components/MenuItems"));
|
|
14
19
|
const defaultLogo_1 = __importDefault(require("../../Assets/defaultLogo"));
|
|
15
20
|
const OverflowTooltipText_1 = __importDefault(require("./components/OverflowTooltipText"));
|
|
16
21
|
const SecondaryBar_1 = __importDefault(require("./SecondaryBar"));
|
|
17
22
|
const OtherApps_1 = __importDefault(require("./components/OtherApps"));
|
|
18
|
-
const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading, onToggle, }) => {
|
|
23
|
+
const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading, onToggle, overlay, onClose, }) => {
|
|
19
24
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
20
25
|
if (isLoading) {
|
|
21
26
|
return ((0, jsx_runtime_1.jsx)(react_2.Box, { w: "100%", px: toggle ? 2 : 4, py: 2, h: Sidebar_1.HEADER_HEIGHT, display: "flex", alignItems: "center", flexShrink: 0, children: toggle ? ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", gap: 4, justifyContent: "center", w: "100%", children: (0, jsx_runtime_1.jsx)(react_2.Skeleton, { w: "28px", h: "28px", borderRadius: "md", startColor: "gray.600", endColor: "gray.500" }) })) : ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 3, w: "100%", children: [(0, jsx_runtime_1.jsx)(react_2.Skeleton, { w: "28px", h: "28px", borderRadius: "md", startColor: "gray.600", endColor: "gray.500" }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: "1.25rem", w: "60%", borderRadius: "md", startColor: "gray.600", endColor: "gray.500" })] })) }));
|
|
22
27
|
}
|
|
23
28
|
const logoNode = logo ? ((0, jsx_runtime_1.jsx)(react_2.Image, { borderRadius: "md", boxSize: "1.75rem", src: logo, alt: "Company Logo", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, "aria-label": toggle ? "Expand sidebar" : undefined })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { bg: theme.colors.primary[500], color: theme.colors.white, borderRadius: "md", boxSize: "1.75rem", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, "aria-label": toggle ? "Expand sidebar" : undefined, children: (0, jsx_runtime_1.jsx)(defaultLogo_1.default, {}) }));
|
|
24
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { h: Sidebar_1.HEADER_HEIGHT, w: "100%", alignItems: "center", justifyContent: toggle ? "center" : "flex-start", gap: "8px", px: toggle ? "8px" : "10px", borderBottom: "1px solid", borderColor: "whiteAlpha.100", minW: 0, overflow: "hidden", flexShrink: 0, children: [logoNode, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", fontWeight: 600, fontSize: "12.5px", textAlign: "left", color: theme.colors.white, lineHeight: "1.3", as: "p", width: "100%", children: companyName !== null && companyName !== void 0 ? companyName : "" }), companySubtitle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "10px", color: "whiteAlpha.500", lineHeight: "1.3", isTruncated: true, children: companySubtitle }))] })), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: onToggle, "aria-label": "Collapse sidebar", w: "22px", h: "22px", borderRadius: "5px", bg: "whiteAlpha.100", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 14, color: theme.colors.white, opacity: 0.6 }) }))] }));
|
|
29
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { h: Sidebar_1.HEADER_HEIGHT, w: "100%", alignItems: "center", justifyContent: toggle ? "center" : "flex-start", gap: "8px", px: toggle ? "8px" : "10px", borderBottom: "1px solid", borderColor: "whiteAlpha.100", minW: 0, overflow: "hidden", flexShrink: 0, children: [logoNode, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", fontWeight: 600, fontSize: "12.5px", textAlign: "left", color: theme.colors.white, lineHeight: "1.3", as: "p", width: "100%", children: companyName !== null && companyName !== void 0 ? companyName : "" }), companySubtitle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "10px", color: "whiteAlpha.500", lineHeight: "1.3", isTruncated: true, children: companySubtitle }))] })), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: overlay ? onClose : onToggle, "aria-label": overlay ? "Close menu" : "Collapse sidebar", w: "22px", h: "22px", borderRadius: "5px", bg: "whiteAlpha.100", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", children: overlay ? ((0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 15, color: theme.colors.white, opacity: 0.7 })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 14, color: theme.colors.white, opacity: 0.6 })) }))] }));
|
|
25
30
|
};
|
|
26
31
|
const SkeletonMenuRow = ({ toggle }) => ((0, jsx_runtime_1.jsx)(react_2.Box, { w: "100%", px: toggle ? 1 : 2, py: 2, children: toggle ? ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", gap: 4, justifyContent: "center", children: (0, jsx_runtime_1.jsx)(react_2.Skeleton, { w: "24px", h: "24px", borderRadius: "md", startColor: "gray.600", endColor: "gray.500" }) })) : ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 3, children: [(0, jsx_runtime_1.jsx)(react_2.Skeleton, { w: "18px", h: "18px", borderRadius: "md", startColor: "gray.600", endColor: "gray.500" }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: "0.875rem", w: "80%", borderRadius: "md", startColor: "gray.600", endColor: "gray.500" })] })) }));
|
|
27
|
-
const AddNewButton = ({ toggle, onClick }) => {
|
|
32
|
+
const AddNewButton = ({ toggle, onClick, overlay }) => {
|
|
28
33
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
29
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { role: "group", alignItems: "center", gap: "9px", px: "10px", py: "7px", borderRadius: "7px", cursor: "pointer", w: "100%", mb: "2px", justifyContent: toggle ? "center" : "flex-start", _hover: { backgroundColor: "whiteAlpha.100" }, transition: "background 0.12s", onClick: onClick, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { w: "18px", h: "18px", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, color: theme.colors.primary[300] }) }), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "12.5px", color: "whiteAlpha.900", fontWeight: "medium", children: "Add New" }))] }));
|
|
34
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { role: "group", alignItems: "center", gap: "9px", px: "10px", py: overlay ? "11px" : "7px", borderRadius: "7px", cursor: "pointer", w: "100%", mb: "2px", justifyContent: toggle ? "center" : "flex-start", _hover: { backgroundColor: "whiteAlpha.100" }, transition: "background 0.12s", onClick: onClick, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { w: "18px", h: "18px", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, color: theme.colors.primary[300] }) }), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "12.5px", color: "whiteAlpha.900", fontWeight: "medium", children: "Add New" }))] }));
|
|
30
35
|
};
|
|
31
36
|
const deriveInitials = (user) => {
|
|
32
37
|
if (user.initials)
|
|
@@ -38,19 +43,53 @@ const deriveInitials = (user) => {
|
|
|
38
43
|
return parts[0].slice(0, 2).toUpperCase();
|
|
39
44
|
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
40
45
|
};
|
|
41
|
-
const UserFooter = ({ user, toggle }) => {
|
|
46
|
+
const UserFooter = ({ user, toggle, overlay }) => {
|
|
42
47
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
43
48
|
const avatar = user.avatarUrl ? ((0, jsx_runtime_1.jsx)(react_2.Image, { src: user.avatarUrl, alt: user.name, boxSize: "26px", borderRadius: "full", objectFit: "cover", flexShrink: 0 })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: "26px", borderRadius: "full", bg: theme.colors.primary.opacity[32], color: theme.colors.primary[300], display: "flex", alignItems: "center", justifyContent: "center", fontSize: "10px", fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
|
|
44
|
-
return ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: "whiteAlpha.100", p: "8px 6px", flexShrink: 0, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", onClick: user.onClick, align: "center", gap: "8px", px: "8px", py: "6px", w: "100%", borderRadius: "7px", cursor: "pointer", bg: "transparent", border: "none", justify: toggle ? "center" : "flex-start", _hover: { bg: "whiteAlpha.100" }, transition: "background 0.12s", children: [avatar, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, textAlign: "left", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "11.5px", fontWeight: 500, color: "whiteAlpha.800", isTruncated: true, children: user.name }), user.role && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "10px", color: "whiteAlpha.500", isTruncated: true, children: user.role }))] })), !toggle && (0, jsx_runtime_1.jsx)(lucide_react_1.MoreVertical, { size: 14, color: theme.colors.white, opacity: 0.3 })] }) }));
|
|
49
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: "whiteAlpha.100", p: "8px 6px", flexShrink: 0, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", onClick: user.onClick, align: "center", gap: "8px", px: "8px", py: overlay ? "10px" : "6px", w: "100%", borderRadius: "7px", cursor: "pointer", bg: "transparent", border: "none", justify: toggle ? "center" : "flex-start", _hover: { bg: "whiteAlpha.100" }, transition: "background 0.12s", children: [avatar, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, textAlign: "left", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "11.5px", fontWeight: 500, color: "whiteAlpha.800", isTruncated: true, children: user.name }), user.role && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "10px", color: "whiteAlpha.500", isTruncated: true, children: user.role }))] })), !toggle && (0, jsx_runtime_1.jsx)(lucide_react_1.MoreVertical, { size: 14, color: theme.colors.white, opacity: 0.3 })] }) }));
|
|
45
50
|
};
|
|
46
|
-
|
|
51
|
+
// Footer "cell" — one segment of the Collapse | Hide/Show control.
|
|
52
|
+
const ControlCell = ({ onClick, label, accent, children }) => {
|
|
47
53
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
48
|
-
return ((0, jsx_runtime_1.
|
|
54
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", flex: "1", minW: 0, alignItems: "center", justifyContent: "center", gap: "7px", px: "6px", py: "8px", cursor: "pointer", border: "none", bg: accent ? theme.colors.primary.opacity[16] : "transparent", onClick: onClick, _hover: { bg: accent ? theme.colors.primary.opacity[32] : "whiteAlpha.100" }, transition: "background 0.15s", children: [children, label && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "11.5px", color: accent ? theme.colors.primary[300] : "whiteAlpha.700", fontWeight: "medium", children: label }))] }));
|
|
55
|
+
};
|
|
56
|
+
// Collapse (mini-rail) sits next to the Hide/Show navbar-mode toggle. In the
|
|
57
|
+
// desktop mobile-nav overlay only "Show" (return to the docked sidebar) is shown;
|
|
58
|
+
// below `lg` (pure responsive overlay) there is no navbar-mode control.
|
|
59
|
+
const FooterControls = ({ toggle, overlay, mobileNav, onToggleCollapse, onToggleMobileNav, }) => {
|
|
60
|
+
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
61
|
+
const iconColor = theme.colors.white;
|
|
62
|
+
const shell = (children) => ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: "whiteAlpha.100", p: "6px", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(react_2.Flex, { display: "flex", gap: "0", borderRadius: "8px", overflow: "hidden", border: "1px solid", borderColor: "whiteAlpha.100", bg: "whiteAlpha.50", sx: { "& > * + *": { borderLeft: "1px solid", borderColor: "whiteAlpha.100" } }, children: children }) }));
|
|
63
|
+
if (overlay) {
|
|
64
|
+
// Pure below-lg overlay (no manual nav-mode switch) → no footer control.
|
|
65
|
+
if (!mobileNav || !onToggleMobileNav)
|
|
66
|
+
return null;
|
|
67
|
+
return shell((0, jsx_runtime_1.jsx)(ControlCell, { onClick: onToggleMobileNav, label: "Show", accent: true, children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeft, { size: 14, color: theme.colors.primary[300] }) }));
|
|
68
|
+
}
|
|
69
|
+
return shell((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ControlCell, { onClick: onToggleCollapse, label: toggle ? undefined : "Collapse", children: toggle ? ((0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRightToLine, { size: 14, color: iconColor, opacity: 0.6 })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ArrowLeftToLine, { size: 14, color: iconColor, opacity: 0.6 })) }), onToggleMobileNav && ((0, jsx_runtime_1.jsx)(ControlCell, { onClick: onToggleMobileNav, label: toggle ? undefined : "Hide", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Maximize2, { size: 14, color: iconColor, opacity: 0.6 }) }))] }));
|
|
49
70
|
};
|
|
50
71
|
// --- Main Sidebar component ---
|
|
51
|
-
function Sidebar({ menus, activeMenu, handleMenuClick, handleSecondaryNavClick, toggle, changeToggle, logo, companyName, companySubtitle, user, isDisableAddNew = false, onAddNewClick, selectedSubMenu, selectedSecondaryItem, isLoading, loadingLines, open = true, otherApps, }) {
|
|
52
|
-
var _a;
|
|
72
|
+
function Sidebar({ menus, activeMenu, handleMenuClick, handleSecondaryNavClick, toggle, changeToggle, logo, companyName, companySubtitle, user, isDisableAddNew = false, onAddNewClick, selectedSubMenu, selectedSecondaryItem, isLoading, loadingLines, open = true, otherApps, mobileOpen = false, onMobileClose, mobileNav = false, onToggleMobileNav, }) {
|
|
73
|
+
var _a, _b;
|
|
53
74
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
75
|
+
// Below `lg` the sidebar renders as a slide-in overlay above the content; at
|
|
76
|
+
// `lg` and up it is inline (the original behaviour, untouched).
|
|
77
|
+
const belowLg = (_a = (0, react_2.useBreakpointValue)({ base: true, lg: false }, { ssr: false })) !== null && _a !== void 0 ? _a : false;
|
|
78
|
+
// Overlay ("mobile navbar") presentation is active when the viewport is below
|
|
79
|
+
// `lg` OR the Hide/Show toggle has forced it on at any width.
|
|
80
|
+
const overlay = belowLg || mobileNav;
|
|
81
|
+
// In overlay mode the panel is always fully expanded — the mini-rail/collapse
|
|
82
|
+
// is a desktop-only space affordance — so children render as if `toggle=false`.
|
|
83
|
+
const effToggle = overlay ? false : toggle;
|
|
84
|
+
const isOverlayOpen = overlay && mobileOpen;
|
|
85
|
+
// In overlay mode, navigating to a leaf item auto-closes the overlay (content
|
|
86
|
+
// returns to full-screen). Parent items with a submenu only expand, so they
|
|
87
|
+
// must NOT close it.
|
|
88
|
+
const handleMenuClickInternal = (menu) => {
|
|
89
|
+
handleMenuClick === null || handleMenuClick === void 0 ? void 0 : handleMenuClick(menu);
|
|
90
|
+
if (overlay && !(menu.subMenu && menu.subMenu.length > 0))
|
|
91
|
+
onMobileClose === null || onMobileClose === void 0 ? void 0 : onMobileClose();
|
|
92
|
+
};
|
|
54
93
|
// Refs let the effects read the latest values without adding them to dep arrays,
|
|
55
94
|
// which would cause infinite toggle loops since changeToggle flips state.
|
|
56
95
|
const toggleRef = (0, react_1.useRef)(toggle);
|
|
@@ -59,7 +98,7 @@ function Sidebar({ menus, activeMenu, handleMenuClick, handleSecondaryNavClick,
|
|
|
59
98
|
changeToggleRef.current = changeToggle;
|
|
60
99
|
const activeTop = menus.find((m) => String(m.title) === String(activeMenu)) ||
|
|
61
100
|
menus.find((m) => String(m.id) === String(activeMenu));
|
|
62
|
-
const secondaryItems = (
|
|
101
|
+
const secondaryItems = (_b = activeTop === null || activeTop === void 0 ? void 0 : activeTop.secondaryItems) !== null && _b !== void 0 ? _b : [];
|
|
63
102
|
// Sync toggle with external `open` prop.
|
|
64
103
|
// `open=false` → collapsed (toggle=true); `open=true` → expanded (toggle=false).
|
|
65
104
|
(0, react_1.useEffect)(() => {
|
|
@@ -74,5 +113,84 @@ function Sidebar({ menus, activeMenu, handleMenuClick, handleSecondaryNavClick,
|
|
|
74
113
|
changeToggleRef.current();
|
|
75
114
|
}
|
|
76
115
|
}, [secondaryItems.length]);
|
|
77
|
-
|
|
116
|
+
// Esc closes the overlay.
|
|
117
|
+
(0, react_1.useEffect)(() => {
|
|
118
|
+
if (!isOverlayOpen)
|
|
119
|
+
return;
|
|
120
|
+
const onKey = (e) => {
|
|
121
|
+
if (e.key === "Escape")
|
|
122
|
+
onMobileClose === null || onMobileClose === void 0 ? void 0 : onMobileClose();
|
|
123
|
+
};
|
|
124
|
+
document.addEventListener("keydown", onKey);
|
|
125
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
126
|
+
}, [isOverlayOpen, onMobileClose]);
|
|
127
|
+
// Lock body scroll while the overlay is open.
|
|
128
|
+
(0, react_1.useEffect)(() => {
|
|
129
|
+
if (!isOverlayOpen)
|
|
130
|
+
return;
|
|
131
|
+
const prev = document.body.style.overflow;
|
|
132
|
+
document.body.style.overflow = "hidden";
|
|
133
|
+
return () => {
|
|
134
|
+
document.body.style.overflow = prev;
|
|
135
|
+
};
|
|
136
|
+
}, [isOverlayOpen]);
|
|
137
|
+
// Swipe-left-to-close. Tracks pointer start; commits to a horizontal drag only
|
|
138
|
+
// when the gesture is mostly horizontal, so vertical menu scrolling is unaffected.
|
|
139
|
+
const dragStart = (0, react_1.useRef)(null);
|
|
140
|
+
const [dragX, setDragX] = (0, react_1.useState)(0);
|
|
141
|
+
const [dragging, setDragging] = (0, react_1.useState)(false);
|
|
142
|
+
const onPointerDown = (e) => {
|
|
143
|
+
if (!isOverlayOpen)
|
|
144
|
+
return;
|
|
145
|
+
dragStart.current = { x: e.clientX, y: e.clientY };
|
|
146
|
+
};
|
|
147
|
+
const onPointerMove = (e) => {
|
|
148
|
+
const start = dragStart.current;
|
|
149
|
+
if (!start)
|
|
150
|
+
return;
|
|
151
|
+
const dx = e.clientX - start.x;
|
|
152
|
+
const dy = e.clientY - start.y;
|
|
153
|
+
if (!dragging) {
|
|
154
|
+
if (Math.abs(dy) > Math.abs(dx)) {
|
|
155
|
+
dragStart.current = null; // vertical → let the list scroll
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (dx < -6)
|
|
159
|
+
setDragging(true);
|
|
160
|
+
else
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
setDragX(Math.min(0, dx));
|
|
164
|
+
};
|
|
165
|
+
const onPointerUp = (e) => {
|
|
166
|
+
const start = dragStart.current;
|
|
167
|
+
const committed = dragging;
|
|
168
|
+
dragStart.current = null;
|
|
169
|
+
setDragging(false);
|
|
170
|
+
setDragX(0);
|
|
171
|
+
if (committed && start && e.clientX - start.x < -96)
|
|
172
|
+
onMobileClose === null || onMobileClose === void 0 ? void 0 : onMobileClose();
|
|
173
|
+
};
|
|
174
|
+
const baseTransform = dragging
|
|
175
|
+
? `translateX(${dragX}px)`
|
|
176
|
+
: isOverlayOpen
|
|
177
|
+
? "translateX(0)"
|
|
178
|
+
: "translateX(-100%)";
|
|
179
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Box, { display: mobileNav ? "block" : { base: "block", lg: "none" }, position: "fixed", inset: 0, bg: "blackAlpha.600", zIndex: Z_SCRIM, opacity: isOverlayOpen ? 1 : 0, visibility: isOverlayOpen ? "visible" : "hidden", transition: "opacity 0.28s ease, visibility 0.28s ease", onClick: onMobileClose, "aria-hidden": "true" }), (0, jsx_runtime_1.jsxs)(react_2.Box, { position: mobileNav ? "fixed" : { base: "fixed", lg: "sticky" }, top: 0, left: mobileNav ? 0 : { base: 0, lg: "auto" }, bottom: mobileNav ? 0 : { base: 0, lg: "auto" }, zIndex: mobileNav ? Z_PANEL : { base: Z_PANEL, lg: "auto" }, height: "100vh", maxW: mobileNav ? "88vw" : { base: "88vw", lg: "none" }, transform: mobileNav ? baseTransform : { base: baseTransform, lg: "none" }, transition: mobileNav
|
|
180
|
+
? dragging
|
|
181
|
+
? "none"
|
|
182
|
+
: "transform 0.28s cubic-bezier(0.22, 1, 0.36, 1)"
|
|
183
|
+
: {
|
|
184
|
+
base: dragging
|
|
185
|
+
? "none"
|
|
186
|
+
: "transform 0.28s cubic-bezier(0.22, 1, 0.36, 1)",
|
|
187
|
+
lg: "all 0.5s",
|
|
188
|
+
}, borderRadius: 0, boxShadow: mobileNav ? "10px 0 40px rgba(0,0,0,0.45)" : { base: "10px 0 40px rgba(0,0,0,0.45)", lg: theme.shadows.lg }, display: "flex", background: theme.colors.sidebar.background[500], borderRight: "1px solid", borderColor: "whiteAlpha.100", role: overlay ? "dialog" : undefined, "aria-modal": overlay ? true : undefined, "aria-label": overlay ? "Main navigation" : undefined, "aria-hidden": overlay && !mobileOpen ? true : undefined, sx: { touchAction: overlay ? "pan-y" : "auto" }, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { width: mobileNav ? OVERLAY_WIDTH : { base: OVERLAY_WIDTH, lg: toggle ? "4.688rem" : "13rem" }, transition: "width 0.5s ease", display: "flex", flexDirection: "column", justifyContent: "space-between", children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { flexDir: "column", w: "100%", as: "nav", h: "100vh", children: [(0, jsx_runtime_1.jsx)(SidebarHeader, { logo: logo, companyName: companyName, companySubtitle: companySubtitle, toggle: effToggle, isLoading: isLoading, onToggle: changeToggle, overlay: overlay, onClose: onMobileClose }), (0, jsx_runtime_1.jsx)(react_2.Box, { id: "sidebar-scroll-container", flex: "1", minH: 0, w: "100%", overflowY: "auto", overflowX: "hidden", p: "8px 6px", css: {
|
|
189
|
+
...Sidebar_1.FlexCss,
|
|
190
|
+
transition: "all 0.3s ease",
|
|
191
|
+
// (a) larger touch targets for menu rows in overlay mode
|
|
192
|
+
...(overlay
|
|
193
|
+
? { "[data-menu-id]": { paddingTop: "10px", paddingBottom: "10px" } }
|
|
194
|
+
: {}),
|
|
195
|
+
}, children: isLoading ? (Array.from({ length: loadingLines !== null && loadingLines !== void 0 ? loadingLines : 15 }).map((_, i) => ((0, jsx_runtime_1.jsx)(SkeletonMenuRow, { toggle: effToggle }, i)))) : ((0, jsx_runtime_1.jsx)(MenuItems_1.default, { activeMenu: activeMenu, menus: menus, handleMenuClick: handleMenuClickInternal, toggle: effToggle, selectedSubMenu: selectedSubMenu })) }), (0, jsx_runtime_1.jsxs)(react_2.Box, { flexShrink: 0, children: [!isDisableAddNew && ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: "whiteAlpha.100", p: "8px 6px", children: (0, jsx_runtime_1.jsx)(AddNewButton, { toggle: effToggle, onClick: onAddNewClick, overlay: overlay }) })), (0, jsx_runtime_1.jsx)(OtherApps_1.default, { toggle: effToggle, otherApps: otherApps !== null && otherApps !== void 0 ? otherApps : [] }), user && (0, jsx_runtime_1.jsx)(UserFooter, { user: user, toggle: effToggle, overlay: overlay }), (0, jsx_runtime_1.jsx)(FooterControls, { toggle: toggle, overlay: overlay, mobileNav: mobileNav, onToggleCollapse: changeToggle, onToggleMobileNav: onToggleMobileNav })] })] }) }), secondaryItems.length > 0 && ((0, jsx_runtime_1.jsx)(SecondaryBar_1.default, { items: secondaryItems, defaultCollapsed: effToggle, collapsedWidth: "3.5rem", expandedWidth: "10rem", selected: selectedSecondaryItem, onItemClick: handleSecondaryNavClick, title: activeTop === null || activeTop === void 0 ? void 0 : activeTop.title, icon: activeTop === null || activeTop === void 0 ? void 0 : activeTop.icon })), overlay && ((0, jsx_runtime_1.jsx)(react_2.Box, { display: mobileOpen ? "block" : "none", position: "absolute", top: "50%", right: "6px", transform: "translateY(-50%)", w: "4px", h: "42px", borderRadius: "full", bg: "whiteAlpha.300", "aria-hidden": "true" }))] })] }));
|
|
78
196
|
}
|
|
@@ -25,6 +25,31 @@ export type SidebarProps = {
|
|
|
25
25
|
loadingLines?: number;
|
|
26
26
|
open?: boolean;
|
|
27
27
|
otherApps?: OtherAppsProps['otherApps'];
|
|
28
|
+
/**
|
|
29
|
+
* Below the `lg` breakpoint the sidebar renders as a slide-in overlay above
|
|
30
|
+
* the content (it does not occupy layout space). `mobileOpen` controls that
|
|
31
|
+
* overlay's visibility; it has no effect at `lg` and up, where the sidebar is
|
|
32
|
+
* always inline. Wire it to the NavigationBar hamburger (`onSideBarToggole`).
|
|
33
|
+
*/
|
|
34
|
+
mobileOpen?: boolean;
|
|
35
|
+
/** Called when the overlay is dismissed (backdrop click, Esc, close button, or swipe). */
|
|
36
|
+
onMobileClose?: () => void;
|
|
37
|
+
/**
|
|
38
|
+
* Forces the "mobile navbar" presentation at ANY width: the sidebar leaves the
|
|
39
|
+
* inline layout and behaves as the slide-in overlay (hamburger + full-screen
|
|
40
|
+
* content), exactly like below `lg` — but on big screens too. This is a layout
|
|
41
|
+
* switch, not a close: toggling it never hides the navigation, it only changes
|
|
42
|
+
* how it is presented. When `false` the breakpoint alone decides (inline at
|
|
43
|
+
* `lg`+, overlay below `lg`).
|
|
44
|
+
*/
|
|
45
|
+
mobileNav?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Handler for the footer Hide/Show control that flips `mobileNav`. Render the
|
|
48
|
+
* control only when provided. Wire it so entering mobile-nav also opens the
|
|
49
|
+
* overlay (keeps the sidebar visible) and leaving it returns to the docked
|
|
50
|
+
* sidebar — see the playground for the canonical wiring.
|
|
51
|
+
*/
|
|
52
|
+
onToggleMobileNav?: () => void;
|
|
28
53
|
};
|
|
29
54
|
export type MenuProps = {
|
|
30
55
|
id: string | number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SideBarProps.d.ts","sourceRoot":"","sources":["../../../src/Components/SideBar/SideBarProps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEzC,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5C,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACpD,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"SideBarProps.d.ts","sourceRoot":"","sources":["../../../src/Components/SideBar/SideBarProps.tsx"],"names":[],"mappings":"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"}
|