valaxy-theme-press 0.0.1 → 0.0.3
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 +8 -0
- package/client/index.ts +1 -0
- package/components/DocsBoard.vue +24 -0
- package/components/PressArticle.vue +15 -10
- package/components/PressArticleCard.vue +6 -2
- package/components/PressAside.vue +87 -0
- package/components/PressBackdrop.vue +39 -0
- package/components/PressButton.vue +31 -0
- package/components/PressCategories.vue +71 -0
- package/components/PressCategory.vue +58 -0
- package/components/PressDocFooter.vue +15 -0
- package/components/PressDocFooterLastUpdated.vue +44 -0
- package/components/PressFeature.vue +61 -0
- package/components/PressFeatures.vue +26 -0
- package/components/PressFooter.vue +53 -0
- package/components/PressHome.vue +15 -0
- package/components/PressHomeFeatures.vue +12 -0
- package/components/PressHomeHero.vue +34 -0
- package/components/PressLocalNav.vue +109 -0
- package/components/PressNav.vue +17 -35
- package/components/PressOutline.vue +111 -0
- package/components/PressOutlineItem.vue +48 -0
- package/components/PressSidebar.vue +88 -0
- package/components/PressToggleLocale.vue +1 -1
- package/components/ValaxyMain.vue +56 -12
- package/components/nav/PressNavBar.vue +111 -0
- package/components/nav/PressNavItemGroup.vue +101 -0
- package/components/nav/PressNavItemLink.vue +39 -0
- package/components/nav/PressSwitchAppearance.vue +71 -0
- package/composables/edit-link.ts +14 -0
- package/composables/index.ts +1 -0
- package/config/index.ts +7 -12
- package/layouts/404.vue +13 -12
- package/layouts/home.vue +1 -7
- package/layouts/layout.vue +52 -39
- package/node/index.ts +1 -42
- package/package.json +16 -15
- package/pages/[..all].vue +15 -0
- package/setup/main.ts +89 -0
- package/styles/css-vars.scss +46 -0
- package/styles/helper.scss +34 -0
- package/styles/index.scss +7 -0
- package/styles/markdown.scss +49 -0
- package/types/home.d.ts +5 -0
- package/types/index.d.ts +71 -0
- package/valaxy.config.ts +38 -0
- package/LICENSE +0 -21
- package/components/PressHeader.vue +0 -26
- package/pages/index.vue +0 -8
- package/tsup.config.ts +0 -16
- package/types/index.ts +0 -30
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import type { NavItemGroup } from '../../types'
|
|
4
|
+
defineProps<{
|
|
5
|
+
item: NavItemGroup
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const open = ref(false)
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<div
|
|
13
|
+
ref="el"
|
|
14
|
+
class="flex self-stretch relative group"
|
|
15
|
+
:aria-expanded="open"
|
|
16
|
+
aria-haspopup="true"
|
|
17
|
+
@mouseenter="open = true"
|
|
18
|
+
@mouseleave="open = false"
|
|
19
|
+
>
|
|
20
|
+
<button
|
|
21
|
+
type="button"
|
|
22
|
+
class="button flex items-center"
|
|
23
|
+
@click="open = !open"
|
|
24
|
+
>
|
|
25
|
+
<span class="text">
|
|
26
|
+
{{ item.text }}
|
|
27
|
+
</span>
|
|
28
|
+
<div i-ri-arrow-drop-down-line />
|
|
29
|
+
</button>
|
|
30
|
+
|
|
31
|
+
<div class="menu grow" flex="~ col" items="start">
|
|
32
|
+
<AppLink v-for="itemLink in item.items" :key="itemLink.text" class="menu-item" p="x-3" :to="itemLink.link">
|
|
33
|
+
{{ itemLink.text }}
|
|
34
|
+
</AppLink>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<style lang="scss" scoped>
|
|
40
|
+
.group .button{
|
|
41
|
+
color: var(--pr-nav-text);
|
|
42
|
+
font-weight: 500;
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.group[aria-expanded="true"] .button{
|
|
47
|
+
color: rgba(60, 60, 60, 0.70);
|
|
48
|
+
transition: color 0.25s;
|
|
49
|
+
|
|
50
|
+
.dark &{
|
|
51
|
+
color: rgba(235, 235, 235, 0.6)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.menu {
|
|
56
|
+
position: absolute;
|
|
57
|
+
left: 50%;
|
|
58
|
+
|
|
59
|
+
min-width: 128px;
|
|
60
|
+
opacity: 0;
|
|
61
|
+
visibility: hidden;
|
|
62
|
+
transition: opacity 0.25s, visibility 0.25s, transform 0.25s;
|
|
63
|
+
transform: translateX(-50%) translateY(calc(var(--pr-nav-height) / 2));
|
|
64
|
+
|
|
65
|
+
border-radius: 12px;
|
|
66
|
+
padding: 12px;
|
|
67
|
+
border: 1px solid rgba(60, 60, 60, 0.12);
|
|
68
|
+
background-color: #ffffff;
|
|
69
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.08);
|
|
70
|
+
.dark &{
|
|
71
|
+
background-color: #242424;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&-item{
|
|
75
|
+
display: flex;
|
|
76
|
+
width: 100%;
|
|
77
|
+
border-radius: 6px;
|
|
78
|
+
color: var(--pr-nav-text);
|
|
79
|
+
line-height: 32px;
|
|
80
|
+
font-size: 14px;
|
|
81
|
+
font-weight: 500;
|
|
82
|
+
white-space: nowrap;
|
|
83
|
+
transition: background-color .25s,color .25s;
|
|
84
|
+
|
|
85
|
+
&:hover{
|
|
86
|
+
background-color: #f1f1f1;
|
|
87
|
+
color: var(--va-c-brand);
|
|
88
|
+
|
|
89
|
+
.dark &{
|
|
90
|
+
background-color: #2f2f2f;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.group[aria-expanded="true"] > .menu {
|
|
98
|
+
opacity: 1;
|
|
99
|
+
visibility: visible;
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useRoute } from 'vue-router'
|
|
3
|
+
import type { NavItemLink } from '../../types'
|
|
4
|
+
defineProps<{
|
|
5
|
+
item: NavItemLink
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const route = useRoute()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<AppLink
|
|
13
|
+
class="press-nav-item-link"
|
|
14
|
+
:class="{
|
|
15
|
+
active: route.path === item.link,
|
|
16
|
+
}"
|
|
17
|
+
:to="item.link"
|
|
18
|
+
rel="noopener"
|
|
19
|
+
show-external-icon
|
|
20
|
+
>
|
|
21
|
+
{{ item.text }}
|
|
22
|
+
</AppLink>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<style lang="scss" scoped>
|
|
26
|
+
.press-nav-item-link{
|
|
27
|
+
font-size: 14px;
|
|
28
|
+
font-weight: 500;
|
|
29
|
+
color: var(--pr-nav-text);
|
|
30
|
+
transition: color 0.25s;
|
|
31
|
+
|
|
32
|
+
&:hover{
|
|
33
|
+
color: var(--va-c-brand);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
.active{
|
|
37
|
+
color: var(--va-c-brand);
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { isDark, toggleDark } from 'valaxy'
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<template>
|
|
6
|
+
<button class="switch switch-appearance" type="button" aria-label="Toggle Dark Mode" @click="toggleDark()">
|
|
7
|
+
<span class="check">
|
|
8
|
+
<span class="icon-wrap">
|
|
9
|
+
<div v-if="!isDark" class="icon" i-ri-sun-line />
|
|
10
|
+
<div v-else class="icon" i-ri-moon-line />
|
|
11
|
+
</span>
|
|
12
|
+
</span>
|
|
13
|
+
</button>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<style lang="scss" scoped>
|
|
17
|
+
.switch {
|
|
18
|
+
position: relative;
|
|
19
|
+
display: block;
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
width: 40px;
|
|
22
|
+
height: 22px;
|
|
23
|
+
border-radius: 11px;
|
|
24
|
+
border: 1px solid var(--pr-switch-divider);
|
|
25
|
+
background-color: var(--pr-switch-bg);
|
|
26
|
+
transition: border-color 0.25s, background-color 0.25s;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.switch:hover {
|
|
30
|
+
border-color: #8e8e8e;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.check {
|
|
34
|
+
position: absolute;
|
|
35
|
+
top: 1px;
|
|
36
|
+
left: 1px;
|
|
37
|
+
width: 18px;
|
|
38
|
+
height: 18px;
|
|
39
|
+
border-radius: 50%;
|
|
40
|
+
background-color: #ffffff;
|
|
41
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
42
|
+
transition: background-color 0.25s, transform 0.25s;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.dark .check {
|
|
46
|
+
background-color: #1a1a1a;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.icon-wrap {
|
|
50
|
+
box-sizing: border-box;
|
|
51
|
+
display: block;
|
|
52
|
+
padding: 3px;
|
|
53
|
+
width: 18px;
|
|
54
|
+
height: 18px;
|
|
55
|
+
border-radius: 50%;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.icon {
|
|
59
|
+
width: 12px;
|
|
60
|
+
height: 12px;
|
|
61
|
+
background-color: rgba(60, 60, 60, 0.7);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.dark .icon {
|
|
65
|
+
background-color: rgba(255, 255, 255, 0.87);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.dark .switch-appearance :deep(.check) {
|
|
69
|
+
transform: translateX(18px);
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useData } from 'valaxy'
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useThemeConfig } from '.'
|
|
4
|
+
|
|
5
|
+
export function useEditLink() {
|
|
6
|
+
const themeConfig = useThemeConfig()
|
|
7
|
+
return computed(() => {
|
|
8
|
+
const { text = 'Edit this page', pattern } = themeConfig.value.editLink || {}
|
|
9
|
+
const { relativePath } = useData()
|
|
10
|
+
const url = pattern.replace(/:path/g, relativePath)
|
|
11
|
+
|
|
12
|
+
return { url, text }
|
|
13
|
+
})
|
|
14
|
+
}
|
package/composables/index.ts
CHANGED
package/config/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ThemeConfig
|
|
1
|
+
import type { ThemeConfig } from '../types'
|
|
2
2
|
|
|
3
3
|
export const anonymousImage = 'https://cdn.yunyoujun.cn/img/avatar/none.jpg'
|
|
4
4
|
|
|
@@ -12,18 +12,13 @@ export const defaultThemeConfig: ThemeConfig = {
|
|
|
12
12
|
primary: '#0078E7',
|
|
13
13
|
},
|
|
14
14
|
|
|
15
|
+
sidebar: [],
|
|
15
16
|
nav: [],
|
|
16
|
-
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
editLink: {
|
|
19
|
+
pattern: 'https://github.com/YunYouJun/valaxy/edit/main/docs/:path',
|
|
20
|
+
text: 'Edit this page on GitHub',
|
|
21
|
+
},
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
* generateSafelist by config
|
|
22
|
-
* @param themeConfig
|
|
23
|
-
* @returns
|
|
24
|
-
*/
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
|
-
export function generateSafelist(themeConfig: ThemeUserConfig) {
|
|
27
|
-
const safelist: string[] = []
|
|
28
|
-
return safelist
|
|
23
|
+
footer: {},
|
|
29
24
|
}
|
package/layouts/404.vue
CHANGED
|
@@ -8,18 +8,19 @@ const { t } = useI18n()
|
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
10
|
<Layout>
|
|
11
|
-
<template #
|
|
12
|
-
<div
|
|
13
|
-
<div text-4xl>
|
|
14
|
-
<div i-ri-alarm-warning-line inline-block />
|
|
15
|
-
</div>
|
|
16
|
-
<router-view />
|
|
17
|
-
<div>
|
|
18
|
-
<button btn text-sm m="3 t8" @click="router.back()">
|
|
19
|
-
{{ t('button.back') }}
|
|
20
|
-
</button>
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
11
|
+
<template #sidebar>
|
|
12
|
+
<div />
|
|
23
13
|
</template>
|
|
14
|
+
<div text="center" m="t-20">
|
|
15
|
+
<div text-4xl>
|
|
16
|
+
<div i-ri-alarm-warning-line inline-block />
|
|
17
|
+
</div>
|
|
18
|
+
<router-view />
|
|
19
|
+
<div>
|
|
20
|
+
<button btn text-sm m="3 t8" @click="router.back()">
|
|
21
|
+
{{ t('button.back') }}
|
|
22
|
+
</button>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
24
25
|
</Layout>
|
|
25
26
|
</template>
|
package/layouts/home.vue
CHANGED
package/layouts/layout.vue
CHANGED
|
@@ -1,45 +1,58 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useLayout, useSidebar } from 'valaxy'
|
|
3
|
+
|
|
4
|
+
const { isOpen: isSidebarOpen, open: openSidebar, close: closeSidebar } = useSidebar()
|
|
5
|
+
const layout = useLayout()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
1
8
|
<template>
|
|
2
|
-
<div class="antialiased">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
<div class="layout antialiased">
|
|
10
|
+
<PressNav />
|
|
11
|
+
<PressLocalNav :open="isSidebarOpen" @open-menu="openSidebar()" />
|
|
12
|
+
<slot name="sidebar">
|
|
13
|
+
<PressSidebar v-if="layout !== 'post'" :open="isSidebarOpen" />
|
|
14
|
+
</slot>
|
|
15
|
+
<PressBackdrop :show="isSidebarOpen" @click="closeSidebar" />
|
|
16
|
+
|
|
17
|
+
<slot>
|
|
18
|
+
<router-view v-slot="{ Component }">
|
|
19
|
+
<component :is="Component">
|
|
20
|
+
<template #main-header>
|
|
21
|
+
<slot name="main-header" />
|
|
22
|
+
</template>
|
|
6
23
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
<
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
24
|
+
<template #main-header-after>
|
|
25
|
+
<slot name="main-header-after" />
|
|
26
|
+
</template>
|
|
27
|
+
<template #main>
|
|
28
|
+
<slot name="main" />
|
|
29
|
+
</template>
|
|
30
|
+
<template #main-content>
|
|
31
|
+
<slot name="main-content" />
|
|
32
|
+
</template>
|
|
33
|
+
<template #main-content-after>
|
|
34
|
+
<slot name="main-content-after" />
|
|
35
|
+
</template>
|
|
36
|
+
<template #main-nav-before>
|
|
37
|
+
<slot name="main-nav-before" />
|
|
38
|
+
</template>
|
|
39
|
+
<template #main-nav-after>
|
|
40
|
+
<slot name="main-nav-after" />
|
|
41
|
+
</template>
|
|
42
|
+
<template #aside>
|
|
43
|
+
<slot name="aside" />
|
|
44
|
+
</template>
|
|
45
|
+
<template #aside-custom>
|
|
46
|
+
<slot name="aside-custom" />
|
|
47
|
+
</template>
|
|
48
|
+
<template #footer>
|
|
49
|
+
<slot name="footer" />
|
|
50
|
+
</template>
|
|
51
|
+
</component>
|
|
52
|
+
</router-view>
|
|
53
|
+
</slot>
|
|
14
54
|
|
|
15
|
-
|
|
16
|
-
<slot name="main-header-after" />
|
|
17
|
-
</template>
|
|
18
|
-
<template #main>
|
|
19
|
-
<slot name="main" />
|
|
20
|
-
</template>
|
|
21
|
-
<template #main-content>
|
|
22
|
-
<slot name="main-content" />
|
|
23
|
-
</template>
|
|
24
|
-
<template #main-content-after>
|
|
25
|
-
<slot name="main-content-after" />
|
|
26
|
-
</template>
|
|
27
|
-
<template #main-nav-before>
|
|
28
|
-
<slot name="main-nav-before" />
|
|
29
|
-
</template>
|
|
30
|
-
<template #main-nav-after>
|
|
31
|
-
<slot name="main-nav-after" />
|
|
32
|
-
</template>
|
|
33
|
-
<template #aside-custom>
|
|
34
|
-
<slot name="aside-custom" />
|
|
35
|
-
</template>
|
|
36
|
-
<template #footer>
|
|
37
|
-
<slot name="footer" />
|
|
38
|
-
</template>
|
|
39
|
-
</component>
|
|
40
|
-
</router-view>
|
|
41
|
-
</slot>
|
|
42
|
-
</main>
|
|
55
|
+
<PressFooter />
|
|
43
56
|
</div>
|
|
44
57
|
</template>
|
|
45
58
|
|
package/node/index.ts
CHANGED
|
@@ -1,43 +1,2 @@
|
|
|
1
|
-
import { defineThemePlugin } from 'valaxy'
|
|
2
|
-
import type { ResolvedValaxyOptions } from 'valaxy'
|
|
3
|
-
import type { Plugin } from 'vite'
|
|
4
|
-
|
|
5
1
|
export * from '../config'
|
|
6
|
-
export * from '../types'
|
|
7
|
-
|
|
8
|
-
export interface UserOptions {
|
|
9
|
-
colors: {
|
|
10
|
-
primary: string
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function ThemeYunVitePlugin(options: ResolvedValaxyOptions): Plugin {
|
|
15
|
-
const themeConfig = options.config.themeConfig
|
|
16
|
-
return {
|
|
17
|
-
name: 'valaxy-theme-yun',
|
|
18
|
-
enforce: 'pre',
|
|
19
|
-
config() {
|
|
20
|
-
return {
|
|
21
|
-
css: {
|
|
22
|
-
preprocessorOptions: {
|
|
23
|
-
scss: {
|
|
24
|
-
additionalData: `$c-primary: ${themeConfig.colors?.primary || '#0078E7'} !default;`,
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
optimizeDeps: {
|
|
30
|
-
exclude: ['@docsearch/js'],
|
|
31
|
-
},
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export default defineThemePlugin((options) => {
|
|
38
|
-
return {
|
|
39
|
-
vite: {
|
|
40
|
-
plugins: [ThemeYunVitePlugin(options)],
|
|
41
|
-
},
|
|
42
|
-
}
|
|
43
|
-
})
|
|
2
|
+
export * from '../types/index.d'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valaxy-theme-press",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Docs Theme for Valaxy",
|
|
5
5
|
"author": {
|
|
6
6
|
"email": "me@yunyoujun.cn",
|
|
@@ -14,24 +14,25 @@
|
|
|
14
14
|
"url": "https://github.com/YunYouJun/valaxy/tree/main/packages/valaxy-theme-press"
|
|
15
15
|
},
|
|
16
16
|
"exports": {
|
|
17
|
-
".": {
|
|
18
|
-
"require": "./dist/index.js",
|
|
19
|
-
"import": "./dist/index.mjs"
|
|
20
|
-
},
|
|
21
17
|
"./*": "./*"
|
|
22
18
|
},
|
|
23
|
-
"main": "
|
|
24
|
-
"
|
|
25
|
-
"types": "dist/index.d.ts",
|
|
19
|
+
"main": "node/index.ts",
|
|
20
|
+
"types": "types/index.d.ts",
|
|
26
21
|
"dependencies": {
|
|
27
|
-
"@docsearch/css": "^3.
|
|
28
|
-
"@docsearch/js": "^3.
|
|
22
|
+
"@docsearch/css": "^3.3.0",
|
|
23
|
+
"@docsearch/js": "^3.3.0"
|
|
29
24
|
},
|
|
30
25
|
"devDependencies": {
|
|
31
|
-
"valaxy": "
|
|
26
|
+
"valaxy": "workspace:*"
|
|
32
27
|
},
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
28
|
+
"pnpm": {
|
|
29
|
+
"peerDependencyRules": {
|
|
30
|
+
"ignoreMissing": [
|
|
31
|
+
"@algolia/client-search",
|
|
32
|
+
"@types/react",
|
|
33
|
+
"react",
|
|
34
|
+
"react-dom"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
36
37
|
}
|
|
37
|
-
}
|
|
38
|
+
}
|
package/setup/main.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { defineAppSetup } from 'valaxy'
|
|
2
|
+
import { nextTick } from 'vue'
|
|
3
|
+
|
|
4
|
+
export default defineAppSetup((ctx) => {
|
|
5
|
+
const { router, isClient } = ctx
|
|
6
|
+
if (!isClient)
|
|
7
|
+
return
|
|
8
|
+
|
|
9
|
+
window.addEventListener(
|
|
10
|
+
'click',
|
|
11
|
+
(e) => {
|
|
12
|
+
const link = (e.target as Element).closest('a')
|
|
13
|
+
if (link) {
|
|
14
|
+
const { protocol, hostname, pathname, hash, target } = link
|
|
15
|
+
const currentUrl = window.location
|
|
16
|
+
const extMatch = pathname.match(/\.\w+$/)
|
|
17
|
+
// only intercept inbound links
|
|
18
|
+
if (
|
|
19
|
+
!e.ctrlKey
|
|
20
|
+
&& !e.shiftKey
|
|
21
|
+
&& !e.altKey
|
|
22
|
+
&& !e.metaKey
|
|
23
|
+
&& target !== '_blank'
|
|
24
|
+
&& protocol === currentUrl.protocol
|
|
25
|
+
&& hostname === currentUrl.hostname
|
|
26
|
+
&& !(extMatch && extMatch[0] !== '.html')
|
|
27
|
+
) {
|
|
28
|
+
if (pathname === currentUrl.pathname) {
|
|
29
|
+
e.preventDefault()
|
|
30
|
+
// scroll between hash anchors in the same page
|
|
31
|
+
if (hash && hash !== currentUrl.hash) {
|
|
32
|
+
history.pushState(null, '', hash)
|
|
33
|
+
// still emit the event so we can listen to it in themes
|
|
34
|
+
window.dispatchEvent(new Event('hashchange'))
|
|
35
|
+
// use smooth scroll when clicking on header anchor links
|
|
36
|
+
scrollTo(link, hash, link.classList.contains('header-anchor'))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{ capture: true },
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
window.addEventListener('hashchange', (e) => {
|
|
46
|
+
e.preventDefault()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
router.beforeEach((to, from) => {
|
|
50
|
+
if (to.path !== from.path)
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
nextTick(() => {
|
|
54
|
+
scrollTo(document.body, to.hash, true)
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
function scrollTo(el: HTMLElement, hash: string, smooth = false) {
|
|
60
|
+
let target: Element | null = null
|
|
61
|
+
try {
|
|
62
|
+
target = el.classList.contains('header-anchor')
|
|
63
|
+
? el
|
|
64
|
+
: (decodeURIComponent(hash) && document.querySelector(decodeURIComponent(hash))) || null
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
console.warn(e)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (target) {
|
|
71
|
+
const targetPadding = -64
|
|
72
|
+
const targetTop
|
|
73
|
+
= window.scrollY
|
|
74
|
+
+ (target as HTMLElement).getBoundingClientRect().top
|
|
75
|
+
+ targetPadding
|
|
76
|
+
|
|
77
|
+
// only smooth scroll if distance is smaller than screen height.
|
|
78
|
+
if (!smooth || Math.abs(targetTop - window.scrollY) > window.innerHeight) {
|
|
79
|
+
window.scrollTo(0, targetTop)
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
window.scrollTo({
|
|
83
|
+
left: 0,
|
|
84
|
+
top: targetTop,
|
|
85
|
+
behavior: 'smooth',
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--pr-c-indigo-lighter: #c9def1;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
--pr-c-text-code: #374562;
|
|
7
|
+
--pr-c-text-1: #213547;
|
|
8
|
+
|
|
9
|
+
// aside
|
|
10
|
+
--pr-aside-text-1: var(--pr-c-text-1);
|
|
11
|
+
--pr-aside-text-2: rgba(60, 60, 60, 0.702);
|
|
12
|
+
|
|
13
|
+
--pr-aside-divider: rgba(60, 60, 60, 0.122);
|
|
14
|
+
|
|
15
|
+
--pr-c-divider-light: rgba(60, 60, 60, 0.12);
|
|
16
|
+
|
|
17
|
+
// nav
|
|
18
|
+
--pr-nav-height: var(--pr-nav-height-mobile);
|
|
19
|
+
--pr-nav-height-mobile: 60px;
|
|
20
|
+
--pr-nav-text: var(--pr-c-text-1);
|
|
21
|
+
|
|
22
|
+
// z-index
|
|
23
|
+
--va-z-overlay: var(--pr-z-index-backdrop);
|
|
24
|
+
--pr-z-index-local-nav: 8;
|
|
25
|
+
--pr-z-index-nav: 9;
|
|
26
|
+
--pr-z-index-backdrop: 10;
|
|
27
|
+
--pr-z-index-aside: 11;
|
|
28
|
+
--pr-z-index-sidebar: 12;
|
|
29
|
+
|
|
30
|
+
// switch
|
|
31
|
+
--pr-switch-divider: rgba(60, 60, 60, 0.29);
|
|
32
|
+
--pr-switch-bg: #f1f1f1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.dark {
|
|
36
|
+
--pr-c-text-code: var(--pr-c-indigo-lighter);
|
|
37
|
+
--pr-c-text-1: #ffffffde;
|
|
38
|
+
|
|
39
|
+
// aside
|
|
40
|
+
--pr-aside-text-2: #ebebeb99;
|
|
41
|
+
--pr-aside-divider: rgba(84, 84, 84, 0.48);
|
|
42
|
+
|
|
43
|
+
// switch
|
|
44
|
+
--pr-switch-divider: rgba(84, 84, 84, 0.65);
|
|
45
|
+
--pr-switch-bg: #3a3a3a;
|
|
46
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
.gradient-text {
|
|
2
|
+
background-clip: text;
|
|
3
|
+
-webkit-background-clip: text;
|
|
4
|
+
-webkit-text-fill-color: transparent;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.sese-btn {
|
|
8
|
+
position: relative;
|
|
9
|
+
z-index: 0;
|
|
10
|
+
|
|
11
|
+
@apply transition;
|
|
12
|
+
|
|
13
|
+
&:hover {
|
|
14
|
+
@apply shadow;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.press-icon-btn {
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
|
|
25
|
+
border: none;
|
|
26
|
+
width: 3rem;
|
|
27
|
+
height: 3rem;
|
|
28
|
+
|
|
29
|
+
border-radius: 50%;
|
|
30
|
+
|
|
31
|
+
div {
|
|
32
|
+
font-size: 1.2rem;
|
|
33
|
+
}
|
|
34
|
+
}
|