feat(auto-complete): add a buggy version of auto-complete

This commit is contained in:
07akioni 2019-11-22 18:49:53 +08:00
parent 95b5861b5b
commit f535fc74d0
6 changed files with 220 additions and 6 deletions

View File

@ -11,6 +11,7 @@
<template v-slot:nav>
<doc-header
:lang="lang"
:items="flattenedItems"
@lang-change="handleLangChange"
/>
</template>
@ -383,6 +384,19 @@ export default {
}
]
},
flattenedItems () {
const flattenedItems = []
const traverse = items => {
if (items) {
items.forEach(item => {
if (item.childItems) traverse(item.childItems)
else flattenedItems.push(item)
})
}
}
traverse(this.items)
return flattenedItems
},
lang: {
get () {
return this.$route.params.lang || 'en-us'

View File

@ -0,0 +1,28 @@
# Basic
# Basic
```html
<n-auto-complete :options="options" v-model="value"/>
<br>
{{ value }}
```
```js
export default {
computed: {
options () {
return [
'@gmail.com',
'@163.com',
'@qq.com'
].map(suffix => ({
label: this.value + suffix,
value: this.value + suffix,
}))
}
},
data () {
return {
value: ''
}
}
}
```

View File

@ -17,7 +17,9 @@
<img src="./assets/images/naivelogo.svg">
Naive UI ({{ version }})
</div>
<div />
<div style="width: 200px; margin-left: 48px;">
<n-auto-complete v-model="searchInputValue" placeholder="Search in Naive UI" :options="searchOptions" @select="handleSelect" />
</div>
<div class="theme-picker">
<n-select
v-model="NApp.$parent.theme"
@ -46,10 +48,15 @@ export default {
lang: {
type: String,
required: true
},
items: {
type: Array,
default: () => []
}
},
data () {
return {
searchInputValue: '',
version,
theme: 'dark',
langOptions: [
@ -65,6 +72,16 @@ export default {
}
},
computed: {
searchOptions () {
if (!this.searchInputValue) return []
return this.items.filter(item => {
// console.log(item.name.toLowerCase(), this.searchInputValue.toLowerCase())
return ~item.name.toLowerCase().indexOf(this.searchInputValue.toLowerCase())
}).slice(0, 6).map(item => ({
label: item.name,
value: item.path
}))
},
options: function () {
return [
{
@ -79,6 +96,10 @@ export default {
}
},
methods: {
handleSelect (value) {
this.$router.push(value)
document.body.focus()
},
handleThemeChange (theme) {
this.NApp.$parent.theme = theme
},

View File

@ -71,6 +71,7 @@ import layout from './documentation/components/layout'
import avatar from './documentation/components/avatar'
import result from './documentation/components/result'
import thing from './documentation/components/thing'
import autoComplete from './documentation/components/autoComplete'
import demo from './demo'
import ComponentDemo from './utils/ComponentDemo'
@ -193,7 +194,8 @@ const routes = [
{ path: '/n-card', component: card },
{ path: '/n-avatar', component: avatar },
{ path: '/n-result', component: result },
{ path: '/n-thing', component: thing }
{ path: '/n-thing', component: thing },
{ path: '/n-auto-complete', component: autoComplete }
])
},
{

View File

@ -9,6 +9,9 @@ export default {
inject: {
NSelect: {
default: null
},
NAutoComplete: {
default: null
}
},
data () {
@ -18,10 +21,17 @@ export default {
mounting: true
}
},
computed: {
injection () {
if (this.NSelect) return this.NSelect
if (this.NAutoComplete) return this.NAutoComplete
return null
}
},
watch: {
options (value) {
if (this.NSelect) {
this.NSelect.collectedOptions = value
if (this.injection) {
this.injection.collectedOptions = value
}
}
},

View File

@ -1,9 +1,148 @@
<template>
<div>example</div>
<div class="n-auto-complete">
<n-base-select-option-collector v-if="!!$slots.default">
<slot />
</n-base-select-option-collector>
<n-input ref="activator" :value="value" :placeholder="placeholder" @focus="active = true" @input="handleInput" />
<div
ref="contentContainer"
v-clickoutside="handleClickOutsideMenu"
class="n-detached-content-container n-select-detached-content-container"
:class="{
[namespace]: namespace
}"
>
<div
ref="content"
class="n-detached-content-content"
>
<transition name="n-select-menu--transition">
<n-base-select-menu
v-if="active"
ref="contentInner"
class="n-select-menu"
:theme="synthesizedTheme"
:pattern="value"
:options="filteredOptions"
:multiple="false"
:size="size"
:remote="remote"
:loading="loading"
:no-data-content="'Please Search'"
:not-found-content="'Not Found'"
:emit-option="false"
:filterable="false"
:is-selected="isSelected"
:use-slot="!!$slots.default"
@menu-toggle-option="handleToggleOption"
>
<n-base-select-render-options v-if="!!$slots.default" :options="filteredOptions" />
</n-base-select-menu>
</transition>
</div>
</div>
</div>
</template>
<script>
import NInput from '../../Input'
import detachable from '../../../mixins/detachable'
import placeable from '../../../mixins/placeable'
import zindexable from '../../../mixins/zindexable'
import clickoutside from '../../../directives/clickoutside'
import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable'
import asformitem from '../../../mixins/asformitem'
import {
NBaseSelectMenu,
NBaseSelectOptionCollector,
NBaseSelectRenderOptions
} from '../../../base/SelectMenu'
export default {
name: 'NAutoComplete'
name: 'NAutoComplete',
components: {
NInput,
NBaseSelectMenu,
NBaseSelectOptionCollector,
NBaseSelectRenderOptions
},
directives: {
clickoutside
},
mixins: [
withapp,
themeable,
detachable,
zindexable,
placeable,
asformitem()
],
props: {
placeholder: {
type: String,
default: null
},
value: {
type: String,
required: true
},
size: {
type: String,
default: 'medium'
},
options: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: false
},
remote: {
type: Boolean,
default: false
},
placement: {
type: String,
default: 'bottom-start'
},
widthMode: {
type: String,
default: 'activator'
}
},
data () {
return {
active: false
}
},
computed: {
filteredOptions () {
return this.options.map(literal => typeof literal === 'string' ? ({
label: literal,
value: literal
}) : literal)
}
},
methods: {
isSelected () {
},
handleInput (value) {
this.$emit('input', value)
this.active = true
},
handleToggleOption (option) {
this.$emit('input', option.label)
this.$emit('select', option.value)
this.active = false
},
handleClickOutsideMenu (e) {
if (!this.$refs.activator.$el.contains(e.target)) {
this.active = false
}
}
}
}
</script>