feat: publicize doc implemetation

This commit is contained in:
Justineo
2020-08-13 11:47:56 +08:00
parent 55b9b044f2
commit 1e5fcff6ad
372 changed files with 50636 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
<template>
<button
class="one-back-to-top"
:class="{
scrolled: !top
}"
aria-hidden="true"
@click="scrollToTop"
>
<veui-icon
class="icon"
name="arrow-up"
:label="t('toTop')"
/>
</button>
</template>
<script>
import { Icon } from 'veui'
import i18n from 'veui/mixins/i18n'
import 'veui-theme-dls-icons/arrow-up'
import { debounce } from 'lodash'
export default {
name: 'one-back-to-top',
components: {
'veui-icon': Icon
},
mixins: [i18n],
data () {
return {
top: true
}
},
mounted () {
this.check = debounce(() => {
this.top = window.scrollY === 0
}, 300)
window.addEventListener('scroll', this.check)
this.check()
},
beforeDestroy () {
this.check.cancel()
window.removeEventListener('scroll', this.check)
},
methods: {
scrollToTop () {
window.scrollTo(0, 0)
}
}
}
</script>
<style lang="stylus" scoped>
.one-back-to-top
position fixed
right 35px
bottom 35px
width 43px
height 43px
border 1px solid #dbdbdb
border-radius 50%
opacity 0
outline none
box-shadow 0 0 2px #dbdbdb
cursor pointer
transition background-color 0.3s, opacity 0.3s
&:hover
&.focus-visible
background-color #f7f7f7
&:active
background-color #ececec
.icon
position absolute
top 50%
left 50%
transform translate(-50%, -50%)
.scrolled
opacity 1
</style>

137
components/OneDemo.vue Normal file
View File

@@ -0,0 +1,137 @@
<template>
<article
class="one-demo"
:class="{ expanded: localExpanded }"
>
<section class="demo">
<browser-window
v-if="browser"
:url="browser"
width="80%"
height="400px"
>
<slot/>
</browser-window>
<slot v-else/>
</section>
<section
v-if="$slots.desc"
class="desc"
>
<slot name="desc"/>
</section>
<section
v-if="$slots.source"
ref="source"
class="source"
:style="{ height: localExpanded ? `${sourceHeight || 0}px` : '0' }"
>
<slot name="source"/>
</section>
<button
class="toggle"
@click="localExpanded = !localExpanded"
>
<veui-icon
class="arrow"
name="chevron-down"
/> {{ t(localExpanded ? 'hideCode' : 'showCode') }}
</button>
</article>
</template>
<script>
import { Icon } from 'veui'
import i18n from 'veui/mixins/i18n'
import { BrowserWindow } from 'vue-windows'
import 'veui-theme-dls-icons/chevron-down'
export default {
name: 'one-demo',
components: {
'veui-icon': Icon,
BrowserWindow
},
mixins: [i18n],
props: {
expanded: Boolean,
browser: String
},
data () {
return {
sourceHeight: 0,
localExpanded: this.expanded
}
},
watch: {
expanded (val) {
this.localExpanded = val
},
localExpanded (val) {
this.$emit('update:expanded', val)
}
},
mounted () {
let source = this.$refs.source
let style = source.style
style.height = ''
style.height = source.offsetHeight
this.sourceHeight = source.offsetHeight
style.height = '0'
}
}
</script>
<style src="vue-windows/dist/vue-windows.css"></style>
<style lang="stylus" scoped>
.one-demo
overflow hidden
.arrow
transition transform 0.3s
height 1.2em
margin-right 4px
.one-demo.expanded &
transform rotateZ(180deg)
.demo
border 1px solid #eee
padding 30px
.desc
border 1px solid #eee
padding 18px 20px
background-color #fcfcfc
.source
transition height 0.3s
& >>> pre
margin-top 0
margin-bottom 0
.desc
.source >>> pre
.toggle
margin-top -1px
.toggle
position relative
display flex
justify-content center
align-items center
line-height 2
width 100%
height 40px
border 1px solid #eee
background-color #fff
transition background-color 0.3s
outline none
cursor pointer
&:hover
&.focus-visible
background-color #fafafa
</style>

