layui/.svn/pristine/ad/ad58b7e4119d7451ed1d771f6584acc1c7763973.svn-base
2022-12-09 16:41:41 +08:00

207 lines
5.0 KiB
Plaintext

<script lang="ts">
export default {
name: "LayInput",
};
</script>
<script setup lang="ts">
import "./index.less";
import { LayIcon } from "@layui/icons-vue";
import { computed, ref, useSlots, watch } from "vue";
import PasswordIcon from "./svg/Password.vue";
import UnPasswordIcon from "./svg/unPassword.vue";
import { InputSize } from "./interface";
export interface InputProps {
name?: string;
type?: string;
prefixIcon?: string;
suffixIcon?: string;
modelValue?: string | number | string[] | undefined;
allowClear?: boolean;
autocomplete?: string;
placeholder?: string;
autofocus?: boolean;
disabled?: boolean;
readonly?: boolean;
password?: boolean;
size?: InputSize;
maxlength?: number;
max?: number;
min?: number;
}
const props = withDefaults(defineProps<InputProps>(), {
disabled: false,
readonly: false,
allowClear: false,
autofocus: false,
password: false,
modelValue: "",
size: "md",
});
interface InputEmits {
(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<InputEmits>();
const slots = useSlots();
const type = ref(props.type);
const currentValue = ref<string>(
String(props.modelValue == null ? "" : props.modelValue)
);
const hasContent = computed(() => (props.modelValue as string)?.length > 0);
const isPassword = computed(() => type.value == "password");
const composing = ref(false);
watch(
() => props.type,
() => {
type.value = props.type;
}
);
watch(
() => props.modelValue,
() => {
currentValue.value = String(
props.modelValue == null ? "" : props.modelValue
);
}
);
const onInput = function (event: Event) {
const inputElement = event.target as HTMLInputElement;
const value = inputElement.value;
emit("input", value);
if (composing.value) return;
emit("update:modelValue", value);
};
const onClear = () => {
emit("update:modelValue", "");
emit("clear");
};
const onFocus = (event: Event) => {
emit("focus", event);
};
const onChange = (event: Event) => {
const inputElement = event.target as HTMLInputElement;
const value = inputElement.value;
emit("change", value);
};
const onBlur = (event: Event) => {
if (props.type === "number") {
onNumberBlur(event);
}
emit("blur", event);
};
const onNumberBlur = (event: Event) => {
let value = (event.target as HTMLInputElement).value;
if (value === "") {
value = props.min ? String(props.min) : "0";
} else {
if (props.max && props.max < Number(value)) value = props.max.toString();
if (props.min && props.min > Number(value)) value = props.min.toString();
}
emit("update:modelValue", value);
};
const onCompositionstart = () => {
composing.value = true;
};
const onCompositionend = (event: Event) => {
composing.value = false;
onInput(event);
};
const classes = computed(() => {
return {
"layui-input-disabled": props.disabled,
"layui-input-has-prefix": slots.prefix || props.prefixIcon,
};
});
const showPassword = () => {
if (isPassword.value) {
type.value = "text";
} else {
type.value = "password";
}
};
</script>
<template>
<div class="layui-input" :class="classes" :size="size">
<div class="layui-input-prepend" v-if="slots.prepend">
<slot name="prepend"></slot>
</div>
<div class="layui-input-wrapper">
<span class="layui-input-prefix" v-if="slots.prefix || props.prefixIcon">
<slot name="prefix" v-if="slots.prefix"></slot>
<lay-icon
v-else
:type="props.prefixIcon"
class="layui-input-prefix-icon"
></lay-icon>
</span>
<input
:type="type"
:name="name"
:disabled="disabled"
:placeholder="placeholder"
:autofocus="autofocus"
:autocomplete="autocomplete"
:maxlength="maxlength"
:max="max"
:min="min"
:readonly="readonly"
:value="currentValue"
@input="onInput"
@change="onChange"
@focus="onFocus"
@blur="onBlur"
@compositionstart="onCompositionstart"
@compositionend="onCompositionend"
/>
<span
class="layui-input-password"
@click="showPassword"
v-if="password && hasContent"
>
<password-icon v-if="isPassword"></password-icon>
<un-password-icon v-else></un-password-icon>
</span>
<span
class="layui-input-clear"
v-if="allowClear && hasContent && !disabled"
>
<lay-icon type="layui-icon-close-fill" @click.stop="onClear"></lay-icon>
</span>
<span class="layui-input-suffix" v-if="slots.suffix || props.suffixIcon">
<slot name="suffix" v-if="slots.suffix"></slot>
<lay-icon
v-else
:type="props.suffixIcon"
class="layui-input-suffix-icon"
></lay-icon>
</span>
</div>
<div class="layui-input-append" v-if="slots.append">
<slot name="append"></slot>
</div>
</div>
</template>