valaxy-theme-hairy 0.2.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) 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 +17 -0
  5. package/components/{HairyUserPopup.vue → HairyDrawer.vue} +16 -16
  6. package/components/HairyFooter.vue +12 -9
  7. package/components/HairyHeader.vue +10 -9
  8. package/components/HairyImage.vue +3 -2
  9. package/components/HairyImageGroup.vue +12 -16
  10. package/components/HairyNavbar.vue +56 -0
  11. package/components/HairyPageArchives.vue +59 -0
  12. package/components/HairyPageTags.vue +48 -0
  13. package/components/{HairyPostList.vue → HairyPosts.vue} +3 -3
  14. package/components/{HairyNavSearch.vue → HairySearch.vue} +23 -87
  15. package/components/{HairyUserCard.vue → HairySidebar.vue} +4 -4
  16. package/components/HairyTabbar.vue +56 -0
  17. package/components/PageTags.vue +48 -0
  18. package/components/ValaxyMain.vue +3 -3
  19. package/components/navbar/HairyNav.vue +16 -0
  20. package/components/navbar/HairyNavExpand.vue +12 -0
  21. package/components/navbar/HairyNavItem.vue +35 -0
  22. package/components/navbar/HairyNavbarBackground.vue +7 -0
  23. package/components/navbar/HairyNavbarSearch.vue +8 -0
  24. package/components/{HairyNavTitle.vue → navbar/HairyNavbarTitle.vue} +5 -3
  25. package/components/navbar/HairyNavbarToggleDark.vue +22 -0
  26. package/components/{HairyBreadcrumb.vue → parts/HairyBreadcrumb.vue} +2 -2
  27. package/components/{HairyBreadcrumbItem.vue → parts/HairyBreadcrumbItem.vue} +1 -4
  28. package/components/{lib/fish.js → parts/HairyFootFish.js} +5 -7
  29. package/components/parts/HairyFootFish.vue +38 -0
  30. package/components/{HairyPostTitle.vue → parts/HairyHeadHero.vue} +6 -5
  31. package/components/{HairyWaves.vue → parts/HairyHeadWaves.vue} +5 -5
  32. package/components/parts/HairyImageGlobal.vue +51 -0
  33. package/components/{HairyImageViewer.vue → parts/HairyImageViewer.vue} +5 -4
  34. package/components/parts/HairyLink.vue +21 -0
  35. package/components/{HairyMenu.vue → parts/HairyMenu.vue} +2 -1
  36. package/components/{HairyMenuItem.vue → parts/HairyMenuItem.vue} +11 -4
  37. package/components/parts/HairyOutline.vue +99 -0
  38. package/components/parts/HairyOutlineItem.vue +48 -0
  39. package/components/{HairySocialLinks.vue → parts/HairySocialLinks.vue} +2 -2
  40. package/components/{HairyTimelinePostItem.vue → parts/HairyTimelineContent.vue} +7 -8
  41. package/components/parts/HairyUserNav.vue +95 -0
  42. package/components/{article-layout → posts}/HairyArticleImage.vue +18 -19
  43. package/components/{article-layout → posts}/HairyArticleSeries.vue +8 -5
  44. package/components/{article-layout → posts}/HairyArticleText.vue +11 -4
  45. package/components/posts/HairyPostFooter.vue +15 -0
  46. package/components/{article-layout → posts}/HairyPostImageList.vue +4 -5
  47. package/components/{article-layout → posts}/HairyPostTextsList.vue +0 -1
  48. package/components/posts/HairyPostToggleLayout.vue +36 -0
  49. package/components/third/HairyAlgoliaSearch.vue +17 -0
  50. package/components/third/HairyFuseSearch.vue +10 -0
  51. package/components/third/HairyFuseSearchDialog.vue +32 -0
  52. package/components/third/HairyFuseSearchDropdown.vue +77 -0
  53. package/components/third/HairyFuseSearchFooter.vue +28 -0
  54. package/components/third/HairyFuseSearchHeader.vue +30 -0
  55. package/components/third/HairyFuseSearchHit.vue +52 -0
  56. package/components/third/HairySearchBtnDisplay.vue +29 -0
  57. package/components/third/HairySearchBtnInput.vue +20 -0
  58. package/components/third/HairySearchBtnKeys.vue +19 -0
  59. package/components/{HairyCarousel.vue → third/HairySwiperCarousel.vue} +6 -6
  60. package/{hooks/useYearArchives.ts → composables/archives.ts} +4 -3
  61. package/composables/category.ts +43 -0
  62. package/composables/config.ts +11 -0
  63. package/composables/dark.ts +13 -0
  64. package/composables/fuse.ts +60 -0
  65. package/composables/index.ts +8 -0
  66. package/composables/layout.ts +16 -0
  67. package/composables/outline.ts +49 -0
  68. package/composables/tags.ts +36 -0
  69. package/layouts/archive-month.vue +13 -0
  70. package/layouts/archive-year.vue +13 -0
  71. package/layouts/archives.vue +9 -9
  72. package/layouts/categories.vue +11 -4
  73. package/layouts/default.vue +9 -3
  74. package/layouts/home.vue +28 -18
  75. package/layouts/post.vue +42 -36
  76. package/layouts/tag.vue +8 -4
  77. package/layouts/tags.vue +12 -4
  78. package/{modules → library}/loading.ts +18 -6
  79. package/{modules → library}/scroll.ts +3 -2
  80. package/locales/zh-CN.yml +0 -2
  81. package/node/images/default.json +139 -0
  82. package/node/images/index.ts +46 -0
  83. package/node/index.ts +2 -0
  84. package/node/theme/index.ts +78 -0
  85. package/package.json +22 -28
  86. package/pages/archives/[year]/[month]/index.vue +15 -18
  87. package/pages/archives/[year]/index.vue +20 -20
  88. package/pages/archives/index.vue +1 -54
  89. package/pages/categories/{[...categories].vue → [...its].vue} +29 -36
  90. package/pages/index.vue +1 -1
  91. package/pages/page/[page].vue +2 -2
  92. package/pages/tags/[tag]/index.vue +38 -0
  93. package/pages/tags/index.vue +1 -36
  94. package/setup/main.ts +1 -1
  95. package/store/index.ts +1 -0
  96. package/store/modules/global.ts +12 -0
  97. package/styles/components/index.scss +4 -0
  98. package/styles/{markdown.scss → components/markdown.scss} +2 -1
  99. package/styles/components/nprogress.scss +16 -0
  100. package/styles/css-vars.scss +11 -0
  101. package/styles/element-plus/tabs.scss +1 -1
  102. package/styles/element-plus/timeline.scss +1 -1
  103. package/styles/global.scss +39 -0
  104. package/styles/index.scss +4 -73
  105. package/tsconfig.json +27 -0
  106. package/types/index.d.ts +163 -0
  107. package/unocss.config.ts +5 -1
  108. package/utils/index.ts +21 -39
  109. package/valaxy.config.ts +21 -24
  110. package/@types/markdown-it.d.ts +0 -1
  111. package/@types/markdown-toc.d.ts +0 -1
  112. package/@types/types.d.ts +0 -1
  113. package/@types/valaxy.d.ts +0 -10
  114. package/components/HairyAlgoliaSearchBox.vue +0 -118
  115. package/components/HairyBackToTop.vue +0 -72
  116. package/components/HairyDivider.vue +0 -0
  117. package/components/HairyFooterFish.vue +0 -29
  118. package/components/HairyLayout.vue +0 -28
  119. package/components/HairyLink.vue +0 -10
  120. package/components/HairyLinks.vue +0 -69
  121. package/components/HairyMeting.vue +0 -19
  122. package/components/HairyNav.vue +0 -42
  123. package/components/HairyNavBackground.vue +0 -7
  124. package/components/HairyNavMenu.vue +0 -11
  125. package/components/HairyNavToggleDark.vue +0 -16
  126. package/components/HairyPostToggleLayout.vue +0 -33
  127. package/components/HairyToc.vue +0 -135
  128. package/components/HairyUserNav.vue +0 -64
  129. package/components/HairyUserTab.vue +0 -40
  130. package/components/HairyWaline.vue +0 -44
  131. package/hooks/setupDefaultDark.ts +0 -11
  132. package/hooks/useCategory.ts +0 -18
  133. package/hooks/useCategoryPost.ts +0 -21
  134. package/hooks/useContext.ts +0 -13
  135. package/hooks/useHeaderHeight.ts +0 -9
  136. package/hooks/usePostLayout.ts +0 -16
  137. package/images.json +0 -140
  138. package/index.d.ts +0 -100
  139. package/layouts/hairy.vue +0 -36
  140. package/layouts/month.vue +0 -6
  141. package/layouts/year.vue +0 -6
  142. package/node/addon-hairy.ts +0 -36
  143. package/node/addon-images.ts +0 -61
  144. package/node/addon-meting.ts +0 -13
  145. package/node/addon-statistics.ts +0 -19
  146. package/node/addon-toc.ts +0 -20
  147. package/node/utils.ts +0 -20
  148. package/pages/tags/[tag].vue +0 -40
  149. package/utils/createContext.ts +0 -40
  150. package/utils/fonts.ts +0 -15
  151. /package/components/{HairyUserStats.vue → parts/HairyUserStats.vue} +0 -0
  152. /package/components/{article-layout → posts}/HairyArticleTop.vue +0 -0
  153. /package/{modules → library}/loading.scss +0 -0
  154. /package/{shims.d.ts → node/images/shims.d.ts} +0 -0
  155. /package/styles/{aplayer.scss → components/aplayer.scss} +0 -0
  156. /package/styles/{scrollbar.scss → components/scrollbar.scss} +0 -0
