valaxy-theme-yun 0.20.0-beta.1 → 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.
Files changed (36) 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 +11 -1
  10. package/components/YunOverview.vue +0 -5
  11. package/components/YunPagination.vue +8 -5
  12. package/components/YunPostCollapse.vue +5 -3
  13. package/components/layout/YunLayoutWrapper.vue +3 -7
  14. package/components/project/YunProjectCard.vue +29 -3
  15. package/components/project/YunProjectCollection.vue +1 -1
  16. package/components/project/YunProjectToggleButton.vue +1 -0
  17. package/components/prologue/PrologueSquare.vue +9 -8
  18. package/components/prologue/YunAEFrame.vue +68 -85
  19. package/components/site/YunSiteDescription.vue +11 -0
  20. package/components/site/YunSiteLinkItem.vue +1 -1
  21. package/components/site/YunSiteSubtitle.vue +14 -0
  22. package/components/ui/YunDivider.vue +3 -0
  23. package/composables/animation.ts +33 -0
  24. package/layouts/404.vue +1 -3
  25. package/layouts/albums.vue +25 -24
  26. package/layouts/archives.vue +0 -1
  27. package/layouts/categories.vue +8 -4
  28. package/layouts/gallery.vue +31 -30
  29. package/layouts/home.vue +5 -11
  30. package/layouts/tags.vue +11 -5
  31. package/package.json +9 -5
  32. package/styles/animations/index.scss +37 -0
  33. package/styles/layout/index.scss +0 -5
  34. package/unocss.config.ts +0 -1
  35. package/utils/animation.ts +2 -0
  36. package/valaxy.config.ts +1 -0
