valaxy-theme-yun 0.20.2 → 0.20.3
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/App.vue +8 -4
- package/components/ValaxyMain.vue +7 -4
- package/components/YunAside.vue +2 -2
- package/components/YunBanner.vue +31 -28
- package/components/YunFullscreenMenu.vue +23 -14
- package/components/YunFuseSearch.vue +7 -54
- package/components/YunNavMenu.vue +3 -124
- package/components/YunOverlay.vue +1 -1
- package/components/YunSearchBtn.vue +2 -1
- package/components/YunSearchTrigger.vue +2 -11
- package/components/YunSidebarCard.vue +3 -0
- package/components/YunSidebarLinks.vue +1 -1
- package/components/YunSiteInfo.vue +1 -1
- package/components/layout/YunLayoutLeft.vue +1 -1
- package/components/layout/YunLayoutWrapper.vue +12 -2
- package/components/menu/YunNavMenuTitle.vue +11 -4
- package/components/prologue/PrologueSquare.vue +7 -5
- package/components/site/YunFullscreenMenuItem.vue +1 -2
- package/components/site/YunFullscreenMenuList.vue +7 -2
- package/components/theme/nimbo/YunNimboBanner.vue +0 -0
- package/components/theme/nimbo/YunNimboNavMenu.vue +130 -0
- package/components/theme/strato/YunStratoApp.vue +10 -0
- package/components/theme/strato/YunStratoBanner.vue +0 -0
- package/components/theme/strato/YunStratoNavMenu.vue +81 -0
- package/components/{YunSidebar.vue → theme/strato/YunStratoSidebar.vue} +19 -16
- package/components/ui/YunBannerCharContainer.vue +24 -0
- package/components/ui/YunGradientDivider.vue +24 -0
- package/composables/helper.ts +16 -1
- package/composables/useYunBanner.ts +21 -0
- package/layouts/collection.vue +9 -12
- package/layouts/collections.vue +12 -15
- package/layouts/home.vue +4 -1
- package/package.json +3 -3
- package/stores/app.ts +11 -0
- package/styles/css-vars.scss +5 -0
- package/styles/vars.scss +3 -1
package/App.vue
CHANGED
@@ -31,16 +31,16 @@ useHead({
|
|
31
31
|
const themeConfig = useThemeConfig()
|
32
32
|
|
33
33
|
const app = useAppStore()
|
34
|
-
const
|
34
|
+
const yun = useYunAppStore()
|
35
35
|
const route = useRoute()
|
36
36
|
|
37
37
|
watch(
|
38
38
|
() => route.meta.layout,
|
39
39
|
() => {
|
40
40
|
if (route.meta.layout === 'home' || app.isMobile)
|
41
|
-
|
41
|
+
yun.leftSidebar.isOpen = false
|
42
42
|
else
|
43
|
-
|
43
|
+
yun.leftSidebar.isOpen = false
|
44
44
|
},
|
45
45
|
{ immediate: true },
|
46
46
|
)
|
@@ -55,11 +55,15 @@ const isDev = import.meta.env.DEV
|
|
55
55
|
</script>
|
56
56
|
|
57
57
|
<template>
|
58
|
+
<YunStratoApp v-if="yun.isStrato" />
|
58
59
|
<YunDebug v-if="isDev" />
|
59
60
|
|
60
61
|
<YunPageHeaderGradient />
|
61
62
|
<YunNavMenu />
|
62
|
-
|
63
|
+
|
64
|
+
<YunFullscreenMenu v-if="yun.isNimbo" />
|
65
|
+
<YunStratoSidebar v-if="yun.isStrato" />
|
66
|
+
|
63
67
|
<YunFireworks v-if="themeConfig.fireworks.enable" />
|
64
68
|
<slot name="bg">
|
65
69
|
<YunBg v-if="themeConfig.bg_image.enable" />
|
@@ -10,7 +10,6 @@ const props = defineProps<{
|
|
10
10
|
frontmatter: Post
|
11
11
|
data?: PageData
|
12
12
|
}>()
|
13
|
-
|
14
13
|
const siteConfig = useSiteConfig()
|
15
14
|
|
16
15
|
const { styles, icon, color } = usePostProperty(props.frontmatter.type)
|
@@ -37,12 +36,16 @@ onContentUpdated(() => {
|
|
37
36
|
</script>
|
38
37
|
|
39
38
|
<template>
|
40
|
-
<main
|
39
|
+
<main
|
40
|
+
class="yun-main lt-md:w-full" flex="~ center"
|
41
|
+
>
|
41
42
|
<slot name="main">
|
42
43
|
<div
|
43
|
-
class="content w-full md:w-3xl lg:w-2xl xl:w-2xl 2xl:w-4xl"
|
44
|
+
class="content w-full md:w-3xl lg:w-2xl xl:w-2xl 2xl:w-4xl"
|
45
|
+
:class="{
|
44
46
|
'no-aside': !aside,
|
45
|
-
}"
|
47
|
+
}"
|
48
|
+
flex="~ col grow"
|
46
49
|
p="lt-md:0"
|
47
50
|
>
|
48
51
|
<YunCard :cover="frontmatter.cover" m="0" class="relative" :style="styles as StyleValue">
|
package/components/YunAside.vue
CHANGED
@@ -28,7 +28,7 @@ watch(() => [yun.rightSidebar.isOpen, yun.size.isXl], async () => {
|
|
28
28
|
<template>
|
29
29
|
<aside
|
30
30
|
flex="~ col"
|
31
|
-
class="va-card yun-aside sticky top-0 lg:top-
|
31
|
+
class="va-card yun-aside sticky top-0 lg:top-$yun-margin-top min-h-sm"
|
32
32
|
:class="{
|
33
33
|
float: isAsideFloat,
|
34
34
|
show,
|
@@ -70,7 +70,7 @@ watch(() => [yun.rightSidebar.isOpen, yun.size.isXl], async () => {
|
|
70
70
|
width: 0;
|
71
71
|
transform: translateX(100%);
|
72
72
|
transition: all 0.2s map.get($cubic-bezier, 'ease-in-out');
|
73
|
-
max-height: calc(100vh -
|
73
|
+
max-height: calc(100vh - var(--yun-margin-top));
|
74
74
|
|
75
75
|
// float panel
|
76
76
|
&.float {
|
package/components/YunBanner.vue
CHANGED
@@ -7,28 +7,28 @@
|
|
7
7
|
|
8
8
|
import type { CSSProperties } from 'vue'
|
9
9
|
import { computed, onMounted, ref } from 'vue'
|
10
|
-
import {
|
10
|
+
import { sleep } from 'valaxy'
|
11
11
|
import { useThemeConfig } from '../composables'
|
12
|
+
import { useYunAppStore } from '../stores'
|
13
|
+
import { useYunBanner } from '../composables/useYunBanner'
|
12
14
|
|
15
|
+
const yun = useYunAppStore()
|
13
16
|
const themeConfig = useThemeConfig()
|
14
17
|
|
15
|
-
const chars = computed(() => {
|
16
|
-
const arr = []
|
17
|
-
for (let i = 0; i < themeConfig.value.banner.title.length; i++) {
|
18
|
-
const rn = random(1.5, 3.5)
|
19
|
-
arr.push(rn)
|
20
|
-
}
|
21
|
-
return arr
|
22
|
-
})
|
23
18
|
// height of top/bottom line
|
24
|
-
|
19
|
+
|
20
|
+
const { totalCharHeight, chars } = useYunBanner(themeConfig.value.banner)
|
25
21
|
|
26
22
|
const bannerStyles = computed<CSSProperties>(() => {
|
27
|
-
|
23
|
+
const styles: CSSProperties = {
|
28
24
|
'--total-char-height': `${totalCharHeight.value}rem`,
|
29
25
|
'--banner-line-height': `calc(var(--banner-height, 100 * var(--vh)) / 2 - ${totalCharHeight.value / 2}rem)`,
|
30
26
|
'justify-content': 'space-between',
|
31
27
|
}
|
28
|
+
if (yun.isStrato)
|
29
|
+
styles.borderBottom = `1px solid var(--banner-line-color)`
|
30
|
+
|
31
|
+
return styles
|
32
32
|
})
|
33
33
|
|
34
34
|
const lineStatus = ref<
|
@@ -43,10 +43,12 @@ const animationStatus = ref('banner')
|
|
43
43
|
onMounted(async () => {
|
44
44
|
await sleep(500)
|
45
45
|
lineStatus.value = 'active'
|
46
|
-
|
47
|
-
|
46
|
+
if (yun.isNimbo) {
|
47
|
+
await sleep(500)
|
48
|
+
lineStatus.value = 'exit'
|
48
49
|
|
49
|
-
|
50
|
+
animationStatus.value = 'prologue'
|
51
|
+
}
|
50
52
|
})
|
51
53
|
</script>
|
52
54
|
|
@@ -58,20 +60,21 @@ onMounted(async () => {
|
|
58
60
|
:class="lineStatusClass"
|
59
61
|
/>
|
60
62
|
</div>
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
63
|
+
|
64
|
+
<template v-if="yun.isNimbo">
|
65
|
+
<YunBannerCharContainer
|
66
|
+
v-if="animationStatus === 'banner'"
|
67
|
+
:title="themeConfig.banner.title"
|
68
|
+
:chars="chars"
|
69
|
+
/>
|
70
|
+
<PrologueSquare v-else class="z-1" />
|
71
|
+
</template>
|
72
|
+
<template v-if="yun.isStrato">
|
73
|
+
<YunBannerCharContainer
|
74
|
+
:title="themeConfig.banner.title"
|
75
|
+
:chars="chars"
|
76
|
+
/>
|
77
|
+
</template>
|
75
78
|
|
76
79
|
<div class="banner-line-container bottom">
|
77
80
|
<div
|
@@ -10,32 +10,33 @@ const app = useAppStore()
|
|
10
10
|
</script>
|
11
11
|
|
12
12
|
<template>
|
13
|
-
<Transition name="slide-down">
|
13
|
+
<Transition :name="app.isMobile ? 'slide-down' : 'slide-left'">
|
14
14
|
<div
|
15
15
|
v-if="yunApp.fullscreenMenu.isOpen"
|
16
16
|
ref="fullscreenMenuRef"
|
17
17
|
p="t-20 md:t-26"
|
18
18
|
class="yun-fullscreen-menu fixed left-0 right-0 bottom-0 top-0 bg-$va-c-bg-soft z-$yun-z-fullscreen-menu overflow-auto"
|
19
19
|
>
|
20
|
-
<div class="flex-center gap-2">
|
20
|
+
<!-- <div v-if="app.isMobile" class="flex-center gap-2">
|
21
21
|
<YunToggleDark transition />
|
22
22
|
<YunToggleLocale v-if="app.showToggleLocale" />
|
23
|
-
</div>
|
23
|
+
</div> -->
|
24
24
|
|
25
|
-
<
|
26
|
-
<YunFullscreenMenuItem
|
27
|
-
:page="{
|
28
|
-
name: '站点主页',
|
29
|
-
icon: 'i-ri-home-2-line',
|
30
|
-
url: '/',
|
31
|
-
}"
|
32
|
-
/>
|
33
|
-
</YunFullscreenMenuList>
|
34
|
-
|
35
|
-
<div v-if="!yunApp.size.isLg" class="mt-4">
|
25
|
+
<div v-if="!yunApp.size.isLg" class="my-4">
|
36
26
|
<YunSiteInfo class="text-center" />
|
27
|
+
|
28
|
+
<YunGradientDivider class="my-2 op-20" />
|
29
|
+
|
37
30
|
<YunPostsInfo />
|
38
31
|
</div>
|
32
|
+
<YunGradientDivider v-if="!yunApp.size.isLg" class="my-2 op-20" />
|
33
|
+
|
34
|
+
<YunFullscreenMenuList />
|
35
|
+
|
36
|
+
<YunGradientDivider v-if="!yunApp.size.isLg" class="my-2 op-20" />
|
37
|
+
<div v-if="!yunApp.size.isLg" class="flex-center">
|
38
|
+
<YunConfig />
|
39
|
+
</div>
|
39
40
|
</div>
|
40
41
|
</Transition>
|
41
42
|
</template>
|
@@ -44,6 +45,8 @@ const app = useAppStore()
|
|
44
45
|
@use 'sass:map';
|
45
46
|
@use 'valaxy-theme-yun/styles/vars.scss' as *;
|
46
47
|
|
48
|
+
.slide-left-enter-active,
|
49
|
+
.slide-left-leave-active,
|
47
50
|
.slide-down-enter-active,
|
48
51
|
.slide-down-leave-active {
|
49
52
|
opacity: 1;
|
@@ -57,4 +60,10 @@ const app = useAppStore()
|
|
57
60
|
opacity: 0;
|
58
61
|
transform: translateY(-100%);
|
59
62
|
}
|
63
|
+
|
64
|
+
.slide-left-enter-from,
|
65
|
+
.slide-left-leave-to {
|
66
|
+
opacity: 0;
|
67
|
+
transform: translateX(-100%);
|
68
|
+
}
|
60
69
|
</style>
|
@@ -1,70 +1,23 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import
|
3
|
-
import { useFuse } from '@vueuse/integrations/useFuse'
|
4
|
-
import { computed, ref, watch } from 'vue'
|
2
|
+
import { ref } from 'vue'
|
5
3
|
import { useI18n } from 'vue-i18n'
|
6
|
-
import {
|
7
|
-
import type { FuseListItem } from 'valaxy/types'
|
4
|
+
import { useFuseSearch } from 'valaxy'
|
8
5
|
|
9
6
|
import { isClient, onClickOutside, useScrollLock } from '@vueuse/core'
|
10
7
|
|
11
|
-
|
8
|
+
defineProps<{
|
12
9
|
open: boolean
|
13
10
|
}>()
|
14
11
|
const emit = defineEmits(['close'])
|
15
12
|
|
16
|
-
const searchContainer = ref<HTMLElement>()
|
17
|
-
|
18
|
-
const isLocked = useScrollLock(isClient ? document.body : null)
|
19
|
-
|
20
|
-
const { t } = useI18n()
|
21
|
-
|
22
|
-
const fuseListData = ref<FuseListItem[]>([])
|
23
|
-
|
24
|
-
const siteConfig = useSiteConfig()
|
25
|
-
const keys = computed(() => {
|
26
|
-
const ks = siteConfig.value.fuse.options.keys || []
|
27
|
-
return ks.length === 0
|
28
|
-
? ['title', 'tags', 'categories', 'excerpt']
|
29
|
-
: ks
|
30
|
-
})
|
31
|
-
|
32
13
|
const input = ref('')
|
33
|
-
// todo export options
|
34
|
-
const useFuseOptions = computed<UseFuseOptions<FuseListItem>>(() => ({
|
35
|
-
fuseOptions: {
|
36
|
-
includeMatches: true,
|
37
|
-
findAllMatches: true,
|
38
14
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
// threshold: 0.99,
|
43
|
-
// ignoreLocation: true,
|
44
|
-
},
|
45
|
-
// resultLimit: resultLimit.value,
|
46
|
-
// matchAllWhenSearchEmpty: matchAllWhenSearchEmpty.value,
|
47
|
-
}))
|
48
|
-
const { results } = useFuse(input, fuseListData, useFuseOptions)
|
15
|
+
const isLocked = useScrollLock(isClient ? document.documentElement : null)
|
16
|
+
const { t } = useI18n()
|
17
|
+
const { results } = useFuseSearch(input)
|
49
18
|
|
50
19
|
const searchInputRef = ref<HTMLInputElement>()
|
51
|
-
|
52
|
-
watch(() => props.open, async () => {
|
53
|
-
if (!props.open)
|
54
|
-
return
|
55
|
-
|
56
|
-
const fuseListDataPath = siteConfig.value.fuse.dataPath.startsWith('http')
|
57
|
-
? siteConfig.value.fuse.dataPath
|
58
|
-
: `${import.meta.env.BASE_URL}${siteConfig.value.fuse.dataPath}`
|
59
|
-
fetch(fuseListDataPath)
|
60
|
-
.then(res => res.json())
|
61
|
-
.then((data) => {
|
62
|
-
if (Array.isArray(data))
|
63
|
-
fuseListData.value = data
|
64
|
-
|
65
|
-
searchInputRef.value?.focus()
|
66
|
-
})
|
67
|
-
})
|
20
|
+
const searchContainer = ref<HTMLElement>()
|
68
21
|
|
69
22
|
onClickOutside(searchInputRef, () => {
|
70
23
|
// emit('close')
|
@@ -1,131 +1,10 @@
|
|
1
1
|
<script setup lang="ts">
|
2
|
-
import { onMounted, ref, watch } from 'vue'
|
3
|
-
import { useAppStore, useSiteConfig } from 'valaxy'
|
4
|
-
import { useRoute } from 'vue-router'
|
5
2
|
import { useYunAppStore } from '../stores'
|
6
|
-
// import { useThemeConfig } from '../composables'
|
7
3
|
|
8
|
-
|
9
|
-
const yunApp = useYunAppStore()
|
10
|
-
const siteConfig = useSiteConfig()
|
11
|
-
// const themeConfig = useThemeConfig()
|
12
|
-
|
13
|
-
const showMenu = ref(false)
|
14
|
-
const route = useRoute()
|
15
|
-
onMounted(() => {
|
16
|
-
if (route.meta.layout === 'home') {
|
17
|
-
setTimeout(() => {
|
18
|
-
showMenu.value = true
|
19
|
-
}, 600)
|
20
|
-
}
|
21
|
-
else {
|
22
|
-
showMenu.value = true
|
23
|
-
}
|
24
|
-
})
|
25
|
-
|
26
|
-
const playAnimation = ref(false)
|
27
|
-
watch(() => yunApp.scrollY, () => {
|
28
|
-
if (yunApp.scrollY > 10)
|
29
|
-
playAnimation.value = true
|
30
|
-
else
|
31
|
-
playAnimation.value = false
|
32
|
-
})
|
33
|
-
|
34
|
-
const app = useAppStore()
|
4
|
+
const yun = useYunAppStore()
|
35
5
|
</script>
|
36
6
|
|
37
7
|
<template>
|
38
|
-
<
|
39
|
-
|
40
|
-
>
|
41
|
-
<div
|
42
|
-
v-if="showMenu"
|
43
|
-
class="yun-nav-menu z-$yun-z-nav-menu"
|
44
|
-
border="~ solid $va-c-text"
|
45
|
-
:class="{
|
46
|
-
play: playAnimation,
|
47
|
-
}"
|
48
|
-
>
|
49
|
-
<!-- -->
|
50
|
-
<ValaxyHamburger
|
51
|
-
:active="yunApp.fullscreenMenu.isOpen"
|
52
|
-
class="menu-btn sidebar-toggle leading-4 size-12"
|
53
|
-
inline-flex cursor="pointer"
|
54
|
-
hover="bg-white/80 dark:bg-black/80"
|
55
|
-
z="$yun-z-menu-btn"
|
56
|
-
@click="yunApp.fullscreenMenu.toggle()"
|
57
|
-
/>
|
58
|
-
<YunNavMenuItem icon="i-ri-home-4-line" to="/" />
|
59
|
-
|
60
|
-
<div class="flex flex-1 flex-center">
|
61
|
-
<YunNavMenuTitle />
|
62
|
-
</div>
|
63
|
-
|
64
|
-
<div class="inline-flex-center">
|
65
|
-
<!-- <template v-if="!app.isMobile && themeConfig.nav">
|
66
|
-
<template v-for="item in themeConfig.nav" :key="item.text">
|
67
|
-
<AppLink
|
68
|
-
v-if="'link' in item"
|
69
|
-
:to="item.link"
|
70
|
-
class="menu-btn inline-flex-center p-2 transition text-$va-c-text"
|
71
|
-
inline-flex cursor="pointer"
|
72
|
-
hover="bg-white/80 dark:bg-black/80"
|
73
|
-
z="$yun-z-menu-btn"
|
74
|
-
>
|
75
|
-
{{ item.text }}
|
76
|
-
</AppLink>
|
77
|
-
<template v-else-if="'items' in item" />
|
78
|
-
</template>
|
79
|
-
</template> -->
|
80
|
-
|
81
|
-
<YunToggleLocale
|
82
|
-
v-if="yunApp.size.isSm && app.showToggleLocale"
|
83
|
-
class="rounded-none!"
|
84
|
-
/>
|
85
|
-
<YunToggleDark class="rounded-none!" transition />
|
86
|
-
<YunSearchTrigger v-if="siteConfig.search.enable" />
|
87
|
-
</div>
|
88
|
-
</div>
|
89
|
-
</Transition>
|
8
|
+
<YunStratoNavMenu v-if="yun.isStrato" />
|
9
|
+
<YunNimboNavMenu v-else-if="yun.isNimbo" />
|
90
10
|
</template>
|
91
|
-
|
92
|
-
<style lang="scss">
|
93
|
-
@use 'sass:map';
|
94
|
-
@use 'valaxy-theme-yun/styles/vars.scss' as *;
|
95
|
-
@use "valaxy/client/styles/mixins/index.scss" as *;
|
96
|
-
|
97
|
-
.yun-nav-menu {
|
98
|
-
position: fixed;
|
99
|
-
|
100
|
-
// safari not support
|
101
|
-
// animation-timeline: scroll();
|
102
|
-
// animation-range: 0 calc(30vh), exit;
|
103
|
-
background-color: transparent;
|
104
|
-
box-shadow: none;
|
105
|
-
display: flex;
|
106
|
-
top: var(--rect-margin);
|
107
|
-
left: var(--rect-margin);
|
108
|
-
right: var(--rect-margin);
|
109
|
-
align-items: center;
|
110
|
-
justify-content: space-between;
|
111
|
-
height: 50px;
|
112
|
-
transition: all 0.5s map.get($cubic-bezier, 'ease-in');
|
113
|
-
|
114
|
-
&.play {
|
115
|
-
top: 0;
|
116
|
-
left: 0;
|
117
|
-
right: 0;
|
118
|
-
background-color: var(--va-c-bg);
|
119
|
-
border-color: rgb(0 0 0 / 0.1);
|
120
|
-
|
121
|
-
--un-shadow: var(--un-shadow-inset) 0 20px 25px -5px var(--un-shadow-color, rgb(0 0 0 / 0.1)), var(--un-shadow-inset) 0 8px 10px -6px var(--un-shadow-color, rgb(0 0 0 / 0.1));
|
122
|
-
|
123
|
-
box-shadow: var(--un-ring-offset-shadow), var(--un-ring-shadow),
|
124
|
-
var(--un-shadow);
|
125
|
-
}
|
126
|
-
|
127
|
-
.vt-hamburger-top, .vt-hamburger-middle, .vt-hamburger-bottom {
|
128
|
-
background-color: var(--va-c-text);
|
129
|
-
}
|
130
|
-
}
|
131
|
-
</style>
|
@@ -22,8 +22,8 @@ function onClick() {
|
|
22
22
|
<template>
|
23
23
|
<button
|
24
24
|
class="yun-search-btn popup-trigger size-12 inline-flex justify-center items-center"
|
25
|
+
:class="!open && 'hover-bg-white/80 hover:bg-black/80'"
|
25
26
|
text="xl $va-c-text"
|
26
|
-
hover="bg-white/80 dark:bg-black/80"
|
27
27
|
:title="t('menu.search')"
|
28
28
|
@click="onClick"
|
29
29
|
>
|
@@ -35,5 +35,6 @@ function onClick() {
|
|
35
35
|
<style lang="scss">
|
36
36
|
.yun-search-btn {
|
37
37
|
z-index: var(--yun-z-search-btn);
|
38
|
+
transition: background-color var(--va-transition-duration);
|
38
39
|
}
|
39
40
|
</style>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
2
|
import { useSiteConfig } from 'valaxy'
|
3
3
|
import { computed, defineAsyncComponent, onMounted, ref } from 'vue'
|
4
|
-
import {
|
4
|
+
import { useHotKey } from '../composables'
|
5
5
|
|
6
6
|
const siteConfig = useSiteConfig()
|
7
7
|
|
@@ -14,20 +14,11 @@ function togglePopup() {
|
|
14
14
|
open.value = !open.value
|
15
15
|
}
|
16
16
|
|
17
|
-
function handleSearchHotKey(event: KeyboardEvent) {
|
18
|
-
if (
|
19
|
-
(event.key.toLowerCase() === 'k' && (event.metaKey || event.ctrlKey))
|
20
|
-
) {
|
21
|
-
event.preventDefault()
|
22
|
-
togglePopup()
|
23
|
-
}
|
24
|
-
}
|
25
|
-
|
26
17
|
const algoliaRef = ref()
|
27
18
|
onMounted(() => {
|
28
19
|
// algolia has its own hotkey
|
29
20
|
if (isFuse.value)
|
30
|
-
|
21
|
+
useHotKey('k', togglePopup)
|
31
22
|
})
|
32
23
|
|
33
24
|
function openSearch() {
|
@@ -6,6 +6,9 @@
|
|
6
6
|
<YunCard class="p-4 min-h-sm" flex="~ col gap-1">
|
7
7
|
<YunSiteInfo class="text-center" />
|
8
8
|
<YunPostsInfo />
|
9
|
+
<YunGradientDivider class="my-2 op-20" />
|
9
10
|
<YunSocialLinks />
|
11
|
+
<YunGradientDivider class="my-2 op-20" />
|
12
|
+
<YunSidebarLinks />
|
10
13
|
</YunCard>
|
11
14
|
</template>
|
@@ -5,7 +5,7 @@ const siteConfig = useSiteConfig()
|
|
5
5
|
</script>
|
6
6
|
|
7
7
|
<template>
|
8
|
-
<div class="site-info gap-1 items-center" flex="~ col"
|
8
|
+
<div class="site-info gap-1 items-center" flex="~ col" p="t-8">
|
9
9
|
<RouterLink
|
10
10
|
class="site-author-avatar inline-flex-center" to="/about"
|
11
11
|
>
|
@@ -5,7 +5,7 @@ const yun = useYunAppStore()
|
|
5
5
|
</script>
|
6
6
|
|
7
7
|
<template>
|
8
|
-
<div v-if="yun.size.isLg" flex="~ col" class="gap-4 sticky top-
|
8
|
+
<div v-if="yun.size.isLg" flex="~ col" class="gap-4 sticky top-$yun-margin-top w-80">
|
9
9
|
<YunSidebarCard />
|
10
10
|
<YunAdBoard />
|
11
11
|
</div>
|
@@ -1,12 +1,22 @@
|
|
1
1
|
<script setup lang="ts">
|
2
|
+
import { computed } from 'vue'
|
3
|
+
import { useYunAppStore } from '../../stores'
|
4
|
+
|
2
5
|
// common layout
|
6
|
+
|
7
|
+
const yun = useYunAppStore()
|
8
|
+
const classes = computed(() => {
|
9
|
+
if (yun.isNimbo)
|
10
|
+
return 'mt-24 md:mt-36'
|
11
|
+
return 'mt-12'
|
12
|
+
})
|
3
13
|
</script>
|
4
14
|
|
5
15
|
<template>
|
6
16
|
<div
|
7
17
|
flex="~"
|
8
|
-
|
9
|
-
class="
|
18
|
+
class="w-full m-auto justify-center items-start gap-4"
|
19
|
+
:class="classes"
|
10
20
|
>
|
11
21
|
<slot />
|
12
22
|
</div>
|
@@ -1,16 +1,23 @@
|
|
1
1
|
<script setup lang="ts">
|
2
2
|
import { useFrontmatter, useSiteConfig } from 'valaxy'
|
3
|
-
import { ref, watch } from 'vue'
|
4
|
-
import { useRouter } from 'vue-router'
|
3
|
+
import { computed, ref, watch } from 'vue'
|
4
|
+
import { useRoute, useRouter } from 'vue-router'
|
5
5
|
import { useYunAppStore } from '../../stores'
|
6
6
|
|
7
7
|
const yunApp = useYunAppStore()
|
8
8
|
const fm = useFrontmatter()
|
9
9
|
const siteConfig = useSiteConfig()
|
10
10
|
|
11
|
+
const route = useRoute()
|
11
12
|
const showPostTitle = ref(false)
|
13
|
+
const showSiteTitle = computed(() => {
|
14
|
+
if (yunApp.isStrato)
|
15
|
+
return route.path === '/' ? false : yunApp.scrollY < 10
|
16
|
+
return !showPostTitle.value
|
17
|
+
})
|
12
18
|
watch(() => yunApp.scrollY, () => {
|
13
|
-
|
19
|
+
if (yunApp.isNimbo)
|
20
|
+
showPostTitle.value = yunApp.scrollY > 200
|
14
21
|
})
|
15
22
|
|
16
23
|
const router = useRouter()
|
@@ -57,7 +64,7 @@ function goToLink() {
|
|
57
64
|
{{ fm.subtitle }}
|
58
65
|
</span>
|
59
66
|
</div>
|
60
|
-
<span v-
|
67
|
+
<span v-if="showSiteTitle" class="font-light truncate">
|
61
68
|
{{ siteConfig.title }}
|
62
69
|
</span>
|
63
70
|
</div>
|
@@ -56,16 +56,18 @@ const showContent = ref(false)
|
|
56
56
|
<YunAuthorName class="mt-3" />
|
57
57
|
<YunAuthorIntro />
|
58
58
|
|
59
|
-
<
|
60
|
-
|
61
|
-
|
59
|
+
<div
|
60
|
+
flex="~ col"
|
61
|
+
class="gap-2 items-center justify-center"
|
62
|
+
my-4 md:my-6
|
63
|
+
py-4 md:py-6
|
64
|
+
border="t-1px b-1px black/60 dark:white/60"
|
65
|
+
>
|
62
66
|
<YunSiteTitle />
|
63
67
|
<YunSiteSubtitle />
|
64
68
|
<YunSiteDescription />
|
65
69
|
</div>
|
66
70
|
|
67
|
-
<YunDivider />
|
68
|
-
|
69
71
|
<div
|
70
72
|
class="mt-4 flex-center w-64 md:w-100 m-auto gap-2"
|
71
73
|
flex="~ wrap"
|
@@ -11,8 +11,7 @@ const yunApp = useYunAppStore()
|
|
11
11
|
|
12
12
|
<template>
|
13
13
|
<AppLink
|
14
|
-
class="link-item
|
15
|
-
inline-flex
|
14
|
+
class="inline-flex link-item items-center justify-center md:justify-start gap-2 transition rounded text-xl p-3 sm:(text-3xl p-6) lg:(text-4xl p-7 w-full)"
|
16
15
|
:to="page.url" :title="page.name"
|
17
16
|
:style="`color:${page.color}`"
|
18
17
|
hover="bg-gray-100/50 dark:bg-gray-800/50"
|
@@ -1,14 +1,19 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
+
import { useAppStore } from 'valaxy'
|
2
3
|
import { useThemeConfig } from '../../composables'
|
3
4
|
|
5
|
+
const app = useAppStore()
|
4
6
|
const themeConfig = useThemeConfig()
|
5
7
|
</script>
|
6
8
|
|
7
9
|
<template>
|
8
10
|
<div
|
9
|
-
class="links flex-center"
|
10
|
-
flex="~
|
11
|
+
class="links flex-center lg:flex-col"
|
12
|
+
flex="~" text="left"
|
11
13
|
p="x-$rect-margin"
|
14
|
+
:class="{
|
15
|
+
'flex-wrap': app.isMobile,
|
16
|
+
}"
|
12
17
|
>
|
13
18
|
<slot />
|
14
19
|
<YunFullscreenMenuItem
|
File without changes
|
@@ -0,0 +1,130 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import { onMounted, ref, watch } from 'vue'
|
3
|
+
import { useAppStore, useSiteConfig } from 'valaxy'
|
4
|
+
import { useRoute } from 'vue-router'
|
5
|
+
import { useYunAppStore } from '../../../stores'
|
6
|
+
// import { useThemeConfig } from '../composables'
|
7
|
+
|
8
|
+
// const app = useAppStore()
|
9
|
+
const yunApp = useYunAppStore()
|
10
|
+
const siteConfig = useSiteConfig()
|
11
|
+
// const themeConfig = useThemeConfig()
|
12
|
+
|
13
|
+
const showMenu = ref(false)
|
14
|
+
const route = useRoute()
|
15
|
+
onMounted(() => {
|
16
|
+
if (route.meta.layout === 'home') {
|
17
|
+
setTimeout(() => {
|
18
|
+
showMenu.value = true
|
19
|
+
}, 600)
|
20
|
+
}
|
21
|
+
else {
|
22
|
+
showMenu.value = true
|
23
|
+
}
|
24
|
+
})
|
25
|
+
|
26
|
+
const playAnimation = ref(false)
|
27
|
+
watch(() => yunApp.scrollY, () => {
|
28
|
+
if (yunApp.scrollY > 10)
|
29
|
+
playAnimation.value = true
|
30
|
+
else
|
31
|
+
playAnimation.value = false
|
32
|
+
})
|
33
|
+
|
34
|
+
const app = useAppStore()
|
35
|
+
</script>
|
36
|
+
|
37
|
+
<template>
|
38
|
+
<Transition
|
39
|
+
enter-active-class="animate-fade-in"
|
40
|
+
>
|
41
|
+
<div
|
42
|
+
v-if="showMenu"
|
43
|
+
class="yun-nav-menu z-$yun-z-nav-menu fixed bg-transparent"
|
44
|
+
border="~ solid $va-c-text"
|
45
|
+
:class="{
|
46
|
+
play: playAnimation,
|
47
|
+
}"
|
48
|
+
>
|
49
|
+
<!-- -->
|
50
|
+
<div class="inline-flex justify-start items-center flex-1">
|
51
|
+
<ValaxyHamburger
|
52
|
+
:active="yunApp.fullscreenMenu.isOpen"
|
53
|
+
class="menu-btn sidebar-toggle leading-4 size-12"
|
54
|
+
inline-flex cursor="pointer"
|
55
|
+
hover="bg-white/80 dark:bg-black/80"
|
56
|
+
z="$yun-z-menu-btn"
|
57
|
+
@click="yunApp.fullscreenMenu.toggle()"
|
58
|
+
/>
|
59
|
+
<YunNavMenuItem icon="i-ri-home-4-line" to="/" />
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div class="flex flex-1 flex-center">
|
63
|
+
<YunNavMenuTitle />
|
64
|
+
</div>
|
65
|
+
|
66
|
+
<div class="inline-flex-center justify-end items-center flex-1">
|
67
|
+
<!-- <template v-if="!app.isMobile && themeConfig.nav">
|
68
|
+
<template v-for="item in themeConfig.nav" :key="item.text">
|
69
|
+
<AppLink
|
70
|
+
v-if="'link' in item"
|
71
|
+
:to="item.link"
|
72
|
+
class="menu-btn inline-flex-center p-2 transition text-$va-c-text"
|
73
|
+
inline-flex cursor="pointer"
|
74
|
+
hover="bg-white/80 dark:bg-black/80"
|
75
|
+
z="$yun-z-menu-btn"
|
76
|
+
>
|
77
|
+
{{ item.text }}
|
78
|
+
</AppLink>
|
79
|
+
<template v-else-if="'items' in item" />
|
80
|
+
</template>
|
81
|
+
</template> -->
|
82
|
+
|
83
|
+
<YunToggleLocale
|
84
|
+
v-if="yunApp.size.isSm && app.showToggleLocale"
|
85
|
+
class="rounded-none!"
|
86
|
+
/>
|
87
|
+
<YunToggleDark class="rounded-none!" transition />
|
88
|
+
<YunSearchTrigger v-if="siteConfig.search.enable" />
|
89
|
+
</div>
|
90
|
+
</div>
|
91
|
+
</Transition>
|
92
|
+
</template>
|
93
|
+
|
94
|
+
<style lang="scss" scoped>
|
95
|
+
@use 'sass:map';
|
96
|
+
@use 'valaxy-theme-yun/styles/vars.scss' as *;
|
97
|
+
@use "valaxy/client/styles/mixins/index.scss" as *;
|
98
|
+
|
99
|
+
.yun-nav-menu {
|
100
|
+
// safari not support
|
101
|
+
// animation-timeline: scroll();
|
102
|
+
// animation-range: 0 calc(30vh), exit;
|
103
|
+
box-shadow: none;
|
104
|
+
display: flex;
|
105
|
+
top: var(--rect-margin);
|
106
|
+
left: var(--rect-margin);
|
107
|
+
right: var(--rect-margin);
|
108
|
+
align-items: center;
|
109
|
+
justify-content: space-between;
|
110
|
+
height: 50px;
|
111
|
+
transition: all 0.5s map.get($cubic-bezier, 'ease-in');
|
112
|
+
|
113
|
+
&.play {
|
114
|
+
top: 0;
|
115
|
+
left: 0;
|
116
|
+
right: 0;
|
117
|
+
background-color: var(--va-c-bg);
|
118
|
+
border-color: rgb(0 0 0 / 0.1);
|
119
|
+
|
120
|
+
--un-shadow: var(--un-shadow-inset) 0 20px 25px -5px var(--un-shadow-color, rgb(0 0 0 / 0.1)), var(--un-shadow-inset) 0 8px 10px -6px var(--un-shadow-color, rgb(0 0 0 / 0.1));
|
121
|
+
|
122
|
+
box-shadow: var(--un-ring-offset-shadow), var(--un-ring-shadow),
|
123
|
+
var(--un-shadow);
|
124
|
+
}
|
125
|
+
|
126
|
+
.vt-hamburger-top, .vt-hamburger-middle, .vt-hamburger-bottom {
|
127
|
+
background-color: var(--va-c-text);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
</style>
|
File without changes
|
@@ -0,0 +1,81 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import { computed, onMounted, ref, watch } from 'vue'
|
3
|
+
import { useAppStore, useSiteConfig } from 'valaxy'
|
4
|
+
import { useRoute } from 'vue-router'
|
5
|
+
import { useYunAppStore } from '../../../stores'
|
6
|
+
// import { useThemeConfig } from '../composables'
|
7
|
+
|
8
|
+
// const app = useAppStore()
|
9
|
+
const yunApp = useYunAppStore()
|
10
|
+
const siteConfig = useSiteConfig()
|
11
|
+
// const themeConfig = useThemeConfig()
|
12
|
+
|
13
|
+
const showMenu = ref(false)
|
14
|
+
const route = useRoute()
|
15
|
+
onMounted(() => {
|
16
|
+
if (route.meta.layout === 'home') {
|
17
|
+
setTimeout(() => {
|
18
|
+
showMenu.value = true
|
19
|
+
}, 600)
|
20
|
+
}
|
21
|
+
else {
|
22
|
+
showMenu.value = true
|
23
|
+
}
|
24
|
+
})
|
25
|
+
|
26
|
+
const playAnimation = ref(false)
|
27
|
+
watch(() => yunApp.scrollY, () => {
|
28
|
+
if (yunApp.scrollY > 10)
|
29
|
+
playAnimation.value = true
|
30
|
+
else
|
31
|
+
playAnimation.value = false
|
32
|
+
})
|
33
|
+
|
34
|
+
const app = useAppStore()
|
35
|
+
|
36
|
+
const showHamburger = computed(() => {
|
37
|
+
return app.isMobile ? true : route.meta.layout === 'home'
|
38
|
+
})
|
39
|
+
</script>
|
40
|
+
|
41
|
+
<template>
|
42
|
+
<div class="fixed left-0 top-0" z="$yun-z-left-sidebar-menu">
|
43
|
+
<ValaxyHamburger
|
44
|
+
v-if="showHamburger"
|
45
|
+
:active="yunApp.leftSidebar.isOpen"
|
46
|
+
class="menu-btn sidebar-toggle leading-4 size-12 fixed"
|
47
|
+
inline-flex cursor="pointer"
|
48
|
+
hover="bg-white/80 dark:bg-black/80"
|
49
|
+
@click="yunApp.leftSidebar.toggle()"
|
50
|
+
/>
|
51
|
+
<YunNavMenuItem v-else icon="i-ri-home-4-line" to="/" />
|
52
|
+
</div>
|
53
|
+
|
54
|
+
<Transition
|
55
|
+
enter-active-class="animate-fade-in"
|
56
|
+
>
|
57
|
+
<div
|
58
|
+
v-if="showMenu"
|
59
|
+
class="yun-nav-menu z-$yun-z-nav-menu fixed w-full flex justify-between items-center top-0"
|
60
|
+
:class="{
|
61
|
+
play: playAnimation,
|
62
|
+
}"
|
63
|
+
>
|
64
|
+
<!-- -->
|
65
|
+
<div class="inline-flex justify-start items-center flex-1" />
|
66
|
+
|
67
|
+
<div class="flex flex-1 flex-center">
|
68
|
+
<YunNavMenuTitle />
|
69
|
+
</div>
|
70
|
+
|
71
|
+
<div class="inline-flex flex-1 justify-end items-center">
|
72
|
+
<YunToggleLocale
|
73
|
+
v-if="yunApp.size.isSm && app.showToggleLocale"
|
74
|
+
class="rounded-none!"
|
75
|
+
/>
|
76
|
+
<YunToggleDark class="rounded-none!" transition />
|
77
|
+
<YunSearchTrigger v-if="siteConfig.search.enable" />
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
</Transition>
|
81
|
+
</template>
|
@@ -1,17 +1,18 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
2
|
import { ref } from 'vue'
|
3
|
-
import { useYunAppStore } from '
|
3
|
+
import { useYunAppStore } from '../../../stores'
|
4
4
|
|
5
5
|
defineProps<{
|
6
6
|
showHamburger?: boolean
|
7
7
|
}>()
|
8
8
|
|
9
|
-
const
|
9
|
+
const yun = useYunAppStore()
|
10
10
|
const showOverview = ref(false)
|
11
11
|
</script>
|
12
12
|
|
13
13
|
<template>
|
14
|
-
|
14
|
+
<!-- class="md:hidden" -->
|
15
|
+
<YunOverlay :show="yun.leftSidebar.isOpen" @click="yun.leftSidebar.toggle()" />
|
15
16
|
|
16
17
|
<!-- <ValaxyHamburger
|
17
18
|
:active="yunStore.leftSidebar.isOpen"
|
@@ -22,12 +23,14 @@ const showOverview = ref(false)
|
|
22
23
|
/> -->
|
23
24
|
|
24
25
|
<aside
|
25
|
-
|
26
|
+
id="yun-left-sidebar"
|
27
|
+
class="va-card transition yun-sidebar fixed inset-y-0 left-0 overflow-y-auto"
|
26
28
|
:class="{
|
27
|
-
'open':
|
29
|
+
'open': yun.leftSidebar.isOpen,
|
28
30
|
'md:translate-x-0': !showHamburger,
|
29
31
|
}"
|
30
|
-
text="center" bg="$yun-sidebar-bg-color contain no-repeat"
|
32
|
+
text="center" bg="$yun-sidebar-bg-color contain no-repeat"
|
33
|
+
z="$yun-z-left-sidebar"
|
31
34
|
>
|
32
35
|
<div v-if="$slots.default" class="sidebar-nav" m="t-6">
|
33
36
|
<button
|
@@ -58,7 +61,7 @@ const showOverview = ref(false)
|
|
58
61
|
@use 'sass:map';
|
59
62
|
@use 'valaxy-theme-yun/styles/vars.scss' as *;
|
60
63
|
|
61
|
-
|
64
|
+
#yun-left-sidebar {
|
62
65
|
width: calc(100vw - 64px);
|
63
66
|
max-width: var(--va-sidebar-width);
|
64
67
|
background-image: var(--yun-sidebar-bg-img);
|
@@ -71,17 +74,17 @@ const showOverview = ref(false)
|
|
71
74
|
&.open {
|
72
75
|
transform: translateX(0);
|
73
76
|
}
|
74
|
-
}
|
75
|
-
|
76
|
-
.sidebar-nav {
|
77
|
-
.sidebar-nav-item {
|
78
|
-
color: var(--va-c-primary);
|
79
|
-
border: 1px solid var(--va-c-primary);
|
80
77
|
|
81
|
-
|
78
|
+
.sidebar-nav {
|
79
|
+
.sidebar-nav-item {
|
80
|
+
color: var(--va-c-primary);
|
82
81
|
border: 1px solid var(--va-c-primary);
|
83
|
-
|
84
|
-
|
82
|
+
|
83
|
+
&.active {
|
84
|
+
border: 1px solid var(--va-c-primary);
|
85
|
+
color: white;
|
86
|
+
background-color: var(--va-c-primary);
|
87
|
+
}
|
85
88
|
}
|
86
89
|
}
|
87
90
|
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import type { CSSProperties } from 'vue'
|
3
|
+
|
4
|
+
defineProps<{
|
5
|
+
title: string
|
6
|
+
chars: number[]
|
7
|
+
}>()
|
8
|
+
</script>
|
9
|
+
|
10
|
+
<template>
|
11
|
+
<div class="banner-char-container">
|
12
|
+
<div v-for="c, i in title" :key="i" class="char-box">
|
13
|
+
<span
|
14
|
+
:class="[i % 2 !== 0 ? 'char-right' : 'char-left']" :style="{
|
15
|
+
'--banner-char-size': `${chars[i]}rem`,
|
16
|
+
} as CSSProperties"
|
17
|
+
>
|
18
|
+
<span class="char">
|
19
|
+
{{ c }}
|
20
|
+
</span>
|
21
|
+
</span>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</template>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<template>
|
2
|
+
<div class="yun-gradient-line" />
|
3
|
+
</template>
|
4
|
+
|
5
|
+
<style lang="scss">
|
6
|
+
.yun-gradient-line {
|
7
|
+
--c-end: rgba(0 0 0 / 0);
|
8
|
+
--c-mid: rgba(0 0 0 / 1);
|
9
|
+
}
|
10
|
+
|
11
|
+
.dark {
|
12
|
+
.yun-gradient-line {
|
13
|
+
--c-end: rgba(255 255 255 / 0);
|
14
|
+
--c-mid: rgba(255 255 255 / 1);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
/* stylelint-disable-next-line no-duplicate-selectors */
|
19
|
+
.yun-gradient-line {
|
20
|
+
width: 100%;
|
21
|
+
height: 1px;
|
22
|
+
background: linear-gradient(to right, var(--c-end) 0%, var(--c-mid) 50%, var(--c-end) 100%);
|
23
|
+
}
|
24
|
+
</style>
|
package/composables/helper.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { ref, watch } from 'vue'
|
2
|
-
import { isClient } from '@vueuse/core'
|
2
|
+
import { isClient, useEventListener } from '@vueuse/core'
|
3
3
|
|
4
4
|
/**
|
5
5
|
* fetch data from source, and random
|
@@ -25,3 +25,18 @@ export function useRandomData<T>(source: string | T[], random = false) {
|
|
25
25
|
data,
|
26
26
|
}
|
27
27
|
}
|
28
|
+
|
29
|
+
export function useHotKey(key: string, callback: () => void) {
|
30
|
+
const isHotKeyActive = ref(false)
|
31
|
+
|
32
|
+
function handleHotKey(event: KeyboardEvent) {
|
33
|
+
if (event.key.toLowerCase() === key.toLowerCase() && (event.metaKey || event.ctrlKey)) {
|
34
|
+
event.preventDefault()
|
35
|
+
callback()
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
useEventListener('keydown', handleHotKey)
|
40
|
+
|
41
|
+
return { isHotKeyActive }
|
42
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { computed } from 'vue'
|
2
|
+
import { random } from 'valaxy'
|
3
|
+
import type { YunTheme } from '../types'
|
4
|
+
|
5
|
+
export function useYunBanner(options: YunTheme.Banner) {
|
6
|
+
const chars = computed(() => {
|
7
|
+
const arr = []
|
8
|
+
for (let i = 0; i < options.title.length; i++) {
|
9
|
+
const rn = random(1.5, 3.5)
|
10
|
+
arr.push(rn)
|
11
|
+
}
|
12
|
+
return arr
|
13
|
+
})
|
14
|
+
|
15
|
+
const totalCharHeight = computed(() => chars.value.reduce((a, b) => a + b, 0))
|
16
|
+
|
17
|
+
return {
|
18
|
+
chars,
|
19
|
+
totalCharHeight,
|
20
|
+
}
|
21
|
+
}
|
package/layouts/collection.vue
CHANGED
@@ -3,16 +3,13 @@
|
|
3
3
|
</script>
|
4
4
|
|
5
5
|
<template>
|
6
|
-
<
|
7
|
-
<slot
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
</div>
|
16
|
-
</component>
|
17
|
-
</RouterView>
|
6
|
+
<YunLayoutWrapper>
|
7
|
+
<RouterView v-slot="{ Component }">
|
8
|
+
<component :is="Component">
|
9
|
+
<div flex="~ wrap" gap="4">
|
10
|
+
Collection
|
11
|
+
</div>
|
12
|
+
</component>
|
13
|
+
</RouterView>
|
14
|
+
</YunLayoutWrapper>
|
18
15
|
</template>
|
package/layouts/collections.vue
CHANGED
@@ -5,19 +5,16 @@ const { collections } = useCollections()
|
|
5
5
|
</script>
|
6
6
|
|
7
7
|
<template>
|
8
|
-
<
|
9
|
-
<slot
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
</div>
|
21
|
-
</component>
|
22
|
-
</RouterView>
|
8
|
+
<YunLayoutWrapper>
|
9
|
+
<RouterView v-slot="{ Component }">
|
10
|
+
<component :is="Component">
|
11
|
+
<div flex="~ wrap" gap="4">
|
12
|
+
<YunCollectionItem
|
13
|
+
v-for="collection in collections" :key="collection.id"
|
14
|
+
:collection="collection"
|
15
|
+
/>
|
16
|
+
</div>
|
17
|
+
</component>
|
18
|
+
</RouterView>
|
19
|
+
</YunLayoutWrapper>
|
23
20
|
</template>
|
package/layouts/home.vue
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
import { computed } from 'vue'
|
3
3
|
import { useRoute } from 'vue-router'
|
4
4
|
import { useThemeConfig } from '../composables'
|
5
|
+
import { useYunAppStore } from '../stores'
|
6
|
+
|
7
|
+
const yun = useYunAppStore()
|
5
8
|
|
6
9
|
const route = useRoute()
|
7
10
|
const themeConfig = useThemeConfig()
|
@@ -24,7 +27,7 @@ const showNotice = computed(() => {
|
|
24
27
|
<template v-if="!isPage">
|
25
28
|
<YunBanner />
|
26
29
|
<YunSay v-if="themeConfig.say.enable" w="full" />
|
27
|
-
<YunPrologue class="absolute left-0 top-0 right-0 bottom-0" />
|
30
|
+
<YunPrologue v-if="yun.isNimbo" class="absolute left-0 top-0 right-0 bottom-0" />
|
28
31
|
</template>
|
29
32
|
|
30
33
|
<YunNotice
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "valaxy-theme-yun",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.20.
|
4
|
+
"version": "0.20.3",
|
5
5
|
"author": {
|
6
6
|
"email": "me@yunyoujun.cn",
|
7
7
|
"name": "YunYouJun",
|
@@ -29,11 +29,11 @@
|
|
29
29
|
"animejs": "^3.2.2",
|
30
30
|
"gsap": "^3.12.5",
|
31
31
|
"primevue": "^4.2.1",
|
32
|
-
"radix-vue": "^1.9.
|
32
|
+
"radix-vue": "^1.9.9"
|
33
33
|
},
|
34
34
|
"devDependencies": {
|
35
35
|
"@types/animejs": "^3.1.12",
|
36
|
-
"valaxy": "0.20.
|
36
|
+
"valaxy": "0.20.3",
|
37
37
|
"valaxy-addon-waline": "0.2.0"
|
38
38
|
},
|
39
39
|
"scripts": {
|
package/stores/app.ts
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
import { acceptHMRUpdate, defineStore } from 'pinia'
|
2
2
|
import { isClient, useScroll, useToggle } from '@vueuse/core'
|
3
3
|
import { useScreenSize } from 'valaxy'
|
4
|
+
import { computed } from 'vue'
|
5
|
+
import { useThemeConfig } from '../composables'
|
4
6
|
|
5
7
|
export const useYunAppStore = defineStore('yun-app', () => {
|
8
|
+
const themeConfig = useThemeConfig()
|
9
|
+
// v1 Theme
|
10
|
+
const isStrato = computed(() => themeConfig.value.type === 'strato')
|
11
|
+
// v2 Theme
|
12
|
+
const isNimbo = computed(() => themeConfig.value.type === 'nimbo')
|
13
|
+
|
6
14
|
// 左侧边栏
|
7
15
|
const [isLeftSidebarOpen, toggleLeftSidebar] = useToggle()
|
8
16
|
// 右侧边栏
|
@@ -28,6 +36,9 @@ export const useYunAppStore = defineStore('yun-app', () => {
|
|
28
36
|
toggle: toggleFullscreenMenu,
|
29
37
|
},
|
30
38
|
scrollY: isClient ? useScroll(window).y : 0,
|
39
|
+
|
40
|
+
isStrato,
|
41
|
+
isNimbo,
|
31
42
|
}
|
32
43
|
})
|
33
44
|
|
package/styles/css-vars.scss
CHANGED