UNPKG

zent

Version:

一套前端设计语言和基于React的实现

550 lines (457 loc) 17.3 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof2 = require('babel-runtime/helpers/typeof'); var _typeof3 = _interopRequireDefault(_typeof2); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _omit = require('lodash/omit'); var _omit2 = _interopRequireDefault(_omit); var _isEqual = require('lodash/isEqual'); var _isEqual2 = _interopRequireDefault(_isEqual); var _isArray = require('lodash/isArray'); var _isArray2 = _interopRequireDefault(_isArray); var _noop = require('lodash/noop'); var _noop2 = _interopRequireDefault(_noop); var _cloneDeep = require('lodash/cloneDeep'); var _cloneDeep2 = _interopRequireDefault(_cloneDeep); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _popover = require('../popover'); var _popover2 = _interopRequireDefault(_popover); var _trigger = require('./trigger'); var _trigger2 = _interopRequireDefault(_trigger); var _Popup = require('./Popup'); var _Popup2 = _interopRequireDefault(_Popup); var _SimpleTrigger = require('./trigger/SimpleTrigger'); var _SimpleTrigger2 = _interopRequireDefault(_SimpleTrigger); var _SelectTrigger = require('./trigger/SelectTrigger'); var _SelectTrigger2 = _interopRequireDefault(_SelectTrigger); var _InputTrigger = require('./trigger/InputTrigger'); var _InputTrigger2 = _interopRequireDefault(_InputTrigger); var _TagsTrigger = require('./trigger/TagsTrigger'); var _TagsTrigger2 = _interopRequireDefault(_TagsTrigger); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } /** * Select */ var PopoverClickTrigger = function (_Popover$Trigger$Clic) { (0, _inherits3['default'])(PopoverClickTrigger, _Popover$Trigger$Clic); function PopoverClickTrigger() { (0, _classCallCheck3['default'])(this, PopoverClickTrigger); return (0, _possibleConstructorReturn3['default'])(this, (PopoverClickTrigger.__proto__ || Object.getPrototypeOf(PopoverClickTrigger)).apply(this, arguments)); } (0, _createClass3['default'])(PopoverClickTrigger, [{ key: 'getTriggerProps', value: function getTriggerProps(child) { var _this2 = this; return { onClick: function onClick(evt) { evt.preventDefault(); if (_this2.props.contentVisible) { _this2.props.close(); } else if (!child.props.disabled) { _this2.props.open(); _this2.triggerEvent(child, 'onClick', evt); } } }; } }]); return PopoverClickTrigger; }(_popover2['default'].Trigger.Click); var Select = function (_ref) { (0, _inherits3['default'])(Select, _ref); function Select(props) { (0, _classCallCheck3['default'])(this, Select); var _this3 = (0, _possibleConstructorReturn3['default'])(this, (Select.__proto__ || Object.getPrototypeOf(Select)).call(this, props)); _this3.triggerChangeHandler = function (data) { _this3.setState(data); }; _this3.triggerDeleteHandler = function (data) { var selectedItems = _this3.state.selectedItems; selectedItems = selectedItems.filter(function (item) { return item.cid !== data.cid; }); _this3.setState({ selectedItems: selectedItems }, function () { _this3.props.onDelete(data); }); }; _this3.optionChangedHandler = function (ev, selectedItem) { var result = {}; ev = ev || { preventDefault: _noop2['default'], stopPropagation: _noop2['default'] }; var _this3$props = _this3.props, onEmptySelected = _this3$props.onEmptySelected, optionValue = _this3$props.optionValue, optionText = _this3$props.optionText, tags = _this3$props.tags, onChange = _this3$props.onChange; var selectedItems = _this3.state.selectedItems; if (!selectedItem) { onEmptySelected(ev); return; } var args = (0, _omit2['default'])(selectedItem, ['cid']); result[optionValue] = selectedItem.value; result[optionText] = selectedItem.text; var data = (0, _extends3['default'])({}, args, result); if (tags) { if (!selectedItems.some(function (item) { return item.cid === selectedItem.cid; })) { selectedItems.push(selectedItem); } } _this3.setState({ keyword: null, selectedItems: selectedItems, selectedItem: selectedItem }, function () { onChange({ target: (0, _extends3['default'])({}, _this3.props, { type: tags ? 'select-multiple' : 'select-one', value: selectedItem.value }), preventDefault: function preventDefault() { ev.preventDefault(); }, stopPropagation: function stopPropagation() { ev.stopPropagation(); } }, data); }); }; _this3.handlePopoverVisibleChange = function (visible) { if (visible) { _this3.props.onOpen(); } _this3.setState({ open: visible }); }; if (props.simple) { _this3.trigger = _SimpleTrigger2['default']; } else if (props.search) { _this3.trigger = _InputTrigger2['default']; } else if (props.tags) { _this3.trigger = _TagsTrigger2['default']; } else { _this3.trigger = props.trigger; } _this3.state = Object.assign({ selectedItems: [], selectedItem: { value: '', text: '' } }, props); return _this3; } (0, _createClass3['default'])(Select, [{ key: 'componentWillMount', value: function componentWillMount() { /** * data支持字符串数组和对象数组两种模式 * * 字符串数组默认value为下标 * 对象数组需提供value和text, 或者通过 optionValue-prop optionText-prop 自定义 * */ this.uniformedData = this.uniformData(this.props); this.traverseData(this.props); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { this.uniformedData = this.uniformData(nextProps); this.traverseData(nextProps); } /** * 将使用 child-element 传入的 Options 格式化为对象数组(未严格约束) * data-prop 的优先级高于 child-element * * @param {object} props - props of Select * @returns {object[]} uniformedData - 格式化后对象数组 * @returns {string} uniformedData[].cid - internal id of option * @returns {string} uniformedData[].text - text of an option * @returns {any} uniformedData[].value - token of an option * @memberof Select */ }, { key: 'uniformData', value: function uniformData(props) { var data = props.data, children = props.children, optionValue = props.optionValue, optionText = props.optionText; var uniformedData = void 0; // data-prop 高优先级, 格式化 optionValue、optionText if (data) { return uniformedData = data.map(function (option, index) { // 处理字符串数组 if ((typeof option === 'undefined' ? 'undefined' : (0, _typeof3['default'])(option)) !== 'object') { return { text: option, value: option, cid: '' + index }; } // hacky the quirk when optionText = 'value' and avoid modify props var optCopy = (0, _cloneDeep2['default'])(option); optCopy.cid = '' + index; if (optionValue) { optCopy.value = option[optionValue]; } if (optionText) { optCopy.text = option[optionText]; } return optCopy; }); } // 格式化 child-element if (children) { uniformedData = _react.Children.map(children, function (item, index) { var value = item.props.value; value = typeof value === 'undefined' ? item : value; return Object.assign({}, item.props, { value: value, cid: '' + index, text: item.props.children }); }); } return uniformedData; } /** * accept uniformed data to traverse then inject selected option or options to next state * * @param {object[]} data - uniformedData * @param {object} props - props of Select * @memberof Select */ }, { key: 'traverseData', value: function traverseData(props) { var _this4 = this; var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.uniformedData; // option 数组置空后重置组件状态 if (!data.length) { return this.setState({ selectedItem: {}, selectedItems: [] }); } var _state = this.state, selectedItem = _state.selectedItem, selectedItems = _state.selectedItems; var value = props.value, index = props.index, initialIndex = props.initialIndex, initialValue = props.initialValue; // initialize selected internal state var selected = { sItem: selectedItem, sItems: [] }; data.forEach(function (item, i) { // 处理 quirk 默认选项(initialIndex, initialValue) if (selectedItems.length === 0 && !selectedItem.cid && (initialValue !== null || initialIndex !== null)) { var coord = { value: initialValue, index: initialIndex }; _this4.locateSelected(selected, coord, item, i); } // 处理受控逻辑(index, value) if (value !== null || index !== null) { _this4.locateSelected(selected, { value: value, index: index }, item, i); } }); this.setState({ selectedItem: selected.sItem, selectedItems: selected.sItems }); } /** * judge if param 'item' selected * * @param {object} state - next state marked selected item or items * @param {object} coord - coordinate for seleted judging * @param {object} item - option object after uniformed * @param {number} i - index of option in options list * @memberof Select * */ }, { key: 'locateSelected', value: function locateSelected(state, coord, item, i) { var value = coord.value, index = coord.index; if ((0, _isArray2['default'])(value) && value.indexOf(item.value) > -1) { // rerender 去重 if (!state.sItems.find(function (selected) { return selected.value === item.value; })) { state.sItems.push(item); } } else if ((0, _isArray2['default'])(value) && value.length === 0) { // 多选重置 state.sItem = {}; state.sItems = []; } else if ((typeof value === 'undefined' ? 'undefined' : (0, _typeof3['default'])(value)) === 'object' && (0, _isEqual2['default'])(value, item.value)) { state.sItem = item; } else if (typeof value !== 'undefined' && (typeof value === 'undefined' ? 'undefined' : (0, _typeof3['default'])(value)) !== 'object' && '' + item.value === '' + value || index !== 'undefined' && '' + i === '' + index) { state.sItem = item; } else if (!value && !index && value !== 0) { // github#406 修复option-value为假值数字0时的异常重置。 // 单选重置 state.sItem = {}; state.sItems = []; } } // 接收trigger改变后的数据,将数据传给popup // 将被选中的option的数据传给trigger }, { key: 'render', value: function render() { var _this5 = this; var _props = this.props, placeholder = _props.placeholder, maxToShow = _props.maxToShow, className = _props.className, popupClassName = _props.popupClassName, disabled = _props.disabled, emptyText = _props.emptyText, _props$filter = _props.filter, filter = _props$filter === undefined ? this.props.onFilter : _props$filter, onAsyncFilter = _props.onAsyncFilter, searchPlaceholder = _props.searchPlaceholder, autoWidth = _props.autoWidth, width = _props.width; var _state2 = this.state, open = _state2.open, selectedItems = _state2.selectedItems, _state2$selectedItem = _state2.selectedItem, selectedItem = _state2$selectedItem === undefined ? {} : _state2$selectedItem, extraFilter = _state2.extraFilter, _state2$keyword = _state2.keyword, keyword = _state2$keyword === undefined ? null : _state2$keyword; var _selectedItem$cid = selectedItem.cid, cid = _selectedItem$cid === undefined ? '' : _selectedItem$cid; var disabledCls = disabled ? 'disabled' : ''; var prefixCls = this.props.prefix + '-select'; return _react2['default'].createElement( _popover2['default'], { display: 'inline-block', position: _popover2['default'].Position.AutoBottomLeft, visible: open, className: prefixCls + ' ' + popupClassName, wrapperClassName: prefixCls + ' ' + className + ' ' + disabledCls, onVisibleChange: this.handlePopoverVisibleChange, width: width }, _react2['default'].createElement( PopoverClickTrigger, null, _react2['default'].createElement(_trigger2['default'], (0, _extends3['default'])({ disabled: disabled, prefixCls: prefixCls, trigger: this.trigger, placeholder: placeholder, selectedItems: selectedItems, keyword: keyword }, selectedItem, { onChange: this.triggerChangeHandler, onDelete: this.triggerDeleteHandler })) ), _react2['default'].createElement( _popover2['default'].Content, null, _react2['default'].createElement(_Popup2['default'], { ref: function ref(_ref2) { return _this5.popup = _ref2; }, cid: cid, prefixCls: prefixCls, data: this.uniformedData, selectedItems: selectedItems, extraFilter: extraFilter, searchPlaceholder: searchPlaceholder, emptyText: emptyText, keyword: keyword, filter: filter, onAsyncFilter: onAsyncFilter, maxToShow: maxToShow, onChange: this.optionChangedHandler, onFocus: this.popupFocusHandler, onBlur: this.popupBlurHandler, autoWidth: autoWidth }) ) ); } }]); return Select; }(_react.PureComponent || _react.Component); Select.propTypes = { data: _propTypes2['default'].array, prefix: _propTypes2['default'].string, className: _propTypes2['default'].string, open: _propTypes2['default'].bool, popupClassName: _propTypes2['default'].string, disabled: _propTypes2['default'].bool, placeholder: _propTypes2['default'].string, maxToShow: _propTypes2['default'].number, searchPlaceholder: _propTypes2['default'].string, emptyText: _propTypes2['default'].node, selectedItem: _propTypes2['default'].shape({ value: _propTypes2['default'].any, text: _propTypes2['default'].string }), trigger: _propTypes2['default'].func, optionValue: _propTypes2['default'].string, optionText: _propTypes2['default'].string, onChange: _propTypes2['default'].func, onDelete: _propTypes2['default'].func, filter: _propTypes2['default'].func, onAsyncFilter: _propTypes2['default'].func, onEmptySelected: _propTypes2['default'].func, onOpen: _propTypes2['default'].func, width: _propTypes2['default'].oneOfType([_propTypes2['default'].number, _propTypes2['default'].string]), // 自动根据ref计算弹层宽度 autoWidth: _propTypes2['default'].bool }; Select.defaultProps = { prefix: 'zent', disabled: false, className: '', open: false, popupClassName: '', trigger: _SelectTrigger2['default'], placeholder: '请选择', searchPlaceholder: '', emptyText: '没有找到匹配项', selectedItem: { value: '', text: '' }, selectedItems: [], optionValue: 'value', optionText: 'text', onChange: _noop2['default'], onDelete: _noop2['default'], onEmptySelected: _noop2['default'], onOpen: _noop2['default'], autoWidth: false, // HACK value: null, index: null, initialValue: null, initialIndex: null }; exports['default'] = Select;