valaxy-theme-hairy 0.2.2 → 1.0.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/client/index.ts +1 -0
- package/components/HairyBody.vue +15 -17
- package/components/HairyComment.vue +33 -0
- package/components/HairyContainer.vue +13 -0
- package/components/{HairyUserPopup.vue → HairyDrawer.vue} +14 -13
- package/components/HairyFooter.vue +12 -9
- package/components/HairyHeader.vue +10 -9
- package/components/HairyImage.vue +2 -1
- package/components/HairyImageGroup.vue +12 -16
- package/components/HairyNavbar.vue +56 -0
- package/components/{HairyPostList.vue → HairyPosts.vue} +3 -3
- package/components/{HairyNavSearch.vue → HairySearch.vue} +23 -87
- package/components/{HairyUserCard.vue → HairySidebar.vue} +4 -4
- package/components/{HairyUserTab.vue → HairyTabbar.vue} +27 -11
- package/components/PageTags.vue +48 -0
- package/components/ValaxyMain.vue +3 -3
- package/components/navbar/HairyNav.vue +16 -0
- package/components/navbar/HairyNavExpand.vue +12 -0
- package/components/navbar/HairyNavItem.vue +35 -0
- package/components/navbar/HairyNavbarBackground.vue +7 -0
- package/components/navbar/HairyNavbarSearch.vue +8 -0
- package/components/{HairyNavTitle.vue → navbar/HairyNavbarTitle.vue} +5 -3
- package/components/navbar/HairyNavbarToggleDark.vue +22 -0
- package/components/{HairyBreadcrumb.vue → parts/HairyBreadcrumb.vue} +1 -1
- package/components/{HairyBreadcrumbItem.vue → parts/HairyBreadcrumbItem.vue} +1 -4
- package/components/{lib/fish.js → parts/HairyFootFish.js} +5 -7
- package/components/parts/HairyFootFish.vue +38 -0
- package/components/{HairyPostTitle.vue → parts/HairyHeadHero.vue} +6 -5
- package/components/{HairyWaves.vue → parts/HairyHeadWaves.vue} +5 -5
- package/components/parts/HairyImageGlobal.vue +51 -0
- package/components/{HairyImageViewer.vue → parts/HairyImageViewer.vue} +4 -3
- package/components/parts/HairyLink.vue +21 -0
- package/components/{HairyMenu.vue → parts/HairyMenu.vue} +2 -1
- package/components/{HairyMenuItem.vue → parts/HairyMenuItem.vue} +11 -4
- package/components/parts/HairyOutline.vue +99 -0
- package/components/parts/HairyOutlineItem.vue +48 -0
- package/components/{HairySocialLinks.vue → parts/HairySocialLinks.vue} +2 -2
- package/components/{HairyTimelinePostItem.vue → parts/HairyTimelineContent.vue} +7 -8
- package/components/parts/HairyUserNav.vue +95 -0
- package/components/{article-layout → posts}/HairyArticleImage.vue +18 -19
- package/components/{article-layout → posts}/HairyArticleSeries.vue +8 -5
- package/components/{article-layout → posts}/HairyArticleText.vue +11 -4
- package/components/posts/HairyPostFooter.vue +15 -0
- package/components/{article-layout → posts}/HairyPostImageList.vue +4 -5
- package/components/{article-layout → posts}/HairyPostTextsList.vue +0 -1
- package/components/posts/HairyPostToggleLayout.vue +36 -0
- package/components/third/HairyAlgoliaSearch.vue +17 -0
- package/components/third/HairyFuseSearch.vue +10 -0
- package/components/third/HairyFuseSearchDialog.vue +32 -0
- package/components/third/HairyFuseSearchDropdown.vue +77 -0
- package/components/third/HairyFuseSearchFooter.vue +28 -0
- package/components/third/HairyFuseSearchHeader.vue +30 -0
- package/components/third/HairyFuseSearchHit.vue +52 -0
- package/components/third/HairySearchBtnDisplay.vue +29 -0
- package/components/third/HairySearchBtnInput.vue +20 -0
- package/components/third/HairySearchBtnKeys.vue +19 -0
- package/components/{HairyCarousel.vue → third/HairySwiperCarousel.vue} +6 -6
- package/{hooks/useYearArchives.ts → composables/archives.ts} +4 -3
- package/composables/category.ts +43 -0
- package/composables/config.ts +11 -0
- package/composables/dark.ts +13 -0
- package/composables/fuse.ts +60 -0
- package/composables/index.ts +8 -0
- package/composables/layout.ts +16 -0
- package/composables/outline.ts +49 -0
- package/composables/tags.ts +36 -0
- package/layouts/archive-month.vue +13 -0
- package/layouts/archive-year.vue +13 -0
- package/layouts/archive.vue +11 -0
- package/layouts/categories.vue +11 -4
- package/layouts/default.vue +8 -7
- package/layouts/home.vue +28 -18
- package/layouts/post.vue +41 -35
- package/layouts/tag.vue +8 -4
- package/layouts/tags.vue +11 -4
- package/{modules → library}/loading.ts +18 -6
- package/{modules → library}/scroll.ts +3 -2
- package/locales/zh-CN.yml +0 -2
- package/node/images/default.json +139 -0
- package/node/images/index.ts +46 -0
- package/node/index.ts +2 -0
- package/node/theme/index.ts +78 -0
- package/package.json +22 -28
- package/pages/archives/[year]/[month]/index.vue +15 -16
- package/pages/archives/[year]/index.vue +20 -18
- package/pages/archives/index.vue +10 -8
- package/pages/categories/{[...categories].vue → [...its].vue} +29 -34
- package/pages/index.vue +1 -1
- package/pages/page/[page].vue +2 -2
- package/pages/tags/{[tag].vue → [tag]/index.vue} +12 -12
- package/pages/tags/index.vue +12 -5
- package/setup/main.ts +1 -1
- package/store/index.ts +1 -0
- package/store/modules/global.ts +12 -0
- package/styles/components/index.scss +4 -0
- package/styles/{markdown.scss → components/markdown.scss} +2 -1
- package/styles/components/nprogress.scss +16 -0
- package/styles/css-vars.scss +11 -0
- package/styles/element-plus/tabs.scss +1 -1
- package/styles/element-plus/timeline.scss +1 -1
- package/styles/global.scss +39 -0
- package/styles/index.scss +4 -73
- package/tsconfig.json +27 -0
- package/types/index.d.ts +163 -0
- package/unocss.config.ts +5 -1
- package/utils/index.ts +21 -39
- package/valaxy.config.ts +21 -24
- package/@types/markdown-it.d.ts +0 -1
- package/@types/markdown-toc.d.ts +0 -1
- package/@types/types.d.ts +0 -1
- package/@types/valaxy.d.ts +0 -10
- package/components/HairyAlgoliaSearchBox.vue +0 -118
- package/components/HairyBackToTop.vue +0 -72
- package/components/HairyDivider.vue +0 -0
- package/components/HairyFooterFish.vue +0 -29
- package/components/HairyLayout.vue +0 -28
- package/components/HairyLink.vue +0 -10
- package/components/HairyLinks.vue +0 -69
- package/components/HairyMeting.vue +0 -19
- package/components/HairyNav.vue +0 -42
- package/components/HairyNavBackground.vue +0 -7
- package/components/HairyNavMenu.vue +0 -11
- package/components/HairyNavToggleDark.vue +0 -16
- package/components/HairyPostToggleLayout.vue +0 -33
- package/components/HairyToc.vue +0 -135
- package/components/HairyUserNav.vue +0 -64
- package/components/HairyWaline.vue +0 -44
- package/hooks/setupDefaultDark.ts +0 -11
- package/hooks/useCategory.ts +0 -18
- package/hooks/useCategoryPost.ts +0 -21
- package/hooks/useContext.ts +0 -13
- package/hooks/useHeaderHeight.ts +0 -9
- package/hooks/usePostLayout.ts +0 -16
- package/images.json +0 -140
- package/index.d.ts +0 -100
- package/layouts/archives.vue +0 -11
- package/layouts/hairy.vue +0 -36
- package/layouts/month.vue +0 -6
- package/layouts/year.vue +0 -6
- package/node/addon-hairy.ts +0 -36
- package/node/addon-images.ts +0 -61
- package/node/addon-meting.ts +0 -13
- package/node/addon-statistics.ts +0 -19
- package/node/addon-toc.ts +0 -20
- package/node/utils.ts +0 -20
- package/utils/createContext.ts +0 -40
- package/utils/fonts.ts +0 -15
- /package/components/{HairyUserStats.vue → parts/HairyUserStats.vue} +0 -0
- /package/components/{article-layout → posts}/HairyArticleTop.vue +0 -0
- /package/{modules → library}/loading.scss +0 -0
- /package/{shims.d.ts → node/images/shims.d.ts} +0 -0
- /package/styles/{aplayer.scss → components/aplayer.scss} +0 -0
- /package/styles/{scrollbar.scss → components/scrollbar.scss} +0 -0
package/client/index.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export * from '../composables'
|
package/components/HairyBody.vue
CHANGED
@@ -1,43 +1,38 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import { useFrontmatter } from 'valaxy'
|
3
|
-
import { computed } from 'vue'
|
4
|
-
import { useRoute } from 'vue-router'
|
5
|
-
const fr = useFrontmatter()
|
6
|
-
const route = useRoute()
|
7
|
-
|
8
|
-
const showWaline = computed(() => route.path.includes('/posts/') || fr.value.waline)
|
9
2
|
</script>
|
10
3
|
|
11
4
|
<template>
|
12
|
-
<div class="
|
13
|
-
<div class="mx-auto
|
14
|
-
<div class="relative flex-1 pt-2
|
5
|
+
<div class="min-h-49vh relative z-5">
|
6
|
+
<div class="mx-auto container flex z-1 relative">
|
7
|
+
<div class="relative flex-1 pt-2 main">
|
15
8
|
<slot />
|
16
|
-
<
|
9
|
+
<HairyComment />
|
17
10
|
</div>
|
18
|
-
|
19
11
|
<div class="ml-4 w-60 lg:block hidden">
|
20
12
|
<div class="sticky top-3.125rem z-1">
|
21
13
|
<slot v-if="$slots.slide" name="slide" />
|
22
|
-
<
|
14
|
+
<HairySidebar v-else />
|
23
15
|
</div>
|
24
16
|
</div>
|
25
17
|
</div>
|
18
|
+
|
26
19
|
<div class="HairyBodyBackground" />
|
27
20
|
</div>
|
28
21
|
</template>
|
29
22
|
|
30
23
|
<style lang="scss">
|
31
24
|
.HairyBodyBackground {
|
32
|
-
@apply
|
33
|
-
@apply absolute top-0 max-h-150vh top-5 bottom-0 w-full transition-opacity;
|
25
|
+
@apply absolute top-0 max-h-150vh top-5 bottom-0 w-full;
|
34
26
|
opacity: 0;
|
35
27
|
}
|
28
|
+
.main {
|
29
|
+
background: linear-gradient(to bottom,#fafafa 0,#fff 20%) no-repeat top;
|
30
|
+
padding: 1.25rem;
|
31
|
+
border-radius: 10px
|
32
|
+
}
|
36
33
|
|
37
34
|
.dark {
|
38
35
|
.HairyBodyBackground {
|
39
|
-
transition-delay: 200ms;
|
40
|
-
transition-delay: 0;
|
41
36
|
opacity: 1;
|
42
37
|
background-image:
|
43
38
|
linear-gradient(to bottom, var(--hy-c-waves-dimm) 0%, transparent 60%, var(--hy-c-waves-dimm) 100%), url(./images/bg.jpg);
|
@@ -47,5 +42,8 @@ const showWaline = computed(() => route.path.includes('/posts/') || fr.value.wal
|
|
47
42
|
filter: blur(0px);
|
48
43
|
background-size: cover;
|
49
44
|
}
|
45
|
+
.main {
|
46
|
+
background: transparent;
|
47
|
+
}
|
50
48
|
}
|
51
49
|
</style>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<script lang="ts" setup>
|
2
|
+
import { useAddonWaline } from 'valaxy-addon-waline'
|
3
|
+
|
4
|
+
const addon = useAddonWaline()
|
5
|
+
</script>
|
6
|
+
|
7
|
+
<template>
|
8
|
+
<WalineClient w="full" :options="addon.options" />
|
9
|
+
</template>
|
10
|
+
|
11
|
+
<style lang="scss">
|
12
|
+
// 可以在此处覆盖 waline 样式
|
13
|
+
:root {
|
14
|
+
--waline-theme-color: var(--hy-c-primary);
|
15
|
+
--waline-active-color: var(--hy-c-primary-dark)
|
16
|
+
}
|
17
|
+
|
18
|
+
.wl-editor {
|
19
|
+
padding: 4px;
|
20
|
+
width: calc(100% - 1rem - 8px);
|
21
|
+
}
|
22
|
+
.wl-emoji-popup {
|
23
|
+
border-bottom: none !important;
|
24
|
+
z-index: 1000;
|
25
|
+
}
|
26
|
+
.wl-emoji-popup .wl-tabs {
|
27
|
+
height: auto !important;
|
28
|
+
overflow-x: auto !important;
|
29
|
+
padding: 0 !important;
|
30
|
+
margin-left: -1px;
|
31
|
+
margin-right: -1px;
|
32
|
+
}
|
33
|
+
</style>
|
@@ -2,23 +2,24 @@
|
|
2
2
|
import 'element-plus/es/components/drawer/style/index'
|
3
3
|
import { ElDrawer } from 'element-plus/es/components/drawer/index'
|
4
4
|
import { useRoute } from 'vue-router'
|
5
|
-
import {
|
6
|
-
import {
|
7
|
-
|
5
|
+
import { watch } from 'vue'
|
6
|
+
import { storeToRefs } from 'pinia'
|
7
|
+
import { useGlobalStore } from '../store'
|
8
|
+
|
8
9
|
const route = useRoute()
|
9
|
-
const isPost = computed(() => route.fullPath.includes('/posts/'))
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
const { showDrawer } = storeToRefs(useGlobalStore())
|
12
|
+
|
13
|
+
watch(() => route.fullPath, () => showDrawer.value = false)
|
14
14
|
</script>
|
15
15
|
|
16
16
|
<template>
|
17
|
-
<
|
18
|
-
<
|
19
|
-
<
|
20
|
-
<
|
21
|
-
|
17
|
+
<ElDrawer v-model="showDrawer" direction="ltr" size="auto" @close="showDrawer = false">
|
18
|
+
<div class="h-24px" />
|
19
|
+
<HairyTabbar v-if="route.fullPath.includes('/posts/')" />
|
20
|
+
<HairySidebar v-else />
|
21
|
+
<div class="dark:hidden absolute inset-0 bg-white bg-opacity-85" />
|
22
|
+
</ElDrawer>
|
22
23
|
</template>
|
23
24
|
|
24
25
|
<style lang="scss">
|
@@ -38,7 +39,7 @@ watch(() => route.fullPath, () => {
|
|
38
39
|
.dark {
|
39
40
|
.el-drawer {
|
40
41
|
background: radial-gradient(black, transparent);
|
41
|
-
|
42
|
+
box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
|
42
43
|
}
|
43
44
|
}
|
44
45
|
</style>
|
@@ -1,23 +1,26 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
2
|
import { capitalize, computed } from 'vue'
|
3
|
-
import { useConfig, useThemeConfig } from 'valaxy'
|
3
|
+
import { useConfig, useSiteConfig, useThemeConfig } from 'valaxy'
|
4
4
|
import { useI18n } from 'vue-i18n'
|
5
5
|
import pkg from 'valaxy/package.json'
|
6
|
-
import
|
6
|
+
import type { HairyTheme } from 'valaxy-theme-hairy'
|
7
7
|
|
8
8
|
const { t } = useI18n()
|
9
9
|
|
10
10
|
const config = useConfig()
|
11
|
-
const
|
11
|
+
const sideConfig = useSiteConfig()
|
12
|
+
const themeConfig = useThemeConfig<HairyTheme.Config>()
|
12
13
|
|
13
14
|
const year = new Date().getFullYear()
|
14
15
|
|
15
16
|
const isThisYear = computed(() => {
|
16
|
-
return year === themeConfig.value.footer
|
17
|
+
return year === themeConfig.value.footer?.since
|
17
18
|
})
|
18
19
|
|
19
20
|
const poweredHtml = computed(() => t('footer.powered', [`<a href="${pkg.repository}" target="_blank" rel="noopener">Valaxy</a> v${pkg.version}`]))
|
20
|
-
const footerIcon = computed(() => themeConfig.value.footer
|
21
|
+
const footerIcon = computed(() => themeConfig.value.footer?.icon)
|
22
|
+
|
23
|
+
// const frontmatter = useFrontmatter()
|
21
24
|
</script>
|
22
25
|
|
23
26
|
<template>
|
@@ -41,11 +44,11 @@ const footerIcon = computed(() => themeConfig.value.footer.icon)
|
|
41
44
|
<div :class="footerIcon.name" />
|
42
45
|
</a>
|
43
46
|
|
44
|
-
<span>{{
|
47
|
+
<span>{{ sideConfig.author.name }}</span>
|
45
48
|
<span class="mx-2">|</span>
|
46
|
-
<span
|
49
|
+
<span class="flex items-center">
|
47
50
|
<div class="i-ri-eye-fill mr-1" />
|
48
|
-
<span class="waline-pageview-count" data-path="/"
|
51
|
+
<span class="waline-pageview-count" data-path="/">-</span>
|
49
52
|
</span>
|
50
53
|
</div>
|
51
54
|
<div v-if="themeConfig.footer.powered" class="powered" m="2">
|
@@ -54,6 +57,6 @@ const footerIcon = computed(() => themeConfig.value.footer.icon)
|
|
54
57
|
</div>
|
55
58
|
|
56
59
|
<slot />
|
57
|
-
<
|
60
|
+
<HairyFootFish />
|
58
61
|
</footer>
|
59
62
|
</template>
|
@@ -1,26 +1,27 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import {
|
2
|
+
import { storeToRefs } from 'pinia'
|
3
|
+
import { useGlobalStore } from '../store'
|
3
4
|
|
4
5
|
defineProps<{
|
5
|
-
headline?:
|
6
|
-
title?:
|
6
|
+
headline?: string
|
7
|
+
title?: string
|
7
8
|
description?: string
|
8
9
|
}>()
|
9
10
|
|
10
|
-
const { headerRef } =
|
11
|
+
const { headerRef } = storeToRefs(useGlobalStore())
|
11
12
|
</script>
|
12
13
|
|
13
14
|
<template>
|
14
|
-
<header ref="headerRef" class="
|
15
|
+
<header ref="headerRef" class="relative animate__animated animate__fadeIn">
|
15
16
|
<div class="h-30vh lt-md:h-60vh min-h-80 flex-center">
|
16
|
-
<
|
17
|
+
<HairyHeadHero v-if="title || headline || description || $slots.description" class="relative z-2" :title="title" v-bind="$props">
|
17
18
|
<template #description>
|
18
19
|
<slot name="description" />
|
19
20
|
</template>
|
20
|
-
</
|
21
|
+
</HairyHeadHero>
|
21
22
|
</div>
|
22
|
-
<
|
23
|
-
<
|
23
|
+
<HairySwiperCarousel class="inset-0" style="position: absolute" />
|
24
|
+
<HairyHeadWaves class="relative z-10" />
|
24
25
|
</header>
|
25
26
|
</template>
|
26
27
|
|
@@ -2,9 +2,10 @@
|
|
2
2
|
import { ElImage, imageProps } from 'element-plus/es/components/image/index'
|
3
3
|
import 'element-plus/es/components/image/style/index'
|
4
4
|
import { inject } from 'vue'
|
5
|
+
|
5
6
|
const props = defineProps(imageProps)
|
6
7
|
|
7
|
-
const preview = inject<
|
8
|
+
const preview = inject<any>('HairyImageGroup:preview', undefined)
|
8
9
|
</script>
|
9
10
|
|
10
11
|
<template>
|
@@ -1,19 +1,17 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
2
|
import { computed, provide, useCssVars, useSlots } from 'vue'
|
3
|
-
import {
|
3
|
+
import { renderOverlay } from '@overlastic/vue'
|
4
4
|
import type { ImageViewerProps } from 'element-plus/es/components/image-viewer/index'
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import HairyImageViewer from './HairyImageViewer.vue'
|
5
|
+
import { atWillToUnit } from '@hairy/utils'
|
6
|
+
import HairyImageViewer from './parts/HairyImageViewer.vue'
|
8
7
|
|
9
8
|
const props = withDefaults(defineProps<{
|
10
|
-
row?:
|
11
|
-
col?:
|
12
|
-
gap?:
|
9
|
+
row?: string | number
|
10
|
+
col?: string | number
|
11
|
+
gap?: string | number
|
13
12
|
justify?: string
|
14
13
|
align?: string
|
15
|
-
}>(),
|
16
|
-
{
|
14
|
+
}>(), {
|
17
15
|
row: 'auto',
|
18
16
|
col: 'auto',
|
19
17
|
gap: 10,
|
@@ -36,13 +34,11 @@ const paths = computed(() => slots
|
|
36
34
|
.filter(Boolean) as string[],
|
37
35
|
)
|
38
36
|
|
39
|
-
|
37
|
+
function preview(url: string) {
|
40
38
|
const initialIndex = paths.value.findIndex(v => v === url) || 0
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
initialIndex,
|
45
|
-
},
|
39
|
+
renderOverlay<Partial<ImageViewerProps>>(HairyImageViewer, {
|
40
|
+
urlList: paths.value,
|
41
|
+
initialIndex,
|
46
42
|
})
|
47
43
|
}
|
48
44
|
|
@@ -51,7 +47,7 @@ provide('HairyImageGroup:preview', preview)
|
|
51
47
|
|
52
48
|
<template>
|
53
49
|
<div class="HairyImageGroup">
|
54
|
-
<slot
|
50
|
+
<slot />
|
55
51
|
</div>
|
56
52
|
</template>
|
57
53
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<script lang="ts" setup>
|
2
|
+
import { storeToRefs } from 'pinia'
|
3
|
+
import { computed, onMounted, ref } from 'vue'
|
4
|
+
import { useElementSize, useScroll, whenever } from '@vueuse/core'
|
5
|
+
import { useSiteConfig } from 'valaxy'
|
6
|
+
import { useGlobalStore } from '../store'
|
7
|
+
|
8
|
+
// get header height
|
9
|
+
const globalStore = useGlobalStore()
|
10
|
+
const { headerRef } = storeToRefs(globalStore)
|
11
|
+
const headerSize = useElementSize(headerRef)
|
12
|
+
const headerHeight = computed(() => headerSize.height.value)
|
13
|
+
|
14
|
+
// get document scroll
|
15
|
+
const documentRef = ref()
|
16
|
+
const scroll = useScroll(documentRef)
|
17
|
+
const dire = ref<'top' | 'bottom'>('top')
|
18
|
+
|
19
|
+
whenever(() => scroll.directions.top, () => dire.value = 'top')
|
20
|
+
whenever(() => scroll.directions.bottom, () => dire.value = 'bottom')
|
21
|
+
|
22
|
+
const show = computed(() => {
|
23
|
+
return scroll.y.value < (headerHeight.value / 2)
|
24
|
+
|| dire.value === 'top'
|
25
|
+
})
|
26
|
+
const config = useSiteConfig()
|
27
|
+
onMounted(() => documentRef.value = document)
|
28
|
+
</script>
|
29
|
+
|
30
|
+
<template>
|
31
|
+
<div
|
32
|
+
class="fixed w-full h-3.125rem lt-sm:h-3.5rem top-0 opacity-0 z-10000"
|
33
|
+
:class="[show && 'opacity-100']"
|
34
|
+
>
|
35
|
+
<div class="px-12px md:px-0 mx-auto container flex relative z-1 h-full">
|
36
|
+
<div class="flex items-center lt-sm:order-1 lt-sm:flex-1 justify-center">
|
37
|
+
<HairyLink class="px-2.5" type="white" :href="config.url">
|
38
|
+
{{ config.title }}
|
39
|
+
</HairyLink>
|
40
|
+
</div>
|
41
|
+
<div class="flex items-center sm:flex-1">
|
42
|
+
<HairyNavExpand class="sm:hidden pl-2 pr-13" />
|
43
|
+
<HairyNav class="lt-sm:hidden" />
|
44
|
+
<slot name="nav" />
|
45
|
+
</div>
|
46
|
+
<div class="flex-center order-1">
|
47
|
+
<HairyNavbarToggleDark />
|
48
|
+
<HairySearch />
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
|
52
|
+
<HairyNavbarBackground />
|
53
|
+
</div>
|
54
|
+
</template>
|
55
|
+
|
56
|
+
<style lang="scss" scoped></style>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
import { computed, defineProps, ref, withDefaults } from 'vue'
|
3
3
|
import type { Post } from 'valaxy'
|
4
4
|
import { usePostList } from 'valaxy'
|
5
|
-
import {
|
5
|
+
import { useLayoutPost } from '../composables'
|
6
6
|
|
7
7
|
const props = withDefaults(defineProps<{
|
8
8
|
type?: string
|
@@ -13,7 +13,7 @@ const props = withDefaults(defineProps<{
|
|
13
13
|
curPage: 1,
|
14
14
|
pagination: false,
|
15
15
|
})
|
16
|
-
const layout =
|
16
|
+
const layout = useLayoutPost()
|
17
17
|
|
18
18
|
const pageSize = ref(7)
|
19
19
|
const routes = usePostList({ type: props.type || '' })
|
@@ -27,7 +27,7 @@ const displayedPosts = computed(() => props.pagination ? pagePosts.value : posts
|
|
27
27
|
<HairyPostToggleLayout />
|
28
28
|
<HairyPostImageList v-if="layout.includes('image')" :posts="displayedPosts" />
|
29
29
|
<HairyPostTextsList v-else :posts="displayedPosts" />
|
30
|
-
<ValaxyPagination v-if="pagination" :cur-page="curPage" :page-size="pageSize" :total="posts.length" />
|
30
|
+
<ValaxyPagination v-if="pagination" class="mb-6" :cur-page="curPage" :page-size="pageSize" :total="posts.length" />
|
31
31
|
</div>
|
32
32
|
</template>
|
33
33
|
|
@@ -1,89 +1,18 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import '
|
3
|
-
import { computed
|
4
|
-
import { useConfig } from 'valaxy'
|
2
|
+
import { useSiteConfig } from 'valaxy'
|
3
|
+
import { computed } from 'vue'
|
5
4
|
|
6
|
-
const
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
const config = useConfig()
|
11
|
-
const search = computed(() => config.value.search)
|
12
|
-
const enable = computed(() => search.value.algolia.enable)
|
13
|
-
|
14
|
-
// to avoid loading the docsearch js upfront (which is more than 1/3 of the
|
15
|
-
// payload), we delay initializing it until the user has actually clicked or
|
16
|
-
// hit the hotkey to invoke it.
|
17
|
-
const loaded = ref(false)
|
18
|
-
|
19
|
-
const metaKey = ref()
|
20
|
-
|
21
|
-
onMounted(() => {
|
22
|
-
if (!search.value.enable || !search.value.algolia.enable)
|
23
|
-
return
|
24
|
-
|
25
|
-
// meta key detect (same logic as in @docsearch/js)
|
26
|
-
metaKey.value.textContent = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)
|
27
|
-
? '⌘'
|
28
|
-
: 'Ctrl'
|
29
|
-
|
30
|
-
const handleSearchHotKey = (e: KeyboardEvent) => {
|
31
|
-
if (e.key === 'k' && (e.ctrlKey || e.metaKey)) {
|
32
|
-
e.preventDefault()
|
33
|
-
load()
|
34
|
-
remove()
|
35
|
-
}
|
36
|
-
}
|
37
|
-
function remove() {
|
38
|
-
window.removeEventListener('keydown', handleSearchHotKey)
|
39
|
-
}
|
40
|
-
|
41
|
-
window.addEventListener('keydown', handleSearchHotKey)
|
42
|
-
onUnmounted(remove)
|
43
|
-
})
|
44
|
-
function load() {
|
45
|
-
if (!loaded.value)
|
46
|
-
loaded.value = true
|
47
|
-
}
|
5
|
+
const siteConfig = useSiteConfig()
|
6
|
+
const isAlgolia = computed(() => siteConfig.value.search.type === 'algolia')
|
7
|
+
const isFuse = computed(() => siteConfig.value.search.type === 'fuse')
|
48
8
|
</script>
|
49
9
|
|
50
10
|
<template>
|
51
|
-
<
|
52
|
-
|
53
|
-
<div v-else id="docsearch" @click="load">
|
54
|
-
<button
|
55
|
-
type="button"
|
56
|
-
class="DocSearch DocSearch-Button"
|
57
|
-
aria-label="Search"
|
58
|
-
>
|
59
|
-
<span class="DocSearch-Button-Container lt-sm:text-size-xl">
|
60
|
-
<svg
|
61
|
-
class="DocSearch-Search-Icon"
|
62
|
-
width="20"
|
63
|
-
height="20"
|
64
|
-
viewBox="0 0 20 20"
|
65
|
-
>
|
66
|
-
<path
|
67
|
-
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"
|
68
|
-
stroke="currentColor"
|
69
|
-
fill="none"
|
70
|
-
fill-rule="evenodd"
|
71
|
-
stroke-linecap="round"
|
72
|
-
stroke-linejoin="round"
|
73
|
-
/>
|
74
|
-
</svg>
|
75
|
-
<span class="DocSearch-Button-Placeholder">Search</span>
|
76
|
-
</span>
|
77
|
-
<span class="DocSearch-Button-Keys">
|
78
|
-
<kbd ref="metaKey" class="DocSearch-Button-Key">Meta</kbd>
|
79
|
-
<kbd class="DocSearch-Button-Key">K</kbd>
|
80
|
-
</span>
|
81
|
-
</button>
|
82
|
-
</div>
|
83
|
-
</div>
|
11
|
+
<HairyAlgoliaSearch v-if="isAlgolia" />
|
12
|
+
<HairyFuseSearch v-if="isFuse" />
|
84
13
|
</template>
|
85
14
|
|
86
|
-
<style>
|
15
|
+
<style lang="scss">
|
87
16
|
.VPNavBarSearch {
|
88
17
|
display: flex;
|
89
18
|
align-items: center;
|
@@ -133,7 +62,7 @@ function load() {
|
|
133
62
|
width: 32px;
|
134
63
|
height: 55px;
|
135
64
|
background: transparent;
|
136
|
-
transition:
|
65
|
+
transition: all 0.25s;
|
137
66
|
}
|
138
67
|
|
139
68
|
.DocSearch-Button:hover {
|
@@ -146,7 +75,7 @@ function load() {
|
|
146
75
|
}
|
147
76
|
|
148
77
|
.DocSearch-Button:focus:not(:focus-visible) {
|
149
|
-
outline: none
|
78
|
+
outline: none;
|
150
79
|
}
|
151
80
|
|
152
81
|
@media (min-width: 768px) {
|
@@ -161,8 +90,15 @@ function load() {
|
|
161
90
|
}
|
162
91
|
|
163
92
|
.DocSearch-Button:hover {
|
93
|
+
background-color: rgba(255, 255, 255, 0.4);
|
164
94
|
border-color: var(--hy-c-brand);
|
165
|
-
|
95
|
+
}
|
96
|
+
|
97
|
+
.dark {
|
98
|
+
.DocSearch-Button:hover {
|
99
|
+
background-color: transparent;
|
100
|
+
border-color: var(--hy-c-brand);
|
101
|
+
}
|
166
102
|
}
|
167
103
|
}
|
168
104
|
|
@@ -242,7 +178,7 @@ function load() {
|
|
242
178
|
transition: color 0.5s, border-color 0.5s;
|
243
179
|
}
|
244
180
|
|
245
|
-
.DocSearch-Button .DocSearch-Button-Key
|
181
|
+
.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key {
|
246
182
|
border-right: 1px solid var(--hy-c-divider);
|
247
183
|
border-left: none;
|
248
184
|
border-radius: 0 4px 4px 0;
|
@@ -250,10 +186,6 @@ function load() {
|
|
250
186
|
padding-right: 6px;
|
251
187
|
}
|
252
188
|
|
253
|
-
.dark .DocSearch-Footer {
|
254
|
-
border-top: 1px solid var(--hy-c-divider);
|
255
|
-
}
|
256
|
-
|
257
189
|
.DocSearch-Form {
|
258
190
|
border: 1px solid var(--hy-c-brand);
|
259
191
|
background-color: var(--hy-c-white);
|
@@ -262,4 +194,8 @@ function load() {
|
|
262
194
|
.dark .DocSearch-Form {
|
263
195
|
background-color: var(--hy-c-bg-mute);
|
264
196
|
}
|
197
|
+
|
198
|
+
.dark .DocSearch-Footer {
|
199
|
+
border-top: 1px solid var(--hy-c-divider);
|
200
|
+
}
|
265
201
|
</style>
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import {
|
2
|
+
import { useSiteConfig, useThemeConfig } from 'valaxy'
|
3
3
|
import { computed } from 'vue'
|
4
4
|
import type { HairyTheme } from 'valaxy-theme-hairy'
|
5
5
|
|
6
|
-
const config =
|
7
|
-
const theme = useThemeConfig<HairyTheme>()
|
6
|
+
const config = useSiteConfig()
|
7
|
+
const theme = useThemeConfig<HairyTheme.Config>()
|
8
8
|
|
9
9
|
const name = computed(() => theme.value.user?.name || config.value.author.name)
|
10
10
|
const description = computed(() => theme.value.user?.description || config.value.description)
|
@@ -13,7 +13,7 @@ const description = computed(() => theme.value.user?.description || config.value
|
|
13
13
|
<template>
|
14
14
|
<div class="pt-5 animate__animated animate__fadeIn relative z-1">
|
15
15
|
<div class="flex flex-col items-center">
|
16
|
-
<img class="mx-auto w-40 rounded-full -mx-1px" :src="config.author.avatar"
|
16
|
+
<img class="mx-auto w-40 rounded-full -mx-1px" :src="config.author.avatar">
|
17
17
|
<div class="leading-loose mt-2">
|
18
18
|
{{ name }}
|
19
19
|
</div>
|
@@ -2,23 +2,39 @@
|
|
2
2
|
import { ElTabPane, ElTabs } from 'element-plus/es/components/tabs/index'
|
3
3
|
import 'element-plus/es/components/tabs/style/index'
|
4
4
|
import 'element-plus/es/components/tab-pane/style/index'
|
5
|
-
import { provide, ref } from 'vue'
|
5
|
+
import { computed, provide, ref } from 'vue'
|
6
|
+
|
7
|
+
import type { DefaultTheme } from 'valaxy/types'
|
8
|
+
import { useFrontmatter, useThemeConfig } from 'valaxy'
|
9
|
+
|
6
10
|
const active = ref('aside')
|
11
|
+
|
12
|
+
const frontmatter = useFrontmatter()
|
13
|
+
const themeConfig = useThemeConfig()
|
14
|
+
|
15
|
+
const pageOutline = computed<DefaultTheme.Config['outline']>(
|
16
|
+
() => frontmatter.value.outline ?? themeConfig.value.outline,
|
17
|
+
)
|
18
|
+
|
19
|
+
const pageOutlineNotUndefined = computed(() =>
|
20
|
+
typeof pageOutline.value !== 'undefined',
|
21
|
+
)
|
22
|
+
|
7
23
|
provide('HairyUserTab:active', active)
|
8
24
|
</script>
|
9
25
|
|
10
26
|
<template>
|
11
|
-
<
|
12
|
-
<
|
27
|
+
<ElTabs v-model="active" class="pt-3">
|
28
|
+
<ElTabPane v-if="pageOutlineNotUndefined" name="aside">
|
13
29
|
<template #label>
|
14
30
|
<div class="flex items-center">
|
15
31
|
<div class="i-ri-list-check-2" />
|
16
32
|
<span class="ml-1">Aside</span>
|
17
33
|
</div>
|
18
34
|
</template>
|
19
|
-
<
|
20
|
-
</
|
21
|
-
<
|
35
|
+
<HairyOutline />
|
36
|
+
</ElTabPane>
|
37
|
+
<ElTabPane label="Series" name="series">
|
22
38
|
<template #label>
|
23
39
|
<div class="flex items-center gap-1">
|
24
40
|
<div class="i-ri-flow-chart" />
|
@@ -26,15 +42,15 @@ provide('HairyUserTab:active', active)
|
|
26
42
|
</div>
|
27
43
|
</template>
|
28
44
|
<HairyArticleSeries />
|
29
|
-
</
|
30
|
-
<
|
45
|
+
</ElTabPane>
|
46
|
+
<ElTabPane label="User" name="user">
|
31
47
|
<template #label>
|
32
48
|
<div class="flex items-center gap-1">
|
33
49
|
<div class="i-ri-user-line" />
|
34
50
|
<span class="ml-1">User</span>
|
35
51
|
</div>
|
36
52
|
</template>
|
37
|
-
<
|
38
|
-
</
|
39
|
-
</
|
53
|
+
<HairySidebar />
|
54
|
+
</ElTabPane>
|
55
|
+
</ElTabs>
|
40
56
|
</template>
|