valaxy-theme-yun 0.3.10 → 0.5.0
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/README.md +4 -4
- package/components/YunAlgoliaSearchBox.vue +151 -0
- package/components/YunBanner.vue +1 -1
- package/components/YunBase.vue +1 -1
- package/components/YunCategories.vue +1 -1
- package/components/YunCategory.vue +3 -2
- package/components/YunOverview.vue +1 -1
- package/components/YunPostCollapse.vue +1 -1
- package/components/YunPostMeta.vue +1 -1
- package/components/YunSay.vue +1 -1
- package/components/YunSearch.vue +130 -0
- package/components/YunSidebarLinks.vue +1 -1
- package/components/YunSidebarNav.vue +1 -1
- package/components/YunSocialLinks.vue +1 -1
- package/components/YunSponsor.vue +1 -1
- package/components/YunTwikoo.vue +1 -1
- package/components/YunWaline.vue +1 -1
- package/config/index.ts +4 -0
- package/dist/index.d.ts +4 -1
- package/layouts/archives.vue +1 -1
- package/layouts/base.vue +3 -3
- package/layouts/categories.vue +5 -3
- package/layouts/home.vue +2 -2
- package/layouts/post.vue +1 -1
- package/layouts/tags.vue +1 -1
- package/package.json +3 -3
- package/styles/layout/post.scss +19 -1
- package/components/YunAlgoliaSearch.vue +0 -227
package/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
<p align=
|
1
|
+
<p align="center">
|
2
2
|
<img width="200" src="https://cdn.jsdelivr.net/gh/YunYouJun/yun/images/meme/yun-good-alpha-compressed.png">
|
3
3
|
</p>
|
4
4
|
|
5
|
-
<p align=
|
5
|
+
<p align="center">
|
6
6
|
Theme-Yun<sup><em>(vue)</em></sup>
|
7
7
|
</p>
|
8
8
|
|
@@ -27,7 +27,7 @@ pnpm build
|
|
27
27
|
## [Sponsors](https://sponsors.yunyoujun.cn)
|
28
28
|
|
29
29
|
<p align="center">
|
30
|
-
<a href="https://
|
31
|
-
<img src='https://
|
30
|
+
<a href="https://sponsors.yunyoujun.cn">
|
31
|
+
<img src='https://fastly.jsdelivr.net/gh/YunYouJun/sponsors/public/sponsors.svg'/>
|
32
32
|
</a>
|
33
33
|
</p>
|
@@ -0,0 +1,151 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import '@docsearch/css'
|
3
|
+
import docsearch from '@docsearch/js'
|
4
|
+
import type { DocSearchHit } from '@docsearch/react/dist/esm/types'
|
5
|
+
import { onMounted } from 'vue'
|
6
|
+
import type { AlgoliaSearchOptions } from 'valaxy'
|
7
|
+
import { useConfig } from 'valaxy/client'
|
8
|
+
import { useRoute, useRouter } from 'vue-router'
|
9
|
+
|
10
|
+
const router = useRouter()
|
11
|
+
const route = useRoute()
|
12
|
+
const config = useConfig()
|
13
|
+
|
14
|
+
onMounted(() => {
|
15
|
+
initialize(config.value.search.algolia)
|
16
|
+
setTimeout(poll, 16)
|
17
|
+
})
|
18
|
+
|
19
|
+
/**
|
20
|
+
* poll until open
|
21
|
+
*/
|
22
|
+
function poll() {
|
23
|
+
// programmatically open the search box after initialize
|
24
|
+
const e = new Event('keydown') as any
|
25
|
+
|
26
|
+
e.key = 'k'
|
27
|
+
e.metaKey = true
|
28
|
+
|
29
|
+
window.dispatchEvent(e)
|
30
|
+
|
31
|
+
setTimeout(() => {
|
32
|
+
if (!document.querySelector('.DocSearch-Modal'))
|
33
|
+
poll()
|
34
|
+
}, 16)
|
35
|
+
}
|
36
|
+
|
37
|
+
function initialize(userOptions: AlgoliaSearchOptions) {
|
38
|
+
// note: multi-lang search support is removed since the theme
|
39
|
+
// doesn't support multiple locales as of now.
|
40
|
+
const options = Object.assign({}, userOptions, {
|
41
|
+
container: '#docsearch',
|
42
|
+
navigator: {
|
43
|
+
navigate({ itemUrl }: { itemUrl: string }) {
|
44
|
+
const { pathname: hitPathname } = new URL(
|
45
|
+
window.location.origin + itemUrl,
|
46
|
+
)
|
47
|
+
// router doesn't handle same-page navigation so we use the native
|
48
|
+
// browser location API for anchor navigation
|
49
|
+
if (route.path === hitPathname)
|
50
|
+
window.location.assign(window.location.origin + itemUrl)
|
51
|
+
|
52
|
+
else
|
53
|
+
router.push(itemUrl)
|
54
|
+
},
|
55
|
+
},
|
56
|
+
transformItems(items: DocSearchHit[]) {
|
57
|
+
return items.map((item) => {
|
58
|
+
return Object.assign({}, item, {
|
59
|
+
url: getRelativePath(item.url),
|
60
|
+
})
|
61
|
+
})
|
62
|
+
},
|
63
|
+
hitComponent({ hit, children }: { hit: DocSearchHit; children: any }) {
|
64
|
+
const relativeHit = hit.url.startsWith('http')
|
65
|
+
? getRelativePath(hit.url as string)
|
66
|
+
: hit.url
|
67
|
+
return {
|
68
|
+
__v: null,
|
69
|
+
type: 'a',
|
70
|
+
ref: undefined,
|
71
|
+
constructor: undefined,
|
72
|
+
key: undefined,
|
73
|
+
props: {
|
74
|
+
href: hit.url,
|
75
|
+
onClick(event: MouseEvent) {
|
76
|
+
if (isSpecialClick(event))
|
77
|
+
return
|
78
|
+
|
79
|
+
// we rely on the native link scrolling when user is already on
|
80
|
+
// the right anchor because Router doesn't support duplicated
|
81
|
+
// history entries.
|
82
|
+
if (route.path === relativeHit)
|
83
|
+
return
|
84
|
+
|
85
|
+
// if the hits goes to another page, we prevent the native link
|
86
|
+
// behavior to leverage the Router loading feature.
|
87
|
+
if (route.path !== relativeHit)
|
88
|
+
event.preventDefault()
|
89
|
+
|
90
|
+
router.go(relativeHit)
|
91
|
+
},
|
92
|
+
children,
|
93
|
+
},
|
94
|
+
}
|
95
|
+
},
|
96
|
+
})
|
97
|
+
docsearch(options)
|
98
|
+
}
|
99
|
+
|
100
|
+
function isSpecialClick(event: MouseEvent) {
|
101
|
+
return (
|
102
|
+
event.button === 1
|
103
|
+
|| event.altKey
|
104
|
+
|| event.ctrlKey
|
105
|
+
|| event.metaKey
|
106
|
+
|| event.shiftKey
|
107
|
+
)
|
108
|
+
}
|
109
|
+
|
110
|
+
function getRelativePath(absoluteUrl: string) {
|
111
|
+
const { pathname, hash } = new URL(absoluteUrl)
|
112
|
+
return pathname + hash
|
113
|
+
}
|
114
|
+
</script>
|
115
|
+
|
116
|
+
<template>
|
117
|
+
<div id="docsearch" class="hidden" />
|
118
|
+
</template>
|
119
|
+
|
120
|
+
<style lang="scss">
|
121
|
+
.DocSearch {
|
122
|
+
--docsearch-primary-color: var(--va-c-primary);
|
123
|
+
--docsearch-highlight-color: var(--docsearch-primary-color);
|
124
|
+
--docsearch-text-color: var(--va-c-text-primary);
|
125
|
+
--docsearch-muted-color: var(--va-c-text-light);
|
126
|
+
--docsearch-searchbox-focus-background: transparent;
|
127
|
+
--docsearch-searchbox-shadow: none;
|
128
|
+
|
129
|
+
--docsearch-key-gradient: transparent;
|
130
|
+
--docsearch-key-shadow: none;
|
131
|
+
|
132
|
+
--docsearch-modal-background: var(--va-c-bg-light);
|
133
|
+
--docsearch-footer-background: var(--va-c-bg);
|
134
|
+
|
135
|
+
input {
|
136
|
+
&::placeholder {
|
137
|
+
color: var(--va-c-text-dark);
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
.dark .DocSearch {
|
143
|
+
--docsearch-modal-shadow: none;
|
144
|
+
--docsearch-footer-shadow: none;
|
145
|
+
--docsearch-hit-shadow: none;
|
146
|
+
}
|
147
|
+
|
148
|
+
.DocSearch-Form {
|
149
|
+
border: 1px solid var(--va-c-primary);
|
150
|
+
}
|
151
|
+
</style>
|
package/components/YunBanner.vue
CHANGED
package/components/YunBase.vue
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
2
|
import { ref } from 'vue'
|
3
|
-
import type {
|
4
|
-
import {
|
3
|
+
import type { Post } from 'valaxy'
|
4
|
+
import type { Category } from 'valaxy/client'
|
5
|
+
import { isParentCategory } from 'valaxy/client'
|
5
6
|
import { useI18n } from 'vue-i18n'
|
6
7
|
|
7
8
|
const props = withDefaults(defineProps<{
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
2
|
import { computed, ref, watch } from 'vue'
|
3
3
|
import type { Post } from 'valaxy'
|
4
|
-
import { formatDate, sortByDate } from 'valaxy'
|
4
|
+
import { formatDate, sortByDate } from 'valaxy/client'
|
5
5
|
import { useI18n } from 'vue-i18n'
|
6
6
|
|
7
7
|
const props = defineProps<{
|
package/components/YunSay.vue
CHANGED
@@ -0,0 +1,130 @@
|
|
1
|
+
<script lang="ts" setup>
|
2
|
+
import { defineAsyncComponent, onMounted, onUnmounted, ref } from 'vue'
|
3
|
+
import { useI18n } from 'vue-i18n'
|
4
|
+
|
5
|
+
const YunAlgoliaSearchBox = __ALGOLIA__
|
6
|
+
? defineAsyncComponent(() => import('./YunAlgoliaSearchBox.vue'))
|
7
|
+
: () => null
|
8
|
+
|
9
|
+
const { t } = useI18n()
|
10
|
+
|
11
|
+
// to avoid loading the docsearch js upfront (which is more than 1/3 of the
|
12
|
+
// payload), we delay initializing it until the user has actually clicked or
|
13
|
+
// hit the hotkey to invoke it.
|
14
|
+
const loaded = ref(false)
|
15
|
+
|
16
|
+
function load() {
|
17
|
+
if (!loaded.value)
|
18
|
+
loaded.value = true
|
19
|
+
}
|
20
|
+
|
21
|
+
onMounted(() => {
|
22
|
+
if (!__ALGOLIA__)
|
23
|
+
return
|
24
|
+
|
25
|
+
const handleSearchHotKey = (e: KeyboardEvent) => {
|
26
|
+
if (e.key === 'k' && (e.ctrlKey || e.metaKey)) {
|
27
|
+
e.preventDefault()
|
28
|
+
load()
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
30
|
+
remove()
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
const remove = () => {
|
35
|
+
window.removeEventListener('keydown', handleSearchHotKey)
|
36
|
+
}
|
37
|
+
|
38
|
+
window.addEventListener('keydown', handleSearchHotKey)
|
39
|
+
|
40
|
+
onUnmounted(remove)
|
41
|
+
})
|
42
|
+
|
43
|
+
const trigger = () => {
|
44
|
+
const e = new Event('keydown') as any
|
45
|
+
|
46
|
+
e.key = 'k'
|
47
|
+
e.metaKey = true
|
48
|
+
|
49
|
+
window.dispatchEvent(e)
|
50
|
+
}
|
51
|
+
</script>
|
52
|
+
|
53
|
+
<template>
|
54
|
+
<div>
|
55
|
+
<button class="search-btn popup-trigger yun-icon-btn" :title="t('menu.search')" @click="trigger">
|
56
|
+
<div i-ri-search-line />
|
57
|
+
<!-- <div v-else text="!2xl" i-ri-close-line /> -->
|
58
|
+
</button>
|
59
|
+
|
60
|
+
<YunAlgoliaSearchBox v-if="loaded" />
|
61
|
+
</div>
|
62
|
+
</template>
|
63
|
+
|
64
|
+
<style lang="scss">
|
65
|
+
@use 'sass:map';
|
66
|
+
@use '~/styles/vars' as *;
|
67
|
+
|
68
|
+
.search-btn {
|
69
|
+
position: fixed;
|
70
|
+
top: 0.6rem;
|
71
|
+
right: 0.8rem;
|
72
|
+
|
73
|
+
color: var(--va-c-primary);
|
74
|
+
z-index: var(--yun-z-search-btn);
|
75
|
+
}
|
76
|
+
|
77
|
+
.search-popup {
|
78
|
+
position: fixed;
|
79
|
+
top: 0;
|
80
|
+
left: 0;
|
81
|
+
width: 100%;
|
82
|
+
height: 100%;
|
83
|
+
|
84
|
+
backdrop-filter: blur(30px);
|
85
|
+
-webkit-backdrop-filter: blur(30px);
|
86
|
+
|
87
|
+
text-align: center;
|
88
|
+
padding-top: 3.5rem;
|
89
|
+
margin: 0;
|
90
|
+
z-index: var(--yun-z-search-popup);
|
91
|
+
transition: 0.6s;
|
92
|
+
}
|
93
|
+
|
94
|
+
.search-header {
|
95
|
+
.close-icon {
|
96
|
+
position: fixed;
|
97
|
+
top: 0.6rem;
|
98
|
+
right: 0.8rem;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
.search-input {
|
103
|
+
background: transparent;
|
104
|
+
color: var(--va-c-text);
|
105
|
+
font-size: 1.5rem;
|
106
|
+
border-radius: 3rem;
|
107
|
+
padding: 1rem 1.5rem;
|
108
|
+
border: 1px solid var(--va-c-gray);
|
109
|
+
box-sizing: border-box;
|
110
|
+
width: 90%;
|
111
|
+
max-width: 800px;
|
112
|
+
font-family: var(--va-font-serif);
|
113
|
+
font-weight: 900;
|
114
|
+
text-align: center;
|
115
|
+
}
|
116
|
+
|
117
|
+
.popup {
|
118
|
+
.search-icon, .close-icon {
|
119
|
+
display: inline-block;
|
120
|
+
width: 2rem;
|
121
|
+
height: 2rem;
|
122
|
+
padding: 0.5rem;
|
123
|
+
|
124
|
+
.icon {
|
125
|
+
width: 2rem;
|
126
|
+
height: 2rem;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
</style>
|
package/components/YunTwikoo.vue
CHANGED
package/components/YunWaline.vue
CHANGED
package/config/index.ts
CHANGED
package/dist/index.d.ts
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
import { Plugin } from 'vite';
|
2
2
|
|
3
3
|
declare const anonymousImage = "https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg";
|
4
|
+
declare namespace YunTheme {
|
5
|
+
type Config = ThemeConfig;
|
6
|
+
}
|
4
7
|
/**
|
5
8
|
* Theme Config
|
6
9
|
*/
|
@@ -124,4 +127,4 @@ interface UserOptions {
|
|
124
127
|
}
|
125
128
|
declare function yunPlugin(userOptions?: Partial<ThemeConfig>): Plugin;
|
126
129
|
|
127
|
-
export { ThemeConfig, ThemeUserConfig, UserOptions, anonymousImage, yunPlugin as default, defaultThemeConfig, generateSafelist, yunPlugin };
|
130
|
+
export { ThemeConfig, ThemeUserConfig, UserOptions, YunTheme, anonymousImage, yunPlugin as default, defaultThemeConfig, generateSafelist, yunPlugin };
|
package/layouts/archives.vue
CHANGED
package/layouts/base.vue
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import { useConfig, useFrontmatter, usePostProperty, usePostTitle } from 'valaxy'
|
2
|
+
import { useConfig, useFrontmatter, usePostProperty, usePostTitle } from 'valaxy/client'
|
3
3
|
const frontmatter = useFrontmatter()
|
4
4
|
|
5
5
|
const config = useConfig()
|
@@ -22,7 +22,7 @@ const title = usePostTitle(frontmatter)
|
|
22
22
|
<div flex="~ 1 col" w="full" p="l-4 lt-md:0" class="content">
|
23
23
|
<YunCard m="0" p="4" class="relative sm:p-6 lg:px-12 xl:px-16" :style="styles">
|
24
24
|
<slot name="header">
|
25
|
-
<YunPageHeader :title="title" :icon="frontmatter.icon || icon" :color="frontmatter.color || color" />
|
25
|
+
<YunPageHeader :title="title" :icon="frontmatter.icon || icon" :color="frontmatter.color || color" :cover="frontmatter.cover" />
|
26
26
|
</slot>
|
27
27
|
<template #content>
|
28
28
|
<slot name="content">
|
@@ -58,7 +58,7 @@ const title = usePostTitle(frontmatter)
|
|
58
58
|
</slot>
|
59
59
|
</main>
|
60
60
|
|
61
|
-
<
|
61
|
+
<YunSearch v-if="config.search.enable" />
|
62
62
|
<YunBackToTop />
|
63
63
|
</template>
|
64
64
|
|
package/layouts/categories.vue
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
2
|
import { computed, ref } from 'vue'
|
3
|
-
import { useCategory, useFrontmatter, useInvisibleElement, usePostList, usePostTitle } from 'valaxy'
|
3
|
+
import { useCategory, useFrontmatter, useInvisibleElement, usePostList, usePostTitle } from 'valaxy/client'
|
4
4
|
import { useI18n } from 'vue-i18n'
|
5
5
|
import { useRoute, useRouter } from 'vue-router'
|
6
6
|
|
@@ -15,12 +15,14 @@ const curCategory = computed(() => (route.query.category as string || ''))
|
|
15
15
|
const postList = usePostList()
|
16
16
|
const posts = computed(() => {
|
17
17
|
const list = postList.value.filter((post) => {
|
18
|
-
if (post.categories) {
|
18
|
+
if (post.categories && curCategory.value !== 'Uncategorized') {
|
19
19
|
if (typeof post.categories === 'string')
|
20
20
|
return post.categories === curCategory.value
|
21
21
|
else
|
22
22
|
return post.categories.includes(curCategory.value)
|
23
23
|
}
|
24
|
+
if (!post.categories && curCategory.value === 'Uncategorized')
|
25
|
+
return post.categories === undefined
|
24
26
|
return false
|
25
27
|
})
|
26
28
|
return list
|
@@ -61,7 +63,7 @@ const title = usePostTitle(frontmatter)
|
|
61
63
|
</template>
|
62
64
|
|
63
65
|
<YunCard v-if="curCategory" ref="collapse" m="t-4" w="full">
|
64
|
-
<YunPageHeader m="t-4" :title="curCategory" icon="i-ri-folder-open-line" />
|
66
|
+
<YunPageHeader m="t-4" :title="curCategory === 'Uncategorized' ? t('category.uncategorized') : curCategory" icon="i-ri-folder-open-line" />
|
65
67
|
<YunPostCollapse w="full" m="b-4" p="x-20 lt-sm:x-5" :posts="posts" />
|
66
68
|
</YunCard>
|
67
69
|
</YunBase>
|
package/layouts/home.vue
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import { useConfig } from 'valaxy'
|
2
|
+
import { useConfig } from 'valaxy/client'
|
3
3
|
import { useLayout } from '~/composables'
|
4
4
|
|
5
5
|
import { useAppStore } from '~/stores/app'
|
@@ -34,5 +34,5 @@ const isHome = useLayout('home')
|
|
34
34
|
</ValaxyFooter>
|
35
35
|
</main>
|
36
36
|
|
37
|
-
<
|
37
|
+
<YunSearch v-if="config.search.enable" />
|
38
38
|
</template>
|
package/layouts/post.vue
CHANGED
package/layouts/tags.vue
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<script lang="ts" setup>
|
2
|
-
import { useFrontmatter, useInvisibleElement, usePostList, usePostTitle, useTags, useThemeConfig } from 'valaxy'
|
2
|
+
import { useFrontmatter, useInvisibleElement, usePostList, usePostTitle, useTags, useThemeConfig } from 'valaxy/client'
|
3
3
|
import { useI18n } from 'vue-i18n'
|
4
4
|
import { computed, ref } from 'vue'
|
5
5
|
import { useRoute, useRouter } from 'vue-router'
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "valaxy-theme-yun",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.5.0",
|
4
4
|
"author": {
|
5
5
|
"email": "me@yunyoujun.cn",
|
6
6
|
"name": "YunYouJun",
|
@@ -15,10 +15,10 @@
|
|
15
15
|
"types": "dist/index.d.ts",
|
16
16
|
"dependencies": {
|
17
17
|
"@iconify-json/ant-design": "^1.1.2",
|
18
|
-
"@iconify-json/simple-icons": "^1.1.
|
18
|
+
"@iconify-json/simple-icons": "^1.1.15"
|
19
19
|
},
|
20
20
|
"devDependencies": {
|
21
|
-
"valaxy": "0.
|
21
|
+
"valaxy": "0.5.0"
|
22
22
|
},
|
23
23
|
"scripts": {
|
24
24
|
"build": "tsup",
|
package/styles/layout/post.scss
CHANGED
@@ -5,6 +5,24 @@
|
|
5
5
|
max-width: var(--yun-post-card-max-width);
|
6
6
|
}
|
7
7
|
|
8
|
+
.post-card-image {
|
9
|
+
@extend .post-card;
|
10
|
+
|
11
|
+
.post-card-image-info-text {
|
12
|
+
height: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
@include mobile {
|
16
|
+
.post-card-info {
|
17
|
+
flex-direction: column;
|
18
|
+
}
|
19
|
+
|
20
|
+
img {
|
21
|
+
width: 100%;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
8
26
|
.post-title {
|
9
27
|
display: flex;
|
10
28
|
justify-content: center;
|
@@ -75,4 +93,4 @@
|
|
75
93
|
&:before {
|
76
94
|
content: none;
|
77
95
|
}
|
78
|
-
}
|
96
|
+
}
|
@@ -1,227 +0,0 @@
|
|
1
|
-
<script lang="ts" setup>
|
2
|
-
import { ref, watch } from 'vue'
|
3
|
-
import { useMagicKeys } from '@vueuse/core'
|
4
|
-
import { useI18n } from 'vue-i18n'
|
5
|
-
import { useConfig } from 'valaxy'
|
6
|
-
import { useAlgoliaSearch } from '~/composables/search/algolia'
|
7
|
-
|
8
|
-
const { t } = useI18n()
|
9
|
-
|
10
|
-
const config = useConfig()
|
11
|
-
const showPopup = ref(false)
|
12
|
-
|
13
|
-
const { Escape } = useMagicKeys()
|
14
|
-
|
15
|
-
useAlgoliaSearch({
|
16
|
-
...config.value.search.algolia,
|
17
|
-
hits: {
|
18
|
-
per_page: 8,
|
19
|
-
},
|
20
|
-
})
|
21
|
-
|
22
|
-
watch(Escape, () => {
|
23
|
-
showPopup.value = false
|
24
|
-
})
|
25
|
-
|
26
|
-
watch(showPopup, () => {
|
27
|
-
if (showPopup.value)
|
28
|
-
document.documentElement.classList.add('no-scroll')
|
29
|
-
else
|
30
|
-
document.documentElement.classList.remove('no-scroll')
|
31
|
-
})
|
32
|
-
</script>
|
33
|
-
|
34
|
-
<template>
|
35
|
-
<button class="search-btn popup-trigger yun-icon-btn" :title="t('menu.search')" @click="showPopup = !showPopup">
|
36
|
-
<div v-if="!showPopup" i-ri-search-line />
|
37
|
-
<div v-else text="!2xl" i-ri-close-line />
|
38
|
-
</button>
|
39
|
-
|
40
|
-
<transition>
|
41
|
-
<div v-show="showPopup" class="search-popup">
|
42
|
-
<div class="search-header" />
|
43
|
-
<div class="search-input-container" />
|
44
|
-
<div class="algolia-results">
|
45
|
-
<div id="algolia-stats" />
|
46
|
-
<div id="algolia-hits" />
|
47
|
-
<div id="algolia-pagination" class="algolia-pagination" />
|
48
|
-
</div>
|
49
|
-
</div>
|
50
|
-
</transition>
|
51
|
-
</template>
|
52
|
-
|
53
|
-
<style lang="scss">
|
54
|
-
@use 'sass:map';
|
55
|
-
@use '~/styles/vars' as *;
|
56
|
-
|
57
|
-
.search-btn {
|
58
|
-
position: fixed;
|
59
|
-
top: 0.6rem;
|
60
|
-
right: 0.8rem;
|
61
|
-
|
62
|
-
color: var(--va-c-primary);
|
63
|
-
z-index: var(--yun-z-search-btn);
|
64
|
-
}
|
65
|
-
|
66
|
-
.search-popup {
|
67
|
-
position: fixed;
|
68
|
-
top: 0;
|
69
|
-
left: 0;
|
70
|
-
width: 100%;
|
71
|
-
height: 100%;
|
72
|
-
|
73
|
-
backdrop-filter: blur(30px);
|
74
|
-
-webkit-backdrop-filter: blur(30px);
|
75
|
-
|
76
|
-
text-align: center;
|
77
|
-
padding-top: 3.5rem;
|
78
|
-
margin: 0;
|
79
|
-
z-index: var(--yun-z-search-popup);
|
80
|
-
transition: 0.6s;
|
81
|
-
}
|
82
|
-
|
83
|
-
.search-header {
|
84
|
-
.close-icon {
|
85
|
-
position: fixed;
|
86
|
-
top: 0.6rem;
|
87
|
-
right: 0.8rem;
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
|
-
.search-input {
|
92
|
-
background: transparent;
|
93
|
-
color: var(--va-c-text);
|
94
|
-
font-size: 1.5rem;
|
95
|
-
border-radius: 3rem;
|
96
|
-
padding: 1rem 1.5rem;
|
97
|
-
border: 1px solid var(--va-c-gray);
|
98
|
-
box-sizing: border-box;
|
99
|
-
width: 90%;
|
100
|
-
max-width: 800px;
|
101
|
-
font-family: var(--va-font-serif);
|
102
|
-
font-weight: 900;
|
103
|
-
text-align: center;
|
104
|
-
}
|
105
|
-
|
106
|
-
.popup {
|
107
|
-
.search-icon, .close-icon {
|
108
|
-
display: inline-block;
|
109
|
-
width: 2rem;
|
110
|
-
height: 2rem;
|
111
|
-
padding: 0.5rem;
|
112
|
-
|
113
|
-
.icon {
|
114
|
-
width: 2rem;
|
115
|
-
height: 2rem;
|
116
|
-
}
|
117
|
-
}
|
118
|
-
}
|
119
|
-
|
120
|
-
.ais-Stats {
|
121
|
-
.ais-Stats-text {
|
122
|
-
display: flex;
|
123
|
-
justify-content: center;
|
124
|
-
align-items: center;
|
125
|
-
|
126
|
-
position: relative;
|
127
|
-
|
128
|
-
padding-bottom: 8px;
|
129
|
-
margin-bottom: 8px;
|
130
|
-
font-size: small;
|
131
|
-
}
|
132
|
-
}
|
133
|
-
|
134
|
-
.algolia-powered {
|
135
|
-
position: absolute;
|
136
|
-
top: 0;
|
137
|
-
right: 1rem;
|
138
|
-
|
139
|
-
display: inline-flex;
|
140
|
-
justify-content: center;
|
141
|
-
align-items: center;
|
142
|
-
|
143
|
-
img {
|
144
|
-
width: 1rem;
|
145
|
-
height: 1rem;
|
146
|
-
display: inline-flex;
|
147
|
-
}
|
148
|
-
}
|
149
|
-
|
150
|
-
.algolia-results {
|
151
|
-
position: relative;
|
152
|
-
overflow: auto;
|
153
|
-
padding: 10px 30px 0 30px;
|
154
|
-
|
155
|
-
hr {
|
156
|
-
margin-top: 10px;
|
157
|
-
margin-bottom: 0;
|
158
|
-
}
|
159
|
-
}
|
160
|
-
|
161
|
-
.algolia-hit-item {
|
162
|
-
display: flex;
|
163
|
-
justify-content: center;
|
164
|
-
}
|
165
|
-
|
166
|
-
.algolia-hit-item-link {
|
167
|
-
display: block;
|
168
|
-
width: 100%;
|
169
|
-
padding: 0.5rem;
|
170
|
-
border-bottom: 1px dashed #ccc;
|
171
|
-
font-family: var(--va-font-serif);
|
172
|
-
font-weight: 900;
|
173
|
-
font-size: 1.2rem;
|
174
|
-
max-width: 800px;
|
175
|
-
|
176
|
-
mark {
|
177
|
-
color: var(--va-c-danger);
|
178
|
-
font-family: 900;
|
179
|
-
background-color: transparent;
|
180
|
-
text-decoration: underline;
|
181
|
-
}
|
182
|
-
|
183
|
-
small {
|
184
|
-
display: flex;
|
185
|
-
font-size: 12px;
|
186
|
-
justify-content: center;
|
187
|
-
font-family: var(--va-font-sans);
|
188
|
-
font-weight: normal;
|
189
|
-
line-height: 1;
|
190
|
-
margin-top: -0.2rem;
|
191
|
-
}
|
192
|
-
}
|
193
|
-
|
194
|
-
.algolia-pagination {
|
195
|
-
margin-top: 1rem;
|
196
|
-
.ais-Pagination-list {
|
197
|
-
display: flex;
|
198
|
-
padding-inline-start: 0;
|
199
|
-
}
|
200
|
-
|
201
|
-
.pagination-item {
|
202
|
-
display: inline-flex;
|
203
|
-
list-style-type: none;
|
204
|
-
}
|
205
|
-
|
206
|
-
.page-number {
|
207
|
-
border-top: none;
|
208
|
-
}
|
209
|
-
|
210
|
-
.disabled-item {
|
211
|
-
display: none;
|
212
|
-
}
|
213
|
-
|
214
|
-
.active {
|
215
|
-
.page-number {
|
216
|
-
background: var(--page-btn-active-bg-color);
|
217
|
-
color: var(--va-c-bg);
|
218
|
-
}
|
219
|
-
}
|
220
|
-
}
|
221
|
-
|
222
|
-
.ais-Hits-list {
|
223
|
-
margin: 0;
|
224
|
-
list-style-type: none;
|
225
|
-
padding-inline-start: 0;
|
226
|
-
}
|
227
|
-
</style>
|