mp-colorui
Version:
MP ColorUI 是一款基于 Taro 框架并且联合 Color-UI CSS 库开发的多端 UI 组件库(支持小程序端和H5端)
233 lines (227 loc) • 8.55 kB
JavaScript
import Nerv from "nervjs";
var _this = this;
import { Image, Input, View, ScrollView } from "@tarojs/components";
import Taro, { createSelectorQuery as _createSelectorQuery } from "@tarojs/taro-h5";
import ClButton from "../button/index";
import ClIcon from "../icon/index";
import "./index.scss";
import { classNames, screenPercent } from "../../lib/index";
import ClSearchResult from "../searchBar/searchResult/index";
import ClCard from "../card/index";
class ClInput extends Taro.Component {
render() {
const props = this.props;
const [focus, setFocus] = Taro.useState(false);
const [normalType, setNormalType] = Taro.useState();
const [tempInput, setTempInput] = Taro.useState("");
const [initValue, setInitValue] = Taro.useState(props.value);
const [inputId, setInputId] = Taro.useState(`cl-input-${+new Date()}`);
const [materialWidth, setMaterialWidth] = Taro.useState("0px");
const [defaultValue, setDefaultValue] = Taro.useState(props.defaultValue);
const [showComplete, setShowComplete] = Taro.useState(false);
const [firstInit, setFirstInit] = Taro.useState(true);
Taro.useMemo(() => {
if (props.defaultValue !== "" && defaultValue === "") {
setDefaultValue(defaultValue);
}
}, [props.defaultValue]);
const isH5 = Taro.ENV_TYPE.WEB === Taro.getEnv();
const onChange = event => {
setFirstInit(false);
let input = event.detail.value;
setInitValue(input);
props.autoComplete && setShowComplete(true);
if (props.type === "number") {
if (Taro.ENV_TYPE.WEB === Taro.getEnv()) {
if (!isNaN(event.data - 0)) {
if (event.data === null) {
input = tempInput.slice(0, tempInput.length - 1);
} else {
input = tempInput + parseInt(`${event.data - 0}`);
}
} else {
input = tempInput;
}
setTempInput(input);
setTimeout(() => {
setInitValue(input);
});
} else {
input = !isNaN(event.detail.value - 0) ? event.detail.value : null;
if (input !== null) {
setTempInput(input);
setInitValue(input);
} else {
setTimeout(() => {
setInitValue(tempInput);
});
}
}
} else if (props.type === "digit") {
if (Taro.ENV_TYPE.WEB === Taro.getEnv()) {
if (!isNaN(event.data - 0)) {
if (event.data === null) {
input = tempInput.slice(0, tempInput.length - 1);
} else {
input = tempInput + parseInt(`${event.data - 0}`);
}
} else {
input = event.data === "." && tempInput.indexOf(".") === -1 ? tempInput + event.data : tempInput;
}
setTempInput(input);
setTimeout(() => {
setInitValue(input);
});
} else {
input = !isNaN(event.detail.value - 0) ? event.detail.value : null;
if (input !== null) {
setTempInput(input);
setInitValue(input);
} else {
setTimeout(() => {
setInitValue(tempInput);
});
}
}
} else {
setInitValue(input);
}
props.onChange && props.onChange(input);
};
const onBlur = event => {
setFocus(false);
props.onBlur && props.onBlur(event.detail.value);
};
const onFocus = event => {
setFocus(true);
props.onFocus && props.onFocus(event.detail.value);
};
const onIconClick = event => {
props.onIconClick && props.onIconClick(event);
};
const onImageClick = event => {
props.onImageClick && props.onImageClick(event);
};
if (props.type !== "password") {
if (props.type !== normalType) {
setNormalType(props.type);
}
}
const iconComponent = props.icon ? <View onClick={onIconClick}>
<ClIcon {...props.icon} />
</View> : "";
const buttonComponent = props.button ? <ClButton {...props.button} /> : "";
const imageComponent = props.image ? <View onClick={onImageClick} style={{}}>
<Image src={props.image || ""} mode="aspectFit" style={{
maxWidth: Taro.pxTransform(100),
maxHeight: Taro.pxTransform(100)
}} />
</View> : "";
const autoCompleteComponent = props.autoComplete ? <View style={{
position: "absolute",
top: Taro.pxTransform(100),
left: Taro.pxTransform(0),
width: `100%`,
display: showComplete ? "" : "none"
}}>
<ClCard shadow={false} bgColor={this.props.bgColor} type="full">
<ScrollView scrollY style={{ maxHeight: "300px" }}>
<ClSearchResult showLoading={props.completeLoading} result={props.completes ? props.completes.map(str => ({
title: str
})) : []} onTouchResult={index => {
if (props.completes) {
setInitValue(props.completes[index]);
setTempInput(props.completes[index]);
props.onTouchResult && props.onTouchResult(props.completes[index], index);
}
setShowComplete(false);
}} />
</ScrollView>
</ClCard>
</View> : "";
let { title, placeholder, value, adjustPosition, type, maxLength, disabled, renderCustomRight, autoFocus } = props;
let titleWidth = props.titleWidth === "auto" ? {} : {
width: Taro.pxTransform(props.titleWidth || 200)
};
Taro.useMemo(() => {
setInitValue(value);
}, [props.value]);
Taro.useEffect(() => {
if (props.pattern === "material") {
if (isH5) {
const content = document.querySelector(`#${inputId}`);
const width = content.clientWidth;
setMaterialWidth(Taro.pxTransform(width / screenPercent));
} else {
const query = _createSelectorQuery().in(this.$scope);
const view = query.select("#cl-input");
view.boundingClientRect().exec(res => {
const data = res[0];
setMaterialWidth(Taro.pxTransform(data.width / screenPercent));
});
}
}
}, [props.title]);
const renderMaterialTitle = <View className={`${focus || initValue ? "materialFocus" : "materialBlur"}`} style={titleWidth} id="cl-input">
{title}
</View>;
const renderMaterialTitle_H5 = <View className={`${focus || initValue ? "materialFocus" : "materialBlur"}`} style={titleWidth} id={inputId}>
{title}
</View>;
const normalTitle = <View className="title" style={titleWidth}>
{title}
</View>;
return <View className={classNames(`cu-form-group ${focus ? "focus" : "blur"}`, props.className)} style={Object.assign({ position: "relative" }, props.style)}>
{title && props.pattern === "normal" ? normalTitle : ""}
{title && props.pattern === "material" ? isH5 ? renderMaterialTitle_H5 : renderMaterialTitle : ""}
<View style={{
position: "relative",
display: "flex",
width: "100%",
alignItems: "center",
flex: 1
}}>
<Input autoFocus={autoFocus} placeholder={placeholder} value={firstInit && defaultValue ? defaultValue : initValue} onInput={onChange} onBlur={onBlur} onFocus={onFocus} adjustPosition={adjustPosition} type={normalType} password={type === "password"} maxLength={maxLength || -1} disabled={disabled} style={{
textAlign: props.align,
flex: "1 0 auto",
paddingLeft: `${props.pattern === "material" && !(focus || initValue) ? materialWidth : 0}`,
paddingRight: props.clear ? Taro.pxTransform(60) : ""
}} />
<View style={{
position: "absolute",
right: 0,
display: props.clear && initValue !== "" && !firstInit ? "relative" : "none"
}} onClick={e => {
e.stopPropagation();
setInitValue("");
}}>
<ClIcon iconName="roundclosefill" size="xsmall" color="gray" />
</View>
</View>
{iconComponent}
{buttonComponent}
{imageComponent}
{renderCustomRight}
{autoCompleteComponent}
</View>;
}
}
ClInput.options = {
addGlobalClass: true
};
ClInput.defaultProps = {
autoFocus: false,
titleWidth: "auto",
align: "left",
pattern: "normal",
value: undefined,
placeholder: "",
type: "text",
adjustPosition: true,
defaultValue: "",
completeLoading: false,
completes: [],
autoComplete: false,
onTouchResult: () => {}
};
export default ClInput;