naive-ui/demo/SiteHeader.vue

263 lines
6.3 KiB
Vue
Raw Normal View History

2019-09-17 19:28:28 +08:00
<template>
2020-03-03 19:25:25 +08:00
<n-layout-header
bordered
:style="{
2020-03-11 21:06:19 +08:00
position: 'relative',
2020-03-03 19:25:25 +08:00
zIndex: zIndex
}"
>
<div class="nav">
2020-05-30 21:41:10 +08:00
<n-config-consumer v-slot="{ styleScheme }" abstract>
<div
class="ui-logo"
:style="{
2020-05-31 14:21:09 +08:00
color: styleScheme.primaryTextColor,
transition: `color .3s ${styleScheme.easeInOutCubicBezier}`
2020-05-30 21:41:10 +08:00
}"
@click="handleLogoClick"
>
<img src="./assets/images/naivelogo.svg">
Naive UI ({{ version }})
</div>
</n-config-consumer>
2020-03-03 19:25:25 +08:00
<div style=" margin-left: 56px; display: flex; align-items: center;">
<n-auto-complete
2020-09-30 14:56:45 +08:00
v-model:value="searchInputValue"
2020-03-03 19:25:25 +08:00
style="width: 216px;"
:z-index="zIndex && zIndex + 1"
2020-10-07 20:45:51 +08:00
:placeholder="t('searchPlaceholder')"
2020-03-03 19:25:25 +08:00
:options="searchOptions"
clear-after-select
blur-after-select
@select="handleSelect"
/>
<div class="nav-menu">
2020-09-17 10:43:29 +08:00
<n-menu
mode="horizontal"
:model-value="menuValue"
:items="menuItems"
@select="handleMenuSelect"
/>
2020-03-03 19:25:25 +08:00
</div>
</div>
<div style="display: flex;">
2020-09-17 10:43:29 +08:00
<n-tag class="nav-picker" @click="handleThemeChange">
{{ themeOptions[theme].label }}
2020-03-03 19:25:25 +08:00
</n-tag>
2020-09-17 10:43:29 +08:00
<n-tag class="nav-picker" @click="handleLanguageChange">
2020-03-03 19:25:25 +08:00
{{ langOptions[lang].label }}
</n-tag>
2020-03-05 09:57:29 +08:00
<n-tag
2020-09-27 22:27:25 +08:00
v-if="env === 'development'"
2020-03-05 09:57:29 +08:00
class="nav-picker"
2020-09-27 13:53:16 +08:00
@click="handleModeChange"
2020-03-05 09:57:29 +08:00
>
2020-09-27 22:27:25 +08:00
{{ modeOptions[displayMode].label }}
2020-03-05 09:57:29 +08:00
</n-tag>
2020-02-27 18:09:23 +08:00
</div>
</div>
2020-03-03 19:25:25 +08:00
</n-layout-header>
2019-09-17 19:28:28 +08:00
</template>
<script>
2020-10-07 20:45:51 +08:00
import { computed, readonly, ref } from 'vue'
2020-07-22 17:40:38 +08:00
import version from '../src/version'
2020-10-07 20:45:51 +08:00
import { useSiteTheme, useSiteLang, displayModeRef, envRef, i18n } from './util-compositions'
2019-09-17 19:28:28 +08:00
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))
}
2019-09-17 19:28:28 +08:00
export default {
2020-09-27 22:27:25 +08:00
name: 'SiteHeader',
inject: ['message'],
2019-09-24 16:59:07 +08:00
props: {
items: {
type: Array,
default: () => []
2020-09-27 22:27:25 +08:00
}
},
setup () {
2020-10-07 20:45:51 +08:00
const { t } = i18n({
'zh-CN': {
'dark': '深色',
'light': '浅色',
'searchPlaceholder': '搜索',
'home': '首页',
'doc': '文档',
'common': '常规',
'debug': '调试',
'alreadyHome': '别点了,你已经在首页了'
},
'en-US': {
'dark': 'Dark',
'light': 'Light',
'searchPlaceholder': 'Search',
'home': 'Home',
'doc': 'Documentation',
'common': 'Common',
'debug': 'Debug',
'alreadyHome': "You've already been in home page. No clicking."
}
})
const menuItemsRef = computed(() => {
return [
{
name: 'home',
title: t('home')
},
{
name: 'doc',
title: t('doc')
}
]
})
const themeOptionsRef = computed(() => ({
dark: {
label: t('light'),
next: 'light'
},
light: {
label: t('dark'),
next: 'dark'
}
}))
2020-09-27 22:27:25 +08:00
return {
2020-10-07 20:45:51 +08:00
t,
searchInputValue: ref(''),
version,
2020-09-27 22:27:25 +08:00
env: envRef,
displayMode: displayModeRef,
lang: useSiteLang(),
2020-10-07 20:45:51 +08:00
theme: useSiteTheme(),
menuItems: menuItemsRef,
themeOptions: themeOptionsRef,
langOptions: readonly({
2020-02-29 17:40:09 +08:00
'zh-CN': {
2019-09-21 17:03:37 +08:00
label: 'English',
2020-02-29 17:40:09 +08:00
next: 'en-US'
},
'en-US': {
label: '中文',
next: 'zh-CN'
2019-09-21 17:03:37 +08:00
}
2020-10-07 20:45:51 +08:00
}),
modeOptions: readonly({
2020-09-27 22:27:25 +08:00
debug: {
2020-03-05 13:46:19 +08:00
label: 'Production',
2020-03-04 14:34:14 +08:00
next: 'common'
},
2020-09-27 22:27:25 +08:00
common: {
2020-03-04 14:34:14 +08:00
label: 'Debug',
next: 'debug'
}
2020-10-07 20:45:51 +08:00
})
2019-09-17 19:28:28 +08:00
}
},
2019-09-23 11:32:50 +08:00
computed: {
2020-03-03 19:25:25 +08:00
zIndex () {
const path = this.$route.path
2020-09-27 13:53:16 +08:00
return (path.endsWith('n-modal') || path.endsWith('n-drawer') || path.endsWith('n-dialog')) ? null : 3000
2020-03-03 19:25:25 +08:00
},
2020-02-27 18:09:23 +08:00
menuValue () {
if (/^(\/[^/]+){2}\/doc/.test(this.$route.path)) return 'doc'
else if (this.$route.name === 'home') return 'home'
return null
},
searchOptions () {
2020-02-11 18:10:49 +08:00
function getLabel (item) {
if (item.title) return item.title + (item.titleExtra ? (' ' + item.titleExtra) : '')
return item.name
}
if (!this.searchInputValue) return []
2020-02-11 18:10:49 +08:00
const replaceRegex = / |-/g
return this.items.filter(item => {
2020-02-11 18:10:49 +08:00
const pattern = this.searchInputValue.toLowerCase().replace(replaceRegex, '').slice(0, 20)
const label = getLabel(item).toLowerCase().replace(replaceRegex, '')
2020-02-26 17:21:03 +08:00
return match(pattern, label)
}).map(item => ({
2020-02-11 18:10:49 +08:00
label: getLabel(item),
value: item.path
}))
2019-09-23 11:32:50 +08:00
}
},
2019-09-17 19:28:28 +08:00
methods: {
2020-02-27 23:03:15 +08:00
handleLogoClick () {
2020-09-27 22:27:25 +08:00
if (/^(\/[^/]+){2}$/.test(this.$route.path)) {
2020-10-07 20:45:51 +08:00
this.message.info(this.t('alreadyHome'))
2020-09-27 22:27:25 +08:00
return
}
2020-02-27 23:03:15 +08:00
this.$router.push(
/^(\/[^/]+){2}/.exec(this.$route.path)[0]
2020-02-27 23:03:15 +08:00
)
},
handleSelect (value) {
this.$router.push(value)
2020-02-27 18:09:23 +08:00
},
handleMenuSelect (value) {
if (value === 'home') {
this.$router.push(
/^(\/[^/]+){2}/.exec(this.$route.path)[0]
2020-02-27 18:09:23 +08:00
)
} if (value === 'doc') {
if (/^(\/[^/]+){2}\/doc/.test(this.$route.path)) {
2020-02-27 18:09:23 +08:00
} else {
this.$router.push(
/^(\/[^/]+){2}/.exec(this.$route.path)[0] + '/doc/start'
2020-02-27 18:09:23 +08:00
)
}
}
},
2020-02-29 17:40:09 +08:00
handleThemeChange () {
2020-09-27 22:27:25 +08:00
this.theme = this.themeOptions[this.theme].next
},
2020-03-04 14:34:14 +08:00
handleModeChange () {
2020-09-27 22:27:25 +08:00
this.displayMode = this.modeOptions[this.displayMode].next
2020-03-04 03:01:15 +08:00
},
2020-02-29 17:40:09 +08:00
handleLanguageChange () {
2020-09-27 22:27:25 +08:00
this.lang = this.langOptions[this.lang].next
2019-09-17 19:28:28 +08:00
}
}
}
</script>
<style lang="scss" scoped>
.nav {
display: grid;
2020-02-29 17:40:09 +08:00
grid-template-columns: 288px 1fr auto 32px;
2020-02-27 18:09:23 +08:00
grid-template-rows: 63px;
2019-09-17 19:28:28 +08:00
align-items: center;
}
.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;
2020-02-22 20:25:10 +08:00
padding-left: 36px;
2019-10-20 00:18:55 +08:00
font-size: 18px;
}
.ui-logo > img {
margin-right: 12px;
height: 32px;
width: 32px;
2019-09-17 19:28:28 +08:00
}
2020-02-27 18:09:23 +08:00
.nav-menu {
padding-left: 32px;
}
2020-09-17 10:43:29 +08:00
2020-10-07 20:45:51 +08:00
.nav-menu::v-deep(.n-menu-item) {
height: 63px !important;
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 {
cursor: pointer;
margin-right: 12px;
&:last-child {
margin-right: 0;
}
2019-09-17 19:28:28 +08:00
}
</style>