diff --git a/src/form/input.js b/src/form/input.js
index 8cefcaa..3ddb88a 100644
--- a/src/form/input.js
+++ b/src/form/input.js
@@ -4,15 +4,27 @@
* @date 2023/03/06 15:17:25
*/
-import { nextTick, css, html, Component } from '@bd/core'
+import {
+ nextTick,
+ css,
+ html,
+ Component,
+ classMap,
+ outsideClick
+} from '@bd/core'
import '../icon/index.js'
+import '../scroll/index.js'
+const ANIMATION = {
+ duration: 100,
+ custom: [{ transform: 'scaleY(0)' }, { transform: 'scaleY(1)' }]
+}
class Input extends Component {
static props = {
readOnly: false,
autofocus: false,
disabled: false,
- closeable: false,
+ clearable: false,
icon: '',
size: 'l',
placeholder: '',
@@ -25,11 +37,16 @@ class Input extends Component {
},
lazy: 0 // 并发拦截时间, 单位毫秒
}
-
+ #list = []
+ #originList = []
+ #isComposing = false
+ #selectIndex = -1
+ #listShowing = false
+ #stamp = 0
static styles = [
css`
:host {
- overflow: hidden;
+ position: relative;
display: inline-flex;
min-width: 228px;
height: 36px;
@@ -109,25 +126,28 @@ class Input extends Component {
.suggestion {
overflow: hidden;
- display: none;
- position: fixed;
- z-index: 10240;
+ position: absolute;
+ z-index: 1;
left: 0;
- top: 0;
- width: 200px;
+ top: calc(100% + 4px);
+ width: 100%;
height: auto;
max-height: 200px;
- min-height: 46px;
padding: 4px 0;
border-radius: 4px;
- background: var(--color-plain-1);
+ // background: var(--color-plain-1);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
-
+ transform-origin: top;
+ // transition: transform linear 00s;
+ // transform: scaleY(0);
+ wc-scroll {
+ max-height: 200px;
+ }
.list {
width: 100%;
}
- &.show {
- display: flex;
+ &.hide {
+ display: none;
}
li {
@@ -349,6 +369,11 @@ class Input extends Component {
}
render() {
+ let classes = classMap({
+ suggestion: true,
+ hide: !this.#list.length
+ })
+
return html`
@@ -356,7 +381,10 @@ class Input extends Component {
ref="input"
@input=${this.onInput}
@change=${this.onChange}
+ @compositionstart=${this.onCompositionstart}
+ @compositionend=${this.onCompositionend}
@keydown=${this.onKeyDown}
+ @focus=${this.onFocus}
placeholder=${this.placeholder}
maxlength=${this.maxlength}
minlength=${this.minlength}
@@ -365,26 +393,129 @@ class Input extends Component {
autofocus=${this.autofocus}
:value=${this.value}
/>
- ${this.closeable && this.value ? this.renderClose() : ''}
+ ${this.clearable && this.value ? this.renderClose() : ''}
${this.icon
? html`
`
: html`
`}
+
+
+
+ ${this.#list.map(
+ (li, idx) =>
+ html`-
+ ${li.value}
+
`
+ )}
+
+
+
`
}
+ onCompositionstart() {
+ this.#isComposing = true
+ }
+ onCompositionend() {
+ this.#isComposing = false
+ this.filterSuggestList()
+ }
+ filterSuggestList() {
+ if (!this.#originList.length) {
+ return
+ }
+ if (!this.value) {
+ this.#list = this.#originList
+ } else {
+ this.#list = this.#originList.filter(li =>
+ li.value.startsWith(this.value)
+ )
+ }
+ if (!this.#listShowing) {
+ this.#listShowing = true
+ this.$refs.suggestion.$animate()
+ }
+ this.$requestUpdate()
+ }
onInput(e) {
+ let { lazy } = this
this.value = e.currentTarget.value
+ if (lazy && Date.now() - this.#stamp < lazy) {
+ return
+ }
+ this.#stamp = Date.now()
+ if (!this.#isComposing) {
+ this.filterSuggestList()
+ this.$emit('fetch-suggest', {
+ value: this.value,
+ send: list => {
+ this.#originList = this.#list = list
+ this.$requestUpdate()
+ }
+ })
+ }
+ }
+ onClick(e) {
+ let index = e.target.getAttribute('index')
+ this.value = this.#list[index].value
+ this.#list = [this.#list[index]]
+ this.$refs.suggestion.$animate(true)
+ this.#listShowing = false
}
onClickClose() {
this.$refs.input.value = ''
this.value = ''
+ if (this.#originList.length) {
+ this.filterSuggestList()
+ }
}
onChange() {
this.$emit('change')
}
onKeyDown(e) {
+ let { lazy, minlength, value } = this
if (e.keyCode === 13) {
- this.$emit('submit')
+ e.preventDefault()
+ if (this.#selectIndex > -1 && this.#listShowing) {
+ this.value = this.#list[this.#selectIndex].value
+ this.#list = [this.#list[this.#selectIndex]]
+ this.#selectIndex = 0
+ this.$requestUpdate()
+ this.$refs.suggestion.$animate(true)
+ this.#listShowing = false
+ return this.$emit('select') //输入建议存在,则第1次回车的时候, 不触发提交
+ }
+ if (lazy && Date.now() - this.#stamp < lazy) {
+ return
+ }
+ this.#stamp = Date.now()
+ if (minlength && value.length < minlength) {
+ return
+ }
+ return this.$emit('submit')
+ }
+ if (e.keyCode === 38 || e.keyCode === 40) {
+ e.preventDefault()
+ let step = e.keyCode === 38 ? -1 : 1
+
+ this.#selectIndex += step
+ if (this.#selectIndex < 0) {
+ this.#selectIndex = 0
+ }
+ if (this.#selectIndex > this.#list.length - 1) {
+ this.#selectIndex = this.#list.length - 1
+ }
+ let target = this.$refs.list.children[this.#selectIndex]
+ this.$refs.scroller.scrollTop = target.offsetTop - 150
+ this.$requestUpdate()
+ }
+ }
+ onFocus() {
+ if (!this.#listShowing) {
+ this.#listShowing = true
+ this.$refs.suggestion.$animate()
}
}
mounted() {
@@ -392,6 +523,10 @@ class Input extends Component {
// 火狐浏览器需要手动focus()才能聚焦成功
nextTick(_ => this.$refs.input.focus())
}
+ outsideClick(this, () => {
+ this.#listShowing = false
+ this.$refs.suggestion.$animate(true)
+ })
}
}