UNPKG

vui-design

Version:

A high quality UI Toolkit based on Vue.js

255 lines (231 loc) 7.32 kB
import Emitter from "../../mixins/emitter"; import PropTypes from "../../utils/prop-types"; import is from "../../utils/is"; import getClassNamePrefix from "../../utils/getClassNamePrefix"; export const createProps = () => { return { classNamePrefix: PropTypes.string, name: PropTypes.string, type: PropTypes.string, size: PropTypes.oneOf(["small", "medium", "large"]), minWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), indeterminate: PropTypes.bool.def(false), checked: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.number]).def(false), disabled: PropTypes.bool.def(false), checkedValue: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.number]).def(true), uncheckedValue: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.number]).def(false), validator: PropTypes.bool.def(true) }; }; export default { name: "vui-checkbox", inject: { vuiForm: { default: undefined }, vuiCheckboxGroup: { default: undefined }, vuiChoiceGroup: { default: undefined } }, mixins: [ Emitter ], inheritAttrs: false, model: { prop: "checked", event: "input" }, props: createProps(), data() { const { $props: props } = this; const state = { focused: false, checked: props.checked }; return { state }; }, watch: { checked(value) { if (this.state.checked === value) { return; } this.state.checked = value; } }, methods: { handleFocus(e) { this.state.focused = true; this.$emit("focus"); }, handleBlur(e) { this.state.focused = false; this.$emit("blur"); }, handleChange(e) { const { vuiCheckboxGroup, vuiChoiceGroup, $refs: references, $props: props } = this; const checked = e.target.checked; if (props.disabled) { return; } if (vuiCheckboxGroup) { const beforeCheck = vuiCheckboxGroup.beforeSelect || vuiCheckboxGroup.beforeCheck; const callback = () => vuiCheckboxGroup.handleChange(checked, props.value); let hook = true; if (is.function(beforeCheck)) { hook = beforeCheck(props.value); } if (is.boolean(hook) && hook === false) { references.checkbox.checked = ""; } else if (is.promise(hook)) { hook.then(() => callback()).catch(() => references.checkbox.checked = ""); } else { callback(); } } else if (vuiChoiceGroup) { vuiChoiceGroup.handleChange("checkbox", checked, props.value); } else { const value = checked ? props.checkedValue : props.uncheckedValue; this.state.checked = value; this.$emit("input", value); this.$emit('change', value); if (props.validator) { this.dispatch("vui-form-item", "change", value); } } } }, render() { const { vuiForm, vuiCheckboxGroup, vuiChoiceGroup, $slots: slots, $attrs: attrs, $props: props, state } = this; const { handleFocus, handleBlur, handleChange } = this; // props & state let type, name, label, value, size, minWidth, focused, indeterminate, checked, disabled; if (vuiCheckboxGroup) { type = vuiCheckboxGroup.type; name = vuiCheckboxGroup.name; } else if (vuiChoiceGroup) { type = vuiChoiceGroup.type; name = vuiChoiceGroup.name; } else { type = props.type; name = props.name; } label = slots.default || props.label; value = props.value; if (props.size) { size = props.size; } else if (vuiCheckboxGroup && vuiCheckboxGroup.size) { size = vuiCheckboxGroup.size; } else if (vuiChoiceGroup && vuiChoiceGroup.size) { size = vuiChoiceGroup.size; } else if (vuiForm && vuiForm.size) { size = vuiForm.size; } else { size = "medium"; } if (props.minWidth) { minWidth = props.minWidth; } else if (vuiCheckboxGroup && vuiCheckboxGroup.minWidth) { minWidth = vuiCheckboxGroup.minWidth; } else if (vuiChoiceGroup && vuiChoiceGroup.minWidth) { minWidth = vuiChoiceGroup.minWidth; } focused = state.focused; indeterminate = props.indeterminate; if (vuiCheckboxGroup) { checked = vuiCheckboxGroup.state.value.indexOf(value) > -1; } else if (vuiChoiceGroup) { checked = is.array(vuiChoiceGroup.state.value) && vuiChoiceGroup.state.value.indexOf(value) > -1; } else { checked = state.checked === props.checkedValue; } if (vuiForm && vuiForm.disabled) { disabled = vuiForm.disabled; } else if (vuiCheckboxGroup && vuiCheckboxGroup.disabled) { disabled = vuiCheckboxGroup.disabled; } else if (vuiChoiceGroup && vuiChoiceGroup.disabled) { disabled = vuiChoiceGroup.disabled; } else { disabled = props.disabled; } // class const classNamePrefix = getClassNamePrefix(props.classNamePrefix, type === "button" ? "checkbox-button" : "checkbox"); let classes = {}; classes.el = { [`${classNamePrefix}`]: true, [`${classNamePrefix}-${size}`]: size, [`${classNamePrefix}-focused`]: focused, [`${classNamePrefix}-indeterminate`]: indeterminate, [`${classNamePrefix}-checked`]: checked, [`${classNamePrefix}-disabled`]: disabled }; classes.elInput = `${classNamePrefix}-input`; classes.elLabel = `${classNamePrefix}-label`; // style let styles = {}; if (type === "button" && minWidth) { styles.el = { minWidth: is.string(minWidth) ? minWidth : `${minWidth}px` }; } // render const attributes = { ref: "checkbox", attrs: attrs, on: { focus: handleFocus, blur: handleBlur, change: handleChange } }; return ( <label class={classes.el} style={styles.el}> <div class={classes.elInput}> { !type ? ( <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024"> <path d="M0.020966 0l1023.958044 0 0 1024-1023.958044 0 0-1024Z"></path> </svg> ) : null } { !type ? ( <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1248 1024"> <path d="M123.800257 460.153135l291.677674 232.393077 726.28329-669.078427s48.722384-44.483585 91.293444-9.727389c12.638284 10.392563 27.272086 39.993364-5.653359 86.388252L469.106727 988.380911s-58.120238 79.570536-127.131004-0.831161L14.711914 545.710226s-38.829006-59.865554 9.72861-95.701892c16.463333-11.973111 53.713011-30.763938 99.360954 10.14358z"></path> </svg> ) : null } <input type="checkbox" name={name} value={value} checked={checked} disabled={disabled} {...attributes} /> </div> { label ? ( <div class={classes.elLabel}>{label}</div> ) : null } </label> ); } };