import React , { MouseEventHandler , ReactNode , memo } from 'react' ; import { rem } from 'polished' ; import styled from 'styled-components' ; import { CalendarDayLabel } from './CalendarDayLabel' ; import { IrisProps } from '../../../../utils' ; export type DateRange = [ Date | undefined ] | [ Date , Date | undefined ] ; type Props = IrisProps < { children : ReactNode ; range : DateRange ; draftRange : DateRange ; inactive ? : boolean ; pastMinDate ? : boolean ; pastMaxDate ? : boolean ; date : Date ; onMouseEnter ? : MouseEventHandler ; } > ; function Day ( { children , className , onClick , onMouseEnter , inactive , pastMinDate , pastMaxDate , date , range , draftRange , } ) { const isStart = isSameDate ( date , range [ 0 ] ) || isSameDate ( date , draftRange [ 0 ] ) ; const hasEnd = range [ 1 ] instanceof Date ; const isEnd = isSameDate ( date , range [ 1 ] ) || isSameDate ( date , draftRange [ 1 ] ) ; const isTrack = isInDateRange ( date , range ) ; const isControl = isStart || isEnd ; const handleClick = ( event ) => { if ( ! inactive && ! pastMinDate && ! pastMaxDate && onClick ) { onClick ( event ) ; } } ; const handleMouseEnter = ( event ) => { if ( ! inactive && ! pastMinDate && ! pastMaxDate && onMouseEnter ) { onMouseEnter ( event ) ; } } ; return ( < CalendarGridItem className = { className } onClick = { handleClick } onMouseEnter = { handleMouseEnter } > { ! inactive && ( < CalendarDayLabel isControl = { isControl } isPast = { pastMinDate || pastMaxDate } isTrack = { isTrack } isStart = { isStart && hasEnd } isEnd = { isEnd } > { children } < /CalendarDayLabel>)} < /CalendarGridItem>); } export const CalendarGridItem = styled . div `
  position: relative;
  flex: 0 0 calc(100% / 7);
  width: calc(100% / 7);
  padding: ${ rem ( 1 ) };
  text-align: center;
  cursor: default;
  font-size: ${ rem ( 14 ) };
  font-weight: 500;
` ; const DayStyled = styled ( Day ) `
  margin-bottom: ${ rem ( 4 ) };
  &::before {
    content: ' ';
    display: block;
    width: 100%;
    height: 0;
    padding-bottom: 100%;
  }
  cursor: ${ ( props ) => props . onClick && ! props . inactive ? 'pointer' : 'default' };
` ; export const CalendarDay = memo ( DayStyled , calendarDayEqual ) ; function isSameDate ( a ? , b ? ) { if ( ! ( a && b ) ) { return a === b ; } return ( a . getFullYear ( ) === b . getFullYear ( ) && a . getMonth ( ) === b . getMonth ( ) && a . getDate ( ) === b . getDate ( ) ) ; } function isInDateRange ( a , range ) { const [ start , end ] = range ; if ( ! ( start && end ) ) { return false ; } if ( a > start && a < end ) { return true ; } return false ; } function generateCompareProps ( day ) { const { date , range , draftRange } = day ; const props = [ ] ; let i = 0 ; props [ i ++ ] = ( isSameDate ( date , range [ 0 ] ) || isSameDate ( date , draftRange [ 0 ] ) ) && range [ 1 ] instanceof Date ; props [ i ++ ] = isSameDate ( date , range [ 1 ] ) || isSameDate ( date , draftRange [ 1 ] ) ; props [ i ++ ] = isInDateRange ( date , range ) ; props [ i ++ ] = day . inactive ; props [ i ++ ] = day . pastMinDate ; props [ i ++ ] = day . pastMaxDate ; return props ; } function calendarDayEqual ( prev , next ) { const p = generateCompareProps ( prev ) ; const n = generateCompareProps ( next ) ; for ( let i = 0 ; i < p . length ; i ++ ) { if ( p [ i ] !== n [ i ] ) { return false ; } } return false ; }