import React, { useCallback } from 'react';
import { useStyles2 } from '../../../themes';
import Calendar from 'react-calendar';
import { css } from '@emotion/css';
import { Icon } from '../../Icon/Icon';
import { TimePickerCalendarProps } from './TimePickerCalendar';
import { GrafanaTheme2, dateTime, dateTimeParse, DateTime, TimeZone } from '@grafana/data';
export function Body({ onChange, from, to, timeZone }: TimePickerCalendarProps) {
const value = inputToValue(from, to);
const onCalendarChange = useOnCalendarChange(onChange, timeZone);
const styles = useStyles2(getBodyStyles);
return (
}
prevLabel={}
onChange={onCalendarChange}
locale="en"
/>
);
}
Body.displayName = 'Body';
export function inputToValue(from: DateTime, to: DateTime, invalidDateDefault: Date = new Date()): Date[] {
const fromAsDate = from.toDate();
const toAsDate = to.toDate();
const fromAsValidDate = dateTime(fromAsDate).isValid() ? fromAsDate : invalidDateDefault;
const toAsValidDate = dateTime(toAsDate).isValid() ? toAsDate : invalidDateDefault;
if (fromAsValidDate > toAsValidDate) {
return [toAsValidDate, fromAsValidDate];
}
return [fromAsValidDate, toAsValidDate];
}
function useOnCalendarChange(onChange: (from: DateTime, to: DateTime) => void, timeZone?: TimeZone) {
return useCallback(
(value: Date | Date[]) => {
if (!Array.isArray(value)) {
return console.error('onCalendarChange: should be run in selectRange={true}');
}
const from = dateTimeParse(dateInfo(value[0]), { timeZone });
const to = dateTimeParse(dateInfo(value[1]), { timeZone });
onChange(from, to);
},
[onChange, timeZone]
);
}
function dateInfo(date: Date): number[] {
return [date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()];
}
export const getBodyStyles = (theme: GrafanaTheme2) => {
return {
title: css`
color: ${theme.colors.text};
background-color: ${theme.colors.background.primary};
font-size: ${theme.typography.size.md};
border: 1px solid transparent;
&:hover {
position: relative;
}
`,
body: css`
z-index: ${theme.zIndex.modal};
background-color: ${theme.colors.background.primary};
width: 268px;
.react-calendar__navigation__label,
.react-calendar__navigation__arrow,
.react-calendar__navigation {
padding-top: 4px;
background-color: inherit;
color: ${theme.colors.text};
border: 0;
font-weight: ${theme.typography.fontWeightMedium};
}
.react-calendar__month-view__weekdays {
background-color: inherit;
text-align: center;
color: ${theme.colors.primary.text};
abbr {
border: 0;
text-decoration: none;
cursor: default;
display: block;
padding: 4px 0 4px 0;
}
}
.react-calendar__month-view__days {
background-color: inherit;
}
.react-calendar__tile,
.react-calendar__tile--now {
margin-bottom: 4px;
background-color: inherit;
height: 26px;
}
.react-calendar__navigation__label,
.react-calendar__navigation > button:focus,
.time-picker-calendar-tile:focus {
outline: 0;
}
.react-calendar__tile--active,
.react-calendar__tile--active:hover {
color: ${theme.colors.primary.contrastText};
font-weight: ${theme.typography.fontWeightMedium};
background: ${theme.colors.primary.main};
box-shadow: none;
border: 0px;
}
.react-calendar__tile--rangeEnd,
.react-calendar__tile--rangeStart {
padding: 0;
border: 0px;
color: ${theme.colors.primary.contrastText};
font-weight: ${theme.typography.fontWeightMedium};
background: ${theme.colors.primary.main};
abbr {
background-color: ${theme.colors.primary.main};
border-radius: 100px;
display: block;
padding-top: 2px;
height: 26px;
}
}
.react-calendar__tile--rangeStart {
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
.react-calendar__tile--rangeEnd {
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
`,
};
};