valaxy-theme-hairy 0.2.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. package/client/index.ts +1 -0
  2. package/components/HairyBody.vue +15 -17
  3. package/components/HairyComment.vue +33 -0
  4. package/components/HairyContainer.vue +13 -0
  5. package/components/{HairyUserPopup.vue → HairyDrawer.vue} +14 -13
  6. package/components/HairyFooter.vue +12 -9
  7. package/components/HairyHeader.vue +10 -9
  8. package/components/HairyImage.vue +2 -1
  9. package/components/HairyImageGroup.vue +12 -16
  10. package/components/HairyNavbar.vue +56 -0
  11. package/components/{HairyPostList.vue → HairyPosts.vue} +3 -3
  12. package/components/{HairyNavSearch.vue → HairySearch.vue} +23 -87
  13. package/components/{HairyUserCard.vue → HairySidebar.vue} +4 -4
  14. package/components/{HairyUserTab.vue → HairyTabbar.vue} +27 -11
  15. package/components/PageTags.vue +48 -0
  16. package/components/ValaxyMain.vue +3 -3
  17. package/components/navbar/HairyNav.vue +16 -0
  18. package/components/navbar/HairyNavExpand.vue +12 -0
  19. package/components/navbar/HairyNavItem.vue +35 -0
  20. package/components/navbar/HairyNavbarBackground.vue +7 -0
  21. package/components/navbar/HairyNavbarSearch.vue +8 -0
  22. package/components/{HairyNavTitle.vue → navbar/HairyNavbarTitle.vue} +5 -3
  23. package/components/navbar/HairyNavbarToggleDark.vue +22 -0
  24. package/components/{HairyBreadcrumb.vue → parts/HairyBreadcrumb.vue} +1 -1
  25. package/components/{HairyBreadcrumbItem.vue → parts/HairyBreadcrumbItem.vue} +1 -4
  26. package/components/{lib/fish.js → parts/HairyFootFish.js} +5 -7
  27. package/components/parts/HairyFootFish.vue +38 -0
  28. package/components/{HairyPostTitle.vue → parts/HairyHeadHero.vue} +6 -5
  29. package/components/{HairyWaves.vue → parts/HairyHeadWaves.vue} +5 -5
  30. package/components/parts/HairyImageGlobal.vue +51 -0
  31. package/components/{HairyImageViewer.vue → parts/HairyImageViewer.vue} +4 -3
  32. package/components/parts/HairyLink.vue +21 -0
  33. package/components/{HairyMenu.vue → parts/HairyMenu.vue} +2 -1
  34. package/components/{HairyMenuItem.vue → parts/HairyMenuItem.vue} +11 -4
  35. package/components/parts/HairyOutline.vue +99 -0
  36. package/components/parts/HairyOutlineItem.vue +48 -0
  37. package/components/{HairySocialLinks.vue → parts/HairySocialLinks.vue} +2 -2
  38. package/components/{HairyTimelinePostItem.vue → parts/HairyTimelineContent.vue} +7 -8
  39. package/components/parts/HairyUserNav.vue +95 -0
  40. package/components/{article-layout → posts}/HairyArticleImage.vue +18 -19
  41. package/components/{article-layout → posts}/HairyArticleSeries.vue +8 -5
  42. package/components/{article-layout → posts}/HairyArticleText.vue +11 -4
  43. package/components/posts/HairyPostFooter.vue +15 -0
  44. package/components/{article-layout → posts}/HairyPostImageList.vue +4 -5
  45. package/components/{article-layout → posts}/HairyPostTextsList.vue +0 -1
  46. package/components/posts/HairyPostToggleLayout.vue +36 -0
  47. package/components/third/HairyAlgoliaSearch.vue +17 -0
  48. package/components/third/HairyFuseSearch.vue +10 -0
  49. package/components/third/HairyFuseSearchDialog.vue +32 -0
  50. package/components/third/HairyFuseSearchDropdown.vue +77 -0
  51. package/components/third/HairyFuseSearchFooter.vue +28 -0
  52. package/components/third/HairyFuseSearchHeader.vue +30 -0
  53. package/components/third/HairyFuseSearchHit.vue +52 -0
  54. package/components/third/HairySearchBtnDisplay.vue +29 -0
  55. package/components/third/HairySearchBtnInput.vue +20 -0
  56. package/components/third/HairySearchBtnKeys.vue +19 -0
  57. package/components/{HairyCarousel.vue → third/HairySwiperCarousel.vue} +6 -6
  58. package/{hooks/useYearArchives.ts → composables/archives.ts} +4 -3
  59. package/composables/category.ts +43 -0
  60. package/composables/config.ts +11 -0
  61. package/composables/dark.ts +13 -0
  62. package/composables/fuse.ts +60 -0
  63. package/composables/index.ts +8 -0
  64. package/composables/layout.ts +16 -0
  65. package/composables/outline.ts +49 -0
  66. package/composables/tags.ts +36 -0
  67. package/layouts/archive-month.vue +13 -0
  68. package/layouts/archive-year.vue +13 -0
  69. package/layouts/archive.vue +11 -0
  70. package/layouts/categories.vue +11 -4
  71. package/layouts/default.vue +8 -7
  72. package/layouts/home.vue +28 -18
  73. package/layouts/post.vue +41 -35
  74. package/layouts/tag.vue +8 -4
  75. package/layouts/tags.vue +11 -4
  76. package/{modules → library}/loading.ts +18 -6
  77. package/{modules → library}/scroll.ts +3 -2
  78. package/locales/zh-CN.yml +0 -2
  79. package/node/images/default.json +139 -0
  80. package/node/images/index.ts +46 -0
  81. package/node/index.ts +2 -0
  82. package/node/theme/index.ts +78 -0
  83. package/package.json +22 -28
  84. package/pages/archives/[year]/[month]/index.vue +15 -16
  85. package/pages/archives/[year]/index.vue +20 -18
  86. package/pages/archives/index.vue +10 -8
  87. package/pages/categories/{[...categories].vue → [...its].vue} +29 -34
  88. package/pages/index.vue +1 -1
  89. package/pages/page/[page].vue +2 -2
  90. package/pages/tags/{[tag].vue → [tag]/index.vue} +12 -12
  91. package/pages/tags/index.vue +12 -5
  92. package/setup/main.ts +1 -1
  93. package/store/index.ts +1 -0
  94. package/store/modules/global.ts +12 -0
  95. package/styles/components/index.scss +4 -0
  96. package/styles/{markdown.scss → components/markdown.scss} +2 -1
  97. package/styles/components/nprogress.scss +16 -0
  98. package/styles/css-vars.scss +11 -0
  99. package/styles/element-plus/tabs.scss +1 -1
  100. package/styles/element-plus/timeline.scss +1 -1
  101. package/styles/global.scss +39 -0
  102. package/styles/index.scss +4 -73
  103. package/tsconfig.json +27 -0
  104. package/types/index.d.ts +163 -0
  105. package/unocss.config.ts +5 -1
  106. package/utils/index.ts +21 -39
  107. package/valaxy.config.ts +21 -24
  108. package/@types/markdown-it.d.ts +0 -1
  109. package/@types/markdown-toc.d.ts +0 -1
  110. package/@types/types.d.ts +0 -1
  111. package/@types/valaxy.d.ts +0 -10
  112. package/components/HairyAlgoliaSearchBox.vue +0 -118
  113. package/components/HairyBackToTop.vue +0 -72
  114. package/components/HairyDivider.vue +0 -0
  115. package/components/HairyFooterFish.vue +0 -29
  116. package/components/HairyLayout.vue +0 -28
  117. package/components/HairyLink.vue +0 -10
  118. package/components/HairyLinks.vue +0 -69
  119. package/components/HairyMeting.vue +0 -19
  120. package/components/HairyNav.vue +0 -42
  121. package/components/HairyNavBackground.vue +0 -7
  122. package/components/HairyNavMenu.vue +0 -11
  123. package/components/HairyNavToggleDark.vue +0 -16
  124. package/components/HairyPostToggleLayout.vue +0 -33
  125. package/components/HairyToc.vue +0 -135
  126. package/components/HairyUserNav.vue +0 -64
  127. package/components/HairyWaline.vue +0 -44
  128. package/hooks/setupDefaultDark.ts +0 -11
  129. package/hooks/useCategory.ts +0 -18
  130. package/hooks/useCategoryPost.ts +0 -21
  131. package/hooks/useContext.ts +0 -13
  132. package/hooks/useHeaderHeight.ts +0 -9
  133. package/hooks/usePostLayout.ts +0 -16
  134. package/images.json +0 -140
  135. package/index.d.ts +0 -100
  136. package/layouts/archives.vue +0 -11
  137. package/layouts/hairy.vue +0 -36
  138. package/layouts/month.vue +0 -6
  139. package/layouts/year.vue +0 -6
  140. package/node/addon-hairy.ts +0 -36
  141. package/node/addon-images.ts +0 -61
  142. package/node/addon-meting.ts +0 -13
  143. package/node/addon-statistics.ts +0 -19
  144. package/node/addon-toc.ts +0 -20
  145. package/node/utils.ts +0 -20
  146. package/utils/createContext.ts +0 -40
  147. package/utils/fonts.ts +0 -15
  148. /package/components/{HairyUserStats.vue → parts/HairyUserStats.vue} +0 -0
  149. /package/components/{article-layout → posts}/HairyArticleTop.vue +0 -0
  150. /package/{modules → library}/loading.scss +0 -0
  151. /package/{shims.d.ts → node/images/shims.d.ts} +0 -0
  152. /package/styles/{aplayer.scss → components/aplayer.scss} +0 -0
  153. /package/styles/{scrollbar.scss → components/scrollbar.scss} +0 -0
