@nutui/nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
324 lines (323 loc) • 16.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "Popup", {
enumerable: true,
get: function() {
return Popup;
}
});
var _interop_require_default = require("@swc/helpers/_/_interop_require_default");
var _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
var _async_to_generator = require("@swc/helpers/_/_async_to_generator");
var _define_property = require("@swc/helpers/_/_define_property");
var _object_spread = require("@swc/helpers/_/_object_spread");
var _object_spread_props = require("@swc/helpers/_/_object_spread_props");
var _sliced_to_array = require("@swc/helpers/_/_sliced_to_array");
var _ts_generator = require("@swc/helpers/_/_ts_generator");
var _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
var _taro = require("@tarojs/taro");
var _reactdom = require("react-dom");
var _classnames = /*#__PURE__*/ _interop_require_default._(require("classnames"));
var _iconsreacttaro = require("@nutui/icons-react-taro");
var _components = require("@tarojs/components");
var _getrect = require("../../utils/taro/get-rect");
var _overlay = require("../overlay/overlay");
var _index = /*#__PURE__*/ _interop_require_default._(require("../overlay/index"));
var _uselockscoll = require("../../hooks/taro/use-lock-scoll");
var _platform = require("../../utils/taro/platform");
var _pxtransform = require("../../utils/taro/px-transform");
var _configprovider = require("../configprovider/configprovider");
var defaultProps = (0, _object_spread_props._)((0, _object_spread._)({}, _overlay.defaultOverlayProps), {
position: 'center',
transition: '',
overlayStyle: {},
overlayClassName: '',
closeable: false,
closeIconPosition: 'top-right',
closeIcon: 'close',
destroyOnClose: false,
portal: null,
overlay: true,
round: false,
resizable: false,
minHeight: '',
onOpen: function onOpen() {},
onClose: function onClose() {},
onOverlayClick: function onOverlayClick() {
return true;
},
onCloseIconClick: function onCloseIconClick() {
return true;
},
onTouchStart: function onTouchStart() {},
onTouchMove: function onTouchMove() {},
onTouchEnd: function onTouchEnd() {}
});
// 默认1000,参看variables
var _zIndex = 1100;
var Popup = function Popup(props) {
var _$_object_spread = (0, _object_spread._)({}, defaultProps, props), children = _$_object_spread.children, visible = _$_object_spread.visible, overlay = _$_object_spread.overlay, closeOnOverlayClick = _$_object_spread.closeOnOverlayClick, overlayStyle = _$_object_spread.overlayStyle, overlayClassName = _$_object_spread.overlayClassName, zIndex = _$_object_spread.zIndex, lockScroll = _$_object_spread.lockScroll, duration = _$_object_spread.duration, closeable = _$_object_spread.closeable, closeIconPosition = _$_object_spread.closeIconPosition, closeIcon = _$_object_spread.closeIcon, left = _$_object_spread.left, title = _$_object_spread.title, top = _$_object_spread.top, description = _$_object_spread.description, style = _$_object_spread.style, transition = _$_object_spread.transition, round = _$_object_spread.round, position = _$_object_spread.position, className = _$_object_spread.className, destroyOnClose = _$_object_spread.destroyOnClose, portal = _$_object_spread.portal, resizable = _$_object_spread.resizable, minHeight = _$_object_spread.minHeight, onOpen = _$_object_spread.onOpen, onClose = _$_object_spread.onClose, onOverlayClick = _$_object_spread.onOverlayClick, onCloseIconClick = _$_object_spread.onCloseIconClick, afterShow = _$_object_spread.afterShow, afterClose = _$_object_spread.afterClose, onClick = _$_object_spread.onClick, onTouchStart = _$_object_spread.onTouchStart, onTouchMove = _$_object_spread.onTouchMove, onTouchEnd = _$_object_spread.onTouchEnd, closeAriaLabel = _$_object_spread.closeAriaLabel;
var innerIndex = zIndex || _zIndex;
var _useState = (0, _sliced_to_array._)((0, _react.useState)(innerIndex), 2), index = _useState[0], setIndex = _useState[1];
var _useState1 = (0, _sliced_to_array._)((0, _react.useState)(visible), 2), innerVisible = _useState1[0], setInnerVisible = _useState1[1];
var _useState2 = (0, _sliced_to_array._)((0, _react.useState)(true), 2), showChildren = _useState2[0], setShowChildren = _useState2[1];
var _useState3 = (0, _sliced_to_array._)((0, _react.useState)(''), 2), transitionName = _useState3[0], setTransitionName = _useState3[1];
var nodeRef = (0, _uselockscoll.useLockScrollTaro)(innerVisible && lockScroll);
var topNodeRef = _react.default.useRef(null);
var rootRect = (0, _react.useRef)(null);
var touchStartRef = (0, _react.useRef)(0);
var touchMoveDistanceRef = (0, _react.useRef)(0);
var heightRef = (0, _react.useRef)(0);
var defaultHeightRef = (0, _react.useRef)(0);
var isTouching = (0, _react.useRef)(false);
var locale = (0, _configprovider.useConfig)().locale;
var classPrefix = 'nut-popup';
var overlayStyles = (0, _object_spread._)({}, overlayStyle);
var contentZIndex = (0, _platform.harmony)() ? index + 1 : index // 解决harmony层级问题
;
var popStyles = (0, _object_spread._)({
zIndex: contentZIndex,
minHeight: minHeight
}, style);
var _obj;
var popClassName = (0, _classnames.default)(classPrefix, (_obj = {}, (0, _define_property._)(_obj, "".concat(classPrefix, "-round"), round || position === 'bottom'), (0, _define_property._)(_obj, "".concat(classPrefix, "-").concat(position), true), _obj), className);
var _useState4 = (0, _sliced_to_array._)((0, _react.useState)(''), 2), popupHeight = _useState4[0], setPopupHeight = _useState4[1];
var _useState5 = (0, _sliced_to_array._)((0, _react.useState)(''), 2), topBottom = _useState5[0], setTopBottom = _useState5[1];
var resizeStyles = function resizeStyles() {
if (popupHeight !== '') {
return {
height: popupHeight
};
}
};
var open = function open() {
if (!innerVisible) {
// 当高度改变后,再次打开时,将高度置为初始高度
if (position === 'bottom' && resizable && nodeRef.current && heightRef.current) {
setPopupHeight((0, _pxtransform.pxTransform)(defaultHeightRef.current));
}
setInnerVisible(true);
setIndex(++innerIndex);
}
if (destroyOnClose) {
setShowChildren(true);
}
onOpen && onOpen();
};
var getPopupHeight = function getPopupHeight() {
return (0, _async_to_generator._)(function() {
var _nodeRef_current, rect, height;
return (0, _ts_generator._)(this, function(_state) {
switch(_state.label){
case 0:
return [
4,
(0, _getrect.getRectInMultiPlatformWithoutCache)(nodeRef.current)
];
case 1:
rect = _state.sent();
height = ((_nodeRef_current = nodeRef.current) === null || _nodeRef_current === void 0 ? void 0 : _nodeRef_current.offsetHeight) || (rect === null || rect === void 0 ? void 0 : rect.height);
setTopBottom((0, _pxtransform.pxTransform)(height));
return [
2
];
}
});
})();
};
(0, _react.useEffect)(function() {
if (innerVisible && topNodeRef.current && nodeRef.current) {
(0, _taro.nextTick)(function() {
(0, _taro.nextTick)(function() {
getPopupHeight();
});
});
}
}, [
innerVisible
]);
var close = function close() {
if (innerVisible) {
setInnerVisible(false);
if (destroyOnClose) {
setTimeout(function() {
setShowChildren(false);
}, Number(duration));
}
onClose && onClose();
}
};
var handleOverlayClick = function handleOverlayClick(e) {
e.stopPropagation();
if (closeOnOverlayClick && onOverlayClick(e)) {
close();
}
};
var handleCloseIconClick = function handleCloseIconClick(e) {
onCloseIconClick(e) && close();
};
var renderCloseIcon = function renderCloseIcon() {
var closeClasses = (0, _classnames.default)("".concat(classPrefix, "-title-right"), "".concat(classPrefix, "-title-right-").concat(closeIconPosition));
return /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, closeable && /*#__PURE__*/ _react.default.createElement(_components.View, {
className: closeClasses,
onClick: handleCloseIconClick,
ariaRole: "button",
ariaLabel: closeAriaLabel || locale.close
}, /*#__PURE__*/ _react.default.isValidElement(closeIcon) ? closeIcon : /*#__PURE__*/ _react.default.createElement(_iconsreacttaro.Close, null)));
};
var renderTop = function renderTop() {
if (!top) return null;
return /*#__PURE__*/ _react.default.createElement(_components.View, {
className: "".concat(classPrefix, "-bottom-top"),
ref: topNodeRef,
style: {
bottom: topBottom
}
}, top);
};
var renderTitle = function renderTitle() {
if (left || title || description) {
return /*#__PURE__*/ _react.default.createElement(_components.View, {
className: "".concat(classPrefix, "-title")
}, position === 'bottom' && /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, left && /*#__PURE__*/ _react.default.createElement(_components.View, {
className: "".concat(classPrefix, "-title-left")
}, left), (title || description) && /*#__PURE__*/ _react.default.createElement(_components.View, {
className: "".concat(classPrefix, "-title-wrapper")
}, title && /*#__PURE__*/ _react.default.createElement(_components.View, {
className: "".concat(classPrefix, "-title-title")
}, title), description && /*#__PURE__*/ _react.default.createElement(_components.View, {
className: "".concat(classPrefix, "-title-description ").concat(title ? "".concat(classPrefix, "-title-description-gap") : '')
}, description))), renderCloseIcon());
}
if (closeable) {
return renderCloseIcon();
}
};
var handleTouchStart = function handleTouchStart(event) {
return (0, _async_to_generator._)(function() {
var _nodeRef_current, _rootRect_current, e, rect;
return (0, _ts_generator._)(this, function(_state) {
switch(_state.label){
case 0:
if (position !== 'bottom' || !resizable || !nodeRef.current) return [
2
];
e = event;
// 开始touch,记录下touch的pageY,用以判断是向上滑动还是向下滑动
touchStartRef.current = e.touches[0].pageY;
// 标记开始滑动
isTouching.current = true;
return [
4,
(0, _getrect.getRectInMultiPlatformWithoutCache)(nodeRef.current)
];
case 1:
rect = _state.sent();
rootRect.current = rect;
heightRef.current = ((_nodeRef_current = nodeRef.current) === null || _nodeRef_current === void 0 ? void 0 : _nodeRef_current.offsetHeight) || ((_rootRect_current = rootRect.current) === null || _rootRect_current === void 0 ? void 0 : _rootRect_current.height) || 0;
if (!defaultHeightRef.current) defaultHeightRef.current = heightRef.current;
onTouchStart === null || onTouchStart === void 0 ? void 0 : onTouchStart(heightRef.current, e);
return [
2
];
}
});
})();
};
var handleTouchMove = function handleTouchMove(event) {
if (position !== 'bottom' || !resizable || !nodeRef.current || !rootRect.current) return;
var e = event;
e.stopPropagation();
// 计算位移:move过程中,当前的pageY 与 start值比较
touchMoveDistanceRef.current = e.touches[0].pageY - touchStartRef.current;
var handleMove = function handleMove() {
var min = typeof minHeight === 'number' ? minHeight : parseInt(String(minHeight || 0), 10) || 0;
var currentHeight = Math.max(min, heightRef.current - touchMoveDistanceRef.current);
setPopupHeight((0, _pxtransform.pxTransform)(currentHeight));
if (touchMoveDistanceRef.current > 0 && isTouching.current) {
// 向下滑动
onTouchMove === null || onTouchMove === void 0 ? void 0 : onTouchMove(currentHeight, e, 'down');
} else {
// 向上滑动
onTouchMove === null || onTouchMove === void 0 ? void 0 : onTouchMove(currentHeight, e, 'up');
}
};
requestAnimationFrame(handleMove);
};
var handleTouchEnd = function handleTouchEnd(event) {
if (position !== 'bottom' || !resizable || !nodeRef.current || !rootRect.current) return;
var e = event;
isTouching.current = false;
var min = typeof minHeight === 'number' ? minHeight : parseInt(String(minHeight || 0), 10) || 0;
var currentHeight = Math.max(min, heightRef.current - touchMoveDistanceRef.current);
onTouchEnd === null || onTouchEnd === void 0 ? void 0 : onTouchEnd(currentHeight, e);
};
var renderPop = function renderPop() {
return /*#__PURE__*/ _react.default.createElement(_components.View, {
ref: nodeRef,
style: (0, _object_spread._)((0, _object_spread_props._)((0, _object_spread._)({}, popStyles), {
display: innerVisible ? (popStyles === null || popStyles === void 0 ? void 0 : popStyles.display) || 'block' : 'none'
}), resizeStyles()),
className: popClassName,
onClick: onClick,
catchMove: lockScroll,
onTouchStart: handleTouchStart,
onTouchMove: handleTouchMove,
onTouchEnd: handleTouchEnd,
onTouchCancel: handleTouchEnd
}, renderTop(), renderTitle(), showChildren ? children : null);
};
// const renderPop = () => {
// return (
// <CSSTransition
// nodeRef={nodeRef}
// classNames={transitionName}
// mountOnEnter
// unmountOnExit={destroyOnClose}
// timeout={duration}
// in={innerVisible}
// onEntered={afterShow}
// onExited={afterClose}
// >
// {renderContent()}
// </CSSTransition>
// )
// }
var renderNode = function renderNode() {
return /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, overlay ? /*#__PURE__*/ _react.default.createElement(_index.default, {
zIndex: index,
style: overlayStyles,
className: overlayClassName,
visible: innerVisible,
closeOnOverlayClick: closeOnOverlayClick,
lockScroll: lockScroll,
duration: duration,
onClick: handleOverlayClick
}) : null, renderPop());
};
(0, _react.useEffect)(function() {
visible ? open() : close();
}, [
visible
]);
(0, _react.useEffect)(function() {
setTransitionName(transition || "".concat(classPrefix, "-slide-").concat(position));
}, [
position,
transition
]);
var resolveContainer = function resolveContainer(getContainer) {
return (typeof getContainer === 'function' ? getContainer() : getContainer) || document.body;
};
var renderToContainer = function renderToContainer(getContainer, node) {
if (getContainer) {
var container = resolveContainer(getContainer);
return /*#__PURE__*/ (0, _reactdom.createPortal)(node, container);
}
return node;
};
return /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, renderToContainer(portal, renderNode()));
};
Popup.displayName = 'NutPopup';