UNPKG

tntd

Version:

tntd是基于 TNT Design 设计体系的 React UI 组件库,主要用于研发企业级中后台产品。

769 lines (767 loc) 28.5 kB
"use strict"; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _react = _interopRequireWildcard(require("react")); var _configProvider = require("../config-provider"); var _select = _interopRequireDefault(require("../select")); var _empty = _interopRequireDefault(require("../empty")); var _spin = _interopRequireDefault(require("../spin")); var _utils = require("../utils"); var _DropDownWrap = _interopRequireDefault(require("./DropDownWrap")); var _prevLocale = require("../prev-locale"); require("./index.less"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } function _readOnlyError(r) { throw new TypeError('"' + r + '" is read-only'); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } var __rest = void 0 && (void 0).__rest || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var defaultPlaceholder = (0, _prevLocale.getText)('select', (0, _prevLocale.getLanguage)()); // 页面实际渲染的下拉菜单数量,实际为 2 * ITEM_ELEMENT_NUMBER var ITEM_ELEMENT_NUMBER = 30; // Select size 配置 var ITEM_HEIGHT_CFG = { small: 24, large: 40, "default": 32 }; var ARROW_CODE = { 40: 'down', 38: 'up' }; var DROPDOWN_HEIGHT = 224; var Option = _select["default"].Option; var SuperSelect = /*#__PURE__*/function (_PureComponent) { function SuperSelect(props) { var _this; _classCallCheck(this, SuperSelect); _this = _callSuper(this, SuperSelect, [props]); Object.defineProperty(_this, "turnChildren", { enumerable: true, configurable: true, writable: true, value: function value(children) { if (!children) return []; var arr = []; if (children && children.props) { arr.push(children); } else { children.forEach(function (item) { if (item) { if (item instanceof Array) { arr = arr.concat(item); } else { arr.push(item); } } }); } return arr; } }); Object.defineProperty(_this, "formulaWidth", { enumerable: true, configurable: true, writable: true, value: function value() { // 获取dom设置宽度 var _this$props = _this.props, arr2 = _this$props.children, _this$props$dropdownM = _this$props.dropdownMatchSelectWidth, dropdownMatchSelectWidth = _this$props$dropdownM === void 0 ? true : _this$props$dropdownM, maxWidth = _this$props.maxWidth; var selectDom = document.getElementById(_this.id); var selectWidth; if (selectDom) { selectWidth = selectDom.clientWidth || selectDom.offsetWidth; } var arr = []; var formulaMaxWidth = 10; if (!dropdownMatchSelectWidth) { formulaMaxWidth = maxWidth || 10; } if (!dropdownMatchSelectWidth && !maxWidth) { var _children = _this.turnChildren(arr2); for (var i = 0; i < _children.length; i++) { var val = _children[i].props.children; var textWidth = _this.getTextPixelWith(val); arr.push(textWidth.toFixed(2)); } if (arr.length > 0) { formulaMaxWidth = Math.max.apply(Math, arr); } } _this.setState({ selectWidth: selectWidth, maxWidth: formulaMaxWidth }); } }); // 获取单行文本的像素宽度 Object.defineProperty(_this, "getTextPixelWith", { enumerable: true, configurable: true, writable: true, value: function value(text) { var fontStyle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '14px'; var canvas = document.createElement('canvas'); // 创建 canvas 画布 var context = canvas.getContext('2d'); // 获取 canvas 绘图上下文环境 context.font = fontStyle; // 设置字体样式,使用前设置好对应的 font 样式才能准确获取文字的像素长度 var dimension = context.measureText(text); // 测量文字 return dimension.width; } }); Object.defineProperty(_this, "getItemStyle", { enumerable: true, configurable: true, writable: true, value: function value(i) { return { position: 'absolute', top: _this.ITEM_HEIGHT * i, width: '100%', height: _this.ITEM_HEIGHT }; } }); Object.defineProperty(_this, "preventEvent", { enumerable: true, configurable: true, writable: true, value: function value(e) { e.preventDefault(); } }); Object.defineProperty(_this, "addEvent", { enumerable: true, configurable: true, writable: true, value: function value() { _this.scrollEle = document.querySelector(".".concat(_this.dropdownClassName)); // 下拉菜单未展开时元素不存在 if (!_this.scrollEle) return; _this.scrollEle.addEventListener('mousedown', _this.preventEvent, false); _this.scrollEle.addEventListener('scroll', _this.onScroll, false); _this.inputEle = document.querySelector("#".concat(_this.id)); if (!_this.inputEle) return; _this.inputEle.addEventListener('keydown', _this.onKeyDown, false); } }); // 模拟 antd select 按下 上下箭头 键时滚动列表 Object.defineProperty(_this, "onKeyDown", { enumerable: true, configurable: true, writable: true, value: function value(e) { var _ref = e || {}, keyCode = _ref.keyCode; setTimeout(function () { var activeItem = document.querySelector(".".concat(_this.dropdownClassName, " .ant-select-dropdown-menu-item-active")); if (!activeItem) return; var offsetTop = activeItem.offsetTop; var isUp = ARROW_CODE[keyCode] === 'up'; var isDown = ARROW_CODE[keyCode] === 'down'; // 在所有列表第一行按上键 if (offsetTop - _this.prevTop > DROPDOWN_HEIGHT && isUp && _this.scrollEle) { _this.scrollEle.scrollTo(0, _this.allHeight - DROPDOWN_HEIGHT); _this.prevTop = _this.allHeight; return; } // 在所有列表中最后一行按下键 if (_this.prevTop > offsetTop + DROPDOWN_HEIGHT && isDown && _this.scrollEle) { _this.scrollEle.scrollTo(0, 0); _this.prevTop = 0; return; } _this.prevTop = offsetTop; // 向下滚动到下拉框最后一行时,向下滚动一行的高度 if (offsetTop > _this.scrollEle.scrollTop + DROPDOWN_HEIGHT - _this.ITEM_HEIGHT + 10 && isDown) { _this.scrollEle.scrollTo(0, _this.scrollTop + _this.ITEM_HEIGHT); return; } // 向上滚动到下拉框第一一行时,向上滚动一行的高度 if (offsetTop < _this.scrollEle.scrollTop && isUp) { _this.scrollEle.scrollTo(0, _this.scrollTop - _this.ITEM_HEIGHT); } }, 100); } }); Object.defineProperty(_this, "onScroll", { enumerable: true, configurable: true, writable: true, value: function value() { return _this.throttleByHeight(_this.onScrollReal); } }); Object.defineProperty(_this, "onScrollReal", { enumerable: true, configurable: true, writable: true, value: function value() { _this.allList = _this.getUseChildrenList(); var _this$getStartAndEndI = _this.getStartAndEndIndex(), startIndex = _this$getStartAndEndI.startIndex, endIndex = _this$getStartAndEndI.endIndex; _this.prevScrollTop = _this.scrollTop; // 重新渲染列表组件 Wrap var allHeight = _this.allList.length * _this.ITEM_HEIGHT || 100; _this.wrap.reactList(allHeight, startIndex, endIndex); } }); Object.defineProperty(_this, "throttleByHeight", { enumerable: true, configurable: true, writable: true, value: function value() { _this.scrollTop = _this.scrollEle.scrollTop; // 滚动的高度 var delta = _this.prevScrollTop - _this.scrollTop; delta = delta < 0 ? 0 - delta : delta; delta > _this.reactDelta && _this.onScrollReal(); } }); // 列表可展示所有 children Object.defineProperty(_this, "getUseChildrenList", { enumerable: true, configurable: true, writable: true, value: function value() { return _this.state.filterChildren || _this.state.children; } }); Object.defineProperty(_this, "getStartAndEndIndex", { enumerable: true, configurable: true, writable: true, value: function value() { // 滚动后显示在列表可视区中的第一个 item 的 index var showIndex = Number((_this.scrollTop / _this.ITEM_HEIGHT).toFixed(0)); var startIndex = showIndex - ITEM_ELEMENT_NUMBER < 0 ? 0 : showIndex - ITEM_ELEMENT_NUMBER / 2; var endIndex = showIndex + ITEM_ELEMENT_NUMBER; return { startIndex: startIndex, endIndex: endIndex }; } }); // 须使用 setTimeout 确保在 dom 加载完成之后添加事件 Object.defineProperty(_this, "setSuperDropDownMenu", { enumerable: true, configurable: true, writable: true, value: function value(visible) { if (!visible) return; _this.allList = _this.getUseChildrenList(); if (!_this.eventTimer || !_this.scrollEle) { _this.eventTimer = setTimeout(function () { return _this.addEvent(); }, 0); } else { var allHeight = _this.allList.length * _this.ITEM_HEIGHT || 100; // 下拉列表单独重新渲染 var _this$getStartAndEndI2 = _this.getStartAndEndIndex(), startIndex = _this$getStartAndEndI2.startIndex, endIndex = _this$getStartAndEndI2.endIndex; setTimeout(function () { _this.wrap && _this.wrap.reactList(allHeight, startIndex, endIndex); }, 0); } } }); Object.defineProperty(_this, "onDropdownVisibleChange", { enumerable: true, configurable: true, writable: true, value: function value(visible) { var onDropdownVisibleChange = _this.props.onDropdownVisibleChange; onDropdownVisibleChange && onDropdownVisibleChange(visible); var _this$state = _this.state, value = _this$state.value, children = _this$state.children; // 关闭下拉框前清空筛选条件,防止下次打开任然显示筛选后的 options if (!visible) { // 定时器确保关闭后再设置 filterChildren,防止列表刷新闪烁 setTimeout(function () { _this.setState({ filterChildren: null }); _this.setDefaultScrollTop(value); }, 100); // this.removeEvent(); } else { // this.addEvent(); if (value) { // 如果已有 value, 设置默认滚动位置 _this.setDefaultScrollTop(); // 设置下拉列表显示数据 _this.setSuperDropDownMenu(visible); } else if (!value && value !== 0 && children && children.length > 0) { // 无数据时,下拉回归至第一个 var val = children[0].props.value; _this.setDefaultScrollTop(val); } } } }); Object.defineProperty(_this, "onDeselect", { enumerable: true, configurable: true, writable: true, value: function value(_value) { var onDeselect = _this.props.onDeselect; onDeselect && onDeselect(_value); } }); // 在搜索重新计算下拉滚动条高度 Object.defineProperty(_this, "onChange", { enumerable: true, configurable: true, writable: true, value: function value(_value2, opt) { var _this$props2 = _this.props, showSearch = _this$props2.showSearch, onChange = _this$props2.onChange, autoClearSearchValue = _this$props2.autoClearSearchValue, maxCount = _this$props2.maxCount, mode = _this$props2.mode; if (showSearch || _this.isMultiple) { // 搜索模式下选择后是否需要重置搜索状态 if (autoClearSearchValue !== false) { _this.setState({ filterChildren: null }, function () { // 搜索成功后重新设置列表的总高度 _this.setSuperDropDownMenu(true); }); } } if (mode === 'multiple') { if (_value2.length <= maxCount) { _this.setState({ value: _value2 }); } } else { _this.setState({ value: _value2 }); } onChange && onChange(_value2, opt); if (mode !== 'multiple') { _this.select && _this.select.blur(); } } }); Object.defineProperty(_this, "onSearch", { enumerable: true, configurable: true, writable: true, value: function value(v) { var _this$props3 = _this.props, showSearch = _this$props3.showSearch, onSearch = _this$props3.onSearch, filterOption = _this$props3.filterOption, arr = _this$props3.children; var children = _this.turnChildren(arr); if (showSearch && filterOption !== false) { // 须根据 filterOption(如有该自定义函数)手动 filter 搜索匹配的列表 var filterChildren = null; if (typeof filterOption === 'function') { filterChildren = children.filter(function (item) { return filterOption(v, item); }); } else if (filterOption === undefined) { filterChildren = children.filter(function (item) { return _this.filterOption(v, item); }); } // 搜索框有值,去除disabled=true的children var newFilterChild = []; filterChildren && filterChildren.forEach(function (item, index) { if (!item.props.disabled) { newFilterChild.push(item); } }); filterChildren = newFilterChild; // 设置下拉列表显示数据 _this.setState({ filterChildren: v === '' ? null : filterChildren }, function () { setTimeout(function () { // 搜索后需要重置滚动位置到0,防止上次 scrollTop 位置无数据 if (filterChildren && _this.scrollEle) { _this.scrollTop = 0; _this.scrollEle.scrollTo(0, 0); } // 搜索成功后需要重新设置列表的总高度 _this.setSuperDropDownMenu(true); }, 0); }); } onSearch && onSearch(v); } }); Object.defineProperty(_this, "filterOption", { enumerable: true, configurable: true, writable: true, value: function value(v, option) { // 自定义过滤对应的 option 属性配置 var filterProps = _this.props.optionFilterProp || 'value'; return "".concat(option.props[filterProps]).indexOf(v) >= 0; } }); Object.defineProperty(_this, "setDefaultScrollTop", { enumerable: true, configurable: true, writable: true, value: function value(data) { var value = _this.state.value; var arr = _this.props.children; var children = _this.turnChildren(arr); var val = data || data === 0 ? data : value; var _loop = function _loop() { var item = children[i]; var itemValue = item.props.value; if (itemValue === val || Array.isArray(val) && val.includes(itemValue)) { var targetScrollTop = i * _this.ITEM_HEIGHT; setTimeout(function () { if (!_this.scrollEle) { _this.addEvent(); } _this.scrollEle && _this.scrollEle.scrollTo(0, targetScrollTop); }, 100); return { v: void 0 }; } }, _ret; for (var i = 0; i < children.length; i++) { _ret = _loop(); if (_ret) return _ret.v; } } }); Object.defineProperty(_this, "removeEvent", { enumerable: true, configurable: true, writable: true, value: function value() { if (!_this.scrollEle) return; _this.scrollEle.removeEventListener('mousedown', _this.preventEvent, false); _this.scrollEle.removeEventListener('scroll', _this.onScroll, false); if (!_this.inputEle) return; _this.inputEle.removeEventListener('keydown', _this.onKeyDown, false); } }); var mode = props.mode, defaultValue = props.defaultValue, value = props.value, optionHeight = props.optionHeight, arr = props.children; _this.isMultiple = ['tags', 'multiple'].includes(mode); var children = _this.turnChildren(arr); // 设置默认 value var defaultV = _this.isMultiple ? [] : ''; defaultV = value || defaultValue || defaultV; _this.state = { children: children || [], filterChildren: null, value: defaultV, maxWidth: null, selectWidth: null }; // 下拉菜单项行高 _this.ITEM_HEIGHT = optionHeight || ITEM_HEIGHT_CFG[props.size || 'default']; // 可视区 dom 高度 _this.visibleDomHeight = _this.ITEM_HEIGHT * ITEM_ELEMENT_NUMBER; // 滚动时重新渲染的 scrollTop 判断值,大于 reactDelta 则刷新下拉列表 _this.reactDelta = _this.visibleDomHeight / 3; // 是否拖动滚动条快速滚动状态 _this.isStopReact = false; // 上一次滚动的 scrollTop 值 _this.prevScrollTop = 0; // 上一次按下方向键时 scrollTop 值 _this.prevTop = 0; _this.scrollTop = 0; // className _this.dropdownClassName = "dc".concat(+new Date()); _this.id = "sid".concat(+new Date()); return _this; } _inherits(SuperSelect, _PureComponent); return _createClass(SuperSelect, [{ key: "componentDidMount", value: function componentDidMount() { var _this2 = this; // defaultOpens=true 时添加滚动事件 setTimeout(function () { _this2.addEvent(); }, 500); var arr = this.props.children; var children = this.turnChildren(arr); // if (children && children.length > 0) { this.formulaWidth(); // } } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var _this3 = this; var _this$props4 = this.props, mode = _this$props4.mode, defaultValue = _this$props4.defaultValue, value = _this$props4.value, children = _this$props4.children; var arr = this.turnChildren(children); if (prevProps.children !== children) { this.isMultiple = ['tags', 'multiple'].includes(mode); this.setState({ children: arr || [], filterChildren: null }, function () { if (arr && arr.length > 0) { // 设置下拉列表显示数据 if (!value) { _this3.scrollTop = 0; _this3.scrollEle && _this3.scrollEle.scrollTo(0, 0); _this3.setSuperDropDownMenu(true); } _this3.formulaWidth(); if (!_this3.inputEle) { _this3.removeEvent(); _this3.addEvent(); } } }); } if (prevProps.value !== value) { // 更新时设置默认 value var defaultV = this.isMultiple ? [] : ''; defaultV = value || defaultValue || defaultV; this.setState({ value: defaultV }); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { this.removeEvent(); } }, { key: "render", value: function render() { var _this4 = this; var _this$state2 = this.state, maxWidth = _this$state2.maxWidth, selectWidth = _this$state2.selectWidth; var _a = this.props, dropdownStyle = _a.dropdownStyle, optionLabelProp = _a.optionLabelProp, dropdownClassName = _a.dropdownClassName, _a$placeholder = _a.placeholder, placeholder = _a$placeholder === void 0 ? defaultPlaceholder : _a$placeholder, capitalize = _a.capitalize, renderEmpty = _a.renderEmpty, props = __rest(_a, ["dropdownStyle", "optionLabelProp", "dropdownClassName", "placeholder", "capitalize", "renderEmpty"]); this.allList = this.getUseChildrenList(); this.allHeight = this.allList.length * this.ITEM_HEIGHT || 100; var _this$getStartAndEndI3 = this.getStartAndEndIndex(), startIndex = _this$getStartAndEndI3.startIndex, endIndex = _this$getStartAndEndI3.endIndex; var dynamicWidth = maxWidth; if (this.allList.length === 0 || maxWidth < selectWidth) { dynamicWidth = selectWidth; } dropdownStyle = Object.assign(Object.assign({ maxHeight: "".concat(DROPDOWN_HEIGHT, "px") }, dropdownStyle), { overflow: 'auto', position: 'relative', maxWidth: dynamicWidth }); var value = this.state.value; // 判断处于 antd Form 中时不自动设置 value var _props = Object.assign({}, props); // 先删除 value,再手动赋值,防止空 value 影响 placeholder delete _props.value; // value 为空字符会隐藏 placeholder,改为 undefined if (typeof value === 'string' && !value) { _props.value = undefined; } else { _props.value = value; } optionLabelProp = optionLabelProp || 'children'; return _react["default"].createElement(_select["default"], Object.assign({}, _props, { id: this.id, placeholder: (0, _utils.capitalizeFirstLetter)(placeholder, capitalize), onSearch: this.onSearch, onChange: this.onChange, dropdownClassName: "".concat(this.dropdownClassName, " ").concat(dropdownClassName || ''), optionLabelProp: optionLabelProp, dropdownStyle: dropdownStyle, onDropdownVisibleChange: this.onDropdownVisibleChange, onDeselect: this.onDeselect, ref: function ref(ele) { return _this4.select = ele; }, dropdownRender: function dropdownRender(menu, props) { if (_props.loading) { return _react["default"].createElement(_spin["default"], { size: "small", style: { marginLeft: 8 } }); } if (_this4.allList.length === 0) { return _react["default"].createElement("div", { className: "tntd-select-empty-container" }, renderEmpty ? renderEmpty('Select') : _react["default"].createElement(_empty["default"], { image: _empty["default"].PRESENTED_IMAGE_SIMPLE })); } return _react["default"].createElement(_DropDownWrap["default"], Object.assign({}, { startIndex: startIndex, endIndex: endIndex, allHeight: _this4.allHeight, menu: menu, itemHeight: _this4.ITEM_HEIGHT }, { ref: function ref(ele) { _this4.wrap = ele; } })); } }), this.allList); } }]); }(_react.PureComponent); function TntdSelect(props) { return _react["default"].createElement(_configProvider.ConfigConsumer, null, function (_ref2) { var renderEmpty = _ref2.renderEmpty; return _react["default"].createElement(SuperSelect, Object.assign({}, props, { renderEmpty: renderEmpty })); }); } TntdSelect.Option = Option; var _default = exports["default"] = TntdSelect;