@@ -0,0 +1 @@
1
+ export * from '../composables'
@@ -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="HairyBody min-h-49vh relative">
13
- <div class="mx-auto breakpoint flex z-1 relative">
14
- <div class="relative flex-1 pt-2 w-0">
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
- <HairyWaline v-if="showWaline" />
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
- <HairyUserCard v-else />
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 transition-all duration-200;
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>
@@ -0,0 +1,13 @@
1
+ <script lang="ts" setup>
2
+ import { onMounted } from 'vue'
3
+ import { setupDefaultDark } from '../composables'
4
+
5
+ onMounted(setupDefaultDark)
6
+ </script>
7
+
8
+ <template>
9
+ <div class="min-h-80vh">
10
+ <slot />
11
+ <HairyDrawer />
12
+ </div>
13
+ </template>
@@ -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 { computed, watch } from 'vue'
6
- import { useContext } from '../hooks/useContext'
7
- const { drawerShow } = useContext()
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
- watch(() => route.fullPath, () => {
12
- drawerShow.value = false
13
- })
11
+ const { showDrawer } = storeToRefs(useGlobalStore())
12
+
13
+ watch(() => route.fullPath, () => showDrawer.value = false)
14
14
  </script>
15
15
 
16
16
  <template>
17
- <el-drawer v-model="drawerShow" direction="ltr" size="auto" @close="drawerShow = false">
18
- <HairyUserTab v-if="isPost" />
19
- <HairyUserCard v-else />
20
- <div class="dark:hidden absolute inset-0 bg-white bg-opacity-85 blur-5" />
21
- </el-drawer>
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 HairyFooterFish from './HairyFooterFish.vue'
6
+ import type { HairyTheme } from 'valaxy-theme-hairy'
7
7
 
