-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f7f4bf5
commit 870895c
Showing
7 changed files
with
265 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
.van-swipe-cell { | ||
position: relative; | ||
overflow: hidden; | ||
} | ||
.van-swipe-cell__left, | ||
.van-swipe-cell__right { | ||
position: absolute; | ||
top: 0; | ||
height: 100%; | ||
} | ||
.van-swipe-cell__left { | ||
left: 0; | ||
transform: translate3d(-100%, 0, 0); | ||
} | ||
.van-swipe-cell__right { | ||
right: 0; | ||
transform: translate3d(100%, 0, 0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// packages | ||
import React, { | ||
FunctionComponent, | ||
useRef, | ||
useState, | ||
CSSProperties, | ||
useMemo, | ||
ReactElement, | ||
isValidElement, | ||
} from 'react'; | ||
import clsx from 'clsx'; | ||
import { View } from 'remax/wechat'; | ||
import { useNativeEffect } from 'remax'; | ||
// internal | ||
import { Select } from '../tools/Switch'; | ||
import { range } from '../tools/range'; | ||
import withDefaultProps from '../tools/with-default-props-advance'; | ||
import './SwipeCell.css'; | ||
import uuid from '../tools/uuid'; | ||
|
||
// 默认值填充属性 | ||
interface NeutralSwipeCellProps { | ||
asyncClose: boolean; | ||
disabled: boolean; | ||
} | ||
|
||
interface ExogenousSwipeCellProps { | ||
// 标识符 | ||
name: string; | ||
left?: ReactElement; | ||
right?: ReactElement; | ||
// 容器类名,用以覆盖内部 | ||
className?: string; | ||
onClick?: (event: unknown) => void; | ||
} | ||
|
||
type SwipeCellProps = NeutralSwipeCellProps & ExogenousSwipeCellProps; | ||
|
||
// scope | ||
const DefaultSwipeCellProps: NeutralSwipeCellProps = { | ||
asyncClose: false, | ||
disabled: false, | ||
}; | ||
|
||
const SwipeCell: FunctionComponent<SwipeCellProps> = (props) => { | ||
const threshold = 0.35; | ||
const { className, left, right, onClick, children } = props; | ||
const classnames = { | ||
container: clsx(className, 'van-swipe-cell'), | ||
}; | ||
|
||
const visibility = { | ||
left: isValidElement(left), | ||
right: isValidElement(right), | ||
}; | ||
|
||
const ids = useMemo( | ||
() => ({ | ||
left: uuid(), | ||
right: uuid(), | ||
}), | ||
[] | ||
); | ||
// 计算左右元素宽度 | ||
const $width$ = useRef({ | ||
left: 0, | ||
right: 0, | ||
}); | ||
|
||
// run only once, declare left, right one time | ||
useNativeEffect(() => { | ||
const qs = wx.createSelectorQuery(); | ||
|
||
qs.select(`#${ids.left}`).boundingClientRect(); | ||
qs.select(`#${ids.right}`).boundingClientRect(); | ||
|
||
qs.exec( | ||
( | ||
results: [ | ||
BoundingClientRectResult | undefined, | ||
BoundingClientRectResult | undefined | ||
] | ||
) => { | ||
$width$.current.left = results[0]?.width || 0; | ||
$width$.current.right = results[1]?.width || 0; | ||
} | ||
); | ||
}, []); | ||
|
||
// 滑动逻辑处理 | ||
const [offset, setOffset] = useState(0); | ||
// 滑动状态 | ||
const $touch$ = useRef({ | ||
status: 'SILENT', | ||
startX: 0, | ||
startOffset: 0, | ||
}); | ||
|
||
const onTouchStart = (event: any) => { | ||
$touch$.current = { | ||
status: 'START', | ||
startX: event.touches[0].clientX, | ||
startOffset: offset, | ||
}; | ||
}; | ||
|
||
const onTouchMove = (event: any) => { | ||
// 状态标记,用以 transition 样式计算 | ||
$touch$.current.status = 'DRAGING'; | ||
|
||
// 滑动距离计算 value 变化 | ||
const deltaX = event.touches[0].clientX - $touch$.current.startX; | ||
const next = $touch$.current.startOffset + deltaX; | ||
|
||
setOffset(range(next, -$width$.current.right, $width$.current.left)); | ||
}; | ||
|
||
const onTouchEnd = () => { | ||
// 状态标记,用以 transition 样式计算 | ||
$touch$.current.status = 'SILENT'; | ||
|
||
// 计算终值 | ||
if (visibility.right && -offset > $width$.current.right * threshold) { | ||
setOffset(-$width$.current.right); | ||
} else if (visibility.left && offset > $width$.current.left * threshold) { | ||
setOffset($width$.current.left); | ||
} else { | ||
setOffset(0); | ||
} | ||
}; | ||
|
||
const onClickWrap = (event: any) => { | ||
// 关闭 swipe 状态 | ||
setOffset(0); | ||
|
||
if (typeof onClick === 'function') { | ||
onClick(event); | ||
} | ||
}; | ||
|
||
const swipeStyle: CSSProperties = { | ||
transform: `translate3d(${offset}px, 0, 0)`, | ||
transition: | ||
$touch$.current.status === 'DRAGGING' | ||
? 'none' | ||
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)', | ||
}; | ||
|
||
return ( | ||
<View | ||
className={classnames.container} | ||
onTouchStart={onTouchStart} | ||
onTouchMove={onTouchMove} | ||
onTouchEnd={onTouchEnd} | ||
onClick={onClickWrap} | ||
> | ||
<View style={swipeStyle}> | ||
<Select in={visibility.left}> | ||
<View id={ids.left} className="van-swipe-cell__left"> | ||
{left} | ||
</View> | ||
</Select> | ||
{children} | ||
<Select in={visibility.right}> | ||
<View id={ids.right} className="van-swipe-cell__right"> | ||
{right} | ||
</View> | ||
</Select> | ||
</View> | ||
</View> | ||
); | ||
}; | ||
|
||
export default withDefaultProps<ExogenousSwipeCellProps, NeutralSwipeCellProps>( | ||
DefaultSwipeCellProps | ||
)(SwipeCell); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** | ||
* @description - nothing but export component | ||
*/ | ||
export { default } from './SwipeCell'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// eslint-disable-next-line import/prefer-default-export | ||
export function range(value: number, min: number, max: number): number { | ||
return Math.min(Math.max(value, min), max); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,3 +124,7 @@ page { | |
.demo-block__checkbox { | ||
margin-top: 6px; | ||
} | ||
|
||
.demo-block__card { | ||
--card-background-color: #fff; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// packages | ||
import React from 'react'; | ||
import { View, Text } from 'remax/wechat'; | ||
|
||
// internal | ||
import CellGroup from '../../../packages/CellGroup'; | ||
import Cell from '../../../packages/Cell'; | ||
import Button from '../../../packages/Button'; | ||
import Image from '../../../packages/Image'; | ||
import Card from '../../../packages/Card'; | ||
import SwipeCell from '../../../packages/SwipeCell'; | ||
|
||
export default () => { | ||
const left = <Button type="info">收藏</Button>; | ||
const right = ( | ||
<> | ||
<Button type="info" style={{ height: '100%' }}> | ||
收藏 | ||
</Button> | ||
<Button type="danger" style={{ height: '100%' }}> | ||
删除 | ||
</Button> | ||
</> | ||
); | ||
|
||
return ( | ||
<View className="demo-block"> | ||
<Text className="demo-block__title">基础用法</Text> | ||
<View> | ||
<SwipeCell name="2048" left={left} right={right}> | ||
<CellGroup> | ||
<Cell title="太平洋土著" /> | ||
</CellGroup> | ||
</SwipeCell> | ||
</View> | ||
|
||
<Text className="demo-block__title">基础用法</Text> | ||
<View> | ||
<SwipeCell name="二氧化碳" right={right}> | ||
<Card | ||
num={2} | ||
price="2.00" | ||
desc="描述信息" | ||
title="2018秋冬新款男士休闲时尚军绿飞行夹克秋冬新款男" | ||
className="demo-block__card" | ||
thumb={ | ||
<Image | ||
mode="aspectFit" | ||
className="van-card__img" | ||
src="https://img.yzcdn.cn/upload_files/2017/07/02/af5b9f44deaeb68000d7e4a711160c53.jpg" | ||
/> | ||
} | ||
/> | ||
</SwipeCell> | ||
</View> | ||
</View> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters