valaxy-theme-yun 0.20.0-beta.1 → 0.20.0-beta.11

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.
Files changed (42) hide show
  1. package/bump.config.ts +7 -0
  2. package/components/ValaxyMain.vue +11 -18
  3. package/components/YunAdBoard.vue +4 -0
  4. package/components/YunAlbum.vue +13 -3
  5. package/components/YunAlbumList.vue +5 -11
  6. package/components/YunCategories.vue +2 -1
  7. package/components/YunCategory.vue +23 -37
  8. package/components/YunCategoryChildItem.vue +49 -0
  9. package/components/YunLayoutPostTag.vue +12 -1
  10. package/components/YunNotice.vue +6 -5
  11. package/components/YunOverview.vue +0 -5
  12. package/components/YunPagination.vue +12 -5
  13. package/components/YunPostCollapse.vue +5 -3
  14. package/components/YunPostList.vue +8 -7
  15. package/components/YunPrologue.vue +1 -1
  16. package/components/animation/LineBurstEffects.vue +8 -5
  17. package/components/author/YunAuthorAvatar.vue +2 -1
  18. package/components/layout/YunLayoutWrapper.vue +3 -7
  19. package/components/project/YunProjectCard.vue +29 -3
  20. package/components/project/YunProjectCollection.vue +1 -1
  21. package/components/project/YunProjectToggleButton.vue +1 -0
  22. package/components/prologue/PrologueSquare.vue +81 -109
  23. package/components/prologue/YunAEFrame.vue +68 -85
  24. package/components/site/YunSiteDescription.vue +11 -0
  25. package/components/site/YunSiteLinkItem.vue +1 -1
  26. package/components/site/YunSiteSubtitle.vue +14 -0
  27. package/components/ui/YunDivider.vue +3 -0
  28. package/composables/animation.ts +37 -0
  29. package/layouts/404.vue +1 -3
  30. package/layouts/albums.vue +25 -24
  31. package/layouts/archives.vue +0 -1
  32. package/layouts/categories.vue +8 -4
  33. package/layouts/gallery.vue +31 -30
  34. package/layouts/home.vue +6 -12
  35. package/layouts/tags.vue +11 -5
  36. package/package.json +9 -5
  37. package/styles/animations/index.scss +45 -0
  38. package/styles/css-vars.scss +1 -1
  39. package/styles/layout/index.scss +0 -5
  40. package/unocss.config.ts +0 -1
  41. package/utils/animation.ts +2 -0
  42. package/valaxy.config.ts +1 -0
@@ -1,66 +1,10 @@
1
1
  <script setup lang="ts">
2
- import { useMotion } from '@vueuse/motion'
3
2
  import { ref } from 'vue'
4
- import { useSiteConfig } from 'valaxy'
5
- import { cubicBezier } from '../../client/constants'
6
3
  import { useThemeConfig } from '../../composables'
7
4
 
8
- const siteConfig = useSiteConfig()
9
5
  const themeConfig = useThemeConfig()
10
6
 
11
7
  const showContent = ref(false)
12
- const avatarRef = ref<HTMLElement>()
13
- const motionInstance = useMotion(avatarRef, {
14
- initial: {
15
- borderRadius: '0%',
16
- width: 'var(--total-char-height)',
17
- height: 'var(--total-char-height)',
18
- rotate: 135,
19
- y: '0%',
20
- },
21
- enter: {
22
- borderRadius: '50%',
23
- rotate: 0,
24
- y: '0%',
25
- width: '120px',
26
- height: '120px',
27
- boxShadow: 'none',
28
- transition: {
29
- type: 'keyframes',
30
- ease: cubicBezier.easeIn,
31
- duration: 800,
32
- onComplete: () => {
33
- motionInstance.variant.value = 'leave'
34
- showContent.value = true
35
- },
36
- },
37
- },
38
- leave: {
39
- // y: '-50%',
40
- boxShadow: '0 5px 100px rgba(0, 0, 0, 0.15)',
41
- transition: {
42
- type: 'keyframes',
43
- ease: cubicBezier.easeInOut,
44
- duration: 500,
45
- },
46
- },
47
- })
48
-
49
- const introRef = ref<HTMLElement>()
50
- useMotion(introRef, {
51
- initial: {
52
- y: '0%',
53
- },
54
- enter: {
55
- y: 'calc(-50%)',
56
- transition: {
57
- delay: 800,
58
- type: 'keyframes',
59
- ease: cubicBezier.easeInOut,
60
- duration: 400,
61
- },
62
- },
63
- })
64
8
  </script>
