diff --git a/packages/calendar/src/TimeRange.tsx b/packages/calendar/src/TimeRange.tsx index b01e5eb5e..88d79252f 100644 --- a/packages/calendar/src/TimeRange.tsx +++ b/packages/calendar/src/TimeRange.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useMemo } from 'react' import { Container, SvgWrapper, useValueFormatter, useTheme, useDimensions } from '@nivo/core' import { BoxLegendSvg } from '@nivo/legends' @@ -24,7 +24,7 @@ const InnerTimeRange = ({ square = timeRangeDefaultProps.square, colors = timeRangeDefaultProps.colors, colorScale, - data, + data: _data, direction = timeRangeDefaultProps.direction, minValue = timeRangeDefaultProps.minValue, maxValue = timeRangeDefaultProps.maxValue, @@ -35,13 +35,12 @@ const InnerTimeRange = ({ monthLegendOffset = timeRangeDefaultProps.monthLegendOffset, monthLegendPosition = timeRangeDefaultProps.monthLegendPosition, - weekdayLegendsOffset = timeRangeDefaultProps.weekdayLegendsOffset, + weekdayLegendOffset = timeRangeDefaultProps.weekdayLegendOffset, dayBorderColor = timeRangeDefaultProps.dayBorderColor, dayBorderWidth = timeRangeDefaultProps.dayBorderWidth, daySpacing = timeRangeDefaultProps.daySpacing, dayRadius = timeRangeDefaultProps.dayRadius, - daysInRange = timeRangeDefaultProps.daysInRange, isInteractive = timeRangeDefaultProps.isInteractive, tooltip = timeRangeDefaultProps.tooltip, @@ -59,12 +58,20 @@ const InnerTimeRange = ({ partialMargin ) + const data = useMemo( + () => + _data + .map(data => ({ ...data, date: new Date(`${data.day}T00:00:00`) })) + .sort((left, right) => left.day.localeCompare(right.day)), + [_data] + ) + const theme = useTheme() const colorScaleFn = useColorScale({ data, minValue, maxValue, colors, colorScale }) const { cellHeight, cellWidth } = computeCellSize({ square, - offset: weekdayLegendsOffset, + offset: weekdayLegendOffset, totalDays: data.length + data[0].date.getDay(), width: innerWidth, height: innerHeight, @@ -73,8 +80,7 @@ const InnerTimeRange = ({ }) const days = computeCellPositions({ - offset: weekdayLegendsOffset, - daysInRange, + offset: weekdayLegendOffset, colorScale: colorScaleFn, cellHeight, cellWidth, @@ -91,7 +97,6 @@ const InnerTimeRange = ({ cellHeight, cellWidth, days, - daysInRange, }).months ) diff --git a/packages/calendar/src/compute/timeRange.ts b/packages/calendar/src/compute/timeRange.ts index 0f6854a06..2280f13fe 100644 --- a/packages/calendar/src/compute/timeRange.ts +++ b/packages/calendar/src/compute/timeRange.ts @@ -1,9 +1,7 @@ import { timeWeek } from 'd3-time' -import { timeRangeDefaultProps } from '../props' // Interfaces interface ComputeBaseProps { - daysInRange: number direction: 'horizontal' | 'vertical' } @@ -90,8 +88,8 @@ export const computeCellSize = ({ totalDays, width, height, -}: Omit) => { - const { daysInRange } = timeRangeDefaultProps +}: ComputeCellSize) => { + const daysInRange = 7 let rows let columns let widthRest = width @@ -184,6 +182,8 @@ export const computeCellPositions = ({ year, date, color: colorScale(dateValue.value), + width: cellWidth, + height: cellHeight, } }) @@ -213,15 +213,14 @@ export const computeWeekdays = ({ return ticks.map(day => ({ value: arrayOfWeekdays[day], rotation: direction === 'horizontal' ? 0 : -90, - y: direction === 'horizontal' ? sizes.height * (day + 1) - daySpacing / 2 : 0, - x: direction === 'horizontal' ? 0 : sizes.width * (day + 1) - daySpacing / 2, + y: direction === 'horizontal' ? sizes.height * (day + 1) - sizes.height / 3 : 0, + x: direction === 'horizontal' ? 0 : sizes.width * (day + 1) - sizes.width / 3, })) } export const computeMonthLegends = ({ direction, daySpacing, - daysInRange, days, cellHeight, cellWidth, @@ -245,12 +244,12 @@ export const computeMonthLegends = ({ if (direction === 'horizontal') { bbox.x = day.coordinates.x - daySpacing - bbox.height = daysInRange * cellHeight + daySpacing + bbox.height = cellHeight + daySpacing bbox.width = cellWidth + daySpacing * 2 } else { bbox.y = day.coordinates.y - daySpacing bbox.height = cellHeight + daySpacing * 2 - bbox.width = daysInRange * cellWidth + daySpacing * 2 + bbox.width = cellWidth + daySpacing * 2 } acc.months[key] = { diff --git a/packages/calendar/src/props.ts b/packages/calendar/src/props.ts index 61725bac8..4c9fc33ec 100644 --- a/packages/calendar/src/props.ts +++ b/packages/calendar/src/props.ts @@ -48,12 +48,8 @@ export const calendarCanvasDefaultProps = { export const timeRangeDefaultProps = { ...calendarDefaultProps, - dayBorderWidth: 0, dayBorderColor: '#fff', dayRadius: 0, - daySpacing: 10, - daysInRange: 7, - monthLegendOffset: 0, square: true, - weekdayLegendsOffset: 65, + weekdayLegendOffset: 75, } as const diff --git a/packages/calendar/src/types.ts b/packages/calendar/src/types.ts index 62717b88b..da42d809f 100644 --- a/packages/calendar/src/types.ts +++ b/packages/calendar/src/types.ts @@ -170,39 +170,45 @@ export type CalendarCanvasProps = Dimensions & Partial< CommonCalendarProps & InteractivityProps | Datum, HTMLCanvasElement> & { - pixelRatio?: number + pixelRatio: number } > -export type TimeRangeDatum = { - day: string - date: Date - value: number -} - -export type TimeRangeDayData = TimeRangeDatum & { +export type TimeRangeDayData = CalendarDatum & { coordinates: { x: number y: number } + date: Date firstWeek: number month: number year: number color: string + width: number + height: number } export type TimeRangeTooltipProps = Omit & { value: string } -export type TimeRangeSvgProps = Dimensions & { data: TimeRangeDatum[] } & Partial< - CommonCalendarProps & - InteractivityProps & { +export type TimeRangeSvgProps = Dimensions & { data: CalendarDatum[] } & Partial< + Omit< + CommonCalendarProps, + | 'emptyColor' + | 'yearLegend' + | 'yearSpacing' + | 'yearLegendOffset' + | 'yearLegendPosition' + | 'monthSpacing' + | 'monthBorderWidth' + | 'monthBorderColor' + > & + InteractivityProps & { dayRadius: number - daysInRange: number square: boolean role: string - weekdayLegendsOffset: number + weekdayLegendOffset: number } > diff --git a/packages/calendar/stories/timeRange.stories.tsx b/packages/calendar/stories/timeRange.stories.tsx index 452f94ea8..3ce25c990 100644 --- a/packages/calendar/stories/timeRange.stories.tsx +++ b/packages/calendar/stories/timeRange.stories.tsx @@ -1,24 +1,10 @@ import React from 'react' import { storiesOf } from '@storybook/react' import { withKnobs, number, date, boolean } from '@storybook/addon-knobs' -import { timeDays } from 'd3-time' -import { timeFormat } from 'd3-time-format' +import { generateOrderedDayCounts } from '@nivo/generators' import { TimeRange, ResponsiveTimeRange } from '../src' -const generateOrderedDayCounts = ({ from, to }: { from: Date; to: Date }) => { - const days = timeDays(from, to) - const dayFormat = timeFormat('%Y-%m-%d') - - return days.map(day => { - return { - value: Math.round(Math.random() * 400), - date: day, - day: dayFormat(day), - } - }) -} - const stories = storiesOf('TimeRange', module) stories.addDecorator(withKnobs) @@ -38,12 +24,11 @@ stories.add('TimeRange horizontal', () => { bottom: number('margin-bottom', 40), left: number('margin-left', 40), }, - data: generateOrderedDayCounts({ - from, - to, - }), - daySpacing: number('daySpacing', 10), + data: generateOrderedDayCounts(from, to), + daySpacing: number('daySpacing', 0), }} + monthLegendOffset={10} + dayBorderWidth={1} height={number('height', 250)} width={number('width', 655)} legendFormat={value => value / 10 + 'M'} @@ -95,10 +80,7 @@ stories.add('responsive', () => { bottom: number('margin-bottom', 40), left: number('margin-left', 40), }, - data: generateOrderedDayCounts({ - from, - to, - }), + data: generateOrderedDayCounts(from, to), daySpacing: number('daySpacing', 10), }} /> @@ -120,13 +102,10 @@ stories.add('TimeRange vertical', () => { bottom: number('margin-bottom', 40), left: number('margin-left', 40), }, - data: generateOrderedDayCounts({ - from, - to, - }), + data: generateOrderedDayCounts(from, to), daySpacing: number('daySpacing', 10), }} - weekdayLegendsOffset={0} + weekdayLegendOffset={0} height={number('height', 900)} width={number('width', 250)} direction="vertical"