@campxdev/react-blueprint 2.3.8 → 2.3.9

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.
Files changed (30) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/types/src/components/Layout/AppLayout/components/AppBar.d.ts +4 -3
  3. package/dist/cjs/types/src/components/Layout/AppLayout/components/PersistentSidebar.d.ts +14 -0
  4. package/dist/cjs/types/src/components/Layout/AppLayout/components/Sidebar/interfaces.d.ts +2 -0
  5. package/dist/cjs/types/src/components/Layout/AppLayout/components/UserProfilePopup.d.ts +3 -2
  6. package/dist/cjs/types/src/components/Layout/AppLayout/types.d.ts +7 -0
  7. package/dist/esm/index.js +2 -2
  8. package/dist/esm/types/src/components/Layout/AppLayout/components/AppBar.d.ts +4 -3
  9. package/dist/esm/types/src/components/Layout/AppLayout/components/PersistentSidebar.d.ts +14 -0
  10. package/dist/esm/types/src/components/Layout/AppLayout/components/Sidebar/interfaces.d.ts +2 -0
  11. package/dist/esm/types/src/components/Layout/AppLayout/components/UserProfilePopup.d.ts +3 -2
  12. package/dist/esm/types/src/components/Layout/AppLayout/types.d.ts +7 -0
  13. package/dist/index.d.ts +48 -40
  14. package/package.json +1 -1
  15. package/src/App.tsx +9 -37
  16. package/src/components/Layout/AppLayout/AppLayout.tsx +61 -20
  17. package/src/components/Layout/AppLayout/components/AppBar.tsx +35 -49
  18. package/src/components/Layout/AppLayout/components/PersistentSidebar.tsx +171 -0
  19. package/src/components/Layout/AppLayout/components/Sidebar/MenuBar.tsx +8 -4
  20. package/src/components/Layout/AppLayout/components/Sidebar/MenuItem.tsx +123 -46
  21. package/src/components/Layout/AppLayout/components/Sidebar/interfaces.ts +2 -0
  22. package/src/components/Layout/AppLayout/components/Sidebar/styles.ts +0 -2
  23. package/src/components/Layout/AppLayout/components/UserProfilePopup.tsx +42 -12
  24. package/src/components/Layout/AppLayout/types.ts +9 -0
  25. package/src/components/Layout/PageHeader/components/Views/Views.tsx +3 -2
  26. package/src/components/Navigation/Breadcrumbs/Breadcrumbs.tsx +1 -1
  27. package/src/components/Navigation/Sidebar/SidebarV2.tsx +1 -1
  28. package/src/themes/colorTokens/darkColorTokens.tsx +1 -1
  29. package/src/themes/colorTokens/lightColorTokens.ts +1 -1
  30. package/src/themes/commonTheme.ts +1 -1
@@ -1,16 +1,17 @@
1
1
  import React from 'react';
2
- import { SideMenuItemProps } from './Sidebar/interfaces';
3
2
  interface AppBarProps {
4
3
  /** Right section component (actions, profile, etc.) */
5
4
  rightSection?: React.ReactNode;
6
5
  /** Center section component (workspace switcher, etc.) */
7
6
  centerSection?: React.ReactNode;
8
- /** Menu items for mobile drawer */
9
- menu?: SideMenuItemProps[];
10
7
  /** Custom className for the AppBar */
11
8
  className?: string;
12
9
  /** Custom styles for the AppBar */
13
10
  sx?: any;
11
+ /** Hide hamburger menu (for persistent sidebar mode) */
12
+ hideHamburger?: boolean;
13
+ /** Callback to toggle sidebar (for persistent sidebar mode on mobile) */
14
+ onToggleSidebar?: () => void;
14
15
  }
15
16
  export declare const AppBar: React.FC<AppBarProps>;
