├── public
├── favicon.ico
├── logo192.png
├── logo512.png
├── robots.txt
├── manifest.json
└── index.html
├── src
├── assets
│ └── Images
│ │ └── logo.ico
├── components
│ ├── animate
│ │ ├── features.js
│ │ ├── variants
│ │ │ ├── actions.js
│ │ │ ├── path.js
│ │ │ ├── index.js
│ │ │ ├── container.js
│ │ │ ├── transition.js
│ │ │ ├── rotate.js
│ │ │ ├── scale.js
│ │ │ ├── flip.js
│ │ │ ├── slide.js
│ │ │ ├── fade.js
│ │ │ ├── background.js
│ │ │ ├── bounce.js
│ │ │ └── zoom.js
│ │ ├── MotionLazyContainer.js
│ │ ├── index.js
│ │ ├── TextAnimate.js
│ │ ├── MotionContainer.js
│ │ ├── MotionViewport.js
│ │ ├── IconButtonAnimate.js
│ │ ├── DialogAnimate.js
│ │ └── FabButtonAnimate.js
│ ├── Chat
│ │ ├── index.js
│ │ ├── Footer.js
│ │ └── Header.js
│ ├── LoadingScreen.js
│ ├── Iconify.js
│ ├── settings
│ │ ├── drawer
│ │ │ ├── BoxMask.js
│ │ │ ├── SettingFullscreen.js
│ │ │ ├── SettingContrast.js
│ │ │ ├── SettingMode.js
│ │ │ ├── SettingDirection.js
│ │ │ ├── SettingStretch.js
│ │ │ ├── ToggleButton.js
│ │ │ ├── SettingColorPresets.js
│ │ │ ├── SettingLayout.js
│ │ │ └── index.js
│ │ ├── ThemeLocalization.js
│ │ ├── index.js
│ │ ├── ThemeRtlLayout.js
│ │ ├── ThemeColorPresets.js
│ │ └── ThemeContrast.js
│ ├── AntSwitch.js
│ └── Scrollbar.js
├── pages
│ ├── Page404.js
│ └── dashboard
│ │ └── GeneralApp.js
├── theme
│ ├── overrides
│ │ ├── Link.js
│ │ ├── Select.js
│ │ ├── Stepper.js
│ │ ├── Badge.js
│ │ ├── Breadcrumbs.js
│ │ ├── Popover.js
│ │ ├── Skeleton.js
│ │ ├── Radio.js
│ │ ├── Typography.js
│ │ ├── SvgIcon.js
│ │ ├── Timeline.js
│ │ ├── Tooltip.js
│ │ ├── Menu.js
│ │ ├── Paper.js
│ │ ├── LoadingButton.js
│ │ ├── Autocomplete.js
│ │ ├── ControlLabel.js
│ │ ├── Progress.js
│ │ ├── Slider.js
│ │ ├── Avatar.js
│ │ ├── TreeView.js
│ │ ├── Drawer.js
│ │ ├── Rating.js
│ │ ├── List.js
│ │ ├── Backdrop.js
│ │ ├── Card.js
│ │ ├── Switch.js
│ │ ├── Fab.js
│ │ ├── Accordion.js
│ │ ├── Checkbox.js
│ │ ├── Pagination.js
│ │ ├── CssBaseline.js
│ │ ├── ButtonGroup.js
│ │ ├── Chip.js
│ │ ├── Tabs.js
│ │ ├── Dialog.js
│ │ ├── ToggleButton.js
│ │ ├── Button.js
│ │ ├── Input.js
│ │ ├── Alert.js
│ │ ├── Table.js
│ │ ├── index.js
│ │ ├── DataGrid.js
│ │ └── CustomIcons.js
│ ├── breakpoints.js
│ ├── index.js
│ ├── typography.js
│ ├── palette.js
│ └── shadows.js
├── layouts
│ ├── main
│ │ └── index.js
│ └── dashboard
│ │ └── index.js
├── hooks
│ ├── useSettings.js
│ ├── useLocales.js
│ ├── useResponsive.js
│ └── useLocalStorage.js
├── routes
│ ├── paths.js
│ └── index.js
├── utils
│ ├── uuidv4.js
│ ├── highlight.js
│ ├── flattenArray.js
│ ├── getFileData.js
│ ├── formatNumber.js
│ ├── formatTime.js
│ ├── getColorName.js
│ ├── createAvatar.js
│ ├── jwt.js
│ ├── cssStyles.js
│ ├── getColorPresets.js
│ ├── getFontValue.js
│ └── getFileFormat.js
├── App.js
├── reportWebVitals.js
├── index.js
├── config.js
├── data
│ └── index.js
└── contexts
│ └── SettingsContext.js
├── .gitignore
├── package.json
└── README.md
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/assets/Images/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app/HEAD/src/assets/Images/logo.ico
--------------------------------------------------------------------------------
/src/components/animate/features.js:
--------------------------------------------------------------------------------
1 | import { domMax } from 'framer-motion';
2 |
3 | export default domMax;
4 |
--------------------------------------------------------------------------------
/src/components/Chat/index.js:
--------------------------------------------------------------------------------
1 | export {default as ChatHeader} from "./Header";
2 | export {default as ChatFooter} from "./Footer";
--------------------------------------------------------------------------------
/src/pages/Page404.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Page404 = () => {
4 | return <>404>;
5 | };
6 |
7 |
8 | export default Page404;
--------------------------------------------------------------------------------
/src/components/LoadingScreen.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const LoadingScreen = () => {
4 | return <>Loading...>;
5 | };
6 |
7 | export default LoadingScreen;
8 |
--------------------------------------------------------------------------------
/src/pages/dashboard/GeneralApp.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const GeneralApp = () => {
4 |
5 | return (
6 | <>
7 | App
8 | >
9 | );
10 | };
11 |
12 | export default GeneralApp;
13 |
--------------------------------------------------------------------------------
/src/components/animate/variants/actions.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export const varHover = (scale) => ({
4 | hover: {
5 | scale: scale || 1.1
6 | }
7 | });
8 |
--------------------------------------------------------------------------------
/src/theme/overrides/Link.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Link() {
4 | return {
5 | MuiLink: {
6 | defaultProps: {
7 | underline: 'hover',
8 | },
9 | },
10 | };
11 | }
12 |
--------------------------------------------------------------------------------
/src/layouts/main/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Outlet } from "react-router-dom";
3 |
4 | const MainLayout = () => {
5 | return (
6 | <>
7 |
Main Layout
8 |
9 |
10 | >
11 | );
12 | };
13 |
14 | export default MainLayout;
15 |
--------------------------------------------------------------------------------
/src/theme/breakpoints.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | const breakpoints = {
4 | values: {
5 | xs: 0,
6 | sm: 600,
7 | md: 900,
8 | lg: 1200,
9 | xl: 1536
10 | }
11 | };
12 |
13 | export default breakpoints;
14 |
--------------------------------------------------------------------------------
/src/hooks/useSettings.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import {SettingsContext} from '../contexts/SettingsContext';
3 |
4 | // ----------------------------------------------------------------------
5 |
6 | const useSettings = () => useContext(SettingsContext);
7 |
8 | export default useSettings;
9 |
--------------------------------------------------------------------------------
/src/layouts/dashboard/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Outlet } from "react-router-dom";
3 |
4 | const DashboardLayout = () => {
5 |
6 | return (
7 | <>
8 | Dashboard Layout
9 |
10 | >
11 | );
12 | };
13 |
14 | export default DashboardLayout;
15 |
--------------------------------------------------------------------------------
/src/theme/overrides/Select.js:
--------------------------------------------------------------------------------
1 | import { InputSelectIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Select() {
6 | return {
7 | MuiSelect: {
8 | defaultProps: {
9 | IconComponent: InputSelectIcon,
10 | },
11 | },
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/src/theme/overrides/Stepper.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Stepper(theme) {
4 | return {
5 | MuiStepConnector: {
6 | styleOverrides: {
7 | line: {
8 | borderColor: theme.palette.divider,
9 | },
10 | },
11 | },
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/src/routes/paths.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | function path(root, sublink) {
4 | return `${root}${sublink}`;
5 | }
6 |
7 | const ROOTS_DASHBOARD = "/";
8 |
9 | export const PATH_DASHBOARD = {
10 | root: ROOTS_DASHBOARD,
11 | general: {
12 | app: path(ROOTS_DASHBOARD, "app"),
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/src/theme/overrides/Badge.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Badge() {
4 | return {
5 | MuiBadge: {
6 | styleOverrides: {
7 | dot: {
8 | width: 10,
9 | height: 10,
10 | borderRadius: '50%',
11 | },
12 | },
13 | },
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/animate/variants/path.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export const TRANSITION = {
4 | duration: 2,
5 | ease: [0.43, 0.13, 0.23, 0.96]
6 | };
7 |
8 | export const varPath = {
9 | animate: {
10 | fillOpacity: [0, 0, 1],
11 | pathLength: [1, 0.4, 0],
12 | transition: TRANSITION
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/src/utils/uuidv4.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // ----------------------------------------------------------------------
3 |
4 | export default function uuidv4() {
5 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
6 | const r = (Math.random() * 16) | 0,
7 | v = c === 'x' ? r : (r & 0x3) | 0x8;
8 | return v.toString(16);
9 | });
10 | }
11 |
--------------------------------------------------------------------------------
/src/components/animate/variants/index.js:
--------------------------------------------------------------------------------
1 | export * from './path';
2 | export * from './fade';
3 | export * from './zoom';
4 | export * from './flip';
5 | export * from './slide';
6 | export * from './scale';
7 | export * from './bounce';
8 | export * from './rotate';
9 | export * from './actions';
10 | export * from './container';
11 | export * from './transition';
12 | export * from './background';
13 |
--------------------------------------------------------------------------------
/src/theme/overrides/Breadcrumbs.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Breadcrumbs(theme) {
4 | return {
5 | MuiBreadcrumbs: {
6 | styleOverrides: {
7 | separator: {
8 | marginLeft: theme.spacing(2),
9 | marginRight: theme.spacing(2),
10 | },
11 | },
12 | },
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/src/utils/highlight.js:
--------------------------------------------------------------------------------
1 | import hljs from 'highlight.js';
2 | import 'highlight.js/styles/atom-one-dark-reasonable.css';
3 |
4 | // ----------------------------------------------------------------------
5 |
6 | hljs.configure({
7 | languages: ['javascript', 'jsx', 'sh', 'bash', 'html', 'scss', 'css', 'json'],
8 | });
9 |
10 | if (typeof window !== 'undefined') {
11 | window.hljs = hljs;
12 | }
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/theme/overrides/Popover.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Popover(theme) {
4 | return {
5 | MuiPopover: {
6 | styleOverrides: {
7 | paper: {
8 | boxShadow: theme.customShadows.dropdown,
9 | borderRadius: Number(theme.shape.borderRadius) * 1.5,
10 | },
11 | },
12 | },
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | // routes
2 | import Router from "./routes";
3 | // theme
4 | import ThemeProvider from './theme';
5 | // components
6 | import ThemeSettings from './components/settings';
7 |
8 | function App() {
9 | return (
10 |
11 |
12 | {" "}
13 | {" "}
14 |
15 |
16 | );
17 | }
18 |
19 | export default App;
20 |
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/src/theme/overrides/Skeleton.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Skeleton(theme) {
4 | return {
5 | MuiSkeleton: {
6 | defaultProps: {
7 | animation: 'wave',
8 | },
9 |
10 | styleOverrides: {
11 | root: {
12 | backgroundColor: theme.palette.background.neutral,
13 | },
14 | },
15 | },
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/src/utils/flattenArray.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function flattenArray(list, key = 'children') {
4 | let children = [];
5 |
6 | const flatten = list?.map((item) => {
7 | if (item[key] && item[key].length) {
8 | children = [...children, ...item[key]];
9 | }
10 | return item;
11 | });
12 |
13 | return flatten?.concat(children.length ? flattenArray(children, key) : children);
14 | }
15 |
--------------------------------------------------------------------------------
/src/theme/overrides/Radio.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Radio(theme) {
4 | return {
5 | MuiRadio: {
6 | styleOverrides: {
7 | root: {
8 | padding: theme.spacing(1),
9 | svg: {
10 | fontSize: 24,
11 | '&[font-size=small]': {
12 | fontSize: 20,
13 | },
14 | },
15 | },
16 | },
17 | },
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/src/theme/overrides/Typography.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Typography(theme) {
4 | return {
5 | MuiTypography: {
6 | styleOverrides: {
7 | paragraph: {
8 | marginBottom: theme.spacing(2),
9 | },
10 | gutterBottom: {
11 | marginBottom: theme.spacing(1),
12 | },
13 | article: {
14 | fontWeight: 700
15 | }
16 | },
17 | },
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/src/theme/overrides/SvgIcon.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function SvgIcon() {
4 | return {
5 | MuiSvgIcon: {
6 | styleOverrides: {
7 | fontSizeSmall: {
8 | width: 20,
9 | height: 20,
10 | fontSize: 'inherit',
11 | },
12 | fontSizeLarge: {
13 | width: 32,
14 | height: 32,
15 | fontSize: 'inherit',
16 | },
17 | },
18 | },
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/theme/overrides/Timeline.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Timeline(theme) {
4 | return {
5 | MuiTimelineDot: {
6 | styleOverrides: {
7 | root: {
8 | boxShadow: 'none',
9 | },
10 | },
11 | },
12 |
13 | MuiTimelineConnector: {
14 | styleOverrides: {
15 | root: {
16 | backgroundColor: theme.palette.divider,
17 | },
18 | },
19 | },
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/src/theme/overrides/Tooltip.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Tooltip(theme) {
4 | const isLight = theme.palette.mode === 'light';
5 |
6 | return {
7 | MuiTooltip: {
8 | styleOverrides: {
9 | tooltip: {
10 | backgroundColor: theme.palette.grey[isLight ? 800 : 700],
11 | },
12 | arrow: {
13 | color: theme.palette.grey[isLight ? 800 : 700],
14 | },
15 | },
16 | },
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/Iconify.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | // icons
3 | import { Icon } from '@iconify/react';
4 | // @mui
5 | import { Box } from '@mui/material';
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | Iconify.propTypes = {
10 | icon: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
11 | sx: PropTypes.object,
12 | };
13 |
14 | export default function Iconify({ icon, sx, ...other }) {
15 | return ;
16 | }
17 |
--------------------------------------------------------------------------------
/src/theme/overrides/Menu.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Menu(theme) {
4 | return {
5 | MuiMenuItem: {
6 | styleOverrides: {
7 | root: {
8 | fontSize: 14,
9 | fontWeight: 600,
10 | '&.Mui-selected': {
11 | backgroundColor: theme.palette.action.selected,
12 | '&:hover': {
13 | backgroundColor: theme.palette.action.hover,
14 | },
15 | },
16 | },
17 | },
18 | },
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/theme/overrides/Paper.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Paper(theme) {
4 | return {
5 | MuiPaper: {
6 | defaultProps: {
7 | elevation: 0,
8 | },
9 |
10 | variants: [
11 | {
12 | props: { variant: 'outlined' },
13 | style: { borderColor: theme.palette.grey[500_12] },
14 | },
15 | ],
16 |
17 | styleOverrides: {
18 | root: {
19 | backgroundImage: 'none',
20 | },
21 | },
22 | },
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/src/theme/overrides/LoadingButton.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function LoadingButton() {
4 | return {
5 | MuiLoadingButton: {
6 | styleOverrides: {
7 | root: {
8 | '&.MuiButton-text': {
9 | '& .MuiLoadingButton-startIconPendingStart': {
10 | marginLeft: 0,
11 | },
12 | '& .MuiLoadingButton-endIconPendingEnd': {
13 | marginRight: 0,
14 | },
15 | },
16 | },
17 | },
18 | },
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/utils/getFileData.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function getFileData(file, index) {
4 | if (typeof file === 'string') {
5 | return {
6 | key: index ? `${file}-${index}` : file,
7 | preview: file,
8 | };
9 | }
10 |
11 | return {
12 | key: index ? `${file.name}-${index}` : file.name,
13 | name: file.name,
14 | size: file.size,
15 | path: file.path,
16 | type: file.type,
17 | preview: file.preview,
18 | lastModified: file.lastModified,
19 | lastModifiedDate: file.lastModifiedDate,
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/animate/MotionLazyContainer.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { LazyMotion } from 'framer-motion';
3 |
4 | // ----------------------------------------------------------------------
5 |
6 | // eslint-disable-next-line import/extensions
7 | const loadFeatures = () => import('./features.js').then((res) => res.default);
8 |
9 | MotionLazyContainer.propTypes = {
10 | children: PropTypes.node
11 | };
12 |
13 | export default function MotionLazyContainer({ children }) {
14 | return (
15 |
16 | {children}
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/animate/index.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export * from './variants';
4 |
5 | export { default as DialogAnimate } from './DialogAnimate';
6 | export { default as TextAnimate } from './TextAnimate';
7 |
8 | export { default as FabButtonAnimate } from './FabButtonAnimate';
9 | export { default as IconButtonAnimate } from './IconButtonAnimate';
10 |
11 | export { default as MotionViewport } from './MotionViewport';
12 | export { default as MotionContainer } from './MotionContainer';
13 | export { default as MotionLazyContainer } from './MotionLazyContainer';
14 |
--------------------------------------------------------------------------------
/src/components/animate/variants/container.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export const varContainer = (props) => {
4 | const staggerIn = props?.staggerIn || 0.05;
5 | const delayIn = props?.staggerIn || 0.05;
6 | const staggerOut = props?.staggerIn || 0.05;
7 |
8 | return {
9 | animate: {
10 | transition: {
11 | staggerChildren: staggerIn,
12 | delayChildren: delayIn
13 | }
14 | },
15 | exit: {
16 | transition: {
17 | staggerChildren: staggerOut,
18 | staggerDirection: -1
19 | }
20 | }
21 | };
22 | };
23 |
--------------------------------------------------------------------------------
/src/theme/overrides/Autocomplete.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Autocomplete(theme) {
4 | return {
5 | MuiAutocomplete: {
6 | styleOverrides: {
7 | paper: {
8 | boxShadow: theme.customShadows.dropdown,
9 | },
10 | listbox: {
11 | padding: theme.spacing(0, 1),
12 | '& .MuiAutocomplete-option': {
13 | padding: theme.spacing(1),
14 | margin: theme.spacing(1, 0),
15 | borderRadius: theme.shape.borderRadius,
16 | },
17 | },
18 | },
19 | },
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/src/theme/overrides/ControlLabel.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function ControlLabel(theme) {
4 | return {
5 | MuiFormControlLabel: {
6 | styleOverrides: {
7 | label: {
8 | ...theme.typography.body2,
9 | },
10 | },
11 | },
12 | MuiFormHelperText: {
13 | styleOverrides: {
14 | root: {
15 | marginTop: theme.spacing(1),
16 | },
17 | },
18 | },
19 | MuiFormLabel: {
20 | styleOverrides: {
21 | root: {
22 | color: theme.palette.text.disabled,
23 | },
24 | },
25 | },
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/src/utils/formatNumber.js:
--------------------------------------------------------------------------------
1 | import numeral from 'numeral';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export function fCurrency(number) {
6 | return numeral(number).format(Number.isInteger(number) ? '$0,0' : '$0,0.00');
7 | }
8 |
9 | export function fPercent(number) {
10 | return numeral(number / 100).format('0.0%');
11 | }
12 |
13 | export function fNumber(number) {
14 | return numeral(number).format();
15 | }
16 |
17 | export function fShortenNumber(number) {
18 | return numeral(number).format('0.00a').replace('.00', '');
19 | }
20 |
21 | export function fData(number) {
22 | return numeral(number).format('0.0 b');
23 | }
24 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/BoxMask.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | // @mui
3 | import { Radio, FormControlLabel } from '@mui/material';
4 |
5 | // ----------------------------------------------------------------------
6 |
7 | BoxMask.propTypes = {
8 | value: PropTypes.string,
9 | };
10 |
11 | export default function BoxMask({ value }) {
12 | return (
13 | }
17 | sx={{
18 | m: 0,
19 | top: 0,
20 | right: 0,
21 | bottom: 0,
22 | left: 0,
23 | position: 'absolute',
24 | }}
25 | />
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/src/theme/overrides/Progress.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Progress(theme) {
4 | const isLight = theme.palette.mode === 'light';
5 |
6 | return {
7 | MuiLinearProgress: {
8 | styleOverrides: {
9 | root: {
10 | borderRadius: 4,
11 | overflow: 'hidden',
12 | },
13 | bar: {
14 | borderRadius: 4,
15 | },
16 | colorPrimary: {
17 | backgroundColor: theme.palette.primary[isLight ? 'lighter' : 'darker'],
18 | },
19 | buffer: {
20 | backgroundColor: 'transparent',
21 | },
22 | },
23 | },
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/src/utils/formatTime.js:
--------------------------------------------------------------------------------
1 | import { format, getTime, formatDistanceToNow } from 'date-fns';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export function fDate(date) {
6 | return format(new Date(date), 'dd MMMM yyyy');
7 | }
8 |
9 | export function fDateTime(date) {
10 | return format(new Date(date), 'dd MMM yyyy HH:mm');
11 | }
12 |
13 | export function fTimestamp(date) {
14 | return getTime(new Date(date));
15 | }
16 |
17 | export function fDateTimeSuffix(date) {
18 | return format(new Date(date), 'dd/MM/yyyy hh:mm p');
19 | }
20 |
21 | export function fToNow(date) {
22 | return formatDistanceToNow(new Date(date), {
23 | addSuffix: true,
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/settings/ThemeLocalization.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | // @mui
3 | import { ThemeProvider, createTheme, useTheme } from '@mui/material/styles';
4 | // hooks
5 | import useLocales from '../../hooks/useLocales';
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | ThemeLocalization.propTypes = {
10 | children: PropTypes.node.isRequired,
11 | };
12 |
13 | export default function ThemeLocalization({ children }) {
14 | const defaultTheme = useTheme();
15 |
16 | const { currentLang } = useLocales();
17 |
18 | const theme = createTheme(defaultTheme, currentLang.systemValue);
19 |
20 | return {children};
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/animate/variants/transition.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export const varTranHover = (props) => {
4 | const duration = props?.duration || 0.32;
5 | const ease = props?.ease || [0.43, 0.13, 0.23, 0.96];
6 |
7 | return { duration, ease };
8 | };
9 |
10 | export const varTranEnter = (props) => {
11 | const duration = props?.durationIn || 0.64;
12 | const ease = props?.easeIn || [0.43, 0.13, 0.23, 0.96];
13 |
14 | return { duration, ease };
15 | };
16 |
17 | export const varTranExit = (props) => {
18 | const duration = props?.durationOut || 0.48;
19 | const ease = props?.easeOut || [0.43, 0.13, 0.23, 0.96];
20 |
21 | return { duration, ease };
22 | };
23 |
--------------------------------------------------------------------------------
/src/theme/overrides/Slider.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Slider(theme) {
4 | const isLight = theme.palette.mode === 'light';
5 |
6 | return {
7 | MuiSlider: {
8 | defaultProps: {
9 | size: 'small',
10 | },
11 |
12 | styleOverrides: {
13 | root: {
14 | '&.Mui-disabled': {
15 | color: theme.palette.action.disabled,
16 | },
17 | },
18 | markLabel: {
19 | fontSize: 13,
20 | color: theme.palette.text.disabled,
21 | },
22 | valueLabel: {
23 | borderRadius: 8,
24 | backgroundColor: theme.palette.grey[isLight ? 800 : 700],
25 | },
26 | },
27 | },
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/src/theme/overrides/Avatar.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Avatar(theme) {
4 | return {
5 | MuiAvatar: {
6 | styleOverrides: {
7 | colorDefault: {
8 | color: theme.palette.text.secondary,
9 | backgroundColor: theme.palette.grey[400],
10 | },
11 | },
12 | },
13 | MuiAvatarGroup: {
14 | styleOverrides: {
15 | avatar: {
16 | fontSize: 16,
17 | fontWeight: theme.typography.fontWeightMedium,
18 | '&:first-of-type': {
19 | fontSize: 14,
20 | color: theme.palette.primary.main,
21 | backgroundColor: theme.palette.primary.lighter,
22 | },
23 | },
24 | },
25 | },
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/src/theme/overrides/TreeView.js:
--------------------------------------------------------------------------------
1 | import { TreeViewCollapseIcon, TreeViewExpandIcon, TreeViewEndIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function TreeView(theme) {
6 | return {
7 | MuiTreeView: {
8 | defaultProps: {
9 | defaultCollapseIcon: ,
10 | defaultExpandIcon: ,
11 | defaultEndIcon: ,
12 | },
13 | },
14 | MuiTreeItem: {
15 | styleOverrides: {
16 | label: { ...theme.typography.body2 },
17 | iconContainer: { width: 'auto' },
18 | },
19 | },
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/src/theme/overrides/Drawer.js:
--------------------------------------------------------------------------------
1 | import { alpha } from '@mui/material';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Drawer(theme) {
6 | const isLight = theme.palette.mode === 'light';
7 |
8 | return {
9 | MuiDrawer: {
10 | styleOverrides: {
11 | modal: {
12 | '&[role="presentation"]': {
13 | '& .MuiDrawer-paperAnchorLeft': {
14 | boxShadow: `8px 24px 24px 12px ${alpha(theme.palette.grey[900], isLight ? 0.16 : 0.48)}`,
15 | },
16 | '& .MuiDrawer-paperAnchorRight': {
17 | boxShadow: `-8px 24px 24px 12px ${alpha(theme.palette.grey[900], isLight ? 0.16 : 0.48)}`,
18 | },
19 | },
20 | },
21 | },
22 | },
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/src/theme/overrides/Rating.js:
--------------------------------------------------------------------------------
1 | import { StarIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | const ICON_SMALL = { width: 20, height: 20 };
6 | const ICON_LARGE = { width: 28, height: 28 };
7 |
8 | export default function Rating(theme) {
9 | return {
10 | MuiRating: {
11 | defaultProps: {
12 | emptyIcon: ,
13 | icon: ,
14 | },
15 |
16 | styleOverrides: {
17 | root: {
18 | '&.Mui-disabled': {
19 | opacity: 0.48,
20 | },
21 | },
22 | iconEmpty: { color: theme.palette.grey[500_48] },
23 | sizeSmall: { '& svg': { ...ICON_SMALL } },
24 | sizeLarge: { '& svg': { ...ICON_LARGE } },
25 | },
26 | },
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/utils/getColorName.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function getColorName(hex) {
4 | let color;
5 |
6 | switch (hex) {
7 | case '#00AB55':
8 | color = 'Green';
9 | break;
10 | case '#000000':
11 | color = 'Black';
12 | break;
13 | case '#FFFFFF':
14 | color = 'White';
15 | break;
16 | case '#FFC0CB':
17 | color = 'Pink';
18 | break;
19 | case '#FF4842':
20 | color = 'Red';
21 | break;
22 | case '#1890FF':
23 | color = 'Blue';
24 | break;
25 | case '#94D82D':
26 | color = 'Greenyellow';
27 | break;
28 | case '#FFC107':
29 | color = 'Orange';
30 | break;
31 | default:
32 | color = hex;
33 | }
34 |
35 | return color;
36 | }
37 |
--------------------------------------------------------------------------------
/src/theme/overrides/List.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function List(theme) {
4 | return {
5 | MuiListItemIcon: {
6 | styleOverrides: {
7 | root: {
8 | color: 'inherit',
9 | minWidth: 'auto',
10 | marginRight: theme.spacing(2),
11 | },
12 | },
13 | },
14 | MuiListItemAvatar: {
15 | styleOverrides: {
16 | root: {
17 | minWidth: 'auto',
18 | marginRight: theme.spacing(2),
19 | },
20 | },
21 | },
22 | MuiListItemText: {
23 | styleOverrides: {
24 | root: {
25 | marginTop: 0,
26 | marginBottom: 0,
27 | },
28 | multiline: {
29 | marginTop: 0,
30 | marginBottom: 0,
31 | },
32 | },
33 | },
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/src/theme/overrides/Backdrop.js:
--------------------------------------------------------------------------------
1 | import { alpha } from '@mui/material/styles';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Backdrop(theme) {
6 | const varLow = alpha(theme.palette.grey[900], 0.48);
7 | const varHigh = alpha(theme.palette.grey[900], 1);
8 |
9 | return {
10 | MuiBackdrop: {
11 | styleOverrides: {
12 | root: {
13 | background: [
14 | `rgb(22,28,36)`,
15 | `-moz-linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`,
16 | `-webkit-linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`,
17 | `linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`,
18 | ],
19 | '&.MuiBackdrop-invisible': {
20 | background: 'transparent',
21 | },
22 | },
23 | },
24 | },
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/src/components/animate/variants/rotate.js:
--------------------------------------------------------------------------------
1 | //
2 | import { varTranEnter, varTranExit } from './transition';
3 |
4 | // ----------------------------------------------------------------------
5 |
6 | export const varRotate = (props) => {
7 | const durationIn = props?.durationIn;
8 | const durationOut = props?.durationOut;
9 | const easeIn = props?.easeIn;
10 | const easeOut = props?.easeOut;
11 |
12 | return {
13 | // IN
14 | in: {
15 | initial: { opacity: 0, rotate: -360 },
16 | animate: { opacity: 1, rotate: 0, transition: varTranEnter({ durationIn, easeIn }) },
17 | exit: { opacity: 0, rotate: -360, transition: varTranExit({ durationOut, easeOut }) }
18 | },
19 |
20 | // OUT
21 | out: {
22 | initial: { opacity: 1, rotate: 0 },
23 | animate: { opacity: 0, rotate: -360, transition: varTranExit({ durationOut, easeOut }) }
24 | }
25 | };
26 | };
27 |
--------------------------------------------------------------------------------
/src/components/settings/index.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | //
3 | import SettingsDrawer from './drawer';
4 | //
5 | import ThemeContrast from './ThemeContrast';
6 | import ThemeRtlLayout from './ThemeRtlLayout';
7 | import ThemeColorPresets from './ThemeColorPresets';
8 | import ThemeLocalization from './ThemeLocalization';
9 |
10 | // ----------------------------------------------------------------------
11 |
12 | ThemeSettings.propTypes = {
13 | children: PropTypes.node.isRequired,
14 | };
15 |
16 | export default function ThemeSettings({ children }) {
17 | return (
18 |
19 |
20 |
21 |
22 | {children}
23 |
24 |
25 |
26 |
27 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/src/hooks/useLocales.js:
--------------------------------------------------------------------------------
1 | import { useTranslation } from 'react-i18next';
2 | import useSettings from './useSettings';
3 | // config
4 | import { allLangs, defaultLang } from '../config';
5 |
6 | // ----------------------------------------------------------------------
7 |
8 | export default function useLocales() {
9 | const { i18n, t: translate } = useTranslation();
10 |
11 | const { onChangeDirectionByLang } = useSettings();
12 |
13 | const langStorage = localStorage.getItem('i18nextLng');
14 |
15 | const currentLang = allLangs.find((_lang) => _lang.value === langStorage) || defaultLang;
16 |
17 | const handleChangeLanguage = (newlang) => {
18 | i18n.changeLanguage(newlang);
19 | onChangeDirectionByLang(newlang);
20 | };
21 |
22 | return {
23 | onChangeLang: handleChangeLanguage,
24 | translate: (text, options) => translate(text, options),
25 | currentLang,
26 | allLangs,
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/hooks/useResponsive.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { useTheme } from '@mui/material/styles';
3 | import useMediaQuery from '@mui/material/useMediaQuery';
4 |
5 | // ----------------------------------------------------------------------
6 |
7 | export default function useResponsive(query, key, start, end) {
8 | const theme = useTheme();
9 |
10 | const mediaUp = useMediaQuery(theme.breakpoints.up(key));
11 |
12 | const mediaDown = useMediaQuery(theme.breakpoints.down(key));
13 |
14 | const mediaBetween = useMediaQuery(theme.breakpoints.between(start, end));
15 |
16 | const mediaOnly = useMediaQuery(theme.breakpoints.only(key));
17 |
18 | if (query === 'up') {
19 | return mediaUp;
20 | }
21 |
22 | if (query === 'down') {
23 | return mediaDown;
24 | }
25 |
26 | if (query === 'between') {
27 | return mediaBetween;
28 | }
29 |
30 | if (query === 'only') {
31 | return mediaOnly;
32 | }
33 | return null;
34 | }
35 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import { BrowserRouter } from 'react-router-dom';
4 | import { HelmetProvider } from "react-helmet-async";
5 | import App from "./App";
6 | import reportWebVitals from "./reportWebVitals";
7 |
8 | // contexts
9 | import SettingsProvider from "./contexts/SettingsContext";
10 |
11 | const root = ReactDOM.createRoot(document.getElementById("root"));
12 |
13 | root.render(
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | );
24 |
25 | // If you want to start measuring performance in your app, pass a function
26 | // to log results (for example: reportWebVitals(console.log))
27 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
28 | reportWebVitals();
29 |
--------------------------------------------------------------------------------
/src/components/settings/ThemeRtlLayout.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { useEffect } from 'react';
3 | // rtl
4 | import rtlPlugin from 'stylis-plugin-rtl';
5 | // emotion
6 | import createCache from '@emotion/cache';
7 | import { CacheProvider } from '@emotion/react';
8 | // @mui
9 | import { useTheme } from '@mui/material/styles';
10 |
11 | // ----------------------------------------------------------------------
12 |
13 | ThemeRtlLayout.propTypes = {
14 | children: PropTypes.node,
15 | };
16 |
17 | export default function ThemeRtlLayout({ children }) {
18 | const theme = useTheme();
19 |
20 | useEffect(() => {
21 | document.dir = theme.direction;
22 | }, [theme.direction]);
23 |
24 | const cacheRtl = createCache({
25 | key: theme.direction === 'rtl' ? 'rtl' : 'css',
26 | stylisPlugins: theme.direction === 'rtl' ? [rtlPlugin] : [],
27 | });
28 |
29 | return {children};
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/animate/TextAnimate.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { m } from 'framer-motion';
3 | // @mui
4 | import { Box } from '@mui/material';
5 | //
6 | import { varFade } from './variants';
7 |
8 | // ----------------------------------------------------------------------
9 |
10 | TextAnimate.propTypes = {
11 | text: PropTypes.string.isRequired,
12 | variants: PropTypes.object,
13 | sx: PropTypes.object
14 | };
15 |
16 | export default function TextAnimate({ text, variants, sx, ...other }) {
17 | return (
18 |
28 | {text.split('').map((letter, index) => (
29 |
30 | {letter}
31 |
32 | ))}
33 |
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/src/theme/overrides/Card.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Card(theme) {
4 | return {
5 | MuiCard: {
6 | styleOverrides: {
7 | root: {
8 | position: 'relative',
9 | boxShadow: theme.customShadows.card,
10 | borderRadius: Number(theme.shape.borderRadius) * 2,
11 | zIndex: 0, // Fix Safari overflow: hidden with border radius
12 | },
13 | },
14 | },
15 | MuiCardHeader: {
16 | defaultProps: {
17 | titleTypographyProps: { variant: 'h6' },
18 | subheaderTypographyProps: { variant: 'body2', marginTop: theme.spacing(0.5) },
19 | },
20 | styleOverrides: {
21 | root: {
22 | padding: theme.spacing(3, 3, 0),
23 | },
24 | },
25 | },
26 | MuiCardContent: {
27 | styleOverrides: {
28 | root: {
29 | padding: theme.spacing(3),
30 | },
31 | },
32 | },
33 | };
34 | }
35 |
--------------------------------------------------------------------------------
/src/components/animate/MotionContainer.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { m } from 'framer-motion';
3 | // @mui
4 | import { Box } from '@mui/material';
5 | //
6 | import { varContainer } from './variants';
7 |
8 | // ----------------------------------------------------------------------
9 |
10 | MotionContainer.propTypes = {
11 | action: PropTypes.bool,
12 | animate: PropTypes.bool,
13 | children: PropTypes.node.isRequired
14 | };
15 |
16 | export default function MotionContainer({ animate, action = false, children, ...other }) {
17 | if (action) {
18 | return (
19 |
26 | {children}
27 |
28 | );
29 | }
30 |
31 | return (
32 |
33 | {children}
34 |
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/src/components/animate/MotionViewport.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { m } from 'framer-motion';
3 | // @mui
4 | import { Box } from '@mui/material';
5 | // hooks
6 | import useResponsive from '../../hooks/useResponsive';
7 | //
8 | import { varContainer } from '.';
9 |
10 | // ----------------------------------------------------------------------
11 |
12 | MotionViewport.propTypes = {
13 | children: PropTypes.node.isRequired,
14 | disableAnimatedMobile: PropTypes.bool,
15 | };
16 |
17 | export default function MotionViewport({ children, disableAnimatedMobile = false, ...other }) {
18 | const isMobile = useResponsive('down', 'sm');
19 |
20 | if (isMobile && disableAnimatedMobile) {
21 | return {children};
22 | }
23 |
24 | return (
25 |
33 | {children}
34 |
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/src/theme/overrides/Switch.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Switch(theme) {
4 | const isLight = theme.palette.mode === 'light';
5 |
6 | return {
7 | MuiSwitch: {
8 | styleOverrides: {
9 | thumb: {
10 | boxShadow: theme.customShadows.z1,
11 | },
12 | track: {
13 | opacity: 1,
14 | backgroundColor: theme.palette.grey[500],
15 | },
16 | switchBase: {
17 | left: 0,
18 | right: 'auto',
19 | '&:not(:.Mui-checked)': {
20 | color: theme.palette.grey[isLight ? 100 : 300],
21 | },
22 | '&.Mui-checked.Mui-disabled, &.Mui-disabled': {
23 | color: theme.palette.grey[isLight ? 400 : 600],
24 | },
25 | '&.Mui-disabled+.MuiSwitch-track': {
26 | opacity: 1,
27 | backgroundColor: `${theme.palette.action.disabledBackground} !important`,
28 | },
29 | },
30 | },
31 | },
32 | };
33 | }
34 |
--------------------------------------------------------------------------------
/src/theme/overrides/Fab.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Fab(theme) {
4 | return {
5 | MuiFab: {
6 | defaultProps: {
7 | color: 'primary',
8 | },
9 |
10 | styleOverrides: {
11 | root: {
12 | boxShadow: theme.customShadows.z8,
13 | '&:hover': {
14 | boxShadow: 'none',
15 | backgroundColor: theme.palette.grey[400],
16 | },
17 | },
18 | primary: {
19 | boxShadow: theme.customShadows.primary,
20 | '&:hover': {
21 | backgroundColor: theme.palette.primary.dark,
22 | },
23 | },
24 | secondary: {
25 | boxShadow: theme.customShadows.secondary,
26 | '&:hover': {
27 | backgroundColor: theme.palette.secondary.dark,
28 | },
29 | },
30 | extended: {
31 | '& svg': {
32 | marginRight: theme.spacing(1),
33 | },
34 | },
35 | },
36 | },
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/src/theme/overrides/Accordion.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Accordion(theme) {
4 | return {
5 | MuiAccordion: {
6 | styleOverrides: {
7 | root: {
8 | '&.Mui-expanded': {
9 | boxShadow: theme.customShadows.z8,
10 | borderRadius: theme.shape.borderRadius,
11 | },
12 | '&.Mui-disabled': {
13 | backgroundColor: 'transparent',
14 | },
15 | },
16 | },
17 | },
18 | MuiAccordionSummary: {
19 | styleOverrides: {
20 | root: {
21 | paddingLeft: theme.spacing(2),
22 | paddingRight: theme.spacing(1),
23 | '&.Mui-disabled': {
24 | opacity: 1,
25 | color: theme.palette.action.disabled,
26 | '& .MuiTypography-root': {
27 | color: 'inherit',
28 | },
29 | },
30 | },
31 | expandIconWrapper: {
32 | color: 'inherit',
33 | },
34 | },
35 | },
36 | };
37 | }
38 |
--------------------------------------------------------------------------------
/src/utils/createAvatar.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | const PRIMARY_NAME = ['A', 'N', 'H', 'L', 'Q', '9', '8'];
4 | const INFO_NAME = ['F', 'G', 'T', 'I', 'J', '1', '2', '3'];
5 | const SUCCESS_NAME = ['K', 'D', 'Y', 'B', 'O', '4', '5'];
6 | const WARNING_NAME = ['P', 'E', 'R', 'S', 'C', 'U', '6', '7'];
7 | const ERROR_NAME = ['V', 'W', 'X', 'M', 'Z'];
8 |
9 | function getFirstCharacter(name) {
10 | return name && name.charAt(0).toUpperCase();
11 | }
12 |
13 | function getAvatarColor(name) {
14 | if (PRIMARY_NAME.includes(getFirstCharacter(name))) return 'primary';
15 | if (INFO_NAME.includes(getFirstCharacter(name))) return 'info';
16 | if (SUCCESS_NAME.includes(getFirstCharacter(name))) return 'success';
17 | if (WARNING_NAME.includes(getFirstCharacter(name))) return 'warning';
18 | if (ERROR_NAME.includes(getFirstCharacter(name))) return 'warning';
19 | return 'default';
20 | }
21 |
22 | export default function createAvatar(name) {
23 | return {
24 | name: getFirstCharacter(name),
25 | color: getAvatarColor(name),
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/src/hooks/useLocalStorage.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function useLocalStorage(key, defaultValue) {
6 | const [value, setValue] = useState(() => {
7 | const storedValue = localStorage.getItem(key);
8 |
9 | return storedValue === null ? defaultValue : JSON.parse(storedValue);
10 | });
11 |
12 | useEffect(() => {
13 | const listener = (e) => {
14 | if (e.storageArea === localStorage && e.key === key) {
15 | setValue(JSON.parse(e.newValue));
16 | }
17 | };
18 | window.addEventListener('storage', listener);
19 |
20 | return () => {
21 | window.removeEventListener('storage', listener);
22 | };
23 | }, [key, defaultValue]);
24 |
25 | const setValueInLocalStorage = (newValue) => {
26 | setValue((currentValue) => {
27 | const result = typeof newValue === 'function' ? newValue(currentValue) : newValue;
28 |
29 | localStorage.setItem(key, JSON.stringify(result));
30 |
31 | return result;
32 | });
33 | };
34 |
35 | return [value, setValueInLocalStorage];
36 | }
37 |
--------------------------------------------------------------------------------
/src/theme/overrides/Checkbox.js:
--------------------------------------------------------------------------------
1 | import { CheckboxIcon, CheckboxCheckedIcon, CheckboxIndeterminateIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Checkbox(theme) {
6 | return {
7 | MuiCheckbox: {
8 | defaultProps: {
9 | icon: ,
10 | checkedIcon: ,
11 | indeterminateIcon: ,
12 | },
13 |
14 | styleOverrides: {
15 | root: {
16 | padding: theme.spacing(1),
17 | '&.Mui-checked.Mui-disabled, &.Mui-disabled': {
18 | color: theme.palette.action.disabled,
19 | },
20 | '& .MuiSvgIcon-fontSizeMedium': {
21 | width: 24,
22 | height: 24,
23 | },
24 | '& .MuiSvgIcon-fontSizeSmall': {
25 | width: 20,
26 | height: 20,
27 | },
28 | svg: {
29 | fontSize: 24,
30 | '&[font-size=small]': {
31 | fontSize: 20,
32 | },
33 | },
34 | },
35 | },
36 | },
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/src/theme/overrides/Pagination.js:
--------------------------------------------------------------------------------
1 | import { alpha } from '@mui/material/styles';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Pagination(theme) {
6 | return {
7 | MuiPaginationItem: {
8 | styleOverrides: {
9 | root: {
10 | '&.Mui-selected': {
11 | fontWeight: theme.typography.fontWeightBold,
12 | },
13 | },
14 | textPrimary: {
15 | '&.Mui-selected': {
16 | color: theme.palette.primary.main,
17 | backgroundColor: alpha(theme.palette.primary.main, 0.08),
18 | '&:hover, &.Mui-focusVisible': {
19 | backgroundColor: `${alpha(theme.palette.primary.main, 0.24)} !important`,
20 | },
21 | },
22 | },
23 | outlined: {
24 | border: `1px solid ${theme.palette.grey[500_32]}`,
25 | },
26 | outlinedPrimary: {
27 | '&.Mui-selected': {
28 | backgroundColor: alpha(theme.palette.primary.main, 0.08),
29 | border: `1px solid ${alpha(theme.palette.primary.main, 0.24)}`,
30 | },
31 | },
32 | },
33 | },
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/src/routes/index.js:
--------------------------------------------------------------------------------
1 | import { Suspense, lazy } from "react";
2 | import { Navigate, useRoutes } from "react-router-dom";
3 |
4 | // layouts
5 | import DashboardLayout from "../layouts/dashboard";
6 |
7 | // config
8 | import { DEFAULT_PATH } from "../config";
9 | import LoadingScreen from "../components/LoadingScreen";
10 |
11 | const Loadable = (Component) => (props) => {
12 | return (
13 | }>
14 |
15 |
16 | );
17 | };
18 |
19 | export default function Router() {
20 | return useRoutes([
21 | {
22 | path: "/",
23 | element: ,
24 | children: [
25 | { element: , index: true },
26 | { path: "app", element: },
27 |
28 | { path: "404", element: },
29 | { path: "*", element: },
30 | ],
31 | },
32 | { path: "*", element: },
33 | ]);
34 | }
35 |
36 | const GeneralApp = Loadable(
37 | lazy(() => import("../pages/dashboard/GeneralApp")),
38 | );
39 | const Page404 = Loadable(lazy(() => import("../pages/Page404")));
40 |
--------------------------------------------------------------------------------
/src/theme/overrides/CssBaseline.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function CssBaseline() {
4 | return {
5 | MuiCssBaseline: {
6 | styleOverrides: {
7 | '*': {
8 | margin: 0,
9 | padding: 0,
10 | boxSizing: 'border-box',
11 | },
12 | html: {
13 | width: '100%',
14 | height: '100%',
15 | WebkitOverflowScrolling: 'touch',
16 | },
17 | body: {
18 | width: '100%',
19 | height: '100%',
20 | },
21 | '#root': {
22 | width: '100%',
23 | height: '100%',
24 | },
25 | input: {
26 | '&[type=number]': {
27 | MozAppearance: 'textfield',
28 | '&::-webkit-outer-spin-button': {
29 | margin: 0,
30 | WebkitAppearance: 'none',
31 | },
32 | '&::-webkit-inner-spin-button': {
33 | margin: 0,
34 | WebkitAppearance: 'none',
35 | },
36 | },
37 | },
38 | img: {
39 | display: 'block',
40 | maxWidth: '100%',
41 | },
42 | },
43 | },
44 | };
45 | }
46 |
--------------------------------------------------------------------------------
/src/components/settings/ThemeColorPresets.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { useMemo } from 'react';
3 | // @mui
4 | import { alpha, ThemeProvider, createTheme, useTheme } from '@mui/material/styles';
5 | // hooks
6 | import useSettings from '../../hooks/useSettings';
7 | //
8 | import componentsOverride from '../../theme/overrides';
9 |
10 | // ----------------------------------------------------------------------
11 |
12 | ThemeColorPresets.propTypes = {
13 | children: PropTypes.node,
14 | };
15 |
16 | export default function ThemeColorPresets({ children }) {
17 | const defaultTheme = useTheme();
18 |
19 | const { setColor } = useSettings();
20 |
21 | const themeOptions = useMemo(
22 | () => ({
23 | ...defaultTheme,
24 | palette: {
25 | ...defaultTheme.palette,
26 | primary: setColor,
27 | },
28 | customShadows: {
29 | ...defaultTheme.customShadows,
30 | primary: `0 8px 16px 0 ${alpha(setColor.main, 0.24)}`,
31 | },
32 | }),
33 | [setColor, defaultTheme]
34 | );
35 |
36 | const theme = createTheme(themeOptions);
37 |
38 | theme.components = componentsOverride(theme);
39 |
40 | return {children};
41 | }
42 |
--------------------------------------------------------------------------------
/src/components/AntSwitch.js:
--------------------------------------------------------------------------------
1 | import { Switch } from "@mui/material";
2 | import { styled } from "@mui/material/styles";
3 |
4 | const AntSwitch = styled(Switch)(({ theme }) => ({
5 | width: 40,
6 | height: 20,
7 | padding: 0,
8 | display: "flex",
9 | "&:active": {
10 | "& .MuiSwitch-thumb": {
11 | width: 15,
12 | },
13 | "& .MuiSwitch-switchBase.Mui-checked": {
14 | transform: "translateX(9px)",
15 | },
16 | },
17 | "& .MuiSwitch-switchBase": {
18 | padding: 2,
19 | "&.Mui-checked": {
20 | transform: "translateX(20px)",
21 | color: "#fff",
22 | "& + .MuiSwitch-track": {
23 | opacity: 1,
24 | backgroundColor: theme.palette.primary.main,
25 | },
26 | },
27 | },
28 | "& .MuiSwitch-thumb": {
29 | boxShadow: "0 2px 4px 0 rgb(0 35 11 / 20%)",
30 | width: 16,
31 | height: 16,
32 | borderRadius: 8,
33 | transition: theme.transitions.create(["width"], {
34 | duration: 200,
35 | }),
36 | },
37 | "& .MuiSwitch-track": {
38 | borderRadius: 20 / 2,
39 | opacity: 1,
40 | backgroundColor:
41 | theme.palette.mode === "dark"
42 | ? "rgba(255,255,255,.35)"
43 | : "rgba(0,0,0,.25)",
44 | boxSizing: "border-box",
45 | },
46 | }));
47 |
48 | export default AntSwitch;
49 |
--------------------------------------------------------------------------------
/src/components/animate/variants/scale.js:
--------------------------------------------------------------------------------
1 | //
2 | import { varTranEnter, varTranExit } from './transition';
3 |
4 | // ----------------------------------------------------------------------
5 |
6 | export const varScale = (props) => {
7 | const durationIn = props?.durationIn;
8 | const durationOut = props?.durationOut;
9 | const easeIn = props?.easeIn;
10 | const easeOut = props?.easeOut;
11 |
12 | return {
13 | // IN
14 | inX: {
15 | initial: { scaleX: 0, opacity: 0 },
16 | animate: { scaleX: 1, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
17 | exit: { scaleX: 0, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
18 | },
19 | inY: {
20 | initial: { scaleY: 0, opacity: 0 },
21 | animate: { scaleY: 1, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
22 | exit: { scaleY: 0, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
23 | },
24 |
25 | // OUT
26 | outX: {
27 | initial: { scaleX: 1, opacity: 1 },
28 | animate: { scaleX: 0, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) }
29 | },
30 | outY: {
31 | initial: { scaleY: 1, opacity: 1 },
32 | animate: { scaleY: 0, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) }
33 | }
34 | };
35 | };
36 |
--------------------------------------------------------------------------------
/src/components/animate/variants/flip.js:
--------------------------------------------------------------------------------
1 | import { varTranEnter, varTranExit } from './transition';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export const varFlip = (props) => {
6 | const durationIn = props?.durationIn;
7 | const durationOut = props?.durationOut;
8 | const easeIn = props?.easeIn;
9 | const easeOut = props?.easeOut;
10 |
11 | return {
12 | // IN
13 | inX: {
14 | initial: { rotateX: -180, opacity: 0 },
15 | animate: { rotateX: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
16 | exit: { rotateX: -180, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
17 | },
18 | inY: {
19 | initial: { rotateY: -180, opacity: 0 },
20 | animate: { rotateY: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
21 | exit: { rotateY: -180, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
22 | },
23 |
24 | // OUT
25 | outX: {
26 | initial: { rotateX: 0, opacity: 1 },
27 | animate: { rotateX: 70, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
28 | },
29 | outY: {
30 | initial: { rotateY: 0, opacity: 1 },
31 | animate: { rotateY: 70, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
32 | }
33 | };
34 | };
35 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/SettingFullscreen.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | // @mui
3 | import { alpha } from '@mui/material/styles';
4 | import { Button } from '@mui/material';
5 | //
6 | import Iconify from '../../Iconify';
7 |
8 | // ----------------------------------------------------------------------
9 |
10 | export default function SettingFullscreen() {
11 | const [fullscreen, setFullscreen] = useState(false);
12 |
13 | const toggleFullScreen = () => {
14 | if (!document.fullscreenElement) {
15 | document.documentElement.requestFullscreen();
16 | setFullscreen(true);
17 | } else if (document.exitFullscreen) {
18 | document.exitFullscreen();
19 | setFullscreen(false);
20 | }
21 | };
22 |
23 | return (
24 | }
30 | onClick={toggleFullScreen}
31 | sx={{
32 | fontSize: 14,
33 | ...(fullscreen && {
34 | bgcolor: (theme) => alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
35 | }),
36 | }}
37 | >
38 | {fullscreen ? 'Exit Fullscreen' : 'Fullscreen'}
39 |
40 | );
41 | }
42 |
--------------------------------------------------------------------------------
/src/theme/overrides/ButtonGroup.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function ButtonGroup(theme) {
4 | const styleContained = (color) => ({
5 | props: { variant: 'contained', color },
6 | style: { boxShadow: theme.customShadows[color] },
7 | });
8 |
9 | return {
10 | MuiButtonGroup: {
11 | variants: [
12 | {
13 | props: { variant: 'contained', color: 'inherit' },
14 | style: { boxShadow: theme.customShadows.z8 },
15 | },
16 | styleContained('primary'),
17 | styleContained('secondary'),
18 | styleContained('info'),
19 | styleContained('success'),
20 | styleContained('warning'),
21 | styleContained('error'),
22 |
23 | {
24 | props: { disabled: true },
25 | style: {
26 | boxShadow: 'none',
27 | '& .MuiButtonGroup-grouped.Mui-disabled': {
28 | color: theme.palette.action.disabled,
29 | borderColor: `${theme.palette.action.disabledBackground} !important`,
30 | '&.MuiButton-contained': {
31 | backgroundColor: theme.palette.action.disabledBackground,
32 | },
33 | },
34 | },
35 | },
36 | ],
37 |
38 | styleOverrides: {
39 | root: {
40 | '&:hover': {
41 | boxShadow: 'none',
42 | },
43 | },
44 | },
45 | },
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/src/theme/overrides/Chip.js:
--------------------------------------------------------------------------------
1 | import { CloseIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Chip(theme) {
6 | return {
7 | MuiChip: {
8 | defaultProps: {
9 | deleteIcon: ,
10 | },
11 |
12 | styleOverrides: {
13 | colorDefault: {
14 | '& .MuiChip-avatarMedium, .MuiChip-avatarSmall': {
15 | color: theme.palette.text.secondary,
16 | },
17 | },
18 | outlined: {
19 | borderColor: theme.palette.grey[500_32],
20 | '&.MuiChip-colorPrimary': {
21 | borderColor: theme.palette.primary.main,
22 | },
23 | '&.MuiChip-colorSecondary': {
24 | borderColor: theme.palette.secondary.main,
25 | },
26 | },
27 | //
28 | avatarColorInfo: {
29 | color: theme.palette.info.contrastText,
30 | backgroundColor: theme.palette.info.dark,
31 | },
32 | avatarColorSuccess: {
33 | color: theme.palette.success.contrastText,
34 | backgroundColor: theme.palette.success.dark,
35 | },
36 | avatarColorWarning: {
37 | color: theme.palette.warning.contrastText,
38 | backgroundColor: theme.palette.warning.dark,
39 | },
40 | avatarColorError: {
41 | color: theme.palette.error.contrastText,
42 | backgroundColor: theme.palette.error.dark,
43 | },
44 | },
45 | },
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/src/theme/overrides/Tabs.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Tabs(theme) {
4 | return {
5 | MuiTabs: {
6 | styleOverrides: {
7 | scrollButtons: {
8 | width: 48,
9 | borderRadius: '50%',
10 | },
11 | },
12 | },
13 | MuiTab: {
14 | styleOverrides: {
15 | root: {
16 | padding: 0,
17 | fontWeight: theme.typography.fontWeightMedium,
18 | borderTopLeftRadius: theme.shape.borderRadius,
19 | borderTopRightRadius: theme.shape.borderRadius,
20 | '&.Mui-selected': {
21 | color: theme.palette.text.primary,
22 | },
23 | '&:not(:last-of-type)': {
24 | marginRight: theme.spacing(5),
25 | },
26 | '@media (min-width: 600px)': {
27 | minWidth: 48,
28 | },
29 | },
30 | labelIcon: {
31 | minHeight: 48,
32 | flexDirection: 'row',
33 | '& > *:first-of-type': {
34 | marginBottom: 0,
35 | marginRight: theme.spacing(1),
36 | },
37 | },
38 | wrapped: {
39 | flexDirection: 'row',
40 | whiteSpace: 'nowrap',
41 | },
42 | textColorInherit: {
43 | opacity: 1,
44 | color: theme.palette.text.secondary,
45 | },
46 | },
47 | },
48 | MuiTabPanel: {
49 | styleOverrides: {
50 | root: {
51 | padding: 0,
52 | },
53 | },
54 | },
55 | };
56 | }
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chat",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@emoji-mart/data": "^1.0.6",
7 | "@emoji-mart/react": "^1.0.1",
8 | "@emotion/react": "^11.10.4",
9 | "@emotion/styled": "^11.10.4",
10 | "@iconify/react": "^4.0.0",
11 | "@mui/material": "^5.10.8",
12 | "@testing-library/jest-dom": "^5.16.5",
13 | "@testing-library/react": "^13.4.0",
14 | "@testing-library/user-event": "^13.5.0",
15 | "emoji-mart": "^5.2.2",
16 | "framer-motion": "^7.5.3",
17 | "phosphor-react": "^1.4.1",
18 | "prop-types": "^15.8.1",
19 | "react": "^18.2.0",
20 | "react-dom": "^18.2.0",
21 | "react-helmet-async": "^1.3.0",
22 | "react-i18next": "^11.18.6",
23 | "react-router-dom": "^6.4.2",
24 | "react-scripts": "5.0.1",
25 | "simplebar-react": "^2.4.3",
26 | "stylis-plugin-rtl": "^2.0.2",
27 | "web-vitals": "^2.1.4"
28 | },
29 | "scripts": {
30 | "start": "react-scripts start",
31 | "build": "react-scripts build",
32 | "test": "react-scripts test",
33 | "eject": "react-scripts eject"
34 | },
35 | "eslintConfig": {
36 | "extends": [
37 | "react-app",
38 | "react-app/jest"
39 | ]
40 | },
41 | "browserslist": {
42 | "production": [
43 | ">0.2%",
44 | "not dead",
45 | "not op_mini all"
46 | ],
47 | "development": [
48 | "last 1 chrome version",
49 | "last 1 firefox version",
50 | "last 1 safari version"
51 | ]
52 | },
53 | "devDependencies": {
54 | "@faker-js/faker": "^7.5.0"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { enUS, frFR, zhCN, viVN, arSD } from '@mui/material/locale';
3 |
4 | // routes
5 | import { PATH_DASHBOARD } from "./routes/paths";
6 |
7 | export const defaultSettings = {
8 | themeMode: "light",
9 | themeDirection: "ltr",
10 | themeContrast: "default",
11 | themeLayout: "horizontal",
12 | themeColorPresets: "default",
13 | themeStretch: false,
14 | };
15 |
16 | export const NAVBAR = {
17 | BASE_WIDTH: 260,
18 | DASHBOARD_WIDTH: 280,
19 | DASHBOARD_COLLAPSE_WIDTH: 88,
20 | //
21 | DASHBOARD_ITEM_ROOT_HEIGHT: 48,
22 | DASHBOARD_ITEM_SUB_HEIGHT: 40,
23 | DASHBOARD_ITEM_HORIZONTAL_HEIGHT: 32,
24 | };
25 |
26 | export const allLangs = [
27 | {
28 | label: 'English',
29 | value: 'en',
30 | systemValue: enUS,
31 | icon: '/assets/icons/flags/ic_flag_en.svg',
32 | },
33 | {
34 | label: 'French',
35 | value: 'fr',
36 | systemValue: frFR,
37 | icon: '/assets/icons/flags/ic_flag_fr.svg',
38 | },
39 | {
40 | label: 'Vietnamese',
41 | value: 'vn',
42 | systemValue: viVN,
43 | icon: '/assets/icons/flags/ic_flag_vn.svg',
44 | },
45 | {
46 | label: 'Chinese',
47 | value: 'cn',
48 | systemValue: zhCN,
49 | icon: '/assets/icons/flags/ic_flag_cn.svg',
50 | },
51 | {
52 | label: 'Arabic (Sudan)',
53 | value: 'ar',
54 | systemValue: arSD,
55 | icon: '/assets/icons/flags/ic_flag_sa.svg',
56 | },
57 | ];
58 |
59 | export const defaultLang = allLangs[0]; // English
60 |
61 |
62 |
63 | // DEFAULT ROOT PATH
64 | export const DEFAULT_PATH = PATH_DASHBOARD.general.app; // as '/app'
65 |
--------------------------------------------------------------------------------
/src/utils/jwt.js:
--------------------------------------------------------------------------------
1 | import jwtDecode from 'jwt-decode';
2 | // routes
3 | import { PATH_AUTH } from '../routes/paths';
4 | //
5 | import axios from './axios';
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | const isValidToken = (accessToken) => {
10 | if (!accessToken) {
11 | return false;
12 | }
13 | const decoded = jwtDecode(accessToken);
14 |
15 | const currentTime = Date.now() / 1000;
16 |
17 | return decoded.exp > currentTime;
18 | };
19 |
20 | const handleTokenExpired = (exp) => {
21 | let expiredTimer;
22 |
23 | const currentTime = Date.now();
24 |
25 | // Test token expires after 10s
26 | // const timeLeft = currentTime + 10000 - currentTime; // ~10s
27 | const timeLeft = exp * 1000 - currentTime;
28 |
29 | clearTimeout(expiredTimer);
30 |
31 | expiredTimer = setTimeout(() => {
32 | // eslint-disable-next-line no-alert
33 | alert('Token expired');
34 |
35 | localStorage.removeItem('accessToken');
36 |
37 | window.location.href = PATH_AUTH.login;
38 | }, timeLeft);
39 | };
40 |
41 | const setSession = (accessToken) => {
42 | if (accessToken) {
43 | localStorage.setItem('accessToken', accessToken);
44 | axios.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
45 |
46 | // This function below will handle when token is expired
47 | const { exp } = jwtDecode(accessToken); // ~3 days by codingmonks server
48 | handleTokenExpired(exp);
49 | } else {
50 | localStorage.removeItem('accessToken');
51 | delete axios.defaults.headers.common.Authorization;
52 | }
53 | };
54 |
55 | export { isValidToken, setSession };
56 |
--------------------------------------------------------------------------------
/src/theme/overrides/Dialog.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Dialog(theme) {
4 | return {
5 | MuiDialog: {
6 | styleOverrides: {
7 | paper: {
8 | boxShadow: theme.customShadows.dialog,
9 | '&.MuiPaper-rounded': {
10 | borderRadius: Number(theme.shape.borderRadius) * 2,
11 | },
12 | '&.MuiDialog-paperFullScreen': {
13 | borderRadius: 0,
14 | },
15 | '&.MuiDialog-paper .MuiDialogActions-root': {
16 | padding: theme.spacing(3),
17 | },
18 | '@media (max-width: 600px)': {
19 | margin: theme.spacing(2),
20 | },
21 | '@media (max-width: 663.95px)': {
22 | '&.MuiDialog-paperWidthSm.MuiDialog-paperScrollBody': {
23 | maxWidth: '100%',
24 | },
25 | },
26 | },
27 | paperFullWidth: {
28 | width: '100%',
29 | },
30 | },
31 | },
32 | MuiDialogTitle: {
33 | styleOverrides: {
34 | root: {
35 | padding: theme.spacing(3, 3, 0),
36 | },
37 | },
38 | },
39 | MuiDialogContent: {
40 | styleOverrides: {
41 | root: {
42 | borderTop: 0,
43 | borderBottom: 0,
44 | padding: theme.spacing(3),
45 | },
46 | },
47 | },
48 | MuiDialogActions: {
49 | styleOverrides: {
50 | root: {
51 | '& > :not(:first-of-type)': {
52 | marginLeft: theme.spacing(1.5),
53 | },
54 | },
55 | },
56 | },
57 | };
58 | }
59 |
--------------------------------------------------------------------------------
/src/theme/overrides/ToggleButton.js:
--------------------------------------------------------------------------------
1 | import { alpha } from '@mui/material/styles';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function ToggleButton(theme) {
6 | const style = (color) => ({
7 | props: { color },
8 | style: {
9 | '&:hover': {
10 | borderColor: alpha(theme.palette[color].main, 0.48),
11 | backgroundColor: alpha(theme.palette[color].main, theme.palette.action.hoverOpacity),
12 | },
13 | '&.Mui-selected': {
14 | borderColor: alpha(theme.palette[color].main, 0.48),
15 | },
16 | },
17 | });
18 |
19 | return {
20 | MuiToggleButton: {
21 | variants: [
22 | {
23 | props: { color: 'standard' },
24 | style: {
25 | '&.Mui-selected': {
26 | backgroundColor: theme.palette.action.selected,
27 | },
28 | },
29 | },
30 | style('primary'),
31 | style('secondary'),
32 | style('info'),
33 | style('success'),
34 | style('warning'),
35 | style('error'),
36 | ],
37 | },
38 | MuiToggleButtonGroup: {
39 | styleOverrides: {
40 | root: {
41 | borderRadius: theme.shape.borderRadius,
42 | backgroundColor: theme.palette.background.paper,
43 | border: `solid 1px ${theme.palette.grey[500_12]}`,
44 | '& .MuiToggleButton-root': {
45 | margin: 4,
46 | borderColor: 'transparent !important',
47 | borderRadius: `${theme.shape.borderRadius}px !important`,
48 | },
49 | },
50 | },
51 | },
52 | };
53 | }
54 |
--------------------------------------------------------------------------------
/src/theme/overrides/Button.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Button(theme) {
4 | return {
5 | MuiButton: {
6 | styleOverrides: {
7 | root: {
8 | '&:hover': {
9 | boxShadow: 'none',
10 | },
11 | },
12 | sizeLarge: {
13 | height: 48,
14 | },
15 | // contained
16 | containedInherit: {
17 | color: theme.palette.grey[800],
18 | boxShadow: theme.customShadows.z8,
19 | '&:hover': {
20 | backgroundColor: theme.palette.grey[400],
21 | },
22 | },
23 | containedPrimary: {
24 | boxShadow: theme.customShadows.primary,
25 | },
26 | containedSecondary: {
27 | boxShadow: theme.customShadows.secondary,
28 | },
29 | containedInfo: {
30 | boxShadow: theme.customShadows.info,
31 | },
32 | containedSuccess: {
33 | boxShadow: theme.customShadows.success,
34 | },
35 | containedWarning: {
36 | boxShadow: theme.customShadows.warning,
37 | },
38 | containedError: {
39 | boxShadow: theme.customShadows.error,
40 | },
41 | // outlined
42 | outlinedInherit: {
43 | border: `1px solid ${theme.palette.grey[500_32]}`,
44 | '&:hover': {
45 | backgroundColor: theme.palette.action.hover,
46 | },
47 | },
48 | textInherit: {
49 | '&:hover': {
50 | backgroundColor: theme.palette.action.hover,
51 | },
52 | },
53 | },
54 | },
55 | };
56 | }
57 |
--------------------------------------------------------------------------------
/src/theme/index.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types";
2 | import { useMemo } from "react";
3 | // @mui
4 | import { CssBaseline } from "@mui/material";
5 | import {
6 | createTheme,
7 | ThemeProvider as MUIThemeProvider,
8 | StyledEngineProvider,
9 | } from "@mui/material/styles";
10 | // hooks
11 | import useSettings from "../hooks/useSettings.js";
12 | //
13 | import palette from "./palette";
14 | import typography from "./typography";
15 | import breakpoints from "./breakpoints";
16 | import componentsOverride from "./overrides";
17 | import shadows, { customShadows } from "./shadows";
18 |
19 | // ----------------------------------------------------------------------
20 |
21 | ThemeProvider.propTypes = {
22 | children: PropTypes.node,
23 | };
24 |
25 | export default function ThemeProvider({ children }) {
26 | const { themeMode, themeDirection } = useSettings();
27 |
28 | const isLight = themeMode === "light";
29 |
30 | const themeOptions = useMemo(
31 | () => ({
32 | palette: isLight ? palette.light : palette.dark,
33 | typography,
34 | breakpoints,
35 | shape: { borderRadius: 8 },
36 | direction: themeDirection,
37 | shadows: isLight ? shadows.light : shadows.dark,
38 | customShadows: isLight ? customShadows.light : customShadows.dark,
39 | }),
40 | [isLight, themeDirection]
41 | );
42 |
43 | const theme = createTheme(themeOptions);
44 |
45 | theme.components = componentsOverride(theme);
46 |
47 | return (
48 |
49 |
50 |
51 | {children}
52 |
53 |
54 | );
55 | }
56 |
--------------------------------------------------------------------------------
/src/components/animate/IconButtonAnimate.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { m } from 'framer-motion';
3 | import { forwardRef } from 'react';
4 | // @mui
5 | import { Box, IconButton } from '@mui/material';
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | const IconButtonAnimate = forwardRef(({ children, size = 'medium', ...other }, ref) => (
10 |
11 |
12 | {children}
13 |
14 |
15 | ));
16 |
17 | IconButtonAnimate.propTypes = {
18 | children: PropTypes.node.isRequired,
19 | color: PropTypes.oneOf(['inherit', 'default', 'primary', 'secondary', 'info', 'success', 'warning', 'error']),
20 | size: PropTypes.oneOf(['small', 'medium', 'large'])
21 | };
22 |
23 | export default IconButtonAnimate;
24 |
25 | // ----------------------------------------------------------------------
26 |
27 | const varSmall = {
28 | hover: { scale: 1.1 },
29 | tap: { scale: 0.95 }
30 | };
31 |
32 | const varMedium = {
33 | hover: { scale: 1.09 },
34 | tap: { scale: 0.97 }
35 | };
36 |
37 | const varLarge = {
38 | hover: { scale: 1.08 },
39 | tap: { scale: 0.99 }
40 | };
41 |
42 | AnimateWrap.propTypes = {
43 | children: PropTypes.node.isRequired,
44 | size: PropTypes.oneOf(['small', 'medium', 'large'])
45 | };
46 |
47 | function AnimateWrap({ size, children }) {
48 | const isSmall = size === 'small';
49 | const isLarge = size === 'large';
50 |
51 | return (
52 |
61 | {children}
62 |
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/src/components/animate/DialogAnimate.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { m, AnimatePresence } from 'framer-motion';
3 | // @mui
4 | import { Dialog, Box, Paper } from '@mui/material';
5 | //
6 | import { varFade } from './variants';
7 |
8 | // ----------------------------------------------------------------------
9 |
10 | DialogAnimate.propTypes = {
11 | children: PropTypes.node.isRequired,
12 | onClose: PropTypes.func,
13 | open: PropTypes.bool.isRequired,
14 | sx: PropTypes.object,
15 | variants: PropTypes.object
16 | };
17 |
18 | export default function DialogAnimate({ open = false, variants, onClose, children, sx, ...other }) {
19 | return (
20 |
21 | {open && (
22 |
55 | )}
56 |
57 | );
58 | }
59 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/SettingContrast.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { styled } from '@mui/material/styles';
3 | import { Grid, RadioGroup, CardActionArea } from '@mui/material';
4 | // hooks
5 | import useSettings from '../../../hooks/useSettings';
6 | //
7 | import Iconify from '../../Iconify';
8 | import BoxMask from './BoxMask';
9 |
10 | // ----------------------------------------------------------------------
11 |
12 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({
13 | height: 72,
14 | display: 'flex',
15 | alignItems: 'center',
16 | justifyContent: 'center',
17 | color: theme.palette.text.disabled,
18 | border: `solid 1px ${theme.palette.grey[500_12]}`,
19 | borderRadius: Number(theme.shape.borderRadius) * 1.25,
20 | }));
21 |
22 | // ----------------------------------------------------------------------
23 |
24 | export default function SettingContrast() {
25 | const { themeContrast, onChangeContrast } = useSettings();
26 |
27 | return (
28 |
29 |
30 | {['default', 'bold'].map((contrast, index) => {
31 | const isSelected = themeContrast === contrast;
32 |
33 | return (
34 |
35 | theme.customShadows.z20,
40 | }),
41 | }}
42 | >
43 |
44 |
45 |
46 |
47 | );
48 | })}
49 |
50 |
51 | );
52 | }
53 |
--------------------------------------------------------------------------------
/src/theme/overrides/Input.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Input(theme) {
4 | return {
5 | MuiInputBase: {
6 | styleOverrides: {
7 | root: {
8 | '&.Mui-disabled': {
9 | '& svg': { color: theme.palette.text.disabled },
10 | },
11 | },
12 | input: {
13 | '&::placeholder': {
14 | opacity: 1,
15 | color: theme.palette.text.disabled,
16 | },
17 | },
18 | },
19 | },
20 | MuiInput: {
21 | styleOverrides: {
22 | underline: {
23 | '&:before': {
24 | borderBottomColor: theme.palette.grey[500_56],
25 | },
26 | },
27 | },
28 | },
29 | MuiFilledInput: {
30 | styleOverrides: {
31 | root: {
32 | backgroundColor: theme.palette.grey[500_12],
33 | '&:hover': {
34 | backgroundColor: theme.palette.grey[500_16],
35 | },
36 | '&.Mui-focused': {
37 | backgroundColor: theme.palette.action.focus,
38 | },
39 | '&.Mui-disabled': {
40 | backgroundColor: theme.palette.action.disabledBackground,
41 | },
42 | },
43 | underline: {
44 | '&:before': {
45 | borderBottomColor: theme.palette.grey[500_56],
46 | },
47 | },
48 | },
49 | },
50 | MuiOutlinedInput: {
51 | styleOverrides: {
52 | root: {
53 | '& .MuiOutlinedInput-notchedOutline': {
54 | borderColor: theme.palette.grey[500_32],
55 | },
56 | '&.Mui-disabled': {
57 | '& .MuiOutlinedInput-notchedOutline': {
58 | borderColor: theme.palette.action.disabledBackground,
59 | },
60 | },
61 | },
62 | },
63 | },
64 | };
65 | }
66 |
--------------------------------------------------------------------------------
/src/utils/cssStyles.js:
--------------------------------------------------------------------------------
1 | import { alpha } from '@mui/material/styles';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | function getDirection(value = 'bottom') {
6 | return {
7 | top: 'to top',
8 | right: 'to right',
9 | bottom: 'to bottom',
10 | left: 'to left',
11 | }[value];
12 | }
13 |
14 | // ----------------------------------------------------------------------
15 |
16 | export default function cssStyles(theme) {
17 | return {
18 | bgBlur: (props) => {
19 | const color = props?.color || theme?.palette.background.default || '#000000';
20 | const blur = props?.blur || 6;
21 | const opacity = props?.opacity || 0.8;
22 |
23 | return {
24 | backdropFilter: `blur(${blur}px)`,
25 | WebkitBackdropFilter: `blur(${blur}px)`, // Fix on Mobile
26 | backgroundColor: alpha(color, opacity),
27 | };
28 | },
29 | bgGradient: (props) => {
30 | const direction = getDirection(props?.direction);
31 | const startColor = props?.startColor || `${alpha('#000000', 0)} 0%`;
32 | const endColor = props?.endColor || '#000000 75%';
33 |
34 | return {
35 | background: `linear-gradient(${direction}, ${startColor}, ${endColor});`,
36 | };
37 | },
38 | bgImage: (props) => {
39 | const url = props?.url || '/assets/bg_gradient.jpg';
40 | const direction = getDirection(props?.direction);
41 | const startColor = props?.startColor || alpha(theme?.palette.grey[900] || '#000000', 0.88);
42 | const endColor = props?.endColor || alpha(theme?.palette.grey[900] || '#000000', 0.88);
43 |
44 | return {
45 | background: `linear-gradient(${direction}, ${startColor}, ${endColor}), url(${url})`,
46 | backgroundSize: 'cover',
47 | backgroundRepeat: 'no-repeat',
48 | backgroundPosition: 'center center',
49 | };
50 | },
51 | };
52 | }
53 |
--------------------------------------------------------------------------------
/src/utils/getColorPresets.js:
--------------------------------------------------------------------------------
1 | // theme
2 | import palette from "../theme/palette";
3 |
4 | export const colorPresets = [
5 | // DEFAULT
6 | {
7 | name: "default",
8 | ...palette.light.primary,
9 | },
10 | // PURPLE
11 | {
12 | name: "purple",
13 | lighter: "#EBD6FD",
14 | light: "#B985F4",
15 | main: "#7635dc",
16 | dark: "#431A9E",
17 | darker: "#200A69",
18 | contrastText: "#fff",
19 | },
20 | // CYAN
21 | {
22 | name: "cyan",
23 | lighter: "#D1FFFC",
24 | light: "#76F2FF",
25 | main: "#1CCAFF",
26 | dark: "#0E77B7",
27 | darker: "#053D7A",
28 | contrastText: palette.light.grey[800],
29 | },
30 | // BLUE
31 | {
32 | name: "blue",
33 | lighter: "#D1E9FC",
34 | light: "#76B0F1",
35 | main: "#2065D1",
36 | dark: "#103996",
37 | darker: "#061B64",
38 |
39 | contrastText: "#fff",
40 | },
41 | // ORANGE
42 | {
43 | name: "orange",
44 | lighter: "#FEF4D4",
45 | light: "#FED680",
46 | main: "#fda92d",
47 | dark: "#B66816",
48 | darker: "#793908",
49 | contrastText: palette.light.grey[800],
50 | },
51 | // RED
52 | {
53 | name: "red",
54 | lighter: "#FFE3D5",
55 | light: "#FFC1AC",
56 | main: "#FF3030",
57 | dark: "#B71833",
58 | darker: "#7A0930",
59 | contrastText: "#fff",
60 | },
61 | ];
62 |
63 | export const defaultPreset = colorPresets[0];
64 | export const purplePreset = colorPresets[1];
65 | export const cyanPreset = colorPresets[2];
66 | export const bluePreset = colorPresets[3];
67 | export const orangePreset = colorPresets[4];
68 | export const redPreset = colorPresets[5];
69 |
70 | export default function getColorPresets(presetsKey) {
71 | return {
72 | purple: purplePreset,
73 | cyan: cyanPreset,
74 | blue: bluePreset,
75 | orange: orangePreset,
76 | red: redPreset,
77 | default: defaultPreset,
78 | }[presetsKey];
79 | }
80 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/SettingMode.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { styled } from '@mui/material/styles';
3 | import { Grid, RadioGroup, CardActionArea } from '@mui/material';
4 | // hooks
5 | import useSettings from '../../../hooks/useSettings';
6 | //
7 | import Iconify from '../../Iconify';
8 | import BoxMask from './BoxMask';
9 |
10 | // ----------------------------------------------------------------------
11 |
12 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({
13 | height: 72,
14 | display: 'flex',
15 | alignItems: 'center',
16 | justifyContent: 'center',
17 | color: theme.palette.text.disabled,
18 | border: `solid 1px ${theme.palette.grey[500_12]}`,
19 | borderRadius: Number(theme.shape.borderRadius) * 1.25,
20 | }));
21 |
22 | // ----------------------------------------------------------------------
23 |
24 | export default function SettingMode() {
25 | const { themeMode, onChangeMode } = useSettings();
26 |
27 | return (
28 |
29 |
30 | {['light', 'dark'].map((mode, index) => {
31 | const isSelected = themeMode === mode;
32 |
33 | return (
34 |
35 | theme.customShadows.z20,
41 | }),
42 | }}
43 | >
44 |
45 |
46 |
47 |
48 | );
49 | })}
50 |
51 |
52 | );
53 | }
54 |
--------------------------------------------------------------------------------
/src/components/Scrollbar.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import SimpleBarReact from 'simplebar-react';
3 | // @mui
4 | import { alpha, styled } from '@mui/material/styles';
5 | import { Box } from '@mui/material';
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | const RootStyle = styled('div')(() => ({
10 | flexGrow: 1,
11 | height: '100%',
12 | overflow: 'scroll',
13 | }));
14 |
15 | const SimpleBarStyle = styled(SimpleBarReact)(({ theme }) => ({
16 | // maxHeight: '100%',
17 | '& .simplebar-scrollbar': {
18 | '&:before': {
19 | backgroundColor: alpha(theme.palette.grey[600], 0.48),
20 | },
21 | '&.simplebar-visible:before': {
22 | opacity: 1,
23 | },
24 | },
25 | '& .simplebar-track.simplebar-vertical': {
26 | width: 10,
27 | },
28 | '& .simplebar-track.simplebar-horizontal .simplebar-scrollbar': {
29 | height: 6,
30 | },
31 | '& .simplebar-mask': {
32 | zIndex: 'inherit',
33 | },
34 | "& .simplebar-placeholder": {
35 | height: '0 !important',
36 | }
37 | }));
38 |
39 | // ----------------------------------------------------------------------
40 |
41 | Scrollbar.propTypes = {
42 | children: PropTypes.node.isRequired,
43 | sx: PropTypes.object,
44 | };
45 |
46 | export default function Scrollbar({ children, sx, ...other }) {
47 | const userAgent = typeof navigator === 'undefined' ? 'SSR' : navigator.userAgent;
48 |
49 | const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
50 |
51 | if (isMobile) {
52 | return (
53 |
54 | {children}
55 |
56 | );
57 | }
58 |
59 | return (
60 |
61 |
62 | {children}
63 |
64 |
65 | );
66 | }
67 |
68 | export {SimpleBarStyle};
69 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/SettingDirection.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { styled } from '@mui/material/styles';
3 | import { Grid, RadioGroup, CardActionArea } from '@mui/material';
4 | // hooks
5 | import useSettings from '../../../hooks/useSettings';
6 | //
7 | import Iconify from '../../Iconify';
8 | import BoxMask from './BoxMask';
9 |
10 | // ----------------------------------------------------------------------
11 |
12 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({
13 | height: 72,
14 | display: 'flex',
15 | alignItems: 'center',
16 | justifyContent: 'center',
17 | color: theme.palette.text.disabled,
18 | border: `solid 1px ${theme.palette.grey[500_12]}`,
19 | borderRadius: Number(theme.shape.borderRadius) * 1.25,
20 | }));
21 |
22 | // ----------------------------------------------------------------------
23 |
24 | export default function SettingDirection() {
25 | const { themeDirection, onChangeDirection } = useSettings();
26 |
27 | return (
28 |
29 |
30 | {['ltr', 'rtl'].map((direction, index) => {
31 | const isSelected = themeDirection === direction;
32 |
33 | return (
34 |
35 | theme.customShadows.z20,
40 | }),
41 | }}
42 | >
43 |
48 |
49 |
50 |
51 | );
52 | })}
53 |
54 |
55 | );
56 | }
57 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/SettingStretch.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { styled } from '@mui/material/styles';
3 | import { CardActionArea, Stack } from '@mui/material';
4 | // hooks
5 | import useSettings from '../../../hooks/useSettings';
6 | //
7 | import Iconify from '../../Iconify';
8 |
9 | // ----------------------------------------------------------------------
10 |
11 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({
12 | padding: theme.spacing(2),
13 | color: theme.palette.text.disabled,
14 | border: `solid 1px ${theme.palette.grey[500_12]}`,
15 | backgroundColor: theme.palette.background.neutral,
16 | borderRadius: Number(theme.shape.borderRadius) * 1.25,
17 | }));
18 |
19 | // ----------------------------------------------------------------------
20 |
21 | export default function SettingStretch() {
22 | const { themeStretch, onToggleStretch } = useSettings();
23 |
24 | const ICON_SIZE = {
25 | width: themeStretch ? 24 : 18,
26 | height: themeStretch ? 24 : 18,
27 | };
28 |
29 | return (
30 | theme.palette.primary.main,
35 | }),
36 | }}
37 | >
38 | theme.customShadows.z12,
51 | transition: (theme) => theme.transitions.create('width'),
52 | ...(themeStretch && {
53 | width: 1,
54 | color: 'primary.main',
55 | }),
56 | }}
57 | >
58 |
59 |
60 |
61 |
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
19 |
20 |
24 |
33 | Chat App
34 |
35 |
36 |
37 |
38 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/ToggleButton.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | // @mui
3 | import { alpha, styled } from '@mui/material/styles';
4 | import { Tooltip } from '@mui/material';
5 | // utils
6 | import cssStyles from '../../../utils/cssStyles';
7 | //
8 | import Iconify from '../../Iconify';
9 | import { IconButtonAnimate } from '../../animate';
10 |
11 | // ----------------------------------------------------------------------
12 |
13 | const RootStyle = styled('span')(({ theme }) => ({
14 | ...cssStyles(theme).bgBlur({ opacity: 0.64 }),
15 | right: 0,
16 | top: '50%',
17 | position: 'fixed',
18 | marginTop: theme.spacing(-3),
19 | padding: theme.spacing(0.5),
20 | zIndex: theme.zIndex.drawer + 2,
21 | borderRadius: '24px 0 20px 24px',
22 | boxShadow: `-12px 12px 32px -4px ${alpha(
23 | theme.palette.mode === 'light' ? theme.palette.grey[600] : theme.palette.common.black,
24 | 0.36
25 | )}`,
26 | }));
27 |
28 | const DotStyle = styled('span')(({ theme }) => ({
29 | top: 8,
30 | width: 8,
31 | height: 8,
32 | right: 10,
33 | borderRadius: '50%',
34 | position: 'absolute',
35 | backgroundColor: theme.palette.error.main,
36 | }));
37 |
38 | // ----------------------------------------------------------------------
39 |
40 | ToggleButton.propTypes = {
41 | notDefault: PropTypes.bool,
42 | onToggle: PropTypes.func,
43 | open: PropTypes.bool,
44 | };
45 |
46 | export default function ToggleButton({ notDefault, open, onToggle }) {
47 | return (
48 |
49 | {notDefault && !open && }
50 |
51 |
52 | theme.transitions.create('all'),
58 | '&:hover': {
59 | color: 'primary.main',
60 | bgcolor: (theme) => alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity),
61 | },
62 | }}
63 | >
64 |
65 |
66 |
67 |
68 | );
69 | }
70 |
--------------------------------------------------------------------------------
/src/utils/getFontValue.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { useTheme } from '@mui/material/styles';
3 | // hooks
4 | import useResponsive from '../hooks/useResponsive';
5 |
6 | // ----------------------------------------------------------------------
7 |
8 | export default function GetFontValue(variant) {
9 | const theme = useTheme();
10 |
11 | const breakpoints = useWidth();
12 |
13 | const key = theme.breakpoints.up(breakpoints === 'xl' ? 'lg' : breakpoints);
14 |
15 | const hasResponsive =
16 | variant === 'h1' ||
17 | variant === 'h2' ||
18 | variant === 'h3' ||
19 | variant === 'h4' ||
20 | variant === 'h5' ||
21 | variant === 'h6';
22 |
23 | const getFont =
24 | hasResponsive && theme.typography[variant][key] ? theme.typography[variant][key] : theme.typography[variant];
25 |
26 | const fontSize = remToPx(getFont.fontSize);
27 |
28 | const lineHeight = Number(theme.typography[variant].lineHeight) * fontSize;
29 |
30 | const { fontWeight } = theme.typography[variant];
31 |
32 | const { letterSpacing } = theme.typography[variant];
33 |
34 | return { fontSize, lineHeight, fontWeight, letterSpacing };
35 | }
36 |
37 | // ----------------------------------------------------------------------
38 |
39 | export function remToPx(value) {
40 | return Math.round(parseFloat(value) * 16);
41 | }
42 |
43 | export function pxToRem(value) {
44 | return `${value / 16}rem`;
45 | }
46 |
47 | export function responsiveFontSizes({ sm, md, lg }) {
48 | return {
49 | '@media (min-width:600px)': {
50 | fontSize: pxToRem(sm),
51 | },
52 | '@media (min-width:900px)': {
53 | fontSize: pxToRem(md),
54 | },
55 | '@media (min-width:1200px)': {
56 | fontSize: pxToRem(lg),
57 | },
58 | };
59 | }
60 |
61 | // ----------------------------------------------------------------------
62 |
63 | function useWidth() {
64 | const theme = useTheme();
65 |
66 | const keys = [...theme.breakpoints.keys].reverse();
67 |
68 | return (
69 | keys.reduce((output, key) => {
70 | // eslint-disable-next-line react-hooks/rules-of-hooks
71 | const matches = useResponsive('up', key);
72 |
73 | return !output && matches ? key : output;
74 | }, null) || 'xs'
75 | );
76 | }
77 |
--------------------------------------------------------------------------------
/src/components/animate/variants/slide.js:
--------------------------------------------------------------------------------
1 | //
2 | import { varTranEnter, varTranExit } from './transition';
3 |
4 | // ----------------------------------------------------------------------
5 |
6 | export const varSlide = (props) => {
7 | const distance = props?.distance || 160;
8 | const durationIn = props?.durationIn;
9 | const durationOut = props?.durationOut;
10 | const easeIn = props?.easeIn;
11 | const easeOut = props?.easeOut;
12 |
13 | return {
14 | // IN
15 | inUp: {
16 | initial: { y: distance },
17 | animate: { y: 0, transition: varTranEnter({ durationIn, easeIn }) },
18 | exit: { y: distance, transition: varTranExit({ durationOut, easeOut }) }
19 | },
20 | inDown: {
21 | initial: { y: -distance },
22 | animate: { y: 0, transition: varTranEnter({ durationIn, easeIn }) },
23 | exit: { y: -distance, transition: varTranExit({ durationOut, easeOut }) }
24 | },
25 | inLeft: {
26 | initial: { x: -distance },
27 | animate: { x: 0, transition: varTranEnter({ durationIn, easeIn }) },
28 | exit: { x: -distance, transition: varTranExit({ durationOut, easeOut }) }
29 | },
30 | inRight: {
31 | initial: { x: distance },
32 | animate: { x: 0, transition: varTranEnter({ durationIn, easeIn }) },
33 | exit: { x: distance, transition: varTranExit({ durationOut, easeOut }) }
34 | },
35 |
36 | // OUT
37 | outUp: {
38 | initial: { y: 0 },
39 | animate: { y: -distance, transition: varTranEnter({ durationIn, easeIn }) },
40 | exit: { y: 0, transition: varTranExit({ durationOut, easeOut }) }
41 | },
42 | outDown: {
43 | initial: { y: 0 },
44 | animate: { y: distance, transition: varTranEnter({ durationIn, easeIn }) },
45 | exit: { y: 0, transition: varTranExit({ durationOut, easeOut }) }
46 | },
47 | outLeft: {
48 | initial: { x: 0 },
49 | animate: { x: -distance, transition: varTranEnter({ durationIn, easeIn }) },
50 | exit: { x: 0, transition: varTranExit({ durationOut, easeOut }) }
51 | },
52 | outRight: {
53 | initial: { x: 0 },
54 | animate: { x: distance, transition: varTranEnter({ durationIn, easeIn }) },
55 | exit: { x: 0, transition: varTranExit({ durationOut, easeOut }) }
56 | }
57 | };
58 | };
59 |
--------------------------------------------------------------------------------
/src/theme/overrides/Alert.js:
--------------------------------------------------------------------------------
1 | import { ErrorIcon, InfoIcon, SuccessIcon, WarningIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Alert(theme) {
6 | const isLight = theme.palette.mode === 'light';
7 |
8 | const standardStyle = (color) => ({
9 | color: theme.palette[color][isLight ? 'darker' : 'lighter'],
10 | backgroundColor: theme.palette[color][isLight ? 'lighter' : 'darker'],
11 | '& .MuiAlert-icon': {
12 | color: theme.palette[color][isLight ? 'main' : 'light'],
13 | },
14 | });
15 |
16 | const filledStyle = (color) => ({
17 | color: theme.palette[color].contrastText,
18 | });
19 |
20 | const outlinedStyle = (color) => ({
21 | color: theme.palette[color][isLight ? 'darker' : 'lighter'],
22 | border: `solid 1px ${theme.palette[color][isLight ? 'light' : 'dark']}`,
23 | backgroundColor: theme.palette[color][isLight ? 'lighter' : 'darker'],
24 | '& .MuiAlert-icon': {
25 | color: theme.palette[color][isLight ? 'main' : 'light'],
26 | },
27 | });
28 |
29 | return {
30 | MuiAlert: {
31 | defaultProps: {
32 | iconMapping: {
33 | info: ,
34 | success: ,
35 | warning: ,
36 | error: ,
37 | },
38 | },
39 |
40 | styleOverrides: {
41 | message: {
42 | '& .MuiAlertTitle-root': {
43 | marginBottom: theme.spacing(0.5),
44 | },
45 | },
46 | action: {
47 | '& button:not(:first-of-type)': {
48 | marginLeft: theme.spacing(1),
49 | },
50 | },
51 |
52 | standardInfo: standardStyle('info'),
53 | standardSuccess: standardStyle('success'),
54 | standardWarning: standardStyle('warning'),
55 | standardError: standardStyle('error'),
56 |
57 | filledInfo: filledStyle('info'),
58 | filledSuccess: filledStyle('success'),
59 | filledWarning: filledStyle('warning'),
60 | filledError: filledStyle('error'),
61 |
62 | outlinedInfo: outlinedStyle('info'),
63 | outlinedSuccess: outlinedStyle('success'),
64 | outlinedWarning: outlinedStyle('warning'),
65 | outlinedError: outlinedStyle('error'),
66 | },
67 | },
68 | };
69 | }
70 |
--------------------------------------------------------------------------------
/src/theme/typography.js:
--------------------------------------------------------------------------------
1 | import { pxToRem, responsiveFontSizes } from '../utils/getFontValue';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | const FONT_PRIMARY = 'Manrope, Public Sans, sans-serif'; // Google Font
6 | // const FONT_SECONDARY = 'CircularStd, sans-serif'; // Local Font
7 |
8 | const typography = {
9 | fontFamily: FONT_PRIMARY,
10 | fontWeightRegular: 400,
11 | fontWeightMedium: 600,
12 | fontWeightBold: 700,
13 | h1: {
14 | fontWeight: 700,
15 | lineHeight: 80 / 64,
16 | fontSize: pxToRem(40),
17 | letterSpacing: 2,
18 | ...responsiveFontSizes({ sm: 52, md: 58, lg: 64 }),
19 | },
20 | h2: {
21 | fontWeight: 700,
22 | lineHeight: 64 / 48,
23 | fontSize: pxToRem(32),
24 | ...responsiveFontSizes({ sm: 40, md: 44, lg: 48 }),
25 | },
26 | h3: {
27 | fontWeight: 700,
28 | lineHeight: 1.5,
29 | fontSize: pxToRem(24),
30 | ...responsiveFontSizes({ sm: 26, md: 30, lg: 32 }),
31 | },
32 | h4: {
33 | fontWeight: 700,
34 | lineHeight: 1.5,
35 | fontSize: pxToRem(20),
36 | ...responsiveFontSizes({ sm: 20, md: 24, lg: 24 }),
37 | },
38 | h5: {
39 | fontWeight: 700,
40 | lineHeight: 1.5,
41 | fontSize: pxToRem(18),
42 | ...responsiveFontSizes({ sm: 19, md: 20, lg: 20 }),
43 | },
44 | h6: {
45 | fontWeight: 700,
46 | lineHeight: 28 / 18,
47 | fontSize: pxToRem(17),
48 | ...responsiveFontSizes({ sm: 18, md: 18, lg: 18 }),
49 | },
50 | subtitle1: {
51 | fontWeight: 600,
52 | lineHeight: 1.5,
53 | fontSize: pxToRem(16),
54 | },
55 | subtitle2: {
56 | fontWeight: 700,
57 | lineHeight: 22 / 14,
58 | fontSize: pxToRem(14),
59 | },
60 | body1: {
61 | lineHeight: 1.5,
62 | fontSize: pxToRem(16),
63 | },
64 | body2: {
65 | lineHeight: 22 / 14,
66 | fontSize: pxToRem(14),
67 | fontWeight: 600,
68 | },
69 | caption: {
70 | lineHeight: 1.5,
71 | fontSize: pxToRem(12),
72 | fontWeight: 600,
73 | },
74 | overline: {
75 | fontWeight: 700,
76 | lineHeight: 1.5,
77 | fontSize: pxToRem(12),
78 | textTransform: 'uppercase',
79 | },
80 | button: {
81 | fontWeight: 700,
82 | lineHeight: 24 / 14,
83 | fontSize: pxToRem(14),
84 | textTransform: 'capitalize',
85 | },
86 | article: {
87 | fontWeight: 700,
88 | }
89 | };
90 |
91 | export default typography;
92 |
--------------------------------------------------------------------------------
/src/components/settings/ThemeContrast.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { useMemo } from 'react';
3 | // @mui
4 | import { CssBaseline } from '@mui/material';
5 | import { alpha, ThemeProvider, createTheme, useTheme } from '@mui/material/styles';
6 | // hooks
7 | import useSettings from '../../hooks/useSettings';
8 | //
9 | import componentsOverride from '../../theme/overrides';
10 |
11 | // ----------------------------------------------------------------------
12 |
13 | ThemeContrast.propTypes = {
14 | children: PropTypes.node,
15 | };
16 |
17 | export default function ThemeContrast({ children }) {
18 | const defaultTheme = useTheme();
19 |
20 | const { themeContrast } = useSettings();
21 |
22 | const isLight = defaultTheme.palette.mode === 'light';
23 |
24 | const shadowColor = isLight ? defaultTheme.palette.grey[500] : defaultTheme.palette.common.black;
25 |
26 | const styles = {
27 | bgDefault: defaultTheme.palette.background.default,
28 | bgBold: isLight ? defaultTheme.palette.grey[100] : defaultTheme.palette.grey[900],
29 | cardDefault: defaultTheme.components?.MuiCard?.styleOverrides?.root,
30 | cardBold: {
31 | zIndex: 0,
32 | position: 'relative',
33 | borderRadius: Number(defaultTheme.shape.borderRadius) * 2,
34 | boxShadow: `0 0 1px 0 ${alpha(shadowColor, 0.48)}, 0 2px 4px -1px ${alpha(shadowColor, 0.24)}`,
35 | },
36 | };
37 |
38 | const themeOptions = useMemo(
39 | () => ({
40 | ...defaultTheme,
41 | palette: {
42 | ...defaultTheme.palette,
43 | background: {
44 | ...defaultTheme.palette.background,
45 | default: themeContrast === 'bold' ? styles.bgBold : styles.bgDefault,
46 | },
47 | },
48 | components: {
49 | MuiCard: {
50 | styleOverrides: {
51 | root: themeContrast === 'bold' ? styles.cardBold : styles.cardDefault,
52 | },
53 | },
54 | },
55 | }),
56 |
57 | [defaultTheme, themeContrast, styles.bgBold, styles.bgDefault, styles.cardBold, styles.cardDefault]
58 | );
59 |
60 | const theme = createTheme(themeOptions);
61 |
62 | theme.components = {
63 | ...componentsOverride(theme),
64 | MuiCard: themeOptions.components?.MuiCard,
65 | };
66 |
67 | return (
68 |
69 |
70 | {children}
71 |
72 | );
73 | }
74 |
--------------------------------------------------------------------------------
/src/theme/overrides/Table.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Table(theme) {
4 | return {
5 | MuiTableRow: {
6 | styleOverrides: {
7 | root: {
8 | '&.Mui-selected': {
9 | backgroundColor: theme.palette.action.selected,
10 | '&:hover': {
11 | backgroundColor: theme.palette.action.hover,
12 | },
13 | },
14 | },
15 | },
16 | },
17 | MuiTableCell: {
18 | styleOverrides: {
19 | root: {
20 | borderBottom: 'none',
21 | },
22 | head: {
23 | color: theme.palette.text.secondary,
24 | backgroundColor: theme.palette.background.neutral,
25 | '&:first-of-type': {
26 | paddingLeft: theme.spacing(3),
27 | borderTopLeftRadius: theme.shape.borderRadius,
28 | borderBottomLeftRadius: theme.shape.borderRadius,
29 | boxShadow: `inset 8px 0 0 ${theme.palette.background.paper}`,
30 | },
31 | '&:last-of-type': {
32 | paddingRight: theme.spacing(3),
33 | borderTopRightRadius: theme.shape.borderRadius,
34 | borderBottomRightRadius: theme.shape.borderRadius,
35 | boxShadow: `inset -8px 0 0 ${theme.palette.background.paper}`,
36 | },
37 | },
38 | stickyHeader: {
39 | backgroundColor: theme.palette.background.paper,
40 | backgroundImage: `linear-gradient(to bottom, ${theme.palette.background.neutral} 0%, ${theme.palette.background.neutral} 100%)`,
41 | },
42 | body: {
43 | '&:first-of-type': {
44 | paddingLeft: theme.spacing(3),
45 | },
46 | '&:last-of-type': {
47 | paddingRight: theme.spacing(3),
48 | },
49 | },
50 | },
51 | },
52 | MuiTablePagination: {
53 | styleOverrides: {
54 | root: {
55 | borderTop: `solid 1px ${theme.palette.divider}`,
56 | },
57 | toolbar: {
58 | height: 64,
59 | },
60 | select: {
61 | '&:focus': {
62 | borderRadius: theme.shape.borderRadius,
63 | },
64 | },
65 | selectIcon: {
66 | width: 20,
67 | height: 20,
68 | marginTop: -4,
69 | },
70 | },
71 | },
72 | };
73 | }
74 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/SettingColorPresets.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { alpha, styled } from '@mui/material/styles';
3 | import { Box, Grid, RadioGroup, CardActionArea } from '@mui/material';
4 | // hooks
5 | import useSettings from '../../../hooks/useSettings';
6 | //
7 | import BoxMask from './BoxMask';
8 |
9 | // ----------------------------------------------------------------------
10 |
11 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({
12 | height: 48,
13 | display: 'flex',
14 | alignItems: 'center',
15 | justifyContent: 'center',
16 | color: theme.palette.text.disabled,
17 | border: `solid 1px ${theme.palette.grey[500_12]}`,
18 | borderRadius: Number(theme.shape.borderRadius) * 1.25,
19 | }));
20 |
21 | // ----------------------------------------------------------------------
22 |
23 | export default function SettingColorPresets() {
24 | const { themeColorPresets, onChangeColor, colorOption } = useSettings();
25 |
26 | return (
27 |
28 |
29 | {colorOption.map((color) => {
30 | const colorName = color.name;
31 | const colorValue = color.value;
32 | const isSelected = themeColorPresets === colorName;
33 |
34 | return (
35 |
36 |
45 |
53 | theme.transitions.create('all', {
54 | easing: theme.transitions.easing.easeInOut,
55 | duration: theme.transitions.duration.shorter,
56 | }),
57 | ...(isSelected && { transform: 'none' }),
58 | }}
59 | />
60 |
61 |
62 |
63 |
64 | );
65 | })}
66 |
67 |
68 | );
69 | }
70 |
--------------------------------------------------------------------------------
/src/components/animate/FabButtonAnimate.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { m } from 'framer-motion';
3 | import { forwardRef } from 'react';
4 | // @mui
5 | import { useTheme } from '@mui/material/styles';
6 | import { Box, Fab } from '@mui/material';
7 |
8 | // ----------------------------------------------------------------------
9 |
10 | const FabButtonAnimate = forwardRef(({ color = 'primary', size = 'large', children, sx, sxWrap, ...other }, ref) => {
11 | const theme = useTheme();
12 |
13 | if (color === 'default' || color === 'inherit' || color === 'primary' || color === 'secondary') {
14 | return (
15 |
16 |
17 | {children}
18 |
19 |
20 | );
21 | }
22 |
23 | return (
24 |
25 |
39 | {children}
40 |
41 |
42 | );
43 | });
44 |
45 | FabButtonAnimate.propTypes = {
46 | children: PropTypes.node.isRequired,
47 | color: PropTypes.oneOf(['inherit', 'default', 'primary', 'secondary', 'info', 'success', 'warning', 'error']),
48 | size: PropTypes.oneOf(['small', 'medium', 'large']),
49 | sx: PropTypes.object,
50 | sxWrap: PropTypes.object
51 | };
52 |
53 | export default FabButtonAnimate;
54 |
55 | // ----------------------------------------------------------------------
56 |
57 | const varSmall = {
58 | hover: { scale: 1.07 },
59 | tap: { scale: 0.97 }
60 | };
61 |
62 | const varMedium = {
63 | hover: { scale: 1.06 },
64 | tap: { scale: 0.98 }
65 | };
66 |
67 | const varLarge = {
68 | hover: { scale: 1.05 },
69 | tap: { scale: 0.99 }
70 | };
71 |
72 | AnimateWrap.propTypes = {
73 | children: PropTypes.node.isRequired,
74 | size: PropTypes.oneOf(['small', 'medium', 'large']),
75 | sxWrap: PropTypes.object
76 | };
77 |
78 | function AnimateWrap({ size, children, sxWrap }) {
79 | const isSmall = size === 'small';
80 | const isLarge = size === 'large';
81 |
82 | return (
83 |
93 | {children}
94 |
95 | );
96 | }
97 |
--------------------------------------------------------------------------------
/src/theme/overrides/index.js:
--------------------------------------------------------------------------------
1 | import Fab from './Fab';
2 | import Card from './Card';
3 | import Chip from './Chip';
4 | import Tabs from './Tabs';
5 | import Menu from './Menu';
6 | import Link from './Link';
7 | import Lists from './List';
8 | import Table from './Table';
9 | import Alert from './Alert';
10 | import Badge from './Badge';
11 | import Paper from './Paper';
12 | import Input from './Input';
13 | import Radio from './Radio';
14 | import Drawer from './Drawer';
15 | import Dialog from './Dialog';
16 | import Avatar from './Avatar';
17 | import Rating from './Rating';
18 | import Slider from './Slider';
19 | import Button from './Button';
20 | import Switch from './Switch';
21 | import Select from './Select';
22 | import SvgIcon from './SvgIcon';
23 | import Tooltip from './Tooltip';
24 | import Popover from './Popover';
25 | import Stepper from './Stepper';
26 | import DataGrid from './DataGrid';
27 | import Skeleton from './Skeleton';
28 | import Backdrop from './Backdrop';
29 | import Progress from './Progress';
30 | import Timeline from './Timeline';
31 | import TreeView from './TreeView';
32 | import Checkbox from './Checkbox';
33 | import Accordion from './Accordion';
34 | import Typography from './Typography';
35 | import Pagination from './Pagination';
36 | import Breadcrumbs from './Breadcrumbs';
37 | import ButtonGroup from './ButtonGroup';
38 | import CssBaseline from './CssBaseline';
39 | import Autocomplete from './Autocomplete';
40 | import ToggleButton from './ToggleButton';
41 | import ControlLabel from './ControlLabel';
42 | import LoadingButton from './LoadingButton';
43 |
44 | // ----------------------------------------------------------------------
45 |
46 | export default function ComponentsOverrides(theme) {
47 | return Object.assign(
48 | Fab(theme),
49 | Tabs(theme),
50 | Chip(theme),
51 | Card(theme),
52 | Menu(theme),
53 | Link(theme),
54 | Input(theme),
55 | Radio(theme),
56 | Badge(theme),
57 | Lists(theme),
58 | Table(theme),
59 | Paper(theme),
60 | Alert(theme),
61 | Switch(theme),
62 | Select(theme),
63 | Button(theme),
64 | Rating(theme),
65 | Dialog(theme),
66 | Avatar(theme),
67 | Slider(theme),
68 | Drawer(theme),
69 | Stepper(theme),
70 | Tooltip(theme),
71 | Popover(theme),
72 | SvgIcon(theme),
73 | Checkbox(theme),
74 | DataGrid(theme),
75 | Skeleton(theme),
76 | Timeline(theme),
77 | TreeView(theme),
78 | Backdrop(theme),
79 | Progress(theme),
80 | Accordion(theme),
81 | Typography(theme),
82 | Pagination(theme),
83 | ButtonGroup(theme),
84 | Breadcrumbs(theme),
85 | CssBaseline(theme),
86 | Autocomplete(theme),
87 | ControlLabel(theme),
88 | ToggleButton(theme),
89 | LoadingButton(theme)
90 | );
91 | }
92 |
--------------------------------------------------------------------------------
/src/components/animate/variants/fade.js:
--------------------------------------------------------------------------------
1 | import { varTranEnter, varTranExit } from './transition';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export const varFade = (props) => {
6 | const distance = props?.distance || 120;
7 | const durationIn = props?.durationIn;
8 | const durationOut = props?.durationOut;
9 | const easeIn = props?.easeIn;
10 | const easeOut = props?.easeOut;
11 |
12 | return {
13 | // IN
14 | in: {
15 | initial: { opacity: 0 },
16 | animate: { opacity: 1, transition: varTranEnter },
17 | exit: { opacity: 0, transition: varTranExit }
18 | },
19 | inUp: {
20 | initial: { y: distance, opacity: 0 },
21 | animate: { y: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
22 | exit: { y: distance, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
23 | },
24 | inDown: {
25 | initial: { y: -distance, opacity: 0 },
26 | animate: { y: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
27 | exit: { y: -distance, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
28 | },
29 | inLeft: {
30 | initial: { x: -distance, opacity: 0 },
31 | animate: { x: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
32 | exit: { x: -distance, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
33 | },
34 | inRight: {
35 | initial: { x: distance, opacity: 0 },
36 | animate: { x: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
37 | exit: { x: distance, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
38 | },
39 |
40 | // OUT
41 | out: {
42 | initial: { opacity: 1 },
43 | animate: { opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
44 | exit: { opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
45 | },
46 | outUp: {
47 | initial: { y: 0, opacity: 1 },
48 | animate: { y: -distance, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
49 | exit: { y: 0, opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
50 | },
51 | outDown: {
52 | initial: { y: 0, opacity: 1 },
53 | animate: { y: distance, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
54 | exit: { y: 0, opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
55 | },
56 | outLeft: {
57 | initial: { x: 0, opacity: 1 },
58 | animate: { x: -distance, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
59 | exit: { x: 0, opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
60 | },
61 | outRight: {
62 | initial: { x: 0, opacity: 1 },
63 | animate: { x: distance, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
64 | exit: { x: 0, opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
65 | }
66 | };
67 | };
68 |
--------------------------------------------------------------------------------
/src/theme/overrides/DataGrid.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function DataGrid(theme) {
4 | return {
5 | MuiDataGrid: {
6 | styleOverrides: {
7 | root: {
8 | borderRadius: 0,
9 | border: `1px solid transparent`,
10 | '& .MuiTablePagination-root': {
11 | borderTop: 0,
12 | },
13 | },
14 | cell: {
15 | borderBottom: `1px solid ${theme.palette.divider}`,
16 | },
17 | columnSeparator: {
18 | color: theme.palette.divider,
19 | },
20 | toolbarContainer: {
21 | padding: theme.spacing(2),
22 | backgroundColor: theme.palette.background.neutral,
23 | '& .MuiButton-root': {
24 | marginRight: theme.spacing(1.5),
25 | color: theme.palette.text.primary,
26 | '&:hover': {
27 | backgroundColor: theme.palette.action.hover,
28 | },
29 | },
30 | },
31 | paper: {
32 | boxShadow: theme.customShadows.dropdown,
33 | },
34 | menu: {
35 | '& .MuiPaper-root': {
36 | boxShadow: theme.customShadows.dropdown,
37 | },
38 | '& .MuiMenuItem-root': {
39 | ...theme.typography.body2,
40 | '& .MuiListItemIcon-root': {
41 | minWidth: 'auto',
42 | },
43 | },
44 | },
45 | panelFooter: {
46 | padding: theme.spacing(2),
47 | justifyContent: 'flex-end',
48 | borderTop: `1px solid ${theme.palette.divider}`,
49 | '& .MuiButton-root': {
50 | '&:first-of-type': {
51 | marginRight: theme.spacing(1.5),
52 | color: theme.palette.text.primary,
53 | '&:hover': {
54 | backgroundColor: theme.palette.action.hover,
55 | },
56 | },
57 | '&:last-of-type': {
58 | color: theme.palette.common.white,
59 | backgroundColor: theme.palette.primary.main,
60 | '&:hover': {
61 | backgroundColor: theme.palette.primary.dark,
62 | },
63 | },
64 | },
65 | },
66 | filterForm: {
67 | padding: theme.spacing(1.5, 0),
68 | '& .MuiFormControl-root': {
69 | margin: theme.spacing(0, 0.5),
70 | },
71 | '& .MuiInput-root': {
72 | marginTop: theme.spacing(3),
73 | '&::before, &::after': {
74 | display: 'none',
75 | },
76 | '& .MuiNativeSelect-select, .MuiInput-input': {
77 | ...theme.typography.body2,
78 | padding: theme.spacing(0.75, 1),
79 | borderRadius: theme.shape.borderRadius,
80 | backgroundColor: theme.palette.background.neutral,
81 | },
82 | '& .MuiSvgIcon-root': {
83 | right: 4,
84 | },
85 | },
86 | },
87 | },
88 | },
89 | };
90 | }
91 |
--------------------------------------------------------------------------------
/src/components/animate/variants/background.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export const varBgColor = (props) => {
4 | const colors = props?.colors || ['#19dcea', '#b22cff'];
5 | const duration = props?.duration || 5;
6 | const ease = props?.ease || 'linear';
7 |
8 | return {
9 | animate: {
10 | background: colors,
11 | transition: { duration, ease }
12 | }
13 | };
14 | };
15 |
16 | // ----------------------------------------------------------------------
17 |
18 | export const varBgKenburns = (props) => {
19 | const duration = props?.duration || 5;
20 | const ease = props?.ease || 'easeOut';
21 |
22 | return {
23 | top: {
24 | animate: {
25 | scale: [1, 1.25],
26 | y: [0, -15],
27 | transformOrigin: ['50% 16%', 'top'],
28 | transition: { duration, ease }
29 | }
30 | },
31 | right: {
32 | animate: {
33 | scale: [1, 1.25],
34 | x: [0, 20],
35 | y: [0, -15],
36 | transformOrigin: ['84% 50%', 'right'],
37 | transition: { duration, ease }
38 | }
39 | },
40 | bottom: {
41 | animate: {
42 | scale: [1, 1.25],
43 | y: [0, 15],
44 | transformOrigin: ['50% 84%', 'bottom'],
45 | transition: { duration, ease }
46 | }
47 | },
48 | left: {
49 | animate: {
50 | scale: [1, 1.25],
51 | x: [0, -20],
52 | y: [0, 15],
53 | transformOrigin: ['16% 50%', 'left'],
54 | transition: { duration, ease }
55 | }
56 | }
57 | };
58 | };
59 |
60 | // ----------------------------------------------------------------------
61 |
62 | export const varBgPan = (props) => {
63 | const colors = props?.colors || ['#ee7752', '#e73c7e', '#23a6d5', '#23d5ab'];
64 | const duration = props?.duration || 5;
65 | const ease = props?.ease || 'linear';
66 |
67 | const gradient = (deg) => `linear-gradient(${deg}deg, ${colors})`;
68 |
69 | return {
70 | top: {
71 | animate: {
72 | backgroundImage: [gradient(0), gradient(0)],
73 | backgroundPosition: ['center 99%', 'center 1%'],
74 | backgroundSize: ['100% 600%', '100% 600%'],
75 | transition: { duration, ease }
76 | }
77 | },
78 | right: {
79 | animate: {
80 | backgroundPosition: ['1% center', '99% center'],
81 | backgroundImage: [gradient(270), gradient(270)],
82 | backgroundSize: ['600% 100%', '600% 100%'],
83 | transition: { duration, ease }
84 | }
85 | },
86 | bottom: {
87 | animate: {
88 | backgroundImage: [gradient(0), gradient(0)],
89 | backgroundPosition: ['center 1%', 'center 99%'],
90 | backgroundSize: ['100% 600%', '100% 600%'],
91 | transition: { duration, ease }
92 | }
93 | },
94 | left: {
95 | animate: {
96 | backgroundPosition: ['99% center', '1% center'],
97 | backgroundImage: [gradient(270), gradient(270)],
98 | backgroundSize: ['600% 100%', '600% 100%'],
99 | transition: { duration, ease }
100 | }
101 | }
102 | };
103 | };
104 |
--------------------------------------------------------------------------------
/src/utils/getFileFormat.js:
--------------------------------------------------------------------------------
1 | // components
2 | import Image from '../components/Image';
3 | import Iconify from '../components/Iconify';
4 |
5 | // ----------------------------------------------------------------------
6 |
7 | const FORMAT_IMG = ['jpg', 'jpeg', 'gif', 'bmp', 'png'];
8 | const FORMAT_VIDEO = ['m4v', 'avi', 'mpg', 'mp4', 'webm'];
9 | const FORMAT_WORD = ['doc', 'docx'];
10 | const FORMAT_EXCEL = ['xls', 'xlsx'];
11 | const FORMAT_POWERPOINT = ['ppt', 'pptx'];
12 | const FORMAT_PDF = ['pdf'];
13 | const FORMAT_PHOTOSHOP = ['psd'];
14 | const FORMAT_ILLUSTRATOR = ['ai', 'esp'];
15 |
16 | export function getFileType(fileUrl = '') {
17 | return (fileUrl && fileUrl.split('.').pop()) || '';
18 | }
19 |
20 | export function getFileName(fileUrl) {
21 | return fileUrl.substring(fileUrl.lastIndexOf('/') + 1).replace(/\.[^/.]+$/, '');
22 | }
23 |
24 | export function getFileFullName(fileUrl) {
25 | return fileUrl.split('/').pop();
26 | }
27 |
28 | export function getFileFormat(fileUrl) {
29 | let format;
30 |
31 | switch (fileUrl.includes(getFileType(fileUrl))) {
32 | case FORMAT_IMG.includes(getFileType(fileUrl)):
33 | format = 'image';
34 | break;
35 | case FORMAT_VIDEO.includes(getFileType(fileUrl)):
36 | format = 'video';
37 | break;
38 | case FORMAT_WORD.includes(getFileType(fileUrl)):
39 | format = 'word';
40 | break;
41 | case FORMAT_EXCEL.includes(getFileType(fileUrl)):
42 | format = 'excel';
43 | break;
44 | case FORMAT_POWERPOINT.includes(getFileType(fileUrl)):
45 | format = 'powerpoint';
46 | break;
47 | case FORMAT_PDF.includes(getFileType(fileUrl)):
48 | format = 'pdf';
49 | break;
50 | case FORMAT_PHOTOSHOP.includes(getFileType(fileUrl)):
51 | format = 'photoshop';
52 | break;
53 | case FORMAT_ILLUSTRATOR.includes(getFileType(fileUrl)):
54 | format = 'illustrator';
55 | break;
56 | default:
57 | format = getFileType(fileUrl);
58 | }
59 |
60 | return format;
61 | }
62 |
63 | const getIcon = (name) => (
64 |
69 | );
70 |
71 | export function getFileThumb(fileUrl) {
72 | let thumb;
73 | switch (getFileFormat(fileUrl)) {
74 | case 'video':
75 | thumb = getIcon('format_video');
76 | break;
77 | case 'word':
78 | thumb = getIcon('format_word');
79 | break;
80 | case 'excel':
81 | thumb = getIcon('format_excel');
82 | break;
83 | case 'powerpoint':
84 | thumb = getIcon('format_powerpoint');
85 | break;
86 | case 'pdf':
87 | thumb = getIcon('format_pdf');
88 | break;
89 | case 'photoshop':
90 | thumb = getIcon('format_photoshop');
91 | break;
92 | case 'illustrator':
93 | thumb = getIcon('format_ai');
94 | break;
95 | case 'image':
96 | thumb = ;
97 | break;
98 | default:
99 | thumb = ;
100 | }
101 | return thumb;
102 | }
103 |
--------------------------------------------------------------------------------
/src/components/animate/variants/bounce.js:
--------------------------------------------------------------------------------
1 | import { varTranEnter, varTranExit } from './transition';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export const varBounce = (props) => {
6 | const durationIn = props?.durationIn;
7 | const durationOut = props?.durationOut;
8 | const easeIn = props?.easeIn;
9 | const easeOut = props?.easeOut;
10 |
11 | return {
12 | // IN
13 | in: {
14 | initial: {},
15 | animate: {
16 | scale: [0.3, 1.1, 0.9, 1.03, 0.97, 1],
17 | opacity: [0, 1, 1, 1, 1, 1],
18 | transition: varTranEnter({ durationIn, easeIn }),
19 | },
20 | exit: {
21 | scale: [0.9, 1.1, 0.3],
22 | opacity: [1, 1, 0],
23 | },
24 | },
25 | inUp: {
26 | initial: {},
27 | animate: {
28 | y: [720, -24, 12, -4, 0],
29 | scaleY: [4, 0.9, 0.95, 0.985, 1],
30 | opacity: [0, 1, 1, 1, 1],
31 | transition: { ...varTranEnter({ durationIn, easeIn }) },
32 | },
33 | exit: {
34 | y: [12, -24, 720],
35 | scaleY: [0.985, 0.9, 3],
36 | opacity: [1, 1, 0],
37 | transition: varTranExit({ durationOut, easeOut }),
38 | },
39 | },
40 | inDown: {
41 | initial: {},
42 | animate: {
43 | y: [-720, 24, -12, 4, 0],
44 | scaleY: [4, 0.9, 0.95, 0.985, 1],
45 | opacity: [0, 1, 1, 1, 1],
46 | transition: varTranEnter({ durationIn, easeIn }),
47 | },
48 | exit: {
49 | y: [-12, 24, -720],
50 | scaleY: [0.985, 0.9, 3],
51 | opacity: [1, 1, 0],
52 | transition: varTranExit({ durationOut, easeOut }),
53 | },
54 | },
55 | inLeft: {
56 | initial: {},
57 | animate: {
58 | x: [-720, 24, -12, 4, 0],
59 | scaleX: [3, 1, 0.98, 0.995, 1],
60 | opacity: [0, 1, 1, 1, 1],
61 | transition: varTranEnter({ durationIn, easeIn }),
62 | },
63 | exit: {
64 | x: [0, 24, -720],
65 | scaleX: [1, 0.9, 2],
66 | opacity: [1, 1, 0],
67 | transition: varTranExit({ durationOut, easeOut }),
68 | },
69 | },
70 | inRight: {
71 | initial: {},
72 | animate: {
73 | x: [720, -24, 12, -4, 0],
74 | scaleX: [3, 1, 0.98, 0.995, 1],
75 | opacity: [0, 1, 1, 1, 1],
76 | transition: varTranEnter({ durationIn, easeIn }),
77 | },
78 | exit: {
79 | x: [0, -24, 720],
80 | scaleX: [1, 0.9, 2],
81 | opacity: [1, 1, 0],
82 | transition: varTranExit({ durationOut, easeOut }),
83 | },
84 | },
85 |
86 | // OUT
87 | out: {
88 | animate: { scale: [0.9, 1.1, 0.3], opacity: [1, 1, 0] },
89 | },
90 | outUp: {
91 | animate: { y: [-12, 24, -720], scaleY: [0.985, 0.9, 3], opacity: [1, 1, 0] },
92 | },
93 | outDown: {
94 | animate: { y: [12, -24, 720], scaleY: [0.985, 0.9, 3], opacity: [1, 1, 0] },
95 | },
96 | outLeft: {
97 | animate: { x: [0, 24, -720], scaleX: [1, 0.9, 2], opacity: [1, 1, 0] },
98 | },
99 | outRight: {
100 | animate: { x: [0, -24, 720], scaleX: [1, 0.9, 2], opacity: [1, 1, 0] },
101 | },
102 | };
103 | };
104 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13 |
14 | The page will reload when you make changes.\
15 | You may also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!**
35 |
36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39 |
40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `npm run build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/src/components/animate/variants/zoom.js:
--------------------------------------------------------------------------------
1 | import { varTranEnter, varTranExit } from './transition';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export const varZoom = (props) => {
6 | const distance = props?.distance || 720;
7 | const durationIn = props?.durationIn;
8 | const durationOut = props?.durationOut;
9 | const easeIn = props?.easeIn;
10 | const easeOut = props?.easeOut;
11 |
12 | return {
13 | // IN
14 | in: {
15 | initial: { scale: 0, opacity: 0 },
16 | animate: { scale: 1, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
17 | exit: { scale: 0, opacity: 0, transition: varTranExit({ durationOut, easeOut }) },
18 | },
19 | inUp: {
20 | initial: { scale: 0, opacity: 0, translateY: distance },
21 | animate: {
22 | scale: 1,
23 | opacity: 1,
24 | translateY: 0,
25 | transition: varTranEnter({ durationIn, easeIn }),
26 | },
27 | exit: {
28 | scale: 0,
29 | opacity: 0,
30 | translateY: distance,
31 | transition: varTranExit({ durationOut, easeOut }),
32 | },
33 | },
34 | inDown: {
35 | initial: { scale: 0, opacity: 0, translateY: -distance },
36 | animate: {
37 | scale: 1,
38 | opacity: 1,
39 | translateY: 0,
40 | transition: varTranEnter({ durationIn, easeIn }),
41 | },
42 | exit: {
43 | scale: 0,
44 | opacity: 0,
45 | translateY: -distance,
46 | transition: varTranExit({ durationOut, easeOut }),
47 | },
48 | },
49 | inLeft: {
50 | initial: { scale: 0, opacity: 0, translateX: -distance },
51 | animate: {
52 | scale: 1,
53 | opacity: 1,
54 | translateX: 0,
55 | transition: varTranEnter({ durationIn, easeIn }),
56 | },
57 | exit: {
58 | scale: 0,
59 | opacity: 0,
60 | translateX: -distance,
61 | transition: varTranExit({ durationOut, easeOut }),
62 | },
63 | },
64 | inRight: {
65 | initial: { scale: 0, opacity: 0, translateX: distance },
66 | animate: {
67 | scale: 1,
68 | opacity: 1,
69 | translateX: 0,
70 | transition: varTranEnter({ durationIn, easeIn }),
71 | },
72 | exit: {
73 | scale: 0,
74 | opacity: 0,
75 | translateX: distance,
76 | transition: varTranExit({ durationOut, easeOut }),
77 | },
78 | },
79 |
80 | // OUT
81 | out: {
82 | initial: { scale: 1, opacity: 1 },
83 | animate: { scale: 0, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
84 | },
85 | outUp: {
86 | initial: { scale: 1, opacity: 1 },
87 | animate: {
88 | scale: 0,
89 | opacity: 0,
90 | translateY: -distance,
91 | transition: varTranEnter({ durationIn, easeIn }),
92 | },
93 | },
94 | outDown: {
95 | initial: { scale: 1, opacity: 1 },
96 | animate: {
97 | scale: 0,
98 | opacity: 0,
99 | translateY: distance,
100 | transition: varTranEnter({ durationIn, easeIn }),
101 | },
102 | },
103 | outLeft: {
104 | initial: { scale: 1, opacity: 1 },
105 | animate: {
106 | scale: 0,
107 | opacity: 0,
108 | translateX: -distance,
109 | transition: varTranEnter({ durationIn, easeIn }),
110 | },
111 | },
112 | outRight: {
113 | initial: { scale: 1, opacity: 1 },
114 | animate: {
115 | scale: 0,
116 | opacity: 0,
117 | translateX: distance,
118 | transition: varTranEnter({ durationIn, easeIn }),
119 | },
120 | },
121 | };
122 | };
123 |
--------------------------------------------------------------------------------
/src/theme/palette.js:
--------------------------------------------------------------------------------
1 | import { alpha } from '@mui/material/styles';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | function createGradient(color1, color2) {
6 | return `linear-gradient(to bottom, ${color1}, ${color2})`;
7 | }
8 |
9 | // SETUP COLORS
10 | const PRIMARY = {
11 | lighter: '#C8FACD',
12 | light: '#5BE584',
13 | main: '#0162C4',
14 | dark: '#007B55',
15 | darker: '#005249',
16 | };
17 | const SECONDARY = {
18 | lighter: '#D6E4FF',
19 | light: '#84A9FF',
20 | main: '#3366FF',
21 | dark: '#1939B7',
22 | darker: '#091A7A',
23 | };
24 | const INFO = {
25 | lighter: '#D0F2FF',
26 | light: '#74CAFF',
27 | main: '#1890FF',
28 | dark: '#0C53B7',
29 | darker: '#04297A',
30 | };
31 | const SUCCESS = {
32 | lighter: '#E9FCD4',
33 | light: '#AAF27F',
34 | main: '#54D62C',
35 | dark: '#229A16',
36 | darker: '#08660D',
37 | };
38 | const WARNING = {
39 | lighter: '#FFF7CD',
40 | light: '#FFE16A',
41 | main: '#FFC107',
42 | dark: '#B78103',
43 | darker: '#7A4F01',
44 | };
45 | const ERROR = {
46 | lighter: '#FFE7D9',
47 | light: '#FFA48D',
48 | main: '#FF4842',
49 | dark: '#B72136',
50 | darker: '#7A0C2E',
51 | };
52 |
53 | const GREY = {
54 | 0: '#FFFFFF',
55 | 100: '#F9FAFB',
56 | 200: '#F4F6F8',
57 | 300: '#DFE3E8',
58 | 400: '#C4CDD5',
59 | 500: '#919EAB',
60 | 600: '#637381',
61 | 700: '#454F5B',
62 | 800: '#212B36',
63 | 900: '#161C24',
64 | 500_8: alpha('#919EAB', 0.08),
65 | 500_12: alpha('#919EAB', 0.12),
66 | 500_16: alpha('#919EAB', 0.16),
67 | 500_24: alpha('#919EAB', 0.24),
68 | 500_32: alpha('#919EAB', 0.32),
69 | 500_48: alpha('#919EAB', 0.48),
70 | 500_56: alpha('#919EAB', 0.56),
71 | 500_80: alpha('#919EAB', 0.8),
72 | };
73 |
74 | const GRADIENTS = {
75 | primary: createGradient(PRIMARY.light, PRIMARY.main),
76 | info: createGradient(INFO.light, INFO.main),
77 | success: createGradient(SUCCESS.light, SUCCESS.main),
78 | warning: createGradient(WARNING.light, WARNING.main),
79 | error: createGradient(ERROR.light, ERROR.main),
80 | };
81 |
82 | const CHART_COLORS = {
83 | violet: ['#826AF9', '#9E86FF', '#D0AEFF', '#F7D2FF'],
84 | blue: ['#2D99FF', '#83CFFF', '#A5F3FF', '#CCFAFF'],
85 | green: ['#2CD9C5', '#60F1C8', '#A4F7CC', '#C0F2DC'],
86 | yellow: ['#FFE700', '#FFEF5A', '#FFF7AE', '#FFF3D6'],
87 | red: ['#FF6C40', '#FF8F6D', '#FFBD98', '#FFF2D4'],
88 | };
89 |
90 | const COMMON = {
91 | common: { black: '#000', white: '#fff' },
92 | primary: { ...PRIMARY, contrastText: '#fff' },
93 | secondary: { ...SECONDARY, contrastText: '#fff' },
94 | info: { ...INFO, contrastText: '#fff' },
95 | success: { ...SUCCESS, contrastText: GREY[800] },
96 | warning: { ...WARNING, contrastText: GREY[800] },
97 | error: { ...ERROR, contrastText: '#fff' },
98 | grey: GREY,
99 | gradients: GRADIENTS,
100 | chart: CHART_COLORS,
101 | divider: GREY[500_24],
102 | action: {
103 | hover: GREY[500_8],
104 | selected: GREY[500_16],
105 | disabled: GREY[500_80],
106 | disabledBackground: GREY[500_24],
107 | focus: GREY[500_24],
108 | hoverOpacity: 0.08,
109 | disabledOpacity: 0.48,
110 | },
111 | };
112 |
113 | const palette = {
114 | light: {
115 | ...COMMON,
116 | mode: 'light',
117 | text: { primary: GREY[800], secondary: GREY[600], disabled: GREY[500] },
118 | background: { paper: '#fff', default: '#fff', neutral: GREY[200] },
119 | action: { active: GREY[600], ...COMMON.action },
120 | },
121 | dark: {
122 | ...COMMON,
123 | mode: 'dark',
124 | text: { primary: '#fff', secondary: GREY[500], disabled: GREY[600] },
125 | background: { paper: GREY[800], default: GREY[900], neutral: GREY[500_16] },
126 | action: { active: GREY[500], ...COMMON.action },
127 | },
128 | };
129 |
130 | export default palette;
131 |
--------------------------------------------------------------------------------
/src/theme/shadows.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { alpha } from '@mui/material/styles';
3 | //
4 | import palette from './palette';
5 |
6 | // ----------------------------------------------------------------------
7 |
8 | const LIGHT_MODE = palette.light.grey[500];
9 | const DARK_MODE = '#000000';
10 |
11 | const createShadow = (color) => {
12 | const transparent1 = alpha(color, 0.2);
13 | const transparent2 = alpha(color, 0.14);
14 | const transparent3 = alpha(color, 0.12);
15 | return [
16 | 'none',
17 | `0px 2px 1px -1px ${transparent1},0px 1px 1px 0px ${transparent2},0px 1px 3px 0px ${transparent3}`,
18 | `0px 3px 1px -2px ${transparent1},0px 2px 2px 0px ${transparent2},0px 1px 5px 0px ${transparent3}`,
19 | `0px 3px 3px -2px ${transparent1},0px 3px 4px 0px ${transparent2},0px 1px 8px 0px ${transparent3}`,
20 | `0px 2px 4px -1px ${transparent1},0px 4px 5px 0px ${transparent2},0px 1px 10px 0px ${transparent3}`,
21 | `0px 3px 5px -1px ${transparent1},0px 5px 8px 0px ${transparent2},0px 1px 14px 0px ${transparent3}`,
22 | `0px 3px 5px -1px ${transparent1},0px 6px 10px 0px ${transparent2},0px 1px 18px 0px ${transparent3}`,
23 | `0px 4px 5px -2px ${transparent1},0px 7px 10px 1px ${transparent2},0px 2px 16px 1px ${transparent3}`,
24 | `0px 5px 5px -3px ${transparent1},0px 8px 10px 1px ${transparent2},0px 3px 14px 2px ${transparent3}`,
25 | `0px 5px 6px -3px ${transparent1},0px 9px 12px 1px ${transparent2},0px 3px 16px 2px ${transparent3}`,
26 | `0px 6px 6px -3px ${transparent1},0px 10px 14px 1px ${transparent2},0px 4px 18px 3px ${transparent3}`,
27 | `0px 6px 7px -4px ${transparent1},0px 11px 15px 1px ${transparent2},0px 4px 20px 3px ${transparent3}`,
28 | `0px 7px 8px -4px ${transparent1},0px 12px 17px 2px ${transparent2},0px 5px 22px 4px ${transparent3}`,
29 | `0px 7px 8px -4px ${transparent1},0px 13px 19px 2px ${transparent2},0px 5px 24px 4px ${transparent3}`,
30 | `0px 7px 9px -4px ${transparent1},0px 14px 21px 2px ${transparent2},0px 5px 26px 4px ${transparent3}`,
31 | `0px 8px 9px -5px ${transparent1},0px 15px 22px 2px ${transparent2},0px 6px 28px 5px ${transparent3}`,
32 | `0px 8px 10px -5px ${transparent1},0px 16px 24px 2px ${transparent2},0px 6px 30px 5px ${transparent3}`,
33 | `0px 8px 11px -5px ${transparent1},0px 17px 26px 2px ${transparent2},0px 6px 32px 5px ${transparent3}`,
34 | `0px 9px 11px -5px ${transparent1},0px 18px 28px 2px ${transparent2},0px 7px 34px 6px ${transparent3}`,
35 | `0px 9px 12px -6px ${transparent1},0px 19px 29px 2px ${transparent2},0px 7px 36px 6px ${transparent3}`,
36 | `0px 10px 13px -6px ${transparent1},0px 20px 31px 3px ${transparent2},0px 8px 38px 7px ${transparent3}`,
37 | `0px 10px 13px -6px ${transparent1},0px 21px 33px 3px ${transparent2},0px 8px 40px 7px ${transparent3}`,
38 | `0px 10px 14px -6px ${transparent1},0px 22px 35px 3px ${transparent2},0px 8px 42px 7px ${transparent3}`,
39 | `0px 11px 14px -7px ${transparent1},0px 23px 36px 3px ${transparent2},0px 9px 44px 8px ${transparent3}`,
40 | `0px 11px 15px -7px ${transparent1},0px 24px 38px 3px ${transparent2},0px 9px 46px 8px ${transparent3}`,
41 | ];
42 | };
43 |
44 | const createCustomShadow = (color) => {
45 | const transparent = alpha(color, 0.16);
46 | return {
47 | z1: `0 1px 2px 0 ${transparent}`,
48 | z8: `0 8px 16px 0 ${transparent}`,
49 | z12: `0 12px 24px -4px ${transparent}`,
50 | z16: `0 16px 32px -4px ${transparent}`,
51 | z20: `0 20px 40px -4px ${transparent}`,
52 | z24: `0 24px 48px 0 ${transparent}`,
53 | //
54 | primary: `0 8px 16px 0 ${alpha(palette.light.primary.main, 0.24)}`,
55 | info: `0 8px 16px 0 ${alpha(palette.light.info.main, 0.24)}`,
56 | secondary: `0 8px 16px 0 ${alpha(palette.light.secondary.main, 0.24)}`,
57 | success: `0 8px 16px 0 ${alpha(palette.light.success.main, 0.24)}`,
58 | warning: `0 8px 16px 0 ${alpha(palette.light.warning.main, 0.24)}`,
59 | error: `0 8px 16px 0 ${alpha(palette.light.error.main, 0.24)}`,
60 | //
61 | card: `0 0 2px 0 ${alpha(color, 0.2)}, 0 12px 24px -4px ${alpha(color, 0.12)}`,
62 | dialog: `-40px 40px 80px -8px ${alpha(palette.light.common.black, 0.24)}`,
63 | dropdown: `0 0 2px 0 ${alpha(color, 0.24)}, -20px 20px 40px -4px ${alpha(color, 0.24)}`,
64 | };
65 | };
66 |
67 | export const customShadows = {
68 | light: createCustomShadow(LIGHT_MODE),
69 | dark: createCustomShadow(DARK_MODE),
70 | };
71 |
72 | const shadows = {
73 | light: createShadow(LIGHT_MODE),
74 | dark: createShadow(DARK_MODE),
75 | };
76 |
77 | export default shadows;
78 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/SettingLayout.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | // @mui
3 | import { styled, alpha } from '@mui/material/styles';
4 | import { Grid, RadioGroup, CardActionArea, Box, Stack } from '@mui/material';
5 | // hooks
6 | import useSettings from '../../../hooks/useSettings';
7 | //
8 | import BoxMask from './BoxMask';
9 |
10 | // ----------------------------------------------------------------------
11 |
12 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({
13 | display: 'flex',
14 | flexDirection: 'column',
15 | padding: theme.spacing(1.5),
16 | color: theme.palette.text.disabled,
17 | border: `solid 1px ${theme.palette.grey[500_12]}`,
18 | borderRadius: Number(theme.shape.borderRadius) * 1.25,
19 | }));
20 |
21 | // ----------------------------------------------------------------------
22 |
23 | export default function SettingLayout() {
24 | const { themeLayout, onChangeLayout } = useSettings();
25 |
26 | return (
27 |
28 |
29 | {['horizontal', 'vertical'].map((layout) => {
30 | const isSelected = themeLayout === layout;
31 | const isVertical = layout === 'vertical';
32 |
33 | return (
34 |
35 | theme.customShadows.z20,
40 | }),
41 | }}
42 | >
43 | {isVertical ? : }
44 |
45 |
46 |
47 | );
48 | })}
49 |
50 |
51 | );
52 | }
53 |
54 | // ----------------------------------------------------------------------
55 |
56 | VerticalBox.propTypes = {
57 | isSelected: PropTypes.bool,
58 | };
59 |
60 | const style = {
61 | width: 1,
62 | height: 32,
63 | borderRadius: 0.5,
64 | };
65 |
66 | function VerticalBox({ isSelected }) {
67 | return (
68 | <>
69 | alpha(theme.palette.text.disabled, 0.72),
75 | ...(isSelected && {
76 | bgcolor: (theme) => alpha(theme.palette.primary.main, 0.72),
77 | }),
78 | }}
79 | />
80 | `dashed 1px ${theme.palette.divider}`,
84 | bgcolor: (theme) => alpha(theme.palette.text.disabled, 0.08),
85 | ...(isSelected && {
86 | border: (theme) => `dashed 1px ${theme.palette.primary.main}`,
87 | bgcolor: (theme) => alpha(theme.palette.primary.main, 0.16),
88 | }),
89 | }}
90 | />
91 | >
92 | );
93 | }
94 |
95 | HorizontalBox.propTypes = {
96 | isSelected: PropTypes.bool,
97 | };
98 |
99 | function HorizontalBox({ isSelected }) {
100 | return (
101 | <>
102 | alpha(theme.palette.text.disabled, 0.72),
108 | ...(isSelected && {
109 | bgcolor: (theme) => alpha(theme.palette.primary.main, 0.72),
110 | }),
111 | }}
112 | />
113 |
114 | alpha(theme.palette.text.disabled, 0.32),
119 | ...(isSelected && {
120 | bgcolor: (theme) => alpha(theme.palette.primary.main, 0.32),
121 | }),
122 | }}
123 | />
124 | `dashed 1px ${theme.palette.divider}`,
129 | bgcolor: (theme) => alpha(theme.palette.text.disabled, 0.08),
130 | ...(isSelected && {
131 | border: (theme) => `dashed 1px ${theme.palette.primary.main}`,
132 | bgcolor: (theme) => alpha(theme.palette.primary.main, 0.16),
133 | }),
134 | }}
135 | />
136 |
137 | >
138 | );
139 | }
140 |
--------------------------------------------------------------------------------
/src/data/index.js:
--------------------------------------------------------------------------------
1 | import { faker } from "@faker-js/faker";
2 | import {
3 | ChatCircleDots,
4 | Gear,
5 | GearSix,
6 | Phone,
7 | SignOut,
8 | User,
9 | Users,
10 | } from "phosphor-react";
11 |
12 | const Profile_Menu = [
13 | {
14 | title: "Profile",
15 | icon: ,
16 | },
17 | {
18 | title: "Settings",
19 | icon: ,
20 | },
21 | {
22 | title: "Profile",
23 | icon: ,
24 | },
25 | ];
26 |
27 | const Nav_Buttons = [
28 | {
29 | index: 0,
30 | icon: ,
31 | },
32 | {
33 | index: 1,
34 | icon: ,
35 | },
36 | {
37 | index: 2,
38 | icon: ,
39 | },
40 | ];
41 |
42 | const Nav_Setting = [
43 | {
44 | index: 3,
45 | icon: ,
46 | },
47 | ];
48 |
49 | const ChatList = [
50 | {
51 | id: 0,
52 | img: faker.image.avatar(),
53 | name: faker.name.firstName(),
54 | msg: faker.music.songName(),
55 | time: "9:36",
56 | unread: 0,
57 | pinned: true,
58 | online: true,
59 | },
60 | {
61 | id: 1,
62 | img: faker.image.avatar(),
63 | name: faker.name.firstName(),
64 | msg: faker.music.songName(),
65 | time: "12:02",
66 | unread: 2,
67 | pinned: true,
68 | online: false,
69 | },
70 | {
71 | id: 2,
72 | img: faker.image.avatar(),
73 | name: faker.name.firstName(),
74 | msg: faker.music.songName(),
75 | time: "10:35",
76 | unread: 3,
77 | pinned: false,
78 | online: true,
79 | },
80 | {
81 | id: 3,
82 | img: faker.image.avatar(),
83 | name: faker.name.firstName(),
84 | msg: faker.music.songName(),
85 | time: "04:00",
86 | unread: 0,
87 | pinned: false,
88 | online: true,
89 | },
90 | {
91 | id: 4,
92 | img: faker.image.avatar(),
93 | name: faker.name.firstName(),
94 | msg: faker.music.songName(),
95 | time: "08:42",
96 | unread: 0,
97 | pinned: false,
98 | online: false,
99 | },
100 | {
101 | id: 5,
102 | img: faker.image.avatar(),
103 | name: faker.name.firstName(),
104 | msg: faker.music.songName(),
105 | time: "08:42",
106 | unread: 0,
107 | pinned: false,
108 | online: false,
109 | },
110 | {
111 | id: 6,
112 | img: faker.image.avatar(),
113 | name: faker.name.firstName(),
114 | msg: faker.music.songName(),
115 | time: "08:42",
116 | unread: 0,
117 | pinned: false,
118 | online: false,
119 | },
120 | {
121 | id: 7,
122 | img: faker.image.avatar(),
123 | name: faker.name.firstName(),
124 | msg: faker.music.songName(),
125 | time: "08:42",
126 | unread: 0,
127 | pinned: false,
128 | online: false,
129 | },
130 | ];
131 |
132 | const Chat_History = [
133 | {
134 | type: "msg",
135 | message: "Hi 👋🏻, How are ya ?",
136 | incoming: true,
137 | outgoing: false,
138 | },
139 | {
140 | type: "divider",
141 | text: "Today",
142 | },
143 | {
144 | type: "msg",
145 | message: "Hi 👋 Panda, not bad, u ?",
146 | incoming: false,
147 | outgoing: true,
148 | },
149 | {
150 | type: "msg",
151 | message: "Can you send me an abstarct image?",
152 | incoming: false,
153 | outgoing: true,
154 | },
155 | {
156 | type: "msg",
157 | message: "Ya sure, sending you a pic",
158 | incoming: true,
159 | outgoing: false,
160 | },
161 |
162 | {
163 | type: "msg",
164 | subtype: "img",
165 | message: "Here You Go",
166 | img: faker.image.abstract(),
167 | incoming: true,
168 | outgoing: false,
169 | },
170 | {
171 | type: "msg",
172 | message: "Can you please send this in file format?",
173 | incoming: false,
174 | outgoing: true,
175 | },
176 |
177 | {
178 | type: "msg",
179 | subtype: "doc",
180 | message: "Yes sure, here you go.",
181 | incoming: true,
182 | outgoing: false,
183 | },
184 | {
185 | type: "msg",
186 | subtype: "link",
187 | preview: faker.image.cats(),
188 | message: "Yep, I can also do that",
189 | incoming: true,
190 | outgoing: false,
191 | },
192 | {
193 | type: "msg",
194 | subtype: "reply",
195 | reply: "This is a reply",
196 | message: "Yep, I can also do that",
197 | incoming: false,
198 | outgoing: true,
199 | },
200 | ];
201 |
202 | const Message_options = [
203 | {
204 | title: "Reply",
205 | },
206 | {
207 | title: "React to message",
208 | },
209 | {
210 | title: "Forward message",
211 | },
212 | {
213 | title: "Star message",
214 | },
215 | {
216 | title: "Report",
217 | },
218 | {
219 | title: "Delete Message",
220 | },
221 | ];
222 |
223 | export {
224 | Profile_Menu,
225 | Nav_Setting,
226 | Nav_Buttons,
227 | ChatList,
228 | Chat_History,
229 | Message_options,
230 | };
231 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/index.js:
--------------------------------------------------------------------------------
1 | import { AnimatePresence, m } from "framer-motion";
2 | import { useState, useEffect } from "react";
3 | // @mui
4 | import { alpha, styled } from "@mui/material/styles";
5 | import {
6 | Stack,
7 | Divider,
8 | Backdrop,
9 | Typography,
10 | IconButton,
11 | } from "@mui/material";
12 | // hooks
13 | import useSettings from "../../../hooks/useSettings";
14 | // utils
15 | import cssStyles from "../../../utils/cssStyles";
16 | // config
17 | import { NAVBAR, defaultSettings } from "../../../config";
18 | //
19 | import Iconify from "../../Iconify";
20 | import Scrollbar from "../../Scrollbar";
21 | //
22 | import ToggleButton from "./ToggleButton";
23 | import SettingDirection from "./SettingDirection";
24 | import SettingFullscreen from "./SettingFullscreen";
25 | import SettingColorPresets from "./SettingColorPresets";
26 |
27 | // ----------------------------------------------------------------------
28 |
29 | const RootStyle = styled(m.div)(({ theme }) => ({
30 | ...cssStyles(theme).bgBlur({
31 | color: theme.palette.background.paper,
32 | opacity: 0.92,
33 | }),
34 | top: 0,
35 | right: 0,
36 | bottom: 0,
37 | display: "flex",
38 | position: "fixed",
39 | overflow: "hidden",
40 | width: NAVBAR.BASE_WIDTH,
41 | flexDirection: "column",
42 | margin: theme.spacing(2),
43 | paddingBottom: theme.spacing(3),
44 | zIndex: theme.zIndex.drawer + 3,
45 | borderRadius: Number(theme.shape.borderRadius) * 1.5,
46 | boxShadow: `-24px 12px 32px -4px ${alpha(
47 | theme.palette.mode === "light"
48 | ? theme.palette.grey[500]
49 | : theme.palette.common.black,
50 | 0.16
51 | )}`,
52 | }));
53 |
54 | // ----------------------------------------------------------------------
55 |
56 | export default function SettingsDrawer() {
57 | const {
58 | themeMode,
59 | themeLayout,
60 | themeStretch,
61 | themeContrast,
62 | themeDirection,
63 | themeColorPresets,
64 | onResetSetting,
65 | } = useSettings();
66 |
67 | const [open, setOpen] = useState(false);
68 |
69 | const notDefault =
70 | themeMode !== defaultSettings.themeMode ||
71 | themeLayout !== defaultSettings.themeLayout ||
72 | themeStretch !== defaultSettings.themeStretch ||
73 | themeContrast !== defaultSettings.themeContrast ||
74 | themeDirection !== defaultSettings.themeDirection ||
75 | themeColorPresets !== defaultSettings.themeColorPresets;
76 |
77 | useEffect(() => {
78 | if (open) {
79 | document.body.style.overflow = "hidden";
80 | } else {
81 | document.body.style.overflow = "";
82 | }
83 | }, [open]);
84 |
85 | const handleToggle = () => {
86 | setOpen((prev) => !prev);
87 | };
88 |
89 | const handleClose = () => {
90 | setOpen(false);
91 | };
92 |
93 | return (
94 | <>
95 | theme.zIndex.drawer + 1,
101 | }}
102 | />
103 |
104 | {!open && (
105 |
110 | )}
111 |
112 |
113 | {open && (
114 | <>
115 |
116 |
122 |
123 | Settings
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | Direction
141 |
142 |
143 |
144 |
145 | Presets
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | >
154 | )}
155 |
156 | >
157 | );
158 | }
159 |
--------------------------------------------------------------------------------
/src/contexts/SettingsContext.js:
--------------------------------------------------------------------------------
1 | // provider === component
2 | import { createContext, useEffect } from "react";
3 | import { defaultSettings } from "../config";
4 | import useLocalStorage from "../hooks/useLocalStorage";
5 | import getColorPresets, {
6 | defaultPreset,
7 | colorPresets,
8 | } from "../utils/getColorPresets";
9 |
10 | const initialState = {
11 | ...defaultSettings,
12 |
13 | // Mode
14 | onToggleMode: () => {},
15 | onChangeMode: () => {},
16 |
17 | // Direction
18 | onToggleDirection: () => {},
19 | onChangeDirection: () => {},
20 | onChangeDirectionByLang: () => {},
21 |
22 | // Layout
23 | onToggleLayout: () => {},
24 | onChangeLayout: () => {},
25 |
26 | // Contrast
27 | onToggleContrast: () => {},
28 | onChangeContrast: () => {},
29 |
30 | // Color
31 | onChangeColor: () => {},
32 | setColor: defaultPreset,
33 | colorOption: [],
34 |
35 | // Stretch
36 | onToggleStretch: () => {},
37 |
38 | // Reset
39 | onResetSetting: () => {},
40 | };
41 |
42 | const SettingsContext = createContext(initialState);
43 |
44 | const SettingsProvider = ({ children }) => {
45 | const [settings, setSettings] = useLocalStorage("settings", {
46 | themeMode: initialState.themeMode,
47 | themeLayout: initialState.themeLayout,
48 | themeStretch: initialState.themeStretch,
49 | themeContrast: initialState.themeContrast,
50 | themeDirection: initialState.themeDirection,
51 | themeColorPresets: initialState.themeColorPresets,
52 | });
53 |
54 | const isArabic = localStorage.getItem("i18nextLng") === "ar";
55 |
56 | useEffect(() => {
57 | if (isArabic) {
58 | onChangeDirectionByLang("ar");
59 | }
60 | // eslint-disable-next-line react-hooks/exhaustive-deps
61 | }, [isArabic]);
62 |
63 | // Mode
64 |
65 | const onToggleMode = () => {
66 | setSettings({
67 | ...settings,
68 | themeMode: settings.themeMode === "light" ? "dark" : "light",
69 | });
70 | };
71 |
72 | const onChangeMode = (event) => {
73 | setSettings({
74 | ...settings,
75 | themeMode: event.target.value,
76 | });
77 | };
78 |
79 | // Direction
80 |
81 | const onToggleDirection = () => {
82 | setSettings({
83 | ...settings,
84 | themeDirection: settings.themeDirection === "rtl" ? "ltr" : "rtl",
85 | });
86 | };
87 |
88 | const onChangeDirection = (event) => {
89 | setSettings({
90 | ...settings,
91 | themeDirection: event.target.value,
92 | });
93 | };
94 |
95 | const onChangeDirectionByLang = (lang) => {
96 | setSettings({
97 | ...settings,
98 | themeDirection: lang === "ar" ? "rtl" : "ltr",
99 | });
100 | };
101 |
102 | // Layout
103 |
104 | const onToggleLayout = () => {
105 | setSettings({
106 | ...settings,
107 | themeLayout:
108 | settings.themeLayout === "vertical" ? "horizontal" : "vertical",
109 | });
110 | };
111 |
112 | const onChangeLayout = (event) => {
113 | setSettings({
114 | ...settings,
115 | themeLayout: event.target.value,
116 | });
117 | };
118 |
119 | // Contrast
120 |
121 | const onToggleContrast = () => {
122 | setSettings({
123 | ...settings,
124 | themeContrast: settings.themeContrast === "default" ? "bold" : "default",
125 | });
126 | };
127 |
128 | const onChangeContrast = (event) => {
129 | setSettings({
130 | ...settings,
131 | themeContrast: event.target.value,
132 | });
133 | };
134 |
135 | // Color
136 |
137 | const onChangeColor = (event) => {
138 | setSettings({
139 | ...settings,
140 | themeColorPresets: event.target.value,
141 | });
142 | };
143 |
144 | // Stretch
145 |
146 | const onToggleStretch = () => {
147 | setSettings({
148 | ...settings,
149 | themeStretch: !settings.themeStretch,
150 | });
151 | };
152 |
153 | // Reset
154 |
155 | const onResetSetting = () => {
156 | setSettings({
157 | themeMode: initialState.themeMode,
158 | themeLayout: initialState.themeLayout,
159 | themeStretch: initialState.themeStretch,
160 | themeContrast: initialState.themeContrast,
161 | themeDirection: initialState.themeDirection,
162 | themeColorPresets: initialState.themeColorPresets,
163 | });
164 | };
165 |
166 | return (
167 | ({
193 | name: color.name,
194 | value: color.main,
195 | })),
196 |
197 | // Reset
198 | onResetSetting,
199 | }}
200 | >
201 | {children}
202 |
203 | );
204 | };
205 |
206 | export {SettingsContext};
207 |
208 | export default SettingsProvider;
--------------------------------------------------------------------------------
/src/components/Chat/Footer.js:
--------------------------------------------------------------------------------
1 | import {
2 | Box,
3 | Fab,
4 | IconButton,
5 | InputAdornment,
6 | Stack,
7 | TextField,
8 | Tooltip,
9 | } from "@mui/material";
10 | import {
11 | Camera,
12 | File,
13 | Image,
14 | LinkSimple,
15 | PaperPlaneTilt,
16 | Smiley,
17 | Sticker,
18 | User,
19 | } from "phosphor-react";
20 | import { useTheme, styled } from "@mui/material/styles";
21 | import React from "react";
22 | import { useSearchParams } from "react-router-dom";
23 | import useResponsive from "../../hooks/useResponsive";
24 |
25 | import data from "@emoji-mart/data";
26 | import Picker from "@emoji-mart/react";
27 |
28 | const StyledInput = styled(TextField)(({ theme }) => ({
29 | "& .MuiInputBase-input": {
30 | paddingTop: "12px !important",
31 | paddingBottom: "12px !important",
32 | },
33 | }));
34 |
35 | const Actions = [
36 | {
37 | color: "#4da5fe",
38 | icon: ,
39 | y: 102,
40 | title: "Photo/Video",
41 | },
42 | {
43 | color: "#1b8cfe",
44 | icon: ,
45 | y: 172,
46 | title: "Stickers",
47 | },
48 | {
49 | color: "#0172e4",
50 | icon: ,
51 | y: 242,
52 | title: "Image",
53 | },
54 | {
55 | color: "#0159b2",
56 | icon: ,
57 | y: 312,
58 | title: "Document",
59 | },
60 | {
61 | color: "#013f7f",
62 | icon: ,
63 | y: 382,
64 | title: "Contact",
65 | },
66 | ];
67 |
68 | const ChatInput = ({ openPicker, setOpenPicker }) => {
69 | const [openActions, setOpenActions] = React.useState(false);
70 |
71 | return (
72 |
80 |
86 | {Actions.map((el) => (
87 |
88 | {
90 | setOpenActions(!openActions);
91 | }}
92 | sx={{
93 | position: "absolute",
94 | top: -el.y,
95 | backgroundColor: el.color,
96 | }}
97 | aria-label="add"
98 | >
99 | {el.icon}
100 |
101 |
102 | ))}
103 |
104 |
105 |
106 | {
108 | setOpenActions(!openActions);
109 | }}
110 | >
111 |
112 |
113 |
114 |
115 | ),
116 | endAdornment: (
117 |
118 |
119 | {
121 | setOpenPicker(!openPicker);
122 | }}
123 | >
124 |
125 |
126 |
127 |
128 | ),
129 | }}
130 | />
131 | );
132 | };
133 |
134 | const Footer = () => {
135 | const theme = useTheme();
136 |
137 | const isMobile = useResponsive("between", "md", "xs", "sm");
138 |
139 | const [searchParams] = useSearchParams();
140 |
141 | const [openPicker, setOpenPicker] = React.useState(false);
142 | return (
143 |
149 |
160 |
161 |
162 |
175 |
180 |
181 | {/* Chat Input */}
182 |
183 |
184 |
192 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 | );
206 | };
207 |
208 | export default Footer;
209 |
--------------------------------------------------------------------------------
/src/components/Chat/Header.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | Avatar,
4 | Badge,
5 | Box,
6 | Divider,
7 | Fade,
8 | IconButton,
9 | Menu,
10 | MenuItem,
11 | Stack,
12 | styled,
13 | Typography,
14 | } from "@mui/material";
15 | import { useTheme } from "@mui/material/styles";
16 | import { CaretDown, MagnifyingGlass, Phone, VideoCamera } from "phosphor-react";
17 | import { faker } from "@faker-js/faker";
18 | import { useSearchParams } from "react-router-dom";
19 | import useResponsive from "../../hooks/useResponsive";
20 |
21 | const StyledBadge = styled(Badge)(({ theme }) => ({
22 | "& .MuiBadge-badge": {
23 | backgroundColor: "#44b700",
24 | color: "#44b700",
25 | boxShadow: `0 0 0 2px ${theme.palette.background.paper}`,
26 | "&::after": {
27 | position: "absolute",
28 | top: 0,
29 | left: 0,
30 | width: "100%",
31 | height: "100%",
32 | borderRadius: "50%",
33 | animation: "ripple 1.2s infinite ease-in-out",
34 | border: "1px solid currentColor",
35 | content: '""',
36 | },
37 | },
38 | "@keyframes ripple": {
39 | "0%": {
40 | transform: "scale(.8)",
41 | opacity: 1,
42 | },
43 | "100%": {
44 | transform: "scale(2.4)",
45 | opacity: 0,
46 | },
47 | },
48 | }));
49 |
50 | const Conversation_Menu = [
51 | {
52 | title: "Contact info",
53 | },
54 | {
55 | title: "Mute notifications",
56 | },
57 | {
58 | title: "Clear messages",
59 | },
60 | {
61 | title: "Delete chat",
62 | },
63 | ];
64 |
65 | const ChatHeader = () => {
66 | const isMobile = useResponsive("between", "md", "xs", "sm");
67 | const [searchParams, setSearchParams] = useSearchParams();
68 | const theme = useTheme();
69 |
70 | const [conversationMenuAnchorEl, setConversationMenuAnchorEl] =
71 | React.useState(null);
72 | const openConversationMenu = Boolean(conversationMenuAnchorEl);
73 | const handleClickConversationMenu = (event) => {
74 | setConversationMenuAnchorEl(event.currentTarget);
75 | };
76 | const handleCloseConversationMenu = () => {
77 | setConversationMenuAnchorEl(null);
78 | };
79 |
80 | return (
81 |
90 |
96 | {
98 | searchParams.set("open", true);
99 | setSearchParams(searchParams);
100 | }}
101 | spacing={2}
102 | direction="row"
103 | >
104 |
105 |
113 |
114 |
115 |
116 |
117 | {faker.name.fullName()}
118 | Online
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | {!isMobile && (
129 |
130 |
131 |
132 | )}
133 |
134 |
135 |
144 |
145 |
146 |
182 |
183 |
184 |
185 | );
186 | };
187 |
188 | export default ChatHeader;
189 |
--------------------------------------------------------------------------------
/src/theme/overrides/CustomIcons.js:
--------------------------------------------------------------------------------
1 | import { SvgIcon } from '@mui/material';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | // CloseIcon
6 | export function CloseIcon(props) {
7 | return (
8 |
9 |
10 |
11 | );
12 | }
13 |
14 | // StarIcon
15 | export function StarIcon(props) {
16 | return (
17 |
18 |
19 |
20 | );
21 | }
22 |
23 | // Using for Alert
24 | export function InfoIcon(props) {
25 | return (
26 |
27 |
28 |
29 | );
30 | }
31 |
32 | export function WarningIcon(props) {
33 | return (
34 |
35 |
36 |
37 | );
38 | }
39 |
40 | export function SuccessIcon(props) {
41 | return (
42 |
43 |
44 |
45 | );
46 | }
47 |
48 | export function ErrorIcon(props) {
49 | return (
50 |
51 |
52 |
53 | );
54 | }
55 |
56 | // Using for Checkbox
57 | export function CheckboxIcon(props) {
58 | return (
59 |
60 |
61 |
62 | );
63 | }
64 |
65 | export function CheckboxCheckedIcon(props) {
66 | return (
67 |
68 |
69 |
70 | );
71 | }
72 |
73 | export function CheckboxIndeterminateIcon(props) {
74 | return (
75 |
76 |
77 |
78 | );
79 | }
80 |
81 | // Using for Select Input
82 | export function InputSelectIcon(props) {
83 | return (
84 |
93 |
94 |
95 | );
96 | }
97 |
98 | // Using for TreeView
99 | export function TreeViewCollapseIcon(props) {
100 | return (
101 |
102 |
103 |
104 | );
105 | }
106 |
107 | export function TreeViewExpandIcon(props) {
108 | return (
109 |
110 |
111 |
112 | );
113 | }
114 |
115 | export function TreeViewEndIcon(props) {
116 | return (
117 |
118 |
119 |
120 | );
121 | }
122 |
--------------------------------------------------------------------------------