From 5651075cbc9dd2de769dff8016db7892b5412a9a Mon Sep 17 00:00:00 2001 From: hejiasheng Date: Fri, 21 Sep 2018 16:23:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(component):=20=E5=AE=8C=E6=88=90=20SwipeAc?= =?UTF-8?q?tion=20=E7=BB=84=E4=BB=B6=E7=BC=96=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.js | 1 + src/components/swipe-action/index.js | 150 ++++++++++++++++++ src/components/swipe-action/index.scss | 28 ++++ src/components/swipe-action/options/index.js | 54 +++++++ .../swipe-action/options/index.scss | 12 ++ src/pages/action/swipe-action/index.js | 123 ++++++++++++++ src/pages/action/swipe-action/index.scss | 5 + src/pages/panel/index.js | 27 ++-- 8 files changed, 389 insertions(+), 11 deletions(-) create mode 100644 src/components/swipe-action/index.js create mode 100644 src/components/swipe-action/index.scss create mode 100644 src/components/swipe-action/options/index.js create mode 100644 src/components/swipe-action/options/index.scss create mode 100644 src/pages/action/swipe-action/index.js create mode 100644 src/pages/action/swipe-action/index.scss diff --git a/src/app.js b/src/app.js index a52b8229d..98d212881 100644 --- a/src/app.js +++ b/src/app.js @@ -23,6 +23,7 @@ class App extends Component { 'pages/action/modal/index', 'pages/action/progress/index', 'pages/action/action-sheet/index', + 'pages/action/swipe-action/index', 'pages/action/activity-indicator/index', 'pages/navigation/drawer/index', 'pages/navigation/pagination/index', diff --git a/src/components/swipe-action/index.js b/src/components/swipe-action/index.js new file mode 100644 index 000000000..5f0417396 --- /dev/null +++ b/src/components/swipe-action/index.js @@ -0,0 +1,150 @@ +import Taro from '@tarojs/taro' +import { View, Text } from '@tarojs/components' + +import PropTypes from 'prop-types' +import classNames from 'classnames' +import _isFunction from 'lodash/isFunction' + +import AtComponent from '../../common/component' +import AtSwipeActionOptions from './options/index' + +import './index.scss' + +export default class AtSwipeAction extends AtComponent { + constructor () { + super(...arguments) + + this.startX = null + this.maxOffsetSize = 0 + this.isTouching = false + this.endValue = 0 + + this.state = { + offsetSize: 0 + } + } + + handleTouchStart = e => { + const { clientX } = e.touches[0] + + if (this.props.disabled) return + + this.startX = clientX + this.isTouching = true + } + + handleTouchEnd = () => { + this.isTouching = false + + const { offsetSize } = this.state + + this.endValue = offsetSize + + const breakpoint = this.maxOffsetSize / 2 + const absOffsetSize = Math.abs(offsetSize) + + if (absOffsetSize > breakpoint) { + this.endValue = -this.maxOffsetSize + return this.setState({ + offsetSize: -this.maxOffsetSize + }) + } + + this.endValue = 0 + + this.setState({ + offsetSize: 0 + }) + } + + handleTouchMove = e => { + const { clientX } = e.touches[0] + if (this.isTouching) { + const offsetSize = clientX - this.startX + const isRight = offsetSize > 0 + + if (this.state.offsetSize === 0 && isRight) return + + const value = this.endValue + offsetSize + this.setState({ + offsetSize: value >= 0 ? 0 : value + }) + } + } + + handleDomInfo = ({ width }) => { + this.maxOffsetSize = width + } + + handleClick = (item, index, ...arg) => { + const { onClick, autoClose } = this.props + if (_isFunction(onClick)) { + onClick(item, index, ...arg) + } + if (autoClose) { + this.setState({ + offsetSize: 0 + }) + } + } + + render () { + const { offsetSize } = this.state + const { options } = this.props + const rootClass = classNames('at-swipe-action', this.props.className) + + return ( + + + {this.props.children} + + + {Array.isArray(options) && options.length > 0 ? ( + + {options.map((item, key) => ( + + {item.text} + + ))} + + ) : null} + + ) + } +} + +AtSwipeAction.defaultProps = {} + +AtSwipeAction.propTypes = { + disabled: PropTypes.bool, + autoClose: PropTypes.bool, + options: PropTypes.arrayOf( + PropTypes.shape({ + text: PropTypes.string, + style: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), + className: PropTypes.oneOfType([ + PropTypes.object, + PropTypes.string, + PropTypes.array + ]) + }) + ) +} diff --git a/src/components/swipe-action/index.scss b/src/components/swipe-action/index.scss new file mode 100644 index 000000000..8dc87fac7 --- /dev/null +++ b/src/components/swipe-action/index.scss @@ -0,0 +1,28 @@ +@import "../../style/mixins/index.scss"; +@import "../../style/theme/default.scss"; + +.at-swipe-action { + position: relative; + overflow: hidden; + + &__content { + background-color: white; + position: relative; + z-index: 2; + font-size: $font-size-lg; + transition: transform 200ms $timing-func; + } + + &__option { + @include active; + @include align-items(center); + + height: 100%; + background-color: $color-grey-2; + display: inline-flex; + color: $color-white; + font-size: $font-size-base; + padding: 0 $spacing-h-xl; + text-align: center; + } +} diff --git a/src/components/swipe-action/options/index.js b/src/components/swipe-action/options/index.js new file mode 100644 index 000000000..ef79d982d --- /dev/null +++ b/src/components/swipe-action/options/index.js @@ -0,0 +1,54 @@ +import Taro from '@tarojs/taro' +import { View } from '@tarojs/components' + +// import PropTypes from 'prop-types' +import classNames from 'classnames' + +import AtComponent from '../../../common/component' + +import './index.scss' + +const REM_LAYOUT_DELAY = 500 + +export default class AtSwiperActionOptions extends AtComponent { + delay = () => + new Promise(resolve => { + if (Taro.getEnv() === Taro.ENV_TYPE.WEB) { + return setTimeout(() => { + resolve() + }, REM_LAYOUT_DELAY) + } + if (Taro.getEnv() === Taro.ENV_TYPE.WEAPP) { + return resolve() + } + }) + + componentDidMount () { + const selector = Taro.createSelectorQuery().in(this.$scope) + + this.delay().then(() => { + selector + .select('.at-swipe-action__options') + .fields({ + size: true + }) + .exec(res => { + console.log(res[0]) + this.props.onQueryedDom(res[0]) + }) + }) + } + + render () { + const rootClass = classNames( + 'at-swipe-action__options', + this.props.className + ) + + return {this.props.children} + } +} + +AtSwiperActionOptions.defaultProps = {} + +AtSwiperActionOptions.propTypes = {} diff --git a/src/components/swipe-action/options/index.scss b/src/components/swipe-action/options/index.scss new file mode 100644 index 000000000..31d0ffda4 --- /dev/null +++ b/src/components/swipe-action/options/index.scss @@ -0,0 +1,12 @@ +@import '../../../style/mixins/libs/flex.scss'; + +.at-swipe-action__options { + @include align-items(center); + + display: inline-flex; + position: absolute; + top: 0; + right: 0; + z-index: 1; + height: 100%; +} diff --git a/src/pages/action/swipe-action/index.js b/src/pages/action/swipe-action/index.js new file mode 100644 index 000000000..e7a6fdf33 --- /dev/null +++ b/src/pages/action/swipe-action/index.js @@ -0,0 +1,123 @@ +/* eslint taro/custom-component-children: 0 */ + +import Taro from '@tarojs/taro' +import { View } from '@tarojs/components' + +import AtList from '../../../components/list/index' +import AtListItem from '../../../components/list/item/index' +import AtSwipeAction from '../../../components/swipe-action/index' + +import DocsHeader from '../../components/doc-header' + +import './index.scss' + +const OPTIONS = [ + { + text: '取消', + style: { + backgroundColor: '#6190E8' + } + }, + { + text: '确认', + style: { + backgroundColor: '#FF4949' + } + } +] + +export default class SwipeActionPage extends Taro.Component { + config = { + navigationBarTitleText: 'Taro UI' + } + + handleClick = (item, key, e) => { + console.log('触发了点击', item, key, e) + } + + render () { + return ( + + {/* S Header */} + + {/* E Header */} + + {/* S Body */} + + {/* 无 Title */} + + 普通使用 + + + + AtSwipeAction 一般使用场景 + + + + + + + 禁止滑动 + + + + 禁止滑动展示 + + + + + + + 自动关闭 + + + + 自动关闭展示 + + + + + + + 传递点击事件 + + + + 点击事件展示 + + + + + + + 与List组件使用 + + + + + + + + + + + + + + + + + + + ) + } +} diff --git a/src/pages/action/swipe-action/index.scss b/src/pages/action/swipe-action/index.scss new file mode 100644 index 000000000..be632f7f7 --- /dev/null +++ b/src/pages/action/swipe-action/index.scss @@ -0,0 +1,5 @@ +.swipe-action-page { + .normal { + line-height: 50px; + } +} diff --git a/src/pages/panel/index.js b/src/pages/panel/index.js index 7fdc0e4e5..80498f657 100644 --- a/src/pages/panel/index.js +++ b/src/pages/panel/index.js @@ -46,7 +46,7 @@ export default class PanelBasic extends Component { } }, list: { - 'basic': [ + basic: [ { id: 'Color', name: '颜色' @@ -64,7 +64,7 @@ export default class PanelBasic extends Component { name: '按钮' } ], - 'view': [ + view: [ { id: 'Avatar', name: '头像' @@ -94,7 +94,7 @@ export default class PanelBasic extends Component { name: '滑块视图容器' } ], - 'action': [ + action: [ { id: 'Action-Sheet', name: '动作面板' @@ -114,9 +114,13 @@ export default class PanelBasic extends Component { { id: 'Toast', name: '轻提示' + }, + { + id: 'Swipe-Action', + name: '滑动按钮' } ], - 'form': [ + form: [ { id: 'Input', name: '输入框' @@ -158,7 +162,7 @@ export default class PanelBasic extends Component { name: '滑动条' } ], - 'layout': [ + layout: [ { id: 'Flex', name: '弹性布局' @@ -180,7 +184,7 @@ export default class PanelBasic extends Component { name: '浮动弹层' } ], - 'navigation': [ + navigation: [ { id: 'NavBar', name: '导航栏' @@ -235,10 +239,11 @@ export default class PanelBasic extends Component { {/* S Header */} - { - icon ? - : - } + {icon ? ( + + ) : ( + + )} {title} @@ -256,7 +261,7 @@ export default class PanelBasic extends Component { onClick={this.gotoComponent} > {`${item.id} ${item.name}`} - + ))}