@@ -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>
@@ -0,0 +1,56 @@
1
+ <script lang="ts" setup>
2
+ import { ElTabPane, ElTabs } from 'element-plus/es/components/tabs/index'
3
+ import 'element-plus/theme-chalk/el-tabs.css'
4
+ import 'element-plus/theme-chalk/el-tab-pane.css'
5
+ import { computed, provide, ref } from 'vue'
6
+
7
+ import type { DefaultTheme } from 'valaxy/types'
8
+ import { useFrontmatter, useThemeConfig } from 'valaxy'
9
+
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
+
23
+ provide('HairyUserTab:active', active)
24
+ </script>
25
+
26
+ <template>
27
+ <ElTabs v-model="active" class="pt-3">
28
+ <ElTabPane v-if="pageOutlineNotUndefined" name="aside">
29
+ <template #label>
30
+ <div class="flex items-center">
31
+ <div class="i-ri-list-check-2" />
32
+ <span class="ml-1">Aside</span>
33
+ </div>
34
+ </template>
35
+ <HairyOutline />
36
+ </ElTabPane>
37
+ <ElTabPane label="Series" name="series">
38
+ <template #label>
39
+ <div class="flex items-center gap-1">
40
+ <div class="i-ri-flow-chart" />
41
+ <span class="ml-1">Series</span>
42
+ </div>
43
+ </template>
44
+ <HairyArticleSeries />
45
+ </ElTabPane>
46
+ <ElTabPane label="User" name="user">
47
+ <template #label>
48
+ <div class="flex items-center gap-1">
49
+ <div class="i-ri-user-line" />
50
+ <span class="ml-1">User</span>
51
+ </div>
52
+ </template>
53
+ <HairySidebar />
54
+ </ElTabPane>
55
+ </ElTabs>
56
+ </template>
@@ -0,0 +1,48 @@
1
+ <script lang="ts" setup>
2
+ import { useRouter } from 'vue-router'
3
+ import { useHairyTags } from '../../composables'
4
+
5
+ const router = useRouter()
6
+
7
+ const { getTagStyle, tags } = useHairyTags({
8
+ primary: '#1bc9a6',
9
+ })
10
+
11
+ function displayTag(tag: string) {
12
+ router.push(`/tags/${tag}`)
13
+ }
14
+ </script>
15
+
16
+ <template>
17
+ <div class="min-h-59vh flex-center flex-col">
18
+ <div text="center" class="text-size-2.5em pt-10 mb-5">
19
+ 目前共计 {{ Array.from(tags).length }} 个标签
20
+ </div>
21
+ <div text="center" class="max-w-7xl flex flex-wrap justify-center items-center gap-2">
22
+ <a
23
+ v-for="[key, tag] in Array.from(tags).sort()"
24
+ :key="key" class="post-tag cursor-pointer"
25
+ :style="getTagStyle(tag.count)"
26
+ p="1"
27
+ @click="displayTag(key.toString())"
28
+ >
29
+ {{ key }}
30
+ </a>
31
+ </div>
32
+ </div>
33
+ </template>
34
+
35
+ <route lang="yaml">
36
+ meta:
37
+ layout: tags
38
+ </route>
39
+
40
+ <style lang="scss" scoped>
41
+ a {
42
+ color: var(--yun-tag-color);
43
+ &:hover {
44
+ --un-text-opacity: 1;
45
+ color: var(--hy-c-primary-dark);
46
+ }
47
+ }
48
+ </style>
@@ -1,12 +1,12 @@
1
1
  <script lang="ts" setup>
