|
@@ -2,12 +2,12 @@
|
|
|
import { useMediaQuery } from '@vueuse/core'
|
|
|
import { isEmpty } from 'lodash-es'
|
|
|
import { NScrollbar } from 'naive-ui'
|
|
|
-import { computed, provide, watch, reactive } from 'vue'
|
|
|
+import { computed, provide, watch, ref } from 'vue'
|
|
|
|
|
|
import texturePng from '@/assets/texture.png'
|
|
|
import { EmptyPlaceholder } from '@/components'
|
|
|
import { useComponentThemeOverrides } from '@/composable/useComponentThemeOverrides'
|
|
|
-import { mediaQueryInjectionKey } from '@/injection'
|
|
|
+import { mediaQueryInjectionKey, layoutSlideDirectionInjectionKey } from '@/injection'
|
|
|
import { usePreferencesStore } from '@/stores'
|
|
|
import { useTabsStore } from '@/stores'
|
|
|
|
|
@@ -19,6 +19,8 @@ import FooterLayout from './footer/index.vue'
|
|
|
import HeaderLayout from './header/index.vue'
|
|
|
import MainLayout from './main/index.vue'
|
|
|
|
|
|
+import type { LayoutSlideDirection } from '@/injection'
|
|
|
+
|
|
|
defineOptions({
|
|
|
name: 'Layout',
|
|
|
})
|
|
@@ -27,22 +29,28 @@ const tabsStore = useTabsStore()
|
|
|
const preferencesStore = usePreferencesStore()
|
|
|
const { scrollbarInMainLayout } = useComponentThemeOverrides()
|
|
|
|
|
|
-const mediaQuery = reactive({
|
|
|
+const mediaQuery = {
|
|
|
sm: useMediaQuery('(max-width: 640px)'),
|
|
|
md: useMediaQuery('(max-width: 768px)'),
|
|
|
lg: useMediaQuery('(max-width: 1024px)'),
|
|
|
xl: useMediaQuery('(max-width: 1280px)'),
|
|
|
- '2xl': useMediaQuery('(max-width: 1536px)'),
|
|
|
-})
|
|
|
+ xxl: useMediaQuery('(max-width: 1536px)'),
|
|
|
+}
|
|
|
+
|
|
|
+const layoutSlideDirection = ref<LayoutSlideDirection>(null)
|
|
|
|
|
|
-const mobileLayoutTranslateOffset = computed(() => {
|
|
|
- return preferencesStore.layoutSlideDirection === 'right'
|
|
|
+const layoutTranslateOffset = computed(() => {
|
|
|
+ return layoutSlideDirection.value === 'right'
|
|
|
? preferencesStore.preferences.menu.maxWidth || 0
|
|
|
- : preferencesStore.layoutSlideDirection === 'left'
|
|
|
+ : layoutSlideDirection.value === 'left'
|
|
|
? -62
|
|
|
: 0
|
|
|
})
|
|
|
|
|
|
+function setLayoutSlideDirection(direction: LayoutSlideDirection) {
|
|
|
+ layoutSlideDirection.value = direction === layoutSlideDirection.value ? null : direction
|
|
|
+}
|
|
|
+
|
|
|
watch(
|
|
|
() => mediaQuery.sm,
|
|
|
(isMaxSm) => {
|
|
@@ -58,29 +66,34 @@ watch(
|
|
|
)
|
|
|
|
|
|
provide(mediaQueryInjectionKey, mediaQuery)
|
|
|
+
|
|
|
+provide(layoutSlideDirectionInjectionKey, {
|
|
|
+ direction: layoutSlideDirection,
|
|
|
+ setDirection: setLayoutSlideDirection,
|
|
|
+})
|
|
|
</script>
|
|
|
<template>
|
|
|
<div
|
|
|
class="relative flex h-svh overflow-hidden"
|
|
|
:style="{ backgroundImage: `url(${texturePng})` }"
|
|
|
>
|
|
|
- <MobileLeftAside v-if="mediaQuery.sm" />
|
|
|
+ <MobileLeftAside v-if="mediaQuery.sm.value" />
|
|
|
<div
|
|
|
class="relative flex h-full w-full flex-col border-naive-border transition-[border-color,rounded,transform] max-sm:rounded-xl sm:transform-none!"
|
|
|
:class="{
|
|
|
- 'overflow-hidden rounded-xl border': mediaQuery.sm && mobileLayoutTranslateOffset,
|
|
|
+ 'overflow-hidden rounded-xl border': mediaQuery.sm.value && layoutTranslateOffset,
|
|
|
}"
|
|
|
:style="
|
|
|
- mediaQuery.sm && preferencesStore.layoutSlideDirection
|
|
|
+ mediaQuery.sm.value && layoutSlideDirection
|
|
|
? {
|
|
|
- transform: `translate(${mobileLayoutTranslateOffset}px) scale(0.88)`,
|
|
|
+ transform: `translate(${layoutTranslateOffset}px) scale(0.88)`,
|
|
|
}
|
|
|
: null
|
|
|
"
|
|
|
>
|
|
|
<HeaderLayout />
|
|
|
<div class="flex flex-1 overflow-hidden">
|
|
|
- <AsideLayout v-if="!mediaQuery.sm" />
|
|
|
+ <AsideLayout v-if="!mediaQuery.sm.value" />
|
|
|
<div class="relative flex flex-1 flex-col overflow-x-hidden">
|
|
|
<Transition
|
|
|
type="transition"
|
|
@@ -93,7 +106,9 @@ provide(mediaQueryInjectionKey, mediaQuery)
|
|
|
>
|
|
|
<div
|
|
|
v-if="
|
|
|
- !mediaQuery.sm && !isEmpty(tabsStore.tabs) && preferencesStore.preferences.showTabs
|
|
|
+ !mediaQuery.sm.value &&
|
|
|
+ !isEmpty(tabsStore.tabs) &&
|
|
|
+ preferencesStore.preferences.showTabs
|
|
|
"
|
|
|
class="grid shrink-0 items-baseline overflow-hidden"
|
|
|
>
|
|
@@ -103,7 +118,7 @@ provide(mediaQueryInjectionKey, mediaQuery)
|
|
|
<NScrollbar
|
|
|
class="transition-[padding]"
|
|
|
:class="{
|
|
|
- 'pb-4': mediaQuery.sm && preferencesStore.layoutSlideDirection,
|
|
|
+ 'pb-4': mediaQuery.sm.value && layoutSlideDirection,
|
|
|
}"
|
|
|
container-class="main-container"
|
|
|
:theme-overrides="scrollbarInMainLayout"
|
|
@@ -131,7 +146,7 @@ provide(mediaQueryInjectionKey, mediaQuery)
|
|
|
leave-from-class="grid-rows-[1fr]"
|
|
|
>
|
|
|
<div
|
|
|
- v-if="!mediaQuery.sm && preferencesStore.preferences.showFooter"
|
|
|
+ v-if="!mediaQuery.sm.value && preferencesStore.preferences.showFooter"
|
|
|
class="grid shrink-0 items-baseline overflow-hidden"
|
|
|
>
|
|
|
<FooterLayout />
|
|
@@ -140,6 +155,6 @@ provide(mediaQueryInjectionKey, mediaQuery)
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <MobileRightAside v-if="mediaQuery.sm" />
|
|
|
+ <MobileRightAside v-if="mediaQuery.sm.value" />
|
|
|
</div>
|
|
|
</template>
|