initial commit

This commit is contained in:
2026-06-23 13:28:38 +07:00
commit 966ed115b2
590 changed files with 111412 additions and 0 deletions
@@ -0,0 +1,14 @@
// Thanks: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
export const useDynamicVhCssProperty = () => {
const vh = ref(0)
const updateVh = () => {
vh.value = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh', `${vh.value}px`)
}
tryOnBeforeMount(() => {
updateVh()
useEventListener('resize', updateVh)
})
}
@@ -0,0 +1,204 @@
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,
}
}