2
2
  import type { PageData, Post } from 'valaxy'
3
- import { useConfig } from 'valaxy'
3
+ import { useSiteConfig } from 'valaxy'
4
4
 
5
5
  defineProps<{
6
6
  frontmatter: Post
7
7
  data?: PageData
8
8
  }>()
9
- const config = useConfig()
9
+ const siteConfig = useSiteConfig()
10
10
  </script>
11
11
 
12
12
  <template>
@@ -34,7 +34,7 @@ const config = useConfig()
34
34
 
35
35
  <slot name="main-nav-after" />
36
36
 
37
- <slot v-if="config.comment.enable && frontmatter.comment !== false" name="comment" />
37
+ <slot v-if="siteConfig.comment.enable && frontmatter.comment !== false" name="comment" />
38
38
 
39
39
  <slot name="footer" />
40
40
  </slot>
@@ -0,0 +1,16 @@
1
+ <script lang="ts" setup>
2
+ import type { HairyTheme } from 'valaxy-theme-hairy'
3
+ import { useThemeConfig } from 'valaxy'
4
+ import { computed } from 'vue'
5
+
6
+ const themeConfig = useThemeConfig<HairyTheme.Config>()
7
+ const nav = computed(() => themeConfig.value.nav || [])
8
+ </script>
9
+
10
+ <template>
11
+ <div class="flex items-center h-12.5">
12
+ <HairyNavItem v-for="(item, index) in nav" :key="index" :item="item" />
13
+ </div>
14
+ </template>
15
+
16
+ <style lang="scss" scoped></style>
@@ -0,0 +1,12 @@
1
+ <script lang="ts" setup>
2
+ import { storeToRefs } from 'pinia'
3
+ import { useGlobalStore } from '../../store'
4
+
5
+ const { showDrawer } = storeToRefs(useGlobalStore())
6
+ </script>
7
+
8
+ <template>
9
+ <button class="yun-icon-btn lt-sm:text-size-xl" @click="showDrawer = !showDrawer">
10
+ <div i="ri-menu-fill" />
11
+ </button>
12
+ </template>
@@ -0,0 +1,35 @@
1
+ <script lang="ts" setup>
2
+ import type { NavItem } from 'valaxy-theme-hairy'
3
+ import { computed } from 'vue'
4
+ import { useRoute } from 'vue-router'
5
+
6
+ const props = defineProps<{
7
+ item: NavItem
8
+ }>()
9
+ const urlReg = /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/
10
+ const isLink = computed(() => urlReg.test(props.item?.link || ''))
11
+ const isPointer = computed(() => Boolean(props.item.link) || isLink.value)
12
+
13
+ const route = useRoute()
14
+
15
+ const active = computed(() => {
16
+ return !isLink.value && (
17
+ props.item.link === '/'
18
+ ? route.path === props.item.link
19
+ : route.path.includes(props.item.link!)
20
+ )
21
+ })
22
+ </script>
23
+
24
+ <template>
25
+ <a href="" class="px-2.5 HairyMenuItem" :class="[isPointer ? 'cursor-pointer' : 'select-none', active && 'text-primary active']">
26
+ <HairyLink class="flex items-center" type="white" :href="item.link" :target="isLink ? '__blank' : ''">
27
+ <div v-if="item.icon" class="mr-1 icon" :class="item.icon" />
28
+ <div class="question">
29
+ {{ item.text }}
30
+ </div>
31
+ </HairyLink>
32
+ </a>
33
+ </template>
34
+
35
+ <style lang="scss" scoped></style>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <div class="HairyNavBackground absolute inset-0 bg-white bg-opacity-85 dark:bg-black dark:bg-opacity-80 blur-4" />
3
+ </template>
4
+
5
+ <style>
6
+
7
+ </style>
@@ -0,0 +1,8 @@
1
+ <script lang="ts" setup>
2
+ </script>
3
+
4
+ <template>
5
+ <div />
6
+ </template>
7
+
8
+ <style lang="scss" scoped></style>
@@ -1,7 +1,9 @@
1
1
  <script lang="ts" setup>
