diff --git a/src/packages/swipe/__tests__/swipe.spec.tsx b/src/packages/swipe/__tests__/swipe.spec.tsx
index 83901c44d3..649c303675 100644
--- a/src/packages/swipe/__tests__/swipe.spec.tsx
+++ b/src/packages/swipe/__tests__/swipe.spec.tsx
@@ -1,10 +1,11 @@
import * as React from 'react'
-import { render } from '@testing-library/react'
+import { render, fireEvent, act } from '@testing-library/react'
import '@testing-library/jest-dom'
import Swipe from '../index'
import Cell from '../../cell'
import Button from '../../button'
import InputNumber from '../../inputnumber'
+import * as getRectModule from '@/utils/get-rect'
test('base swipe', () => {
const { container } = render(
@@ -96,3 +97,196 @@ test('base swipe content', async () => {
container.querySelector('.nut-swipe .nut-swipe-right .nut-button-wrap')
).toHaveTextContent('购物车')
})
+
+test('swipe right to open via touch', () => {
+ const spy = jest.spyOn(getRectModule, 'getRect').mockReturnValue({
+ width: 80,
+ height: 40,
+ top: 0,
+ left: 0,
+ right: 80,
+ bottom: 40,
+ })
+
+ const onOpen = jest.fn()
+ const { container } = render(
+
+ 删除
+
+ }
+ onOpen={onOpen}
+ >
+ |
+
+ )
+
+ const wrapper = container.querySelector('.nut-swipe') as HTMLElement
+
+ act(() => {
+ fireEvent.touchStart(wrapper, {
+ touches: [{ clientX: 200, clientY: 0, pageX: 200, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchMove(wrapper, {
+ touches: [{ clientX: 100, clientY: 0, pageX: 100, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchEnd(wrapper, {
+ changedTouches: [{ clientX: 100, clientY: 0 }],
+ })
+ })
+
+ expect(onOpen).toHaveBeenCalled()
+ spy.mockRestore()
+})
+
+test('swipe left to open via touch', () => {
+ const spy = jest.spyOn(getRectModule, 'getRect').mockReturnValue({
+ width: 80,
+ height: 40,
+ top: 0,
+ left: 0,
+ right: 80,
+ bottom: 40,
+ })
+
+ const onOpen = jest.fn()
+ const { container } = render(
+
+ 选择
+
+ }
+ onOpen={onOpen}
+ >
+ |
+
+ )
+
+ const wrapper = container.querySelector('.nut-swipe') as HTMLElement
+
+ act(() => {
+ fireEvent.touchStart(wrapper, {
+ touches: [{ clientX: 100, clientY: 0, pageX: 100, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchMove(wrapper, {
+ touches: [{ clientX: 200, clientY: 0, pageX: 200, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchEnd(wrapper, {
+ changedTouches: [{ clientX: 200, clientY: 0 }],
+ })
+ })
+
+ expect(onOpen).toHaveBeenCalled()
+ spy.mockRestore()
+})
+
+test('swipe close after opened', () => {
+ const spy = jest.spyOn(getRectModule, 'getRect').mockReturnValue({
+ width: 80,
+ height: 40,
+ top: 0,
+ left: 0,
+ right: 80,
+ bottom: 40,
+ })
+
+ const onClose = jest.fn()
+ const { container } = render(
+
+ 删除
+
+ }
+ onClose={onClose}
+ >
+ |
+
+ )
+
+ const wrapper = container.querySelector('.nut-swipe') as HTMLElement
+
+ // Open first
+ act(() => {
+ fireEvent.touchStart(wrapper, {
+ touches: [{ clientX: 200, clientY: 0, pageX: 200, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchMove(wrapper, {
+ touches: [{ clientX: 100, clientY: 0, pageX: 100, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchEnd(wrapper, {
+ changedTouches: [{ clientX: 100, clientY: 0 }],
+ })
+ })
+
+ // Close by swiping back
+ act(() => {
+ fireEvent.touchStart(wrapper, {
+ touches: [{ clientX: 100, clientY: 0, pageX: 100, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchMove(wrapper, {
+ touches: [{ clientX: 200, clientY: 0, pageX: 200, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchEnd(wrapper, {
+ changedTouches: [{ clientX: 200, clientY: 0 }],
+ })
+ })
+
+ expect(onClose).toHaveBeenCalled()
+ spy.mockRestore()
+})
+
+test('disabled swipe should not respond to touch', () => {
+ const onOpen = jest.fn()
+ const { container } = render(
+
+ 删除
+
+ }
+ onOpen={onOpen}
+ >
+ |
+
+ )
+
+ const wrapper = container.querySelector('.nut-swipe') as HTMLElement
+
+ act(() => {
+ fireEvent.touchStart(wrapper, {
+ touches: [{ clientX: 200, clientY: 0, pageX: 200, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchMove(wrapper, {
+ touches: [{ clientX: 100, clientY: 0, pageX: 100, pageY: 0 }],
+ })
+ })
+ act(() => {
+ fireEvent.touchEnd(wrapper, {
+ changedTouches: [{ clientX: 100, clientY: 0 }],
+ })
+ })
+
+ expect(onOpen).not.toHaveBeenCalled()
+})
diff --git a/src/packages/swipe/swipe.taro.tsx b/src/packages/swipe/swipe.taro.tsx
index 8ff06cabc1..e2ad4fd88b 100644
--- a/src/packages/swipe/swipe.taro.tsx
+++ b/src/packages/swipe/swipe.taro.tsx
@@ -142,7 +142,8 @@ export const Swipe = forwardRef<
if (touch.isHorizontal()) {
lockClick.current = true
const newState = { ...state, dragging: true }
- const isEdge = !opened || touch.deltaX.current * startOffset.current < 0
+ const isEdge =
+ !opened.current || touch.deltaX.current * startOffset.current < 0
if (isEdge) {
preventDefault(event, true)
}
@@ -170,7 +171,7 @@ export const Swipe = forwardRef<
const toggle = (side: PositionX) => {
const offset = Math.abs(state.offset)
const base = 0.3
- const baseNum = opened ? 1 - base : base
+ const baseNum = opened.current ? 1 - base : base
const width =
side === 'left' ? actionWidth.current.left : actionWidth.current.right
if (width && offset > Number(width) * baseNum) {
diff --git a/src/packages/swipe/swipe.tsx b/src/packages/swipe/swipe.tsx
index df5ee1f38f..991a664ed7 100644
--- a/src/packages/swipe/swipe.tsx
+++ b/src/packages/swipe/swipe.tsx
@@ -52,6 +52,8 @@ export const Swipe = forwardRef<
left: 0,
right: 0,
})
+ const actionWidthRef = useRef(actionWidth)
+ actionWidthRef.current = actionWidth
const wrapperStyle = {
transform: `translate3d(${state.offset}px, 0, 0)`,
transitionDuration: state.dragging ? '0s' : '.6s',
@@ -78,7 +80,8 @@ export const Swipe = forwardRef<
if (touch.isHorizontal()) {
lockClick.current = true
const newState = { ...state, dragging: true }
- const isEdge = !opened || touch.deltaX.current * startOffset.current < 0
+ const isEdge =
+ !opened.current || touch.deltaX.current * startOffset.current < 0
if (isEdge) {
preventDefault(event, true)
}
@@ -108,7 +111,7 @@ export const Swipe = forwardRef<
const toggle = (side: PositionX) => {
const offset = Math.abs(state.offset)
const base = 0.3
- const baseNum = opened ? 1 - base : base
+ const baseNum = opened.current ? 1 - base : base
const width = side === 'left' ? leftWidth : rightWidth
if (width && offset > Number(width) * baseNum) {
@@ -151,22 +154,22 @@ export const Swipe = forwardRef<
}
return 0
}
- const leftRef = useCallback(
- (node: Element | null) => {
- if (node !== null) {
- setActionWidth((v) => ({ ...v, left: getNodeWidth(node) }))
+ const leftRef = useCallback((node: Element | null) => {
+ if (node !== null) {
+ const width = getNodeWidth(node)
+ if (width !== actionWidthRef.current.left) {
+ setActionWidth((v) => ({ ...v, left: width }))
}
- },
- [props.leftAction]
- )
- const rightRef = useCallback(
- (node: Element | null) => {
- if (node !== null) {
- setActionWidth((v) => ({ ...v, right: getNodeWidth(node) }))
+ }
+ }, [])
+ const rightRef = useCallback((node: Element | null) => {
+ if (node !== null) {
+ const width = getNodeWidth(node)
+ if (width !== actionWidthRef.current.right) {
+ setActionWidth((v) => ({ ...v, right: width }))
}
- },
- [props.rightAction]
- )
+ }
+ }, [])
const renderActionContent = (side: PositionX, measuredRef: any) => {
if (props[`${side}Action`]) {
return (