62 lines
1.8 KiB
Vue
62 lines
1.8 KiB
Vue
<script>
|
|
import { toRefs, defineComponent, h, useSlots, computed } from "vue";
|
|
import { hash } from "ohash";
|
|
import { useAsyncData, fetchContentNavigation, useState, useContent } from "#imports";
|
|
import { NuxtLink } from "#components";
|
|
const ContentNavigation = defineComponent({
|
|
name: "ContentNavigation",
|
|
props: {
|
|
/**
|
|
* A query to be passed to `fetchContentNavigation()`.
|
|
*/
|
|
query: {
|
|
type: Object,
|
|
required: false,
|
|
default: void 0
|
|
}
|
|
},
|
|
async setup(props) {
|
|
const {
|
|
query
|
|
} = toRefs(props);
|
|
const queryBuilder = computed(() => {
|
|
if (typeof query.value?.params === "function") {
|
|
return query.value.params();
|
|
}
|
|
return query.value;
|
|
});
|
|
if (!queryBuilder.value && useState("dd-navigation").value) {
|
|
const { navigation: navigation2 } = useContent();
|
|
return { navigation: navigation2 };
|
|
}
|
|
const { data: navigation } = await useAsyncData(
|
|
`content-navigation-${hash(queryBuilder.value)}`,
|
|
() => fetchContentNavigation(queryBuilder.value)
|
|
);
|
|
return { navigation };
|
|
},
|
|
/**
|
|
* Navigation empty fallback
|
|
* @slot empty
|
|
*/
|
|
render(ctx) {
|
|
const slots = useSlots();
|
|
const { navigation } = ctx;
|
|
const renderLink = (link) => h(NuxtLink, { to: link._path }, () => link.title);
|
|
const renderLinks = (data, level) => h(
|
|
"ul",
|
|
level ? { "data-level": level } : null,
|
|
data.map((link) => {
|
|
if (link.children) {
|
|
return h("li", null, [renderLink(link), renderLinks(link.children, level + 1)]);
|
|
}
|
|
return h("li", null, renderLink(link));
|
|
})
|
|
);
|
|
const defaultNode = (data) => renderLinks(data, 0);
|
|
return slots?.default ? slots.default({ navigation, ...this.$attrs }) : defaultNode(navigation);
|
|
}
|
|
});
|
|
export default ContentNavigation;
|
|
</script>
|