UNPKG

zarm

Version:

基于 React 的移动端UI库

233 lines (209 loc) 8.12 kB
import _extends from "@babel/runtime/helpers/extends"; import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _regeneratorRuntime from "@babel/runtime/regenerator"; import { useDrag } from '@use-gesture/react'; import { createBEM } from '@zarm-design/bem'; import React, { useCallback, useContext, useRef } from 'react'; import { ConfigContext } from '../config-provider'; import useClickAway from '../use-click-away'; import { useSafeState } from '../utils/hooks'; import SwipeActionItem from './SwipeActionItem'; var SwipeAction = /*#__PURE__*/React.forwardRef(function (props, ref) { var _leftRef$current, _rightRef$current; var children = props.children, className = props.className, leftActions = props.leftActions, rightActions = props.rightActions, moveDistanceRatio = props.moveDistanceRatio, moveTimeSpan = props.moveTimeSpan, initialAnimationDuration = props.animationDuration, offset = props.offset, autoClose = props.autoClose, disabled = props.disabled, onClose = props.onClose, onOpen = props.onOpen; var isOpen = useRef(null); var pending = useRef(false); var leftRef = useRef(); var rightRef = useRef(); var swipeActionWrap = useRef(ref || null); var _useContext = useContext(ConfigContext), prefixCls = _useContext.prefixCls; var _useSafeState = useSafeState(0), _useSafeState2 = _slicedToArray(_useSafeState, 2), offsetLeft = _useSafeState2[0], setOffsetLeft = _useSafeState2[1]; var _useSafeState3 = useSafeState(initialAnimationDuration), _useSafeState4 = _slicedToArray(_useSafeState3, 2), animationDuration = _useSafeState4[0], setAnimationDuration = _useSafeState4[1]; var bem = createBEM('swipe-action', { prefixCls: prefixCls }); var doTransition = useCallback(function (_ref) { var offsetX = _ref.offsetX, duration = _ref.duration; setAnimationDuration(duration); setOffsetLeft(offsetX); }, [offsetLeft]); useClickAway(swipeActionWrap.current, function () { close(); }, 'ontouchstart' in window ? 'touchstart' : 'mousedown'); var dragStart = useRef(0); var close = function close() { if (pending.current) return; doTransition({ offsetX: 0, duration: initialAnimationDuration }); isOpen.current = null; dragStart.current = 0; }; var renderButtons = function renderButtons(actions, direction, refs) { if (!actions || actions.length === 0) { return; } var cls = bem('actions', [_defineProperty({}, "".concat(direction), true)]); return /*#__PURE__*/React.createElement("div", { className: cls, ref: refs }, actions.map(function (action, index) { return /*#__PURE__*/React.createElement(SwipeActionItem, _extends({}, action, { key: +index, onClick: /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() { var _action$onClick; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: pending.current = true; _context.next = 3; return (_action$onClick = action.onClick) === null || _action$onClick === void 0 ? void 0 : _action$onClick.call(action); case 3: pending.current = false; if (autoClose) { close === null || close === void 0 ? void 0 : close(); } case 5: case "end": return _context.stop(); } } }, _callee); })) })); })); }; var dragging = useRef(false); var btnsLeftWidth = (leftRef === null || leftRef === void 0 ? void 0 : (_leftRef$current = leftRef.current) === null || _leftRef$current === void 0 ? void 0 : _leftRef$current.offsetWidth) || 0; var btnsRightWidth = (rightRef === null || rightRef === void 0 ? void 0 : (_rightRef$current = rightRef.current) === null || _rightRef$current === void 0 ? void 0 : _rightRef$current.offsetWidth) || 0; var bind = useDrag(function (state) { var _state$offset = _slicedToArray(state.offset, 1), offsetX = _state$offset[0]; if (isOpen.current === 'right' && offsetX < 0 || isOpen.current === 'left' && offsetX > 0) { return false; } if (state.down) { dragging.current = true; } if (!dragging.current) return; dragStart.current = offsetX; if (offsetX > 0 && !(leftRef !== null && leftRef !== void 0 && leftRef.current)) { return false; } if (offsetX < 0 && !(rightRef !== null && rightRef !== void 0 && rightRef.current)) { return false; } if (state.last) { var timeSpan = Math.floor(state.elapsedTime); var distanceX = 0; var _isOpen = false; if (btnsLeftWidth > 0 && (offsetX / btnsLeftWidth > moveDistanceRatio || offsetX > 0 && timeSpan <= moveTimeSpan)) { distanceX = btnsLeftWidth; _isOpen = true; } else if (btnsRightWidth > 0 && offsetX / btnsRightWidth < -moveDistanceRatio || offsetX < 0 && timeSpan <= moveTimeSpan) { distanceX = -btnsRightWidth; _isOpen = true; } doTransition({ offsetX: distanceX, duration: initialAnimationDuration }); if (_isOpen) { // 打开 isOpen.current = distanceX > 0 ? 'left' : 'right'; onOpen === null || onOpen === void 0 ? void 0 : onOpen(); } else { // 还原 close(); } window.setTimeout(function () { dragging.current = false; }); } else { doTransition({ offsetX: offsetX, duration: 0 }); } }, { from: function from() { return [dragStart.current, 0]; }, bounds: function bounds() { var _leftRef$current2, _rightRef$current2; var leftWidth = (leftRef === null || leftRef === void 0 ? void 0 : (_leftRef$current2 = leftRef.current) === null || _leftRef$current2 === void 0 ? void 0 : _leftRef$current2.offsetWidth) || 0; var rightWidth = (rightRef === null || rightRef === void 0 ? void 0 : (_rightRef$current2 = rightRef.current) === null || _rightRef$current2 === void 0 ? void 0 : _rightRef$current2.offsetWidth) || 0; return { left: -rightWidth - offset, right: leftWidth + offset }; }, enabled: !disabled, axis: 'x', pointer: { touch: true }, preventScroll: true, triggerAllEvents: true }); var style = { WebkitTransitionDuration: "".concat(animationDuration, "ms"), transitionDuration: "".concat(animationDuration, "ms"), WebkitTransform: "translate3d(".concat(offsetLeft, "px, 0, 0)"), transform: "translate3d(".concat(offsetLeft, "px, 0, 0)") }; var cls = bem([className]); return /*#__PURE__*/React.createElement(React.Fragment, null, leftActions || rightActions ? /*#__PURE__*/React.createElement("div", _extends({ ref: swipeActionWrap, className: cls, style: props.style }, bind()), renderButtons(leftActions, 'left', leftRef), renderButtons(rightActions, 'right', rightRef), /*#__PURE__*/React.createElement("div", { className: bem('content'), style: style, onTransitionEnd: function onTransitionEnd() { return !isOpen.current && (onClose === null || onClose === void 0 ? void 0 : onClose()); }, onClick: function onClick(e) { if (isOpen.current && !dragging.current) { e.preventDefault(); e.stopPropagation(); close(); } } }, children)) : children); }); SwipeAction.displayName = 'SwipeAction'; SwipeAction.defaultProps = { leftActions: [], rightActions: [], moveDistanceRatio: 0.5, moveTimeSpan: 300, animationDuration: 300, offset: 10, autoClose: true, disabled: false }; export default SwipeAction;