2
- import { useConfig } from 'valaxy'
3
- const config = useConfig()
4
- const hrefToUrl = () => {
2
+ import { useSiteConfig } from 'valaxy'
3
+
4
+ const config = useSiteConfig()
5
+
6
+ function hrefToUrl() {
5
7
  location.href = config.value.url
6
8
  }
7
9
  </script>
@@ -0,0 +1,22 @@
1
+ <script lang="ts" setup>
2
+ import { useI18n } from 'vue-i18n'
3
+ import { computed } from 'vue'
4
+ import { useAppStore } from 'valaxy'
5
+
6
+ const { t } = useI18n()
7
+ const appStore = useAppStore()
8
+ const dark = computed(() => appStore.isDark)
9
+
10
+ const themeTitle = computed(() => {
11
+ return dark.value ? t('button.toggle_light') : t('button.toggle_dark')
12
+ })
13
+ </script>
14
+
15
+ <template>
16
+ <button
17
+ class="yun-icon-btn bg-light-1 p-1 dark:bg-transparent rounded-5 lt-sm:text-size-xl"
18
+ :title="themeTitle" :style="{ color: dark ? '' : '#f1cb64' }" @click="($event) => appStore.toggleDarkWithTransition($event, { duration: 600, easing: 'ease-in-out' })"
19
+ >
20
+ <div i="ri-sun-line dark:ri-moon-line" />
21
+ </button>
22
+ </template>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import { ElBreadcrumb, breadcrumbProps } from 'element-plus/es/components/breadcrumb/index'
3
- import 'element-plus/es/components/breadcrumb/style/index'
3
+ import 'element-plus/theme-chalk/el-breadcrumb.css'
4
4
  import type { PropType } from 'vue'
5
5
  import { computed } from 'vue'
6
6
 
@@ -26,7 +26,7 @@ const text = computed(() => `"${props.after || ''}"`)
26
26
  }
