diff --git a/src/form/textarea.js b/src/form/textarea.js new file mode 100644 index 0000000..27ada78 --- /dev/null +++ b/src/form/textarea.js @@ -0,0 +1,220 @@ +/** + * {文本域组件} + * @author yutent + * @date 2023/03/18 14:14:25 + */ + +import { css, html, Component, nextTick } from '@bd/core' + +class TextArea extends Component { + static props = { + value: { + type: String, + default: '', + attributes: false + }, + type: '', + autofocus: false, + readOnly: false, + disabled: false, + maxlength: null, + minlength: null, + 'show-limit': false, + lazy: 0 // 并发拦截时间, 单位毫秒 + } + + static styles = [ + // 基础样式 + css` + :host { + display: flex; + width: 100%; + height: 80px; + user-select: none; + -moz-user-select: none; + color: var(--color-dark-1); + border-radius: 3px; + cursor: text; + transition: box-shadow 0.15s linear; + } + + .label { + position: relative; + width: 100%; + height: 100%; + font-size: 14px; + border: 1px solid var(--color-grey-2); + border-radius: inherit; + background: var(--bg-color, #fff); + color: inherit; + cursor: inherit; + + textarea { + flex: 1; + min-width: 36px; + width: 100%; + height: 100%; + padding: 5px 8px; + border: 0; + border-radius: inherit; + color: inherit; + font: inherit; + background: none; + outline: none; + box-shadow: none; + cursor: inherit; + resize: none; + + &::placeholder { + color: var(--color-grey-1); + } + } + + .input-stat { + display: none; + position: absolute; + right: 4px; + bottom: 2px; + z-index: 1; + line-height: 1; + font-size: 12px; + color: var(--color-grey-2); + } + } + + :host([show-limit]) { + .label { + padding-bottom: 14px; + + .input-stat { + display: block; + } + } + } + + /* --- */ + + :host([disabled]) { + cursor: not-allowed; + + .label { + background: var(--color-plain-1); + opacity: 0.6; + } + } + + :host([readonly]) { + cursor: default; + } + + /* ----- 类型(颜色) ----- */ + :host(:focus-within) { + box-shadow: 0 0 0 2px var(--color-plain-a); + } + :host([type='primary']:focus-within) { + box-shadow: 0 0 0 2px var(--color-teal-a); + } + :host([type='info']:focus-within) { + box-shadow: 0 0 0 2px var(--color-blue-a); + } + :host([type='success']:focus-within) { + box-shadow: 0 0 0 2px var(--color-green-a); + } + :host([type='danger']:focus-within) { + box-shadow: 0 0 0 2px var(--color-red-a); + } + :host([type='warning']:focus-within) { + box-shadow: 0 0 0 2px var(--color-orange-a); + } + + :host([type='primary']) .label { + border-color: var(--color-teal-2); + } + :host([type='info']) .label { + border-color: var(--color-blue-2); + } + :host([type='success']) .label { + border-color: var(--color-green-2); + } + :host([type='danger']) .label { + border-color: var(--color-red-2); + } + :host([type='warning']) .label { + border-color: var(--color-orange-2); + } + + :host([no-border]), + :host(:focus-within[no-border]) { + box-shadow: none; + .label { + border: 0; + } + } + ` + ] + onInput(e) { + this.value = e.target.value + } + onKeydown(ev) { + // console.log(ev.target) + let { minlength, lazy } = this + let val = this.value + let now = Date.now() + + // 回车触发submit事件 + // 要按Ctrl Or Cmd键, 才会触发 + if (ev.keyCode === 13 && (ev.ctrlKey || ev.metaKey)) { + // + if (this.disabled || this.readOnly) { + return + } + + // 并发拦截 + if (lazy && now - this.stamp < lazy) { + return + } + if (minlength && minlength > 0) { + if (val.length < minlength) { + return + } + } + + this.stamp = now + this.$emit('submit', { value: this.value }) + } + } + onChange(e) { + this.$emit(e.type) + } + render() { + return html` +
+ + ${this['show-limit'] + ? html`
+ ${this.value.length}/${this.maxlength || '∞'} +
` + : ''} +
+ ` + } + mounted() { + if (this.autofocus) { + // 火狐浏览器需要手动focus()才能聚焦成功 + nextTick(_ => this.$refs.textarea.focus()) + } + } +} + +customElements.define('wc-textarea', TextArea)