initial commit

This commit is contained in:
ferdiansyah783
2025-08-05 12:35:40 +07:00
commit fffa2ead5c
1069 changed files with 118056 additions and 0 deletions
@@ -0,0 +1,147 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
import Radio from '@mui/material/Radio'
import Checkbox from '@mui/material/Checkbox'
import Typography from '@mui/material/Typography'
import { styled } from '@mui/material/styles'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { CustomInputHorizontalProps } from './types'
const Root = styled('div', {
name: 'MuiCustomInputHorizontal',
slot: 'root'
})(({ theme }) => ({
blockSize: '100%',
display: 'flex',
gap: theme.spacing(1),
borderRadius: 'var(--mui-shape-borderRadius)',
cursor: 'pointer',
position: 'relative',
alignItems: 'flex-start',
border: '1px solid var(--mui-palette-customColors-inputBorder)',
padding: theme.spacing(4),
color: 'var(--mui-palette-text-primary)',
transition: theme.transitions.create(['border-color'], {
duration: theme.transitions.duration.shorter
}),
'&:hover': {
borderColor: 'var(--mui-palette-action-active)'
},
'&.active': {
borderColor: 'var(--mui-palette-primary-main)',
'& i, & svg': {
color: 'var(--mui-palette-primary-main) !important'
}
}
}))
const Title = styled(Typography, {
name: 'MuiCustomInputHorizontal',
slot: 'title'
})(({ theme }) => ({
fontWeight: theme.typography.fontWeightMedium,
color: 'var(--mui-palette-text-primary) !important'
}))
const Meta = styled(Typography, {
name: 'MuiCustomInputHorizontal',
slot: 'meta'
})(({ theme }) => ({
...theme.typography.body2,
color: 'var(--mui-palette-text-disabled) !important'
}))
const Content = styled(Typography, {
name: 'MuiCustomInputHorizontal',
slot: 'content'
})(({ theme }) => ({
...theme.typography.body2
}))
const RadioInput = styled(Radio, {
name: 'MuiCustomInputHorizontal',
slot: 'input'
})(({ theme }) => ({
marginBlockStart: theme.spacing(-0.25),
marginInlineStart: theme.spacing(-0.25)
}))
const CheckboxInput = styled(Checkbox, {
name: 'MuiCustomInputHorizontal',
slot: 'input'
})(({ theme }) => ({
marginBlockStart: theme.spacing(-0.25),
marginInlineStart: theme.spacing(-0.25)
}))
const CustomInputHorizontal = (props: CustomInputHorizontalProps) => {
// Props
const { type, data, name, selected, gridProps, handleChange, color = 'primary' } = props
// Vars
const { meta, title, value, content } = data
const renderData = () => {
if (meta && title && content) {
return (
<div className='flex flex-col bs-full is-full gap-1.5'>
<div className='flex items-start justify-between is-full mbs-1.5'>
{typeof title === 'string' ? <Title>{title}</Title> : title}
{typeof meta === 'string' ? <Meta>{meta}</Meta> : meta}
</div>
{typeof content === 'string' ? <Content>{content}</Content> : content}
</div>
)
} else if (meta && title && !content) {
return (
<div className='flex items-start justify-between is-full mbs-1.5'>
{typeof title === 'string' ? <Title>{title}</Title> : title}
{typeof meta === 'string' ? <Meta>{meta}</Meta> : meta}
</div>
)
} else if (!meta && title && content) {
return (
<div className='flex flex-col bs-full gap-1 mbs-1.5'>
{typeof title === 'string' ? <Title>{title}</Title> : title}
{typeof content === 'string' ? <Content>{content}</Content> : content}
</div>
)
} else if (!meta && !title && content) {
return typeof content === 'string' ? <Content className='mbs-1.5'>{content}</Content> : content
} else if (!meta && title && !content) {
return typeof title === 'string' ? <Title className='mbs-1.5'>{title}</Title> : title
} else {
return null
}
}
return data ? (
<Grid {...gridProps}>
<Root
onClick={() => handleChange(value)}
className={classnames({
active: type === 'radio' ? selected === value : selected.includes(value)
})}
>
{type === 'radio' ? (
<RadioInput name={name} color={color} value={value} onChange={handleChange} checked={selected === value} />
) : (
<CheckboxInput
color={color}
name={`${name}-${value}`}
checked={selected.includes(value)}
onChange={() => handleChange(value)}
/>
)}
{renderData()}
</Root>
</Grid>
) : null
}
export default CustomInputHorizontal
@@ -0,0 +1,82 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
import Checkbox from '@mui/material/Checkbox'
import { styled } from '@mui/material/styles'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { CustomInputImgProps } from './types'
const Root = styled('div', {
name: 'MuiCustomImage',
slot: 'Root'
})({
blockSize: '100%',
display: 'flex',
borderRadius: 'var(--mui-shape-borderRadius)',
cursor: 'pointer',
overflow: 'hidden',
position: 'relative',
alignItems: 'center',
flexDirection: 'column',
justifyContent: 'center',
border: '1px solid var(--mui-palette-divider)',
'&:hover': {
borderColor: 'var(--mui-palette-action-active)'
},
'&.active': {
borderColor: 'var(--mui-palette-primary-main)'
},
'&:not(.active):not(:hover) .MuiCheckbox-root': {
display: 'none'
}
})
const CheckboxInput = styled(Checkbox, {
name: 'MuiCustomImage',
slot: 'Input'
})({
top: 7,
right: 7,
position: 'absolute'
})
const Image = styled('img', {
name: 'MuiCustomImage',
slot: 'Image'
})({
maxWidth: '100%'
})
const CustomCheckboxImg = (props: CustomInputImgProps) => {
// Props
const { type, data, name, selected, gridProps, handleChange, color = 'primary' } = props
// Vars
const { alt, img, value } = data
const renderComponent = () => {
return (
<Grid {...gridProps}>
<Root className={classnames({ active: selected.includes(value) })} onClick={() => handleChange(value)}>
{typeof img === 'string' ? <Image src={img} alt={alt ?? `checkbox-image-${value}`} /> : img}
{type === 'radio' ? null : (
<CheckboxInput
color={color}
name={`${name}-${value}`}
checked={selected.includes(value)}
onChange={() => handleChange(value)}
/>
)}
</Root>
</Grid>
)
}
return data ? renderComponent() : null
}
export default CustomCheckboxImg
@@ -0,0 +1,119 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
import Radio from '@mui/material/Radio'
import Checkbox from '@mui/material/Checkbox'
import Typography from '@mui/material/Typography'
import { styled } from '@mui/material/styles'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { CustomInputVerticalProps } from './types'
const Root = styled('div', {
name: 'MuiCustomInputVertical',
slot: 'root'
})(({ theme }) => ({
display: 'flex',
blockSize: '100%',
cursor: 'pointer',
position: 'relative',
alignItems: 'center',
gap: theme.spacing(2),
flexDirection: 'column',
padding: theme.spacing(4),
borderRadius: 'var(--mui-shape-borderRadius)',
border: '1px solid var(--mui-palette-customColors-inputBorder)',
color: 'var(--mui-palette-text-primary)',
transition: theme.transitions.create(['border-color'], {
duration: theme.transitions.duration.shorter
}),
'&:hover': {
borderColor: 'var(--mui-palette-action-active)'
},
'&.active': {
borderColor: 'var(--mui-palette-primary-main)',
'& > svg, & > i': {
color: 'var(--mui-palette-primary-main) !important'
}
},
'&.radio-only .MuiRadio-root': {
marginTop: theme.spacing(-2)
},
'&.checkbox-only .MuiCheckbox-root': {
marginTop: theme.spacing(-2)
}
}))
const Title = styled(Typography, {
name: 'MuiCustomInputVertical',
slot: 'title'
})(({ theme }) => ({
fontWeight: theme.typography.fontWeightMedium,
color: 'var(--mui-palette-text-primary) !important'
}))
const Content = styled(Typography, {
name: 'MuiCustomInputVertical',
slot: 'content'
})(({ theme }) => ({
...theme.typography.body2,
textAlign: 'center'
}))
const RadioInput = styled(Radio, {
name: 'MuiCustomInputVertical',
slot: 'input'
})(({ theme }) => ({
marginBottom: theme.spacing(-2)
}))
const CheckboxInput = styled(Checkbox, {
name: 'MuiCustomInputVertical',
slot: 'input'
})(({ theme }) => ({
marginBottom: theme.spacing(-2)
}))
const CustomInputVertical = (props: CustomInputVerticalProps) => {
// Props
const { type, data, name, selected, gridProps, handleChange, color = 'primary' } = props
// Vars
const { title, value, content, asset } = data
const renderComponent = () => {
return (
<Grid {...gridProps}>
<Root
onClick={() => handleChange(value)}
className={classnames({
'radio-only': type === 'radio' && !asset && !title && !content,
'checkbox-only': type === 'checkbox' && !asset && !title && !content,
active: type === 'radio' ? selected === value : selected.includes(value)
})}
>
{asset || null}
{title ? typeof title === 'string' ? <Title>{title}</Title> : title : null}
{content ? typeof content === 'string' ? <Content>{content}</Content> : content : null}
{type === 'radio' ? (
<RadioInput name={name} color={color} value={value} onChange={handleChange} checked={selected === value} />
) : (
<CheckboxInput
color={color}
name={`${name}-${value}`}
checked={selected.includes(value)}
onChange={() => handleChange(value)}
/>
)}
</Root>
</Grid>
)
}
return data ? renderComponent() : null
}
export default CustomInputVertical
@@ -0,0 +1,96 @@
// React Imports
import type { ChangeEvent, ReactNode } from 'react'
// MUI Imports
import type { Grid2Props } from '@mui/material/Grid2'
// Type Imports
import type { ThemeColor } from '@core/types'
// Types of Horizontal Custom Inputs
export type CustomInputHorizontalData = {
value: string
content?: ReactNode
isSelected?: boolean
} & (
| {
meta: ReactNode
title: ReactNode
}
| {
meta?: never
title?: never
}
| {
title: ReactNode
meta?: never
}
)
export type CustomInputHorizontalProps = {
name: string
color?: ThemeColor
gridProps?: Grid2Props
data: CustomInputHorizontalData
} & (
| {
type: 'checkbox'
selected: string[]
handleChange: (value: string) => void
}
| {
type: 'radio'
selected: string
handleChange: (value: string | ChangeEvent<HTMLInputElement>) => void
}
)
// Types of Vertical Custom Inputs
export type CustomInputVerticalData = {
value: string
title?: ReactNode
content?: ReactNode
isSelected?: boolean
asset?: ReactNode
}
export type CustomInputVerticalProps = {
name: string
color?: ThemeColor
gridProps?: Grid2Props
data: CustomInputVerticalData
} & (
| {
type: 'checkbox'
selected: string[]
handleChange: (value: string) => void
}
| {
type: 'radio'
selected: string
handleChange: (value: string | ChangeEvent<HTMLInputElement>) => void
}
)
// Types of Custom Inputs with Images
export type CustomInputImgData = {
alt?: string
value: string
img: ReactNode
isSelected?: boolean
}
export type CustomInputImgProps = {
name: string
color?: ThemeColor
gridProps: Grid2Props
data: CustomInputImgData
} & (
| {
type: 'checkbox'
selected: string[]
handleChange: (value: string) => void
}
| {
type: 'radio'
selected: string
handleChange: (value: string | ChangeEvent<HTMLInputElement>) => void
}
)
+486
View File
@@ -0,0 +1,486 @@
'use client'
// React Imports
import { useRef, useState } from 'react'
// Next Imports
import { usePathname } from 'next/navigation'
import Link from 'next/link'
// MUI Imports
import Chip from '@mui/material/Chip'
import Fade from '@mui/material/Fade'
import Paper from '@mui/material/Paper'
import Popper from '@mui/material/Popper'
import { useTheme } from '@mui/material/styles'
import ClickAwayListener from '@mui/material/ClickAwayListener'
import Switch from '@mui/material/Switch'
import type { Breakpoint } from '@mui/material/styles'
// Third-party Imports
import classnames from 'classnames'
import { useDebounce, useMedia } from 'react-use'
import { HexColorPicker, HexColorInput } from 'react-colorful'
import PerfectScrollbar from 'react-perfect-scrollbar'
// Type Imports
import type { Settings } from '@core/contexts/settingsContext'
import type { Direction } from '@core/types'
import type { PrimaryColorConfig } from '@configs/primaryColorConfig'
// Icon Imports
import SkinDefault from '@core/svg/SkinDefault'
import SkinBordered from '@core/svg/SkinBordered'
import LayoutVertical from '@core/svg/LayoutVertical'
import LayoutCollapsed from '@core/svg/LayoutCollapsed'
import LayoutHorizontal from '@core/svg/LayoutHorizontal'
import ContentCompact from '@core/svg/ContentCompact'
import ContentWide from '@core/svg/ContentWide'
import DirectionLtr from '@core/svg/DirectionLtr'
import DirectionRtl from '@core/svg/DirectionRtl'
// Config Imports
import primaryColorConfig from '@configs/primaryColorConfig'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
// Style Imports
import styles from './styles.module.css'
type CustomizerProps = {
breakpoint?: Breakpoint | 'xxl' | `${number}px` | `${number}rem` | `${number}em`
dir?: Direction
disableDirection?: boolean
}
const getLocalePath = (pathName: string, locale: string) => {
if (!pathName) return '/'
const segments = pathName.split('/')
segments[1] = locale
return segments.join('/')
}
type DebouncedColorPickerProps = {
settings: Settings
isColorFromPrimaryConfig: PrimaryColorConfig | undefined
handleChange: (field: keyof Settings | 'primaryColor', value: Settings[keyof Settings] | string) => void
}
const DebouncedColorPicker = (props: DebouncedColorPickerProps) => {
// Props
const { settings, isColorFromPrimaryConfig, handleChange } = props
// States
const [debouncedColor, setDebouncedColor] = useState(settings.primaryColor ?? primaryColorConfig[0].main)
// Hooks
useDebounce(() => handleChange('primaryColor', debouncedColor), 200, [debouncedColor])
return (
<>
<HexColorPicker
color={!isColorFromPrimaryConfig ? (settings.primaryColor ?? primaryColorConfig[0].main) : '#eee'}
onChange={setDebouncedColor}
/>
<HexColorInput
className={styles.colorInput}
color={!isColorFromPrimaryConfig ? (settings.primaryColor ?? primaryColorConfig[0].main) : '#eee'}
onChange={setDebouncedColor}
prefixed
placeholder='Type a color'
/>
</>
)
}
const Customizer = ({ breakpoint = 'lg', dir = 'ltr', disableDirection = false }: CustomizerProps) => {
// States
const [isOpen, setIsOpen] = useState(false)
const [direction, setDirection] = useState(dir)
const [isMenuOpen, setIsMenuOpen] = useState(false)
// Refs
const anchorRef = useRef<HTMLDivElement | null>(null)
// Hooks
const theme = useTheme()
const pathName = usePathname()
const { settings, updateSettings, resetSettings, isSettingsChanged } = useSettings()
const isSystemDark = useMedia('(prefers-color-scheme: dark)', false)
// Vars
let breakpointValue: CustomizerProps['breakpoint']
switch (breakpoint) {
case 'xxl':
breakpointValue = '1920px'
break
case 'xl':
breakpointValue = `${theme.breakpoints.values.xl}px`
break
case 'lg':
breakpointValue = `${theme.breakpoints.values.lg}px`
break
case 'md':
breakpointValue = `${theme.breakpoints.values.md}px`
break
case 'sm':
breakpointValue = `${theme.breakpoints.values.sm}px`
break
case 'xs':
breakpointValue = `${theme.breakpoints.values.xs}px`
break
default:
breakpointValue = breakpoint
}
const breakpointReached = useMedia(`(max-width: ${breakpointValue})`, false)
const isMobileScreen = useMedia('(max-width: 600px)', false)
const isBelowLgScreen = useMedia('(max-width: 1200px)', false)
const isColorFromPrimaryConfig = primaryColorConfig.find(item => item.main === settings.primaryColor)
const ScrollWrapper = isBelowLgScreen ? 'div' : PerfectScrollbar
const handleToggle = () => {
setIsOpen(!isOpen)
}
// Update Settings
const handleChange = (field: keyof Settings | 'direction', value: Settings[keyof Settings] | Direction) => {
// Update direction state
if (field === 'direction') {
setDirection(value as Direction)
} else {
// Update settings in cookie
updateSettings({ [field]: value })
}
}
const handleMenuClose = (event: MouseEvent | TouchEvent): void => {
if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) {
return
}
setIsMenuOpen(false)
}
return (
!breakpointReached && (
<div
className={classnames('customizer', styles.customizer, {
[styles.show]: isOpen,
[styles.smallScreen]: isMobileScreen
})}
>
<div className={styles.toggler} onClick={handleToggle}>
<i className='tabler-settings text-[22px]' />
</div>
<div className={styles.header}>
<div className='flex flex-col'>
<h4 className={styles.customizerTitle}>Theme Customizer</h4>
<p className={styles.customizerSubtitle}>Customize & Preview in Real Time</p>
</div>
<div className='flex gap-4'>
<div onClick={resetSettings} className='relative flex cursor-pointer'>
<i className='tabler-refresh text-textPrimary' />
<div className={classnames(styles.dotStyles, { [styles.show]: isSettingsChanged })} />
</div>
<i className='tabler-x text-textPrimary cursor-pointer' onClick={handleToggle} />
</div>
</div>
<ScrollWrapper
{...(isBelowLgScreen
? { className: 'bs-full overflow-y-auto overflow-x-hidden' }
: { options: { wheelPropagation: false, suppressScrollX: true } })}
>
<div className={styles.customizerBody}>
<div className='flex flex-col gap-6'>
<Chip label='Theming' size='small' color='primary' variant='tonal' className='self-start rounded-sm' />
<div className='flex flex-col gap-2'>
<p className='font-medium'>Primary Color</p>
<div className='flex items-center justify-between'>
{primaryColorConfig.map(item => (
<div
key={item.main}
className={classnames(styles.primaryColorWrapper, {
[styles.active]: settings.primaryColor === item.main
})}
onClick={() => handleChange('primaryColor', item.main)}
>
<div className={styles.primaryColor} style={{ backgroundColor: item.main }} />
</div>
))}
<div
ref={anchorRef}
className={classnames(styles.primaryColorWrapper, {
[styles.active]: !isColorFromPrimaryConfig
})}
onClick={() => setIsMenuOpen(prev => !prev)}
>
<div
className={classnames(styles.primaryColor, 'flex items-center justify-center')}
style={{
backgroundColor: !isColorFromPrimaryConfig
? settings.primaryColor
: 'var(--mui-palette-action-selected)',
color: isColorFromPrimaryConfig
? 'var(--mui-palette-text-primary)'
: 'var(--mui-palette-primary-contrastText)'
}}
>
<i className='tabler-color-picker text-xl' />
</div>
</div>
<Popper
transition
open={isMenuOpen}
disablePortal
anchorEl={anchorRef.current}
placement='bottom-end'
className='z-[1]'
>
{({ TransitionProps }) => (
<Fade {...TransitionProps} style={{ transformOrigin: 'right top' }}>
<Paper elevation={6} className={styles.colorPopup}>
<ClickAwayListener onClickAway={handleMenuClose}>
<div>
<DebouncedColorPicker
settings={settings}
isColorFromPrimaryConfig={isColorFromPrimaryConfig}
handleChange={handleChange}
/>
</div>
</ClickAwayListener>
</Paper>
</Fade>
)}
</Popper>
</div>
</div>
<div className='flex flex-col gap-2'>
<p className='font-medium'>Mode</p>
<div className='flex items-center justify-between'>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, styles.modeWrapper, {
[styles.active]: settings.mode === 'light'
})}
onClick={() => handleChange('mode', 'light')}
>
<i className='tabler-sun text-[30px]' />
</div>
<p className={styles.itemLabel} onClick={() => handleChange('mode', 'light')}>
Light
</p>
</div>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, styles.modeWrapper, {
[styles.active]: settings.mode === 'dark'
})}
onClick={() => handleChange('mode', 'dark')}
>
<i className='tabler-moon-stars text-[30px]' />
</div>
<p className={styles.itemLabel} onClick={() => handleChange('mode', 'dark')}>
Dark
</p>
</div>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, styles.modeWrapper, {
[styles.active]: settings.mode === 'system'
})}
onClick={() => handleChange('mode', 'system')}
>
<i className='tabler-device-laptop text-[30px]' />
</div>
<p className={styles.itemLabel} onClick={() => handleChange('mode', 'system')}>
System
</p>
</div>
</div>
</div>
<div className='flex flex-col gap-2'>
<p className='font-medium'>Skin</p>
<div className='flex items-center gap-4'>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, { [styles.active]: settings.skin === 'default' })}
onClick={() => handleChange('skin', 'default')}
>
<SkinDefault />
</div>
<p className={styles.itemLabel} onClick={() => handleChange('skin', 'default')}>
Default
</p>
</div>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, { [styles.active]: settings.skin === 'bordered' })}
onClick={() => handleChange('skin', 'bordered')}
>
<SkinBordered />
</div>
<p className={styles.itemLabel} onClick={() => handleChange('skin', 'bordered')}>
Bordered
</p>
</div>
</div>
</div>
{settings.mode === 'dark' ||
(settings.mode === 'system' && isSystemDark) ||
settings.layout === 'horizontal' ? null : (
<div className='flex items-center justify-between'>
<label className='font-medium cursor-pointer' htmlFor='customizer-semi-dark'>
Semi Dark
</label>
<Switch
id='customizer-semi-dark'
checked={settings.semiDark === true}
onChange={() => handleChange('semiDark', !settings.semiDark)}
/>
</div>
)}
</div>
<hr className={styles.hr} />
<div className='flex flex-col gap-6'>
<Chip label='Layout' variant='tonal' size='small' color='primary' className='self-start rounded-sm' />
<div className='flex flex-col gap-2'>
<p className='font-medium'>Layouts</p>
<div className='flex items-center justify-between'>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, { [styles.active]: settings.layout === 'vertical' })}
onClick={() => handleChange('layout', 'vertical')}
>
<LayoutVertical />
</div>
<p className={styles.itemLabel} onClick={() => handleChange('layout', 'vertical')}>
Vertical
</p>
</div>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, { [styles.active]: settings.layout === 'collapsed' })}
onClick={() => handleChange('layout', 'collapsed')}
>
<LayoutCollapsed />
</div>
<p className={styles.itemLabel} onClick={() => handleChange('layout', 'collapsed')}>
Collapsed
</p>
</div>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, { [styles.active]: settings.layout === 'horizontal' })}
onClick={() => handleChange('layout', 'horizontal')}
>
<LayoutHorizontal />
</div>
<p className={styles.itemLabel} onClick={() => handleChange('layout', 'horizontal')}>
Horizontal
</p>
</div>
</div>
</div>
<div className='flex flex-col gap-2'>
<p className='font-medium'>Content</p>
<div className='flex items-center gap-4'>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, {
[styles.active]: settings.contentWidth === 'compact'
})}
onClick={() =>
updateSettings({
navbarContentWidth: 'compact',
contentWidth: 'compact',
footerContentWidth: 'compact'
})
}
>
<ContentCompact />
</div>
<p
className={styles.itemLabel}
onClick={() =>
updateSettings({
navbarContentWidth: 'compact',
contentWidth: 'compact',
footerContentWidth: 'compact'
})
}
>
Compact
</p>
</div>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, { [styles.active]: settings.contentWidth === 'wide' })}
onClick={() =>
updateSettings({ navbarContentWidth: 'wide', contentWidth: 'wide', footerContentWidth: 'wide' })
}
>
<ContentWide />
</div>
<p
className={styles.itemLabel}
onClick={() =>
updateSettings({ navbarContentWidth: 'wide', contentWidth: 'wide', footerContentWidth: 'wide' })
}
>
Wide
</p>
</div>
</div>
</div>
{!disableDirection && (
<div className='flex flex-col gap-2'>
<p className='font-medium'>Direction</p>
<div className='flex items-center gap-4'>
<Link href={getLocalePath(pathName, 'en')}>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, {
[styles.active]: direction === 'ltr'
})}
>
<DirectionLtr />
</div>
<p className={styles.itemLabel}>
Left to Right <br />
(English)
</p>
</div>
</Link>
<Link href={getLocalePath(pathName, 'ar')}>
<div className='flex flex-col items-start gap-0.5'>
<div
className={classnames(styles.itemWrapper, {
[styles.active]: direction === 'rtl'
})}
>
<DirectionRtl />
</div>
<p className={styles.itemLabel}>
Right to Left <br />
(Arabic)
</p>
</div>
</Link>
</div>
</div>
)}
</div>
</div>
</ScrollWrapper>
</div>
)
)
}
export default Customizer
@@ -0,0 +1,174 @@
.customizer {
block-size: 100%;
inline-size: 400px;
display: flex;
flex-direction: column;
background-color: var(--mui-palette-background-paper);
position: fixed;
inset-block-start: 0;
inset-inline-end: -400px;
box-shadow: none;
z-index: var(--customizer-z-index);
transition-property: inset-inline-end, box-shadow;
transition-duration: 300ms;
transition-timing-function: ease-in-out;
&.show {
inset-inline-end: 0 !important;
box-shadow: var(--mui-customShadows-xl);
}
&.smallScreen {
inline-size: 375px;
inset-inline-end: -375px;
&.show .toggler {
display: none;
}
.header,
.customizerBody {
padding-inline: 10px;
}
}
}
.toggler {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
position: absolute;
inset-block-start: 20%;
inset-inline-end: 100%;
transform: translateY(-20%);
padding: 8px;
background-color: var(--primary-color);
color: var(--mui-palette-primary-contrastText);
border-start-start-radius: var(--border-radius);
border-end-start-radius: var(--border-radius);
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding-block: 16px;
padding-inline: 24px;
border-block-end: 1px solid var(--border-color);
}
.customizerTitle {
font-size: 15px;
font-weight: 500;
}
.customizerSubtitle {
font-size: 13px;
line-height: 1.538462;
color: var(--mui-palette-text-secondary);
}
.dotStyles {
position: absolute;
inset-block-start: 0;
inset-inline-end: -5px;
block-size: 8px;
inline-size: 8px;
border-radius: 50%;
background-color: var(--mui-palette-error-main);
transform: scale(0);
transition-property: transform;
transition-duration: 300ms;
transition-timing-function: ease-in-out;
&.show {
transform: scale(1);
}
}
.customizerBody {
display: flex;
flex-direction: column;
padding: 24px;
gap: 32px;
}
.itemWrapper {
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
outline: 1px solid transparent;
min-inline-size: 106px;
min-block-size: 68px;
cursor: pointer;
&.active {
border-color: var(--primary-color);
outline: 1px solid var(--primary-color);
}
}
.itemLabel {
font-size: 13px;
line-height: 1.538462;
cursor: pointer;
color: var(--mui-palette-text-secondary);
}
.primaryColorWrapper {
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
outline: 1px solid transparent;
block-size: 50px;
inline-size: 50px;
padding: 8px;
cursor: pointer;
&.active {
border-color: var(--primary-color);
outline: 1px solid var(--primary-color);
}
}
.primaryColor {
block-size: 100%;
inline-size: 100%;
border-radius: var(--border-radius);
}
.modeWrapper {
min-block-size: 54px;
&.active {
color: var(--primary-color);
background-color: var(--mui-palette-primary-lighterOpacity);
}
}
.hr {
border: 0;
border-block-start: 1px solid var(--border-color);
}
.colorPopup {
padding: 16px;
margin-block-start: 1px;
& .colorInput {
inline-size: 100%;
margin-block-start: 16px;
border-radius: var(--mui-shape-borderRadius);
padding-block: 8px;
padding-inline: 10px;
border: 1px solid var(--mui-palette-divider);
font-size: 14px;
}
}
+34
View File
@@ -0,0 +1,34 @@
// React imports
import { forwardRef } from 'react'
import type { ElementType } from 'react'
// MUI imports
import Paper from '@mui/material/Paper'
import Autocomplete from '@mui/material/Autocomplete'
import type { AutocompleteProps } from '@mui/material/Autocomplete'
const CustomAutocomplete = forwardRef(
<
T,
Multiple extends boolean | undefined,
DisableClearable extends boolean | undefined,
FreeSolo extends boolean | undefined,
ChipComponent extends ElementType
>(
props: AutocompleteProps<T, Multiple, DisableClearable, FreeSolo, ChipComponent>,
ref: any
) => {
return (
// eslint-disable-next-line lines-around-comment
<Autocomplete
{...props}
ref={ref}
slots={{
paper: props => <Paper {...props} />
}}
/>
)
}
) as typeof Autocomplete
export default CustomAutocomplete
+51
View File
@@ -0,0 +1,51 @@
'use client'
// React Imports
import { forwardRef } from 'react'
// MUI Imports
import MuiAvatar from '@mui/material/Avatar'
import { lighten, styled } from '@mui/material/styles'
import type { AvatarProps } from '@mui/material/Avatar'
// Type Imports
import type { ThemeColor } from '@core/types'
export type CustomAvatarProps = AvatarProps & {
color?: ThemeColor
skin?: 'filled' | 'light' | 'light-static'
size?: number
}
const Avatar = styled(MuiAvatar)<CustomAvatarProps>(({ skin, color, size, theme }) => {
return {
...(color &&
skin === 'light' && {
backgroundColor: `var(--mui-palette-${color}-lightOpacity)`,
color: `var(--mui-palette-${color}-main)`
}),
...(color &&
skin === 'light-static' && {
backgroundColor: lighten(theme.palette[color as ThemeColor].main, 0.84),
color: `var(--mui-palette-${color}-main)`
}),
...(color &&
skin === 'filled' && {
backgroundColor: `var(--mui-palette-${color}-main)`,
color: `var(--mui-palette-${color}-contrastText)`
}),
...(size && {
height: size,
width: size
})
}
})
const CustomAvatar = forwardRef<HTMLDivElement, CustomAvatarProps>((props: CustomAvatarProps, ref) => {
// Props
const { color, skin = 'filled', ...rest } = props
return <Avatar color={color} skin={skin} ref={ref} {...rest} />
})
export default CustomAvatar
+25
View File
@@ -0,0 +1,25 @@
'use client'
// MUI Imports
import MuiBadge from '@mui/material/Badge'
import type { BadgeProps } from '@mui/material/Badge'
import { styled } from '@mui/material/styles'
export type CustomBadgeProps = BadgeProps & {
tonal?: 'true' | 'false'
}
const Badge = styled(MuiBadge)<CustomBadgeProps>(({ tonal, color }) => {
return {
...(tonal === 'true' && {
'& .MuiBadge-badge.MuiBadge-standard': {
color: `var(--mui-palette-${color}-main)`,
backgroundColor: `var(--mui-palette-${color}-lightOpacity)`
}
})
}
})
const CustomBadge = (props: CustomBadgeProps) => <Badge {...props} />
export default CustomBadge
+25
View File
@@ -0,0 +1,25 @@
'use client'
// React Imports
import React from 'react'
// Mui Imports
import MuiChip from '@mui/material/Chip'
import { styled } from '@mui/material'
import type { ChipProps } from '@mui/material/Chip'
export type CustomChipProps = ChipProps & {
round?: 'true' | 'false'
}
const Chip = styled(MuiChip)<CustomChipProps>(({ round }) => {
return {
...(round === 'true' && {
borderRadius: 500
})
}
})
const CustomChip = (props: CustomChipProps) => <Chip {...props} />
export default CustomChip
+79
View File
@@ -0,0 +1,79 @@
'use client'
import MuiButton from '@mui/material/Button'
import { styled } from '@mui/material/styles'
// Config Imports
import themeConfig from '@configs/themeConfig'
const CustomIconButton = styled(MuiButton)(({ color, size, theme, variant }) => {
return {
minInlineSize: 0,
transition: 'none',
...(size === 'small'
? {
fontSize: '20px',
padding: theme.spacing(variant === 'outlined' ? 1 : 1.25),
'& i, & svg': {
fontSize: 'inherit'
}
}
: {
...(size === 'large'
? {
fontSize: '24px',
padding: theme.spacing(variant === 'outlined' ? 2.75 : 3),
'& i, & svg': {
fontSize: 'inherit'
}
}
: {
fontSize: '22px',
padding: theme.spacing(variant === 'outlined' ? 1.75 : 2),
'& i, & svg': {
fontSize: 'inherit'
}
})
}),
...(!color && {
color: 'var(--mui-palette-action-active)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active': {
backgroundColor: 'rgb(var(--mui-palette-text-primaryChannel) / 0.08)'
},
...(themeConfig.disableRipple && {
'&.Mui-focusVisible:not(.Mui-disabled)': {
backgroundColor: 'rgb(var(--mui-palette-text-primaryChannel) / 0.08)'
}
}),
'&.Mui-disabled': {
opacity: 0.45,
color: 'var(--mui-palette-action-active)'
},
...(variant === 'outlined' && {
border: 'none !important',
...(size === 'small'
? {
padding: theme.spacing(1.25)
}
: {
...(size === 'large'
? {
padding: theme.spacing(3)
}
: {
padding: theme.spacing(2)
})
})
}),
...(variant === 'contained' && {
boxShadow: 'none !important',
backgroundColor: 'transparent'
}),
...(variant === 'tonal' && {
backgroundColor: 'transparent'
})
})
}
}) as typeof MuiButton
export default CustomIconButton
+69
View File
@@ -0,0 +1,69 @@
// MUI Imports
import MuiTabList from '@mui/lab/TabList'
import { styled } from '@mui/material/styles'
import type { TabListProps } from '@mui/lab/TabList'
// Type Imports
import type { ThemeColor } from '@core/types'
export type CustomTabListProps = TabListProps & {
color?: ThemeColor
pill?: 'true' | 'false'
}
const TabList = styled(MuiTabList)<CustomTabListProps>(({ color, theme, pill, orientation }) => ({
...(pill === 'true' && {
minHeight: 38,
...(orientation === 'vertical'
? {
borderInlineEnd: 0
}
: {
borderBlockEnd: 0
}),
'&, & .MuiTabs-scroller': {
...(orientation === 'vertical' && {
boxSizing: 'content-box'
}),
margin: `${theme.spacing(-1, -1, -1.5, -1)} !important`,
padding: theme.spacing(1, 1, 1.5, 1)
},
'& .MuiTabs-indicator': {
display: 'none'
},
'& .MuiTabs-flexContainer': {
gap: theme.spacing(1)
},
'& .Mui-selected': {
backgroundColor: `var(--mui-palette-${color}-main) !important`,
color: `var(--mui-palette-${color}-contrastText) !important`,
boxShadow: `var(--mui-customShadows-${color}-sm)`
},
'& .MuiTab-root': {
minHeight: 38,
padding: theme.spacing(2, 5),
borderRadius: 'var(--mui-shape-borderRadius)',
'&:hover': {
border: 0,
backgroundColor: `var(--mui-palette-${color}-lightOpacity)`,
color: `var(--mui-palette-${color}-main)`,
...(orientation === 'vertical'
? {
paddingInlineEnd: theme.spacing(5)
}
: {
paddingBlockEnd: theme.spacing(2)
})
}
}
})
}))
const CustomTabList = (props: CustomTabListProps) => {
// Props
const { color = 'primary', ...rest } = props
return <TabList color={color} {...rest} />
}
export default CustomTabList
+270
View File
@@ -0,0 +1,270 @@
'use client'
// React Imports
import { forwardRef } from 'react'
// MUI Imports
import { styled } from '@mui/material/styles'
import TextField from '@mui/material/TextField'
import type { TextFieldProps } from '@mui/material/TextField'
import type { InputLabelProps } from '@mui/material/InputLabel'
const TextFieldStyled = styled(TextField)<TextFieldProps>(({ theme }) => ({
'& .MuiInputLabel-root': {
transform: 'none',
width: 'fit-content',
maxWidth: '100%',
lineHeight: 1.153,
position: 'relative',
fontSize: theme.typography.body2.fontSize,
marginBottom: theme.spacing(1),
color: 'var(--mui-palette-text-primary)',
'&:not(.Mui-error).MuiFormLabel-colorPrimary.Mui-focused': {
color: 'var(--mui-palette-primary-main) !important'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-text-disabled)'
},
'&.Mui-error': {
color: 'var(--mui-palette-error-main)'
}
},
'& .MuiInputBase-root': {
backgroundColor: 'transparent !important',
border: `1px solid var(--mui-palette-customColors-inputBorder)`,
'&:not(.Mui-focused):not(.Mui-disabled):not(.Mui-error):hover': {
borderColor: 'var(--mui-palette-action-active)'
},
'&:before, &:after': {
display: 'none'
},
'&.MuiInputBase-sizeSmall': {
borderRadius: 'var(--mui-shape-borderRadius)'
},
'&.Mui-error': {
borderColor: 'var(--mui-palette-error-main)'
},
'&.Mui-focused': {
borderWidth: 2,
'& .MuiInputBase-input:not(.MuiInputBase-readOnly):not([readonly])::placeholder': {
transform: 'translateX(4px)'
},
'& :not(textarea).MuiFilledInput-input': {
padding: '6.25px 13px'
},
'&:not(.Mui-error).MuiInputBase-colorPrimary': {
borderColor: 'var(--mui-palette-primary-main)',
boxShadow: 'var(--mui-customShadows-primary-sm)'
},
'&.MuiInputBase-colorSecondary': {
borderColor: 'var(--mui-palette-secondary-main)'
},
'&.MuiInputBase-colorInfo': {
borderColor: 'var(--mui-palette-info-main)'
},
'&.MuiInputBase-colorSuccess': {
borderColor: 'var(--mui-palette-success-main)'
},
'&.MuiInputBase-colorWarning': {
borderColor: 'var(--mui-palette-warning-main)'
},
'&.MuiInputBase-colorError': {
borderColor: 'var(--mui-palette-error-main)'
},
'&.Mui-error': {
borderColor: 'var(--mui-palette-error-main)'
}
},
'&.Mui-disabled': {
backgroundColor: 'var(--mui-palette-action-hover) !important'
}
},
// Adornments
'& .MuiInputAdornment-root': {
marginBlockStart: '0px !important',
'&.MuiInputAdornment-positionStart + .MuiInputBase-input:not(textarea)': {
paddingInlineStart: '0px !important'
}
},
'& .MuiInputBase-inputAdornedEnd.MuiInputBase-input': {
paddingInlineEnd: '0px !important'
},
'& .MuiInputBase-sizeSmall.MuiInputBase-adornedStart.Mui-focused': {
paddingInlineStart: '13px',
'& .MuiInputBase-input': {
paddingInlineStart: '0px !important'
}
},
'& .MuiInputBase-sizeSmall.MuiInputBase-adornedStart:not(.MuiAutocomplete-inputRoot)': {
paddingInlineStart: '14px'
},
'& .MuiInputBase-sizeSmall.MuiInputBase-adornedEnd:not(.MuiAutocomplete-inputRoot)': {
paddingInlineEnd: '14px'
},
'& .MuiInputBase-sizeSmall.MuiInputBase-adornedEnd.Mui-focused:not(.MuiAutocomplete-inputRoot)': {
paddingInlineEnd: '13px',
'& .MuiInputBase-input': {
paddingInlineEnd: '0px !important'
}
},
'& :not(.MuiInputBase-sizeSmall).MuiInputBase-adornedStart.Mui-focused': {
paddingInlineStart: '15px',
'& .MuiInputBase-input': {
paddingInlineStart: '0px !important'
}
},
'& :not(.MuiInputBase-sizeSmall).MuiInputBase-adornedStart': {
paddingInlineStart: '16px'
},
'& :not(.MuiInputBase-sizeSmall).MuiInputBase-adornedEnd.Mui-focused': {
paddingInlineEnd: '15px',
'& .MuiInputBase-input': {
paddingInlineEnd: '0px !important'
}
},
'& :not(.MuiInputBase-sizeSmall).MuiInputBase-adornedEnd': {
paddingInlineEnd: '16px'
},
'& .MuiInputAdornment-sizeMedium': {
'i, svg': {
fontSize: '1.25rem'
}
},
'& .MuiInputBase-input': {
'&:not(textarea).MuiInputBase-inputSizeSmall': {
padding: '7.25px 14px'
},
'&:not(.MuiInputBase-readOnly):not([readonly])::placeholder': {
transition: theme.transitions.create(['opacity', 'transform'], {
duration: theme.transitions.duration.shorter
})
}
},
'& :not(.MuiInputBase-sizeSmall).MuiInputBase-root': {
borderRadius: '8px',
fontSize: '17px',
lineHeight: '1.41',
'& .MuiInputBase-input': {
padding: '10.8px 16px'
},
'&.Mui-focused': {
'& .MuiInputBase-input': {
padding: '9.8px 15px'
}
}
},
'& .MuiFormHelperText-root': {
lineHeight: 1.154,
margin: theme.spacing(1, 0, 0),
fontSize: theme.typography.body2.fontSize,
'&.Mui-error': {
color: 'var(--mui-palette-error-main)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-text-disabled)'
}
},
// For Select
'& .MuiSelect-select.MuiInputBase-inputSizeSmall, & .MuiNativeSelect-select.MuiInputBase-inputSizeSmall': {
'& ~ i, & ~ svg': {
inlineSize: '1.125rem',
blockSize: '1.125rem'
}
},
'& .MuiSelect-select': {
// lineHeight: 1.5,
minHeight: 'unset !important',
lineHeight: '1.4375em',
'&.MuiInputBase-input': {
paddingInlineEnd: '32px !important'
}
},
'& .Mui-focused .MuiSelect-select': {
'& ~ i, & ~ svg': {
right: '0.9375rem'
}
},
'& .MuiSelect-select:focus, & .MuiNativeSelect-select:focus': {
backgroundColor: 'transparent'
},
// For Autocomplete
'& :not(.MuiInputBase-sizeSmall).MuiAutocomplete-inputRoot': {
paddingBlock: '5.55px',
'& .MuiAutocomplete-input': {
paddingInline: '8px !important',
paddingBlock: '5.25px !important'
},
'&.Mui-focused .MuiAutocomplete-input': {
paddingInlineStart: '7px !important'
},
'&.Mui-focused': {
paddingBlock: '4.55px !important'
},
'& .MuiAutocomplete-endAdornment': {
top: 'calc(50% - 12px)'
}
},
'& .MuiAutocomplete-inputRoot.MuiInputBase-sizeSmall': {
paddingBlock: '4.75px !important',
paddingInlineStart: '10px',
'&.Mui-focused': {
paddingBlock: '3.75px !important',
paddingInlineStart: '9px',
'.MuiAutocomplete-input': {
paddingBlock: '2.5px',
paddingInline: '3px !important'
}
},
'& .MuiAutocomplete-input': {
paddingInline: '3px !important'
}
},
'& .MuiAutocomplete-inputRoot': {
display: 'flex',
gap: '0.25rem',
'& .MuiAutocomplete-tag': {
margin: 0
}
},
'& .MuiAutocomplete-inputRoot.Mui-focused .MuiAutocomplete-endAdornment': {
right: '.9375rem'
},
// For Textarea
'& .MuiInputBase-multiline': {
'&.MuiInputBase-sizeSmall': {
padding: '6px 14px',
'&.Mui-focused': {
padding: '5px 13px'
}
},
'& textarea.MuiInputBase-inputSizeSmall:placeholder-shown': {
overflowX: 'hidden'
}
}
}))
const CustomTextField = forwardRef((props: TextFieldProps, ref) => {
const { size = 'small', slotProps, ...rest } = props
return (
<TextFieldStyled
size={size}
inputRef={ref}
{...rest}
variant='filled'
slotProps={{
...slotProps,
inputLabel: { ...slotProps?.inputLabel, shrink: true } as InputLabelProps
}}
/>
)
})
export default CustomTextField
+141
View File
@@ -0,0 +1,141 @@
'use client'
// React Imports
import { useRef, useState } from 'react'
import type { ReactElement, ReactNode, SyntheticEvent } from 'react'
// Next Imports
import Link from 'next/link'
// MUI Imports
import Tooltip from '@mui/material/Tooltip'
import Box from '@mui/material/Box'
import Popper from '@mui/material/Popper'
import MenuItem from '@mui/material/MenuItem'
import MenuList from '@mui/material/MenuList'
import ClickAwayListener from '@mui/material/ClickAwayListener'
import Fade from '@mui/material/Fade'
import Paper from '@mui/material/Paper'
import IconButton from '@mui/material/IconButton'
import Divider from '@mui/material/Divider'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { OptionsMenuType, OptionType, OptionMenuItemType } from './types'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
const IconButtonWrapper = (props: Pick<OptionsMenuType, 'tooltipProps'> & { children: ReactElement }) => {
// Props
const { tooltipProps, children } = props
return tooltipProps?.title ? <Tooltip {...tooltipProps}>{children}</Tooltip> : children
}
const MenuItemWrapper = ({ children, option }: { children: ReactNode; option: OptionMenuItemType }) => {
if (option.href) {
return (
<Box component={Link} href={option.href} {...option.linkProps}>
{children}
</Box>
)
} else {
return <>{children}</>
}
}
const OptionMenu = (props: OptionsMenuType) => {
// Props
const { tooltipProps, icon, iconClassName, options, leftAlignMenu, iconButtonProps } = props
// States
const [open, setOpen] = useState(false)
// Refs
const anchorRef = useRef<HTMLButtonElement>(null)
// Hooks
const { settings } = useSettings()
const handleToggle = () => {
setOpen(prevOpen => !prevOpen)
}
const handleClose = (event: Event | SyntheticEvent) => {
if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) {
return
}
setOpen(false)
}
return (
<>
<IconButtonWrapper tooltipProps={tooltipProps}>
<IconButton ref={anchorRef} size='small' onClick={handleToggle} {...iconButtonProps}>
{typeof icon === 'string' ? (
<i className={classnames(icon, iconClassName)} />
) : (icon as ReactNode) ? (
icon
) : (
<i className={classnames('tabler-dots-vertical', iconClassName)} />
)}
</IconButton>
</IconButtonWrapper>
<Popper
open={open}
anchorEl={anchorRef.current}
placement={leftAlignMenu ? 'bottom-start' : 'bottom-end'}
transition
disablePortal
sx={{ zIndex: 1 }}
>
{({ TransitionProps }) => (
<Fade {...TransitionProps}>
<Paper className={settings.skin === 'bordered' ? 'border shadow-none' : 'shadow-lg'}>
<ClickAwayListener onClickAway={handleClose}>
<MenuList autoFocusItem={open}>
{options.map((option: OptionType, index: number) => {
if (typeof option === 'string') {
return (
<MenuItem key={index} onClick={handleClose}>
{option}
</MenuItem>
)
} else if ('divider' in option) {
return option.divider && <Divider key={index} {...option.dividerProps} />
} else {
return (
<MenuItem
key={index}
{...option.menuItemProps}
{...(option.href && { className: 'p-0' })}
onClick={e => {
handleClose(e)
option.menuItemProps && option.menuItemProps.onClick
? option.menuItemProps.onClick(e)
: null
}}
>
<MenuItemWrapper option={option}>
{(typeof option.icon === 'string' ? <i className={option.icon} /> : option.icon) || null}
{option.text}
</MenuItemWrapper>
</MenuItem>
)
}
})}
</MenuList>
</ClickAwayListener>
</Paper>
</Fade>
)}
</Popper>
</>
)
}
export default OptionMenu
+42
View File
@@ -0,0 +1,42 @@
// React Imports
import type { ReactNode } from 'react'
// Next Imports
import type { LinkProps } from 'next/link'
// MUI Imports
import type { IconButtonProps } from '@mui/material/IconButton'
import type { MenuItemProps } from '@mui/material/MenuItem'
import type { DividerProps } from '@mui/material/Divider'
import type { BoxProps } from '@mui/material/Box'
import type { TooltipProps } from '@mui/material/Tooltip'
export type OptionDividerType = {
divider: boolean
dividerProps?: DividerProps
href?: never
icon?: never
text?: never
linkProps?: never
menuItemProps?: never
}
export type OptionMenuItemType = {
text: ReactNode
icon?: ReactNode
linkProps?: BoxProps<'a'>
href?: LinkProps['href']
menuItemProps?: MenuItemProps
divider?: never
dividerProps?: never
}
export type OptionType = string | OptionDividerType | OptionMenuItemType
export type OptionsMenuType = {
tooltipProps?: Omit<TooltipProps, 'children'>
icon?: ReactNode
iconClassName?: string
options: OptionType[]
leftAlignMenu?: boolean
iconButtonProps?: IconButtonProps
}
@@ -0,0 +1,51 @@
'use client'
// React Imports
import type { ReactNode } from 'react'
// MUI Imports
import Zoom from '@mui/material/Zoom'
import { styled } from '@mui/material/styles'
import useScrollTrigger from '@mui/material/useScrollTrigger'
interface ScrollToTopProps {
className?: string
children: ReactNode
}
const ScrollToTopStyled = styled('div')(({ theme }) => ({
zIndex: 'var(--mui-zIndex-fab)',
position: 'fixed',
insetInlineEnd: theme.spacing(10),
insetBlockEnd: theme.spacing(14)
}))
const ScrollToTop = (props: ScrollToTopProps) => {
// Props
const { children, className } = props
// Hooks
// init trigger
const trigger = useScrollTrigger({
threshold: 400,
disableHysteresis: true
})
const handleClick = () => {
const anchor = document.querySelector('body')
if (anchor) {
anchor.scrollIntoView({ behavior: 'smooth' })
}
}
return (
<Zoom in={trigger}>
<ScrollToTopStyled className={className} onClick={handleClick} role='presentation'>
{children}
</ScrollToTopStyled>
</Zoom>
)
}
export default ScrollToTop
+137
View File
@@ -0,0 +1,137 @@
'use client'
// React Imports
import type { ReactNode } from 'react'
import { createContext, useMemo, useState } from 'react'
// Type Imports
import type { Mode, Skin, Layout, LayoutComponentWidth } from '@core/types'
// Config Imports
import themeConfig from '@configs/themeConfig'
import primaryColorConfig from '@configs/primaryColorConfig'
// Hook Imports
import { useObjectCookie } from '@core/hooks/useObjectCookie'
// Settings type
export type Settings = {
mode?: Mode
skin?: Skin
semiDark?: boolean
layout?: Layout
navbarContentWidth?: LayoutComponentWidth
contentWidth?: LayoutComponentWidth
footerContentWidth?: LayoutComponentWidth
primaryColor?: string
}
// UpdateSettingsOptions type
type UpdateSettingsOptions = {
updateCookie?: boolean
}
// SettingsContextProps type
type SettingsContextProps = {
settings: Settings
updateSettings: (settings: Partial<Settings>, options?: UpdateSettingsOptions) => void
isSettingsChanged: boolean
resetSettings: () => void
updatePageSettings: (settings: Partial<Settings>) => () => void
}
type Props = {
children: ReactNode
settingsCookie: Settings | null
mode?: Mode
}
// Initial Settings Context
export const SettingsContext = createContext<SettingsContextProps | null>(null)
// Settings Provider
export const SettingsProvider = (props: Props) => {
// Initial Settings
const initialSettings: Settings = {
mode: themeConfig.mode,
skin: themeConfig.skin,
semiDark: themeConfig.semiDark,
layout: themeConfig.layout,
navbarContentWidth: themeConfig.navbar.contentWidth,
contentWidth: themeConfig.contentWidth,
footerContentWidth: themeConfig.footer.contentWidth,
primaryColor: primaryColorConfig[0].main
}
const updatedInitialSettings = {
...initialSettings,
mode: props.mode || themeConfig.mode
}
// Cookies
const [settingsCookie, updateSettingsCookie] = useObjectCookie<Settings>(
themeConfig.settingsCookieName,
JSON.stringify(props.settingsCookie) !== '{}' ? props.settingsCookie : updatedInitialSettings
)
// State
const [_settingsState, _updateSettingsState] = useState<Settings>(
JSON.stringify(settingsCookie) !== '{}' ? settingsCookie : updatedInitialSettings
)
const updateSettings = (settings: Partial<Settings>, options?: UpdateSettingsOptions) => {
const { updateCookie = true } = options || {}
_updateSettingsState(prev => {
const newSettings = { ...prev, ...settings }
// Update cookie if needed
if (updateCookie) updateSettingsCookie(newSettings)
return newSettings
})
}
/**
* Updates the settings for page with the provided settings object.
* Updated settings won't be saved to cookie hence will be reverted once navigating away from the page.
*
* @param settings - The partial settings object containing the properties to update.
* @returns A function to reset the page settings.
*
* @example
* useEffect(() => {
* return updatePageSettings({ theme: 'dark' });
* }, []);
*/
const updatePageSettings = (settings: Partial<Settings>): (() => void) => {
updateSettings(settings, { updateCookie: false })
// Returns a function to reset the page settings
return () => updateSettings(settingsCookie, { updateCookie: false })
}
const resetSettings = () => {
updateSettings(initialSettings)
}
const isSettingsChanged = useMemo(
() => JSON.stringify(initialSettings) !== JSON.stringify(_settingsState),
// eslint-disable-next-line react-hooks/exhaustive-deps
[_settingsState]
)
return (
<SettingsContext.Provider
value={{
settings: _settingsState,
updateSettings,
isSettingsChanged,
resetSettings,
updatePageSettings
}}
>
{props.children}
</SettingsContext.Provider>
)
}
+37
View File
@@ -0,0 +1,37 @@
// React Imports
import { useMemo } from 'react'
// Third-party imports
import { useColorScheme } from '@mui/material'
// Type imports
import type { Mode } from '@core/types'
// Hook Imports
import { useSettings } from './useSettings'
export const useImageVariant = (
mode: Mode,
imgLight: string,
imgDark: string,
imgLightBordered?: string,
imgDarkBordered?: string
): string => {
// Hooks
const { settings } = useSettings()
const { mode: muiMode, systemMode: muiSystemMode } = useColorScheme()
return useMemo(() => {
const currentMode = muiMode === 'system' ? muiSystemMode : muiMode || mode
const isBordered = settings?.skin === 'bordered'
const isDarkMode = currentMode === 'dark'
if (isBordered && imgLightBordered && imgDarkBordered) {
return isDarkMode ? imgDarkBordered : imgLightBordered
}
return isDarkMode ? imgDark : imgLight
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mode, muiMode, muiSystemMode])
}
+38
View File
@@ -0,0 +1,38 @@
'use client'
// React Imports
import { useEffect } from 'react'
// Hook Imports
import { useCookie, useMedia } from 'react-use'
// Type Imports
import { useColorScheme } from '@mui/material'
import { useSettings } from '@core/hooks/useSettings'
const useLayoutInit = (colorSchemeFallback: 'light' | 'dark') => {
// Hooks
const { settings } = useSettings()
const { setMode } = useColorScheme()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, updateCookieColorPref] = useCookie('colorPref')
const isDark = useMedia('(prefers-color-scheme: dark)', colorSchemeFallback === 'dark')
useEffect(() => {
const appMode = isDark ? 'dark' : 'light'
updateCookieColorPref(appMode)
if (settings.mode === 'system') {
// We need to change the mode in settings context to apply the mode change to MUI components
setMode(appMode)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isDark])
// This hook does not return anything as it is only used to initialize color preference cookie and settings context on first load
}
export default useLayoutInit
+19
View File
@@ -0,0 +1,19 @@
// React Imports
import { useMemo } from 'react'
// Third-party Imports
import { useCookie } from 'react-use'
export const useObjectCookie = <T>(key: string, fallback?: T | null): [T, (newVal: T) => void] => {
// Hooks
const [valStr, updateCookie] = useCookie(key)
// eslint-disable-next-line react-hooks/exhaustive-deps
const value = useMemo<T>(() => (valStr ? JSON.parse(valStr) : fallback), [valStr])
const updateValue = (newVal: T) => {
updateCookie(JSON.stringify(newVal))
}
return [value, updateValue]
}
+16
View File
@@ -0,0 +1,16 @@
// React Imports
import { useContext } from 'react'
// Context Imports
import { SettingsContext } from '@core/contexts/settingsContext'
export const useSettings = () => {
// Hooks
const context = useContext(SettingsContext)
if (!context) {
throw new Error('useSettingsContext must be used within a SettingsProvider')
}
return context
}
@@ -0,0 +1,112 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { MenuItemStyles } from '@menu/types'
// Util Imports
import { menuClasses } from '@menu/utils/menuClasses'
const menuItemStyles = (theme: Theme, iconClass: string): MenuItemStyles => ({
root: ({ level }) => ({
...(level === 0 && {
borderRadius: 6
}),
[`&.${menuClasses.open} > .${menuClasses.button}`]: {
backgroundColor: 'var(--mui-palette-action-selected) !important'
},
...(level === 0
? {
[`& .${menuClasses.button}.${menuClasses.active}`]: {
color: 'var(--mui-palette-primary-contrastText) !important',
background:
theme.direction === 'ltr'
? `linear-gradient(270deg,
rgb(var(--mui-palette-primary-mainChannel) / 0.7) 0%,
var(--mui-palette-primary-main) 100%) !important`
: `linear-gradient(270deg,
var(--mui-palette-primary-main) 100%,
rgb(var(--mui-palette-primary-mainChannel) / 0.7) 100%) !important`
}
}
: {
[`&:not([aria-expanded]) > .${menuClasses.button}.${menuClasses.active}`]: {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)'
},
[`&[aria-expanded] > .${menuClasses.button}.${menuClasses.active}`]: {
backgroundColor: 'var(--mui-palette-action-selected) !important'
}
}),
[`&.${menuClasses.disabled} > .${menuClasses.button}`]: {
color: 'var(--mui-palette-text-disabled)',
'& *': {
color: 'inherit'
}
}
}),
button: {
borderRadius: 'var(--border-radius)',
paddingInline: theme.spacing(4),
'&:not(:has(.MuiChip-root))': {
paddingBlock: theme.spacing(2)
},
'&:has(.MuiChip-root)': {
paddingBlock: theme.spacing(1.75)
},
[`&:not(.${menuClasses.active}):hover, &:not(.${menuClasses.active}):focus-visible, &:not(.${menuClasses.active})[aria-expanded="true"]`]:
{
backgroundColor: 'var(--mui-palette-action-hover)'
}
},
icon: ({ level }) => ({
marginInlineEnd: theme.spacing(2),
...(level < 2 ? { fontSize: '1.375rem' } : { fontSize: '0.75rem', color: 'var(--mui-palette-text-secondary)' }),
'& > i, & > svg': {
fontSize: 'inherit'
},
[`& .${iconClass}`]: {
fontSize: '0.75rem',
color: 'var(--mui-palette-text-secondary)',
...(level === 1 && {
marginInline: theme.spacing(1.25)
}),
[`.${menuClasses.active} &`]: {
color: 'var(--mui-palette-primary-main)'
}
}
}),
prefix: {
marginInlineEnd: theme.spacing(2)
},
suffix: {
marginInlineStart: theme.spacing(2)
},
subMenuStyles: {
zIndex: 'calc(var(--header-z-index) + 1)'
},
subMenuExpandIcon: {
fontSize: '1.25rem',
marginInlineStart: theme.spacing(2),
'& i, & svg': {
fontSize: 'inherit'
}
},
subMenuContent: {
borderRadius: 'var(--border-radius)',
backgroundColor: 'var(--mui-palette-background-paper)',
boxShadow: 'var(--mui-customShadows-lg)',
'[data-skin="bordered"] &': {
boxShadow: 'none',
border: '1px solid var(--mui-palette-divider)'
},
'& > ul, & > div > ul': {
padding: theme.spacing(2),
'& > li:not(:last-child)': {
marginBlockEnd: theme.spacing(0.5)
}
}
}
})
export default menuItemStyles
@@ -0,0 +1,12 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const menuRootStyles = (theme: Theme) => {
return {
'& > ul > li:not(:last-of-type)': {
marginInlineEnd: theme.spacing(1.5)
}
}
}
export default menuRootStyles
+110
View File
@@ -0,0 +1,110 @@
// MUI imports
import Box from '@mui/material/Box'
import { styled } from '@mui/material/styles'
import type { BoxProps } from '@mui/material/Box'
const StepperWrapper = styled(Box)<BoxProps>(({ theme }) => {
return {
[theme.breakpoints.down('md')]: {
'& .MuiStepper-horizontal:not(.MuiStepper-alternativeLabel)': {
flexDirection: 'column',
alignItems: 'flex-start'
}
},
'& .MuiStep-root': {
'& .MuiStepLabel-iconContainer:empty': {
display: 'none'
},
'& .step-label': {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
'& .MuiAvatar-root': {
marginInlineEnd: theme.spacing(3)
}
},
'& .step-number': {
...theme.typography.h4,
marginRight: theme.spacing(2),
color: 'var(--mui-palette-text-primary) !important'
},
'&:not(:has(.step-subtitle)) .step-number': {
...theme.typography.h6
},
'& .step-title': {
...theme.typography.body1,
fontWeight: 500,
color: 'var(--mui-palette-text-primary)'
},
'& .step-subtitle': {
...theme.typography.body2
},
'& .MuiStepLabel-root.Mui-disabled': {
'& .step-number': {
color: 'var(--mui-palette-text-disabled)'
}
},
'& .Mui-error': {
'& .MuiStepLabel-labelContainer, & .step-number, & .step-title, & .step-subtitle': {
color: 'var(--mui-palette-error-main) !important'
}
}
},
'& .MuiStepConnector-root': {
'& .MuiStepConnector-line': {
borderBlockStartWidth: 3,
borderRadius: 3
},
'&.Mui-active, &.Mui-completed': {
'& .MuiStepConnector-line': {
borderColor: 'var(--mui-palette-primary-main)'
}
},
'&.Mui-disabled .MuiStepConnector-line': {
borderColor: 'var(--mui-palette-primary-lightOpacity)'
}
},
'& .MuiStepper-alternativeLabel': {
'& .MuiStepConnector-root': {
top: 10
},
'& .MuiStepLabel-labelContainer': {
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
'& > * + *': {
marginTop: theme.spacing(1)
}
}
},
'& .MuiStepper-vertical': {
'& .MuiStep-root': {
'& .step-label': {
justifyContent: 'flex-start'
},
'& .MuiStepContent-root': {
borderInlineStartWidth: 3,
marginLeft: theme.spacing(2.25),
borderColor: 'var(--mui-palette-primary-main)'
},
'& .button-wrapper': {
marginTop: theme.spacing(4)
},
'&.active + .MuiStepConnector-root .MuiStepConnector-line': {
borderColor: 'var(--mui-palette-primary-main)'
}
},
'& .MuiStepConnector-root': {
marginLeft: theme.spacing(2.25),
'& .MuiStepConnector-line': {
borderBlockStartWidth: 0,
borderInlineStartWidth: 3,
borderRadius: 0
}
}
}
}
}) as typeof Box
export default StepperWrapper
+96
View File
@@ -0,0 +1,96 @@
.table {
inline-size: 100%;
border-collapse: collapse;
font-size: 0.8125rem;
white-space: nowrap;
[align='right'] > * {
text-align: end;
}
[align='center'] > * {
text-align: center;
}
thead {
text-transform: uppercase;
color: var(--mui-palette-text-primary);
border-block-start: 1px solid var(--border-color);
th {
font-weight: 500;
font-size: 0.8125rem;
letter-spacing: 0.2px;
line-height: 1.8462;
text-align: start;
block-size: 56px;
&:not(:first-of-type):not(:last-of-type) {
padding-block: 0.5rem;
padding-inline: 1rem;
}
&:first-of-type {
&:not(:has(input[type='checkbox'])) {
padding-block: 0.5rem;
padding-inline: 1.5rem 1rem;
}
&:has(input[type='checkbox']) {
padding-inline-start: 0.9375rem;
}
}
&:last-of-type {
padding-block: 0.5rem;
padding-inline: 1rem 1.5rem;
}
}
}
tbody {
color: var(--mui-palette-text-secondary);
th,
td {
font-size: 0.9375rem;
line-height: 1.4667;
block-size: 50px;
&:not(:first-of-type):not(:last-of-type) {
padding-block: 0.5rem;
padding-inline: 1rem;
}
&:first-of-type {
&:not(:has(input[type='checkbox'])) {
padding-block: 0.5rem;
padding-inline: 1.5rem 1rem;
}
&:has(input[type='checkbox']) {
inline-size: 51px;
padding-inline-start: 0.9375rem;
}
}
&:last-of-type {
padding-block: 0.5rem;
padding-inline: 1rem 1.5rem;
}
}
tr:not(:last-child) {
border-block-end: 1px solid var(--border-color);
}
tr {
border-block-start: 1px solid var(--border-color);
}
}
}
.cellWithInput input {
inline-size: 100%;
background-color: transparent;
font-size: inherit;
color: inherit;
border-radius: var(--mui-shape-customBorderRadius-sm);
padding-block: 6px;
padding-inline: 10px;
margin-inline: -10px;
&:focus-visible {
outline: 1px solid var(--mui-palette-primary-main);
}
}
+167
View File
@@ -0,0 +1,167 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { MenuItemStyles } from '@menu/types'
import type { VerticalNavState } from '@menu/contexts/verticalNavContext'
// Util Imports
import { menuClasses } from '@menu/utils/menuClasses'
const menuItemStyles = (verticalNavOptions: VerticalNavState, theme: Theme): MenuItemStyles => {
// Vars
const { isCollapsed, isHovered, isPopoutWhenCollapsed, transitionDuration } = verticalNavOptions
const popoutCollapsed = isPopoutWhenCollapsed && isCollapsed
const popoutExpanded = isPopoutWhenCollapsed && !isCollapsed
const collapsedNotHovered = isCollapsed && !isHovered
return {
root: ({ level }) => ({
...(!isPopoutWhenCollapsed || popoutExpanded || (popoutCollapsed && level === 0)
? {
marginBlockStart: theme.spacing(1.5)
}
: {
marginBlockStart: 0
}),
[`&.${menuClasses.subMenuRoot}.${menuClasses.open} > .${menuClasses.button}, &.${menuClasses.subMenuRoot} > .${menuClasses.button}.${menuClasses.active}`]:
{
backgroundColor: 'var(--mui-palette-action-selected) !important'
},
[`&.${menuClasses.disabled} > .${menuClasses.button}`]: {
color: 'var(--mui-palette-text-disabled)',
'& *': {
color: 'inherit'
}
},
[`&:not(.${menuClasses.subMenuRoot}) > .${menuClasses.button}.${menuClasses.active}`]: {
...(popoutCollapsed && level > 0
? {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)',
[`& .${menuClasses.icon}`]: {
color: 'var(--mui-palette-primary-main)'
}
}
: {
color: 'var(--mui-palette-primary-contrastText)',
background:
theme.direction === 'ltr'
? `linear-gradient(270deg,
rgb(var(--mui-palette-primary-mainChannel) / 0.7) 0%,
var(--mui-palette-primary-main) 100%) !important`
: `linear-gradient(270deg,
var(--mui-palette-primary-main) 100%,
rgb(var(--mui-palette-primary-mainChannel) / 0.7) 100%) !important`,
boxShadow: 'var(--mui-customShadows-primary-sm)',
[`& .${menuClasses.icon}`]: {
color: 'inherit'
}
})
}
}),
button: ({ level, active }) => ({
paddingBlock: '8px',
paddingInline: '12px',
borderRadius: 'var(--border-radius)',
...(!(isCollapsed && !isHovered) && {
'&:has(.MuiChip-root)': {
paddingBlock: theme.spacing(1.75)
}
}),
...((!isPopoutWhenCollapsed || popoutExpanded || (popoutCollapsed && level === 0)) && {
borderRadius: 'var(--mui-shape-borderRadius)',
transition: `padding-inline-start ${transitionDuration}ms ease-in-out`
}),
...(!active && {
'&:hover, &:focus-visible': {
backgroundColor: 'var(--mui-palette-action-hover)'
},
'&[aria-expanded="true"]': {
backgroundColor: 'var(--mui-palette-action-selected)'
}
})
}),
icon: ({ level }) => ({
transition: `margin-inline-end ${transitionDuration}ms ease-in-out`,
...(level === 0 && {
fontSize: '1.375rem'
}),
...(level > 0 && {
fontSize: '0.75rem',
color: 'var(--mui-palette-text-secondary)'
}),
...(level === 0 && {
marginInlineEnd: theme.spacing(2)
}),
...(level > 0 && {
marginInlineEnd: theme.spacing(3.5)
}),
...(level === 1 &&
!popoutCollapsed && {
marginInlineStart: theme.spacing(1.5)
}),
...(level > 1 && {
marginInlineStart: theme.spacing((popoutCollapsed ? 0 : 1.5) + 2.5 * (level - 1))
}),
...(collapsedNotHovered && {
marginInlineEnd: 0
}),
...(popoutCollapsed &&
level > 0 && {
marginInlineEnd: theme.spacing(2)
}),
'& > i, & > svg': {
fontSize: 'inherit'
}
}),
prefix: {
marginInlineEnd: theme.spacing(2)
},
label: ({ level }) => ({
...((!isPopoutWhenCollapsed || popoutExpanded || (popoutCollapsed && level === 0)) && {
transition: `opacity ${transitionDuration}ms ease-in-out`,
...(collapsedNotHovered && {
opacity: 0
})
})
}),
suffix: {
marginInlineStart: theme.spacing(2)
},
subMenuExpandIcon: {
fontSize: '1.25rem',
marginInlineStart: theme.spacing(2),
'& i, & svg': {
fontSize: 'inherit'
}
},
subMenuContent: ({ level }) => ({
zIndex: 'calc(var(--drawer-z-index) + 1)',
borderRadius: 'var(--border-radius)',
backgroundColor: popoutCollapsed ? 'var(--mui-palette-background-paper)' : 'transparent',
...(popoutCollapsed && {
'& > ul, & > div > ul': {
[`& > li:not(:last-child), & > li > .${menuClasses.button}:not(:last-child)`]: {
marginBlockEnd: `${theme.spacing(0.5)} !important`
}
},
...(level === 0 && {
boxShadow: 'var(--mui-customShadows-sm)',
'[data-skin="bordered"] ~ [data-floating-ui-portal] &': {
boxShadow: 'none',
border: '1px solid var(--mui-palette-divider)'
},
[`& .${menuClasses.button}`]: {
paddingInline: theme.spacing(4)
},
padding: theme.spacing(2)
})
})
})
}
}
export default menuItemStyles
@@ -0,0 +1,53 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { VerticalNavState } from '@menu/contexts/verticalNavContext'
import type { MenuProps } from '@menu/vertical-menu'
// Util Imports
import { menuClasses } from '@menu/utils/menuClasses'
const menuSectionStyles = (verticalNavOptions: VerticalNavState, theme: Theme): MenuProps['menuSectionStyles'] => {
// Vars
const { isCollapsed, isHovered } = verticalNavOptions
const collapsedNotHovered = isCollapsed && !isHovered
return {
root: {
marginBlockStart: theme.spacing(0),
[`& .${menuClasses.menuSectionContent}`]: {
color: 'var(--mui-palette-text-disabled)',
paddingInline: '12px !important',
paddingBlock: `${theme.spacing(collapsedNotHovered ? 3.625 : 1.5)} !important`,
marginBlockStart: theme.spacing(3.5),
'&:before': {
content: '""',
blockSize: 1,
inlineSize: '1.375rem',
backgroundColor: 'var(--mui-palette-text-disabled)'
},
...(!collapsedNotHovered && {
'&:before': {
content: 'none'
}
}),
[`& .${menuClasses.menuSectionLabel}`]: {
flexGrow: 0,
textTransform: 'uppercase',
fontSize: '13px',
lineHeight: 1.38462,
letterSpacing: '0.4px',
...(collapsedNotHovered && {
display: 'none'
})
}
}
}
}
}
export default menuSectionStyles
@@ -0,0 +1,59 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { VerticalNavState } from '@menu/contexts/verticalNavContext'
// Util Imports
import { menuClasses, verticalNavClasses } from '@menu/utils/menuClasses'
const navigationCustomStyles = (verticalNavOptions: VerticalNavState, theme: Theme) => {
// Vars
const { collapsedWidth, isCollapsed, isHovered, transitionDuration } = verticalNavOptions
const collapsedHovered = isCollapsed && isHovered
const collapsedNotHovered = isCollapsed && !isHovered
return {
color: 'var(--mui-palette-text-primary)',
zIndex: 'var(--drawer-z-index) !important',
[`& .${verticalNavClasses.header}`]: {
paddingBlock: theme.spacing(5),
paddingInline: theme.spacing(5.5, 4),
...(collapsedNotHovered && {
paddingInline: theme.spacing(((collapsedWidth as number) - 35) / 8),
'& a': {
transform: `translateX(-${22 - ((collapsedWidth as number) - 29) / 2}px)`
}
}),
'& a': {
transition: `transform ${transitionDuration}ms ease`
}
},
[`& .${verticalNavClasses.container}`]: {
transition: theme.transitions.create(['inline-size', 'inset-inline-start', 'box-shadow'], {
duration: transitionDuration,
easing: 'ease-in-out'
}),
borderColor: 'transparent',
boxShadow: 'var(--mui-customShadows-sm)',
'[data-skin="bordered"] &': {
boxShadow: 'none',
...(collapsedHovered && {
boxShadow: 'var(--mui-customShadows-sm)'
}),
borderColor: 'var(--mui-palette-divider)'
}
},
[`& .${menuClasses.root}`]: {
paddingBlock: theme.spacing(1),
paddingInline: theme.spacing(3)
},
[`& .${verticalNavClasses.backdrop}`]: {
backgroundColor: 'var(--backdrop-color)'
}
}
}
export default navigationCustomStyles
+20
View File
@@ -0,0 +1,20 @@
// React Imports
import type { SVGAttributes } from 'react'
const ContentCompact = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<rect x='19.4209' y='4.67169' width='64.7547' height='8.8' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='22.3447' y='6.87164' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='65.5146' y='6.87164' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='71.4014' y='6.87164' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='77.2881' y='6.87164' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='44.3525' y='19.6135' width='40.2264' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='19.4209' y='19.6135' width='19.0455' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='19.4209' y='42.4545' width='65.1591' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
</svg>
)
}
export default ContentCompact
+20
View File
@@ -0,0 +1,20 @@
// React Imports
import type { SVGAttributes } from 'react'
const ContentWide = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<rect x='6.6875' y='4.67169' width='90.6244' height='8.8' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='10.165' y='6.87164' width='4.90566' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='75.2002' y='6.87164' width='4.90566' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='82.0674' y='6.87164' width='4.90566' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='88.9346' y='6.87164' width='4.90566' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='41.3652' y='19.6135' width='55.9476' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='6.6875' y='19.6135' width='26.4888' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='6.6875' y='42.4545' width='90.6244' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
</svg>
)
}
export default ContentWide
+96
View File
@@ -0,0 +1,96 @@
// React Imports
import type { SVGAttributes } from 'react'
const DirectionLtr = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<rect x='5.20215' y='4.12146' width='24.0976' height='57.5885' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect
x='10.3232'
y='16.8697'
width='13.8545'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='10.3232'
y='25.5618'
width='9.87943'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='10.3232'
y='34.2538'
width='12.3826'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='10.3232' y='42.946' width='6.08818' height='2.0921' rx='1.04605' fill='currentColor' fillOpacity='0.3' />
<rect
x='10.3232'
y='51.6384'
width='8.09094'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='35.5137' y='4.12134' width='62.3885' height='57.5885' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect
x='43.7578'
y='14.1833'
width='13.8545'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='43.7578'
y='22.8753'
width='32.8013'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='43.7578'
y='31.5674'
width='41.2076'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='43.7578'
y='40.2593'
width='32.8013'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='43.7578'
y='48.9517'
width='5.77482'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
</svg>
)
}
export default DirectionLtr
+96
View File
@@ -0,0 +1,96 @@
// React Imports
import type { SVGAttributes } from 'react'
const DirectionRtl = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<rect x='73.4756' y='4.12134' width='24.0976' height='57.5885' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect
x='78.5986'
y='16.8697'
width='13.8545'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='82.5713'
y='25.5618'
width='9.87943'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='80.0693'
y='34.2537'
width='12.3826'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='86.3633'
y='42.9459'
width='6.08818'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='84.3613'
y='51.6382'
width='8.09094'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='5.20215' y='4.12146' width='62.3885' height='57.5885' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='45.709' y='14.1833' width='13.8545' height='2.0921' rx='1.04605' fill='currentColor' fillOpacity='0.3' />
<rect
x='26.7617'
y='22.8754'
width='32.8013'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='18.3555'
y='31.5674'
width='41.2076'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='26.7617'
y='40.2594'
width='32.8013'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='53.7881'
y='48.9517'
width='5.77482'
height='2.0921'
rx='1.04605'
fill='currentColor'
fillOpacity='0.3'
/>
</svg>
)
}
export default DirectionRtl
+62
View File
@@ -0,0 +1,62 @@
// React Imports
import type { SVGAttributes } from 'react'
const LayoutCollapsed = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<path
d='M0 4C0 1.79086 1.79086 0 4 0H13.7359V66H4C1.79086 66 0 64.2091 0 62V4Z'
fill='currentColor'
fillOpacity='0.04'
/>
<rect
x='2.94336'
y='23.8839'
width='7.84906'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='3.43359' y='5.88135' width='6.86793' height='6.79412' rx='2' fill='currentColor' fillOpacity='0.3' />
<rect
x='2.94336'
y='34.4382'
width='7.84906'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='2.94336'
y='44.9923'
width='7.84906'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='2.94336'
y='55.5463'
width='7.84906'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='21.4717' y='4.67169' width='75.437' height='8.8' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='25.6172' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='78.248' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='84.1348' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='90.0215' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='50.4912' y='19.6134' width='46.8212' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='21.4717' y='19.6134' width='22.1679' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='21.4717' y='42.4545' width='75.8413' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
</svg>
)
}
export default LayoutCollapsed
+45
View File
@@ -0,0 +1,45 @@
// React Imports
import type { SVGAttributes } from 'react'
const LayoutHorizontal = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<rect x='44.0068' y='19.6136' width='46.8212' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='14.9854' y='19.6136' width='22.1679' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='14.9854' y='42.4547' width='75.8413' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='14.9248' y='4.68896' width='74.1506' height='9.00999' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='20.0264' y='6.50403' width='6.00327' height='5.38019' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='33.877' y='7.96356' width='6.6372' height='2.46129' rx='1.23064' fill='currentColor' fillOpacity='0.3' />
<rect
x='48.3652'
y='7.96356'
width='6.6372'
height='2.46129'
rx='1.23064'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='62.8506'
y='7.96356'
width='6.6372'
height='2.46129'
rx='1.23064'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='77.3379'
y='7.96356'
width='6.6372'
height='2.46129'
rx='1.23064'
fill='currentColor'
fillOpacity='0.3'
/>
</svg>
)
}
export default LayoutHorizontal
+62
View File
@@ -0,0 +1,62 @@
// React Imports
import type { SVGAttributes } from 'react'
const LayoutVertical = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<path
d='M0 4C0 1.79086 1.79086 0 4 0H27.4717V66H4C1.79086 66 0 64.2091 0 62V4Z'
fill='currentColor'
fillOpacity='0.08'
/>
<rect
x='4.90625'
y='23.8839'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='8.83008' y='5.88135' width='9.81132' height='9.70588' rx='2' fill='currentColor' fillOpacity='0.3' />
<rect
x='4.90625'
y='34.4382'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='4.90625'
y='44.9923'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='4.90625'
y='55.5463'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='32.1523' y='4.67169' width='64.7547' height='8.8' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='35.0781' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='78.248' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='84.1348' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='90.0215' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='57.0859' y='19.6134' width='40.2264' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='32.1523' y='19.6134' width='19.0455' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='32.1523' y='42.4545' width='65.1591' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
</svg>
)
}
export default LayoutVertical
+37
View File
@@ -0,0 +1,37 @@
// React Imports
import type { SVGAttributes } from 'react'
const Logo = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='1.4583em' height='1em' viewBox='0 0 35 24' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M0.00188479 0V7.47707C0.00188479 7.47707 -0.145285 9.83135 2.161 11.8242L14.9358 23.9961L21.5792 23.9107L20.5136 10.7809L17.9947 7.82497L10.0778 0H0.00188479Z'
fill='currentColor'
/>
<path
opacity='0.06'
fillRule='evenodd'
clipRule='evenodd'
d='M8.39807 17.9307L13.6581 3.53127L18.059 7.91564L8.39807 17.9307Z'
fill='#161616'
/>
<path
opacity='0.06'
fillRule='evenodd'
clipRule='evenodd'
d='M8.81183 17.3645L15.2093 5.06165L18.0926 7.94695L8.81183 17.3645Z'
fill='#161616'
/>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M8.47955 17.8436L25.8069 0H34.9091V7.50963C34.9091 7.50963 34.7195 10.0128 33.4463 11.3517L21.5808 24H14.9387L8.47955 17.8436Z'
fill='currentColor'
/>
</svg>
)
}
export default Logo
+57
View File
@@ -0,0 +1,57 @@
// React Imports
import type { SVGAttributes } from 'react'
const SkinDefault = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<rect
x='4.90625'
y='23.8839'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='8.83008' y='5.88135' width='9.81132' height='9.70588' rx='2' fill='currentColor' fillOpacity='0.3' />
<rect
x='4.90625'
y='34.4381'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='4.90625'
y='44.9923'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='4.90625'
y='55.5462'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='34.6152' y='5.17166' width='63.7547' height='7.8' rx='1.5' stroke='currentColor' strokeOpacity='0.12' />
<rect x='37.0391' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='80.21' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='86.0957' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='91.002' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='58.9844' y='20.1134' width='39.2264' height='16.6' rx='1.5' stroke='currentColor' strokeOpacity='0.12' />
<rect x='34.6152' y='20.1134' width='18.0455' height='16.6' rx='1.5' stroke='currentColor' strokeOpacity='0.12' />
<rect x='34.6152' y='42.9545' width='63.7547' height='16.6' rx='1.5' stroke='currentColor' strokeOpacity='0.12' />
</svg>
)
}
export default SkinDefault
+62
View File
@@ -0,0 +1,62 @@
// React Imports
import type { SVGAttributes } from 'react'
const SkinDefault = (props: SVGAttributes<SVGElement>) => {
return (
<svg width='104' height='66' viewBox='0 0 104 66' fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<rect width='104' height='66' rx='4' fill='currentColor' fillOpacity='0.02' />
<path
d='M0 4C0 1.79086 1.79086 0 4 0H27.4717V66H4C1.79086 66 0 64.2091 0 62V4Z'
fill='currentColor'
fillOpacity='0.08'
/>
<rect
x='4.90625'
y='23.8839'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='8.83008' y='5.88135' width='9.81132' height='9.70588' rx='2' fill='currentColor' fillOpacity='0.3' />
<rect
x='4.90625'
y='34.4381'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='4.90625'
y='44.9923'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect
x='4.90625'
y='55.5462'
width='17.6604'
height='2.78946'
rx='1.39473'
fill='currentColor'
fillOpacity='0.3'
/>
<rect x='34.1152' y='4.67166' width='64.7547' height='8.8' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='37.0391' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='80.21' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='86.0957' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='91.9824' y='6.87158' width='3.92453' height='4.4' rx='1' fill='currentColor' fillOpacity='0.3' />
<rect x='58.4844' y='19.6134' width='40.2264' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='34.1152' y='19.6134' width='19.0455' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
<rect x='34.1152' y='42.4545' width='64.7547' height='17.6' rx='2' fill='currentColor' fillOpacity='0.08' />
</svg>
)
}
export default SkinDefault
+91
View File
@@ -0,0 +1,91 @@
import plugin from 'tailwindcss/plugin'
export default plugin(function () {}, {
theme: {
borderColor: ({ theme }) => ({
...theme('colors'),
DEFAULT: 'var(--border-color, currentColor)'
}),
borderRadius: {
none: '0px',
xs: 'var(--mui-shape-customBorderRadius-xs)',
sm: 'var(--mui-shape-customBorderRadius-sm)',
DEFAULT: '0.375rem',
md: 'var(--mui-shape-customBorderRadius-md)',
lg: 'var(--mui-shape-customBorderRadius-lg)',
xl: 'var(--mui-shape-customBorderRadius-xl)',
'2xl': '0.75rem',
'3xl': '1rem',
'4xl': '1.5rem',
full: '9999px'
},
screens: {
sm: '600px',
md: '900px',
lg: '1200px',
xl: '1536px',
'2xl': '1920px'
},
extend: {
boxShadow: {
xs: 'var(--mui-customShadows-xs)',
sm: 'var(--mui-customShadows-sm)',
DEFAULT: 'var(--mui-customShadows-md)',
md: 'var(--mui-customShadows-md)',
lg: 'var(--mui-customShadows-lg)',
xl: 'var(--mui-customShadows-xl)',
primarySm: 'var(--mui-customShadows-primary-sm)',
primaryMd: 'var(--mui-customShadows-primary-md)',
primaryLg: 'var(--mui-customShadows-primary-lg)',
secondarySm: 'var(--mui-customShadows-secondary-sm)',
secondaryMd: 'var(--mui-customShadows-secondary-md)',
secondaryLg: 'var(--mui-customShadows-secondary-lg)',
errorSm: 'var(--mui-customShadows-error-sm)',
errorMd: 'var(--mui-customShadows-error-md)',
errorLg: 'var(--mui-customShadows-error-lg)',
warningSm: 'var(--mui-customShadows-warning-sm)',
warningMd: 'var(--mui-customShadows-warning-md)',
warningLg: 'var(--mui-customShadows-warning-lg)',
infoSm: 'var(--mui-customShadows-info-sm)',
infoMd: 'var(--mui-customShadows-info-md)',
infoLg: 'var(--mui-customShadows-info-lg)',
successSm: 'var(--mui-customShadows-success-sm)',
successMd: 'var(--mui-customShadows-success-md)',
successLg: 'var(--mui-customShadows-success-lg)'
},
colors: {
primary: 'var(--primary-color)',
primaryLight: 'var(--mui-palette-primary-lightOpacity)',
primaryLighter: 'var(--mui-palette-primary-lighterOpacity)',
secondary: 'var(--mui-palette-secondary-main)',
error: 'var(--mui-palette-error-main)',
errorLight: 'var(--mui-palette-error-lightOpacity)',
errorLighter: 'var(--mui-palette-error-lighterOpacity)',
warning: 'var(--mui-palette-warning-main)',
info: 'var(--mui-palette-info-main)',
success: 'var(--mui-palette-success-main)',
textPrimary: 'var(--mui-palette-text-primary)',
textSecondary: 'var(--mui-palette-text-secondary)',
textDisabled: 'var(--mui-palette-text-disabled)',
actionActive: 'var(--mui-palette-action-active)',
actionHover: 'var(--mui-palette-action-hover)',
actionSelected: 'var(--mui-palette-action-selected)',
actionFocus: 'var(--mui-palette-action-focus)',
backgroundPaper: 'var(--mui-palette-background-paper)',
backgroundDefault: 'var(--mui-palette-background-default)',
backgroundChat: 'var(--mui-palette-customColors-chatBg)',
backdrop: 'var(--backdrop-color)',
facebook: '#4267B2',
twitter: '#1DA1F2',
linkedin: '#007BB6'
},
zIndex: {
header: 'var(--header-z-index)',
footer: 'var(--footer-z-index)',
customizer: 'var(--customizer-z-index)',
search: 'var(--search-z-index)',
drawer: 'var(--drawer-z-index)'
}
}
}
})
+316
View File
@@ -0,0 +1,316 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { Skin } from '@core/types'
const colorSchemes = (skin: Skin): Theme['colorSchemes'] => {
return {
light: {
palette: {
primary: {
main: '#7367F0',
light: '#8F85F3',
dark: '#675DD8',
lighterOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.38)'
},
secondary: {
main: '#808390',
light: '#999CA6',
dark: '#737682',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.38)'
},
error: {
main: '#FF4C51',
light: '#FF7074',
dark: '#E64449',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.38)'
},
warning: {
main: '#FF9F43',
light: '#FFB269',
dark: '#E68F3C',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.38)'
},
info: {
main: '#00BAD1',
light: '#33C8DA',
dark: '#00A7BC',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.38)'
},
success: {
main: '#28C76F',
light: '#53D28C',
dark: '#24B364',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.38)'
},
text: {
primary: `rgb(var(--mui-mainColorChannels-light) / 0.9)`,
secondary: `rgb(var(--mui-mainColorChannels-light) / 0.7)`,
disabled: `rgb(var(--mui-mainColorChannels-light) / 0.4)`,
primaryChannel: 'var(--mui-mainColorChannels-light)',
secondaryChannel: 'var(--mui-mainColorChannels-light)'
},
divider: `rgb(var(--mui-mainColorChannels-light) / 0.12)`,
dividerChannel: 'var(--mui-mainColorChannels-light)',
background: {
default: skin === 'bordered' ? '#FFFFFF' : '#F8F7FA',
paper: '#FFFFFF',
paperChannel: '255 255 255'
},
action: {
active: `rgb(var(--mui-mainColorChannels-light) / 0.6)`,
hover: `rgb(var(--mui-mainColorChannels-light) / 0.06)`,
selected: `rgb(var(--mui-mainColorChannels-light) / 0.08)`,
disabled: `rgb(var(--mui-mainColorChannels-light) / 0.3)`,
disabledBackground: `rgb(var(--mui-mainColorChannels-light) / 0.16)`,
focus: `rgb(var(--mui-mainColorChannels-light) / 0.1)`,
focusOpacity: 0.1,
activeChannel: 'var(--mui-mainColorChannels-light)',
selectedChannel: 'var(--mui-mainColorChannels-light)'
},
Alert: {
errorColor: 'var(--mui-palette-error-main)',
warningColor: 'var(--mui-palette-warning-main)',
infoColor: 'var(--mui-palette-info-main)',
successColor: 'var(--mui-palette-success-main)',
errorStandardBg: 'var(--mui-palette-error-lightOpacity)',
warningStandardBg: 'var(--mui-palette-warning-lightOpacity)',
infoStandardBg: 'var(--mui-palette-info-lightOpacity)',
successStandardBg: 'var(--mui-palette-success-lightOpacity)',
errorFilledColor: 'var(--mui-palette-error-contrastText)',
warningFilledColor: 'var(--mui-palette-warning-contrastText)',
infoFilledColor: 'var(--mui-palette-info-contrastText)',
successFilledColor: 'var(--mui-palette-success-contrastText)',
errorFilledBg: 'var(--mui-palette-error-main)',
warningFilledBg: 'var(--mui-palette-warning-main)',
infoFilledBg: 'var(--mui-palette-info-main)',
successFilledBg: 'var(--mui-palette-success-main)'
},
Avatar: {
defaultBg: '#EEEDF0'
},
Chip: {
defaultBorder: 'var(--mui-palette-divider)'
},
FilledInput: {
bg: 'var(--mui-palette-action-hover)',
hoverBg: 'var(--mui-palette-action-selected)',
disabledBg: 'var(--mui-palette-action-hover)'
},
SnackbarContent: {
bg: '#2F2B3D',
color: 'var(--mui-palette-background-paper)'
},
Switch: {
defaultColor: 'var(--mui-palette-common-white)',
defaultDisabledColor: 'var(--mui-palette-common-white)',
primaryDisabledColor: 'var(--mui-palette-common-white)',
secondaryDisabledColor: 'var(--mui-palette-common-white)',
errorDisabledColor: 'var(--mui-palette-common-white)',
warningDisabledColor: 'var(--mui-palette-common-white)',
infoDisabledColor: 'var(--mui-palette-common-white)',
successDisabledColor: 'var(--mui-palette-common-white)'
},
Tooltip: {
bg: '#2F2B3D'
},
TableCell: {
border: 'var(--mui-palette-divider)'
},
customColors: {
bodyBg: '#F8F7FA',
chatBg: '#F3F2F5',
greyLightBg: '#FAFAFA',
inputBorder: `rgb(var(--mui-mainColorChannels-light) / 0.22)`,
tableHeaderBg: '#FFFFFF',
tooltipText: '#FFFFFF',
trackBg: '#F1F0F2'
}
}
},
dark: {
palette: {
primary: {
main: '#7367F0',
light: '#8F85F3',
dark: '#675DD8',
lighterOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-primary-mainChannel) / 0.38)'
},
secondary: {
main: '#808390',
light: '#999CA6',
dark: '#737682',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.38)'
},
error: {
main: '#FF4C51',
light: '#FF7074',
dark: '#E64449',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-error-mainChannel) / 0.38)'
},
warning: {
main: '#FF9F43',
light: '#FFB269',
dark: '#E68F3C',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-warning-mainChannel) / 0.38)'
},
info: {
main: '#00BAD1',
light: '#33C8DA',
dark: '#00A7BC',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-info-mainChannel) / 0.38)'
},
success: {
main: '#28C76F',
light: '#53D28C',
dark: '#24B364',
contrastText: '#FFF',
lighterOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.08)',
lightOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.16)',
mainOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.24)',
darkOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.32)',
darkerOpacity: 'rgb(var(--mui-palette-success-mainChannel) / 0.38)'
},
text: {
primary: `rgb(var(--mui-mainColorChannels-dark) / 0.9)`,
secondary: `rgb(var(--mui-mainColorChannels-dark) / 0.7)`,
disabled: `rgb(var(--mui-mainColorChannels-dark) / 0.4)`,
primaryChannel: 'var(--mui-mainColorChannels-dark)',
secondaryChannel: 'var(--mui-mainColorChannels-dark)'
},
divider: `rgb(var(--mui-mainColorChannels-dark) / 0.12)`,
dividerChannel: 'var(--mui-mainColorChannels-dark)',
background: {
default: skin === 'bordered' ? '#2F3349' : '#25293C',
paper: '#2F3349',
paperChannel: '47 51 73'
},
action: {
active: `rgb(var(--mui-mainColorChannels-dark) / 0.6)`,
hover: `rgb(var(--mui-mainColorChannels-dark) / 0.06)`,
selected: `rgb(var(--mui-mainColorChannels-dark) / 0.08)`,
disabled: `rgb(var(--mui-mainColorChannels-dark) / 0.3)`,
disabledBackground: `rgb(var(--mui-mainColorChannels-dark) / 0.16)`,
focus: `rgb(var(--mui-mainColorChannels-dark) / 0.1)`,
focusOpacity: 0.1,
activeChannel: 'var(--mui-mainColorChannels-dark)',
selectedChannel: 'var(--mui-mainColorChannels-dark)'
},
Alert: {
errorColor: 'var(--mui-palette-error-main)',
warningColor: 'var(--mui-palette-warning-main)',
infoColor: 'var(--mui-palette-info-main)',
successColor: 'var(--mui-palette-success-main)',
errorStandardBg: 'var(--mui-palette-error-lightOpacity)',
warningStandardBg: 'var(--mui-palette-warning-lightOpacity)',
infoStandardBg: 'var(--mui-palette-info-lightOpacity)',
successStandardBg: 'var(--mui-palette-success-lightOpacity)',
errorFilledColor: 'var(--mui-palette-error-contrastText)',
warningFilledColor: 'var(--mui-palette-warning-contrastText)',
infoFilledColor: 'var(--mui-palette-info-contrastText)',
successFilledColor: 'var(--mui-palette-success-contrastText)',
errorFilledBg: 'var(--mui-palette-error-main)',
warningFilledBg: 'var(--mui-palette-warning-main)',
infoFilledBg: 'var(--mui-palette-info-main)',
successFilledBg: 'var(--mui-palette-success-main)'
},
Avatar: {
defaultBg: '#373B50'
},
Chip: {
defaultBorder: 'var(--mui-palette-divider)'
},
FilledInput: {
bg: 'var(--mui-palette-action-hover)',
hoverBg: 'var(--mui-palette-action-selected)',
disabledBg: `var(--mui-palette-action-hover)`
},
SnackbarContent: {
bg: '#F7F4FF',
color: 'var(--mui-palette-background-paper)'
},
Switch: {
defaultColor: 'var(--mui-palette-common-white)',
defaultDisabledColor: 'var(--mui-palette-common-white)',
primaryDisabledColor: 'var(--mui-palette-common-white)',
secondaryDisabledColor: 'var(--mui-palette-common-white)',
errorDisabledColor: 'var(--mui-palette-common-white)',
warningDisabledColor: 'var(--mui-palette-common-white)',
infoDisabledColor: 'var(--mui-palette-common-white)',
successDisabledColor: 'var(--mui-palette-common-white)'
},
Tooltip: {
bg: '#F7F4FF'
},
TableCell: {
border: 'var(--mui-palette-divider)'
},
customColors: {
bodyBg: '#25293C',
chatBg: '#202534',
greyLightBg: '#353A52',
inputBorder: `rgb(var(--mui-mainColorChannels-dark) / 0.22)`,
tableHeaderBg: '#2F3349',
tooltipText: '#2F3349',
trackBg: '#3A3F57'
}
}
}
} as Theme['colorSchemes']
}
export default colorSchemes
+47
View File
@@ -0,0 +1,47 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { SystemMode } from '@core/types'
const customShadows = (mode: SystemMode): Theme['customShadows'] => {
return {
xs: `0px 1px 6px rgb(var(--mui-mainColorChannels-${mode}Shadow) / ${mode === 'light' ? 0.1 : 0.16})`,
sm: `0px 2px 8px rgb(var(--mui-mainColorChannels-${mode}Shadow) / ${mode === 'light' ? 0.12 : 0.18})`,
md: `0px 3px 12px rgb(var(--mui-mainColorChannels-${mode}Shadow) / ${mode === 'light' ? 0.14 : 0.2})`,
lg: `0px 4px 18px rgb(var(--mui-mainColorChannels-${mode}Shadow) / ${mode === 'light' ? 0.16 : 0.22})`,
xl: `0px 5px 30px rgb(var(--mui-mainColorChannels-${mode}Shadow) / ${mode === 'light' ? 0.18 : 0.24})`,
primary: {
sm: '0px 2px 6px rgb(var(--mui-palette-primary-mainChannel) / 0.3)',
md: '0px 4px 16px rgb(var(--mui-palette-primary-mainChannel) / 0.4)',
lg: '0px 6px 20px rgb(var(--mui-palette-primary-mainChannel) / 0.5)'
},
secondary: {
sm: '0px 2px 6px rgb(var(--mui-palette-secondary-mainChannel) / 0.3)',
md: '0px 4px 16px rgb(var(--mui-palette-secondary-mainChannel) / 0.4)',
lg: '0px 6px 20px rgb(var(--mui-palette-secondary-mainChannel) / 0.5)'
},
error: {
sm: '0px 2px 6px rgb(var(--mui-palette-error-mainChannel) / 0.3)',
md: '0px 4px 16px rgb(var(--mui-palette-error-mainChannel) / 0.4)',
lg: '0px 6px 20px rgb(var(--mui-palette-error-mainChannel) / 0.5)'
},
warning: {
sm: '0px 2px 6px rgb(var(--mui-palette-warning-mainChannel) / 0.3)',
md: '0px 4px 16px rgb(var(--mui-palette-warning-mainChannel) / 0.4)',
lg: '0px 6px 20px rgb(var(--mui-palette-warning-mainChannel) / 0.5)'
},
info: {
sm: '0px 2px 6px rgb(var(--mui-palette-info-mainChannel) / 0.3)',
md: '0px 4px 16px rgb(var(--mui-palette-info-mainChannel) / 0.4)',
lg: '0px 6px 20px rgb(var(--mui-palette-info-mainChannel) / 0.5)'
},
success: {
sm: '0px 2px 6px rgb(var(--mui-palette-success-mainChannel) / 0.3)',
md: '0px 4px 16px rgb(var(--mui-palette-success-mainChannel) / 0.4)',
lg: '0px 6px 20px rgb(var(--mui-palette-success-mainChannel) / 0.5)'
}
}
}
export default customShadows
+49
View File
@@ -0,0 +1,49 @@
// Next Imports
import { Public_Sans } from 'next/font/google'
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { Settings } from '@core/contexts/settingsContext'
import type { SystemMode, Skin } from '@core/types'
// Theme Options Imports
import overrides from './overrides'
import colorSchemes from './colorSchemes'
import spacing from './spacing'
import shadows from './shadows'
import customShadows from './customShadows'
import typography from './typography'
const public_sans = Public_Sans({ subsets: ['latin'], weight: ['300', '400', '500', '600', '700', '800', '900'] })
const theme = (settings: Settings, mode: SystemMode, direction: Theme['direction']): Theme => {
return {
direction,
components: overrides(settings.skin as Skin),
colorSchemes: colorSchemes(settings.skin as Skin),
...spacing,
shape: {
borderRadius: 6,
customBorderRadius: {
xs: 2,
sm: 4,
md: 6,
lg: 8,
xl: 10
}
},
shadows: shadows(mode),
typography: typography(public_sans.style.fontFamily),
customShadows: customShadows(mode),
mainColorChannels: {
light: '47 43 61',
dark: '225 222 245',
lightShadow: '47 43 61',
darkShadow: '19 17 32'
}
} as Theme
}
export default theme
+86
View File
@@ -0,0 +1,86 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { Skin } from '@core/types'
const accordion = (skin: Skin): Theme['components'] => ({
MuiAccordion: {
defaultProps: {
...(skin === 'bordered' && {
variant: 'outlined'
})
},
styleOverrides: {
root: ({ theme }) => ({
transition: theme.transitions.create(['margin', 'border-radius', 'box-shadow']),
'&:not(:last-child)': {
marginBlockEnd: theme.spacing(2)
},
borderRadius: 'var(--mui-shape-borderRadius)',
...(skin !== 'bordered' && {
boxShadow: 'var(--mui-customShadows-xs)'
}),
'&:before': {
content: 'none'
},
'&.Mui-expanded': {
...(skin !== 'bordered' && {
boxShadow: 'var(--mui-customShadows-md)'
}),
marginBlockStart: 0
}
})
}
},
MuiAccordionSummary: {
defaultProps: {
expandIcon: <i className='tabler-chevron-right' />
},
styleOverrides: {
root: ({ theme }) => ({
minHeight: 46,
padding: theme.spacing(3, 5),
paddingInlineStart: theme.spacing(6),
gap: theme.spacing(2),
color: 'var(--mui-palette-text-primary)',
'&.Mui-expanded': {
minHeight: 46,
'& .MuiAccordionSummary-expandIconWrapper': {
transform: 'rotate(90deg)'
}
},
'& .MuiAccordionSummary-expandIconWrapper': {
transform: theme.direction === 'rtl' && 'rotate(180deg)'
},
'& .MuiTypography-root': {
color: 'inherit',
fontWeight: theme.typography.fontWeightMedium
}
}),
content: {
margin: '0 !important'
},
expandIconWrapper: {
color: 'var(--mui-palette-text-primary)',
fontSize: '1.25rem',
'& i, & svg': {
fontSize: 'inherit'
}
}
}
},
MuiAccordionDetails: {
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(6),
paddingTop: theme.spacing(0),
'& .MuiTypography-root': {
color: 'var(--mui-palette-text-secondary)'
}
})
}
}
})
export default accordion
+180
View File
@@ -0,0 +1,180 @@
// React Imports
import React from 'react'
// MUI Imports
import type { Theme } from '@mui/material/styles'
const alerts: Theme['components'] = {
MuiAlert: {
defaultProps: {
iconMapping: {
error: <i className='tabler-alert-circle' />,
warning: <i className='tabler-alert-triangle' />,
info: <i className='tabler-info-circle' />,
success: <i className='tabler-circle-check' />
}
},
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(3, 4),
gap: theme.spacing(4),
...theme.typography.body1,
'&:not(:has(.MuiAlertTitle-root))': {
'& .MuiAlert-icon + .MuiAlert-message': {
alignSelf: 'center'
}
},
variants: [
{
props: { variant: 'standard', severity: 'error' },
style: {
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-error-main)',
color: 'var(--mui-palette-error-contrastText)'
}
}
},
{
props: { variant: 'standard', severity: 'warning' },
style: {
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-warning-main)',
color: 'var(--mui-palette-warning-contrastText)'
}
}
},
{
props: { variant: 'standard', severity: 'info' },
style: {
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-info-main)',
color: 'var(--mui-palette-info-contrastText)'
}
}
},
{
props: { variant: 'standard', severity: 'success' },
style: {
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-success-main)',
color: 'var(--mui-palette-success-contrastText)'
}
}
},
{
props: { variant: 'outlined', severity: 'error' },
style: {
borderColor: 'var(--mui-palette-error-main)',
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-error-lightOpacity)',
color: 'var(--mui-palette-error-main)'
}
}
},
{
props: { variant: 'outlined', severity: 'warning' },
style: {
borderColor: 'var(--mui-palette-warning-main)',
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-warning-lightOpacity)',
color: 'var(--mui-palette-warning-main)'
}
}
},
{
props: { variant: 'outlined', severity: 'info' },
style: {
borderColor: 'var(--mui-palette-info-main)',
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-info-lightOpacity)',
color: 'var(--mui-palette-info-main)'
}
}
},
{
props: { variant: 'outlined', severity: 'success' },
style: {
borderColor: 'var(--mui-palette-success-main)',
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-success-lightOpacity)',
color: 'var(--mui-palette-success-main)'
}
}
},
{
props: { variant: 'filled', severity: 'error' },
style: {
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-common-white)',
color: 'var(--mui-palette-error-main)',
boxShadow: 'var(--mui-customShadows-xs)'
}
}
},
{
props: { variant: 'filled', severity: 'warning' },
style: {
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-common-white)',
color: 'var(--mui-palette-warning-main)',
boxShadow: 'var(--mui-customShadows-xs)'
}
}
},
{
props: { variant: 'filled', severity: 'info' },
style: {
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-common-white)',
color: 'var(--mui-palette-info-main)',
boxShadow: 'var(--mui-customShadows-xs)'
}
}
},
{
props: { variant: 'filled', severity: 'success' },
style: {
'& .MuiAlert-icon': {
backgroundColor: 'var(--mui-palette-common-white)',
color: 'var(--mui-palette-success-main)',
boxShadow: 'var(--mui-customShadows-xs)'
}
}
}
]
}),
icon: {
padding: 0,
margin: 0,
minInlineSize: 30,
blockSize: 30,
borderRadius: 'var(--mui-shape-borderRadius)',
alignItems: 'center',
justifyContent: 'center',
'& i, & svg': {
fontSize: 'inherit'
}
},
message: {
padding: 0
},
action: {
padding: 0,
marginRight: 0
}
}
},
MuiAlertTitle: {
styleOverrides: {
root: ({ theme }) => ({
fontSize: theme.typography.h5.fontSize,
lineHeight: 1.33333,
marginTop: 0,
marginBottom: theme.spacing(1),
color: 'inherit'
})
}
}
}
export default alerts
@@ -0,0 +1,79 @@
// React Imports
import React from 'react'
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { Skin } from '@core/types'
const autocomplete = (skin: Skin): Theme['components'] => ({
MuiAutocomplete: {
defaultProps: {
...(skin === 'bordered' && {
slotProps: {
paper: {
variant: 'outlined'
}
}
}),
ChipProps: {
size: 'small'
},
popupIcon: <i className='tabler-chevron-down' />
},
styleOverrides: {
root: {
'& .MuiButtonBase-root.Mui-disabled i, & .MuiButtonBase-root.Mui-disabled svg': {
color: 'var(--mui-palette-action-disabled)'
},
'& .MuiOutlinedInput-input': {
height: '1.4375em'
}
},
input: {
'& + .MuiAutocomplete-endAdornment': {
right: '1rem',
'& i, & svg': {
fontSize: '1.25rem',
color: 'var(--mui-palette-text-primary)'
},
'& .MuiAutocomplete-clearIndicator': {
padding: 2
}
},
'&.MuiInputBase-inputSizeSmall + .MuiAutocomplete-endAdornment': {
'& i, & svg': {
fontSize: '1rem'
}
}
},
paper: {
...(skin !== 'bordered' && {
boxShadow: 'var(--mui-customShadows-lg)',
marginBlockStart: '0.125rem'
})
},
listbox: ({ theme }) => ({
'& .MuiAutocomplete-option': {
paddingBlock: theme.spacing(2),
marginInline: theme.spacing(2),
marginBlock: theme.spacing(0.5),
borderRadius: 'var(--mui-shape-borderRadius)',
'&[aria-selected="true"]': {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)',
'&.Mui-focused, &.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-primary-mainOpacity)'
}
}
},
'& .MuiAutocomplete-option.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-action-hover)'
}
})
}
}
})
export default autocomplete
+38
View File
@@ -0,0 +1,38 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const avatar: Theme['components'] = {
MuiAvatarGroup: {
styleOverrides: {
root: ({ theme }) => ({
justifyContent: 'flex-end',
'& .MuiAvatar-root': {
borderColor: 'var(--mui-palette-background-paper)'
},
'&.pull-up .MuiAvatar-root': {
cursor: 'pointer',
transition: theme.transitions.create(['box-shadow', 'transform'], {
easing: 'ease',
duration: theme.transitions.duration.shorter
}),
'&:hover': {
zIndex: 2,
boxShadow: 'var(--mui-customShadows-md)',
transform: 'translateY(-5px)'
}
}
})
}
},
MuiAvatar: {
styleOverrides: {
root: ({ theme }) => ({
color: 'var(--mui-palette-text-primary)',
fontSize: theme.typography.body1.fontSize,
lineHeight: 1.2
})
}
}
}
export default avatar
+16
View File
@@ -0,0 +1,16 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const backdrop: Theme['components'] = {
MuiBackdrop: {
styleOverrides: {
root: {
'&:not(.MuiBackdrop-invisible)': {
backgroundColor: 'var(--backdrop-color)'
}
}
}
}
}
export default backdrop
+19
View File
@@ -0,0 +1,19 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const badges: Theme['components'] = {
MuiBadge: {
styleOverrides: {
standard: ({ theme }) => ({
height: 24,
minWidth: 24,
borderRadius: 20,
fontSize: theme.typography.subtitle2.fontSize,
lineHeight: 1.23077,
padding: theme.spacing(1, 2)
})
}
}
}
export default badges
+26
View File
@@ -0,0 +1,26 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const breadcrumbs: Theme['components'] = {
MuiBreadcrumbs: {
styleOverrides: {
root: {
'& svg, & i': {
fontSize: '1.25rem'
},
'& a': {
textDecoration: 'none',
color: 'var(--mui-palette-primary-main)'
}
},
li: ({ theme }) => ({
lineHeight: theme.typography.body1.lineHeight,
'& > *:not(a)': {
color: 'var(--mui-palette-text-primary)'
}
})
}
}
}
export default breadcrumbs
+279
View File
@@ -0,0 +1,279 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Config Imports
import themeConfig from '@configs/themeConfig'
const buttonGroup: Theme['components'] = {
MuiButtonGroup: {
defaultProps: {
disableRipple: themeConfig.disableRipple
},
styleOverrides: {
root: {
variants: [
{
props: { variant: 'text', color: 'primary' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-primary-main)'
}
}
}
},
{
props: { variant: 'text', color: 'secondary' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-secondary-main)'
}
}
}
},
{
props: { variant: 'text', color: 'error' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-error-main)'
}
}
}
},
{
props: { variant: 'text', color: 'warning' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-warning-main)'
}
}
}
},
{
props: { variant: 'text', color: 'info' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-info-main)'
}
}
}
},
{
props: { variant: 'text', color: 'success' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-success-main)'
}
}
}
},
{
props: { variant: 'contained', color: 'primary' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-primary-sm)'
},
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-primary-dark)'
}
}
}
},
{
props: { variant: 'contained', color: 'secondary' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-secondary-sm)'
},
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-secondary-dark)'
}
}
}
},
{
props: { variant: 'contained', color: 'error' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-error-sm)'
},
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-error-dark)'
}
}
}
},
{
props: { variant: 'contained', color: 'warning' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-warning-sm)'
},
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-warning-dark)'
}
}
}
},
{
props: { variant: 'contained', color: 'info' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-info-sm)'
},
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-info-dark)'
}
}
}
},
{
props: { variant: 'contained', color: 'success' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-success-sm)'
},
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderColor: 'var(--mui-palette-success-dark)'
}
}
}
},
{
props: { variant: 'tonal', color: 'primary', orientation: 'horizontal' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderRight: '1px solid var(--mui-palette-primary-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'secondary', orientation: 'horizontal' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderRight: '1px solid var(--mui-palette-secondary-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'error', orientation: 'horizontal' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderRight: '1px solid var(--mui-palette-error-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'warning', orientation: 'horizontal' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderRight: '1px solid var(--mui-palette-warning-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'info', orientation: 'horizontal' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderRight: '1px solid var(--mui-palette-info-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'success', orientation: 'horizontal' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderRight: '1px solid var(--mui-palette-success-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'primary', orientation: 'vertical' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderBottom: '1px solid var(--mui-palette-primary-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'secondary', orientation: 'vertical' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderBottom: '1px solid var(--mui-palette-secondary-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'error', orientation: 'vertical' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderBottom: '1px solid var(--mui-palette-error-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'warning', orientation: 'vertical' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderBottom: '1px solid var(--mui-palette-warning-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'info', orientation: 'vertical' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderBottom: '1px solid var(--mui-palette-info-darkOpacity)'
}
}
}
},
{
props: { variant: 'tonal', color: 'success', orientation: 'vertical' },
style: {
'& .MuiButtonGroup-firstButton, & .MuiButtonGroup-middleButton': {
'&, &.Mui-disabled': {
borderBottom: '1px solid var(--mui-palette-success-darkOpacity)'
}
}
}
}
]
}
}
}
}
export default buttonGroup
+459
View File
@@ -0,0 +1,459 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Config Imports
import themeConfig from '@configs/themeConfig'
const iconStyles = (size?: string) => ({
'& > *:nth-of-type(1)': {
...(size === 'small'
? {
fontSize: '14px'
}
: {
...(size === 'medium'
? {
fontSize: '16px'
}
: {
fontSize: '20px'
})
})
}
})
const button: Theme['components'] = {
MuiButtonBase: {
defaultProps: {
disableRipple: themeConfig.disableRipple
}
},
MuiButton: {
styleOverrides: {
root: ({ theme, ownerState }) => ({
'&.Mui-disabled': {
opacity: 0.45
},
transition: theme.transitions.create('all', {
duration: theme.transitions.duration.short
}),
'&:not(.Mui-disabled):active': {
transform: 'scale(0.98)'
},
...(ownerState.variant === 'text'
? {
...(ownerState.size === 'small' && {
padding: theme.spacing(1.5, 2.25)
}),
...(ownerState.size === 'medium' && {
padding: theme.spacing(2, 3)
}),
...(ownerState.size === 'large' && {
padding: theme.spacing(2.75, 4)
})
}
: {
...(ownerState.variant === 'outlined'
? {
...(ownerState.size === 'small' && {
padding: theme.spacing(1.25, 3.25)
}),
...(ownerState.size === 'medium' && {
padding: theme.spacing(1.75, 4.75)
}),
...(ownerState.size === 'large' && {
padding: theme.spacing(2.5, 6.25)
})
}
: {
...(ownerState.size === 'small' && {
padding: theme.spacing(1.5, 3.5)
}),
...(ownerState.size === 'medium' && {
padding: theme.spacing(2, 5)
}),
...(ownerState.size === 'large' && {
padding: theme.spacing(2.75, 6.5)
})
})
}),
variants: [
{
props: { variant: 'text', color: 'primary' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-primary-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-primary-main)'
}
}
},
{
props: { variant: 'text', color: 'secondary' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-secondary-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-secondary-main)'
}
}
},
{
props: { variant: 'text', color: 'error' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-error-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-error-main)'
}
}
},
{
props: { variant: 'text', color: 'warning' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-warning-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-warning-main)'
}
}
},
{
props: { variant: 'text', color: 'info' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-info-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-info-main)'
}
}
},
{
props: { variant: 'text', color: 'success' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-success-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-success-main)'
}
}
},
{
props: { variant: 'outlined', color: 'primary' },
style: {
borderColor: 'var(--mui-palette-primary-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-primary-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-primary-main)',
borderColor: 'var(--mui-palette-primary-main)'
}
}
},
{
props: { variant: 'outlined', color: 'secondary' },
style: {
borderColor: 'var(--mui-palette-secondary-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-secondary-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-secondary-main)',
borderColor: 'var(--mui-palette-secondary-main)'
}
}
},
{
props: { variant: 'outlined', color: 'error' },
style: {
borderColor: 'var(--mui-palette-error-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-error-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-error-main)',
borderColor: 'var(--mui-palette-error-main)'
}
}
},
{
props: { variant: 'outlined', color: 'warning' },
style: {
borderColor: 'var(--mui-palette-warning-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-warning-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-warning-main)',
borderColor: 'var(--mui-palette-warning-main)'
}
}
},
{
props: { variant: 'outlined', color: 'info' },
style: {
borderColor: 'var(--mui-palette-info-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-info-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-info-main)',
borderColor: 'var(--mui-palette-info-main)'
}
}
},
{
props: { variant: 'outlined', color: 'success' },
style: {
borderColor: 'var(--mui-palette-success-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-success-lighterOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-success-main)',
borderColor: 'var(--mui-palette-success-main)'
}
}
},
{
props: { variant: 'contained', color: 'primary' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-primary-sm)'
},
'&:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-primary-dark)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-primary-contrastText)',
backgroundColor: 'var(--mui-palette-primary-main)'
}
}
},
{
props: { variant: 'contained', color: 'secondary' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-secondary-sm)'
},
'&:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-secondary-dark)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-secondary-contrastText)',
backgroundColor: 'var(--mui-palette-secondary-main)'
}
}
},
{
props: { variant: 'contained', color: 'error' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-error-sm)'
},
'&:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-error-dark)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-error-contrastText)',
backgroundColor: 'var(--mui-palette-error-main)'
}
}
},
{
props: { variant: 'contained', color: 'warning' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-warning-sm)'
},
'&:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-warning-dark)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-warning-contrastText)',
backgroundColor: 'var(--mui-palette-warning-main)'
}
}
},
{
props: { variant: 'contained', color: 'info' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-info-sm)'
},
'&:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-info-dark)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-info-contrastText)',
backgroundColor: 'var(--mui-palette-info-main)'
}
}
},
{
props: { variant: 'contained', color: 'success' },
style: {
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-success-sm)'
},
'&:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-success-dark)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-success-contrastText)',
backgroundColor: 'var(--mui-palette-success-main)'
}
}
},
{
props: { variant: 'tonal', color: 'primary' },
style: {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-primary-mainOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-primary-main)'
}
}
},
{
props: { variant: 'tonal', color: 'secondary' },
style: {
backgroundColor: 'var(--mui-palette-secondary-lightOpacity)',
color: 'var(--mui-palette-secondary-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-secondary-mainOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-secondary-main)'
}
}
},
{
props: { variant: 'tonal', color: 'error' },
style: {
backgroundColor: 'var(--mui-palette-error-lightOpacity)',
color: 'var(--mui-palette-error-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-error-mainOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-error-main)'
}
}
},
{
props: { variant: 'tonal', color: 'warning' },
style: {
backgroundColor: 'var(--mui-palette-warning-lightOpacity)',
color: 'var(--mui-palette-warning-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-warning-mainOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-warning-main)'
}
}
},
{
props: { variant: 'tonal', color: 'info' },
style: {
backgroundColor: 'var(--mui-palette-info-lightOpacity)',
color: 'var(--mui-palette-info-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-info-mainOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-info-main)'
}
}
},
{
props: { variant: 'tonal', color: 'success' },
style: {
backgroundColor: 'var(--mui-palette-success-lightOpacity)',
color: 'var(--mui-palette-success-main)',
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active, &.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))':
{
backgroundColor: 'var(--mui-palette-success-mainOpacity)'
},
'&.Mui-disabled': {
color: 'var(--mui-palette-success-main)'
}
}
}
]
}),
sizeSmall: ({ theme }) => ({
lineHeight: 1.38462,
fontSize: theme.typography.body2.fontSize,
borderRadius: 'var(--mui-shape-customBorderRadius-sm)'
}),
sizeLarge: {
fontSize: '1.0625rem',
lineHeight: 1.529412,
borderRadius: 'var(--mui-shape-customBorderRadius-lg)'
},
startIcon: ({ theme, ownerState }) => ({
...(ownerState.size === 'small'
? {
marginInlineEnd: theme.spacing(1.5)
}
: {
...(ownerState.size === 'medium'
? {
marginInlineEnd: theme.spacing(2)
}
: {
marginInlineEnd: theme.spacing(2.5)
})
}),
...iconStyles(ownerState.size)
}),
endIcon: ({ theme, ownerState }) => ({
...(ownerState.size === 'small'
? {
marginInlineStart: theme.spacing(1.5)
}
: {
...(ownerState.size === 'medium'
? {
marginInlineStart: theme.spacing(2)
}
: {
marginInlineStart: theme.spacing(2.5)
})
}),
...iconStyles(ownerState.size)
})
}
}
}
export default button
+94
View File
@@ -0,0 +1,94 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { Skin } from '@core/types'
const card = (skin: Skin): Theme['components'] => {
return {
MuiCard: {
defaultProps: {
...(skin === 'bordered' && {
variant: 'outlined'
})
},
styleOverrides: {
root: ({ ownerState }) => ({
...(ownerState.variant !== 'outlined' && {
boxShadow: 'var(--mui-customShadows-md)'
})
})
}
},
MuiCardHeader: {
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(6),
'& + .MuiCardContent-root, & + .MuiCardActions-root': {
paddingBlockStart: 0
},
'& + .MuiCollapse-root .MuiCardContent-root:first-child, & + .MuiCollapse-root .MuiCardActions-root:first-child':
{
paddingBlockStart: 0
}
}),
subheader: ({ theme }) => ({
...theme.typography.subtitle1,
color: 'rgb(var(--mui-palette-text-primaryChannel) / 0.55)'
}),
action: ({ theme }) => ({
...theme.typography.body1,
color: 'var(--mui-palette-text-disabled)',
marginBlock: 0,
marginInlineEnd: 0,
'& .MuiIconButton-root': {
color: 'inherit'
}
})
}
},
MuiCardContent: {
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(6),
color: 'var(--mui-palette-text-secondary)',
'&:last-child': {
paddingBlockEnd: theme.spacing(6)
},
'& + .MuiCardHeader-root, & + .MuiCardContent-root, & + .MuiCardActions-root': {
paddingBlockStart: 0
},
'& + .MuiCollapse-root .MuiCardHeader-root:first-child, & + .MuiCollapse-root .MuiCardContent-root:first-child, & + .MuiCollapse-root .MuiCardActions-root:first-child':
{
paddingBlockStart: 0
}
})
}
},
MuiCardActions: {
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(6),
'& .MuiButtonBase-root:not(:first-of-type)': {
marginInlineStart: theme.spacing(4)
},
'&:where(.card-actions-dense)': {
padding: theme.spacing(3),
'& .MuiButton-text': {
paddingInline: theme.spacing(3)
}
},
'& + .MuiCardHeader-root, & + .MuiCardContent-root, & + .MuiCardActions-root': {
paddingBlockStart: 0
},
'& + .MuiCollapse-root .MuiCardHeader-root:first-child, & + .MuiCollapse-root .MuiCardContent-root:first-child, & + .MuiCollapse-root .MuiCardActions-root:first-child':
{
paddingBlockStart: 0
}
})
}
}
}
}
export default card
+107
View File
@@ -0,0 +1,107 @@
// React Imports
import React from 'react'
// MUI Imports
import type { Theme } from '@mui/material/styles'
const Icon = () => {
return (
<svg width='1em' height='1em' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
d='M4 7C4 5.34315 5.34315 4 7 4H17C18.6569 4 20 5.34315 20 7V17C20 18.6569 18.6569 20 17 20H7C5.34315 20 4 18.6569 4 17V7Z'
stroke='var(--mui-palette-text-disabled)'
strokeWidth='2'
/>
</svg>
)
}
const IndeterminateIcon = () => {
return (
<svg width='1em' height='1em' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path d='M3 7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4v10a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V7Z' fill='currentColor' />
<path
d='M8.5 12h7'
stroke='var(--mui-palette-common-white)'
strokeWidth='1.5'
strokeLinecap='round'
strokeLinejoin='round'
/>
</svg>
)
}
const CheckedIcon = () => {
return (
<svg width='1em' height='1em' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path d='M3 7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4v10a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V7Z' fill='currentColor' />
<path
d='m8.5 12 2.5 2.5 5-5'
stroke='var(--mui-palette-common-white)'
strokeWidth='1.5'
strokeLinecap='round'
strokeLinejoin='round'
/>
</svg>
)
}
const checkbox: Theme['components'] = {
MuiCheckbox: {
defaultProps: {
icon: <Icon />,
indeterminateIcon: <IndeterminateIcon />,
checkedIcon: <CheckedIcon />
},
styleOverrides: {
root: ({ theme, ownerState }) => ({
...(ownerState.size === 'small'
? {
padding: theme.spacing(1),
'& svg': {
fontSize: '1.25rem'
}
}
: {
padding: theme.spacing(1.5),
'& svg': {
fontSize: '1.5rem'
}
}),
'&:not(.Mui-checked):not(.Mui-disabled):not(.MuiCheckbox-indeterminate) svg, &:not(.Mui-checked):not(.Mui-disabled):not(.MuiCheckbox-indeterminate) i':
{
color: 'var(--mui-palette-text-disabled)'
},
'&.Mui-checked:not(.Mui-disabled) svg, &.MuiCheckbox-indeterminate:not(.Mui-disabled) svg': {
filter: `drop-shadow(var(--mui-customShadows-${ownerState.color}-sm))`
},
'&.Mui-disabled': {
opacity: 0.45,
'&:not(.Mui-checked)': {
color: 'var(--mui-palette-text-disabled)'
},
'&.Mui-checked.MuiCheckbox-colorPrimary': {
color: 'var(--mui-palette-primary-main)'
},
'&.Mui-checked.MuiCheckbox-colorSecondary': {
color: 'var(--mui-palette-secondary-main)'
},
'&.Mui-checked.MuiCheckbox-colorError': {
color: 'var(--mui-palette-error-main)'
},
'&.Mui-checked.MuiCheckbox-colorWarning': {
color: 'var(--mui-palette-warning-main)'
},
'&.Mui-checked.MuiCheckbox-colorInfo': {
color: 'var(--mui-palette-info-main)'
},
'&.Mui-checked.MuiCheckbox-colorSuccess': {
color: 'var(--mui-palette-success-main)'
}
}
})
}
}
}
export default checkbox
+204
View File
@@ -0,0 +1,204 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const chip: Theme['components'] = {
MuiChip: {
styleOverrides: {
root: ({ ownerState, theme }) => ({
...theme.typography.body2,
fontWeight: theme.typography.fontWeightMedium,
'&.MuiChip-outlined:not(.MuiChip-colorDefault)': {
borderColor: `var(--mui-palette-${ownerState.color}-main)`
},
...(ownerState.size === 'small'
? {
borderRadius: 'var(--mui-shape-customBorderRadius-sm)'
}
: {
borderRadius: 'var(--mui-shape-borderRadius)'
}),
'& .MuiChip-deleteIcon': {
...(ownerState.size === 'small'
? {
fontSize: '1rem',
marginInlineEnd: theme.spacing(1),
marginInlineStart: theme.spacing(-2)
}
: {
fontSize: '1.25rem',
marginInlineEnd: theme.spacing(1.5),
marginInlineStart: theme.spacing(-2)
})
},
'& .MuiChip-avatar, & .MuiChip-icon': {
'& i, & svg': {
...(ownerState.size === 'small'
? {
fontSize: 13
}
: {
fontSize: 15
})
},
...(ownerState.size === 'small'
? {
blockSize: 16,
inlineSize: 16,
marginInlineStart: theme.spacing(1),
marginInlineEnd: theme.spacing(-1.5)
}
: {
blockSize: 20,
inlineSize: 20,
marginInlineStart: theme.spacing(1.5),
marginInlineEnd: theme.spacing(-2)
})
},
'&.Mui-disabled': {
opacity: 0.45
},
variants: [
{
props: { variant: 'tonal', color: 'primary' },
style: {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)',
'&.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-primary-mainOpacity)'
},
'& .MuiChip-deleteIcon': {
color: 'rgb(var(--mui-palette-primary-mainChannel) / 0.7)',
'&:hover': {
color: 'var(--mui-palette-primary-main)'
}
},
'&.MuiChip-clickable:hover': {
backgroundColor: 'var(--mui-palette-primary-main)',
color: 'var(--mui-palette-common-white)'
}
}
},
{
props: { variant: 'tonal', color: 'secondary' },
style: {
backgroundColor: 'var(--mui-palette-secondary-lightOpacity)',
color: 'var(--mui-palette-secondary-main)',
'&.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-secondary-mainOpacity)'
},
'& .MuiChip-deleteIcon': {
color: 'rgb(var(--mui-palette-secondary-mainChannel) / 0.7)',
'&:hover': {
color: 'var(--mui-palette-secondary-main)'
}
},
'&.MuiChip-clickable:hover': {
backgroundColor: 'var(--mui-palette-secondary-main)',
color: 'var(--mui-palette-common-white)'
}
}
},
{
props: { variant: 'tonal', color: 'error' },
style: {
backgroundColor: 'var(--mui-palette-error-lightOpacity)',
color: 'var(--mui-palette-error-main)',
'&.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-error-mainOpacity)'
},
'& .MuiChip-deleteIcon': {
color: 'rgb(var(--mui-palette-error-mainChannel) / 0.7)',
'&:hover': {
color: 'var(--mui-palette-error-main)'
}
},
'&.MuiChip-clickable:hover': {
backgroundColor: 'var(--mui-palette-error-main)',
color: 'var(--mui-palette-common-white)'
}
}
},
{
props: { variant: 'tonal', color: 'warning' },
style: {
backgroundColor: 'var(--mui-palette-warning-lightOpacity)',
color: 'var(--mui-palette-warning-main)',
'&.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-warning-mainOpacity)'
},
'& .MuiChip-deleteIcon': {
color: 'rgb(var(--mui-palette-warning-mainChannel) / 0.7)',
'&:hover': {
color: 'var(--mui-palette-warning-main)'
}
},
'&.MuiChip-clickable:hover': {
backgroundColor: 'var(--mui-palette-warning-main)',
color: 'var(--mui-palette-common-white)'
}
}
},
{
props: { variant: 'tonal', color: 'info' },
style: {
backgroundColor: 'var(--mui-palette-info-lightOpacity)',
color: 'var(--mui-palette-info-main)',
'&.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-info-mainOpacity)'
},
'& .MuiChip-deleteIcon': {
color: 'rgb(var(--mui-palette-info-mainChannel) / 0.7)',
'&:hover': {
color: 'var(--mui-palette-info-main)'
}
},
'&.MuiChip-clickable:hover': {
backgroundColor: 'var(--mui-palette-info-main)',
color: 'var(--mui-palette-common-white)'
}
}
},
{
props: { variant: 'tonal', color: 'success' },
style: {
backgroundColor: 'var(--mui-palette-success-lightOpacity)',
color: 'var(--mui-palette-success-main)',
'&.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-success-mainOpacity)'
},
'& .MuiChip-deleteIcon': {
color: 'rgb(var(--mui-palette-success-mainChannel) / 0.7)',
'&:hover': {
color: 'var(--mui-palette-success-main)'
}
},
'&.MuiChip-clickable:hover': {
backgroundColor: 'var(--mui-palette-success-main)',
color: 'var(--mui-palette-common-white)'
}
}
}
]
}),
label: ({ ownerState, theme }) => ({
...(ownerState.size === 'small'
? {
paddingInline: theme.spacing(2.5),
paddingBlock: theme.spacing(0.5)
}
: {
paddingInline: theme.spacing(3)
})
}),
iconMedium: {
fontSize: '1.25rem'
},
iconSmall: {
fontSize: '1rem'
}
}
}
}
export default chip
+71
View File
@@ -0,0 +1,71 @@
//MUI Imports
import type { Theme } from '@mui/material/styles'
//Type Imports
import type { Skin } from '@core/types'
const dialog = (skin: Skin): Theme['components'] => ({
MuiDialog: {
styleOverrides: {
paper: ({ theme }) => ({
borderRadius: 'var(--mui-shape-customBorderRadius-lg)',
...(skin !== 'bordered'
? {
boxShadow: 'var(--mui-customShadows-lg)'
}
: {
boxShadow: 'none'
}),
[theme.breakpoints.down('sm')]: {
'&:not(.MuiDialog-paperFullScreen)': {
margin: theme.spacing(6)
}
}
}),
paperFullScreen: {
borderRadius: 0
}
}
},
MuiDialogTitle: {
defaultProps: {
variant: 'h5'
},
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(6),
'& + .MuiDialogActions-root': {
paddingTop: 0
}
})
}
},
MuiDialogContent: {
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(6),
'& + .MuiDialogContent-root, & + .MuiDialogActions-root': {
paddingTop: 0
}
})
}
},
MuiDialogActions: {
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(6),
'& .MuiButtonBase-root:not(:first-of-type)': {
marginInlineStart: theme.spacing(4)
},
'&:where(.dialog-actions-dense)': {
padding: theme.spacing(3),
'& .MuiButton-text': {
paddingInline: theme.spacing(3)
}
}
})
}
}
})
export default dialog
+26
View File
@@ -0,0 +1,26 @@
// MUI Imports
import type { Theme } from '@mui/material'
// Type Imports
import type { Skin } from '@core/types'
const drawer = (skin: Skin): Theme['components'] => ({
MuiDrawer: {
defaultProps: {
...(skin === 'bordered' && {
PaperProps: {
elevation: 0
}
})
},
styleOverrides: {
paper: {
...(skin !== 'bordered' && {
boxShadow: 'var(--mui-customShadows-lg)'
})
}
}
}
})
export default drawer
+72
View File
@@ -0,0 +1,72 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const fab: Theme['components'] = {
MuiFab: {
styleOverrides: {
root: {
variants: [
{
props: { color: 'default' },
style: {
color: 'rgb(var(--mui-mainColorChannels-light) / 0.9)',
'&.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-grey-A100)'
}
}
},
{
props: { color: 'primary' },
style: {
'&.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-primary-dark)'
}
}
},
{
props: { color: 'secondary' },
style: {
'&.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-secondary-dark)'
}
}
},
{
props: { color: 'error' },
style: {
'&.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-error-dark)'
}
}
},
{
props: { color: 'warning' },
style: {
'&.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-warning-dark)'
}
}
},
{
props: { color: 'info' },
style: {
'&.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-info-dark)'
}
}
},
{
props: { color: 'success' },
style: {
'&.Mui-focusVisible:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'var(--mui-palette-success-dark)'
}
}
}
]
}
}
}
}
export default fab
@@ -0,0 +1,22 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const formControlLabel: Theme['components'] = {
MuiFormControlLabel: {
styleOverrides: {
root: ({ theme }) => ({
marginInlineStart: theme.spacing(-2)
}),
label: {
'&, &.Mui-disabled': {
color: 'var(--mui-palette-text-primary)'
},
'&.Mui-disabled': {
opacity: 0.45
}
}
}
}
}
export default formControlLabel
+148
View File
@@ -0,0 +1,148 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Config Imports
import themeConfig from '@configs/themeConfig'
const iconButton: Theme['components'] = {
MuiIconButton: {
styleOverrides: {
root: {
'& .MuiSvgIcon-root, & i, & svg': {
fontSize: 'inherit'
},
variants: [
{
props: { color: 'default' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active': {
backgroundColor: 'rgb(var(--mui-palette-text-primaryChannel) / 0.08)'
},
...(themeConfig.disableRipple && {
'&.Mui-focusVisible:not(.Mui-disabled)': {
backgroundColor: 'rgb(var(--mui-palette-text-primaryChannel) / 0.08)'
}
}),
'&.Mui-disabled': {
opacity: 0.45,
color: 'var(--mui-palette-action-active)'
}
}
},
{
props: { color: 'primary' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active': {
backgroundColor: 'var(--mui-palette-primary-lighterOpacity)'
},
...(themeConfig.disableRipple && {
'&.Mui-focusVisible:not(.Mui-disabled)': {
backgroundColor: 'var(--mui-palette-primary-lighterOpacity)'
}
}),
'&.Mui-disabled': {
opacity: 0.45,
color: 'var(--mui-palette-primary-main)'
}
}
},
{
props: { color: 'secondary' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active': {
backgroundColor: 'var(--mui-palette-secondary-lighterOpacity)'
},
...(themeConfig.disableRipple && {
'&.Mui-focusVisible:not(.Mui-disabled)': {
backgroundColor: 'var(--mui-palette-secondary-lighterOpacity)'
}
}),
'&.Mui-disabled': {
opacity: 0.45,
color: 'var(--mui-palette-secondary-main)'
}
}
},
{
props: { color: 'error' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active': {
backgroundColor: 'var(--mui-palette-error-lighterOpacity)'
},
...(themeConfig.disableRipple && {
'&.Mui-focusVisible:not(.Mui-disabled)': { backgroundColor: 'var(--mui-palette-error-lighterOpacity)' }
}),
'&.Mui-disabled': {
opacity: 0.45,
color: 'var(--mui-palette-error-main)'
}
}
},
{
props: { color: 'warning' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active': {
backgroundColor: 'var(--mui-palette-warning-lighterOpacity)'
},
...(themeConfig.disableRipple && {
'&.Mui-focusVisible:not(.Mui-disabled)': {
backgroundColor: 'var(--mui-palette-warning-lighterOpacity)'
}
}),
'&.Mui-disabled': {
opacity: 0.45,
color: 'var(--mui-palette-warning-main)'
}
}
},
{
props: { color: 'info' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active': {
backgroundColor: 'var(--mui-palette-info-lighterOpacity)'
},
...(themeConfig.disableRipple && {
'&.Mui-focusVisible:not(.Mui-disabled)': { backgroundColor: 'var(--mui-palette-info-lighterOpacity)' }
}),
'&.Mui-disabled': {
opacity: 0.45,
color: 'var(--mui-palette-info-main)'
}
}
},
{
props: { color: 'success' },
style: {
'&:not(.Mui-disabled):hover, &:not(.Mui-disabled):active': {
backgroundColor: 'var(--mui-palette-success-lighterOpacity)'
},
...(themeConfig.disableRipple && {
'&.Mui-focusVisible:not(.Mui-disabled)': {
backgroundColor: 'var(--mui-palette-success-lighterOpacity)'
}
}),
'&.Mui-disabled': {
opacity: 0.45,
color: 'var(--mui-palette-success-main)'
}
}
}
]
},
sizeSmall: ({ theme }) => ({
padding: theme.spacing(1.25),
fontSize: '1.25rem'
}),
sizeMedium: ({ theme }) => ({
padding: theme.spacing(2),
fontSize: '1.375rem'
}),
sizeLarge: ({ theme }) => ({
padding: theme.spacing(3),
fontSize: '1.5rem'
})
}
}
}
export default iconButton
+84
View File
@@ -0,0 +1,84 @@
// Type Imports
import type { Skin } from '@core/types'
// Override Imports
import Accordion from './accordion'
import Alerts from './alert'
import Autocomplete from './autocomplete'
import avatar from './avatar'
import backdrop from './backdrop'
import badges from './badges'
import breadcrumbs from './breadcrumbs'
import button from './button'
import buttonGroup from './button-group'
import card from './card'
import Checkbox from './checkbox'
import chip from './chip'
import dialog from './dialog'
import drawer from './drawer'
import fab from './fab'
import formControlLabel from './form-control-label'
import iconButton from './icon-button'
import input from './input'
import list from './list'
import menu from './menu'
import pagination from './pagination'
import paper from './paper'
import popover from './popover'
import progress from './progress'
import Radio from './radio'
import Rating from './rating'
import select from './select'
import slider from './slider'
import snackbar from './snackbar'
import switchOverrides from './switch'
import tablePagination from './table-pagination'
import tabs from './tabs'
import timeline from './timeline'
import toggleButton from './toggle-button'
import tooltip from './tooltip'
import typography from './typography'
const overrides = (skin: Skin) => {
return Object.assign(
{},
Accordion(skin),
Alerts,
Autocomplete(skin),
avatar,
backdrop,
badges,
breadcrumbs,
button,
buttonGroup,
card(skin),
Checkbox,
chip,
dialog(skin),
drawer(skin),
fab,
formControlLabel,
iconButton,
input,
list,
menu(skin),
pagination,
paper,
popover(skin),
progress,
Radio,
Rating,
select,
slider,
snackbar(skin),
switchOverrides,
tablePagination,
tabs,
timeline,
toggleButton,
tooltip,
typography
)
}
export default overrides
+120
View File
@@ -0,0 +1,120 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const input: Theme['components'] = {
MuiFormControl: {
styleOverrides: {
root: {
'&:has(.MuiRadio-root) .MuiFormHelperText-root, &:has(.MuiCheckbox-root) .MuiFormHelperText-root, &:has(.MuiSwitch-root) .MuiFormHelperText-root':
{
marginInline: 0
}
}
}
},
MuiInputBase: {
styleOverrides: {
root: {
lineHeight: 1.6,
'&.MuiInput-underline': {
'&:before': {
borderColor: 'var(--mui-palette-customColors-inputBorder)'
},
'&:not(.Mui-disabled, .Mui-error):hover:before': {
borderColor: 'var(--mui-palette-action-active)'
}
},
'&.Mui-disabled .MuiInputAdornment-root, &.Mui-disabled .MuiInputAdornment-root > *': {
color: 'var(--mui-palette-action-disabled)'
}
}
}
},
MuiFilledInput: {
styleOverrides: {
root: {
borderStartStartRadius: 4,
borderStartEndRadius: 4,
'&:before': {
borderBottom: '1px solid var(--mui-palette-text-secondary)'
},
'&:hover:before': {
borderBottom: '1px solid var(--mui-palette-text-primary)'
},
'&.Mui-disabled:before': {
borderBottomStyle: 'solid',
opacity: 0.38
}
}
}
},
MuiInputLabel: {
styleOverrides: {
shrink: ({ ownerState }) => ({
...(ownerState.variant === 'outlined' && {
transform: 'translate(14px, -8px) scale(0.867)'
}),
...(ownerState.variant === 'filled' && {
transform: `translate(12px, ${ownerState.size === 'small' ? 4 : 7}px) scale(0.867)`
}),
...(ownerState.variant === 'standard' && {
transform: 'translate(0, -1.5px) scale(0.867)'
})
})
}
},
MuiOutlinedInput: {
styleOverrides: {
root: {
'&:not(.Mui-focused):not(.Mui-error):not(.Mui-disabled):hover .MuiOutlinedInput-notchedOutline': {
borderColor: 'var(--mui-palette-action-active)'
},
'&.Mui-disabled .MuiOutlinedInput-notchedOutline': {
borderColor: 'var(--mui-palette-divider)'
},
'&:not(.Mui-error).MuiInputBase-colorPrimary.Mui-focused': {
boxShadow: 'var(--mui-customShadows-primary-sm)'
}
},
input: ({ theme, ownerState }) => ({
...(ownerState?.size === 'medium' && {
'&:not(.MuiInputBase-inputMultiline, .MuiInputBase-inputAdornedStart)': {
padding: theme.spacing(4)
},
height: '1.5em'
}),
'& ~ .MuiOutlinedInput-notchedOutline': {
borderColor: 'var(--mui-palette-customColors-inputBorder)'
}
}),
notchedOutline: {
'& legend': {
fontSize: '0.867em'
}
}
}
},
MuiInputAdornment: {
styleOverrides: {
root: {
color: 'var(--mui-palette-text-primary)',
'& i, & svg': {
fontSize: '1rem !important'
},
'& *': {
color: 'inherit !important'
}
}
}
},
MuiFormHelperText: {
styleOverrides: {
root: {
lineHeight: 1,
letterSpacing: 'unset'
}
}
}
}
export default input
+81
View File
@@ -0,0 +1,81 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const list: Theme['components'] = {
MuiListItem: {
styleOverrides: {
root: ({ theme }) => ({
gap: theme.spacing(3)
}),
padding: ({ theme, ownerState }) => ({
...(!ownerState.dense && {
paddingBlock: theme.spacing(2),
paddingInlineStart: theme.spacing(5)
})
})
}
},
MuiListItemAvatar: {
styleOverrides: {
root: {
minInlineSize: 'unset'
}
}
},
MuiListItemIcon: {
styleOverrides: {
root: {
minInlineSize: 0,
color: 'var(--mui-palette-text-primary)',
fontSize: '1.375rem',
'& > svg, & > i': {
fontSize: 'inherit'
}
}
}
},
MuiListItemButton: {
styleOverrides: {
root: ({ theme, ownerState }) => ({
gap: theme.spacing(2),
...(!ownerState.dense && {
paddingBlock: theme.spacing(2)
}),
paddingInlineStart: theme.spacing(5),
'&.Mui-selected': {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
'&:hover, &.Mui-focused, &.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-primary-mainOpacity)'
},
'& .MuiTypography-root': {
color: 'var(--mui-palette-primary-main)'
},
'& + .MuiListItemSecondaryAction-root .MuiIconButton-root': {
color: 'var(--mui-palette-primary-main)'
}
}
})
}
},
MuiListItemText: {
styleOverrides: {
root: {
margin: 0
},
primary: {
color: 'var(--mui-palette-text-primary)'
}
}
},
MuiListSubheader: {
styleOverrides: {
root: ({ theme }) => ({
...theme.typography.subtitle2,
paddingBlock: 10,
paddingInline: theme.spacing(5)
})
}
}
}
export default list
+63
View File
@@ -0,0 +1,63 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { Skin } from '@core/types'
const menu = (skin: Skin): Theme['components'] => ({
MuiMenu: {
defaultProps: {
...(skin === 'bordered' && {
slotProps: {
paper: {
elevation: 0
}
}
})
},
styleOverrides: {
paper: ({ theme }) => ({
marginBlockStart: theme.spacing(0.5),
...(skin !== 'bordered' && {
boxShadow: 'var(--mui-customShadows-lg)'
})
})
}
},
MuiMenuItem: {
styleOverrides: {
root: ({ theme }) => ({
paddingBlock: theme.spacing(2),
gap: theme.spacing(2),
color: 'var(--mui-palette-text-primary)',
marginInline: theme.spacing(2),
borderRadius: 'var(--mui-shape-borderRadius)',
'& i, & svg': {
fontSize: '1.375rem'
},
'& .MuiListItemIcon-root': {
minInlineSize: 0
},
'&:not(:last-of-type)': {
marginBlockEnd: theme.spacing(0.5)
},
'&.Mui-selected': {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)',
'& .MuiListItemIcon-root': {
color: 'var(--mui-palette-primary-main)'
},
'&:hover, &.Mui-focused, &.Mui-focusVisible': {
backgroundColor: 'var(--mui-palette-primary-mainOpacity)'
}
},
'&.Mui-disabled': {
color: 'var(--mui-palette-text-disabled)',
opacity: 0.45
}
})
}
}
})
export default menu
+177
View File
@@ -0,0 +1,177 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const pagination: Theme['components'] = {
MuiPagination: {
styleOverrides: {
root: {
variants: [
{
props: { variant: 'text', color: 'primary' },
style: {
'& .MuiPaginationItem-root.Mui-selected.Mui-disabled': {
backgroundColor: 'var(--mui-palette-primary-main)',
color: 'var(--mui-palette-primary-contrastText)'
}
}
},
{
props: { variant: 'text', color: 'secondary' },
style: {
'& .MuiPaginationItem-root.Mui-selected.Mui-disabled': {
backgroundColor: 'var(--mui-palette-secondary-main)',
color: 'var(--mui-palette-secondary-contrastText)'
}
}
},
{
props: { variant: 'outlined' },
style: {
'& .MuiPaginationItem-root': {
borderColor: 'var(--mui-palette-customColors-inputBorder)'
}
}
},
{
props: { variant: 'outlined', color: 'primary' },
style: {
'& .MuiPaginationItem-root.Mui-selected': {
color: 'var(--mui-palette-primary-main)',
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
borderColor: 'rgb(var(--mui-palette-primary-mainChannel))'
}
}
},
{
props: { variant: 'outlined', color: 'secondary' },
style: {
'& .MuiPaginationItem-root.Mui-selected': {
color: 'var(--mui-palette-secondary-main)',
backgroundColor: 'var(--mui-palette-secondary-lightOpacity)',
borderColor: 'rgb(var(--mui-palette-secondary-mainChannel))'
}
}
},
{
props: { variant: 'tonal' },
style: {
'& .MuiPaginationItem-root:not(.MuiPaginationItem-ellipsis)': {
backgroundColor: 'var(--mui-palette-action-selected)'
}
}
},
{
props: { variant: 'tonal', color: 'standard' },
style: {
'& .MuiPaginationItem-root.Mui-selected': {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)',
'&:hover': {
backgroundColor: 'var(--mui-palette-primary-mainOpacity)'
}
},
'& .MuiPaginationItem-root:hover:not(.Mui-selected):not(.MuiPaginationItem-ellipsis)': {
backgroundColor: 'var(--mui-palette-action-disabledBackground)'
},
'& .MuiPaginationItem-root.Mui-selected.Mui-disabled': {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)'
}
}
},
{
props: { variant: 'tonal', color: 'primary' },
style: {
'& .MuiPaginationItem-root.Mui-selected': {
backgroundColor: 'var(--mui-palette-primary-main)',
color: 'var(--mui-palette-primary-contrastText)',
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-primary-sm)'
},
'&:hover': {
backgroundColor: 'var(--mui-palette-primary-dark)'
}
},
'& .MuiPaginationItem-root:hover:not(.Mui-selected):not(.MuiPaginationItem-ellipsis)': {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)'
},
'& .MuiPaginationItem-root.Mui-selected.Mui-disabled': {
backgroundColor: 'var(--mui-palette-primary-main)',
color: 'var(--mui-palette-primary-contrastText)'
}
}
},
{
props: { variant: 'tonal', color: 'secondary' },
style: {
'& .MuiPaginationItem-root.Mui-selected': {
backgroundColor: 'var(--mui-palette-secondary-main)',
color: 'var(--mui-palette-secondary-contrastText)',
'&:not(.Mui-disabled)': {
boxShadow: 'var(--mui-customShadows-secondary-sm)'
},
'&:hover': {
backgroundColor: 'var(--mui-palette-secondary-dark)'
}
},
'& .MuiPaginationItem-root:hover:not(.Mui-selected):not(.MuiPaginationItem-ellipsis)': {
backgroundColor: 'var(--mui-palette-secondary-mainOpacity)'
},
'& .MuiPaginationItem-root.Mui-selected.Mui-disabled': {
backgroundColor: 'var(--mui-palette-secondary-main)',
color: 'var(--mui-palette-secondary-contrastText)'
}
}
}
]
},
ul: {
rowGap: 6
}
}
},
MuiPaginationItem: {
styleOverrides: {
root: ({ ownerState }) => ({
...(ownerState.size === 'medium' && {
height: '2.375rem',
minWidth: '2.375rem'
}),
...(ownerState.shape !== 'rounded' && {
borderRadius: '50px'
}),
'&.Mui-selected.Mui-disabled': {
color: 'var(--mui-palette-text-primary)',
opacity: 0.45
},
'&.Mui-disabled': {
opacity: 0.45
},
...(ownerState.shape === 'rounded' &&
ownerState.size === 'small' && {
borderRadius: 'var(--mui-shape-customBorderRadius-sm)'
}),
...(ownerState.shape === 'rounded' &&
ownerState.size === 'large' && {
borderRadius: 'var(--mui-shape-customBorderRadius-lg)'
})
}),
ellipsis: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center'
},
sizeSmall: {
height: '1.875rem',
minWidth: '1.875rem'
},
sizeLarge: {
height: '3rem',
minWidth: '3rem'
}
}
}
}
export default pagination
+14
View File
@@ -0,0 +1,14 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const paper: Theme['components'] = {
MuiPaper: {
styleOverrides: {
root: {
backgroundImage: 'none'
}
}
}
}
export default paper
+21
View File
@@ -0,0 +1,21 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { Skin } from '@core/types'
const popover = (skin: Skin): Theme['components'] => ({
MuiPopover: {
styleOverrides: {
paper: {
...(skin === 'bordered'
? { boxShadow: 'none', border: '1px solid var(--mui-palette-divider)' }
: {
boxShadow: 'var(--mui-customShadows-sm)'
})
}
}
}
})
export default popover
+22
View File
@@ -0,0 +1,22 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const progress: Theme['components'] = {
MuiLinearProgress: {
styleOverrides: {
root: ({ theme }) => ({
blockSize: 6,
borderRadius: 'var(--mui-shape-borderRadius)',
backgroundColor: 'var(--mui-palette-customColors-trackBg)',
'& .MuiLinearProgress-bar': {
borderRadius: 'var(--mui-shape-borderRadius)'
},
'& .MuiLinearProgress-dashed': {
marginTop: theme.spacing(0.2)
}
})
}
}
}
export default progress
+84
View File
@@ -0,0 +1,84 @@
// React Imports
import React from 'react'
// MUI Imports
import type { Theme } from '@mui/material/styles'
const IconChecked = () => {
return (
<svg width='1em' height='1em' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
d='M5.5 12a6.5 6.5 0 1 1 13 0 6.5 6.5 0 0 1-13 0Z'
fill='var(--mui-palette-common-white)'
stroke='currentColor'
strokeWidth='5'
/>
</svg>
)
}
const UncheckedIcon = () => {
return (
<svg width='1em' height='1em' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path d='M4 12a8 8 0 1 1 16 0 8 8 0 0 1-16 0Z' stroke='var(--mui-palette-text-disabled)' strokeWidth='2' />
</svg>
)
}
const radio: Theme['components'] = {
MuiRadio: {
defaultProps: {
icon: <UncheckedIcon />,
checkedIcon: <IconChecked />
},
styleOverrides: {
root: ({ theme, ownerState }) => ({
...(ownerState.size === 'small'
? {
padding: theme.spacing(1),
'& svg': {
fontSize: '1.25rem'
}
}
: {
padding: theme.spacing(1.5),
'& svg': {
fontSize: '1.5rem'
}
}),
'&:not(.Mui-checked):not(.Mui-disabled) svg, &:not(.Mui-checked):not(.Mui-disabled) i': {
color: 'var(--mui-palette-text-disabled)'
},
'&.Mui-checked:not(.Mui-disabled) svg': {
filter: `drop-shadow(var(--mui-customShadows-${ownerState.color}-sm))`
},
'&.Mui-disabled': {
opacity: 0.45,
'&:not(.Mui-checked)': {
color: 'var(--mui-palette-text-secondary)'
},
'&.Mui-checked.MuiRadio-colorPrimary': {
color: 'var(--mui-palette-primary-main)'
},
'&.Mui-checked.MuiRadio-colorSecondary': {
color: 'var(--mui-palette-secondary-main)'
},
'&.Mui-checked.MuiRadio-colorError': {
color: 'var(--mui-palette-error-main)'
},
'&.Mui-checked.MuiRadio-colorWarning': {
color: 'var(--mui-palette-warning-main)'
},
'&.Mui-checked.MuiRadio-colorInfo': {
color: 'var(--mui-palette-info-main)'
},
'&.Mui-checked.MuiRadio-colorSuccess': {
color: 'var(--mui-palette-success-main)'
}
}
})
}
}
}
export default radio
+35
View File
@@ -0,0 +1,35 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const rating: Theme['components'] = {
MuiRating: {
defaultProps: {
emptyIcon: <i className='tabler-star' />,
icon: <i className='tabler-star-filled' />
},
styleOverrides: {
root: {
gap: '2px',
color: 'var(--mui-palette-warning-main)',
'& i, & svg': {
flexShrink: 0
},
'& .MuiRating-decimal > label:first-of-type, & .MuiRating-decimal > span:first-of-type': {
zIndex: 1
}
},
sizeSmall: {
'& .MuiRating-icon i, & .MuiRating-icon svg': {
fontSize: '1.25rem'
}
},
sizeLarge: {
'& .MuiRating-icon i, & .MuiRating-icon svg': {
fontSize: '1.75rem'
}
}
}
}
}
export default rating
+60
View File
@@ -0,0 +1,60 @@
// React Imports
import React from 'react'
// MUI Imports
import type { Theme } from '@mui/material/styles'
const SelectIcon = () => {
return <i className='tabler-chevron-down' />
}
const iconStyles = (theme: Theme) => ({
userSelect: 'none',
display: 'inline-block',
fill: 'currentColor',
flexShrink: 0,
transition: theme.transitions.create('fill', {
duration: theme.transitions.duration.shorter
}),
fontSize: '1.25rem',
position: 'absolute',
right: '1rem',
pointerEvents: 'none'
})
const select: Theme['components'] = {
MuiSelect: {
defaultProps: {
IconComponent: SelectIcon
},
styleOverrides: {
select: ({ theme, ownerState }) => ({
...(ownerState.variant === 'outlined' && {
height: '1.5em'
}),
'&[aria-expanded="true"] ~ i, &[aria-expanded="true"] ~ svg': {
transform: 'rotate(180deg)'
},
'& ~ i, & ~ svg': iconStyles(theme as Theme),
'&.MuiInputBase-inputSizeSmall': {
'& ~ i, & ~ svg': {
height: '1.125rem',
width: '1.125rem'
}
},
'&:not(aria-label="Without label") ~ .MuiOutlinedInput-notchedOutline > legend > span': {
paddingInline: '5px'
}
})
}
},
MuiNativeSelect: {
styleOverrides: {
select: ({ theme }) => ({
'& + i, & + svg': iconStyles(theme as Theme)
})
}
}
}
export default select
+100
View File
@@ -0,0 +1,100 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const slider: Theme['components'] = {
MuiSlider: {
styleOverrides: {
root: ({ ownerState }) => ({
boxSizing: 'border-box',
...(ownerState.orientation === 'horizontal'
? ownerState.size !== 'small'
? { blockSize: 6 }
: { blockSize: 4 }
: ownerState.size !== 'small'
? { inlineSize: 6 }
: { inlineSize: 4 }),
'&.Mui-disabled': {
opacity: 0.45,
color: `var(--mui-palette-${ownerState.color}-main)`
}
}),
thumb: ({ ownerState }) => ({
...(ownerState.size === 'small'
? {
blockSize: 14,
inlineSize: 14,
border: '2px solid currentColor',
'&:hover, &.Mui-focusVisible': {
boxShadow: `0 0 0 7px var(--mui-palette-${ownerState.color}-lightOpacity)`
},
'&.Mui-active.Mui-focusVisible': {
boxShadow: `0 0 0 10px var(--mui-palette-${ownerState.color}-lightOpacity)`
}
}
: {
blockSize: 22,
inlineSize: 22,
border: '4px solid currentColor'
}),
backgroundColor: 'var(--mui-palette-common-white)',
...(!ownerState.disabled && {
boxShadow: 'var(--mui-customShadows-sm)'
}),
'&:before': {
boxShadow: 'none'
},
'&:after': {
...(ownerState.size === 'small'
? {
blockSize: 28,
inlineSize: 28
}
: {
blockSize: 38,
inlineSize: 38
})
},
'&:hover, &.Mui-focusVisible': {
boxShadow: `0 0 0 8px var(--mui-palette-${ownerState.color}-lightOpacity)`
},
'&.Mui-active.Mui-focusVisible': {
boxShadow: `0 0 0 13px var(--mui-palette-${ownerState.color}-lightOpacity)`
}
}),
rail: ({ ownerState }) => ({
opacity: 1,
color: `var(--mui-palette-${ownerState.color}-lightOpacity)`,
...(ownerState.track === 'inverted' && {
backgroundColor: `var(--mui-palette-${ownerState.color}-main)`
})
}),
valueLabel: ({ theme, ownerState }) => ({
...(ownerState.size === 'small'
? {
...theme.typography.caption,
padding: theme.spacing(0.5, 2),
borderRadius: 'var(--mui-shape-customBorderRadius-sm)'
}
: {
...theme.typography.body2,
fontWeight: theme.typography.fontWeightMedium,
padding: theme.spacing(0.5, 2.5),
borderRadius: 'var(--mui-shape-borderRadius)'
}),
color: 'var(--mui-palette-customColors-tooltipText)',
backgroundColor: 'var(--mui-palette-Tooltip-bg)',
'&:before': {
display: 'none'
}
}),
track: ({ theme, ownerState }) => ({
...(ownerState.track === 'inverted' && {
backgroundColor: `color-mix(in srgb, ${theme.palette[ownerState.color || 'primary'].main} 16%, var(--mui-palette-background-paper))`,
borderColor: `color-mix(in srgb, ${theme.palette[ownerState.color || 'primary'].main} 16%, var(--mui-palette-background-paper))`
})
})
}
}
}
export default slider
+27
View File
@@ -0,0 +1,27 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { Skin } from '@core/types'
const snackbar = (skin: Skin): Theme['components'] => ({
MuiSnackbarContent: {
styleOverrides: {
root: ({ theme }) => ({
padding: theme.spacing(0, 4),
...(skin !== 'bordered'
? {
boxShadow: 'var(--mui-customShadows-xs)'
}
: {
boxShadow: 'none'
}),
'& .MuiSnackbarContent-message': {
paddingBlock: theme.spacing(3)
}
})
}
}
})
export default snackbar
+74
View File
@@ -0,0 +1,74 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const switchOverrides: Theme['components'] = {
MuiSwitch: {
defaultProps: {
disableRipple: true
},
styleOverrides: {
root: ({ theme, ownerState }) => ({
'&:has(.Mui-disabled)': {
opacity: 0.45
},
...(ownerState.size !== 'small'
? {
width: 46,
height: 36,
padding: theme.spacing(2.25, 2)
}
: {
width: 42,
height: 30,
padding: theme.spacing(1.75, 2),
'& .MuiSwitch-thumb': {
width: 12,
height: 12
},
'& .MuiSwitch-switchBase': {
padding: 7,
left: 3,
'&.Mui-checked': {
left: -3
}
}
})
}),
switchBase: ({ ownerState }) => ({
top: 2,
left: 1,
'&.Mui-checked': {
left: -7,
color: 'var(--mui-palette-common-white)',
'& + .MuiSwitch-track': {
opacity: 1
}
},
'&.Mui-checked:not(.Mui-disabled) + .MuiSwitch-track': {
boxShadow: `var(--mui-customShadows-${ownerState.color}-sm)`
},
'&:not(.Mui-checked) + .MuiSwitch-track': {
boxShadow: '0 0 4px rgb(0 0 0 / 0.16) inset'
},
'&.Mui-disabled + .MuiSwitch-track': {
opacity: 1
},
'&:hover:not(:has(span.MuiTouchRipple-root))': {
backgroundColor: 'transparent'
}
}),
thumb: {
width: 14,
height: 14,
boxShadow: 'var(--mui-customShadows-xs)'
},
track: {
opacity: 1,
borderRadius: 10,
backgroundColor: 'var(--mui-palette-action-focus)'
}
}
}
}
export default switchOverrides
@@ -0,0 +1,19 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const tablePagination: Theme['components'] = {
MuiTablePagination: {
styleOverrides: {
toolbar: ({ theme }) => ({
paddingInlineEnd: `${theme.spacing(3)} !important`
}),
select: {
'& ~ i, & ~ svg': {
right: '2px !important'
}
}
}
}
}
export default tablePagination
+101
View File
@@ -0,0 +1,101 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const tabs: Theme['components'] = {
MuiTabs: {
styleOverrides: {
root: ({ theme, ownerState }) => ({
minBlockSize: 38,
...(ownerState.orientation === 'horizontal'
? {
borderBlockEnd: '1px solid var(--mui-palette-divider)'
}
: {
borderInlineEnd: '1px solid var(--mui-palette-divider)'
}),
'& .MuiTab-root:hover': {
...(ownerState.orientation === 'horizontal'
? {
paddingBlockEnd: theme.spacing(1.5),
...(ownerState.textColor === 'secondary'
? {
color: 'var(--mui-palette-secondary-main)',
borderBlockEnd: '2px solid var(--mui-palette-secondary-lightOpacity)'
}
: {
color: 'var(--mui-palette-primary-main)',
borderBlockEnd: '2px solid var(--mui-palette-primary-lightOpacity)'
})
}
: {
paddingInlineEnd: theme.spacing(4.5),
...(ownerState.textColor === 'secondary'
? {
color: 'var(--mui-palette-secondary-main)',
borderInlineEnd: '2px solid var(--mui-palette-secondary-mainOpacity)'
}
: {
color: 'var(--mui-palette-primary-main)',
borderInlineEnd: '2px solid var(--mui-palette-primary-mainOpacity)'
})
}),
'& .MuiTabScrollButton-root': {
borderRadius: 'var(--mui-shape-borderRadius)'
}
},
'& ~ .MuiTabPanel-root': {
...(ownerState.orientation === 'horizontal'
? {
paddingBlockStart: theme.spacing(6)
}
: {
paddingInlineStart: theme.spacing(6)
})
}
}),
vertical: {
minWidth: 131,
'& .MuiTab-root': {
minWidth: 130
}
}
}
},
MuiTab: {
defaultProps: {
disableRipple: true
},
styleOverrides: {
root: ({ theme, ownerState }) => ({
lineHeight: 1.4667,
padding: theme.spacing(2, 5),
minBlockSize: 38,
color: 'var(--mui-palette-text-primary)',
'& > .MuiTab-icon': {
fontSize: '1.125rem',
...(ownerState.iconPosition === 'top' && {
marginBlockEnd: theme.spacing(1.5)
}),
...(ownerState.iconPosition === 'bottom' && {
marginBlockStart: theme.spacing(1.5)
}),
...(ownerState.iconPosition === 'start' && {
marginInlineEnd: theme.spacing(1.5)
}),
...(ownerState.iconPosition === 'end' && {
marginInlineStart: theme.spacing(1.5)
})
}
})
}
},
MuiTabPanel: {
styleOverrides: {
root: {
padding: 0
}
}
}
}
export default tabs
+164
View File
@@ -0,0 +1,164 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const timeline: Theme['components'] = {
MuiTimeline: {
styleOverrides: {
root: {
padding: 0
}
}
},
MuiTimelineDot: {
styleOverrides: {
root: ({ theme }) => ({
margin: theme.spacing(3, 0),
boxShadow: 'none',
'&:has(> i), &:has(> svg)': {
padding: 6
},
'& > svg, & > i': {
fontSize: '1.25rem'
},
'&:has(svg)': {
width: 32,
height: 32,
alignItems: 'center',
justifyContent: 'center'
},
variants: [
{
props: { variant: 'outlined' },
style: {
padding: 5,
'& + .MuiTimelineConnector-root': {
backgroundColor: 'transparent',
borderInlineStart: '1px dashed var(--mui-palette-divider)'
},
'&:has(+ .MuiTimelineConnector-root)': {
marginBlock: '0.625rem'
}
}
},
{
props: { variant: 'filled', color: 'grey' },
style: {
boxShadow: '0 0 0 3px rgb(var(--mui-palette-action-activeChannel) / 0.04)'
}
},
{
props: { variant: 'filled', color: 'primary' },
style: {
boxShadow: '0 0 0 3px var(--mui-palette-primary-lightOpacity)'
}
},
{
props: { variant: 'filled', color: 'secondary' },
style: {
boxShadow: '0 0 0 3px var(--mui-palette-secondary-lightOpacity)'
}
},
{
props: { variant: 'filled', color: 'error' },
style: {
boxShadow: '0 0 0 3px var(--mui-palette-error-lightOpacity)'
}
},
{
props: { variant: 'filled', color: 'warning' },
style: {
boxShadow: '0 0 0 3px var(--mui-palette-warning-lightOpacity)'
}
},
{
props: { variant: 'filled', color: 'info' },
style: {
boxShadow: '0 0 0 3px var(--mui-palette-info-lightOpacity)'
}
},
{
props: { variant: 'filled', color: 'success' },
style: {
boxShadow: '0 0 0 3px var(--mui-palette-success-lightOpacity)'
}
},
{
props: { variant: 'tonal' },
style: {
border: 0,
'&:has(+ .MuiTimelineConnector-root)': {
marginBlock: '1rem'
}
}
},
{
props: { variant: 'tonal', color: 'grey' },
style: {
backgroundColor: 'var(--mui-palette-action-selected)',
color: 'var(--mui-palette-text-primary)'
}
},
{
props: { variant: 'tonal', color: 'primary' },
style: {
backgroundColor: 'var(--mui-palette-primary-lightOpacity)',
color: 'var(--mui-palette-primary-main)'
}
},
{
props: { variant: 'tonal', color: 'secondary' },
style: {
backgroundColor: 'var(--mui-palette-secondary-lightOpacity)',
color: 'var(--mui-palette-secondary-main)'
}
},
{
props: { variant: 'tonal', color: 'error' },
style: {
backgroundColor: 'var(--mui-palette-error-lightOpacity)',
color: 'var(--mui-palette-error-main)'
}
},
{
props: { variant: 'tonal', color: 'warning' },
style: {
backgroundColor: 'var(--mui-palette-warning-lightOpacity)',
color: 'var(--mui-palette-warning-main)'
}
},
{
props: { variant: 'tonal', color: 'info' },
style: {
backgroundColor: 'var(--mui-palette-info-lightOpacity)',
color: 'var(--mui-palette-info-main)'
}
},
{
props: { variant: 'tonal', color: 'success' },
style: {
backgroundColor: 'var(--mui-palette-success-lightOpacity)',
color: 'var(--mui-palette-success-main)'
}
}
]
})
}
},
MuiTimelineConnector: {
styleOverrides: {
root: {
width: 1,
backgroundColor: 'var(--mui-palette-divider)'
}
}
},
MuiTimelineContent: {
styleOverrides: {
root: {
paddingBottom: '1rem'
}
}
}
}
export default timeline
@@ -0,0 +1,34 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const toggleButton: Theme['components'] = {
MuiToggleButtonGroup: {
styleOverrides: {
root: ({ ownerState }) => ({
...(ownerState.size === 'small' && {
borderRadius: 'var(--mui-shape-customBorderRadius-sm)'
}),
...(ownerState.size === 'large' && {
borderRadius: 'var(--mui-shape-customBorderRadius-lg)'
})
})
}
},
MuiToggleButton: {
styleOverrides: {
root: {
'&:not(.Mui-selected):not(.Mui-disabled)': {
color: 'var(--mui-palette-text-secondary)'
}
},
sizeSmall: {
borderRadius: 'var(--mui-shape-customBorderRadius-sm)'
},
sizeLarge: {
borderRadius: 'var(--mui-shape-customBorderRadius-lg)'
}
}
}
}
export default toggleButton
+33
View File
@@ -0,0 +1,33 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const tooltip: Theme['components'] = {
MuiTooltip: {
styleOverrides: {
tooltip: ({ theme }) => ({
borderRadius: 'var(--mui-shape-customBorderRadius-sm)',
fontSize: theme.typography.subtitle2.fontSize,
lineHeight: 1.539,
color: 'var(--mui-palette-customColors-tooltipText)',
paddingInline: theme.spacing(3),
paddingBlock: 5
}),
popper: {
'&[data-popper-placement*="bottom"] .MuiTooltip-tooltip': {
marginTop: '6px !important'
},
'&[data-popper-placement*="top"] .MuiTooltip-tooltip': {
marginBottom: '6px !important'
},
'&[data-popper-placement*="left"] .MuiTooltip-tooltip': {
marginRight: '6px !important'
},
'&[data-popper-placement*="right"] .MuiTooltip-tooltip': {
marginLeft: '6px !important'
}
}
}
}
}
export default tooltip
+70
View File
@@ -0,0 +1,70 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const typography: Theme['components'] = {
MuiTypography: {
styleOverrides: {
root: {
variants: [
{
props: { variant: 'h1' },
style: { color: 'var(--mui-palette-text-primary)' }
},
{
props: { variant: 'h2' },
style: { color: 'var(--mui-palette-text-primary)' }
},
{
props: { variant: 'h3' },
style: { color: 'var(--mui-palette-text-primary)' }
},
{
props: { variant: 'h4' },
style: { color: 'var(--mui-palette-text-primary)' }
},
{
props: { variant: 'h5' },
style: { color: 'var(--mui-palette-text-primary)' }
},
{
props: { variant: 'h6' },
style: { color: 'var(--mui-palette-text-primary)' }
},
{
props: { variant: 'subtitle1' },
style: { color: 'rgb(var(--mui-palette-text-primaryChannel) / 0.55)' }
},
{
props: { variant: 'subtitle2' },
style: { color: 'rgb(var(--mui-palette-text-primaryChannel) / 0.55)' }
},
{
props: { variant: 'body1' },
style: { color: 'var(--mui-palette-text-secondary)' }
},
{
props: { variant: 'body2' },
style: { color: 'var(--mui-palette-text-secondary)' }
},
{
props: { variant: 'button' },
style: { color: 'var(--mui-palette-text-primary)' }
},
{
props: { variant: 'caption' },
style: { color: 'var(--mui-palette-text-disabled)' }
},
{
props: { variant: 'overline' },
style: { color: 'var(--mui-palette-text-primary)' }
}
]
},
gutterBottom: ({ theme }) => ({
marginBottom: theme.spacing(2)
})
}
}
}
export default typography
+39
View File
@@ -0,0 +1,39 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Type Imports
import type { SystemMode } from '@core/types'
const shadows = (mode: SystemMode): Theme['shadows'] => {
const color = `var(--mui-mainColorChannels-${mode}Shadow)`
return [
'none',
`0px 2px 1px -1px rgb(${color} / 0.2),0px 1px 1px 0px rgb(${color} / 0.14),0px 1px 3px 0px rgb(${color} / 0.12)`,
`0px 3px 1px -2px rgb(${color} / 0.2),0px 2px 2px 0px rgb(${color} / 0.14),0px 1px 5px 0px rgb(${color} / 0.12)`,
`0px 3px 3px -2px rgb(${color} / 0.2),0px 3px 4px 0px rgb(${color} / 0.14),0px 1px 8px 0px rgb(${color} / 0.12)`,
`0px 2px 4px -1px rgb(${color} / 0.2),0px 4px 5px 0px rgb(${color} / 0.14),0px 1px 10px 0px rgb(${color} / 0.12)`,
`0px 3px 5px -1px rgb(${color} / 0.2),0px 5px 8px 0px rgb(${color} / 0.14),0px 1px 14px 0px rgb(${color} / 0.12)`,
`0px 3px 5px -1px rgb(${color} / 0.2),0px 6px 10px 0px rgb(${color} / 0.14),0px 1px 18px 0px rgb(${color} / 0.12)`,
`0px 4px 5px -2px rgb(${color} / 0.2),0px 7px 10px 1px rgb(${color} / 0.14),0px 2px 16px 1px rgb(${color} / 0.12)`,
`0px 5px 5px -3px rgb(${color} / 0.2),0px 8px 10px 1px rgb(${color} / 0.14),0px 3px 14px 2px rgb(${color} / 0.12)`,
`0px 5px 6px -3px rgb(${color} / 0.2),0px 9px 12px 1px rgb(${color} / 0.14),0px 3px 16px 2px rgb(${color} / 0.12)`,
`0px 6px 6px -3px rgb(${color} / 0.2),0px 10px 14px 1px rgb(${color} / 0.14),0px 4px 18px 3px rgb(${color} / 0.12)`,
`0px 6px 7px -4px rgb(${color} / 0.2),0px 11px 15px 1px rgb(${color} / 0.14),0px 4px 20px 3px rgb(${color} / 0.12)`,
`0px 7px 8px -4px rgb(${color} / 0.2),0px 12px 17px 2px rgb(${color} / 0.14),0px 5px 22px 4px rgb(${color} / 0.12)`,
`0px 7px 8px -4px rgb(${color} / 0.2),0px 13px 19px 2px rgb(${color} / 0.14),0px 5px 24px 4px rgb(${color} / 0.12)`,
`0px 7px 9px -4px rgb(${color} / 0.2),0px 14px 21px 2px rgb(${color} / 0.14),0px 5px 26px 4px rgb(${color} / 0.12)`,
`0px 8px 9px -5px rgb(${color} / 0.2),0px 15px 22px 2px rgb(${color} / 0.14),0px 6px 28px 5px rgb(${color} / 0.12)`,
`0px 8px 10px -5px rgb(${color} / 0.2),0px 16px 24px 2px rgb(${color} / 0.14),0px 6px 30px 5px rgb(${color} / 0.12)`,
`0px 8px 11px -5px rgb(${color} / 0.2),0px 17px 26px 2px rgb(${color} / 0.14),0px 6px 32px 5px rgb(${color} / 0.12)`,
`0px 9px 11px -5px rgb(${color} / 0.2),0px 18px 28px 2px rgb(${color} / 0.14),0px 7px 34px 6px rgb(${color} / 0.12)`,
`0px 9px 12px -6px rgb(${color} / 0.2),0px 19px 29px 2px rgb(${color} / 0.14),0px 7px 36px 6px rgb(${color} / 0.12)`,
`0px 10px 13px -6px rgb(${color} / 0.2),0px 20px 31px 3px rgb(${color} / 0.14),0px 8px 38px 7px rgb(${color} / 0.12)`,
`0px 10px 13px -6px rgb(${color} / 0.2),0px 21px 33px 3px rgb(${color} / 0.14),0px 8px 40px 7px rgb(${color} / 0.12)`,
`0px 10px 14px -6px rgb(${color} / 0.2),0px 22px 35px 3px rgb(${color} / 0.14),0px 8px 42px 7px rgb(${color} / 0.12)`,
`0px 11px 14px -7px rgb(${color} / 0.2),0px 23px 36px 3px rgb(${color} / 0.14),0px 9px 44px 8px rgb(${color} / 0.12)`,
`0px 11px 15px -7px rgb(${color} / 0.2),0px 24px 38px 3px rgb(${color} / 0.14),0px 9px 46px 8px rgb(${color} / 0.12)`
]
}
export default shadows
+5
View File
@@ -0,0 +1,5 @@
const spacing = {
spacing: (factor: number) => `${0.25 * factor}rem`
}
export default spacing
+88
View File
@@ -0,0 +1,88 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
const typography = (fontFamily: string): Theme['typography'] =>
({
fontFamily:
typeof fontFamily === 'undefined' || fontFamily === ''
? [
'"Public Sans"',
'sans-serif',
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"'
].join(',')
: fontFamily,
fontSize: 13.125,
h1: {
fontSize: '2.875rem',
fontWeight: 500,
lineHeight: 1.47826
},
h2: {
fontSize: '2.375rem',
fontWeight: 500,
lineHeight: 1.47368421
},
h3: {
fontSize: '1.75rem',
fontWeight: 500,
lineHeight: 1.5
},
h4: {
fontSize: '1.5rem',
fontWeight: 500,
lineHeight: 1.58334
},
h5: {
fontSize: '1.125rem',
fontWeight: 500,
lineHeight: 1.5556
},
h6: {
fontSize: '0.9375rem',
fontWeight: 500,
lineHeight: 1.46667
},
subtitle1: {
fontSize: '0.9375rem',
lineHeight: 1.46667
},
subtitle2: {
fontSize: '0.8125rem',
fontWeight: 400,
lineHeight: 1.53846154
},
body1: {
fontSize: '0.9375rem',
lineHeight: 1.46667
},
body2: {
fontSize: '0.8125rem',
lineHeight: 1.53846154
},
button: {
fontSize: '0.9375rem',
lineHeight: 1.46667,
textTransform: 'none'
},
caption: {
fontSize: '0.8125rem',
lineHeight: 1.38462,
letterSpacing: '0.4px'
},
overline: {
fontSize: '0.75rem',
lineHeight: 1.16667,
letterSpacing: '0.8px'
}
}) as Theme['typography']
export default typography
+22
View File
@@ -0,0 +1,22 @@
// React Imports
import type { ReactNode } from 'react'
export type Layout = 'vertical' | 'collapsed' | 'horizontal'
export type Skin = 'default' | 'bordered'
export type Mode = 'system' | 'light' | 'dark'
export type SystemMode = 'light' | 'dark'
export type Direction = 'ltr' | 'rtl'
export type LayoutComponentWidth = 'compact' | 'wide'
export type LayoutComponentPosition = 'fixed' | 'static'
export type ChildrenType = {
children: ReactNode
}
export type ThemeColor = 'primary' | 'secondary' | 'error' | 'warning' | 'info' | 'success'
+48
View File
@@ -0,0 +1,48 @@
// Next Imports
import { cookies } from 'next/headers'
// Type Imports
import type { Settings } from '@core/contexts/settingsContext'
import type { SystemMode } from '@core/types'
// Config Imports
import themeConfig from '@configs/themeConfig'
export const getSettingsFromCookie = async (): Promise<Settings> => {
const cookieStore = await cookies()
const cookieName = themeConfig.settingsCookieName
return JSON.parse(cookieStore.get(cookieName)?.value || '{}')
}
export const getMode = async () => {
const settingsCookie = await getSettingsFromCookie()
// Get mode from cookie or fallback to theme config
const _mode = settingsCookie.mode || themeConfig.mode
return _mode
}
export const getSystemMode = async (): Promise<SystemMode> => {
const cookieStore = await cookies()
const mode = await getMode()
const colorPrefCookie = (cookieStore.get('colorPref')?.value || 'light') as SystemMode
return (mode === 'system' ? colorPrefCookie : mode) || 'light'
}
export const getServerMode = async () => {
const mode = await getMode()
const systemMode = await getSystemMode()
return mode === 'system' ? systemMode : mode
}
export const getSkin = async () => {
const settingsCookie = await getSettingsFromCookie()
return settingsCookie.skin || 'default'
}
+36
View File
@@ -0,0 +1,36 @@
'use client'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { ChildrenType, SystemMode } from '@core/types'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
import useLayoutInit from '@core/hooks/useLayoutInit'
// Util Imports
import { blankLayoutClasses } from './utils/layoutClasses'
type Props = ChildrenType & {
systemMode: SystemMode
}
const BlankLayout = (props: Props) => {
// Props
const { children, systemMode } = props
// Hooks
const { settings } = useSettings()
useLayoutInit(systemMode)
return (
<div className={classnames(blankLayoutClasses.root, 'is-full bs-full')} data-skin={settings.skin}>
{children}
</div>
)
}
export default BlankLayout
+44
View File
@@ -0,0 +1,44 @@
// React Imports
import type { ReactNode } from 'react'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { ChildrenType } from '@core/types'
// Context Imports
import { HorizontalNavProvider } from '@menu/contexts/horizontalNavContext'
// Component Imports
import LayoutContent from './components/horizontal/LayoutContent'
// Util Imports
import { horizontalLayoutClasses } from './utils/layoutClasses'
// Styled Component Imports
import StyledContentWrapper from './styles/horizontal/StyledContentWrapper'
type HorizontalLayoutProps = ChildrenType & {
header?: ReactNode
footer?: ReactNode
}
const HorizontalLayout = (props: HorizontalLayoutProps) => {
// Props
const { header, footer, children } = props
return (
<div className={classnames(horizontalLayoutClasses.root, 'flex flex-auto')}>
<HorizontalNavProvider>
<StyledContentWrapper className={classnames(horizontalLayoutClasses.contentWrapper, 'flex flex-col is-full')}>
{header || null}
<LayoutContent>{children}</LayoutContent>
{footer || null}
</StyledContentWrapper>
</HorizontalNavProvider>
</div>
)
}
export default HorizontalLayout
+36
View File
@@ -0,0 +1,36 @@
'use client'
// React Imports
import type { ReactElement } from 'react'
// Type Imports
import type { SystemMode } from '@core/types'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
import useLayoutInit from '@core/hooks/useLayoutInit'
type LayoutWrapperProps = {
systemMode: SystemMode
verticalLayout: ReactElement
horizontalLayout: ReactElement
}
const LayoutWrapper = (props: LayoutWrapperProps) => {
// Props
const { systemMode, verticalLayout, horizontalLayout } = props
// Hooks
const { settings } = useSettings()
useLayoutInit(systemMode)
// Return the layout based on the layout context
return (
<div className='flex flex-col flex-auto' data-skin={settings.skin}>
{settings.layout === 'horizontal' ? horizontalLayout : verticalLayout}
</div>
)
}
export default LayoutWrapper
+44
View File
@@ -0,0 +1,44 @@
// React Imports
import type { ReactNode } from 'react'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { ChildrenType } from '@core/types'
// Component Imports
import LayoutContent from './components/vertical/LayoutContent'
// Util Imports
import { verticalLayoutClasses } from './utils/layoutClasses'
// Styled Component Imports
import StyledContentWrapper from './styles/vertical/StyledContentWrapper'
type VerticalLayoutProps = ChildrenType & {
navigation?: ReactNode
navbar?: ReactNode
footer?: ReactNode
}
const VerticalLayout = (props: VerticalLayoutProps) => {
// Props
const { navbar, footer, navigation, children } = props
return (
<div className={classnames(verticalLayoutClasses.root, 'flex flex-auto')}>
{navigation || null}
<StyledContentWrapper
className={classnames(verticalLayoutClasses.contentWrapper, 'flex flex-col min-is-0 is-full')}
>
{navbar || null}
{/* Content */}
<LayoutContent>{children}</LayoutContent>
{footer || null}
</StyledContentWrapper>
</div>
)
}
export default VerticalLayout
@@ -0,0 +1,56 @@
'use client'
// Third-party Imports
import classnames from 'classnames'
import type { CSSObject } from '@emotion/styled'
// Type Imports
import type { ChildrenType } from '@core/types'
// Config Imports
import themeConfig from '@configs/themeConfig'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
// Util Imports
import { horizontalLayoutClasses } from '@layouts/utils/layoutClasses'
// Styled Component Imports
import StyledFooter from '@layouts/styles/horizontal/StyledFooter'
type Props = ChildrenType & {
overrideStyles?: CSSObject
}
const Footer = (props: Props) => {
// Props
const { children, overrideStyles } = props
// Hooks
const { settings } = useSettings()
// Vars
const { footerContentWidth } = settings
const footerStatic = themeConfig.footer.type === 'static'
const footerFixed = themeConfig.footer.type === 'fixed'
const footerContentCompact = footerContentWidth === 'compact'
const footerContentWide = footerContentWidth === 'wide'
return (
<StyledFooter
overrideStyles={overrideStyles}
className={classnames(horizontalLayoutClasses.footer, {
[horizontalLayoutClasses.footerStatic]: footerStatic,
[horizontalLayoutClasses.footerFixed]: footerFixed,
[horizontalLayoutClasses.footerContentCompact]: footerContentCompact,
[horizontalLayoutClasses.footerContentWide]: footerContentWide
})}
>
<div className={horizontalLayoutClasses.footerContentWrapper}>{children}</div>
</StyledFooter>
)
}
export default Footer
@@ -0,0 +1,63 @@
'use client'
// MUI Imports
import { useTheme } from '@mui/material/styles'
// Third-party Imports
import classnames from 'classnames'
import type { CSSObject } from '@emotion/styled'
// Type Imports
import type { ChildrenType } from '@core/types'
// Config Imports
import themeConfig from '@configs/themeConfig'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
// Util Imports
import { horizontalLayoutClasses } from '@layouts/utils/layoutClasses'
// Styled Component Imports
import StyledHeader from '@layouts/styles/horizontal/StyledHeader'
type Props = ChildrenType & {
overrideStyles?: CSSObject
}
const Header = (props: Props) => {
// Props
const { children, overrideStyles } = props
// Hooks
const { settings } = useSettings()
const theme = useTheme()
// Vars
const { navbarContentWidth } = settings
const headerFixed = themeConfig.navbar.type === 'fixed'
const headerStatic = themeConfig.navbar.type === 'static'
const headerBlur = themeConfig.navbar.blur === true
const headerContentCompact = navbarContentWidth === 'compact'
const headerContentWide = navbarContentWidth === 'wide'
return (
<StyledHeader
theme={theme}
overrideStyles={overrideStyles}
className={classnames(horizontalLayoutClasses.header, {
[horizontalLayoutClasses.headerFixed]: headerFixed,
[horizontalLayoutClasses.headerStatic]: headerStatic,
[horizontalLayoutClasses.headerBlur]: headerBlur,
[horizontalLayoutClasses.headerContentCompact]: headerContentCompact,
[horizontalLayoutClasses.headerContentWide]: headerContentWide
})}
>
{children}
</StyledHeader>
)
}
export default Header
@@ -0,0 +1,43 @@
'use client'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { ChildrenType } from '@core/types'
// Config Imports
import themeConfig from '@configs/themeConfig'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
// Util Imports
import { horizontalLayoutClasses } from '@layouts/utils/layoutClasses'
// Styled Component Imports
import StyledMain from '@layouts/styles/shared/StyledMain'
const LayoutContent = ({ children }: ChildrenType) => {
// Hooks
const { settings } = useSettings()
// Vars
const contentCompact = settings.contentWidth === 'compact'
const contentWide = settings.contentWidth === 'wide'
return (
<StyledMain
isContentCompact={contentCompact}
className={classnames(horizontalLayoutClasses.content, 'flex-auto', {
[`${horizontalLayoutClasses.contentCompact} is-full`]: contentCompact,
[horizontalLayoutClasses.contentWide]: contentWide
})}
style={{ padding: themeConfig.layoutPadding }}
>
{children}
</StyledMain>
)
}
export default LayoutContent
@@ -0,0 +1,18 @@
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { ChildrenType } from '@core/types'
// Util Imports
import { horizontalLayoutClasses } from '@layouts/utils/layoutClasses'
const Navbar = ({ children }: ChildrenType) => {
return (
<div className={classnames(horizontalLayoutClasses.navbar, 'flex items-center justify-between is-full')}>
{children}
</div>
)
}
export default Navbar
@@ -0,0 +1,60 @@
'use client'
// Third-party Imports
import classnames from 'classnames'
import type { CSSObject } from '@emotion/styled'
// Type Imports
import type { ChildrenType } from '@core/types'
// Config Imports
import themeConfig from '@configs/themeConfig'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
// Util Imports
import { verticalLayoutClasses } from '@layouts/utils/layoutClasses'
// Styled Component Imports
import StyledFooter from '@layouts/styles/vertical/StyledFooter'
type Props = ChildrenType & {
overrideStyles?: CSSObject
}
const Footer = (props: Props) => {
// Props
const { children, overrideStyles } = props
// Hooks
const { settings } = useSettings()
// Vars
const { footerContentWidth } = settings
const footerDetached = themeConfig.footer.detached === true
const footerAttached = themeConfig.footer.detached === false
const footerStatic = themeConfig.footer.type === 'static'
const footerFixed = themeConfig.footer.type === 'fixed'
const footerContentCompact = footerContentWidth === 'compact'
const footerContentWide = footerContentWidth === 'wide'
return (
<StyledFooter
overrideStyles={overrideStyles}
className={classnames(verticalLayoutClasses.footer, 'is-full', {
[verticalLayoutClasses.footerDetached]: footerDetached,
[verticalLayoutClasses.footerAttached]: footerAttached,
[verticalLayoutClasses.footerStatic]: footerStatic,
[verticalLayoutClasses.footerFixed]: footerFixed,
[verticalLayoutClasses.footerContentCompact]: footerContentCompact,
[verticalLayoutClasses.footerContentWide]: footerContentWide
})}
>
<div className={verticalLayoutClasses.footerContentWrapper}>{children}</div>
</StyledFooter>
)
}
export default Footer
@@ -0,0 +1,39 @@
'use client'
// Third-party Imports
import classnames from 'classnames'
// Type Imports
import type { ChildrenType } from '@core/types'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
// Util Imports
import { verticalLayoutClasses } from '@layouts/utils/layoutClasses'
// Styled Component Imports
import StyledMain from '@layouts/styles/shared/StyledMain'
const LayoutContent = ({ children }: ChildrenType) => {
// Hooks
const { settings } = useSettings()
// Vars
const contentCompact = settings.contentWidth === 'compact'
const contentWide = settings.contentWidth === 'wide'
return (
<StyledMain
isContentCompact={contentCompact}
className={classnames(verticalLayoutClasses.content, 'flex-auto', {
[`${verticalLayoutClasses.contentCompact} is-full`]: contentCompact,
[verticalLayoutClasses.contentWide]: contentWide
})}
>
{children}
</StyledMain>
)
}
export default LayoutContent
@@ -0,0 +1,76 @@
'use client'
// MUI Imports
import { useTheme } from '@mui/material/styles'
import useScrollTrigger from '@mui/material/useScrollTrigger'
// Third-party Imports
import classnames from 'classnames'
import type { CSSObject } from '@emotion/styled'
// Type Imports
import type { ChildrenType } from '@core/types'
// Config Imports
import themeConfig from '@configs/themeConfig'
// Hook Imports
import { useSettings } from '@core/hooks/useSettings'
// Util Imports
import { verticalLayoutClasses } from '@layouts/utils/layoutClasses'
// Styled Component Imports
import StyledHeader from '@layouts/styles/vertical/StyledHeader'
type Props = ChildrenType & {
overrideStyles?: CSSObject
}
const Navbar = (props: Props) => {
// Props
const { children, overrideStyles } = props
// Hooks
const { settings } = useSettings()
const theme = useTheme()
const trigger = useScrollTrigger({
threshold: 0,
disableHysteresis: true
})
// Vars
const { navbarContentWidth } = settings
const headerFixed = themeConfig.navbar.type === 'fixed'
const headerStatic = themeConfig.navbar.type === 'static'
const headerFloating = themeConfig.navbar.floating === true
const headerDetached = themeConfig.navbar.detached === true
const headerAttached = themeConfig.navbar.detached === false
const headerBlur = themeConfig.navbar.blur === true
const headerContentCompact = navbarContentWidth === 'compact'
const headerContentWide = navbarContentWidth === 'wide'
return (
<StyledHeader
theme={theme}
overrideStyles={overrideStyles}
className={classnames(verticalLayoutClasses.header, {
[verticalLayoutClasses.headerFixed]: headerFixed,
[verticalLayoutClasses.headerStatic]: headerStatic,
[verticalLayoutClasses.headerFloating]: headerFloating,
[verticalLayoutClasses.headerDetached]: !headerFloating && headerDetached,
[verticalLayoutClasses.headerAttached]: !headerFloating && headerAttached,
[verticalLayoutClasses.headerBlur]: headerBlur,
[verticalLayoutClasses.headerContentCompact]: headerContentCompact,
[verticalLayoutClasses.headerContentWide]: headerContentWide,
scrolled: trigger
})}
>
<div className={classnames(verticalLayoutClasses.navbar, 'flex bs-full')}>{children}</div>
</StyledHeader>
)
}
export default Navbar
@@ -0,0 +1,15 @@
'use client'
// Third-party Imports
import styled from '@emotion/styled'
// Util Imports
import { commonLayoutClasses, horizontalLayoutClasses } from '@layouts/utils/layoutClasses'
const StyledContentWrapper = styled.div`
&:has(.${horizontalLayoutClasses.content}>.${commonLayoutClasses.contentHeightFixed}) {
max-block-size: 100dvh;
}
`
export default StyledContentWrapper
@@ -0,0 +1,44 @@
// Third-party Imports
import styled from '@emotion/styled'
import type { CSSObject } from '@emotion/styled'
// Config Imports
import themeConfig from '@configs/themeConfig'
// Util Imports
import { horizontalLayoutClasses } from '@layouts/utils/layoutClasses'
type StyledFooterProps = {
overrideStyles?: CSSObject
}
const StyledFooter = styled.footer<StyledFooterProps>`
&.${horizontalLayoutClasses.footerFixed} {
position: sticky;
inset-block-end: 0;
z-index: var(--footer-z-index);
background-color: var(--mui-palette-background-paper);
box-shadow: 0 3px 12px 0px rgb(var(--mui-mainColorChannels-lightShadow) / 0.14);
[data-mui-color-scheme='dark'] & {
box-shadow: 0 3px 12px 0px rgb(var(--mui-mainColorChannels-darkShadow) / 0.14);
}
[data-skin='bordered'] & {
box-shadow: none;
border-block-start: 1px solid var(--border-color);
}
}
&.${horizontalLayoutClasses.footerContentCompact} .${horizontalLayoutClasses.footerContentWrapper} {
margin-inline: auto;
max-inline-size: ${themeConfig.compactContentWidth}px;
}
.${horizontalLayoutClasses.footerContentWrapper} {
padding-block: 16px;
padding-inline: ${themeConfig.layoutPadding}px;
}
${({ overrideStyles }) => overrideStyles}
`
export default StyledFooter
@@ -0,0 +1,57 @@
// MUI Imports
import type { Theme } from '@mui/material/styles'
// Third-party Imports
import styled from '@emotion/styled'
import type { CSSObject } from '@emotion/styled'
// Config Imports
import themeConfig from '@configs/themeConfig'
// Util Imports
import { horizontalLayoutClasses } from '@layouts/utils/layoutClasses'
type StyledHeaderProps = {
theme: Theme
overrideStyles?: CSSObject
}
const StyledHeader = styled.header<StyledHeaderProps>`
box-shadow: var(--mui-customShadows-sm);
[data-skin='bordered'] & {
box-shadow: none;
border-block-end: 1px solid var(--border-color);
}
&:not(.${horizontalLayoutClasses.headerBlur}) {
background-color: var(--mui-palette-background-paper);
}
&.${horizontalLayoutClasses.headerBlur} {
backdrop-filter: blur(6px);
background-color: rgb(var(--background-color-rgb) / 0.88);
}
&.${horizontalLayoutClasses.headerFixed} {
position: sticky;
inset-block-start: 0;
z-index: var(--header-z-index);
}
&.${horizontalLayoutClasses.headerContentCompact} .${horizontalLayoutClasses.navbar} {
margin-inline: auto;
max-inline-size: ${themeConfig.compactContentWidth}px;
}
.${horizontalLayoutClasses.navbar} {
position: relative;
min-block-size: var(--header-height);
padding-block: 8px;
padding-inline: ${themeConfig.layoutPadding}px;
}
${({ overrideStyles }) => overrideStyles}
`
export default StyledHeader
+29
View File
@@ -0,0 +1,29 @@
// Third-party Imports
import styled from '@emotion/styled'
// Config Imports
import themeConfig from '@configs/themeConfig'
// Util Imports
import { commonLayoutClasses } from '@layouts/utils/layoutClasses'
type StyledMainProps = {
isContentCompact: boolean
}
const StyledMain = styled.main<StyledMainProps>`
padding: ${themeConfig.layoutPadding}px;
${({ isContentCompact }) =>
isContentCompact &&
`
margin-inline: auto;
max-inline-size: ${themeConfig.compactContentWidth}px;
`}
&:has(.${commonLayoutClasses.contentHeightFixed}) {
display: flex;
overflow: hidden;
}
`
export default StyledMain
@@ -0,0 +1,15 @@
'use client'
// Third-party Imports
import styled from '@emotion/styled'
// Util Imports
import { commonLayoutClasses, verticalLayoutClasses } from '@layouts/utils/layoutClasses'
const StyledContentWrapper = styled.div`
&:has(.${verticalLayoutClasses.content}>.${commonLayoutClasses.contentHeightFixed}) {
max-block-size: 100dvh;
}
`
export default StyledContentWrapper

Some files were not shown because too many files have changed in this diff Show More