115
components/OneDetails.vue Normal file
View File

@@ -0,0 +1,115 @@
<template>
<div
:class="{
'one-details': true,
expanded
}"
>
<button
class="summary"
@click="toggle"
>
<veui-icon
class="arrow"
name="chevron-right"
/> {{ summary }}
</button>
<div
ref="content"
class="content"
:style="style"
@transitionend="stable = true"
>
<slot/>
</div>
</div>
</template>
<script>
import { Icon } from 'veui'
import 'veui-theme-dls-icons/chevron-right'
export default {
name: 'one-details',
components: {
'veui-icon': Icon
},
props: {
summary: {
type: String,
required: true,
default: '详细信息'
}
},
data () {
return {
expanded: false,
intrinsicHeight: 0,
height: 0,
stable: true
}
},
computed: {
style () {
return this.stable
? this.expanded
? null
: 'height: 0'
: `height: ${this.height}px`
}
},
mounted () {
this.updateHeight()
},
methods: {
toggle () {
this.expanded = !this.expanded
this.stable = false
this.height = this.intrinsicHeight
if (!this.expanded) {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
this.height = 0
})
})
}
},
updateHeight () {
let { content } = this.$refs
this.intrinsicHeight = content.scrollHeight
}
}
}
</script>
<style lang="stylus" scoped>
.one-details
overflow hidden
.summary
border none
background none
padding-left 0
cursor help
outline none
display flex
align-items center
line-height 1em
&:hover
color #333
.content
overflow hidden
transition height 0.3s
.arrow
transition transform 0.3s
margin-right 8px
width 1.2em
height 1.2em
.expanded > .summary > &
transform rotateZ(90deg)
</style>

203
components/OneFooter.vue Normal file
View File

@@ -0,0 +1,203 @@
<template>
<footer class="one-footer">
<nav
class="links"
:class="{ empty: single }"
>
<nuxt-link
v-if="prev && level > 0"
key="prev"
class="prev"
:to="prev.to"
>
{{ prev.title }}
</nuxt-link>
<nuxt-link
v-if="next && level > 0"
key="next"
class="next"
:to="next.to"
>
{{ next.title }}
</nuxt-link>
</nav>
<p class="copyright">
© Baidu, Inc. {{ year }}
</p>
</footer>
</template>
<script>
import { compact, find, findIndex } from 'lodash'
import i18n from '../common/i18n'
export default {
name: 'one-footer',
mixins: [i18n],
props: {
nav: {
type: Array,
default () {
return []
}
}
},
data () {
return {
year: new Date().getFullYear()
}
},
computed: {
links () {
let segments = compact(this.canonicalPath.split('/'))
return getLinks(this.nav, segments)
},
level () {
return this.links ? this.links.level : 0
},
base () {
return this.links ? this.links.base : null
},
prev () {
return this.resolve(this.links ? this.links.prev : null)
},
next () {
return this.resolve(this.links ? this.links.next : null)
},
single () {
return (!this.prev && !this.next) || this.level < 1
}
},
watch: {
single: {
handler (val) {
this.$emit('update', {
hasLinks: !val
})
},
immediate: true
}
},
methods: {
resolve (link) {
let { slug, title, link: lk } = link || {}
if (typeof slug !== 'string' || lk === false) {
return null
}
let base = this.base
return {
title,
to: this.getLocalePath(slug ? `${base}/${slug}` : base)
}
}
}
}
function findSibling (items, start, forward) {
if ((start === 0 && !forward) || (start === items.length - 1 && forward)) {
return null
}
let candidates = forward
? items.slice(start + 1)
: items.slice(0, start).reverse()
return find(candidates, ({ disabled }) => !disabled)
}
function getLinks (nav, remaining, level = 0, base = '') {
let [segment = '', ...segments] = [...remaining]
let i = findIndex(nav, ({ slug }) => slug === segment)
if (i === -1) {
return null
}
let links = {
prev: findSibling(nav, i, false),
next: findSibling(nav, i, true),
level,
base
}
let sub = nav[i].children
if (!sub) {
if (segments.length) {
return null
}
return links
}
return (
getLinks(sub, segments, level + 1, segment ? `${base}/${segment}` : base) ||
links
)
}
</script>
<style lang="stylus" scoped>
arrow()
content ""
display block
width 23px
height 33px
background #333 url("/icons/angle.svg") no-repeat 50% 50% / auto 21.5px
transition background-color 0.3s
.one-footer
clear both
padding 0 60px
.links
border-top 1px solid #eee
padding 20px 0 80px
overflow hidden
.empty
display none
overflow hidden
.prev
.next
display block
line-height 33px
color #333
text-decoration none
&:hover
&.focus-visible
&::before
&::after
background-color #5b5b5b
&:active
&::before
&::after
background-color #818181
.prev::before
.next::after
arrow()
.prev
float left
&::before
float left
margin-right 15px
transform rotate(180deg)
.next
float right
&::after
float right
margin-left 15px
.copyright
margin 0
padding 25px 0 20px
border-top 1px solid #eee
line-height 1
font-size 12px
text-align center
</style>

