UNPKG

ukelli-ui

Version:

Base on React's UI lib. Make frontend's dev simpler and faster.

286 lines (285 loc) 12.3 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; import React from 'react'; import ReactDOM from 'react-dom'; import classnames from 'classnames'; import { IsFunc, DebounceClass } from 'basic-helper'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import { Icon } from '../icon'; import { ClickAway } from '../click-away'; import { getElementOffsetInfo } from '../utils/get-elem-offset'; import positionFilter from '../position-filter'; import setDOMById from '../set-dom'; import { getTop, getBottom, } from '../utils/position'; var dropdownContainerID = 'DropdownContainer'; var dropdownContainerDOM; var offset = 10; var calculateOverlayPosition = function (options) { var target = options.target, position = options.position, overlayElem = options.overlayElem, scrollX = options.scrollX, scrollY = options.scrollY; var _a = getElementOffsetInfo(target), offsetTop = _a.offsetTop, offsetLeft = _a.offsetLeft, offsetWidth = _a.offsetWidth, offsetHeight = _a.offsetHeight; var overlayElemWidth = overlayElem.offsetWidth; var overlayElemHeight = overlayElem.offsetHeight; var offsetInfo = { offsetWidth: offsetWidth, offsetHeight: offsetHeight, elemHeight: overlayElemHeight, elemWidth: overlayElemWidth, offsetLeft: offsetLeft, offsetTop: offsetTop }; var posiInfo; var _position = []; // const left = getLeft(offsetInfo); if (position.indexOf('top') !== -1) { posiInfo = getTop(offsetInfo); } else if (position.indexOf('bottom') !== -1) { posiInfo = getBottom(offsetInfo); } if (position.indexOf('right') !== -1) { posiInfo.left = offsetLeft + offsetWidth - overlayElemWidth; _position.push('right'); } else { _position.push('left'); } _position.push(posiInfo.position); // overlayElem.classList.add(position); // console.log(overlayElem.classList) _position.forEach(function (p) { overlayElem.classList.add(p); }); // res = { top, left }; // topAnimation(overlayElem, top); overlayElem.style.left = posiInfo.left - scrollX + "px"; overlayElem.style.top = posiInfo.top - scrollY + "px"; // setTimeout(() => overlayElem.classList.add('done'), 50); // return { top, left }; return posiInfo; }; var DropdownWrapper = /** @class */ (function (_super) { __extends(DropdownWrapper, _super); function DropdownWrapper(props) { var _this = _super.call(this, props) || this; _this.state = { isShow: false, searchValue: '' }; // 记录是否已经渲染过一次 overlay _this._shown = false; _this.handleClickAway = function () { if (_this.state.isShow) _this.hide(); }; _this.handleClickMenu = function (e, preventDefault) { if (preventDefault === void 0) { preventDefault = false; } var _a = _this.props, outside = _a.outside, scrollElem = _a.scrollElem; if (outside) { if (preventDefault) e.preventDefault(); // const { clientX, clientY } = e; if (!_this.addScrollListener && scrollElem) { var _scrollElem = scrollElem(); _scrollElem.addEventListener('scroll', _this.hide); } _this.addScrollListener = true; } _this.showSubMenu(); _this.focusInput(); }; _this.showSubMenu = function (isShow) { if (isShow === void 0) { isShow = true; } _this.setState({ isShow: !!isShow, }); }; _this.hide = function () { var scrollElem = _this.props.scrollElem; if (_this.addScrollListener && scrollElem) { var elem = scrollElem(); elem.removeEventListener('scroll', _this.hide); _this.addScrollListener = false; } /** 一定隐藏成功 */ if (!_this.hideDebounce) _this.hideDebounce = new DebounceClass(); _this.hideDebounce.exec(_this._hide, 50); }; _this._hide = function () { _this.setState({ isShow: false, searchValue: '' }); }; _this.saveInput = function (_i) { if (_i) _this._input = _i; }; _this.onSearch = function (e) { var val = e.target.value.trim(); _this.setState({ searchValue: val }); }; _this.getPropsForOverlay = function () { return (__assign(__assign({}, _this.state), { hide: _this.hide, showSubMenu: _this.showSubMenu, focusInput: _this.focusInput })); }; _this.saveItems = function (e) { _this.overlayElem = e; if (!e) return; var _a = _this.props, scrollX = _a.scrollX, scrollY = _a.scrollY; calculateOverlayPosition({ overlayElem: _this.overlayElem, target: _this.displayTitleDOM, position: _this._position, scrollX: scrollX, scrollY: scrollY }); }; _this.overlayRender = function () { var _a = _this.props, overlay = _a.overlay, outside = _a.outside, _b = _a.position, position = _b === void 0 ? '' : _b; var isShow = _this.state.isShow; // const isLeft = position.indexOf('left') !== -1; // const caretOffset = this.displayTitleDOM ? this.displayTitleDOM.offsetWidth / 2 : 10; var overlayClasses = classnames("dropdown-items", !outside && _this._position, isShow && 'show'); var dropdownCom = (React.createElement(TransitionGroup, { component: null }, React.createElement(CSSTransition, { key: isShow ? "opened" : "closed", classNames: "drop-menu", timeout: 200 }, isShow ? (React.createElement("div", __assign({ ref: outside ? function (e) { return _this.saveItems(e); } : null }, _this.bindOverlayTrigger(), { className: overlayClasses }), React.createElement("span", { className: "caret" }), overlay && overlay(_this.getPropsForOverlay()))) : React.createElement("span", null)))); return outside ? ReactDOM.createPortal(dropdownCom, dropdownContainerDOM) : dropdownCom; }; _this.saveClickAway = function (e) { _this.clickAwayRef = e; if (e) { _this.updateNodeRef = e.updateNodeRef; } }; _this.getDfaultChild = function (menuTitle) { var withInput = _this.props.withInput; var searchValue = _this.state.searchValue; return (React.createElement("div", { className: "display-menu" }, React.createElement("div", { className: "display-title" }, menuTitle), withInput && (React.createElement("input", { type: "text", ref: _this.saveInput, placeholder: typeof menuTitle === 'string' ? menuTitle : '', value: searchValue, className: "search-input", onChange: _this.onSearch })), React.createElement("div", { className: "icon-wrap" }, React.createElement(Icon, { n: "angle-down" })))); }; _this.childrenRender = function () { var _a = _this.props, children = _a.children, menuTitle = _a.menuTitle; var child; var _title = menuTitle; switch (true) { case IsFunc(children): child = children(_this.getPropsForOverlay()); break; case React.isValidElement(children): child = children; break; default: if (typeof children === 'string') { _title = children; } child = _this.getDfaultChild(_title); break; } return child; }; _this.handleMouseEnter = function (event) { if (_this.delayExec) _this.delayExec.cancel(); _this.handleClickMenu(event); }; _this.handleMouseLeave = function () { if (!_this.delayExec) _this.delayExec = new DebounceClass(); _this.delayExec.exec(_this.handleClickAway, 200); }; _this.bindOverlayTrigger = function () { var _a = _this.props, trigger = _a.trigger, outside = _a.outside; var res = {}; switch (trigger) { case 'click': if (outside) { res = { onClick: function (e) { return _this.handleClickMenu(e, true); } }; } break; case 'hover': res = { onMouseEnter: _this.handleMouseEnter, onMouseLeave: _this.handleMouseLeave }; break; } return res; }; _this.bindWrapperTrigger = function () { var trigger = _this.props.trigger; var res = {}; switch (trigger) { case 'click': res = { onClick: _this.handleClickMenu }; break; case 'hover': res = { onMouseEnter: _this.handleMouseEnter, onMouseLeave: _this.handleMouseLeave }; break; } return res; }; _this._position = positionFilter(props.position).split(' '); if (!dropdownContainerDOM) dropdownContainerDOM = setDOMById(dropdownContainerID, '__dropdown-menu outside'); return _this; } DropdownWrapper.prototype.focusInput = function () { this._input && this._input.focus(); }; DropdownWrapper.prototype.render = function () { var _this = this; var isShow = this.state.isShow; var _a = this.props, className = _a.className, withInput = _a.withInput, style = _a.style, error = _a.error, outside = _a.outside; var classNames = classnames("__dropdown-menu", className && className, withInput && "input-mode", error && 'error', isShow && 'show', !outside && this._position); return (React.createElement(ClickAway, { ref: this.saveClickAway, onClickAway: this.handleClickAway }, React.createElement("div", { className: classNames, style: style }, React.createElement("span", __assign({ className: "menu-wrapper", ref: function (e) { _this.displayTitleDOM = e; } }, this.bindWrapperTrigger()), this.childrenRender()), this.overlayRender()))); }; DropdownWrapper.defaultProps = { withInput: true, menuTitle: 'Title', trigger: 'click', outside: false, scrollX: 0, scrollY: 0, position: 'bottom,left', scrollElem: function () { return document; } }; return DropdownWrapper; }(React.PureComponent)); export default DropdownWrapper;