kui-vue
Version:
A lightweight desktop UI component library suitable for Vue.js 2.
287 lines (272 loc) • 7.72 kB
JSX
import Icon from "../icon";
import { isEmpty } from "../utils/number";
import { Search, CloseCircle, EyeOutline, EyeOffOutline } from "kui-icons";
import InputGroup from "./inputGroup.jsx";
import { defineComponent, ref, nextTick, watch, inject, provide } from "vue";
import { withInstall } from "../utils/vue";
import InputBox from "./inputBox";
import { sizeMap, filterSize } from "../utils/size";
const Input = defineComponent({
name: "Input",
props: {
clearable: { type: Boolean, default: true },
visiblePasswordIcon: { type: Boolean, default: true },
size: {
type: String,
validator(value) {
return sizeMap.indexOf(value) >= 0;
},
},
value: { type: [String, Number, Array, Object] },
disabled: Boolean,
type: {
validator(value) {
return (
[
"text",
"textarea",
"password",
"url",
"email",
"date",
"search",
"hidden",
].indexOf(value) >= 0
);
},
default: "text",
},
icon: [String, Array],
suffix: String,
prefix: String,
theme: String,
shape: String,
formatter: Function,
parser: Function,
inputType: { type: String, default: "input" },
},
setup(ps, { slots, emit, attrs, expose, listeners }) {
const currentValue = ref(ps.value);
const focused = ref(false);
const showPassword = ref(false);
const inputRef = ref();
const parentSize = inject("size", null);
provide("size", ps.size || filterSize(parentSize));
watch(
() => ps.value,
(v) => {
currentValue.value = v;
}
);
const focus = () => {
inputRef?.value.focus();
};
const blur = () => {
inputRef?.value.blur();
};
expose({ focus, blur });
const clear = () => {
// emit("update:value", ""); // for 3
emit("input", "");
currentValue.value = "";
nextTick(() => {
focus();
});
};
const iconClick = () => {
!ps.disabled && emit("icon-click");
};
const togglePassword = (e) => {
if (ps.disabled) return;
showPassword.value = !showPassword.value;
// let type = showPassword.value ? "text" : "password";
// inputRef.value.type = type;
};
const searchEvent = (e) => {
if (ps.disabled) return;
emit("search", currentValue.value);
};
const getSuffix = () => {
let { suffix, visiblePasswordIcon, type, inputType } = ps;
const SearchNode =
"search" in listeners ? (
<Icon
type={Search}
class="k-input-search-icon"
onClick={searchEvent}
/>
) : null;
const Password =
type == "password" && visiblePasswordIcon ? (
<Icon
class="k-input-password-icon"
type={!showPassword.value ? EyeOutline : EyeOffOutline}
onClick={togglePassword}
/>
) : null;
const suffixNode =
slots.suffix?.() ||
(suffix ? <div class="k-input-suffix">{suffix}</div> : null);
return Password || SearchNode || suffixNode;
};
return () => {
const {
icon,
size = filterSize(parentSize),
disabled,
type,
clearable,
suffix,
theme,
prefix,
shape,
inputType,
} = ps;
const slotSuffix = slots.suffix?.();
const slotPrefix = slots.prefix?.();
let multiple =
(icon ||
// attrs.onSearch ||
"search" in listeners ||
slotSuffix ||
suffix ||
slotPrefix ||
prefix ||
type == "password" ||
clearable ||
slots.controls) &&
type !== "hidden";
const inputProps = {
attrs: { ...attrs },
props: {
disabled,
multiple,
size,
type,
theme,
shape,
inputRef: inputRef,
inputType,
value: currentValue.value,
showPassword: showPassword.value,
},
on: {
...listeners,
input: (e) => {
let v = e.target.value;
currentValue.value = v;
emit("input", v);
},
focus: (e) => {
focused.value = true;
emit("focus", e);
},
blur: (e) => {
focused.value = false;
emit("blur", e);
},
},
};
let textInput = <InputBox {...inputProps} />;
if (!multiple) return textInput;
let clearableShow =
clearable &&
!isEmpty(currentValue.value) &&
type != "password" &&
attrs.readonly === undefined;
const props = {
class: {
[`k-${inputType}`]: true,
[`k-${inputType}-focus`]: focused.value,
[`k-${inputType}-disabled`]: disabled,
[`k-${inputType}-has-clear`]: clearableShow,
[`k-${inputType}-sm`]: size == "small",
[`k-${inputType}-lg`]: size == "large",
[`k-${inputType}-${theme}`]: theme && theme != "solid",
[`k-${inputType}-circle`]: shape == "circle",
},
};
// const prefixNode = prefix ? <div class={`k-input-prefix`}>{prefix}</div> : null;
if (slotPrefix || slotSuffix) {
const preChildren = [];
if (slotPrefix)
preChildren.push(
<div class="k-input-group-prefix">{slotPrefix}</div>
);
const innerChildren = [];
if (icon)
innerChildren.push(
<Icon
type={icon}
class={`k-${inputType}-icon`}
onClick={iconClick}
/>
);
if (prefix)
innerChildren.push(
<div class={`k-${inputType}-prefix`}>{prefix}</div>
);
innerChildren.push(textInput);
if (clearable)
innerChildren.push(
<Icon
type={CloseCircle}
class={[
`k-${inputType}-clearable`,
{ [`k-${inputType}-clearable-hidden`]: !clearableShow },
]}
onClick={clear}
/>
);
const sufChildren = [];
if (slotSuffix)
sufChildren.push(
<div class="k-input-group-suffix">{slotSuffix}</div>
);
if (slots.controls) innerChildren.push(slots.controls?.());
return (
<InputGroup size={size}>
{preChildren}
<div {...props} mult>
{innerChildren}
</div>
{sufChildren}
</InputGroup>
);
} else {
const suffixNode = getSuffix();
const children = [];
if (icon)
children.push(
<Icon
type={icon}
class={`k-${inputType}-icon`}
onClick={iconClick}
/>
);
if (prefix)
children.push(<div class={`k-${inputType}-prefix`}>{prefix}</div>);
children.push(textInput);
if (clearable)
children.push(
<Icon
type={CloseCircle}
class={[
`k-${inputType}-clearable`,
{ [`k-${inputType}-clearable-hidden`]: !clearableShow },
]}
onClick={clear}
/>
);
if (suffixNode) children.push(suffixNode);
if (slots.controls) children.push(slots.controls?.());
return (
<div {...props} mult>
{...children}
</div>
);
}
};
},
});
export default withInstall(Input);