@campxdev/react-blueprint 1.7.6 → 1.7.8

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 (33) hide show
  1. package/package.json +1 -1
  2. package/src/assets/images/svg/index.ts +1 -1
  3. package/src/components/Assets/ErrorPages/InternalServerError.tsx +2 -2
  4. package/src/components/Assets/ErrorPages/NoInternetConnection.tsx +2 -2
  5. package/src/components/Assets/ErrorPages/NoItemFound.tsx +2 -2
  6. package/src/components/Assets/ErrorPages/PageNotFound.tsx +2 -2
  7. package/src/components/Assets/ErrorPages/UnAuthorized.tsx +2 -2
  8. package/src/components/Assets/Icons/IconComponents/HamburgerMenuIcon.tsx +20 -0
  9. package/src/components/Assets/Icons/IconComponents/ObeIcon.tsx +3 -3
  10. package/src/components/Assets/Icons/IconComponents/ReportIssueIcon.tsx +53 -0
  11. package/src/components/Assets/Icons/Icons.tsx +4 -0
  12. package/src/components/DataDisplay/DataTable/DataTable.tsx +1 -3
  13. package/src/components/DataDisplay/EmptyIllustration/EmptyIllustration.tsx +2 -2
  14. package/src/components/DataDisplay/StatusCard/StatusCard.tsx +67 -0
  15. package/src/components/DataDisplay/export.ts +1 -0
  16. package/src/components/Feedback/Snackbar/Snackbar.tsx +37 -26
  17. package/src/components/Input/SingleSelect/components/SingleInput.tsx +13 -10
  18. package/src/components/Layout/AppHeader/AppHeader.tsx +39 -22
  19. package/src/components/Layout/AppHeader/styles/styles.tsx +13 -1
  20. package/src/components/Navigation/Breadcrumbs/Breadcrumbs.tsx +4 -0
  21. package/src/components/Navigation/PreviewFiles/PreviewFiles.tsx +115 -21
  22. package/src/components/Navigation/Sidebar/MenuBar.tsx +176 -0
  23. package/src/components/Navigation/Sidebar/Sidebar.tsx +94 -190
  24. package/src/components/Navigation/Sidebar/styles.tsx +24 -9
  25. package/src/components/Navigation/TabsContainer/TabsContainer.tsx +4 -0
  26. package/src/components/Navigation/UploadDialog/Styles.tsx +1 -1
  27. package/src/components/Navigation/UploadDialog/UploadDialog.tsx +17 -27
  28. package/src/components/Navigation/UploadDialog/UploadDialogContainer.tsx +9 -7
  29. package/src/stories/DataDisplay/StatusCard.stories.tsx +62 -0
  30. package/src/stories/Input/SingleSelect.stories.tsx +6 -1
  31. package/src/stories/Navigation/PreviewFiles.stories.tsx +33 -64
  32. package/src/stories/Navigation/TabsContainer.stories.tsx +11 -1
  33. package/src/themes/commonTheme.ts +9 -7
@@ -1,32 +1,56 @@
1
1
  import {
2
2
  Box,
3
3
  BoxProps,
4
+ IconButton,
4
5
  Stack,
5
6
  styled,
6
7
  Typography,
7
8
  useTheme,
8
9
  } from '@mui/material';
9
- import { FC, ReactNode, useCallback, useMemo, useState } from 'react';
10
+ import { FC, useCallback, useEffect, useState } from 'react';
10
11
  import { Icons } from '../../export';
11
12
 
12
13
  export type PreviewFilesProps = {
13
- files: File[] | File | null;
14
+ files: File[] | File | string[] | string | null;
14
15
  label?: string;
15
- actions?: (file: File) => ReactNode;
16
- } & BoxProps;
16
+ onChange?: (newFiles: File[], deletedFile: File) => void;
17
+ showDownload?: boolean;
18
+ } & Omit<BoxProps, 'onChange'>;
17
19
 
