mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-22 07:08:44 +00:00
SPRINT-18: fixed to dashboards, removed and moved around all the things
This commit is contained in:
358
src/qqq/components/horseshoe/sidenav/SideNav.tsx
Normal file
358
src/qqq/components/horseshoe/sidenav/SideNav.tsx
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Box from "@mui/material/Box";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import Link from "@mui/material/Link";
|
||||
import List from "@mui/material/List";
|
||||
import {ReactNode, useEffect, useReducer, useState} from "react";
|
||||
import {NavLink, useLocation} from "react-router-dom";
|
||||
import {setMiniSidenav, setTransparentSidenav, setWhiteSidenav, useMaterialUIController,} from "qqq/context";
|
||||
import AuthenticationButton from "qqq/components/buttons/AuthenticationButton";
|
||||
import SideNavCollapse from "qqq/components/horseshoe/sidenav/SideNavCollapse";
|
||||
import SideNavItem from "qqq/components/horseshoe/sidenav/SideNavItem";
|
||||
import SideNavList from "qqq/components/horseshoe/sidenav/SideNavList";
|
||||
import SidenavRoot from "qqq/components/horseshoe/sidenav/SideNavRoot";
|
||||
import sidenavLogoLabel from "qqq/components/horseshoe/sidenav/styles/SideNav";
|
||||
import MDTypography from "qqq/components/legacy/MDTypography";
|
||||
|
||||
|
||||
interface Props
|
||||
{
|
||||
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark";
|
||||
icon?: string;
|
||||
logo?: string;
|
||||
companyName?: string;
|
||||
routes: {
|
||||
[key: string]:
|
||||
| ReactNode
|
||||
| string
|
||||
| {
|
||||
[key: string]:
|
||||
| ReactNode
|
||||
| string
|
||||
| {
|
||||
[key: string]:
|
||||
| ReactNode
|
||||
| string
|
||||
| {
|
||||
[key: string]: ReactNode | string;
|
||||
}[];
|
||||
}[];
|
||||
}[];
|
||||
}[];
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
function Sidenav({color, icon, logo, companyName, routes, ...rest}: Props): JSX.Element
|
||||
{
|
||||
const [openCollapse, setOpenCollapse] = useState<boolean | string>(false);
|
||||
const [openNestedCollapse, setOpenNestedCollapse] = useState<boolean | string>(false);
|
||||
const [controller, dispatch] = useMaterialUIController();
|
||||
const {miniSidenav, transparentSidenav, whiteSidenav, darkMode} = controller;
|
||||
const location = useLocation();
|
||||
const {pathname} = location;
|
||||
const collapseName = pathname.split("/").slice(1)[0];
|
||||
const items = pathname.split("/").slice(1);
|
||||
const itemParentName = items[1];
|
||||
const itemName = items[items.length - 1];
|
||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||
|
||||
let textColor:
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "info"
|
||||
| "success"
|
||||
| "warning"
|
||||
| "error"
|
||||
| "dark"
|
||||
| "white"
|
||||
| "inherit"
|
||||
| "text"
|
||||
| "light" = "white";
|
||||
|
||||
if (transparentSidenav || (whiteSidenav && !darkMode))
|
||||
{
|
||||
textColor = "dark";
|
||||
}
|
||||
else if (whiteSidenav && darkMode)
|
||||
{
|
||||
textColor = "inherit";
|
||||
}
|
||||
|
||||
const closeSidenav = () => setMiniSidenav(dispatch, true);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
setOpenCollapse(collapseName);
|
||||
setOpenNestedCollapse(itemParentName);
|
||||
}, []);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
// A function that sets the mini state of the sidenav.
|
||||
function handleMiniSidenav()
|
||||
{
|
||||
setMiniSidenav(dispatch, window.innerWidth < 1200);
|
||||
setTransparentSidenav(dispatch, window.innerWidth < 1200 ? false : transparentSidenav);
|
||||
setWhiteSidenav(dispatch, window.innerWidth < 1200 ? false : whiteSidenav);
|
||||
}
|
||||
|
||||
/**
|
||||
The event listener that's calling the handleMiniSidenav function when resizing the window.
|
||||
*/
|
||||
window.addEventListener("resize", handleMiniSidenav);
|
||||
window.onload = () =>
|
||||
{
|
||||
forceUpdate();
|
||||
};
|
||||
|
||||
// Call the handleMiniSidenav function to set the state with the initial value.
|
||||
handleMiniSidenav();
|
||||
|
||||
// Remove event listener on cleanup
|
||||
return () => window.removeEventListener("resize", handleMiniSidenav);
|
||||
}, [dispatch, location]);
|
||||
|
||||
// Render all the nested collapse items from the routes.js
|
||||
const renderNestedCollapse = (collapse: any) =>
|
||||
{
|
||||
const template = collapse.map(({name, route, key, href}: any) =>
|
||||
href ? (
|
||||
<Link
|
||||
key={key}
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
sx={{textDecoration: "none"}}
|
||||
>
|
||||
<SideNavItem name={name} nested />
|
||||
</Link>
|
||||
) : (
|
||||
<NavLink to={route} key={key} style={{textDecoration: "none"}}>
|
||||
<SideNavItem name={name} active={route === pathname} nested />
|
||||
</NavLink>
|
||||
)
|
||||
);
|
||||
|
||||
return template;
|
||||
};
|
||||
// Render the all the collpases from the routes.js
|
||||
const renderCollapse = (collapses: any) =>
|
||||
collapses.map(({name, collapse, route, href, key}: any) =>
|
||||
{
|
||||
let returnValue;
|
||||
|
||||
if (collapse)
|
||||
{
|
||||
returnValue = (
|
||||
<SideNavItem
|
||||
key={key}
|
||||
color={color}
|
||||
name={name}
|
||||
active={key === itemParentName ? "isParent" : false}
|
||||
open={openNestedCollapse === key}
|
||||
onClick={({currentTarget}: any) =>
|
||||
openNestedCollapse === key && currentTarget.classList.contains("MuiListItem-root")
|
||||
? setOpenNestedCollapse(false)
|
||||
: setOpenNestedCollapse(key)
|
||||
}
|
||||
>
|
||||
{renderNestedCollapse(collapse)}
|
||||
</SideNavItem>
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = href ? (
|
||||
<Link
|
||||
href={href}
|
||||
key={key}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
sx={{textDecoration: "none"}}
|
||||
>
|
||||
<SideNavItem color={color} name={name} active={key === itemName} />
|
||||
</Link>
|
||||
) : (
|
||||
<NavLink to={route} key={key} style={{textDecoration: "none"}}>
|
||||
<SideNavItem color={color} name={name} active={key === itemName} />
|
||||
</NavLink>
|
||||
);
|
||||
}
|
||||
return <SideNavList key={key}>{returnValue}</SideNavList>;
|
||||
});
|
||||
|
||||
// Render all the routes from the routes.js (All the visible items on the Sidenav)
|
||||
const renderRoutes = routes.map(
|
||||
({type, name, icon, title, collapse, noCollapse, key, href, route}: any) =>
|
||||
{
|
||||
let returnValue;
|
||||
|
||||
if (type === "collapse")
|
||||
{
|
||||
if (href)
|
||||
{
|
||||
returnValue = (
|
||||
<Link
|
||||
href={href}
|
||||
key={key}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
sx={{textDecoration: "none"}}
|
||||
>
|
||||
<SideNavCollapse
|
||||
name={name}
|
||||
icon={icon}
|
||||
active={key === collapseName}
|
||||
noCollapse={noCollapse}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
else if (noCollapse && route)
|
||||
{
|
||||
returnValue = (
|
||||
<NavLink to={route} key={key}>
|
||||
<SideNavCollapse
|
||||
name={name}
|
||||
icon={icon}
|
||||
noCollapse={noCollapse}
|
||||
active={key === collapseName}
|
||||
>
|
||||
{collapse ? renderCollapse(collapse) : null}
|
||||
</SideNavCollapse>
|
||||
</NavLink>
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = (
|
||||
<SideNavCollapse
|
||||
key={key}
|
||||
name={name}
|
||||
icon={icon}
|
||||
active={key === collapseName}
|
||||
open={openCollapse === key}
|
||||
noCollapse={noCollapse}
|
||||
onClick={() => (! noCollapse ? (openCollapse === key ? setOpenCollapse(false) : setOpenCollapse(key)) : null) }
|
||||
>
|
||||
{collapse ? renderCollapse(collapse) : null}
|
||||
</SideNavCollapse>
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (type === "title")
|
||||
{
|
||||
returnValue = (
|
||||
<MDTypography
|
||||
key={key}
|
||||
color={textColor}
|
||||
display="block"
|
||||
variant="caption"
|
||||
fontWeight="bold"
|
||||
textTransform="uppercase"
|
||||
pl={3}
|
||||
mt={2}
|
||||
mb={1}
|
||||
ml={1}
|
||||
>
|
||||
{title}
|
||||
</MDTypography>
|
||||
);
|
||||
}
|
||||
else if (type === "divider")
|
||||
{
|
||||
returnValue = (
|
||||
<Divider
|
||||
key={key}
|
||||
light={
|
||||
(!darkMode && !whiteSidenav && !transparentSidenav) ||
|
||||
(darkMode && !transparentSidenav && whiteSidenav)
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<SidenavRoot
|
||||
{...rest}
|
||||
variant="permanent"
|
||||
ownerState={{transparentSidenav, whiteSidenav, miniSidenav, darkMode}}
|
||||
>
|
||||
<Box pt={3} mr={1} pb={0} px={4} textAlign="center">
|
||||
<Box
|
||||
display={{xs: "block", xl: "none"}}
|
||||
position="absolute"
|
||||
top={0}
|
||||
right={0}
|
||||
p={1.625}
|
||||
onClick={closeSidenav}
|
||||
sx={{cursor: "pointer"}}
|
||||
>
|
||||
<MDTypography variant="h6" color="secondary">
|
||||
<Icon sx={{fontWeight: "bold"}}>close</Icon>
|
||||
</MDTypography>
|
||||
</Box>
|
||||
<Box component={NavLink} to="/" display="flex" alignItems="center">
|
||||
{!miniSidenav && logo && <Box component="img" src={logo} alt="Logo" width="100%" />}
|
||||
{miniSidenav && icon && <Box component="img" src={icon} alt="Icon" width="160%" />}
|
||||
{!miniSidenav && companyName && <Box width={!companyName && "100%"} sx={(theme: any) => sidenavLogoLabel(theme, {miniSidenav})}>
|
||||
<MDTypography component="h6" variant="button" fontWeight="medium" color={textColor}>
|
||||
{companyName}
|
||||
</MDTypography>
|
||||
</Box>
|
||||
}
|
||||
</Box>
|
||||
</Box>
|
||||
<Divider
|
||||
light={
|
||||
(!darkMode && !whiteSidenav && !transparentSidenav) ||
|
||||
(darkMode && !transparentSidenav && whiteSidenav)
|
||||
}
|
||||
/>
|
||||
<List>{renderRoutes}</List>
|
||||
<Divider
|
||||
light={
|
||||
(!darkMode && !whiteSidenav && !transparentSidenav) ||
|
||||
(darkMode && !transparentSidenav && whiteSidenav)
|
||||
}
|
||||
/>
|
||||
<AuthenticationButton />
|
||||
</SidenavRoot>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for Sidenav
|
||||
Sidenav.defaultProps = {
|
||||
color: "info",
|
||||
icon: "",
|
||||
logo: "",
|
||||
companyName: "",
|
||||
};
|
||||
|
||||
export default Sidenav;
|
121
src/qqq/components/horseshoe/sidenav/SideNavCollapse.tsx
Normal file
121
src/qqq/components/horseshoe/sidenav/SideNavCollapse.tsx
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Box from "@mui/material/Box";
|
||||
import Collapse from "@mui/material/Collapse";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import ListItem from "@mui/material/ListItem";
|
||||
import ListItemIcon from "@mui/material/ListItemIcon";
|
||||
import ListItemText from "@mui/material/ListItemText";
|
||||
import {ReactNode} from "react";
|
||||
import {collapseArrow, collapseIcon, collapseIconBox, collapseItem, collapseText,} from "qqq/components/horseshoe/sidenav/styles/SideNavCollapse";
|
||||
import {useMaterialUIController} from "qqq/context";
|
||||
|
||||
// Declaring props types for SideNavCollapse
|
||||
interface Props {
|
||||
icon: ReactNode;
|
||||
name: string;
|
||||
children?: ReactNode;
|
||||
active?: Boolean;
|
||||
noCollapse?: Boolean;
|
||||
open?: Boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
function SideNavCollapse({
|
||||
icon,
|
||||
name,
|
||||
children,
|
||||
active,
|
||||
noCollapse,
|
||||
open,
|
||||
...rest
|
||||
}: Props): JSX.Element
|
||||
{
|
||||
const [controller] = useMaterialUIController();
|
||||
const {miniSidenav, transparentSidenav, whiteSidenav, darkMode} = controller;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListItem component="li">
|
||||
<Box
|
||||
{...rest}
|
||||
sx={(theme: any) =>
|
||||
collapseItem(theme, {active, transparentSidenav, whiteSidenav, darkMode})
|
||||
}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={(theme) => collapseIconBox(theme, {transparentSidenav, whiteSidenav, darkMode})}
|
||||
>
|
||||
{typeof icon === "string" ? (
|
||||
<Icon sx={(theme) => collapseIcon(theme, {active})}>{icon}</Icon>
|
||||
) : (
|
||||
icon
|
||||
)}
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primary={name}
|
||||
sx={(theme) =>
|
||||
collapseText(theme, {
|
||||
miniSidenav,
|
||||
transparentSidenav,
|
||||
whiteSidenav,
|
||||
active,
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
||||
<Icon
|
||||
sx={(theme) =>
|
||||
collapseArrow(theme, {
|
||||
noCollapse,
|
||||
transparentSidenav,
|
||||
whiteSidenav,
|
||||
miniSidenav,
|
||||
open,
|
||||
active,
|
||||
darkMode,
|
||||
})
|
||||
}
|
||||
>
|
||||
expand_less
|
||||
</Icon>
|
||||
</Box>
|
||||
</ListItem>
|
||||
{children && (
|
||||
<Collapse in={Boolean(open)} unmountOnExit>
|
||||
{children}
|
||||
</Collapse>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for SideNavCollapse
|
||||
SideNavCollapse.defaultProps = {
|
||||
active: false,
|
||||
noCollapse: false,
|
||||
children: false,
|
||||
open: false,
|
||||
};
|
||||
|
||||
export default SideNavCollapse;
|
100
src/qqq/components/horseshoe/sidenav/SideNavItem.tsx
Normal file
100
src/qqq/components/horseshoe/sidenav/SideNavItem.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Box from "@mui/material/Box";
|
||||
import Collapse from "@mui/material/Collapse";
|
||||
import Icon from "@mui/material/Icon";
|
||||
import ListItem from "@mui/material/ListItem";
|
||||
import ListItemText from "@mui/material/ListItemText";
|
||||
import {Theme} from "@mui/material/styles";
|
||||
import {ReactNode} from "react";
|
||||
import {useMaterialUIController} from "qqq/context";
|
||||
import {item, itemArrow, itemContent} from "qqq/components/horseshoe/sidenav/styles/SideNavItem";
|
||||
|
||||
// Declaring props types for SideNavCollapse
|
||||
interface Props {
|
||||
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark";
|
||||
name: string;
|
||||
active?: boolean | string;
|
||||
nested?: boolean;
|
||||
children?: ReactNode;
|
||||
open?: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
function SideNavItem({color, name, active, nested, children, open, ...rest}: Props): JSX.Element
|
||||
{
|
||||
const [controller] = useMaterialUIController();
|
||||
const {miniSidenav, transparentSidenav, whiteSidenav, darkMode} = controller;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListItem
|
||||
{...rest}
|
||||
component="li"
|
||||
sx={(theme) => item(theme, {active, color, transparentSidenav, whiteSidenav, darkMode})}
|
||||
>
|
||||
<Box
|
||||
sx={(theme: Theme): any =>
|
||||
itemContent(theme, {
|
||||
active,
|
||||
miniSidenav,
|
||||
name,
|
||||
open,
|
||||
nested,
|
||||
transparentSidenav,
|
||||
whiteSidenav,
|
||||
darkMode,
|
||||
})
|
||||
}
|
||||
>
|
||||
<ListItemText primary={name} />
|
||||
{children && (
|
||||
<Icon
|
||||
component="i"
|
||||
sx={(theme) =>
|
||||
itemArrow(theme, {open, miniSidenav, transparentSidenav, whiteSidenav, darkMode})
|
||||
}
|
||||
>
|
||||
expand_less
|
||||
</Icon>
|
||||
)}
|
||||
</Box>
|
||||
</ListItem>
|
||||
{children && (
|
||||
<Collapse in={open} timeout="auto" unmountOnExit {...rest}>
|
||||
{children}
|
||||
</Collapse>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Declaring default props for SideNavItem
|
||||
SideNavItem.defaultProps = {
|
||||
color: "info",
|
||||
active: false,
|
||||
nested: false,
|
||||
children: false,
|
||||
open: false,
|
||||
};
|
||||
|
||||
export default SideNavItem;
|
39
src/qqq/components/horseshoe/sidenav/SideNavList.tsx
Normal file
39
src/qqq/components/horseshoe/sidenav/SideNavList.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import List from "@mui/material/List";
|
||||
import {ReactNode} from "react";
|
||||
|
||||
function SideNavList({children}: { children: ReactNode }): JSX.Element
|
||||
{
|
||||
return (
|
||||
<List
|
||||
sx={{
|
||||
px: 2,
|
||||
my: 0.3,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</List>
|
||||
);
|
||||
}
|
||||
|
||||
export default SideNavList;
|
101
src/qqq/components/horseshoe/sidenav/SideNavRoot.tsx
Normal file
101
src/qqq/components/horseshoe/sidenav/SideNavRoot.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Drawer from "@mui/material/Drawer";
|
||||
import {styled, Theme} from "@mui/material/styles";
|
||||
|
||||
export default styled(Drawer)(({theme, ownerState}: { theme?: Theme | any; ownerState: any }) =>
|
||||
{
|
||||
const {palette, boxShadows, transitions, breakpoints, functions} = theme;
|
||||
const {transparentSidenav, whiteSidenav, miniSidenav, darkMode} = ownerState;
|
||||
|
||||
const sidebarWidth = 250;
|
||||
const {transparent, gradients, white, background} = palette;
|
||||
const {xxl} = boxShadows;
|
||||
const {pxToRem, linearGradient} = functions;
|
||||
|
||||
let backgroundValue = darkMode
|
||||
? background.sidenav
|
||||
: linearGradient(gradients.dark.main, gradients.dark.state);
|
||||
|
||||
if (transparentSidenav)
|
||||
{
|
||||
backgroundValue = transparent.main;
|
||||
}
|
||||
else if (whiteSidenav)
|
||||
{
|
||||
backgroundValue = white.main;
|
||||
}
|
||||
|
||||
// styles for the sidenav when miniSidenav={false}
|
||||
const drawerOpenStyles = () => ({
|
||||
background: backgroundValue,
|
||||
transform: "translateX(0)",
|
||||
transition: transitions.create("transform", {
|
||||
easing: transitions.easing.sharp,
|
||||
duration: transitions.duration.shorter,
|
||||
}),
|
||||
|
||||
[breakpoints.up("xl")]: {
|
||||
boxShadow: transparentSidenav ? "none" : xxl,
|
||||
marginBottom: transparentSidenav ? 0 : "inherit",
|
||||
left: "0",
|
||||
width: sidebarWidth,
|
||||
transform: "translateX(0)",
|
||||
transition: transitions.create(["width", "background-color"], {
|
||||
easing: transitions.easing.sharp,
|
||||
duration: transitions.duration.enteringScreen,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
// styles for the sidenav when miniSidenav={true}
|
||||
const drawerCloseStyles = () => ({
|
||||
background: backgroundValue,
|
||||
transform: `translateX(${pxToRem(-320)})`,
|
||||
transition: transitions.create("transform", {
|
||||
easing: transitions.easing.sharp,
|
||||
duration: transitions.duration.shorter,
|
||||
}),
|
||||
|
||||
[breakpoints.up("xl")]: {
|
||||
boxShadow: transparentSidenav ? "none" : xxl,
|
||||
marginBottom: transparentSidenav ? 0 : "inherit",
|
||||
left: "0",
|
||||
width: pxToRem(96),
|
||||
overflowX: "hidden",
|
||||
transform: "translateX(0)",
|
||||
transition: transitions.create(["width", "background-color"], {
|
||||
easing: transitions.easing.sharp,
|
||||
duration: transitions.duration.shorter,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
"& .MuiDrawer-paper": {
|
||||
boxShadow: xxl,
|
||||
border: "none",
|
||||
|
||||
...(miniSidenav ? drawerCloseStyles() : drawerOpenStyles()),
|
||||
},
|
||||
};
|
||||
});
|
46
src/qqq/components/horseshoe/sidenav/styles/SideNav.ts
Normal file
46
src/qqq/components/horseshoe/sidenav/styles/SideNav.ts
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @mui material components
|
||||
import {Theme} from "@mui/material/styles";
|
||||
|
||||
export default function sidenavLogoLabel(theme: Theme, ownerState: any)
|
||||
{
|
||||
const {functions, transitions, typography, breakpoints} = theme;
|
||||
const {miniSidenav} = ownerState;
|
||||
|
||||
const {pxToRem} = functions;
|
||||
const {fontWeightMedium} = typography;
|
||||
|
||||
return {
|
||||
ml: 0.5,
|
||||
fontWeight: fontWeightMedium,
|
||||
wordSpacing: pxToRem(-1),
|
||||
transition: transitions.create("opacity", {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.standard,
|
||||
}),
|
||||
|
||||
[breakpoints.up("xl")]: {
|
||||
opacity: miniSidenav ? 0 : 1,
|
||||
},
|
||||
};
|
||||
}
|
193
src/qqq/components/horseshoe/sidenav/styles/SideNavCollapse.ts
Normal file
193
src/qqq/components/horseshoe/sidenav/styles/SideNavCollapse.ts
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {Theme} from "@mui/material/styles";
|
||||
|
||||
function collapseItem(theme: Theme, ownerState: any)
|
||||
{
|
||||
const {palette, transitions, breakpoints, boxShadows, borders, functions} = theme;
|
||||
const {active, transparentSidenav, whiteSidenav, darkMode} = ownerState;
|
||||
|
||||
const {white, transparent, dark, grey} = palette;
|
||||
const {md} = boxShadows;
|
||||
const {borderRadius} = borders;
|
||||
const {pxToRem, rgba} = functions;
|
||||
|
||||
return {
|
||||
background: () =>
|
||||
{
|
||||
let backgroundValue;
|
||||
|
||||
if (transparentSidenav && darkMode)
|
||||
{
|
||||
backgroundValue = active ? rgba(white.main, 0.2) : transparent.main;
|
||||
}
|
||||
else if (transparentSidenav && !darkMode)
|
||||
{
|
||||
backgroundValue = active ? grey[300] : transparent.main;
|
||||
}
|
||||
else if (whiteSidenav)
|
||||
{
|
||||
backgroundValue = active ? grey[200] : transparent.main;
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundValue = active ? rgba(white.main, 0.2) : transparent.main;
|
||||
}
|
||||
|
||||
return backgroundValue;
|
||||
},
|
||||
color: (transparentSidenav && !darkMode) || whiteSidenav ? dark.main : white.main,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
width: "100%",
|
||||
padding: `${pxToRem(8)} ${pxToRem(16)}`,
|
||||
margin: `${pxToRem(1.5)} ${pxToRem(16)}`,
|
||||
borderRadius: borderRadius.md,
|
||||
cursor: "pointer",
|
||||
userSelect: "none",
|
||||
whiteSpace: "nowrap",
|
||||
boxShadow: active && !whiteSidenav && !darkMode && !transparentSidenav ? md : "none",
|
||||
[breakpoints.up("xl")]: {
|
||||
transition: transitions.create(["box-shadow", "background-color"], {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.shorter,
|
||||
}),
|
||||
},
|
||||
|
||||
"&:hover, &:focus": {
|
||||
backgroundColor:
|
||||
transparentSidenav && !darkMode
|
||||
? grey[300]
|
||||
: rgba(whiteSidenav ? grey[400] : white.main, 0.2),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function collapseIconBox(theme: Theme, ownerState: any)
|
||||
{
|
||||
const {palette, transitions, borders, functions} = theme;
|
||||
const {transparentSidenav, whiteSidenav, darkMode} = ownerState;
|
||||
|
||||
const {white, dark} = palette;
|
||||
const {borderRadius} = borders;
|
||||
const {pxToRem} = functions;
|
||||
|
||||
return {
|
||||
minWidth: pxToRem(32),
|
||||
minHeight: pxToRem(32),
|
||||
color: (transparentSidenav && !darkMode) || whiteSidenav ? dark.main : white.main,
|
||||
borderRadius: borderRadius.md,
|
||||
display: "grid",
|
||||
placeItems: "center",
|
||||
transition: transitions.create("margin", {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.standard,
|
||||
}),
|
||||
|
||||
"& svg, svg g": {
|
||||
color: transparentSidenav || whiteSidenav ? dark.main : white.main,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const collapseIcon = ({palette: {white, gradients}}: Theme, {active}: any) => ({
|
||||
color: active ? white.main : gradients.dark.state,
|
||||
});
|
||||
|
||||
function collapseText(theme: any, ownerState: any)
|
||||
{
|
||||
const {typography, transitions, breakpoints, functions} = theme;
|
||||
const {miniSidenav, transparentSidenav, active} = ownerState;
|
||||
|
||||
const {size, fontWeightRegular, fontWeightLight} = typography;
|
||||
const {pxToRem} = functions;
|
||||
|
||||
return {
|
||||
marginLeft: pxToRem(10),
|
||||
|
||||
[breakpoints.up("xl")]: {
|
||||
opacity: miniSidenav || (miniSidenav && transparentSidenav) ? 0 : 1,
|
||||
maxWidth: miniSidenav || (miniSidenav && transparentSidenav) ? 0 : "100%",
|
||||
marginLeft: miniSidenav || (miniSidenav && transparentSidenav) ? 0 : pxToRem(10),
|
||||
transition: transitions.create(["opacity", "margin"], {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.standard,
|
||||
}),
|
||||
},
|
||||
|
||||
"& span": {
|
||||
fontWeight: active ? fontWeightRegular : fontWeightLight,
|
||||
fontSize: size.sm,
|
||||
lineHeight: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function collapseArrow(theme: Theme, ownerState: any)
|
||||
{
|
||||
const {palette, typography, transitions, breakpoints, functions} = theme;
|
||||
const {noCollapse, transparentSidenav, whiteSidenav, miniSidenav, open, active, darkMode} =
|
||||
ownerState;
|
||||
|
||||
const {white, dark} = palette;
|
||||
const {size} = typography;
|
||||
const {pxToRem, rgba} = functions;
|
||||
|
||||
return {
|
||||
fontSize: `${size.lg} !important`,
|
||||
fontWeight: 700,
|
||||
marginBottom: pxToRem(-1),
|
||||
transform: open ? "rotate(0)" : "rotate(-180deg)",
|
||||
color: () =>
|
||||
{
|
||||
let colorValue;
|
||||
|
||||
if (transparentSidenav && darkMode)
|
||||
{
|
||||
colorValue = open || active ? white.main : rgba(white.main, 0.25);
|
||||
}
|
||||
else if (transparentSidenav || whiteSidenav)
|
||||
{
|
||||
colorValue = open || active ? dark.main : rgba(dark.main, 0.25);
|
||||
}
|
||||
else
|
||||
{
|
||||
colorValue = open || active ? white.main : rgba(white.main, 0.5);
|
||||
}
|
||||
|
||||
return colorValue;
|
||||
},
|
||||
transition: transitions.create(["color", "transform", "opacity"], {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.shorter,
|
||||
}),
|
||||
|
||||
[breakpoints.up("xl")]: {
|
||||
display:
|
||||
noCollapse || (transparentSidenav && miniSidenav) || miniSidenav
|
||||
? "none !important"
|
||||
: "block !important",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export {collapseItem, collapseIconBox, collapseIcon, collapseText, collapseArrow};
|
179
src/qqq/components/horseshoe/sidenav/styles/SideNavItem.ts
Normal file
179
src/qqq/components/horseshoe/sidenav/styles/SideNavItem.ts
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {Theme} from "@mui/material/styles";
|
||||
|
||||
function item(theme: Theme | any, ownerState: any)
|
||||
{
|
||||
const {palette, borders, functions, transitions} = theme;
|
||||
const {active, color, transparentSidenav, whiteSidenav, darkMode} = ownerState;
|
||||
|
||||
const {transparent, white, grey} = palette;
|
||||
const {borderRadius} = borders;
|
||||
const {rgba} = functions;
|
||||
|
||||
return {
|
||||
pl: 3,
|
||||
mt: 0.375,
|
||||
mb: 0.3,
|
||||
width: "100%",
|
||||
borderRadius: borderRadius.md,
|
||||
cursor: "pointer",
|
||||
backgroundColor: () =>
|
||||
{
|
||||
let backgroundValue = transparent.main;
|
||||
|
||||
if (
|
||||
(active === "isParent" && !transparentSidenav && !whiteSidenav) ||
|
||||
(active === "isParent" && transparentSidenav && darkMode)
|
||||
)
|
||||
{
|
||||
backgroundValue = rgba(white.main, 0.2);
|
||||
}
|
||||
else if (active === "isParent" && transparentSidenav)
|
||||
{
|
||||
backgroundValue = grey[300];
|
||||
}
|
||||
else if (active === "isParent" && whiteSidenav)
|
||||
{
|
||||
backgroundValue = grey[200];
|
||||
}
|
||||
else if (active)
|
||||
{
|
||||
backgroundValue = palette[color].main;
|
||||
}
|
||||
|
||||
return backgroundValue;
|
||||
},
|
||||
transition: transitions.create("background-color", {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.shorter,
|
||||
}),
|
||||
|
||||
"&:hover, &:focus": {
|
||||
backgroundColor:
|
||||
!active &&
|
||||
rgba((transparentSidenav && !darkMode) || whiteSidenav ? grey[400] : white.main, 0.2),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function itemContent(theme: Theme, ownerState: any)
|
||||
{
|
||||
const {palette, typography, transitions, functions} = theme;
|
||||
const {miniSidenav, name, active, transparentSidenav, whiteSidenav, darkMode} = ownerState;
|
||||
|
||||
const {white, dark} = palette;
|
||||
const {size, fontWeightRegular, fontWeightLight} = typography;
|
||||
const {pxToRem} = functions;
|
||||
|
||||
return {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
padding: `${pxToRem(12)} ${pxToRem(16)}`,
|
||||
marginLeft: pxToRem(18),
|
||||
userSelect: "none",
|
||||
position: "relative",
|
||||
|
||||
"& span": {
|
||||
color:
|
||||
((transparentSidenav && !darkMode) || whiteSidenav) && (active === "isParent" || !active)
|
||||
? dark.main
|
||||
: white.main,
|
||||
fontWeight: active ? fontWeightRegular : fontWeightLight,
|
||||
fontSize: size.sm,
|
||||
opacity: miniSidenav ? 0 : 1,
|
||||
transition: transitions.create(["opacity", "color"], {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.standard,
|
||||
}),
|
||||
},
|
||||
|
||||
"&::before": {
|
||||
color:
|
||||
((transparentSidenav && !darkMode) || whiteSidenav) && (active === "isParent" || !active)
|
||||
? dark.main
|
||||
: white.main,
|
||||
fontWeight: fontWeightRegular,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
left: pxToRem(-15),
|
||||
opacity: 1,
|
||||
borderRadius: "50%",
|
||||
fontSize: size.sm,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function itemArrow(theme: Theme, ownerState: any)
|
||||
{
|
||||
const {palette, typography, transitions, breakpoints, functions} = theme;
|
||||
const {noCollapse, transparentSidenav, whiteSidenav, miniSidenav, open, active, darkMode} =
|
||||
ownerState;
|
||||
|
||||
const {white, dark} = palette;
|
||||
const {size} = typography;
|
||||
const {pxToRem, rgba} = functions;
|
||||
|
||||
return {
|
||||
fontSize: `${size.lg} !important`,
|
||||
fontWeight: 700,
|
||||
marginBottom: pxToRem(-1),
|
||||
transform: open ? "rotate(0)" : "rotate(-180deg)",
|
||||
color: () =>
|
||||
{
|
||||
let colorValue;
|
||||
|
||||
if (transparentSidenav && darkMode)
|
||||
{
|
||||
colorValue = open || active ? white.main : rgba(white.main, 0.25);
|
||||
}
|
||||
else if (transparentSidenav || whiteSidenav)
|
||||
{
|
||||
colorValue = open || active ? dark.main : rgba(dark.main, 0.25);
|
||||
}
|
||||
else
|
||||
{
|
||||
colorValue = open || active ? white.main : rgba(white.main, 0.5);
|
||||
}
|
||||
|
||||
return colorValue;
|
||||
},
|
||||
transition: transitions.create(["color", "transform", "opacity"], {
|
||||
easing: transitions.easing.easeInOut,
|
||||
duration: transitions.duration.shorter,
|
||||
}),
|
||||
|
||||
[breakpoints.up("xl")]: {
|
||||
display:
|
||||
noCollapse || (transparentSidenav && miniSidenav) || miniSidenav
|
||||
? "none !important"
|
||||
: "block !important",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export {item, itemContent, itemArrow};
|
Reference in New Issue
Block a user