2019-09-17 19:28:28 +08:00
|
|
|
<template>
|
2021-04-05 17:59:04 +08:00
|
|
|
<n-layout-header bordered class="nav" :style="style">
|
|
|
|
<n-text tag="div" class="ui-logo" :depth="1" @click="handleLogoClick">
|
|
|
|
<img src="./assets/images/naivelogo.svg" />
|
|
|
|
<span v-if="!isMobile">Naive UI</span>
|
|
|
|
</n-text>
|
|
|
|
<div :style="!isMobile ? 'display: flex; align-items: center;' : ''">
|
|
|
|
<div class="nav-menu" v-if="!isMobile">
|
|
|
|
<n-menu
|
|
|
|
mode="horizontal"
|
|
|
|
:value="menuValue"
|
|
|
|
:options="menuOptions"
|
|
|
|
@update:value="handleMenuUpdateValue"
|
2020-03-03 19:25:25 +08:00
|
|
|
/>
|
|
|
|
</div>
|
2021-04-05 17:59:04 +08:00
|
|
|
<n-auto-complete
|
|
|
|
v-model:value="searchPattern"
|
|
|
|
:style="!isMobile ? 'width: 216px; margin-left: 24px' : undefined"
|
|
|
|
:placeholder="t('searchPlaceholder')"
|
|
|
|
:options="searchOptions"
|
|
|
|
clear-after-select
|
|
|
|
blur-after-select
|
|
|
|
@select="handleSearch"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div style="display: flex" v-if="!isMobile">
|
|
|
|
<n-button size="small" class="nav-picker" @click="handleThemeUpdate">
|
|
|
|
{{ themeLabelMap[theme] }}
|
|
|
|
</n-button>
|
|
|
|
<n-popselect
|
|
|
|
:options="localeOptions"
|
|
|
|
v-model:value="locale"
|
|
|
|
overlap
|
|
|
|
placement="top"
|
|
|
|
trigger="click"
|
|
|
|
>
|
|
|
|
<n-button size="small" class="nav-picker">
|
|
|
|
{{ localeLabelMap[locale] }}
|
2020-11-23 02:22:41 +08:00
|
|
|
</n-button>
|
2021-04-05 17:59:04 +08:00
|
|
|
</n-popselect>
|
|
|
|
<n-popselect
|
|
|
|
v-if="tusimple || dev"
|
|
|
|
:options="configProviderOptions"
|
|
|
|
v-model:value="configProviderName"
|
|
|
|
overlap
|
|
|
|
placement="top"
|
|
|
|
trigger="click"
|
|
|
|
>
|
|
|
|
<n-button size="small" class="nav-picker">
|
|
|
|
{{ configProviderLabels[configProviderName] }}
|
2020-11-28 14:33:04 +08:00
|
|
|
</n-button>
|
2021-04-05 17:59:04 +08:00
|
|
|
</n-popselect>
|
|
|
|
<n-popselect
|
|
|
|
v-if="dev"
|
|
|
|
:options="displayModeOptions"
|
|
|
|
v-model:value="displayMode"
|
|
|
|
overlap
|
|
|
|
placement="top"
|
|
|
|
trigger="click"
|
|
|
|
>
|
|
|
|
<n-button size="small" class="nav-picker">{{
|
|
|
|
displayModeLabelMap[displayMode]
|
|
|
|
}}</n-button>
|
|
|
|
</n-popselect>
|
|
|
|
<n-button size="small">
|
|
|
|
{{ version }}
|
|
|
|
</n-button>
|
2019-11-22 18:49:53 +08:00
|
|
|
</div>
|
2021-04-05 17:59:04 +08:00
|
|
|
<n-popover
|
|
|
|
v-else
|
|
|
|
style="padding: 0; width: 288px"
|
|
|
|
placement="bottom-end"
|
|
|
|
display-directive="show"
|
2021-04-05 19:03:09 +08:00
|
|
|
trigger="click"
|
2021-04-05 17:59:04 +08:00
|
|
|
>
|
|
|
|
<template #trigger>
|
|
|
|
<n-icon size="20" style="margin-left: 12px"><menu-outline /></n-icon>
|
|
|
|
</template>
|
|
|
|
<div style="overflow: auto; max-height: 80vh">
|
|
|
|
<n-menu
|
|
|
|
:value="mobileMenuValue"
|
|
|
|
:options="mobileMenuOptions"
|
|
|
|
:indent="18"
|
|
|
|
@update:value="handleMobileUpdateMenu"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</n-popover>
|
2020-03-03 19:25:25 +08:00
|
|
|
</n-layout-header>
|
2019-09-17 19:28:28 +08:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
2021-02-19 13:48:10 +08:00
|
|
|
import { computed, ref } from 'vue'
|
2021-04-05 17:59:04 +08:00
|
|
|
import { useRouter, useRoute } from 'vue-router'
|
2021-03-30 02:25:22 +08:00
|
|
|
import { useMessage, version } from 'naive-ui'
|
2021-04-05 17:59:04 +08:00
|
|
|
import { MenuOutline } from '@vicons/ionicons5'
|
|
|
|
import { i18n, useIsMobile } from './utils/composables'
|
|
|
|
import { findMenuValue } from './utils/route'
|
2020-12-12 13:51:22 +08:00
|
|
|
import {
|
2021-01-13 12:01:02 +08:00
|
|
|
useThemeName,
|
|
|
|
useLocaleName,
|
|
|
|
useDisplayMode,
|
2021-02-17 23:31:56 +08:00
|
|
|
useFlattenedDocOptions,
|
2021-04-05 17:59:04 +08:00
|
|
|
useConfigProviderName,
|
|
|
|
useDocOptions,
|
|
|
|
useComponentOptions
|
2021-01-13 12:01:02 +08:00
|
|
|
} from './store'
|
2019-09-17 19:28:28 +08:00
|
|
|
|
2021-04-05 17:59:04 +08:00
|
|
|
// match substr
|
2020-02-26 17:21:03 +08:00
|
|
|
function match (pattern, string) {
|
|
|
|
if (!pattern.length) return true
|
|
|
|
if (!string.length) return false
|
|
|
|
if (pattern[0] === string[0]) return match(pattern.slice(1), string.slice(1))
|
|
|
|
return match(pattern, string.slice(1))
|
|
|
|
}
|
|
|
|
|
2021-04-05 17:59:04 +08:00
|
|
|
const locales = {
|
|
|
|
'zh-CN': {
|
|
|
|
dark: '深色',
|
|
|
|
light: '浅色',
|
|
|
|
searchPlaceholder: '搜索',
|
|
|
|
home: '首页',
|
|
|
|
doc: '文档',
|
|
|
|
component: '组件',
|
|
|
|
common: '常规',
|
|
|
|
debug: '调试',
|
|
|
|
alreadyHome: '别点了,你已经在首页了',
|
|
|
|
tusimpleTheme: '图森主题',
|
|
|
|
defaultTheme: '默认主题'
|
|
|
|
},
|
|
|
|
'en-US': {
|
|
|
|
dark: 'Dark',
|
|
|
|
light: 'Light',
|
|
|
|
searchPlaceholder: 'Search',
|
|
|
|
home: 'Home',
|
|
|
|
doc: 'Docs',
|
|
|
|
component: 'Components',
|
|
|
|
common: 'Common',
|
|
|
|
debug: 'Debug',
|
|
|
|
alreadyHome: 'You are already in home page. No clicking anymore.',
|
|
|
|
tusimpleTheme: 'Tusimple Theme',
|
|
|
|
defaultTheme: 'Default Theme'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-17 19:28:28 +08:00
|
|
|
export default {
|
2020-09-27 22:27:25 +08:00
|
|
|
name: 'SiteHeader',
|
2021-04-05 17:59:04 +08:00
|
|
|
components: {
|
|
|
|
MenuOutline
|
|
|
|
},
|
2020-09-27 22:27:25 +08:00
|
|
|
setup () {
|
2021-03-26 01:09:16 +08:00
|
|
|
const message = useMessage()
|
2021-04-05 17:59:04 +08:00
|
|
|
const route = useRoute()
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
|
|
// i18n
|
|
|
|
const { t } = i18n(locales)
|
|
|
|
|
|
|
|
// menu
|
|
|
|
const menuOptionsRef = computed(() => {
|
2020-10-07 20:45:51 +08:00
|
|
|
return [
|
|
|
|
{
|
2021-02-14 14:52:14 +08:00
|
|
|
key: 'home',
|
2020-10-07 20:45:51 +08:00
|
|
|
title: t('home')
|
|
|
|
},
|
|
|
|
{
|
2021-02-14 14:52:14 +08:00
|
|
|
key: 'doc',
|
2020-10-07 20:45:51 +08:00
|
|
|
title: t('doc')
|
2021-02-14 14:52:14 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'component',
|
|
|
|
title: t('component')
|
2020-10-07 20:45:51 +08:00
|
|
|
}
|
|
|
|
]
|
|
|
|
})
|
2021-04-05 17:59:04 +08:00
|
|
|
const themeAndLocaleReg = /^(\/[^/]+){2}/
|
|
|
|
function handleMenuUpdateValue (value) {
|
|
|
|
if (value === 'home') {
|
|
|
|
router.push(themeAndLocaleReg.exec(route.path)[0])
|
|
|
|
}
|
|
|
|
if (value === 'doc') {
|
|
|
|
if (!/^(\/[^/]+){2}\/docs/.test(route.path)) {
|
|
|
|
router.push(
|
|
|
|
themeAndLocaleReg.exec(route.path)[0] + '/docs/installation'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (value === 'component') {
|
|
|
|
if (!/^(\/[^/]+){2}\/components/.test(route.path)) {
|
|
|
|
router.push(
|
|
|
|
themeAndLocaleReg.exec(route.path)[0] + '/components/n-button'
|
|
|
|
)
|
|
|
|
}
|
2020-10-07 20:45:51 +08:00
|
|
|
}
|
2021-04-05 17:59:04 +08:00
|
|
|
}
|
|
|
|
const menuValueRef = computed(() => {
|
|
|
|
if (/\/docs\//.test(route.path)) return 'doc'
|
|
|
|
if (/\/components\//.test(route.path)) return 'component'
|
|
|
|
else if (route.name === 'home') return 'home'
|
|
|
|
return null
|
|
|
|
})
|
|
|
|
|
|
|
|
// mobile options
|
|
|
|
const docOptionsRef = useDocOptions()
|
|
|
|
const componentOptionsRef = useComponentOptions()
|
|
|
|
const mobileMenuOptionsRef = computed(() => {
|
|
|
|
return [
|
|
|
|
{
|
|
|
|
key: 'theme',
|
|
|
|
title: themeLabelMapRef.value[themeNameRef.value]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'locale',
|
|
|
|
title: localeNameRef.value === 'zh-CN' ? 'English' : '中文'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'home',
|
|
|
|
title: t('home')
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'doc',
|
|
|
|
title: t('doc'),
|
|
|
|
children: docOptionsRef.value
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'component',
|
|
|
|
title: t('component'),
|
|
|
|
children: componentOptionsRef.value
|
|
|
|
}
|
|
|
|
]
|
|
|
|
})
|
|
|
|
const mobileMenuValueRef = computed(() => {
|
|
|
|
return findMenuValue(mobileMenuOptionsRef.value, route.path)
|
|
|
|
})
|
|
|
|
function handleMobileUpdateMenu (value, { path }) {
|
|
|
|
if (value === 'theme') {
|
|
|
|
handleThemeUpdate()
|
|
|
|
} else if (value === 'locale') {
|
|
|
|
if (localeNameRef.value === 'zh-CN') {
|
|
|
|
localeNameRef.value = 'en-US'
|
|
|
|
} else {
|
|
|
|
localeNameRef.value = 'zh-CN'
|
|
|
|
}
|
|
|
|
} else if (path) {
|
|
|
|
router.push(path)
|
|
|
|
} else {
|
|
|
|
handleMenuUpdateValue(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// theme
|
|
|
|
const themeNameRef = useThemeName()
|
|
|
|
const themeLabelMapRef = computed(() => ({
|
|
|
|
dark: t('light'),
|
|
|
|
light: t('dark')
|
2020-10-07 20:45:51 +08:00
|
|
|
}))
|
2021-04-05 17:59:04 +08:00
|
|
|
function handleThemeUpdate () {
|
|
|
|
if (themeNameRef.value === 'dark') {
|
|
|
|
themeNameRef.value = 'light'
|
|
|
|
} else {
|
|
|
|
themeNameRef.value = 'dark'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// locale
|
|
|
|
const localeNameRef = useLocaleName()
|
|
|
|
const localeLabelMap = {
|
|
|
|
'zh-CN': '中文',
|
|
|
|
'en-US': 'English'
|
|
|
|
}
|
|
|
|
const localeOptions = [
|
|
|
|
{
|
|
|
|
label: 'English',
|
|
|
|
value: 'en-US'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: '中文',
|
|
|
|
value: 'zh-CN'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
// display mode
|
|
|
|
const displayModeRef = useDisplayMode()
|
|
|
|
const displayModeLabelMap = {
|
|
|
|
common: 'Prod',
|
|
|
|
debug: 'Debug'
|
|
|
|
}
|
|
|
|
const displayModeOptions = [
|
|
|
|
{
|
|
|
|
label: 'Prod',
|
|
|
|
value: 'common'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Debug',
|
|
|
|
value: 'debug'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
// config provider
|
|
|
|
const configProviderNameRef = useConfigProviderName()
|
2021-03-03 17:26:54 +08:00
|
|
|
const configProviderLabelsRef = computed(() => ({
|
|
|
|
tusimple: t('tusimpleTheme'),
|
|
|
|
default: t('defaultTheme')
|
|
|
|
}))
|
|
|
|
const configProviderOptionsRef = computed(() => [
|
|
|
|
{
|
|
|
|
label: t('defaultTheme'),
|
|
|
|
value: 'default'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: t('tusimpleTheme'),
|
|
|
|
value: 'tusimple'
|
|
|
|
}
|
|
|
|
])
|
2021-04-05 17:59:04 +08:00
|
|
|
|
|
|
|
// search
|
|
|
|
const searchableOptionsRef = useFlattenedDocOptions()
|
|
|
|
const searchPatternRef = ref('')
|
|
|
|
const searchOptionsRef = computed(() => {
|
2020-02-11 18:10:49 +08:00
|
|
|
function getLabel (item) {
|
2021-02-14 15:19:32 +08:00
|
|
|
if (item.label) {
|
|
|
|
return item.label + (item.extra ? ' ' + item.extra : '')
|
2020-12-12 15:33:41 +08:00
|
|
|
}
|
2021-02-14 15:19:32 +08:00
|
|
|
return item.key
|
2020-02-11 18:10:49 +08:00
|
|
|
}
|
2021-04-05 17:59:04 +08:00
|
|
|
if (!searchPatternRef.value) return []
|
2020-02-11 18:10:49 +08:00
|
|
|
const replaceRegex = / |-/g
|
2021-04-05 17:59:04 +08:00
|
|
|
return searchableOptionsRef.value
|
2020-12-12 13:51:22 +08:00
|
|
|
.filter((item) => {
|
2021-04-05 17:59:04 +08:00
|
|
|
const pattern = searchPatternRef.value
|
2020-12-12 13:51:22 +08:00
|
|
|
.toLowerCase()
|
|
|
|
.replace(replaceRegex, '')
|
|
|
|
.slice(0, 20)
|
|
|
|
const label = getLabel(item).toLowerCase().replace(replaceRegex, '')
|
|
|
|
return match(pattern, label)
|
|
|
|
})
|
|
|
|
.map((item) => ({
|
|
|
|
label: getLabel(item),
|
|
|
|
value: item.path
|
|
|
|
}))
|
2021-04-05 17:59:04 +08:00
|
|
|
})
|
|
|
|
function handleSearch (value) {
|
|
|
|
router.push(value)
|
2019-09-23 11:32:50 +08:00
|
|
|
}
|
2021-04-05 17:59:04 +08:00
|
|
|
|
|
|
|
// common
|
|
|
|
const isMobileRef = useIsMobile()
|
|
|
|
function handleLogoClick () {
|
|
|
|
if (/^(\/[^/]+){2}$/.test(route.path)) {
|
|
|
|
message.info(t('alreadyHome'))
|
2020-09-27 22:27:25 +08:00
|
|
|
return
|
|
|
|
}
|
2021-04-05 17:59:04 +08:00
|
|
|
router.push(/^(\/[^/]+){2}/.exec(route.path)[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
// mobileMenuOptions,
|
|
|
|
tusimple: process.env.TUSIMPLE,
|
|
|
|
dev: __DEV__,
|
|
|
|
message,
|
|
|
|
t,
|
|
|
|
version,
|
|
|
|
isMobile: isMobileRef,
|
|
|
|
// theme
|
|
|
|
theme: themeNameRef,
|
|
|
|
handleThemeUpdate,
|
|
|
|
themeLabelMap: themeLabelMapRef,
|
|
|
|
// displayMode
|
|
|
|
displayMode: displayModeRef,
|
|
|
|
displayModeLabelMap,
|
|
|
|
displayModeOptions,
|
|
|
|
// locale
|
|
|
|
locale: localeNameRef,
|
|
|
|
localeLabelMap,
|
|
|
|
localeOptions,
|
|
|
|
// configProvider
|
|
|
|
configProviderName: configProviderNameRef,
|
|
|
|
configProviderOptions: configProviderOptionsRef,
|
|
|
|
configProviderLabels: configProviderLabelsRef,
|
|
|
|
// search
|
|
|
|
searchPattern: searchPatternRef,
|
|
|
|
searchOptions: searchOptionsRef,
|
|
|
|
handleSearch,
|
|
|
|
// menu
|
|
|
|
menuOptions: menuOptionsRef,
|
|
|
|
menuValue: menuValueRef,
|
|
|
|
handleMenuUpdateValue,
|
|
|
|
// mobile menu
|
|
|
|
mobileMenuOptions: mobileMenuOptionsRef,
|
|
|
|
handleMobileUpdateMenu,
|
|
|
|
mobileMenuValue: mobileMenuValueRef,
|
|
|
|
// common
|
|
|
|
handleLogoClick,
|
|
|
|
style: computed(() => {
|
|
|
|
return isMobileRef.value
|
|
|
|
? {
|
|
|
|
'--side-padding': '16px',
|
|
|
|
'grid-template-columns': 'auto 1fr auto'
|
|
|
|
}
|
|
|
|
: {
|
|
|
|
'--side-padding': '32px',
|
|
|
|
'grid-template-columns':
|
|
|
|
'calc(272px - var(--side-padding)) 1fr auto'
|
|
|
|
}
|
|
|
|
})
|
2019-09-17 19:28:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
2020-11-01 19:35:00 +08:00
|
|
|
<style scoped>
|
2019-09-17 19:28:28 +08:00
|
|
|
.nav {
|
|
|
|
display: grid;
|
2020-02-27 18:09:23 +08:00
|
|
|
grid-template-rows: 63px;
|
2019-09-17 19:28:28 +08:00
|
|
|
align-items: center;
|
2021-04-05 17:59:04 +08:00
|
|
|
padding: 0 var(--side-padding);
|
2019-09-17 19:28:28 +08:00
|
|
|
}
|
2020-11-23 02:22:41 +08:00
|
|
|
|
2019-09-17 19:28:28 +08:00
|
|
|
.ui-logo {
|
2020-02-27 23:03:15 +08:00
|
|
|
cursor: pointer;
|
2019-10-20 00:18:55 +08:00
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
font-size: 18px;
|
|
|
|
}
|
2020-11-23 02:22:41 +08:00
|
|
|
|
2019-10-20 00:18:55 +08:00
|
|
|
.ui-logo > img {
|
|
|
|
margin-right: 12px;
|
|
|
|
height: 32px;
|
|
|
|
width: 32px;
|
2019-09-17 19:28:28 +08:00
|
|
|
}
|
2020-11-23 02:22:41 +08:00
|
|
|
|
2020-02-27 18:09:23 +08:00
|
|
|
.nav-menu {
|
2020-11-28 13:34:45 +08:00
|
|
|
padding-left: 36px;
|
2020-02-27 18:09:23 +08:00
|
|
|
}
|
2020-09-17 10:43:29 +08:00
|
|
|
|
2020-03-04 14:34:14 +08:00
|
|
|
.nav-picker {
|
|
|
|
margin-right: 12px;
|
2020-11-01 19:35:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.nav-picker:last-child {
|
|
|
|
margin-right: 0;
|
2019-09-17 19:28:28 +08:00
|
|
|
}
|
|
|
|
</style>
|
2020-11-14 20:38:30 +08:00
|
|
|
|
|
|
|
<style>
|
|
|
|
.nav-menu .n-menu-item {
|
|
|
|
height: 63px !important;
|
|
|
|
}
|
|
|
|
</style>
|