UNPKG

@babylimon/react-calendar-timeline

Version:
240 lines (222 loc) 6.08 kB
import React from 'react' import PropTypes from 'prop-types' import { TimelineHeadersConsumer } from './HeadersContext' import { TimelineStateConsumer } from '../timeline/TimelineStateContext' import { iterateTimes, calculateXPositionForTime } from '../utility/calendar' export class CustomHeader extends React.Component { static propTypes = { //component props children: PropTypes.func.isRequired, unit: PropTypes.string.isRequired, //Timeline context timeSteps: PropTypes.object.isRequired, visibleTimeStart: PropTypes.number.isRequired, visibleTimeEnd: PropTypes.number.isRequired, canvasTimeStart: PropTypes.number.isRequired, canvasTimeEnd: PropTypes.number.isRequired, canvasWidth: PropTypes.number.isRequired, showPeriod: PropTypes.func.isRequired, headerData: PropTypes.object, getLeftOffsetFromDate: PropTypes.func.isRequired, height: PropTypes.number.isRequired, } constructor(props) { super(props) const { canvasTimeStart, canvasTimeEnd, canvasWidth, unit, timeSteps, showPeriod, getLeftOffsetFromDate } = props const intervals = this.getHeaderIntervals({ canvasTimeStart, canvasTimeEnd, canvasWidth, unit, timeSteps, showPeriod, getLeftOffsetFromDate }) this.state = { intervals } } shouldComponentUpdate(nextProps) { if ( nextProps.canvasTimeStart !== this.props.canvasTimeStart || nextProps.canvasTimeEnd !== this.props.canvasTimeEnd || nextProps.canvasWidth !== this.props.canvasWidth || nextProps.unit !== this.props.unit || nextProps.timeSteps !== this.props.timeSteps || nextProps.showPeriod !== this.props.showPeriod || nextProps.children !== this.props.children || nextProps.headerData !== this.props.headerData ) { return true } return false } UNSAFE_componentWillReceiveProps(nextProps) { if ( nextProps.canvasTimeStart !== this.props.canvasTimeStart || nextProps.canvasTimeEnd !== this.props.canvasTimeEnd || nextProps.canvasWidth !== this.props.canvasWidth || nextProps.unit !== this.props.unit || nextProps.timeSteps !== this.props.timeSteps || nextProps.showPeriod !== this.props.showPeriod ) { const { canvasTimeStart, canvasTimeEnd, canvasWidth, unit, timeSteps, showPeriod, getLeftOffsetFromDate } = nextProps const intervals = this.getHeaderIntervals({ canvasTimeStart, canvasTimeEnd, canvasWidth, unit, timeSteps, showPeriod, getLeftOffsetFromDate }) this.setState({ intervals }) } } getHeaderIntervals = ({ canvasTimeStart, canvasTimeEnd, unit, timeSteps, getLeftOffsetFromDate }) => { const intervals = [] iterateTimes( canvasTimeStart, canvasTimeEnd, unit, timeSteps, (startTime, endTime) => { const left = getLeftOffsetFromDate(startTime.valueOf()) const right = getLeftOffsetFromDate(endTime.valueOf()) const width = right - left intervals.push({ startTime, endTime, labelWidth: width, left }) } ) return intervals } getRootProps = (props = {}) => { const { style } = props return { style: Object.assign({}, style ? style : {}, { position: 'relative', width: this.props.canvasWidth, height: this.props.height, }) } } getIntervalProps = (props = {}) => { const { interval, style } = props if (!interval) throw new Error('you should provide interval to the prop getter') const { startTime, labelWidth, left } = interval return { style: this.getIntervalStyle({ style, startTime, labelWidth, canvasTimeStart: this.props.canvasTimeStart, unit: this.props.unit, left }), key: `label-${startTime.valueOf()}` } } getIntervalStyle = ({ left, labelWidth, style }) => { return { ...style, left, width: labelWidth, position: 'absolute' } } getStateAndHelpers = () => { const { canvasTimeStart, canvasTimeEnd, unit, showPeriod, timelineWidth, visibleTimeStart, visibleTimeEnd, headerData, } = this.props //TODO: only evaluate on changing params return { timelineContext: { timelineWidth, visibleTimeStart, visibleTimeEnd, canvasTimeStart, canvasTimeEnd }, headerContext: { unit, intervals: this.state.intervals }, getRootProps: this.getRootProps, getIntervalProps: this.getIntervalProps, showPeriod, data: headerData, } } render() { const props = this.getStateAndHelpers() const Renderer = this.props.children return <Renderer {...props}/> } } const CustomHeaderWrapper = ({ children, unit, headerData, height }) => ( <TimelineStateConsumer> {({ getTimelineState, showPeriod, getLeftOffsetFromDate }) => { const timelineState = getTimelineState() return ( <TimelineHeadersConsumer> {({ timeSteps }) => ( <CustomHeader children={children} timeSteps={timeSteps} showPeriod={showPeriod} unit={unit ? unit : timelineState.timelineUnit} {...timelineState} headerData={headerData} getLeftOffsetFromDate={getLeftOffsetFromDate} height={height} /> )} </TimelineHeadersConsumer> ) }} </TimelineStateConsumer> ) CustomHeaderWrapper.propTypes = { children: PropTypes.func.isRequired, unit: PropTypes.string, headerData: PropTypes.object, height: PropTypes.number, } CustomHeaderWrapper.defaultProps = { height: 30, } export default CustomHeaderWrapper