65
9
 
66
10
  <template>
@@ -74,66 +18,77 @@ useMotion(introRef, {
74
18
  <slot />
75
19
 
76
20
  <div
77
- ref="introRef"
78
21
  flex="~ col center"
79
- class="info relative"
22
+ class="info relative duration-800 transition-cubic-bezier-ease-in"
23
+ :class="{
24
+ 'translate-y--1/2': showContent,
25
+ }"
80
26
  >
81
- <div
82
- ref="avatarRef" flex="~ col" class="absolute yun-square bg-$va-c-text square-rotate w-full"
83
- >
84
- <LineBurstEffects
85
- class="absolute top-0 left-0 right-0 bottom-0 size-full scale-200"
86
- :duration="800"
87
- />
88
- <YunAuthorAvatar />
89
- </div>
90
-
91
- <div
92
- v-if="showContent"
93
- v-motion
94
- :initial="{
95
- opacity: 0,
96
- y: '0',
97
- }"
98
- :enter="{
99
- opacity: 1,
100
- y: 'calc(50% + 60px)',
101
- transition: {
102
- type: 'keyframes',
103
- ease: cubicBezier.easeInOut,
104
- duration: 400,
105
- },
106
- }"
27
+ <Transition
28
+ enter-from-class="enter-from"
29
+ enter-to-class="enter-to"
30
+ appear
31
+ @after-appear="showContent = true"
107
32
  >
108
- <YunAuthorName class="mt-3" />
109
- <YunAuthorIntro />
110
- <YunSiteTitle />
111
- <h4 v-if="siteConfig.subtitle" class="site-subtitle block text-$va-c-text op-80" text="sm">
112
- {{ siteConfig.subtitle }}
113
- </h4>
114
- <div v-if="siteConfig.description" class="site-description my-1">
115
- {{ siteConfig.description }}
116
- </div>
117
-
118
33
  <div
119
- class="mt-4 flex-center w-50 md:w-100 m-auto gap-2"
120
- flex="~ wrap"
121
- p="x-$rect-margin"
34
+ flex="~ col"
35
+ class="absolute yun-square bg-$va-c-text square-rotate w-full z-1"
122
36
  >
123
- <YunSiteLinkItem
124
- :page="{
125
- name: '博客文章',
126
- icon: 'i-ri-article-line',
127
- url: '/posts/',
128
- }"
129
- />
130
- <slot />
131
- <YunSiteLinkItem
132
- v-for="item, i in themeConfig.pages"
133
- :key="i" :page="item"
37
+ <LineBurstEffects
38
+ class="absolute top-0 left-0 right-0 bottom-0 size-full scale-200"
39
+ :delay="1000"
40
+ :duration="600"
134
41
  />
42
+ <Transition
43
+ enter-from-class="op-0"
44
+ enter-to-class="op-100"
45
+ enter-active-class="transition-400 delay-400"
46
+ appear
47
+ >
48
+ <YunAuthorAvatar />
49
+ </Transition>
135
50
  </div>
136
- </div>
51
+ </Transition>
52
+
53
+ <Transition
54
+ enter-from-class="translate-y-0"
55
+ enter-active-class="duration-800 transition-cubic-bezier-ease-in"
56
+ appear
57
+ >
58
+ <div v-if="showContent" class="translate-y-[calc(50%+50px)] animate-fade-in">
59
+ <YunAuthorName class="mt-3" />
60
+ <YunAuthorIntro />
61
+
62
+ <YunDivider />
63
+
64
+ <div flex="~ col" class="gap-2 items-center justify-center">
65
+ <YunSiteTitle />
66
+ <YunSiteSubtitle />
67
+ <YunSiteDescription />
68
+ </div>
69
+
70
+ <YunDivider />
71
+
72
+ <div
73
+ class="mt-4 flex-center w-64 md:w-100 m-auto gap-2"
74
+ flex="~ wrap"
75
+ p="x-$rect-margin"
76
+ >
77
+ <YunSiteLinkItem
78
+ :page="{
79
+ name: '博客文章',
80
+ icon: 'i-ri-article-line',
81
+ url: '/posts/',
82
+ }"
83
+ />
84
+ <slot />
85
+ <YunSiteLinkItem
86
+ v-for="item, i in themeConfig.pages"
87
+ :key="i" :page="item"
88
+ />
89
+ </div>
90
+ </div>
91
+ </Transition>
137
92
  </div>
