init
This commit is contained in:
54
src/component/textarea/index.less
Normal file
54
src/component/textarea/index.less
Normal file
@@ -0,0 +1,54 @@
|
||||
:root {
|
||||
--textarea-border-radius: var(--global-border-radius);
|
||||
--textarea-border-color: var(--global-neutral-color-3);
|
||||
}
|
||||
|
||||
.layui-textarea {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
background-color: #fff;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
border-radius: var(--textarea-border-radius);
|
||||
border-color: var(--textarea-border-color);
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
line-height: 20px;
|
||||
min-height: 100px;
|
||||
padding: 6px 10px;
|
||||
resize: vertical;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layui-textarea-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layui-textarea:hover,
|
||||
.layui-textarea:focus {
|
||||
border-color: #d2d2d2 !important;
|
||||
}
|
||||
|
||||
.layui-textarea-clear {
|
||||
position: absolute;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.layui-textarea::-webkit-input-placeholder {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.layui-texterea-count {
|
||||
color: inherit;
|
||||
white-space: nowrap;
|
||||
pointer-events: none;
|
||||
text-align: right;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.layui-textarea-disabled {
|
||||
cursor: not-allowed !important;
|
||||
opacity: 0.6;
|
||||
}
|
||||
5
src/component/textarea/index.ts
Normal file
5
src/component/textarea/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { withInstall, WithInstallType } from "../../utils";
|
||||
import Component from "./index.vue";
|
||||
|
||||
const component: WithInstallType<typeof Component> = withInstall(Component);
|
||||
export default component;
|
||||
107
src/component/textarea/index.vue
Normal file
107
src/component/textarea/index.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "LayTextarea",
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LayIcon } from "@layui/icons-vue";
|
||||
import { computed, ref } from "vue";
|
||||
import "./index.less";
|
||||
|
||||
export interface TextareaProps {
|
||||
name?: string;
|
||||
modelValue?: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
showCount?: boolean;
|
||||
allowClear?: boolean;
|
||||
maxlength?: number;
|
||||
}
|
||||
|
||||
const props = defineProps<TextareaProps>();
|
||||
|
||||
interface TextareaEmits {
|
||||
(e: "blur", event: Event): void;
|
||||
(e: "input", value: string): void;
|
||||
(e: "update:modelValue", value: string): void;
|
||||
(e: "change", value: string): void;
|
||||
(e: "focus", event: Event): void;
|
||||
(e: "clear"): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<TextareaEmits>();
|
||||
const composing = ref(false);
|
||||
|
||||
const onInput = function (event: Event) {
|
||||
const inputElement = event.target as HTMLInputElement;
|
||||
emit("input", inputElement.value);
|
||||
if (composing.value) {
|
||||
return;
|
||||
}
|
||||
emit("update:modelValue", inputElement.value);
|
||||
};
|
||||
|
||||
const onFocus = function (event: Event) {
|
||||
emit("focus", event);
|
||||
};
|
||||
|
||||
const onBlur = function (event: Event) {
|
||||
emit("blur", event);
|
||||
};
|
||||
|
||||
const onChange = (event: Event) => {
|
||||
const inputElement = event.target as HTMLInputElement;
|
||||
emit("change", inputElement.value);
|
||||
};
|
||||
|
||||
const onClear = function () {
|
||||
emit("update:modelValue", "");
|
||||
emit("clear");
|
||||
};
|
||||
|
||||
const onCompositionstart = () => {
|
||||
composing.value = true;
|
||||
};
|
||||
|
||||
const onCompositionend = (event: Event) => {
|
||||
composing.value = false;
|
||||
onInput(event);
|
||||
};
|
||||
|
||||
const hasContent = computed(() => (props.modelValue as string)?.length > 0);
|
||||
|
||||
const wordCount = computed(() => {
|
||||
let count = String(props.modelValue?.length ?? 0);
|
||||
if (props.maxlength) {
|
||||
count += "/" + props.maxlength;
|
||||
}
|
||||
return count;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="layui-textarea-wrapper">
|
||||
<textarea
|
||||
class="layui-textarea"
|
||||
:value="modelValue"
|
||||
:placeholder="placeholder"
|
||||
:name="name"
|
||||
:disabled="disabled"
|
||||
:maxlength="maxlength"
|
||||
:class="{ 'layui-textarea-disabled': disabled }"
|
||||
@compositionstart="onCompositionstart"
|
||||
@compositionend="onCompositionend"
|
||||
@input="onInput"
|
||||
@focus="onFocus"
|
||||
@change="onChange"
|
||||
@blur="onBlur"
|
||||
></textarea>
|
||||
<span class="layui-textarea-clear" v-if="allowClear && hasContent">
|
||||
<lay-icon type="layui-icon-close-fill" @click="onClear"></lay-icon>
|
||||
</span>
|
||||
<div v-if="showCount" class="layui-texterea-count">
|
||||
{{ wordCount }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
0
src/component/textarea/interface.ts
Normal file
0
src/component/textarea/interface.ts
Normal file
Reference in New Issue
Block a user