refactor: use deconstruct syntax to handle component props (#744)
This commit is contained in:
parent
0e38265f96
commit
d4ad65a1ea
@ -4,13 +4,13 @@ import { computed, nextTick, ref, useTemplateRef, watch } from 'vue'
|
|||||||
|
|
||||||
import '@vuepress/helper/transition/fade-in.css'
|
import '@vuepress/helper/transition/fade-in.css'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { label, total } = defineProps<{
|
||||||
label: string
|
label: string
|
||||||
total: number
|
total: number
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const active = ref(false)
|
const active = ref(false)
|
||||||
const list = computed(() => Array.from({ length: props.total }, (_, i) => i))
|
const list = computed(() => Array.from({ length: total }, (_, i) => i))
|
||||||
const position = ref({ x: 0, y: 0 })
|
const position = ref({ x: 0, y: 0 })
|
||||||
|
|
||||||
const popover = useTemplateRef<HTMLDivElement>('popover')
|
const popover = useTemplateRef<HTMLDivElement>('popover')
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useInterval } from '@vueuse/core'
|
|||||||
import { onMounted, toRef, watch } from 'vue'
|
import { onMounted, toRef, watch } from 'vue'
|
||||||
import { useAudioPlayer } from '../composables/audio.js'
|
import { useAudioPlayer } from '../composables/audio.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { src, autoplay, type, volume, startTime, endTime } = defineProps<{
|
||||||
src: string
|
src: string
|
||||||
autoplay?: boolean
|
autoplay?: boolean
|
||||||
type?: string
|
type?: string
|
||||||
@ -13,20 +13,19 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { paused, play, pause, seek, setVolume } = useAudioPlayer(
|
const { paused, play, pause, seek, setVolume } = useAudioPlayer(
|
||||||
toRef(() => props.src),
|
toRef(() => src),
|
||||||
{
|
{
|
||||||
type: toRef(() => props.type || ''),
|
type: toRef(() => type || ''),
|
||||||
autoplay: props.autoplay,
|
autoplay,
|
||||||
oncanplay: () => {
|
oncanplay: () => {
|
||||||
if (props.startTime) {
|
if (startTime)
|
||||||
seek(props.startTime)
|
seek(startTime)
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ontimeupdate: (time) => {
|
ontimeupdate: (time) => {
|
||||||
if (props.endTime && time >= props.endTime) {
|
if (endTime && time >= endTime) {
|
||||||
pause()
|
pause()
|
||||||
if (props.startTime) {
|
if (startTime) {
|
||||||
seek(props.startTime)
|
seek(startTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -56,7 +55,7 @@ function toggle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
watch(() => props.volume, (volume) => {
|
watch(() => volume, (volume) => {
|
||||||
if (typeof volume !== 'undefined') {
|
if (typeof volume !== 'undefined') {
|
||||||
setVolume(volume)
|
setVolume(volume)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,16 +12,12 @@ interface MessageData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const { feature, past = 2, future = 1, meta = '' } = defineProps<{
|
||||||
feature: string
|
feature: string
|
||||||
past?: number
|
past?: number
|
||||||
future?: number
|
future?: number
|
||||||
meta?: string
|
meta?: string
|
||||||
}>(), {
|
}>()
|
||||||
past: 2,
|
|
||||||
future: 1,
|
|
||||||
meta: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
const url = 'https://caniuse.pengzhanbo.cn/'
|
const url = 'https://caniuse.pengzhanbo.cn/'
|
||||||
|
|
||||||
@ -29,7 +25,7 @@ const height = ref('330px')
|
|||||||
|
|
||||||
const isDark = useDarkMode()
|
const isDark = useDarkMode()
|
||||||
const source = computed(() => {
|
const source = computed(() => {
|
||||||
const source = `${url}${props.feature}#past=${props.past}&future=${props.future}&meta=${props.meta}&theme=${isDark.value ? 'dark' : 'light'}`
|
const source = `${url}${feature}#past=${past}&future=${future}&meta=${meta}&theme=${isDark.value ? 'dark' : 'light'}`
|
||||||
|
|
||||||
return source
|
return source
|
||||||
})
|
})
|
||||||
@ -40,8 +36,8 @@ useEventListener('message', (event) => {
|
|||||||
if (
|
if (
|
||||||
type === 'ciu_embed'
|
type === 'ciu_embed'
|
||||||
&& payload
|
&& payload
|
||||||
&& payload.feature === props.feature
|
&& payload.feature === feature
|
||||||
&& payload.meta === props.meta
|
&& payload.meta === meta
|
||||||
) {
|
) {
|
||||||
height.value = `${Math.ceil(payload.height)}px`
|
height.value = `${Math.ceil(payload.height)}px`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import { useDarkMode } from '@vuepress/helper/client'
|
import { useDarkMode } from '@vuepress/helper/client'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { user, slash, title, preview, editable, tab, theme, width, height } = defineProps<{
|
||||||
user: string
|
user: string
|
||||||
slash: string
|
slash: string
|
||||||
title?: string
|
title?: string
|
||||||
@ -19,16 +19,16 @@ const CODEPEN_LINK = 'https://codepen.io/'
|
|||||||
const isDark = useDarkMode()
|
const isDark = useDarkMode()
|
||||||
|
|
||||||
const link = computed(() => {
|
const link = computed(() => {
|
||||||
const middle = props.preview ? '/embed/preview/' : '/embed/'
|
const middle = preview ? '/embed/preview/' : '/embed/'
|
||||||
const params = new URLSearchParams()
|
const params = new URLSearchParams()
|
||||||
|
|
||||||
props.editable && params.set('editable', 'true')
|
editable && params.set('editable', 'true')
|
||||||
props.tab && params.set('default-tab', props.tab)
|
tab && params.set('default-tab', tab)
|
||||||
|
|
||||||
const theme = props.theme ?? (isDark.value ? 'dark' : 'light')
|
const themeMode = theme ?? (isDark.value ? 'dark' : 'light')
|
||||||
theme && params.set('theme-id', theme)
|
themeMode && params.set('theme-id', themeMode)
|
||||||
|
|
||||||
return `${CODEPEN_LINK}${props.user}${middle}${props.slash}?${params.toString()}`
|
return `${CODEPEN_LINK}${user}${middle}${slash}?${params.toString()}`
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { inject, ref } from 'vue'
|
import { inject, ref } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { type, filename, level, diff, expanded, focus, filepath } = defineProps<{
|
||||||
type: 'file' | 'folder'
|
type: 'file' | 'folder'
|
||||||
filename: string
|
filename: string
|
||||||
level: number
|
level: number
|
||||||
@ -18,17 +18,17 @@ const onNodeClick = inject<
|
|||||||
(filename: string, type: 'file' | 'folder') => void
|
(filename: string, type: 'file' | 'folder') => void
|
||||||
>('on-file-tree-node-click', () => {})
|
>('on-file-tree-node-click', () => {})
|
||||||
|
|
||||||
const active = ref(props.expanded)
|
const active = ref(expanded)
|
||||||
|
|
||||||
function nodeClick() {
|
function nodeClick() {
|
||||||
if (props.filename === '…' || props.filename === '...')
|
if (filename === '…' || filename === '...')
|
||||||
return
|
return
|
||||||
|
|
||||||
onNodeClick(props.filepath || props.filename, props.type)
|
onNodeClick(filepath || filename, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle(ev: MouseEvent) {
|
function toggle(ev: MouseEvent) {
|
||||||
if (props.type === 'folder') {
|
if (type === 'folder') {
|
||||||
const el = ev.target as HTMLElement
|
const el = ev.target as HTMLElement
|
||||||
if (!el.matches('.comment, .comment *')) {
|
if (!el.matches('.comment, .comment *')) {
|
||||||
active.value = !active.value
|
active.value = !active.value
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import { useDarkMode } from '@vuepress/helper/client'
|
import { useDarkMode } from '@vuepress/helper/client'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { source, title, tab, theme, width, height } = defineProps<{
|
||||||
source: string
|
source: string
|
||||||
title?: string
|
title?: string
|
||||||
tab: string
|
tab: string
|
||||||
@ -14,8 +14,8 @@ const props = defineProps<{
|
|||||||
const isDark = useDarkMode()
|
const isDark = useDarkMode()
|
||||||
|
|
||||||
const link = computed(() => {
|
const link = computed(() => {
|
||||||
const theme = props.theme === 'dark' ? '/dark/' : isDark.value ? '/dark/' : ''
|
const themeMode = theme === 'dark' ? '/dark/' : isDark.value ? '/dark/' : ''
|
||||||
return `https://jsfiddle.net/${props.source}/embedded/${props.tab}${theme}`
|
return `https://jsfiddle.net/${source}/embedded/${tab}${themeMode}`
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const props = defineProps<ReplitTokenMeta>()
|
const { source, theme, width, height: h, title } = defineProps<ReplitTokenMeta>()
|
||||||
|
|
||||||
// magic height
|
// magic height
|
||||||
const height = ref('47px')
|
const height = ref('47px')
|
||||||
@ -19,18 +19,18 @@ const REPLIT_LINK = 'https://replit.com/'
|
|||||||
const isDark = useDarkMode()
|
const isDark = useDarkMode()
|
||||||
|
|
||||||
const link = computed(() => {
|
const link = computed(() => {
|
||||||
const url = new URL(`/${props.source}`, REPLIT_LINK)
|
const url = new URL(`/${source}`, REPLIT_LINK)
|
||||||
url.searchParams.set('embed', 'true')
|
url.searchParams.set('embed', 'true')
|
||||||
|
|
||||||
const theme = props.theme || (isDark.value ? 'dark' : 'light')
|
const themeMode = theme || (isDark.value ? 'dark' : 'light')
|
||||||
url.searchParams.set('theme', theme)
|
url.searchParams.set('theme', themeMode)
|
||||||
|
|
||||||
return url.toString()
|
return url.toString()
|
||||||
})
|
})
|
||||||
|
|
||||||
function onload() {
|
function onload() {
|
||||||
loaded.value = true
|
loaded.value = true
|
||||||
height.value = props.height || '450px'
|
height.value = h || '450px'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -5,27 +5,27 @@ import { onMounted, ref, shallowRef, watch } from 'vue'
|
|||||||
interface TabProps extends Record<string, unknown> {
|
interface TabProps extends Record<string, unknown> {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
const props = withDefaults(defineProps<{
|
const { id, tabId = '', active = 0, data } = defineProps<{
|
||||||
id: string
|
id: string
|
||||||
tabId?: string
|
tabId?: string
|
||||||
active?: number
|
active?: number
|
||||||
data: TabProps[]
|
data: TabProps[]
|
||||||
}>(), { active: 0, tabId: '' })
|
}>()
|
||||||
|
|
||||||
const TAB_STORE_NAME = 'VUEPRESS_TAB_STORE'
|
const TAB_STORE_NAME = 'VUEPRESS_TAB_STORE'
|
||||||
|
|
||||||
const tabStore = useStorage<Record<string, string>>(TAB_STORE_NAME, {})
|
const tabStore = useStorage<Record<string, string>>(TAB_STORE_NAME, {})
|
||||||
|
|
||||||
// Index of current active item
|
// Index of current active item
|
||||||
const activeIndex = ref(props.active)
|
const activeIndex = ref(active)
|
||||||
|
|
||||||
// Refs of the tab buttons
|
// Refs of the tab buttons
|
||||||
const tabRefs = shallowRef<HTMLUListElement[]>([])
|
const tabRefs = shallowRef<HTMLUListElement[]>([])
|
||||||
|
|
||||||
// Update store
|
// Update store
|
||||||
function updateStore(): void {
|
function updateStore(): void {
|
||||||
if (props.tabId)
|
if (tabId)
|
||||||
tabStore.value[props.tabId] = props.data[activeIndex.value].id
|
tabStore.value[tabId] = data[activeIndex.value]?.id
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate next tab
|
// Activate next tab
|
||||||
@ -59,26 +59,26 @@ function keyboardHandler(event: KeyboardEvent, index: number): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getInitialIndex(): number {
|
function getInitialIndex(): number {
|
||||||
if (props.tabId) {
|
if (tabId) {
|
||||||
const valueIndex = props.data.findIndex(
|
const valueIndex = data.findIndex(
|
||||||
({ id }) => tabStore.value[props.tabId] === id,
|
({ id }) => tabStore.value[tabId] === id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (valueIndex !== -1)
|
if (valueIndex !== -1)
|
||||||
return valueIndex
|
return valueIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
return props.active
|
return active
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
activeIndex.value = getInitialIndex()
|
activeIndex.value = getInitialIndex()
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => tabStore.value[props.tabId],
|
() => tabStore.value[tabId],
|
||||||
(newValue, oldValue) => {
|
(newValue, oldValue) => {
|
||||||
if (props.tabId && newValue !== oldValue) {
|
if (tabId && newValue !== oldValue) {
|
||||||
const index = props.data.findIndex(({ id }) => id === newValue)
|
const index = data.findIndex(({ id }) => id === newValue)
|
||||||
|
|
||||||
if (index !== -1)
|
if (index !== -1)
|
||||||
activeIndex.value = index
|
activeIndex.value = index
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, provide, ref, useTemplateRef, watch } from 'vue'
|
import { onMounted, provide, ref, useTemplateRef, watch } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const { title, height = '320px', entryFile } = defineProps<{
|
||||||
title?: string
|
title?: string
|
||||||
height?: string
|
height?: string
|
||||||
entryFile?: string
|
entryFile?: string
|
||||||
}>(), { height: '320px' })
|
}>()
|
||||||
|
|
||||||
const activeNode = ref(props.entryFile || '')
|
const activeNode = ref(entryFile || '')
|
||||||
const isEmpty = ref(true)
|
const isEmpty = ref(true)
|
||||||
const codePanel = useTemplateRef<HTMLDivElement>('codePanel')
|
const codePanel = useTemplateRef<HTMLDivElement>('codePanel')
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="vp-code-tree">
|
<div class="vp-code-tree">
|
||||||
<div class="code-tree-panel" :style="{ 'max-height': props.height }">
|
<div class="code-tree-panel" :style="{ 'max-height': height }">
|
||||||
<div v-if="title" class="code-tree-title" :title="title">
|
<div v-if="title" class="code-tree-title" :title="title">
|
||||||
<span>{{ title }}</span>
|
<span>{{ title }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -52,7 +52,7 @@ onMounted(() => {
|
|||||||
<slot name="file-tree" />
|
<slot name="file-tree" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ref="codePanel" class="code-panel" :style="{ height: props.height }">
|
<div ref="codePanel" class="code-panel" :style="{ height }">
|
||||||
<slot />
|
<slot />
|
||||||
<div v-if="isEmpty" class="code-tree-empty">
|
<div v-if="isEmpty" class="code-tree-empty">
|
||||||
<span class="vpi-code-tree-empty" />
|
<span class="vpi-code-tree-empty" />
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
import { provide, ref } from 'vue'
|
import { provide, ref } from 'vue'
|
||||||
import { INJECT_COLLAPSE_KEY } from '../options.js'
|
import { INJECT_COLLAPSE_KEY } from '../options.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { accordion, index } = defineProps<{
|
||||||
accordion?: boolean
|
accordion?: boolean
|
||||||
index?: number
|
index?: number
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const currentIndex = ref<number | undefined>(props.index)
|
const currentIndex = ref<number | undefined>(index)
|
||||||
|
|
||||||
provide(INJECT_COLLAPSE_KEY, {
|
provide(INJECT_COLLAPSE_KEY, {
|
||||||
accordion: props.accordion ?? false,
|
accordion: accordion ?? false,
|
||||||
index: currentIndex,
|
index: currentIndex,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { INJECT_COLLAPSE_KEY } from '../options.js'
|
|||||||
|
|
||||||
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { expand, index } = defineProps<{
|
||||||
expand?: boolean
|
expand?: boolean
|
||||||
index: number
|
index: number
|
||||||
}>()
|
}>()
|
||||||
@ -20,36 +20,36 @@ if (__VUEPRESS_DEV__ && !collapse) {
|
|||||||
throw new Error('<VPCollapseItem /> must be used inside <VPCollapse />')
|
throw new Error('<VPCollapseItem /> must be used inside <VPCollapse />')
|
||||||
}
|
}
|
||||||
|
|
||||||
const expand = ref(
|
const expanded = ref(
|
||||||
collapse?.accordion && typeof collapse.index.value !== 'undefined'
|
collapse?.accordion && typeof collapse.index.value !== 'undefined'
|
||||||
? props.index === collapse.index.value
|
? index === collapse.index.value
|
||||||
: props.expand,
|
: expand,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (collapse?.accordion) {
|
if (collapse?.accordion) {
|
||||||
watch(collapse?.index, () => {
|
watch(collapse?.index, () => {
|
||||||
expand.value = collapse?.index.value === props.index
|
expanded.value = collapse?.index.value === index
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
if (collapse?.accordion) {
|
if (collapse?.accordion) {
|
||||||
if (collapse.index.value === props.index && expand.value) {
|
if (collapse.index.value === index && expanded.value) {
|
||||||
expand.value = false
|
expanded.value = false
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
collapse!.index.value = props.index!
|
collapse!.index.value = index!
|
||||||
expand.value = true
|
expanded.value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expand.value = !expand.value
|
expanded.value = !expanded.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="vp-collapse-item" :class="{ expand }">
|
<div class="vp-collapse-item" :class="{ expanded }">
|
||||||
<div class="vp-collapse-header" @click="toggle">
|
<div class="vp-collapse-header" @click="toggle">
|
||||||
<span class="vpi-chevron-right" />
|
<span class="vpi-chevron-right" />
|
||||||
<p class="vp-collapse-title">
|
<p class="vp-collapse-title">
|
||||||
@ -57,7 +57,7 @@ function toggle() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<FadeInExpandTransition>
|
<FadeInExpandTransition>
|
||||||
<div v-show="expand" class="vp-collapse-content">
|
<div v-show="expanded" class="vp-collapse-content">
|
||||||
<div class="vp-collapse-content-inner">
|
<div class="vp-collapse-content-inner">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
@ -95,7 +95,7 @@ function toggle() {
|
|||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vp-collapse-item.expand .vpi-chevron-right {
|
.vp-collapse-item.expanded .vpi-chevron-right {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,14 @@ import { useExpand } from '../composables/demo.js'
|
|||||||
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
||||||
import '../styles/demo.css'
|
import '../styles/demo.css'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { type, title, desc, expanded } = defineProps<{
|
||||||
type?: 'vue' | 'markdown'
|
type?: 'vue' | 'markdown'
|
||||||
title?: string
|
title?: string
|
||||||
desc?: string
|
desc?: string
|
||||||
expanded?: boolean
|
expanded?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const [showCode, toggleCode] = useExpand(props.expanded)
|
const [showCode, toggleCode] = useExpand(expanded)
|
||||||
|
|
||||||
const draw = useTemplateRef<HTMLIFrameElement>('draw')
|
const draw = useTemplateRef<HTMLIFrameElement>('draw')
|
||||||
const vueDraw = useTemplateRef<HTMLIFrameElement>('draw-vue')
|
const vueDraw = useTemplateRef<HTMLIFrameElement>('draw-vue')
|
||||||
@ -30,7 +30,7 @@ function resizeAndPositionVueDraw() {
|
|||||||
vueDraw.value.style.left = `${rect.x + scrollLeft}px`
|
vueDraw.value.style.left = `${rect.x + scrollLeft}px`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.type === 'vue' && !__VUEPRESS_SSR__) {
|
if (type === 'vue' && !__VUEPRESS_SSR__) {
|
||||||
watch([draw, vueDraw], () => {
|
watch([draw, vueDraw], () => {
|
||||||
resizeAndPositionVueDraw()
|
resizeAndPositionVueDraw()
|
||||||
if (draw.value && vueDraw.value) {
|
if (draw.value && vueDraw.value) {
|
||||||
|
|||||||
@ -8,29 +8,29 @@ import '@vuepress/helper/transition/fade-in.css'
|
|||||||
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
||||||
import '../styles/demo.css'
|
import '../styles/demo.css'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { title, desc, expanded, config } = defineProps<{
|
||||||
title?: string
|
title?: string
|
||||||
desc?: string
|
desc?: string
|
||||||
expanded?: boolean
|
expanded?: boolean
|
||||||
config?: DemoConfig
|
config?: DemoConfig
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const [showCode, toggleCode] = useExpand(props.expanded)
|
const [showCode, toggleCode] = useExpand(expanded)
|
||||||
|
|
||||||
const { resources, showResources, toggleResources } = useResources(
|
const { resources, showResources, toggleResources } = useResources(
|
||||||
useTemplateRef<HTMLDivElement>('resourcesEl'),
|
useTemplateRef<HTMLDivElement>('resourcesEl'),
|
||||||
() => props.config,
|
() => config,
|
||||||
)
|
)
|
||||||
|
|
||||||
const { id, height } = useNormalDemo(
|
const { id, height } = useNormalDemo(
|
||||||
useTemplateRef<HTMLIFrameElement>('draw'),
|
useTemplateRef<HTMLIFrameElement>('draw'),
|
||||||
() => props.title,
|
() => title,
|
||||||
() => props.config,
|
() => config,
|
||||||
)
|
)
|
||||||
|
|
||||||
const data = useFence(
|
const data = useFence(
|
||||||
useTemplateRef<HTMLDivElement>('fence'),
|
useTemplateRef<HTMLDivElement>('fence'),
|
||||||
() => props.config,
|
() => config,
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { decodeData } from '@vuepress/helper/client'
|
|||||||
import { useClipboard, useToggle } from '@vueuse/core'
|
import { useClipboard, useToggle } from '@vueuse/core'
|
||||||
import { computed, useTemplateRef } from 'vue'
|
import { computed, useTemplateRef } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { title, align = 'left', copy, maxContent, fullWidth, markdown } = defineProps<{
|
||||||
/** 表格标题 */
|
/** 表格标题 */
|
||||||
title?: string
|
title?: string
|
||||||
/** 对其方式 */
|
/** 对其方式 */
|
||||||
@ -19,7 +19,7 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const tableEl = useTemplateRef('table')
|
const tableEl = useTemplateRef('table')
|
||||||
const rawContent = computed(() => props.markdown ? decodeData(props.markdown) : '')
|
const rawContent = computed(() => markdown ? decodeData(markdown) : '')
|
||||||
|
|
||||||
const [isHTMLCopied, toggleHTMLCopy] = useToggle()
|
const [isHTMLCopied, toggleHTMLCopy] = useToggle()
|
||||||
const [isMDCopied, toggleMDCopy] = useToggle()
|
const [isMDCopied, toggleMDCopy] = useToggle()
|
||||||
@ -35,7 +35,7 @@ function onCopy(type: 'html' | 'md') {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="vp-table" :class="{ [align || 'left']: true, full: fullWidth }">
|
<div class="vp-table" :class="{ [align]: true, full: fullWidth }">
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<div class="table-content">
|
<div class="table-content">
|
||||||
<div v-if="copy" class="table-toolbar">
|
<div v-if="copy" class="table-toolbar">
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import { computed, provide } from 'vue'
|
import { computed, provide } from 'vue'
|
||||||
import { INJECT_TIMELINE_KEY } from '../options.js'
|
import { INJECT_TIMELINE_KEY } from '../options.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { horizontal, card, placement, line } = defineProps<{
|
||||||
horizontal?: boolean
|
horizontal?: boolean
|
||||||
card?: boolean
|
card?: boolean
|
||||||
placement?: 'left' | 'right' | 'between'
|
placement?: 'left' | 'right' | 'between'
|
||||||
@ -10,10 +10,10 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
provide(INJECT_TIMELINE_KEY, computed(() => ({
|
provide(INJECT_TIMELINE_KEY, computed(() => ({
|
||||||
line: props.line || 'solid',
|
line: line || 'solid',
|
||||||
card: props.card ?? false,
|
card: card ?? false,
|
||||||
horizontal: props.horizontal ?? false,
|
horizontal: horizontal ?? false,
|
||||||
placement: props.placement || 'left',
|
placement: placement || 'left',
|
||||||
})))
|
})))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useMediaQuery } from '@vueuse/core'
|
|||||||
import { computed, inject } from 'vue'
|
import { computed, inject } from 'vue'
|
||||||
import { INJECT_TIMELINE_KEY } from '../options.js'
|
import { INJECT_TIMELINE_KEY } from '../options.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { time, type, card, line, icon, color, placement } = defineProps<{
|
||||||
time?: string
|
time?: string
|
||||||
type?: 'info' | 'tip' | 'success' | 'warning' | 'danger' | 'caution' | 'important' | (string & {})
|
type?: 'info' | 'tip' | 'success' | 'warning' | 'danger' | 'caution' | 'important' | (string & {})
|
||||||
card?: boolean
|
card?: boolean
|
||||||
@ -25,17 +25,17 @@ const defaultOptions = inject<ComputedRef<{
|
|||||||
|
|
||||||
const timeline = computed(() => {
|
const timeline = computed(() => {
|
||||||
const between = defaultOptions?.value.placement === 'between' && !is639.value
|
const between = defaultOptions?.value.placement === 'between' && !is639.value
|
||||||
const placement = defaultOptions?.value.placement === 'between' ? 'left' : defaultOptions?.value.placement
|
const defaultPlacement = defaultOptions?.value.placement === 'between' ? 'left' : defaultOptions?.value.placement
|
||||||
return {
|
return {
|
||||||
time: props.time,
|
time,
|
||||||
type: props.type || 'info',
|
type: type || 'info',
|
||||||
line: props.line || defaultOptions?.value.line || 'solid',
|
line: line || defaultOptions?.value.line || 'solid',
|
||||||
icon: props.icon,
|
icon,
|
||||||
color: props.color,
|
color,
|
||||||
horizontal: defaultOptions?.value.horizontal ?? false,
|
horizontal: defaultOptions?.value.horizontal ?? false,
|
||||||
between: between ? props.placement || 'left' : false,
|
between: between ? placement || 'left' : false,
|
||||||
placement: between ? '' : (placement || 'left'),
|
placement: between ? '' : (defaultPlacement || 'left'),
|
||||||
card: props.card ?? defaultOptions?.value.card ?? false,
|
card: card ?? defaultOptions?.value.card ?? false,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import BackIcon from './icons/BackIcon.vue'
|
|||||||
import ClearIcon from './icons/ClearIcon.vue'
|
import ClearIcon from './icons/ClearIcon.vue'
|
||||||
import SearchIcon from './icons/SearchIcon.vue'
|
import SearchIcon from './icons/SearchIcon.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { locales, options } = defineProps<{
|
||||||
locales: SearchBoxLocales
|
locales: SearchBoxLocales
|
||||||
options: SearchOptions
|
options: SearchOptions
|
||||||
}>()
|
}>()
|
||||||
@ -42,7 +42,7 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const routeLocale = useRouteLocale()
|
const routeLocale = useRouteLocale()
|
||||||
const locale = useLocale(toRef(props.locales))
|
const locale = useLocale(toRef(() => locales))
|
||||||
|
|
||||||
const el = shallowRef<HTMLElement>()
|
const el = shallowRef<HTMLElement>()
|
||||||
const resultsEl = shallowRef<HTMLElement>()
|
const resultsEl = shallowRef<HTMLElement>()
|
||||||
@ -71,15 +71,15 @@ const searchIndex = computedAsync(async () =>
|
|||||||
prefix: true,
|
prefix: true,
|
||||||
boost: { title: 4, text: 2, titles: 1 },
|
boost: { title: 4, text: 2, titles: 1 },
|
||||||
},
|
},
|
||||||
...props.options.miniSearch?.searchOptions,
|
...options.miniSearch?.searchOptions,
|
||||||
...props.options.miniSearch?.options,
|
...options.miniSearch?.options,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
const disableQueryPersistence = computed(() =>
|
const disableQueryPersistence = computed(() =>
|
||||||
props.options?.disableQueryPersistence === true,
|
options?.disableQueryPersistence === true,
|
||||||
)
|
)
|
||||||
const filterText = disableQueryPersistence.value
|
const filterText = disableQueryPersistence.value
|
||||||
? ref('')
|
? ref('')
|
||||||
|
|||||||
@ -3,11 +3,11 @@ import type { SearchBoxLocales } from '../../shared/index.js'
|
|||||||
import { toRef } from 'vue'
|
import { toRef } from 'vue'
|
||||||
import { useLocale } from '../composables/index.js'
|
import { useLocale } from '../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { locales } = defineProps<{
|
||||||
locales: SearchBoxLocales
|
locales: SearchBoxLocales
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const locale = useLocale(toRef(props.locales))
|
const locale = useLocale(toRef(() => locales))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@ -6,14 +6,14 @@ import { withBase } from 'vuepress/client'
|
|||||||
import { isLinkHttp } from 'vuepress/shared'
|
import { isLinkHttp } from 'vuepress/shared'
|
||||||
import { useData } from '../../composables/index.js'
|
import { useData } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<ThemeHomeBanner>()
|
const { banner, bannerMask, hero } = defineProps<ThemeHomeBanner>()
|
||||||
|
|
||||||
const DEFAULT_BANNER = 'https://api.pengzhanbo.cn/wallpaper/bing'
|
const DEFAULT_BANNER = 'https://api.pengzhanbo.cn/wallpaper/bing'
|
||||||
|
|
||||||
const { isDark, frontmatter: matter } = useData<'home'>()
|
const { isDark, frontmatter: matter } = useData<'home'>()
|
||||||
|
|
||||||
const mask = computed(() => {
|
const mask = computed(() => {
|
||||||
const mask = props.bannerMask ?? matter.value.bannerMask
|
const mask = bannerMask ?? matter.value.bannerMask
|
||||||
if (typeof mask !== 'object')
|
if (typeof mask !== 'object')
|
||||||
return mask || 0
|
return mask || 0
|
||||||
|
|
||||||
@ -21,17 +21,17 @@ const mask = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const bannerStyle = computed(() => {
|
const bannerStyle = computed(() => {
|
||||||
const banner = props.banner ?? matter.value.banner
|
const _banner = banner ?? matter.value.banner
|
||||||
const link = banner ? isLinkHttp(banner) ? banner : withBase(banner) : DEFAULT_BANNER
|
const link = _banner ? isLinkHttp(_banner) ? _banner : withBase(_banner) : DEFAULT_BANNER
|
||||||
return {
|
return {
|
||||||
'background-image': `url(${link})`,
|
'background-image': `url(${link})`,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const name = computed(() => props.hero?.name ?? matter.value.hero?.name ?? 'Plume')
|
const name = computed(() => hero?.name ?? matter.value.hero?.name ?? 'Plume')
|
||||||
const tagline = computed(() => props.hero?.tagline ?? matter.value.hero?.tagline ?? 'A VuePress Theme')
|
const tagline = computed(() => hero?.tagline ?? matter.value.hero?.tagline ?? 'A VuePress Theme')
|
||||||
const text = computed(() => props.hero?.text ?? matter.value.hero?.text)
|
const text = computed(() => hero?.text ?? matter.value.hero?.text)
|
||||||
const actions = computed(() => props.hero?.actions ?? matter.value.hero?.actions ?? [])
|
const actions = computed(() => hero?.actions ?? matter.value.hero?.actions ?? [])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@ -5,38 +5,38 @@ import { withBase } from 'vuepress/client'
|
|||||||
import { isLinkHttp } from 'vuepress/shared'
|
import { isLinkHttp } from 'vuepress/shared'
|
||||||
import { useDarkMode } from '../../composables/index.js'
|
import { useDarkMode } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<ThemeHomeConfigBase & {
|
const { backgroundAttachment, backgroundImage, containerClass, full } = defineProps<ThemeHomeConfigBase & {
|
||||||
containerClass?: any
|
containerClass?: any
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const isDark = useDarkMode()
|
const isDark = useDarkMode()
|
||||||
|
|
||||||
const styles = computed(() => {
|
const styles = computed(() => {
|
||||||
if (!props.backgroundImage)
|
if (!backgroundImage)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
const image = typeof props.backgroundImage === 'string' ? props.backgroundImage : (props.backgroundImage[isDark.value ? 'dark' : 'light'] ?? props.backgroundImage.light)
|
const image = typeof backgroundImage === 'string' ? backgroundImage : (backgroundImage[isDark.value ? 'dark' : 'light'] ?? backgroundImage.light)
|
||||||
|
|
||||||
if (!image)
|
if (!image)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
const link = isLinkHttp(image) ? props.backgroundImage : withBase(image)
|
const link = isLinkHttp(image) ? backgroundImage : withBase(image)
|
||||||
return {
|
return {
|
||||||
'background-image': `url(${link})`,
|
'background-image': `url(${link})`,
|
||||||
'background-size': 'cover',
|
'background-size': 'cover',
|
||||||
'background-position': 'center',
|
'background-position': 'center',
|
||||||
'background-repeat': 'no-repeat',
|
'background-repeat': 'no-repeat',
|
||||||
'background-attachment': props.backgroundAttachment || '',
|
'background-attachment': backgroundAttachment || '',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const containerClass = computed(() => normalizeClass(props.containerClass || ''))
|
const containerClasses = computed(() => normalizeClass(containerClass || ''))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="vp-home-box" :class="{ full: props.full }" :style="styles">
|
<div class="vp-home-box" :class="{ full }" :style="styles">
|
||||||
<slot name="before" />
|
<slot name="before" />
|
||||||
<div class="container" :class="containerClass">
|
<div class="container" :class="containerClasses">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
<slot name="after" />
|
<slot name="after" />
|
||||||
|
|||||||
@ -6,15 +6,15 @@ import VPLink from '@theme/VPLink.vue'
|
|||||||
import { isLinkAbsolute, isLinkHttp } from '@vuepress/helper/client'
|
import { isLinkAbsolute, isLinkHttp } from '@vuepress/helper/client'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<ThemeHomeFeature>()
|
const { icon, link, linkText, rel, target, title, details } = defineProps<ThemeHomeFeature>()
|
||||||
|
|
||||||
const ICONIFY_NAME = /^[\w-]+:[\w-]+$/
|
const ICONIFY_NAME = /^[\w-]+:[\w-]+$/
|
||||||
|
|
||||||
const isIconify = computed(() => {
|
const isIconify = computed(() => {
|
||||||
if (typeof props.icon !== 'string' || isLinkAbsolute(props.icon) || isLinkHttp(props.icon)) {
|
if (typeof icon !== 'string' || isLinkAbsolute(icon) || isLinkHttp(icon)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return ICONIFY_NAME.test(props.icon)
|
return ICONIFY_NAME.test(icon)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -4,10 +4,10 @@ import VPHomeBox from '@theme/Home/VPHomeBox.vue'
|
|||||||
import VPHomeFeature from '@theme/Home/VPHomeFeature.vue'
|
import VPHomeFeature from '@theme/Home/VPHomeFeature.vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<ThemeHomeFeatures>()
|
const { features, title, description, type, backgroundImage, backgroundAttachment, full, index } = defineProps<ThemeHomeFeatures>()
|
||||||
|
|
||||||
const grid = computed(() => {
|
const grid = computed(() => {
|
||||||
const length = props.features?.length
|
const length = features?.length
|
||||||
|
|
||||||
if (!length)
|
if (!length)
|
||||||
return undefined
|
return undefined
|
||||||
@ -32,11 +32,13 @@ const grid = computed(() => {
|
|||||||
<VPHomeBox
|
<VPHomeBox
|
||||||
v-if="features"
|
v-if="features"
|
||||||
class="vp-home-features"
|
class="vp-home-features"
|
||||||
:type="type"
|
v-bind="{
|
||||||
:background-image="backgroundImage"
|
type,
|
||||||
:background-attachment="backgroundAttachment"
|
backgroundAttachment,
|
||||||
:full="full"
|
backgroundImage,
|
||||||
:index="index"
|
full,
|
||||||
|
index,
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<h2 v-if="title" class="title" v-html="title" />
|
<h2 v-if="title" class="title" v-html="title" />
|
||||||
<p v-if="description" class="description" v-html="description" />
|
<p v-if="description" class="description" v-html="description" />
|
||||||
@ -48,15 +50,7 @@ const grid = computed(() => {
|
|||||||
class="item"
|
class="item"
|
||||||
:class="[grid]"
|
:class="[grid]"
|
||||||
>
|
>
|
||||||
<VPHomeFeature
|
<VPHomeFeature v-bind="feature" />
|
||||||
:icon="feature.icon"
|
|
||||||
:title="feature.title"
|
|
||||||
:details="feature.details"
|
|
||||||
:link="feature.link"
|
|
||||||
:link-text="feature.linkText"
|
|
||||||
:rel="feature.rel"
|
|
||||||
:target="feature.target"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VPHomeBox>
|
</VPHomeBox>
|
||||||
|
|||||||
@ -3,7 +3,8 @@ import type { ThemeHomeHero } from '../../../shared/index.js'
|
|||||||
import { effectComponents, effects } from '@internal/home-hero-effects'
|
import { effectComponents, effects } from '@internal/home-hero-effects'
|
||||||
import ImageBg from '@theme/background/ImageBg.vue'
|
import ImageBg from '@theme/background/ImageBg.vue'
|
||||||
import VPButton from '@theme/VPButton.vue'
|
import VPButton from '@theme/VPButton.vue'
|
||||||
import { computed, nextTick, onMounted, onUnmounted, watch } from 'vue'
|
import { hasGlobalComponent } from '@vuepress/helper/client'
|
||||||
|
import { computed, markRaw, nextTick, onMounted, onUnmounted, resolveComponent, watch } from 'vue'
|
||||||
import { isPlainObject } from 'vuepress/shared'
|
import { isPlainObject } from 'vuepress/shared'
|
||||||
import { useData } from '../../composables/index.js'
|
import { useData } from '../../composables/index.js'
|
||||||
import { inBrowser } from '../../utils/index.js'
|
import { inBrowser } from '../../utils/index.js'
|
||||||
@ -15,10 +16,11 @@ const hero = computed(() => props.hero ?? frontmatter.value.hero ?? {})
|
|||||||
const actions = computed(() => hero.value.actions ?? [])
|
const actions = computed(() => hero.value.actions ?? [])
|
||||||
|
|
||||||
const effect = computed(() => {
|
const effect = computed(() => {
|
||||||
const effect = props.effect || props.background
|
if (props.effect)
|
||||||
if (!effect || !effects.includes(effect))
|
return props.effect
|
||||||
return null
|
if (props.background && effects.includes(props.background))
|
||||||
return effect as typeof effects[number]
|
return props.background
|
||||||
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
const effectConfig = computed(() => {
|
const effectConfig = computed(() => {
|
||||||
@ -37,6 +39,17 @@ const effectConfig = computed(() => {
|
|||||||
return props.effectConfig
|
return props.effectConfig
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const realEffectComponent = computed(() => {
|
||||||
|
if (!effect.value)
|
||||||
|
return null
|
||||||
|
if (effectComponents[effect.value])
|
||||||
|
return markRaw(effectComponents[effect.value])
|
||||||
|
if (hasGlobalComponent(effect.value))
|
||||||
|
return resolveComponent(effect.value)
|
||||||
|
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
|
||||||
function noTransition() {
|
function noTransition() {
|
||||||
document.documentElement.classList.add('no-transition')
|
document.documentElement.classList.add('no-transition')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -85,7 +98,7 @@ onUnmounted(() => {
|
|||||||
[effect ?? '']: !!effect,
|
[effect ?? '']: !!effect,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<component :is="effectComponents[effect]" v-if="effect" v-bind="effectConfig" />
|
<component :is="realEffectComponent" v-if="realEffectComponent" v-bind="effectConfig" />
|
||||||
<ImageBg v-else v-bind="props" />
|
<ImageBg v-else v-bind="props" />
|
||||||
|
|
||||||
<div class="hero-container">
|
<div class="hero-container">
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import VPImage from '@theme/VPImage.vue'
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useData } from '../../composables/index.js'
|
import { useData } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<ThemeHomeProfile>()
|
const { name, description, avatar, circle, type, backgroundImage, backgroundAttachment, full, index } = defineProps<ThemeHomeProfile>()
|
||||||
|
|
||||||
const { theme } = useData()
|
const { theme } = useData()
|
||||||
|
|
||||||
@ -13,10 +13,10 @@ const rawProfile = computed(() => theme.value.profile)
|
|||||||
|
|
||||||
const profile = computed(() => {
|
const profile = computed(() => {
|
||||||
return {
|
return {
|
||||||
name: props.name || rawProfile.value?.name,
|
name: name || rawProfile.value?.name,
|
||||||
description: props.description || rawProfile.value?.description,
|
description: description || rawProfile.value?.description,
|
||||||
avatar: props.avatar || rawProfile.value?.avatar || rawProfile.value?.url,
|
avatar: avatar || rawProfile.value?.avatar || rawProfile.value?.url,
|
||||||
circle: props.circle || rawProfile.value?.circle,
|
circle: circle || rawProfile.value?.circle,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -24,11 +24,7 @@ const profile = computed(() => {
|
|||||||
<template>
|
<template>
|
||||||
<VPHomeBox
|
<VPHomeBox
|
||||||
class="vp-home-profile"
|
class="vp-home-profile"
|
||||||
:type="type"
|
v-bind="{ type, backgroundAttachment, backgroundImage, full, index }"
|
||||||
:background-image="backgroundImage"
|
|
||||||
:background-attachment="backgroundAttachment"
|
|
||||||
:full="full"
|
|
||||||
:index="index"
|
|
||||||
>
|
>
|
||||||
<VPImage v-if="profile.avatar" :image="profile.avatar" :class="{ circle: profile.circle }" />
|
<VPImage v-if="profile.avatar" :image="profile.avatar" :class="{ circle: profile.circle }" />
|
||||||
|
|
||||||
|
|||||||
@ -4,11 +4,9 @@ import VPHomeBox from '@theme/Home/VPHomeBox.vue'
|
|||||||
import VPImage from '@theme/VPImage.vue'
|
import VPImage from '@theme/VPImage.vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<ThemeHomeTextImage>()
|
const { width, title, description, list, image, type, backgroundImage, backgroundAttachment, full, index } = defineProps<ThemeHomeTextImage>()
|
||||||
|
|
||||||
const maxWidth = computed(() => {
|
const maxWidth = computed(() => {
|
||||||
const width = props.width
|
|
||||||
|
|
||||||
if (typeof width === 'number')
|
if (typeof width === 'number')
|
||||||
return `${width}px`
|
return `${width}px`
|
||||||
|
|
||||||
@ -19,12 +17,8 @@ const maxWidth = computed(() => {
|
|||||||
<template>
|
<template>
|
||||||
<VPHomeBox
|
<VPHomeBox
|
||||||
class="vp-home-text-image"
|
class="vp-home-text-image"
|
||||||
:type="type"
|
|
||||||
:background-image="backgroundImage"
|
|
||||||
:background-attachment="backgroundAttachment"
|
|
||||||
:full="full"
|
|
||||||
:container-class="{ reverse: type === 'text-image' }"
|
:container-class="{ reverse: type === 'text-image' }"
|
||||||
:index="index"
|
v-bind="{ type, backgroundAttachment, backgroundImage, full, index }"
|
||||||
>
|
>
|
||||||
<div class="content-image">
|
<div class="content-image">
|
||||||
<VPImage :image="image" :style="{ maxWidth }" />
|
<VPImage :image="image" :style="{ maxWidth }" />
|
||||||
@ -39,7 +33,7 @@ const maxWidth = computed(() => {
|
|||||||
<p v-if="description" class="description" v-html="description" />
|
<p v-if="description" class="description" v-html="description" />
|
||||||
|
|
||||||
<ul v-if="list && list.length" class="list">
|
<ul v-if="list && list.length" class="list">
|
||||||
<li v-for="(item, index) in list" :key="index">
|
<li v-for="(item, i) in list" :key="i">
|
||||||
<template v-if="typeof item === 'object'">
|
<template v-if="typeof item === 'object'">
|
||||||
<h3 v-if="item.title" v-html="item.title" />
|
<h3 v-if="item.title" v-html="item.title" />
|
||||||
<p v-if="item.description" v-html="item.description" />
|
<p v-if="item.description" v-html="item.description" />
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { useWindowScroll } from '@vueuse/core'
|
|||||||
import { ref, watchPostEffect } from 'vue'
|
import { ref, watchPostEffect } from 'vue'
|
||||||
import { useData, useSidebar } from '../../composables/index.js'
|
import { useData, useSidebar } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { isScreenOpen } = defineProps<{
|
||||||
isScreenOpen: boolean
|
isScreenOpen: boolean
|
||||||
}>()
|
}>()
|
||||||
defineEmits<(e: 'toggleScreen') => void>()
|
defineEmits<(e: 'toggleScreen') => void>()
|
||||||
@ -27,7 +27,7 @@ watchPostEffect(() => {
|
|||||||
'has-sidebar': hasSidebar.value,
|
'has-sidebar': hasSidebar.value,
|
||||||
'home': frontmatter.value.pageLayout === 'home',
|
'home': frontmatter.value.pageLayout === 'home',
|
||||||
'top': y.value === 0,
|
'top': y.value === 0,
|
||||||
'screen-open': props.isScreenOpen,
|
'screen-open': isScreenOpen,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
defineProps<{
|
const { active } = defineProps<{
|
||||||
active: boolean
|
active: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { resolveRouteFullPath } from 'vuepress/client'
|
|||||||
import { useData } from '../../composables/index.js'
|
import { useData } from '../../composables/index.js'
|
||||||
import { isActive } from '../../utils/index.js'
|
import { isActive } from '../../utils/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { item } = defineProps<{
|
||||||
item: ResolvedNavItemWithChildren
|
item: ResolvedNavItemWithChildren
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@ -20,14 +20,14 @@ function isChildActive(navItem: ResolvedNavItem): boolean {
|
|||||||
return isActive(
|
return isActive(
|
||||||
page.value.path,
|
page.value.path,
|
||||||
resolveRouteFullPath(navItem.link),
|
resolveRouteFullPath(navItem.link),
|
||||||
!!props.item.activeMatch,
|
!!item.activeMatch,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return navItem.items.some(isChildActive)
|
return navItem.items.some(isChildActive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const childrenActive = computed(() => isChildActive(props.item))
|
const childrenActive = computed(() => isChildActive(item))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { resolveRouteFullPath } from 'vuepress/client'
|
|||||||
import { useData } from '../../composables/index.js'
|
import { useData } from '../../composables/index.js'
|
||||||
import { isActive } from '../../utils/index.js'
|
import { isActive } from '../../utils/index.js'
|
||||||
|
|
||||||
defineProps<{
|
const { item } = defineProps<{
|
||||||
item: ResolvedNavItemWithLink
|
item: ResolvedNavItemWithLink
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { inBrowser } from '../../utils/index.js'
|
|||||||
|
|
||||||
import '@vuepress/helper/transition/fade-in.css'
|
import '@vuepress/helper/transition/fade-in.css'
|
||||||
|
|
||||||
defineProps<{
|
const { open } = defineProps<{
|
||||||
open: boolean
|
open: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { computed, ref } from 'vue'
|
|||||||
|
|
||||||
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { text, icon, badge, items } = defineProps<{
|
||||||
text: string
|
text: string
|
||||||
icon?: ThemeIcon
|
icon?: ThemeIcon
|
||||||
badge?: string | ThemeBadge
|
badge?: string | ThemeBadge
|
||||||
@ -19,7 +19,7 @@ const props = defineProps<{
|
|||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
|
|
||||||
const groupId = computed(
|
const groupId = computed(
|
||||||
() => `nav-screen-menu-group-${props.text.replace(' ', '-').toLowerCase()}`,
|
() => `nav-screen-menu-group-${text.replace(' ', '-').toLowerCase()}`,
|
||||||
)
|
)
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import VPIcon from '@theme/VPIcon.vue'
|
|||||||
import VPLink from '@theme/VPLink.vue'
|
import VPLink from '@theme/VPLink.vue'
|
||||||
import { inject } from 'vue'
|
import { inject } from 'vue'
|
||||||
|
|
||||||
defineProps<{
|
const { item } = defineProps<{
|
||||||
item: ResolvedNavItemWithLink
|
item: ResolvedNavItemWithLink
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import type { NavItemWithLink, ThemeIcon } from '../../../shared/index.js'
|
|||||||
import VPNavScreenMenuGroupLink from '@theme/Nav/VPNavScreenMenuGroupLink.vue'
|
import VPNavScreenMenuGroupLink from '@theme/Nav/VPNavScreenMenuGroupLink.vue'
|
||||||
import VPIcon from '@theme/VPIcon.vue'
|
import VPIcon from '@theme/VPIcon.vue'
|
||||||
|
|
||||||
defineProps<{
|
const { icon, text, items } = defineProps<{
|
||||||
icon?: ThemeIcon
|
icon?: ThemeIcon
|
||||||
text?: string
|
text?: string
|
||||||
items: NavItemWithLink[]
|
items: NavItemWithLink[]
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import VPIcon from '@theme/VPIcon.vue'
|
|||||||
import VPLink from '@theme/VPLink.vue'
|
import VPLink from '@theme/VPLink.vue'
|
||||||
import { inject } from 'vue'
|
import { inject } from 'vue'
|
||||||
|
|
||||||
defineProps<{
|
const { item } = defineProps<{
|
||||||
item: ResolvedNavItemWithLink
|
item: ResolvedNavItemWithLink
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@ -3,12 +3,10 @@ import type { CategoryItem, CategoryItemWithPost } from '../../composables/index
|
|||||||
import VPCategoriesGroup from '@theme/Posts/VPCategoriesGroup.vue'
|
import VPCategoriesGroup from '@theme/Posts/VPCategoriesGroup.vue'
|
||||||
import VPLink from '@theme/VPLink.vue'
|
import VPLink from '@theme/VPLink.vue'
|
||||||
|
|
||||||
withDefaults(defineProps<{
|
const { items, depth = 0 } = defineProps<{
|
||||||
items: (CategoryItem | CategoryItemWithPost)[]
|
items: (CategoryItem | CategoryItemWithPost)[]
|
||||||
depth?: number
|
depth?: number
|
||||||
}>(), {
|
}>()
|
||||||
depth: 0,
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@ -5,12 +5,11 @@ import { computed, onMounted, ref, watch } from 'vue'
|
|||||||
import { useRoute } from 'vuepress/client'
|
import { useRoute } from 'vuepress/client'
|
||||||
import { useData } from '../../composables/index.js'
|
import { useData } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const { item, depth = 0 } = defineProps<{
|
||||||
item: CategoryItem
|
item: CategoryItem
|
||||||
depth?: number
|
depth?: number
|
||||||
}>(), {
|
}>()
|
||||||
depth: 0,
|
|
||||||
})
|
|
||||||
const { collection } = useData<'page', 'post'>()
|
const { collection } = useData<'page', 'post'>()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const el = ref<HTMLDivElement | null>(null)
|
const el = ref<HTMLDivElement | null>(null)
|
||||||
@ -28,16 +27,16 @@ const expandDepth = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => [route.query, props.item, expandDepth.value],
|
() => [route.query, item, expandDepth.value],
|
||||||
() => {
|
() => {
|
||||||
const id = route.query.id as string
|
const id = route.query.id as string
|
||||||
if (!id) {
|
if (!id) {
|
||||||
expand.value = props.depth <= expandDepth.value
|
expand.value = depth <= expandDepth.value
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expand.value = hasExpand(props.item, id)
|
expand.value = hasExpand(item, id)
|
||||||
}
|
}
|
||||||
isExpand.value = id ? props.item.id === id : false
|
isExpand.value = id ? item.id === id : false
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useData } from '../../composables/index.js'
|
import { useData } from '../../composables/index.js'
|
||||||
|
|
||||||
defineProps<{
|
const { page, isFirstPage, isLastPage, pageRange } = defineProps<{
|
||||||
page: number
|
page: number
|
||||||
totalPage: number
|
totalPage: number
|
||||||
isFirstPage: boolean
|
isFirstPage: boolean
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { computed, onMounted, ref } from 'vue'
|
|||||||
import { withBase } from 'vuepress/client'
|
import { withBase } from 'vuepress/client'
|
||||||
import { useData, useInternalLink, useTagColors } from '../../composables/index.js'
|
import { useData, useInternalLink, useTagColors } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { post, index } = defineProps<{
|
||||||
post: ThemePostsItem
|
post: ThemePostsItem
|
||||||
index: number
|
index: number
|
||||||
}>()
|
}>()
|
||||||
@ -14,9 +14,9 @@ const props = defineProps<{
|
|||||||
const isMobile = ref(false)
|
const isMobile = ref(false)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
isMobile.value = _isMobile(navigator.userAgent)
|
isMobile.value = _isMobile()
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
isMobile.value = _isMobile(navigator.userAgent)
|
isMobile.value = _isMobile()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -24,15 +24,15 @@ const { collection } = useData<'page', 'post'>()
|
|||||||
const colors = useTagColors()
|
const colors = useTagColors()
|
||||||
const { categories: categoriesLink, tags: tagsLink } = useInternalLink()
|
const { categories: categoriesLink, tags: tagsLink } = useInternalLink()
|
||||||
|
|
||||||
const createTime = computed(() => props.post.createTime?.split(/\s|T/)[0].replace(/\//g, '-'))
|
const createTime = computed(() => post.createTime?.split(/\s|T/)[0].replace(/\//g, '-'))
|
||||||
const categoryList = computed(() => props.post.categoryList ?? [])
|
const categoryList = computed(() => post.categoryList ?? [])
|
||||||
|
|
||||||
const sticky = computed(() => {
|
const sticky = computed(() => {
|
||||||
if (typeof props.post.sticky === 'boolean') {
|
if (typeof post.sticky === 'boolean') {
|
||||||
return props.post.sticky
|
return post.sticky
|
||||||
}
|
}
|
||||||
else if (typeof props.post.sticky === 'number') {
|
else if (typeof post.sticky === 'number') {
|
||||||
return props.post.sticky >= 0
|
return post.sticky >= 0
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@ -40,7 +40,7 @@ const sticky = computed(() => {
|
|||||||
const tags = computed(() => {
|
const tags = computed(() => {
|
||||||
const tagTheme = collection.value?.tagsTheme ?? 'colored'
|
const tagTheme = collection.value?.tagsTheme ?? 'colored'
|
||||||
|
|
||||||
return (props.post.tags ?? [])
|
return (post.tags ?? [])
|
||||||
.slice(0, 4)
|
.slice(0, 4)
|
||||||
.map(tag => ({
|
.map(tag => ({
|
||||||
name: tag,
|
name: tag,
|
||||||
@ -49,18 +49,18 @@ const tags = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const cover = computed<PostsCoverStyle | null>(() => {
|
const cover = computed<PostsCoverStyle | null>(() => {
|
||||||
if (!props.post.cover)
|
if (!post.cover)
|
||||||
return null
|
return null
|
||||||
const opt = collection.value?.postCover ?? 'right'
|
const opt = collection.value?.postCover ?? 'right'
|
||||||
const options = typeof opt === 'string' ? { layout: opt } : opt
|
const options = typeof opt === 'string' ? { layout: opt } : opt
|
||||||
return { layout: 'right', ratio: '4:3', ...options, ...props.post.coverStyle }
|
return { layout: 'right', ratio: '4:3', ...options, ...post.coverStyle }
|
||||||
})
|
})
|
||||||
|
|
||||||
const coverLayout = computed(() => {
|
const coverLayout = computed(() => {
|
||||||
if (isMobile.value)
|
if (isMobile.value)
|
||||||
return 'top'
|
return 'top'
|
||||||
const layout = cover.value?.layout ?? 'right'
|
const layout = cover.value?.layout ?? 'right'
|
||||||
const odd = (props.index + 1) % 2 === 1
|
const odd = (index + 1) % 2 === 1
|
||||||
if (layout === 'odd-left')
|
if (layout === 'odd-left')
|
||||||
return odd ? 'left' : 'right'
|
return odd ? 'left' : 'right'
|
||||||
if (layout === 'odd-right')
|
if (layout === 'odd-right')
|
||||||
@ -69,7 +69,7 @@ const coverLayout = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const coverCompact = computed(() => {
|
const coverCompact = computed(() => {
|
||||||
if (props.post.excerpt || coverLayout.value === 'top')
|
if (post.excerpt || coverLayout.value === 'top')
|
||||||
return false
|
return false
|
||||||
return cover.value?.compact ?? false
|
return cover.value?.compact ?? false
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import VPTransitionDrop from '@theme/VPTransitionDrop.vue'
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { usePostListControl } from '../../composables/index.js'
|
import { usePostListControl } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { homePosts } = defineProps<{
|
||||||
homePosts?: boolean
|
homePosts?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ const {
|
|||||||
isFirstPage,
|
isFirstPage,
|
||||||
isPaginationEnabled,
|
isPaginationEnabled,
|
||||||
changePage,
|
changePage,
|
||||||
} = usePostListControl(computed(() => !!props.homePosts))
|
} = usePostListControl(computed(() => !!homePosts))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import VPTransitionFadeSlideY from '@theme/VPTransitionFadeSlideY.vue'
|
|||||||
import { onBeforeUnmount, watch } from 'vue'
|
import { onBeforeUnmount, watch } from 'vue'
|
||||||
import { forceUpdateCollection, useData } from '../../composables/index.js'
|
import { forceUpdateCollection, useData } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { homePosts, collection } = defineProps<{
|
||||||
homePosts?: boolean
|
homePosts?: boolean
|
||||||
type?: string
|
type?: string
|
||||||
onlyOnce?: boolean
|
onlyOnce?: boolean
|
||||||
@ -20,8 +20,8 @@ const props = defineProps<{
|
|||||||
const { theme, page } = useData()
|
const { theme, page } = useData()
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => [props.homePosts, props.collection],
|
() => [homePosts, collection],
|
||||||
() => forceUpdateCollection(props.homePosts ? (props.collection || true) : undefined),
|
() => forceUpdateCollection(homePosts ? (collection || true) : undefined),
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import VPLink from '@theme/VPLink.vue'
|
|||||||
import { useRoute } from 'vuepress/client'
|
import { useRoute } from 'vuepress/client'
|
||||||
import { usePostsExtract } from '../../composables/index.js'
|
import { usePostsExtract } from '../../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { isLocal } = defineProps<{
|
||||||
isLocal?: boolean
|
isLocal?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ const { hasPostsExtract, tags, archives, categories } = usePostsExtract()
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="hasPostsExtract" class="vp-posts-nav" :class="{ local: props.isLocal }">
|
<div v-if="hasPostsExtract" class="vp-posts-nav" :class="{ local: isLocal }">
|
||||||
<VPLink
|
<VPLink
|
||||||
v-if="tags.link"
|
v-if="tags.link"
|
||||||
class="nav-link"
|
class="nav-link"
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import VPLink from '@theme/VPLink.vue'
|
import VPLink from '@theme/VPLink.vue'
|
||||||
|
|
||||||
defineProps<{
|
const { postList } = defineProps<{
|
||||||
postList: {
|
postList: {
|
||||||
title: string
|
title: string
|
||||||
path: string
|
path: string
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import '@vuepress/helper/transition/fade-in.css'
|
import '@vuepress/helper/transition/fade-in.css'
|
||||||
|
|
||||||
defineProps<{
|
const { show } = defineProps<{
|
||||||
show: boolean
|
show: boolean
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { useRoute } from 'vuepress/client'
|
|||||||
import { useData, usePostsPageData, useSidebar } from '../composables/index.js'
|
import { useData, usePostsPageData, useSidebar } from '../composables/index.js'
|
||||||
import { inBrowser } from '../utils/index.js'
|
import { inBrowser } from '../utils/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { isNotFound } = defineProps<{
|
||||||
isNotFound?: boolean
|
isNotFound?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ watch(
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
id="VPContent" vp-content class="vp-content" :class="{
|
id="VPContent" vp-content class="vp-content" :class="{
|
||||||
'has-sidebar': hasSidebar && !props.isNotFound,
|
'has-sidebar': hasSidebar && !isNotFound,
|
||||||
'is-home': frontmatter.pageLayout === 'home',
|
'is-home': frontmatter.pageLayout === 'home',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useData } from '../composables/index.js'
|
import { useData } from '../composables/index.js'
|
||||||
|
|
||||||
defineProps<{
|
const { title, anchor } = defineProps<{
|
||||||
title?: string
|
title?: string
|
||||||
anchor: string
|
anchor: string
|
||||||
}>()
|
}>()
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { MenuItem } from '../composables/index.js'
|
import type { MenuItem } from '../composables/index.js'
|
||||||
|
|
||||||
defineProps<{
|
const { headers, root } = defineProps<{
|
||||||
headers: MenuItem[]
|
headers: MenuItem[]
|
||||||
root?: boolean
|
root?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useData, useEncryptCompare } from '../composables/index.js'
|
import { useData, useEncryptCompare } from '../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { global, info } = defineProps<{
|
||||||
global?: boolean
|
global?: boolean
|
||||||
info?: string
|
info?: string
|
||||||
}>()
|
}>()
|
||||||
@ -18,7 +18,7 @@ async function onSubmit() {
|
|||||||
if (unlocking.value)
|
if (unlocking.value)
|
||||||
return
|
return
|
||||||
|
|
||||||
const compare = props.global ? compareGlobal : comparePage
|
const compare = global ? compareGlobal : comparePage
|
||||||
unlocking.value = true
|
unlocking.value = true
|
||||||
const result = await compare(password.value)
|
const result = await compare(password.value)
|
||||||
unlocking.value = false
|
unlocking.value = false
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import VPMenu from '@theme/VPMenu.vue'
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useFlyout } from '../composables/index.js'
|
import { useFlyout } from '../composables/index.js'
|
||||||
|
|
||||||
defineProps<{
|
const { prefixIcon, icon, button, label, items, badge } = defineProps<{
|
||||||
prefixIcon?: ThemeIcon
|
prefixIcon?: ThemeIcon
|
||||||
icon?: any
|
icon?: any
|
||||||
button?: string
|
button?: string
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import type { FriendGroup } from '../../shared/index.js'
|
import type { FriendGroup } from '../../shared/index.js'
|
||||||
import VPFriendsItem from '@theme/VPFriendsItem.vue'
|
import VPFriendsItem from '@theme/VPFriendsItem.vue'
|
||||||
|
|
||||||
defineProps<{
|
const { group } = defineProps<{
|
||||||
group: FriendGroup
|
group: FriendGroup
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { computed } from 'vue'
|
|||||||
import { useDarkMode } from '../composables/index.js'
|
import { useDarkMode } from '../composables/index.js'
|
||||||
import VPSocialLinks from './VPSocialLinks.vue'
|
import VPSocialLinks from './VPSocialLinks.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { friend } = defineProps<{
|
||||||
friend: FriendsItem
|
friend: FriendsItem
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@ -21,9 +21,9 @@ function getStyle(name: string, color?: string | { light: string, dark: string }
|
|||||||
|
|
||||||
const friendStyle = computed(() => {
|
const friendStyle = computed(() => {
|
||||||
return {
|
return {
|
||||||
...getStyle('--vp-friends-text-color', props.friend.color),
|
...getStyle('--vp-friends-text-color', friend.color),
|
||||||
...getStyle('--vp-friends-bg-color', props.friend.backgroundColor),
|
...getStyle('--vp-friends-bg-color', friend.backgroundColor),
|
||||||
...getStyle('--vp-friends-name-color', props.friend.nameColor),
|
...getStyle('--vp-friends-name-color', friend.nameColor),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import VPIconImage from '@theme/VPIconImage.vue'
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { isLinkHttp } from 'vuepress/shared'
|
import { isLinkHttp } from 'vuepress/shared'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { provider, name, size, color, extra } = defineProps<{
|
||||||
provider?: 'iconify' | 'iconfont' | 'fontawesome'
|
provider?: 'iconify' | 'iconfont' | 'fontawesome'
|
||||||
name: string | { svg: string }
|
name: string | { svg: string }
|
||||||
size?: string | number
|
size?: string | number
|
||||||
@ -18,20 +18,20 @@ declare const __MD_POWER_ICON_PROVIDER__: 'iconify' | 'iconfont' | 'fontawesome'
|
|||||||
declare const __MD_POWER_ICON_PREFIX__: string
|
declare const __MD_POWER_ICON_PREFIX__: string
|
||||||
|
|
||||||
const type = computed(() => {
|
const type = computed(() => {
|
||||||
const provider = props.provider || __MD_POWER_ICON_PROVIDER__
|
|
||||||
// name -> https://example.com/icon.svg
|
// name -> https://example.com/icon.svg
|
||||||
// name -> /icon.svg
|
// name -> /icon.svg
|
||||||
if (typeof props.name === 'string' && (isLinkHttp(props.name) || props.name[0] === '/')) {
|
if (typeof name === 'string' && (isLinkHttp(name) || name[0] === '/')) {
|
||||||
return 'link'
|
return 'link'
|
||||||
}
|
}
|
||||||
|
|
||||||
// name -> { svg: '<svg></svg>' }
|
// name -> { svg: '<svg></svg>' }
|
||||||
if (typeof props.name === 'object' && !!props.name.svg) {
|
if (typeof name === 'object' && !!name.svg) {
|
||||||
return 'svg'
|
return 'svg'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (provider === 'iconfont' || provider === 'fontawesome') {
|
const _provider = provider || __MD_POWER_ICON_PROVIDER__
|
||||||
return provider
|
if (_provider === 'iconfont' || _provider === 'fontawesome') {
|
||||||
|
return _provider
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'iconify'
|
return 'iconify'
|
||||||
@ -43,8 +43,7 @@ function parseSize(size: string | number): string {
|
|||||||
return String(size)
|
return String(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
const size = computed(() => {
|
const rect = computed(() => {
|
||||||
const size = props.size
|
|
||||||
if (!size)
|
if (!size)
|
||||||
return undefined
|
return undefined
|
||||||
|
|
||||||
@ -56,9 +55,9 @@ const size = computed(() => {
|
|||||||
return { width, height: height || width }
|
return { width, height: height || width }
|
||||||
})
|
})
|
||||||
const binding = computed(() => ({
|
const binding = computed(() => ({
|
||||||
name: props.name as string,
|
name: name as string,
|
||||||
color: props.color,
|
color,
|
||||||
size: size.value,
|
size: rect.value,
|
||||||
prefix: __MD_POWER_ICON_PREFIX__ as any,
|
prefix: __MD_POWER_ICON_PREFIX__ as any,
|
||||||
}))
|
}))
|
||||||
</script>
|
</script>
|
||||||
@ -66,7 +65,7 @@ const binding = computed(() => ({
|
|||||||
<template>
|
<template>
|
||||||
<VPIconImage
|
<VPIconImage
|
||||||
v-if="type === 'link' || type === 'svg'"
|
v-if="type === 'link' || type === 'svg'"
|
||||||
:type="type" :name="name" :color="color" :size="size"
|
:type="type" :name="name" :color="color" :size="rect"
|
||||||
/>
|
/>
|
||||||
<VPIconfont
|
<VPIconfont
|
||||||
v-else-if="type === 'iconfont'"
|
v-else-if="type === 'iconfont'"
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import type { FontAwesomePrefix } from 'vuepress-plugin-md-power/client'
|
import type { FontAwesomePrefix } from 'vuepress-plugin-md-power/client'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { name, size, color, prefix, extra } = defineProps<{
|
||||||
name: string
|
name: string
|
||||||
size?: { width?: string, height?: string }
|
size?: { width?: string, height?: string }
|
||||||
color?: string
|
color?: string
|
||||||
@ -25,20 +25,19 @@ const configs: Record<string, FontAwesomePrefix[]> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const iconName = computed(() => {
|
const iconName = computed(() => {
|
||||||
const icon = props.name.includes(':') ? props.name : `${props.prefix || 'fas'}:${props.name}`
|
const icon = name.includes(':') ? name : `${prefix || 'fas'}:${name}`
|
||||||
const [type, name] = icon.split(':')
|
const [type, iconName] = icon.split(':')
|
||||||
let prefix = 'solid'
|
let _prefix = 'solid'
|
||||||
for (const [key, alias] of Object.entries(configs)) {
|
for (const [key, alias] of Object.entries(configs)) {
|
||||||
if (alias.includes(type as FontAwesomePrefix)) {
|
if (alias.includes(type as FontAwesomePrefix)) {
|
||||||
prefix = key
|
_prefix = key
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return `${prefix.split(' ').map(v => `fa-${v.trim()}`).join(' ')} fa-${name}`
|
return `${_prefix.split(' ').map(v => `fa-${v.trim()}`).join(' ')} fa-${iconName}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const extraClasses = computed(() => {
|
const extraClasses = computed(() => {
|
||||||
const extra = props.extra
|
|
||||||
if (!extra)
|
if (!extra)
|
||||||
return []
|
return []
|
||||||
return extra.split(' ').map(v => v.trim().startsWith('fa-') ? v : `fa-${v}`)
|
return extra.split(' ').map(v => v.trim().startsWith('fa-') ? v : `fa-${v}`)
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { computed } from 'vue'
|
|||||||
import { withBase } from 'vuepress/client'
|
import { withBase } from 'vuepress/client'
|
||||||
import { isLinkHttp } from 'vuepress/shared'
|
import { isLinkHttp } from 'vuepress/shared'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { type, name, color, size } = defineProps<{
|
||||||
type: 'link' | 'svg'
|
type: 'link' | 'svg'
|
||||||
name: string | { svg: string }
|
name: string | { svg: string }
|
||||||
color?: string
|
color?: string
|
||||||
@ -11,14 +11,14 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const svg = computed(() => {
|
const svg = computed(() => {
|
||||||
if (props.type === 'svg' && typeof props.name === 'object' && 'svg' in props.name) {
|
if (type === 'svg' && typeof name === 'object' && 'svg' in name) {
|
||||||
return props.name.svg
|
return name.svg
|
||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
})
|
})
|
||||||
const link = computed(() => {
|
const link = computed(() => {
|
||||||
if (props.type === 'link') {
|
if (type === 'link') {
|
||||||
const link = props.name as string
|
const link = name as string
|
||||||
return isLinkHttp(link) ? link : withBase(link)
|
return isLinkHttp(link) ? link : withBase(link)
|
||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
|
|||||||
@ -1,20 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
const { name, size, color, prefix } = defineProps<{
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
name: string
|
name: string
|
||||||
size?: { width?: string, height?: string }
|
size?: { width?: string, height?: string }
|
||||||
color?: string
|
color?: string
|
||||||
prefix?: string
|
prefix?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const prefix = computed(() => props.prefix || 'iconfont icon-')
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<i
|
<i
|
||||||
class="vp-icon"
|
class="vp-icon"
|
||||||
:class="`${prefix}${name}`"
|
:class="`${prefix || 'iconfont icon-'}${name}`"
|
||||||
:style="{ color, 'font-size': size?.height || '1em' }"
|
:style="{ color, 'font-size': size?.height || '1em' }"
|
||||||
data-provider="iconfont"
|
data-provider="iconfont"
|
||||||
aria-hidden
|
aria-hidden
|
||||||
|
|||||||
@ -9,7 +9,7 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const props = defineProps<{
|
const { name, size, color, prefix, extra } = defineProps<{
|
||||||
name: string
|
name: string
|
||||||
size?: { width?: string, height?: string }
|
size?: { width?: string, height?: string }
|
||||||
color?: string
|
color?: string
|
||||||
@ -23,10 +23,9 @@ const loaded = ref(false)
|
|||||||
const iconsData = useIconsData()
|
const iconsData = useIconsData()
|
||||||
|
|
||||||
const iconName = computed(() => {
|
const iconName = computed(() => {
|
||||||
const name = props.name
|
|
||||||
if (name.includes(':'))
|
if (name.includes(':'))
|
||||||
return name
|
return name
|
||||||
return props.prefix ? `${props.prefix}:${name}` : name
|
return prefix ? `${prefix}:${name}` : name
|
||||||
})
|
})
|
||||||
|
|
||||||
const localIconName = computed(() => iconsData.value[iconName.value])
|
const localIconName = computed(() => iconsData.value[iconName.value])
|
||||||
@ -37,13 +36,13 @@ async function loadRemoteIcon() {
|
|||||||
|
|
||||||
if (!localIconName.value) {
|
if (!localIconName.value) {
|
||||||
loaded.value = false
|
loaded.value = false
|
||||||
icon.value = await loadIcon(props.name)
|
icon.value = await loadIcon(name)
|
||||||
}
|
}
|
||||||
loaded.value = true
|
loaded.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!__VUEPRESS_SSR__)
|
if (!__VUEPRESS_SSR__)
|
||||||
watch(() => props.name, loadRemoteIcon, { immediate: true })
|
watch(() => name, loadRemoteIcon, { immediate: true })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@ -4,13 +4,12 @@ import { computed } from 'vue'
|
|||||||
import { withBase } from 'vuepress/client'
|
import { withBase } from 'vuepress/client'
|
||||||
import { numToUnit } from '../utils/index.js'
|
import { numToUnit } from '../utils/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { image, alt } = defineProps<{
|
||||||
image: ThemeImage
|
image: ThemeImage
|
||||||
alt?: string
|
alt?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const styles = computed(() => {
|
const styles = computed(() => {
|
||||||
const image = props.image
|
|
||||||
if (!image || typeof image === 'string')
|
if (!image || typeof image === 'string')
|
||||||
return ''
|
return ''
|
||||||
if (!image.width || !image.height)
|
if (!image.width || !image.height)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useWindowScroll } from '@vueuse/core'
|
|||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { useData, useHeaders, usePostsPageData, useSidebar } from '../composables/index.js'
|
import { useData, useHeaders, usePostsPageData, useSidebar } from '../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { open, showOutline } = defineProps<{
|
||||||
open: boolean
|
open: boolean
|
||||||
showOutline: boolean
|
showOutline: boolean
|
||||||
}>()
|
}>()
|
||||||
@ -39,7 +39,7 @@ const classes = computed(() => {
|
|||||||
'fixed': empty.value,
|
'fixed': empty.value,
|
||||||
'reached-top': y.value >= navHeight.value,
|
'reached-top': y.value >= navHeight.value,
|
||||||
'is-posts': isPosts.value && !isPostsLayout.value,
|
'is-posts': isPosts.value && !isPostsLayout.value,
|
||||||
'with-outline': !props.showOutline,
|
'with-outline': !showOutline,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { useData } from '../composables/index.js'
|
|||||||
|
|
||||||
import '@vuepress/helper/transition/fade-in-scale-up.css'
|
import '@vuepress/helper/transition/fade-in-scale-up.css'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { headers, navHeight } = defineProps<{
|
||||||
headers: MenuItem[]
|
headers: MenuItem[]
|
||||||
navHeight: number
|
navHeight: number
|
||||||
}>()
|
}>()
|
||||||
@ -18,7 +18,7 @@ const vh = ref(0)
|
|||||||
const items = ref<HTMLDivElement>()
|
const items = ref<HTMLDivElement>()
|
||||||
const btn = ref<HTMLButtonElement>()
|
const btn = ref<HTMLButtonElement>()
|
||||||
|
|
||||||
watch(() => props.headers, () => {
|
watch(() => headers, () => {
|
||||||
open.value = false
|
open.value = false
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ onClickOutside(items, () => {
|
|||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
open.value = !open.value
|
open.value = !open.value
|
||||||
vh.value = window.innerHeight + Math.min(window.scrollY - props.navHeight, 0)
|
vh.value = window.innerHeight + Math.min(window.scrollY - navHeight, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onItemClick(e: Event) {
|
function onItemClick(e: Event) {
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import VPMenuGroup from '@theme/VPMenuGroup.vue'
|
import VPMenuGroup from '@theme/VPMenuGroup.vue'
|
||||||
import VPMenuLink from '@theme/VPMenuLink.vue'
|
import VPMenuLink from '@theme/VPMenuLink.vue'
|
||||||
|
|
||||||
defineProps<{
|
const { items } = defineProps<{
|
||||||
items?: any[]
|
items?: any[]
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import VPIcon from '@theme/VPIcon.vue'
|
import VPIcon from '@theme/VPIcon.vue'
|
||||||
import VPMenuLink from '@theme/VPMenuLink.vue'
|
import VPMenuLink from '@theme/VPMenuLink.vue'
|
||||||
|
|
||||||
defineProps<{
|
const { text, icon, items } = defineProps<{
|
||||||
text?: string
|
text?: string
|
||||||
icon?: string | { svg: string }
|
icon?: string | { svg: string }
|
||||||
items: any[]
|
items: any[]
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { resolveRouteFullPath } from 'vuepress/client'
|
|||||||
import { useData } from '../composables/index.js'
|
import { useData } from '../composables/index.js'
|
||||||
import { isActive } from '../utils/index.js'
|
import { isActive } from '../utils/index.js'
|
||||||
|
|
||||||
defineProps<{
|
const { item } = defineProps<{
|
||||||
item: any
|
item: any
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { useRoutePath } from 'vuepress/client'
|
|||||||
import { useData, useSidebar } from '../composables/index.js'
|
import { useData, useSidebar } from '../composables/index.js'
|
||||||
import { inBrowser } from '../utils/index.js'
|
import { inBrowser } from '../utils/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { open } = defineProps<{
|
||||||
open: boolean
|
open: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@ -20,9 +20,9 @@ const navEl = ref<HTMLElement | null>(null)
|
|||||||
const isLocked = useScrollLock(inBrowser ? document.body : null)
|
const isLocked = useScrollLock(inBrowser ? document.body : null)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
[() => props.open, navEl],
|
[() => open, navEl],
|
||||||
() => {
|
() => {
|
||||||
if (props.open) {
|
if (open) {
|
||||||
isLocked.value = true
|
isLocked.value = true
|
||||||
navEl.value?.focus()
|
navEl.value?.focus()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import type { ResolvedSidebarItem } from '../../shared/index.js'
|
|||||||
import VPSidebarItem from '@theme/VPSidebarItem.vue'
|
import VPSidebarItem from '@theme/VPSidebarItem.vue'
|
||||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
|
|
||||||
defineProps<{
|
const { items } = defineProps<{
|
||||||
items: ResolvedSidebarItem[]
|
items: ResolvedSidebarItem[]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { useSidebarControl } from '../composables/index.js'
|
|||||||
|
|
||||||
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
import '@vuepress/helper/transition/fade-in-height-expand.css'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { item, depth } = defineProps<{
|
||||||
item: ResolvedSidebarItem
|
item: ResolvedSidebarItem
|
||||||
depth: number
|
depth: number
|
||||||
}>()
|
}>()
|
||||||
@ -22,7 +22,7 @@ const {
|
|||||||
hasActiveLink,
|
hasActiveLink,
|
||||||
hasChildren,
|
hasChildren,
|
||||||
toggle,
|
toggle,
|
||||||
} = useSidebarControl(computed(() => props.item))
|
} = useSidebarControl(computed(() => item))
|
||||||
|
|
||||||
const sectionTag = computed(() => (hasChildren.value ? 'section' : `div`))
|
const sectionTag = computed(() => (hasChildren.value ? 'section' : `div`))
|
||||||
|
|
||||||
@ -31,17 +31,17 @@ const linkTag = computed(() => (isLink.value ? 'a' : 'div'))
|
|||||||
const textTag = computed(() => {
|
const textTag = computed(() => {
|
||||||
return !hasChildren.value
|
return !hasChildren.value
|
||||||
? 'p'
|
? 'p'
|
||||||
: props.depth + 2 === 7
|
: depth + 2 === 7
|
||||||
? 'p'
|
? 'p'
|
||||||
: `h${props.depth + 2}`
|
: `h${depth + 2}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const itemRole = computed(() => (isLink.value ? undefined : 'button'))
|
const itemRole = computed(() => (isLink.value ? undefined : 'button'))
|
||||||
|
|
||||||
const isSeparator = computed(() => props.item.link?.startsWith('---'))
|
const isSeparator = computed(() => item.link?.startsWith('---'))
|
||||||
|
|
||||||
const classes = computed(() => [
|
const classes = computed(() => [
|
||||||
[`level-${props.depth}`],
|
[`level-${depth}`],
|
||||||
{ collapsible: collapsible.value },
|
{ collapsible: collapsible.value },
|
||||||
{ collapsed: collapsed.value },
|
{ collapsed: collapsed.value },
|
||||||
{ 'is-link': isLink.value },
|
{ 'is-link': isLink.value },
|
||||||
@ -53,13 +53,13 @@ function onItemInteraction(e: MouseEvent | Event) {
|
|||||||
if ('key' in e && e.key !== 'Enter')
|
if ('key' in e && e.key !== 'Enter')
|
||||||
return
|
return
|
||||||
|
|
||||||
if (!props.item.link) {
|
if (!item.link) {
|
||||||
toggle()
|
toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCaretClick() {
|
function onCaretClick() {
|
||||||
if (props.item.link) {
|
if (item.link) {
|
||||||
toggle()
|
toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,16 +2,16 @@
|
|||||||
import type { SocialLinkIcon } from '../../shared/index.js'
|
import type { SocialLinkIcon } from '../../shared/index.js'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { icon, link, ariaLabel } = defineProps<{
|
||||||
icon: SocialLinkIcon
|
icon: SocialLinkIcon
|
||||||
link: string
|
link: string
|
||||||
ariaLabel?: string
|
ariaLabel?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const svg = computed(() => {
|
const svg = computed(() => {
|
||||||
if (typeof props.icon === 'object')
|
if (typeof icon === 'object')
|
||||||
return props.icon.svg
|
return icon.svg
|
||||||
return `<span class="vpi-social-${props.icon}" />`
|
return `<span class="vpi-social-${icon}" />`
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import type { SocialLink as SocialLinkType } from '../../shared/index.js'
|
import type { SocialLink as SocialLinkType } from '../../shared/index.js'
|
||||||
import VPSocialLink from '@theme/VPSocialLink.vue'
|
import VPSocialLink from '@theme/VPSocialLink.vue'
|
||||||
|
|
||||||
defineProps<{
|
const { links } = defineProps<{
|
||||||
links: SocialLinkType[]
|
links: SocialLinkType[]
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -7,10 +7,7 @@ interface Props {
|
|||||||
duration?: number
|
duration?: number
|
||||||
appear?: boolean
|
appear?: boolean
|
||||||
}
|
}
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const { delay = 0, duration = 0.25, appear } = defineProps<Props>()
|
||||||
delay: 0,
|
|
||||||
duration: 0.25,
|
|
||||||
})
|
|
||||||
|
|
||||||
const { theme } = useData()
|
const { theme } = useData()
|
||||||
|
|
||||||
@ -36,7 +33,7 @@ function setStyle(item: Element) {
|
|||||||
_transition = value && !value.includes('all') ? `${value || ''}, ` : ' '
|
_transition = value && !value.includes('all') ? `${value || ''}, ` : ' '
|
||||||
}
|
}
|
||||||
|
|
||||||
el.style.transition = `${_transition}transform ${props.duration}s ease-in-out ${props.delay}s, opacity ${props.duration}s ease-in-out ${props.delay}s`
|
el.style.transition = `${_transition}transform ${duration}s ease-in-out ${delay}s, opacity ${duration}s ease-in-out ${delay}s`
|
||||||
}
|
}
|
||||||
|
|
||||||
function unsetStyle(item: Element) {
|
function unsetStyle(item: Element) {
|
||||||
|
|||||||
@ -2,17 +2,14 @@
|
|||||||
import type { ThemeBadge } from '../../../shared/index.js'
|
import type { ThemeBadge } from '../../../shared/index.js'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<ThemeBadge>(), {
|
const { type = 'tip', text, color, bgColor, borderColor = 'transparent' } = defineProps<ThemeBadge>()
|
||||||
type: 'tip',
|
|
||||||
borderColor: 'transparent',
|
|
||||||
})
|
|
||||||
|
|
||||||
const customStyle = computed(() => {
|
const customStyle = computed(() => {
|
||||||
if (props.color || props.bgColor) {
|
if (color || bgColor) {
|
||||||
return {
|
return {
|
||||||
color: props.color,
|
color,
|
||||||
backgroundColor: props.bgColor,
|
backgroundColor: bgColor,
|
||||||
borderColor: props.borderColor,
|
borderColor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
|
|||||||
@ -2,19 +2,19 @@
|
|||||||
import VPIcon from '@theme/VPIcon.vue'
|
import VPIcon from '@theme/VPIcon.vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { title, icon = '' } = defineProps<{
|
||||||
title?: string
|
title?: string
|
||||||
icon?: string | { svg: string }
|
icon?: string | { svg: string }
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const icon = computed<string | { svg: string } | undefined>(() => {
|
const iconName = computed<string | { svg: string }>(() => {
|
||||||
if (props.icon?.[0] === '{') {
|
if (typeof icon === 'string' && icon?.[0] === '{') {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(icon) as { svg: string }
|
return JSON.parse(icon) as { svg: string }
|
||||||
}
|
}
|
||||||
catch {}
|
catch {}
|
||||||
}
|
}
|
||||||
return props.icon
|
return icon
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ const icon = computed<string | { svg: string } | undefined>(() => {
|
|||||||
<article class="vp-card-wrapper">
|
<article class="vp-card-wrapper">
|
||||||
<slot name="title">
|
<slot name="title">
|
||||||
<p v-if="title || icon" class="title">
|
<p v-if="title || icon" class="title">
|
||||||
<VPIcon v-if="icon" :name="icon" />
|
<VPIcon v-if="icon" :name="iconName" />
|
||||||
<span v-if="title" class="text" v-html="title" />
|
<span v-if="title" class="text" v-html="title" />
|
||||||
</p>
|
</p>
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import { useMediaQuery } from '@vueuse/core'
|
import { useMediaQuery } from '@vueuse/core'
|
||||||
import { onMounted, ref, toValue, watch } from 'vue'
|
import { onMounted, ref, toValue, watch } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { cols } = defineProps<{
|
||||||
cols?: string | number | { sm?: number, md?: number, lg?: number }
|
cols?: string | number | { sm?: number, md?: number, lg?: number }
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@ -12,13 +12,13 @@ const repeat = ref(1)
|
|||||||
|
|
||||||
function resolveCols() {
|
function resolveCols() {
|
||||||
const reset = { sm: 1, md: 2, lg: 2 }
|
const reset = { sm: 1, md: 2, lg: 2 }
|
||||||
if (!props.cols)
|
if (!cols)
|
||||||
return reset
|
return reset
|
||||||
if (typeof props.cols === 'number' || typeof props.cols === 'string') {
|
if (typeof cols === 'number' || typeof cols === 'string') {
|
||||||
const cols = Number(props.cols)
|
const res = Number(cols)
|
||||||
return { sm: cols, md: cols, lg: cols }
|
return { sm: res, md: res, lg: res }
|
||||||
}
|
}
|
||||||
return { ...reset, ...toValue(props.cols) }
|
return { ...reset, ...toValue(cols) }
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRepeat() {
|
function getRepeat() {
|
||||||
@ -30,7 +30,7 @@ function getRepeat() {
|
|||||||
return cols.sm
|
return cols.sm
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => [md.value, lg.value, props.cols], () => {
|
watch([md, lg, () => cols], () => {
|
||||||
repeat.value = getRepeat()
|
repeat.value = getRepeat()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,10 @@ import type { VNode } from 'vue'
|
|||||||
import { useDebounceFn, useMediaQuery, useResizeObserver } from '@vueuse/core'
|
import { useDebounceFn, useMediaQuery, useResizeObserver } from '@vueuse/core'
|
||||||
import { cloneVNode, computed, markRaw, mergeProps, nextTick, onMounted, ref, shallowRef, useId, watch } from 'vue'
|
import { cloneVNode, computed, markRaw, mergeProps, nextTick, onMounted, ref, shallowRef, useId, watch } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const { cols = { sm: 2, md: 2, lg: 3 }, gap = 16 } = defineProps<{
|
||||||
cols?: number | { sm?: number, md?: number, lg?: number }
|
cols?: number | { sm?: number, md?: number, lg?: number }
|
||||||
gap?: number
|
gap?: number
|
||||||
}>(), {
|
}>()
|
||||||
cols: () => ({ sm: 2, md: 2, lg: 3 }),
|
|
||||||
gap: 16,
|
|
||||||
})
|
|
||||||
|
|
||||||
const slots = defineSlots<{ default: () => VNode[] | null }>()
|
const slots = defineSlots<{ default: () => VNode[] | null }>()
|
||||||
const uuid = useId()
|
const uuid = useId()
|
||||||
@ -29,16 +26,16 @@ const rawList = computed(() => {
|
|||||||
|
|
||||||
function resolveColumnsLength() {
|
function resolveColumnsLength() {
|
||||||
let length = 1
|
let length = 1
|
||||||
if (typeof props.cols === 'number') {
|
if (typeof cols === 'number') {
|
||||||
length = props.cols
|
length = cols
|
||||||
}
|
}
|
||||||
else if (typeof props.cols === 'object') {
|
else if (typeof cols === 'object') {
|
||||||
if (isLg.value)
|
if (isLg.value)
|
||||||
length = props.cols.lg || 3
|
length = cols.lg || 3
|
||||||
else if (isMd.value)
|
else if (isMd.value)
|
||||||
length = props.cols.md || 2
|
length = cols.md || 2
|
||||||
else
|
else
|
||||||
length = props.cols.sm || 2
|
length = cols.sm || 2
|
||||||
}
|
}
|
||||||
|
|
||||||
columnsLength.value = Number(length)
|
columnsLength.value = Number(length)
|
||||||
@ -62,7 +59,7 @@ async function drawColumns() {
|
|||||||
const index = heights.indexOf(Math.min(...heights))
|
const index = heights.indexOf(Math.min(...heights))
|
||||||
|
|
||||||
columns[index].push(item)
|
columns[index].push(item)
|
||||||
heights[index] += height + props.gap
|
heights[index] += height + gap
|
||||||
}
|
}
|
||||||
columnsList.value = columns
|
columnsList.value = columns
|
||||||
}
|
}
|
||||||
@ -71,7 +68,7 @@ onMounted(() => {
|
|||||||
if (__VUEPRESS_SSR__)
|
if (__VUEPRESS_SSR__)
|
||||||
return
|
return
|
||||||
|
|
||||||
watch(() => [isMd.value, isLg.value, props.cols], resolveColumnsLength, { immediate: true })
|
watch([isMd, isLg, () => cols], resolveColumnsLength, { immediate: true })
|
||||||
|
|
||||||
drawColumns()
|
drawColumns()
|
||||||
const debounceDraw = useDebounceFn(drawColumns)
|
const debounceDraw = useDebounceFn(drawColumns)
|
||||||
@ -81,9 +78,9 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="masonry" class="vp-card-masonry" :class="[`cols-${columnsLength}`]" :style="{ 'grid-gap': `${props.gap}px`, '--card-masonry-cols': columnsLength }" data-allow-mismatch>
|
<div ref="masonry" class="vp-card-masonry" :class="[`cols-${columnsLength}`]" :style="{ 'grid-gap': `${gap}px`, '--card-masonry-cols': columnsLength }" data-allow-mismatch>
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<div v-for="(column, index) in columnsList" :key="`${uuid}-${index}`" class="card-masonry-item" :style="{ gap: `${props.gap}px` }">
|
<div v-for="(column, index) in columnsList" :key="`${uuid}-${index}`" class="card-masonry-item" :style="{ gap: `${gap}px` }">
|
||||||
<component :is="item" v-for="item in column" :key="item.props!.class" />
|
<component :is="item" v-for="item in column" :key="item.props!.class" />
|
||||||
</div>
|
</div>
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { usePageLang, withBase } from 'vuepress/client'
|
import { usePageLang, withBase } from 'vuepress/client'
|
||||||
|
|
||||||
const props = defineProps<{
|
const { image, title, description, href, author, date, width, center } = defineProps<{
|
||||||
image: string
|
image: string
|
||||||
title?: string
|
title?: string
|
||||||
description?: string
|
description?: string
|
||||||
@ -15,42 +15,40 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const lang = usePageLang()
|
const lang = usePageLang()
|
||||||
|
|
||||||
const date = computed(() => {
|
const dateStr = computed(() => {
|
||||||
if (!props.date)
|
if (!date)
|
||||||
return ''
|
return ''
|
||||||
const date = props.date instanceof Date ? props.date : new Date(props.date)
|
const instance = date instanceof Date ? date : new Date(date)
|
||||||
const intl = new Intl.DateTimeFormat(
|
const intl = new Intl.DateTimeFormat(
|
||||||
lang.value,
|
lang.value,
|
||||||
{ year: 'numeric', month: 'short', day: 'numeric' },
|
{ year: 'numeric', month: 'short', day: 'numeric' },
|
||||||
)
|
)
|
||||||
|
|
||||||
return intl.format(date)
|
return intl.format(instance)
|
||||||
})
|
})
|
||||||
|
|
||||||
const styles = computed(() => {
|
const styles = computed(() => ({
|
||||||
const width = props.width
|
width: width
|
||||||
? String(Number(props.width)) === String(props.width)
|
? String(Number(width)) === String(width)
|
||||||
? `${props.width}px`
|
? `${width}px`
|
||||||
: props.width
|
: width
|
||||||
: undefined
|
: undefined,
|
||||||
|
}))
|
||||||
return { width }
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="vp-image-card" :style="styles" :class="{ center }">
|
<div class="vp-image-card" :style="styles" :class="{ center }">
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
<img :src="withBase(image)" :alt="title" loading="lazy">
|
<img :src="withBase(image)" :alt="title" loading="lazy">
|
||||||
<div v-if="title || author || date || description" class="image-info">
|
<div v-if="title || author || dateStr || description" class="image-info">
|
||||||
<h3 v-if="title" class="title">
|
<h3 v-if="title" class="title">
|
||||||
<a v-if="href" :href="href" target="_blank" rel="noopener noreferrer" class="no-icon">{{ title }}</a>
|
<a v-if="href" :href="href" target="_blank" rel="noopener noreferrer" class="no-icon">{{ title }}</a>
|
||||||
<span v-else>{{ title }}</span>
|
<span v-else>{{ title }}</span>
|
||||||
</h3>
|
</h3>
|
||||||
<p v-if="author || date" class="copyright">
|
<p v-if="author || date" class="copyright">
|
||||||
<span v-if="author">{{ author }}</span>
|
<span v-if="author">{{ author }}</span>
|
||||||
<span v-if="author && date"> | </span>
|
<span v-if="author && dateStr"> | </span>
|
||||||
<span v-if="date">{{ date }}</span>
|
<span v-if="dateStr">{{ dateStr }}</span>
|
||||||
</p>
|
</p>
|
||||||
<p v-if="description" class="description">
|
<p v-if="description" class="description">
|
||||||
{{ description }}
|
{{ description }}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import VPIcon from '@theme/VPIcon.vue'
|
import VPIcon from '@theme/VPIcon.vue'
|
||||||
import VPLink from '@theme/VPLink.vue'
|
import VPLink from '@theme/VPLink.vue'
|
||||||
|
|
||||||
defineProps<{
|
const { href, title, icon, description, target, rel } = defineProps<{
|
||||||
href: string
|
href: string
|
||||||
title?: string
|
title?: string
|
||||||
icon?: string | { svg: string }
|
icon?: string | { svg: string }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user