@tarojsx/ui
Version:
We reinvents the UI for Taro3+
189 lines • 8.78 kB
JavaScript
import classnames from 'classnames';
import dayjs from 'dayjs';
import React from 'react';
import { Swiper, SwiperItem, View } from '@tarojs/components';
import { delayQuerySelector } from '../../utils';
import generateCalendarGroup from '../common/helper';
import AtCalendarDateList from '../ui/date-list/index';
import AtCalendarDayList from '../ui/day-list/index';
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 React.Component {
constructor(props) {
super(props);
this.changeCount = 0;
this.currentSwiperIndex = 1;
this.startX = 0;
this.swipeStartPoint = 0;
this.isPreMonth = false;
this.maxWidth = 0;
this.isTouching = false;
this.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;
};
this.handleTouchStart = (e) => {
if (!this.props.isSwiper) {
return;
}
this.isTouching = true;
this.startX = e.touches[0].clientX;
};
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,
});
};
this.animateMoveSlide = (offset, callback) => {
this.setState({
isAnimate: true,
}, () => {
this.setState({
offsetSize: offset,
});
setTimeout(() => {
this.setState({
isAnimate: false,
}, () => {
callback && callback();
});
}, ANIMTE_DURATION);
});
};
this.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);
};
this.handleChange = (e) => {
const { current, source } = e.detail;
if (source === 'touch') {
this.currentSwiperIndex = current;
this.changeCount += 1;
}
};
this.handleAnimateFinish = () => {
if (this.changeCount > 0) {
this.props.onSwipeMonth(this.isPreMonth ? -this.changeCount : this.changeCount);
this.changeCount = 0;
}
};
this.handleSwipeTouchStart = (e) => {
const { clientY, clientX } = e.changedTouches[0];
this.swipeStartPoint = this.props.isVertical ? clientY : clientX;
};
this.handleSwipeTouchEnd = (e) => {
const { clientY, clientX } = e.changedTouches[0];
this.isPreMonth = this.props.isVertical
? clientY - this.swipeStartPoint > 0
: clientX - this.swipeStartPoint > 0;
};
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,
};
}
componentDidMount() {
delayQuerySelector('.at-calendar-slider__main').then((res) => {
this.maxWidth = res[0].width;
});
}
UNSAFE_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,
});
}
render() {
const { isSwiper } = this.props;
const { isAnimate, offsetSize, listGroup } = this.state;
if (!isSwiper) {
return (React.createElement(View, { className: classnames('main', 'at-calendar-slider__main', `at-calendar-slider__main--${process.env.TARO_ENV}`) },
React.createElement(AtCalendarDayList, null),
React.createElement(View, { className: "main__body body" },
React.createElement(View, { className: "body__slider body__slider--now" },
React.createElement(AtCalendarDateList, { list: listGroup[1].list, onClick: this.props.onDayClick, onLongClick: this.props.onLongClick })))));
}
/* 需要 Taro 组件库维护 Swiper 使 小程序 和 H5 的表现保持一致 */
if (process.env.TARO_ENV === 'h5') {
return (React.createElement(View, { className: classnames('main', 'at-calendar-slider__main', `at-calendar-slider__main--${process.env.TARO_ENV}`), onTouchEnd: this.handleTouchEnd, onTouchMove: this.handleTouchMove, onTouchStart: this.handleTouchStart },
React.createElement(AtCalendarDayList, null),
React.createElement(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)` : '',
} },
React.createElement(View, { className: "body__slider body__slider--pre" },
React.createElement(AtCalendarDateList, { list: listGroup[0].list })),
React.createElement(View, { className: "body__slider body__slider--now" },
React.createElement(AtCalendarDateList, { list: listGroup[1].list, onClick: this.props.onDayClick, onLongClick: this.props.onLongClick })),
React.createElement(View, { className: "body__slider body__slider--next" },
React.createElement(AtCalendarDateList, { list: listGroup[2].list })))));
}
return (React.createElement(View, { className: classnames('main', 'at-calendar-slider__main', `at-calendar-slider__main--${process.env.TARO_ENV}`) },
React.createElement(AtCalendarDayList, null),
React.createElement(Swiper, { circular: true, current: 1, skipHiddenItemLayout: true, className: classnames('main__body'), onChange: this.handleChange, vertical: this.props.isVertical, onAnimationFinish: this.handleAnimateFinish, onTouchEnd: this.handleSwipeTouchEnd, onTouchStart: this.handleSwipeTouchStart }, listGroup.map((item, key) => (React.createElement(SwiperItem, { key: item.value, itemId: key.toString() },
React.createElement(AtCalendarDateList, { list: item.list, onClick: this.props.onDayClick, onLongClick: this.props.onLongClick })))))));
}
}
AtCalendarBody.defaultProps = defaultProps;
//# sourceMappingURL=index.js.map