UNPKG

nuxt

Version:

[![Nuxt banner](./.github/assets/banner.png)](https://nuxt.com)

91 lines (90 loc) 3.08 kB
import { Suspense, Transition, computed, defineComponent, h, inject, mergeProps, nextTick, onMounted, provide, ref, unref } from "vue"; import { _wrapIf } from "./utils.js"; import { useRoute } from "#app/composables/router"; import { useRoute as useVueRouterRoute } from "#build/pages"; import layouts from "#build/layouts"; import { appLayoutTransition as defaultLayoutTransition } from "#build/nuxt.config.mjs"; import { useNuxtApp } from "#app"; export const LayoutMetaSymbol = Symbol("layout-meta"); export default defineComponent({ name: "NuxtLayout", inheritAttrs: false, props: { name: { type: [String, Boolean, Object], default: null } }, setup(props, context) { const nuxtApp = useNuxtApp(); const injectedRoute = inject("_route"); const route = injectedRoute === useRoute() ? useVueRouterRoute() : injectedRoute; const layout = computed(() => unref(props.name) ?? route.meta.layout ?? "default"); const layoutRef = ref(); context.expose({ layoutRef }); return () => { const done = nuxtApp.deferHydration(); const hasLayout = layout.value && layout.value in layouts; if (process.dev && layout.value && !hasLayout && layout.value !== "default") { console.warn(`Invalid layout \`${layout.value}\` selected.`); } const transitionProps = route.meta.layoutTransition ?? defaultLayoutTransition; return _wrapIf(Transition, hasLayout && transitionProps, { default: () => h(Suspense, { suspensible: true, onResolve: () => { nextTick(done); } }, { default: () => _wrapIf(LayoutProvider, hasLayout && { layoutProps: mergeProps(context.attrs, { ref: layoutRef }), key: layout.value, name: layout.value, shouldProvide: !props.name, hasTransition: !!transitionProps }, context.slots).default() }) }).default(); }; } }); const LayoutProvider = defineComponent({ name: "NuxtLayoutProvider", inheritAttrs: false, props: { name: { type: String }, layoutProps: { type: Object }, hasTransition: { type: Boolean }, shouldProvide: { type: Boolean } }, setup(props, context) { if (props.shouldProvide) { const name = props.name; provide(LayoutMetaSymbol, { isCurrent: (route) => name === (route.meta.layout ?? "default") }); } let vnode; if (process.dev && process.client) { onMounted(() => { nextTick(() => { if (["#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.`); } }); }); } return () => { if (process.dev && process.client && props.hasTransition) { vnode = h(layouts[props.name], props.layoutProps, context.slots); return vnode; } return h(layouts[props.name], props.layoutProps, context.slots); }; } });