101 lines
2.4 KiB
Vue
101 lines
2.4 KiB
Vue
<!--
|
|
Table Of content
|
|
|
|
`mode` can be either 'all', 'onlyCurrentTree' or 'onlySiblings'
|
|
|
|
Usage:
|
|
|
|
<Toc columns='2' maxDepth='3' mode='onlySiblings'/>
|
|
-->
|
|
<script setup lang='ts'>
|
|
import type { TocItem } from '@slidev/types'
|
|
import { computed } from 'vue'
|
|
import { useSlideContext } from '../context'
|
|
import TocList from './TocList.vue'
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
columns?: string | number
|
|
listClass?: string | string[]
|
|
start?: string | number
|
|
listStyle?: string | string[]
|
|
maxDepth?: string | number
|
|
minDepth?: string | number
|
|
mode?: 'all' | 'onlyCurrentTree' | 'onlySiblings'
|
|
}>(),
|
|
{
|
|
columns: 1,
|
|
listClass: '',
|
|
start: 1,
|
|
listStyle: '',
|
|
maxDepth: Number.POSITIVE_INFINITY,
|
|
minDepth: 1,
|
|
mode: 'all',
|
|
},
|
|
)
|
|
|
|
const { $slidev } = useSlideContext()
|
|
|
|
function filterTreeDepth(tree: TocItem[], level = 1): TocItem[] {
|
|
if (level > Number(props.maxDepth)) {
|
|
return []
|
|
}
|
|
else if (level < Number(props.minDepth)) {
|
|
const activeItem = tree.find((item: TocItem) => item.active || item.activeParent)
|
|
return activeItem ? filterTreeDepth(activeItem.children, level + 1) : []
|
|
}
|
|
return tree
|
|
.map((item: TocItem) => ({
|
|
...item,
|
|
children: filterTreeDepth(item.children, level + 1),
|
|
}))
|
|
}
|
|
|
|
function filterOnlyCurrentTree(tree: TocItem[]): TocItem[] {
|
|
return tree
|
|
.filter(
|
|
(item: TocItem) => item.active || item.activeParent || item.hasActiveParent,
|
|
)
|
|
.map((item: TocItem) => ({
|
|
...item,
|
|
children: filterOnlyCurrentTree(item.children),
|
|
}))
|
|
}
|
|
|
|
function filterOnlySiblings(tree: TocItem[]): TocItem[] {
|
|
const treehasActiveItem = tree.some(
|
|
(item: TocItem) => item.active || item.activeParent || item.hasActiveParent,
|
|
)
|
|
return tree
|
|
.filter(() => treehasActiveItem)
|
|
.map((item: TocItem) => ({
|
|
...item,
|
|
children: filterOnlySiblings(item.children),
|
|
}))
|
|
}
|
|
|
|
const toc = computed(() => {
|
|
const tree = $slidev?.nav.tocTree
|
|
if (!tree)
|
|
return []
|
|
let tocTree = filterTreeDepth(tree)
|
|
if (props.mode === 'onlyCurrentTree')
|
|
tocTree = filterOnlyCurrentTree(tocTree)
|
|
else if (props.mode === 'onlySiblings')
|
|
tocTree = filterOnlySiblings(tocTree)
|
|
return tocTree
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="slidev-toc" :style="`column-count:${columns}`">
|
|
<TocList
|
|
:level="1"
|
|
:start="start"
|
|
:list-style="listStyle"
|
|
:list="toc"
|
|
:list-class="listClass"
|
|
/>
|
|
</div>
|
|
</template>
|