205 lines
6.7 KiB
JavaScript
205 lines
6.7 KiB
JavaScript
import { AppContentLayoutNav, NavbarType } from '../enums'
|
||
import { config } from '@layouts/config'
|
||
import { injectionKeyIsVerticalNavHovered } from '@layouts'
|
||
|
||
export const useLayouts = () => {
|
||
const navbarType = computed({
|
||
get() {
|
||
return config.navbar.type.value
|
||
},
|
||
set(value) {
|
||
config.navbar.type.value = value
|
||
},
|
||
})
|
||
|
||
const isNavbarBlurEnabled = computed({
|
||
get() {
|
||
return config.navbar.navbarBlur.value
|
||
},
|
||
set(value) {
|
||
config.navbar.navbarBlur.value = value
|
||
localStorage.setItem(`${config.app.title}-navbarBlur`, value.toString())
|
||
},
|
||
})
|
||
|
||
const _setAppDir = dir => {
|
||
document.documentElement.setAttribute('dir', dir)
|
||
}
|
||
|
||
const footerType = computed({
|
||
get() {
|
||
return config.footer.type.value
|
||
},
|
||
set(value) {
|
||
config.footer.type.value = value
|
||
},
|
||
})
|
||
|
||
const isVerticalNavCollapsed = computed({
|
||
get() {
|
||
return config.verticalNav.isVerticalNavCollapsed.value
|
||
},
|
||
set(val) {
|
||
config.verticalNav.isVerticalNavCollapsed.value = val
|
||
localStorage.setItem(`${config.app.title}-isVerticalNavCollapsed`, val.toString())
|
||
},
|
||
})
|
||
|
||
const appContentWidth = computed({
|
||
get() {
|
||
return config.app.contentWidth.value
|
||
},
|
||
set(val) {
|
||
config.app.contentWidth.value = val
|
||
localStorage.setItem(`${config.app.title}-contentWidth`, val.toString())
|
||
},
|
||
})
|
||
|
||
const appContentLayoutNav = computed({
|
||
get() {
|
||
return config.app.contentLayoutNav.value
|
||
},
|
||
set(val) {
|
||
config.app.contentLayoutNav.value = val
|
||
|
||
// If Navbar type is hidden while switching to horizontal nav => Reset it to sticky
|
||
if (val === AppContentLayoutNav.Horizontal) {
|
||
if (navbarType.value === NavbarType.Hidden)
|
||
navbarType.value = NavbarType.Sticky
|
||
isVerticalNavCollapsed.value = false
|
||
}
|
||
},
|
||
})
|
||
|
||
const horizontalNavType = computed({
|
||
get() {
|
||
return config.horizontalNav.type.value
|
||
},
|
||
set(value) {
|
||
config.horizontalNav.type.value = value
|
||
},
|
||
})
|
||
|
||
const isLessThanOverlayNavBreakpoint = computed(() => {
|
||
return windowWidth => unref(windowWidth) < config.app.overlayNavFromBreakpoint
|
||
})
|
||
|
||
const _layoutClasses = computed(() => (windowWidth, windowScrollY) => {
|
||
const route = useRoute()
|
||
|
||
return [
|
||
`layout-nav-type-${appContentLayoutNav.value}`,
|
||
`layout-navbar-${navbarType.value}`,
|
||
`layout-footer-${footerType.value}`,
|
||
{
|
||
'layout-vertical-nav-collapsed': isVerticalNavCollapsed.value
|
||
&& appContentLayoutNav.value === 'vertical'
|
||
&& !isLessThanOverlayNavBreakpoint.value(windowWidth),
|
||
},
|
||
{ [`horizontal-nav-${horizontalNavType.value}`]: appContentLayoutNav.value === 'horizontal' },
|
||
`layout-content-width-${appContentWidth.value}`,
|
||
{ 'layout-overlay-nav': isLessThanOverlayNavBreakpoint.value(windowWidth) },
|
||
{ 'window-scrolled': unref(windowScrollY) },
|
||
route.meta.layoutWrapperClasses ? route.meta.layoutWrapperClasses : null,
|
||
]
|
||
})
|
||
|
||
const switchToVerticalNavOnLtOverlayNavBreakpoint = windowWidth => {
|
||
/*
|
||
ℹ️ This is flag will hold nav type need to render when switching between lgAndUp from mdAndDown window width
|
||
|
||
Requirement: When we nav is set to `horizontal` and we hit the `mdAndDown` breakpoint nav type shall change to `vertical` nav
|
||
Now if we go back to `lgAndUp` breakpoint from `mdAndDown` how we will know which was previous nav type in large device?
|
||
|
||
Let's assign value of `appContentLayoutNav` as default value of lgAndUpNav. Why 🤔?
|
||
If template is viewed in lgAndUp
|
||
We will assign `appContentLayoutNav` value to `lgAndUpNav` because at this point both constant is same
|
||
Hence, for `lgAndUpNav` it will take value from theme config file
|
||
else
|
||
It will always show vertical nav and if user increase the window width it will fallback to `appContentLayoutNav` value
|
||
But `appContentLayoutNav` will be value set in theme config file
|
||
*/
|
||
const lgAndUpNav = ref(appContentLayoutNav.value)
|
||
|
||
|
||
/*
|
||
There might be case where we manually switch from vertical to horizontal nav and vice versa in `lgAndUp` screen
|
||
So when user comes back from `mdAndDown` to `lgAndUp` we can set updated nav type
|
||
For this we need to update the `lgAndUpNav` value if screen is `lgAndUp`
|
||
*/
|
||
watch(appContentLayoutNav, value => {
|
||
if (!isLessThanOverlayNavBreakpoint.value(windowWidth))
|
||
lgAndUpNav.value = value
|
||
})
|
||
|
||
/*
|
||
This is layout switching part
|
||
If it's `mdAndDown` => We will use vertical nav no matter what previous nav type was
|
||
Or if it's `lgAndUp` we need to switch back to `lgAndUp` nav type. For this we will tracker property `lgAndUpNav`
|
||
*/
|
||
watch(() => isLessThanOverlayNavBreakpoint.value(windowWidth), val => {
|
||
if (!val)
|
||
appContentLayoutNav.value = lgAndUpNav.value
|
||
else
|
||
appContentLayoutNav.value = AppContentLayoutNav.Vertical
|
||
}, { immediate: true })
|
||
}
|
||
|
||
|
||
/*
|
||
This function will return true if current state is mini. Mini state means vertical nav is:
|
||
- Collapsed
|
||
- Isn't hovered by mouse
|
||
- nav is not less than overlay breakpoint (hence, isn't overlay menu)
|
||
|
||
ℹ️ We are getting `isVerticalNavHovered` as param instead of via `inject` because
|
||
we are using this in `VerticalNav.vue` component which provide it and I guess because
|
||
same component is providing & injecting we are getting undefined error
|
||
*/
|
||
const isVerticalNavMini = (windowWidth, isVerticalNavHovered = null) => {
|
||
const isVerticalNavHoveredLocal = isVerticalNavHovered || inject(injectionKeyIsVerticalNavHovered) || ref(false)
|
||
|
||
return computed(() => isVerticalNavCollapsed.value && !isVerticalNavHoveredLocal.value && !isLessThanOverlayNavBreakpoint.value(unref(windowWidth)))
|
||
}
|
||
|
||
const dynamicI18nProps = computed(() => (key, tag = 'span') => {
|
||
if (config.app.enableI18n) {
|
||
return {
|
||
keypath: key,
|
||
tag,
|
||
scope: 'global',
|
||
}
|
||
}
|
||
|
||
return {}
|
||
})
|
||
|
||
const isAppRtl = computed({
|
||
get() {
|
||
return config.app.isRtl.value
|
||
},
|
||
set(value) {
|
||
config.app.isRtl.value = value
|
||
localStorage.setItem(`${config.app.title}-isRtl`, value.toString())
|
||
_setAppDir(value ? 'rtl' : 'ltr')
|
||
},
|
||
})
|
||
|
||
return {
|
||
navbarType,
|
||
isNavbarBlurEnabled,
|
||
footerType,
|
||
isVerticalNavCollapsed,
|
||
appContentWidth,
|
||
appContentLayoutNav,
|
||
horizontalNavType,
|
||
isLessThanOverlayNavBreakpoint,
|
||
_layoutClasses,
|
||
switchToVerticalNavOnLtOverlayNavBreakpoint,
|
||
isVerticalNavMini,
|
||
dynamicI18nProps,
|
||
isAppRtl,
|
||
_setAppDir,
|
||
}
|
||
}
|