2022-12-11 21:44:52 +00:00
|
|
|
import type { Ref, VNode } from 'vue'
|
|
|
|
import { computed, defineComponent, h, inject, nextTick, onMounted, Transition, unref } from 'vue'
|
2022-10-24 08:36:49 +00:00
|
|
|
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
2022-03-14 10:47:24 +00:00
|
|
|
import { _wrapIf } from './utils'
|
|
|
|
import { useRoute } from '#app'
|
2021-10-21 19:16:52 +00:00
|
|
|
// @ts-ignore
|
2022-10-24 08:36:49 +00:00
|
|
|
import { useRoute as useVueRouterRoute } from '#build/pages'
|
|
|
|
// @ts-ignore
|
2021-06-30 16:32:22 +00:00
|
|
|
import layouts from '#build/layouts'
|
2022-08-23 14:24:20 +00:00
|
|
|
// @ts-ignore
|
|
|
|
import { appLayoutTransition as defaultLayoutTransition } from '#build/nuxt.config.mjs'
|
2022-01-31 18:58:19 +00:00
|
|
|
|
2022-10-08 14:18:57 +00:00
|
|
|
// TODO: revert back to defineAsyncComponent when https://github.com/vuejs/core/issues/6638 is resolved
|
|
|
|
const LayoutLoader = defineComponent({
|
2022-11-29 12:16:41 +00:00
|
|
|
inheritAttrs: false,
|
2022-10-08 14:18:57 +00:00
|
|
|
props: {
|
|
|
|
name: String,
|
|
|
|
...process.dev ? { hasTransition: Boolean } : {}
|
|
|
|
},
|
|
|
|
async setup (props, context) {
|
|
|
|
let vnode: VNode
|
|
|
|
|
|
|
|
if (process.dev && process.client) {
|
|
|
|
onMounted(() => {
|
|
|
|
nextTick(() => {
|
|
|
|
if (props.name && ['#comment', '#text'].includes(vnode?.el?.nodeName)) {
|
|
|
|
console.warn(`[nuxt] \`${props.name}\` layout does not have a single root node and will cause errors when navigating between routes.`)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const LayoutComponent = await layouts[props.name]().then((r: any) => r.default || r)
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
if (process.dev && process.client && props.hasTransition) {
|
2022-11-29 12:16:41 +00:00
|
|
|
vnode = h(LayoutComponent, context.attrs, context.slots)
|
2022-10-08 14:18:57 +00:00
|
|
|
return vnode
|
|
|
|
}
|
2022-11-29 12:16:41 +00:00
|
|
|
return h(LayoutComponent, context.attrs, context.slots)
|
2022-10-08 14:18:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2021-06-30 16:32:22 +00:00
|
|
|
export default defineComponent({
|
2022-11-29 12:16:41 +00:00
|
|
|
inheritAttrs: false,
|
2021-06-30 16:32:22 +00:00
|
|
|
props: {
|
|
|
|
name: {
|
2022-01-17 18:27:23 +00:00
|
|
|
type: [String, Boolean, Object] as unknown as () => string | false | Ref<string | false>,
|
2022-01-31 18:58:19 +00:00
|
|
|
default: null
|
2021-06-30 16:32:22 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
setup (props, context) {
|
2022-10-08 14:18:57 +00:00
|
|
|
// Need to ensure (if we are not a child of `<NuxtPage>`) that we use synchronous route (not deferred)
|
|
|
|
const injectedRoute = inject('_route') as RouteLocationNormalizedLoaded
|
|
|
|
const route = injectedRoute === useRoute() ? useVueRouterRoute() : injectedRoute
|
|
|
|
const layout = computed(() => unref(props.name) ?? route.meta.layout as string ?? 'default')
|
2022-01-31 18:58:19 +00:00
|
|
|
|
2022-08-23 10:25:48 +00:00
|
|
|
let vnode: VNode
|
|
|
|
let _layout: string | false
|
|
|
|
if (process.dev && process.client) {
|
|
|
|
onMounted(() => {
|
|
|
|
nextTick(() => {
|
2022-09-22 13:54:55 +00:00
|
|
|
if (_layout && _layout in layouts && ['#comment', '#text'].includes(vnode?.el?.nodeName)) {
|
2022-08-23 10:25:48 +00:00
|
|
|
console.warn(`[nuxt] \`${_layout}\` layout does not have a single root node and will cause errors when navigating between routes.`)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-06-30 16:32:22 +00:00
|
|
|
return () => {
|
2022-10-08 14:18:57 +00:00
|
|
|
const hasLayout = layout.value && layout.value in layouts
|
|
|
|
if (process.dev && layout.value && !hasLayout && layout.value !== 'default') {
|
|
|
|
console.warn(`Invalid layout \`${layout.value}\` selected.`)
|
2021-06-30 16:32:22 +00:00
|
|
|
}
|
2022-01-31 18:58:19 +00:00
|
|
|
|
2022-08-23 10:25:48 +00:00
|
|
|
const transitionProps = route.meta.layoutTransition ?? defaultLayoutTransition
|
|
|
|
|
2022-01-31 18:58:19 +00:00
|
|
|
// We avoid rendering layout transition if there is no layout to render
|
2022-08-23 10:25:48 +00:00
|
|
|
return _wrapIf(Transition, hasLayout && transitionProps, {
|
2022-11-29 12:16:41 +00:00
|
|
|
default: () => _wrapIf(LayoutLoader, hasLayout && { key: layout.value, name: layout.value, hasTransition: process.dev ? !!transitionProps : undefined, ...context.attrs }, context.slots).default()
|
2022-08-23 10:25:48 +00:00
|
|
|
}).default()
|
2021-06-30 16:32:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|