27
27
  .el-breadcrumb .el-breadcrumb__inner,
28
28
  .el-breadcrumb .el-breadcrumb__item:last-child .el-breadcrumb__inner {
29
- color: initial;
29
+ color: var(--va-c-text);
30
30
  }
31
31
  .el-breadcrumb .el-breadcrumb__inner.is-link {
32
32
  @apply border-b border-dashed hover:border-primary hover:text-primary transition-all cursor-pointer;
@@ -1,5 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import { ElBreadcrumbItem, breadcrumbItemProps } from 'element-plus/es/components/breadcrumb/index'
3
+
3
4
  defineProps(breadcrumbItemProps)
4
5
  </script>
5
6
 
@@ -8,7 +9,3 @@ defineProps(breadcrumbItemProps)
8
9
  <slot />
9
10
  </ElBreadcrumbItem>
10
11
  </template>
11
-
12
- <style lang="scss" scoped>
13
-
14
- </style>
@@ -1,8 +1,5 @@
1
+ /* eslint-disable ts/no-use-before-define */
1
2
  /* eslint-disable eqeqeq */
2
- /* eslint-disable no-var */
3
- /* eslint-disable vars-on-top */
4
- /* eslint-disable @typescript-eslint/no-use-before-define */
5
- /* eslint-disable no-undef */
6
3
 
7
4
  class RENDERER {
8
5
  ENABLE = false
@@ -185,7 +182,7 @@ class RENDERER {
185
182
  }
186
183
  }
187
184
 
188
- var SURFACE_POINT = function (renderer, x) {
185
+ const SURFACE_POINT = function (renderer, x) {
189
186
  this.renderer = renderer
190
187
  this.x = x
191
188
  this.init()
@@ -236,7 +233,7 @@ SURFACE_POINT.prototype = {
236
233
  },
237
234
  }
238
235
 
239
- var FISH = function (renderer) {
236
+ const FISH = function (renderer) {
240
237
  this.renderer = renderer
241
238
  this.init()
242
239
  }
@@ -247,7 +244,8 @@ FISH.prototype = {
247
244
  this.direction = Math.random() < 0.5
248
245
  this.x = this.direction ? this.renderer.width + this.renderer.THRESHOLD : -this.renderer.THRESHOLD
249
246
  this.previousY = this.y
250
- this.vx = this.getRandomValue(4, 10) * (this.direction ? -1 : 1)
247
+ this.vx = this.getRandomValue(4, 7) * (this.direction ? -1 : 1)
248
+
251
249
  if (this.renderer.reverse) {
252
250
  this.y = this.getRandomValue((this.renderer.height * 1) / 10, (this.renderer.height * 4) / 10)
253
251
  this.vy = this.getRandomValue(2, 5)
@@ -0,0 +1,38 @@
1
+ <!-- eslint-disable no-new -->
2
+ <script lang="ts" setup>
3
+ import { computed, onMounted, ref, watch } from 'vue'
4
+ import { useScriptTag } from '@vueuse/core'
5
+ import { useAppStore } from 'valaxy'
6
+ import { RENDERER } from './HairyFootFish'
7
+
8
+ const fishContainer = ref()
9
+
10
+ const tag = useScriptTag('https://cdn.bootcdn.net/ajax/libs/zepto/1.2.0/zepto.min.js')
11
+ const appStore = useAppStore()
12
+ const dark = computed(() => appStore.isDark)
13
+
14
+ let renderer: RENDERER
15
+
16
+ function reset() {
17
+ const color = dark.value ? 'hsl(0, 0%, 95%)' : 'hsl(0, 0%, 80%)'
18
+ if (!renderer)
19
+ renderer = new RENDERER(color)
20
+ else
21
+ renderer.setColor(color)
22
+ }
23
+
24
+ onMounted(() => {
25
+ tag.load()
26
+ .then(reset)
27
+ })
28
+ watch(dark, reset)
29
+ </script>
30
+
31
+ <template>
32
+ <div
33
+ id="jsi-flying-fish-container"
34
+ ref="fishContainer"
35
+ class="z-1 relative"
36
+ style="margin-top: -60px;"
37
+ />
38
+ </template>
@@ -1,20 +1,21 @@
1
1
  <script lang="ts" setup>
2
2
  import { useFrontmatter } from 'valaxy'
3
3
  import { computed } from 'vue'
4
+
4
5
  const props = defineProps<{
5
- headline?: String
6
- title: String
6
+ headline?: string
7
+ title: string
7
8
  description?: string
8
9
  }>()
9
10
 
10
11
  const post = useFrontmatter()
11
12
 
12
- const headline = computed(() => post.value.headline || props.headline)
13
- const title = computed(() => post.value.title || props.title)
13
+ const headline = computed(() => props.headline || post.value.headline)
14
+ const title = computed(() => props.title || post.value.title)
14
15
  </script>
15
16
 
16
17
  <template>
17
- <div class="flex-center flex-col text-shadow-lg text-white">
18
+ <div class="flex-center flex-col text-shadow-lg text-white mx-12px text-center">
18
19
  <div v-if="headline" class="font-frederick text-size-3.35em lt-sm:text-size-3rem leading-snug">
19
20
  {{ headline }}
20
21
  </div>
@@ -3,14 +3,14 @@
3
3
  class="waves w-full min-h-100px max-h-150px"
4
4
  viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"
5
5
  >
6
- <defs>
6
+ <defs>rgba(250,250,250,var(--un-bg-opacity))
7
7
  <path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
8
8
  </defs>
9
9
  <g class="parallax">
10
- <use class="transition-all duration-200" xlink:href="#gentle-wave" x="48" y="0" fill="var(--hy-c-waves-dimm-1)" />
11
- <use class="transition-all duration-200" xlink:href="#gentle-wave" x="48" y="3" fill="var(--hy-c-waves-dimm-2)" />
12
- <use class="transition-all duration-200" xlink:href="#gentle-wave" x="48" y="5" fill="var(--hy-c-waves-dimm-3)" />
13
- <use class="transition-all duration-200" xlink:href="#gentle-wave" x="48" y="7" fill="var(--hy-c-waves-dimm)" />
10
+ <use class="" xlink:href="#gentle-wave" x="48" y="0" fill="var(--hy-c-waves-dimm-1)" />
11
+ <use class="" xlink:href="#gentle-wave" x="48" y="3" fill="var(--hy-c-waves-dimm-2)" />
12
+ <use class="" xlink:href="#gentle-wave" x="48" y="5" fill="var(--hy-c-waves-dimm-3)" />
13
+ <use class="" xlink:href="#gentle-wave" x="48" y="7" fill="var(--hy-c-waves-dimm)" />
14
14
  </g>
15
15
  </svg>
16
16
  </template>
@@ -0,0 +1,51 @@
1
+ <script lang="ts" setup>
2
+ import { provide, useCssVars } from 'vue'
3
+ import { renderOverlay } from '@overlastic/vue'
4
+ import type { ImageViewerProps } from 'element-plus/es/components/image-viewer/index'
5
+ import { atWillToUnit } from '@hairy/utils'
6
+ import HairyImageViewer from './HairyImageViewer.vue'
7
+
8
+ const props = withDefaults(defineProps<{
9
+ row?: string | number
10
+ col?: string | number
11
+ gap?: string | number
12
+ justify?: string
13
+ align?: string
14
+ }>(), {
15
+ row: 'auto',
16
+ col: 'auto',
17
+ gap: 10,
18
+ justify: 'space-evenly',
19
+ align: 'initial',
20
+ })
21
+
22
+ useCssVars(() => ({
23
+ width: atWillToUnit(props.row),
24
+ height: atWillToUnit(props.col),
25
+ gap: atWillToUnit(props.gap),
26
+ justify: props.justify,
27
+ align: props.align,
28
+ }))
29
+
30
+ // TODO global find images
31
+ // const slots = useSlots()
32
+ // const paths = computed(() => slots
33
+ // .default?.()
34
+ // .map(v => v.props?.src)
35
+ // .filter(Boolean) as string[],
36
+ // )
37
+
38
+ function preview(url: string) {
39
+ // const initialIndex = paths.value.findIndex(v => v === url) || 0
40
+ renderOverlay<Partial<ImageViewerProps>>(HairyImageViewer, {
41
+ urlList: [url],
42
+ initialIndex: 0,
43
+ })
44
+ }
45
+
46
+ provide('HairyImageGroup:preview', preview)
47
+ </script>
48
+
49
+ <template>
50
+ <slot />
51
+ </template>
@@ -1,11 +1,12 @@
1
1
  <script lang="ts" setup>
2
- import { useOverlayMeta } from 'unoverlay-vue'
2
+ import { usePrograms } from '@overlastic/vue'
3
3
  import { ElImageViewer, imageViewerProps } from 'element-plus/es/components/image-viewer/index'
4
- import 'element-plus/es/components/image-viewer/style/index'
4
+ import 'element-plus/theme-chalk/el-image-viewer.css'
5
5
  import { onMounted, onUnmounted } from 'vue'
6
+
6
7
  const props = defineProps(imageViewerProps)
7
8
 
8
- const { visible, confirm } = useOverlayMeta()
9
+ const { visible, resolve } = usePrograms()
9
10
 
10
11
  onMounted(() => {
11
12
  document.body.style.overflow = 'hidden'
@@ -17,6 +18,6 @@ onUnmounted(() => {
17
18
 
18
19
  <template>
19
20
  <div class="HairyImageViewer fixed inset-0 z-2000">
20
- <ElImageViewer v-if="visible" v-bind="props" @close="confirm()"></ElImageViewer>
21
+ <ElImageViewer v-if="visible" v-bind="props" @close="resolve()" />
21
22
  </div>
22
23
  </template>