@ithinkdt/naive
Version:
iThinkDT Naive UI
204 lines (177 loc) • 7.83 kB
JSX
import { defineComponent, ref, toRef, computed, useSlots, provide } from 'vue'
import { useRouter } from 'vue-router'
import { until, useElementSize, throttledWatch } from '@vueuse/core'
import { NScrollbar, NButton, NIcon, NTooltip } from 'ithinkdt-ui'
import { useAuth, useTheme, DtLayoutView, modals } from '@ithinkdt/core'
import { useClass } from '@ithinkdt/common'
import { IModals } from '../assets'
import { ThemeProvider } from '../naive'
import { CSS_STYLE_PREFIX as p } from '@ithinkdt/core/cssr'
import { createStyle } from './layout.style.js'
export const DtLayout = defineComponent({
name: 'DtLayout',
setup() {
const cls = `${p}-layout`
createStyle(cls)
const auth = useAuth()
const theme = useTheme()
const router = useRouter()
const layoutRef = ref()
const hidden = useClass(
layoutRef,
`${cls}--hide-sidebar`,
computed(
() =>
!theme.hasSidebar ||
theme.menuPlacement === 'topbar' ||
(theme.logoPlacement === 'split' && !auth.activedMenuPath[0]?.children?.length) ||
(theme.menuPlacement === 'sidebar' && !auth.modules?.length),
),
)
useClass(
layoutRef,
`${cls}--collpased-sidebar`,
computed(() => !hidden.value && !theme.isFixedSidebar),
)
useClass(document.body, 'dark', toRef(theme, 'isDark'))
const transition = ref(false)
until(router.currentRoute)
.toBeTruthy()
.then(() => (transition.value = true))
const transitionBind = {
name: `${cls}__main-content-`,
// mode: 'out-in',
}
const slots = useSlots()
provide('__INJECT_SLOTS__', slots)
const Top = () => (
<>
{theme.logoPlacement === 'topbar' || hidden.value ? (
<div class={`${cls}__topbar-logo-wrapper`}>{slots.logo?.()}</div>
) : undefined}
{theme.collpaseBtnPlacement === 'topbar' ? (
<div class={`${cls}__topbar-collpase-btn`}>{slots.collpase?.({ size: 'medium' })}</div>
) : undefined}
{theme.menuPlacement === 'sidebar' ? (
theme.hasBreadcrumb && slots.breadcrumb ? (
<div class={`${cls}__topbar-breadcrumb`}>{slots.breadcrumb()}</div>
) : undefined
) : (
slots.nav?.({ full: theme.menuPlacement === 'topbar' })
)}
<div class={`${cls}__topbar-space`} />
{modals.some((m) => m.visible === null) ? (
<NTooltip>
{{
default: () => '打开已收起的对话框',
trigger: () => (
<NButton
text
style="font-size: 18px"
onClick={() => {
for (const m of modals) m.visible ??= true
}}
>
<NIcon>
<IModals />
</NIcon>
</NButton>
),
}}
</NTooltip>
) : undefined}
{slots.extra?.()}
{theme.showAppearence ? slots.appearence?.() : undefined}
{theme.showI18n ? slots.language?.() : undefined}
{theme.showFullscreen ? slots.fullscreen?.() : undefined}
{theme.showMessage ? slots.message?.() : undefined}
{slots.avator?.()}
</>
)
const Side = () => (
<>
{theme.logoPlacement === 'sidebar' ? (
<div class={`${cls}__sidebar-logo-wrapper`}>{slots.logo?.()}</div>
) : undefined}
{theme.menuPlacement === 'topbar' ? undefined : (
<NScrollbar>{slots.side?.({ full: theme.menuPlacement === 'sidebar' })}</NScrollbar>
)}
{theme.collpaseBtnPlacement === 'sidebar' ? (
<div class={`${cls}__sidebar-collpase-btn`}>{slots.collpase?.({ size: 'large' })}</div>
) : undefined}
</>
)
const contentRef = ref()
const { width: contentwidth, height: contentHeight } = useElementSize(contentRef)
const style = ref({})
throttledWatch(
[contentwidth, contentHeight],
([w, h]) => {
style.value = {
[`--${p}_body-width`]: w + 'px',
[`--${p}_body-height`]: h + 'px',
}
},
{ immediate: true, throttle: 1000 / 25 },
)
return () => {
return (
<div
class={[
cls,
theme.logoPlacement === 'sidebar' && !hidden.value
? `${cls}--logo-in-sidebar`
: `${cls}--logo-in-topbar`,
{
[`${cls}--dark`]: theme.isDark,
[`${cls}--full-tab`]: theme.fullTab,
[`${cls}--transition`]: transition.value,
},
]}
ref={layoutRef}
>
<header v-show={theme.hasTopbar} class={`${cls}__topbar`}>
{theme.topbarDark && !theme.isDark ? (
<ThemeProvider theme="dark">
<Top />
</ThemeProvider>
) : (
<Top />
)}
</header>
<aside v-show={theme.hasSidebar} class={{ [`${cls}__sidebar`]: true }}>
{theme.sidebarDark && !theme.isDark ? (
<ThemeProvider theme="dark">
<Side />
</ThemeProvider>
) : (
<Side />
)}
</aside>
<main class={`${cls}__main`}>
{theme.multiTab ? (
<div class={`${cls}__tabsbar`}>
{slots.tabs?.({
showBreadcrumb: theme.hasBreadcrumb && theme.menuPlacement !== 'sidebar',
})}
</div>
) : undefined}
<div class={`${cls}__main-body`} ref={contentRef} style={style.value}>
{/* */}
{/* <NScrollbar xScrollable> */}
{/* <div class={`${cls}__main-content`}> */}
<DtLayoutView transition={transitionBind} />
{/* </div> */}
{/* </NScrollbar> */}
</div>
</main>
{theme.hasFooter ? (
<footer class={[`${cls}__footer`, theme.floatFooter ? `${cls}__footer--float` : undefined]}>
{slots.footer?.({ description: theme.footer })}
</footer>
) : undefined}
</div>
)
}
},
})