UNPKG

taro-material

Version:

Mini Program components that implement Google's Material Design.

208 lines 7.85 kB
import Nerv from "nervjs"; import * as tslib_1 from "tslib"; import dayjs from 'dayjs'; import classnames from 'classnames'; import Taro from "@tarojs/taro-h5"; import bind from 'bind-decorator'; import { View, Swiper, SwiperItem } from '@tarojs/components'; import AtCalendarDayList from "../ui/day-list/index"; import AtCalendarDateList from "../ui/date-list/index"; import generateCalendarGroup from "../common/helper"; import { delayQuerySelector } from "../../../common/utils"; const ANIMTE_DURATION = 300; const defaultProps = { marks: [], selectedDate: { end: Date.now(), start: Date.now() }, format: 'YYYY-MM-DD', generateDate: Date.now() }; export default class AtCalendarBody extends Taro.Component { constructor(props) { super(...arguments); this.changeCount = 0; this.currentSwiperIndex = 1; this.startX = 0; this.swipeStartPoint = 0; this.isPreMonth = false; this.maxWidth = 0; this.isTouching = false; this.handleTouchMove = e => { if (!this.props.isSwiper) { return; } if (!this.isTouching) return; const { clientX } = e.touches[0]; const offsetSize = clientX - this.startX; this.setState({ offsetSize }); }; const { validDates, marks, format, minDate, maxDate, generateDate, selectedDate, selectedDates } = props; this.generateFunc = generateCalendarGroup({ validDates, format, minDate, maxDate, marks, selectedDates }); const listGroup = this.getGroups(generateDate, selectedDate); this.state = { listGroup, offsetSize: 0, isAnimate: false }; } getGroups(generateDate, selectedDate) { const dayjsDate = dayjs(generateDate); const arr = []; const preList = this.generateFunc(dayjsDate.subtract(1, 'month').valueOf(), selectedDate); const nowList = this.generateFunc(generateDate, selectedDate, true); const nextList = this.generateFunc(dayjsDate.add(1, 'month').valueOf(), selectedDate); const preListIndex = this.currentSwiperIndex === 0 ? 2 : this.currentSwiperIndex - 1; const nextListIndex = this.currentSwiperIndex === 2 ? 0 : this.currentSwiperIndex + 1; arr[preListIndex] = preList; arr[nextListIndex] = nextList; arr[this.currentSwiperIndex] = nowList; return arr; } componentWillReceiveProps(nextProps) { const { validDates, marks, format, minDate, maxDate, generateDate, selectedDate, selectedDates } = nextProps; this.generateFunc = generateCalendarGroup({ validDates, format, minDate, maxDate, marks, selectedDates }); const listGroup = this.getGroups(generateDate, selectedDate); this.setState({ offsetSize: 0, listGroup }); } componentDidMount() { delayQuerySelector(this, '.at-calendar-slider__main').then(res => { this.maxWidth = res[0].width; }); } handleTouchStart(e) { if (!this.props.isSwiper) { return; } this.isTouching = true; this.startX = e.touches[0].clientX; } animateMoveSlide(offset, callback) { this.setState({ isAnimate: true }, () => { this.setState({ offsetSize: offset }); setTimeout(() => { this.setState({ isAnimate: false }, () => { callback && callback(); }); }, ANIMTE_DURATION); }); } handleTouchEnd() { if (!this.props.isSwiper) { return; } const { offsetSize } = this.state; this.isTouching = false; const isRight = offsetSize > 0; const breakpoint = this.maxWidth / 2; const absOffsetSize = Math.abs(offsetSize); if (absOffsetSize > breakpoint) { const res = isRight ? this.maxWidth : -this.maxWidth; return this.animateMoveSlide(res, () => { this.props.onSwipeMonth(isRight ? -1 : 1); }); } this.animateMoveSlide(0); } handleChange(e) { const { current, source } = e.detail; if (source === 'touch') { this.currentSwiperIndex = current; this.changeCount = this.changeCount + 1; } } handleAnimateFinish() { if (this.changeCount > 0) { this.props.onSwipeMonth(this.isPreMonth ? -this.changeCount : this.changeCount); this.changeCount = 0; } } handleSwipeTouchStart(e) { const { clientY, clientX } = e.changedTouches[0]; this.swipeStartPoint = this.props.isVertical ? clientY : clientX; } handleSwipeTouchEnd(e) { const { clientY, clientX } = e.changedTouches[0]; this.isPreMonth = this.props.isVertical ? clientY - this.swipeStartPoint > 0 : clientX - this.swipeStartPoint > 0; } render() { const { isSwiper } = this.props; const { isAnimate, offsetSize, listGroup } = this.state; if (!isSwiper) { return <View className={classnames('main', 'at-calendar-slider__main', `at-calendar-slider__main--${"h5"}`)}> <AtCalendarDayList /> <View className="main__body body"> <View className="body__slider body__slider--now"> <AtCalendarDateList list={listGroup[1].list} onClick={this.props.onDayClick} onLongClick={this.props.onLongClick} /> </View> </View> </View>; } /* 需要 Taro 组件库维护 Swiper 使 小程序 和 H5 的表现保持一致 */ { return <View className={classnames('main', 'at-calendar-slider__main', `at-calendar-slider__main--${"h5"}`)} onTouchEnd={this.handleTouchEnd} onTouchMove={this.handleTouchMove} onTouchStart={this.handleTouchStart}> <AtCalendarDayList /> <View className={classnames('main__body body', { 'main__body--slider': isSwiper, 'main__body--animate': isAnimate })} style={{ transform: isSwiper ? `translateX(-100%) translate3d(${offsetSize},0,0)` : '', WebkitTransform: isSwiper ? `translateX(-100%) translate3d(${offsetSize}px,0,0)` : '' }}> <View className="body__slider body__slider--pre"> <AtCalendarDateList list={listGroup[0].list} /> </View> <View className="body__slider body__slider--now"> <AtCalendarDateList list={listGroup[1].list} onClick={this.props.onDayClick} onLongClick={this.props.onLongClick} /> </View> <View className="body__slider body__slider--next"> <AtCalendarDateList list={listGroup[2].list} /> </View> </View> </View>; } return <View className={classnames('main', 'at-calendar-slider__main', `at-calendar-slider__main--${"h5"}`)}> <AtCalendarDayList /> <Swiper circular current={1} skipHiddenItemLayout className={classnames('main__body')} onChange={this.handleChange} vertical={this.props.isVertical} onAnimationFinish={this.handleAnimateFinish} onTouchEnd={this.handleSwipeTouchEnd} onTouchStart={this.handleSwipeTouchStart}> {listGroup.map((item, key) => <SwiperItem key={item.value} itemId={key.toString()}> <AtCalendarDateList list={item.list} onClick={this.props.onDayClick} onLongClick={this.props.onLongClick} /> </SwiperItem>)} </Swiper> </View>; } } AtCalendarBody.options = { addGlobalClass: true }; AtCalendarBody.defaultProps = defaultProps; tslib_1.__decorate([bind], AtCalendarBody.prototype, "getGroups", null); tslib_1.__decorate([bind], AtCalendarBody.prototype, "handleTouchStart", null); tslib_1.__decorate([bind], AtCalendarBody.prototype, "handleTouchEnd", null); tslib_1.__decorate([bind], AtCalendarBody.prototype, "handleChange", null); tslib_1.__decorate([bind], AtCalendarBody.prototype, "handleAnimateFinish", null); tslib_1.__decorate([bind], AtCalendarBody.prototype, "handleSwipeTouchStart", null); tslib_1.__decorate([bind], AtCalendarBody.prototype, "handleSwipeTouchEnd", null);