react-garden
Version:
React + TypeScript + ThreeJS app using Material UI on NextJS, Apollo Client, GraphQL + WordPress REST APIs, for ThreeD web development.. a part of the threed.ai code family.
391 lines (360 loc) • 14.7 kB
JavaScript
// ** React Imports
import { useState } from 'react'
// ** Third Party Components
import PerfectScrollbar from 'react-perfect-scrollbar'
// ** MUI Imports
import Radio from '@mui/material/Radio'
import Switch from '@mui/material/Switch'
import Divider from '@mui/material/Divider'
import { styled } from '@mui/material/styles'
import IconButton from '@mui/material/IconButton'
import InputLabel from '@mui/material/InputLabel'
import RadioGroup from '@mui/material/RadioGroup'
import Typography from '@mui/material/Typography'
import Box from '@mui/material/Box'
import FormControlLabel from '@mui/material/FormControlLabel'
import MuiDrawer from '@mui/material/Drawer'
// ** Icons Imports
import Check from 'mdi-material-ui/Check'
import Close from 'mdi-material-ui/Close'
import CogOutline from 'mdi-material-ui/CogOutline'
// ** Hook Import
import { useSettings } from '~/@core/hooks/useSettings'
const Toggler = styled(Box)(({ theme }) => ({
right: 0,
top: '50%',
display: 'flex',
cursor: 'pointer',
position: 'fixed',
padding: theme.spacing(2),
zIndex: theme.zIndex.modal,
transform: 'translateY(-50%)',
backgroundColor: theme.palette.primary.main,
borderTopLeftRadius: theme.shape.borderRadius,
borderBottomLeftRadius: theme.shape.borderRadius
}))
const Drawer = styled(MuiDrawer)(({ theme }) => ({
width: 400,
zIndex: theme.zIndex.modal,
'& .MuiFormControlLabel-root': {
marginRight: '0.6875rem'
},
'& .MuiDrawer-paper': {
border: 0,
width: 400,
zIndex: theme.zIndex.modal,
boxShadow: theme.shadows[9]
}
}))
const CustomizerSpacing = styled('div')(({ theme }) => ({
padding: theme.spacing(5, 6)
}))
const ColorBox = styled(Box)(({ theme }) => ({
width: 40,
height: 40,
display: 'flex',
cursor: 'pointer',
alignItems: 'center',
justifyContent: 'center',
margin: theme.spacing(0, 1.5),
color: theme.palette.common.white,
transition: 'box-shadow .25s ease',
borderRadius: theme.shape.borderRadius
}))
const Customizer = () => {
// ** State
const [open, setOpen] = useState(false)
// ** Hook
const { settings, saveSettings } = useSettings()
// ** Vars
const {
mode,
skin,
appBar,
footer,
layout,
navHidden,
direction,
appBarBlur,
themeColor,
navCollapsed,
contentWidth,
verticalNavToggleType
} = settings
const handleChange = (field, value) => {
saveSettings({ ...settings, [field]: value })
}
return (
<div className='customizer'>
<Toggler className='customizer-toggler' onClick={() => setOpen(true)}>
<CogOutline sx={{ height: 20, width: 20, color: 'common.white' }} />
</Toggler>
<Drawer open={open} hideBackdrop anchor='right' variant='persistent'>
<Box
className='customizer-header'
sx={{
position: 'relative',
p: theme => theme.spacing(3.5, 5),
borderBottom: theme => `1px solid ${theme.palette.divider}`
}}
>
<Typography variant='h6' sx={{ fontWeight: 600, textTransform: 'uppercase' }}>
Theme Customizer
</Typography>
<Typography sx={{ color: 'text.secondary' }}>Customize & Preview in Real Time</Typography>
<IconButton
onClick={() => setOpen(false)}
sx={{
right: 20,
top: '50%',
position: 'absolute',
color: 'text.secondary',
transform: 'translateY(-50%)'
}}
>
<Close fontSize='small' />
</IconButton>
</Box>
<PerfectScrollbar options={{ wheelPropagation: false }}>
<CustomizerSpacing className='customizer-body'>
<Typography
component='p'
variant='caption'
sx={{ mb: 4, color: 'text.disabled', textTransform: 'uppercase' }}
>
Theming
</Typography>
<Box sx={{ mb: 4 }}>
<Typography>Skin</Typography>
<RadioGroup
row
value={skin}
onChange={e => handleChange('skin', e.target.value)}
sx={{ '& .MuiFormControlLabel-label': { fontSize: '.875rem', color: 'text.secondary' } }}
>
<FormControlLabel value='default' label='Default' control={<Radio />} />
<FormControlLabel value='bordered' label='Bordered' control={<Radio />} />
{layout === 'horizontal' ? null : (
<FormControlLabel value='semi-dark' label='Semi Dark' control={<Radio />} />
)}
</RadioGroup>
</Box>
<Box sx={{ mb: 4 }}>
<Typography>Mode</Typography>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<InputLabel
htmlFor='change-mode'
sx={{ cursor: 'pointer', fontSize: '0.875rem', color: 'text.secondary' }}
>
Light
</InputLabel>
<Switch
id='change-mode'
name='change-mode'
checked={mode === 'dark'}
onChange={e => handleChange('mode', e.target.checked ? 'dark' : 'light')}
/>
<InputLabel
htmlFor='change-mode'
sx={{ cursor: 'pointer', fontSize: '0.875rem', color: 'text.secondary' }}
>
Dark
</InputLabel>
</Box>
</Box>
<Box>
<Typography sx={{ mb: 2.5 }}>Primary Color</Typography>
<Box sx={{ display: 'flex' }}>
<ColorBox
onClick={() => handleChange('themeColor', 'primary')}
sx={{
ml: 0,
backgroundColor: '#4C9900', // '#9155FD',
...(themeColor === 'primary' ? { boxShadow: 9 } : { '&:hover': { boxShadow: 4 } })
}}
>
{themeColor === 'primary' ? <Check fontSize='small' /> : null}
</ColorBox>
<ColorBox
onClick={() => handleChange('themeColor', 'secondary')}
sx={{
backgroundColor: 'secondary.main',
...(themeColor === 'secondary' ? { boxShadow: 9 } : { '&:hover': { boxShadow: 4 } })
}}
>
{themeColor === 'secondary' ? <Check fontSize='small' /> : null}
</ColorBox>
<ColorBox
onClick={() => handleChange('themeColor', 'success')}
sx={{
backgroundColor: 'success.main',
...(themeColor === 'success' ? { boxShadow: 9 } : { '&:hover': { boxShadow: 4 } })
}}
>
{themeColor === 'success' ? <Check fontSize='small' /> : null}
</ColorBox>
<ColorBox
onClick={() => handleChange('themeColor', 'error')}
sx={{
backgroundColor: 'error.main',
...(themeColor === 'error' ? { boxShadow: 9 } : { '&:hover': { boxShadow: 4 } })
}}
>
{themeColor === 'error' ? <Check fontSize='small' /> : null}
</ColorBox>
<ColorBox
onClick={() => handleChange('themeColor', 'warning')}
sx={{
backgroundColor: 'warning.main',
...(themeColor === 'warning' ? { boxShadow: 9 } : { '&:hover': { boxShadow: 4 } })
}}
>
{themeColor === 'warning' ? <Check fontSize='small' /> : null}
</ColorBox>
<ColorBox
onClick={() => handleChange('themeColor', 'info')}
sx={{
mr: 0,
backgroundColor: 'info.main',
...(themeColor === 'info' ? { boxShadow: 9 } : { '&:hover': { boxShadow: 4 } })
}}
>
{themeColor === 'info' ? <Check fontSize='small' /> : null}
</ColorBox>
</Box>
</Box>
</CustomizerSpacing>
<Divider sx={{ m: 0 }} />
<CustomizerSpacing className='customizer-body'>
<Typography
component='p'
variant='caption'
sx={{ mb: 4, color: 'text.disabled', textTransform: 'uppercase' }}
>
Layout
</Typography>
<Box sx={{ mb: 4 }}>
<Typography>Content Width</Typography>
<RadioGroup
row
value={contentWidth}
onChange={e => handleChange('contentWidth', e.target.value)}
sx={{ '& .MuiFormControlLabel-label': { fontSize: '.875rem', color: 'text.secondary' } }}
>
<FormControlLabel value='full' label='Full' control={<Radio />} />
<FormControlLabel value='boxed' label='Boxed' control={<Radio />} />
</RadioGroup>
</Box>
<Box sx={{ mb: 4 }}>
<Typography>AppBar Type</Typography>
<RadioGroup
row
value={appBar}
onChange={e => handleChange('appBar', e.target.value)}
sx={{ '& .MuiFormControlLabel-label': { fontSize: '.875rem', color: 'text.secondary' } }}
>
<FormControlLabel value='fixed' label='Fixed' control={<Radio />} />
<FormControlLabel value='static' label='Static' control={<Radio />} />
{layout === 'horizontal' ? null : (
<FormControlLabel value='hidden' label='Hidden' control={<Radio />} />
)}
</RadioGroup>
</Box>
<Box sx={{ mb: 4 }}>
<Typography>Footer Type</Typography>
<RadioGroup
row
value={footer}
onChange={e => handleChange('footer', e.target.value)}
sx={{ '& .MuiFormControlLabel-label': { fontSize: '.875rem', color: 'text.secondary' } }}
>
<FormControlLabel value='fixed' label='Fixed' control={<Radio />} />
<FormControlLabel value='static' label='Static' control={<Radio />} />
<FormControlLabel value='hidden' label='Hidden' control={<Radio />} />
</RadioGroup>
</Box>
<Box sx={{ mb: 4, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Typography>AppBar Blur</Typography>
<Switch
name='appBarBlur'
checked={appBarBlur}
onChange={e => handleChange('appBarBlur', e.target.checked)}
/>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Typography>RTL</Typography>
<Switch
name='direction'
checked={direction === 'rtl'}
onChange={e => handleChange('direction', e.target.checked ? 'rtl' : 'ltr')}
/>
</Box>
</CustomizerSpacing>
<Divider sx={{ m: 0 }} />
<CustomizerSpacing className='customizer-body'>
<Typography
component='p'
variant='caption'
sx={{ mb: 4, color: 'text.disabled', textTransform: 'uppercase' }}
>
Menu
</Typography>
<Box sx={{ mb: layout === 'horizontal' && appBar === 'hidden' ? {} : 4 }}>
<Typography>Menu Layout</Typography>
<RadioGroup
row
value={layout}
onChange={e => {
saveSettings({
...settings,
layout: e.target.value,
lastLayout: e.target.value
})
}}
sx={{ '& .MuiFormControlLabel-label': { fontSize: '.875rem', color: 'text.secondary' } }}
>
<FormControlLabel value='vertical' label='Vertical' control={<Radio />} />
<FormControlLabel value='horizontal' label='Horizontal' control={<Radio />} />
</RadioGroup>
</Box>
{navHidden || layout === 'horizontal' ? null : (
<Box sx={{ mb: 4 }}>
<Typography>Menu Toggle</Typography>
<RadioGroup
row
value={verticalNavToggleType}
onChange={e => handleChange('verticalNavToggleType', e.target.value)}
sx={{ '& .MuiFormControlLabel-label': { fontSize: '.875rem', color: 'text.secondary' } }}
>
<FormControlLabel value='accordion' label='Accordion' control={<Radio />} />
<FormControlLabel value='collapse' label='Collapse' control={<Radio />} />
</RadioGroup>
</Box>
)}
{navHidden || layout === 'horizontal' ? null : (
<Box sx={{ mb: 4, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Typography>Menu Collapsed</Typography>
<Switch
name='navCollapsed'
checked={navCollapsed}
onChange={e => handleChange('navCollapsed', e.target.checked)}
/>
</Box>
)}
{layout === 'horizontal' && appBar === 'hidden' ? null : (
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Typography>Menu Hidden</Typography>
<Switch
name='navHidden'
checked={navHidden}
onChange={e => handleChange('navHidden', e.target.checked)}
/>
</Box>
)}
</CustomizerSpacing>
</PerfectScrollbar>
</Drawer>
</div>
)
}
export default Customizer