UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

222 lines (221 loc) 8.08 kB
import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react"; import classNames from "classnames"; import { useTouch } from "../../hooks/use-touch"; import { getRect } from "../../utils/get-rect"; function preventDefault(event, isStopPropagation) { if (typeof event.cancelable !== 'boolean' || event.cancelable) { event.preventDefault(); } if (isStopPropagation) { event.stopPropagation(); } } var defaultProps = { name: '' }; export var Swipe = /*#__PURE__*/ forwardRef(function(props, instanceRef) { var classPrefix = 'nut-swipe'; var touch = useTouch(); var _$_object_spread = _object_spread({}, defaultProps, props), children = _$_object_spread.children, className = _$_object_spread.className, style = _$_object_spread.style; var root = useRef(); var opened = useRef(false); var lockClick = useRef(false); var startOffset = useRef(0); var _useState = _sliced_to_array(useState({ offset: 0, dragging: false }), 2), state = _useState[0], setState = _useState[1]; var _useState1 = _sliced_to_array(useState({ left: 0, right: 0 }), 2), actionWidth = _useState1[0], setActionWidth = _useState1[1]; var wrapperStyle = { transform: "translate3d(".concat(state.offset, "px, 0, 0)"), transitionDuration: state.dragging ? '0s' : '.6s' }; var leftWidth = actionWidth.left; var rightWidth = actionWidth.right; var onTouchStart = function(event) { if (!props.disabled) { var _props_onTouchStart; startOffset.current = state.offset; touch.start(event); (_props_onTouchStart = props.onTouchStart) === null || _props_onTouchStart === void 0 ? void 0 : _props_onTouchStart.call(props, event); } }; var onTouchMove = function(event) { var _props_onTouchMove; if (props.disabled) { return; } touch.move(event); (_props_onTouchMove = props.onTouchMove) === null || _props_onTouchMove === void 0 ? void 0 : _props_onTouchMove.call(props, event); if (touch.isHorizontal()) { lockClick.current = true; var newState = _object_spread_props(_object_spread({}, state), { dragging: true }); var isEdge = !opened || touch.deltaX.current * startOffset.current < 0; if (isEdge) { preventDefault(event, true); } newState.offset = rangeCalculation(touch.deltaX.current + startOffset.current, -rightWidth, leftWidth); setState(newState); } }; var onTouchEnd = function(event) { if (state.dragging) { var _props_onTouchEnd; setState(function(v) { return _object_spread_props(_object_spread({}, v), { dragging: false }); }); toggle(state.offset > 0 ? 'left' : 'right'); setTimeout(function() { lockClick.current = false; }, 0); (_props_onTouchEnd = props.onTouchEnd) === null || _props_onTouchEnd === void 0 ? void 0 : _props_onTouchEnd.call(props, event); } }; var toggle = function(side) { var offset = Math.abs(state.offset); var base = 0.3; var baseNum = opened ? 1 - base : base; var width = side === 'left' ? leftWidth : rightWidth; if (width && offset > Number(width) * baseNum) { open(side); } else { close(side); } }; var open = function(side) { var _props_onOpen; opened.current = true; var offset = side === 'left' ? leftWidth : -rightWidth; var name = props.name; (_props_onOpen = props.onOpen) === null || _props_onOpen === void 0 ? void 0 : _props_onOpen.call(props, { name: name, position: side }); setState(function(v) { return _object_spread_props(_object_spread({}, v), { offset: Number(offset) || 0 }); }); }; var close = function(position) { if (opened.current) { var _props_onClose; opened.current = false; (_props_onClose = props.onClose) === null || _props_onClose === void 0 ? void 0 : _props_onClose.call(props, { name: props.name, position: position || 'left' }); } setState(function(v) { return _object_spread_props(_object_spread({}, v), { offset: 0 }); }); }; var rangeCalculation = function(num, min, max) { return Math.min(Math.max(Number(num), Number(min)), Number(max)); }; var getNodeWidth = function(node) { if (node) { var ele = getRect(node); return ele.width; } return 0; }; var leftRef = useCallback(function(node) { if (node !== null) { setActionWidth(function(v) { return _object_spread_props(_object_spread({}, v), { left: getNodeWidth(node) }); }); } }, [ props.leftAction ]); var rightRef = useCallback(function(node) { if (node !== null) { setActionWidth(function(v) { return _object_spread_props(_object_spread({}, v), { right: getNodeWidth(node) }); }); } }, [ props.rightAction ]); var renderActionContent = function(side, measuredRef) { if (props["".concat(side, "Action")]) { return /*#__PURE__*/ React.createElement("div", { ref: measuredRef, className: "".concat(classPrefix, "-").concat(side), onClick: function(e) { return handleOperate(e, side); } }, props["".concat(side, "Action")]); } return null; }; var handleOperate = function(event, position) { event.stopPropagation(); if (props.beforeClose) { props.beforeClose(position); } else { props.onActionClick && props.onActionClick(event, position); } }; useImperativeHandle(instanceRef, function() { return { open: open, close: function() { return close(); } }; }); useEffect(function() { var handler = function(event) { var targets = [ root ]; if (targets.some(function(targetItem) { var targetElement = targetItem.current || targetItem; return !targetElement || (targetElement === null || targetElement === void 0 ? void 0 : targetElement.contains(event.target)); })) { return; } close(); }; document.addEventListener('touchstart', handler); return function() { document.removeEventListener('touchstart', handler); }; }, []); return /*#__PURE__*/ React.createElement("div", { ref: root, className: classNames(classPrefix, className), onTouchStart: function(e) { return onTouchStart(e); }, onTouchMove: function(e) { return onTouchMove(e); }, onTouchEnd: function(e) { return onTouchEnd(e); }, style: style }, /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-wrapper"), style: wrapperStyle }, renderActionContent('left', leftRef), children, renderActionContent('right', rightRef))); }); Swipe.displayName = 'NutSwipe';