8
8
  const { t } = useI18n()
9
9
 
10
10
  const config = useConfig()
11
- const themeConfig = useThemeConfig()
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.since
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.icon)
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>{{ config.author.name }}</span>
47
+ <span>{{ sideConfig.author.name }}</span>
45
48
  <span class="mx-2">|</span>
46
- <span v-if="config.comment.waline" class="flex items-center">
49
+ <span class="flex items-center">
47
50
  <div class="i-ri-eye-fill mr-1" />
48
- <span class="waline-pageview-count" data-path="/">1</span>
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
- <HairyFooterFish />
60
+ <HairyFootFish />
58
61
  </footer>
59
62
  </template>
@@ -1,26 +1,27 @@
1
1
  <script lang="ts" setup>
2
- import { useContext } from '../hooks/useContext'
2
+ import { storeToRefs } from 'pinia'
3
+ import { useGlobalStore } from '../store'
3
4
 
4
5
  defineProps<{
5
- headline?: String
6
- title?: String
6
+ headline?: string
7
+ title?: string
7
8
  description?: string
8
9
  }>()
9
10
 
10
- const { headerRef } = useContext()
11
+ const { headerRef } = storeToRefs(useGlobalStore())
11
12
  </script>
12
13
 
13
14
  <template>
14
- <header ref="headerRef" class="HairyHeader relative animate__animated animate__fadeIn">
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
- <HairyPostTitle v-if="title" class="relative z-2" :title="title" v-bind="$props">
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
- </HairyPostTitle>
21
+ </HairyHeadHero>
21
22
  </div>