89
components/OneHeader.vue Normal file
View File

@@ -0,0 +1,89 @@
<template>
<header class="one-header">
<h1>Baidu DLS</h1>
<a
href="http://dls.baidu.com/"
target="_blank"
>返回 DLS</a>
<veui-dropdown
label="Vue"
:options="options"
@click="redirect"
/>
</header>
</template>
<script>
import { Dropdown } from 'veui'
export default {
name: 'one-header',
components: {
'veui-dropdown': Dropdown
},
data () {
return {
options: [
{
label: 'Vue',
value: '/'
},
{
label: 'React',
value: 'http://one-ui.baidu-int.com/'
},
{
label: 'Angular',
value: 'http://cp01-wangfengjiao01.epc.baidu.com:8404/'
}
]
}
},
methods: {
redirect (url) {
location.href = url
}
}
}
</script>
<style lang="stylus" scoped>
.one-header
position fixed
top 0
left 0
right 0
z-index 20
display flex
align-items center
height 60px
background-color #070628
color #ffffff
padding 0 51px 0 17px
h1
display inline-block
font-size 18px
a
margin-left auto
color #ffffff
font-size 16px
&:hover
color #ffffff
.veui-dropdown
margin-left 40px
& >>> .veui-dropdown-button
color #ffffff
background-color transparent
border-radius 6px
height 28px
display inline-flex
align-items center
.veui-dropdown-label
line-height 1
</style>

313
components/OneMenu.vue Normal file
View File

