initial commit
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,80 @@
|
||||
// Third-party Imports
|
||||
import styled from '@emotion/styled'
|
||||
import type { CSSObject } from '@emotion/styled'
|
||||
|
||||
// Config Imports
|
||||
import themeConfig from '@configs/themeConfig'
|
||||
|
||||
// Util Imports
|
||||
import { verticalLayoutClasses } from '@layouts/utils/layoutClasses'
|
||||
|
||||
type StyledFooterProps = {
|
||||
overrideStyles?: CSSObject
|
||||
}
|
||||
|
||||
const StyledFooter = styled.footer<StyledFooterProps>`
|
||||
&.${verticalLayoutClasses.footerContentCompact} {
|
||||
&.${verticalLayoutClasses.footerDetached} {
|
||||
margin-inline: auto;
|
||||
max-inline-size: ${themeConfig.compactContentWidth}px;
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.footerAttached} .${verticalLayoutClasses.footerContentWrapper} {
|
||||
margin-inline: auto;
|
||||
max-inline-size: ${themeConfig.compactContentWidth}px;
|
||||
}
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.footerFixed} {
|
||||
position: sticky;
|
||||
inset-block-end: 0;
|
||||
z-index: var(--footer-z-index);
|
||||
|
||||
&.${verticalLayoutClasses.footerAttached},
|
||||
&.${verticalLayoutClasses.footerDetached}
|
||||
.${verticalLayoutClasses.footerContentWrapper} {
|
||||
background-color: var(--mui-palette-background-paper);
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.footerDetached} {
|
||||
pointer-events: none;
|
||||
padding-inline: ${themeConfig.layoutPadding}px;
|
||||
|
||||
& .${verticalLayoutClasses.footerContentWrapper} {
|
||||
pointer-events: auto;
|
||||
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);
|
||||
}
|
||||
border-start-start-radius: var(--border-radius);
|
||||
border-start-end-radius: var(--border-radius);
|
||||
|
||||
[data-skin='bordered'] & {
|
||||
box-shadow: none;
|
||||
border-inline: 1px solid var(--border-color);
|
||||
border-block-start: 1px solid var(--border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.footerAttached} {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& .${verticalLayoutClasses.footerContentWrapper} {
|
||||
padding-block: 16px;
|
||||
padding-inline: ${themeConfig.layoutPadding}px;
|
||||
}
|
||||
|
||||
${({ overrideStyles }) => overrideStyles}
|
||||
`
|
||||
|
||||
export default StyledFooter
|
||||
@@ -0,0 +1,178 @@
|
||||
// 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 { verticalLayoutClasses } from '@layouts/utils/layoutClasses'
|
||||
|
||||
type StyledHeaderProps = {
|
||||
theme: Theme
|
||||
overrideStyles?: CSSObject
|
||||
}
|
||||
|
||||
const StyledHeader = styled.header<StyledHeaderProps>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
inline-size: 100%;
|
||||
flex-shrink: 0;
|
||||
min-block-size: var(--header-height);
|
||||
|
||||
&.${verticalLayoutClasses.headerContentCompact} {
|
||||
&.${verticalLayoutClasses.headerFloating}
|
||||
.${verticalLayoutClasses.navbar},
|
||||
&.${verticalLayoutClasses.headerDetached}
|
||||
.${verticalLayoutClasses.navbar},
|
||||
&.${verticalLayoutClasses.headerAttached}
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerFloating}
|
||||
.${verticalLayoutClasses.navbar},
|
||||
&.${verticalLayoutClasses.headerFixed}.${verticalLayoutClasses.headerDetached}
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
max-inline-size: calc(${themeConfig.compactContentWidth}px - ${2 * themeConfig.layoutPadding}px);
|
||||
}
|
||||
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
max-inline-size: ${themeConfig.compactContentWidth}px;
|
||||
}
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerFixed} {
|
||||
position: sticky;
|
||||
inset-block-start: 0;
|
||||
z-index: var(--header-z-index);
|
||||
|
||||
&:not(.${verticalLayoutClasses.headerBlur}).scrolled.${verticalLayoutClasses.headerAttached},
|
||||
&:not(.${verticalLayoutClasses.headerBlur}).scrolled.${verticalLayoutClasses.headerDetached}
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
background-color: var(--mui-palette-background-paper);
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerDetached}.scrolled .${verticalLayoutClasses.navbar} {
|
||||
box-shadow: var(--mui-customShadows-sm);
|
||||
|
||||
[data-skin='bordered'] & {
|
||||
box-shadow: none;
|
||||
border-inline: 1px solid var(--border-color);
|
||||
border-block-end: 1px solid var(--border-color);
|
||||
}
|
||||
}
|
||||
&.${verticalLayoutClasses.headerDetached} .${verticalLayoutClasses.navbar} {
|
||||
border-end-start-radius: var(--border-radius);
|
||||
border-end-end-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerDetached}, &.${verticalLayoutClasses.headerFloating} {
|
||||
pointer-events: none;
|
||||
|
||||
& .${verticalLayoutClasses.navbar} {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerBlur} {
|
||||
&.scrolled.${verticalLayoutClasses.headerAttached},
|
||||
&.scrolled.${verticalLayoutClasses.headerDetached}
|
||||
.${verticalLayoutClasses.navbar},
|
||||
&.${verticalLayoutClasses.headerFloating}
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
backdrop-filter: blur(6px);
|
||||
background-color: rgb(var(--background-color-rgb) / 0.88);
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerFloating} {
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
inset-block-start: 0;
|
||||
inset-inline: 0;
|
||||
block-size: 100%;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgb(var(--mui-palette-background-defaultChannel) / 0.7) 44%,
|
||||
rgb(var(--mui-palette-background-defaultChannel) / 0.43) 73%,
|
||||
rgb(var(--mui-palette-background-defaultChannel) / 0)
|
||||
);
|
||||
backdrop-filter: blur(10px);
|
||||
mask: linear-gradient(
|
||||
var(--mui-palette-background-default),
|
||||
var(--mui-palette-background-default) 18%,
|
||||
transparent 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerAttached}.scrolled {
|
||||
box-shadow: var(--mui-customShadows-sm);
|
||||
|
||||
[data-skin='bordered'] & {
|
||||
box-shadow: none;
|
||||
border-block-end: 1px solid var(--border-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerFloating}
|
||||
.${verticalLayoutClasses.navbar},
|
||||
&:not(.${verticalLayoutClasses.headerFloating}).${verticalLayoutClasses.headerAttached},
|
||||
&:not(.${verticalLayoutClasses.headerFloating}).${verticalLayoutClasses.headerDetached}
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
${({ theme }) =>
|
||||
`transition: ${theme.transitions.create(['box-shadow', 'border-width', 'padding-inline', 'backdrop-filter'])}`};
|
||||
}
|
||||
&:not(.${verticalLayoutClasses.headerFloating}).${verticalLayoutClasses.headerAttached}
|
||||
.${verticalLayoutClasses.navbar},
|
||||
&:not(.${verticalLayoutClasses.headerFloating}).${verticalLayoutClasses.headerDetached}.scrolled
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
padding-inline: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerFloating} {
|
||||
padding-block-start: 16px;
|
||||
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
background-color: var(--mui-palette-background-paper);
|
||||
border-radius: var(--border-radius);
|
||||
padding-inline: 16px;
|
||||
box-shadow: var(--mui-customShadows-sm);
|
||||
|
||||
[data-skin='bordered'] & {
|
||||
box-shadow: none;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.${verticalLayoutClasses.headerFloating}
|
||||
.${verticalLayoutClasses.navbar},
|
||||
&.${verticalLayoutClasses.headerFixed}.${verticalLayoutClasses.headerDetached}
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
inline-size: calc(100% - ${2 * themeConfig.layoutPadding}px);
|
||||
}
|
||||
|
||||
&:not(.${verticalLayoutClasses.headerFloating}).${verticalLayoutClasses.headerStatic}
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
padding-inline: 16px;
|
||||
}
|
||||
|
||||
.${verticalLayoutClasses.navbar} {
|
||||
position: relative;
|
||||
padding-block: 8px;
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
${({ overrideStyles }) => overrideStyles}
|
||||
`
|
||||
|
||||
export default StyledHeader
|
||||
@@ -0,0 +1,73 @@
|
||||
// Classes for vertical layout
|
||||
export const verticalLayoutClasses = {
|
||||
root: 'ts-vertical-layout',
|
||||
contentWrapper: 'ts-vertical-layout-content-wrapper',
|
||||
header: 'ts-vertical-layout-header',
|
||||
headerFixed: 'ts-vertical-layout-header-fixed',
|
||||
headerStatic: 'ts-vertical-layout-header-static',
|
||||
headerFloating: 'ts-vertical-layout-header-floating',
|
||||
headerDetached: 'ts-vertical-layout-header-detached',
|
||||
headerAttached: 'ts-vertical-layout-header-attached',
|
||||
headerContentCompact: 'ts-vertical-layout-header-content-compact',
|
||||
headerContentWide: 'ts-vertical-layout-header-content-wide',
|
||||
headerBlur: 'ts-vertical-layout-header-blur',
|
||||
navbar: 'ts-vertical-layout-navbar',
|
||||
navbarContent: 'ts-vertical-layout-navbar-content',
|
||||
content: 'ts-vertical-layout-content',
|
||||
contentCompact: 'ts-vertical-layout-content-compact',
|
||||
contentWide: 'ts-vertical-layout-content-wide',
|
||||
footer: 'ts-vertical-layout-footer',
|
||||
footerStatic: 'ts-vertical-layout-footer-static',
|
||||
footerFixed: 'ts-vertical-layout-footer-fixed',
|
||||
footerDetached: 'ts-vertical-layout-footer-detached',
|
||||
footerAttached: 'ts-vertical-layout-footer-attached',
|
||||
footerContentWrapper: 'ts-vertical-layout-footer-content-wrapper',
|
||||
footerContent: 'ts-vertical-layout-footer-content',
|
||||
footerContentCompact: 'ts-vertical-layout-footer-content-compact',
|
||||
footerContentWide: 'ts-vertical-layout-footer-content-wide'
|
||||
}
|
||||
|
||||
// Classes for horizontal layout
|
||||
export const horizontalLayoutClasses = {
|
||||
root: 'ts-horizontal-layout',
|
||||
contentWrapper: 'ts-horizontal-layout-content-wrapper',
|
||||
header: 'ts-horizontal-layout-header',
|
||||
headerFixed: 'ts-horizontal-layout-header-fixed',
|
||||
headerStatic: 'ts-horizontal-layout-header-static',
|
||||
headerContentCompact: 'ts-horizontal-layout-header-content-compact',
|
||||
headerContentWide: 'ts-horizontal-layout-header-content-wide',
|
||||
headerBlur: 'ts-horizontal-layout-header-blur',
|
||||
navbar: 'ts-horizontal-layout-navbar',
|
||||
navbarContent: 'ts-horizontal-layout-navbar-content',
|
||||
navigation: 'ts-horizontal-layout-navigation',
|
||||
navigationContentWrapper: 'ts-horizontal-layout-navigation-content-wrapper',
|
||||
content: 'ts-horizontal-layout-content',
|
||||
contentCompact: 'ts-horizontal-layout-content-compact',
|
||||
contentWide: 'ts-horizontal-layout-content-wide',
|
||||
footer: 'ts-horizontal-layout-footer',
|
||||
footerStatic: 'ts-horizontal-layout-footer-static',
|
||||
footerFixed: 'ts-horizontal-layout-footer-fixed',
|
||||
footerContentWrapper: 'ts-horizontal-layout-footer-content-wrapper',
|
||||
footerContent: 'ts-horizontal-layout-footer-content',
|
||||
footerContentCompact: 'ts-horizontal-layout-footer-content-compact',
|
||||
footerContentWide: 'ts-horizontal-layout-footer-content-wide'
|
||||
}
|
||||
|
||||
// Classes for blank layout
|
||||
export const blankLayoutClasses = {
|
||||
root: 'ts-blank-layout'
|
||||
}
|
||||
|
||||
// Classes for front layout
|
||||
export const frontLayoutClasses = {
|
||||
root: 'ts-front-layout-root',
|
||||
header: 'ts-front-layout-header',
|
||||
navbar: 'ts-front-layout-navbar',
|
||||
navbarContent: 'ts-front-layout-navbar-content',
|
||||
footer: 'ts-front-layout-footer'
|
||||
}
|
||||
|
||||
// Common classes for Vertical and Horizontal layouts
|
||||
export const commonLayoutClasses = {
|
||||
contentHeightFixed: 'ts-layout-content-height-fixed'
|
||||
}
|
||||
Reference in New Issue
Block a user