22
- <HairyCarousel class="inset-0" style="position: absolute" />
23
- <HairyWaves class="relative z-10" />
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<(url: string) => void>('HairyImageGroup:preview')
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 { executeOverlay } from 'unoverlay-vue'
3
+ import { renderOverlay } from '@overlastic/vue'
4
4
  import type { ImageViewerProps } from 'element-plus/es/components/image-viewer/index'
5
- import type { AtWillNumber } from '../utils'
6
- import { atWillToUnit } from '../utils'
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?: AtWillNumber
11
- col?: AtWillNumber
12
- gap?: AtWillNumber
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
- const preview = (url: string) => {
37
+ function preview(url: string) {
40
38
  const initialIndex = paths.value.findIndex(v => v === url) || 0
41
- executeOverlay<Partial<ImageViewerProps>>(HairyImageViewer, {
42
- props: {
43
- urlList: paths.value,
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></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 { usePostLayout } from '../hooks/usePostLayout'
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 = usePostLayout()
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 '@docsearch/css'
3
- import { computed, defineAsyncComponent, onMounted, onUnmounted, ref } from 'vue'
4
- import { useConfig } from 'valaxy'
2
+ import { useSiteConfig } from 'valaxy'
3
+ import { computed } from 'vue'
5
4
 
6
- const HairyAlgoliaSearchBox = __ALGOLIA__
7
- ? defineAsyncComponent(() => import('./HairyAlgoliaSearchBox.vue'))
8
- : () => null
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
- <div v-if="enable" class="VPNavBarSearch">
52
- <HairyAlgoliaSearchBox v-if="loaded" />
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: border-color 0.25s;
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 !important;
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
- /* background: var(--hy-c-bg-alt); */
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 + .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 { useConfig, useThemeConfig } from 'valaxy'
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 = useConfig()
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
- <el-tabs v-model="active" class="pt-3">
12
- <el-tab-pane name="aside">
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
- <HairyToc />
20
- </el-tab-pane>
21
- <el-tab-pane label="Series" name="series">
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
- </el-tab-pane>
30
- <el-tab-pane label="User" name="user">
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
- <HairyUserCard />
38
- </el-tab-pane>
39
- </el-tabs>
53
+ <HairySidebar />
54
+ </ElTabPane>
55
+ </ElTabs>
40
56
  </template>