增加textarea组件

master
chenjiajian 2023-03-18 14:14:39 +08:00
parent ee1c91bfa0
commit dd77738f6c
1 changed files with 220 additions and 0 deletions

220
src/form/textarea.js Normal file
View File

@ -0,0 +1,220 @@
/**
* {文本域组件}
* @author yutent<yutent.io@gmail.com>
* @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`
<div class="label">
<textarea
ref="textarea"
spellcheck="false"
readonly=${this.readOnly}
disabled=${this.disabled}
maxlength=${this.maxlength}
minlength=${this.minlength}
autofocus=${this.autofocus}
@input=${this.onInput}
@keydown=${this.onKeydown}
@change=${this.onChange}
></textarea>
${this['show-limit']
? html`<div class="input-stat">
${this.value.length}/${this.maxlength || '∞'}
</div>`
: ''}
</div>
`
}
mounted() {
if (this.autofocus) {
// 火狐浏览器需要手动focus()才能聚焦成功
nextTick(_ => this.$refs.textarea.focus())
}
}
}
customElements.define('wc-textarea', TextArea)