package/bump.config.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'bumpp'
2
+
3
+ export default defineConfig({
4
+ commit: false,
5
+ tag: false,
6
+ push: false,
7
+ })
@@ -46,16 +46,17 @@ onContentUpdated(() => {
46
46
  p="lt-md:0"
47
47
  >
48
48
  <YunCard :cover="frontmatter.cover" m="0" class="relative" :style="styles as StyleValue">
49
- <slot name="main-header">
50
- <YunPageHeader
51
- class="mb-2 mt-8"
52
- :title="title"
53
- :icon="frontmatter.icon || icon"
54
- :color="frontmatter.color || color"
55
- :cover="frontmatter.cover"
56
- :page-title-class="frontmatter.pageTitleClass"
57
- />
58
- </slot>
49
+ <div class="mt-8 mb-4">
50
+ <slot name="main-header">
51
+ <YunPageHeader
52
+ :title="title"
53
+ :icon="frontmatter.icon || icon"
54
+ :color="frontmatter.color || color"
55
+ :cover="frontmatter.cover"
56
+ :page-title-class="frontmatter.pageTitleClass"
57
+ />
58
+ </slot>
59
+ </div>
59
60
  <slot name="main-header-after" />
60
61
 
61
62
  <div p="x-4 b-8" class="sm:px-6 lg:px-12 xl:px-16" w="full">
@@ -97,14 +98,6 @@ onContentUpdated(() => {
97
98
  <style lang="scss">
98
99
  @use 'valaxy/client/styles/mixins/index.scss' as *;
99
100
 
100
- @include screen('md') {
101
- .yun-main {
102
- &.has-sidebar {
103
- padding-left: var(--va-sidebar-width);
104
- }
105
- }
106
- }
107
-
108
101
  @include screen('xl') {
109
102
  .content{
110
103
  // 8px scrollbar width
@@ -0,0 +1,4 @@
1
+ <template>
2
+ <!-- empty -->
3
+ <div />
4
+ </template>
@@ -9,7 +9,7 @@ defineProps<{
9
9
 
10
10
  <template>
11
11
  <AppLink class="yun-album-list-item" :to="album.url">
12
- <figure :title="album.desc">
12
+ <figure class="m-10" flex="~ col" :title="album.desc">
13
13
  <img
14
14
  loading="lazy"
15
15
  class="yun-album-list-cover"
@@ -17,9 +17,19 @@ defineProps<{
17
17
  :alt="album.caption"
18
18
  :on-error="onImgError"
19
19
  >
20
- <figcaption>
21
- {{ album.caption }}
20
+ <figcaption class="yun-album-caption yun-title-effects text-$va-c-text inline-flex">
21
+ {{ album.caption }}
22
22
  </figcaption>
23
23
  </figure>
24
24
  </AppLink>
25
25
  </template>
26
+
27
+ <style lang="scss">
28
+ .yun-album-caption {
29
+ position: absolute;
30
+ bottom: -3rem;
31
+ display: block;
32
+ text-align: center;
33
+ width: 100%;
34
+ }
35
+ </style>
@@ -7,8 +7,11 @@ defineProps<{
7
7
  </script>
8
8
 
9
9
  <template>
10
- <div class="yun-album-list">
11
- <YunAlbum v-for="album in albums" :key="album.url" :album="album" />
10
+ <div class="yun-album-list mb-4">
11
+ <YunAlbum
12
+ v-for="album in albums" :key="album.url"
13
+ :album="album"
14
+ />
12
15
  </div>
13
16
  </template>
14
17
 
@@ -26,7 +29,6 @@ defineProps<{
26
29
  figure {
27
30
  position: relative;
28
31
  width: 15rem;
29
- margin: 2rem;
30
32
 
31
33
  &::before {
32
34
  content: '';
@@ -53,14 +55,6 @@ defineProps<{
53
55
  object-fit: cover;
54
56
  background-color: #eee;
55
57
  }
56
-
57
- figcaption {
58
- position: absolute;
59
- bottom: -2.5rem;
60
- display: block;
61
- text-align: center;
62
- width: 100%;
63
- }
64
58
  }
65
59
  }
66
60
  }
@@ -26,11 +26,12 @@ const categoryList = computed(() => {
26
26
  <template>
27
27
  <div flex="~ col">
28
28
  <ul
29
- v-for="category in categories.values()"
29
+ v-for="(category, i) in categories.values()"
30
30
  :key="category.name"
31
31
  class="category-list"
32
32
  >
33
33
  <YunCategory
34
+ :i="i"
34
35
  :parent-key="category.name"
35
36
  :category="category"
36
37
  :level="level + 1"
@@ -1,11 +1,13 @@
1
1
  <script lang="ts" setup>
2
- import { computed, onMounted, ref } from 'vue'
2
+ import { onMounted, ref } from 'vue'
3
3
  import type { CategoryList, Post } from 'valaxy'
4
- import { isCategoryList, useInvisibleElement } from 'valaxy'
4
+ import { useInvisibleElement } from 'valaxy'
5
5
  import { useI18n } from 'vue-i18n'
6
- import { useRoute, useRouter } from 'vue-router'
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
  /**
@@ -61,11 +49,21 @@ onMounted(() => {
61
49
  if (postCollapseEl)
62
50
  postCollapseElRef.value = postCollapseEl
63
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
+ }
64
61
  </script>
65
62
 
66
63
  <template>
67
64
  <li
68
- class="category-list-item inline-flex items-center cursor-pointer w-full gap-2 transition px-3 py-2 rounded"
65
+ ref="categoryRef"
66
+ class="category-list-item inline-flex items-center cursor-pointer w-full gap-2 px-3 py-2 rounded"
69
67
  hover="bg-black/5"
70
68
  >
71
69
  <span
@@ -98,28 +96,16 @@ onMounted(() => {
98
96
  >
99
97
  <ul v-if="!collapse">
100
98
  <li
101
- v-for="categoryItem, i in category.children.values()" :key="i"
99
+ v-for="categoryItem, cI in category.children.values()"
100
+ :key="cI"
102
101
  class="post-list-item text-$va-c-text" m="l-4"
103
102
  hover="text-$va-c-primary-lighter"
104
103
  >
105
- <template v-if="isCategoryList(categoryItem)">
106
- <YunCategory
107
- :parent-key="parentKey ? `${parentKey}/${categoryItem.name}` : categoryItem.name"
108
- :category="categoryItem"
109
- :collapsable="!categoryList.includes(categoryItem.name)"
110
- />
111
- </template>
112
-
113
- <template v-else>
114
- <RouterLink
115
- v-if="categoryItem.title" :to="categoryItem.path || ''"
116
- class="inline-flex items-center gap-2 px-3 py-2 w-full rounded transition"
117
- hover="bg-black/5"
118
- >
119
- <div i-ri-file-text-line />
120
- <span font="serif black">{{ getTitle(categoryItem) }}</span>
121
- </RouterLink>
122
- </template>
104
+ <YunCategoryChildItem
105
+ :i="cI"
106
+ :category-item="categoryItem"
107
+ :parent-key="parentKey"
108
+ />
123
109
  </li>
124
110
  </ul>
125
111
  </Transition>
@@ -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>
@@ -1,12 +1,22 @@
1
1
  <script lang="ts" setup>
2
- defineProps<{
2
+ import { ref } from 'vue'
3
+ import { useYunSpringAnimation } from '../composables/animation'
4
+
5
+ const props = defineProps<{
6
+ i?: number
3
7
  title: string
4
8
  count: number
5
9
  }>()
10
+
11
+ const tagRef = ref<HTMLElement>()
12
+ useYunSpringAnimation(tagRef, {
13
+ i: props.i || 0,
14
+ })
6
15
  </script>
7
16
 
8
17
  <template>
9
18
  <span
19
+ ref="tagRef"
10
20
  inline-flex my="2" p="1"
11
21
  class="post-tag cursor-pointer items-baseline leading-4"
12
22
  >
@@ -25,9 +25,4 @@
25
25
  font-family: get-css-var('font-serif');
26
26
  font-weight: 900;
27
27
  }
28
-
29
- .site-description {
30
- color: var(--va-c-text);
31
- font-size: 0.8rem;
32
- }
33
28
  </style>
@@ -48,7 +48,7 @@ const { curPage, totalPages, showPage, getTo, surLen, prevTo, nextTo, showPrev,
48
48
 
49
49
  <style lang="scss">
50
50
  :root {
51
- --page-btn-bg-color: rgba(255, 255, 255, 0.5);
51
+ --page-btn-bg-color: rgb(255 255 255 / 0.5);
52
52
  --page-btn-hover-bg-color: var(--va-c-primary-lighter);
53
53
  --page-btn-active-bg-color: var(--va-c-primary-light);
54
54
  }
@@ -69,10 +69,10 @@ const { curPage, totalPages, showPage, getTo, surLen, prevTo, nextTo, showPrev,
69
69
  width: 2rem;
70
70
  height: 2rem;
71
71
  margin: 0;
72
- transition: background-color var(--va-transition-duration) ease;
73
72
 
74
73
  // disabled attr
75
74
  &[disabled] {
75
+ color: var(--va-c-text-light);
76
76
  background-color: var(--va-c-bg-mute);
77
77
  }
78
78
  }
@@ -84,19 +84,22 @@ const { curPage, totalPages, showPage, getTo, surLen, prevTo, nextTo, showPrev,
84
84
  background-color: var(--page-btn-bg-color);
85
85
 
86
86
  &:hover {
87
- color: var(--va-c-bg);
87
+ // color: var(--va-c-bg);
88
+ color: white;
88
89
  background: var(--page-btn-hover-bg-color);
89
90
  }
90
91
 
91
92
  &:active {
92
- color: var(--va-c-bg);
93
+ // color: var(--va-c-bg);
94
+ color: white;
93
95
  background: var(--page-btn-active-bg-color);
94
96
  }
95
97
 
96
98
  &.active {
99
+ // color: var(--va-c-bg);
100
+ color: white;
97
101
  font-weight: normal;
98
102
  background: var(--page-btn-active-bg-color);
99
- color: var(--va-c-bg);
100
103
  cursor: default;
101
104
  }
102
105
 
@@ -45,9 +45,11 @@ const sortedYears = computed(() => {
45
45
 
46
46
  <template>
47
47
  <div class="post-collapse px-10 lt-sm:px-5 max-w-3xl" relative>
48
- <div w="full" text="center" class="yun-text-light" p="2">
49
- {{ t('counter.archives', posts.length) }}
50
- </div>
48
+ <Transition appear enter-active-class="animate-fade-in animate-duration-400">
49
+ <div w="full" text="center" class="yun-text-light" p="2">
50
+ {{ t('counter.archives', posts.length) }}
51
+ </div>
52
+ </Transition>
51
53
 
52
54
  <div class="post-collapse-action" text="center">
53
55
  <button class="yun-icon-btn shadow hover:shadow-md" @click="isDesc = !isDesc">
@@ -1,16 +1,12 @@
1
1
  <script setup lang="ts">
2
- import { useYunAppStore } from '../../stores'
3
-
4
- const yun = useYunAppStore()
2
+ // common layout
5
3
  </script>
6
4
 
7
5
  <template>
8
6
  <div
9
7
  flex="~"
10
- class="mt-24 md:mt-36 w-full max-w-screen-2xl m-auto justify-center items-start gap-4"
11
- :class="{
12
- 'flex-col': yun.size.isXs,
13
- }"
8
+ m="t-24 md:t-36"
9
+ class="w-full max-w-screen-2xl m-auto justify-center items-start gap-4"
14
10
  >
15
11
  <slot />
16
12
  </div>
@@ -1,9 +1,34 @@
1
1
  <script setup lang="ts">
2
- import { type CSSProperties, computed } from 'vue'
2
+ import { type CSSProperties, computed, ref } from 'vue'
3
3
  import { TinyColor } from '@ctrl/tinycolor'
4
+ import { useMotion } from '@vueuse/motion'
4
5
  import type { ProjectItem } from '../../types'
6
+ import { cubicBezier } from '../../client/constants'
7
+
8
+ const props = defineProps<{
9
+ i: number
10
+ project: ProjectItem
11
+ }>()
12
+
13
+ const cardRef = ref<HTMLElement>()
14
+ useMotion(cardRef, {
15
+ initial: {
16
+ opacity: 0,
17
+ y: 50,
18
+ },
19
+ enter: {
20
+ opacity: 1,
21
+ y: 0,
22
+ transition: {
23
+ delay: props.i * 50,
24
+ type: 'spring',
25
+ ease: cubicBezier.easeIn,
26
+ damping: 8,
27
+ duration: 400,
28
+ },
29
+ },
30
+ })
5
31
 
6
- const props = defineProps<{ project: ProjectItem }>()
7
32
  const cardStyle = computed(() => {
8
33
  const styles: CSSProperties = {
9
34
  color: props.project.textColor,
@@ -63,8 +88,9 @@ const links = computed(() => [
63
88
 
64
89
  <template>
65
90
  <div
91
+ ref="cardRef"
66
92
  flex="~ col center"
67
- class="m-2 w-90 transform rounded shadow-md grayscale-30 transition duration-400"
93
+ class="m-2 w-90 transform rounded shadow-md grayscale-30"
68
94
  bg="opacity-80 gradient-to-br"
69
95
  p="x-2 b-12"
70
96
  hover="shadow-lg grayscale-0"
@@ -11,5 +11,5 @@ defineProps<{
11
11
  <div class="w-full flex justify-center" text="xl" font="black" m="b-2 t-4">
12
12
  {{ title }}
13
13
  </div>
14
- <YunProjectCard v-for="project, i in projects" :key="i" :project="project" />
14
+ <YunProjectCard v-for="project, i in projects" :key="i" :project="project" :i="i" />
15
15
  </template>
@@ -9,6 +9,7 @@ defineProps<{
9
9
  class="bg-white-90 m-2 inline-flex items-center justify-center rounded px-2 gap-2 h-8"
10
10
  :class="{
11
11
  'bg-blue-500 text-white': active,
12
+ 'hover:bg-$va-c-bg-soft': !active,
12
13
  }"
13
14
  >
14
15
  <slot />
@@ -1,11 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  import { useMotion } from '@vueuse/motion'
3
3
  import { ref } from 'vue'
4
- import { useSiteConfig } from 'valaxy'
5
4
  import { cubicBezier } from '../../client/constants'
6
5
  import { useThemeConfig } from '../../composables'
7
6
 
8
- const siteConfig = useSiteConfig()
9
7
  const themeConfig = useThemeConfig()
10
8
 
11
9
  const showContent = ref(false)
@@ -107,14 +105,17 @@ useMotion(introRef, {
107
105
  >
108
106
  <YunAuthorName class="mt-3" />
109
107
  <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 }}
108
+
109
+ <YunDivider />
110
+
111
+ <div flex="~ col" class="gap-2 items-center justify-center">
112
+ <YunSiteTitle />
113
+ <YunSiteSubtitle />
114
+ <YunSiteDescription />
116
115
  </div>
117
116
 
117
+ <YunDivider />
118
+
118
119
  <div
119
120
  class="mt-4 flex-center w-50 md:w-100 m-auto gap-2"
120
121
  flex="~ wrap"
@@ -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: 10px;
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,33 @@
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
+ useMotion(target, {
17
+ initial: {
18
+ opacity: 0,
19
+ y: options.y || 40,
20
+ },
21
+ enter: {
22
+ opacity: 1,
23
+ y: 0,
24
+ transition: {
25
+ delay: options.i * 50,
26
+ type: 'spring',
27
+ ease: cubicBezier.easeIn,
28
+ damping: 8,
29
+ duration: options.duration || 400,
30
+ },
31
+ },
32
+ })
33
+ }
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>
package/layouts/home.vue CHANGED
@@ -1,10 +1,8 @@
1
1
  <script lang="ts" setup>
2
2
  import { computed } from 'vue'
3
3
  import { useRoute } from 'vue-router'
4
- import { useYunAppStore } from '../stores'
5
4
  import { useThemeConfig } from '../composables'
6
5
 
7
- const yunStore = useYunAppStore()
8
6
  const route = useRoute()
9
7
  const themeConfig = useThemeConfig()
10
8
 
@@ -17,16 +15,12 @@ const showNotice = computed(() => {
17
15
  </script>
18
16
 
19
17
  <template>
20
- <main
21
- class="yun-main flex-center"
18
+ <YunLayoutWrapper
19
+ class="items-center flex-col"
22
20
  :class="{
23
- 'pl-0': !yunStore.leftSidebar.isOpen,
24
- 'md:pl-$va-sidebar-width': yunStore.leftSidebar.isOpen,
25
- 'pt-36': isPage,
26
- }" flex="~ col" w="full"
21
+ 'mt-0!': !isPage,
22
+ }"
27
23
  >
28
- <YunSidebar :show-hamburger="true" />
29
-
30
24
  <template v-if="!isPage">
31
25
  <YunBanner />
32
26
  <YunSay v-if="themeConfig.say.enable" w="full" />
@@ -49,5 +43,5 @@ const showNotice = computed(() => {
49
43
  </slot>
50
44
 
51
45
  <YunFooter />
52
- </main>
46
+ </YunLayoutWrapper>
53
47
  </template>
package/layouts/tags.vue CHANGED
@@ -53,6 +53,7 @@ function displayTag(tag: string) {
53
53
  }
54
54
 
55
55
  const title = usePostTitle(frontmatter)
56
+ const tagArr = computed(() => Array.from(tags.value).sort())
56
57
 
57
58
  // use flex to fix `overflow-wrap: break-words;` not working in Safari
58
59
  </script>
@@ -65,7 +66,6 @@ const title = usePostTitle(frontmatter)
65
66
  <component :is="Component">
66
67
  <template #main-header>
67
68
  <YunPageHeader
68
- class="mt-8"
69
69
  :title="title || t('menu.tags')"
70
70
  :icon="frontmatter.icon || 'i-ri-tag-line'"
71
71
  :color="frontmatter.color"
@@ -73,14 +73,20 @@ const title = usePostTitle(frontmatter)
73
73
  />
74
74
  </template>
75
75
  <template #main-content>
76
- <div class="yun-text-light" text="center" p="2">
77
- {{ t('counter.tags', Array.from(tags).length) }}
78
- </div>
76
+ <Transition
77
+ enter-active-class="animate-fade-in animate-duration-400"
78
+ appear
79
+ >
80
+ <div class="yun-text-light" text="center" p="2">
81
+ {{ t('counter.tags', tagArr.length) }}
82
+ </div>
83
+ </Transition>
79
84
 
80
85
  <div class="justify-center items-end" flex="~ wrap" gap="1">
81
86
  <YunLayoutPostTag
82
- v-for="[key, tag] in Array.from(tags).sort()"
87
+ v-for="([key, tag], i) in tagArr"
83
88
  :key="key"
89
+ :i="i"
84
90
  :title="key"
85
91
  :count="tag.count"
86
92
  :style="getTagStyle(tag.count)"
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "valaxy-theme-yun",
3
- "version": "0.20.0-beta.1",
3
+ "type": "module",
4
+ "version": "0.20.0-beta.10",
4
5
  "author": {
5
6
  "email": "me@yunyoujun.cn",
6
7
  "name": "YunYouJun",
@@ -19,9 +20,12 @@
19
20
  },
20
21
  "main": "index.ts",
21
22
  "module": "index.ts",
23
+ "scripts": {
24
+ "release": "bumpp && npm publish"
25
+ },
22
26
  "dependencies": {
23
27
  "@ctrl/tinycolor": "^4.1.0",
24
- "@explosions/fireworks": "^0.0.2",
28
+ "@explosions/fireworks": "^0.1.0",
25
29
  "@iconify-json/ant-design": "^1.2.1",
26
30
  "@iconify-json/simple-icons": "^1.2.5",
27
31
  "@vueuse/motion": "^2.2.5",
@@ -32,7 +36,7 @@
32
36
  },
33
37
  "devDependencies": {
34
38
  "@types/animejs": "^3.1.12",
35
- "valaxy-addon-waline": "0.2.0",
36
- "valaxy": "0.20.0-beta.1"
39
+ "valaxy": "workspace:*",
40
+ "valaxy-addon-waline": "workspace:*"
37
41
  }
38
- }
42
+ }
@@ -34,3 +34,40 @@
34
34
  opacity: 1;
35
35
  }
36
36
  }
37
+
38
+ // title-effects
39
+ .yun-title-effects {
40
+ position: relative;
41
+
42
+ &::before,
43
+ &::after {
44
+ content: "";
45
+ position: absolute;
46
+ width: 10px;
47
+ height: 10px;
48
+ opacity: 0;
49
+ border: 2px solid;
50
+ transition: 0.3s;
51
+ transition-timing-function: cubic-bezier(0.17, 0.67, 0.05, 1.29);
52
+ }
53
+
54
+ &::before {
55
+ top: 0;
56
+ left: 0;
57
+ border-width: 2px 0 0 2px;
58
+ transform: translate3d(10px, 10px, 0);
59
+ }
60
+
61
+ &::after {
62
+ right: 0;
63
+ bottom: 0;
64
+ border-width: 0 2px 2px 0;
65
+ transform: translate3d(-10px, -10px, 0);
66
+ }
67
+
68
+ &:hover::before,
69
+ &:hover::after {
70
+ opacity: 1;
71
+ transform: translate3d(0, 0, 0);
72
+ }
73
+ }
@@ -6,8 +6,3 @@
6
6
  html {
7
7
  overflow-y: scroll;
8
8
  }
9
-
10
- .yun-main {
11
- transition: padding-left var(--va-transition-duration);
12
- transition-timing-function: map.get($cubic-bezier, 'ease-in-out');
13
- }
package/unocss.config.ts CHANGED
@@ -2,7 +2,6 @@ import { defineConfig } from 'unocss'
2
2
 
3
3
  export default defineConfig({
4
4
  shortcuts: [
5
- ['yun-main', 'lt-md:pl-0'],
6
5
  ['yun-card', 'transition yun-transition shadow hover:shadow-lg'],
7
6
  ],
8
7
  rules: [
@@ -1,4 +1,6 @@
1
1
  import { gsap } from 'gsap'
2
+ // gsap/ScrollToPlugin is ESM, but gsap not include 'type:module' in package.json
3
+ // use cjs for vite-ssg, optimizeDeps for ESM
2
4
  import ScrollToPlugin from 'gsap/dist/ScrollToPlugin'
3
5
 
4
6
  gsap.registerPlugin(ScrollToPlugin)
package/valaxy.config.ts CHANGED
@@ -20,6 +20,7 @@ function ThemeVitePlugin(options: ResolvedValaxyOptions<ThemeConfig>): Plugin {
20
20
  },
21
21
 
22
22
  optimizeDeps: {
23
+ include: ['gsap/dist/ScrollToPlugin'],
23
24
  exclude: ['@docsearch/js'],
24
25
  },
25
26
  }