@@ -0,0 +1,313 @@
<template>
<aside class="one-nav">
<nav class="secondary">
<h2><span>VEUI<small>beta</small></span></h2>
<section class="desc">
<a href="https://github.com/ecomfe/veui">
<img
alt="VEUI on GitHub"
src="https://badgen.net/badge/-/GitHub?icon=github&label"
width="69.2"
height="20"
>
</a>
<nuxt-link
:class="{
'locale-swith': true,
disabled: altLocale.disabled
}"
:to="altLocale.disabled ? '' : altLocale.to"
>
{{ altLocale.label }}
</nuxt-link>
</section>
<section class="filter">
<input
type="text"
placeholder="Search…"
class="search"
>
</section>
<menu class="menu">
<template v-for="(item, i) in nav">
<li
:key="`menu-${i}`"
class="menu-item"
>
<nuxt-link
v-if="item.link !== false"
class="menu-link"
:exact="item.exact"
:to="getLocalePath(`/${item.slug}`)"
>
{{ item.title }}
</nuxt-link>
<span
v-else
class="menu-link"
>{{ item.title }}</span>
<menu
v-if="item.children && item.children.length"
class="menu"
>
<template
v-for="(subItem, j) in item.children"
>
<li
v-if="!subItem.hidden"
:key="`sub-${j}`"
class="menu-item"
>
<nuxt-link
:class="{
'menu-link': true,
'menu-link-disabled': subItem.disabled,
'menu-link-sub': subItem.sub,
'menu-link-active': isActive(`/${item.slug}/${subItem.slug}`)
}"
:exact="subItem.exact"
:to="subItem.disabled ? '/' : getLocalePath(`/${item.slug}/${subItem.slug}`)"
v-html="getTitleHTML(subItem.title)"
/>
</li>
</template>
</menu>
</li>
</template>
</menu>
</nav>
</aside>
</template>
<script>
import { escape } from 'lodash'
import i18n from '../common/i18n'
export default {
name: 'one-menu',
mixins: [i18n],
props: {
nav: {
type: Array,
default () {
return []
}
}
},
computed: {
altLocale () {
let { canonicalPath, locale, getLocalePath, isPathDisabled } = this
let altLocale = locale === 'zh-Hans' ? 'en-US' : 'zh-Hans'
let label = locale === 'zh-Hans' ? 'English' : '中文'
let disabled = isPathDisabled(canonicalPath, altLocale)
return {
to: disabled ? '' : getLocalePath(canonicalPath, altLocale),
disabled,
label
}
}
},
watch: {
$route: 'scrollActiveIntoView'
},
mounted () {
this.scrollActiveIntoView()
},
beforeDestroy () {
clearTimeout(this.timer)
},
methods: {
getTitleHTML (title) {
let [main, sub] = title.split(' - ')
return escape(main) + (sub ? `<small>${escape(sub)}</small>` : '')
},
isActive (path) {
let { route = {} } = this.$router.resolve(path) || {}
return route.name === this.$route.name
},
scrollActiveIntoView () {
this.timer = setTimeout(() => {
if (!this.$el) {
return
}
let active =
this.$el.querySelector('.nuxt-link-exact-active') ||
this.$el.querySelector('.menu-link-active')
if (!active) {
return
}
let menu = active.offsetParent
if (!menu) {
return
}
if (
active.offsetTop < menu.scrollTop ||
active.offsetTop + active.offsetHeight > menu.scrollTop
) {
active.scrollIntoView({
behavior: 'smooth',
block: 'nearest'
})
}
})
}
}
}
</script>
<style lang="stylus" scoped>
.one-nav
position fixed
top 60px
bottom 0
left 0
z-index 1
padding-top 30px
border-right 1px solid #e5e5e5
.primary
margin-left -250px
.secondary
height 100%
position relative
display flex
justify-content stretch
flex-direction column
float left
width 240px
h2
display flex
align-items center
margin 0 0 0 20px
font-size 20px
font-weight 500
span
position relative
small
position absolute
font-size 16px
font-weight 400
transform scale(0.75) translateY(-3px)
margin-left 3px
opacity 0.7
a
display block
& + .desc
display flex
align-items center
margin-top 15px
margin-left 20px
img
display block
.locale-swith
display block
margin-left 12px
padding 0 6px
border 1px solid #dbdbdb
border-radius 3px
line-height 18px
font-size 12px
text-align center
text-decoration none
transition all 0.2s
&:hover
border-color #999
.filter
margin-top 20px
margin-left 20px
.search
display block
width 180px
height 32px
padding 0 7px
border 1px solid #dbdbdb
border-radius 4px
outline none
font-size 13px
transition all 0.2s
&.focus-visible
border-color #999
box-shadow 0 0 0 2px rgba(0, 0, 0, 0.15)
& > .menu
position relative
width 100%
flex 1 1 auto
margin-top 25px
padding-left 20px
overflow auto
.menu
.menu-item
.menu-link
float left
clear left
.menu .menu
margin 3.5px 0
.menu-item
margin 3.5px 0
font-size 16px
.menu-item
font-size 13px
.menu-link
color #333
font-weight 400
& >>> small
color #999
font-size 13px
margin-left 10px
white-space nowrap
&::after
display block
.menu-link
float left
clear left
color #333
font-weight 500
padding 9px 0
text-decoration none
&-disabled
opacity 0.3
pointer-events none
// &-sub
// margin-left 10px
&::after
background-color #999
.nuxt-link-exact-active::after
.menu-link-active::after
width 100%
left 0
background-color #333
.toggle
margin-right 15px
font-size 13px
vertical-align middle
.disabled
opacity 0.3
pointer-events none
</style>