Skip to content

Commit

Permalink
feat(calendar): add monthSpacing prop (#964)
Browse files Browse the repository at this point in the history
* Add month spacing to @nivo/calendar

* feat(website): Add daySpacing to calendar component

* fix(calendar): Add monthSpacing to types

Co-authored-by: Neil Kistner <neil.kistner@gmail.com>
  • Loading branch information
fguitton and wyze committed Jun 22, 2020
1 parent 5be120a commit 8f55046
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 14 deletions.
1 change: 1 addition & 0 deletions packages/calendar/index.d.ts
Expand Up @@ -46,6 +46,7 @@ declare module '@nivo/calendar' {
yearLegendOffset: number

monthLegend: (year: number, month: number, date: Date) => string | number
monthSpacing: number
monthBorderWidth: number
monthBorderColor: string
monthLegendOffset: number
Expand Down
55 changes: 43 additions & 12 deletions packages/calendar/src/compute.js
Expand Up @@ -37,6 +37,7 @@ export const computeDomain = (data, minSpec, maxSpec) => {
* @param {number} direction
* @param {array} yearRange
* @param {number} yearSpacing
* @param {number} monthSpacing
* @param {number} daySpacing
* @param {number} maxWeeks
* @returns {number}
Expand All @@ -47,22 +48,23 @@ const computeCellSize = ({
direction,
yearRange,
yearSpacing,
monthSpacing,
daySpacing,
maxWeeks,
}) => {
let hCellSize
let vCellSize

if (direction === 'horizontal') {
hCellSize = (width - daySpacing * maxWeeks) / maxWeeks
hCellSize = (width - monthSpacing * 12 - daySpacing * maxWeeks) / maxWeeks
vCellSize =
(height - (yearRange.length - 1) * yearSpacing - yearRange.length * (8 * daySpacing)) /
(yearRange.length * 7)
} else {
hCellSize =
(width - (yearRange.length - 1) * yearSpacing - yearRange.length * (8 * daySpacing)) /
(yearRange.length * 7)
vCellSize = (height - daySpacing * maxWeeks) / maxWeeks
vCellSize = (height - monthSpacing * 12 - daySpacing * maxWeeks) / maxWeeks
}

return Math.min(hCellSize, vCellSize)
Expand All @@ -75,6 +77,7 @@ const computeCellSize = ({
* @param {number} cellSize
* @param {number} yearIndex
* @param {number} yearSpacing
* @param {number} monthSpacing
* @param {number} daySpacing
* @param {string} direction
* @param {number} originX
Expand All @@ -86,6 +89,7 @@ const monthPathAndBBox = ({
cellSize,
yearIndex,
yearSpacing,
monthSpacing,
daySpacing,
direction,
originX,
Expand All @@ -100,13 +104,16 @@ const monthPathAndBBox = ({
const firstDay = date.getDay()
const lastDay = t1.getDay()

// offset according to year index
// offset according to year index and month
let xO = originX
let yO = originY
const yearOffset = yearIndex * (7 * (cellSize + daySpacing) + yearSpacing)
const monthOffset = date.getMonth() * monthSpacing
if (direction === 'horizontal') {
yO += yearOffset
xO += monthOffset
} else {
yO += monthOffset
xO += yearOffset
}

Expand Down Expand Up @@ -154,8 +161,18 @@ const monthPathAndBBox = ({
*/
const memoMonthPathAndBBox = memoize(
monthPathAndBBox,
({ date, cellSize, yearIndex, yearSpacing, daySpacing, direction, originX, originY }) => {
return `${date.toString()}.${cellSize}.${yearIndex}.${yearSpacing}.${daySpacing}.${direction}.${originX}.${originY}`
({
date,
cellSize,
yearIndex,
yearSpacing,
monthSpacing,
daySpacing,
direction,
originX,
originY,
}) => {
return `${date.toString()}.${cellSize}.${yearIndex}.${yearSpacing}.${monthSpacing}.${daySpacing}.${direction}.${originX}.${originY}`
}
)

Expand All @@ -164,15 +181,20 @@ const memoMonthPathAndBBox = memoize(
*
* @param {number} cellSize
* @param {number} yearSpacing
* @param {number} monthSpacing
* @param {number} daySpacing
* @returns { function(): { x: number, y: number } }
*/
const cellPositionHorizontal = (cellSize, yearSpacing, daySpacing) => {
const cellPositionHorizontal = (cellSize, yearSpacing, monthSpacing, daySpacing) => {
return (originX, originY, d, yearIndex) => {
const weekOfYear = timeWeek.count(timeYear(d), d)

return {
x: originX + weekOfYear * (cellSize + daySpacing) + daySpacing / 2,
x:
originX +
weekOfYear * (cellSize + daySpacing) +
daySpacing / 2 +
d.getMonth() * monthSpacing,
y:
originY +
d.getDay() * (cellSize + daySpacing) +
Expand All @@ -187,10 +209,11 @@ const cellPositionHorizontal = (cellSize, yearSpacing, daySpacing) => {
*
* @param {number} cellSize
* @param {number} yearSpacing
* @param {number} monthSpacing
* @param {number} daySpacing
* @returns { function(): { x: number, y: number } }
*/
const cellPositionVertical = (cellSize, yearSpacing, daySpacing) => {
const cellPositionVertical = (cellSize, yearSpacing, monthSpacing, daySpacing) => {
return (originX, originY, d, yearIndex) => {
const weekOfYear = timeWeek.count(timeYear(d), d)

Expand All @@ -200,7 +223,11 @@ const cellPositionVertical = (cellSize, yearSpacing, daySpacing) => {
d.getDay() * (cellSize + daySpacing) +
daySpacing / 2 +
yearIndex * (yearSpacing + 7 * (cellSize + daySpacing)),
y: originY + weekOfYear * (cellSize + daySpacing) + daySpacing / 2,
y:
originY +
weekOfYear * (cellSize + daySpacing) +
daySpacing / 2 +
d.getMonth() * monthSpacing,
}
}
}
Expand All @@ -217,6 +244,7 @@ const dayFormat = timeFormat('%Y-%m-%d')
* @param {string|Date} to
* @param {string} direction
* @param {number} yearSpacing
* @param {number} monthSpacing
* @param {number} daySpacing
* @param {string} align
* @returns {object}
Expand All @@ -228,6 +256,7 @@ export const computeLayout = ({
to,
direction,
yearSpacing,
monthSpacing,
daySpacing,
align,
}) => {
Expand All @@ -248,11 +277,12 @@ export const computeLayout = ({
direction,
yearRange,
yearSpacing,
monthSpacing,
daySpacing,
maxWeeks,
})

const monthsSize = cellSize * maxWeeks + daySpacing * maxWeeks
const monthsSize = cellSize * maxWeeks + daySpacing * maxWeeks + monthSpacing * 12
const yearsSize =
(cellSize + daySpacing) * 7 * yearRange.length + yearSpacing * (yearRange.length - 1)

Expand All @@ -276,9 +306,9 @@ export const computeLayout = ({

let cellPosition
if (direction === 'horizontal') {
cellPosition = cellPositionHorizontal(cellSize, yearSpacing, daySpacing)
cellPosition = cellPositionHorizontal(cellSize, yearSpacing, monthSpacing, daySpacing)
} else {
cellPosition = cellPositionVertical(cellSize, yearSpacing, daySpacing)
cellPosition = cellPositionVertical(cellSize, yearSpacing, monthSpacing, daySpacing)
}

let years = []
Expand Down Expand Up @@ -311,6 +341,7 @@ export const computeLayout = ({
direction,
yearIndex: i,
yearSpacing,
monthSpacing,
daySpacing,
cellSize,
}),
Expand Down
15 changes: 13 additions & 2 deletions packages/calendar/src/enhance.js
Expand Up @@ -33,15 +33,26 @@ const commonEnhancers = [
}
),
withPropsOnChange(
['width', 'height', 'from', 'to', 'direction', 'yearSpacing', 'daySpacing', 'align'],
({ width, height, from, to, direction, yearSpacing, daySpacing, align }) => {
[
'width',
'height',
'from',
'to',
'direction',
'yearSpacing',
'monthSpacing',
'daySpacing',
'align',
],
({ width, height, from, to, direction, yearSpacing, monthSpacing, daySpacing, align }) => {
return computeLayout({
width,
height,
from,
to,
direction,
yearSpacing,
monthSpacing,
daySpacing,
align,
})
Expand Down
2 changes: 2 additions & 0 deletions packages/calendar/src/props.js
Expand Up @@ -46,6 +46,7 @@ const commonPropTypes = {
monthBorderWidth: PropTypes.number.isRequired,
monthBorderColor: PropTypes.string.isRequired,
monthLegend: PropTypes.func.isRequired,
monthSpacing: PropTypes.number.isRequired,
monthLegendPosition: PropTypes.oneOf(['before', 'after']).isRequired,
monthLegendOffset: PropTypes.number.isRequired,

Expand Down Expand Up @@ -90,6 +91,7 @@ const commonDefaultProps = {

monthBorderWidth: 2,
monthBorderColor: '#000',
monthSpacing: 0,
monthLegend: (year, month, date) => monthLabelFormat(date),
monthLegendPosition: 'before',
monthLegendOffset: 10,
Expand Down
2 changes: 2 additions & 0 deletions packages/calendar/stories/calendar.stories.js
Expand Up @@ -68,3 +68,5 @@ stories.add('custom tooltip', () => (
{...commonProps}
/>
))

stories.add('month spacing', () => <Calendar {...commonProps} monthSpacing={25} />)
15 changes: 15 additions & 0 deletions website/src/data/components/calendar/props.js
Expand Up @@ -252,6 +252,21 @@ const props = [
},
},
// Months
{
key: 'monthSpacing',
help: 'define spacing between each month row/column depending on the direction.',
type: 'number',
required: false,
defaultValue: defaults.monthSpacing,
controlType: 'range',
group: 'Months',
controlOptions: {
unit: 'px',
min: 0,
max: 160,
step: 5,
},
},
{
key: 'monthBorderWidth',
flavors: ['svg', 'api'],
Expand Down
1 change: 1 addition & 0 deletions website/src/pages/calendar/canvas.js
Expand Up @@ -47,6 +47,7 @@ const initialProperties = {
yearLegendPosition: 'before',
yearLegendOffset: 10,

monthSpacing: 0,
monthBorderWidth: 2,
monthBorderColor: '#ffffff',
monthLegendPosition: 'before',
Expand Down
1 change: 1 addition & 0 deletions website/src/pages/calendar/index.js
Expand Up @@ -44,6 +44,7 @@ const initialProperties = {
yearLegendPosition: 'before',
yearLegendOffset: 10,

monthSpacing: 0,
monthBorderWidth: 2,
monthBorderColor: '#ffffff',
monthLegendPosition: 'before',
Expand Down

0 comments on commit 8f55046

Please sign in to comment.