@voidzero-dev/vitepress-theme 4.5.1 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -8
- package/package.json +6 -2
- package/src/components/oss/FeatureGrid.vue +4 -2
- package/src/components/oss/Hero.vue +9 -3
- package/src/components/vitepress-default/VPFlyout.vue +13 -4
- package/src/components/vitepress-default/VPMenuLink.vue +5 -0
- package/src/components/vitepress-default/VPNavBarMenuGroup.vue +1 -0
- package/src/components/vitepress-default/VPNavBarMenuLink.vue +6 -1
- package/src/components/vitepress-default/VPNavScreenMenu.vue +1 -0
- package/src/components/vitepress-default/VPNavScreenMenuGroup.vue +10 -1
- package/src/components/vitepress-default/VPNavScreenMenuGroupLink.vue +7 -1
- package/src/components/vitepress-default/VPNavScreenMenuLink.vue +7 -1
- package/src/components/vitepress-default/VPSidebarItem.vue +32 -2
- package/src/composables/vitepress-default/icon.ts +13 -0
- package/src/index.ts +1 -0
- package/src/types/theme-config.ts +18 -0
package/README.md
CHANGED
|
@@ -4,14 +4,11 @@ Shared VitePress theme for VoidZero projects, including Vite+, Vite, Vitest, Rol
|
|
|
4
4
|
|
|
5
5
|
## Publishing package
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
4. Push to remote `git push origin vx.y.z`
|
|
13
|
-
5. Go to GitHub UI > "Releases" > "Tags" > Click the latest tag > "Create release from tag"
|
|
14
|
-
6. Click "Publish release"
|
|
7
|
+
```bash
|
|
8
|
+
pnpm release <version> # e.g. pnpm release 4.6.1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This updates `package.json`, commits, tags, and pushes. CI publishes to npm and creates the GitHub release.
|
|
15
12
|
|
|
16
13
|
## Developing locally
|
|
17
14
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voidzero-dev/vitepress-theme",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.0",
|
|
4
4
|
"description": "Shared VitePress theme for VoidZero projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -32,10 +32,14 @@
|
|
|
32
32
|
"mark.js": "8.11.1",
|
|
33
33
|
"minisearch": "^7.2.0",
|
|
34
34
|
"reka-ui": "^2.5.1",
|
|
35
|
-
"tailwindcss": "^4.1.18"
|
|
35
|
+
"tailwindcss": "^4.1.18",
|
|
36
|
+
"@iconify/vue": "^5.0.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@types/mark.js": "^8.11.12",
|
|
39
40
|
"typescript": "^5.9.3"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"release": "node scripts/release.ts"
|
|
40
44
|
}
|
|
41
45
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { Icon } from '@iconify/vue'
|
|
2
3
|
import { useData } from 'vitepress'
|
|
3
4
|
|
|
4
5
|
const { frontmatter } = useData()
|
|
@@ -7,11 +8,12 @@ const { frontmatter } = useData()
|
|
|
7
8
|
<template>
|
|
8
9
|
<section v-if="frontmatter.features"
|
|
9
10
|
class="wrapper wrapper--ticks border-t grid md:grid-cols-2 divide-x divide-y divide-nickel">
|
|
10
|
-
<div v-for="feature in frontmatter.features" :key="feature.icon"
|
|
11
|
+
<div v-for="feature in frontmatter.features" :key="feature.icon || feature.iconify"
|
|
11
12
|
class="flex flex-col gap-3 justify-between border-r-0 md:odd:border-r md:nth-last-2:border-b-0">
|
|
12
13
|
<div class="px-10 py-8 sm:px-15 sm:py-12 flex flex-col gap-3">
|
|
13
14
|
<p class="text-2xl">
|
|
14
|
-
|
|
15
|
+
<Icon v-if="feature.iconify" :icon="feature.iconify" width="1em" height="1em" />
|
|
16
|
+
<template v-else>{{ feature.icon }}</template>
|
|
15
17
|
</p>
|
|
16
18
|
<h5 class="text-balance sm:text-pretty text-white">
|
|
17
19
|
{{ feature.title }}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script setup lang="ts">
|
|
2
2
|
import { useData } from 'vitepress'
|
|
3
3
|
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
background?: string
|
|
6
|
+
}>()
|
|
7
|
+
|
|
4
8
|
const { frontmatter } = useData()
|
|
5
9
|
</script>
|
|
6
10
|
|
|
@@ -27,9 +31,11 @@ const { frontmatter } = useData()
|
|
|
27
31
|
</div>
|
|
28
32
|
</div>
|
|
29
33
|
</div>
|
|
30
|
-
<div class="flex flex-col">
|
|
34
|
+
<div class="flex flex-col bg-cover bg-center" :style="props.background ? { backgroundImage: `url(${props.background})` } : undefined">
|
|
31
35
|
<div class="relative px-10 pb-10 md:pt-10 h-full flex flex-col justify-center overflow-clip">
|
|
32
|
-
<
|
|
36
|
+
<slot name="hero-image">
|
|
37
|
+
<img v-if="frontmatter.hero.image?.src" :src="frontmatter.hero.image.src" :alt="frontmatter.hero.image.alt" class="max-h-[20rem]">
|
|
38
|
+
</slot>
|
|
33
39
|
</div>
|
|
34
40
|
</div>
|
|
35
41
|
</div>
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
<script lang="ts" setup generic="T extends DefaultTheme.NavItem">
|
|
2
2
|
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
|
+
import type { IconOption } from '../../types/theme-config'
|
|
3
4
|
import { ref } from 'vue'
|
|
4
5
|
import { useFlyout } from '@vp-composables/flyout'
|
|
6
|
+
import { useIcon } from '@vp-composables/icon'
|
|
7
|
+
import { Icon } from '@iconify/vue'
|
|
5
8
|
import VPMenu from './VPMenu.vue'
|
|
6
9
|
|
|
7
|
-
defineProps<{
|
|
8
|
-
icon?:
|
|
10
|
+
const props = defineProps<{
|
|
11
|
+
icon?: IconOption
|
|
9
12
|
button?: string
|
|
10
13
|
label?: string
|
|
11
14
|
items?: T[]
|
|
12
15
|
}>()
|
|
13
16
|
|
|
17
|
+
const resolvedIcon = useIcon(() => props.icon)
|
|
18
|
+
|
|
14
19
|
const open = ref(false)
|
|
15
20
|
const el = ref<HTMLElement>()
|
|
16
21
|
|
|
@@ -36,8 +41,8 @@ function onBlur() {
|
|
|
36
41
|
:aria-label="label"
|
|
37
42
|
@click="open = !open"
|
|
38
43
|
>
|
|
39
|
-
<span v-if="button ||
|
|
40
|
-
<
|
|
44
|
+
<span v-if="button || resolvedIcon" class="flex items-center gap-1 leading-normal overflow-hidden">
|
|
45
|
+
<Icon v-if="resolvedIcon" :icon="resolvedIcon" class="shrink-0 mr-0.5" />
|
|
41
46
|
<span v-if="button" v-html="button" class="overflow-hidden text-ellipsis"></span>
|
|
42
47
|
<span class="vpi-chevron-down text-sm shrink-0" />
|
|
43
48
|
</span>
|
|
@@ -76,4 +81,8 @@ button[aria-expanded="true"] + .menu,
|
|
|
76
81
|
.VPFlyout:hover .menu {
|
|
77
82
|
display: block;
|
|
78
83
|
}
|
|
84
|
+
|
|
85
|
+
.VPFlyout.active button {
|
|
86
|
+
color: var(--vp-c-brand-1);
|
|
87
|
+
}
|
|
79
88
|
</style>
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
4
|
import { useData } from '@vp-composables/data'
|
|
5
|
+
import { useIcon } from '@vp-composables/icon'
|
|
5
6
|
import { isActive } from '../../support/vitepress-default/shared-utils'
|
|
7
|
+
import { Icon } from '@iconify/vue'
|
|
6
8
|
import VPLink from './VPLink.vue'
|
|
7
9
|
|
|
8
10
|
const props = defineProps<{
|
|
@@ -12,6 +14,8 @@ const props = defineProps<{
|
|
|
12
14
|
|
|
13
15
|
const { page } = useData()
|
|
14
16
|
|
|
17
|
+
const icon = useIcon(() => props.item.icon)
|
|
18
|
+
|
|
15
19
|
const href = computed(() =>
|
|
16
20
|
typeof props.item.link === 'function'
|
|
17
21
|
? props.item.link(page.value)
|
|
@@ -38,6 +42,7 @@ defineOptions({ inheritAttrs: false })
|
|
|
38
42
|
:rel="props.rel ?? item.rel"
|
|
39
43
|
:no-icon="item.noIcon"
|
|
40
44
|
>
|
|
45
|
+
<Icon v-if="icon" :icon="icon" class="shrink-0 mr-0.5" />
|
|
41
46
|
<span v-html="item.text"></span>
|
|
42
47
|
</VPLink>
|
|
43
48
|
</div>
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
4
|
import { useData } from '@vp-composables/data'
|
|
5
|
+
import { useIcon } from '@vp-composables/icon'
|
|
5
6
|
import { isActive } from '../../support/vitepress-default/shared-utils'
|
|
7
|
+
import { Icon } from '@iconify/vue'
|
|
6
8
|
import VPLink from './VPLink.vue'
|
|
7
9
|
|
|
8
10
|
const props = defineProps<{
|
|
@@ -11,6 +13,8 @@ const props = defineProps<{
|
|
|
11
13
|
|
|
12
14
|
const { page } = useData()
|
|
13
15
|
|
|
16
|
+
const icon = useIcon(() => props.item.icon)
|
|
17
|
+
|
|
14
18
|
const href = computed(() =>
|
|
15
19
|
typeof props.item.link === 'function'
|
|
16
20
|
? props.item.link(page.value)
|
|
@@ -20,7 +24,7 @@ const href = computed(() =>
|
|
|
20
24
|
|
|
21
25
|
<template>
|
|
22
26
|
<VPLink
|
|
23
|
-
class="flex items-center px-3 py-2 text-base font-heading text-primary
|
|
27
|
+
class="flex items-center gap-1 px-3 py-2 text-base font-heading text-primary
|
|
24
28
|
dark:text-white hover:opacity-85 transition-opacity whitespace-nowrap overflow-hidden text-ellipsis"
|
|
25
29
|
:class="{
|
|
26
30
|
active: isActive(
|
|
@@ -29,6 +33,7 @@ const href = computed(() =>
|
|
|
29
33
|
!!item.activeMatch
|
|
30
34
|
)
|
|
31
35
|
}" :href :target="item.target" :rel="item.rel" :no-icon="item.noIcon" tabindex="0">
|
|
36
|
+
<Icon v-if="icon" :icon="icon" class="shrink-0 mr-0.5" />
|
|
32
37
|
<span v-html="item.text"></span>
|
|
33
38
|
</VPLink>
|
|
34
39
|
</template>
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import type { IconOption } from '../../types/theme-config'
|
|
2
3
|
import { computed, ref } from 'vue'
|
|
4
|
+
import { useIcon } from '@vp-composables/icon'
|
|
5
|
+
import { Icon } from '@iconify/vue'
|
|
3
6
|
import VPNavScreenMenuGroupLink from './VPNavScreenMenuGroupLink.vue'
|
|
4
7
|
import VPNavScreenMenuGroupSection from './VPNavScreenMenuGroupSection.vue'
|
|
5
8
|
|
|
6
9
|
const props = defineProps<{
|
|
7
10
|
text: string
|
|
11
|
+
icon?: IconOption
|
|
8
12
|
items: any[]
|
|
9
13
|
}>()
|
|
10
14
|
|
|
15
|
+
const resolvedIcon = useIcon(() => props.icon)
|
|
16
|
+
|
|
11
17
|
const isOpen = ref(false)
|
|
12
18
|
|
|
13
19
|
const groupId = computed(
|
|
@@ -27,7 +33,10 @@ function toggle() {
|
|
|
27
33
|
:aria-expanded="isOpen"
|
|
28
34
|
@click="toggle"
|
|
29
35
|
>
|
|
30
|
-
<span class="
|
|
36
|
+
<span class="flex items-center">
|
|
37
|
+
<Icon v-if="resolvedIcon" :icon="resolvedIcon" class="shrink-0 mr-0.5" />
|
|
38
|
+
<span class="button-text" v-html="text"></span>
|
|
39
|
+
</span>
|
|
31
40
|
<span class="vpi-plus button-icon" />
|
|
32
41
|
</button>
|
|
33
42
|
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
3
|
import { computed, inject } from 'vue'
|
|
4
4
|
import { useData } from '@vp-composables/data'
|
|
5
|
+
import { useIcon } from '@vp-composables/icon'
|
|
5
6
|
import { navInjectionKey } from '@vp-composables/nav'
|
|
7
|
+
import { Icon } from '@iconify/vue'
|
|
6
8
|
import VPLink from './VPLink.vue'
|
|
7
9
|
|
|
8
10
|
const props = defineProps<{
|
|
@@ -11,6 +13,8 @@ const props = defineProps<{
|
|
|
11
13
|
|
|
12
14
|
const { page } = useData()
|
|
13
15
|
|
|
16
|
+
const icon = useIcon(() => props.item.icon)
|
|
17
|
+
|
|
14
18
|
const href = computed(() =>
|
|
15
19
|
typeof props.item.link === 'function'
|
|
16
20
|
? props.item.link(page.value)
|
|
@@ -29,13 +33,15 @@ const { closeScreen } = inject(navInjectionKey)!
|
|
|
29
33
|
:no-icon="item.noIcon"
|
|
30
34
|
@click="closeScreen"
|
|
31
35
|
>
|
|
36
|
+
<Icon v-if="icon" :icon="icon" class="shrink-0 mr-0.5" />
|
|
32
37
|
<span v-html="item.text"></span>
|
|
33
38
|
</VPLink>
|
|
34
39
|
</template>
|
|
35
40
|
|
|
36
41
|
<style scoped>
|
|
37
42
|
.VPNavScreenMenuGroupLink {
|
|
38
|
-
display:
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
39
45
|
margin-left: 12px;
|
|
40
46
|
line-height: 32px;
|
|
41
47
|
font-size: 14px;
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
3
|
import { computed, inject } from 'vue'
|
|
4
4
|
import { useData } from '@vp-composables/data'
|
|
5
|
+
import { useIcon } from '@vp-composables/icon'
|
|
5
6
|
import { navInjectionKey } from '@vp-composables/nav'
|
|
7
|
+
import { Icon } from '@iconify/vue'
|
|
6
8
|
import VPLink from './VPLink.vue'
|
|
7
9
|
|
|
8
10
|
const props = defineProps<{
|
|
@@ -11,6 +13,8 @@ const props = defineProps<{
|
|
|
11
13
|
|
|
12
14
|
const { page } = useData()
|
|
13
15
|
|
|
16
|
+
const icon = useIcon(() => props.item.icon)
|
|
17
|
+
|
|
14
18
|
const href = computed(() =>
|
|
15
19
|
typeof props.item.link === 'function'
|
|
16
20
|
? props.item.link(page.value)
|
|
@@ -29,13 +33,15 @@ const { closeScreen } = inject(navInjectionKey)!
|
|
|
29
33
|
:no-icon="item.noIcon"
|
|
30
34
|
@click="closeScreen"
|
|
31
35
|
>
|
|
36
|
+
<Icon v-if="icon" :icon="icon" class="shrink-0 mr-0.5" />
|
|
32
37
|
<span v-html="item.text"></span>
|
|
33
38
|
</VPLink>
|
|
34
39
|
</template>
|
|
35
40
|
|
|
36
41
|
<style scoped>
|
|
37
42
|
.VPNavScreenMenuLink {
|
|
38
|
-
display:
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
39
45
|
border-bottom: 1px solid var(--vp-c-divider);
|
|
40
46
|
padding: 12px 0 11px;
|
|
41
47
|
line-height: 24px;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
4
|
import { useSidebarItemControl } from '@vp-composables/sidebar'
|
|
5
|
+
import { useIcon } from '@vp-composables/icon'
|
|
6
|
+
import { Icon } from '@iconify/vue'
|
|
5
7
|
import VPLink from './VPLink.vue'
|
|
6
8
|
|
|
7
9
|
const props = defineProps<{
|
|
@@ -52,10 +54,12 @@ function onItemInteraction(e: MouseEvent | Event) {
|
|
|
52
54
|
function onCaretClick() {
|
|
53
55
|
props.item.link && toggle()
|
|
54
56
|
}
|
|
57
|
+
|
|
58
|
+
const itemIcon = useIcon(() => (props.item as any).icon)
|
|
55
59
|
</script>
|
|
56
60
|
|
|
57
61
|
<template>
|
|
58
|
-
<component :is="sectionTag" class="VPSidebarItem" :class="classes">
|
|
62
|
+
<component :is="sectionTag" class="VPSidebarItem" :class="[classes, { 'has-icon': itemIcon }]">
|
|
59
63
|
<div
|
|
60
64
|
v-if="item.text"
|
|
61
65
|
class="item"
|
|
@@ -77,9 +81,13 @@ function onCaretClick() {
|
|
|
77
81
|
:rel="item.rel"
|
|
78
82
|
:target="item.target"
|
|
79
83
|
>
|
|
84
|
+
<Icon v-if="itemIcon" :icon="itemIcon" class="sidebar-icon shrink-0 mr-0.5" />
|
|
80
85
|
<component :is="textTag" class="text" v-html="item.text" />
|
|
81
86
|
</VPLink>
|
|
82
|
-
<
|
|
87
|
+
<template v-else>
|
|
88
|
+
<Icon v-if="itemIcon" :icon="itemIcon" class="sidebar-icon shrink-0 mr-0.5" />
|
|
89
|
+
<component :is="textTag" class="text" v-html="item.text" />
|
|
90
|
+
</template>
|
|
83
91
|
|
|
84
92
|
<div
|
|
85
93
|
v-if="item.collapsed != null && item.items && item.items.length"
|
|
@@ -112,6 +120,8 @@ function onCaretClick() {
|
|
|
112
120
|
.item {
|
|
113
121
|
position: relative;
|
|
114
122
|
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
gap: 6px;
|
|
115
125
|
width: 100%;
|
|
116
126
|
}
|
|
117
127
|
|
|
@@ -139,6 +149,7 @@ function onCaretClick() {
|
|
|
139
149
|
.link {
|
|
140
150
|
display: flex;
|
|
141
151
|
align-items: center;
|
|
152
|
+
gap: 6px;
|
|
142
153
|
flex-grow: 1;
|
|
143
154
|
}
|
|
144
155
|
|
|
@@ -229,6 +240,7 @@ function onCaretClick() {
|
|
|
229
240
|
transform: rotate(0)/*rtl:rotate(180deg)*/;
|
|
230
241
|
}
|
|
231
242
|
|
|
243
|
+
.VPSidebarItem.level-0.has-icon > .items,
|
|
232
244
|
.VPSidebarItem.level-1 .items,
|
|
233
245
|
.VPSidebarItem.level-2 .items,
|
|
234
246
|
.VPSidebarItem.level-3 .items,
|
|
@@ -241,4 +253,22 @@ function onCaretClick() {
|
|
|
241
253
|
.VPSidebarItem.collapsed .items {
|
|
242
254
|
display: none;
|
|
243
255
|
}
|
|
256
|
+
|
|
257
|
+
.sidebar-icon {
|
|
258
|
+
color: var(--vp-c-brand-1);
|
|
259
|
+
height: 1.2em;
|
|
260
|
+
width: 1.2em;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Child-level icons (framework logos etc.) use text color instead of brand.
|
|
264
|
+
Multi-color icons have explicit SVG fills and are unaffected. */
|
|
265
|
+
.VPSidebarItem:not(.level-0) > .item .sidebar-icon {
|
|
266
|
+
color: var(--vp-c-text-1);
|
|
267
|
+
height: 1em;
|
|
268
|
+
width: 1em;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.VPSidebarItem.level-0.has-icon > .items {
|
|
272
|
+
margin-left: 6px;
|
|
273
|
+
}
|
|
244
274
|
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { computed, type MaybeRefOrGetter, toValue } from 'vue'
|
|
2
|
+
import { useData } from './data'
|
|
3
|
+
import type { IconOption } from '../../types/theme-config'
|
|
4
|
+
|
|
5
|
+
export function useIcon(icon: MaybeRefOrGetter<IconOption | undefined>) {
|
|
6
|
+
const { isDark } = useData()
|
|
7
|
+
return computed(() => {
|
|
8
|
+
const val = toValue(icon)
|
|
9
|
+
if (!val) return undefined
|
|
10
|
+
if (typeof val === 'string') return val
|
|
11
|
+
return isDark.value ? val.dark : val.light
|
|
12
|
+
})
|
|
13
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
import type { DefaultTheme } from 'vitepress/theme'
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Icon option — a single string for both modes, or per-mode variants
|
|
9
|
+
*/
|
|
10
|
+
export type IconOption = string | { light: string; dark: string }
|
|
11
|
+
|
|
7
12
|
/**
|
|
8
13
|
* Grid size options for sponsor display
|
|
9
14
|
*/
|
|
@@ -98,5 +103,18 @@ declare module 'vitepress' {
|
|
|
98
103
|
variant?: 'voidzero' | 'viteplus' | 'vite' | 'vitest' | 'rolldown' | 'oxc'
|
|
99
104
|
banner?: BannerConfig
|
|
100
105
|
}
|
|
106
|
+
|
|
107
|
+
// Add icon support to nav and sidebar items
|
|
108
|
+
interface NavItemWithLink {
|
|
109
|
+
icon?: IconOption
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface NavItemWithChildren {
|
|
113
|
+
icon?: IconOption
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Note: SidebarItem is a type alias (not interface) so it can't be
|
|
117
|
+
// augmented. Sidebar icon support works via runtime casting in
|
|
118
|
+
// VPSidebarItem.vue — the icon property is passed through config objects.
|
|
101
119
|
}
|
|
102
120
|
}
|