valaxy-theme-press 0.0.2 → 0.0.4
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/client/index.ts +1 -0
- package/components/PressAlgoliaSearch.vue +208 -0
- package/components/PressArticle.vue +27 -16
- package/components/PressArticleCard.vue +6 -2
- package/components/PressAside.vue +38 -27
- package/components/PressBackdrop.vue +1 -1
- package/components/PressButton.vue +5 -12
- package/components/PressCategories.vue +24 -3
- package/components/PressCategory.vue +24 -15
- package/components/PressDocFooter.vue +15 -0
- package/components/PressDocFooterLastUpdated.vue +44 -0
- package/components/PressFeature.vue +1 -1
- package/components/PressFeatures.vue +1 -1
- package/components/PressFooter.vue +53 -0
- package/components/PressHome.vue +1 -7
- package/components/PressHomeFeatures.vue +1 -0
- package/components/PressHomeHero.vue +7 -8
- package/components/PressLocalNav.vue +9 -9
- package/components/PressNav.vue +30 -5
- package/components/PressNavBar.vue +94 -0
- package/components/PressNavBarAppearance.vue +5 -0
- package/components/PressNavBarHamburger.vue +79 -0
- package/components/PressNavBarMenu.vue +14 -0
- package/components/PressNavBarSearch.vue +40 -0
- package/components/PressNavBarSocialLinks.vue +26 -0
- package/components/PressNavBarTranslations.vue +5 -0
- package/components/PressNavItemGroup.vue +101 -0
- package/components/PressNavItemLink.vue +40 -0
- package/components/PressNavScreen.vue +95 -0
- package/components/PressNavScreenAppearance.vue +32 -0
- package/components/PressNavScreenMenu.vue +22 -0
- package/components/PressNavScreenMenuGroup.vue +115 -0
- package/components/PressNavScreenMenuGroupLink.vue +32 -0
- package/components/PressNavScreenMenuGroupSection.vue +37 -0
- package/components/PressNavScreenMenuLink.vue +33 -0
- package/components/PressNavScreenSocialLinks.vue +13 -0
- package/components/PressNavScreenTranslations.vue +7 -0
- package/components/{PressToc.vue → PressOutline.vue} +14 -39
- package/components/PressOutlineItem.vue +48 -0
- package/components/PressPostList.vue +3 -3
- package/components/PressSidebar.vue +31 -10
- package/components/PressSocialLink.vue +40 -0
- package/components/PressSocialLinks.vue +26 -0
- package/components/ValaxyMain.vue +60 -42
- package/composables/edit-link.ts +14 -0
- package/composables/index.ts +1 -0
- package/composables/nav.ts +37 -0
- package/config/index.ts +13 -2
- package/layouts/layout.vue +5 -3
- package/package.json +15 -5
- package/pages/[..all].vue +1 -0
- package/setup/main.ts +5 -4
- package/styles/css-vars.scss +16 -8
- package/styles/helper.scss +0 -10
- package/styles/markdown.scss +18 -8
- package/types/index.d.ts +76 -22
- package/utils/index.ts +9 -0
- package/valaxy.config.ts +7 -0
- package/LICENSE +0 -21
- package/components/DocsBoard.vue +0 -24
- package/components/nav/PressNavBar.vue +0 -123
- /package/components/{nav/PressSwitchAppearance.vue → PressSwitchAppearance.vue} +0 -0
package/client/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../composables'
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useI18n } from 'vue-i18n'
|
|
3
|
+
import { useAddonAlgolia } from 'valaxy-addon-algolia'
|
|
4
|
+
|
|
5
|
+
const { t } = useI18n()
|
|
6
|
+
|
|
7
|
+
const { loaded, load, metaKey } = useAddonAlgolia()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div>
|
|
12
|
+
<AlgoliaSearchBox v-if="loaded" />
|
|
13
|
+
|
|
14
|
+
<div v-else id="docsearch" @click="load">
|
|
15
|
+
<button
|
|
16
|
+
class="DocSearch DocSearch-Button"
|
|
17
|
+
aria-label="Search"
|
|
18
|
+
>
|
|
19
|
+
<span class="DocSearch-Button-Container">
|
|
20
|
+
<svg
|
|
21
|
+
class="DocSearch-Search-Icon"
|
|
22
|
+
width="20"
|
|
23
|
+
height="20"
|
|
24
|
+
viewBox="0 0 20 20"
|
|
25
|
+
>
|
|
26
|
+
<path
|
|
27
|
+
d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
|
|
28
|
+
stroke="currentColor"
|
|
29
|
+
fill="none"
|
|
30
|
+
fill-rule="evenodd"
|
|
31
|
+
stroke-linecap="round"
|
|
32
|
+
stroke-linejoin="round"
|
|
33
|
+
/>
|
|
34
|
+
</svg>
|
|
35
|
+
<span class="DocSearch-Button-Placeholder">{{ t('search.placeholder') }}</span>
|
|
36
|
+
</span>
|
|
37
|
+
<span class="DocSearch-Button-Keys">
|
|
38
|
+
<kbd class="DocSearch-Button-Key" />
|
|
39
|
+
<kbd class="DocSearch-Button-Key">K</kbd>
|
|
40
|
+
</span>
|
|
41
|
+
</button>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<style>
|
|
47
|
+
.DocSearch-Button {
|
|
48
|
+
display: flex;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
align-items: center;
|
|
51
|
+
margin: 0;
|
|
52
|
+
padding: 0;
|
|
53
|
+
width: 32px;
|
|
54
|
+
height: 55px;
|
|
55
|
+
background: transparent;
|
|
56
|
+
transition: border-color 0.25s;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.DocSearch-Button:hover {
|
|
60
|
+
background: transparent;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.DocSearch-Button:focus {
|
|
64
|
+
outline: 1px dotted;
|
|
65
|
+
outline: 5px auto -webkit-focus-ring-color;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.DocSearch-Button:focus:not(:focus-visible) {
|
|
69
|
+
outline: none !important;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@media (min-width: 768px) {
|
|
73
|
+
.DocSearch-Button {
|
|
74
|
+
justify-content: flex-start;
|
|
75
|
+
border: 1px solid transparent;
|
|
76
|
+
border-radius: 8px;
|
|
77
|
+
padding: 0 10px 0 12px;
|
|
78
|
+
width: 100%;
|
|
79
|
+
height: 40px;
|
|
80
|
+
background-color: var(--va-c-bg-alt);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.DocSearch-Button:hover {
|
|
84
|
+
border-color: var(--va-c-brand);
|
|
85
|
+
background: var(--va-c-bg-alt);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.DocSearch-Button .DocSearch-Button-Container {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.DocSearch-Button .DocSearch-Search-Icon {
|
|
95
|
+
position: relative;
|
|
96
|
+
width: 16px;
|
|
97
|
+
height: 16px;
|
|
98
|
+
color: var(--va-c-text-1);
|
|
99
|
+
fill: currentColor;
|
|
100
|
+
transition: color 0.5s;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.DocSearch-Button:hover .DocSearch-Search-Icon {
|
|
104
|
+
color: var(--va-c-text-1);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@media (min-width: 768px) {
|
|
108
|
+
.DocSearch-Button .DocSearch-Search-Icon {
|
|
109
|
+
top: 1px;
|
|
110
|
+
margin-right: 8px;
|
|
111
|
+
width: 14px;
|
|
112
|
+
height: 14px;
|
|
113
|
+
color: var(--va-c-text-2);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.DocSearch-Button .DocSearch-Button-Placeholder {
|
|
118
|
+
display: none;
|
|
119
|
+
margin-top: 2px;
|
|
120
|
+
padding: 0 16px 0 0;
|
|
121
|
+
font-size: 13px;
|
|
122
|
+
font-weight: 500;
|
|
123
|
+
color: var(--va-c-text-2);
|
|
124
|
+
transition: color 0.5s;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.DocSearch-Button:hover .DocSearch-Button-Placeholder {
|
|
128
|
+
color: var(--va-c-text-1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@media (min-width: 768px) {
|
|
132
|
+
.DocSearch-Button .DocSearch-Button-Placeholder {
|
|
133
|
+
display: inline-block;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.DocSearch-Button .DocSearch-Button-Keys {
|
|
138
|
+
/*rtl:ignore*/
|
|
139
|
+
direction: ltr;
|
|
140
|
+
display: none;
|
|
141
|
+
min-width: auto;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@media (min-width: 768px) {
|
|
145
|
+
.DocSearch-Button .DocSearch-Button-Keys {
|
|
146
|
+
display: flex;
|
|
147
|
+
align-items: center;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.DocSearch-Button .DocSearch-Button-Key {
|
|
152
|
+
display: block;
|
|
153
|
+
margin: 2px 0 0 0;
|
|
154
|
+
border: 1px solid var(--va-c-divider);
|
|
155
|
+
/*rtl:begin:ignore*/
|
|
156
|
+
border-right: none;
|
|
157
|
+
border-radius: 4px 0 0 4px;
|
|
158
|
+
padding-left: 6px;
|
|
159
|
+
/*rtl:end:ignore*/
|
|
160
|
+
min-width: 0;
|
|
161
|
+
width: auto;
|
|
162
|
+
height: 22px;
|
|
163
|
+
font-family: var(--va-font-sans);
|
|
164
|
+
font-size: 12px;
|
|
165
|
+
font-weight: 500;
|
|
166
|
+
transition: color 0.5s, border-color 0.5s;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.DocSearch-Button .DocSearch-Button-Key + .DocSearch-Button-Key {
|
|
170
|
+
/*rtl:begin:ignore*/
|
|
171
|
+
border-right: 1px solid var(--va-c-divider);
|
|
172
|
+
border-left: none;
|
|
173
|
+
border-radius: 0 4px 4px 0;
|
|
174
|
+
padding-left: 2px;
|
|
175
|
+
padding-right: 6px;
|
|
176
|
+
/*rtl:end:ignore*/
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.DocSearch-Button .DocSearch-Button-Key:first-child {
|
|
180
|
+
font-size: 1px;
|
|
181
|
+
letter-spacing: -12px;
|
|
182
|
+
color: transparent;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.DocSearch-Button .DocSearch-Button-Key:first-child:after {
|
|
186
|
+
content: v-bind(metaKey);
|
|
187
|
+
font-size: 12px;
|
|
188
|
+
letter-spacing: normal;
|
|
189
|
+
color: var(--docsearch-muted-color);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.DocSearch-Button .DocSearch-Button-Key:first-child > * {
|
|
193
|
+
display: none;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.dark .DocSearch-Footer {
|
|
197
|
+
border-top: 1px solid var(--va-c-divider);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.DocSearch-Form {
|
|
201
|
+
border: 1px solid var(--va-c-brand);
|
|
202
|
+
background-color: var(--va-c-white);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.dark .DocSearch-Form {
|
|
206
|
+
background-color: var(--va-c-bg-soft-mute);
|
|
207
|
+
}
|
|
208
|
+
</style>
|
|
@@ -2,36 +2,41 @@
|
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import { useRoute } from 'vue-router'
|
|
4
4
|
|
|
5
|
-
import { useFrontmatter,
|
|
5
|
+
import { useFrontmatter, useSiteStore } from 'valaxy'
|
|
6
|
+
import { useI18n } from 'vue-i18n'
|
|
7
|
+
import { getLocaleTitle } from '../utils'
|
|
8
|
+
|
|
6
9
|
const frontmatter = useFrontmatter()
|
|
7
10
|
|
|
8
11
|
const route = useRoute()
|
|
9
|
-
const
|
|
12
|
+
const site = useSiteStore()
|
|
10
13
|
|
|
11
14
|
function findCurrentIndex() {
|
|
12
|
-
return
|
|
15
|
+
return site.postList.findIndex(p => p.href === route.path)
|
|
13
16
|
}
|
|
14
17
|
|
|
15
|
-
const nextPost = computed(() =>
|
|
16
|
-
const prevPost = computed(() =>
|
|
18
|
+
const nextPost = computed(() => site.postList[findCurrentIndex() - 1])
|
|
19
|
+
const prevPost = computed(() => site.postList[findCurrentIndex() + 1])
|
|
20
|
+
|
|
21
|
+
const { locale } = useI18n()
|
|
22
|
+
const localeTitle = computed(() => getLocaleTitle(locale.value, frontmatter.value))
|
|
17
23
|
</script>
|
|
18
24
|
|
|
19
25
|
<template>
|
|
20
|
-
<article class="xl:divide-y xl:divide-gray-200">
|
|
21
|
-
<header class="pt-
|
|
26
|
+
<article class="xl:divide-y xl:divide-gray-200 max-w-7xl m-auto" p="x-6" w="full">
|
|
27
|
+
<header class="pt-20 xl:pb-10 space-y-1 text-center">
|
|
22
28
|
<PressDate :date="frontmatter.date" />
|
|
23
29
|
<h1
|
|
24
30
|
class="
|
|
25
31
|
text-3xl
|
|
26
32
|
leading-9
|
|
27
33
|
font-extrabold
|
|
28
|
-
text-gray-900
|
|
29
34
|
tracking-tight
|
|
30
35
|
sm:text-4xl sm:leading-10
|
|
31
36
|
md:text-5xl md:leading-14
|
|
32
37
|
"
|
|
33
38
|
>
|
|
34
|
-
{{
|
|
39
|
+
{{ localeTitle }}
|
|
35
40
|
</h1>
|
|
36
41
|
</header>
|
|
37
42
|
|
|
@@ -40,14 +45,14 @@ const prevPost = computed(() => posts.value[findCurrentIndex() + 1])
|
|
|
40
45
|
divide-y
|
|
41
46
|
xl:divide-y-0
|
|
42
47
|
divide-gray-200
|
|
43
|
-
xl:grid xl:grid-cols-
|
|
48
|
+
xl:grid xl:grid-cols-12 xl:gap-x-6
|
|
44
49
|
pb-16
|
|
45
50
|
xl:pb-20
|
|
46
51
|
"
|
|
47
52
|
style="grid-template-rows: auto 1fr"
|
|
48
53
|
>
|
|
49
54
|
<PressAuthor v-if="frontmatter.author" :frontmatter="frontmatter" />
|
|
50
|
-
<div class="divide-y divide-gray-200 xl:pb-0 xl:col-span-
|
|
55
|
+
<div class="divide-y divide-gray-200 xl:pb-0 xl:col-span-8 xl:row-span-2">
|
|
51
56
|
<router-view />
|
|
52
57
|
</div>
|
|
53
58
|
|
|
@@ -57,7 +62,7 @@ const prevPost = computed(() => posts.value[findCurrentIndex() + 1])
|
|
|
57
62
|
font-medium
|
|
58
63
|
leading-5
|
|
59
64
|
divide-y divide-gray-200
|
|
60
|
-
xl:col-start-1 xl:row-start-2
|
|
65
|
+
xl:col-start-1 xl:row-start-2 xl:col-span-2
|
|
61
66
|
"
|
|
62
67
|
>
|
|
63
68
|
<div v-if="nextPost" class="py-8">
|
|
@@ -65,19 +70,25 @@ const prevPost = computed(() => posts.value[findCurrentIndex() + 1])
|
|
|
65
70
|
Next Article
|
|
66
71
|
</h2>
|
|
67
72
|
<div class="link">
|
|
68
|
-
<
|
|
73
|
+
<router-link :to="nextPost.href">
|
|
74
|
+
{{ nextPost.title }}
|
|
75
|
+
</router-link>
|
|
69
76
|
</div>
|
|
70
77
|
</div>
|
|
71
|
-
<div v-if="prevPost" class="py-8">
|
|
78
|
+
<div v-if="prevPost && prevPost.href" class="py-8">
|
|
72
79
|
<h2 class="text-xs tracking-wide uppercase text-gray-500">
|
|
73
80
|
Previous Article
|
|
74
81
|
</h2>
|
|
75
82
|
<div class="link">
|
|
76
|
-
<
|
|
83
|
+
<router-link :to="prevPost.href">
|
|
84
|
+
{{ prevPost.title }}
|
|
85
|
+
</router-link>
|
|
77
86
|
</div>
|
|
78
87
|
</div>
|
|
79
88
|
<div class="pt-8">
|
|
80
|
-
<
|
|
89
|
+
<router-link class="link" to="/">
|
|
90
|
+
← Back to Home
|
|
91
|
+
</router-link>
|
|
81
92
|
</div>
|
|
82
93
|
</footer>
|
|
83
94
|
</div>
|
|
@@ -12,7 +12,9 @@ defineProps<{
|
|
|
12
12
|
<div class="space-y-5 xl:col-span-3">
|
|
13
13
|
<div class="space-y-6">
|
|
14
14
|
<h2 class="text-2xl leading-8 font-bold tracking-tight">
|
|
15
|
-
<
|
|
15
|
+
<router-link class="text-gray-900" :to="post.path || ''">
|
|
16
|
+
{{ post.title }}
|
|
17
|
+
</router-link>
|
|
16
18
|
</h2>
|
|
17
19
|
<div
|
|
18
20
|
v-if="post.excerpt"
|
|
@@ -21,7 +23,9 @@ defineProps<{
|
|
|
21
23
|
/>
|
|
22
24
|
</div>
|
|
23
25
|
<div class="text-base leading-6 font-medium">
|
|
24
|
-
<
|
|
26
|
+
<router-link class="link" aria-label="read more" :to="post.path || ''">
|
|
27
|
+
Read more →
|
|
28
|
+
</router-link>
|
|
25
29
|
</div>
|
|
26
30
|
</div>
|
|
27
31
|
</article>
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import { useAppStore } from 'valaxy/client/stores/app'
|
|
2
|
+
import { useAppStore, useFrontmatter } from 'valaxy'
|
|
3
|
+
import PressOutline from './PressOutline.vue'
|
|
5
4
|
|
|
6
5
|
const frontmatter = useFrontmatter()
|
|
7
|
-
const data = useData()
|
|
8
|
-
// const { t } = useI18n()
|
|
9
6
|
const app = useAppStore()
|
|
10
7
|
</script>
|
|
11
8
|
|
|
12
9
|
<template>
|
|
13
10
|
<button
|
|
14
|
-
class="
|
|
15
|
-
|
|
11
|
+
class="toc-btn shadow-lg fixed press-icon-btn z-99 xl:hidden!"
|
|
12
|
+
right="5" bottom="8"
|
|
16
13
|
@click="app.toggleRightSidebar()"
|
|
17
14
|
>
|
|
18
15
|
<div i-ri-file-list-line />
|
|
@@ -21,43 +18,48 @@ const app = useAppStore()
|
|
|
21
18
|
<ValaxyOverlay :show="app.isRightSidebarOpen" @click="app.toggleRightSidebar()" />
|
|
22
19
|
|
|
23
20
|
<aside
|
|
24
|
-
class="press-aside lt-xl:fixed
|
|
25
|
-
press-card xl:(shadow-none hover:shadow-none)
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
class="press-aside lt-xl:fixed shadow
|
|
22
|
+
press-card xl:(shadow-none hover:shadow-none) hover:shadow-lg"
|
|
23
|
+
flex="~ col grow"
|
|
24
|
+
p="l-0 xl:l-8" text="center"
|
|
25
|
+
z="$"
|
|
28
26
|
:class="app.isRightSidebarOpen && 'open'"
|
|
29
27
|
>
|
|
28
|
+
<div class="aside-curtain" />
|
|
30
29
|
<div class="aside-container lt-xl:fixed" flex="~ col">
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<
|
|
30
|
+
<div class="aside-content overflow-auto" flex="~ col">
|
|
31
|
+
<PressOutline v-if="frontmatter.toc !== false" />
|
|
32
|
+
<div class="flex-grow" />
|
|
33
|
+
<div v-if="$slots.default" class="custom-container">
|
|
34
|
+
<slot />
|
|
35
|
+
</div>
|
|
35
36
|
</div>
|
|
36
37
|
</div>
|
|
37
38
|
</aside>
|
|
38
39
|
</template>
|
|
39
40
|
|
|
40
41
|
<style lang="scss">
|
|
41
|
-
@use 'valaxy/client/styles/mixins' as *;
|
|
42
|
+
@use 'valaxy/client/styles/mixins/index.scss' as *;
|
|
42
43
|
|
|
43
44
|
.press-card{
|
|
44
|
-
box-shadow: none;
|
|
45
45
|
background-color: var(--va-c-bg);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
.press-aside {
|
|
49
|
-
position: relative;
|
|
50
|
-
min-width: 272px;
|
|
51
|
-
transform: translateX(100%);
|
|
52
49
|
top: 0;
|
|
53
50
|
bottom: 0;
|
|
54
51
|
right: 0;
|
|
55
|
-
z-index:
|
|
52
|
+
z-index: var(--pr-z-aside);
|
|
53
|
+
width: var(--va-aside-width);
|
|
54
|
+
|
|
55
|
+
transform: translateX(100%);
|
|
56
56
|
|
|
57
57
|
transition: box-shadow var(--va-transition-duration), opacity 0.25s,
|
|
58
58
|
transform var(--va-transition-duration) cubic-bezier(0.19, 1, 0.22, 1);
|
|
59
59
|
|
|
60
60
|
&.open {
|
|
61
|
+
position: fixed;
|
|
62
|
+
right: 0;
|
|
61
63
|
display: block;
|
|
62
64
|
transform: translateX(0);
|
|
63
65
|
}
|
|
@@ -65,13 +67,22 @@ const app = useAppStore()
|
|
|
65
67
|
|
|
66
68
|
.aside-container {
|
|
67
69
|
position: sticky;
|
|
68
|
-
top:
|
|
69
|
-
margin-top: calc(var(--pr-nav-height) * -1 -
|
|
70
|
-
padding-top: calc(var(--pr-nav-height) +
|
|
70
|
+
top: 0;
|
|
71
|
+
margin-top: calc(var(--pr-nav-height) * -1 - 20px);
|
|
72
|
+
padding-top: calc(var(--pr-nav-height) + 20px);
|
|
71
73
|
height: 100vh;
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
.aside-curtain {
|
|
77
|
+
position: fixed;
|
|
78
|
+
bottom: 0;
|
|
79
|
+
z-index: 10;
|
|
80
|
+
width: 220px;
|
|
81
|
+
height: 32px;
|
|
82
|
+
background: linear-gradient(transparent,var(--va-c-bg) 70%);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@include screen('xl') {
|
|
75
86
|
.aside-container {
|
|
76
87
|
top: 0;
|
|
77
88
|
}
|
|
@@ -82,7 +93,7 @@ const app = useAppStore()
|
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
.toc-btn {
|
|
85
|
-
color: var(--va-c-
|
|
86
|
-
background-color: var(--va-c-
|
|
96
|
+
color: var(--va-c-bg);
|
|
97
|
+
background-color: var(--va-c-primary);
|
|
87
98
|
}
|
|
88
99
|
</style>
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
-
import { useRouter } from 'vue-router'
|
|
4
|
-
import { EXTERNAL_URL_RE } from 'valaxy'
|
|
5
3
|
|
|
6
4
|
const props = defineProps<{
|
|
7
5
|
theme: 'brand' | 'alt'
|
|
@@ -9,9 +7,6 @@ const props = defineProps<{
|
|
|
9
7
|
text: string
|
|
10
8
|
}>()
|
|
11
9
|
|
|
12
|
-
const isUrl = computed(() => EXTERNAL_URL_RE.test(props.link))
|
|
13
|
-
const router = useRouter()
|
|
14
|
-
|
|
15
10
|
const classes = computed(() => {
|
|
16
11
|
const arr = []
|
|
17
12
|
if (props.theme === 'brand')
|
|
@@ -24,15 +19,13 @@ const classes = computed(() => {
|
|
|
24
19
|
</script>
|
|
25
20
|
|
|
26
21
|
<template>
|
|
27
|
-
<
|
|
28
|
-
:
|
|
22
|
+
<AppLink
|
|
23
|
+
:to="link"
|
|
29
24
|
m="2"
|
|
30
25
|
:class="classes"
|
|
31
|
-
class="sese-btn btn" bg="gradient-to-r"
|
|
32
|
-
|
|
33
|
-
:target="isUrl ? '_blank' : undefined"
|
|
34
|
-
@click="!isUrl && router.push(link)"
|
|
26
|
+
class="sese-btn btn rounded-full hover:shadow-lg" bg="gradient-to-r"
|
|
27
|
+
p="x-6"
|
|
35
28
|
>
|
|
36
29
|
{{ text }}
|
|
37
|
-
</
|
|
30
|
+
</AppLink>
|
|
38
31
|
</template>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { useThemeConfig } from 'valaxy'
|
|
2
3
|
import type { Categories } from 'valaxy'
|
|
3
|
-
import { ref } from 'vue'
|
|
4
|
+
import { computed, ref } from 'vue'
|
|
4
5
|
|
|
5
6
|
const props = withDefaults(defineProps<{
|
|
6
7
|
categories: Categories
|
|
@@ -16,15 +17,31 @@ const props = withDefaults(defineProps<{
|
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
const collapsable = ref(props.collapsable)
|
|
20
|
+
|
|
21
|
+
const themeConfig = useThemeConfig()
|
|
22
|
+
const sidebar = computed(() => themeConfig.value.sidebar)
|
|
19
23
|
</script>
|
|
20
24
|
|
|
21
25
|
<template>
|
|
22
|
-
<ul v-for="
|
|
23
|
-
<PressCategory
|
|
26
|
+
<ul v-for="item in sidebar" :key="item" class="category-list">
|
|
27
|
+
<PressCategory
|
|
28
|
+
v-if="categories.find(c => c.name === item)"
|
|
29
|
+
:category="categories.find(c => c.name === item)"
|
|
30
|
+
:level="level + 1"
|
|
31
|
+
:display-category="displayCategory"
|
|
32
|
+
:collapsable="collapsable"
|
|
33
|
+
/>
|
|
24
34
|
</ul>
|
|
25
35
|
</template>
|
|
26
36
|
|
|
27
37
|
<style lang="scss">
|
|
38
|
+
.category-list {
|
|
39
|
+
&:first-child {
|
|
40
|
+
.category-list-item {
|
|
41
|
+
border-top: 0px;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
28
45
|
.post-list-item {
|
|
29
46
|
a {
|
|
30
47
|
color: var(--va-c-text-light);
|
|
@@ -47,4 +64,8 @@ const collapsable = ref(props.collapsable)
|
|
|
47
64
|
}
|
|
48
65
|
}
|
|
49
66
|
}
|
|
67
|
+
|
|
68
|
+
.category-list+.category-list {
|
|
69
|
+
margin-top: 1rem;
|
|
70
|
+
}
|
|
50
71
|
</style>
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { ref } from 'vue'
|
|
3
3
|
import type { Category, Post } from 'valaxy'
|
|
4
|
-
import {
|
|
4
|
+
import { isCategoryList } from 'valaxy'
|
|
5
5
|
import { useI18n } from 'vue-i18n'
|
|
6
6
|
|
|
7
7
|
const props = withDefaults(defineProps<{
|
|
8
|
-
name: string
|
|
9
8
|
// to eliminate the warning
|
|
10
9
|
category: Category
|
|
11
10
|
level?: number
|
|
@@ -22,30 +21,40 @@ const props = withDefaults(defineProps<{
|
|
|
22
21
|
const collapsable = ref(props.collapsable)
|
|
23
22
|
const { t, locale } = useI18n()
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
const lang = locale.value
|
|
24
|
+
function getTitle(post: Post | any) {
|
|
25
|
+
const lang = locale.value
|
|
27
26
|
return post[`title_${lang}`] ? post[`title_${lang}`] : post.title
|
|
28
27
|
}
|
|
29
28
|
</script>
|
|
30
29
|
|
|
31
30
|
<template>
|
|
32
|
-
<li
|
|
33
|
-
|
|
31
|
+
<li
|
|
32
|
+
v-if="category.total"
|
|
33
|
+
p="t-2"
|
|
34
|
+
w="full" border="t t-$pr-c-divider-light"
|
|
35
|
+
class="category-list-item inline-flex items-center justify-between"
|
|
36
|
+
>
|
|
37
|
+
<span class="category-name" font="bold" m="l-1" @click="displayCategory ? displayCategory(category.name) : null">
|
|
38
|
+
{{ category.name === 'Uncategorized' ? t('category.uncategorized') : category.name }}
|
|
39
|
+
<!-- <sup font="normal">[{{ category.total }}]</sup> -->
|
|
40
|
+
</span>
|
|
41
|
+
<span class="folder-action inline-flex cursor-pointer" opacity="50" @click="collapsable = !collapsable">
|
|
34
42
|
<div v-if="collapsable" i-ri-folder-add-line />
|
|
35
|
-
<div v-else
|
|
36
|
-
<span class="category-name" m="l-1" @click="displayCategory ? displayCategory(name) : null">
|
|
37
|
-
{{ name === 'Uncategorized' ? t('category.uncategorized') : name }} [{{ category.total }}]
|
|
43
|
+
<div v-else i-ri-folder-reduce-line />
|
|
38
44
|
</span>
|
|
39
45
|
</li>
|
|
40
46
|
|
|
41
47
|
<template v-if="!collapsable">
|
|
42
|
-
<ul
|
|
43
|
-
<li v-for="
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
|
|
48
|
+
<ul>
|
|
49
|
+
<li v-for="categoryItem, i in category.children" :key="i" class="post-list-item">
|
|
50
|
+
<template v-if="!isCategoryList(categoryItem)">
|
|
51
|
+
<router-link v-if="categoryItem.title" :to="categoryItem.path || ''" class="inline-flex items-center" active-class="active">
|
|
52
|
+
<span m="l-1" text="sm">{{ getTitle(categoryItem) }}</span>
|
|
53
|
+
</router-link>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<PressCategory v-else :category="categoryItem" :display-category="displayCategory" :collapsable="collapsable" />
|
|
47
57
|
</li>
|
|
48
58
|
</ul>
|
|
49
|
-
<PressCategories v-else :categories="category.children" :display-category="displayCategory" :collapsable="collapsable" />
|
|
50
59
|
</template>
|
|
51
60
|
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useEditLink } from '../composables'
|
|
3
|
+
|
|
4
|
+
const editLink = useEditLink()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<div flex justify="between" text="sm">
|
|
9
|
+
<a flex items="center" :href="editLink.url" target="_blank">
|
|
10
|
+
<div i-ri-external-link-line />
|
|
11
|
+
<span ml-1>{{ editLink.text }}</span>
|
|
12
|
+
</a>
|
|
13
|
+
<PressDocFooterLastUpdated />
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|