mirror of https://github.com/halo-dev/halo
parent
ee0fa26c8b
commit
239e1a11da
|
@ -0,0 +1,73 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
rows: {
|
||||||
|
type: Number,
|
||||||
|
default: 3,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:modelValue"]);
|
||||||
|
|
||||||
|
function handleInput(e: Event) {
|
||||||
|
const { value } = e.target as HTMLInputElement;
|
||||||
|
emit("update:modelValue", value);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="textarea-wrapper">
|
||||||
|
<textarea
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:value="modelValue"
|
||||||
|
@input="handleInput"
|
||||||
|
:disabled="disabled"
|
||||||
|
:rows="rows"
|
||||||
|
>
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss">
|
||||||
|
.textarea-wrapper {
|
||||||
|
@apply box-border;
|
||||||
|
@apply relative;
|
||||||
|
@apply w-full;
|
||||||
|
@apply inline-flex;
|
||||||
|
textarea {
|
||||||
|
@apply outline-0;
|
||||||
|
@apply bg-white;
|
||||||
|
@apply antialiased;
|
||||||
|
@apply w-full;
|
||||||
|
@apply text-black;
|
||||||
|
@apply block;
|
||||||
|
@apply transition-all;
|
||||||
|
@apply appearance-none;
|
||||||
|
|
||||||
|
@apply p-3;
|
||||||
|
@apply text-sm;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
border-color: #4ccba0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #4ccba0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
@apply opacity-50;
|
||||||
|
@apply cursor-not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
import { VTextarea } from "../index";
|
||||||
|
import { mount } from "@vue/test-utils";
|
||||||
|
|
||||||
|
describe("Textarea", () => {
|
||||||
|
it("should render", function () {
|
||||||
|
expect(VTextarea).toBeDefined();
|
||||||
|
expect(mount(VTextarea).html()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work with placeholder prop", async function () {
|
||||||
|
const textarea = mount(VTextarea);
|
||||||
|
expect(
|
||||||
|
textarea.find("textarea").attributes()["placeholder"]
|
||||||
|
).toBeUndefined();
|
||||||
|
|
||||||
|
// set placeholder prop
|
||||||
|
const placeholderText = "Please enter your text";
|
||||||
|
await textarea.setProps({ placeholder: placeholderText });
|
||||||
|
expect(textarea.find("textarea").attributes()["placeholder"]).toBe(
|
||||||
|
placeholderText
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work with disabled prop", async function () {
|
||||||
|
const textarea = mount(VTextarea);
|
||||||
|
expect(textarea.find("textarea").attributes()["disabled"]).toBeUndefined();
|
||||||
|
|
||||||
|
// set disabled prop
|
||||||
|
await textarea.setProps({ disabled: true });
|
||||||
|
expect(textarea.find("textarea").attributes()["disabled"]).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work with rows prop", function () {
|
||||||
|
const textarea = mount(VTextarea, {
|
||||||
|
propsData: {
|
||||||
|
rows: 5,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(textarea.find("textarea").attributes()["rows"]).toBe("5");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work with v-model", async function () {
|
||||||
|
const wrapper = mount({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: "my name is ryanwang",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<v-textarea v-model="value" />
|
||||||
|
`,
|
||||||
|
components: { VTextarea },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.find("textarea").element.value).toBe("my name is ryanwang");
|
||||||
|
|
||||||
|
// change value
|
||||||
|
await wrapper.setData({
|
||||||
|
value: "my name is ryanwang, my website is https://ryanc.cc",
|
||||||
|
});
|
||||||
|
expect(wrapper.find("textarea").element.value).toBe(
|
||||||
|
"my name is ryanwang, my website is https://ryanc.cc"
|
||||||
|
);
|
||||||
|
|
||||||
|
// change modelValue by textarea element value
|
||||||
|
await wrapper.find("textarea").setValue("my name is ryanwang");
|
||||||
|
expect(wrapper.vm.$data.value).toBe("my name is ryanwang");
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,6 @@
|
||||||
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
|
exports[`Textarea > should render 1`] = `
|
||||||
|
"<div class=\\"textarea-wrapper\\"><textarea rows=\\"3\\">
|
||||||
|
</textarea></div>"
|
||||||
|
`;
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as VTextarea } from "./Textarea.vue";
|
|
@ -77,6 +77,19 @@
|
||||||
<VInput v-model="inputValue" disabled />
|
<VInput v-model="inputValue" disabled />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section class="box border-2 rounded p-2 mb-3">
|
||||||
|
<h1 class="text-xl font-bold mb-2">Textarea</h1>
|
||||||
|
<div class="mb-3">
|
||||||
|
<VTextarea
|
||||||
|
v-model="inputValue"
|
||||||
|
placeholder="Please input your description"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h2 class="mb-1">Disabled:</h2>
|
||||||
|
<div class="mb-3">
|
||||||
|
<VTextarea v-model="inputValue" disabled :rows="4" />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
<section class="box border-2 rounded p-2">
|
<section class="box border-2 rounded p-2">
|
||||||
<h1 class="text-xl font-bold mb-2">Select</h1>
|
<h1 class="text-xl font-bold mb-2">Select</h1>
|
||||||
<h2 class="mb-1">Size:</h2>
|
<h2 class="mb-1">Size:</h2>
|
||||||
|
@ -113,6 +126,7 @@ import { FilledLayout } from "../layouts";
|
||||||
import { VButton } from "@/components/base/button";
|
import { VButton } from "@/components/base/button";
|
||||||
import { VInput } from "@/components/base/input";
|
import { VInput } from "@/components/base/input";
|
||||||
import { VSelect, VOption } from "@/components/base/select";
|
import { VSelect, VOption } from "@/components/base/select";
|
||||||
|
import { VTextarea } from "@/components/base/textarea";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
||||||
const inputValue = ref();
|
const inputValue = ref();
|
||||||
|
|
Loading…
Reference in New Issue