UNPKG

@alifd/next

Version:

A configurable component library for web built on React.

411 lines (363 loc) 14.4 kB
import _extends from 'babel-runtime/helpers/extends'; import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; import _inherits from 'babel-runtime/helpers/inherits'; var _class, _temp; import React, { isValidElement, cloneElement } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import Icon from '../icon'; import { obj, func } from '../util'; import Base from './base'; import Group from './group'; // preventDefault here can stop onBlur to keep focus state function preventDefault(e) { e.preventDefault(); } /** Input */ var Input = (_temp = _class = function (_Base) { _inherits(Input, _Base); function Input(props) { _classCallCheck(this, Input); var _this = _possibleConstructorReturn(this, _Base.call(this, props)); _this.handleKeyDown = function (e) { if (e.keyCode === 13) { _this.props.onPressEnter(e); } _this.onKeyDown(e); }; _this.handleKeyDownFromClear = function (e) { if (e.keyCode === 13) { _this.onClear(e); } }; var value = void 0; if ('value' in props) { value = props.value; } else { value = props.defaultValue; } _this.state = { value: typeof value === 'undefined' ? '' : value }; return _this; } // `Enter` was considered to be two chars in chrome , but one char in ie. // so we make all `Enter` to be two chars Input.prototype.getValueLength = function getValueLength(value) { var nv = '' + value; var strLen = this.props.getValueLength(nv); if (typeof strLen !== 'number') { strLen = nv.length; } return strLen; }; Input.prototype.renderControl = function renderControl() { var _this2 = this; var _props = this.props, hasClear = _props.hasClear, readOnly = _props.readOnly, state = _props.state, prefix = _props.prefix, hint = _props.hint, extra = _props.extra, locale = _props.locale, disabled = _props.disabled, hoverShowClear = _props.hoverShowClear; var lenWrap = this.renderLength(); var stateWrap = null; if (state === 'success') { stateWrap = React.createElement(Icon, { type: 'success-filling', className: prefix + 'input-success-icon' }); } else if (state === 'loading') { stateWrap = React.createElement(Icon, { type: 'loading', className: prefix + 'input-loading-icon' }); } else if (state === 'warning') { stateWrap = React.createElement(Icon, { type: 'warning', className: prefix + 'input-warning-icon' }); } var clearWrap = null; // showClear属性应该与disable属性为互斥状态 var showClear = hasClear && !readOnly && !!('' + this.state.value) && !disabled; if (hint || showClear) { var hintIcon = null; if (hint) { if (typeof hint === 'string') { hintIcon = React.createElement(Icon, { type: hint, className: prefix + 'input-hint' }); } else if (isValidElement(hint)) { hintIcon = cloneElement(hint, { className: classNames(hint.props.className, prefix + 'input-hint') }); } else { hintIcon = hint; } } else { var _classNames; var cls = classNames((_classNames = {}, _classNames[prefix + 'input-hint'] = true, _classNames[prefix + 'input-clear-icon'] = true, _classNames[prefix + 'input-hover-show'] = hoverShowClear, _classNames)); hintIcon = React.createElement(Icon, { type: 'delete-filling', role: 'button', tabIndex: '0', className: cls, 'aria-label': locale.clear, onClick: this.onClear.bind(this), onMouseDown: preventDefault, onKeyDown: this.handleKeyDownFromClear }); } clearWrap = React.createElement( 'span', { className: prefix + 'input-hint-wrap' }, hasClear && hint ? React.createElement(Icon, { type: 'delete-filling', role: 'button', tabIndex: '0', className: prefix + 'input-clear ' + prefix + 'input-clear-icon', 'aria-label': locale.clear, onClick: this.onClear.bind(this), onMouseDown: preventDefault, onKeyDown: this.handleKeyDownFromClear }) : null, hintIcon ); } if (state === 'loading') { clearWrap = null; } return clearWrap || lenWrap || stateWrap || extra ? React.createElement( 'span', { onClick: function onClick() { return _this2.focus(); }, className: prefix + 'input-control' }, clearWrap, lenWrap, stateWrap, extra ) : null; }; Input.prototype.renderLabel = function renderLabel() { var _props2 = this.props, label = _props2.label, prefix = _props2.prefix, id = _props2.id; return label ? React.createElement( 'label', { className: prefix + 'input-label', htmlFor: id }, label ) : null; }; Input.prototype.renderInner = function renderInner(inner, cls) { return inner ? React.createElement( 'span', { className: cls }, inner ) : null; }; Input.prototype.onClear = function onClear(e) { if (this.props.disabled) { return; } // 非受控模式清空内部数据 if (!('value' in this.props)) { this.setState({ value: '' }); } this.props.onChange('', e, 'clear'); this.focus(); }; Input.prototype.render = function render() { var _classNames2, _classNames3, _classNames4, _classNames5, _classNames6, _classNames7, _classNames8; var _props3 = this.props, size = _props3.size, htmlType = _props3.htmlType, htmlSize = _props3.htmlSize, autoComplete = _props3.autoComplete, autoFocus = _props3.autoFocus, disabled = _props3.disabled, style = _props3.style, innerBefore = _props3.innerBefore, innerAfter = _props3.innerAfter, innerBeforeClassName = _props3.innerBeforeClassName, innerAfterClassName = _props3.innerAfterClassName, className = _props3.className, hasBorder = _props3.hasBorder, prefix = _props3.prefix, isPreview = _props3.isPreview, renderPreview = _props3.renderPreview, addonBefore = _props3.addonBefore, addonAfter = _props3.addonAfter, addonTextBefore = _props3.addonTextBefore, addonTextAfter = _props3.addonTextAfter, inputRender = _props3.inputRender, rtl = _props3.rtl, composition = _props3.composition; var hasAddon = addonBefore || addonAfter || addonTextBefore || addonTextAfter; var cls = classNames(this.getClass(), (_classNames2 = {}, _classNames2['' + prefix + size] = true, _classNames2[prefix + 'hidden'] = this.props.htmlType === 'hidden', _classNames2[prefix + 'noborder'] = !hasBorder || this.props.htmlType === 'file', _classNames2[prefix + 'input-group-auto-width'] = hasAddon, _classNames2[prefix + 'disabled'] = disabled, _classNames2[className] = !!className && !hasAddon, _classNames2)); var innerCls = prefix + 'input-inner'; var innerBeforeCls = classNames((_classNames3 = {}, _classNames3[innerCls] = true, _classNames3[prefix + 'before'] = true, _classNames3[innerBeforeClassName] = innerBeforeClassName, _classNames3)); var innerAfterCls = classNames((_classNames4 = {}, _classNames4[innerCls] = true, _classNames4[prefix + 'after'] = true, _classNames4[prefix + 'input-inner-text'] = typeof innerAfter === 'string', _classNames4[innerAfterClassName] = innerAfterClassName, _classNames4)); var previewCls = classNames((_classNames5 = {}, _classNames5[prefix + 'form-preview'] = true, _classNames5[className] = !!className, _classNames5)); var props = this.getProps(); // custom data attributes are assigned to the top parent node // data-类自定义数据属性分配到顶层node节点 var dataProps = obj.pickAttrsWith(this.props, 'data-'); // Custom props are transparently transmitted to the core input node by default // 自定义属性默认透传到核心node节点:input var others = obj.pickOthers(_extends({}, dataProps, Input.propTypes), this.props); if (isPreview) { var value = props.value; var label = this.props.label; if (typeof renderPreview === 'function') { return React.createElement( 'div', _extends({}, others, { className: previewCls }), renderPreview(value, this.props) ); } return React.createElement( 'div', _extends({}, others, { className: previewCls }), addonBefore || addonTextBefore, label, innerBefore, value, innerAfter, addonAfter || addonTextAfter ); } var compositionProps = {}; if (composition) { compositionProps.onCompositionStart = this.handleCompositionStart; compositionProps.onCompositionEnd = this.handleCompositionEnd; } var inputEl = React.createElement('input', _extends({}, others, props, compositionProps, { height: '100%', type: htmlType, size: htmlSize, autoFocus: autoFocus, autoComplete: autoComplete, onKeyDown: this.handleKeyDown, ref: this.saveRef })); var inputWrap = React.createElement( 'span', _extends({}, dataProps, { dir: rtl ? 'rtl' : undefined, className: cls, style: hasAddon ? undefined : style }), this.renderLabel(), this.renderInner(innerBefore, innerBeforeCls), inputRender(inputEl), this.renderInner(innerAfter, innerAfterCls), this.renderControl() ); var groupCls = classNames((_classNames6 = {}, _classNames6[prefix + 'input-group-text'] = true, _classNames6['' + prefix + size] = !!size, _classNames6[prefix + 'disabled'] = disabled, _classNames6)); var addonBeforeCls = classNames((_classNames7 = {}, _classNames7[groupCls] = addonTextBefore, _classNames7)); var addonAfterCls = classNames((_classNames8 = {}, _classNames8[groupCls] = addonTextAfter, _classNames8)); if (hasAddon) { return React.createElement( Group, _extends({}, dataProps, { prefix: prefix, className: className, style: style, disabled: disabled, addonBefore: addonBefore || addonTextBefore, addonBeforeClassName: addonBeforeCls, addonAfter: addonAfter || addonTextAfter, addonAfterClassName: addonAfterCls }), inputWrap ); } return inputWrap; }; return Input; }(Base), _class.getDerivedStateFromProps = Base.getDerivedStateFromProps, _class.propTypes = _extends({}, Base.propTypes, { /** * label */ label: PropTypes.node, /** * 是否出现clear按钮 */ hasClear: PropTypes.bool, /** * 是否有边框 */ hasBorder: PropTypes.bool, /** * 状态 * @enumdesc 错误, 校验中, 成功, 警告 */ state: PropTypes.oneOf(['error', 'loading', 'success', 'warning']), /** * 按下回车的回调 */ onPressEnter: PropTypes.func, onClear: PropTypes.func, /** * 原生type */ htmlType: PropTypes.string, htmlSize: PropTypes.string, /** * 水印 (Icon的type类型,和hasClear占用一个地方) */ hint: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), /** * 文字前附加内容 */ innerBefore: PropTypes.node, /** * 文字后附加内容 */ innerAfter: PropTypes.node, /** * 输入框前附加内容 */ addonBefore: PropTypes.node, /** * 输入框后附加内容 */ addonAfter: PropTypes.node, /** * 输入框前附加文字 */ addonTextBefore: PropTypes.node, /** * 输入框后附加文字 */ addonTextAfter: PropTypes.node, /** * (原生input支持) */ autoComplete: PropTypes.string, /** * 自动聚焦(原生input支持) */ autoFocus: PropTypes.bool, inputRender: PropTypes.func, extra: PropTypes.node, innerBeforeClassName: PropTypes.string, innerAfterClassName: PropTypes.string, /** * 是否为预览态 */ isPreview: PropTypes.bool, /** * 预览态模式下渲染的内容 * @param {number} value 评分值 */ renderPreview: PropTypes.func, /** * hover展示clear (配合 hasClear=true使用) * @version 1.24 */ hoverShowClear: PropTypes.bool }), _class.defaultProps = _extends({}, Base.defaultProps, { autoComplete: 'off', hasBorder: true, isPreview: false, hoverShowClear: false, onPressEnter: func.noop, inputRender: function inputRender(el) { return el; } }), _temp); export { Input as default };