valaxy-theme-hairy 1.2.3 → 1.2.5
Sign up to get free protection for your applications and to get access to all the features.
- package/components/HairyBody.vue +1 -1
- package/components/HairyTabbar.vue +18 -4
- package/components/PageTags.vue +1 -1
- package/components/posts/HairyUpdatedPost.vue +1 -1
- package/components/third/HairyFuseSearchDialog.vue +19 -7
- package/components/third/HairyFuseSearchHeader.vue +4 -2
- package/composables/category.ts +1 -2
- package/layouts/post.vue +1 -1
- package/package.json +1 -1
- package/pages/categories/[...its].vue +4 -1
- package/pages/tags/[tag]/index.vue +2 -2
package/components/HairyBody.vue
CHANGED
@@ -12,7 +12,7 @@ withDefaults(
|
|
12
12
|
<template>
|
13
13
|
<div class="min-h-49vh relative z-5">
|
14
14
|
<div class="mx-auto container flex z-1 relative">
|
15
|
-
<div class="relative flex-1 pt-2 main">
|
15
|
+
<div class="relative flex-1 pt-2 main min-w-0">
|
16
16
|
<slot v-if="$slots.default" />
|
17
17
|
<HairyComment v-if="comment" />
|
18
18
|
</div>
|
@@ -2,16 +2,19 @@
|
|
2
2
|
import { ElTabPane, ElTabs } from 'element-plus'
|
3
3
|
import 'element-plus/theme-chalk/el-tabs.css'
|
4
4
|
import 'element-plus/theme-chalk/el-tab-pane.css'
|
5
|
-
import { computed, provide, ref } from 'vue'
|
5
|
+
import { computed, provide, ref, watch } from 'vue'
|
6
6
|
|
7
7
|
import type { DefaultTheme } from 'valaxy/types'
|
8
8
|
import { useFrontmatter, useThemeConfig } from 'valaxy'
|
9
|
+
import { useOutline } from '../composables'
|
9
10
|
|
10
11
|
const active = ref('aside')
|
11
12
|
|
12
13
|
const frontmatter = useFrontmatter()
|
13
14
|
const themeConfig = useThemeConfig()
|
14
15
|
|
16
|
+
const { headers } = useOutline()
|
17
|
+
|
15
18
|
const pageOutline = computed<DefaultTheme.Config['outline']>(
|
16
19
|
() => frontmatter.value.outline ?? themeConfig.value.outline,
|
17
20
|
)
|
@@ -21,11 +24,20 @@ const pageOutlineNotUndefined = computed(() =>
|
|
21
24
|
)
|
22
25
|
|
23
26
|
provide('HairyUserTab:active', active)
|
27
|
+
|
28
|
+
const bars = computed<Record<string, boolean>>(() => ({
|
29
|
+
aside: pageOutlineNotUndefined.value && !!headers.value.length,
|
30
|
+
series: !!frontmatter.value.categories?.length,
|
31
|
+
user: true,
|
32
|
+
}))
|
33
|
+
const keys = computed(() => Object.keys(bars.value).filter(k => bars.value[k]))
|
34
|
+
|
35
|
+
watch(keys, keys => active.value = keys[0], { immediate: true })
|
24
36
|
</script>
|
25
37
|
|
26
38
|
<template>
|
27
|
-
<ElTabs v-model="active" class="pt-3">
|
28
|
-
<ElTabPane v-if="pageOutlineNotUndefined" name="aside">
|
39
|
+
<ElTabs v-if="keys.length > 1" v-model="active" stretch class="pt-3">
|
40
|
+
<ElTabPane v-if="pageOutlineNotUndefined && headers.length" name="aside">
|
29
41
|
<template #label>
|
30
42
|
<div class="flex items-center">
|
31
43
|
<div class="i-ri-list-check-2" />
|
@@ -34,7 +46,7 @@ provide('HairyUserTab:active', active)
|
|
34
46
|
</template>
|
35
47
|
<HairyOutline />
|
36
48
|
</ElTabPane>
|
37
|
-
<ElTabPane label="Series" name="series">
|
49
|
+
<ElTabPane v-if="frontmatter.categories" label="Series" name="series">
|
38
50
|
<template #label>
|
39
51
|
<div class="flex items-center gap-1">
|
40
52
|
<div class="i-ri-flow-chart" />
|
@@ -53,4 +65,6 @@ provide('HairyUserTab:active', active)
|
|
53
65
|
<HairySidebar />
|
54
66
|
</ElTabPane>
|
55
67
|
</ElTabs>
|
68
|
+
|
69
|
+
<HairySidebar v-else />
|
56
70
|
</template>
|
package/components/PageTags.vue
CHANGED
@@ -20,13 +20,25 @@ whenever(() => !visible.value, () => {
|
|
20
20
|
</script>
|
21
21
|
|
22
22
|
<template>
|
23
|
-
<
|
24
|
-
<div
|
25
|
-
<
|
26
|
-
|
27
|
-
|
23
|
+
<Transition>
|
24
|
+
<div v-if="visible" role="button" class="DocSearch DocSearch-Container " @click="visible = false">
|
25
|
+
<div class="DocSearch-Modal" style="--docsearch-vh: 5.5200000000000005px;" @click.stop>
|
26
|
+
<HairyFuseSearchHeader v-model:text="text" v-model:visible="visible" />
|
27
|
+
<HairyFuseSearchDropdown v-model:visible="visible" :text="text" />
|
28
|
+
<HairyFuseSearchFooter />
|
29
|
+
</div>
|
28
30
|
</div>
|
29
|
-
</
|
31
|
+
</Transition>
|
30
32
|
</template>
|
31
33
|
|
32
|
-
<style lang="scss"
|
34
|
+
<style lang="scss">
|
35
|
+
.v-enter-active,
|
36
|
+
.v-leave-active {
|
37
|
+
transition: opacity 0.3s ease;
|
38
|
+
}
|
39
|
+
|
40
|
+
.v-enter-from,
|
41
|
+
.v-leave-to {
|
42
|
+
opacity: 0;
|
43
|
+
}
|
44
|
+
</style>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import { useModel } from 'vue'
|
2
|
+
import { onMounted, ref, useModel } from 'vue'
|
3
3
|
|
4
4
|
const props = defineProps<{
|
5
5
|
text: string
|
@@ -8,6 +8,8 @@ const props = defineProps<{
|
|
8
8
|
|
9
9
|
const text = useModel(props, 'text')
|
10
10
|
const visible = useModel(props, 'visible')
|
11
|
+
const inputRef = ref<HTMLInputElement>()
|
12
|
+
onMounted(() => inputRef.value?.focus())
|
11
13
|
</script>
|
12
14
|
|
13
15
|
<template>
|
@@ -16,7 +18,7 @@ const visible = useModel(props, 'visible')
|
|
16
18
|
<label id="docsearch-label" class="DocSearch-MagnifierLabel" for="docsearch-input">
|
17
19
|
<svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" /></svg>
|
18
20
|
</label>
|
19
|
-
<input id="docsearch-input" v-model="text" class="DocSearch-Input" aria-autocomplete="both" aria-labelledby="docsearch-label" autocomplete="off" autocorrect="off" autocapitalize="off" enterkeyhint="go" spellcheck="false" autofocus="true" placeholder="Search docs" maxlength="64" type="search" aria-activedescendant="docsearch-item-0" aria-controls="docsearch-list">
|
21
|
+
<input id="docsearch-input" ref="inputRef" v-model="text" class="DocSearch-Input" aria-autocomplete="both" aria-labelledby="docsearch-label" autocomplete="off" autocorrect="off" autocapitalize="off" enterkeyhint="go" spellcheck="false" autofocus="true" placeholder="Search docs" maxlength="64" type="search" aria-activedescendant="docsearch-item-0" aria-controls="docsearch-list">
|
20
22
|
<button type="reset" title="Clear the query" class="DocSearch-Reset" aria-label="Clear the query" :hidden="!text" @click="text = ''">
|
21
23
|
<svg width="20" height="20" viewBox="0 0 20 20"><path d="M10 10l5.09-5.09L10 10l5.09 5.09L10 10zm0 0L4.91 4.91 10 10l-5.09 5.09L10 10z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" /></svg>
|
22
24
|
</button>
|
package/composables/category.ts
CHANGED
@@ -8,8 +8,6 @@ import { isEqual } from 'lodash-es'
|
|
8
8
|
export function useCategory(categories: MaybeRef<string[]>) {
|
9
9
|
const all = useCategories()
|
10
10
|
|
11
|
-
unref(categories)
|
12
|
-
// [BBB]
|
13
11
|
return computed(() => {
|
14
12
|
let parent: PostFrontMatter & Partial<CategoryList> = all.value as any
|
15
13
|
for (const category of unref(categories)) {
|
@@ -21,6 +19,7 @@ export function useCategory(categories: MaybeRef<string[]>) {
|
|
21
19
|
}
|
22
20
|
}
|
23
21
|
}
|
22
|
+
|
24
23
|
return parent
|
25
24
|
})
|
26
25
|
}
|
package/layouts/post.vue
CHANGED
@@ -34,7 +34,7 @@ function displayTag(tag: string) {
|
|
34
34
|
</div>
|
35
35
|
<div v-if="post.tags?.length" class="tags flex-center gap-2 mt-2">
|
36
36
|
<ElTag v-for="(tag) in post.tags" :key="tag" class="dark:bg-dark-50 cursor-pointer" @click="displayTag(tag)">
|
37
|
-
{{ tag }}
|
37
|
+
{{ $t(tag, {}, { missingWarn: false }) }}
|
38
38
|
</ElTag>
|
39
39
|
</div>
|
40
40
|
</template>
|
package/package.json
CHANGED
@@ -14,7 +14,9 @@ const router = useRouter()
|
|
14
14
|
const route = useRoute()
|
15
15
|
|
16
16
|
const categories = computed(() => route.params.its as string)
|
17
|
+
|
17
18
|
const paths = computed(() => categories.value.split('/').filter(Boolean))
|
19
|
+
|
18
20
|
const current = useCategory(paths)
|
19
21
|
const posts = useCategoryPost(paths)
|
20
22
|
|
@@ -26,7 +28,8 @@ function getBreadcrumbPath(index: number) {
|
|
26
28
|
}
|
27
29
|
|
28
30
|
function displayCategory(key: string) {
|
29
|
-
|
31
|
+
const paths = categories.value.split('/').filter(Boolean) // [Notes, Client]
|
32
|
+
router.push({ path: `/categories/${[...paths, key].join('/')}` })
|
30
33
|
}
|
31
34
|
</script>
|
32
35
|
|
@@ -4,7 +4,7 @@ import { usePostList } from 'valaxy'
|
|
4
4
|
import { ElTimeline, ElTimelineItem } from 'element-plus'
|
5
5
|
import { useRoute } from 'vue-router'
|
6
6
|
|
7
|
-
const tag = computed(() => useRoute().params.tag)
|
7
|
+
const tag = computed(() => useRoute().params.tag as string)
|
8
8
|
|
9
9
|
const posts = computed<any[]>(() =>
|
10
10
|
usePostList().value.filter(post => post.tags?.includes(tag.value as string)),
|
@@ -17,7 +17,7 @@ const posts = computed<any[]>(() =>
|
|
17
17
|
首页
|
18
18
|
</HairyBreadcrumbItem>
|
19
19
|
<HairyBreadcrumbItem>
|
20
|
-
{{ tag }}
|
20
|
+
{{ $t(tag, {}, { missingWarn: false }) }}
|
21
21
|
</HairyBreadcrumbItem>
|
22
22
|
</HairyBreadcrumb>
|
23
23
|
<ElTimeline>
|