18
20
  export const PreviewFiles = ({
19
21
  files,
20
22
  label,
21
- actions,
23
+ onChange,
24
+ showDownload,
22
25
  ...props
23
26
  }: PreviewFilesProps) => {
24
- const theme = useTheme();
25
- const [previews, setPreviews] = useState<Record<string, string>>({});
27
+ const theme = useTheme(),
28
+ [previews, setPreviews] = useState<Record<string, string>>({}),
29
+ [resolvedFiles, setResolvedFiles] = useState<File[]>([]);
26
30
 
27
- const fileArray = useMemo(() => {
28
- if (Array.isArray(files)) return files;
29
- return files ? [files] : [];
31
+ useEffect(() => {
32
+ const resolveFiles = async () => {
33
+ if (!files) {
34
+ setResolvedFiles([]);
35
+ return;
36
+ }
37
+
38
+ if (Array.isArray(files)) {
39
+ const promises = files.map((file) =>
40
+ typeof file === 'string'
41
+ ? createFileFromUrl(file)
42
+ : Promise.resolve(file),
43
+ );
44
+ const resolved = await Promise.all(promises);
45
+ setResolvedFiles(resolved);
46
+ } else {
47
+ const singleFile =
48
+ typeof files === 'string' ? await createFileFromUrl(files) : files;
49
+ setResolvedFiles([singleFile]);
50
+ }
51
+ };
52
+
53
+ resolveFiles();
30
54
  }, [files]);
31
55
 
32
56
  const handleFilePreview = useCallback(
@@ -48,7 +72,18 @@ export const PreviewFiles = ({
48
72
  [previews],
49
73
  );
50
74
 
51
- if (fileArray.length === 0) return null;
75
+ const handleDownload = (file: File) => {
76
+ const url = URL.createObjectURL(file);
77
+ const a = document.createElement('a');
78
+ a.href = url;
79
+ a.download = file.name;
80
+ document.body.appendChild(a);
81
+ a.click();
82
+ document.body.removeChild(a);
83
+ URL.revokeObjectURL(url);
84
+ };
85
+
86
+ if (resolvedFiles.length === 0) return <></>;
52
87
 
53
88
  return (
54
89
  <Box {...props}>
@@ -62,7 +97,7 @@ export const PreviewFiles = ({
62
97
  {label}
63
98
  </Typography>
64
99
  )}
65
- {fileArray.map((file, index) => (
100
+ {resolvedFiles.map((file, index) => (
66
101
  <PreviewContainer key={index} onClick={() => handleFilePreview(file)}>
67
102
  <Stack
68
103
  direction={'row'}
@@ -83,15 +118,29 @@ export const PreviewFiles = ({
83
118
  </Stack>
84
119
  </Stack>
85
120
 
86
- {actions && (
87
- <Box
88
- onClick={(event: React.MouseEvent<HTMLDivElement>) => {
89
- event.stopPropagation();
90
- }}
91
- >
92
- {actions(file)}
93
- </Box>
94
- )}
121
+ <Box
122
+ onClick={(event: React.MouseEvent<HTMLDivElement>) => {
123
+ event.stopPropagation();
124
+ }}
125
+ >
126
+ {showDownload && (
127
+ <IconButton onClick={() => handleDownload(file)}>
128
+ <Icons.DownloadIcon />
129
+ </IconButton>
130
+ )}
131
+ {onChange && (
132
+ <IconButton
133
+ onClick={() => {
134
+ onChange(
135
+ resolvedFiles.filter((f, i) => i !== index),
136
+ file,
137
+ );
138
+ }}
139
+ >
140
+ <Icons.DeleteIcon />
141
+ </IconButton>
142
+ )}
143
+ </Box>
95
144
  </PreviewContainer>
96
145
  ))}
97
146
  </Box>
@@ -138,3 +187,48 @@ const getFileIcon = (file: File) => {
138
187
  )?.[1] || Icons.AttachmentIcon;
139
188
  return <IconComponent size={30} />;
140
189
  };
190
+
191
+ const createFileFromUrl = async (fileUrl: string): Promise<File> => {
192
+ const extensionToMimeType: Record<string, string> = {
193
+ '.jpg': 'image/jpeg',
194
+ '.jpeg': 'image/jpeg',
195
+ '.png': 'image/png',
196
+ '.gif': 'image/gif',
197
+ '.pdf': 'application/pdf',
198
+ '.xlsx':
199
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
200
+ '.xls': 'application/vnd.ms-excel',
201
+ '.doc': 'application/msword',
202
+ '.docx':
203
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
204
+ '.txt': 'text/plain',
205
+ };
206
+
207
+ const fileName = fileUrl.split('/').pop() || 'unknown_file',
208
+ extension = Object.keys(extensionToMimeType).find((ext) =>
209
+ fileUrl.endsWith(ext),
210
+ ),
211
+ mimeType = extension
212
+ ? extensionToMimeType[extension]
213
+ : 'application/octet-stream';
214
+
215
+ try {
216
+ // Fetch the file from the given URL
217
+ const response = await fetch(fileUrl);
218
+ if (!response.ok) {
219
+ throw new Error(`Failed to fetch file from ${fileUrl}`);
220
+ }
221
+
222
+ // Convert the response to a Blob
223
+ const blob = await response.blob();
224
+
225
+ // Create and return a File object from the Blob
226
+ return new File([blob], fileName, {
227
+ type: mimeType,
228
+ lastModified: Date.now(),
229
+ });
230
+ } catch (error) {
231
+ console.error(`Error creating file from URL: ${error}`);
232
+ throw error;
233
+ }
234
+ };
@@ -0,0 +1,176 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ import { Icons, SideMenuItemProps, Typography } from '../../export';
3
+ import {
4
+ GetActiveMenuProps,
5
+ InternalMenuClickHandlerProps,
6
+ MenuState,
7
+ } from './interfaces';
8
+ import { SideBarMenuItem } from './MenuItem';
9
+ import { createSidebarStyles } from './styles';
10
+
11
+ export const MenuBar = ({
12
+ menu,
13
+ collapsed,
14
+ setCollapsed,
15
+ menuPosition,
16
+ setMenuPosition,
17
+ }: {
18
+ menu: SideMenuItemProps[];
19
+ collapsed: boolean;
20
+ setCollapsed: any;
21
+ menuPosition: number;
22
+ setMenuPosition: any;
23
+ }) => {
24
+ const [currentMenuState, setCurrentMenuState] = useState<MenuState>({
25
+ menu: menu,
26
+ title: null,
27
+ path: null,
28
+ });
29
+ const [history, setHistory] = useState<MenuState[]>([]);
30
+
31
+ const internalMenuClickHandler = ({
32
+ menuTitle,
33
+ menuPath,
34
+ internalMenu,
35
+ }: InternalMenuClickHandlerProps) => {
36
+ if (menuTitle && menuPath && internalMenu) {
37
+ setHistory((prev) => [
38
+ ...prev,
39
+ {
40
+ title: currentMenuState.title,
41
+ path: currentMenuState.path,
42
+ menu: currentMenuState.menu,
43
+ },
44
+ ]);
45
+
46
+ setCurrentMenuState({
47
+ title: menuTitle,
48
+ path: menuPath,
49
+ menu: internalMenu,
50
+ });
51
+
52
+ setMenuPosition(collapsed ? 60 : 250);
53
+ }
54
+ };
55
+
56
+ const previousMenuClickHandler = () => {
57
+ const prev = history && history.length > 0 && history.pop();
58
+
59
+ if (prev && prev.menu) {
60
+ setCollapsed(false);
61
+ setCurrentMenuState({
62
+ menu: prev.menu,
63
+ title: prev.title,
64
+ path: prev.path,
65
+ });
66
+ setHistory([...history]);
67
+ setMenuPosition(collapsed ? -60 : -250);
68
+ }
69
+ };
70
+
71
+ const getActiveMenu = ({
72
+ menu,
73
+ pathArray,
74
+ previousMenuState,
75
+ }: GetActiveMenuProps): MenuState => {
76
+ setHistory((prevHistory) => [
77
+ ...prevHistory,
78
+ {
79
+ title: previousMenuState?.title,
80
+ path: previousMenuState?.path,
81
+ menu: previousMenuState.menu,
82
+ },
83
+ ]);
84
+
85
+ const item = menu.find((item: any) => item.path === `/${pathArray[0]}`);
86
+
87
+ if (item) {
88
+ if (!item.menu) {
89
+ return previousMenuState;
90
+ } else if (pathArray.length > 1) {
91
+ return getActiveMenu({
92
+ menu: item.menu,
93
+ pathArray: pathArray.slice(1),
94
+ previousMenuState: {
95
+ title: item.name,
96
+ path: previousMenuState.path
97
+ ? previousMenuState.path + item.path
98
+ : item.path,
99
+ menu: item.menu,
100
+ },
101
+ });
102
+ } else {
103
+ return {
104
+ title: item.name,
105
+ path: previousMenuState.path
106
+ ? previousMenuState.path + item.path
107
+ : item.path,
108
+ menu: item.menu,
109
+ };
110
+ }
111
+ } else {
112
+ return previousMenuState;
113
+ }
114
+ };
115
+
116
+ useEffect(() => {
117
+ const currentPathArray = window.location.pathname.split('/');
118
+
119
+ if (currentPathArray.length > 2) {
120
+ currentPathArray.splice(0, 2);
121
+ currentPathArray.pop();
122
+ }
123
+
124
+ const activeMenu = getActiveMenu({
125
+ menu: currentMenuState.menu,
126
+ pathArray: currentPathArray,
127
+ previousMenuState: currentMenuState,
128
+ });
129
+
130
+ setCurrentMenuState({
131
+ title: activeMenu?.title,
132
+ path: activeMenu.path,
133
+ menu: activeMenu?.menu,
134
+ });
135
+ }, []);
136
+
137
+ const { StyledMenuBar, StyledMenuHeaderButton } = useMemo(
138
+ () => createSidebarStyles(collapsed),
139
+ [collapsed, menuPosition],
140
+ );
141
+ return (
142
+ <StyledMenuBar>
143
+ {currentMenuState.title && (
144
+ <StyledMenuHeaderButton
145
+ direction="row"
146
+ justifyContent={collapsed ? 'center' : 'flex-start'}
147
+ onClick={() => previousMenuClickHandler()}
148
+ >
149
+ {collapsed ? (
150
+ <Icons.ArrowBackIcon size={20} />
151
+ ) : (
152
+ <>
153
+ <Icons.ArrowBackIcon size={20} />
154
+ <Typography variant="button1">
155
+ {currentMenuState.title}
156
+ </Typography>
157
+ </>
158
+ )}
159
+ </StyledMenuHeaderButton>
160
+ )}
161
+ {currentMenuState.menu &&
162
+ currentMenuState.menu.length > 0 &&
163
+ currentMenuState.menu?.map((item: any, index: number) => (
164
+ <SideBarMenuItem
165
+ key={index}
166
+ index={index}
167
+ collapsed={collapsed}
168
+ setCollapsed={setCollapsed}
169
+ menuItem={item}
170
+ currentMenuPath={currentMenuState.path}
171
+ internalMenuClickHandler={internalMenuClickHandler}
172
+ />
173
+ ))}
174
+ </StyledMenuBar>
175
+ );
176
+ };
@@ -1,18 +1,19 @@
1
- import { Box } from '@mui/material';
1
+ import {
2
+ Box,
3
+ Drawer,
4
+ IconButton,
5
+ Stack,
6
+ useMediaQuery,
7
+ useTheme,
8
+ } from '@mui/material';
2
9
  import { motion } from 'framer-motion';
3
- import { ReactElement, useEffect, useMemo, useState } from 'react';
10
+ import { ReactElement, useMemo, useState } from 'react';
4
11
  import { CampxFullLogoIcon } from '../../Assets/Icons/IconComponents/CampxFullLogoIcon';
5
12
  import { CampxIcon } from '../../Assets/Icons/IconComponents/CampxIcon';
13
+ import { HamburgerMenuIcon } from '../../Assets/Icons/IconComponents/HamburgerMenuIcon';
6
14
  import { RightIcon } from '../../Assets/Icons/IconComponents/RightIcon';
7
- import { Typography } from '../../DataDisplay/Typography/Typography';
8
- import { Icons } from '../../export';
9
15
  import { CollapseMenuButton } from './Components';
10
- import { SideBarMenuItem } from './MenuItem';
11
- import {
12
- GetActiveMenuProps,
13
- InternalMenuClickHandlerProps,
14
- MenuState,
15
- } from './interfaces';
16
+ import { MenuBar } from './MenuBar';
16
17
  import { createSidebarStyles } from './styles';
17
18
 
18
19
  export const Sidebar = ({
@@ -24,142 +25,34 @@ export const Sidebar = ({
24
25
  collapsed: boolean;
25
26
  setCollapsed: any;
26
27
  }) => {
27
- const [menuPosition, setMenuPosition] = useState(0);
28
+ const theme = useTheme();
29
+ const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
28
30
 
29
- const [history, setHistory] = useState<MenuState[]>([]);
30
- const [currentMenuState, setCurrentMenuState] = useState<MenuState>({
31
- menu: menu,
32
- title: null,
33
- path: null,
34
- });
31
+ const [menuPosition, setMenuPosition] = useState(0);
35
32
 
36
33
  const toggleSidebar = () => {
37
34
  setMenuPosition(0);
38
35
  setCollapsed(!collapsed);
39
36
  };
40
37
 
41
- const internalMenuClickHandler = ({
42
- menuTitle,
43
- menuPath,
44
- internalMenu,
45
- }: InternalMenuClickHandlerProps) => {
46
- if (menuTitle && menuPath && internalMenu) {
47
- setHistory((prev) => [
48
- ...prev,
49
- {
50
- title: currentMenuState.title,
51
- path: currentMenuState.path,
52
- menu: currentMenuState.menu,
53
- },
54
- ]);
55
-
56
- setCurrentMenuState({
57
- title: menuTitle,
58
- path: menuPath,
59
- menu: internalMenu,
60
- });
61
-
62
- setMenuPosition(collapsed ? 60 : 250);
63
- }
64
- };
65
-
66
- const previousMenuClickHandler = () => {
67
- const prev = history && history.length > 0 && history.pop();
68
-
69
- if (prev && prev.menu) {
70
- setCollapsed(false);
71
- setCurrentMenuState({
72
- menu: prev.menu,
73
- title: prev.title,
74
- path: prev.path,
75
- });
76
- setHistory([...history]);
77
- setMenuPosition(collapsed ? -60 : -250);
78
- }
79
- };
80
-
81
- const getActiveMenu = ({
82
- menu,
83
- pathArray,
84
- previousMenuState,
85
- }: GetActiveMenuProps): MenuState => {
86
- setHistory((prevHistory) => [
87
- ...prevHistory,
88
- {
89
- title: previousMenuState?.title,
90
- path: previousMenuState?.path,
91
- menu: previousMenuState.menu,
92
- },
93
- ]);
38
+ const toggleDrawer =
39
+ (open: boolean | ((prevState: boolean) => boolean)) => () => {
40
+ // setIsDrawerOpen(open);
41
+ setCollapsed(!collapsed);
42
+ };
94
43
 
95
- const item = menu.find((item: any) => item.path === `/${pathArray[0]}`);
96
-
97
- if (item) {
98
- if (!item.menu) {
99
- return previousMenuState;
100
- } else if (pathArray.length > 1) {
101
- return getActiveMenu({
102
- menu: item.menu,
103
- pathArray: pathArray.slice(1),
104
- previousMenuState: {
105
- title: item.name,
106
- path: previousMenuState.path
107
- ? previousMenuState.path + item.path
108
- : item.path,
109
- menu: item.menu,
110
- },
111
- });
112
- } else {
113
- return {
114
- title: item.name,
115
- path: previousMenuState.path
116
- ? previousMenuState.path + item.path
117
- : item.path,
118
- menu: item.menu,
119
- };
120
- }
121
- } else {
122
- return previousMenuState;
123
- }
124
- };
125
-
126
- useEffect(() => {
127
- const currentPathArray = window.location.pathname.split('/');
128
-
129
- if (currentPathArray.length > 2) {
130
- currentPathArray.splice(0, 2);
131
- currentPathArray.pop();
132
- }
133
-
134
- const activeMenu = getActiveMenu({
135
- menu: currentMenuState.menu,
136
- pathArray: currentPathArray,
137
- previousMenuState: currentMenuState,
138
- });
139
-
140
- setCurrentMenuState({
141
- title: activeMenu?.title,
142
- path: activeMenu.path,
143
- menu: activeMenu?.menu,
144
- });
145
- }, []);
146
-
147
- const {
148
- StyledSidebarContainer,
149
- StyledLogoArea,
150
- StyledMenuBar,
151
- StyledCollapsibleSection,
152
- StyledMenuHeaderButton,
153
- StyledListItemIcon,
154
- } = useMemo(() => createSidebarStyles(collapsed), [collapsed, menuPosition]);
44
+ const { StyledSidebarContainer, StyledLogoArea, StyledCollapsibleSection } =
45
+ useMemo(() => createSidebarStyles(collapsed), [collapsed, menuPosition]);
155
46
 
156
47
  return (
157
48
  <motion.div
158
- animate={{ width: collapsed ? '60px' : '250px' }}
49
+ animate={
50
+ !isSmallScreen ? { width: collapsed ? '60px' : '250px' } : undefined
51
+ }
159
52
  transition={{ duration: 0.3, ease: 'circOut' }}
160
53
  style={{
161
- margin: '12px',
162
- height: 'calc(100vh - 24px)',
54
+ margin: isSmallScreen ? '12px 12px 0px 12px' : '12px',
55
+ height: isSmallScreen ? '100%' : 'calc(100vh - 24px)',
163
56
  }}
164
57
  >
165
58
  <StyledSidebarContainer
@@ -169,66 +62,77 @@ export const Sidebar = ({
169
62
  >
170
63
  <Box>
171
64
  <StyledLogoArea collapsed={collapsed}>
172
- {collapsed ? <CampxIcon size={32} /> : <CampxFullLogoIcon />}
65
+ {isSmallScreen || collapsed ? (
66
+ <CampxIcon size={isSmallScreen ? 24 : 32} />
67
+ ) : (
68
+ <CampxFullLogoIcon />
69
+ )}
173
70
  </StyledLogoArea>
174
71
  </Box>
175
72
 
176
- <motion.div
177
- initial={{ x: menuPosition }}
178
- animate={{ x: 0 }}
179
- transition={{
180
- duration: 0.3,
181
- ease: menuPosition ? 'circOut' : 'circIn',
182
- }}
183
- style={{
184
- height: '100%',
185
- }}
186
- >
187
- <StyledMenuBar>
188
- {currentMenuState.title && (
189
- <StyledMenuHeaderButton
190
- direction="row"
191
- justifyContent={collapsed ? 'center' : 'flex-start'}
192
- onClick={() => previousMenuClickHandler()}
193
- >
194
- {collapsed ? (
195
- <Icons.ArrowBackIcon size={20} />
196
- ) : (
197
- <>
198
- <Icons.ArrowBackIcon size={20} />
199
- <Typography variant="button1">
200
- {currentMenuState.title}
201
- </Typography>
202
- </>
203
- )}
204
- </StyledMenuHeaderButton>
205
- )}
206
- {currentMenuState.menu &&
207
- currentMenuState.menu.length > 0 &&
208
- currentMenuState.menu?.map((item: any, index: number) => (
209
- <SideBarMenuItem
210
- key={index}
211
- index={index}
212
- collapsed={collapsed}
213
- setCollapsed={setCollapsed}
214
- menuItem={item}
215
- currentMenuPath={currentMenuState.path}
216
- internalMenuClickHandler={internalMenuClickHandler}
217
- />
218
- ))}
219
- </StyledMenuBar>
220
- </motion.div>
221
- <StyledCollapsibleSection
222
- className="collapsibleSection"
223
- onClick={toggleSidebar}
224
- collapsed={collapsed}
225
- >
226
- {collapsed ? (
227
- <RightIcon size={32} />
228
- ) : (
229
- <CollapseMenuButton collapsed={collapsed} />
230
- )}
231
- </StyledCollapsibleSection>
73
+ {isSmallScreen ? (
74
+ <Stack alignItems={'flex-start'}>
75
+ <IconButton
76
+ onClick={toggleDrawer(true)}
77
+ sx={{ padding: '8px 0px ' }}
78
+ >
79
+ <HamburgerMenuIcon />
80
+ </IconButton>
81
+
82
+ <Drawer
83
+ variant="temporary"
84
+ anchor="left"
85
+ open={!collapsed}
86
+ onClose={toggleDrawer(false)}
87
+ transitionDuration={300}
88
+ SlideProps={{
89
+ direction: 'right',
90
+ timeout: { enter: 500, exit: 500 },
91
+ }}
92
+ >
93
+ <MenuBar
94
+ menu={menu}
95
+ collapsed={collapsed}
96
+ setCollapsed={setCollapsed}
97
+ menuPosition={menuPosition}
98
+ setMenuPosition={setMenuPosition}
99
+ />
100
+ </Drawer>
101
+ </Stack>
102
+ ) : (
103
+ <>
104
+ <motion.div
105
+ initial={{ x: menuPosition }}
106
+ animate={{ x: 0 }}
107
+ transition={{
108
+ duration: 0.3,
109
+ ease: menuPosition ? 'circOut' : 'circIn',
110
+ }}
111
+ style={{
112
+ height: '100%',
113
+ }}
114
+ >
115
+ <MenuBar
116
+ menu={menu}
117
+ collapsed={collapsed}
118
+ setCollapsed={setCollapsed}
119
+ menuPosition={menuPosition}
120
+ setMenuPosition={setMenuPosition}
121
+ />
122
+ </motion.div>
123
+ <StyledCollapsibleSection
124
+ className="collapsibleSection"
125
+ onClick={toggleSidebar}
126
+ collapsed={collapsed}
127
+ >
128
+ {collapsed ? (
129
+ <RightIcon size={32} />
130
+ ) : (
131
+ <CollapseMenuButton collapsed={collapsed} />
132
+ )}
133
+ </StyledCollapsibleSection>
134
+ </>
135
+ )}
232
136
  </StyledSidebarContainer>
233
137
  </motion.div>
234
138
  );