diff --git a/packages/devui-vue/devui/textarea/__tests__/textarea.spec.ts b/packages/devui-vue/devui/textarea/__tests__/textarea.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..d064cdf1ccf9b3be1ab6441e992962376667ae28 --- /dev/null +++ b/packages/devui-vue/devui/textarea/__tests__/textarea.spec.ts @@ -0,0 +1,8 @@ +import { mount } from '@vue/test-utils'; +import { Textarea } from '../index'; + +describe('textarea test', () => { + it('textarea init render', async () => { + // todo + }) +}) diff --git a/packages/devui-vue/devui/textarea/index.ts b/packages/devui-vue/devui/textarea/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..03e83245a0c71c9c6c29e274dbd948d1b7663085 --- /dev/null +++ b/packages/devui-vue/devui/textarea/index.ts @@ -0,0 +1,17 @@ +import type { App } from 'vue' +import Textarea from './src/textarea' + +Textarea.install = function(app: App): void { + app.component(Textarea.name, Textarea) +} + +export { Textarea } + +export default { + title: 'Textarea 多行文本框', + category: '数据录入', + status: '已完成', // TODO: 组件若开发完成则填入"已完成",并删除该注释 + install(app: App): void { + app.use(Textarea as any) + } +} diff --git a/packages/devui-vue/devui/textarea/src/textarea-types.ts b/packages/devui-vue/devui/textarea/src/textarea-types.ts new file mode 100644 index 0000000000000000000000000000000000000000..57acdbb2df3a0d9020db7d3495ac03f53449eac2 --- /dev/null +++ b/packages/devui-vue/devui/textarea/src/textarea-types.ts @@ -0,0 +1,48 @@ +import type { PropType, ExtractPropTypes } from 'vue'; + +export const textareaProps = { + id: { + type: String, + default: undefined, + }, + autofocus: { + type: Boolean, + default: false, + }, + showCount: { + type: Boolean, + default: false, + }, + placeholder: { + type: String, + default: undefined, + }, + value: { + type: String, + default: '', + }, + maxLength: { + type: [String, Number] as PropType, + default: undefined, + }, + disabled: { + type: Boolean, + default: false, + }, + error: { + type: Boolean, + default: false, + }, + cssClass: { + type: String, + default: '', + }, + resize: { + type: String as PropType< + 'none' | 'vertical' | 'horizontal' | 'both' | 'inherit' + >, + default: 'none', + }, +} as const; + +export type TextareaProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/textarea/src/textarea.scss b/packages/devui-vue/devui/textarea/src/textarea.scss new file mode 100644 index 0000000000000000000000000000000000000000..248db7309b1d239993d312c47666bf9c1ccbdf55 --- /dev/null +++ b/packages/devui-vue/devui/textarea/src/textarea.scss @@ -0,0 +1,11 @@ +@import '../../style/core/form'; + +.devui-textarea-wrap { + .devui-textarea-show-count { + text-align: right; + color: inherit; + white-space: nowrap; + pointer-events: none; + font-size: $devui-font-size; + } +} diff --git a/packages/devui-vue/devui/textarea/src/textarea.tsx b/packages/devui-vue/devui/textarea/src/textarea.tsx new file mode 100644 index 0000000000000000000000000000000000000000..52c3f77ae594bc645c47aee6c066df8325eafe1c --- /dev/null +++ b/packages/devui-vue/devui/textarea/src/textarea.tsx @@ -0,0 +1,89 @@ +import { defineComponent, ref } from "vue"; +import { textareaProps, TextareaProps } from "./textarea-types"; +import "./textarea.scss"; + +export default defineComponent({ + name: "DTextarea", + props: textareaProps, + emits: ["update:value", "focus", "blur", "change", "keydown"], + setup(props: TextareaProps, ctx) { + const textareaCls = { + error: props.error, + [props.cssClass]: true, + }; + + const curValueRef = ref(props.value); + const onInput = ($event: Event) => { + const inputValue = ($event.target as HTMLInputElement).value; + curValueRef.value = inputValue; + ctx.emit("update:value", inputValue); + }, + onFocus = ($event: Event) => { + ctx.emit("focus", $event); + }, + onBlur = ($event: Event) => { + ctx.emit("blur", $event); + }, + onChange = ($event: Event) => { + ctx.emit("change", ($event.target as HTMLInputElement).value); + }, + onKeydown = ($event: KeyboardEvent) => { + ctx.emit("keydown", $event); + }; + + return { + textareaCls, + onInput, + onFocus, + onBlur, + onChange, + onKeydown, + curValueRef, + autofocus: props.autofocus, + }; + }, + render() { + const { + id, + placeholder, + disabled, + maxLength, + resize, + textareaCls, + onInput, + onFocus, + onBlur, + onChange, + onKeydown, + showCount, + autofocus, + curValueRef, + } = this; + return ( +
+ + {showCount && ( +
+ {curValueRef.length} + {!(maxLength ?? false) ? "" : " / " + maxLength} +
+ )} +
+ ); + }, +}); diff --git a/packages/devui-vue/docs/components/textarea/index.md b/packages/devui-vue/docs/components/textarea/index.md new file mode 100644 index 0000000000000000000000000000000000000000..4ab5d3e00c72d612a3976937fe3cd1bab7bfb7c5 --- /dev/null +++ b/packages/devui-vue/docs/components/textarea/index.md @@ -0,0 +1,161 @@ +# Textarea 多行文本框 + +文本输入区域。 + +### 何时使用 + +需要手动输入文字,并且文字内容较多时使用。 + +### 基本用法 + +:::demo + +```vue + + +``` + +::: + +### 调整大小 + +:::demo + +```vue + +``` + +::: + +### 显示字数 + +:::demo + +```vue + + +``` + +::: + +### 事件响应 + +:::demo + +```vue + + +``` + +::: + +### d-textarea API + +d-textarea 参数 + +| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 | +| ----------- | --------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------ | --------------------- | ---------- | +| id | string | `-` | 可选,文本框 id | [基本用法](#基本用法) | | +| placeholder | string | `-` | 可选,文本框 placeholder | [基本用法](#基本用法) | | +| value | string | `-` | 可选,文本框默认值 | [基本用法](#基本用法) | | +| disabled | boolean | `false` | 可选,文本框是否被禁用 | [基本用法](#基本用法) | | +| autoFocus | boolean | `false` | 可选,文本框是否自动获得焦点 | [基本用法](#基本用法) | | +| error | boolean | `false` | 可选,文本框是否出现输入错误 | [基本用法](#基本用法) | | +| resize | `'none' \|'vertical' \|'horizontal' \|'both' \|'inherit'` | `'none'` | 可选,文本框是否可调整大小,可选项:不可调整,水平调整,垂直调整,自由调整,默认继承 | [调整大小](#调整大小) | | +| showCount | boolean | `false` | 可选,文本框是否是否展示字数 | [显示字数](#显示字数) | | + +d-textarea 事件 + +| 事件 | 类型 | 说明 | 跳转 Demo | +| ------- | ---------------------- | ------------------------------ | --------------------- | +| update | `EventEmitter` | 文本框内容变化(实时触发) | [事件响应](#事件响应) | +| focus | `EventEmitter` | 文本框获得焦点 | [事件响应](#事件响应) | +| blur | `EventEmitter` | 文本框失去焦点 | [事件响应](#事件响应) | +| change | `EventEmitter` | 文本框内容变化(失去焦点触发) | [事件响应](#事件响应) | +| keydown | `EventEmitter` | 文本框按下键盘 | [事件响应](#事件响应) |