123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- import React from 'react';
- import { isEqual } from 'lodash';
- import cls from 'classnames';
- import PropTypes from 'prop-types';
- import CalendarFoundation, { CalendarAdapter, ParsedEventsType, ParsedEventsWithArray } from '@douyinfe/semi-foundation/calendar/foundation';
- import { cssClasses } from '@douyinfe/semi-foundation/calendar/constants';
- import DayCol from './dayCol';
- import TimeCol from './timeCol';
- import BaseComponent from '../_base/baseComponent';
- import LocaleConsumer from '../locale/localeConsumer';
- import localeContext from '../locale/context';
- import { Locale } from '../locale/interface';
- import { DayCalendarProps } from './interface';
- import '@douyinfe/semi-foundation/calendar/calendar.scss';
- const prefixCls = `${cssClasses.PREFIX}-day`;
- export interface DayCalendarState {
- scrollHeight: number;
- parsedEvents: ParsedEventsWithArray;
- cachedKeys: Array<string>;
- }
- export default class DayCalendar extends BaseComponent<DayCalendarProps, DayCalendarState> {
- static propTypes = {
- displayValue: PropTypes.instanceOf(Date),
- events: PropTypes.array,
- header: PropTypes.node,
- showCurrTime: PropTypes.bool,
- onClick: PropTypes.func,
- mode: PropTypes.string,
- renderTimeDisplay: PropTypes.func,
- markWeekend: PropTypes.bool,
- scrollTop: PropTypes.number,
- width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
- height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
- style: PropTypes.object,
- className: PropTypes.string,
- dateGridRender: PropTypes.func,
- };
- static defaultProps = {
- events: [] as DayCalendarProps['events'],
- displayValue: new Date(),
- mode: 'day',
- };
- static contextType = localeContext;
- dom: React.RefObject<HTMLDivElement>;
- scrollDom: React.RefObject<HTMLDivElement>;
- isWeekend: boolean;
- foundation: CalendarFoundation;
- constructor(props: DayCalendarProps) {
- super(props);
- this.foundation = new CalendarFoundation(this.adapter);
- this.state = {
- scrollHeight: 0,
- parsedEvents: {
- day: [],
- allDay: []
- },
- cachedKeys: [],
- };
- this.dom = React.createRef();
- this.scrollDom = React.createRef();
- this.isWeekend = false;
- }
- get adapter(): CalendarAdapter<DayCalendarProps, DayCalendarState> {
- return {
- ...super.adapter,
- updateScrollHeight: scrollHeight => {
- this.setState({ scrollHeight });
- },
- setParsedEvents: (parsedEvents: ParsedEventsType) => {
- this.setState({ parsedEvents: parsedEvents as ParsedEventsWithArray });
- },
- cacheEventKeys: cachedKeys => {
- this.setState({ cachedKeys });
- },
- };
- }
- componentDidMount() {
- this.foundation.init();
- const { scrollHeight } = this.scrollDom.current;
- this.dom.current.scrollTop = this.props.scrollTop;
- this.foundation.notifyScrollHeight(scrollHeight);
- this.foundation.parseDailyEvents();
- }
- componentDidUpdate(prevProps: DayCalendarProps, prevState: DayCalendarState) {
- const prevEventKeys = prevState.cachedKeys;
- const nowEventKeys = this.props.events.map(event => event.key);
- if (!isEqual(prevEventKeys, nowEventKeys)) {
- this.foundation.parseDailyEvents();
- }
- }
- componentWillUnmount() {
- this.foundation.destroy();
- }
- checkWeekend = (val: Date) => this.foundation.checkWeekend(val);
- renderAllDayEvents = (events: ParsedEventsWithArray['allDay']) => {
- const list = events.map((event, ind) => {
- const { children, key } = event;
- return (
- // eslint-disable-next-line max-len
- <li className={`${cssClasses.PREFIX}-event-item ${cssClasses.PREFIX}-event-allday`} key={key || `allDay-${ind}`}>
- {children}
- </li>
- );
- });
- return list;
- };
- handleClick = (e: React.MouseEvent, val: [Date, number, number, number]) => {
- const { onClick } = this.props;
- const value = this.foundation.formatCbValue(val);
- onClick && onClick(e, value);
- };
- renderAllDay = (events: ParsedEventsWithArray['allDay']) => {
- const allDayCls = `${cssClasses.PREFIX}-all-day`;
- const contentCls = cls(`${allDayCls}-content`, {
- [`${cssClasses.PREFIX}-weekend`]: this.isWeekend,
- });
- return (
- <LocaleConsumer componentName="Calendar">
- {(locale: Locale['Calendar']) => (
- <div className={`${allDayCls}`}>
- <ul className={`${cssClasses.PREFIX}-tag ${allDayCls}-tag ${prefixCls}-sticky-left`}>
- <span>{locale.allDay}</span>
- </ul>
- <div role="gridcell" className={contentCls}>
- <ul className={`${cssClasses.PREFIX}-event-items`}>
- {this.renderAllDayEvents(events)}
- </ul>
- </div>
- </div>
- )}
- </LocaleConsumer>
- );
- };
- render() {
- // eslint-disable-next-line max-len
- const { dateGridRender, displayValue, showCurrTime, renderTimeDisplay, markWeekend, className, height, width, style, header } = this.props;
- const dayCls = cls(prefixCls, className);
- const dayStyle = {
- height,
- width,
- ...style,
- };
- const { parsedEvents, scrollHeight } = this.state;
- this.isWeekend = markWeekend && this.checkWeekend(displayValue);
- return (
- <div className={dayCls} style={dayStyle} ref={this.dom}>
- <div className={`${prefixCls}-sticky-top`}>
- {header}
- {this.renderAllDay(parsedEvents.allDay)}
- </div>
- <div className={`${prefixCls}-scroll-wrapper`}>
- <div className={`${prefixCls}-scroll`} ref={this.scrollDom}>
- <TimeCol
- className={`${prefixCls}-sticky-left`}
- renderTimeDisplay={renderTimeDisplay}
- />
- <DayCol
- events={parsedEvents.day}
- displayValue={displayValue}
- scrollHeight={scrollHeight}
- handleClick={this.handleClick}
- showCurrTime={showCurrTime}
- isWeekend={this.isWeekend}
- dateGridRender={dateGridRender}
- />
- </div>
- </div>
- </div>
- );
- }
- }
|