16
17
  export {};
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { SideMenuItemProps } from './Sidebar/interfaces';
3
+ import { UserProfilePopupProps } from './UserProfilePopup';
4
+ interface PersistentSidebarProps {
5
+ /** Menu items for navigation */
6
+ menu: SideMenuItemProps[];
7
+ userProfileParams: UserProfilePopupProps;
8
+ /** Whether the sidebar is collapsed */
9
+ collapsed: boolean;
10
+ /** Function to toggle sidebar collapse state */
11
+ onToggle: () => void;
12
+ }
13
+ export declare const PersistentSidebar: React.FC<PersistentSidebarProps>;
14
+ export {};
@@ -40,6 +40,7 @@ export interface MenuItemProps {
40
40
  currentMenuPath: string | null;
41
41
  internalMenuClickHandler: (params: InternalMenuClickHandlerProps) => void;
42
42
  onClose?: () => void;
43
+ collapsed?: boolean;
43
44
  }
44
45
  export interface SubMenuItemProps {
45
46
  index: number;
@@ -52,4 +53,5 @@ export interface MenuBarProps {
52
53
  internalMenuClickHandler: (params: InternalMenuClickHandlerProps) => void;
53
54
  previousMenuClickHandler: () => void;
54
55
  onClose?: () => void;
56
+ collapsed?: boolean;
55
57
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- interface UserProfilePopupProps {
2
+ export interface UserProfilePopupProps {
3
3
  /** User's full name */
4
4
  userFullName: string;
5
5
  /** User's designation/role */
@@ -18,6 +18,8 @@ interface UserProfilePopupProps {
18
18
  onActiveDevicesClick?: () => void;
19
19
  /** Account section click handler */
20
20
  onAccountClick?: () => void;
21
+ /**Persistant Side bar collapsed - boolean */
22
+ collapsed?: boolean;
21
23
  }
22
24
  /**
23
25
  * Independent User Profile popup component for AppLayout right section
@@ -38,4 +40,3 @@ interface UserProfilePopupProps {
38
40
  * />
39
41
  */
40
42
  export declare const UserProfilePopup: React.FC<UserProfilePopupProps>;
41
- export {};
@@ -1,5 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { SideMenuItemProps } from './components/Sidebar/interfaces';
3
+ import { UserProfilePopupProps } from './components/UserProfilePopup';
3
4
  export interface HelpDocsAction {
4
5
  name: string;
5
6
  onClick: () => void;
@@ -15,6 +16,8 @@ export interface AppLayoutProps {
15
16
  children: ReactNode;
16
17
  /** Navigation menu items */
17
18
  menu: SideMenuItemProps[];
19
+ /**User profile parameters */
20
+ userProfileParams: UserProfilePopupProps;
18
21
  /** AppBar customization - Primary approach */
19
22
  rightSection?: ReactNode;
20
23
  /** AppBar center section customization */
@@ -23,4 +26,8 @@ export interface AppLayoutProps {
23
26
  mainContainerSx?: any;
24
27
  /** Help documentation configuration for route-based contextual help */
25
28
  helpDocsConfig?: HelpDocsConfig;
29
+ /**
30
+ * Initial collapsed state for persistent sidebar
31
+ */
32
+ initialCollapsed?: boolean;
26
33
  }
package/dist/index.d.ts CHANGED
@@ -956,6 +956,48 @@ interface SubMenuData {
956
956
  permissionKey?: string;
957
957
  }
958
958
 
959
+ interface UserProfilePopupProps {
960
+ /** User's full name */
961
+ userFullName: string;
962
+ /** User's designation/role */
963
+ designation?: string;
964
+ /** Profile dropdown actions (custom menu items) */
965
+ profileActions?: react__default.ReactNode[];
966
+ /** Logout click handler */
967
+ onLogout?: () => void;
968
+ /** Profile image URL */
969
+ profileUrl?: string;
970
+ /** Custom styles for the avatar */
971
+ avatarSx?: any;
972
+ /** Whether to show active devices option */
973
+ showActiveDevices?: boolean;
974
+ /** Active devices click handler */
975
+ onActiveDevicesClick?: () => void;
976
+ /** Account section click handler */
977
+ onAccountClick?: () => void;
978
+ /**Persistant Side bar collapsed - boolean */
979
+ collapsed?: boolean;
980
+ }
981
+ /**
982
+ * Independent User Profile popup component for AppLayout right section
983
+ * No longer depends on UserBox - contains its own implementation
984
+ * Provides clean, flexible props interface
985
+ *
986
+ * @example
987
+ * <UserProfilePopup
988
+ * userFullName="John Doe"
989
+ * designation="Administrator"
990
+ * profileActions={[
991
+ * <SwitchInstitutionPopup key="switch" />,
992
+ * <DropdownMenuItem key="settings" label="Settings" onClick={() => {}} />
993
+ * ]}
994
+ * onLogout={handleLogout}
995
+ * showActiveDevices={true}
996
+ * onActiveDevicesClick={() => console.log('Active devices')}
997
+ * />
998
+ */
999
+ declare const UserProfilePopup: react__default.FC<UserProfilePopupProps>;
1000
+
959
1001
  interface HelpDocsAction {
960
1002
  name: string;
961
1003
  onClick: () => void;
@@ -971,6 +1013,8 @@ interface AppLayoutProps {
971
1013
  children: ReactNode;
972
1014
  /** Navigation menu items */
973
1015
  menu: SideMenuItemProps$1[];
1016
+ /**User profile parameters */
1017
+ userProfileParams: UserProfilePopupProps;
974
1018
  /** AppBar customization - Primary approach */
975
1019
  rightSection?: ReactNode;
976
1020
  /** AppBar center section customization */
@@ -979,6 +1023,10 @@ interface AppLayoutProps {
979
1023
  mainContainerSx?: any;
980
1024
  /** Help documentation configuration for route-based contextual help */
981
1025
  helpDocsConfig?: HelpDocsConfig;
1026
+ /**
1027
+ * Initial collapsed state for persistent sidebar
1028
+ */
1029
+ initialCollapsed?: boolean;
982
1030
  }
983
1031
 
984
1032
  declare const AppLayout: react__default.FC<AppLayoutProps>;
@@ -1046,46 +1094,6 @@ interface SwitchInstitutionPopupProps {
1046
1094
  */
1047
1095
  declare const SwitchInstitutionPopup: react__default.FC<SwitchInstitutionPopupProps>;
1048
1096
 
1049
- interface UserProfilePopupProps {
1050
- /** User's full name */
1051
- userFullName: string;
1052
- /** User's designation/role */
1053
- designation?: string;
1054
- /** Profile dropdown actions (custom menu items) */
1055
- profileActions?: react__default.ReactNode[];
1056
- /** Logout click handler */
1057
- onLogout?: () => void;
1058
- /** Profile image URL */
1059
- profileUrl?: string;
1060
- /** Custom styles for the avatar */
1061
- avatarSx?: any;
1062
- /** Whether to show active devices option */
1063
- showActiveDevices?: boolean;
1064
- /** Active devices click handler */
1065
- onActiveDevicesClick?: () => void;
1066
- /** Account section click handler */
1067
- onAccountClick?: () => void;
1068
- }
1069
- /**
1070
- * Independent User Profile popup component for AppLayout right section
1071
- * No longer depends on UserBox - contains its own implementation
1072
- * Provides clean, flexible props interface
1073
- *
1074
- * @example
1075
- * <UserProfilePopup
1076
- * userFullName="John Doe"
1077
- * designation="Administrator"
1078
- * profileActions={[
1079
- * <SwitchInstitutionPopup key="switch" />,
1080
- * <DropdownMenuItem key="settings" label="Settings" onClick={() => {}} />
1081
- * ]}
1082
- * onLogout={handleLogout}
1083
- * showActiveDevices={true}
1084
- * onActiveDevicesClick={() => console.log('Active devices')}
1085
- * />
1086
- */
1087
- declare const UserProfilePopup: react__default.FC<UserProfilePopupProps>;
1088
-
1089
1097
  type AppHeaderProps = {
1090
1098
  actions?: ReactNode[];
1091
1099
  profileActions?: ReactNode[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campxdev/react-blueprint",
3
- "version": "2.3.8",
3
+ "version": "2.3.9",
4
4
  "description": "React UI component library for CampX applications",
5
5
  "author": "CampX",
6
6
  "license": "MIT",
package/src/App.tsx CHANGED
@@ -6,13 +6,8 @@ import {
6
6
  } from 'react-router-dom';
7
7
  import './App.css';
8
8
 
9
- import { Stack } from '@mui/material';
10
9
  import { Icons } from './components/export';
11
- import {
12
- AppLayout,
13
- SwitchInstitutionPopup,
14
- UserProfilePopup,
15
- } from './components/Layout/AppLayout';
10
+ import { AppLayout } from './components/Layout/AppLayout';
16
11
 
17
12
  // Sample Pages
18
13
  import { Dashboard } from './pages/Dashboard';
@@ -269,39 +264,16 @@ function App() {
269
264
  // In a real app, you would handle logout logic here
270
265
  };
271
266
 
267
+ const userProfileParams = {
268
+ userFullName: 'User',
269
+ designation: 'Admin',
270
+ onLogout: () => {},
271
+ onAccountClick: () => {},
272
+ profileActions: [],
273
+ };
272
274
  return (
273
275
  <Router>
274
- <AppLayout
275
- menu={sampleMenu}
276
- rightSection={
277
- <Stack direction="row" alignItems="center" gap={1}>
278
- <Icons.AdminIcon size={24} />
279
- <UserProfilePopup
280
- userFullName="John Doe"
281
- designation="Administrator"
282
- onLogout={handleLogout}
283
- showActiveDevices={true}
284
- profileActions={[
285
- <SwitchInstitutionPopup
286
- key="switch-institution"
287
- institutionsData={[
288
- {
289
- name: 'Demo University',
290
- code: 'demo',
291
- imageSquare: { url: '' },
292
- },
293
- {
294
- name: 'Test College',
295
- code: 'test',
296
- imageSquare: { url: '' },
297
- },
298
- ]}
299
- />,
300
- ]}
301
- />
302
- </Stack>
303
- }
304
- >
276
+ <AppLayout menu={sampleMenu} userProfileParams={userProfileParams}>
305
277
  <Routes>
306
278
  <Route path="/" element={<Navigate to="/dashboard" replace />} />
307
279
  <Route path="/dashboard" element={<Dashboard />} />
@@ -1,7 +1,9 @@
1
- import { Box, Stack, styled, useTheme } from '@mui/material';
2
- import React from 'react';
1
+ import { Box, Stack, styled, useMediaQuery, useTheme } from '@mui/material';
2
+ import { motion } from 'framer-motion';
3
+ import React, { useState } from 'react';
3
4
  import { AppBar } from './components/AppBar';
4
5
  import { FloatingHelpDocs } from './components/FloatingHelpDocs';
6
+ import { PersistentSidebar } from './components/PersistentSidebar';
5
7
  import { AppLayoutProps } from './types';
6
8
 
7
9
  export const AppLayout: React.FC<AppLayoutProps> = ({
@@ -11,8 +13,14 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
11
13
  centerSection,
12
14
  mainContainerSx = {},
13
15
  helpDocsConfig,
16
+ initialCollapsed,
17
+ userProfileParams,
14
18
  }) => {
15
19
  const theme = useTheme();
20
+ const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
21
+
22
+ // State for persistent sidebar
23
+ const [collapsed, setCollapsed] = useState(isSmallScreen ?? initialCollapsed);
16
24
 
17
25
  // Get help docs actions for current route
18
26
  const getCurrentRouteHelpActions = () => {
@@ -28,41 +36,74 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
28
36
 
29
37
  const helpDocsActions = getCurrentRouteHelpActions();
30
38
 
39
+ const toggleSidebar = () => {
40
+ setCollapsed(!collapsed);
41
+ };
42
+
43
+ // Calculate main content width for persistent sidebar
44
+ const getMainWidth = () => {
45
+ if (isSmallScreen) return '100%';
46
+ return collapsed ? 'calc(100% - 64px)' : 'calc(100% - 250px)';
47
+ };
48
+
31
49
  return (
32
50
  <AppLayoutContainer>
33
- {/* AppBar - Full width at the top */}
34
- <AppBar
35
- rightSection={rightSection}
36
- centerSection={centerSection}
51
+ {/* Persistent Sidebar */}
52
+ <PersistentSidebar
37
53
  menu={menu}
54
+ collapsed={collapsed}
55
+ onToggle={toggleSidebar}
56
+ userProfileParams={userProfileParams}
38
57
  />
39
58
 
40
- {/* Main Content - Single column, centered with max-width */}
41
- <MainContent
42
- sx={{
43
- ...mainContainerSx,
59
+ {/* Main Content Area with dynamic width */}
60
+ <motion.div
61
+ animate={{
62
+ width: getMainWidth(),
63
+ }}
64
+ transition={{ duration: 0.3, ease: [0.32, 0.72, 0, 1] }}
65
+ style={{
66
+ flexDirection: 'column',
67
+ height: '100vh',
68
+ overflow: 'hidden',
44
69
  }}
45
70
  >
46
- {children}
47
- </MainContent>
71
+ {/* AppBar - Top of main content area */}
72
+ <AppBar
73
+ rightSection={rightSection}
74
+ centerSection={centerSection}
75
+ hideHamburger={!isSmallScreen}
76
+ onToggleSidebar={toggleSidebar}
77
+ />
48
78
 
49
- {/* Floating Help Docs - Route-aware contextual help */}
50
- {helpDocsActions.length > 0 && (
51
- <FloatingHelpDocs actions={helpDocsActions} />
52
- )}
79
+ {/* Main Content */}
80
+ <MainContent
81
+ sx={{
82
+ ...mainContainerSx,
83
+ height: `calc(100vh - 90px)`,
84
+ overflow: 'scroll',
85
+ }}
86
+ >
87
+ {children}
88
+ </MainContent>
89
+
90
+ {/* Floating Help Docs - Route-aware contextual help */}
91
+ {helpDocsActions.length > 0 && (
92
+ <FloatingHelpDocs actions={helpDocsActions} />
93
+ )}
94
+ </motion.div>
53
95
  </AppLayoutContainer>
54
96
  );
55
97
  };
56
98
 
57
99
  const AppLayoutContainer = styled(Stack)(({ theme }: { theme?: any }) => ({
58
- flexDirection: 'column',
59
- backgroundColor: theme.palette.surface.defaultBackground,
100
+ flexDirection: 'row',
101
+ backgroundColor: theme.palette.surface.paperBackground,
60
102
  height: '100vh',
61
- overflow: 'scroll',
103
+ overflow: 'hidden',
62
104
  }));
63
105
 
64
106
  const MainContent = styled(Box)(({ theme }: { theme?: any }) => ({
65
- borderRadius: '8px',
66
107
  flex: 1,
67
108
  maxWidth: '1440px', // Max width for content
68
109
  width: '100%',
@@ -1,16 +1,7 @@
1
- import {
2
- IconButton,
3
- Stack,
4
- styled,
5
- useMediaQuery,
6
- useTheme,
7
- } from '@mui/material';
8
- import React, { useState } from 'react';
9
- import { CampxFullLogoIconV2 } from '../../../Assets/Icons/IconComponents/CampxFullLogoIconV2';
1
+ import { IconButton, Stack, styled, useTheme } from '@mui/material';
2
+ import React from 'react';
10
3
  import { CampxIconV2 } from '../../../Assets/Icons/IconComponents/CampxIconV2';
11
4
  import { HamburgerMenuIcon } from '../../../Assets/Icons/IconComponents/HamburgerMenuIcon';
12
- import { SideDrawer } from './SideDrawer';
13
- import { SideMenuItemProps } from './Sidebar/interfaces';
14
5
 
15
6
  const AppBarContainer = styled('header')(({ theme }: { theme?: any }) => ({
16
7
  display: 'flex',
@@ -19,12 +10,12 @@ const AppBarContainer = styled('header')(({ theme }: { theme?: any }) => ({
19
10
  justifyContent: 'space-between',
20
11
  position: 'relative', // Add relative positioning for absolute center positioning
21
12
  width: '100%',
22
- height: '64px',
23
- minHeight: '64px',
13
+ height: '54px',
14
+ minHeight: '54px',
24
15
  backgroundColor: theme.palette.surface.paperBackground,
25
16
  padding: '0 24px 0 0',
26
17
  flexShrink: 0, // Prevent AppBar from shrinking
27
-
18
+ borderBottom: `1px solid ${theme.palette.divider}`,
28
19
  [theme.breakpoints.down('md')]: {
29
20
  height: '54px',
30
21
  minHeight: '54px',
@@ -43,49 +34,51 @@ interface AppBarProps {
43
34
  rightSection?: React.ReactNode;
44
35
  /** Center section component (workspace switcher, etc.) */
45
36
  centerSection?: React.ReactNode;
46
- /** Menu items for mobile drawer */
47
- menu?: SideMenuItemProps[];
48
37
  /** Custom className for the AppBar */
49
38
  className?: string;
50
39
  /** Custom styles for the AppBar */
51
40
  sx?: any;
41
+ /** Hide hamburger menu (for persistent sidebar mode) */
42
+ hideHamburger?: boolean;
43
+ /** Callback to toggle sidebar (for persistent sidebar mode on mobile) */
44
+ onToggleSidebar?: () => void;
52
45
  }
53
46
 
54
47
  export const AppBar: React.FC<AppBarProps> = ({
55
48
  rightSection,
56
49
  centerSection,
57
- menu = [],
58
50
  className = 'appHeaderV2',
59
51
  sx = {},
52
+ hideHamburger = false,
53
+ onToggleSidebar = () => {},
60
54
  }) => {
61
55
  const theme = useTheme();
62
- const isMobile = useMediaQuery(theme.breakpoints.down('md'));
63
- const [drawerOpen, setDrawerOpen] = useState(false);
64
-
65
- const toggleDrawer = () => {
66
- setDrawerOpen(!drawerOpen);
67
- };
68
56
 
69
57
  return (
70
- <AppBarContainer className={className} sx={sx}>
71
- {/* Left section - Hamburger + Logo */}
72
- <Stack direction="row" alignItems="center" gap="12px" height="100%">
73
- <IconButton
74
- onClick={toggleDrawer}
75
- sx={{
76
- padding: '24px',
77
- backgroundColor: theme.palette.secondary.light,
78
- borderRadius: '0px',
79
- [theme.breakpoints.down('md')]: {
80
- padding: '20px',
81
- },
82
- }}
83
- >
84
- <HamburgerMenuIcon />
85
- </IconButton>
86
- {/* CampX Logo - Full logo on desktop, icon on mobile */}
87
- {isMobile ? <CampxIconV2 /> : <CampxFullLogoIconV2 size={28} />}
88
- </Stack>
58
+ <AppBarContainer
59
+ className={className}
60
+ sx={{
61
+ ...sx,
62
+ justifyContent: hideHamburger ? 'flex-end' : 'space-between',
63
+ }}
64
+ >
65
+ {/* Left section - Hamburger + Logo (only show if not hidden) */}
66
+ {!hideHamburger && (
67
+ <Stack gap={'4px'} direction={'row'} alignItems={'center'}>
68
+ <IconButton
69
+ onClick={onToggleSidebar}
70
+ sx={{
71
+ padding: '24px',
72
+ [theme.breakpoints.down('md')]: {
73
+ padding: '20px',
74
+ },
75
+ }}
76
+ >
77
+ <HamburgerMenuIcon />
78
+ </IconButton>
79
+ <CampxIconV2 />
80
+ </Stack>
81
+ )}
89
82
 
90
83
  {/* Center section - Custom content from props */}
91
84
  {centerSection && (
@@ -115,13 +108,6 @@ export const AppBar: React.FC<AppBarProps> = ({
115
108
  {rightSection}
116
109
  </Stack>
117
110
  )}
118
-
119
- {/* Side Drawer */}
120
- <SideDrawer
121
- open={drawerOpen}
122
- onClose={() => setDrawerOpen(false)}
123
- menu={menu}
124
- />
125
111
  </AppBarContainer>
126
112
  );
127
113
  };