valaxy-theme-yun 0.19.13 → 0.20.0-beta.10
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 +30 -4
- package/bump.config.ts +7 -0
- package/client/constants/index.ts +13 -0
- package/components/ValaxyMain.vue +47 -58
- package/components/YunAdBoard.vue +4 -0
- package/components/YunAlbum.vue +13 -3
- package/components/YunAlbumList.vue +5 -11
- package/components/YunAside.vue +66 -43
- package/components/YunBackToTop.vue +11 -4
- package/components/YunBanner.vue +31 -15
- package/components/YunBg.vue +2 -0
- package/components/YunCard.vue +5 -1
- package/components/YunCategories.vue +15 -34
- package/components/YunCategory.vue +57 -40
- package/components/YunCategoryChildItem.vue +49 -0
- package/components/YunClassifyPopover.vue +59 -0
- package/components/YunCloud.vue +5 -10
- package/components/YunConfig.vue +2 -19
- package/components/YunDebug.vue +47 -0
- package/components/YunDock.vue +223 -0
- package/components/YunFooter.vue +56 -4
- package/components/YunFullscreenMenu.vue +57 -0
- package/components/YunGirlItem.vue +98 -0
- package/components/YunGirls.vue +2 -73
- package/components/YunGoDown.vue +8 -15
- package/components/YunLayoutPostTag.vue +11 -1
- package/components/YunLinkItem.vue +62 -0
- package/components/YunLinks.vue +15 -47
- package/components/YunNavMenu.vue +125 -0
- package/components/YunOutline.vue +1 -2
- package/components/YunOverlay.vue +31 -0
- package/components/YunOverview.vue +2 -79
- package/components/YunPageHeader.vue +1 -1
- package/components/YunPagination.vue +108 -0
- package/components/YunPostCard.vue +32 -3
- package/components/YunPostCategories.vue +3 -3
- package/components/YunPostCollapse.vue +12 -75
- package/components/YunPostCollapseItem.vue +137 -0
- package/components/YunPostDateMeta.vue +30 -0
- package/components/YunPostList.vue +6 -11
- package/components/YunPostMeta.vue +31 -39
- package/components/YunPostTags.vue +2 -2
- package/components/YunPostsInfo.vue +41 -0
- package/components/YunPrologue.vue +24 -0
- package/components/YunSearchBtn.vue +8 -6
- package/components/YunSelect.vue +1 -11
- package/components/YunSidebar.vue +7 -4
- package/components/YunSidebarCard.vue +10 -0
- package/components/YunSidebarNav.vue +0 -1
- package/components/YunSiteInfo.vue +72 -0
- package/components/YunSponsor.vue +21 -6
- package/components/animation/LineBurstEffects.vue +75 -0
- package/components/author/YunAuthorAvatar.vue +12 -0
- package/components/author/YunAuthorIntro.vue +11 -0
- package/components/author/YunAuthorName.vue +14 -0
- package/components/config/YunToggleDark.vue +37 -0
- package/components/layout/YunLayoutLeft.vue +12 -0
- package/components/layout/YunLayoutRight.vue +21 -0
- package/components/layout/YunLayoutWrapper.vue +13 -0
- package/components/menu/YunNavMenuItem.vue +22 -0
- package/components/menu/YunNavMenuTitle.vue +86 -0
- package/components/menu/YunPostClassifyNavItem.vue +30 -0
- package/components/page/YunPageHeaderGradient.vue +38 -0
- package/components/project/YunProjectCard.vue +120 -0
- package/components/project/YunProjectCollection.vue +15 -0
- package/components/project/YunProjectLinkItem.vue +60 -0
- package/components/project/YunProjectToggleButton.vue +17 -0
- package/components/project/YunProjects.vue +48 -0
- package/components/prologue/PrologueSocialIcon.vue +58 -0
- package/components/prologue/PrologueSocialLinks.vue +16 -0
- package/components/prologue/PrologueSquare.vue +145 -0
- package/components/prologue/YunAEFrame.vue +138 -0
- package/components/prologue/YunAERect.vue +127 -0
- package/components/site/YunFullscreenMenuItem.vue +26 -0
- package/components/site/YunFullscreenMenuList.vue +19 -0
- package/components/site/YunSiteDescription.vue +11 -0
- package/components/site/YunSiteLinkItem.vue +26 -0
- package/components/site/YunSiteLinks.vue +19 -0
- package/components/site/YunSiteSubtitle.vue +14 -0
- package/components/site/YunSiteTitle.vue +59 -0
- package/components/third/YunWalineMeta.vue +17 -5
- package/components/ui/YunDivider.vue +3 -0
- package/composables/animation.ts +33 -0
- package/docs/zh-CN/config.md +0 -3
- package/layouts/404.vue +1 -3
- package/layouts/albums.vue +25 -24
- package/layouts/archives.vue +32 -21
- package/layouts/categories.vue +47 -31
- package/layouts/default.vue +10 -5
- package/layouts/empty.vue +3 -0
- package/layouts/gallery.vue +31 -30
- package/layouts/home.vue +13 -12
- package/layouts/post.vue +23 -20
- package/layouts/posts.vue +10 -0
- package/layouts/projects.vue +25 -0
- package/layouts/tags.vue +51 -41
- package/node/config.ts +2 -5
- package/package.json +16 -7
- package/pages/page/[page].vue +3 -6
- package/pages/posts/index.vue +11 -0
- package/setup/main.ts +51 -9
- package/stores/app.ts +25 -3
- package/styles/animations/index.scss +73 -0
- package/styles/common/markdown.scss +4 -0
- package/styles/css-vars.scss +19 -1
- package/styles/global.scss +8 -0
- package/styles/index.scss +1 -0
- package/styles/layout/index.scss +2 -4
- package/styles/modules/prologue.scss +1 -0
- package/styles/primevue/index.ts +7 -0
- package/styles/primevue/tooltip.scss +55 -0
- package/styles/primevue/tooltip.ts +14 -0
- package/styles/vars.scss +23 -2
- package/styles/widgets/banner.scss +26 -6
- package/types/index.d.ts +53 -5
- package/types/projects.ts +48 -0
- package/unocss.config.ts +1 -2
- package/utils/animation.ts +35 -0
- package/utils/index.ts +2 -0
- package/valaxy.config.ts +1 -0
@@ -1,11 +1,13 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import {
|
2
|
+
import { onMounted, ref } from 'vue'
|
3
3
|
import type { CategoryList, Post } from 'valaxy'
|
4
|
-
import {
|
4
|
+
import { useInvisibleElement } from 'valaxy'
|
5
5
|
import { useI18n } from 'vue-i18n'
|
6
|
-
import {
|
6
|
+
import { useRouter } from 'vue-router'
|
7
|
+
import { useYunSpringAnimation } from '../composables/animation'
|
7
8
|
|
8
9
|
const props = withDefaults(defineProps<{
|
10
|
+
i?: number
|
9
11
|
parentKey: string
|
10
12
|
// to eliminate the warning
|
11
13
|
category: Post | CategoryList
|
@@ -20,24 +22,10 @@ const props = withDefaults(defineProps<{
|
|
20
22
|
})
|
21
23
|
|
22
24
|
const router = useRouter()
|
23
|
-
const route = useRoute()
|
24
|
-
const categoryList = computed(() => {
|
25
|
-
const c = (route.query.category as string) || ''
|
26
|
-
return Array.isArray(c) ? [c] : c.split('/')
|
27
|
-
})
|
28
25
|
|
29
26
|
const collapse = ref(props.collapsable)
|
30
27
|
const { t } = useI18n()
|
31
28
|
|
32
|
-
/**
|
33
|
-
* i18n
|
34
|
-
*/
|
35
|
-
const { locale } = useI18n()
|
36
|
-
function getTitle(post: Post | any) {
|
37
|
-
const lang = locale.value === 'zh-CN' ? 'zh' : locale.value
|
38
|
-
return post[`title_${lang}`] ? post[`title_${lang}`] : post.title
|
39
|
-
}
|
40
|
-
|
41
29
|
const postCollapseElRef = ref<HTMLElement>()
|
42
30
|
const { show } = useInvisibleElement(postCollapseElRef)
|
43
31
|
/**
|
@@ -45,6 +33,8 @@ const { show } = useInvisibleElement(postCollapseElRef)
|
|
45
33
|
* @param category
|
46
34
|
*/
|
47
35
|
function jumpToDisplayCategory(category: string) {
|
36
|
+
collapse.value = false
|
37
|
+
|
48
38
|
router.push({
|
49
39
|
query: {
|
50
40
|
category,
|
@@ -59,37 +49,64 @@ onMounted(() => {
|
|
59
49
|
if (postCollapseEl)
|
60
50
|
postCollapseElRef.value = postCollapseEl
|
61
51
|
})
|
52
|
+
|
53
|
+
const categoryRef = ref<HTMLElement>()
|
54
|
+
if (props.level === 1) {
|
55
|
+
useYunSpringAnimation(categoryRef, {
|
56
|
+
i: props.i || 0,
|
57
|
+
y: 20,
|
58
|
+
duration: 200,
|
59
|
+
})
|
60
|
+
}
|
62
61
|
</script>
|
63
62
|
|
64
63
|
<template>
|
65
|
-
<li
|
66
|
-
|
64
|
+
<li
|
65
|
+
ref="categoryRef"
|
66
|
+
class="category-list-item inline-flex items-center cursor-pointer w-full gap-2 px-3 py-2 rounded"
|
67
|
+
hover="bg-black/5"
|
68
|
+
>
|
69
|
+
<span
|
70
|
+
class="folder-action inline-flex"
|
71
|
+
hover="text-$va-c-primary-lighter"
|
72
|
+
@click="collapse = !collapse"
|
73
|
+
>
|
67
74
|
<div v-if="collapse" i-ri-folder-add-line />
|
68
|
-
<div v-else
|
75
|
+
<div v-else class="text-$va-c-primary dark:text-$va-c-primary-lighter" i-ri-folder-reduce-line />
|
69
76
|
</span>
|
70
|
-
<span
|
71
|
-
|
77
|
+
<span
|
78
|
+
class="category-name inline-flex items-center gap-2 w-full"
|
79
|
+
@click="jumpToDisplayCategory(parentKey)"
|
80
|
+
>
|
81
|
+
<span>
|
82
|
+
{{ category.name === 'Uncategorized' ? t('category.uncategorized') : category.name }}
|
83
|
+
</span>
|
84
|
+
<span class="rounded-full px-1.5 bg-black/5 shadow-sm" text="xs black/55">
|
85
|
+
{{ category.total }}
|
86
|
+
</span>
|
72
87
|
</span>
|
73
88
|
</li>
|
74
89
|
|
75
|
-
<
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
90
|
+
<Transition
|
91
|
+
enter-active-class="v-enter-active"
|
92
|
+
enter-from-class="v-enter-from"
|
93
|
+
leave-active-class="v-leave-active"
|
94
|
+
leave-to-class="v-leave-to"
|
95
|
+
:duration="{ enter: 200, leave: 0 }"
|
96
|
+
>
|
97
|
+
<ul v-if="!collapse">
|
98
|
+
<li
|
99
|
+
v-for="categoryItem, cI in category.children.values()"
|
100
|
+
:key="cI"
|
101
|
+
class="post-list-item text-$va-c-text" m="l-4"
|
102
|
+
hover="text-$va-c-primary-lighter"
|
103
|
+
>
|
104
|
+
<YunCategoryChildItem
|
105
|
+
:i="cI"
|
106
|
+
:category-item="categoryItem"
|
107
|
+
:parent-key="parentKey"
|
108
|
+
/>
|
92
109
|
</li>
|
93
110
|
</ul>
|
94
|
-
</
|
111
|
+
</Transition>
|
95
112
|
</template>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import type { Post } from 'valaxy'
|
3
|
+
import { isCategoryList } from 'valaxy'
|
4
|
+
import { computed } from 'vue'
|
5
|
+
import { useRoute } from 'vue-router'
|
6
|
+
import { useI18n } from 'vue-i18n'
|
7
|
+
|
8
|
+
defineProps<{
|
9
|
+
i?: number
|
10
|
+
categoryItem: any
|
11
|
+
parentKey?: string
|
12
|
+
}>()
|
13
|
+
|
14
|
+
/**
|
15
|
+
* i18n
|
16
|
+
*/
|
17
|
+
const { locale } = useI18n()
|
18
|
+
function getTitle(post: Post | any) {
|
19
|
+
const lang = locale.value === 'zh-CN' ? 'zh' : locale.value
|
20
|
+
return post[`title_${lang}`] ? post[`title_${lang}`] : post.title
|
21
|
+
}
|
22
|
+
const route = useRoute()
|
23
|
+
const categoryList = computed(() => {
|
24
|
+
const c = (route.query.category as string) || ''
|
25
|
+
return Array.isArray(c) ? [c] : c.split('/')
|
26
|
+
})
|
27
|
+
</script>
|
28
|
+
|
29
|
+
<template>
|
30
|
+
<template v-if="isCategoryList(categoryItem)">
|
31
|
+
<YunCategory
|
32
|
+
:parent-key="parentKey ? `${parentKey}/${categoryItem.name}` : categoryItem.name"
|
33
|
+
:category="categoryItem"
|
34
|
+
:collapsable="!categoryList.includes(categoryItem.name)"
|
35
|
+
/>
|
36
|
+
</template>
|
37
|
+
|
38
|
+
<template v-else>
|
39
|
+
<RouterLink
|
40
|
+
v-if="categoryItem.title"
|
41
|
+
:to="categoryItem.path || ''"
|
42
|
+
class="inline-flex items-center gap-2 px-3 py-2 w-full rounded"
|
43
|
+
hover="bg-black/5"
|
44
|
+
>
|
45
|
+
<div i-ri-file-text-line />
|
46
|
+
<span font="serif black">{{ getTitle(categoryItem) }}</span>
|
47
|
+
</RouterLink>
|
48
|
+
</template>
|
49
|
+
</template>
|
@@ -0,0 +1,59 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import { useMotion } from '@vueuse/motion'
|
3
|
+
import Popover from 'primevue/popover'
|
4
|
+
import { onMounted, ref } from 'vue'
|
5
|
+
|
6
|
+
const op = ref<typeof Popover>()
|
7
|
+
|
8
|
+
const pContentRef = ref<HTMLElement>()
|
9
|
+
const motion = useMotion(pContentRef, {
|
10
|
+
initial: {
|
11
|
+
opacity: 0,
|
12
|
+
translateY: 30,
|
13
|
+
},
|
14
|
+
enter: {
|
15
|
+
opacity: 1,
|
16
|
+
translateY: 0,
|
17
|
+
transition: {
|
18
|
+
type: 'spring',
|
19
|
+
duration: 200,
|
20
|
+
damping: 9,
|
21
|
+
},
|
22
|
+
},
|
23
|
+
})
|
24
|
+
|
25
|
+
onMounted(() => {
|
26
|
+
motion.variant.value = 'initial'
|
27
|
+
|
28
|
+
// 滚动时隐藏
|
29
|
+
window.addEventListener('scroll', () => {
|
30
|
+
motion.variant.value = 'initial'
|
31
|
+
setTimeout(() => {
|
32
|
+
op.value?.hide()
|
33
|
+
}, 200)
|
34
|
+
})
|
35
|
+
})
|
36
|
+
|
37
|
+
function toggle(event: Event) {
|
38
|
+
op.value?.toggle(event)
|
39
|
+
motion.variant.value = op.value?.visible ? 'enter' : 'initial'
|
40
|
+
}
|
41
|
+
</script>
|
42
|
+
|
43
|
+
<template>
|
44
|
+
<YunNavMenuItem
|
45
|
+
icon="i-ri-mind-map" @click="toggle"
|
46
|
+
/>
|
47
|
+
<Popover
|
48
|
+
ref="op"
|
49
|
+
>
|
50
|
+
<div
|
51
|
+
ref="pContentRef"
|
52
|
+
class="p-4 shadow-xl"
|
53
|
+
bg="$va-c-bg-light"
|
54
|
+
>
|
55
|
+
<YunSiteInfo class="text-center" />
|
56
|
+
<YunPostsInfo />
|
57
|
+
</div>
|
58
|
+
</Popover>
|
59
|
+
</template>
|
package/components/YunCloud.vue
CHANGED
@@ -17,26 +17,21 @@
|
|
17
17
|
<style lang="scss">
|
18
18
|
@use 'valaxy/client/styles/mixins/index.scss' as *;
|
19
19
|
|
20
|
+
.dark .yun-cloud {
|
21
|
+
--yun-c-cloud: var(--va-c-bg-soft);
|
22
|
+
}
|
23
|
+
|
20
24
|
.yun-cloud {
|
21
25
|
display: flex;
|
22
26
|
width: 100%;
|
23
|
-
position: absolute;
|
24
|
-
bottom: 0;
|
25
|
-
left: 0;
|
26
|
-
right: 0;
|
27
27
|
z-index: var(--yun-z-cloud);
|
28
28
|
box-sizing: border-box;
|
29
|
-
mix-blend-mode: overlay;
|
30
29
|
|
31
30
|
.waves {
|
32
31
|
display: flex;
|
33
32
|
position: relative;
|
34
33
|
width: 100%;
|
35
|
-
height:
|
36
|
-
|
37
|
-
@include screen('md') {
|
38
|
-
height: 40px;
|
39
|
-
}
|
34
|
+
height: 40px;
|
40
35
|
}
|
41
36
|
|
42
37
|
.parallax {
|
package/components/YunConfig.vue
CHANGED
@@ -1,27 +1,10 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
|
3
|
-
import { computed } from 'vue'
|
4
|
-
import { useAppStore } from 'valaxy'
|
5
|
-
|
6
|
-
const appStore = useAppStore()
|
7
|
-
const { t } = useI18n()
|
8
|
-
|
9
|
-
const themeTitle = computed(() => {
|
10
|
-
return appStore.isDark ? t('button.toggle_light') : t('button.toggle_dark')
|
11
|
-
})
|
12
|
-
|
13
|
-
const styles = computed(() => {
|
14
|
-
return {
|
15
|
-
color: appStore.isDark ? '' : '#f1cb64',
|
16
|
-
}
|
17
|
-
})
|
2
|
+
// sidebar config
|
18
3
|
</script>
|
19
4
|
|
20
5
|
<template>
|
21
6
|
<div>
|
22
|
-
<
|
23
|
-
<div i="ri-sun-line dark:ri-moon-line" />
|
24
|
-
</button>
|
7
|
+
<YunToggleDark />
|
25
8
|
|
26
9
|
<YunToggleLocale />
|
27
10
|
</div>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import { computed } from 'vue'
|
3
|
+
import { useYunAppStore } from '../stores'
|
4
|
+
|
5
|
+
const yun = useYunAppStore()
|
6
|
+
|
7
|
+
const infoList = computed(() => {
|
8
|
+
return [
|
9
|
+
{
|
10
|
+
label: 'xs',
|
11
|
+
value: yun.size.isXs,
|
12
|
+
},
|
13
|
+
{
|
14
|
+
label: 'sm',
|
15
|
+
value: yun.size.isSm,
|
16
|
+
},
|
17
|
+
{
|
18
|
+
label: 'md',
|
19
|
+
value: yun.size.isMd,
|
20
|
+
},
|
21
|
+
{
|
22
|
+
label: 'lg',
|
23
|
+
value: yun.size.isLg,
|
24
|
+
},
|
25
|
+
{
|
26
|
+
label: 'xl',
|
27
|
+
value: yun.size.isXl,
|
28
|
+
},
|
29
|
+
{
|
30
|
+
label: '2xl',
|
31
|
+
value: yun.size.is2xl,
|
32
|
+
},
|
33
|
+
]
|
34
|
+
})
|
35
|
+
</script>
|
36
|
+
|
37
|
+
<template>
|
38
|
+
<div
|
39
|
+
class="bg-black/50 fixed bottom-2 left-2 p-2 gap-1 rounded z-9999"
|
40
|
+
text="xs white" flex="~ col"
|
41
|
+
>
|
42
|
+
<div v-for="item in infoList" :key="item.label" class="gap-2 inline-flex">
|
43
|
+
<span class="w-6" font="bold">{{ item.label }}: </span>
|
44
|
+
<span>{{ item.value ? '✅' : '❌' }}</span>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
</template>
|
@@ -0,0 +1,223 @@
|
|
1
|
+
<script setup>
|
2
|
+
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
3
|
+
import { useToast } from 'primevue/usetoast'
|
4
|
+
import TerminalService from 'primevue/terminalservice'
|
5
|
+
import Dock from 'primevue/dock'
|
6
|
+
import Toast from 'primevue/toast'
|
7
|
+
import { useYunAppStore } from '../stores'
|
8
|
+
|
9
|
+
onMounted(() => {
|
10
|
+
TerminalService.on('command', commandHandler)
|
11
|
+
})
|
12
|
+
|
13
|
+
onBeforeUnmount(() => {
|
14
|
+
TerminalService.off('command', commandHandler)
|
15
|
+
})
|
16
|
+
|
17
|
+
const yunApp = useYunAppStore()
|
18
|
+
const showDock = ref(false)
|
19
|
+
watch(() => yunApp.scrollY, () => {
|
20
|
+
if (yunApp.scrollY > 10)
|
21
|
+
showDock.value = true
|
22
|
+
else
|
23
|
+
showDock.value = false
|
24
|
+
})
|
25
|
+
|
26
|
+
const displayFinder = ref(false)
|
27
|
+
const displayTerminal = ref(false)
|
28
|
+
const displayPhotos = ref(false)
|
29
|
+
const toast = useToast()
|
30
|
+
const items = ref([
|
31
|
+
{
|
32
|
+
label: 'Finder',
|
33
|
+
icon: 'https://primefaces.org/cdn/primevue//images/dock/finder.svg',
|
34
|
+
command: () => {
|
35
|
+
displayFinder.value = true
|
36
|
+
},
|
37
|
+
},
|
38
|
+
{
|
39
|
+
label: 'Terminal',
|
40
|
+
icon: 'https://primefaces.org/cdn/primevue//images/dock/terminal.svg',
|
41
|
+
command: () => {
|
42
|
+
displayTerminal.value = true
|
43
|
+
},
|
44
|
+
},
|
45
|
+
{
|
46
|
+
label: 'App Store',
|
47
|
+
icon: 'https://primefaces.org/cdn/primevue//images/dock/appstore.svg',
|
48
|
+
command: () => {
|
49
|
+
toast.add({ severity: 'error', summary: 'An unexpected error occurred while signing in.', detail: 'UNTRUSTED_CERT_TITLE', group: 'tc', life: 3000 })
|
50
|
+
},
|
51
|
+
},
|
52
|
+
{
|
53
|
+
label: 'Safari',
|
54
|
+
icon: 'https://primefaces.org/cdn/primevue//images/dock/safari.svg',
|
55
|
+
command: () => {
|
56
|
+
toast.add({ severity: 'warn', summary: 'Safari has stopped working', group: 'tc', life: 3000 })
|
57
|
+
},
|
58
|
+
},
|
59
|
+
{
|
60
|
+
label: 'Photos',
|
61
|
+
icon: 'https://primefaces.org/cdn/primevue//images/dock/photos.svg',
|
62
|
+
command: () => {
|
63
|
+
displayPhotos.value = true
|
64
|
+
},
|
65
|
+
},
|
66
|
+
{
|
67
|
+
label: 'GitHub',
|
68
|
+
icon: 'https://primefaces.org/cdn/primevue//images/dock/github.svg',
|
69
|
+
},
|
70
|
+
{
|
71
|
+
label: 'Trash',
|
72
|
+
icon: 'https://primefaces.org/cdn/primevue//images/dock/trash.png',
|
73
|
+
command: () => {
|
74
|
+
toast.add({ severity: 'info', summary: 'Empty Trash', life: 3000 })
|
75
|
+
},
|
76
|
+
},
|
77
|
+
])
|
78
|
+
|
79
|
+
function onDockItemClick(event, item) {
|
80
|
+
if (item.command)
|
81
|
+
item.command()
|
82
|
+
|
83
|
+
event.preventDefault()
|
84
|
+
}
|
85
|
+
|
86
|
+
function commandHandler(text) {
|
87
|
+
let response
|
88
|
+
const argsIndex = text.indexOf(' ')
|
89
|
+
const command = argsIndex !== -1 ? text.substring(0, argsIndex) : text
|
90
|
+
|
91
|
+
switch (command) {
|
92
|
+
case 'date':
|
93
|
+
response = `Today is ${new Date().toDateString()}`
|
94
|
+
break
|
95
|
+
|
96
|
+
case 'greet':
|
97
|
+
response = `Hola ${text.substring(argsIndex + 1)}`
|
98
|
+
break
|
99
|
+
|
100
|
+
case 'random':
|
101
|
+
response = Math.floor(Math.random() * 100)
|
102
|
+
break
|
103
|
+
|
104
|
+
default:
|
105
|
+
response = `Unknown command: ${command}`
|
106
|
+
}
|
107
|
+
|
108
|
+
TerminalService.emit('response', response)
|
109
|
+
}
|
110
|
+
</script>
|
111
|
+
|
112
|
+
<template>
|
113
|
+
<Toast position="top-center" group="tc" />
|
114
|
+
|
115
|
+
<!-- yun-dock slide in -->
|
116
|
+
<Transition
|
117
|
+
name="custom-classes"
|
118
|
+
enter-from-class="opacity-0 translate-y-10"
|
119
|
+
enter-to-class="opacity-100 translate-y-0"
|
120
|
+
leave-from-class="opacity-100 translate-y-0"
|
121
|
+
leave-to-class="opacity-0 translate-y-10"
|
122
|
+
>
|
123
|
+
<Dock
|
124
|
+
v-show="showDock"
|
125
|
+
class="fixed bottom-0 left-0 right-0 z-99 transition" flex="~"
|
126
|
+
:model="items"
|
127
|
+
>
|
128
|
+
<template #item="{ item }">
|
129
|
+
<a
|
130
|
+
v-tooltip.top="item.label" href="#"
|
131
|
+
class="yun-dock-item-link" @click="onDockItemClick($event, item)"
|
132
|
+
>
|
133
|
+
<img :alt="item.label" :src="item.icon" style="width: 100%">
|
134
|
+
</a>
|
135
|
+
</template>
|
136
|
+
</Dock>
|
137
|
+
</Transition>
|
138
|
+
|
139
|
+
<!-- <div class="dock-window dock-advanced">
|
140
|
+
<Dialog v-model:visible="displayTerminal" header="Terminal" :breakpoints="{ '960px': '50vw' }" :style="{ width: '40vw' }" :maximizable="true">
|
141
|
+
<Terminal welcome-message="Welcome to PrimeVue(cmd: 'date', 'greet {0}' and 'random')" prompt="primevue $" />
|
142
|
+
</Dialog>
|
143
|
+
|
144
|
+
<Dialog v-model:visible="displayFinder" header="Finder" :breakpoints="{ '960px': '50vw' }" :style="{ width: '40vw' }" :maximizable="true">
|
145
|
+
<Tree :value="nodes" />
|
146
|
+
</Dialog>
|
147
|
+
|
148
|
+
<Galleria v-model:visible="displayPhotos" :value="images" :responsive-options="responsiveOptions" :num-visible="2" container-style="width: 400px" :circular="true" :full-screen="true" :show-thumbnails="false" :show-item-navigators="true">
|
149
|
+
<template #item="slotProps">
|
150
|
+
<img :src="slotProps.item.itemImageSrc" :alt="slotProps.item.alt" style="width: 100%">
|
151
|
+
</template>
|
152
|
+
</Galleria>
|
153
|
+
</div> -->
|
154
|
+
</template>
|
155
|
+
|
156
|
+
<style lang="scss">
|
157
|
+
:root {
|
158
|
+
--p-dock-background: rgb(255 255 255 / 0.1);
|
159
|
+
--p-dock-border-color: rgb(255 255 255 / 0.2);
|
160
|
+
--p-dock-padding: 0.5rem;
|
161
|
+
--p-dock-border-radius: var(--p-border-radius-xl);
|
162
|
+
--p-dock-item-border-radius: var(--p-content-border-radius);
|
163
|
+
--p-dock-item-padding: 0.5rem;
|
164
|
+
--p-dock-item-size: 3rem;
|
165
|
+
--p-dock-item-focus-ring-width: var(--p-focus-ring-width);
|
166
|
+
--p-dock-item-focus-ring-style: var(--p-focus-ring-style);
|
167
|
+
--p-dock-item-focus-ring-color: var(--p-focus-ring-color);
|
168
|
+
--p-dock-item-focus-ring-offset: var(--p-focus-ring-offset);
|
169
|
+
--p-dock-item-focus-ring-shadow: var(--p-focus-ring-shadow);
|
170
|
+
}
|
171
|
+
|
172
|
+
.yun-dock {
|
173
|
+
position: fixed;
|
174
|
+
display: flex;
|
175
|
+
justify-content: center;
|
176
|
+
align-items: center;
|
177
|
+
z-index: var(--yun-z-dock);
|
178
|
+
|
179
|
+
&-bottom {
|
180
|
+
left: 0;
|
181
|
+
bottom: 0;
|
182
|
+
width: 100%;
|
183
|
+
}
|
184
|
+
|
185
|
+
.yun-dock-list-container {
|
186
|
+
display: flex;
|
187
|
+
pointer-events: auto;
|
188
|
+
background: var(--p-dock-background);
|
189
|
+
border: 1px solid var(--p-dock-border-color);
|
190
|
+
padding: var(--p-dock-padding);
|
191
|
+
border-radius: var(--p-dock-border-radius);
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
.yun-dock-list {
|
196
|
+
margin: 0;
|
197
|
+
padding: 0;
|
198
|
+
list-style: none;
|
199
|
+
display: flex;
|
200
|
+
align-items: center;
|
201
|
+
justify-content: center;
|
202
|
+
outline: 0 none;
|
203
|
+
}
|
204
|
+
|
205
|
+
.yun-dock-item {
|
206
|
+
transition: all 0.2s cubic-bezier(0.4,0,0.2,1);
|
207
|
+
will-change: transform;
|
208
|
+
padding: var(--p-dock-item-padding);
|
209
|
+
border-radius: var(--p-dock-item-border-radius);
|
210
|
+
}
|
211
|
+
|
212
|
+
.yun-dock-item-link {
|
213
|
+
display: flex;
|
214
|
+
flex-direction: column;
|
215
|
+
align-items: center;
|
216
|
+
justify-content: center;
|
217
|
+
position: relative;
|
218
|
+
overflow: hidden;
|
219
|
+
cursor: pointer;
|
220
|
+
width: var(--p-dock-item-size);
|
221
|
+
height: var(--p-dock-item-size);
|
222
|
+
}
|
223
|
+
</style>
|
package/components/YunFooter.vue
CHANGED
@@ -1,10 +1,25 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
2
|
import { capitalize, computed } from 'vue'
|
3
|
-
import { useSiteConfig, useValaxyConfig } from 'valaxy'
|
3
|
+
import { useSiteConfig, useValaxyConfig, useValaxyDark } from 'valaxy'
|
4
4
|
import { useI18n } from 'vue-i18n'
|
5
5
|
import pkg from 'valaxy/package.json'
|
6
6
|
import { useThemeConfig } from '../composables'
|
7
7
|
|
8
|
+
// background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
|
9
|
+
const { isDark } = useValaxyDark()
|
10
|
+
const gradientStyles = computed(() => {
|
11
|
+
if (isDark.value) {
|
12
|
+
return {
|
13
|
+
'--gradient-from': '0 0 0',
|
14
|
+
'--gradient-to': '0 0 0',
|
15
|
+
}
|
16
|
+
}
|
17
|
+
return {
|
18
|
+
'--gradient-from': '161 196 253',
|
19
|
+
'--gradient-to': '194 233 251',
|
20
|
+
}
|
21
|
+
})
|
22
|
+
|
8
23
|
const { t } = useI18n()
|
9
24
|
const config = useValaxyConfig()
|
10
25
|
const siteConfig = useSiteConfig()
|
@@ -15,7 +30,7 @@ const isThisYear = computed(() => {
|
|
15
30
|
return year === themeConfig.value.footer.since
|
16
31
|
})
|
17
32
|
|
18
|
-
const poweredHtml = computed(() => t('footer.powered', [`<a href="${pkg.repository.url}" target="_blank" rel="noopener">Valaxy</a> v${pkg.version}
|
33
|
+
const poweredHtml = computed(() => t('footer.powered', [`<a href="${pkg.repository.url}" target="_blank" rel="noopener">Valaxy</a> <span class="op-60">v${pkg.version}</span>`]))
|
19
34
|
const footerIcon = computed(() => themeConfig.value.footer.icon || {
|
20
35
|
url: pkg.repository.url,
|
21
36
|
name: 'i-ri-cloud-line',
|
@@ -24,7 +39,14 @@ const footerIcon = computed(() => themeConfig.value.footer.icon || {
|
|
24
39
|
</script>
|
25
40
|
|
26
41
|
<template>
|
27
|
-
<footer
|
42
|
+
<footer
|
43
|
+
flex="~ col"
|
44
|
+
class="relative yun-footer va-footer px-4 py-4 pt-0 text-$va-c-text-light w-full mt-14"
|
45
|
+
bg="white dark:$va-c-bg-soft"
|
46
|
+
text="center sm"
|
47
|
+
>
|
48
|
+
<YunCloud class="absolute top--10 left-0 right-0" />
|
49
|
+
|
28
50
|
<div v-if="themeConfig.footer.beian?.enable && themeConfig.footer.beian.icp" class="beian" m="y-2">
|
29
51
|
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener">
|
30
52
|
{{ themeConfig.footer.beian.icp }}
|
@@ -54,9 +76,39 @@ const footerIcon = computed(() => themeConfig.value.footer.icon || {
|
|
54
76
|
</div>
|
55
77
|
|
56
78
|
<div v-if="themeConfig.footer.powered" class="powered" m="2">
|
57
|
-
<span v-html="poweredHtml" />
|
79
|
+
<span v-html="poweredHtml" />
|
80
|
+
<span mx-1>|</span>
|
81
|
+
<span>
|
82
|
+
<span>{{ t('footer.theme') }}</span>
|
83
|
+
<span mx-1>-</span>
|
84
|
+
<a :href="themeConfig.pkg.repository.url" :title="themeConfig.pkg.name" target="_blank">{{ capitalize(config.theme) }}</a>
|
85
|
+
<span class="ml-1 op-60">v{{ themeConfig.pkg.version }}</span>
|
86
|
+
</span>
|
58
87
|
</div>
|
59
88
|
|
60
89
|
<slot />
|
90
|
+
|
91
|
+
<div class="yun-footer-gradient" :style="gradientStyles" />
|
61
92
|
</footer>
|
62
93
|
</template>
|
94
|
+
|
95
|
+
<style lang="scss">
|
96
|
+
.yun-footer {
|
97
|
+
letter-spacing: 0.05rem;
|
98
|
+
line-height: 1.8;
|
99
|
+
}
|
100
|
+
|
101
|
+
.yun-footer-gradient {
|
102
|
+
position: absolute;
|
103
|
+
bottom: 0;
|
104
|
+
left: 0;
|
105
|
+
right: 0;
|
106
|
+
width: 100%;
|
107
|
+
height: 300px;
|
108
|
+
z-index: 999;
|
109
|
+
pointer-events: none;
|
110
|
+
background: linear-gradient(to right,rgb(var(--gradient-from) / 0.2) 0,rgb(var(--gradient-to) / .2) 100%);
|
111
|
+
mask-image: linear-gradient(#fff0,#000 70%);
|
112
|
+
animation: fade-in 2s;
|
113
|
+
}
|
114
|
+
</style>
|