vui-design
Version:
A high quality UI Toolkit based on Vue.js
273 lines (234 loc) • 6.45 kB
JavaScript
import VuiResizeObserver from "../resize-observer";
import VuiIcon from "../icon";
import Locale from "../../mixins/locale";
import PropTypes from "../../utils/prop-types";
import clone from "../../utils/clone";
import getClassNamePrefix from "../../utils/getClassNamePrefix";
import utils from "./utils";
export const createProps = () => {
return {
classNamePrefix: PropTypes.string,
placeholder: PropTypes.string,
value: PropTypes.array.def([]),
optionKeys: PropTypes.object.def(utils.optionKeys),
formatter: PropTypes.func.def((labels, options) => labels.join(" / ")),
searchable: PropTypes.bool.def(false),
keyword: PropTypes.string,
clearable: PropTypes.bool.def(false),
hovered: PropTypes.bool.def(false),
focused: PropTypes.bool.def(false),
disabled: PropTypes.bool.def(false)
};
};
export default {
name: "vui-cascader-selection",
inject: {
vuiCascader: {
default: undefined
}
},
componetns: {
VuiResizeObserver,
VuiIcon
},
mixins: [
Locale
],
props: createProps(),
methods: {
focus() {
const { $refs: references } = this;
if (references.input) {
references.input.focus();
}
},
blur() {
const { $refs: references } = this;
if (references.input) {
references.input.blur();
}
},
handleMouseenter(e) {
const { $props: props } = this;
if (props.disabled) {
return;
}
this.$emit("mouseenter", e);
},
handleMouseleave(e) {
const { $props: props } = this;
if (props.disabled) {
return;
}
this.$emit("mouseleave", e);
},
handleMousedown(e) {
const { $refs: references, $props: props } = this;
if (e.target === references.input || props.disabled) {
return;
}
this.focus();
e.preventDefault();
},
handleClick(e) {
const { $props: props } = this;
if (props.disabled) {
return;
}
this.$emit("click", e);
},
handleFocus(e) {
const { $props: props } = this;
if (props.disabled) {
return;
}
this.$emit("focus", e);
},
handleBlur(e) {
const { $props: props } = this;
if (props.disabled) {
return;
}
this.$emit("blur", e);
},
handleKeydown(e) {
const { $props: props } = this;
if (props.disabled) {
return;
}
this.$emit("keydown", e);
},
handleInput(e) {
const { $props: props } = this;
if (props.disabled) {
return;
}
this.$emit("input", e);
},
handleClear(e) {
const { $props: props } = this;
if (props.disabled) {
return;
}
this.$emit("clear", e);
e.stopPropagation();
},
handleResize() {
this.$emit("resize");
}
},
render() {
const { vuiCascader, $props: props, t: translate } = this;
const { handleMouseenter, handleMouseleave, handleMousedown, handleClick, handleFocus, handleBlur, handleKeydown, handleInput, handleClear, handleResize } = this;
// placeholder
const placeholder = props.placeholder || translate("vui.cascader.placeholder");
// showBtnClear
const showBtnClear = props.clearable && props.hovered && !props.disabled && (props.keyword || props.value.length > 0);
// class
const classNamePrefix = getClassNamePrefix(props.classNamePrefix, "selection");
let classes = {};
classes.el = `${classNamePrefix}`;
classes.elPlaceholder = `${classNamePrefix}-placeholder`;
classes.elValue = `${classNamePrefix}-value`;
classes.elInput = `${classNamePrefix}-input`;
classes.elArraw = `${classNamePrefix}-arrow`;
classes.elBtnClear = `${classNamePrefix}-btn-clear`;
// style
let styles = {};
styles.el = {};
styles.elValue = {};
styles.elPlaceholder = {};
styles.elInput = {};
if (props.disabled) {
styles.el.cursor = "not-allowed";
}
else if (props.focused) {
styles.el.cursor = "text";
}
else {
styles.el.cursor = "pointer";
}
if (props.keyword) {
styles.elValue.opacity = 0;
}
else if (props.focused) {
styles.elValue.opacity = 0.4;
}
else {
styles.elValue.opacity = 1;
}
if (props.value.length === 0) {
styles.elPlaceholder.display = "block";
styles.elPlaceholder.opacity = props.keyword ? 0 : 1;
}
else {
styles.elPlaceholder.display = "none";
styles.elPlaceholder.opacity = 0;
}
if (props.focused) {
styles.elInput.opacity = 1;
}
else {
styles.elInput.opacity = 0;
}
// render
let children = [];
if (props.value.length > 0) {
const labels = props.value.map(option => option[props.optionKeys.label]);
const value = props.formatter(labels, clone(props.value));
children.push(
<div key="value" class={classes.elValue} style={styles.elValue}>{value}</div>
);
}
children.push(
<div key="placeholder" class={classes.elPlaceholder} style={styles.elPlaceholder}>
{placeholder}
</div>
);
children.push(
<div key="input" class={classes.elInput} style={styles.elInput}>
<input
ref="input"
type="text"
autocomplete="off"
value={props.keyword}
readonly={!props.searchable}
disabled={props.disabled}
onFocus={handleFocus}
onBlur={handleBlur}
onKeydown={handleKeydown}
onCompositionstart={handleInput}
onCompositionupdate={handleInput}
onCompositionend={handleInput}
onInput={handleInput}
/>
</div>
);
if (showBtnClear) {
children.push(
<div key="btn-clear" class={classes.elBtnClear} onClick={handleClear}>
<VuiIcon type="crossmark-circle-filled" />
</div>
);
}
else {
children.push(
<div key="arrow" class={classes.elArraw}></div>
);
}
return (
<VuiResizeObserver onResize={handleResize}>
<div
class={classes.el}
style={styles.el}
onMouseenter={handleMouseenter}
onMouseleave={handleMouseleave}
onMousedown={handleMousedown}
onClick={handleClick}
>
{children}
</div>
</VuiResizeObserver>
);
}
};