138
93
  </div>
139
94
  </template>
@@ -141,4 +96,21 @@ useMotion(introRef, {
141
96
  <style lang="scss">
142
97
  @use 'sass:map';
143
98
  @use 'valaxy-theme-yun/styles/vars.scss' as *;
99
+
100
+ .yun-square {
101
+ transition: all 0.8s map.get($cubic-bezier, 'ease-in');
102
+ border-radius: 50%;
103
+ transform: rotate(0deg) translateY(0%);
104
+ width: 100px;
105
+ height: 100px;
106
+ box-shadow: 0 5px 100px rgb(0 0 0 / 0.15);
107
+
108
+ &.enter-from {
109
+ border-radius: 0%;
110
+ width: var(--total-char-height);
111
+ height: var(--total-char-height);
112
+ transform: rotate(135deg) translateY(0%);
113
+ box-shadow: none;
114
+ }
115
+ }
144
116
  </style>
@@ -1,100 +1,44 @@
1
1
  <script setup lang="ts">
2
- import type { PopmotionTransitionProps } from '@vueuse/motion'
3
- import { useMotion } from '@vueuse/motion'
4
- import { useAppStore } from 'valaxy'
5
- import { computed, ref } from 'vue'
6
-
7
- const tlRef = ref<HTMLElement>()
8
- const trRef = ref<HTMLElement>()
9
- const blRef = ref<HTMLElement>()
10
- const brRef = ref<HTMLElement>()
11
-
12
- const app = useAppStore()
13
- const cornerSize = computed(() => {
14
- return app.isMobile ? 40 : 50
15
- })
16
- const cornerMargin = computed(() => {
17
- return app.isMobile ? 10 : 30
18
- })
19
- const cornerBorderSize = computed(() => {
20
- return app.isMobile ? 3 : 5
21
- })
22
-
23
- const cornerTransitionProps: PopmotionTransitionProps = {
24
- type: 'spring',
25
- duration: 600,
26
- }
2
+ import { onMounted, ref } from 'vue'
27
3
 
28
- useMotion(tlRef, {
29
- initial: {
30
- x: -cornerMargin.value,
31
- y: -cornerMargin.value,
32
- },
33
- enter: {
34
- x: 0,
35
- y: 0,
36
- transition: cornerTransitionProps,
37
- },
38
- })
39
-
40
- useMotion(trRef, {
41
- initial: {
42
- x: cornerMargin.value,
43
- y: -cornerMargin.value,
44
- },
45
- enter: {
46
- x: 0,
47
- y: 0,
48
- transition: cornerTransitionProps,
49
- },
50
- })
51
-
52
- useMotion(blRef, {
53
- initial: {
54
- x: -cornerMargin.value,
55
- y: cornerMargin.value,
56
- },
57
- enter: {
58
- x: 0,
59
- y: 0,
60
- transition: cornerTransitionProps,
61
- },
62
- })
63
-
64
- useMotion(brRef, {
65
- initial: {
66
- x: cornerMargin.value,
67
- y: cornerMargin.value,
68
- },
69
- enter: {
70
- x: 0,
71
- y: 0,
72
- transition: cornerTransitionProps,
73
- },
74
- })
75
-
76
- const cssVarStyles = computed(() => {
77
- return {
78
- '--corner-size': `${cornerSize.value}px`,
79
- '--corner-margin': `${cornerMargin.value}px`,
80
- '--corner-border-size': `${cornerBorderSize.value}px`,
81
- }
4
+ const playAnim = ref(false)
5
+ onMounted(() => {
6
+ playAnim.value = true
82
7
  })
83
8
  </script>
84
9
 
85
10
  <template>
86
11
  <div
87
- class="ae-frame" :style="cssVarStyles"
12
+ class="yun-ae-frame"
13
+ :class="{
14
+ play: playAnim,
15
+ }"
88
16
  >
89
- <div ref="tlRef" class="absolute" />
90
- <div ref="trRef" class="absolute" />
91
- <div ref="blRef" class="absolute" />
92
- <div ref="brRef" class="absolute" />
17
+ <div class="tl absolute" />
18
+ <div class="tr absolute" />
19
+ <div class="bl absolute" />
20
+ <div class="br absolute" />
93
21
  </div>
94
22
  </template>
95
23
 
96
24
  <style lang="scss">
97
- .ae-frame {
25
+ @use 'sass:map';
26
+ @use 'valaxy/client/styles/mixins/index.scss' as *;
27
+ @use 'valaxy-theme-yun/styles/vars.scss' as *;
28
+
29
+ @include screen('md') {
30
+ .yun-ae-frame {
31
+ --corner-size: 50px;
32
+ --corner-margin: 30px;
33
+ --corner-border-size: 5px;
34
+ }
35
+ }
36
+
37
+ .yun-ae-frame {
38
+ --corner-size: 40px;
39
+ --corner-margin: 8px;
40
+ --corner-border-size: 3px;
41
+
98
42
  div {
99
43
  width: var(--corner-size);
100
44
  height: var(--corner-size);
@@ -151,5 +95,44 @@ const cssVarStyles = computed(() => {
151
95
  }
152
96
  }
153
97
  }
98
+
99
+ .tl, .tr, .bl, .br {
100
+ position: absolute;
101
+ transition: transform 0.6s map.get($cubic-bezier, 'ease-in');
102
+ }
103
+
104
+ .tl {
105
+ transform: translate(calc(var(--corner-margin) * -1), calc(var(--corner-margin) * -1));
106
+ }
107
+
108
+ .tr {
109
+ transform: translate(calc(var(--corner-margin)), calc(var(--corner-margin) * -1));
110
+ }
111
+
112
+ .bl {
113
+ transform: translate(calc(var(--corner-margin) * -1), calc(var(--corner-margin)));
114
+ }
115
+
116
+ .br {
117
+ transform: translate(calc(var(--corner-margin)), calc(var(--corner-margin)));
118
+ }
119
+
120
+ &.play {
121
+ .tl {
122
+ transform: translate(0, 0);
123
+ }
124
+
125
+ .tr {
126
+ transform: translate(0, 0);
127
+ }
128
+
129
+ .bl {
130
+ transform: translate(0, 0);
131
+ }
132
+
133
+ .br {
134
+ transform: translate(0, 0);
135
+ }
136
+ }
154
137
  }
155
138
  </style>
@@ -0,0 +1,11 @@
1
+ <script setup lang="ts">
2
+ import { useSiteConfig } from 'valaxy'
3
+
4
+ const siteConfig = useSiteConfig()
5
+ </script>
6
+
7
+ <template>
8
+ <div v-if="siteConfig.description" class="site-description text-$va-c-text text-sm">
9
+ {{ siteConfig.description }}
10
+ </div>
11
+ </template>
@@ -15,7 +15,7 @@ const yunApp = useYunAppStore()
15
15
  inline-flex
16
16
  :to="page.url" :title="page.name"
17
17
  :style="`color:${page.color}`"
18
- hover="bg-gray-100/50 dark:bg-gray-800/50"
18
+ hover="bg-white/80 dark:bg-black/80"
19
19
  @click="yunApp.fullscreenMenu.isOpen = false"
20
20
  >
21
21
  <div :class="page.icon" class="icon" />
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import { useSiteConfig } from 'valaxy'
3
+
4
+ const siteConfig = useSiteConfig()
5
+ </script>
6
+
7
+ <template>
8
+ <h4
9
+ v-if="siteConfig.subtitle"
10
+ class="site-subtitle block text-$va-c-text op-80" text="sm"
11
+ >
12
+ {{ siteConfig.subtitle }}
13
+ </h4>
14
+ </template>
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <div class="h-1px bg-black/50 dark:bg-white/80 my-4 md:my-6" />
3
+ </template>
@@ -0,0 +1,37 @@
1
+ import { useMotion } from '@vueuse/motion'
2
+ import type { MaybeRef } from 'vue'
3
+ import { cubicBezier } from '../client/constants'
4
+
5
+ /**
6
+ * 统一的弹跳出现动画
7
+ */
8
+ export function useYunSpringAnimation(target: MaybeRef<HTMLElement | undefined>, options: {
9
+ /**
10
+ * index order
11
+ */
12
+ i: number
13
+ y?: number
14
+ duration?: number
15
+ /**
16
+ * delay in ms
17
+ */
18
+ delay?: number
19
+ }) {
20
+ useMotion(target, {
21
+ initial: {
22
+ opacity: 0,
23
+ y: options.y || 40,
24
+ },
25
+ enter: {
26
+ opacity: 1,
27
+ y: 0,
28
+ transition: {
29
+ delay: options.i * (options.delay || 50),
30
+ type: 'spring',
31
+ ease: cubicBezier.easeIn,
32
+ damping: 8,
33
+ duration: options.duration || 400,
34
+ },
35
+ },
36
+ })
37
+ }
package/layouts/404.vue CHANGED
@@ -7,8 +7,6 @@ const { back } = useBack()
7
7
  </script>
8
8
 
9
9
  <template>
10
- <YunSidebar :show-hamburger="true" />
11
-
12
10
  <main class="va-main w-full h-screen" text="center" flex="~ col" justify="center" items="center">
13
11
  <div class="not-found" title="404" font="mono">
14
12
  404
@@ -27,6 +25,6 @@ const { back } = useBack()
27
25
  <style lang="scss" scoped>
28
26
  .not-found {
29
27
  font-size: 10rem;
30
- text-shadow: 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
28
+ text-shadow: 0 5px 10px rgb(0 0 0 / .25), 0 20px 20px rgb(0 0 0 / .15);
31
29
  }
32
30
  </style>
@@ -20,28 +20,29 @@ const albums = computed(() => frontmatter.value.albums || [])
20
20
  </script>
21
21
 
22
22
  <template>
23
- <YunSidebar v-if="$slots['sidebar-child']">
24
- <slot name="sidebar-child" />
25
- </YunSidebar>
26
- <YunSidebar v-else />
27
-
28
- <RouterView v-slot="{ Component }">
29
- <component :is="Component">
30
- <template #main-header>
31
- <YunPageHeader
32
- :title="title || t('title.album')"
33
- :icon="frontmatter.icon || 'i-ri-gallery-line'"
34
- :color="frontmatter.color"
35
- :page-title-class="frontmatter.pageTitleClass"
36
- />
37
- </template>
38
- <template #main-content>
39
- <div text="center" class="yun-text-light" p="2">
40
- {{ t('counter.albums', albums.length) }}
41
- </div>
42
- <YunAlbumList :albums="albums" />
43
- <RouterView />
44
- </template>
45
- </component>
46
- </RouterView>
23
+ <YunLayoutWrapper>
24
+ <YunLayoutLeft />
25
+
26
+ <RouterView v-slot="{ Component }">
27
+ <component :is="Component">
28
+ <template #main-header>
29
+ <YunPageHeader
30
+ :title="title || t('title.album')"
31
+ :icon="frontmatter.icon || 'i-ri-gallery-line'"
32
+ :color="frontmatter.color"
33
+ :page-title-class="frontmatter.pageTitleClass"
34
+ />
35
+ </template>
36
+ <template #main-content>
37
+ <div text="center" class="yun-text-light" p="2">
38
+ {{ t('counter.albums', albums.length) }}
39
+ </div>
40
+ <YunAlbumList :albums="albums" />
41
+ <RouterView />
42
+ </template>
43
+ </component>
44
+ </RouterView>
45
+ </YunLayoutWrapper>
46
+
47
+ <YunFooter />
47
48
  </template>
@@ -33,7 +33,6 @@ const pageIcon = computed(() => {
33
33
  <component :is="Component">
34
34
  <template #main-header>
35
35
  <YunPageHeader
36
- class="mt-8"
37
36
  :title="title || t('menu.archives')"
38
37
  :icon="pageIcon"
39
38
  :color="frontmatter.color"
@@ -53,7 +53,6 @@ useSchemaOrg([
53
53
  <component :is="Component">
54
54
  <template #main-header>
55
55
  <YunPageHeader
56
- class="mt-8"
57
56
  :title="title || t('menu.categories')"
58
57
  :icon="pageIcon"
59
58
  :color="frontmatter.color"
@@ -61,9 +60,14 @@ useSchemaOrg([
61
60
  />
62
61
  </template>
63
62
  <template #main-content>
64
- <div text="center" class="yun-text-light" p="2">
65
- {{ t('counter.categories', Array.from(categories.children).length) }}
66
- </div>
63
+ <Transition
64
+ enter-active-class="animate-fade-in animate-duration-400"
65
+ appear
66
+ >
67
+ <div text="center" class="yun-text-light" p="2">
68
+ {{ t('counter.categories', Array.from(categories.children).length) }}
69
+ </div>
70
+ </Transition>
67
71
  <YunCategories :categories="categories.children" />
68
72
  <RouterView />
69
73
  </template>
@@ -29,34 +29,35 @@ const YunGallery = runtimeConfig.value.addons['valaxy-addon-lightgallery']
29
29
  </script>
30
30
 
31
31
  <template>
32
- <YunSidebar v-if="$slots['sidebar-child']">
33
- <slot name="sidebar-child" />
34
- </YunSidebar>
35
- <YunSidebar v-else />
36
-
37
- <RouterView v-slot="{ Component }">
38
- <component :is="Component">
39
- <template #main-header>
40
- <YunPageHeader
41
- :title="title || t('title.gallery')"
42
- :icon="frontmatter.icon || 'i-ri-gallery-line'"
43
- :color="frontmatter.color"
44
- :page-title-class="frontmatter.pageTitleClass"
45
- />
46
- </template>
47
- <template #main-content>
48
- <div text="center" class="yun-text-light" p="2">
49
- {{ t('counter.photos', photos.length) }}
50
- </div>
51
- <div class="page-action" text="center">
52
- <a class="yun-icon-btn" :title="t('accessibility.back')" @click="() => router.back()">
53
- <div i-ri-arrow-go-back-line />
54
- </a>
55
- </div>
56
- <ValaxyGalleryDecrypt v-if="frontmatter.encryptedPhotos" :encrypted-photos="frontmatter.encryptedPhotos" />
57
- <YunGallery v-else :photos="photos" />
58
- <RouterView />
59
- </template>
60
- </component>
61
- </RouterView>
32
+ <YunLayoutWrapper>
33
+ <YunLayoutLeft />
34
+
35
+ <RouterView v-slot="{ Component }">
36
+ <component :is="Component">
37
+ <template #main-header>
38
+ <YunPageHeader
39
+ :title="title || t('title.gallery')"
40
+ :icon="frontmatter.icon || 'i-ri-gallery-line'"
41
+ :color="frontmatter.color"
42
+ :page-title-class="frontmatter.pageTitleClass"
43
+ />
44
+ </template>
45
+ <template #main-content>
46
+ <div text="center" class="yun-text-light" p="2">
47
+ {{ t('counter.photos', photos.length) }}
48
+ </div>
49
+ <div class="page-action" text="center">
50
+ <a class="yun-icon-btn" :title="t('accessibility.back')" @click="() => router.back()">
51
+ <div i-ri-arrow-go-back-line />
52
+ </a>
53
+ </div>
54
+ <ValaxyGalleryDecrypt v-if="frontmatter.encryptedPhotos" :encrypted-photos="frontmatter.encryptedPhotos" />
55
+ <YunGallery v-else :photos="photos" />
56
+ <RouterView />
57
+ </template>
58
+ </component>
59
+ </RouterView>
60
+ </YunLayoutWrapper>
61
+
62
+ <YunFooter />
62
63
  </template>